From b6a6079449a5275c283982e19b0c38e165833bb2 Mon Sep 17 00:00:00 2001 From: John McCall Date: Sat, 23 Mar 2013 02:35:54 +0000 Subject: Under ARC, when we're passing the address of a strong variable to an out-parameter using the indirect-writeback conversion, and we copied the current value of the variable to the temporary, make sure that we register an intrinsic use of that value with the optimizer so that the value won't get released until we have a chance to retain it. rdar://13195034 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@177813 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 2bddb6f79f..a5f0689f96 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -217,6 +217,9 @@ struct ARCEntrypoints { /// A void(void) inline asm to use to mark that the return value of /// a call will be immediately retain. llvm::InlineAsm *retainAutoreleasedReturnValueMarker; + + /// void clang.arc.use(...); + llvm::Constant *clang_arc_use; }; /// CodeGenModule - This class organizes the cross-function state that is used -- cgit v1.2.3-70-g09d2 From 495cfa46300979642acde8d93a1f21c9291dac98 Mon Sep 17 00:00:00 2001 From: Nadav Rotem Date: Sat, 23 Mar 2013 06:43:35 +0000 Subject: Make clang to mark static stack allocations with lifetime markers to enable a more aggressive stack coloring. Patch by John McCall with help by Shuxin Yang. rdar://13115369 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@177819 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDecl.cpp | 69 ++++++++++++++++++++++++++++++++++++++++- lib/CodeGen/CGStmt.cpp | 34 +++++++++++++++++--- lib/CodeGen/CodeGenFunction.cpp | 2 +- lib/CodeGen/CodeGenFunction.h | 44 ++++++++++++++++++++++++-- lib/CodeGen/CodeGenModule.cpp | 1 + lib/CodeGen/CodeGenModule.h | 9 ++++++ test/CodeGen/lifetime2.c | 17 ++++++++++ test/CodeGenObjC/arc-blocks.m | 20 ++++++------ test/CodeGenObjC/arc.m | 5 +-- 9 files changed, 180 insertions(+), 21 deletions(-) create mode 100644 test/CodeGen/lifetime2.c (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index a99fe29bda..c095ff96fc 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -452,6 +452,22 @@ namespace { CGF.EmitCall(FnInfo, CleanupFn, ReturnValueSlot(), Args); } }; + + /// A cleanup to call @llvm.lifetime.end. + class CallLifetimeEnd : public EHScopeStack::Cleanup { + llvm::Value *Addr; + llvm::Value *Size; + public: + CallLifetimeEnd(llvm::Value *addr, llvm::Value *size) + : Addr(addr), Size(size) {} + + void Emit(CodeGenFunction &CGF, Flags flags) { + llvm::Value *castAddr = CGF.Builder.CreateBitCast(Addr, CGF.Int8PtrTy); + CGF.Builder.CreateCall2(CGF.CGM.getLLVMLifetimeEndFn(), + Size, castAddr) + ->setDoesNotThrow(); + } + }; } /// EmitAutoVarWithLifetime - Does the setup required for an automatic @@ -756,7 +772,6 @@ static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init, // If a global is all zeros, always use a memset. if (isa(Init)) return true; - // If a non-zero global is <= 32 bytes, always use a memcpy. If it is large, // do it if it will require 6 or fewer scalar stores. // TODO: Should budget depends on the size? Avoiding a large global warrants @@ -768,6 +783,20 @@ static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init, canEmitInitWithFewStoresAfterMemset(Init, StoreBudget); } +/// Should we use the LLVM lifetime intrinsics for the given local variable? +static bool shouldUseLifetimeMarkers(CodeGenFunction &CGF, const VarDecl &D, + unsigned Size) { + // For now, only in optimized builds. + if (CGF.CGM.getCodeGenOpts().OptimizationLevel == 0) + return false; + + // Limit the size of marked objects to 32 bytes. We don't want to increase + // compile time by marking tiny objects. + unsigned SizeThreshold = 32; + + return Size > SizeThreshold; +} + /// EmitAutoVarDecl - Emit code and set up an entry in LocalDeclMap for a /// variable declaration with auto, register, or no storage class specifier. @@ -870,6 +899,20 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { getContext().toCharUnitsFromBits(Target.getPointerAlign(0))); Alloc->setAlignment(allocaAlignment.getQuantity()); DeclPtr = Alloc; + + // Emit a lifetime intrinsic if meaningful. There's no point + // in doing this if we don't have a valid insertion point (?). + uint64_t size = CGM.getDataLayout().getTypeAllocSize(LTy); + if (HaveInsertPoint() && shouldUseLifetimeMarkers(*this, D, size)) { + llvm::Value *sizeV = llvm::ConstantInt::get(Int64Ty, size); + + emission.SizeForLifetimeMarkers = sizeV; + llvm::Value *castAddr = Builder.CreateBitCast(Alloc, Int8PtrTy); + Builder.CreateCall2(CGM.getLLVMLifetimeStartFn(), sizeV, castAddr) + ->setDoesNotThrow(); + } else { + assert(!emission.useLifetimeMarkers()); + } } } else { // Targets that don't support recursion emit locals as globals. @@ -1215,6 +1258,14 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { const VarDecl &D = *emission.Variable; + // Make sure we call @llvm.lifetime.end. This needs to happen + // *last*, so the cleanup needs to be pushed *first*. + if (emission.useLifetimeMarkers()) { + EHStack.pushCleanup(NormalCleanup, + emission.getAllocatedAddress(), + emission.getSizeForLifetimeMarkers()); + } + // Check the type for a cleanup. if (QualType::DestructionKind dtorKind = D.getType().isDestructedType()) emitAutoVarTypeCleanup(emission, dtorKind); @@ -1485,6 +1536,22 @@ void CodeGenFunction::pushRegularPartialArrayCleanup(llvm::Value *arrayBegin, elementType, destroyer); } +/// Lazily declare the @llvm.lifetime.start intrinsic. +llvm::Constant *CodeGenModule::getLLVMLifetimeStartFn() { + if (LifetimeStartFn) return LifetimeStartFn; + LifetimeStartFn = llvm::Intrinsic::getDeclaration(&getModule(), + llvm::Intrinsic::lifetime_start); + return LifetimeStartFn; +} + +/// Lazily declare the @llvm.lifetime.end intrinsic. +llvm::Constant *CodeGenModule::getLLVMLifetimeEndFn() { + if (LifetimeEndFn) return LifetimeEndFn; + LifetimeEndFn = llvm::Intrinsic::getDeclaration(&getModule(), + llvm::Intrinsic::lifetime_end); + return LifetimeEndFn; +} + namespace { /// A cleanup to perform a release of an object at the end of a /// function. This is used to balance out the incoming +1 of a diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 9e7ddfbdc1..06f74600b3 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -319,6 +319,12 @@ CodeGenFunction::getJumpDestForLabel(const LabelDecl *D) { } void CodeGenFunction::EmitLabel(const LabelDecl *D) { + // Add this label to the current lexical scope if we're within any + // normal cleanups. Jumps "in" to this label --- when permitted by + // the language --- may need to be routed around such cleanups. + if (EHStack.hasNormalCleanups() && CurLexicalScope) + CurLexicalScope->addLabel(D); + JumpDest &Dest = LabelMap[D]; // If we didn't need a forward reference to this label, just go @@ -330,16 +336,36 @@ void CodeGenFunction::EmitLabel(const LabelDecl *D) { // it from the branch-fixups list. } else { assert(!Dest.getScopeDepth().isValid() && "already emitted label!"); - Dest = JumpDest(Dest.getBlock(), - EHStack.stable_begin(), - Dest.getDestIndex()); - + Dest.setScopeDepth(EHStack.stable_begin()); ResolveBranchFixups(Dest.getBlock()); } EmitBlock(Dest.getBlock()); } +/// Change the cleanup scope of the labels in this lexical scope to +/// match the scope of the enclosing context. +void CodeGenFunction::LexicalScope::rescopeLabels() { + assert(!Labels.empty()); + EHScopeStack::stable_iterator innermostScope + = CGF.EHStack.getInnermostNormalCleanup(); + + // Change the scope depth of all the labels. + for (SmallVectorImpl::const_iterator + i = Labels.begin(), e = Labels.end(); i != e; ++i) { + assert(CGF.LabelMap.count(*i)); + JumpDest &dest = CGF.LabelMap.find(*i)->second; + assert(dest.getScopeDepth().isValid()); + assert(innermostScope.encloses(dest.getScopeDepth())); + dest.setScopeDepth(innermostScope); + } + + // Reparent the labels if the new scope also has cleanups. + if (innermostScope != EHScopeStack::stable_end() && ParentScope) { + ParentScope->Labels.append(Labels.begin(), Labels.end()); + } +} + void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) { EmitLabel(S.getDecl()); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index bd244355f0..04de55d517 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -45,7 +45,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0), CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0), CXXStructorImplicitParamDecl(0), CXXStructorImplicitParamValue(0), - OutermostConditional(0), TerminateLandingPad(0), + OutermostConditional(0), CurLexicalScope(0), TerminateLandingPad(0), TerminateHandler(0), TrapBB(0) { if (!suppressNewContext) CGM.getCXXABI().getMangleContext().startNewFunction(); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 46848ae2d7..e40a731825 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -562,6 +562,11 @@ public: EHScopeStack::stable_iterator getScopeDepth() const { return ScopeDepth; } unsigned getDestIndex() const { return Index; } + // This should be used cautiously. + void setScopeDepth(EHScopeStack::stable_iterator depth) { + ScopeDepth = depth; + } + private: llvm::BasicBlock *Block; EHScopeStack::stable_iterator ScopeDepth; @@ -853,6 +858,8 @@ public: class LexicalScope: protected RunCleanupsScope { SourceRange Range; + SmallVector Labels; + LexicalScope *ParentScope; LexicalScope(const LexicalScope &) LLVM_DELETED_FUNCTION; void operator=(const LexicalScope &) LLVM_DELETED_FUNCTION; @@ -860,15 +867,23 @@ public: public: /// \brief Enter a new cleanup scope. explicit LexicalScope(CodeGenFunction &CGF, SourceRange Range) - : RunCleanupsScope(CGF), Range(Range) { + : RunCleanupsScope(CGF), Range(Range), ParentScope(CGF.CurLexicalScope) { + CGF.CurLexicalScope = this; if (CGDebugInfo *DI = CGF.getDebugInfo()) DI->EmitLexicalBlockStart(CGF.Builder, Range.getBegin()); } + void addLabel(const LabelDecl *label) { + assert(PerformCleanup && "adding label to dead scope?"); + Labels.push_back(label); + } + /// \brief Exit this cleanup scope, emitting any accumulated /// cleanups. ~LexicalScope() { - if (PerformCleanup) endLexicalScope(); + // If we should perform a cleanup, force them now. Note that + // this ends the cleanup scope before rescoping any labels. + if (PerformCleanup) ForceCleanup(); } /// \brief Force the emission of cleanups now, instead of waiting @@ -880,9 +895,14 @@ public: private: void endLexicalScope() { + CGF.CurLexicalScope = ParentScope; if (CGDebugInfo *DI = CGF.getDebugInfo()) DI->EmitLexicalBlockEnd(CGF.Builder, Range.getEnd()); + if (!Labels.empty()) + rescopeLabels(); } + + void rescopeLabels(); }; @@ -1205,6 +1225,8 @@ private: /// temporary should be destroyed conditionally. ConditionalEvaluation *OutermostConditional; + /// The current lexical scope. + LexicalScope *CurLexicalScope; /// ByrefValueInfoMap - For each __block variable, contains a pair of the LLVM /// type as well as the field number that contains the actual data. @@ -2001,18 +2023,34 @@ public: /// initializer. bool IsConstantAggregate; + /// Non-null if we should use lifetime annotations. + llvm::Value *SizeForLifetimeMarkers; + struct Invalid {}; AutoVarEmission(Invalid) : Variable(0) {} AutoVarEmission(const VarDecl &variable) : Variable(&variable), Address(0), NRVOFlag(0), - IsByRef(false), IsConstantAggregate(false) {} + IsByRef(false), IsConstantAggregate(false), + SizeForLifetimeMarkers(0) {} bool wasEmittedAsGlobal() const { return Address == 0; } public: static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); } + bool useLifetimeMarkers() const { return SizeForLifetimeMarkers != 0; } + llvm::Value *getSizeForLifetimeMarkers() const { + assert(useLifetimeMarkers()); + return SizeForLifetimeMarkers; + } + + /// Returns the raw, allocated address, which is not necessarily + /// the address of the object itself. + llvm::Value *getAllocatedAddress() const { + return Address; + } + /// Returns the address of the object within this declaration. /// Note that this does not chase the forwarding pointer for /// __block decls. diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 173774452e..9f604e860e 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -86,6 +86,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockObjectAssign(0), BlockObjectDispose(0), BlockDescriptorType(0), GenericBlockLiteralType(0), + LifetimeStartFn(0), LifetimeEndFn(0), SanitizerBlacklist(CGO.SanitizerBlacklistFile), SanOpts(SanitizerBlacklist.isIn(M) ? SanitizerOptions::Disabled : LangOpts.Sanitize) { diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index a5f0689f96..fcd48302ae 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -381,6 +381,12 @@ class CodeGenModule : public CodeGenTypeCache { int GlobalUniqueCount; } Block; + /// void @llvm.lifetime.start(i64 %size, i8* nocapture ) + llvm::Constant *LifetimeStartFn; + + /// void @llvm.lifetime.end(i64 %size, i8* nocapture ) + llvm::Constant *LifetimeEndFn; + GlobalDecl initializedGlobalDecl; llvm::BlackList SanitizerBlacklist; @@ -757,6 +763,9 @@ public: ///@} + llvm::Constant *getLLVMLifetimeStartFn(); + llvm::Constant *getLLVMLifetimeEndFn(); + // UpdateCompleteType - Make sure that this type is translated. void UpdateCompletedType(const TagDecl *TD); diff --git a/test/CodeGen/lifetime2.c b/test/CodeGen/lifetime2.c new file mode 100644 index 0000000000..ffff5cca12 --- /dev/null +++ b/test/CodeGen/lifetime2.c @@ -0,0 +1,17 @@ +// RUN: %clang -S -emit-llvm -o - -O2 %s | FileCheck %s -check-prefix=O2 +// RUN: %clang -S -emit-llvm -o - -O0 %s | FileCheck %s -check-prefix=O0 + +extern int bar(char *A, int n); + +// O0-NOT: @llvm.lifetime.start +int foo (int n) { + if (n) { +// O2: @llvm.lifetime.start + char A[100]; + return bar(A, 1); + } else { +// O2: @llvm.lifetime.start + char A[100]; + return bar(A, 2); + } +} diff --git a/test/CodeGenObjC/arc-blocks.m b/test/CodeGenObjC/arc-blocks.m index c7bc502ca0..3281b2aab8 100644 --- a/test/CodeGenObjC/arc-blocks.m +++ b/test/CodeGenObjC/arc-blocks.m @@ -128,7 +128,7 @@ void test4(void) { // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8) // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]] // CHECK-NEXT: call void @objc_release(i8* [[T0]]) - // CHECK-NEXT: ret void + // CHECK: ret void // CHECK: define internal void @__Block_byref_object_copy_ // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6 @@ -207,7 +207,7 @@ void test6(void) { // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8* // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8) // CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]]) - // CHECK-NEXT: ret void + // CHECK: ret void // CHECK: define internal void @__Block_byref_object_copy_ // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6 @@ -256,14 +256,14 @@ void test7(void) { // CHECK: call void @test7_helper( // CHECK-NEXT: call void @objc_destroyWeak(i8** {{%.*}}) // CHECK-NEXT: call void @objc_destroyWeak(i8** [[VAR]]) - // CHECK-NEXT: ret void + // CHECK: ret void // CHECK: define internal void @__test7_block_invoke // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* {{%.*}}, i32 0, i32 5 // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeakRetained(i8** [[SLOT]]) // CHECK-NEXT: call void @test7_consume(i8* [[T0]]) // CHECK-NEXT: call void @objc_release(i8* [[T0]]) - // CHECK-NEXT: ret void + // CHECK: ret void // CHECK: define internal void @__copy_helper_block_ // CHECK: getelementptr @@ -296,7 +296,7 @@ void test7(void) { // CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[D0]] // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8* // CHECK-NEXT: call void @objc_release(i8* [[T2]]) -// CHECK-NEXT: ret void +// CHECK: ret void extern void test8_helper(void (^)(void)); test8_helper(^{ (void) self; }); @@ -354,7 +354,7 @@ void test10a(void) { // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]] // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8* // CHECK-NEXT: call void @objc_release(i8* [[T2]]) - // CHECK-NEXT: ret void + // CHECK: ret void } // : do this copy and dispose with @@ -374,7 +374,7 @@ void test10a(void) { // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()* // CHECK-NEXT: store void ()* [[T3]], void ()** [[D2]], align 8 -// CHECK-NEXT: ret void +// CHECK: ret void // CHECK: define internal void @__Block_byref_object_dispose // CHECK: [[T0:%.*]] = load i8** {{%.*}} @@ -418,7 +418,7 @@ void test10b(void) { // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]] // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8* // CHECK-NEXT: call void @objc_release(i8* [[T2]]) - // CHECK-NEXT: ret void + // CHECK: ret void } // rdar://problem/10088932 @@ -438,7 +438,7 @@ void test11a(void) { // CHECK-NEXT: call void @test11_helper(i8* [[T4]]) // CHECK-NEXT: [[T5:%.*]] = bitcast void ()* [[T3]] to i8* // CHECK-NEXT: call void @objc_release(i8* [[T5]]) - // CHECK-NEXT: ret void + // CHECK: ret void } void test11b(void) { int x; @@ -456,7 +456,7 @@ void test11b(void) { // CHECK-NEXT: store i8* [[T4]], i8** [[B]], align 8 // CHECK-NEXT: [[T5:%.*]] = load i8** [[B]] // CHECK-NEXT: call void @objc_release(i8* [[T5]]) - // CHECK-NEXT: ret void + // CHECK: ret void } // rdar://problem/9979150 diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m index 45cb5d761e..7262dc8d7b 100644 --- a/test/CodeGenObjC/arc.m +++ b/test/CodeGenObjC/arc.m @@ -353,7 +353,7 @@ void test12(void) { // CHECK-NEXT: [[T4:%.*]] = load i8** [[Y]] // CHECK-NEXT: call void @objc_release(i8* [[T4]]) [[NUW]], !clang.imprecise_release // CHECK-NEXT: call void @objc_destroyWeak(i8** [[X]]) - // CHECK-NEXT: ret void + // CHECK: ret void } // Indirect consuming calls. @@ -460,8 +460,9 @@ void test13(void) { void test19() { // CHECK: define void @test19() // CHECK: [[X:%.*]] = alloca [5 x i8*], align 16 + // CHECK: call void @llvm.lifetime.start // CHECK-NEXT: [[T0:%.*]] = bitcast [5 x i8*]* [[X]] to i8* - // CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 40, i32 16, i1 false) + // CHECK: call void @llvm.memset.p0i8.i64(i8* [[T0]], i8 0, i64 40, i32 16, i1 false) id x[5]; extern id test19_helper(void); -- cgit v1.2.3-70-g09d2 From ab4ffe242935ae0dd66fbe0dcc792c1ad38b00c1 Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Thu, 4 Apr 2013 20:14:17 +0000 Subject: Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td (revision 178718) +++ include/clang/Driver/CC1Options.td (working copy) @@ -161,6 +161,8 @@ HelpText<"Use register sized accesses to bit-fields, when possible.">; def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">, HelpText<"Turn off Type Based Alias Analysis">; +def struct_path_tbaa : Flag<["-"], "struct-path-tbaa">, + HelpText<"Turn on struct-path aware Type Based Alias Analysis">; def masm_verbose : Flag<["-"], "masm-verbose">, HelpText<"Generate verbose assembly output">; def mcode_model : Separate<["-"], "mcode-model">, Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td (revision 178718) +++ include/clang/Driver/Options.td (working copy) @@ -587,6 +587,7 @@ Flags<[CC1Option]>, HelpText<"Disable spell-checking">; def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group; def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group; +def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group; def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group; def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group; def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group, Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def (revision 178718) +++ include/clang/Frontend/CodeGenOptions.def (working copy) @@ -85,6 +85,7 @@ VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. +CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA. CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero ///< offset in AddressSanitizer. Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp (revision 178718) +++ lib/CodeGen/CGExpr.cpp (working copy) @@ -1044,7 +1044,8 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue) { return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(), lvalue.getAlignment().getQuantity(), - lvalue.getType(), lvalue.getTBAAInfo()); + lvalue.getType(), lvalue.getTBAAInfo(), + lvalue.getTBAABaseType(), lvalue.getTBAAOffset()); } static bool hasBooleanRepresentation(QualType Ty) { @@ -1106,7 +1107,9 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo) { + llvm::MDNode *TBAAInfo, + QualType TBAABaseType, + uint64_t TBAAOffset) { // For better performance, handle vector loads differently. if (Ty->isVectorType()) { llvm::Value *V; @@ -1158,8 +1161,11 @@ Load->setVolatile(true); if (Alignment) Load->setAlignment(Alignment); - if (TBAAInfo) - CGM.DecorateInstruction(Load, TBAAInfo); + if (TBAAInfo) { + llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, + TBAAOffset); + CGM.DecorateInstruction(Load, TBAAPath); + } if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) || (SanOpts->Enum && Ty->getAs())) { @@ -1217,7 +1223,8 @@ bool Volatile, unsigned Alignment, QualType Ty, llvm::MDNode *TBAAInfo, - bool isInit) { + bool isInit, QualType TBAABaseType, + uint64_t TBAAOffset) { // Handle vectors differently to get better performance. if (Ty->isVectorType()) { @@ -1268,15 +1275,19 @@ llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile); if (Alignment) Store->setAlignment(Alignment); - if (TBAAInfo) - CGM.DecorateInstruction(Store, TBAAInfo); + if (TBAAInfo) { + llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, + TBAAOffset); + CGM.DecorateInstruction(Store, TBAAPath); + } } void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue, bool isInit) { EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(), lvalue.getAlignment().getQuantity(), lvalue.getType(), - lvalue.getTBAAInfo(), isInit); + lvalue.getTBAAInfo(), isInit, lvalue.getTBAABaseType(), + lvalue.getTBAAOffset()); } /// EmitLoadOfLValue - Given an expression that represents a value lvalue, this @@ -2494,9 +2505,12 @@ llvm::Value *addr = base.getAddress(); unsigned cvr = base.getVRQualifiers(); + bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA; if (rec->isUnion()) { // For unions, there is no pointer adjustment. assert(!type->isReferenceType() && "union has reference member"); + // TODO: handle path-aware TBAA for union. + TBAAPath = false; } else { // For structs, we GEP to the field that the record layout suggests. unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field); @@ -2508,6 +2522,8 @@ if (cvr & Qualifiers::Volatile) load->setVolatile(true); load->setAlignment(alignment.getQuantity()); + // Loading the reference will disable path-aware TBAA. + TBAAPath = false; if (CGM.shouldUseTBAA()) { llvm::MDNode *tbaa; if (mayAlias) @@ -2541,6 +2557,16 @@ LValue LV = MakeAddrLValue(addr, type, alignment); LV.getQuals().addCVRQualifiers(cvr); + if (TBAAPath) { + const ASTRecordLayout &Layout = + getContext().getASTRecordLayout(field->getParent()); + // Set the base type to be the base type of the base LValue and + // update offset to be relative to the base type. + LV.setTBAABaseType(base.getTBAABaseType()); + LV.setTBAAOffset(base.getTBAAOffset() + + Layout.getFieldOffset(field->getFieldIndex()) / + getContext().getCharWidth()); + } // __weak attribute on a field is ignored. if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak) Index: lib/CodeGen/CGValue.h =================================================================== --- lib/CodeGen/CGValue.h (revision 178718) +++ lib/CodeGen/CGValue.h (working copy) @@ -157,6 +157,11 @@ Expr *BaseIvarExp; + /// Used by struct-path-aware TBAA. + QualType TBAABaseType; + /// Offset relative to the base type. + uint64_t TBAAOffset; + /// TBAAInfo - TBAA information to attach to dereferences of this LValue. llvm::MDNode *TBAAInfo; @@ -175,6 +180,10 @@ this->ImpreciseLifetime = false; this->ThreadLocalRef = false; this->BaseIvarExp = 0; + + // Initialize fields for TBAA. + this->TBAABaseType = Type; + this->TBAAOffset = 0; this->TBAAInfo = TBAAInfo; } @@ -232,6 +241,12 @@ Expr *getBaseIvarExp() const { return BaseIvarExp; } void setBaseIvarExp(Expr *V) { BaseIvarExp = V; } + QualType getTBAABaseType() const { return TBAABaseType; } + void setTBAABaseType(QualType T) { TBAABaseType = T; } + + uint64_t getTBAAOffset() const { return TBAAOffset; } + void setTBAAOffset(uint64_t O) { TBAAOffset = O; } + llvm::MDNode *getTBAAInfo() const { return TBAAInfo; } void setTBAAInfo(llvm::MDNode *N) { TBAAInfo = N; } Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h (revision 178718) +++ lib/CodeGen/CodeGenFunction.h (working copy) @@ -2211,7 +2211,9 @@ /// the LLVM value representation. llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo = 0); + llvm::MDNode *TBAAInfo = 0, + QualType TBAABaseTy = QualType(), + uint64_t TBAAOffset = 0); /// EmitLoadOfScalar - Load a scalar value from an address, taking /// care to appropriately convert from the memory representation to @@ -2224,7 +2226,9 @@ /// the LLVM value representation. void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo = 0, bool isInit=false); + llvm::MDNode *TBAAInfo = 0, bool isInit = false, + QualType TBAABaseTy = QualType(), + uint64_t TBAAOffset = 0); /// EmitStoreOfScalar - Store a scalar value to an address, taking /// care to appropriately convert from the memory representation to Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp (revision 178718) +++ lib/CodeGen/CodeGenModule.cpp (working copy) @@ -227,6 +227,20 @@ return TBAA->getTBAAStructInfo(QTy); } +llvm::MDNode *CodeGenModule::getTBAAStructTypeInfo(QualType QTy) { + if (!TBAA) + return 0; + return TBAA->getTBAAStructTypeInfo(QTy); +} + +llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(QualType BaseTy, + llvm::MDNode *AccessN, + uint64_t O) { + if (!TBAA) + return 0; + return TBAA->getTBAAStructTagInfo(BaseTy, AccessN, O); +} + void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst, llvm::MDNode *TBAAInfo) { Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo); Index: lib/CodeGen/CodeGenModule.h =================================================================== --- lib/CodeGen/CodeGenModule.h (revision 178718) +++ lib/CodeGen/CodeGenModule.h (working copy) @@ -501,6 +501,11 @@ llvm::MDNode *getTBAAInfo(QualType QTy); llvm::MDNode *getTBAAInfoForVTablePtr(); llvm::MDNode *getTBAAStructInfo(QualType QTy); + /// Return the MDNode in the type DAG for the given struct type. + llvm::MDNode *getTBAAStructTypeInfo(QualType QTy); + /// Return the path-aware tag for given base type, access node and offset. + llvm::MDNode *getTBAAStructTagInfo(QualType BaseTy, llvm::MDNode *AccessN, + uint64_t O); bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor); Index: lib/CodeGen/CodeGenTBAA.cpp =================================================================== --- lib/CodeGen/CodeGenTBAA.cpp (revision 178718) +++ lib/CodeGen/CodeGenTBAA.cpp (working copy) @@ -21,6 +21,7 @@ #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" #include "clang/Frontend/CodeGenOptions.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" @@ -225,3 +226,87 @@ // For now, handle any other kind of type conservatively. return StructMetadataCache[Ty] = NULL; } + +/// Check if the given type can be handled by path-aware TBAA. +static bool isTBAAPathStruct(QualType QTy) { + if (const RecordType *TTy = QTy->getAs()) { + const RecordDecl *RD = TTy->getDecl()->getDefinition(); + // RD can be struct, union, class, interface or enum. + // For now, we only handle struct. + if (RD->isStruct() && !RD->hasFlexibleArrayMember()) + return true; + } + return false; +} + +llvm::MDNode * +CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) { + const Type *Ty = Context.getCanonicalType(QTy).getTypePtr(); + assert(isTBAAPathStruct(QTy)); + + if (llvm::MDNode *N = StructTypeMetadataCache[Ty]) + return N; + + if (const RecordType *TTy = QTy->getAs()) { + const RecordDecl *RD = TTy->getDecl()->getDefinition(); + + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + SmallVector , 4> Fields; + // To reduce the size of MDNode for a given struct type, we only output + // once for all the fields with the same scalar types. + // Offsets for scalar fields in the type DAG are not used. + llvm::SmallSet ScalarFieldTypes; + unsigned idx = 0; + for (RecordDecl::field_iterator i = RD->field_begin(), + e = RD->field_end(); i != e; ++i, ++idx) { + QualType FieldQTy = i->getType(); + llvm::MDNode *FieldNode; + if (isTBAAPathStruct(FieldQTy)) + FieldNode = getTBAAStructTypeInfo(FieldQTy); + else { + FieldNode = getTBAAInfo(FieldQTy); + // Ignore this field if the type already exists. + if (ScalarFieldTypes.count(FieldNode)) + continue; + ScalarFieldTypes.insert(FieldNode); + } + if (!FieldNode) + return StructTypeMetadataCache[Ty] = NULL; + Fields.push_back(std::make_pair( + Layout.getFieldOffset(idx) / Context.getCharWidth(), FieldNode)); + } + + // TODO: This is using the RTTI name. Is there a better way to get + // a unique string for a type? + SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + MContext.mangleCXXRTTIName(QualType(Ty, 0), Out); + Out.flush(); + // Create the struct type node with a vector of pairs (offset, type). + return StructTypeMetadataCache[Ty] = + MDHelper.createTBAAStructTypeNode(OutName, Fields); + } + + return StructMetadataCache[Ty] = NULL; +} + +llvm::MDNode * +CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode, + uint64_t Offset) { + if (!CodeGenOpts.StructPathTBAA) + return AccessNode; + + const Type *BTy = Context.getCanonicalType(BaseQTy).getTypePtr(); + TBAAPathTag PathTag = TBAAPathTag(BTy, AccessNode, Offset); + if (llvm::MDNode *N = StructTagMetadataCache[PathTag]) + return N; + + llvm::MDNode *BNode = 0; + if (isTBAAPathStruct(BaseQTy)) + BNode = getTBAAStructTypeInfo(BaseQTy); + if (!BNode) + return StructTagMetadataCache[PathTag] = AccessNode; + + return StructTagMetadataCache[PathTag] = + MDHelper.createTBAAStructTagNode(BNode, AccessNode, Offset); +} Index: lib/CodeGen/CodeGenTBAA.h =================================================================== --- lib/CodeGen/CodeGenTBAA.h (revision 178718) +++ lib/CodeGen/CodeGenTBAA.h (working copy) @@ -35,6 +35,14 @@ namespace CodeGen { class CGRecordLayout; + struct TBAAPathTag { + TBAAPathTag(const Type *B, const llvm::MDNode *A, uint64_t O) + : BaseT(B), AccessN(A), Offset(O) {} + const Type *BaseT; + const llvm::MDNode *AccessN; + uint64_t Offset; + }; + /// CodeGenTBAA - This class organizes the cross-module state that is used /// while lowering AST types to LLVM types. class CodeGenTBAA { @@ -46,8 +54,13 @@ // MDHelper - Helper for creating metadata. llvm::MDBuilder MDHelper; - /// MetadataCache - This maps clang::Types to llvm::MDNodes describing them. + /// MetadataCache - This maps clang::Types to scalar llvm::MDNodes describing + /// them. llvm::DenseMap MetadataCache; + /// This maps clang::Types to a struct node in the type DAG. + llvm::DenseMap StructTypeMetadataCache; + /// This maps TBAAPathTags to a tag node. + llvm::DenseMap StructTagMetadataCache; /// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing /// them for struct assignments. @@ -89,9 +102,49 @@ /// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of /// the given type. llvm::MDNode *getTBAAStructInfo(QualType QTy); + + /// Get the MDNode in the type DAG for given struct type QType. + llvm::MDNode *getTBAAStructTypeInfo(QualType QType); + /// Get the tag MDNode for a given base type, the actual sclar access MDNode + /// and offset into the base type. + llvm::MDNode *getTBAAStructTagInfo(QualType BaseQType, + llvm::MDNode *AccessNode, uint64_t Offset); }; } // end namespace CodeGen } // end namespace clang +namespace llvm { + +template<> struct DenseMapInfo { + static clang::CodeGen::TBAAPathTag getEmptyKey() { + return clang::CodeGen::TBAAPathTag( + DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey()); + } + + static clang::CodeGen::TBAAPathTag getTombstoneKey() { + return clang::CodeGen::TBAAPathTag( + DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey()); + } + + static unsigned getHashValue(const clang::CodeGen::TBAAPathTag &Val) { + return DenseMapInfo::getHashValue(Val.BaseT) ^ + DenseMapInfo::getHashValue(Val.AccessN) ^ + DenseMapInfo::getHashValue(Val.Offset); + } + + static bool isEqual(const clang::CodeGen::TBAAPathTag &LHS, + const clang::CodeGen::TBAAPathTag &RHS) { + return LHS.BaseT == RHS.BaseT && + LHS.AccessN == RHS.AccessN && + LHS.Offset == RHS.Offset; + } +}; + +} // end namespace llvm + #endif Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp (revision 178718) +++ lib/Driver/Tools.cpp (working copy) @@ -2105,6 +2105,8 @@ options::OPT_fno_strict_aliasing, getToolChain().IsStrictAliasingDefault())) CmdArgs.push_back("-relaxed-aliasing"); + if (Args.hasArg(options::OPT_fstruct_path_tbaa)) + CmdArgs.push_back("-struct-path-tbaa"); if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums, false)) CmdArgs.push_back("-fstrict-enums"); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp (revision 178718) +++ lib/Frontend/CompilerInvocation.cpp (working copy) @@ -324,6 +324,7 @@ Opts.UseRegisterSizedBitfieldAccess = Args.hasArg( OPT_fuse_register_sized_bitfield_access); Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing); + Opts.StructPathTBAA = Args.hasArg(OPT_struct_path_tbaa); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); Index: test/CodeGen/tbaa.cpp =================================================================== --- test/CodeGen/tbaa.cpp (revision 0) +++ test/CodeGen/tbaa.cpp (working copy) @@ -0,0 +1,217 @@ +// RUN: %clang_cc1 -O1 -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -O1 -struct-path-tbaa -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s -check-prefix=PATH +// Test TBAA metadata generated by front-end. + +#include +typedef struct +{ + uint16_t f16; + uint32_t f32; + uint16_t f16_2; + uint32_t f32_2; +} StructA; +typedef struct +{ + uint16_t f16; + StructA a; + uint32_t f32; +} StructB; +typedef struct +{ + uint16_t f16; + StructB b; + uint32_t f32; +} StructC; +typedef struct +{ + uint16_t f16; + StructB b; + uint32_t f32; + uint8_t f8; +} StructD; + +typedef struct +{ + uint16_t f16; + uint32_t f32; +} StructS; +typedef struct +{ + uint16_t f16; + uint32_t f32; +} StructS2; + +uint32_t g(uint32_t *s, StructA *A, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !5 + *s = 1; + A->f32 = 4; + return *s; +} + +uint32_t g2(uint32_t *s, StructA *A, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !8 + *s = 1; + A->f16 = 4; + return *s; +} + +uint32_t g3(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9 + A->f32 = 1; + B->a.f32 = 4; + return A->f32; +} + +uint32_t g4(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !11 + A->f32 = 1; + B->a.f16 = 4; + return A->f32; +} + +uint32_t g5(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !12 + A->f32 = 1; + B->f32 = 4; + return A->f32; +} + +uint32_t g6(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !13 + A->f32 = 1; + B->a.f32_2 = 4; + return A->f32; +} + +uint32_t g7(StructA *A, StructS *S, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !14 + A->f32 = 1; + S->f32 = 4; + return A->f32; +} + +uint32_t g8(StructA *A, StructS *S, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !16 + A->f32 = 1; + S->f16 = 4; + return A->f32; +} + +uint32_t g9(StructS *S, StructS2 *S2, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !17 + S->f32 = 1; + S2->f32 = 4; + return S->f32; +} + +uint32_t g10(StructS *S, StructS2 *S2, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !19 + S->f32 = 1; + S2->f16 = 4; + return S->f32; +} + +uint32_t g11(StructC *C, StructD *D, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !20 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !22 + C->b.a.f32 = 1; + D->b.a.f32 = 4; + return C->b.a.f32; +} + +uint32_t g12(StructC *C, StructD *D, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// TODO: differentiate the two accesses. +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !9 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9 + StructB *b1 = &(C->b); + StructB *b2 = &(D->b); + // b1, b2 have different context. + b1->a.f32 = 1; + b2->a.f32 = 4; + return b1->a.f32; +} + +// CHECK: !1 = metadata !{metadata !"omnipotent char", metadata !2} +// CHECK: !2 = metadata !{metadata !"Simple C/C++ TBAA"} +// CHECK: !4 = metadata !{metadata !"int", metadata !1} +// CHECK: !5 = metadata !{metadata !"short", metadata !1} + +// PATH: !1 = metadata !{metadata !"omnipotent char", metadata !2} +// PATH: !4 = metadata !{metadata !"int", metadata !1} +// PATH: !5 = metadata !{metadata !6, metadata !4, i64 4} +// PATH: !6 = metadata !{metadata !"_ZTS7StructA", i64 0, metadata !7, i64 4, metadata !4} +// PATH: !7 = metadata !{metadata !"short", metadata !1} +// PATH: !8 = metadata !{metadata !6, metadata !7, i64 0} +// PATH: !9 = metadata !{metadata !10, metadata !4, i64 8} +// PATH: !10 = metadata !{metadata !"_ZTS7StructB", i64 0, metadata !7, i64 4, metadata !6, i64 20, metadata !4} +// PATH: !11 = metadata !{metadata !10, metadata !7, i64 4} +// PATH: !12 = metadata !{metadata !10, metadata !4, i64 20} +// PATH: !13 = metadata !{metadata !10, metadata !4, i64 16} +// PATH: !14 = metadata !{metadata !15, metadata !4, i64 4} +// PATH: !15 = metadata !{metadata !"_ZTS7StructS", i64 0, metadata !7, i64 4, metadata !4} +// PATH: !16 = metadata !{metadata !15, metadata !7, i64 0} +// PATH: !17 = metadata !{metadata !18, metadata !4, i64 4} +// PATH: !18 = metadata !{metadata !"_ZTS8StructS2", i64 0, metadata !7, i64 4, metadata !4} +// PATH: !19 = metadata !{metadata !18, metadata !7, i64 0} +// PATH: !20 = metadata !{metadata !21, metadata !4, i64 12} +// PATH: !21 = metadata !{metadata !"_ZTS7StructC", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4} +// PATH: !22 = metadata !{metadata !23, metadata !4, i64 12} +// PATH: !23 = metadata !{metadata !"_ZTS7StructD", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4, i64 32, metadata !1} git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178784 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/CC1Options.td | 2 + include/clang/Driver/Options.td | 1 + include/clang/Frontend/CodeGenOptions.def | 1 + lib/CodeGen/CGExpr.cpp | 42 ++++-- lib/CodeGen/CGValue.h | 15 +++ lib/CodeGen/CodeGenFunction.h | 8 +- lib/CodeGen/CodeGenModule.cpp | 14 ++ lib/CodeGen/CodeGenModule.h | 5 + lib/CodeGen/CodeGenTBAA.cpp | 85 ++++++++++++ lib/CodeGen/CodeGenTBAA.h | 55 +++++++- lib/Driver/Tools.cpp | 2 + lib/Frontend/CompilerInvocation.cpp | 1 + test/CodeGen/tbaa.cpp | 217 ++++++++++++++++++++++++++++++ 13 files changed, 437 insertions(+), 11 deletions(-) create mode 100644 test/CodeGen/tbaa.cpp (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index ab2d5dc4fb..e4dd34509e 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -161,6 +161,8 @@ def fuse_register_sized_bitfield_access: Flag<["-"], "fuse-register-sized-bitfie HelpText<"Use register sized accesses to bit-fields, when possible.">; def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">, HelpText<"Turn off Type Based Alias Analysis">; +def struct_path_tbaa : Flag<["-"], "struct-path-tbaa">, + HelpText<"Turn on struct-path aware Type Based Alias Analysis">; def masm_verbose : Flag<["-"], "masm-verbose">, HelpText<"Generate verbose assembly output">; def mcode_model : Separate<["-"], "mcode-model">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index dd5062c078..112feb77b1 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -587,6 +587,7 @@ def fno_spell_checking : Flag<["-"], "fno-spell-checking">, Group, Flags<[CC1Option]>, HelpText<"Disable spell-checking">; def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group; def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group; +def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group; def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group; def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group; def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group, diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 4b6754d5dc..1c0b9fa99e 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -86,6 +86,7 @@ VALUE_CODEGENOPT(OptimizationLevel, 3, 0) ///< The -O[0-4] option specified. VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. +CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA. CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero ///< offset in AddressSanitizer. diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 9bfaacbbd6..2f5186d1f4 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1044,7 +1044,8 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) { llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue) { return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(), lvalue.getAlignment().getQuantity(), - lvalue.getType(), lvalue.getTBAAInfo()); + lvalue.getType(), lvalue.getTBAAInfo(), + lvalue.getTBAABaseType(), lvalue.getTBAAOffset()); } static bool hasBooleanRepresentation(QualType Ty) { @@ -1106,7 +1107,9 @@ llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) { llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo) { + llvm::MDNode *TBAAInfo, + QualType TBAABaseType, + uint64_t TBAAOffset) { // For better performance, handle vector loads differently. if (Ty->isVectorType()) { llvm::Value *V; @@ -1158,8 +1161,11 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, Load->setVolatile(true); if (Alignment) Load->setAlignment(Alignment); - if (TBAAInfo) - CGM.DecorateInstruction(Load, TBAAInfo); + if (TBAAInfo) { + llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, + TBAAOffset); + CGM.DecorateInstruction(Load, TBAAPath); + } if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) || (SanOpts->Enum && Ty->getAs())) { @@ -1217,7 +1223,8 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, llvm::MDNode *TBAAInfo, - bool isInit) { + bool isInit, QualType TBAABaseType, + uint64_t TBAAOffset) { // Handle vectors differently to get better performance. if (Ty->isVectorType()) { @@ -1268,15 +1275,19 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr, llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile); if (Alignment) Store->setAlignment(Alignment); - if (TBAAInfo) - CGM.DecorateInstruction(Store, TBAAInfo); + if (TBAAInfo) { + llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, + TBAAOffset); + CGM.DecorateInstruction(Store, TBAAPath); + } } void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue, bool isInit) { EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(), lvalue.getAlignment().getQuantity(), lvalue.getType(), - lvalue.getTBAAInfo(), isInit); + lvalue.getTBAAInfo(), isInit, lvalue.getTBAABaseType(), + lvalue.getTBAAOffset()); } /// EmitLoadOfLValue - Given an expression that represents a value lvalue, this @@ -2494,9 +2505,12 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, llvm::Value *addr = base.getAddress(); unsigned cvr = base.getVRQualifiers(); + bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA; if (rec->isUnion()) { // For unions, there is no pointer adjustment. assert(!type->isReferenceType() && "union has reference member"); + // TODO: handle path-aware TBAA for union. + TBAAPath = false; } else { // For structs, we GEP to the field that the record layout suggests. unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field); @@ -2508,6 +2522,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, if (cvr & Qualifiers::Volatile) load->setVolatile(true); load->setAlignment(alignment.getQuantity()); + // Loading the reference will disable path-aware TBAA. + TBAAPath = false; if (CGM.shouldUseTBAA()) { llvm::MDNode *tbaa; if (mayAlias) @@ -2541,6 +2557,16 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, LValue LV = MakeAddrLValue(addr, type, alignment); LV.getQuals().addCVRQualifiers(cvr); + if (TBAAPath) { + const ASTRecordLayout &Layout = + getContext().getASTRecordLayout(field->getParent()); + // Set the base type to be the base type of the base LValue and + // update offset to be relative to the base type. + LV.setTBAABaseType(base.getTBAABaseType()); + LV.setTBAAOffset(base.getTBAAOffset() + + Layout.getFieldOffset(field->getFieldIndex()) / + getContext().getCharWidth()); + } // __weak attribute on a field is ignored. if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak) diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index 0657fdca36..b625b866c0 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -157,6 +157,11 @@ class LValue { Expr *BaseIvarExp; + /// Used by struct-path-aware TBAA. + QualType TBAABaseType; + /// Offset relative to the base type. + uint64_t TBAAOffset; + /// TBAAInfo - TBAA information to attach to dereferences of this LValue. llvm::MDNode *TBAAInfo; @@ -175,6 +180,10 @@ private: this->ImpreciseLifetime = false; this->ThreadLocalRef = false; this->BaseIvarExp = 0; + + // Initialize fields for TBAA. + this->TBAABaseType = Type; + this->TBAAOffset = 0; this->TBAAInfo = TBAAInfo; } @@ -232,6 +241,12 @@ public: Expr *getBaseIvarExp() const { return BaseIvarExp; } void setBaseIvarExp(Expr *V) { BaseIvarExp = V; } + QualType getTBAABaseType() const { return TBAABaseType; } + void setTBAABaseType(QualType T) { TBAABaseType = T; } + + uint64_t getTBAAOffset() const { return TBAAOffset; } + void setTBAAOffset(uint64_t O) { TBAAOffset = O; } + llvm::MDNode *getTBAAInfo() const { return TBAAInfo; } void setTBAAInfo(llvm::MDNode *N) { TBAAInfo = N; } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index f76022fb97..645d5ff237 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -2211,7 +2211,9 @@ public: /// the LLVM value representation. llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo = 0); + llvm::MDNode *TBAAInfo = 0, + QualType TBAABaseTy = QualType(), + uint64_t TBAAOffset = 0); /// EmitLoadOfScalar - Load a scalar value from an address, taking /// care to appropriately convert from the memory representation to @@ -2224,7 +2226,9 @@ public: /// the LLVM value representation. void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo = 0, bool isInit=false); + llvm::MDNode *TBAAInfo = 0, bool isInit = false, + QualType TBAABaseTy = QualType(), + uint64_t TBAAOffset = 0); /// EmitStoreOfScalar - Store a scalar value to an address, taking /// care to appropriately convert from the memory representation to diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 6d85a8835b..c518a5554e 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -227,6 +227,20 @@ llvm::MDNode *CodeGenModule::getTBAAStructInfo(QualType QTy) { return TBAA->getTBAAStructInfo(QTy); } +llvm::MDNode *CodeGenModule::getTBAAStructTypeInfo(QualType QTy) { + if (!TBAA) + return 0; + return TBAA->getTBAAStructTypeInfo(QTy); +} + +llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(QualType BaseTy, + llvm::MDNode *AccessN, + uint64_t O) { + if (!TBAA) + return 0; + return TBAA->getTBAAStructTagInfo(BaseTy, AccessN, O); +} + void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst, llvm::MDNode *TBAAInfo) { Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index fcd48302ae..5b2153e5ff 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -501,6 +501,11 @@ public: llvm::MDNode *getTBAAInfo(QualType QTy); llvm::MDNode *getTBAAInfoForVTablePtr(); llvm::MDNode *getTBAAStructInfo(QualType QTy); + /// Return the MDNode in the type DAG for the given struct type. + llvm::MDNode *getTBAAStructTypeInfo(QualType QTy); + /// Return the path-aware tag for given base type, access node and offset. + llvm::MDNode *getTBAAStructTagInfo(QualType BaseTy, llvm::MDNode *AccessN, + uint64_t O); bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor); diff --git a/lib/CodeGen/CodeGenTBAA.cpp b/lib/CodeGen/CodeGenTBAA.cpp index cfa141ea9a..7e4d34ab89 100644 --- a/lib/CodeGen/CodeGenTBAA.cpp +++ b/lib/CodeGen/CodeGenTBAA.cpp @@ -21,6 +21,7 @@ #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" #include "clang/Frontend/CodeGenOptions.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" @@ -225,3 +226,87 @@ CodeGenTBAA::getTBAAStructInfo(QualType QTy) { // For now, handle any other kind of type conservatively. return StructMetadataCache[Ty] = NULL; } + +/// Check if the given type can be handled by path-aware TBAA. +static bool isTBAAPathStruct(QualType QTy) { + if (const RecordType *TTy = QTy->getAs()) { + const RecordDecl *RD = TTy->getDecl()->getDefinition(); + // RD can be struct, union, class, interface or enum. + // For now, we only handle struct. + if (RD->isStruct() && !RD->hasFlexibleArrayMember()) + return true; + } + return false; +} + +llvm::MDNode * +CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) { + const Type *Ty = Context.getCanonicalType(QTy).getTypePtr(); + assert(isTBAAPathStruct(QTy)); + + if (llvm::MDNode *N = StructTypeMetadataCache[Ty]) + return N; + + if (const RecordType *TTy = QTy->getAs()) { + const RecordDecl *RD = TTy->getDecl()->getDefinition(); + + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + SmallVector , 4> Fields; + // To reduce the size of MDNode for a given struct type, we only output + // once for all the fields with the same scalar types. + // Offsets for scalar fields in the type DAG are not used. + llvm::SmallSet ScalarFieldTypes; + unsigned idx = 0; + for (RecordDecl::field_iterator i = RD->field_begin(), + e = RD->field_end(); i != e; ++i, ++idx) { + QualType FieldQTy = i->getType(); + llvm::MDNode *FieldNode; + if (isTBAAPathStruct(FieldQTy)) + FieldNode = getTBAAStructTypeInfo(FieldQTy); + else { + FieldNode = getTBAAInfo(FieldQTy); + // Ignore this field if the type already exists. + if (ScalarFieldTypes.count(FieldNode)) + continue; + ScalarFieldTypes.insert(FieldNode); + } + if (!FieldNode) + return StructTypeMetadataCache[Ty] = NULL; + Fields.push_back(std::make_pair( + Layout.getFieldOffset(idx) / Context.getCharWidth(), FieldNode)); + } + + // TODO: This is using the RTTI name. Is there a better way to get + // a unique string for a type? + SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + MContext.mangleCXXRTTIName(QualType(Ty, 0), Out); + Out.flush(); + // Create the struct type node with a vector of pairs (offset, type). + return StructTypeMetadataCache[Ty] = + MDHelper.createTBAAStructTypeNode(OutName, Fields); + } + + return StructMetadataCache[Ty] = NULL; +} + +llvm::MDNode * +CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode, + uint64_t Offset) { + if (!CodeGenOpts.StructPathTBAA) + return AccessNode; + + const Type *BTy = Context.getCanonicalType(BaseQTy).getTypePtr(); + TBAAPathTag PathTag = TBAAPathTag(BTy, AccessNode, Offset); + if (llvm::MDNode *N = StructTagMetadataCache[PathTag]) + return N; + + llvm::MDNode *BNode = 0; + if (isTBAAPathStruct(BaseQTy)) + BNode = getTBAAStructTypeInfo(BaseQTy); + if (!BNode) + return StructTagMetadataCache[PathTag] = AccessNode; + + return StructTagMetadataCache[PathTag] = + MDHelper.createTBAAStructTagNode(BNode, AccessNode, Offset); +} diff --git a/lib/CodeGen/CodeGenTBAA.h b/lib/CodeGen/CodeGenTBAA.h index 4c6e045fce..9ddc3aa970 100644 --- a/lib/CodeGen/CodeGenTBAA.h +++ b/lib/CodeGen/CodeGenTBAA.h @@ -35,6 +35,14 @@ namespace clang { namespace CodeGen { class CGRecordLayout; + struct TBAAPathTag { + TBAAPathTag(const Type *B, const llvm::MDNode *A, uint64_t O) + : BaseT(B), AccessN(A), Offset(O) {} + const Type *BaseT; + const llvm::MDNode *AccessN; + uint64_t Offset; + }; + /// CodeGenTBAA - This class organizes the cross-module state that is used /// while lowering AST types to LLVM types. class CodeGenTBAA { @@ -46,8 +54,13 @@ class CodeGenTBAA { // MDHelper - Helper for creating metadata. llvm::MDBuilder MDHelper; - /// MetadataCache - This maps clang::Types to llvm::MDNodes describing them. + /// MetadataCache - This maps clang::Types to scalar llvm::MDNodes describing + /// them. llvm::DenseMap MetadataCache; + /// This maps clang::Types to a struct node in the type DAG. + llvm::DenseMap StructTypeMetadataCache; + /// This maps TBAAPathTags to a tag node. + llvm::DenseMap StructTagMetadataCache; /// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing /// them for struct assignments. @@ -89,9 +102,49 @@ public: /// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of /// the given type. llvm::MDNode *getTBAAStructInfo(QualType QTy); + + /// Get the MDNode in the type DAG for given struct type QType. + llvm::MDNode *getTBAAStructTypeInfo(QualType QType); + /// Get the tag MDNode for a given base type, the actual sclar access MDNode + /// and offset into the base type. + llvm::MDNode *getTBAAStructTagInfo(QualType BaseQType, + llvm::MDNode *AccessNode, uint64_t Offset); }; } // end namespace CodeGen } // end namespace clang +namespace llvm { + +template<> struct DenseMapInfo { + static clang::CodeGen::TBAAPathTag getEmptyKey() { + return clang::CodeGen::TBAAPathTag( + DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey()); + } + + static clang::CodeGen::TBAAPathTag getTombstoneKey() { + return clang::CodeGen::TBAAPathTag( + DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey()); + } + + static unsigned getHashValue(const clang::CodeGen::TBAAPathTag &Val) { + return DenseMapInfo::getHashValue(Val.BaseT) ^ + DenseMapInfo::getHashValue(Val.AccessN) ^ + DenseMapInfo::getHashValue(Val.Offset); + } + + static bool isEqual(const clang::CodeGen::TBAAPathTag &LHS, + const clang::CodeGen::TBAAPathTag &RHS) { + return LHS.BaseT == RHS.BaseT && + LHS.AccessN == RHS.AccessN && + LHS.Offset == RHS.Offset; + } +}; + +} // end namespace llvm + #endif diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 83c140d2b3..77a72ba33a 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -2105,6 +2105,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_strict_aliasing, getToolChain().IsStrictAliasingDefault())) CmdArgs.push_back("-relaxed-aliasing"); + if (Args.hasArg(options::OPT_fstruct_path_tbaa)) + CmdArgs.push_back("-struct-path-tbaa"); if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums, false)) CmdArgs.push_back("-fstrict-enums"); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 611e784814..41f941729a 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -324,6 +324,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.UseRegisterSizedBitfieldAccess = Args.hasArg( OPT_fuse_register_sized_bitfield_access); Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing); + Opts.StructPathTBAA = Args.hasArg(OPT_struct_path_tbaa); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); diff --git a/test/CodeGen/tbaa.cpp b/test/CodeGen/tbaa.cpp new file mode 100644 index 0000000000..c30e4a331d --- /dev/null +++ b/test/CodeGen/tbaa.cpp @@ -0,0 +1,217 @@ +// RUN: %clang_cc1 -O1 -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -O1 -struct-path-tbaa -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s -check-prefix=PATH +// Test TBAA metadata generated by front-end. + +#include +typedef struct +{ + uint16_t f16; + uint32_t f32; + uint16_t f16_2; + uint32_t f32_2; +} StructA; +typedef struct +{ + uint16_t f16; + StructA a; + uint32_t f32; +} StructB; +typedef struct +{ + uint16_t f16; + StructB b; + uint32_t f32; +} StructC; +typedef struct +{ + uint16_t f16; + StructB b; + uint32_t f32; + uint8_t f8; +} StructD; + +typedef struct +{ + uint16_t f16; + uint32_t f32; +} StructS; +typedef struct +{ + uint16_t f16; + uint32_t f32; +} StructS2; + +uint32_t g(uint32_t *s, StructA *A, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !5 + *s = 1; + A->f32 = 4; + return *s; +} + +uint32_t g2(uint32_t *s, StructA *A, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !8 + *s = 1; + A->f16 = 4; + return *s; +} + +uint32_t g3(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9 + A->f32 = 1; + B->a.f32 = 4; + return A->f32; +} + +uint32_t g4(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !11 + A->f32 = 1; + B->a.f16 = 4; + return A->f32; +} + +uint32_t g5(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !12 + A->f32 = 1; + B->f32 = 4; + return A->f32; +} + +uint32_t g6(StructA *A, StructB *B, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !13 + A->f32 = 1; + B->a.f32_2 = 4; + return A->f32; +} + +uint32_t g7(StructA *A, StructS *S, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !14 + A->f32 = 1; + S->f32 = 4; + return A->f32; +} + +uint32_t g8(StructA *A, StructS *S, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !16 + A->f32 = 1; + S->f16 = 4; + return A->f32; +} + +uint32_t g9(StructS *S, StructS2 *S2, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !17 + S->f32 = 1; + S2->f32 = 4; + return S->f32; +} + +uint32_t g10(StructS *S, StructS2 *S2, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14 +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !19 + S->f32 = 1; + S2->f16 = 4; + return S->f32; +} + +uint32_t g11(StructC *C, StructD *D, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !20 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !22 + C->b.a.f32 = 1; + D->b.a.f32 = 4; + return C->b.a.f32; +} + +uint32_t g12(StructC *C, StructD *D, uint64_t count) { +// CHECK: define i32 @{{.*}}( +// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 +// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 +// TODO: differentiate the two accesses. +// PATH: define i32 @{{.*}}( +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !9 +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9 + StructB *b1 = &(C->b); + StructB *b2 = &(D->b); + // b1, b2 have different context. + b1->a.f32 = 1; + b2->a.f32 = 4; + return b1->a.f32; +} + +// CHECK: !1 = metadata !{metadata !"omnipotent char", metadata !2} +// CHECK: !2 = metadata !{metadata !"Simple C/C++ TBAA"} +// CHECK: !4 = metadata !{metadata !"int", metadata !1} +// CHECK: !5 = metadata !{metadata !"short", metadata !1} + +// PATH: !1 = metadata !{metadata !"omnipotent char", metadata !2} +// PATH: !4 = metadata !{metadata !"int", metadata !1} +// PATH: !5 = metadata !{metadata !6, metadata !4, i64 4} +// PATH: !6 = metadata !{metadata !"_ZTS7StructA", i64 0, metadata !7, i64 4, metadata !4} +// PATH: !7 = metadata !{metadata !"short", metadata !1} +// PATH: !8 = metadata !{metadata !6, metadata !7, i64 0} +// PATH: !9 = metadata !{metadata !10, metadata !4, i64 8} +// PATH: !10 = metadata !{metadata !"_ZTS7StructB", i64 0, metadata !7, i64 4, metadata !6, i64 20, metadata !4} +// PATH: !11 = metadata !{metadata !10, metadata !7, i64 4} +// PATH: !12 = metadata !{metadata !10, metadata !4, i64 20} +// PATH: !13 = metadata !{metadata !10, metadata !4, i64 16} +// PATH: !14 = metadata !{metadata !15, metadata !4, i64 4} +// PATH: !15 = metadata !{metadata !"_ZTS7StructS", i64 0, metadata !7, i64 4, metadata !4} +// PATH: !16 = metadata !{metadata !15, metadata !7, i64 0} +// PATH: !17 = metadata !{metadata !18, metadata !4, i64 4} +// PATH: !18 = metadata !{metadata !"_ZTS8StructS2", i64 0, metadata !7, i64 4, metadata !4} +// PATH: !19 = metadata !{metadata !18, metadata !7, i64 0} +// PATH: !20 = metadata !{metadata !21, metadata !4, i64 12} +// PATH: !21 = metadata !{metadata !"_ZTS7StructC", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4} +// PATH: !22 = metadata !{metadata !23, metadata !4, i64 12} +// PATH: !23 = metadata !{metadata !"_ZTS7StructD", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4, i64 32, metadata !1} -- cgit v1.2.3-70-g09d2 From 7cc0a110bcf3fe9c4d1269ea2ae7e72aa7f37531 Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Thu, 4 Apr 2013 21:51:07 +0000 Subject: revert r178784 since it does not have a commit message git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178796 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/CC1Options.td | 2 - include/clang/Driver/Options.td | 1 - include/clang/Frontend/CodeGenOptions.def | 1 - lib/CodeGen/CGExpr.cpp | 42 ++---- lib/CodeGen/CGValue.h | 15 --- lib/CodeGen/CodeGenFunction.h | 8 +- lib/CodeGen/CodeGenModule.cpp | 14 -- lib/CodeGen/CodeGenModule.h | 5 - lib/CodeGen/CodeGenTBAA.cpp | 85 ------------ lib/CodeGen/CodeGenTBAA.h | 55 +------- lib/Driver/Tools.cpp | 2 - lib/Frontend/CompilerInvocation.cpp | 1 - test/CodeGen/tbaa.cpp | 217 ------------------------------ 13 files changed, 11 insertions(+), 437 deletions(-) delete mode 100644 test/CodeGen/tbaa.cpp (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index e4dd34509e..ab2d5dc4fb 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -161,8 +161,6 @@ def fuse_register_sized_bitfield_access: Flag<["-"], "fuse-register-sized-bitfie HelpText<"Use register sized accesses to bit-fields, when possible.">; def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">, HelpText<"Turn off Type Based Alias Analysis">; -def struct_path_tbaa : Flag<["-"], "struct-path-tbaa">, - HelpText<"Turn on struct-path aware Type Based Alias Analysis">; def masm_verbose : Flag<["-"], "masm-verbose">, HelpText<"Generate verbose assembly output">; def mcode_model : Separate<["-"], "mcode-model">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 112feb77b1..dd5062c078 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -587,7 +587,6 @@ def fno_spell_checking : Flag<["-"], "fno-spell-checking">, Group, Flags<[CC1Option]>, HelpText<"Disable spell-checking">; def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group; def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group; -def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group; def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group; def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group; def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group, diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 1c0b9fa99e..4b6754d5dc 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -86,7 +86,6 @@ VALUE_CODEGENOPT(OptimizationLevel, 3, 0) ///< The -O[0-4] option specified. VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. -CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA. CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero ///< offset in AddressSanitizer. diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 2f5186d1f4..9bfaacbbd6 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1044,8 +1044,7 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) { llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue) { return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(), lvalue.getAlignment().getQuantity(), - lvalue.getType(), lvalue.getTBAAInfo(), - lvalue.getTBAABaseType(), lvalue.getTBAAOffset()); + lvalue.getType(), lvalue.getTBAAInfo()); } static bool hasBooleanRepresentation(QualType Ty) { @@ -1107,9 +1106,7 @@ llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) { llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo, - QualType TBAABaseType, - uint64_t TBAAOffset) { + llvm::MDNode *TBAAInfo) { // For better performance, handle vector loads differently. if (Ty->isVectorType()) { llvm::Value *V; @@ -1161,11 +1158,8 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, Load->setVolatile(true); if (Alignment) Load->setAlignment(Alignment); - if (TBAAInfo) { - llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, - TBAAOffset); - CGM.DecorateInstruction(Load, TBAAPath); - } + if (TBAAInfo) + CGM.DecorateInstruction(Load, TBAAInfo); if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) || (SanOpts->Enum && Ty->getAs())) { @@ -1223,8 +1217,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, llvm::MDNode *TBAAInfo, - bool isInit, QualType TBAABaseType, - uint64_t TBAAOffset) { + bool isInit) { // Handle vectors differently to get better performance. if (Ty->isVectorType()) { @@ -1275,19 +1268,15 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr, llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile); if (Alignment) Store->setAlignment(Alignment); - if (TBAAInfo) { - llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, - TBAAOffset); - CGM.DecorateInstruction(Store, TBAAPath); - } + if (TBAAInfo) + CGM.DecorateInstruction(Store, TBAAInfo); } void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue, bool isInit) { EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(), lvalue.getAlignment().getQuantity(), lvalue.getType(), - lvalue.getTBAAInfo(), isInit, lvalue.getTBAABaseType(), - lvalue.getTBAAOffset()); + lvalue.getTBAAInfo(), isInit); } /// EmitLoadOfLValue - Given an expression that represents a value lvalue, this @@ -2505,12 +2494,9 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, llvm::Value *addr = base.getAddress(); unsigned cvr = base.getVRQualifiers(); - bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA; if (rec->isUnion()) { // For unions, there is no pointer adjustment. assert(!type->isReferenceType() && "union has reference member"); - // TODO: handle path-aware TBAA for union. - TBAAPath = false; } else { // For structs, we GEP to the field that the record layout suggests. unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field); @@ -2522,8 +2508,6 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, if (cvr & Qualifiers::Volatile) load->setVolatile(true); load->setAlignment(alignment.getQuantity()); - // Loading the reference will disable path-aware TBAA. - TBAAPath = false; if (CGM.shouldUseTBAA()) { llvm::MDNode *tbaa; if (mayAlias) @@ -2557,16 +2541,6 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, LValue LV = MakeAddrLValue(addr, type, alignment); LV.getQuals().addCVRQualifiers(cvr); - if (TBAAPath) { - const ASTRecordLayout &Layout = - getContext().getASTRecordLayout(field->getParent()); - // Set the base type to be the base type of the base LValue and - // update offset to be relative to the base type. - LV.setTBAABaseType(base.getTBAABaseType()); - LV.setTBAAOffset(base.getTBAAOffset() + - Layout.getFieldOffset(field->getFieldIndex()) / - getContext().getCharWidth()); - } // __weak attribute on a field is ignored. if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak) diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index b625b866c0..0657fdca36 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -157,11 +157,6 @@ class LValue { Expr *BaseIvarExp; - /// Used by struct-path-aware TBAA. - QualType TBAABaseType; - /// Offset relative to the base type. - uint64_t TBAAOffset; - /// TBAAInfo - TBAA information to attach to dereferences of this LValue. llvm::MDNode *TBAAInfo; @@ -180,10 +175,6 @@ private: this->ImpreciseLifetime = false; this->ThreadLocalRef = false; this->BaseIvarExp = 0; - - // Initialize fields for TBAA. - this->TBAABaseType = Type; - this->TBAAOffset = 0; this->TBAAInfo = TBAAInfo; } @@ -241,12 +232,6 @@ public: Expr *getBaseIvarExp() const { return BaseIvarExp; } void setBaseIvarExp(Expr *V) { BaseIvarExp = V; } - QualType getTBAABaseType() const { return TBAABaseType; } - void setTBAABaseType(QualType T) { TBAABaseType = T; } - - uint64_t getTBAAOffset() const { return TBAAOffset; } - void setTBAAOffset(uint64_t O) { TBAAOffset = O; } - llvm::MDNode *getTBAAInfo() const { return TBAAInfo; } void setTBAAInfo(llvm::MDNode *N) { TBAAInfo = N; } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 645d5ff237..f76022fb97 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -2211,9 +2211,7 @@ public: /// the LLVM value representation. llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo = 0, - QualType TBAABaseTy = QualType(), - uint64_t TBAAOffset = 0); + llvm::MDNode *TBAAInfo = 0); /// EmitLoadOfScalar - Load a scalar value from an address, taking /// care to appropriately convert from the memory representation to @@ -2226,9 +2224,7 @@ public: /// the LLVM value representation. void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo = 0, bool isInit = false, - QualType TBAABaseTy = QualType(), - uint64_t TBAAOffset = 0); + llvm::MDNode *TBAAInfo = 0, bool isInit=false); /// EmitStoreOfScalar - Store a scalar value to an address, taking /// care to appropriately convert from the memory representation to diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index c518a5554e..6d85a8835b 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -227,20 +227,6 @@ llvm::MDNode *CodeGenModule::getTBAAStructInfo(QualType QTy) { return TBAA->getTBAAStructInfo(QTy); } -llvm::MDNode *CodeGenModule::getTBAAStructTypeInfo(QualType QTy) { - if (!TBAA) - return 0; - return TBAA->getTBAAStructTypeInfo(QTy); -} - -llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(QualType BaseTy, - llvm::MDNode *AccessN, - uint64_t O) { - if (!TBAA) - return 0; - return TBAA->getTBAAStructTagInfo(BaseTy, AccessN, O); -} - void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst, llvm::MDNode *TBAAInfo) { Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 5b2153e5ff..fcd48302ae 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -501,11 +501,6 @@ public: llvm::MDNode *getTBAAInfo(QualType QTy); llvm::MDNode *getTBAAInfoForVTablePtr(); llvm::MDNode *getTBAAStructInfo(QualType QTy); - /// Return the MDNode in the type DAG for the given struct type. - llvm::MDNode *getTBAAStructTypeInfo(QualType QTy); - /// Return the path-aware tag for given base type, access node and offset. - llvm::MDNode *getTBAAStructTagInfo(QualType BaseTy, llvm::MDNode *AccessN, - uint64_t O); bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor); diff --git a/lib/CodeGen/CodeGenTBAA.cpp b/lib/CodeGen/CodeGenTBAA.cpp index 7e4d34ab89..cfa141ea9a 100644 --- a/lib/CodeGen/CodeGenTBAA.cpp +++ b/lib/CodeGen/CodeGenTBAA.cpp @@ -21,7 +21,6 @@ #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" #include "clang/Frontend/CodeGenOptions.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" @@ -226,87 +225,3 @@ CodeGenTBAA::getTBAAStructInfo(QualType QTy) { // For now, handle any other kind of type conservatively. return StructMetadataCache[Ty] = NULL; } - -/// Check if the given type can be handled by path-aware TBAA. -static bool isTBAAPathStruct(QualType QTy) { - if (const RecordType *TTy = QTy->getAs()) { - const RecordDecl *RD = TTy->getDecl()->getDefinition(); - // RD can be struct, union, class, interface or enum. - // For now, we only handle struct. - if (RD->isStruct() && !RD->hasFlexibleArrayMember()) - return true; - } - return false; -} - -llvm::MDNode * -CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) { - const Type *Ty = Context.getCanonicalType(QTy).getTypePtr(); - assert(isTBAAPathStruct(QTy)); - - if (llvm::MDNode *N = StructTypeMetadataCache[Ty]) - return N; - - if (const RecordType *TTy = QTy->getAs()) { - const RecordDecl *RD = TTy->getDecl()->getDefinition(); - - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - SmallVector , 4> Fields; - // To reduce the size of MDNode for a given struct type, we only output - // once for all the fields with the same scalar types. - // Offsets for scalar fields in the type DAG are not used. - llvm::SmallSet ScalarFieldTypes; - unsigned idx = 0; - for (RecordDecl::field_iterator i = RD->field_begin(), - e = RD->field_end(); i != e; ++i, ++idx) { - QualType FieldQTy = i->getType(); - llvm::MDNode *FieldNode; - if (isTBAAPathStruct(FieldQTy)) - FieldNode = getTBAAStructTypeInfo(FieldQTy); - else { - FieldNode = getTBAAInfo(FieldQTy); - // Ignore this field if the type already exists. - if (ScalarFieldTypes.count(FieldNode)) - continue; - ScalarFieldTypes.insert(FieldNode); - } - if (!FieldNode) - return StructTypeMetadataCache[Ty] = NULL; - Fields.push_back(std::make_pair( - Layout.getFieldOffset(idx) / Context.getCharWidth(), FieldNode)); - } - - // TODO: This is using the RTTI name. Is there a better way to get - // a unique string for a type? - SmallString<256> OutName; - llvm::raw_svector_ostream Out(OutName); - MContext.mangleCXXRTTIName(QualType(Ty, 0), Out); - Out.flush(); - // Create the struct type node with a vector of pairs (offset, type). - return StructTypeMetadataCache[Ty] = - MDHelper.createTBAAStructTypeNode(OutName, Fields); - } - - return StructMetadataCache[Ty] = NULL; -} - -llvm::MDNode * -CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode, - uint64_t Offset) { - if (!CodeGenOpts.StructPathTBAA) - return AccessNode; - - const Type *BTy = Context.getCanonicalType(BaseQTy).getTypePtr(); - TBAAPathTag PathTag = TBAAPathTag(BTy, AccessNode, Offset); - if (llvm::MDNode *N = StructTagMetadataCache[PathTag]) - return N; - - llvm::MDNode *BNode = 0; - if (isTBAAPathStruct(BaseQTy)) - BNode = getTBAAStructTypeInfo(BaseQTy); - if (!BNode) - return StructTagMetadataCache[PathTag] = AccessNode; - - return StructTagMetadataCache[PathTag] = - MDHelper.createTBAAStructTagNode(BNode, AccessNode, Offset); -} diff --git a/lib/CodeGen/CodeGenTBAA.h b/lib/CodeGen/CodeGenTBAA.h index 9ddc3aa970..4c6e045fce 100644 --- a/lib/CodeGen/CodeGenTBAA.h +++ b/lib/CodeGen/CodeGenTBAA.h @@ -35,14 +35,6 @@ namespace clang { namespace CodeGen { class CGRecordLayout; - struct TBAAPathTag { - TBAAPathTag(const Type *B, const llvm::MDNode *A, uint64_t O) - : BaseT(B), AccessN(A), Offset(O) {} - const Type *BaseT; - const llvm::MDNode *AccessN; - uint64_t Offset; - }; - /// CodeGenTBAA - This class organizes the cross-module state that is used /// while lowering AST types to LLVM types. class CodeGenTBAA { @@ -54,13 +46,8 @@ class CodeGenTBAA { // MDHelper - Helper for creating metadata. llvm::MDBuilder MDHelper; - /// MetadataCache - This maps clang::Types to scalar llvm::MDNodes describing - /// them. + /// MetadataCache - This maps clang::Types to llvm::MDNodes describing them. llvm::DenseMap MetadataCache; - /// This maps clang::Types to a struct node in the type DAG. - llvm::DenseMap StructTypeMetadataCache; - /// This maps TBAAPathTags to a tag node. - llvm::DenseMap StructTagMetadataCache; /// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing /// them for struct assignments. @@ -102,49 +89,9 @@ public: /// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of /// the given type. llvm::MDNode *getTBAAStructInfo(QualType QTy); - - /// Get the MDNode in the type DAG for given struct type QType. - llvm::MDNode *getTBAAStructTypeInfo(QualType QType); - /// Get the tag MDNode for a given base type, the actual sclar access MDNode - /// and offset into the base type. - llvm::MDNode *getTBAAStructTagInfo(QualType BaseQType, - llvm::MDNode *AccessNode, uint64_t Offset); }; } // end namespace CodeGen } // end namespace clang -namespace llvm { - -template<> struct DenseMapInfo { - static clang::CodeGen::TBAAPathTag getEmptyKey() { - return clang::CodeGen::TBAAPathTag( - DenseMapInfo::getEmptyKey(), - DenseMapInfo::getEmptyKey(), - DenseMapInfo::getEmptyKey()); - } - - static clang::CodeGen::TBAAPathTag getTombstoneKey() { - return clang::CodeGen::TBAAPathTag( - DenseMapInfo::getTombstoneKey(), - DenseMapInfo::getTombstoneKey(), - DenseMapInfo::getTombstoneKey()); - } - - static unsigned getHashValue(const clang::CodeGen::TBAAPathTag &Val) { - return DenseMapInfo::getHashValue(Val.BaseT) ^ - DenseMapInfo::getHashValue(Val.AccessN) ^ - DenseMapInfo::getHashValue(Val.Offset); - } - - static bool isEqual(const clang::CodeGen::TBAAPathTag &LHS, - const clang::CodeGen::TBAAPathTag &RHS) { - return LHS.BaseT == RHS.BaseT && - LHS.AccessN == RHS.AccessN && - LHS.Offset == RHS.Offset; - } -}; - -} // end namespace llvm - #endif diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 77a72ba33a..83c140d2b3 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -2105,8 +2105,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_strict_aliasing, getToolChain().IsStrictAliasingDefault())) CmdArgs.push_back("-relaxed-aliasing"); - if (Args.hasArg(options::OPT_fstruct_path_tbaa)) - CmdArgs.push_back("-struct-path-tbaa"); if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums, false)) CmdArgs.push_back("-fstrict-enums"); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 41f941729a..611e784814 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -324,7 +324,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.UseRegisterSizedBitfieldAccess = Args.hasArg( OPT_fuse_register_sized_bitfield_access); Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing); - Opts.StructPathTBAA = Args.hasArg(OPT_struct_path_tbaa); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); diff --git a/test/CodeGen/tbaa.cpp b/test/CodeGen/tbaa.cpp deleted file mode 100644 index c30e4a331d..0000000000 --- a/test/CodeGen/tbaa.cpp +++ /dev/null @@ -1,217 +0,0 @@ -// RUN: %clang_cc1 -O1 -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 -O1 -struct-path-tbaa -disable-llvm-optzns %s -emit-llvm -o - | FileCheck %s -check-prefix=PATH -// Test TBAA metadata generated by front-end. - -#include -typedef struct -{ - uint16_t f16; - uint32_t f32; - uint16_t f16_2; - uint32_t f32_2; -} StructA; -typedef struct -{ - uint16_t f16; - StructA a; - uint32_t f32; -} StructB; -typedef struct -{ - uint16_t f16; - StructB b; - uint32_t f32; -} StructC; -typedef struct -{ - uint16_t f16; - StructB b; - uint32_t f32; - uint8_t f8; -} StructD; - -typedef struct -{ - uint16_t f16; - uint32_t f32; -} StructS; -typedef struct -{ - uint16_t f16; - uint32_t f32; -} StructS2; - -uint32_t g(uint32_t *s, StructA *A, uint64_t count) { -// CHECK: define i32 @{{.*}}( -// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 -// PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !5 - *s = 1; - A->f32 = 4; - return *s; -} - -uint32_t g2(uint32_t *s, StructA *A, uint64_t count) { -// CHECK: define i32 @{{.*}}( -// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 -// PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !8 - *s = 1; - A->f16 = 4; - return *s; -} - -uint32_t g3(StructA *A, StructB *B, uint64_t count) { -// CHECK: define i32 @{{.*}}( -// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 -// PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9 - A->f32 = 1; - B->a.f32 = 4; - return A->f32; -} - -uint32_t g4(StructA *A, StructB *B, uint64_t count) { -// CHECK: define i32 @{{.*}}( -// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 -// PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 -// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !11 - A->f32 = 1; - B->a.f16 = 4; - return A->f32; -} - -uint32_t g5(StructA *A, StructB *B, uint64_t count) { -// CHECK: define i32 @{{.*}}( -// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 -// PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !12 - A->f32 = 1; - B->f32 = 4; - return A->f32; -} - -uint32_t g6(StructA *A, StructB *B, uint64_t count) { -// CHECK: define i32 @{{.*}}( -// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 -// PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !13 - A->f32 = 1; - B->a.f32_2 = 4; - return A->f32; -} - -uint32_t g7(StructA *A, StructS *S, uint64_t count) { -// CHECK: define i32 @{{.*}}( -// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 -// PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !14 - A->f32 = 1; - S->f32 = 4; - return A->f32; -} - -uint32_t g8(StructA *A, StructS *S, uint64_t count) { -// CHECK: define i32 @{{.*}}( -// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 -// PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 -// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !16 - A->f32 = 1; - S->f16 = 4; - return A->f32; -} - -uint32_t g9(StructS *S, StructS2 *S2, uint64_t count) { -// CHECK: define i32 @{{.*}}( -// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 -// PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !17 - S->f32 = 1; - S2->f32 = 4; - return S->f32; -} - -uint32_t g10(StructS *S, StructS2 *S2, uint64_t count) { -// CHECK: define i32 @{{.*}}( -// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 -// PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14 -// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !19 - S->f32 = 1; - S2->f16 = 4; - return S->f32; -} - -uint32_t g11(StructC *C, StructD *D, uint64_t count) { -// CHECK: define i32 @{{.*}}( -// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 -// PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !20 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !22 - C->b.a.f32 = 1; - D->b.a.f32 = 4; - return C->b.a.f32; -} - -uint32_t g12(StructC *C, StructD *D, uint64_t count) { -// CHECK: define i32 @{{.*}}( -// CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 -// TODO: differentiate the two accesses. -// PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !9 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9 - StructB *b1 = &(C->b); - StructB *b2 = &(D->b); - // b1, b2 have different context. - b1->a.f32 = 1; - b2->a.f32 = 4; - return b1->a.f32; -} - -// CHECK: !1 = metadata !{metadata !"omnipotent char", metadata !2} -// CHECK: !2 = metadata !{metadata !"Simple C/C++ TBAA"} -// CHECK: !4 = metadata !{metadata !"int", metadata !1} -// CHECK: !5 = metadata !{metadata !"short", metadata !1} - -// PATH: !1 = metadata !{metadata !"omnipotent char", metadata !2} -// PATH: !4 = metadata !{metadata !"int", metadata !1} -// PATH: !5 = metadata !{metadata !6, metadata !4, i64 4} -// PATH: !6 = metadata !{metadata !"_ZTS7StructA", i64 0, metadata !7, i64 4, metadata !4} -// PATH: !7 = metadata !{metadata !"short", metadata !1} -// PATH: !8 = metadata !{metadata !6, metadata !7, i64 0} -// PATH: !9 = metadata !{metadata !10, metadata !4, i64 8} -// PATH: !10 = metadata !{metadata !"_ZTS7StructB", i64 0, metadata !7, i64 4, metadata !6, i64 20, metadata !4} -// PATH: !11 = metadata !{metadata !10, metadata !7, i64 4} -// PATH: !12 = metadata !{metadata !10, metadata !4, i64 20} -// PATH: !13 = metadata !{metadata !10, metadata !4, i64 16} -// PATH: !14 = metadata !{metadata !15, metadata !4, i64 4} -// PATH: !15 = metadata !{metadata !"_ZTS7StructS", i64 0, metadata !7, i64 4, metadata !4} -// PATH: !16 = metadata !{metadata !15, metadata !7, i64 0} -// PATH: !17 = metadata !{metadata !18, metadata !4, i64 4} -// PATH: !18 = metadata !{metadata !"_ZTS8StructS2", i64 0, metadata !7, i64 4, metadata !4} -// PATH: !19 = metadata !{metadata !18, metadata !7, i64 0} -// PATH: !20 = metadata !{metadata !21, metadata !4, i64 12} -// PATH: !21 = metadata !{metadata !"_ZTS7StructC", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4} -// PATH: !22 = metadata !{metadata !23, metadata !4, i64 12} -// PATH: !23 = metadata !{metadata !"_ZTS7StructD", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4, i64 32, metadata !1} -- cgit v1.2.3-70-g09d2 From b37a73d5c6a0c8bb1f6e363d3b53980e4fa0cead Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Thu, 4 Apr 2013 21:53:22 +0000 Subject: Initial support for struct-path aware TBAA. Added TBAABaseType and TBAAOffset in LValue. These two fields are initialized to the actual type and 0, and are updated in EmitLValueForField. Path-aware TBAA tags are enabled for EmitLoadOfScalar and EmitStoreOfScalar. Added command line option -struct-path-tbaa. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178797 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/CC1Options.td | 2 + include/clang/Driver/Options.td | 1 + include/clang/Frontend/CodeGenOptions.def | 1 + lib/CodeGen/CGExpr.cpp | 42 ++++++++++++--- lib/CodeGen/CGValue.h | 15 ++++++ lib/CodeGen/CodeGenFunction.h | 8 ++- lib/CodeGen/CodeGenModule.cpp | 14 +++++ lib/CodeGen/CodeGenModule.h | 5 ++ lib/CodeGen/CodeGenTBAA.cpp | 85 +++++++++++++++++++++++++++++++ lib/CodeGen/CodeGenTBAA.h | 55 +++++++++++++++++++- lib/Driver/Tools.cpp | 2 + lib/Frontend/CompilerInvocation.cpp | 1 + 12 files changed, 220 insertions(+), 11 deletions(-) (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index ab2d5dc4fb..e4dd34509e 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -161,6 +161,8 @@ def fuse_register_sized_bitfield_access: Flag<["-"], "fuse-register-sized-bitfie HelpText<"Use register sized accesses to bit-fields, when possible.">; def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">, HelpText<"Turn off Type Based Alias Analysis">; +def struct_path_tbaa : Flag<["-"], "struct-path-tbaa">, + HelpText<"Turn on struct-path aware Type Based Alias Analysis">; def masm_verbose : Flag<["-"], "masm-verbose">, HelpText<"Generate verbose assembly output">; def mcode_model : Separate<["-"], "mcode-model">, diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index dd5062c078..112feb77b1 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -587,6 +587,7 @@ def fno_spell_checking : Flag<["-"], "fno-spell-checking">, Group, Flags<[CC1Option]>, HelpText<"Disable spell-checking">; def fno_stack_protector : Flag<["-"], "fno-stack-protector">, Group; def fno_strict_aliasing : Flag<["-"], "fno-strict-aliasing">, Group; +def fstruct_path_tbaa : Flag<["-"], "fstruct-path-tbaa">, Group; def fno_strict_enums : Flag<["-"], "fno-strict-enums">, Group; def fno_strict_overflow : Flag<["-"], "fno-strict-overflow">, Group; def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group, diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 4b6754d5dc..1c0b9fa99e 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -86,6 +86,7 @@ VALUE_CODEGENOPT(OptimizationLevel, 3, 0) ///< The -O[0-4] option specified. VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. +CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA. CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero ///< offset in AddressSanitizer. diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 9bfaacbbd6..2f5186d1f4 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1044,7 +1044,8 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) { llvm::Value *CodeGenFunction::EmitLoadOfScalar(LValue lvalue) { return EmitLoadOfScalar(lvalue.getAddress(), lvalue.isVolatile(), lvalue.getAlignment().getQuantity(), - lvalue.getType(), lvalue.getTBAAInfo()); + lvalue.getType(), lvalue.getTBAAInfo(), + lvalue.getTBAABaseType(), lvalue.getTBAAOffset()); } static bool hasBooleanRepresentation(QualType Ty) { @@ -1106,7 +1107,9 @@ llvm::MDNode *CodeGenFunction::getRangeForLoadFromType(QualType Ty) { llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo) { + llvm::MDNode *TBAAInfo, + QualType TBAABaseType, + uint64_t TBAAOffset) { // For better performance, handle vector loads differently. if (Ty->isVectorType()) { llvm::Value *V; @@ -1158,8 +1161,11 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, Load->setVolatile(true); if (Alignment) Load->setAlignment(Alignment); - if (TBAAInfo) - CGM.DecorateInstruction(Load, TBAAInfo); + if (TBAAInfo) { + llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, + TBAAOffset); + CGM.DecorateInstruction(Load, TBAAPath); + } if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) || (SanOpts->Enum && Ty->getAs())) { @@ -1217,7 +1223,8 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, llvm::MDNode *TBAAInfo, - bool isInit) { + bool isInit, QualType TBAABaseType, + uint64_t TBAAOffset) { // Handle vectors differently to get better performance. if (Ty->isVectorType()) { @@ -1268,15 +1275,19 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr, llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile); if (Alignment) Store->setAlignment(Alignment); - if (TBAAInfo) - CGM.DecorateInstruction(Store, TBAAInfo); + if (TBAAInfo) { + llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, + TBAAOffset); + CGM.DecorateInstruction(Store, TBAAPath); + } } void CodeGenFunction::EmitStoreOfScalar(llvm::Value *value, LValue lvalue, bool isInit) { EmitStoreOfScalar(value, lvalue.getAddress(), lvalue.isVolatile(), lvalue.getAlignment().getQuantity(), lvalue.getType(), - lvalue.getTBAAInfo(), isInit); + lvalue.getTBAAInfo(), isInit, lvalue.getTBAABaseType(), + lvalue.getTBAAOffset()); } /// EmitLoadOfLValue - Given an expression that represents a value lvalue, this @@ -2494,9 +2505,12 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, llvm::Value *addr = base.getAddress(); unsigned cvr = base.getVRQualifiers(); + bool TBAAPath = CGM.getCodeGenOpts().StructPathTBAA; if (rec->isUnion()) { // For unions, there is no pointer adjustment. assert(!type->isReferenceType() && "union has reference member"); + // TODO: handle path-aware TBAA for union. + TBAAPath = false; } else { // For structs, we GEP to the field that the record layout suggests. unsigned idx = CGM.getTypes().getCGRecordLayout(rec).getLLVMFieldNo(field); @@ -2508,6 +2522,8 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, if (cvr & Qualifiers::Volatile) load->setVolatile(true); load->setAlignment(alignment.getQuantity()); + // Loading the reference will disable path-aware TBAA. + TBAAPath = false; if (CGM.shouldUseTBAA()) { llvm::MDNode *tbaa; if (mayAlias) @@ -2541,6 +2557,16 @@ LValue CodeGenFunction::EmitLValueForField(LValue base, LValue LV = MakeAddrLValue(addr, type, alignment); LV.getQuals().addCVRQualifiers(cvr); + if (TBAAPath) { + const ASTRecordLayout &Layout = + getContext().getASTRecordLayout(field->getParent()); + // Set the base type to be the base type of the base LValue and + // update offset to be relative to the base type. + LV.setTBAABaseType(base.getTBAABaseType()); + LV.setTBAAOffset(base.getTBAAOffset() + + Layout.getFieldOffset(field->getFieldIndex()) / + getContext().getCharWidth()); + } // __weak attribute on a field is ignored. if (LV.getQuals().getObjCGCAttr() == Qualifiers::Weak) diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index 0657fdca36..b625b866c0 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -157,6 +157,11 @@ class LValue { Expr *BaseIvarExp; + /// Used by struct-path-aware TBAA. + QualType TBAABaseType; + /// Offset relative to the base type. + uint64_t TBAAOffset; + /// TBAAInfo - TBAA information to attach to dereferences of this LValue. llvm::MDNode *TBAAInfo; @@ -175,6 +180,10 @@ private: this->ImpreciseLifetime = false; this->ThreadLocalRef = false; this->BaseIvarExp = 0; + + // Initialize fields for TBAA. + this->TBAABaseType = Type; + this->TBAAOffset = 0; this->TBAAInfo = TBAAInfo; } @@ -232,6 +241,12 @@ public: Expr *getBaseIvarExp() const { return BaseIvarExp; } void setBaseIvarExp(Expr *V) { BaseIvarExp = V; } + QualType getTBAABaseType() const { return TBAABaseType; } + void setTBAABaseType(QualType T) { TBAABaseType = T; } + + uint64_t getTBAAOffset() const { return TBAAOffset; } + void setTBAAOffset(uint64_t O) { TBAAOffset = O; } + llvm::MDNode *getTBAAInfo() const { return TBAAInfo; } void setTBAAInfo(llvm::MDNode *N) { TBAAInfo = N; } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index f76022fb97..645d5ff237 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -2211,7 +2211,9 @@ public: /// the LLVM value representation. llvm::Value *EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo = 0); + llvm::MDNode *TBAAInfo = 0, + QualType TBAABaseTy = QualType(), + uint64_t TBAAOffset = 0); /// EmitLoadOfScalar - Load a scalar value from an address, taking /// care to appropriately convert from the memory representation to @@ -2224,7 +2226,9 @@ public: /// the LLVM value representation. void EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr, bool Volatile, unsigned Alignment, QualType Ty, - llvm::MDNode *TBAAInfo = 0, bool isInit=false); + llvm::MDNode *TBAAInfo = 0, bool isInit = false, + QualType TBAABaseTy = QualType(), + uint64_t TBAAOffset = 0); /// EmitStoreOfScalar - Store a scalar value to an address, taking /// care to appropriately convert from the memory representation to diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 6d85a8835b..c518a5554e 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -227,6 +227,20 @@ llvm::MDNode *CodeGenModule::getTBAAStructInfo(QualType QTy) { return TBAA->getTBAAStructInfo(QTy); } +llvm::MDNode *CodeGenModule::getTBAAStructTypeInfo(QualType QTy) { + if (!TBAA) + return 0; + return TBAA->getTBAAStructTypeInfo(QTy); +} + +llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(QualType BaseTy, + llvm::MDNode *AccessN, + uint64_t O) { + if (!TBAA) + return 0; + return TBAA->getTBAAStructTagInfo(BaseTy, AccessN, O); +} + void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst, llvm::MDNode *TBAAInfo) { Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index fcd48302ae..5b2153e5ff 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -501,6 +501,11 @@ public: llvm::MDNode *getTBAAInfo(QualType QTy); llvm::MDNode *getTBAAInfoForVTablePtr(); llvm::MDNode *getTBAAStructInfo(QualType QTy); + /// Return the MDNode in the type DAG for the given struct type. + llvm::MDNode *getTBAAStructTypeInfo(QualType QTy); + /// Return the path-aware tag for given base type, access node and offset. + llvm::MDNode *getTBAAStructTagInfo(QualType BaseTy, llvm::MDNode *AccessN, + uint64_t O); bool isTypeConstant(QualType QTy, bool ExcludeCtorDtor); diff --git a/lib/CodeGen/CodeGenTBAA.cpp b/lib/CodeGen/CodeGenTBAA.cpp index cfa141ea9a..7e4d34ab89 100644 --- a/lib/CodeGen/CodeGenTBAA.cpp +++ b/lib/CodeGen/CodeGenTBAA.cpp @@ -21,6 +21,7 @@ #include "clang/AST/Mangle.h" #include "clang/AST/RecordLayout.h" #include "clang/Frontend/CodeGenOptions.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/IR/Constants.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" @@ -225,3 +226,87 @@ CodeGenTBAA::getTBAAStructInfo(QualType QTy) { // For now, handle any other kind of type conservatively. return StructMetadataCache[Ty] = NULL; } + +/// Check if the given type can be handled by path-aware TBAA. +static bool isTBAAPathStruct(QualType QTy) { + if (const RecordType *TTy = QTy->getAs()) { + const RecordDecl *RD = TTy->getDecl()->getDefinition(); + // RD can be struct, union, class, interface or enum. + // For now, we only handle struct. + if (RD->isStruct() && !RD->hasFlexibleArrayMember()) + return true; + } + return false; +} + +llvm::MDNode * +CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) { + const Type *Ty = Context.getCanonicalType(QTy).getTypePtr(); + assert(isTBAAPathStruct(QTy)); + + if (llvm::MDNode *N = StructTypeMetadataCache[Ty]) + return N; + + if (const RecordType *TTy = QTy->getAs()) { + const RecordDecl *RD = TTy->getDecl()->getDefinition(); + + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + SmallVector , 4> Fields; + // To reduce the size of MDNode for a given struct type, we only output + // once for all the fields with the same scalar types. + // Offsets for scalar fields in the type DAG are not used. + llvm::SmallSet ScalarFieldTypes; + unsigned idx = 0; + for (RecordDecl::field_iterator i = RD->field_begin(), + e = RD->field_end(); i != e; ++i, ++idx) { + QualType FieldQTy = i->getType(); + llvm::MDNode *FieldNode; + if (isTBAAPathStruct(FieldQTy)) + FieldNode = getTBAAStructTypeInfo(FieldQTy); + else { + FieldNode = getTBAAInfo(FieldQTy); + // Ignore this field if the type already exists. + if (ScalarFieldTypes.count(FieldNode)) + continue; + ScalarFieldTypes.insert(FieldNode); + } + if (!FieldNode) + return StructTypeMetadataCache[Ty] = NULL; + Fields.push_back(std::make_pair( + Layout.getFieldOffset(idx) / Context.getCharWidth(), FieldNode)); + } + + // TODO: This is using the RTTI name. Is there a better way to get + // a unique string for a type? + SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + MContext.mangleCXXRTTIName(QualType(Ty, 0), Out); + Out.flush(); + // Create the struct type node with a vector of pairs (offset, type). + return StructTypeMetadataCache[Ty] = + MDHelper.createTBAAStructTypeNode(OutName, Fields); + } + + return StructMetadataCache[Ty] = NULL; +} + +llvm::MDNode * +CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode, + uint64_t Offset) { + if (!CodeGenOpts.StructPathTBAA) + return AccessNode; + + const Type *BTy = Context.getCanonicalType(BaseQTy).getTypePtr(); + TBAAPathTag PathTag = TBAAPathTag(BTy, AccessNode, Offset); + if (llvm::MDNode *N = StructTagMetadataCache[PathTag]) + return N; + + llvm::MDNode *BNode = 0; + if (isTBAAPathStruct(BaseQTy)) + BNode = getTBAAStructTypeInfo(BaseQTy); + if (!BNode) + return StructTagMetadataCache[PathTag] = AccessNode; + + return StructTagMetadataCache[PathTag] = + MDHelper.createTBAAStructTagNode(BNode, AccessNode, Offset); +} diff --git a/lib/CodeGen/CodeGenTBAA.h b/lib/CodeGen/CodeGenTBAA.h index 4c6e045fce..9ddc3aa970 100644 --- a/lib/CodeGen/CodeGenTBAA.h +++ b/lib/CodeGen/CodeGenTBAA.h @@ -35,6 +35,14 @@ namespace clang { namespace CodeGen { class CGRecordLayout; + struct TBAAPathTag { + TBAAPathTag(const Type *B, const llvm::MDNode *A, uint64_t O) + : BaseT(B), AccessN(A), Offset(O) {} + const Type *BaseT; + const llvm::MDNode *AccessN; + uint64_t Offset; + }; + /// CodeGenTBAA - This class organizes the cross-module state that is used /// while lowering AST types to LLVM types. class CodeGenTBAA { @@ -46,8 +54,13 @@ class CodeGenTBAA { // MDHelper - Helper for creating metadata. llvm::MDBuilder MDHelper; - /// MetadataCache - This maps clang::Types to llvm::MDNodes describing them. + /// MetadataCache - This maps clang::Types to scalar llvm::MDNodes describing + /// them. llvm::DenseMap MetadataCache; + /// This maps clang::Types to a struct node in the type DAG. + llvm::DenseMap StructTypeMetadataCache; + /// This maps TBAAPathTags to a tag node. + llvm::DenseMap StructTagMetadataCache; /// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing /// them for struct assignments. @@ -89,9 +102,49 @@ public: /// getTBAAStructInfo - Get the TBAAStruct MDNode to be used for a memcpy of /// the given type. llvm::MDNode *getTBAAStructInfo(QualType QTy); + + /// Get the MDNode in the type DAG for given struct type QType. + llvm::MDNode *getTBAAStructTypeInfo(QualType QType); + /// Get the tag MDNode for a given base type, the actual sclar access MDNode + /// and offset into the base type. + llvm::MDNode *getTBAAStructTagInfo(QualType BaseQType, + llvm::MDNode *AccessNode, uint64_t Offset); }; } // end namespace CodeGen } // end namespace clang +namespace llvm { + +template<> struct DenseMapInfo { + static clang::CodeGen::TBAAPathTag getEmptyKey() { + return clang::CodeGen::TBAAPathTag( + DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey(), + DenseMapInfo::getEmptyKey()); + } + + static clang::CodeGen::TBAAPathTag getTombstoneKey() { + return clang::CodeGen::TBAAPathTag( + DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey(), + DenseMapInfo::getTombstoneKey()); + } + + static unsigned getHashValue(const clang::CodeGen::TBAAPathTag &Val) { + return DenseMapInfo::getHashValue(Val.BaseT) ^ + DenseMapInfo::getHashValue(Val.AccessN) ^ + DenseMapInfo::getHashValue(Val.Offset); + } + + static bool isEqual(const clang::CodeGen::TBAAPathTag &LHS, + const clang::CodeGen::TBAAPathTag &RHS) { + return LHS.BaseT == RHS.BaseT && + LHS.AccessN == RHS.AccessN && + LHS.Offset == RHS.Offset; + } +}; + +} // end namespace llvm + #endif diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 83c140d2b3..77a72ba33a 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -2105,6 +2105,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_strict_aliasing, getToolChain().IsStrictAliasingDefault())) CmdArgs.push_back("-relaxed-aliasing"); + if (Args.hasArg(options::OPT_fstruct_path_tbaa)) + CmdArgs.push_back("-struct-path-tbaa"); if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums, false)) CmdArgs.push_back("-fstrict-enums"); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 611e784814..41f941729a 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -324,6 +324,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.UseRegisterSizedBitfieldAccess = Args.hasArg( OPT_fuse_register_sized_bitfield_access); Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing); + Opts.StructPathTBAA = Args.hasArg(OPT_struct_path_tbaa); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); -- cgit v1.2.3-70-g09d2 From 0024937dbb23752f606846f4a12aafc712bcde33 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 6 Apr 2013 05:00:46 +0000 Subject: When an internal-linkage function or variable is declared within an extern "C" linkage specification, and is marked as __attribute__((used)), try to also give it the unmangled name (by emitting an internal linkage alias) if nothing else within the translation unit would use that name. This allows inline asm in that translation unit to use the entity via its unmangled name, which people apparently rely on. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178950 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++ lib/CodeGen/CodeGenModule.h | 16 +++++++++++++ test/CodeGenCXX/extern-c.cpp | 27 ++++++++++++++++++++++ 3 files changed, 96 insertions(+) (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index c518a5554e..670f06620d 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -186,6 +186,7 @@ void CodeGenModule::Release() { EmitCtorList(GlobalCtors, "llvm.global_ctors"); EmitCtorList(GlobalDtors, "llvm.global_dtors"); EmitGlobalAnnotations(); + EmitStaticExternCAliases(); EmitLLVMUsed(); if (CodeGenOpts.ModulesAutolink) { @@ -1707,6 +1708,39 @@ unsigned CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D, return AddrSpace; } +template +void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D, + llvm::GlobalValue *GV) { + if (!getLangOpts().CPlusPlus) + return; + + // Must have 'used' attribute, or else inline assembly can't rely on + // the name existing. + if (!D->template hasAttr()) + return; + + // Must have internal linkage and an ordinary name. + if (!D->getIdentifier() || D->getLinkage() != InternalLinkage) + return; + + // Must be in an extern "C" context. Entities declared directly within + // a record are not extern "C" even if the record is in such a context. + const DeclContext *DC = D->getFirstDeclaration()->getDeclContext(); + if (DC->isRecord() || !DC->isExternCContext()) + return; + + // OK, this is an internal linkage entity inside an extern "C" linkage + // specification. Make a note of that so we can give it the "expected" + // mangled name if nothing else is using that name. + StaticExternCMap::iterator I = + StaticExternCValues.insert(std::make_pair(D->getIdentifier(), GV)).first; + + // If we have multiple internal linkage entities with the same name + // in extern "C" regions, none of them gets that name. + if (I->second != GV) + I->second = 0; +} + void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { llvm::Constant *Init = 0; QualType ASTTy = D->getType(); @@ -1805,6 +1839,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { cast(Entry)->eraseFromParent(); } + MaybeHandleStaticInExternC(D, GV); + if (D->hasAttr()) AddGlobalAnnotations(D, GV); @@ -2083,6 +2119,8 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { // FIXME: this is redundant with part of SetFunctionDefinitionAttributes setGlobalVisibility(Fn, D); + MaybeHandleStaticInExternC(D, Fn); + CodeGenFunction(*this).GenerateCode(D, Fn, FI); SetFunctionDefinitionAttributes(D, Fn); @@ -2903,6 +2941,21 @@ static void EmitGlobalDeclMetadata(CodeGenModule &CGM, GlobalMetadata->addOperand(llvm::MDNode::get(CGM.getLLVMContext(), Ops)); } +/// For each function which is declared within an extern "C" region and marked +/// as 'used', but has internal linkage, create an alias from the unmangled +/// name to the mangled name if possible. People expect to be able to refer +/// to such functions with an unmangled name from inline assembly within the +/// same translation unit. +void CodeGenModule::EmitStaticExternCAliases() { + for (StaticExternCMap::iterator I = StaticExternCValues.begin(), + E = StaticExternCValues.end(); + I != E; ++I) + if (I->second && !getModule().getNamedValue(I->first->getName())) + AddUsedGlobal( + new llvm::GlobalAlias(I->second->getType(), I->second->getLinkage(), + I->first->getName(), I->second, &getModule())); +} + /// Emits metadata nodes associating all the global values in the /// current module with the Decls they came from. This is useful for /// projects using IR gen as a subroutine. diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 5b2153e5ff..ccac4371c4 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -305,6 +305,12 @@ class CodeGenModule : public CodeGenTypeCache { llvm::DenseMap AtomicSetterHelperFnMap; llvm::DenseMap AtomicGetterHelperFnMap; + /// Map used to track internal linkage functions declared within + /// extern "C" regions. + typedef llvm::DenseMap StaticExternCMap; + StaticExternCMap StaticExternCValues; + /// CXXGlobalInits - Global variables with initializers that need to run /// before main. std::vector CXXGlobalInits; @@ -736,6 +742,12 @@ public: // variable has been instantiated. void HandleCXXStaticMemberVarInstantiation(VarDecl *VD); + /// \brief If the declaration has internal linkage but is inside an + /// extern "C" linkage specification, prepare to emit an alias for it + /// to the expected name. + template + void MaybeHandleStaticInExternC(const SomeDecl *D, llvm::GlobalValue *GV); + /// AddUsedGlobal - Add a global which should be forced to be /// present in the object file; these are emitted to the llvm.used /// metadata global. @@ -1048,6 +1060,10 @@ private: /// \brief Emit the link options introduced by imported modules. void EmitModuleLinkOptions(); + /// \brief Emit aliases for internal-linkage declarations inside "C" language + /// linkage specifications, giving them the "expected" name where possible. + void EmitStaticExternCAliases(); + void EmitDeclMetadata(); /// EmitCoverageFile - Emit the llvm.gcov metadata used to tell LLVM where diff --git a/test/CodeGenCXX/extern-c.cpp b/test/CodeGenCXX/extern-c.cpp index a8c4f0cdbd..5899b9348c 100644 --- a/test/CodeGenCXX/extern-c.cpp +++ b/test/CodeGenCXX/extern-c.cpp @@ -36,3 +36,30 @@ namespace test2 { extern "C" X test2_b; X test2_b; } + +extern "C" { + static int unused_var; + static int unused_fn() { return 0; } + + __attribute__((used)) static int internal_var; + __attribute__((used)) static int internal_fn() { return 0; } + + __attribute__((used)) static int duplicate_internal_var; + __attribute__((used)) static int duplicate_internal_fn() { return 0; } + + namespace N { + __attribute__((used)) static int duplicate_internal_var; + __attribute__((used)) static int duplicate_internal_fn() { return 0; } + } + + // CHECK: @llvm.used = appending global {{.*}} @internal_var {{.*}} @internal_fn + + // CHECK-NOT: @unused + // CHECK-NOT: @duplicate_internal + // CHECK: @internal_var = alias internal i32* @_Z12internal_var + // CHECK-NOT: @unused + // CHECK-NOT: @duplicate_internal + // CHECK: @internal_fn = alias internal i32 ()* @_Z11internal_fnv + // CHECK-NOT: @unused + // CHECK-NOT: @duplicate_internal +} -- cgit v1.2.3-70-g09d2 From 6797204b89c0edb9496249fba557b45d8cc9ec76 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 6 Apr 2013 07:07:44 +0000 Subject: Remove nondeterminism introduced in r178950. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178952 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 24 +++++++++++++----------- lib/CodeGen/CodeGenModule.h | 1 + 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 670f06620d..e8e3d1ae76 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1732,13 +1732,15 @@ void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D, // OK, this is an internal linkage entity inside an extern "C" linkage // specification. Make a note of that so we can give it the "expected" // mangled name if nothing else is using that name. - StaticExternCMap::iterator I = - StaticExternCValues.insert(std::make_pair(D->getIdentifier(), GV)).first; + std::pair R = + StaticExternCValues.insert(std::make_pair(D->getIdentifier(), GV)); // If we have multiple internal linkage entities with the same name // in extern "C" regions, none of them gets that name. - if (I->second != GV) - I->second = 0; + if (!R.second) + R.first->second = 0; + else + StaticExternCIdents.push_back(D->getIdentifier()); } void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { @@ -2947,13 +2949,13 @@ static void EmitGlobalDeclMetadata(CodeGenModule &CGM, /// to such functions with an unmangled name from inline assembly within the /// same translation unit. void CodeGenModule::EmitStaticExternCAliases() { - for (StaticExternCMap::iterator I = StaticExternCValues.begin(), - E = StaticExternCValues.end(); - I != E; ++I) - if (I->second && !getModule().getNamedValue(I->first->getName())) - AddUsedGlobal( - new llvm::GlobalAlias(I->second->getType(), I->second->getLinkage(), - I->first->getName(), I->second, &getModule())); + for (unsigned I = 0, N = StaticExternCIdents.size(); I != N; ++I) { + IdentifierInfo *Name = StaticExternCIdents[I]; + llvm::GlobalValue *Val = StaticExternCValues[Name]; + if (Val && !getModule().getNamedValue(Name->getName())) + AddUsedGlobal(new llvm::GlobalAlias(Val->getType(), Val->getLinkage(), + Name->getName(), Val, &getModule())); + } } /// Emits metadata nodes associating all the global values in the diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index ccac4371c4..6bc44563fa 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -310,6 +310,7 @@ class CodeGenModule : public CodeGenTypeCache { typedef llvm::DenseMap StaticExternCMap; StaticExternCMap StaticExternCValues; + std::vector StaticExternCIdents; /// CXXGlobalInits - Global variables with initializers that need to run /// before main. -- cgit v1.2.3-70-g09d2 From ca835180412eb4382fe4cc97e9374489b9ad3946 Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Thu, 11 Apr 2013 23:02:56 +0000 Subject: Struct-path aware TBAA: uniformize scalar tag and path tag. For struct-path aware TBAA, we used to use scalar type node as the scalar tag, which has an incompatible format with the struct path tag. We now use the same format: base type, access type and offset. We also uniformize the scalar type node and the struct type node: name, a list of pairs (offset + pointer to MDNode). For scalar type, we have a single pair. These are to make implementaiton of aliasing rules easier. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179335 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGExpr.cpp | 4 +- lib/CodeGen/CodeGenModule.cpp | 13 ++++++- lib/CodeGen/CodeGenModule.h | 9 ++++- lib/CodeGen/CodeGenTBAA.cpp | 47 ++++++++++++++-------- lib/CodeGen/CodeGenTBAA.h | 12 +++++- test/CodeGen/tbaa.cpp | 91 ++++++++++++++++++++++--------------------- 6 files changed, 107 insertions(+), 69 deletions(-) (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index fe0d070105..4d72dc1c88 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1175,7 +1175,7 @@ llvm::Value *CodeGenFunction::EmitLoadOfScalar(llvm::Value *Addr, bool Volatile, if (TBAAInfo) { llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, TBAAOffset); - CGM.DecorateInstruction(Load, TBAAPath); + CGM.DecorateInstruction(Load, TBAAPath, false/*ConvertTypeToTag*/); } if ((SanOpts->Bool && hasBooleanRepresentation(Ty)) || @@ -1289,7 +1289,7 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value *Value, llvm::Value *Addr, if (TBAAInfo) { llvm::MDNode *TBAAPath = CGM.getTBAAStructTagInfo(TBAABaseType, TBAAInfo, TBAAOffset); - CGM.DecorateInstruction(Store, TBAAPath); + CGM.DecorateInstruction(Store, TBAAPath, false/*ConvertTypeToTag*/); } } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index e8e3d1ae76..4126bea295 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -242,9 +242,18 @@ llvm::MDNode *CodeGenModule::getTBAAStructTagInfo(QualType BaseTy, return TBAA->getTBAAStructTagInfo(BaseTy, AccessN, O); } +/// Decorate the instruction with a TBAA tag. For scalar TBAA, the tag +/// is the same as the type. For struct-path aware TBAA, the tag +/// is different from the type: base type, access type and offset. +/// When ConvertTypeToTag is true, we create a tag based on the scalar type. void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst, - llvm::MDNode *TBAAInfo) { - Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo); + llvm::MDNode *TBAAInfo, + bool ConvertTypeToTag) { + if (ConvertTypeToTag && TBAA && CodeGenOpts.StructPathTBAA) + Inst->setMetadata(llvm::LLVMContext::MD_tbaa, + TBAA->getTBAAScalarTagInfo(TBAAInfo)); + else + Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo); } bool CodeGenModule::isTargetDarwin() const { diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 6bc44563fa..f8b09711f7 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -519,8 +519,13 @@ public: bool isPaddedAtomicType(QualType type); bool isPaddedAtomicType(const AtomicType *type); - static void DecorateInstruction(llvm::Instruction *Inst, - llvm::MDNode *TBAAInfo); + /// Decorate the instruction with a TBAA tag. For scalar TBAA, the tag + /// is the same as the type. For struct-path aware TBAA, the tag + /// is different from the type: base type, access type and offset. + /// When ConvertTypeToTag is true, we create a tag based on the scalar type. + void DecorateInstruction(llvm::Instruction *Inst, + llvm::MDNode *TBAAInfo, + bool ConvertTypeToTag = true); /// getSize - Emit the given number of characters as a value of type size_t. llvm::ConstantInt *getSize(CharUnits numChars); diff --git a/lib/CodeGen/CodeGenTBAA.cpp b/lib/CodeGen/CodeGenTBAA.cpp index 7e4d34ab89..bb1ebda908 100644 --- a/lib/CodeGen/CodeGenTBAA.cpp +++ b/lib/CodeGen/CodeGenTBAA.cpp @@ -50,13 +50,25 @@ llvm::MDNode *CodeGenTBAA::getRoot() { return Root; } +// For struct-path aware TBAA, the scalar type has the same format as +// the struct type: name, offset, pointer to another node in the type DAG. +// For scalar TBAA, the scalar type is the same as the scalar tag: +// name and a parent pointer. +llvm::MDNode *CodeGenTBAA::createTBAAScalarType(StringRef Name, + llvm::MDNode *Parent) { + if (CodeGenOpts.StructPathTBAA) + return MDHelper.createTBAAScalarTypeNode(Name, 0, Parent); + else + return MDHelper.createTBAANode(Name, Parent); +} + llvm::MDNode *CodeGenTBAA::getChar() { // Define the root of the tree for user-accessible memory. C and C++ // give special powers to char and certain similar types. However, // these special powers only cover user-accessible memory, and doesn't // include things like vtables. if (!Char) - Char = MDHelper.createTBAANode("omnipotent char", getRoot()); + Char = createTBAAScalarType("omnipotent char", getRoot()); return Char; } @@ -124,7 +136,7 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) { // "underlying types". default: return MetadataCache[Ty] = - MDHelper.createTBAANode(BTy->getName(Features), getChar()); + createTBAAScalarType(BTy->getName(Features), getChar()); } } @@ -132,8 +144,8 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) { // TODO: Implement C++'s type "similarity" and consider dis-"similar" // pointers distinct. if (Ty->isPointerType()) - return MetadataCache[Ty] = MDHelper.createTBAANode("any pointer", - getChar()); + return MetadataCache[Ty] = createTBAAScalarType("any pointer", + getChar()); // Enum types are distinct types. In C++ they have "underlying types", // however they aren't related for TBAA. @@ -160,7 +172,7 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) { llvm::raw_svector_ostream Out(OutName); MContext.mangleCXXRTTIName(QualType(ETy, 0), Out); Out.flush(); - return MetadataCache[Ty] = MDHelper.createTBAANode(OutName, getChar()); + return MetadataCache[Ty] = createTBAAScalarType(OutName, getChar()); } // For now, handle any other kind of type conservatively. @@ -168,7 +180,7 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) { } llvm::MDNode *CodeGenTBAA::getTBAAInfoForVTablePtr() { - return MDHelper.createTBAANode("vtable pointer", getRoot()); + return createTBAAScalarType("vtable pointer", getRoot()); } bool @@ -252,10 +264,6 @@ CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) { const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); SmallVector , 4> Fields; - // To reduce the size of MDNode for a given struct type, we only output - // once for all the fields with the same scalar types. - // Offsets for scalar fields in the type DAG are not used. - llvm::SmallSet ScalarFieldTypes; unsigned idx = 0; for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); i != e; ++i, ++idx) { @@ -263,13 +271,8 @@ CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) { llvm::MDNode *FieldNode; if (isTBAAPathStruct(FieldQTy)) FieldNode = getTBAAStructTypeInfo(FieldQTy); - else { + else FieldNode = getTBAAInfo(FieldQTy); - // Ignore this field if the type already exists. - if (ScalarFieldTypes.count(FieldNode)) - continue; - ScalarFieldTypes.insert(FieldNode); - } if (!FieldNode) return StructTypeMetadataCache[Ty] = NULL; Fields.push_back(std::make_pair( @@ -305,8 +308,18 @@ CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode, if (isTBAAPathStruct(BaseQTy)) BNode = getTBAAStructTypeInfo(BaseQTy); if (!BNode) - return StructTagMetadataCache[PathTag] = AccessNode; + return StructTagMetadataCache[PathTag] = + MDHelper.createTBAAStructTagNode(AccessNode, AccessNode, 0); return StructTagMetadataCache[PathTag] = MDHelper.createTBAAStructTagNode(BNode, AccessNode, Offset); } + +llvm::MDNode * +CodeGenTBAA::getTBAAScalarTagInfo(llvm::MDNode *AccessNode) { + if (llvm::MDNode *N = ScalarTagMetadataCache[AccessNode]) + return N; + + return ScalarTagMetadataCache[AccessNode] = + MDHelper.createTBAAStructTagNode(AccessNode, AccessNode, 0); +} diff --git a/lib/CodeGen/CodeGenTBAA.h b/lib/CodeGen/CodeGenTBAA.h index 9ddc3aa970..f0c9e06f02 100644 --- a/lib/CodeGen/CodeGenTBAA.h +++ b/lib/CodeGen/CodeGenTBAA.h @@ -61,6 +61,8 @@ class CodeGenTBAA { llvm::DenseMap StructTypeMetadataCache; /// This maps TBAAPathTags to a tag node. llvm::DenseMap StructTagMetadataCache; + /// This maps a scalar type to a scalar tag node. + llvm::DenseMap ScalarTagMetadataCache; /// StructMetadataCache - This maps clang::Types to llvm::MDNodes describing /// them for struct assignments. @@ -84,6 +86,11 @@ class CodeGenTBAA { SmallVectorImpl &Fields, bool MayAlias); + /// A wrapper function to create a scalar type. For struct-path aware TBAA, + /// the scalar type has the same format as the struct type: name, offset, + /// pointer to another node in the type DAG. + llvm::MDNode *createTBAAScalarType(StringRef Name, llvm::MDNode *Parent); + public: CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext &VMContext, const CodeGenOptions &CGO, @@ -105,10 +112,13 @@ public: /// Get the MDNode in the type DAG for given struct type QType. llvm::MDNode *getTBAAStructTypeInfo(QualType QType); - /// Get the tag MDNode for a given base type, the actual sclar access MDNode + /// Get the tag MDNode for a given base type, the actual scalar access MDNode /// and offset into the base type. llvm::MDNode *getTBAAStructTagInfo(QualType BaseQType, llvm::MDNode *AccessNode, uint64_t Offset); + + /// Get the sclar tag MDNode for a given scalar type. + llvm::MDNode *getTBAAScalarTagInfo(llvm::MDNode *AccessNode); }; } // end namespace CodeGen diff --git a/test/CodeGen/tbaa.cpp b/test/CodeGen/tbaa.cpp index b7d02fd80a..c256b4af80 100644 --- a/test/CodeGen/tbaa.cpp +++ b/test/CodeGen/tbaa.cpp @@ -49,8 +49,8 @@ uint32_t g(uint32_t *s, StructA *A, uint64_t count) { // CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 // CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 // PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !5 +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa [[TAG_i32:!.*]] +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa [[TAG_A_f32:!.*]] *s = 1; A->f32 = 4; return *s; @@ -61,8 +61,8 @@ uint32_t g2(uint32_t *s, StructA *A, uint64_t count) { // CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 // CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 // PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 -// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !8 +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa [[TAG_i32]] +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa [[TAG_A_f16:!.*]] *s = 1; A->f16 = 4; return *s; @@ -73,8 +73,8 @@ uint32_t g3(StructA *A, StructB *B, uint64_t count) { // CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 // CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 // PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9 +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa [[TAG_A_f32]] +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa [[TAG_B_a_f32:!.*]] A->f32 = 1; B->a.f32 = 4; return A->f32; @@ -85,8 +85,8 @@ uint32_t g4(StructA *A, StructB *B, uint64_t count) { // CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 // CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 // PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 -// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !11 +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa [[TAG_A_f32]] +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa [[TAG_B_a_f16:!.*]] A->f32 = 1; B->a.f16 = 4; return A->f32; @@ -97,8 +97,8 @@ uint32_t g5(StructA *A, StructB *B, uint64_t count) { // CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 // CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 // PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !12 +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa [[TAG_A_f32]] +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa [[TAG_B_f32:!.*]] A->f32 = 1; B->f32 = 4; return A->f32; @@ -109,8 +109,8 @@ uint32_t g6(StructA *A, StructB *B, uint64_t count) { // CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 // CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 // PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !13 +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa [[TAG_A_f32]] +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa [[TAG_B_a_f32_2:!.*]] A->f32 = 1; B->a.f32_2 = 4; return A->f32; @@ -121,8 +121,8 @@ uint32_t g7(StructA *A, StructS *S, uint64_t count) { // CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 // CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 // PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !14 +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa [[TAG_A_f32]] +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa [[TAG_S_f32:!.*]] A->f32 = 1; S->f32 = 4; return A->f32; @@ -133,8 +133,8 @@ uint32_t g8(StructA *A, StructS *S, uint64_t count) { // CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 // CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 // PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !5 -// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !16 +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa [[TAG_A_f32]] +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa [[TAG_S_f16:!.*]] A->f32 = 1; S->f16 = 4; return A->f32; @@ -145,8 +145,8 @@ uint32_t g9(StructS *S, StructS2 *S2, uint64_t count) { // CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 // CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 // PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !17 +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa [[TAG_S_f32]] +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa [[TAG_S2_f32:!.*]] S->f32 = 1; S2->f32 = 4; return S->f32; @@ -157,8 +157,8 @@ uint32_t g10(StructS *S, StructS2 *S2, uint64_t count) { // CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 // CHECK: store i16 4, i16* %{{.*}}, align 2, !tbaa !5 // PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !14 -// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa !19 +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa [[TAG_S_f32]] +// PATH: store i16 4, i16* %{{.*}}, align 2, !tbaa [[TAG_S2_f16:!.*]] S->f32 = 1; S2->f16 = 4; return S->f32; @@ -169,8 +169,8 @@ uint32_t g11(StructC *C, StructD *D, uint64_t count) { // CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa !4 // CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 // PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !20 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !22 +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa [[TAG_C_b_a_f32:!.*]] +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa [[TAG_D_b_a_f32:!.*]] C->b.a.f32 = 1; D->b.a.f32 = 4; return C->b.a.f32; @@ -182,8 +182,8 @@ uint32_t g12(StructC *C, StructD *D, uint64_t count) { // CHECK: store i32 4, i32* %{{.*}}, align 4, !tbaa !4 // TODO: differentiate the two accesses. // PATH: define i32 @{{.*}}( -// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa !9 -// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa !9 +// PATH: store i32 1, i32* %{{.*}}, align 4, !tbaa [[TAG_B_a_f32]] +// PATH: store i32 4, i32* %{{.*}}, align 4, !tbaa [[TAG_B_a_f32]] StructB *b1 = &(C->b); StructB *b2 = &(D->b); // b1, b2 have different context. @@ -197,24 +197,25 @@ uint32_t g12(StructC *C, StructD *D, uint64_t count) { // CHECK: !4 = metadata !{metadata !"int", metadata !1} // CHECK: !5 = metadata !{metadata !"short", metadata !1} -// PATH: !1 = metadata !{metadata !"omnipotent char", metadata !2} -// PATH: !4 = metadata !{metadata !"int", metadata !1} -// PATH: !5 = metadata !{metadata !6, metadata !4, i64 4} -// PATH: !6 = metadata !{metadata !"_ZTS7StructA", i64 0, metadata !7, i64 4, metadata !4} -// PATH: !7 = metadata !{metadata !"short", metadata !1} -// PATH: !8 = metadata !{metadata !6, metadata !7, i64 0} -// PATH: !9 = metadata !{metadata !10, metadata !4, i64 8} -// PATH: !10 = metadata !{metadata !"_ZTS7StructB", i64 0, metadata !7, i64 4, metadata !6, i64 20, metadata !4} -// PATH: !11 = metadata !{metadata !10, metadata !7, i64 4} -// PATH: !12 = metadata !{metadata !10, metadata !4, i64 20} -// PATH: !13 = metadata !{metadata !10, metadata !4, i64 16} -// PATH: !14 = metadata !{metadata !15, metadata !4, i64 4} -// PATH: !15 = metadata !{metadata !"_ZTS7StructS", i64 0, metadata !7, i64 4, metadata !4} -// PATH: !16 = metadata !{metadata !15, metadata !7, i64 0} -// PATH: !17 = metadata !{metadata !18, metadata !4, i64 4} -// PATH: !18 = metadata !{metadata !"_ZTS8StructS2", i64 0, metadata !7, i64 4, metadata !4} -// PATH: !19 = metadata !{metadata !18, metadata !7, i64 0} -// PATH: !20 = metadata !{metadata !21, metadata !4, i64 12} -// PATH: !21 = metadata !{metadata !"_ZTS7StructC", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4} -// PATH: !22 = metadata !{metadata !23, metadata !4, i64 12} -// PATH: !23 = metadata !{metadata !"_ZTS7StructD", i64 0, metadata !7, i64 4, metadata !10, i64 28, metadata !4, i64 32, metadata !1} +// PATH: [[TYPE_CHAR:!.*]] = metadata !{metadata !"omnipotent char", i64 0, metadata !3} +// PATH: [[TAG_i32]] = metadata !{metadata [[TYPE_INT:!.*]], metadata [[TYPE_INT]], i64 0} +// PATH: [[TYPE_INT]] = metadata !{metadata !"int", i64 0, metadata [[TYPE_CHAR]]} +// PATH: [[TAG_A_f32]] = metadata !{metadata [[TYPE_A:!.*]], metadata [[TYPE_INT]], i64 4} +// PATH: [[TYPE_A]] = metadata !{metadata !"_ZTS7StructA", i64 0, metadata [[TYPE_SHORT:!.*]], i64 4, metadata [[TYPE_INT]], i64 8, metadata [[TYPE_SHORT]], i64 12, metadata [[TYPE_INT]]} +// PATH: [[TYPE_SHORT:!.*]] = metadata !{metadata !"short", i64 0, metadata [[TYPE_CHAR]]} +// PATH: [[TAG_A_f16]] = metadata !{metadata [[TYPE_A]], metadata [[TYPE_SHORT]], i64 0} +// PATH: [[TAG_B_a_f32]] = metadata !{metadata [[TYPE_B:!.*]], metadata [[TYPE_INT]], i64 8} +// PATH: [[TYPE_B]] = metadata !{metadata !"_ZTS7StructB", i64 0, metadata [[TYPE_SHORT]], i64 4, metadata [[TYPE_A]], i64 20, metadata [[TYPE_INT]]} +// PATH: [[TAG_B_a_f16]] = metadata !{metadata [[TYPE_B]], metadata [[TYPE_SHORT]], i64 4} +// PATH: [[TAG_B_f32]] = metadata !{metadata [[TYPE_B]], metadata [[TYPE_INT]], i64 20} +// PATH: [[TAG_B_a_f32_2]] = metadata !{metadata [[TYPE_B]], metadata [[TYPE_INT]], i64 16} +// PATH: [[TAG_S_f32]] = metadata !{metadata [[TYPE_S:!.*]], metadata [[TYPE_INT]], i64 4} +// PATH: [[TYPE_S]] = metadata !{metadata !"_ZTS7StructS", i64 0, metadata [[TYPE_SHORT]], i64 4, metadata [[TYPE_INT]]} +// PATH: [[TAG_S_f16]] = metadata !{metadata [[TYPE_S]], metadata [[TYPE_SHORT]], i64 0} +// PATH: [[TAG_S2_f32]] = metadata !{metadata [[TYPE_S2:!.*]], metadata [[TYPE_INT]], i64 4} +// PATH: [[TYPE_S2]] = metadata !{metadata !"_ZTS8StructS2", i64 0, metadata [[TYPE_SHORT]], i64 4, metadata [[TYPE_INT]]} +// PATH: [[TAG_S2_f16]] = metadata !{metadata [[TYPE_S2]], metadata [[TYPE_SHORT]], i64 0} +// PATH: [[TAG_C_b_a_f32]] = metadata !{metadata [[TYPE_C:!.*]], metadata [[TYPE_INT]], i64 12} +// PATH: [[TYPE_C]] = metadata !{metadata !"_ZTS7StructC", i64 0, metadata [[TYPE_SHORT]], i64 4, metadata [[TYPE_B]], i64 28, metadata [[TYPE_INT]]} +// PATH: [[TAG_D_b_a_f32]] = metadata !{metadata [[TYPE_D:!.*]], metadata [[TYPE_INT]], i64 12} +// PATH: [[TYPE_D]] = metadata !{metadata !"_ZTS7StructD", i64 0, metadata [[TYPE_SHORT]], i64 4, metadata [[TYPE_B]], i64 28, metadata [[TYPE_INT]], i64 32, metadata [[TYPE_CHAR]]} -- cgit v1.2.3-70-g09d2 From 84083b74abc4a2d1a9013ce4c75d63ee7d6d1da3 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 13 Apr 2013 01:28:18 +0000 Subject: Use MapVector rather than simulating it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179438 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 10 +++++----- lib/CodeGen/CodeGenModule.h | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 4126bea295..aacabc7867 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1748,8 +1748,6 @@ void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D, // in extern "C" regions, none of them gets that name. if (!R.second) R.first->second = 0; - else - StaticExternCIdents.push_back(D->getIdentifier()); } void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { @@ -2958,9 +2956,11 @@ static void EmitGlobalDeclMetadata(CodeGenModule &CGM, /// to such functions with an unmangled name from inline assembly within the /// same translation unit. void CodeGenModule::EmitStaticExternCAliases() { - for (unsigned I = 0, N = StaticExternCIdents.size(); I != N; ++I) { - IdentifierInfo *Name = StaticExternCIdents[I]; - llvm::GlobalValue *Val = StaticExternCValues[Name]; + for (StaticExternCMap::iterator I = StaticExternCValues.begin(), + E = StaticExternCValues.end(); + I != E; ++I) { + IdentifierInfo *Name = I->first; + llvm::GlobalValue *Val = I->second; if (Val && !getModule().getNamedValue(Name->getName())) AddUsedGlobal(new llvm::GlobalAlias(Val->getType(), Val->getLinkage(), Name->getName(), Val, &getModule())); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index f8b09711f7..1eb0ebb624 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -307,10 +307,9 @@ class CodeGenModule : public CodeGenTypeCache { /// Map used to track internal linkage functions declared within /// extern "C" regions. - typedef llvm::DenseMap StaticExternCMap; + typedef llvm::MapVector StaticExternCMap; StaticExternCMap StaticExternCValues; - std::vector StaticExternCIdents; /// CXXGlobalInits - Global variables with initializers that need to run /// before main. -- cgit v1.2.3-70-g09d2 From 428edb7f7599b4ee44eaad00bb3c330495fc1ad6 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Tue, 16 Apr 2013 15:25:39 +0000 Subject: Objective-C IRGen. Use llvm::WeakVH for caching couple of global symbols used for generation of CF/NS string meta-data so they are not released prematuely in certain corner cases. // rdar:// 13598026. Reviewed by John M. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179599 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 25 +++++++++------ lib/CodeGen/CodeGenModule.h | 4 +-- test/CodeGenObjC/tentative-cfconstantstring.m | 44 +++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 test/CodeGenObjC/tentative-cfconstantstring.m (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index f8627b2b70..5893814d7a 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -2279,7 +2279,8 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty); llvm::Constant *Zeros[] = { Zero, Zero }; - + llvm::Value *V; + // If we don't already have it, get __CFConstantStringClassReference. if (!CFConstantStringClassRef) { llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy); @@ -2287,9 +2288,11 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { llvm::Constant *GV = CreateRuntimeVariable(Ty, "__CFConstantStringClassReference"); // Decay array -> ptr - CFConstantStringClassRef = - llvm::ConstantExpr::getGetElementPtr(GV, Zeros); + V = llvm::ConstantExpr::getGetElementPtr(GV, Zeros); + CFConstantStringClassRef = V; } + else + V = CFConstantStringClassRef; QualType CFTy = getContext().getCFConstantStringType(); @@ -2299,7 +2302,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { llvm::Constant *Fields[4]; // Class pointer. - Fields[0] = CFConstantStringClassRef; + Fields[0] = cast(V); // Flags. llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy); @@ -2386,7 +2389,7 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) { llvm::Constant *Zero = llvm::Constant::getNullValue(Int32Ty); llvm::Constant *Zeros[] = { Zero, Zero }; - + llvm::Value *V; // If we don't already have it, get _NSConstantStringClassReference. if (!ConstantStringClassRef) { std::string StringClass(getLangOpts().ObjCConstantStringClass); @@ -2399,8 +2402,8 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) { GV = getObjCRuntime().GetClassGlobal(str); // Make sure the result is of the correct type. llvm::Type *PTy = llvm::PointerType::getUnqual(Ty); - ConstantStringClassRef = - llvm::ConstantExpr::getBitCast(GV, PTy); + V = llvm::ConstantExpr::getBitCast(GV, PTy); + ConstantStringClassRef = V; } else { std::string str = StringClass.empty() ? "_NSConstantStringClassReference" @@ -2408,10 +2411,12 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) { llvm::Type *PTy = llvm::ArrayType::get(Ty, 0); GV = CreateRuntimeVariable(PTy, str); // Decay array -> ptr - ConstantStringClassRef = - llvm::ConstantExpr::getGetElementPtr(GV, Zeros); + V = llvm::ConstantExpr::getGetElementPtr(GV, Zeros); + ConstantStringClassRef = V; } } + else + V = ConstantStringClassRef; if (!NSConstantStringType) { // Construct the type for a constant NSString. @@ -2450,7 +2455,7 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) { llvm::Constant *Fields[3]; // Class pointer. - Fields[0] = ConstantStringClassRef; + Fields[0] = cast(V); // String pointer. llvm::Constant *C = diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 1eb0ebb624..ab499ae9b4 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -346,11 +346,11 @@ class CodeGenModule : public CodeGenTypeCache { /// CFConstantStringClassRef - Cached reference to the class for constant /// strings. This value has type int * but is actually an Obj-C class pointer. - llvm::Constant *CFConstantStringClassRef; + llvm::WeakVH CFConstantStringClassRef; /// ConstantStringClassRef - Cached reference to the class for constant /// strings. This value has type int * but is actually an Obj-C class pointer. - llvm::Constant *ConstantStringClassRef; + llvm::WeakVH ConstantStringClassRef; /// \brief The LLVM type corresponding to NSConstantString. llvm::StructType *NSConstantStringType; diff --git a/test/CodeGenObjC/tentative-cfconstantstring.m b/test/CodeGenObjC/tentative-cfconstantstring.m new file mode 100644 index 0000000000..c0bea0f2eb --- /dev/null +++ b/test/CodeGenObjC/tentative-cfconstantstring.m @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s +// rdar://13598026 + +@interface NSObject @end + +@class NSString; + +int __CFConstantStringClassReference[24]; + +@interface Bar : NSObject ++(void)format:(NSString *)format,...; +@end + +@interface Foo : NSObject +@end + + +static inline void _inlineFunction() { + [Bar format:@" "]; +} + +@implementation Foo + + ++(NSString *)someMethod { + return @""; +} + +-(void)someMethod { + _inlineFunction(); +} +@end + +// CHECK: @__CFConstantStringClassReference = common global [24 x i32] zeroinitializer, align 16 +// CHECK: @_unnamed_cfstring_{{.*}} = private constant %struct.NSConstantString { i32* getelementptr inbounds ([24 x i32]* @__CFConstantStringClassReference, i32 0, i32 0) + +// CHECK: define internal void @_inlineFunction() +// CHECK-NEXT: entry: +// CHECK-NEXT: [[ZERO:%.*]] = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_ +// CHECK-NEXT: [[ONE:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_" +// CHECK-NEXT: [[TWO:%.*]] = bitcast %struct._class_t* [[ZERO]] to i8* +// CHECK-NEXT: call{{.*}}@objc_msgSend{{.*}}(i8* [[TWO]], i8* [[ONE]], [[ZERO]]* bitcast (%struct.NSConstantString* @_unnamed_cfstring_{{.*}} +// CHECK-NEXT: ret void + -- cgit v1.2.3-70-g09d2 From 64aa4b3ec7e62288e2e66c1935487ece995ca94b Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 16 Apr 2013 22:48:15 +0000 Subject: Standardize accesses to the TargetInfo in IR-gen. Patch by Stephen Lin! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179638 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/ABIInfo.h | 2 ++ lib/CodeGen/CGAtomic.cpp | 2 +- lib/CodeGen/CGBlocks.cpp | 3 ++- lib/CodeGen/CGBuiltin.cpp | 10 ++++---- lib/CodeGen/CGCall.cpp | 9 +++---- lib/CodeGen/CGClass.cpp | 4 +-- lib/CodeGen/CGDebugInfo.cpp | 8 +++--- lib/CodeGen/CGDecl.cpp | 2 +- lib/CodeGen/CGDeclCXX.cpp | 2 +- lib/CodeGen/CGExprAgg.cpp | 2 +- lib/CodeGen/CGExprScalar.cpp | 4 +-- lib/CodeGen/CGObjC.cpp | 2 +- lib/CodeGen/CGObjCMac.cpp | 18 ++++++------- lib/CodeGen/CGObjCRuntime.cpp | 2 +- lib/CodeGen/CGRecordLayoutBuilder.cpp | 8 +++--- lib/CodeGen/CGStmt.cpp | 22 ++++++++-------- lib/CodeGen/CodeGenFunction.cpp | 7 +++-- lib/CodeGen/CodeGenFunction.h | 1 + lib/CodeGen/CodeGenModule.cpp | 24 +++++++----------- lib/CodeGen/CodeGenModule.h | 48 ++++++++++++++++++++--------------- lib/CodeGen/CodeGenTypes.cpp | 12 ++++----- lib/CodeGen/CodeGenTypes.h | 13 ++++++---- lib/CodeGen/ItaniumCXXABI.cpp | 2 +- lib/CodeGen/TargetInfo.cpp | 39 ++++++++++++++-------------- 24 files changed, 126 insertions(+), 120 deletions(-) (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/lib/CodeGen/ABIInfo.h b/lib/CodeGen/ABIInfo.h index 35780f1556..df6dc7216a 100644 --- a/lib/CodeGen/ABIInfo.h +++ b/lib/CodeGen/ABIInfo.h @@ -22,6 +22,7 @@ namespace llvm { namespace clang { class ASTContext; + class TargetInfo; namespace CodeGen { class CGFunctionInfo; @@ -196,6 +197,7 @@ namespace clang { ASTContext &getContext() const; llvm::LLVMContext &getVMContext() const; const llvm::DataLayout &getDataLayout() const; + const TargetInfo &getTarget() const; /// Return the calling convention to use for system runtime /// functions. diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp index 24c930f794..0b48a5c664 100644 --- a/lib/CodeGen/CGAtomic.cpp +++ b/lib/CodeGen/CGAtomic.cpp @@ -327,7 +327,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) { CharUnits alignChars = getContext().getTypeAlignInChars(AtomicTy); unsigned Align = alignChars.getQuantity(); unsigned MaxInlineWidthInBits = - getContext().getTargetInfo().getMaxAtomicInlineWidth(); + getTarget().getMaxAtomicInlineWidth(); bool UseLibcall = (Size != Align || getContext().toBits(sizeChars) > MaxInlineWidthInBits); diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index ab9793132c..f49198a9bf 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -2082,7 +2082,8 @@ llvm::Type *CodeGenFunction::BuildByRefType(const VarDecl *D) { bool Packed = false; CharUnits Align = getContext().getDeclAlign(D); - if (Align > getContext().toCharUnitsFromBits(Target.getPointerAlign(0))) { + if (Align > + getContext().toCharUnitsFromBits(getTarget().getPointerAlign(0))) { // We have to insert padding. // The struct above has 2 32-bit integers. diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 3c89652b6d..37bd8fc1f7 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -296,7 +296,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType); llvm::Type *ResultType = ConvertType(E->getType()); - Value *ZeroUndef = Builder.getInt1(Target.isCLZForZeroUndef()); + Value *ZeroUndef = Builder.getInt1(getTarget().isCLZForZeroUndef()); Value *Result = Builder.CreateCall2(F, ArgValue, ZeroUndef); if (Result->getType() != ResultType) Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, @@ -313,7 +313,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType); llvm::Type *ResultType = ConvertType(E->getType()); - Value *ZeroUndef = Builder.getInt1(Target.isCLZForZeroUndef()); + Value *ZeroUndef = Builder.getInt1(getTarget().isCLZForZeroUndef()); Value *Result = Builder.CreateCall2(F, ArgValue, ZeroUndef); if (Result->getType() != ResultType) Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true, @@ -1430,7 +1430,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, const char *Name = getContext().BuiltinInfo.GetName(BuiltinID); Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic; if (const char *Prefix = - llvm::Triple::getArchTypePrefix(Target.getTriple().getArch())) + llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch())) IntrinsicID = Intrinsic::getIntrinsicForGCCBuiltin(Prefix, Name); if (IntrinsicID != Intrinsic::not_intrinsic) { @@ -1501,7 +1501,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *CodeGenFunction::EmitTargetBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { - switch (Target.getTriple().getArch()) { + switch (getTarget().getTriple().getArch()) { case llvm::Triple::arm: case llvm::Triple::thumb: return EmitARMBuiltinExpr(BuiltinID, E); @@ -1852,7 +1852,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, // Generate target-independent intrinsic; also need to add second argument // for whether or not clz of zero is undefined; on ARM it isn't. Function *F = CGM.getIntrinsic(Intrinsic::ctlz, Ty); - Ops.push_back(Builder.getInt1(Target.isCLZForZeroUndef())); + Ops.push_back(Builder.getInt1(getTarget().isCLZForZeroUndef())); return EmitNeonCall(F, Ops, "vclz"); } case ARM::BI__builtin_neon_vcnt_v: diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index faf32e3008..47f3c64840 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -837,12 +837,11 @@ bool CodeGenModule::ReturnTypeUsesFPRet(QualType ResultType) { default: return false; case BuiltinType::Float: - return getContext().getTargetInfo().useObjCFPRetForRealType(TargetInfo::Float); + return getTarget().useObjCFPRetForRealType(TargetInfo::Float); case BuiltinType::Double: - return getContext().getTargetInfo().useObjCFPRetForRealType(TargetInfo::Double); + return getTarget().useObjCFPRetForRealType(TargetInfo::Double); case BuiltinType::LongDouble: - return getContext().getTargetInfo().useObjCFPRetForRealType( - TargetInfo::LongDouble); + return getTarget().useObjCFPRetForRealType(TargetInfo::LongDouble); } } @@ -853,7 +852,7 @@ bool CodeGenModule::ReturnTypeUsesFP2Ret(QualType ResultType) { if (const ComplexType *CT = ResultType->getAs()) { if (const BuiltinType *BT = CT->getElementType()->getAs()) { if (BT->getKind() == BuiltinType::LongDouble) - return getContext().getTargetInfo().useObjCFP2RetForComplexLongDouble(); + return getTarget().useObjCFP2RetForComplexLongDouble(); } } diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 2ececb0365..05925567b0 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -710,7 +710,7 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) { // Before we go any further, try the complete->base constructor // delegation optimization. if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor) && - CGM.getContext().getTargetInfo().getCXXABI().hasConstructorVariants()) { + CGM.getTarget().getCXXABI().hasConstructorVariants()) { if (CGDebugInfo *DI = getDebugInfo()) DI->EmitLocation(Builder, Ctor->getLocEnd()); EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args); @@ -1278,7 +1278,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { EnterDtorCleanups(Dtor, Dtor_Complete); if (!isTryBody && - CGM.getContext().getTargetInfo().getCXXABI().hasDestructorVariants()) { + CGM.getTarget().getCXXABI().hasDestructorVariants()) { EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false, /*Delegating=*/false, LoadCXXThis()); break; diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 711d686150..7a727de5fa 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -642,7 +642,7 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag, // Size is always the size of a pointer. We can't use getTypeSize here // because that does not return the correct value for references. unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy); - uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS); + uint64_t Size = CGM.getTarget().getPointerWidth(AS); uint64_t Align = CGM.getContext().getTypeAlign(Ty); return DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit), @@ -984,7 +984,7 @@ llvm::DIType CGDebugInfo::getOrCreateInstanceMethodType( const PointerType *ThisPtrTy = cast(ThisPtr); QualType PointeeTy = ThisPtrTy->getPointeeType(); unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy); - uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS); + uint64_t Size = CGM.getTarget().getPointerWidth(AS); uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy); llvm::DIType PointeeType = getOrCreateType(PointeeTy, Unit); llvm::DIType ThisPtrType = DBuilder.createPointerType(PointeeType, Size, Align); @@ -2398,7 +2398,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD, CharUnits Align = CGM.getContext().getDeclAlign(VD); if (Align > CGM.getContext().toCharUnitsFromBits( - CGM.getContext().getTargetInfo().getPointerAlign(0))) { + CGM.getTarget().getPointerAlign(0))) { CharUnits FieldOffsetInBytes = CGM.getContext().toCharUnitsFromBits(FieldOffset); CharUnits AlignedOffsetInBytes @@ -2494,7 +2494,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag, addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); // offset of __forwarding field offset = CGM.getContext().toCharUnitsFromBits( - CGM.getContext().getTargetInfo().getPointerWidth(0)); + CGM.getTarget().getPointerWidth(0)); addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity())); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref)); addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus)); diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 173ca6cb09..9ad9cf022c 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -900,7 +900,7 @@ CodeGenFunction::EmitAutoVarAlloca(const VarDecl &D) { CharUnits allocaAlignment = alignment; if (isByRef) allocaAlignment = std::max(allocaAlignment, - getContext().toCharUnitsFromBits(Target.getPointerAlign(0))); + getContext().toCharUnitsFromBits(getTarget().getPointerAlign(0))); Alloc->setAlignment(allocaAlignment.getQuantity()); DeclPtr = Alloc; diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index fd766bf3de..b18fe45296 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -232,7 +232,7 @@ CreateGlobalInitOrDestructFunction(CodeGenModule &CGM, if (!CGM.getLangOpts().AppleKext) { // Set the section if needed. if (const char *Section = - CGM.getContext().getTargetInfo().getStaticInitSectionSpecifier()) + CGM.getTarget().getStaticInitSectionSpecifier()) Fn->setSection(Section); } diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 1ac13c01ed..6b29b3155a 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -1341,7 +1341,7 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) { // Reference values are always non-null and have the width of a pointer. if (Field->getType()->isReferenceType()) NumNonZeroBytes += CGF.getContext().toCharUnitsFromBits( - CGF.getContext().getTargetInfo().getPointerWidth(0)); + CGF.getTarget().getPointerWidth(0)); else NumNonZeroBytes += GetNumNonZeroBytesInInit(E, CGF); } diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index ffd0eb5572..ea1eae8088 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1634,8 +1634,8 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, else { llvm::APFloat F(static_cast(amount)); bool ignored; - F.convert(CGF.Target.getLongDoubleFormat(), llvm::APFloat::rmTowardZero, - &ignored); + F.convert(CGF.getTarget().getLongDoubleFormat(), + llvm::APFloat::rmTowardZero, &ignored); amt = llvm::ConstantFP::get(VMContext, F); } value = Builder.CreateFAdd(value, amt, isInc ? "inc" : "dec"); diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 3338b33607..d0e4cd49dc 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -714,7 +714,7 @@ PropertyImplStrategy::PropertyImplStrategy(CodeGenModule &CGM, } llvm::Triple::ArchType arch = - CGM.getContext().getTargetInfo().getTriple().getArch(); + CGM.getTarget().getTriple().getArch(); // Most architectures require memory to fit within a single cache // line, so the alignment has to be at least the size of the access. diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 6274e1bfe3..d42f5e5f66 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1949,8 +1949,8 @@ llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM, bool hasUnion = false; SkipIvars.clear(); IvarsInfo.clear(); - unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0); - unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth(); + unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0); + unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); // __isa is the first field in block descriptor and must assume by runtime's // convention that it is GC'able. @@ -2077,7 +2077,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, if (RecFields.empty()) return; - unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth(); + unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { const FieldDecl *Field = RecFields[i]; @@ -2316,8 +2316,8 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) { llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy); if (RunSkipBlockVars.empty()) return nullPtr; - unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0); - unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth(); + unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0); + unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits; // Sort on byte position; captures might not be allocated in order, @@ -2468,8 +2468,8 @@ llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM, RunSkipBlockVars.clear(); bool hasUnion = false; - unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0); - unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth(); + unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0); + unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits; const BlockDecl *blockDecl = blockInfo.getBlockDecl(); @@ -4537,8 +4537,8 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, if (RecFields.empty()) return; - unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0); - unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth(); + unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(0); + unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); if (!RD && CGM.getLangOpts().ObjCAutoRefCount) { const FieldDecl *FirstField = RecFields[0]; FirstFieldDelta = diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp index abd10a29c9..9c0d5189f8 100644 --- a/lib/CodeGen/CGObjCRuntime.cpp +++ b/lib/CodeGen/CGObjCRuntime.cpp @@ -117,7 +117,7 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF, // a synthesized ivar can never be a bit-field, so this is safe. uint64_t FieldBitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar); uint64_t BitOffset = FieldBitOffset % CGF.CGM.getContext().getCharWidth(); - uint64_t AlignmentBits = CGF.CGM.getContext().getTargetInfo().getCharAlign(); + uint64_t AlignmentBits = CGF.CGM.getTarget().getCharAlign(); uint64_t BitFieldSize = Ivar->getBitWidthValue(CGF.getContext()); CharUnits StorageSize = CGF.CGM.getContext().toCharUnitsFromBits( diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index 2c6438b0b6..30ab528ffb 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -276,7 +276,7 @@ bool CGRecordLayoutBuilder::LayoutBitfields(const ASTRecordLayout &Layout, uint64_t FirstFieldOffset = Layout.getFieldOffset(FirstFieldNo); uint64_t NextFieldOffsetInBits = Types.getContext().toBits(NextFieldOffset); - unsigned CharAlign = Types.getContext().getTargetInfo().getCharAlign(); + unsigned CharAlign = Types.getTarget().getCharAlign(); assert(FirstFieldOffset % CharAlign == 0 && "First field offset is misaligned"); CharUnits FirstFieldOffsetInBytes @@ -352,7 +352,7 @@ bool CGRecordLayoutBuilder::LayoutBitfields(const ASTRecordLayout &Layout, assert(EndOffset >= (FirstFieldOffset + TotalBits) && "End offset is not past the end of the known storage bits."); uint64_t SpaceBits = EndOffset - FirstFieldOffset; - uint64_t LongBits = Types.getContext().getTargetInfo().getLongWidth(); + uint64_t LongBits = Types.getTarget().getLongWidth(); uint64_t WidenedBits = (StorageBits / LongBits) * LongBits + llvm::NextPowerOf2(StorageBits % LongBits - 1); assert(WidenedBits >= StorageBits && "Widening shrunk the bits!"); @@ -455,7 +455,7 @@ CGRecordLayoutBuilder::LayoutUnionField(const FieldDecl *Field, return 0; unsigned StorageBits = llvm::RoundUpToAlignment( - FieldSize, Types.getContext().getTargetInfo().getCharAlign()); + FieldSize, Types.getTarget().getCharAlign()); CharUnits NumBytesToAppend = Types.getContext().toCharUnitsFromBits(StorageBits); @@ -814,7 +814,7 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { // Lay out the virtual bases. The MS ABI uses a different // algorithm here due to the lack of primary virtual bases. - if (Types.getContext().getTargetInfo().getCXXABI().hasPrimaryVBases()) { + if (Types.getTarget().getCXXABI().hasPrimaryVBases()) { RD->getIndirectPrimaryBases(IndirectPrimaryBases); if (Layout.isPrimaryBaseVirtual()) IndirectPrimaryBases.insert(Layout.getPrimaryBase()); diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index d10818cf25..dcc423dbdc 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -1451,7 +1451,7 @@ static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str, for (unsigned i = 0, e = StrVal.size()-1; i != e; ++i) { if (StrVal[i] != '\n') continue; SourceLocation LineLoc = Str->getLocationOfByte(i+1, SM, LangOpts, - CGF.Target); + CGF.getTarget()); Locs.push_back(llvm::ConstantInt::get(CGF.Int32Ty, LineLoc.getRawEncoding())); } @@ -1471,7 +1471,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) { TargetInfo::ConstraintInfo Info(S.getOutputConstraint(i), S.getOutputName(i)); - bool IsValid = Target.validateOutputConstraint(Info); (void)IsValid; + bool IsValid = getTarget().validateOutputConstraint(Info); (void)IsValid; assert(IsValid && "Failed to parse output constraint"); OutputConstraintInfos.push_back(Info); } @@ -1479,8 +1479,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) { TargetInfo::ConstraintInfo Info(S.getInputConstraint(i), S.getInputName(i)); - bool IsValid = Target.validateInputConstraint(OutputConstraintInfos.data(), - S.getNumOutputs(), Info); + bool IsValid = + getTarget().validateInputConstraint(OutputConstraintInfos.data(), + S.getNumOutputs(), Info); assert(IsValid && "Failed to parse input constraint"); (void)IsValid; InputConstraintInfos.push_back(Info); } @@ -1504,13 +1505,14 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { // Simplify the output constraint. std::string OutputConstraint(S.getOutputConstraint(i)); - OutputConstraint = SimplifyConstraint(OutputConstraint.c_str() + 1, Target); + OutputConstraint = SimplifyConstraint(OutputConstraint.c_str() + 1, + getTarget()); const Expr *OutExpr = S.getOutputExpr(i); OutExpr = OutExpr->IgnoreParenNoopCasts(getContext()); OutputConstraint = AddVariableConstraints(OutputConstraint, *OutExpr, - Target, CGM, S); + getTarget(), CGM, S); LValue Dest = EmitLValue(OutExpr); if (!Constraints.empty()) @@ -1591,13 +1593,13 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { // Simplify the input constraint. std::string InputConstraint(S.getInputConstraint(i)); - InputConstraint = SimplifyConstraint(InputConstraint.c_str(), Target, + InputConstraint = SimplifyConstraint(InputConstraint.c_str(), getTarget(), &OutputConstraintInfos); InputConstraint = AddVariableConstraints(InputConstraint, *InputExpr->IgnoreParenNoopCasts(getContext()), - Target, CGM, S); + getTarget(), CGM, S); llvm::Value *Arg = EmitAsmInput(Info, InputExpr, Constraints); @@ -1649,7 +1651,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { StringRef Clobber = S.getClobber(i); if (Clobber != "memory" && Clobber != "cc") - Clobber = Target.getNormalizedGCCRegisterName(Clobber); + Clobber = getTarget().getNormalizedGCCRegisterName(Clobber); if (i != 0 || NumConstraints != 0) Constraints += ','; @@ -1660,7 +1662,7 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { } // Add machine specific clobbers - std::string MachineClobbers = Target.getClobbers(); + std::string MachineClobbers = getTarget().getClobbers(); if (!MachineClobbers.empty()) { if (!Constraints.empty()) Constraints += ','; diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 2c3cabe985..cda3ce0286 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -31,8 +31,7 @@ using namespace clang; using namespace CodeGen; CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext) - : CodeGenTypeCache(cgm), CGM(cgm), - Target(CGM.getContext().getTargetInfo()), + : CodeGenTypeCache(cgm), CGM(cgm), Target(cgm.getTarget()), Builder(cgm.getModule().getContext()), SanitizePerformTypeCheck(CGM.getSanOpts().Null | CGM.getSanOpts().Alignment | @@ -279,8 +278,8 @@ void CodeGenFunction::EmitFunctionInstrumentation(const char *Fn) { void CodeGenFunction::EmitMCountInstrumentation() { llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); - llvm::Constant *MCountFn = CGM.CreateRuntimeFunction(FTy, - Target.getMCountName()); + llvm::Constant *MCountFn = + CGM.CreateRuntimeFunction(FTy, getTarget().getMCountName()); EmitNounwindRuntimeCall(MCountFn); } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 941eebe882..f4ac0866c8 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1300,6 +1300,7 @@ public: return getInvokeDestImpl(); } + const TargetInfo &getTarget() const { return Target; } llvm::LLVMContext &getLLVMContext() { return CGM.getLLVMContext(); } //===--------------------------------------------------------------------===// diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 7990a491c0..6c2578f336 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -55,7 +55,7 @@ using namespace CodeGen; static const char AnnotationSection[] = "llvm.metadata"; static CGCXXABI &createCXXABI(CodeGenModule &CGM) { - switch (CGM.getContext().getTargetInfo().getCXXABI().getKind()) { + switch (CGM.getTarget().getCXXABI().getKind()) { case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericARM: case TargetCXXABI::iOS: @@ -73,16 +73,14 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, const TargetOptions &TO, llvm::Module &M, const llvm::DataLayout &TD, DiagnosticsEngine &diags) - : Context(C), LangOpts(C.getLangOpts()), CodeGenOpts(CGO), TargetOpts(TO), - TheModule(M), TheDataLayout(TD), TheTargetCodeGenInfo(0), Diags(diags), - ABI(createCXXABI(*this)), - Types(*this), - TBAA(0), - VTables(*this), ObjCRuntime(0), OpenCLRuntime(0), CUDARuntime(0), + : Context(C), LangOpts(C.getLangOpts()), CodeGenOpts(CGO), TheModule(M), + Diags(diags), TheDataLayout(TD), Target(C.getTargetInfo()), + ABI(createCXXABI(*this)), VMContext(M.getContext()), TBAA(0), + TheTargetCodeGenInfo(0), Types(*this), VTables(*this), + ObjCRuntime(0), OpenCLRuntime(0), CUDARuntime(0), DebugInfo(0), ARCData(0), NoObjCARCExceptionsMetadata(0), RRData(0), CFConstantStringClassRef(0), ConstantStringClassRef(0), NSConstantStringType(0), - VMContext(M.getContext()), NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockObjectAssign(0), BlockObjectDispose(0), BlockDescriptorType(0), GenericBlockLiteralType(0), @@ -256,10 +254,6 @@ void CodeGenModule::DecorateInstruction(llvm::Instruction *Inst, Inst->setMetadata(llvm::LLVMContext::MD_tbaa, TBAAInfo); } -bool CodeGenModule::isTargetDarwin() const { - return getContext().getTargetInfo().getTriple().isOSDarwin(); -} - void CodeGenModule::Error(SourceLocation loc, StringRef error) { unsigned diagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, error); getDiags().Report(Context.getFullLoc(loc), diagID); @@ -2361,7 +2355,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { GV = new llvm::GlobalVariable(getModule(), C->getType(), true, llvm::GlobalVariable::PrivateLinkage, C, "_unnamed_cfstring_"); - if (const char *Sect = getContext().getTargetInfo().getCFStringSection()) + if (const char *Sect = getTarget().getCFStringSection()) GV->setSection(Sect); Entry.setValue(GV); @@ -2486,8 +2480,8 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) { // FIXME. Fix section. if (const char *Sect = LangOpts.ObjCRuntime.isNonFragile() - ? getContext().getTargetInfo().getNSStringNonFragileABISection() - : getContext().getTargetInfo().getNSStringSection()) + ? getTarget().getNSStringNonFragileABISection() + : getTarget().getNSStringSection()) GV->setSection(Sect); Entry.setValue(GV); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index ab499ae9b4..c1f951614a 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -233,15 +233,22 @@ class CodeGenModule : public CodeGenTypeCache { ASTContext &Context; const LangOptions &LangOpts; const CodeGenOptions &CodeGenOpts; - const TargetOptions &TargetOpts; llvm::Module &TheModule; - const llvm::DataLayout &TheDataLayout; - mutable const TargetCodeGenInfo *TheTargetCodeGenInfo; DiagnosticsEngine &Diags; + const llvm::DataLayout &TheDataLayout; + const TargetInfo &Target; CGCXXABI &ABI; - CodeGenTypes Types; - CodeGenTBAA *TBAA; + llvm::LLVMContext &VMContext; + CodeGenTBAA *TBAA; + + mutable const TargetCodeGenInfo *TheTargetCodeGenInfo; + + // This should not be moved earlier, since its initialization depends on some + // of the previous reference members being already initialized and also checks + // if TheTargetCodeGenInfo is NULL + CodeGenTypes Types; + /// VTables - Holds information about C++ vtables. CodeGenVTables VTables; friend class CodeGenVTables; @@ -255,8 +262,8 @@ class CodeGenModule : public CodeGenTypeCache { RREntrypoints *RRData; // WeakRefReferences - A set of references that have only been seen via - // a weakref so far. This is used to remove the weak of the reference if we ever - // see a direct reference or a definition. + // a weakref so far. This is used to remove the weak of the reference if we + // ever see a direct reference or a definition. llvm::SmallPtrSet WeakRefReferences; /// DeferredDecls - This contains all the decls which have definitions but @@ -369,7 +376,6 @@ class CodeGenModule : public CodeGenTypeCache { bool isTriviallyRecursive(const FunctionDecl *F); bool shouldEmitFunction(const FunctionDecl *F); - llvm::LLVMContext &VMContext; /// @name Cache for Blocks Runtime Globals /// @{ @@ -433,9 +439,6 @@ public: return *CUDARuntime; } - /// getCXXABI() - Return a reference to the configured C++ ABI. - CGCXXABI &getCXXABI() { return ABI; } - ARCEntrypoints &getARCEntrypoints() const { assert(getLangOpts().ObjCAutoRefCount && ARCData != 0); return *ARCData; @@ -489,21 +492,24 @@ public: } ASTContext &getContext() const { return Context; } - const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; } const LangOptions &getLangOpts() const { return LangOpts; } + const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; } llvm::Module &getModule() const { return TheModule; } - CodeGenTypes &getTypes() { return Types; } - CodeGenVTables &getVTables() { return VTables; } - VTableContext &getVTableContext() { return VTables.getVTableContext(); } DiagnosticsEngine &getDiags() const { return Diags; } const llvm::DataLayout &getDataLayout() const { return TheDataLayout; } - const TargetInfo &getTarget() const { return Context.getTargetInfo(); } + const TargetInfo &getTarget() const { return Target; } + CGCXXABI &getCXXABI() { return ABI; } llvm::LLVMContext &getLLVMContext() { return VMContext; } - const TargetCodeGenInfo &getTargetCodeGenInfo(); - bool isTargetDarwin() const; - + bool shouldUseTBAA() const { return TBAA != 0; } + const TargetCodeGenInfo &getTargetCodeGenInfo(); + + CodeGenTypes &getTypes() { return Types; } + + CodeGenVTables &getVTables() { return VTables; } + VTableContext &getVTableContext() { return VTables.getVTableContext(); } + llvm::MDNode *getTBAAInfo(QualType QTy); llvm::MDNode *getTBAAInfoForVTablePtr(); llvm::MDNode *getTBAAStructInfo(QualType QTy); @@ -574,8 +580,8 @@ public: return GetAddrOfGlobalVar(cast(GD.getDecl())); } - /// CreateOrReplaceCXXRuntimeVariable - Will return a global variable of the given - /// type. If a variable with a different type already exists then a new + /// CreateOrReplaceCXXRuntimeVariable - Will return a global variable of the + /// given type. If a variable with a different type already exists then a new /// variable with the right type will be created and all uses of the old /// variable will be replaced with a bitcast to the new variable. llvm::GlobalVariable * diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index 8fc78e3de6..6f6e52c033 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -28,12 +28,12 @@ using namespace clang; using namespace CodeGen; -CodeGenTypes::CodeGenTypes(CodeGenModule &CGM) - : Context(CGM.getContext()), Target(Context.getTargetInfo()), - TheModule(CGM.getModule()), TheDataLayout(CGM.getDataLayout()), - TheABIInfo(CGM.getTargetCodeGenInfo().getABIInfo()), - TheCXXABI(CGM.getCXXABI()), - CodeGenOpts(CGM.getCodeGenOpts()), CGM(CGM) { +CodeGenTypes::CodeGenTypes(CodeGenModule &cgm) + : CGM(cgm), Context(cgm.getContext()), TheModule(cgm.getModule()), + TheDataLayout(cgm.getDataLayout()), + Target(cgm.getTarget()), TheCXXABI(cgm.getCXXABI()), + CodeGenOpts(cgm.getCodeGenOpts()), + TheABIInfo(cgm.getTargetCodeGenInfo().getABIInfo()) { SkippedLayout = false; } diff --git a/lib/CodeGen/CodeGenTypes.h b/lib/CodeGen/CodeGenTypes.h index 11fd76fb19..452375f374 100644 --- a/lib/CodeGen/CodeGenTypes.h +++ b/lib/CodeGen/CodeGenTypes.h @@ -60,14 +60,17 @@ namespace CodeGen { class CodeGenTypes { public: // Some of this stuff should probably be left on the CGM. + CodeGenModule &CGM; ASTContext &Context; - const TargetInfo &Target; llvm::Module &TheModule; const llvm::DataLayout &TheDataLayout; - const ABIInfo &TheABIInfo; + const TargetInfo &Target; CGCXXABI &TheCXXABI; const CodeGenOptions &CodeGenOpts; - CodeGenModule &CGM; + + // This should not be moved earlier, since its initialization depends on some + // of the previous reference members being already initialized + const ABIInfo &TheABIInfo; private: /// The opaque type map for Objective-C interfaces. All direct @@ -107,14 +110,14 @@ private: llvm::DenseMap TypeCache; public: - CodeGenTypes(CodeGenModule &CGM); + CodeGenTypes(CodeGenModule &cgm); ~CodeGenTypes(); const llvm::DataLayout &getDataLayout() const { return TheDataLayout; } - const TargetInfo &getTarget() const { return Target; } ASTContext &getContext() const { return Context; } const ABIInfo &getABIInfo() const { return TheABIInfo; } const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; } + const TargetInfo &getTarget() const { return Target; } CGCXXABI &getCXXABI() const { return TheCXXABI; } llvm::LLVMContext &getLLVMContext() { return TheModule.getContext(); } diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 25cd5f58f8..496a0862c8 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -177,7 +177,7 @@ public: } CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { - switch (CGM.getContext().getTargetInfo().getCXXABI().getKind()) { + switch (CGM.getTarget().getCXXABI().getKind()) { // For IR-generation purposes, there's no significant difference // between the ARM and iOS ABIs. case TargetCXXABI::GenericARM: diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index d0b4918c67..ed89e24008 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -55,6 +55,9 @@ const llvm::DataLayout &ABIInfo::getDataLayout() const { return CGT.getDataLayout(); } +const TargetInfo &ABIInfo::getTarget() const { + return CGT.getTarget(); +} void ABIArgInfo::dump() const { raw_ostream &OS = llvm::errs(); @@ -551,8 +554,7 @@ public: int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const { // Darwin uses different dwarf register numbers for EH. - if (CGM.isTargetDarwin()) return 5; - + if (CGM.getTarget().getTriple().isOSDarwin()) return 5; return 4; } @@ -1020,7 +1022,7 @@ bool X86_32TargetCodeGenInfo::initDwarfEHRegSizeTable( // 8 is %eip. AssignToArrayRange(Builder, Address, Four8, 0, 8); - if (CGF.CGM.isTargetDarwin()) { + if (CGF.CGM.getTarget().getTriple().isOSDarwin()) { // 12-16 are st(0..4). Not sure why we stop at 4. // These have size 16, which is sizeof(long double) on // platforms with 8-byte alignment for that type. @@ -1145,7 +1147,7 @@ class X86_64ABIInfo : public ABIInfo { /// required strict binary compatibility with older versions of GCC /// may need to exempt themselves. bool honorsRevision0_98() const { - return !getContext().getTargetInfo().getTriple().isOSDarwin(); + return !getTarget().getTriple().isOSDarwin(); } bool HasAVX; @@ -1369,8 +1371,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Current = Integer; } else if ((k == BuiltinType::Float || k == BuiltinType::Double) || (k == BuiltinType::LongDouble && - getContext().getTargetInfo().getTriple().getOS() == - llvm::Triple::NaCl)) { + getTarget().getTriple().getOS() == llvm::Triple::NaCl)) { Current = SSE; } else if (k == BuiltinType::LongDouble) { Lo = X87; @@ -1458,8 +1459,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Current = SSE; else if (ET == getContext().DoubleTy || (ET == getContext().LongDoubleTy && - getContext().getTargetInfo().getTriple().getOS() == - llvm::Triple::NaCl)) + getTarget().getTriple().getOS() == llvm::Triple::NaCl)) Lo = Hi = SSE; else if (ET == getContext().LongDoubleTy) Current = ComplexX87; @@ -2514,9 +2514,7 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty) const { return ABIArgInfo::getIndirect(0, /*ByVal=*/false); // FIXME: mingw-w64-gcc emits 128-bit struct as i128 - if (Size == 128 && - getContext().getTargetInfo().getTriple().getOS() - == llvm::Triple::MinGW32) + if (Size == 128 && getTarget().getTriple().getOS() == llvm::Triple::MinGW32) return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size)); @@ -2946,8 +2944,7 @@ public: } bool isEABI() const { - StringRef Env = - getContext().getTargetInfo().getTriple().getEnvironmentName(); + StringRef Env = getTarget().getTriple().getEnvironmentName(); return (Env == "gnueabi" || Env == "eabi" || Env == "android" || Env == "androideabi"); } @@ -3046,7 +3043,7 @@ void ARMABIInfo::computeInfo(CGFunctionInfo &FI) const { /// Return the default calling convention that LLVM will use. llvm::CallingConv::ID ARMABIInfo::getLLVMDefaultCC() const { // The default calling convention that LLVM will infer. - if (getContext().getTargetInfo().getTriple().getEnvironmentName()=="gnueabihf") + if (getTarget().getTriple().getEnvironmentName()=="gnueabihf") return llvm::CallingConv::ARM_AAPCS_VFP; else if (isEABI()) return llvm::CallingConv::ARM_AAPCS; @@ -4538,7 +4535,7 @@ llvm::Value* MipsABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, int64_t TypeAlign = getContext().getTypeAlign(Ty) / 8; llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty)); llvm::Value *AddrTyped; - unsigned PtrWidth = getContext().getTargetInfo().getPointerWidth(0); + unsigned PtrWidth = getTarget().getPointerWidth(0); llvm::IntegerType *IntTy = (PtrWidth == 32) ? CGF.Int32Ty : CGF.Int64Ty; if (TypeAlign > MinABIStackAlignInBytes) { @@ -4799,7 +4796,7 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { if (TheTargetCodeGenInfo) return *TheTargetCodeGenInfo; - const llvm::Triple &Triple = getContext().getTargetInfo().getTriple(); + const llvm::Triple &Triple = getTarget().getTriple(); switch (Triple.getArch()) { default: return *(TheTargetCodeGenInfo = new DefaultTargetCodeGenInfo(Types)); @@ -4821,10 +4818,11 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { case llvm::Triple::thumb: { ARMABIInfo::ABIKind Kind = ARMABIInfo::AAPCS; - if (strcmp(getContext().getTargetInfo().getABI(), "apcs-gnu") == 0) + if (strcmp(getTarget().getABI(), "apcs-gnu") == 0) Kind = ARMABIInfo::APCS; else if (CodeGenOpts.FloatABI == "hard" || - (CodeGenOpts.FloatABI != "soft" && Triple.getEnvironment()==llvm::Triple::GNUEABIHF)) + (CodeGenOpts.FloatABI != "soft" && + Triple.getEnvironment() == llvm::Triple::GNUEABIHF)) Kind = ARMABIInfo::AAPCS_VFP; switch (Triple.getOS()) { @@ -4889,7 +4887,7 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { } case llvm::Triple::x86_64: { - bool HasAVX = strcmp(getContext().getTargetInfo().getABI(), "avx") == 0; + bool HasAVX = strcmp(getTarget().getABI(), "avx") == 0; switch (Triple.getOS()) { case llvm::Triple::Win32: @@ -4897,7 +4895,8 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { case llvm::Triple::Cygwin: return *(TheTargetCodeGenInfo = new WinX86_64TargetCodeGenInfo(Types)); case llvm::Triple::NaCl: - return *(TheTargetCodeGenInfo = new NaClX86_64TargetCodeGenInfo(Types, HasAVX)); + return *(TheTargetCodeGenInfo = new NaClX86_64TargetCodeGenInfo(Types, + HasAVX)); default: return *(TheTargetCodeGenInfo = new X86_64TargetCodeGenInfo(Types, HasAVX)); -- cgit v1.2.3-70-g09d2 From 3abae0995b5d4faa3d8cfb1f06118d71a60c7dab Mon Sep 17 00:00:00 2001 From: John McCall Date: Tue, 16 Apr 2013 22:48:20 +0000 Subject: Don't propagate around TargetOptions in IR-gen; we don't use it. Patch by Stephen Lin! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179639 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 4 +--- lib/CodeGen/CodeGenModule.h | 5 ++--- lib/CodeGen/ModuleBuilder.cpp | 14 ++++++-------- 3 files changed, 9 insertions(+), 14 deletions(-) (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 6c2578f336..42be779afb 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -35,7 +35,6 @@ #include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" -#include "clang/Basic/TargetOptions.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/Triple.h" @@ -70,8 +69,7 @@ static CGCXXABI &createCXXABI(CodeGenModule &CGM) { CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO, - const TargetOptions &TO, llvm::Module &M, - const llvm::DataLayout &TD, + llvm::Module &M, const llvm::DataLayout &TD, DiagnosticsEngine &diags) : Context(C), LangOpts(C.getLangOpts()), CodeGenOpts(CGO), TheModule(M), Diags(diags), TheDataLayout(TD), Target(C.getTargetInfo()), diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index c1f951614a..1a803f38c0 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -67,7 +67,6 @@ namespace clang { class VarDecl; class LangOptions; class CodeGenOptions; - class TargetOptions; class DiagnosticsEngine; class AnnotateAttr; class CXXDestructorDecl; @@ -408,8 +407,8 @@ class CodeGenModule : public CodeGenTypeCache { /// @} public: CodeGenModule(ASTContext &C, const CodeGenOptions &CodeGenOpts, - const TargetOptions &TargetOpts, llvm::Module &M, - const llvm::DataLayout &TD, DiagnosticsEngine &Diags); + llvm::Module &M, const llvm::DataLayout &TD, + DiagnosticsEngine &Diags); ~CodeGenModule(); diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp index d6e5f0673f..69e5b32304 100644 --- a/lib/CodeGen/ModuleBuilder.cpp +++ b/lib/CodeGen/ModuleBuilder.cpp @@ -31,15 +31,13 @@ namespace { OwningPtr TD; ASTContext *Ctx; const CodeGenOptions CodeGenOpts; // Intentionally copied in. - const TargetOptions TargetOpts; // Intentionally copied in. protected: OwningPtr M; OwningPtr Builder; public: CodeGeneratorImpl(DiagnosticsEngine &diags, const std::string& ModuleName, - const CodeGenOptions &CGO, const TargetOptions &TO, - llvm::LLVMContext& C) - : Diags(diags), CodeGenOpts(CGO), TargetOpts(TO), + const CodeGenOptions &CGO, llvm::LLVMContext& C) + : Diags(diags), CodeGenOpts(CGO), M(new llvm::Module(ModuleName, C)) {} virtual ~CodeGeneratorImpl() {} @@ -58,8 +56,8 @@ namespace { M->setTargetTriple(Ctx->getTargetInfo().getTriple().getTriple()); M->setDataLayout(Ctx->getTargetInfo().getTargetDescription()); TD.reset(new llvm::DataLayout(Ctx->getTargetInfo().getTargetDescription())); - Builder.reset(new CodeGen::CodeGenModule(Context, CodeGenOpts, TargetOpts, - *M, *TD, Diags)); + Builder.reset(new CodeGen::CodeGenModule(Context, CodeGenOpts, *M, *TD, + Diags)); } virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) { @@ -125,7 +123,7 @@ void CodeGenerator::anchor() { } CodeGenerator *clang::CreateLLVMCodeGen(DiagnosticsEngine &Diags, const std::string& ModuleName, const CodeGenOptions &CGO, - const TargetOptions &TO, + const TargetOptions &/*TO*/, llvm::LLVMContext& C) { - return new CodeGeneratorImpl(Diags, ModuleName, CGO, TO, C); + return new CodeGeneratorImpl(Diags, ModuleName, CGO, C); } -- cgit v1.2.3-70-g09d2 From b80a16eadd0dacabfc1c32412e243ccb99dd664d Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 19 Apr 2013 16:42:07 +0000 Subject: Implement CodeGen for C++11 thread_local, following the Itanium ABI specification as discussed on cxx-abi-dev. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@179858 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Mangle.h | 10 ++ lib/AST/ItaniumMangle.cpp | 18 +++ lib/CodeGen/CGCXXABI.cpp | 11 ++ lib/CodeGen/CGCXXABI.h | 19 +++ lib/CodeGen/CGDeclCXX.cpp | 69 +++++++++-- lib/CodeGen/CGExpr.cpp | 6 +- lib/CodeGen/CodeGenFunction.h | 3 +- lib/CodeGen/CodeGenModule.cpp | 5 +- lib/CodeGen/CodeGenModule.h | 11 ++ lib/CodeGen/ItaniumCXXABI.cpp | 143 +++++++++++++++++++++++ test/CodeGenCXX/cxx11-thread-local-reference.cpp | 26 +++++ test/CodeGenCXX/cxx11-thread-local.cpp | 117 +++++++++++++++++++ 12 files changed, 425 insertions(+), 13 deletions(-) create mode 100644 test/CodeGenCXX/cxx11-thread-local-reference.cpp (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h index 94faa19f1b..b6d22cfb5f 100644 --- a/include/clang/AST/Mangle.h +++ b/include/clang/AST/Mangle.h @@ -141,6 +141,16 @@ public: raw_ostream &) { llvm_unreachable("Target does not support mangling guard variables"); } + // FIXME: Revisit this once we know what we need to do for MSVC compatibility. + virtual void mangleItaniumThreadLocalInit(const VarDecl *D, + raw_ostream &) { + llvm_unreachable("Target does not support mangling thread_local variables"); + } + virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D, + raw_ostream &) { + llvm_unreachable("Target does not support mangling thread_local variables"); + } + /// @} }; diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 0edad3e017..e82b017e4a 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -141,6 +141,8 @@ public: raw_ostream &); void mangleItaniumGuardVariable(const VarDecl *D, raw_ostream &); + void mangleItaniumThreadLocalInit(const VarDecl *D, raw_ostream &); + void mangleItaniumThreadLocalWrapper(const VarDecl *D, raw_ostream &); void mangleInitDiscriminator() { Discriminator = 0; @@ -3531,6 +3533,22 @@ void ItaniumMangleContext::mangleItaniumGuardVariable(const VarDecl *D, Mangler.mangleName(D); } +void ItaniumMangleContext::mangleItaniumThreadLocalInit(const VarDecl *D, + raw_ostream &Out) { + // ::= TH + CXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "_ZTH"; + Mangler.mangleName(D); +} + +void ItaniumMangleContext::mangleItaniumThreadLocalWrapper(const VarDecl *D, + raw_ostream &Out) { + // ::= TW + CXXNameMangler Mangler(*this, Out); + Mangler.getStream() << "_ZTW"; + Mangler.mangleName(D); +} + void ItaniumMangleContext::mangleReferenceTemporary(const VarDecl *D, raw_ostream &Out) { // We match the GCC mangling here. diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp index 3bf6480298..68fecb2d0c 100644 --- a/lib/CodeGen/CGCXXABI.cpp +++ b/lib/CodeGen/CGCXXABI.cpp @@ -259,3 +259,14 @@ llvm::BasicBlock *CGCXXABI::EmitCtorCompleteObjectHandler( ErrorUnsupportedABI(CGF, "complete object detection in ctor"); return 0; } + +void CGCXXABI::EmitThreadLocalInitFuncs( + llvm::ArrayRef > Decls, + llvm::Function *InitFunc) { +} + +LValue CGCXXABI::EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF, + const DeclRefExpr *DRE) { + ErrorUnsupportedABI(CGF, "odr-use of thread_local global"); + return LValue(); +} diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index b736d9437e..1e4da631d6 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -353,6 +353,25 @@ public: /// \param addr - a pointer to pass to the destructor function. virtual void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, llvm::Constant *dtor, llvm::Constant *addr); + + /*************************** thread_local initialization ********************/ + + /// Emits ABI-required functions necessary to initialize thread_local + /// variables in this translation unit. + /// + /// \param Decls The thread_local declarations in this translation unit. + /// \param InitFunc If this translation unit contains any non-constant + /// initialization or non-trivial destruction for thread_local + /// variables, a function to perform the initialization. Otherwise, 0. + virtual void EmitThreadLocalInitFuncs( + llvm::ArrayRef > Decls, + llvm::Function *InitFunc); + + /// Emit a reference to a non-local thread_local variable (including + /// triggering the initialization of all thread_local variables in its + /// translation unit). + virtual LValue EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF, + const DeclRefExpr *DRE); }; // Create an instance of a C++ ABI class: diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index b18fe45296..d406227301 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -156,7 +156,8 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, static llvm::Function * CreateGlobalInitOrDestructFunction(CodeGenModule &CGM, llvm::FunctionType *ty, - const Twine &name); + const Twine &name, + bool TLS = false); /// Create a stub function, suitable for being passed to atexit, /// which passes the given address to the given destructor function. @@ -225,11 +226,11 @@ void CodeGenFunction::EmitCXXGuardedInit(const VarDecl &D, static llvm::Function * CreateGlobalInitOrDestructFunction(CodeGenModule &CGM, llvm::FunctionType *FTy, - const Twine &Name) { + const Twine &Name, bool TLS) { llvm::Function *Fn = llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); - if (!CGM.getLangOpts().AppleKext) { + if (!CGM.getLangOpts().AppleKext && !TLS) { // Set the section if needed. if (const char *Section = CGM.getTarget().getStaticInitSectionSpecifier()) @@ -255,9 +256,6 @@ void CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, llvm::GlobalVariable *Addr, bool PerformInit) { - if (D->getTLSKind()) - ErrorUnsupported(D->getInit(), "dynamic TLS initialization"); - llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); // Create a variable initialization function. @@ -267,12 +265,20 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, CodeGenFunction(*this).GenerateCXXGlobalVarDeclInitFunc(Fn, D, Addr, PerformInit); - if (D->hasAttr()) { + if (D->getTLSKind()) { + // FIXME: Should we support init_priority for thread_local? + // FIXME: Ideally, initialization of instantiated thread_local static data + // members of class templates should not trigger initialization of other + // entities in the TU. + // FIXME: We only need to register one __cxa_thread_atexit function for the + // entire TU. + CXXThreadLocalInits.push_back(Fn); + } else if (D->hasAttr()) { unsigned int order = D->getAttr()->getPriority(); OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size()); PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn)); DelayedCXXInitPosition.erase(D); - } else { + } else { llvm::DenseMap::iterator I = DelayedCXXInitPosition.find(D); if (I == DelayedCXXInitPosition.end()) { @@ -285,6 +291,27 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, } } +void CodeGenModule::EmitCXXThreadLocalInitFunc() { + llvm::Function *InitFn = 0; + if (!CXXThreadLocalInits.empty()) { + // Generate a guarded initialization function. + llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); + InitFn = CreateGlobalInitOrDestructFunction( + *this, FTy, "__tls_init", /*TLS*/ true); + llvm::GlobalVariable *Guard = new llvm::GlobalVariable( + getModule(), Int8Ty, false, llvm::GlobalVariable::InternalLinkage, + llvm::ConstantInt::get(Int8Ty, 0), "__tls_guard"); + Guard->setThreadLocal(true); + CodeGenFunction(*this).GenerateCXXGlobalInitFunc( + InitFn, CXXThreadLocalInits.data(), CXXThreadLocalInits.size(), Guard); + } + + getCXXABI().EmitThreadLocalInitFuncs(CXXThreadLocals, InitFn); + + CXXThreadLocalInits.clear(); + CXXThreadLocals.clear(); +} + void CodeGenModule::EmitCXXGlobalInitFunc() { while (!CXXGlobalInits.empty() && !CXXGlobalInits.back()) @@ -385,7 +412,8 @@ void CodeGenFunction::GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, llvm::Constant **Decls, - unsigned NumDecls) { + unsigned NumDecls, + llvm::GlobalVariable *Guard) { // Initialize debug info if needed. maybeInitializeDebugInfo(); @@ -393,6 +421,22 @@ void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, getTypes().arrangeNullaryFunction(), FunctionArgList(), SourceLocation()); + llvm::BasicBlock *ExitBlock = 0; + if (Guard) { + // If we have a guard variable, check whether we've already performed these + // initializations. This happens for TLS initialization functions. + llvm::Value *GuardVal = Builder.CreateLoad(Guard); + llvm::Value *Uninit = Builder.CreateIsNull(GuardVal, "guard.uninitialized"); + // Mark as initialized before initializing anything else. If the + // initializers use previously-initialized thread_local vars, that's + // probably supposed to be OK, but the standard doesn't say. + Builder.CreateStore(llvm::ConstantInt::get(GuardVal->getType(), 1), Guard); + llvm::BasicBlock *InitBlock = createBasicBlock("init"); + ExitBlock = createBasicBlock("exit"); + Builder.CreateCondBr(Uninit, InitBlock, ExitBlock); + EmitBlock(InitBlock); + } + RunCleanupsScope Scope(*this); // When building in Objective-C++ ARC mode, create an autorelease pool @@ -407,7 +451,12 @@ void CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, EmitRuntimeCall(Decls[i]); Scope.ForceCleanup(); - + + if (ExitBlock) { + Builder.CreateBr(ExitBlock); + EmitBlock(ExitBlock); + } + FinishFunction(); } diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 1c06b7d2d9..a0725b5f9c 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -1824,8 +1824,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { if (const VarDecl *VD = dyn_cast(ND)) { // Check if this is a global variable. - if (VD->hasLinkage() || VD->isStaticDataMember()) + if (VD->hasLinkage() || VD->isStaticDataMember()) { + // If it's thread_local, emit a call to its wrapper function instead. + if (VD->getTLSKind() == VarDecl::TLS_Dynamic) + return CGM.getCXXABI().EmitThreadLocalDeclRefExpr(*this, E); return EmitGlobalVarDeclLValue(*this, E, VD); + } bool isBlockVariable = VD->hasAttr(); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index f4ac0866c8..6e2d62760f 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -2628,7 +2628,8 @@ public: /// variables. void GenerateCXXGlobalInitFunc(llvm::Function *Fn, llvm::Constant **Decls, - unsigned NumDecls); + unsigned NumDecls, + llvm::GlobalVariable *Guard = 0); /// GenerateCXXGlobalDtorsFunc - Generates code for destroying global /// variables. diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 42be779afb..fdd3568472 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -176,6 +176,7 @@ void CodeGenModule::Release() { EmitDeferred(); EmitCXXGlobalInitFunc(); EmitCXXGlobalDtorFunc(); + EmitCXXThreadLocalInitFunc(); if (ObjCRuntime) if (llvm::Function *ObjCInitFunction = ObjCRuntime->ModuleInitFunction()) AddGlobalCtor(ObjCInitFunction); @@ -1477,8 +1478,10 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, GV->setVisibility(GetLLVMVisibility(LV.getVisibility())); } - if (D->getTLSKind()) + if (D->getTLSKind()) { + CXXThreadLocals.push_back(std::make_pair(D, GV)); setTLSMode(GV, *D); + } } if (AddrSpace != Ty->getAddressSpace()) diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 1a803f38c0..0f4fe8ae51 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -317,6 +317,14 @@ class CodeGenModule : public CodeGenTypeCache { llvm::GlobalValue *> StaticExternCMap; StaticExternCMap StaticExternCValues; + /// \brief thread_local variables defined or used in this TU. + std::vector > + CXXThreadLocals; + + /// \brief thread_local variables with initializers that need to run + /// before any thread_local variable in this TU is odr-used. + std::vector CXXThreadLocalInits; + /// CXXGlobalInits - Global variables with initializers that need to run /// before main. std::vector CXXGlobalInits; @@ -1026,6 +1034,9 @@ private: /// a C++ destructor Decl. void EmitCXXDestructor(const CXXDestructorDecl *D, CXXDtorType Type); + /// \brief Emit the function that initializes C++ thread_local variables. + void EmitCXXThreadLocalInitFunc(); + /// EmitCXXGlobalInitFunc - Emit the function that initializes C++ globals. void EmitCXXGlobalInitFunc(); diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 382aa47957..2714c9e728 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -146,6 +146,14 @@ public: llvm::GlobalVariable *DeclPtr, bool PerformInit); void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, llvm::Constant *dtor, llvm::Constant *addr); + + llvm::Function *getOrCreateThreadLocalWrapper(const VarDecl *VD, + llvm::GlobalVariable *Var); + void EmitThreadLocalInitFuncs( + llvm::ArrayRef > Decls, + llvm::Function *InitFunc); + LValue EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF, + const DeclRefExpr *DRE); }; class ARMCXXABI : public ItaniumCXXABI { @@ -1249,3 +1257,138 @@ void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF, CGF.registerGlobalDtorWithAtExit(dtor, addr); } + +/// Get the appropriate linkage for the wrapper function. This is essentially +/// the weak form of the variable's linkage; every translation unit which wneeds +/// the wrapper emits a copy, and we want the linker to merge them. +static llvm::GlobalValue::LinkageTypes getThreadLocalWrapperLinkage( + llvm::GlobalValue::LinkageTypes VarLinkage) { + if (llvm::GlobalValue::isLinkerPrivateLinkage(VarLinkage)) + return llvm::GlobalValue::LinkerPrivateWeakLinkage; + // For internal linkage variables, we don't need an external or weak wrapper. + if (llvm::GlobalValue::isLocalLinkage(VarLinkage)) + return VarLinkage; + return llvm::GlobalValue::WeakODRLinkage; +} + +llvm::Function * +ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD, + llvm::GlobalVariable *Var) { + // Mangle the name for the thread_local wrapper function. + SmallString<256> WrapperName; + { + llvm::raw_svector_ostream Out(WrapperName); + getMangleContext().mangleItaniumThreadLocalWrapper(VD, Out); + Out.flush(); + } + + if (llvm::Value *V = Var->getParent()->getNamedValue(WrapperName)) + return cast(V); + + llvm::Type *RetTy = Var->getType(); + if (VD->getType()->isReferenceType()) + RetTy = RetTy->getPointerElementType(); + + llvm::FunctionType *FnTy = llvm::FunctionType::get(RetTy, false); + llvm::Function *Wrapper = llvm::Function::Create( + FnTy, getThreadLocalWrapperLinkage(Var->getLinkage()), WrapperName.str(), + &CGM.getModule()); + // Always resolve references to the wrapper at link time. + Wrapper->setVisibility(llvm::GlobalValue::HiddenVisibility); + return Wrapper; +} + +void ItaniumCXXABI::EmitThreadLocalInitFuncs( + llvm::ArrayRef > Decls, + llvm::Function *InitFunc) { + for (unsigned I = 0, N = Decls.size(); I != N; ++I) { + const VarDecl *VD = Decls[I].first; + llvm::GlobalVariable *Var = Decls[I].second; + + // Mangle the name for the thread_local initialization function. + SmallString<256> InitFnName; + { + llvm::raw_svector_ostream Out(InitFnName); + getMangleContext().mangleItaniumThreadLocalInit(VD, Out); + Out.flush(); + } + + // If we have a definition for the variable, emit the initialization + // function as an alias to the global Init function (if any). Otherwise, + // produce a declaration of the initialization function. + llvm::GlobalValue *Init = 0; + bool InitIsInitFunc = false; + if (VD->hasDefinition()) { + InitIsInitFunc = true; + if (InitFunc) + Init = + new llvm::GlobalAlias(InitFunc->getType(), Var->getLinkage(), + InitFnName.str(), InitFunc, &CGM.getModule()); + } else { + // Emit a weak global function referring to the initialization function. + // This function will not exist if the TU defining the thread_local + // variable in question does not need any dynamic initialization for + // its thread_local variables. + llvm::FunctionType *FnTy = llvm::FunctionType::get(CGM.VoidTy, false); + Init = llvm::Function::Create( + FnTy, llvm::GlobalVariable::ExternalWeakLinkage, InitFnName.str(), + &CGM.getModule()); + } + + if (Init) + Init->setVisibility(Var->getVisibility()); + + llvm::Function *Wrapper = getOrCreateThreadLocalWrapper(VD, Var); + llvm::LLVMContext &Context = CGM.getModule().getContext(); + llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "", Wrapper); + CGBuilderTy Builder(Entry); + if (InitIsInitFunc) { + if (Init) + Builder.CreateCall(Init); + } else { + // Don't know whether we have an init function. Call it if it exists. + llvm::Value *Have = Builder.CreateIsNotNull(Init); + llvm::BasicBlock *InitBB = llvm::BasicBlock::Create(Context, "", Wrapper); + llvm::BasicBlock *ExitBB = llvm::BasicBlock::Create(Context, "", Wrapper); + Builder.CreateCondBr(Have, InitBB, ExitBB); + + Builder.SetInsertPoint(InitBB); + Builder.CreateCall(Init); + Builder.CreateBr(ExitBB); + + Builder.SetInsertPoint(ExitBB); + } + + // For a reference, the result of the wrapper function is a pointer to + // the referenced object. + llvm::Value *Val = Var; + if (VD->getType()->isReferenceType()) { + llvm::LoadInst *LI = Builder.CreateLoad(Val); + LI->setAlignment(CGM.getContext().getDeclAlign(VD).getQuantity()); + Val = LI; + } + + Builder.CreateRet(Val); + } +} + +LValue ItaniumCXXABI::EmitThreadLocalDeclRefExpr(CodeGenFunction &CGF, + const DeclRefExpr *DRE) { + const VarDecl *VD = cast(DRE->getDecl()); + QualType T = VD->getType(); + llvm::Type *Ty = CGF.getTypes().ConvertTypeForMem(T); + llvm::Value *Val = CGF.CGM.GetAddrOfGlobalVar(VD, Ty); + llvm::Function *Wrapper = + getOrCreateThreadLocalWrapper(VD, cast(Val)); + + Val = CGF.Builder.CreateCall(Wrapper); + + LValue LV; + if (VD->getType()->isReferenceType()) + LV = CGF.MakeNaturalAlignAddrLValue(Val, T); + else + LV = CGF.MakeAddrLValue(Val, DRE->getType(), + CGF.getContext().getDeclAlign(VD)); + // FIXME: need setObjCGCLValueClass? + return LV; +} diff --git a/test/CodeGenCXX/cxx11-thread-local-reference.cpp b/test/CodeGenCXX/cxx11-thread-local-reference.cpp new file mode 100644 index 0000000000..2ea9acda48 --- /dev/null +++ b/test/CodeGenCXX/cxx11-thread-local-reference.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s + +int &f(); + +// CHECK: @r = thread_local global i32* null +thread_local int &r = f(); + +// CHECK: @_ZTH1r = alias void ()* @__tls_init + +int &g() { return r; } + +// CHECK: define {{.*}} @[[R_INIT:.*]]() +// CHECK: call i32* @_Z1fv() +// CHECK: store i32* %{{.*}}, i32** @r, align 8 + +// CHECK: define i32* @_Z1gv() +// CHECK: call i32* @_ZTW1r() +// CHECK: ret i32* %{{.*}} + +// CHECK: define weak_odr hidden i32* @_ZTW1r() { +// CHECK: call void @_ZTH1r() +// CHECK: load i32** @r, align 8 +// CHECK: ret i32* %{{.*}} + +// CHECK: define internal void @__tls_init() +// CHECK: call void @[[R_INIT]]() diff --git a/test/CodeGenCXX/cxx11-thread-local.cpp b/test/CodeGenCXX/cxx11-thread-local.cpp index 5ed582d232..a7141d133b 100644 --- a/test/CodeGenCXX/cxx11-thread-local.cpp +++ b/test/CodeGenCXX/cxx11-thread-local.cpp @@ -1,8 +1,30 @@ // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s +int f(); int g(); +// CHECK: @a = thread_local global i32 0 +thread_local int a = f(); +extern thread_local int b; +// CHECK: @c = global i32 0 +int c = b; +// CHECK: @_ZL1d = internal thread_local global i32 0 +static thread_local int d = g(); + +struct U { static thread_local int m; }; +// CHECK: @_ZN1U1mE = thread_local global i32 0 +thread_local int U::m = f(); + +template struct V { static thread_local int m; }; +template thread_local int V::m = g(); + +// CHECK: @e = global i32 0 +int e = V::m; + +// CHECK: @_ZN1VIiE1mE = weak_odr thread_local global i32 0 + // CHECK: @_ZZ1fvE1n = internal thread_local global i32 0 + // CHECK: @_ZGVZ1fvE1n = internal thread_local global i8 0 // CHECK: @_ZZ8tls_dtorvE1s = internal thread_local global @@ -15,6 +37,24 @@ int g(); // CHECK: @_ZGVZ8tls_dtorvE1u = internal thread_local global i8 0 // CHECK: @_ZGRZ8tls_dtorvE1u = internal thread_local global +// CHECK: @_ZGVN1VIiE1mE = weak_odr thread_local global i64 0 + +// CHECK: @__tls_guard = internal thread_local global i8 0 + +// CHECK: @llvm.global_ctors = appending global {{.*}} @[[GLOBAL_INIT:[^ ]*]] + +// CHECK: @_ZTH1a = alias void ()* @__tls_init +// CHECK: @_ZTHL1d = alias internal void ()* @__tls_init +// CHECK: @_ZTHN1U1mE = alias void ()* @__tls_init +// CHECK: @_ZTHN1VIiE1mE = alias weak_odr void ()* @__tls_init + + +// Individual variable initialization functions: + +// CHECK: define {{.*}} @[[A_INIT:.*]]() +// CHECK: call i32 @_Z1fv() +// CHECK-NEXT: store i32 {{.*}}, i32* @a, align 4 + // CHECK: define i32 @_Z1fv() int f() { // CHECK: %[[GUARD:.*]] = load i8* @_ZGVZ1fvE1n, align 1 @@ -31,6 +71,37 @@ int f() { return n; } +// CHECK: define {{.*}} @[[C_INIT:.*]]() +// CHECK: call i32* @_ZTW1b() +// CHECK-NEXT: load i32* %{{.*}}, align 4 +// CHECK-NEXT: store i32 %{{.*}}, i32* @c, align 4 + +// CHECK: define weak_odr hidden i32* @_ZTW1b() +// CHECK: br i1 icmp ne (void ()* @_ZTH1b, void ()* null), +// not null: +// CHECK: call void @_ZTH1b() +// CHECK: br label +// finally: +// CHECK: ret i32* @b + +// CHECK: define {{.*}} @[[D_INIT:.*]]() +// CHECK: call i32 @_Z1gv() +// CHECK-NEXT: store i32 %{{.*}}, i32* @_ZL1d, align 4 + +// CHECK: define {{.*}} @[[U_M_INIT:.*]]() +// CHECK: call i32 @_Z1fv() +// CHECK-NEXT: store i32 %{{.*}}, i32* @_ZN1U1mE, align 4 + +// CHECK: define {{.*}} @[[E_INIT:.*]]() +// CHECK: call i32* @_ZTWN1VIiE1mE() +// CHECK-NEXT: load i32* %{{.*}}, align 4 +// CHECK-NEXT: store i32 %{{.*}}, i32* @e, align 4 + +// CHECK: define weak_odr hidden i32* @_ZTWN1VIiE1mE() +// CHECK: call void @_ZTHN1VIiE1mE() +// CHECK: ret i32* @_ZN1VIiE1mE + + struct S { S(); ~S(); }; struct T { ~T(); }; @@ -54,3 +125,49 @@ void tls_dtor() { // CHECK: store i8 1, i8* @_ZGVZ8tls_dtorvE1u static thread_local const S &u = S(); } + +// CHECK: declare i32 @__cxa_thread_atexit(void (i8*)*, i8*, i8*) + +// CHECK: define {{.*}} @[[V_M_INIT:.*]]() +// CHECK: load i8* bitcast (i64* @_ZGVN1VIiE1mE to i8*) +// CHECK: %[[V_M_INITIALIZED:.*]] = icmp eq i8 %{{.*}}, 0 +// CHECK: br i1 %[[V_M_INITIALIZED]], +// need init: +// CHECK: call i32 @_Z1gv() +// CHECK: store i32 %{{.*}}, i32* @_ZN1VIiE1mE, align 4 +// CHECK: store i64 1, i64* @_ZGVN1VIiE1mE +// CHECK: br label + +// CHECK: define {{.*}}@[[GLOBAL_INIT:.*]]() +// CHECK: call void @[[C_INIT]]() +// CHECK: call void @[[E_INIT]]() + + +// CHECK: define {{.*}}@__tls_init() +// CHECK: load i8* @__tls_guard +// CHECK: %[[NEED_TLS_INIT:.*]] = icmp eq i8 %{{.*}}, 0 +// CHECK: store i8 1, i8* @__tls_guard +// CHECK: br i1 %[[NEED_TLS_INIT]], +// init: +// CHECK: call void @[[A_INIT]]() +// CHECK: call void @[[D_INIT]]() +// CHECK: call void @[[U_M_INIT]]() +// CHECK: call void @[[V_M_INIT]]() + + +// CHECK: define weak_odr hidden i32* @_ZTW1a() { +// CHECK: call void @_ZTH1a() +// CHECK: ret i32* @a +// CHECK: } + + +// CHECK: declare extern_weak void @_ZTH1b() + + +// CHECK: define internal hidden i32* @_ZTWL1d() +// CHECK: call void @_ZTHL1d() +// CHECK: ret i32* @_ZL1d + +// CHECK: define weak_odr hidden i32* @_ZTWN1U1mE() +// CHECK: call void @_ZTHN1U1mE() +// CHECK: ret i32* @_ZN1U1mE -- cgit v1.2.3-70-g09d2 From 7c6b7ba5f5410d4b552ee53c60d0690522c99959 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Mon, 29 Apr 2013 22:27:16 +0000 Subject: Emit the TLS intialization functions into a list. Add the TLS initialization functions to a list of initialization functions. The back-end takes this list and places the function pointers into the correct section. This way they're called before `main().' git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180739 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDeclCXX.cpp | 1 + lib/CodeGen/CodeGenModule.cpp | 26 ++++++++++++++++++++++++++ lib/CodeGen/CodeGenModule.h | 11 +++++++++++ test/CodeGenCXX/tls-init-funcs.cpp | 21 +++++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 test/CodeGenCXX/tls-init-funcs.cpp (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index 9ffcff2766..4d78ea8f3a 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -304,6 +304,7 @@ void CodeGenModule::EmitCXXThreadLocalInitFunc() { Guard->setThreadLocal(true); CodeGenFunction(*this) .GenerateCXXGlobalInitFunc(InitFn, CXXThreadLocalInits, Guard); + AddTLSInitFunc(InitFn); } getCXXABI().EmitThreadLocalInitFuncs(CXXThreadLocals, InitFn); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index bf67bd1007..6247b15ce9 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -182,6 +182,7 @@ void CodeGenModule::Release() { AddGlobalCtor(ObjCInitFunction); EmitCtorList(GlobalCtors, "llvm.global_ctors"); EmitCtorList(GlobalDtors, "llvm.global_dtors"); + EmitTLSList(TLSInitFuncs); EmitGlobalAnnotations(); EmitStaticExternCAliases(); EmitLLVMUsed(); @@ -479,6 +480,12 @@ void CodeGenModule::AddGlobalDtor(llvm::Function * Dtor, int Priority) { GlobalDtors.push_back(std::make_pair(Dtor, Priority)); } +/// AddTLSInitFunc - Add a function to the list that will initialize TLS +/// variables before main() runs. +void CodeGenModule::AddTLSInitFunc(llvm::Function *Init) { + TLSInitFuncs.push_back(Init); +} + void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) { // Ctor function type is void()*. llvm::FunctionType* CtorFTy = llvm::FunctionType::get(VoidTy, false); @@ -507,6 +514,25 @@ void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) { } } +void CodeGenModule::EmitTLSList(ArrayRef Fns) { + if (Fns.empty()) return; + + // TLS init function types are void()*. + llvm::FunctionType* TLSFTy = llvm::FunctionType::get(VoidTy, false); + llvm::Type *TLSPFTy = llvm::PointerType::getUnqual(TLSFTy); + + SmallVector Inits; + for (ArrayRef::iterator I = Fns.begin(), + E = Fns.end(); I != E; ++I) + Inits.push_back(llvm::ConstantExpr::getBitCast(*I, TLSPFTy)); + + llvm::ArrayType *AT = llvm::ArrayType::get(TLSPFTy, Inits.size()); + new llvm::GlobalVariable(TheModule, AT, false, + llvm::GlobalValue::AppendingLinkage, + llvm::ConstantArray::get(AT, Inits), + "llvm.tls_init_funcs"); +} + llvm::GlobalValue::LinkageTypes CodeGenModule::getFunctionLinkage(const FunctionDecl *D) { GVALinkage Linkage = getContext().GetGVALinkageForFunction(D); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 0f4fe8ae51..ca30096dcb 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -293,6 +293,10 @@ class CodeGenModule : public CodeGenTypeCache { /// priorities to be emitted when the translation unit is complete. CtorList GlobalDtors; + /// TLSInitFuncs - Store the list of TLS initialization functions toe be + /// emitted with the translation unit is complete. + std::vector TLSInitFuncs; + /// MangledDeclNames - A map of canonical GlobalDecls to their mangled names. llvm::DenseMap MangledDeclNames; llvm::BumpPtrAllocator MangledNamesAllocator; @@ -1053,11 +1057,18 @@ private: void AddGlobalCtor(llvm::Function *Ctor, int Priority=65535); void AddGlobalDtor(llvm::Function *Dtor, int Priority=65535); + void AddTLSInitFunc(llvm::Function *Init); + /// EmitCtorList - Generates a global array of functions and priorities using /// the given list and name. This array will have appending linkage and is /// suitable for use as a LLVM constructor or destructor array. void EmitCtorList(const CtorList &Fns, const char *GlobalName); + /// EmitTLSList - Generates a global array of functions with the name + /// `llvm.tls_init_funcs'. This array will have appending linkage and is meant + /// to hold initialization functions for TLS variables. + void EmitTLSList(ArrayRef Fns); + /// EmitFundamentalRTTIDescriptor - Emit the RTTI descriptors for the /// given type. void EmitFundamentalRTTIDescriptor(QualType Type); diff --git a/test/CodeGenCXX/tls-init-funcs.cpp b/test/CodeGenCXX/tls-init-funcs.cpp new file mode 100644 index 0000000000..79b0ea4319 --- /dev/null +++ b/test/CodeGenCXX/tls-init-funcs.cpp @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -std=c++11 -S -emit-llvm %s -o - | FileCheck -check-prefix=BITCODE %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -std=c++11 -S %s -o - | FileCheck -check-prefix=ASM %s + +// BITCODE: @llvm.tls_init_funcs = appending global [1 x void ()*] [void ()* @__tls_init] + +struct A { + A(); +}; + +struct B { + int i; + B(int i); +}; + +thread_local int i = 37; +thread_local A a; +thread_local B b(927); + +// ASM: .section __DATA,__thread_init,thread_local_init_function_pointers +// ASM: .align 3 +// ASM: .quad ___tls_init -- cgit v1.2.3-70-g09d2 From 8f4bdc0e37b4b24a58a15ecf41d1355a3b3fdcbb Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 30 Apr 2013 21:34:13 +0000 Subject: Revert r180739 and r180748: they broke C++11 thread_local on non-Darwin systems and did not do the right thing on Darwin. Original commit message: Emit the TLS intialization functions into a list. Add the TLS initialization functions to a list of initialization functions. The back-end takes this list and places the function pointers into the correct section. This way they're called before `main().' git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180809 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGDeclCXX.cpp | 1 - lib/CodeGen/CodeGenModule.cpp | 26 -------------------------- lib/CodeGen/CodeGenModule.h | 11 ----------- test/CodeGenCXX/tls-init-funcs.cpp | 21 --------------------- 4 files changed, 59 deletions(-) delete mode 100644 test/CodeGenCXX/tls-init-funcs.cpp (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index 4d78ea8f3a..9ffcff2766 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -304,7 +304,6 @@ void CodeGenModule::EmitCXXThreadLocalInitFunc() { Guard->setThreadLocal(true); CodeGenFunction(*this) .GenerateCXXGlobalInitFunc(InitFn, CXXThreadLocalInits, Guard); - AddTLSInitFunc(InitFn); } getCXXABI().EmitThreadLocalInitFuncs(CXXThreadLocals, InitFn); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 6247b15ce9..bf67bd1007 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -182,7 +182,6 @@ void CodeGenModule::Release() { AddGlobalCtor(ObjCInitFunction); EmitCtorList(GlobalCtors, "llvm.global_ctors"); EmitCtorList(GlobalDtors, "llvm.global_dtors"); - EmitTLSList(TLSInitFuncs); EmitGlobalAnnotations(); EmitStaticExternCAliases(); EmitLLVMUsed(); @@ -480,12 +479,6 @@ void CodeGenModule::AddGlobalDtor(llvm::Function * Dtor, int Priority) { GlobalDtors.push_back(std::make_pair(Dtor, Priority)); } -/// AddTLSInitFunc - Add a function to the list that will initialize TLS -/// variables before main() runs. -void CodeGenModule::AddTLSInitFunc(llvm::Function *Init) { - TLSInitFuncs.push_back(Init); -} - void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) { // Ctor function type is void()*. llvm::FunctionType* CtorFTy = llvm::FunctionType::get(VoidTy, false); @@ -514,25 +507,6 @@ void CodeGenModule::EmitCtorList(const CtorList &Fns, const char *GlobalName) { } } -void CodeGenModule::EmitTLSList(ArrayRef Fns) { - if (Fns.empty()) return; - - // TLS init function types are void()*. - llvm::FunctionType* TLSFTy = llvm::FunctionType::get(VoidTy, false); - llvm::Type *TLSPFTy = llvm::PointerType::getUnqual(TLSFTy); - - SmallVector Inits; - for (ArrayRef::iterator I = Fns.begin(), - E = Fns.end(); I != E; ++I) - Inits.push_back(llvm::ConstantExpr::getBitCast(*I, TLSPFTy)); - - llvm::ArrayType *AT = llvm::ArrayType::get(TLSPFTy, Inits.size()); - new llvm::GlobalVariable(TheModule, AT, false, - llvm::GlobalValue::AppendingLinkage, - llvm::ConstantArray::get(AT, Inits), - "llvm.tls_init_funcs"); -} - llvm::GlobalValue::LinkageTypes CodeGenModule::getFunctionLinkage(const FunctionDecl *D) { GVALinkage Linkage = getContext().GetGVALinkageForFunction(D); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index ca30096dcb..0f4fe8ae51 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -293,10 +293,6 @@ class CodeGenModule : public CodeGenTypeCache { /// priorities to be emitted when the translation unit is complete. CtorList GlobalDtors; - /// TLSInitFuncs - Store the list of TLS initialization functions toe be - /// emitted with the translation unit is complete. - std::vector TLSInitFuncs; - /// MangledDeclNames - A map of canonical GlobalDecls to their mangled names. llvm::DenseMap MangledDeclNames; llvm::BumpPtrAllocator MangledNamesAllocator; @@ -1057,18 +1053,11 @@ private: void AddGlobalCtor(llvm::Function *Ctor, int Priority=65535); void AddGlobalDtor(llvm::Function *Dtor, int Priority=65535); - void AddTLSInitFunc(llvm::Function *Init); - /// EmitCtorList - Generates a global array of functions and priorities using /// the given list and name. This array will have appending linkage and is /// suitable for use as a LLVM constructor or destructor array. void EmitCtorList(const CtorList &Fns, const char *GlobalName); - /// EmitTLSList - Generates a global array of functions with the name - /// `llvm.tls_init_funcs'. This array will have appending linkage and is meant - /// to hold initialization functions for TLS variables. - void EmitTLSList(ArrayRef Fns); - /// EmitFundamentalRTTIDescriptor - Emit the RTTI descriptors for the /// given type. void EmitFundamentalRTTIDescriptor(QualType Type); diff --git a/test/CodeGenCXX/tls-init-funcs.cpp b/test/CodeGenCXX/tls-init-funcs.cpp deleted file mode 100644 index 653d6e3910..0000000000 --- a/test/CodeGenCXX/tls-init-funcs.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin11.0.0 -std=c++11 -emit-llvm %s -o - | FileCheck -check-prefix=BITCODE %s -// RUN: %clang_cc1 -triple x86_64-apple-darwin11.0.0 -std=c++11 -S %s -o - | FileCheck -check-prefix=ASM %s - -// BITCODE: @llvm.tls_init_funcs = appending global [1 x void ()*] [void ()* @__tls_init] - -struct A { - A(); -}; - -struct B { - int i; - B(int i); -}; - -thread_local int i = 37; -thread_local A a; -thread_local B b(927); - -// ASM: .section __DATA,__thread_init,thread_local_init_function_pointers -// ASM: .align 3 -// ASM: .quad ___tls_init -- cgit v1.2.3-70-g09d2 From 5543169296beeb183b9c9392debc774fcf493eeb Mon Sep 17 00:00:00 2001 From: Dmitri Gribenko Date: Sun, 5 May 2013 00:41:58 +0000 Subject: Replace ArrayRef() with None, now that we have an implicit ArrayRef constructor from None Patch by Robert Wilhelm. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181139 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclFriend.h | 2 +- include/clang/Sema/Sema.h | 5 ++--- lib/AST/Comment.cpp | 2 +- lib/AST/CommentParser.cpp | 5 ++--- lib/AST/Decl.cpp | 2 +- lib/AST/DeclObjC.cpp | 4 ++-- lib/AST/ExprCXX.cpp | 3 +-- lib/Analysis/BodyFarm.cpp | 8 ++++---- lib/CodeGen/CGCall.cpp | 12 ++++-------- lib/CodeGen/CodeGenModule.h | 3 +-- lib/Frontend/DiagnosticRenderer.cpp | 5 ++--- lib/Parse/ParseExpr.cpp | 3 +-- lib/Sema/SemaChecking.cpp | 4 ++-- lib/Sema/SemaDecl.cpp | 4 +--- lib/Sema/SemaDeclCXX.cpp | 19 ++++++------------- lib/Sema/SemaExpr.cpp | 10 +++++----- lib/Sema/SemaExprObjC.cpp | 8 ++++---- lib/Sema/SemaInit.cpp | 4 ++-- lib/Sema/SemaLambda.cpp | 8 +++----- lib/Sema/SemaLookup.cpp | 2 +- lib/Sema/SemaObjCProperty.cpp | 3 +-- lib/Sema/SemaOverload.cpp | 3 +-- lib/Sema/SemaPseudoObject.cpp | 5 ++--- 23 files changed, 50 insertions(+), 74 deletions(-) (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 253c23c199..3a12878e74 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -101,7 +101,7 @@ public: SourceLocation L, FriendUnion Friend_, SourceLocation FriendL, ArrayRef FriendTypeTPLists - = ArrayRef()); + = None); static FriendDecl *CreateDeserialized(ASTContext &C, unsigned ID, unsigned FriendTypeNumTPLists); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 0e6cc440ea..c61e2886e9 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3066,7 +3066,7 @@ public: bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs = 0, - ArrayRef Args = ArrayRef()); + ArrayRef Args = None); ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S, IdentifierInfo *II, @@ -4510,8 +4510,7 @@ public: CXXCtorInitializer *Initializer); bool SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, - ArrayRef Initializers = - ArrayRef()); + ArrayRef Initializers = None); void SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation); diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp index db55c04544..68c73fd48e 100644 --- a/lib/AST/Comment.cpp +++ b/lib/AST/Comment.cpp @@ -134,7 +134,7 @@ void DeclInfo::fill() { IsObjCMethod = false; IsInstanceMethod = false; IsClassMethod = false; - ParamVars = ArrayRef(); + ParamVars = None; TemplateParameters = NULL; if (!CommentDecl) { diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp index 1224db6e0e..d89c79b3d9 100644 --- a/lib/AST/CommentParser.cpp +++ b/lib/AST/CommentParser.cpp @@ -329,8 +329,7 @@ BlockCommandComment *Parser::parseBlockCommand() { if (isTokBlockCommand()) { // Block command ahead. We can't nest block commands, so pretend that this // command has an empty argument. - ParagraphComment *Paragraph = S.actOnParagraphComment( - ArrayRef()); + ParagraphComment *Paragraph = S.actOnParagraphComment(None); if (PC) { S.actOnParamCommandFinish(PC, Paragraph); return PC; @@ -372,7 +371,7 @@ BlockCommandComment *Parser::parseBlockCommand() { ParagraphComment *Paragraph; if (EmptyParagraph) - Paragraph = S.actOnParagraphComment(ArrayRef()); + Paragraph = S.actOnParagraphComment(None); else { BlockContentComment *Block = parseParagraphOrBlockCommand(); // Since we have checked for a block command, we should have parsed a diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 1f4248c8e5..ff012fc401 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -3429,7 +3429,7 @@ ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID, ArrayRef ImportDecl::getIdentifierLocs() const { if (!ImportedAndComplete.getInt()) - return ArrayRef(); + return None; const SourceLocation *StoredLocs = reinterpret_cast(this + 1); diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index b441f7ff1e..4ddbb22199 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -604,12 +604,12 @@ void ObjCMethodDecl::setMethodParams(ASTContext &C, assert((!SelLocs.empty() || isImplicit()) && "No selector locs for non-implicit method"); if (isImplicit()) - return setParamsAndSelLocs(C, Params, ArrayRef()); + return setParamsAndSelLocs(C, Params, llvm::None); SelLocsKind = hasStandardSelectorLocs(getSelector(), SelLocs, Params, DeclEndLoc); if (SelLocsKind != SelLoc_NonStandard) - return setParamsAndSelLocs(C, Params, ArrayRef()); + return setParamsAndSelLocs(C, Params, llvm::None); setParamsAndSelLocs(C, Params, SelLocs); } diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 277c8c09a5..402d7b532b 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -178,8 +178,7 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(ASTContext &Context, SourceLocation ColonColonLoc, SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType) : Expr(CXXPseudoDestructorExprClass, - Context.getPointerType(Context.getFunctionType(Context.VoidTy, - ArrayRef(), + Context.getPointerType(Context.getFunctionType(Context.VoidTy, None, FunctionProtoType::ExtProtoInfo())), VK_RValue, OK_Ordinary, /*isTypeDependent=*/(Base->isTypeDependent() || diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp index dda26bfab8..4d5c2ee236 100644 --- a/lib/Analysis/BodyFarm.cpp +++ b/lib/Analysis/BodyFarm.cpp @@ -194,8 +194,8 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { // (1) Create the call. DeclRefExpr *DR = M.makeDeclRefExpr(Block); ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty); - CallExpr *CE = new (C) CallExpr(C, ICE, ArrayRef(), C.VoidTy, - VK_RValue, SourceLocation()); + CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue, + SourceLocation()); // (2) Create the assignment to the predicate. IntegerLiteral *IL = @@ -257,8 +257,8 @@ static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) { ASTMaker M(C); DeclRefExpr *DR = M.makeDeclRefExpr(PV); ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty); - CallExpr *CE = new (C) CallExpr(C, ICE, ArrayRef(), C.VoidTy, - VK_RValue, SourceLocation()); + CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue, + SourceLocation()); return CE; } diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 5157dff538..b0f460ec0e 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -77,9 +77,7 @@ CodeGenTypes::arrangeFreeFunctionType(CanQual FTNP) { // When translating an unprototyped function type, always use a // variadic type. return arrangeLLVMFunctionInfo(FTNP->getResultType().getUnqualifiedType(), - ArrayRef(), - FTNP->getExtInfo(), - RequiredArgs(0)); + None, FTNP->getExtInfo(), RequiredArgs(0)); } /// Arrange the LLVM function layout for a value of the given function @@ -257,10 +255,8 @@ CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) { // non-variadic type. if (isa(FTy)) { CanQual noProto = FTy.getAs(); - return arrangeLLVMFunctionInfo(noProto->getResultType(), - ArrayRef(), - noProto->getExtInfo(), - RequiredArgs::All); + return arrangeLLVMFunctionInfo(noProto->getResultType(), None, + noProto->getExtInfo(), RequiredArgs::All); } assert(isa(FTy)); @@ -420,7 +416,7 @@ CodeGenTypes::arrangeFunctionDeclaration(QualType resultType, } const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() { - return arrangeLLVMFunctionInfo(getContext().VoidTy, ArrayRef(), + return arrangeLLVMFunctionInfo(getContext().VoidTy, None, FunctionType::ExtInfo(), RequiredArgs::All); } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 0f4fe8ae51..7bbca80bf4 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -750,8 +750,7 @@ public: llvm::Value *getBuiltinLibFunction(const FunctionDecl *FD, unsigned BuiltinID); - llvm::Function *getIntrinsic(unsigned IID, ArrayRef Tys = - ArrayRef()); + llvm::Function *getIntrinsic(unsigned IID, ArrayRef Tys = None); /// EmitTopLevelDecl - Emit code for a single top level declaration. void EmitTopLevelDecl(Decl *D); diff --git a/lib/Frontend/DiagnosticRenderer.cpp b/lib/Frontend/DiagnosticRenderer.cpp index 3b4f55c6c4..4eee59548c 100644 --- a/lib/Frontend/DiagnosticRenderer.cpp +++ b/lib/Frontend/DiagnosticRenderer.cpp @@ -462,9 +462,8 @@ void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc, Message << "expanded from here"; else Message << "expanded from macro '" << MacroName << "'"; - emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, - Message.str(), - SpellingRanges, ArrayRef(), &SM); + emitDiagnostic(SpellingLoc, DiagnosticsEngine::Note, Message.str(), + SpellingRanges, None, &SM); } DiagnosticNoteRenderer::~DiagnosticNoteRenderer() {} diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 326056daf4..9521ffbc0e 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1414,8 +1414,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { CommaLocsTy CommaLocs; if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteCall(getCurScope(), LHS.get(), - ArrayRef()); + Actions.CodeCompleteCall(getCurScope(), LHS.get(), None); cutOffParsing(); return ExprError(); } diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index c19fe27c7f..6b809cfba2 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2009,7 +2009,7 @@ public: PartialDiagnostic PDiag, SourceLocation StringLoc, bool IsStringLocation, Range StringRange, - ArrayRef Fixit = ArrayRef()); + ArrayRef Fixit = None); protected: bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc, @@ -2036,7 +2036,7 @@ protected: template void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc, bool IsStringLocation, Range StringRange, - ArrayRef Fixit = ArrayRef()); + ArrayRef Fixit = None); void CheckPositionalAndNonpositionalArgs( const analyze_format_string::FormatSpecifier *FS); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 84aa07927c..7b332f9fda 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -6576,9 +6576,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, EPI.Variadic = true; EPI.ExtInfo = FT->getExtInfo(); - QualType R = Context.getFunctionType(FT->getResultType(), - ArrayRef(), - EPI); + QualType R = Context.getFunctionType(FT->getResultType(), None, EPI); NewFD->setType(R); } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 0e3f0aad52..bfde60e8f8 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4576,7 +4576,7 @@ void Sema::CheckExplicitlyDefaultedMemberExceptionSpec( FunctionProtoType::ExtProtoInfo EPI; computeImplicitExceptionSpec(*this, MD->getLocation(), MD).getEPI(EPI); const FunctionProtoType *ImplicitType = cast( - Context.getFunctionType(Context.VoidTy, ArrayRef(), EPI)); + Context.getFunctionType(Context.VoidTy, None, EPI)); // Ensure that it matches. CheckEquivalentExceptionSpec( @@ -6011,7 +6011,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, EPI.Variadic = false; EPI.TypeQuals = 0; EPI.RefQualifier = RQ_None; - return Context.getFunctionType(Context.VoidTy, ArrayRef(), EPI); + return Context.getFunctionType(Context.VoidTy, None, EPI); } /// CheckConversionDeclarator - Called by ActOnDeclarator to check the @@ -6092,8 +6092,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, // of the errors above fired) and with the conversion type as the // return type. if (D.isInvalidType()) - R = Context.getFunctionType(ConvType, ArrayRef(), - Proto->getExtProtoInfo()); + R = Context.getFunctionType(ConvType, None, Proto->getExtProtoInfo()); // C++0x explicit conversion operators. if (D.getDeclSpec().isExplicitSpecified()) @@ -7792,9 +7791,7 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = DefaultCon; - DefaultCon->setType(Context.getFunctionType(Context.VoidTy, - ArrayRef(), - EPI)); + DefaultCon->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); // We don't need to use SpecialMemberIsTrivial here; triviality for default // constructors is easy to compute. @@ -8258,9 +8255,7 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = Destructor; - Destructor->setType(Context.getFunctionType(Context.VoidTy, - ArrayRef(), - EPI)); + Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); AddOverriddenMethods(ClassDecl, Destructor); @@ -8364,9 +8359,7 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, FunctionProtoType::ExtProtoInfo EPI = DtorType->getExtProtoInfo(); EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = Destructor; - Destructor->setType(Context.getFunctionType(Context.VoidTy, - ArrayRef(), - EPI)); + Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); // FIXME: If the destructor has a body that could throw, and the newly created // spec doesn't allow exceptions, we should emit a warning, because this diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 2acbe5961e..f4fd790fca 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2925,8 +2925,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { TemplateArgumentLocInfo ArgInfo; ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo)); } - return BuildLiteralOperatorCall(R, OpNameInfo, ArrayRef(), - Tok.getLocation(), &ExplicitArgs); + return BuildLiteralOperatorCall(R, OpNameInfo, None, Tok.getLocation(), + &ExplicitArgs); } llvm_unreachable("unexpected literal operator lookup result"); @@ -9743,7 +9743,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, FunctionProtoType::ExtProtoInfo EPI; EPI.HasTrailingReturn = false; EPI.TypeQuals |= DeclSpec::TQ_const; - T = Context.getFunctionType(Context.DependentTy, ArrayRef(), EPI); + T = Context.getFunctionType(Context.DependentTy, None, EPI); Sig = Context.getTrivialTypeSourceInfo(T); } @@ -9922,7 +9922,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (isa(FTy)) { FunctionProtoType::ExtProtoInfo EPI; EPI.ExtInfo = Ext; - BlockTy = Context.getFunctionType(RetTy, ArrayRef(), EPI); + BlockTy = Context.getFunctionType(RetTy, None, EPI); // Otherwise, if we don't need to change anything about the function type, // preserve its sugar structure. @@ -9947,7 +9947,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, } else { FunctionProtoType::ExtProtoInfo EPI; EPI.ExtInfo = FunctionType::ExtInfo().withNoReturn(NoReturn); - BlockTy = Context.getFunctionType(RetTy, ArrayRef(), EPI); + BlockTy = Context.getFunctionType(RetTy, None, EPI); } DiagnoseUnusedParameters(BSI->TheDecl->param_begin(), diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index f341d044bb..b36586dacb 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -239,7 +239,7 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, &CX.Idents.get("value"), NumberType, /*TInfo=*/0, SC_None, 0); - Method->setMethodParams(S.Context, value, ArrayRef()); + Method->setMethodParams(S.Context, value, None); } if (!validateBoxingMethod(S, Loc, S.NSNumberDecl, Sel, Method)) @@ -490,7 +490,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { Context.getPointerType(ConstCharType), /*TInfo=*/0, SC_None, 0); - M->setMethodParams(Context, value, ArrayRef()); + M->setMethodParams(Context, value, None); BoxingMethod = M; } @@ -665,7 +665,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { Context.UnsignedLongTy, /*TInfo=*/0, SC_None, 0); Params.push_back(cnt); - Method->setMethodParams(Context, Params, ArrayRef()); + Method->setMethodParams(Context, Params, None); } if (!validateBoxingMethod(*this, SR.getBegin(), NSArrayDecl, Sel, Method)) @@ -788,7 +788,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, Context.UnsignedLongTy, /*TInfo=*/0, SC_None, 0); Params.push_back(cnt); - Method->setMethodParams(Context, Params, ArrayRef()); + Method->setMethodParams(Context, Params, None); } if (!validateBoxingMethod(*this, SR.getBegin(), NSDictionaryDecl, Sel, diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 6bbbcdc17a..9200c181aa 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -330,7 +330,7 @@ void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field, true); InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, MultiExprArg()); if (!InitSeq) { - InitSeq.Diagnose(SemaRef, MemberEntity, Kind, ArrayRef()); + InitSeq.Diagnose(SemaRef, MemberEntity, Kind, None); hadError = true; return; } @@ -448,7 +448,7 @@ InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, true); InitializationSequence InitSeq(SemaRef, ElementEntity, Kind, MultiExprArg()); if (!InitSeq) { - InitSeq.Diagnose(SemaRef, ElementEntity, Kind, ArrayRef()); + InitSeq.Diagnose(SemaRef, ElementEntity, Kind, None); hadError = true; return; } diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index d16bb6a052..c7ba3cc822 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -452,8 +452,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, FunctionProtoType::ExtProtoInfo EPI; EPI.HasTrailingReturn = true; EPI.TypeQuals |= DeclSpec::TQ_const; - QualType MethodTy = Context.getFunctionType(Context.DependentTy, - ArrayRef(), + QualType MethodTy = Context.getFunctionType(Context.DependentTy, None, EPI); MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); ExplicitParams = false; @@ -708,7 +707,7 @@ static void addFunctionPointerConversion(Sema &S, FunctionProtoType::ExtProtoInfo ExtInfo; ExtInfo.TypeQuals = Qualifiers::Const; QualType ConvTy = - S.Context.getFunctionType(FunctionPtrTy, ArrayRef(), ExtInfo); + S.Context.getFunctionType(FunctionPtrTy, None, ExtInfo); SourceLocation Loc = IntroducerRange.getBegin(); DeclarationName Name @@ -779,8 +778,7 @@ static void addBlockPointerConversion(Sema &S, FunctionProtoType::ExtProtoInfo ExtInfo; ExtInfo.TypeQuals = Qualifiers::Const; - QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, ArrayRef(), - ExtInfo); + QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, None, ExtInfo); SourceLocation Loc = IntroducerRange.getBegin(); DeclarationName Name diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 940f8f32fa..9ab3b2d08e 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -731,7 +731,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { EPI.NumExceptions = 0; QualType ExpectedType = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(), - ArrayRef(), EPI); + None, EPI); // Perform template argument deduction against the type that we would // expect the function to have. diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 19a369ff9d..91f0881ae0 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -2007,8 +2007,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, /*TInfo=*/0, SC_None, 0); - SetterMethod->setMethodParams(Context, Argument, - ArrayRef()); + SetterMethod->setMethodParams(Context, Argument, None); AddPropertyAttrs(*this, SetterMethod, property); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index e59c811186..f2773af60b 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -11305,8 +11305,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); Oper != OperEnd; ++Oper) { AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context), - ArrayRef(), CandidateSet, - /*SuppressUserConversions=*/false); + None, CandidateSet, /*SuppressUserConversions=*/false); } bool HadMultipleCandidates = (CandidateSet.size() > 1); diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index 795cfbacfb..2786e89be4 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -1118,8 +1118,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() { /*TInfo=*/0, SC_None, 0); - AtIndexGetter->setMethodParams(S.Context, Argument, - ArrayRef()); + AtIndexGetter->setMethodParams(S.Context, Argument, None); } if (!AtIndexGetter) { @@ -1243,7 +1242,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() { SC_None, 0); Params.push_back(key); - AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef()); + AtIndexSetter->setMethodParams(S.Context, Params, None); } if (!AtIndexSetter) { -- cgit v1.2.3-70-g09d2 From 6b20351a1d6178addfaa86716aaba36f2e9ea188 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Mon, 6 May 2013 16:23:57 +0000 Subject: Allow targets to define minimum alignment for global variables This patch adds a new common code feature that allows platform code to request minimum alignment of global symbols. The background for this is that on SystemZ, the most efficient way to load addresses of global symbol is the LOAD ADDRESS RELATIVE LONG (LARL) instruction. This instruction provides PC-relative addressing, but only to *even* addresses. For this reason, existing compilers will guarantee that global symbols are always aligned to at least 2. [ Since symbols would otherwise already use a default alignment based on their type, this will usually only affect global objects of character type or character arrays. ] GCC also allows creating symbols without that extra alignment by using explicit "aligned" attributes (which then need to be used on both definition and each use of the symbol). To enable support for this with Clang, this patch adds a TargetInfo::MinGlobalAlign variable that provides a global minimum for the alignment of every global object (unless overridden via explicit alignment attribute), and adds code to respect this setting. Within this patch, no platform actually sets the value to anything but the default 1, resulting in no change in behaviour on any existing target. This version of the patch incorporates feedback from reviews by Eric Christopher and John McCall. Thanks to all reviewers! Patch by Richard Sandiford. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181210 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 8 ++++++++ include/clang/Basic/TargetInfo.h | 5 +++++ lib/AST/ASTContext.cpp | 16 ++++++++++++++++ lib/Basic/TargetInfo.cpp | 1 + lib/CodeGen/CodeGenModule.cpp | 10 +++++++++- lib/CodeGen/CodeGenModule.h | 4 ++-- 6 files changed, 41 insertions(+), 3 deletions(-) (limited to 'lib/CodeGen/CodeGenModule.h') diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 902ded55f8..c5d3337fd2 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1593,6 +1593,14 @@ public: /// beneficial for performance to overalign a data type. unsigned getPreferredTypeAlign(const Type *T) const; + /// \brief Return the alignment in bits that should be given to a + /// global variable with type \p T. + unsigned getAlignOfGlobalVar(QualType T) const; + + /// \brief Return the alignment in characters that should be given to a + /// global variable with type \p T. + CharUnits getAlignOfGlobalVarInChars(QualType T) const; + /// \brief Return a conservative estimate of the alignment of the specified /// decl \p D. /// diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index c05f062aee..21325fac36 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -66,6 +66,7 @@ protected: unsigned char LongWidth, LongAlign; unsigned char LongLongWidth, LongLongAlign; unsigned char SuitableAlign; + unsigned char MinGlobalAlign; unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth; unsigned short MaxVectorAlign; const char *DescriptionString; @@ -266,6 +267,10 @@ public: /// object with a fundamental alignment requirement. unsigned getSuitableAlign() const { return SuitableAlign; } + /// getMinGlobalAlign - Return the minimum alignment of a global variable, + /// unless its alignment is explicitly reduced via attributes. + unsigned getMinGlobalAlign() const { return MinGlobalAlign; } + /// getWCharWidth/Align - Return the size of 'wchar_t' for this target, in /// bits. unsigned getWCharWidth() const { return getTypeWidth(WCharType); } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index e6dfd445ad..8d40a6a299 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1283,6 +1283,10 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool RefAsPointee) const { T = getBaseElementType(arrayType); } Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr())); + if (const VarDecl *VD = dyn_cast(D)) { + if (VD->hasGlobalStorage()) + Align = std::max(Align, getTargetInfo().getMinGlobalAlign()); + } } // Fields can be subject to extra alignment constraints, like if @@ -1725,6 +1729,18 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { return ABIAlign; } +/// getAlignOfGlobalVar - Return the alignment in bits that should be given +/// to a global variable of the specified type. +unsigned ASTContext::getAlignOfGlobalVar(QualType T) const { + return std::max(getTypeAlign(T), getTargetInfo().getMinGlobalAlign()); +} + +/// getAlignOfGlobalVarInChars - Return the alignment in characters that +/// should be given to a global variable of the specified type. +CharUnits ASTContext::getAlignOfGlobalVarInChars(QualType T) const { + return toCharUnitsFromBits(getAlignOfGlobalVar(T)); +} + /// DeepCollectObjCIvars - /// This routine first collects all declared, but not synthesized, ivars in /// super class and then collects all ivars, including those synthesized for diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index ff72f495c8..0d44dc010e 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -37,6 +37,7 @@ TargetInfo::TargetInfo(const std::string &T) : TargetOpts(), Triple(T) LongWidth = LongAlign = 32; LongLongWidth = LongLongAlign = 64; SuitableAlign = 64; + MinGlobalAlign = 0; HalfWidth = 16; HalfAlign = 16; FloatWidth = 32; diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index ff183c96e0..0b03a3c4b6 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -2339,6 +2339,8 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { new llvm::GlobalVariable(getModule(), C->getType(), /*isConstant=*/true, Linkage, C, ".str"); GV->setUnnamedAddr(true); + // Don't enforce the target's minimum global alignment, since the only use + // of the string is via this class initializer. if (isUTF16) { CharUnits Align = getContext().getTypeAlignInChars(getContext().ShortTy); GV->setAlignment(Align.getQuantity()); @@ -2472,6 +2474,8 @@ CodeGenModule::GetAddrOfConstantString(const StringLiteral *Literal) { new llvm::GlobalVariable(getModule(), C->getType(), isConstant, Linkage, C, ".str"); GV->setUnnamedAddr(true); + // Don't enforce the target's minimum global alignment, since the only use + // of the string is via this class initializer. CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy); GV->setAlignment(Align.getQuantity()); Fields[1] = llvm::ConstantExpr::getGetElementPtr(GV, Zeros); @@ -2576,7 +2580,7 @@ CodeGenModule::GetConstantArrayFromStringLiteral(const StringLiteral *E) { /// constant array for the given string literal. llvm::Constant * CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) { - CharUnits Align = getContext().getTypeAlignInChars(S->getType()); + CharUnits Align = getContext().getAlignOfGlobalVarInChars(S->getType()); if (S->isAscii() || S->isUTF8()) { SmallString<64> Str(S->getString()); @@ -2645,6 +2649,10 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantString(StringRef Str, if (!GlobalName) GlobalName = ".str"; + if (Alignment == 0) + Alignment = getContext().getAlignOfGlobalVarInChars(getContext().CharTy) + .getQuantity(); + // Don't share any string literals if strings aren't constant. if (LangOpts.WritableStrings) return GenerateStringLiteral(Str, false, *this, GlobalName, Alignment); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 7bbca80bf4..91138c607c 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -713,7 +713,7 @@ public: /// (if one is created). llvm::Constant *GetAddrOfConstantString(StringRef Str, const char *GlobalName=0, - unsigned Alignment=1); + unsigned Alignment=0); /// GetAddrOfConstantCString - Returns a pointer to a character array /// containing the literal and a terminating '\0' character. The result has @@ -723,7 +723,7 @@ public: /// created). llvm::Constant *GetAddrOfConstantCString(const std::string &str, const char *GlobalName=0, - unsigned Alignment=1); + unsigned Alignment=0); /// GetAddrOfConstantCompoundLiteral - Returns a pointer to a constant global /// variable for the given file-scope compound literal expression. -- cgit v1.2.3-70-g09d2