Skip to content

Commit c6d7072

Browse files
authored
[clang][CodeGen] Emit annotations for function declarations. (#66716)
Previously, annotations were only emitted for function definitions. With this change annotations are also emitted for declarations. Also, emitting function annotations is now deferred until the end so that the most up to date declaration is used which will have any inherited annotations.
1 parent efc60dc commit c6d7072

9 files changed

+101
-9
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,7 @@ void CodeGenModule::checkAliases() {
699699
void CodeGenModule::clear() {
700700
DeferredDeclsToEmit.clear();
701701
EmittedDeferredDecls.clear();
702+
DeferredAnnotations.clear();
702703
if (OpenMPRuntime)
703704
OpenMPRuntime->clear();
704705
}
@@ -3165,6 +3166,13 @@ void CodeGenModule::EmitVTablesOpportunistically() {
31653166
}
31663167

31673168
void CodeGenModule::EmitGlobalAnnotations() {
3169+
for (const auto& [MangledName, VD] : DeferredAnnotations) {
3170+
llvm::GlobalValue *GV = GetGlobalValue(MangledName);
3171+
if (GV)
3172+
AddGlobalAnnotations(VD, GV);
3173+
}
3174+
DeferredAnnotations.clear();
3175+
31683176
if (Annotations.empty())
31693177
return;
31703178

@@ -3678,6 +3686,14 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
36783686

36793687
// Ignore declarations, they will be emitted on their first use.
36803688
if (const auto *FD = dyn_cast<FunctionDecl>(Global)) {
3689+
// Update deferred annotations with the latest declaration if the function
3690+
// function was already used or defined.
3691+
if (FD->hasAttr<AnnotateAttr>()) {
3692+
StringRef MangledName = getMangledName(GD);
3693+
if (GetGlobalValue(MangledName))
3694+
DeferredAnnotations[MangledName] = FD;
3695+
}
3696+
36813697
// Forward declarations are emitted lazily on first use.
36823698
if (!FD->doesThisDeclarationHaveABody()) {
36833699
if (!FD->doesDeclarationForceExternallyVisibleDefinition())
@@ -4462,6 +4478,11 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
44624478
llvm::Function::Create(FTy, llvm::Function::ExternalLinkage,
44634479
Entry ? StringRef() : MangledName, &getModule());
44644480

4481+
// Store the declaration associated with this function so it is potentially
4482+
// updated by further declarations or definitions and emitted at the end.
4483+
if (D && D->hasAttr<AnnotateAttr>())
4484+
DeferredAnnotations[MangledName] = cast<ValueDecl>(D);
4485+
44654486
// If we already created a function with the same mangled name (but different
44664487
// type) before, take its name and add it to the list of functions to be
44674488
// replaced with F at the end of CodeGen.
@@ -5748,8 +5769,6 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
57485769
AddGlobalCtor(Fn, CA->getPriority());
57495770
if (const DestructorAttr *DA = D->getAttr<DestructorAttr>())
57505771
AddGlobalDtor(Fn, DA->getPriority(), true);
5751-
if (D->hasAttr<AnnotateAttr>())
5752-
AddGlobalAnnotations(D, Fn);
57535772
if (getLangOpts().OpenMP && D->hasAttr<OMPDeclareTargetDeclAttr>())
57545773
getOpenMPRuntime().emitDeclareTargetFunction(D, GV);
57555774
}

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,10 @@ class CodeGenModule : public CodeGenTypeCache {
431431
/// Global annotations.
432432
std::vector<llvm::Constant*> Annotations;
433433

434+
// Store deferred function annotations so they can be emitted at the end with
435+
// most up to date ValueDecl that will have all the inherited annotations.
436+
llvm::DenseMap<StringRef, const ValueDecl *> DeferredAnnotations;
437+
434438
/// Map used to get unique annotation strings.
435439
llvm::StringMap<llvm::Constant*> AnnotationStrings;
436440

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
2+
3+
// Test annotation attributes are still emitted when the function is used before
4+
// it is defined with annotations.
5+
6+
void foo(void);
7+
void *xxx = (void*)foo;
8+
void __attribute__((annotate("bar"))) foo();
9+
10+
// CHECK: target triple
11+
// CHECK-DAG: private unnamed_addr constant [4 x i8] c"bar\00", section "llvm.metadata"
12+
13+
// CHECK: @llvm.global.annotations = appending global [1 x { ptr, ptr, ptr, i32, ptr }] [{
14+
// CHECK-SAME: { ptr @foo,
15+
// CHECK-SAME: }], section "llvm.metadata"
16+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
2+
3+
// Test annotation attributes are still emitted when the function is used before
4+
// it is defined with annotations.
5+
6+
void foo(void);
7+
void *xxx = (void*)foo;
8+
void __attribute__((annotate("bar"))) foo() {}
9+
10+
// CHECK: target triple
11+
// CHECK-DAG: private unnamed_addr constant [4 x i8] c"bar\00", section "llvm.metadata"
12+
13+
// CHECK: @llvm.global.annotations = appending global [1 x { ptr, ptr, ptr, i32, ptr }] [{
14+
// CHECK-SAME: { ptr @foo,
15+
// CHECK-SAME: }], section "llvm.metadata"
16+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
2+
3+
// Test annotation attributes are emitted for declarations.
4+
5+
__attribute__((annotate("bar"))) int foo();
6+
7+
int main() {
8+
return foo();
9+
}
10+
11+
// CHECK: target triple
12+
// CHECK-DAG: private unnamed_addr constant [4 x i8] c"bar\00", section "llvm.metadata"
13+
14+
// CHECK: @llvm.global.annotations = appending global [1 x { ptr, ptr, ptr, i32, ptr }] [{
15+
// CHECK-SAME: { ptr @foo,
16+
// CHECK-SAME: }], section "llvm.metadata"
17+

clang/test/CodeGen/annotations-global.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ __attribute((address_space(1))) __attribute__((annotate("addrspace1_ann"))) char
3333
// CHECK: @llvm.global.annotations = appending global [11 x { ptr, ptr, ptr, i32, ptr }] [{
3434
// CHECK-SAME: { ptr @a.bar,
3535
// CHECK-SAME: { ptr @a.bar,
36-
// CHECK-SAME: { ptr @a,
37-
// CHECK-SAME: { ptr @a,
38-
// CHECK-SAME: { ptr @a,
39-
// CHECK-SAME: { ptr @a,
4036
// CHECK-SAME: { ptr @sfoo,
4137
// CHECK-SAME: { ptr @sfoo,
4238
// CHECK-SAME: { ptr @foo,
4339
// CHECK-SAME: { ptr @foo,
4440
// CHECK-SAME: { ptr addrspacecast (ptr addrspace(1) @addrspace1_var to ptr),
41+
// CHECK-SAME: { ptr @a,
42+
// CHECK-SAME: { ptr @a,
43+
// CHECK-SAME: { ptr @a,
44+
// CHECK-SAME: { ptr @a,
4545
// CHECK-SAME: }], section "llvm.metadata"
4646

4747
// AS1-GLOBALS: target datalayout = "{{.+}}-A5-G1"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang %s -S -emit-llvm -target x86_64-unknown-linux -o -
2+
3+
// Test annotation attributes on constructors do not crash.
4+
5+
class Foo {
6+
public:
7+
[[clang::annotate("test")]] Foo() {}
8+
};
9+
10+
Foo foo;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang_cc1 %s -S -emit-llvm -triple x86_64-unknown-linux-gnu -o - | FileCheck %s
2+
3+
// Test annotation attributes on destructors do not crash.
4+
5+
struct k {
6+
~k() __attribute__((annotate(""))) {}
7+
};
8+
void m() { k(); }
9+
10+
// CHECK: @llvm.global.annotations = appending global [2 x { ptr, ptr, ptr, i32, ptr }] [{

clang/test/CodeGenCXX/attr-annotate.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
//CHECK: @[[STR1:.*]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*}}attr-annotate.cpp\00", section "llvm.metadata"
44
//CHECK: @[[STR2:.*]] = private unnamed_addr constant [4 x i8] c"abc\00", align 1
55
//CHECK: @[[STR:.*]] = private unnamed_addr constant [5 x i8] c"test\00", section "llvm.metadata"
6-
//CHECK: @[[ARGS:.*]] = private unnamed_addr constant { i32, ptr, i32 } { i32 9, ptr @[[STR2:.*]], i32 8 }, section "llvm.metadata"
7-
//CHECK: @[[ARGS2:.*]] = private unnamed_addr constant { %struct.Struct } { %struct.Struct { ptr @_ZN1AIjLj9EE2SVE, ptr getelementptr (i8, ptr @_ZN1AIjLj9EE2SVE, i64 4) } }, section "llvm.metadata"
8-
//CHECK: @llvm.global.annotations = appending global [2 x { ptr, ptr, ptr, i32, ptr }] [{ ptr, ptr, ptr, i32, ptr } { ptr @_ZN1AIjLj9EE4testILi8EEEvv, ptr @[[STR:.*]], ptr @[[STR1:.*]], i32 {{.*}}, ptr @[[ARGS:.*]] }, { ptr, ptr, ptr, i32, ptr } { ptr @_ZN1AIjLj9EE5test2Ev, ptr @.str.6, ptr @.str.1, i32 24, ptr @[[ARGS2]] }]
6+
//CHECK: @[[ARGS:.*]] = private unnamed_addr constant { %struct.Struct } { %struct.Struct { ptr @_ZN1AIjLj9EE2SVE, ptr getelementptr (i8, ptr @_ZN1AIjLj9EE2SVE, i64 4) } }, section "llvm.metadata"
7+
//CHECK: @[[ARGS2:.*]] = private unnamed_addr constant { i32, ptr, i32 } { i32 9, ptr @[[STR2:.*]], i32 8 }, section "llvm.metadata"
8+
//CHECK: @llvm.global.annotations = appending global [2 x { ptr, ptr, ptr, i32, ptr }] [{ ptr, ptr, ptr, i32, ptr } { ptr @_ZN1AIjLj9EE5test2Ev, ptr @.str.6, ptr @.str.1, i32 24, ptr @[[ARGS]] }, { ptr, ptr, ptr, i32, ptr } { ptr @_ZN1AIjLj9EE4testILi8EEEvv, ptr @[[STR:.*]], ptr @[[STR1:.*]], i32 {{.*}}, ptr @[[ARGS2:.*]] }]
99

1010
constexpr const char* str() {
1111
return "abc";

0 commit comments

Comments
 (0)