Skip to content

Commit

Permalink
[clang][CodeGen] Emit annotations for function declarations. (#66716)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
brendandahl committed Nov 29, 2023
1 parent efc60dc commit c6d7072
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 9 deletions.
23 changes: 21 additions & 2 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,7 @@ void CodeGenModule::checkAliases() {
void CodeGenModule::clear() {
DeferredDeclsToEmit.clear();
EmittedDeferredDecls.clear();
DeferredAnnotations.clear();
if (OpenMPRuntime)
OpenMPRuntime->clear();
}
Expand Down Expand Up @@ -3165,6 +3166,13 @@ void CodeGenModule::EmitVTablesOpportunistically() {
}

void CodeGenModule::EmitGlobalAnnotations() {
for (const auto& [MangledName, VD] : DeferredAnnotations) {
llvm::GlobalValue *GV = GetGlobalValue(MangledName);
if (GV)
AddGlobalAnnotations(VD, GV);
}
DeferredAnnotations.clear();

if (Annotations.empty())
return;

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

// Ignore declarations, they will be emitted on their first use.
if (const auto *FD = dyn_cast<FunctionDecl>(Global)) {
// Update deferred annotations with the latest declaration if the function
// function was already used or defined.
if (FD->hasAttr<AnnotateAttr>()) {
StringRef MangledName = getMangledName(GD);
if (GetGlobalValue(MangledName))
DeferredAnnotations[MangledName] = FD;
}

// Forward declarations are emitted lazily on first use.
if (!FD->doesThisDeclarationHaveABody()) {
if (!FD->doesDeclarationForceExternallyVisibleDefinition())
Expand Down Expand Up @@ -4462,6 +4478,11 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
llvm::Function::Create(FTy, llvm::Function::ExternalLinkage,
Entry ? StringRef() : MangledName, &getModule());

// Store the declaration associated with this function so it is potentially
// updated by further declarations or definitions and emitted at the end.
if (D && D->hasAttr<AnnotateAttr>())
DeferredAnnotations[MangledName] = cast<ValueDecl>(D);

// If we already created a function with the same mangled name (but different
// type) before, take its name and add it to the list of functions to be
// replaced with F at the end of CodeGen.
Expand Down Expand Up @@ -5748,8 +5769,6 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
AddGlobalCtor(Fn, CA->getPriority());
if (const DestructorAttr *DA = D->getAttr<DestructorAttr>())
AddGlobalDtor(Fn, DA->getPriority(), true);
if (D->hasAttr<AnnotateAttr>())
AddGlobalAnnotations(D, Fn);
if (getLangOpts().OpenMP && D->hasAttr<OMPDeclareTargetDeclAttr>())
getOpenMPRuntime().emitDeclareTargetFunction(D, GV);
}
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ class CodeGenModule : public CodeGenTypeCache {
/// Global annotations.
std::vector<llvm::Constant*> Annotations;

// Store deferred function annotations so they can be emitted at the end with
// most up to date ValueDecl that will have all the inherited annotations.
llvm::DenseMap<StringRef, const ValueDecl *> DeferredAnnotations;

/// Map used to get unique annotation strings.
llvm::StringMap<llvm::Constant*> AnnotationStrings;

Expand Down
16 changes: 16 additions & 0 deletions clang/test/CodeGen/annotations-decl-use-decl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s

// Test annotation attributes are still emitted when the function is used before
// it is defined with annotations.

void foo(void);
void *xxx = (void*)foo;
void __attribute__((annotate("bar"))) foo();

// CHECK: target triple
// CHECK-DAG: private unnamed_addr constant [4 x i8] c"bar\00", section "llvm.metadata"

// CHECK: @llvm.global.annotations = appending global [1 x { ptr, ptr, ptr, i32, ptr }] [{
// CHECK-SAME: { ptr @foo,
// CHECK-SAME: }], section "llvm.metadata"

16 changes: 16 additions & 0 deletions clang/test/CodeGen/annotations-decl-use-define.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s

// Test annotation attributes are still emitted when the function is used before
// it is defined with annotations.

void foo(void);
void *xxx = (void*)foo;
void __attribute__((annotate("bar"))) foo() {}

// CHECK: target triple
// CHECK-DAG: private unnamed_addr constant [4 x i8] c"bar\00", section "llvm.metadata"

// CHECK: @llvm.global.annotations = appending global [1 x { ptr, ptr, ptr, i32, ptr }] [{
// CHECK-SAME: { ptr @foo,
// CHECK-SAME: }], section "llvm.metadata"

17 changes: 17 additions & 0 deletions clang/test/CodeGen/annotations-declaration.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s

// Test annotation attributes are emitted for declarations.

__attribute__((annotate("bar"))) int foo();

int main() {
return foo();
}

// CHECK: target triple
// CHECK-DAG: private unnamed_addr constant [4 x i8] c"bar\00", section "llvm.metadata"

// CHECK: @llvm.global.annotations = appending global [1 x { ptr, ptr, ptr, i32, ptr }] [{
// CHECK-SAME: { ptr @foo,
// CHECK-SAME: }], section "llvm.metadata"

8 changes: 4 additions & 4 deletions clang/test/CodeGen/annotations-global.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ __attribute((address_space(1))) __attribute__((annotate("addrspace1_ann"))) char
// CHECK: @llvm.global.annotations = appending global [11 x { ptr, ptr, ptr, i32, ptr }] [{
// CHECK-SAME: { ptr @a.bar,
// CHECK-SAME: { ptr @a.bar,
// CHECK-SAME: { ptr @a,
// CHECK-SAME: { ptr @a,
// CHECK-SAME: { ptr @a,
// CHECK-SAME: { ptr @a,
// CHECK-SAME: { ptr @sfoo,
// CHECK-SAME: { ptr @sfoo,
// CHECK-SAME: { ptr @foo,
// CHECK-SAME: { ptr @foo,
// CHECK-SAME: { ptr addrspacecast (ptr addrspace(1) @addrspace1_var to ptr),
// CHECK-SAME: { ptr @a,
// CHECK-SAME: { ptr @a,
// CHECK-SAME: { ptr @a,
// CHECK-SAME: { ptr @a,
// CHECK-SAME: }], section "llvm.metadata"

// AS1-GLOBALS: target datalayout = "{{.+}}-A5-G1"
Expand Down
10 changes: 10 additions & 0 deletions clang/test/CodeGenCXX/attr-annotate-constructor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %clang %s -S -emit-llvm -target x86_64-unknown-linux -o -

// Test annotation attributes on constructors do not crash.

class Foo {
public:
[[clang::annotate("test")]] Foo() {}
};

Foo foo;
10 changes: 10 additions & 0 deletions clang/test/CodeGenCXX/attr-annotate-destructor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %clang_cc1 %s -S -emit-llvm -triple x86_64-unknown-linux-gnu -o - | FileCheck %s

// Test annotation attributes on destructors do not crash.

struct k {
~k() __attribute__((annotate(""))) {}
};
void m() { k(); }

// CHECK: @llvm.global.annotations = appending global [2 x { ptr, ptr, ptr, i32, ptr }] [{
6 changes: 3 additions & 3 deletions clang/test/CodeGenCXX/attr-annotate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
//CHECK: @[[STR1:.*]] = private unnamed_addr constant [{{.*}} x i8] c"{{.*}}attr-annotate.cpp\00", section "llvm.metadata"
//CHECK: @[[STR2:.*]] = private unnamed_addr constant [4 x i8] c"abc\00", align 1
//CHECK: @[[STR:.*]] = private unnamed_addr constant [5 x i8] c"test\00", section "llvm.metadata"
//CHECK: @[[ARGS:.*]] = private unnamed_addr constant { i32, ptr, i32 } { i32 9, ptr @[[STR2:.*]], i32 8 }, section "llvm.metadata"
//CHECK: @[[ARGS2:.*]] = private unnamed_addr constant { %struct.Struct } { %struct.Struct { ptr @_ZN1AIjLj9EE2SVE, ptr getelementptr (i8, ptr @_ZN1AIjLj9EE2SVE, i64 4) } }, section "llvm.metadata"
//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]] }]
//CHECK: @[[ARGS:.*]] = private unnamed_addr constant { %struct.Struct } { %struct.Struct { ptr @_ZN1AIjLj9EE2SVE, ptr getelementptr (i8, ptr @_ZN1AIjLj9EE2SVE, i64 4) } }, section "llvm.metadata"
//CHECK: @[[ARGS2:.*]] = private unnamed_addr constant { i32, ptr, i32 } { i32 9, ptr @[[STR2:.*]], i32 8 }, section "llvm.metadata"
//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:.*]] }]

constexpr const char* str() {
return "abc";
Expand Down

0 comments on commit c6d7072

Please sign in to comment.