def direct_fieldptr(self, opr): from pypy.translator.llvm.typedefnode import getindexhelper op = opr.op assert opr.rettype != "void" index = getindexhelper(self.db, op.args[1].value, op.args[0].concretetype.TO) assert index != -1 tmpvar = self._tmp() self.codewriter.getelementptr(tmpvar, opr.argtypes[0], opr.argrefs[0], [(self.word, index)]) # getelementptr gets a pointer to the right type, except the generated code really expected # an array of size 1... so we just cast it element_type = self.db.repr_type(op.result.concretetype.TO.OF) + '*' self.codewriter.cast(opr.retref, element_type, tmpvar, opr.rettype)
def get_offset(self, value, indices): " return (from_type, (indices, ...), to_type) " word = self.database.get_machine_word() if isinstance(value, llmemory.ItemOffset): if not indices: indices.append((word, 0)) # skips over a fixed size item (eg array access) from_ = value.TYPE if from_ is not lltype.Void: lasttype, lastvalue = indices[-1] assert lasttype == word indices[-1] = (word, lastvalue + value.repeat) to = value.TYPE elif isinstance(value, llmemory.FieldOffset): if not indices: indices.append((word, 0)) # jumps to a field position in a struct from_ = value.TYPE pos = getindexhelper(self.database, value.fldname, value.TYPE) indices.append((word, pos)) to = getattr(value.TYPE, value.fldname) elif isinstance(value, llmemory.ArrayLengthOffset): assert not value.TYPE._hints.get("nolength", False) if not indices: indices.append((word, 0)) # jumps to the place where the array length is stored from_ = value.TYPE # <Array of T> or <GcArray of T> assert isinstance(value.TYPE, lltype.Array) typedefnode = self.database.obj2node[value.TYPE] indexref = typedefnode.indexref_for_length() indices.append((word, indexref)) to = lltype.Signed elif isinstance(value, llmemory.ArrayItemsOffset): if not indices: if isinstance(value.TYPE, lltype.Array) and value.TYPE._hints.get("nolength", False): pass else: indices.append((word, 0)) if value.TYPE.OF is lltype.Void: # skip over the whole structure in order to get to the # (not-really-existent) array part return self.get_offset(llmemory.ItemOffset(value.TYPE), indices) # jumps to the beginning of array area from_ = value.TYPE if not isinstance(value.TYPE, lltype.FixedSizeArray) and not value.TYPE._hints.get("nolength", False): typedefnode = self.database.obj2node[value.TYPE] indexref = typedefnode.indexref_for_items() indices.append((word, indexref)) indices.append((word, 0)) # go to the 1st item if isinstance(value.TYPE, lltype.FixedSizeArray): indices.append((word, 0)) # go to the 1st item to = value.TYPE.OF elif isinstance(value, llmemory.CompositeOffset): from_, indices, to = self.get_offset(value.offsets[0], indices) for item in value.offsets[1:]: _, indices, to1 = self.get_offset(item, indices) if to1 is not lltype.Void: to = to1 else: raise Exception("unsupported offset") return from_, indices, to