def genop_call(self, sigtoken, gv_fnptr, args_gv): log('%s Builder.genop_call %s,%s,%s' % ( self.block.label, sigtoken, gv_fnptr, [v.operand() for v in args_gv])) argtypes, restype = sigtoken if isinstance(gv_fnptr, AddrConst): gv_fn = Var(self._funcsig_type(args_gv, restype) + '*') self.asm.append(' %s=%s %s %s to %s' % ( gv_fn.operand2(), inttoptr, i32, gv_fnptr.operand2(), gv_fn.type)) funcsig = gv_fn.operand() else: try: funcsig = self.rgenop.funcsig[gv_fnptr.get_integer_value()] except KeyError: funcsig = 'TODO: funcsig here' py.test.skip('call an address directly not supported yet') args_gv2 = [] for v in args_gv: if v.is_const and v.type[-1] == '*': #or use some kind of 'inline' cast (see LangRef) t = Var(v.type) self.asm.append(' %s=%s %s %s to %s' % ( t.operand2(), inttoptr, i32, v.operand2(), v.type)) v = t args_gv2.append(v) gv_returnvar = Var(restype) self.asm.append(' %s=call %s(%s)' % ( gv_returnvar.operand2(), funcsig, ','.join([v.operand() for v in args_gv2]))) return gv_returnvar
def genop_malloc_varsize(self, varsizealloctoken, gv_size): log('%s Builder.genop_malloc_varsize %s,%s' % ( self.block.label, varsizealloctoken, gv_size.operand())) length_offset, items_offset, item_size, item_type = varsizealloctoken gv_gc_malloc_fnaddr = Var('%s (%s)*' % (pi8, i32)) #or use addGlobalFunctionMapping in libllvmjit.restart() self.asm.append(' %s=%s %s %d to %s ;gc_malloc_fnaddr (varsize)' % ( gv_gc_malloc_fnaddr.operand2(), inttoptr, i32, gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) op_size = self._itemaddr(varsizealloctoken, gv_size) gv_result = Var(pi8) self.asm.append(' %s=call %s(%s)' % ( gv_result.operand2(), gv_gc_malloc_fnaddr.operand(), op_size.operand())) gv_p = Var(gv_result.type) self.asm.append(' %s=getelementptr %s,%s %s' % ( gv_p.operand2(), gv_result.operand(), i32, length_offset)) gv_p2 = self._cast_to(gv_p, pi32) #warning: length field hardcoded as int here self.asm.append(' store %s, %s' % (gv_size.operand(), gv_p2.operand())) return gv_result
def op_int_rshift(self, gv_x, gv_y): gv_y_i8 = Var(i8) self.asm.append(' %s=%s %s to %s' % ( gv_y_i8.operand2(), trunc, gv_y.operand(), i8)) gv_result = Var(gv_x.type) self.asm.append(' %s=%sshr %s,%s' % ( gv_result.operand2(), shr_prefix[gv_x.signed], gv_x.operand(), gv_y_i8.operand())) return gv_result
def op_int_lshift(self, gv_x, gv_y): gv_y_i8 = Var(i8) self.asm.append(' %s=%s %s to %s' % ( gv_y_i8.operand2(), trunc, gv_y.operand(), i8)) gv_result = Var(gv_x.type) self.asm.append(' %s=shl %s,%s' % ( gv_result.operand2(), gv_x.operand(), gv_y_i8.operand())) return gv_result
def genop_malloc_fixedsize(self, size): log('%s Builder.genop_malloc_fixedsize %s' % ( self.block.label, str(size))) gv_gc_malloc_fnaddr = Var('%s (%s)*' % (pi8, i32)) gv_result = Var(pi8) #or use addGlobalFunctionMapping in libllvmjit.restart() self.asm.append(' %s=%s %s %d to %s ;gc_malloc_fnaddr' % ( gv_gc_malloc_fnaddr.operand2(), inttoptr, i32, gc_malloc_fnaddr(), gv_gc_malloc_fnaddr.type)) self.asm.append(' %s=call %s(%s %d)' % ( gv_result.operand2(), gv_gc_malloc_fnaddr.operand(), i32, size)) return gv_result
def _itemaddr(self, arraytoken, gv_index): length_offset, items_offset, item_size, item_type = arraytoken gv_size2 = Var(i32) #i386 uses self.itemaddr here self.asm.append(' %s=mul %s,%d' % ( gv_size2.operand2(), gv_index.operand(), item_size)) gv_size3 = Var(i32) self.asm.append(' %s=add %s,%d' % ( gv_size3.operand2(), gv_size2.operand(), items_offset)) return gv_size3
def genop_getfield(self, fieldtoken, gv_ptr): offset, fieldtype = fieldtoken log('%s Builder.genop_getfield (%d,%s) %s' % ( self.block.label, offset, fieldtype, gv_ptr.operand())) gv_ptr_var = self._as_var(gv_ptr) gv_p = Var(gv_ptr.type) self.asm.append(' %s=getelementptr %s,%s %s' % ( gv_p.operand2(), gv_ptr_var.operand(), i32, offset)) gv_p2 = self._cast_to(gv_p, fieldtype + '*') gv_result = Var(fieldtype) self.asm.append(' %s=load %s' % ( gv_result.operand2(), gv_p2.operand())) return gv_result
def _abs(self, gv_x, nullstr='0'): gv_comp = Var(i1) gv_abs_pos = Var(gv_x.type) gv_result = Var(gv_x.type) if nullstr == 'null' or nullstr == '0': cmp = scmp else: cmp = fcmp self.asm.append(' %s=%sge %s,%s' % ( gv_comp.operand2(), cmp, gv_x.operand(), nullstr)) self.asm.append(' %s=sub %s %s,%s' % ( gv_abs_pos.operand2(), gv_x.type, nullstr, gv_x.operand2())) self.asm.append(' %s=select %s,%s,%s' % ( gv_result.operand2(), gv_comp.operand(), gv_x.operand(), gv_abs_pos.operand())) return gv_result
def __init__(self, rgenop, label, inputargtypes): self.rgenop = rgenop self.label = label self.inputargs = [Var(type) for type in inputargtypes] self.phinodes = {} # dict {source block: [source vars]} self.asm = [] rgenop.blocklist.append(self)
def _trunc_to(self, gv_x, restype=None): restype = restype or gv_x.type if restype is gv_x.type: return self.genop_same_as(None, gv_x) gv_result = Var(restype) self.asm.append(' %s=%s %s to %s' % ( gv_result.operand2(), trunc, gv_x.operand(), restype)) return gv_result
def _rgenop1_generic(self, llvm_opcode, gv_x, restype=None): log('%s Builder._rgenop1_generic %s %s' % ( self.block.label, llvm_opcode, gv_x.operand())) restype = restype or gv_x.type gv_result = Var(restype) self.asm.append(' %s=%s %s' % ( gv_result.operand2(), llvm_opcode, gv_x.operand())) return gv_resulgv_comp.operand(), t
def _rgenop2_generic(self, llvm_opcode, gv_arg1, gv_arg2, restype=None): log('%s Builder._rgenop2_generic %s %s,%s' % ( self.block.label, llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) restype = restype or gv_arg1.type gv_result = Var(restype) self.asm.append(' %s=%s %s,%s' % ( gv_result.operand2(), llvm_opcode, gv_arg1.operand(), gv_arg2.operand2())) return gv_result
def _as_var(self, gv): if gv.is_const: gv_var = Var(gv.type) #XXX provide correct cast here self.asm.append(' %s=%s %s %s to %s' % ( gv_var.operand2(), inttoptr, i32, gv.operand2(), gv_var.type)) return gv_var return gv
def genop_getarraysize(self, arraytoken, gv_ptr): log('%s Builder.genop_getarraysize %s,%s' % ( self.block.label, arraytoken, gv_ptr.operand())) array_length_offset, array_items_offset, item_size, item_type = arraytoken gv_ptr_var = self._as_var(gv_ptr) gv_p = Var(gv_ptr_var.type) self.asm.append(' %s=getelementptr %s,%s %s' % ( gv_p.operand2(), gv_ptr_var.operand(), i32, array_length_offset)) gv_p2 = self._cast_to(gv_p, pi32) gv_result = Var(i32) self.asm.append(' %s=load %s' % ( gv_result.operand2(), gv_p2.operand())) return gv_result
def genop_getsubstruct(self, fieldtoken, gv_ptr): offset, fieldtype = fieldtoken log('%s Builder.genop_getsubstruct (%d,%s) %s' % ( self.block.label, offset, fieldtype, gv_ptr.operand())) gv_ptr_var = self._as_var(gv_ptr) gv_sub = Var(gv_ptr.type) self.asm.append(' %s=getelementptr %s,%s %d' % ( gv_sub.operand2(), gv_ptr_var.operand(), i32, offset)) return gv_sub
def _is_true(self, gv_x, nullstr='0'): log('%s Builder._is_true %s' % (self.block.label, gv_x.operand())) gv_result = Var(i1) if nullstr == 'null' or nullstr == '0': cmp = icmp else: cmp = fcmp self.asm.append(' %s=%sne %s,%s' % ( gv_result.operand2(), cmp, gv_x.operand(), nullstr)) return gv_result
def genop_setarrayitem(self, arraytoken, gv_ptr, gv_index, gv_value): array_length_offset, array_items_offset, item_size, item_type = arraytoken log('%s Builder.genop_setarrayitem %s,%s[%s]=%s' % ( self.block.label, arraytoken, gv_ptr.operand(), gv_index.operand(), gv_value.operand())) gv_ptr_var = self._as_var(gv_ptr) gv_p = Var(gv_ptr_var.type) self.asm.append(' %s=getelementptr %s,%s %s' % ( gv_p.operand2(), gv_ptr_var.operand(), i32, array_items_offset)) gv_p2 = self._cast_to(gv_p, item_type + '*') gv_p3 = Var(gv_p2.type) self.asm.append(' %s=getelementptr %s,%s' % ( gv_p3.operand2(), gv_p2.operand(), gv_index.operand())) self.asm.append(' store %s,%s' % ( gv_value.operand(), gv_p3.operand()))
def genop_setfield(self, fieldtoken, gv_ptr, gv_value): offset, fieldtype = fieldtoken log('%s Builder.genop_setfield (%d,%s) %s=%s' % ( self.block.label, offset, fieldtype, gv_ptr.operand(), gv_value.operand())) gv_ptr_var = self._as_var(gv_ptr) gv_p = Var(gv_ptr.type) self.asm.append(' %s=getelementptr %s,%s %s' % ( gv_p.operand2(), gv_ptr_var.operand(), i32, offset)) gv_p2 = self._cast_to(gv_p, fieldtype + '*') self.asm.append(' store %s,%s' % ( gv_value.operand(), gv_p2.operand()))
def _cast_to(self, gv_x, restype=None): t = gv_x.type restype = restype or t if restype is t: return self.genop_same_as(None, gv_x) gv_result = Var(restype) if restype[-1] == '*': if gv_x.is_const: cst = inttoptr t = i32 else: cst = bitcast else: cst = zext self.asm.append(' %s=%s %s %s to %s ;2' % ( gv_result.operand2(), cst, t, gv_x.operand2(), restype)) return gv_result
def genop_same_as(self, kind, gv_x): #XXX why do we need a 'kind' here? if gv_x.is_const: # must always return a var restype = gv_x.type gv_result = Var(restype) v = gv_x.operand2() if restype[-1] == '*': cst = inttoptr t = i32 if v == 'null': v = '0' else: cst = bitcast t = restype self.asm.append(' %s=%s %s %s to %s ;1' % ( gv_result.operand2(), cst, t, v, restype)) return gv_result else: return gv_x
def genop_getarraysubstruct(self, arraytoken, gv_ptr, gv_index): ''' self.mc.MOV(edx, gv_ptr.operand(self)) op = self.itemaddr(edx, arraytoken, gv_index) self.mc.LEA(eax, op) return self.returnvar(eax) ''' #XXX WIP log('%s Builder.genop_getarraysubstruct %s,%s,%s' % ( self.block.label, arraytoken, gv_ptr.operand(), gv_index.operand())) array_length_offset, array_items_offset, item_size, item_type = arraytoken op_size = self._itemaddr(arraytoken, gv_index) gv_ptr_var = self._as_var(gv_ptr) gv_result = Var(pi8) self.asm.append(' %s=getelementptr %s,%s' % ( gv_result.operand2(), gv_ptr_var.operand(), op_size.operand())) return gv_result
def __init__(self, sigtoken, name): self.name = name self.sigtoken = sigtoken argtypes, restype = sigtoken self.inputargs = [Var(type) for type in argtypes]
def op_bool_not(self, gv_x): gv_result = Var(i1) self.asm.append(' %s=select %s,%s false,%s true' % ( gv_result.operand2(), gv_x.operand(), i1, i1)) return gv_result