summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CodeGenFunction.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.h')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h543
1 files changed, 352 insertions, 191 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 22f6f6c5a56..86154e923eb 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -81,6 +81,8 @@ class CGFunctionInfo;
class CGRecordLayout;
class CGBlockInfo;
class CGCXXABI;
+class BlockByrefHelpers;
+class BlockByrefInfo;
class BlockFlags;
class BlockFieldFlags;
@@ -160,9 +162,9 @@ public:
/// ReturnBlock - Unified return block.
JumpDest ReturnBlock;
- /// ReturnValue - The temporary alloca to hold the return value. This is null
- /// iff the function has no return value.
- llvm::Value *ReturnValue;
+ /// ReturnValue - The temporary alloca to hold the return
+ /// value. This is invalid iff the function has no return value.
+ Address ReturnValue;
/// AllocaInsertPoint - This is an instruction in the entry block before which
/// we prefer to insert allocas.
@@ -328,7 +330,7 @@ public:
/// A stack of exception code slots. Entering an __except block pushes a slot
/// on the stack and leaving pops one. The __exception_code() intrinsic loads
/// a value from the top of the stack.
- SmallVector<llvm::Value *, 1> SEHCodeSlotStack;
+ SmallVector<Address, 1> SEHCodeSlotStack;
/// Value returned by __exception_info intrinsic.
llvm::Value *SEHInfo = nullptr;
@@ -420,13 +422,12 @@ public:
/// complete-object destructor of an object of the given type at the
/// given address. Does nothing if T is not a C++ class type with a
/// non-trivial destructor.
- void PushDestructorCleanup(QualType T, llvm::Value *Addr);
+ void PushDestructorCleanup(QualType T, Address Addr);
/// PushDestructorCleanup - Push a cleanup to call the
/// complete-object variant of the given destructor on the object at
/// the given address.
- void PushDestructorCleanup(const CXXDestructorDecl *Dtor,
- llvm::Value *Addr);
+ void PushDestructorCleanup(const CXXDestructorDecl *Dtor, Address Addr);
/// PopCleanupBlock - Will pop the cleanup entry on the stack and
/// process all branch fixups.
@@ -556,13 +557,14 @@ public:
void rescopeLabels();
};
+ typedef llvm::DenseMap<const Decl *, Address> DeclMapTy;
+
/// \brief The scope used to remap some variables as private in the OpenMP
/// loop body (or other captured region emitted without outlining), and to
/// restore old vars back on exit.
class OMPPrivateScope : public RunCleanupsScope {
- typedef llvm::DenseMap<const VarDecl *, llvm::Value *> VarDeclMapTy;
- VarDeclMapTy SavedLocals;
- VarDeclMapTy SavedPrivates;
+ DeclMapTy SavedLocals;
+ DeclMapTy SavedPrivates;
private:
OMPPrivateScope(const OMPPrivateScope &) = delete;
@@ -579,21 +581,30 @@ public:
/// been privatized already.
bool
addPrivate(const VarDecl *LocalVD,
- const std::function<llvm::Value *()> &PrivateGen) {
+ llvm::function_ref<Address()> PrivateGen) {
assert(PerformCleanup && "adding private to dead scope");
- if (SavedLocals.count(LocalVD) > 0) return false;
- SavedLocals[LocalVD] = CGF.LocalDeclMap.lookup(LocalVD);
- CGF.LocalDeclMap.erase(LocalVD);
- auto *V = PrivateGen();
+
+ // Only save it once.
+ if (SavedLocals.count(LocalVD)) return false;
+
+ // Copy the existing local entry to SavedLocals.
+ auto it = CGF.LocalDeclMap.find(LocalVD);
+ if (it != CGF.LocalDeclMap.end()) {
+ SavedLocals.insert({LocalVD, it->second});
+ } else {
+ SavedLocals.insert({LocalVD, Address::invalid()});
+ }
+
+ // Generate the private entry.
+ Address Addr = PrivateGen();
QualType VarTy = LocalVD->getType();
if (VarTy->isReferenceType()) {
- auto *TempAlloca = CGF.CreateMemTemp(VarTy);
- LValue RefLVal = CGF.MakeNaturalAlignAddrLValue(TempAlloca, VarTy);
- CGF.EmitStoreOfScalar(V, RefLVal);
- V = TempAlloca;
+ Address Temp = CGF.CreateMemTemp(VarTy);
+ CGF.Builder.CreateStore(Addr.getPointer(), Temp);
+ Addr = Temp;
}
- SavedPrivates[LocalVD] = V;
- CGF.LocalDeclMap[LocalVD] = SavedLocals[LocalVD];
+ SavedPrivates.insert({LocalVD, Addr});
+
return true;
}
@@ -606,19 +617,14 @@ public:
/// private copies.
/// \return true if at least one variable was privatized, false otherwise.
bool Privatize() {
- for (auto VDPair : SavedPrivates) {
- CGF.LocalDeclMap[VDPair.first] = VDPair.second;
- }
+ copyInto(SavedPrivates, CGF.LocalDeclMap);
SavedPrivates.clear();
return !SavedLocals.empty();
}
void ForceCleanup() {
RunCleanupsScope::ForceCleanup();
- // Remap vars back to the original values.
- for (auto I : SavedLocals) {
- CGF.LocalDeclMap[I.first] = I.second;
- }
+ copyInto(SavedLocals, CGF.LocalDeclMap);
SavedLocals.clear();
}
@@ -627,6 +633,25 @@ public:
if (PerformCleanup)
ForceCleanup();
}
+
+ private:
+ /// Copy all the entries in the source map over the corresponding
+ /// entries in the destination, which must exist.
+ static void copyInto(const DeclMapTy &src, DeclMapTy &dest) {
+ for (auto &pair : src) {
+ if (!pair.second.isValid()) {
+ dest.erase(pair.first);
+ continue;
+ }
+
+ auto it = dest.find(pair.first);
+ if (it != dest.end()) {
+ it->second = pair.second;
+ } else {
+ dest.insert(pair);
+ }
+ }
+ }
};
/// \brief Takes the old cleanup stack size and emits the cleanup blocks
@@ -707,10 +732,11 @@ public:
/// one branch or the other of a conditional expression.
bool isInConditionalBranch() const { return OutermostConditional != nullptr; }
- void setBeforeOutermostConditional(llvm::Value *value, llvm::Value *addr) {
+ void setBeforeOutermostConditional(llvm::Value *value, Address addr) {
assert(isInConditionalBranch());
llvm::BasicBlock *block = OutermostConditional->getStartingBlock();
- new llvm::StoreInst(value, addr, &block->back());
+ auto store = new llvm::StoreInst(value, addr.getPointer(), &block->back());
+ store->setAlignment(addr.getAlignment().getQuantity());
}
/// An RAII object to record that we're evaluating a statement
@@ -869,15 +895,6 @@ public:
}
};
- /// getByrefValueFieldNumber - Given a declaration, returns the LLVM field
- /// number that holds the value.
- std::pair<llvm::Type *, unsigned>
- getByRefValueLLVMField(const ValueDecl *VD) const;
-
- /// BuildBlockByrefAddress - Computes address location of the
- /// variable which is declared as __block.
- llvm::Value *BuildBlockByrefAddress(llvm::Value *BaseAddr,
- const VarDecl *V);
private:
CGDebugInfo *DebugInfo;
bool DisableDebugInfo;
@@ -894,7 +911,6 @@ private:
/// LocalDeclMap - This keeps track of the LLVM allocas or globals for local C
/// decls.
- typedef llvm::DenseMap<const Decl*, llvm::Value*> DeclMapTy;
DeclMapTy LocalDeclMap;
/// Track escaped local variables with auto storage. Used during SEH
@@ -994,7 +1010,7 @@ public:
/// if we need to evaluate a CXXDefaultInitExpr within the evaluation.
class FieldConstructionScope {
public:
- FieldConstructionScope(CodeGenFunction &CGF, llvm::Value *This)
+ FieldConstructionScope(CodeGenFunction &CGF, Address This)
: CGF(CGF), OldCXXDefaultInitExprThis(CGF.CXXDefaultInitExprThis) {
CGF.CXXDefaultInitExprThis = This;
}
@@ -1004,7 +1020,7 @@ public:
private:
CodeGenFunction &CGF;
- llvm::Value *OldCXXDefaultInitExprThis;
+ Address OldCXXDefaultInitExprThis;
};
/// The scope of a CXXDefaultInitExpr. Within this scope, the value of 'this'
@@ -1012,16 +1028,20 @@ public:
class CXXDefaultInitExprScope {
public:
CXXDefaultInitExprScope(CodeGenFunction &CGF)
- : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue) {
- CGF.CXXThisValue = CGF.CXXDefaultInitExprThis;
+ : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue),
+ OldCXXThisAlignment(CGF.CXXThisAlignment) {
+ CGF.CXXThisValue = CGF.CXXDefaultInitExprThis.getPointer();
+ CGF.CXXThisAlignment = CGF.CXXDefaultInitExprThis.getAlignment();
}
~CXXDefaultInitExprScope() {
CGF.CXXThisValue = OldCXXThisValue;
+ CGF.CXXThisAlignment = OldCXXThisAlignment;
}
public:
CodeGenFunction &CGF;
llvm::Value *OldCXXThisValue;
+ CharUnits OldCXXThisAlignment;
};
private:
@@ -1030,10 +1050,12 @@ private:
ImplicitParamDecl *CXXABIThisDecl;
llvm::Value *CXXABIThisValue;
llvm::Value *CXXThisValue;
+ CharUnits CXXABIThisAlignment;
+ CharUnits CXXThisAlignment;
/// The value of 'this' to use when evaluating CXXDefaultInitExprs within
/// this expression.
- llvm::Value *CXXDefaultInitExprThis;
+ Address CXXDefaultInitExprThis = Address::invalid();
/// CXXStructorImplicitParamDecl - When generating code for a constructor or
/// destructor, this will hold the implicit argument (e.g. VTT).
@@ -1052,10 +1074,9 @@ private:
/// handling code.
SourceLocation CurEHLocation;
- /// ByrefValueInfoMap - For each __block variable, contains a pair of the LLVM
- /// type as well as the field number that contains the actual data.
- llvm::DenseMap<const ValueDecl *, std::pair<llvm::Type *,
- unsigned> > ByRefValueInfo;
+ /// BlockByrefInfos - For each __block variable, contains
+ /// information about the layout of the variable.
+ llvm::DenseMap<const ValueDecl *, BlockByrefInfo> BlockByrefInfos;
llvm::BasicBlock *TerminateLandingPad;
llvm::BasicBlock *TerminateHandler;
@@ -1096,15 +1117,15 @@ public:
/// Returns a pointer to the function's exception object and selector slot,
/// which is assigned in every landing pad.
- llvm::Value *getExceptionSlot();
- llvm::Value *getEHSelectorSlot();
+ Address getExceptionSlot();
+ Address getEHSelectorSlot();
/// Returns the contents of the function's exception object and selector
/// slots.
llvm::Value *getExceptionFromSlot();
llvm::Value *getSelectorFromSlot();
- llvm::Value *getNormalCleanupDestSlot();
+ Address getNormalCleanupDestSlot();
llvm::BasicBlock *getUnreachableBlock() {
if (!UnreachableBlock) {
@@ -1131,38 +1152,41 @@ public:
// Cleanups
//===--------------------------------------------------------------------===//
- typedef void Destroyer(CodeGenFunction &CGF, llvm::Value *addr, QualType ty);
+ typedef void Destroyer(CodeGenFunction &CGF, Address addr, QualType ty);
void pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin,
- llvm::Value *arrayEndPointer,
+ Address arrayEndPointer,
QualType elementType,
+ CharUnits elementAlignment,
Destroyer *destroyer);
void pushRegularPartialArrayCleanup(llvm::Value *arrayBegin,
llvm::Value *arrayEnd,
QualType elementType,
+ CharUnits elementAlignment,
Destroyer *destroyer);
void pushDestroy(QualType::DestructionKind dtorKind,
- llvm::Value *addr, QualType type);
+ Address addr, QualType type);
void pushEHDestroy(QualType::DestructionKind dtorKind,
- llvm::Value *addr, QualType type);
- void pushDestroy(CleanupKind kind, llvm::Value *addr, QualType type,
+ Address addr, QualType type);
+ void pushDestroy(CleanupKind kind, Address addr, QualType type,
Destroyer *destroyer, bool useEHCleanupForArray);
- void pushLifetimeExtendedDestroy(CleanupKind kind, llvm::Value *addr,
+ void pushLifetimeExtendedDestroy(CleanupKind kind, Address addr,
QualType type, Destroyer *destroyer,
bool useEHCleanupForArray);
void pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete,
llvm::Value *CompletePtr,
QualType ElementType);
- void pushStackRestore(CleanupKind kind, llvm::Value *SPMem);
- void emitDestroy(llvm::Value *addr, QualType type, Destroyer *destroyer,
+ void pushStackRestore(CleanupKind kind, Address SPMem);
+ void emitDestroy(Address addr, QualType type, Destroyer *destroyer,
bool useEHCleanupForArray);
- llvm::Function *generateDestroyHelper(llvm::Constant *addr, QualType type,
+ llvm::Function *generateDestroyHelper(Address addr, QualType type,
Destroyer *destroyer,
bool useEHCleanupForArray,
const VarDecl *VD);
void emitArrayDestroy(llvm::Value *begin, llvm::Value *end,
- QualType type, Destroyer *destroyer,
+ QualType elementType, CharUnits elementAlign,
+ Destroyer *destroyer,
bool checkZeroLength, bool useEHCleanup);
Destroyer *getDestroyer(QualType::DestructionKind destructionKind);
@@ -1248,15 +1272,25 @@ public:
void emitByrefStructureInit(const AutoVarEmission &emission);
void enterByrefCleanup(const AutoVarEmission &emission);
- llvm::Value *LoadBlockStruct() {
- assert(BlockPointer && "no block pointer set!");
- return BlockPointer;
- }
+ void setBlockContextParameter(const ImplicitParamDecl *D, unsigned argNum,
+ llvm::Value *ptr);
+
+ Address LoadBlockStruct();
void AllocateBlockCXXThisPointer(const CXXThisExpr *E);
void AllocateBlockDecl(const DeclRefExpr *E);
- llvm::Value *GetAddrOfBlockDecl(const VarDecl *var, bool ByRef);
- llvm::Type *BuildByRefType(const VarDecl *var);
+ Address GetAddrOfBlockDecl(const VarDecl *var, bool ByRef);
+
+ /// BuildBlockByrefAddress - Computes the location of the
+ /// data in a variable which is declared as __block.
+ Address emitBlockByrefAddress(Address baseAddr, const VarDecl *V,
+ bool followForward = true);
+ Address emitBlockByrefAddress(Address baseAddr,
+ const BlockByrefInfo &info,
+ bool followForward,
+ const llvm::Twine &name);
+
+ const BlockByrefInfo &getBlockByrefInfo(const VarDecl *var);
void GenerateCode(GlobalDecl GD, llvm::Function *Fn,
const CGFunctionInfo &FnInfo);
@@ -1300,6 +1334,8 @@ public:
void EmitCallAndReturnForThunk(llvm::Value *Callee, const ThunkInfo *Thunk);
+ void FinishThunk();
+
/// Emit a musttail call for a thunk with a potentially adjusted this pointer.
void EmitMustTailThunk(const CXXMethodDecl *MD, llvm::Value *AdjustedThisPtr,
llvm::Value *Callee);
@@ -1338,7 +1374,7 @@ public:
/// GetVTablePtr - Return the Value of the vtable pointer member pointed
/// to by This.
- llvm::Value *GetVTablePtr(llvm::Value *This, llvm::Type *Ty);
+ llvm::Value *GetVTablePtr(Address This, llvm::Type *Ty);
enum CFITypeCheckKind {
CFITCK_VCall,
@@ -1505,39 +1541,79 @@ public:
// Helpers
//===--------------------------------------------------------------------===//
- LValue MakeAddrLValue(llvm::Value *V, QualType T,
- CharUnits Alignment = CharUnits()) {
- return LValue::MakeAddr(V, T, Alignment, getContext(),
+ LValue MakeAddrLValue(Address Addr, QualType T,
+ AlignmentSource AlignSource = AlignmentSource::Type) {
+ return LValue::MakeAddr(Addr, T, getContext(), AlignSource,
CGM.getTBAAInfo(T));
}
+ LValue MakeAddrLValue(llvm::Value *V, QualType T, CharUnits Alignment,
+ AlignmentSource AlignSource = AlignmentSource::Type) {
+ return LValue::MakeAddr(Address(V, Alignment), T, getContext(),
+ AlignSource, CGM.getTBAAInfo(T));
+ }
+
+ LValue MakeNaturalAlignPointeeAddrLValue(llvm::Value *V, QualType T);
LValue MakeNaturalAlignAddrLValue(llvm::Value *V, QualType T);
+ CharUnits getNaturalTypeAlignment(QualType T,
+ AlignmentSource *Source = nullptr,
+ bool forPointeeType = false);
+ CharUnits getNaturalPointeeTypeAlignment(QualType T,
+ AlignmentSource *Source = nullptr);
+
+ Address EmitLoadOfReference(Address Ref, const ReferenceType *RefTy,
+ AlignmentSource *Source = nullptr);
+ LValue EmitLoadOfReferenceLValue(Address Ref, const ReferenceType *RefTy);
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block. The caller is responsible for setting an appropriate alignment on
/// the alloca.
llvm::AllocaInst *CreateTempAlloca(llvm::Type *Ty,
const Twine &Name = "tmp");
+ Address CreateTempAlloca(llvm::Type *Ty, CharUnits align,
+ const Twine &Name = "tmp");
- /// InitTempAlloca - Provide an initial value for the given alloca.
- void InitTempAlloca(llvm::AllocaInst *Alloca, llvm::Value *Value);
+ /// CreateDefaultAlignedTempAlloca - This creates an alloca with the
+ /// default ABI alignment of the given LLVM type.
+ ///
+ /// IMPORTANT NOTE: This is *not* generally the right alignment for
+ /// any given AST type that happens to have been lowered to the
+ /// given IR type. This should only ever be used for function-local,
+ /// IR-driven manipulations like saving and restoring a value. Do
+ /// not hand this address off to arbitrary IRGen routines, and especially
+ /// do not pass it as an argument to a function that might expect a
+ /// properly ABI-aligned value.
+ Address CreateDefaultAlignTempAlloca(llvm::Type *Ty,
+ const Twine &Name = "tmp");
+
+ /// InitTempAlloca - Provide an initial value for the given alloca which
+ /// will be observable at all locations in the function.
+ ///
+ /// The address should be something that was returned from one of
+ /// the CreateTempAlloca or CreateMemTemp routines, and the
+ /// initializer must be valid in the entry block (i.e. it must
+ /// either be a constant or an argument value).
+ void InitTempAlloca(Address Alloca, llvm::Value *Value);
/// CreateIRTemp - Create a temporary IR object of the given type, with
/// appropriate alignment. This routine should only be used when an temporary
/// value needs to be stored into an alloca (for example, to avoid explicit
/// PHI construction), but the type is the IR type, not the type appropriate
/// for storing in memory.
- llvm::AllocaInst *CreateIRTemp(QualType T, const Twine &Name = "tmp");
+ ///
+ /// That is, this is exactly equivalent to CreateMemTemp, but calling
+ /// ConvertType instead of ConvertTypeForMem.
+ Address CreateIRTemp(QualType T, const Twine &Name = "tmp");
/// CreateMemTemp - Create a temporary memory object of the given type, with
/// appropriate alignment.
- llvm::AllocaInst *CreateMemTemp(QualType T, const Twine &Name = "tmp");
+ Address CreateMemTemp(QualType T, const Twine &Name = "tmp");
+ Address CreateMemTemp(QualType T, CharUnits Align, const Twine &Name = "tmp");
/// CreateAggTemp - Create a temporary memory object for the given
/// aggregate type.
AggValueSlot CreateAggTemp(QualType T, const Twine &Name = "tmp") {
- CharUnits Alignment = getContext().getTypeAlignInChars(T);
- return AggValueSlot::forAddr(CreateMemTemp(T, Name), Alignment,
+ return AggValueSlot::forAddr(CreateMemTemp(T, Name),
T.getQualifiers(),
AggValueSlot::IsNotDestructed,
AggValueSlot::DoesNotNeedGCBarriers,
@@ -1570,7 +1646,7 @@ public:
// EmitVAListRef - Emit a "reference" to a va_list; this is either the address
// or the value of the expression, depending on how va_list is defined.
- llvm::Value *EmitVAListRef(const Expr *E);
+ Address EmitVAListRef(const Expr *E);
/// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result will
/// always be accessible even if no aggregate location is provided.
@@ -1578,10 +1654,10 @@ public:
/// EmitAnyExprToMem - Emits the code necessary to evaluate an
/// arbitrary expression into the given memory location.
- void EmitAnyExprToMem(const Expr *E, llvm::Value *Location,
+ void EmitAnyExprToMem(const Expr *E, Address Location,
Qualifiers Quals, bool IsInitializer);
- void EmitAnyExprToExn(const Expr *E, llvm::Value *Addr);
+ void EmitAnyExprToExn(const Expr *E, Address Addr);
/// EmitExprAsInit - Emits the code necessary to initialize a
/// location in memory with the given initializer.
@@ -1601,19 +1677,15 @@ public:
///
/// The difference to EmitAggregateCopy is that tail padding is not copied.
/// This is required for correctness when assigning non-POD structures in C++.
- void EmitAggregateAssign(llvm::Value *DestPtr, llvm::Value *SrcPtr,
+ void EmitAggregateAssign(Address DestPtr, Address SrcPtr,
QualType EltTy) {
bool IsVolatile = hasVolatileMember(EltTy);
- EmitAggregateCopy(DestPtr, SrcPtr, EltTy, IsVolatile, CharUnits::Zero(),
- true);
+ EmitAggregateCopy(DestPtr, SrcPtr, EltTy, IsVolatile, true);
}
- void EmitAggregateCopyCtor(llvm::Value *DestPtr, llvm::Value *SrcPtr,
- QualType DestTy, QualType SrcTy) {
- CharUnits DestTypeAlign = getContext().getTypeAlignInChars(DestTy);
- CharUnits SrcTypeAlign = getContext().getTypeAlignInChars(SrcTy);
+ void EmitAggregateCopyCtor(Address DestPtr, Address SrcPtr,
+ QualType DestTy, QualType SrcTy) {
EmitAggregateCopy(DestPtr, SrcPtr, SrcTy, /*IsVolatile=*/false,
- std::min(DestTypeAlign, SrcTypeAlign),
/*IsAssignment=*/false);
}
@@ -1623,9 +1695,8 @@ public:
/// volatile.
/// \param isAssignment - If false, allow padding to be copied. This often
/// yields more efficient.
- void EmitAggregateCopy(llvm::Value *DestPtr, llvm::Value *SrcPtr,
+ void EmitAggregateCopy(Address DestPtr, Address SrcPtr,
QualType EltTy, bool isVolatile=false,
- CharUnits Alignment = CharUnits::Zero(),
bool isAssignment = false);
/// StartBlock - Start new block named N. If insert block is a dummy block
@@ -1633,10 +1704,11 @@ public:
void StartBlock(const char *N);
/// GetAddrOfLocalVar - Return the address of a local variable.
- llvm::Value *GetAddrOfLocalVar(const VarDecl *VD) {
- llvm::Value *Res = LocalDeclMap[VD];
- assert(Res && "Invalid argument to GetAddrOfLocalVar(), no decl!");
- return Res;
+ Address GetAddrOfLocalVar(const VarDecl *VD) {
+ auto it = LocalDeclMap.find(VD);
+ assert(it != LocalDeclMap.end() &&
+ "Invalid argument to GetAddrOfLocalVar(), no decl!");
+ return it->second;
}
/// getOpaqueLValueMapping - Given an opaque value expression (which
@@ -1671,19 +1743,19 @@ public:
/// EmitNullInitialization - Generate code to set a value of the given type to
/// null, If the type contains data member pointers, they will be initialized
/// to -1 in accordance with the Itanium C++ ABI.
- void EmitNullInitialization(llvm::Value *DestPtr, QualType Ty);
+ void EmitNullInitialization(Address DestPtr, QualType Ty);
// EmitVAArg - Generate code to get an argument from the passed in pointer
// and update it accordingly. The return value is a pointer to the argument.
// FIXME: We should be able to get rid of this method and use the va_arg
// instruction in LLVM instead once it works well enough.
- llvm::Value *EmitVAArg(llvm::Value *VAListAddr, QualType Ty);
+ Address EmitVAArg(Address VAListAddr, QualType Ty);
/// emitArrayLength - Compute the length of an array, even if it's a
/// VLA, and drill down to the base element type.
llvm::Value *emitArrayLength(const ArrayType *arrayType,
QualType &baseType,
- llvm::Value *&addr);
+ Address &addr);
/// EmitVLASize - Capture all the sizes for the VLA expressions in
/// the given variably-modified type and store them in the VLASizeMap.
@@ -1704,6 +1776,7 @@ public:
assert(CXXThisValue && "no 'this' value for this function");
return CXXThisValue;
}
+ Address LoadCXXThisAddress();
/// LoadCXXVTT - Load the VTT parameter to base constructors/destructors have
/// virtual bases.
@@ -1724,25 +1797,27 @@ public:
/// GetAddressOfBaseOfCompleteClass - Convert the given pointer to a
/// complete class to the given direct base.
- llvm::Value *
- GetAddressOfDirectBaseInCompleteClass(llvm::Value *Value,
+ Address
+ GetAddressOfDirectBaseInCompleteClass(Address Value,
const CXXRecordDecl *Derived,
const CXXRecordDecl *Base,
bool BaseIsVirtual);
+ static bool ShouldNullCheckClassCastValue(const CastExpr *Cast);
+
/// GetAddressOfBaseClass - This function will add the necessary delta to the
/// load of 'this' and returns address of the base class.
- llvm::Value *GetAddressOfBaseClass(llvm::Value *Value,
- const CXXRecordDecl *Derived,
- CastExpr::path_const_iterator PathBegin,
- CastExpr::path_const_iterator PathEnd,
- bool NullCheckValue, SourceLocation Loc);
-
- llvm::Value *GetAddressOfDerivedClass(llvm::Value *Value,
- const CXXRecordDecl *Derived,
- CastExpr::path_const_iterator PathBegin,
- CastExpr::path_const_iterator PathEnd,
- bool NullCheckValue);
+ Address GetAddressOfBaseClass(Address Value,
+ const CXXRecordDecl *Derived,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
+ bool NullCheckValue, SourceLocation Loc);
+
+ Address GetAddressOfDerivedClass(Address Value,
+ const CXXRecordDecl *Derived,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd,
+ bool NullCheckValue);
/// GetVTTParameter - Return the VTT parameter that should be passed to a
/// base constructor/destructor with virtual bases.
@@ -1763,21 +1838,21 @@ public:
const FunctionArgList &Args);
void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type,
bool ForVirtualBase, bool Delegating,
- llvm::Value *This, const CXXConstructExpr *E);
+ Address This, const CXXConstructExpr *E);
void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
- llvm::Value *This, llvm::Value *Src,
- const CXXConstructExpr *E);
+ Address This, Address Src,
+ const CXXConstructExpr *E);
void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
const ConstantArrayType *ArrayTy,
- llvm::Value *ArrayPtr,
+ Address ArrayPtr,
const CXXConstructExpr *E,
bool ZeroInitialization = false);
void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D,
llvm::Value *NumElements,
- llvm::Value *ArrayPtr,
+ Address ArrayPtr,
const CXXConstructExpr *E,
bool ZeroInitialization = false);
@@ -1785,15 +1860,15 @@ public:
void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type,
bool ForVirtualBase, bool Delegating,
- llvm::Value *This);
+ Address This);
void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType,
- llvm::Type *ElementTy, llvm::Value *NewPtr,
+ llvm::Type *ElementTy, Address NewPtr,
llvm::Value *NumElements,
llvm::Value *AllocSizeWithoutCookie);
void EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType,
- llvm::Value *Ptr);
+ Address Ptr);
llvm::Value *EmitLifetimeStart(uint64_t Size, llvm::Value *Addr);
void EmitLifetimeEnd(llvm::Value *Size, llvm::Value *Addr);
@@ -1807,9 +1882,9 @@ public:
RValue EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
const Expr *Arg, bool IsDelete);
- llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E);
- llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE);
- llvm::Value* EmitCXXUuidofExpr(const CXXUuidofExpr *E);
+ llvm::Value *EmitCXXTypeidExpr(const CXXTypeidExpr *E);
+ llvm::Value *EmitDynamicCast(Address V, const CXXDynamicCastExpr *DCE);
+ Address EmitCXXUuidofExpr(const CXXUuidofExpr *E);
/// \brief Situations in which we might emit a check for the suitability of a
/// pointer or glvalue.
@@ -1906,12 +1981,9 @@ public:
const VarDecl *Variable;
- /// The alignment of the variable.
- CharUnits Alignment;
-
- /// The address of the alloca. Null if the variable was emitted
+ /// The address of the alloca. Invalid if the variable was emitted
/// as a global constant.
- llvm::Value *Address;
+ Address Addr;
llvm::Value *NRVOFlag;
@@ -1926,14 +1998,14 @@ public:
llvm::Value *SizeForLifetimeMarkers;
struct Invalid {};
- AutoVarEmission(Invalid) : Variable(nullptr) {}
+ AutoVarEmission(Invalid) : Variable(nullptr), Addr(Address::invalid()) {}
AutoVarEmission(const VarDecl &variable)
- : Variable(&variable), Address(nullptr), NRVOFlag(nullptr),
+ : Variable(&variable), Addr(Address::invalid()), NRVOFlag(nullptr),
IsByRef(false), IsConstantAggregate(false),
SizeForLifetimeMarkers(nullptr) {}
- bool wasEmittedAsGlobal() const { return Address == nullptr; }
+ bool wasEmittedAsGlobal() const { return !Addr.isValid(); }
public:
static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
@@ -1948,19 +2020,17 @@ public:
/// Returns the raw, allocated address, which is not necessarily
/// the address of the object itself.
- llvm::Value *getAllocatedAddress() const {
- return Address;
+ Address getAllocatedAddress() const {
+ return Addr;
}
/// Returns the address of the object within this declaration.
/// Note that this does not chase the forwarding pointer for
/// __block decls.
- llvm::Value *getObjectAddress(CodeGenFunction &CGF) const {
- if (!IsByRef) return Address;
+ Address getObjectAddress(CodeGenFunction &CGF) const {
+ if (!IsByRef) return Addr;
- auto F = CGF.getByRefValueLLVMField(Variable);
- return CGF.Builder.CreateStructGEP(F.first, Address, F.second,
- Variable->getNameAsString());
+ return CGF.emitBlockByrefAddress(Addr, Variable, /*forward*/ false);
}
};
AutoVarEmission EmitAutoVarAlloca(const VarDecl &var);
@@ -1972,9 +2042,35 @@ public:
void EmitStaticVarDecl(const VarDecl &D,
llvm::GlobalValue::LinkageTypes Linkage);
+ class ParamValue {
+ llvm::Value *Value;
+ unsigned Alignment;
+ ParamValue(llvm::Value *V, unsigned A) : Value(V), Alignment(A) {}
+ public:
+ static ParamValue forDirect(llvm::Value *value) {
+ return ParamValue(value, 0);
+ }
+ static ParamValue forIndirect(Address addr) {
+ assert(!addr.getAlignment().isZero());
+ return ParamValue(addr.getPointer(), addr.getAlignment().getQuantity());
+ }
+
+ bool isIndirect() const { return Alignment != 0; }
+ llvm::Value *getAnyValue() const { return Value; }
+
+ llvm::Value *getDirectValue() const {
+ assert(!isIndirect());
+ return Value;
+ }
+
+ Address getIndirectAddress() const {
+ assert(isIndirect());
+ return Address(Value, CharUnits::fromQuantity(Alignment));
+ }
+ };
+
/// EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl.
- void EmitParmDecl(const VarDecl &D, llvm::Value *Arg, bool ArgIsPointer,
- unsigned ArgNo);
+ void EmitParmDecl(const VarDecl &D, ParamValue Arg, unsigned ArgNo);
/// protectFromPeepholes - Protect a value that we're intending to
/// store to the side, but which will probably be used later, from
@@ -2011,11 +2107,11 @@ public:
/// \return True if the statement was handled.
bool EmitSimpleStmt(const Stmt *S);
- llvm::Value *EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
- AggValueSlot AVS = AggValueSlot::ignored());
- llvm::Value *EmitCompoundStmtWithoutScope(const CompoundStmt &S,
- bool GetLast = false,
- AggValueSlot AVS =
+ Address EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false,
+ AggValueSlot AVS = AggValueSlot::ignored());
+ Address EmitCompoundStmtWithoutScope(const CompoundStmt &S,
+ bool GetLast = false,
+ AggValueSlot AVS =
AggValueSlot::ignored());
/// EmitLabel - Emit the block for the given label. It is legal to call this
@@ -2085,9 +2181,9 @@ public:
/// either be an alloca or a call to llvm.localrecover if there are nested
/// outlined functions. ParentFP is the frame pointer of the outermost parent
/// frame.
- llvm::Value *recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF,
- llvm::Value *ParentVar,
- llvm::Value *ParentFP);
+ Address recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF,
+ Address ParentVar,
+ llvm::Value *ParentFP);
void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
ArrayRef<const Attr *> Attrs = None);
@@ -2097,7 +2193,7 @@ public:
void GenerateCapturedStmtFunctionProlog(const CapturedStmt &S);
llvm::Function *GenerateCapturedStmtFunctionEpilog(const CapturedStmt &S);
llvm::Function *GenerateCapturedStmtFunction(const CapturedStmt &S);
- llvm::Value *GenerateCapturedStmtArgument(const CapturedStmt &S);
+ Address GenerateCapturedStmtArgument(const CapturedStmt &S);
/// \brief Perform element by element copying of arrays with type \a
/// OriginalType from \a SrcAddr to \a DestAddr using copying procedure
/// generated by \a CopyGen.
@@ -2108,8 +2204,8 @@ public:
/// \param CopyGen Copying procedure that copies value of single array element
/// to another single array element.
void EmitOMPAggregateAssign(
- llvm::Value *DestAddr, llvm::Value *SrcAddr, QualType OriginalType,
- const llvm::function_ref<void(llvm::Value *, llvm::Value *)> &CopyGen);
+ Address DestAddr, Address SrcAddr, QualType OriginalType,
+ const llvm::function_ref<void(Address, Address)> &CopyGen);
/// \brief Emit proper copying of data from one variable to another.
///
/// \param OriginalType Original type of the copied variables.
@@ -2121,8 +2217,8 @@ public:
/// the base array element).
/// \param Copy Actual copygin expression for copying data from \a SrcVD to \a
/// DestVD.
- void EmitOMPCopy(CodeGenFunction &CGF, QualType OriginalType,
- llvm::Value *DestAddr, llvm::Value *SrcAddr,
+ void EmitOMPCopy(QualType OriginalType,
+ Address DestAddr, Address SrcAddr,
const VarDecl *DestVD, const VarDecl *SrcVD,
const Expr *Copy);
/// \brief Emit atomic update code for constructs: \a X = \a X \a BO \a E or
@@ -2258,8 +2354,8 @@ private:
void EmitOMPForOuterLoop(OpenMPScheduleClauseKind ScheduleKind,
const OMPLoopDirective &S,
OMPPrivateScope &LoopScope, bool Ordered,
- llvm::Value *LB, llvm::Value *UB, llvm::Value *ST,
- llvm::Value *IL, llvm::Value *Chunk);
+ Address LB, Address UB, Address ST,
+ Address IL, llvm::Value *Chunk);
/// \brief Emit code for sections directive.
OpenMPDirectiveKind EmitSections(const OMPExecutableDirective &S);
@@ -2306,7 +2402,7 @@ public:
/// that the address will be used to access the object.
LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK);
- RValue convertTempToRValue(llvm::Value *addr, QualType type,
+ RValue convertTempToRValue(Address addr, QualType type,
SourceLocation Loc);
void EmitAtomicInit(Expr *E, LValue lvalue);
@@ -2347,9 +2443,10 @@ public:
/// EmitLoadOfScalar - Load a scalar value from an address, taking
/// care to appropriately convert from the memory representation to
/// the LLVM value representation.
- llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile,
- unsigned Alignment, QualType Ty,
+ llvm::Value *EmitLoadOfScalar(Address Addr, bool Volatile, QualType Ty,
SourceLocation Loc,
+ AlignmentSource AlignSource =
+ AlignmentSource::Type,
llvm::MDNode *TBAAInfo = nullptr,
QualType TBAABaseTy = QualType(),
uint64_t TBAAOffset = 0);
@@ -2363,8 +2460,9 @@ public:
/// EmitStoreOfScalar - Store a scalar value to an address, taking
/// care to appropriately convert from the memory representation to
/// the LLVM value representation.
- void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr,
- bool Volatile, unsigned Alignment, QualType Ty,
+ void EmitStoreOfScalar(llvm::Value *Value, Address Addr,
+ bool Volatile, QualType Ty,
+ AlignmentSource AlignSource = AlignmentSource::Type,
llvm::MDNode *TBAAInfo = nullptr, bool isInit = false,
QualType TBAABaseTy = QualType(),
uint64_t TBAAOffset = 0);
@@ -2433,10 +2531,13 @@ public:
LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
- llvm::Value *EmitExtVectorElementLValue(LValue V);
+ Address EmitExtVectorElementLValue(LValue V);
RValue EmitRValueForField(LValue LV, const FieldDecl *FD, SourceLocation Loc);
+ Address EmitArrayToPointerDecay(const Expr *Array,
+ AlignmentSource *AlignSource = nullptr);
+
class ConstantEmission {
llvm::PointerIntPair<llvm::Constant*, 1, bool> ValueAndIsReference;
ConstantEmission(llvm::Constant *C, bool isReference)
@@ -2576,6 +2677,10 @@ public:
NestedNameSpecifier *Qualifier,
bool IsArrow, const Expr *Base);
// Compute the object pointer.
+ Address EmitCXXMemberDataPointerAddress(const Expr *E, Address base,
+ llvm::Value *memberPtr,
+ const MemberPointerType *memberPtrType,
+ AlignmentSource *AlignSource = nullptr);
RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
ReturnValueSlot ReturnValue);
@@ -2610,7 +2715,7 @@ public:
unsigned Modifier,
const CallExpr *E,
SmallVectorImpl<llvm::Value *> &Ops,
- llvm::Value *Align = nullptr);
+ Address PtrOp0, Address PtrOp1);
llvm::Function *LookupNeonLLVMIntrinsic(unsigned IntrinsicID,
unsigned Modifier, llvm::Type *ArgTy,
const CallExpr *E);
@@ -2656,24 +2761,23 @@ public:
}
// ARC primitives.
- void EmitARCInitWeak(llvm::Value *value, llvm::Value *addr);
- void EmitARCDestroyWeak(llvm::Value *addr);
- llvm::Value *EmitARCLoadWeak(llvm::Value *addr);
- llvm::Value *EmitARCLoadWeakRetained(llvm::Value *addr);
- llvm::Value *EmitARCStoreWeak(llvm::Value *value, llvm::Value *addr,
- bool ignored);
- void EmitARCCopyWeak(llvm::Value *dst, llvm::Value *src);
- void EmitARCMoveWeak(llvm::Value *dst, llvm::Value *src);
+ void EmitARCInitWeak(Address addr, llvm::Value *value);
+ void EmitARCDestroyWeak(Address addr);
+ llvm::Value *EmitARCLoadWeak(Address addr);
+ llvm::Value *EmitARCLoadWeakRetained(Address addr);
+ llvm::Value *EmitARCStoreWeak(Address addr, llvm::Value *value, bool ignored);
+ void EmitARCCopyWeak(Address dst, Address src);
+ void EmitARCMoveWeak(Address dst, Address src);
llvm::Value *EmitARCRetainAutorelease(QualType type, llvm::Value *value);
llvm::Value *EmitARCRetainAutoreleaseNonBlock(llvm::Value *value);
llvm::Value *EmitARCStoreStrong(LValue lvalue, llvm::Value *value,
bool resultIgnored);
- llvm::Value *EmitARCStoreStrongCall(llvm::Value *addr, llvm::Value *value,
+ llvm::Value *EmitARCStoreStrongCall(Address addr, llvm::Value *value,
bool resultIgnored);
llvm::Value *EmitARCRetain(QualType type, llvm::Value *value);
llvm::Value *EmitARCRetainNonBlock(llvm::Value *value);
llvm::Value *EmitARCRetainBlock(llvm::Value *value, bool mandatory);
- void EmitARCDestroyStrong(llvm::Value *addr, ARCPreciseLifetime_t precise);
+ void EmitARCDestroyStrong(Address addr, ARCPreciseLifetime_t precise);
void EmitARCRelease(llvm::Value *value, ARCPreciseLifetime_t precise);
llvm::Value *EmitARCAutorelease(llvm::Value *value);
llvm::Value *EmitARCAutoreleaseReturnValue(llvm::Value *value);
@@ -2765,6 +2869,9 @@ public:
/// EmitLoadOfComplex - Load a complex number from the specified l-value.
ComplexPairTy EmitLoadOfComplex(LValue src, SourceLocation loc);
+ Address emitAddrOfRealComponent(Address complex, QualType complexType);
+ Address emitAddrOfImagComponent(Address complex, QualType complexType);
+
/// AddInitializerToStaticVarDecl - Add the initializer for 'D' to the
/// global variable that has already been created for it. If the initializer
/// has a different type than GV does, this may free GV and return a different
@@ -2799,7 +2906,7 @@ public:
/// variables.
void GenerateCXXGlobalInitFunc(llvm::Function *Fn,
ArrayRef<llvm::Function *> CXXThreadLocals,
- llvm::GlobalVariable *Guard = nullptr);
+ Address Guard = Address::invalid());
/// GenerateCXXGlobalDtorsFunc - Generates code for destroying global
/// variables.
@@ -2814,8 +2921,7 @@ public:
void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest);
- void EmitSynthesizedCXXCopyCtor(llvm::Value *Dest, llvm::Value *Src,
- const Expr *Exp);
+ void EmitSynthesizedCXXCopyCtor(Address Dest, Address Src, const Expr *Exp);
void enterFullExpression(const ExprWithCleanups *E) {
if (E->getNumObjects() == 0) return;
@@ -2827,7 +2933,7 @@ public:
void EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Dest);
- RValue EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest = nullptr);
+ RValue EmitAtomicExpr(AtomicExpr *E, Address Dest = Address::invalid());
//===--------------------------------------------------------------------===//
// Annotations Emission
@@ -2844,7 +2950,7 @@ public:
/// Emit field annotations for the given field & value. Returns the
/// annotation result.
- llvm::Value *EmitFieldAnnotations(const FieldDecl *D, llvm::Value *V);
+ Address EmitFieldAnnotations(const FieldDecl *D, Address V);
//===--------------------------------------------------------------------===//
// Internal Helpers
@@ -2932,6 +3038,12 @@ private:
llvm::SmallVector<std::pair<llvm::Instruction *, llvm::Value *>, 4>
DeferredReplacements;
+ /// Set the address of a local variable.
+ void setAddrOfLocalVar(const VarDecl *VD, Address Addr) {
+ assert(!LocalDeclMap.count(VD) && "Decl already exists in LocalDeclMap!");
+ LocalDeclMap.insert({VD, Addr});
+ }
+
/// ExpandTypeFromArgs - Reconstruct a structure of type \arg Ty
/// from function arguments into \arg Dst. See ABIArgInfo::Expand.
///
@@ -3028,6 +3140,30 @@ public:
const FunctionDecl *CalleeDecl = nullptr,
unsigned ParamsToSkip = 0);
+ /// EmitPointerWithAlignment - Given an expression with a pointer
+ /// type, emit the value and compute our best estimate of the
+ /// alignment of the pointee.
+ ///
+ /// Note that this function will conservatively fall back on the type
+ /// when it doesn't
+ ///
+ /// \param Source - If non-null, this will be initialized with
+ /// information about the source of the alignment. Note that this
+ /// function will conservatively fall back on the type when it
+ /// doesn't recognize the expression, which means that sometimes
+ ///
+ /// a worst-case One
+ /// reasonable way to use this information is when there's a
+ /// language guarantee that the pointer must be aligned to some
+ /// stricter value, and we're simply trying to ensure that
+ /// sufficiently obvious uses of under-aligned objects don't get
+ /// miscompiled; for example, a placement new into the address of
+ /// a local variable. In such a case, it's quite reasonable to
+ /// just ignore the returned alignment when it isn't from an
+ /// explicit source.
+ Address EmitPointerWithAlignment(const Expr *Addr,
+ AlignmentSource *Source = nullptr);
+
private:
QualType getVarArgType(const Expr *Arg);
@@ -3037,16 +3173,11 @@ private:
void EmitDeclMetadata();
- CodeGenModule::ByrefHelpers *
- buildByrefHelpers(llvm::StructType &byrefType,
- const AutoVarEmission &emission);
+ BlockByrefHelpers *buildByrefHelpers(llvm::StructType &byrefType,
+ const AutoVarEmission &emission);
void AddObjCARCExceptionMetadata(llvm::Instruction *Inst);
- /// GetPointeeAlignment - Given an expression with a pointer type, emit the
- /// value and compute our best estimate of the alignment of the pointee.
- std::pair<llvm::Value*, unsigned> EmitPointerWithAlignment(const Expr *Addr);
-
llvm::Value *GetValueForARMHint(unsigned BuiltinID);
};
@@ -3069,17 +3200,23 @@ struct DominatingLLVMValue {
static saved_type save(CodeGenFunction &CGF, llvm::Value *value) {
if (!needsSaving(value)) return saved_type(value, false);
- // Otherwise we need an alloca.
- llvm::Value *alloca =
- CGF.CreateTempAlloca(value->getType(), "cond-cleanup.save");
+ // Otherwise, we need an alloca.
+ auto align = CharUnits::fromQuantity(
+ CGF.CGM.getDataLayout().getPrefTypeAlignment(value->getType()));
+ Address alloca =
+ CGF.CreateTempAlloca(value->getType(), align, "cond-cleanup.save");
CGF.Builder.CreateStore(value, alloca);
- return saved_type(alloca, true);
+ return saved_type(alloca.getPointer(), true);
}
static llvm::Value *restore(CodeGenFunction &CGF, saved_type value) {
+ // If the value says it wasn't saved, trust that it's still dominating.
if (!value.getInt()) return value.getPointer();
- return CGF.Builder.CreateLoad(value.getPointer());
+
+ // Otherwise, it should be an alloca instruction, as set up in save().
+ auto alloca = cast<llvm::AllocaInst>(value.getPointer());
+ return CGF.Builder.CreateAlignedLoad(alloca, alloca->getAlignment());
}
};
@@ -3092,6 +3229,28 @@ template <class T> struct DominatingPointer<T,true> : DominatingLLVMValue {
}
};
+/// A specialization of DominatingValue for Address.
+template <> struct DominatingValue<Address> {
+ typedef Address type;
+
+ struct saved_type {
+ DominatingLLVMValue::saved_type SavedValue;
+ CharUnits Alignment;
+ };
+
+ static bool needsSaving(type value) {
+ return DominatingLLVMValue::needsSaving(value.getPointer());
+ }
+ static saved_type save(CodeGenFunction &CGF, type value) {
+ return { DominatingLLVMValue::save(CGF, value.getPointer()),
+ value.getAlignment() };
+ }
+ static type restore(CodeGenFunction &CGF, saved_type value) {
+ return Address(DominatingLLVMValue::restore(CGF, value.SavedValue),
+ value.Alignment);
+ }
+};
+
/// A specialization of DominatingValue for RValue.
template <> struct DominatingValue<RValue> {
typedef RValue type;
@@ -3100,15 +3259,17 @@ template <> struct DominatingValue<RValue> {
AggregateAddress, ComplexAddress };
llvm::Value *Value;
- Kind K;
- saved_type(llvm::Value *v, Kind k) : Value(v), K(k) {}
+ unsigned K : 3;
+ unsigned Align : 29;
+ saved_type(llvm::Value *v, Kind k, unsigned a = 0)
+ : Value(v), K(k), Align(a) {}
public:
static bool needsSaving(RValue value);
static saved_type save(CodeGenFunction &CGF, RValue value);
RValue restore(CodeGenFunction &CGF);
- // implementations in CGExprCXX.cpp
+ // implementations in CGCleanup.cpp
};
static bool needsSaving(type value) {
OpenPOWER on IntegriCloud