Propagate annotations from source to binary

#1

I’m working on Rust support for an in-house developed hardware extension. This requires the programmer to annotate certain variables and functions. These annotations should be propagated through the compiler, preferably all the way down into the binary.

I already more or less managed to implement the front-end in a crate. For the propagation of the annotations, I’ve found a topic on llvm intrinsics and annotations:

I suppose I might be able to use llvm attributes. However, that requires modifications to the Rust compiler and/or llvm. Since there is no use-case for this work outside of the company, this work would have to be maintained by a very small team. Therefore, I would highly prefer a method that does not involve modifying the Rust compiler and/or llvm. Ideally, no unstable interfaces should be required either.

What would be my options? And if this non-invasive approach turns out to be impossible/impractical, what would be my best next option?

0 Likes

#2

Depending on how you intend to consume the annotation, one approach might be to have a separate section with a list of affected variables/functions:

fn foo() { /* ... */ }
static BAR: i32 = 42;

#[link_section(".my_fancy_symbols")]
#[used]
static FOO_ENTRY: fn() = foo;

#[link_section(".my_fancy_symbols")]
#[used]
static BAR_ENTRY: &'static i32 = &BAR;
0 Likes

#3

Took me some fiddling with my linker script, but I think this can solve my problem. Thank you!

One question though: I could not find any information on the #[used] attribute. Removing it generates a warning about an unused item, so it seems clear what the purpose is, but I’m curious what else I might have missed out. I could only find the information here: https://doc.rust-lang.org/reference/attributes.html

0 Likes

#4

The documentation for that was just added a couple weeks ago. It is currently not published, but you can see the source here: https://github.com/rust-lang-nursery/reference/blob/master/src/abi.md#the-used-attribute It should be published in the nightly docs soonish. Please let me know (or file an issue) if it does not answer your questions.

0 Likes

#5

Ah, thank you! That explains a lot. After reading the documentation, however, I think in my case I’m better off with #[allow(dead_code)] (which I would have used otherwise).

0 Likes

#6

Are you sure? In my example, even if, e.g. the function foo is used, the corresponding static variable FOO_ENTRY is not directly referenced by anything (#[link_section] doesn’t count as a use), so it will be removed when building with optimization enabled. That’s why I added #[used].

0 Likes

#7

As far as I can see, using the #[used] attribute will keep both the actual function/variable and the _ENTRY static variable in the binary. From my tests thus far, it seems that when the _ENTRY variable is removed (so, without the #[used] attribute), the actual function/variable it points to has been optimized away as well. This seems to make sense, since otherwise the _ENTRY contents would be a null pointer. I’ve yet to encounter a situation in which the _ENTRY variable is removed, while the actual function/variable has not been optimized away, but that might be due to my limited amount of tests.

I’m not sure yet if this is acceptable for my use case, so it is nice have the option to use #[used] to ensure the symbols are kept.

0 Likes