Search code examples
c++carmclangllvm

Force a global variable using a specific register by Clang/LLVM


I have the code as follows:

// global.cpp
int a = 5;
register unsigned b __asm("r9");

int test()
{
   b = 4;
   a++;
   b = b + 7;
   int c = a + b;

   return c;
}

I run clang -target arm -c global.cpp -emit-llvm -o global.bc & llc -march=arm -filetype=asm global.bc -o -, but I get the following error:

        .text
        .syntax unified
        .eabi_attribute 67, "2.09"      @ Tag_conformance
        .eabi_attribute 6, 1    @ Tag_CPU_arch
        .eabi_attribute 8, 1    @ Tag_ARM_ISA_use
        .eabi_attribute 34, 1   @ Tag_CPU_unaligned_access
        .eabi_attribute 17, 1   @ Tag_ABI_PCS_GOT_use
        .eabi_attribute 20, 1   @ Tag_ABI_FP_denormal
        .eabi_attribute 21, 1   @ Tag_ABI_FP_exceptions
        .eabi_attribute 23, 3   @ Tag_ABI_FP_number_model
        .eabi_attribute 24, 1   @ Tag_ABI_align_needed
        .eabi_attribute 25, 1   @ Tag_ABI_align_preserved
        .eabi_attribute 38, 1   @ Tag_ABI_FP_16bit_format
        .eabi_attribute 18, 4   @ Tag_ABI_PCS_wchar_t
        .eabi_attribute 26, 2   @ Tag_ABI_enum_size
        .eabi_attribute 14, 0   @ Tag_ABI_PCS_R9_use
        .file   "global.cpp"
LLVM ERROR: Invalid register name "r9".
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
Stack dump:
0.      Program arguments: llc -march=arm -filetype=asm global.bc -o - 
1.      Running pass 'Function Pass Manager' on module 'global.bc'.
2.      Running pass 'ARM Instruction Selection' on function '@_Z4testv'
 #0 0x00007f345d2fea1a llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0xb12a1a)
 #1 0x00007f345d2fc7a4 llvm::sys::RunSignalHandlers() (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0xb107a4)
 #2 0x00007f345d2fc8f8 (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0xb108f8)
 #3 0x00007f345c39fde0 (/lib64/libc.so.6+0x38de0)
 #4 0x00007f345c39fd61 raise (/lib64/libc.so.6+0x38d61)
 #5 0x00007f345c389536 abort (/lib64/libc.so.6+0x22536)
 #6 0x00007f345d2165e6 llvm::report_fatal_error(llvm::Twine const&, bool) (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0xa2a5e6)
 #7 0x00007f345f40b269 (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0x2c1f269)
 #8 0x00007f345dbb9000 llvm::SelectionDAGISel::Select_READ_REGISTER(llvm::SDNode*) (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0x13cd000)
 #9 0x00007f345dbbc52b llvm::SelectionDAGISel::SelectCodeCommon(llvm::SDNode*, unsigned char const*, unsigned int) (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0x13d052b)
#10 0x00007f345f3fcf21 (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0x2c10f21)
#11 0x00007f345dbb85e8 llvm::SelectionDAGISel::DoInstructionSelection() (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0x13cc5e8)
#12 0x00007f345dbc11b5 llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0x13d51b5)
#13 0x00007f345dbc4560 llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0x13d8560)
#14 0x00007f345dbc7501 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0x13db501)
#15 0x00007f345f406014 (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0x2c1a014)
#16 0x00007f345d6c949d (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0xedd49d)
#17 0x00007f345d4503f8 llvm::FPPassManager::runOnFunction(llvm::Function&) (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0xc643f8)
#18 0x00007f345d451971 llvm::FPPassManager::runOnModule(llvm::Module&) (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0xc65971)
#19 0x00007f345d44f70b llvm::legacy::PassManagerImpl::run(llvm::Module&) (/usr/lib/llvm/11/bin/../lib64/libLLVM-11.so+0xc6370b)
#20 0x000056232e849ef6 main (/usr/lib/llvm/11/bin/llc+0xeef6)
#21 0x00007f345c38ae6b __libc_start_main (/lib64/libc.so.6+0x23e6b)
#22 0x000056232e84a6ca _start (/usr/lib/llvm/11/bin/llc+0xf6ca)

Could anyone give me hints how to force global variable b to be stored in register r9 ?

My LLVM & Clang version: 11.0.0

Update: I want to put a global variable to specific register (R9 in this example) since I am planning to port global register variables feature from ARM to my own back-end (I need global variables to be allocated in registers due to that no stack space for doing this). I just would like to confirm if this functionality can be used on ARM, so I could port this feature to my back-end.


Solution

  • "global variables in registers" is only supported for SP register on ARM. Patches are welcome :)