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.
Details
- Reviewers
aaron.ballman efriedma rjmccall erichkeane
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Adding additional reviewers for more opinions.
The changes seem reasonable to me given that the annotation attribute is used to squirrel data from the frontend to the backend (including via plugin attributes) and so its usage is pretty general. But I'd like a second opinion given that this attribute has only passed data along for function definitions for a *long* time. I'm not certain if changing this will cause surprises for the backend.
A little more context for the new reviewers. Over in this patch I added support for annotations to be emitted into WebAssembly. We'd like to use this to mark imported (declarations) and exported (definitions) of functions with special attributes.
Interestingly, I noticed the original patch that added annotations had support for merging annotations of declarations and definitions.
The idea of emitting annotations on declarations seems fine. (LLVM itself doesn't consume annotations anyway; they're meant as an extension mechanism for third-party tools.)
I'm a bit concerned the way this is implemented will end up dropping annotations we would previously emit. For example:
void foo(); void *xxx = (void*)foo; __attribute__((annotate("bar"))) void foo(){}
That example appears to still work the same with my patch:
@xxx = global ptr @foo, align 8 @.str = private unnamed_addr constant [4 x i8] c"bar\00", section "llvm.metadata" @.str.1 = private unnamed_addr constant [8 x i8] c"main2.c\00", section "llvm.metadata" @llvm.global.annotations = appending global [1 x { ptr, ptr, ptr, i32, ptr }] [{ ptr, ptr, ptr, i32, ptr } { ptr @foo, ptr @.str, ptr @.str.1, i32 3, ptr null }], section "llvm.metadata"
I'm not very familiar with the CodeGenModule, so I'm happy to move the call to AddGlobalAnnotations if there is a better place.
Slightly messed up my example because I forgot the function was unprototyped. The following should show what I mean:
void foo(void); void *xxx = (void*)foo; __attribute__((annotate("bar"))) void foo(){}
In terms of where the right place is, I don't recall the exact structure of that code off the top of my head, but I think there's somewhere we handle redeclarations?
I looked into the above issue with mixing declarations and definitions and I think I can fix that by leaving the AddGlobalAnnotations call in EmitGlobalFunctionDefinition and only calling AddGlobalAnnotations from GetOrCreateLLVMFunction when it's for a definition. However, with that I'm running into some duplicate annotations being created with C++ templates that I need to fix.
While looking into the duplicate annotations, I noticed someone else already implemented annotations for declarations, but it was rolled back.
I *thought* this seemed familiar! :-D Be sure to add the test case from the rolled-back review to make sure your patch doesn't trip on the same issue.
I'm happy with this approach.
clang/lib/CodeGen/CodeGenModule.cpp | ||
---|---|---|
4335 | This doesn't quite seem sufficient... I'd expect you'd want to update the map when you see a new declaration. Otherwise we miss annotations on something like: void foo(void); void *xxx = (void*)foo; void __attribute__((annotate("bar"))) foo(); Granted, I wouldn't expect this sort of construct to show up normally, and I'm not sure how hard this is to fix. |
Update deferred annotations whenever EmitGlobalDefinition is called
with a FunctionDecl and it has already been used or defined.
@efriedma I've updated the patch to fix the decl-use-decl example and added a test for it. Anything else?
Reverted this in 88b7e06dcf9723d0869b0c6bee030b4140e4366d as it makes clang crash. Reduced test case in the commit description.
This doesn't quite seem sufficient... I'd expect you'd want to update the map when you see a new declaration. Otherwise we miss annotations on something like:
Granted, I wouldn't expect this sort of construct to show up normally, and I'm not sure how hard this is to fix.