llvm / llvm/llvm-project

Missing ELF attributes for code generation options

Open
#210,840 8 comments 0 reactions 0 assignees View on GitHub
backend:RISC-V llvm:codegen
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

When investigating what turned out to be a misconfigured build, the Fuchsia kernel developers discovered that the Rust compiler can generate object files without matching ELF attributes for key ABI affecting code generation options. In particular, on RISC-V vector instructions were not listed as part of the ELF attributes, when they normally would be. In this case the kernel devs were surprised to find V instructions at all (ultimately due to a misconfigured build, as +v shouldn't have been part of march), but when we were using llvm-objdump, we were surprised to find that the normal attributes that objdump would use to set the right extensions for disassembly were missing `vector support altogether.

When investigating further, I found that the general issue on RISCV is somewhat known: https://github.com/llvm/llvm-project/blob/5ed5468f3810cd3c424eec5e9288884f67594068/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp#L672-#L678

```cpp
// Use MCSubtargetInfo from TargetMachine. Individual functions may have
// attributes that differ from other functions in the module and we have no
// way to know which function is correct.
```

Originally we believed this was Rust and LTO specific, but I was able to trigger this behavior with Clang and without LTO, though some would argue that the following example is an abuse of function attributes.

```cpp
// REQUIRES: riscv-registered-target
// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64gc -c -O2 %s -o %t.o
// RUN: llvm-objdump -d %t.o | FileCheck %s --check-prefix=OBJDUMP
// RUN: llvm-objdump -d --mattr=+zbb %t.o | FileCheck %s --check-prefix=OBJDUMP-ZBB
// RUN: llvm-readelf -A %t.o | FileCheck %s --check-prefix=READELF

// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64gc_zbb -c -O2 %s -o %t_zbb.o
// RUN: llvm-objdump -d %t_zbb.o | FileCheck %s --check-prefix=OBJDUMP-ZBB-ATTR
// RUN: llvm-readelf -A %t_zbb.o | FileCheck %s --check-prefix=READELF-ZBB

#include

// OBJDUMP-LABEL: <_Z10normal_clzy>:
// OBJDUMP-NOT: clz
// OBJDUMP: ret

// OBJDUMP-ZBB-LABEL: <_Z10normal_clzy>:
// OBJDUMP-ZBB-NOT: clz
// OBJDUMP-ZBB: ret

// OBJDUMP-ZBB-ATTR-LABEL: <_Z10normal_clzy>:
// OBJDUMP-ZBB-ATTR-NEXT: {{[0-9a-f]+}}: 60051513 clz a0, a0
// OBJDUMP-ZBB-ATTR-NEXT: {{[0-9a-f]+}}: 8082 ret
uint64_t normal_clz(uint64_t a) {
return __builtin_clzll(a);
}

// OBJDUMP-LABEL: <_Z7zbb_clzy>:
// OBJDUMP-NEXT: {{[0-9a-f]+}}: 60051513
// OBJDUMP-NEXT: {{[0-9a-f]+}}: 8082 ret

// OBJDUMP-ZBB-LABEL: <_Z7zbb_clzy>:
// OBJDUMP-ZBB-NEXT: {{[0-9a-f]+}}: 60051513 clz a0, a0
// OBJDUMP-ZBB-NEXT: {{[0-9a-f]+}}: 8082 ret

// OBJDUMP-ZBB-ATTR-LABEL: <_Z7zbb_clzy>:
// OBJDUMP-ZBB-ATTR-NEXT: {{[0-9a-f]+}}: 60051513 clz a0, a0
// OBJDUMP-ZBB-ATTR-NEXT: {{[0-9a-f]+}}: 8082 ret
__attribute__((target("arch=+zbb")))
uint64_t zbb_clz(uint64_t a) {
return __builtin_clzll(a);
}

// READELF: TagName: arch
// READELF-NOT: zbb

// READELF-ZBB: TagName: arch
// READELF-ZBB-NEXT: Value: {{.*}}zbb

```

@topperc @preames While this manifests in our experience as a RISC-V specific issue, its not clear to me if this is a more fundamental consequence of the per function target features that disproportionately affect RISC-V compared to other architectures. This certainly feels like something we should be able to avoid, but I know a lot of the `-march` handling rules are a bit complicated. I haven't' started looking at how to solve the issue yet, but given the code comment linked above, this seems to be an area we've already encountered problems.

Contributor guide

Open the contributing guide

Research direction

Start with the RISCVAsmPrinter.cpp logic linked in the issue, then run the supplied Clang, llvm-objdump, and llvm-readelf reproducer. Compare the baseline and zbb cases and add or update an LLVM regression test so ELF attributes reflect the code-generation extensions used by the object file.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.