This is an archive of the discontinued LLVM Phabricator instance.

[clang][CodeGen] Emit annotations for function declarations.
AcceptedPublic

Authored by brendandahl on Jul 24 2023, 3:07 PM.

Details

Summary

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.

Diff Detail

Event Timeline

brendandahl created this revision.Jul 24 2023, 3:07 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 24 2023, 3:07 PM
brendandahl requested review of this revision.Jul 24 2023, 3:07 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 24 2023, 3:07 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript

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.

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.

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 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.

Switch to emitting annotations and the end.

I'm happy with this approach.

clang/lib/CodeGen/CodeGenModule.cpp
4327

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.

Cleanup some extra brackets.

@efriedma I've updated the patch to fix the decl-use-decl example and added a test for it. Anything else?

This revision is now accepted and ready to land.Aug 31 2023, 2:17 PM

Rebase and fix unused variable warning.

brendandahl edited the summary of this revision. (Show Details)Sep 12 2023, 1:04 PM

Reverted this in 88b7e06dcf9723d0869b0c6bee030b4140e4366d as it makes clang crash. Reduced test case in the commit description.