/// Replace load sequence which may contain /// a chain of struct_element_addr followed by a load. /// The sequence is traversed starting from the load /// instruction. static SILValue convertLoadSequence(SILValue oldSequence, SILValue newRootValue, SILBuilder &B) { if (isa<GlobalAddrInst>(oldSequence)) return newRootValue; if (auto *LI = dyn_cast<LoadInst>(oldSequence)) { auto newValue = convertLoadSequence(LI->getOperand(), newRootValue, B); LI->replaceAllUsesWith(newValue); return newValue; } // It is a series of struct_element_addr followed by load. if (auto *SEAI = dyn_cast<StructElementAddrInst>(oldSequence)) { auto newValue = convertLoadSequence(SEAI->getOperand(), newRootValue, B); newValue = B.createStructExtract(SEAI->getLoc(), newValue, SEAI->getField()); return newValue; } if (auto *TEAI = dyn_cast<TupleElementAddrInst>(oldSequence)) { auto newValue = convertLoadSequence(TEAI->getOperand(), newRootValue, B); newValue = B.createTupleExtract(TEAI->getLoc(), newValue, TEAI->getFieldNo()); return newValue; } llvm_unreachable("Unknown instruction sequence for reading from a global"); return nullptr; }
SILValue SROAMemoryUseAnalyzer::createAggProjection(SILBuilder &B, SILLocation Loc, SILValue Operand, unsigned EltNo) { if (TT) return B.createTupleExtract(Loc, Operand, EltNo); assert(SD && "SD should not be null since either it or TT must be set at " "this point."); auto Properties = SD->getStoredProperties(); unsigned Counter = 0; for (auto *D : Properties) if (Counter++ == EltNo) return B.createStructExtract(Loc, Operand, D); llvm_unreachable("Unknown field."); }
NullablePtr<SILInstruction> Projection:: createValueProjection(SILBuilder &B, SILLocation Loc, SILValue Base) const { // Grab Base's type. SILType BaseTy = Base.getType(); // If BaseTy is not an object type, bail. if (!BaseTy.isObject()) return nullptr; // If this projection is associated with an address type, convert its type to // an object type. // // We explicitly do not convert Type to be an object if it is a local storage // type since we want it to fail. SILType Ty = Type.isAddress()? Type.getObjectType() : Type; if (!Ty.isObject()) 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.createStructExtract(Loc, Base, cast<VarDecl>(getDecl())); case ProjectionKind::Tuple: return B.createTupleExtract(Loc, Base, getIndex()); case ProjectionKind::Index: return nullptr; case ProjectionKind::Enum: return B.createUncheckedEnumData(Loc, Base, cast<EnumElementDecl>(getDecl())); case ProjectionKind::Class: return nullptr; } }