def getinteriorfieldargs(self, hop, v_self): vlist = [] if None in self.v_offsets: INTERIOR_TYPE = v_self.concretetype.TO nameiter = iter(INTERIOR_TYPE._names) name = nameiter.next() vlist.append( hop.genop( 'getfield', [v_self, flowmodel.Constant(name, lltype.Void)], resulttype=INTERIOR_TYPE._flds[name])) else: vlist.append(v_self) for v_offset in self.v_offsets: if v_offset is None: name = nameiter.next() vlist.append( hop.genop( 'getfield', [v_self, flowmodel.Constant(name, lltype.Void)], resulttype=INTERIOR_TYPE._flds[name])) else: vlist.append(v_offset) if None in self.v_offsets: try: nameiter.next() except StopIteration: pass else: assert False return vlist
class __extend__(pairtype(InteriorPtrRepr, IntegerRepr)): def rtype_getitem((r_ptr, r_item), hop): ARRAY = r_ptr.resulttype.TO ITEM_TYPE = ARRAY.OF if isinstance(ITEM_TYPE, lltype.ContainerType): v_array, v_index = hop.inputargs(r_ptr, lltype.Signed) INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index( ITEM_TYPE) cflags = hop.inputconst(lltype.Void, {'flavor': 'gc'}) args = [flowmodel.Constant(INTERIOR_PTR_TYPE, lltype.Void), cflags] v_interior_ptr = hop.genop( 'malloc', args, resulttype=lltype.Ptr(INTERIOR_PTR_TYPE)) hop.genop('setfield', [ v_interior_ptr, flowmodel.Constant('ptr', lltype.Void), v_array ]) hop.genop('setfield', [ v_interior_ptr, flowmodel.Constant('index', lltype.Void), v_index ]) return v_interior_ptr else: v_self, v_index = hop.inputargs(r_ptr, lltype.Signed) vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index] return hop.genop('getinteriorfield', vlist, resulttype=ITEM_TYPE)
def newgraph(gv_FUNCTYPE, name): FUNCTYPE = _from_opaque(gv_FUNCTYPE).value # 'name' is just a way to track things name = from_opaque_string(name) inputargs = [] erasedinputargs = [] for ARG in FUNCTYPE.ARGS: v = flowmodel.Variable() v.concretetype = ARG inputargs.append(v) v = flowmodel.Variable() v.concretetype = lltype.erasedType(ARG) erasedinputargs.append(v) startblock = flowmodel.Block(inputargs) # insert an exploding operation here which is removed by # builder.end() to ensure that builder.end() is actually called. startblock.operations.append( flowmodel.SpaceOperation("debug_assert", [ flowmodel.Constant(False, lltype.Bool), flowmodel.Constant("you didn't call builder.end()?", lltype.Void) ], varoftype(lltype.Void))) return_var = flowmodel.Variable() return_var.concretetype = FUNCTYPE.RESULT graph = flowmodel.FunctionGraph(name, startblock, return_var) v1 = flowmodel.Variable() v1.concretetype = lltype.erasedType(FUNCTYPE.RESULT) graph.prereturnblock = flowmodel.Block([v1]) casting_link(graph.prereturnblock, [v1], graph.returnblock) substartblock = flowmodel.Block(erasedinputargs) casting_link(graph.startblock, inputargs, substartblock) fptr = lltype.functionptr(FUNCTYPE, name, graph=graph) return genconst(fptr)
def test_sbwk_should_insert_keepalives(): # this is testing something like: # v0 <- op_producing_non_gc # v1 <- op_using_v0 <- split here llops = LowLevelOpList() ptr_a = varoftype(lltype.Ptr(GcA)) v_res = llops.genop("getfield", [ptr_a, model.Constant('b', lltype.Void)], resulttype=lltype.Ptr(NonGcB)) llops.genop("direct_call", [model.Constant(None, lltype.Void), v_res], resulttype=lltype.Void) block = model.Block([ptr_a]) block.operations.extend(llops) block.closeblock(model.Link([], None)) link = split_block_with_keepalive(block, 1) assert 'keepalive' in [op.opname for op in link.target.operations]
def assign(mangled_name, value): if isinstance(value, flowmodel.Constant) and isinstance( value.value, staticmethod): value = flowmodel.Constant(value.value.__get__( 42)) # staticmethod => bare function llvalue = r.convert_desc_or_const(value) setattr(meta_instance, mangled_name, llvalue)
def rtype_simple_call(self, hop): hop2 = hop.copy() func = self.func s_func = hop.rtyper.annotator.bookkeeper.immutablevalue(func) v_ptr = hop2.args_v[0] hop2.r_s_popfirstarg() hop2.v_s_insertfirstarg(v_ptr, annmodel.lltype_to_annotation(self.ll_ptrtype)) hop2.v_s_insertfirstarg(flowmodel.Constant(func), s_func) return hop2.dispatch()
def genconst(llvalue): T = lltype.typeOf(llvalue) T1 = lltype.erasedType(T) if T1 != T: llvalue = lltype.cast_pointer(T1, llvalue) v = flowmodel.Constant(llvalue) v.concretetype = T1 if v.concretetype == lltype.Void: # XXX genconst should not really be used for Void constants assert not isinstance(llvalue, str) and not isinstance( llvalue, lltype.LowLevelType) return _to_opaque(v)
def test_nclc_nongc_not_passed_on(): # +--- inputargs: pointer_to_gc # | v0 <- op_getsubstruct pointer_to_gc 'b' # +--- exitargs: pointer_to_gc (i.e. the pointer to non-gc doesn't leave the block) llops = LowLevelOpList() ptr_a = varoftype(lltype.Ptr(GcA)) v_res = llops.genop("getsubstruct", [ptr_a, model.Constant('b', lltype.Void)], resulttype=lltype.Ptr(NonGcB)) block = model.Block([ptr_a]) block.operations.extend(llops) block.closeblock(model.Link([ptr_a], None)) assert not needs_conservative_livevar_calculation(block)
def test_nclc_should_be_true(): # this is testing a block like: # +--- inputargs: pointer_to_gc # | v0 <- op_getsubstruct pointer_to_gc 'b' # +--- exitargs: v0 (i.e. pointer to non-gc) llops = LowLevelOpList() ptr_a = varoftype(lltype.Ptr(GcA)) v_res = llops.genop("getsubstruct", [ptr_a, model.Constant('b', lltype.Void)], resulttype=lltype.Ptr(NonGcB)) block = model.Block([ptr_a]) block.operations.extend(llops) block.closeblock(model.Link([v_res], None)) assert needs_conservative_livevar_calculation(block)
def test_nclc_ignore_functype(): # +--- inputargs: pointer_to_gc # | v0 <- op_getfield pointer_to_gc 'c' # +--- exitargs: v0 (i.e. a pointer to function) # pointers to functions are 'not gc' but functions are also # immortal so you don't need to muck around inserting keepalives # so *they* don't die! llops = LowLevelOpList() ptr_a = varoftype(lltype.Ptr(GcA)) v_res = llops.genop("getfield", [ptr_a, model.Constant('c', lltype.Void)], resulttype=GcA.c) block = model.Block([ptr_a]) block.operations.extend(llops) block.closeblock(model.Link([v_res], None)) assert not needs_conservative_livevar_calculation(block)
def __init__(self, ptrtype): assert isinstance(ptrtype, lltype.InteriorPtr) self.v_offsets = [] numitemoffsets = 0 for i, offset in enumerate(ptrtype.offsets): if isinstance(offset, int): numitemoffsets += 1 self.v_offsets.append(None) else: assert isinstance(offset, str) self.v_offsets.append(flowmodel.Constant(offset, lltype.Void)) self.parentptrtype = lltype.Ptr(ptrtype.PARENTTYPE) self.resulttype = lltype.Ptr(ptrtype.TO) assert numitemoffsets <= 1 if numitemoffsets > 0: self.lowleveltype = lltype.Ptr(self.parentptrtype._interior_ptr_type_with_index(self.resulttype.TO)) else: self.lowleveltype = self.parentptrtype
def constTYPE(TYPE): assert isinstance(TYPE, lltype.LowLevelType) c = flowmodel.Constant(TYPE) c.concretetype = lltype.Void return _to_opaque(c)
def constFieldName(name): assert isinstance(name, str) c = flowmodel.Constant(name) c.concretetype = lltype.Void return _to_opaque(c)
def placeholder(dummy): c = flowmodel.Constant(dummy) c.concretetype = lltype.Void return _to_opaque(c)
def genzeroconst(gv_TYPE): TYPE = _from_opaque(gv_TYPE).value TYPE = lltype.erasedType(TYPE) c = flowmodel.Constant(TYPE._defl()) c.concretetype = TYPE return _to_opaque(c)