Rust static library with armclang resulting in error: packed-enum clashes with enum_is_int

Hi,

I recently tried to use a C-API for my Rust project in an embedded C project and stumbled on something:

When trying to link the static library to the C project with armclang, I got the following error:

Error: L6242E: Cannot link object 63f8a0b8a638da8c-aeabi_cdcmpeq_check_nan.o as its attributes are incompatible with the image attributes.
   ... packed-enum clashes with enum_is_int.

It seems like the llvm builtins that the Rust compiler includes in the library file have a different setting for the enum size than the object files generated by armclang.

The funny thing is that this error occurs with armclang, but not with clang.

Since I am trying to include my Rust project in an ARM Keil project, I need to be able to compile it with armclang.

I have made an example to reproduce this:

Cargo.toml:

[package]
name = "test_api"
version = "0.1.0"
edition = "2024"

[lib]
name = "test_123"
path = "src/test_123.rs"
crate-type = ["staticlib"]

[dependencies]
panic-halt = "0.2.0"

[build-dependencies]
cbindgen = "0.27.0"

src/test_123.rs:

#![no_std]

use panic_halt as _;

#[unsafe(no_mangle)]
pub extern "C" fn do_stuff(a: u16, b: u16) -> u16 {
    a + b
}

.cargo/config.toml:

[target.'cfg(all(target_arch = "arm", target_os = "none"))']

rustflags = [
  "-C", "link-arg=--nmagic",

  "-C", "link-arg=-Tlink.x",
  "-C", "link-arg=-Map=mem.map",
]

[build]
target = "thumbv8m.main-none-eabi"  

After building this with cargo build, I have put the generated file libtest_123.a with a corresponding header file into directory with a test C file:

test123.h:

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

uint16_t do_stuff(uint16_t a, uint16_t b);

test.c:

#include "test_123.h"

int __aeabi_cdcmpeq_check_nan(double a, double b); 
void DefaultHandler_(void) {

}

int main( void ) 
{

    __aeabi_cdcmpeq_check_nan(42.0, 43.0);

    do_stuff(4, 5);

    while(1);
}

The call of __aeabi_cdcmpeq_check_nan(double a, double b) makes sure that this llvm builtin is not optimized out.

When trying to compile and link this project with

armclang --target=arm-arm-none-eabi -march=armv8m.main test.c -mfpu=none -mfloat-abi=soft -mcmse -o test.elf -I. -L . -ltest_123

the following error message occurs:

Error: L6242E: Cannot link object 63f8a0b8a638da8c-aeabi_cdcmpeq_check_nan.o as its attributes are incompatible with the image attributes.
   ... packed-enum clashes with enum_is_int.
Finished: 1 information, 0 warning and 1 error messages.
armclang: error: linker command failed with exit code 1 (use -v to see invocation)

When using the additional argument -fshort-enums, it compiles and links but the project that I am trying to compile uses -fno-short-enums.

Checking libtest_123.a and a compiled test.o file with llvm-readobj -A, shows the clash:

libtest_123.a:

Attribute {
	Tag: 26
	Value: 1
	TagName: ABI_enum_size
	Description: Packed
}

test.o:

Attribute {
	Tag: 26
	Value: 2
	TagName: ABI_enum_size
	Description: Int32
}

Can someone maybe explain to me, why the Rust compiler seems to use llvm builtins that overrule the same ones used by armclang and why those are with packed enum size?

Also, is there a possibility to change this to Int32 enum size?

Thanks a lot in advance