/// 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; }
void swift:: addRetainsForConvertedDirectResults(SILBuilder &Builder, SILLocation Loc, SILValue ReturnValue, SILInstruction *AI, ArrayRef<ResultDescriptor> DirectResults) { for (auto I : indices(DirectResults)) { auto &RV = DirectResults[I]; if (RV.CalleeRetain.empty()) continue; bool IsSelfRecursionEpilogueRetain = false; for (auto &X : RV.CalleeRetain) { IsSelfRecursionEpilogueRetain |= (AI == X); } // We do not create a retain if this ApplyInst is a self-recursion. if (IsSelfRecursionEpilogueRetain) continue; // Extract the return value if necessary. SILValue SpecificResultValue = ReturnValue; if (DirectResults.size() != 1) SpecificResultValue = Builder.createTupleExtract(Loc, ReturnValue, I); Builder.createRetainValue(Loc, SpecificResultValue); } }
/// Subtract a constant from a builtin integer value. static SILValue getSub(SILLocation Loc, SILValue Val, unsigned SubVal, SILBuilder &B) { SmallVector<SILValue, 4> Args(1, Val); Args.push_back(B.createIntegerLiteral(Loc, Val->getType(), SubVal)); Args.push_back(B.createIntegerLiteral( Loc, SILType::getBuiltinIntegerType(1, B.getASTContext()), -1)); auto *AI = B.createBuiltinBinaryFunctionWithOverflow( Loc, "ssub_with_overflow", Args); return B.createTupleExtract(Loc, AI, 0); }
static void addRetainsForConvertedDirectResults(SILBuilder &Builder, SILLocation Loc, SILValue ReturnValue, ArrayRef<ResultDescriptor> DirectResults) { for (auto I : indices(DirectResults)) { auto &RV = DirectResults[I]; if (RV.CalleeRetain.empty()) continue; // Extract the return value if necessary. SILValue SpecificResultValue = ReturnValue; if (DirectResults.size() != 1) SpecificResultValue = Builder.createTupleExtract(Loc, ReturnValue, I); Builder.createRetainValue(Loc, SpecificResultValue); } }
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; } }