;struct Value { bool on_stack, literal, int loc, val, VType _type } ;Value NV = {false, false, 0, 0, 0, {0, 0, "null", {}, {}}} /; val_from_address (int offset, {}uint8 reg) [{}uint8] ;{}uint8 out = string_from_int(offset) ;out.append('(') ;add_strings(~out, ~reg) ;out.append(')') ;return out ;/ # The temp registers in order /; reg_by_num(int r) [{}uint8] /; if (r == 0) ;return "ax" ;; if (r == 1) ;return "bx" ;; if (r == 2) ;return "cx" ;; if (r == 3) ;return "dx" ;; if (r == 4) ;return "si" ;; if (r == 5) ;return "di" ;; if (r == -1) ;return "sp" ;/ ;return string_from_int(r + 2) ;/ /; ext_by_size(int s) [uint8] /; if (r == 1) ;return 'b' ;; if (r == 2) ;return 'w' ;; if (r == 4) ;return 'l' ;/ ;return 'q' ;/ /; method Value /; get_norm_sz [int] /; if (self._type.ptr !== 0) ;return 8 ;/ ;returnself._type._size ;/ /; get_norm_loc [{}uint8] /; if (self.on_stack) ;return val_from_address(self.loc, "%rsp") ;; if (!(self.on_stack) && self._type.ptr == 0 && is_struct(self._type)) ;{}uint8 out = "(" ;{}uint8 tmp = get_reg(8, reg_by_num(self.loc)) ;add_strings(~out, ~tmp) ;out.append(')') ;return out ;/ /; if (self.literal) ;{}uint8 out = "$" ;{}uint8 num = string_from_int(self.val) ;add_strings(~out, ~num) ;return out ;/ ;int sz = self._type._size /; if (self._type.ptr !== 0) ;sz = 8 ;/ ;return get_reg(sz, reg_by_num(self.loc)) ;/ /; init_val [{}uint8] /; if (self.literal || !self.on_stack) ;return "" ;/ ;{}uint8 out = "\tsub $" ;{}uint8 tmp = string_from_int(self._type._size) ;add_strings(~out, ~tmp) ;tmp = ", %rsp\n" ;add_strings(~out, ~tmp) ;return out ;/ /; standard_op(Value other, {}uint8 op) [{}uint8] ;tnsl.io.print("Std op ") ;tnsl.io.println(op) ;int tsz = other._type._size ;other._type._size = self._type._size ;{}uint8 tmp = other.get_norm_loc() ;other._type._size = tsz ;{}uint8 out = "\t" ;add_strings(~out, ~op) ;out.append(' ') ;add_strings(~out, ~tmp) ;out.append(',') ;out.append(' ') ;tmp = self.get_norm_loc() ;add_strings(~out, ~tmp) ;out.append('\n') ;return out ;/ /; add_value (Value v) [{}uint8] /; if (self.literal) ;self.val = self.val + v.val ;return "" ;; else if (!(self.on_stack)) ;return self.standard_op(v, "add") ;/ ;/ /; sub_value (Value v) [{}uint8] /; if (self.literal) ;self.val = self.val - v.val ;return "" ;; else if (!(self.on_stack)) ;return self.standard_op(v, "sub") ;/ ;/ /; ax_compute(Value v, {}uint8 op, bool save_dx) ;{}uint8 out = "\tpush %rax\n\tpush %rdx\n" /; if (v.on_stack) ;v.loc = v.loc + 16 ;; if (self.on_stack) ;self.loc = self.loc + 16 ;/ ;{}uint8 tmp = "\tmov " ;{}uint8 t2 = v.get_norm_loc() ;add_strings(~tmp, ~t2) ;t2 = ", %rax\n" ;add_strings(~tmp, ~t2) ;add_strings(~out, ~tmp) ;tmp = "\txor %rdx, %rdx\n" ;add_strings(~out, ~tmp) ;tmp = "\t" ;add_strings(~tmp, ~op) ;tmp.append(' ') ;{}uint8 t2 = self.get_norm_loc() ;add_strings(~tmp, ~t2) ;tmp.append('\n') ;add_strings(~out, ~tmp) /; if (save_dx) ;tmp = "\tmov %rdx, " ;; else ;tmp = "\tmov %rax, " ;/ ;add_strings(~tmp, ~t2) ;tmp.append('\n') ;add_strings(~out, ~tmp) /; if (v.on_stack) ;v.loc = v.loc - 16 ;; if (self.on_stack) ;self.loc = self.loc - 16 ;/ ;tmp = "\tpop %rdx\n\tpop %rax" ;add_strings(~out, ~tmp) ;return out ;/ /; mul_value (Value v) [{}uint8] /; if (self.literal) ;self.val = self.val * v.val ;return "" ;; else if (!(self.on_stack)) /; if (self._type.name{0} !== 'u') ;return self.standard_op(v, "imul") ;/ ;return self.ax_compute(v, "mul", false) ;/ ;/ /; div_value (Value v) [{}uint8] /; if (self.literal) ;self.val = self.val + v.val ;return "" ;; else if (!(self.on_stack)) /; if (self._type.name{0} !== 'u') ;return self.ax_compute(v, "idiv", false) ;/ ;return self.ax_compute(v, "div", false) ;/ ;/ /; mod_value (Value v) [{}uint8] /; if (self.literal) ;self.val = self.val / v.val ;return "" ;; else if (!self.on_stack) /; if (self._type.name{0} !== 'u') ;return self.ax_compute(v, "idiv", true) ;/ ;return self.ax_compute(v, "div", true) ;/ ;/ /; ref_value (Value to_ref) [{}uint8] /; if (!to_ref.on_stack) ;return "" ;/ ;return self.standard_op(to_ref, "lea") ;/ /; deref_value [{}uint8] /; if (self._type.ptr == 0) ;return "" ;/ ;Value new = self ;new._type.ptr = new._type.ptr - 1 ;{}uint8 out = "\tmov (" ;{}uint8 tmp = self.get_norm_loc() ;add_strings(~out, ~tmp) ;out.append(')') ;out.append(',') ;out.append(' ') ;tmp = new.get_norm_loc() ;add_strings(~out, ~tmp) ;self = new ;return out ;/ /; get_index (Value index) [Value] /; if (self._type.ptr == 0) ;return NV ;/ ;/ /; set_value (Value v) [{}uint8] /; if (self.literal) ;self.val = v.val ;return "" ;; else if (!(self.on_stack)) /; if (!is_struct(self._type)) ;return self.standard_op(v, "mov") ;/ # This is the case where we are storing an address to # a struct in a register. ;{}charp out = "\tpush %rcx\n\tmov " ;{}charp tmp = self.get_norm_loc() ;add_strings(~out, ~tmp) ;tmp = ", %rcx\n" ;add_strings(~out, ~tmp) ;tmp = self.standard_op(v, "movsb") ;add_strings(~out, ~tmp) ;tmp = "\tpop %rcx" ;add_strings(~out, ~tmp) ;return out ;/ /; if (self._type._size !> 8) /; if (!v.on_stack) ;return self.standard_op(v, "mov") ;/ ;{}charp out = "\tpush %rax\n\tmov " ;{}charp tmp = v.get_norm_loc() ;add_strings(~out, ~tmp) ;tmp = ", %rax\n" ;add_strings(~out, ~tmp) ;tmp = self.standard_op(v, "mov") ;add_strings(~out, ~tmp) ;return out ;/ ;/ /; load_label_address ({}uint8 lab) [{}uint8] ;{}uint8 out = "\tlea " ;{}uint8 tmp = "(%rip), " ;add_strings(~out, ~lab) ;add_strings(~out, ~tmp) ;tmp = self.get_norm_loc() ;add_strings(~out, tmp) ;out.append('\n') ;return out ;/ /; get_member_value ({}uint8 name) [Value] ;Value out = self /; if (self.on_stack) ;out.loc = out.loc + self._type.get_offset(name) ;; else ;out.val = out.val + self._type.get_offset(name) ;/ ;out._type = self._type.get_sub_type(name) ;out._type.ptr = -1 ;return out ;/ /; mov_to_reg (int reg) [{}uint8] /; if (!(self.on_stack)) ;return self.update_loc(0) ;/ ;/ /; update_loc(int loc) [{}uint8] /; if (self.on_stack) ;self.loc = self.loc + loc ;; else if (!(self.literal)) ;{}uint8 out = "\tmov " ;int tsz = self._type._size ;self._type._size = 8 ;{}uint8 tmp = self.get_norm_loc() ;add_strings(~out, ~tmp) ;out.append(',') ;out.append(' ') ;self.loc = loc ;tmp = self.get_norm_loc() ;add_strings(~out, ~tmp) ;out.append('\n') ;self._type._size = tsz ;return out ;/ ;return "" ;/ ;/ /; literal_val (int l, VType t) [Value] ;return {false, true, 0, l, t} ;/ /; track_val(VType ty, bool on_stack, int loc) [Value] ;return {on_stack, false, loc, 0, ty} ;/