NullablePtr<SILInstruction> Projection:: createAddrProjection(SILBuilder &B, SILLocation Loc, SILValue Base) const { // Grab Base's type. SILType BaseTy = Base.getType(); // If BaseTy is not an address type, bail. if (!BaseTy.isAddress()) return nullptr; // If this projection is associated with an object type, convert its type to // an address type. // // *NOTE* We purposely do not handle local storage types here since we want to // always fail in such a case. That is handled by checking that Ty is an // address. SILType Ty = Type.isObject()? Type.getAddressType() : Type; if (!Ty.isAddress()) return nullptr; // Ok, we now know that the type of Base and the type represented by the base // of this projection match and that this projection can be represented as // value. Create the instruction if we can. Otherwise, return nullptr. switch (getKind()) { case ProjectionKind::Struct: return B.createStructElementAddr(Loc, Base, cast<VarDecl>(getDecl())); case ProjectionKind::Tuple: return B.createTupleElementAddr(Loc, Base, getIndex()); case ProjectionKind::Index: { auto Ty = SILType::getBuiltinIntegerType(32, B.getASTContext()); auto *IntLiteral = B.createIntegerLiteral(Loc, Ty, getIndex()); return B.createIndexAddr(Loc, Base, IntLiteral); } case ProjectionKind::Enum: return B.createUncheckedTakeEnumDataAddr(Loc, Base, cast<EnumElementDecl>(getDecl())); case ProjectionKind::Class: return B.createRefElementAddr(Loc, Base, cast<VarDecl>(getDecl())); } }
/// Given an index_raw_pointer Ptr, size_of(Metatype) * Distance create an /// address_to_pointer (index_addr ptr, Distance : $*Metatype) : $RawPointer /// instruction. static SILValue createIndexAddrFrom(IndexRawPointerInst *I, MetatypeInst *Metatype, BuiltinInst *TruncOrBitCast, SILValue Ptr, SILValue Distance, SILType RawPointerTy, SILBuilder &Builder) { Builder.setCurrentDebugScope(I->getDebugScope()); SILType InstanceType = Metatype->getType().getMetatypeInstanceType(I->getModule()); // index_raw_pointer's address type is currently always strict. auto *NewPTAI = Builder.createPointerToAddress( I->getLoc(), Ptr, InstanceType.getAddressType(), /*isStrict*/ true, /*isInvariant*/ false); auto *DistanceAsWord = Builder.createBuiltin(I->getLoc(), TruncOrBitCast->getName(), TruncOrBitCast->getType(), {}, Distance); auto *NewIAI = Builder.createIndexAddr(I->getLoc(), NewPTAI, DistanceAsWord); auto *NewATPI = Builder.createAddressToPointer(I->getLoc(), NewIAI, RawPointerTy); return NewATPI; }