llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.11k stars 11.1k forks source link

Clang-19 crash: fatal error: error in backend: register rbp is allocatable: function has no frame pointer #95500

Open iamanonymouscs opened 1 month ago

iamanonymouscs commented 1 month ago

Description:

I encountered an internal compiler error (ICE) while compiling a C code snippet using Clang version 19.0.0 on Ubuntu Linux. Below are the details of the environment, code, and command lines used: Also ICE on trunk, compiler explorer:https:https://godbolt.org/z/rjba9xznv

OS and Platform:

# uname -a
Linux ubuntu 4.15.0-213-generic #224-Ubuntu SMP Mon Jun 19 13:30:12 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Program:

# cat 1.c

        struct cpssp {
                union {
                        long double d;
                        unsigned long long mmx[2];
                } fpregs[8];
                unsigned int fpstt;
        };
        #define ST0(cpssp)    (cpssp->fpregs[cpssp->fpstt].d)
        #define ST(cpssp, n)  (cpssp->fpregs[(cpssp->fpstt + (n)) & 7].d)

        register struct cpssp *env asm ("rbp");
        unsigned int PARAM1;

        void op_fxchg_ST0_STN(void)
        {
                long double tmp;
                tmp = ST(env, PARAM1);
                ST(env, PARAM1) = ST0(env);
                ST0(env) = tmp;
        }

Command Lines:

# clang 1.c -Wall -Wextra -Werror  -O1 -fno-strict-aliasing -fstack-protector-strong -fno-rtti -fno-exceptions -Wno-unused-function -Wno-unused-parameter -Wno-unused-variable -Wno-vla -Wno-gnu-zero-variadic-macro-arguments  -Werror=unused -Werror=volatile-register-var -c -o 1.o

fatal error: error in backend: register rbp is allocatable: function has no frame pointer
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.  Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang -gdwarf-4 -g -o /app/output.s -mllvm --x86-asm-syntax=intel -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -Wall -Wextra -Werror -O1 -fno-strict-aliasing -fstack-protector-strong -fno-rtti -fno-exceptions -Wno-unused-function -Wno-unused-parameter -Wno-unused-variable -Wno-vla -Wno-gnu-zero-variadic-macro-arguments -Werror=unused -Werror=volatile-register-var -c <source>
1.  <eof> parser at end of file
2.  Code generation
3.  Running pass 'Function Pass Manager' on module '<source>'.
4.  Running pass 'X86 DAG->DAG Instruction Selection' on function '@op_fxchg_ST0_STN'
 #0 0x0000000003a094d8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3a094d8)
 #1 0x0000000003a071bc llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3a071bc)
 #2 0x0000000003950146 llvm::CrashRecoveryContext::HandleExit(int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3950146)
 #3 0x00000000039fe16e llvm::sys::Process::Exit(int, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x39fe16e)
 #4 0x0000000000c68b7a LLVMErrorHandler(void*, char const*, bool) cc1_main.cpp:0:0
 #5 0x000000000395acb3 llvm::report_fatal_error(llvm::Twine const&, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x395acb3)
 #6 0x00000000025fc5e3 llvm::X86TargetLowering::getRegisterByName(char const*, llvm::LLT, llvm::MachineFunction const&) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x25fc5e3)
 #7 0x0000000004be902b llvm::SelectionDAGISel::Select_READ_REGISTER(llvm::SDNode*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4be902b)
 #8 0x0000000004bed3be llvm::SelectionDAGISel::SelectCodeCommon(llvm::SDNode*, unsigned char const*, unsigned int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4bed3be)
 #9 0x000000000256a461 (anonymous namespace)::X86DAGToDAGISel::Select(llvm::SDNode*) X86ISelDAGToDAG.cpp:0:0
#10 0x0000000004be732b llvm::SelectionDAGISel::DoInstructionSelection() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4be732b)
#11 0x0000000004bf5f2a llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4bf5f2a)
#12 0x0000000004bf905d llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4bf905d)
#13 0x0000000004bfa5b8 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4bfa5b8)
#14 0x0000000004beb7af llvm::SelectionDAGISelLegacy::runOnMachineFunction(llvm::MachineFunction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4beb7af)
#15 0x0000000002daecb9 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.0) MachineFunctionPass.cpp:0:0
#16 0x00000000033914e3 llvm::FPPassManager::runOnFunction(llvm::Function&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x33914e3)
#17 0x0000000003391721 llvm::FPPassManager::runOnModule(llvm::Module&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3391721)
#18 0x0000000003391f85 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3391f85)
#19 0x0000000003ca6cad (anonymous namespace)::EmitAssemblyHelper::EmitAssembly(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) BackendUtil.cpp:0:0
#20 0x0000000003ca706b clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3ca706b)
#21 0x00000000042e6e0c clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x42e6e0c)
#22 0x000000000635e95c clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x635e95c)
#23 0x00000000042e7248 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x42e7248)
#24 0x000000000456c079 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x456c079)
#25 0x00000000044f2e9e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x44f2e9e)
#26 0x000000000465354e clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x465354e)
#27 0x0000000000c6adcc cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xc6adcc)
#28 0x0000000000c6412a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#29 0x000000000432a679 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#30 0x0000000003950084 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3950084)
#31 0x000000000432ac6f clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#32 0x00000000042f0b15 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x42f0b15)
#33 0x00000000042f157d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x42f157d)
#34 0x00000000042f9275 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x42f9275)
#35 0x0000000000c682d5 clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xc682d5)
#36 0x0000000000b41d14 main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xb41d14)
#37 0x000076ca51a29d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#38 0x000076ca51a29e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#39 0x0000000000c63bde _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xc63bde)
clang: error: clang frontend command failed with exit code 70 (use -v to see invocation)
Compiler returned: 70
llvmbot commented 1 month ago

@llvm/issue-subscribers-backend-x86

Author: Anonymous (iamanonymouscs)

### Description: I encountered an internal compiler error (ICE) while compiling a C code snippet using Clang version 19.0.0 on Ubuntu Linux. Below are the details of the environment, code, and command lines used: Also ICE on trunk, compiler explorer:https:https://godbolt.org/z/rjba9xznv ### OS and Platform: ``` # uname -a Linux ubuntu 4.15.0-213-generic #224-Ubuntu SMP Mon Jun 19 13:30:12 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux ``` ### Program: ``` # cat 1.c struct cpssp { union { long double d; unsigned long long mmx[2]; } fpregs[8]; unsigned int fpstt; }; #define ST0(cpssp) (cpssp->fpregs[cpssp->fpstt].d) #define ST(cpssp, n) (cpssp->fpregs[(cpssp->fpstt + (n)) & 7].d) register struct cpssp *env asm ("rbp"); unsigned int PARAM1; void op_fxchg_ST0_STN(void) { long double tmp; tmp = ST(env, PARAM1); ST(env, PARAM1) = ST0(env); ST0(env) = tmp; } ``` ### Command Lines: ``` # clang 1.c -Wall -Wextra -Werror -O1 -fno-strict-aliasing -fstack-protector-strong -fno-rtti -fno-exceptions -Wno-unused-function -Wno-unused-parameter -Wno-unused-variable -Wno-vla -Wno-gnu-zero-variadic-macro-arguments -Werror=unused -Werror=volatile-register-var -c -o 1.o fatal error: error in backend: register rbp is allocatable: function has no frame pointer PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script. Stack dump: 0. Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang -gdwarf-4 -g -o /app/output.s -mllvm --x86-asm-syntax=intel -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -Wall -Wextra -Werror -O1 -fno-strict-aliasing -fstack-protector-strong -fno-rtti -fno-exceptions -Wno-unused-function -Wno-unused-parameter -Wno-unused-variable -Wno-vla -Wno-gnu-zero-variadic-macro-arguments -Werror=unused -Werror=volatile-register-var -c <source> 1. <eof> parser at end of file 2. Code generation 3. Running pass 'Function Pass Manager' on module '<source>'. 4. Running pass 'X86 DAG->DAG Instruction Selection' on function '@op_fxchg_ST0_STN' #0 0x0000000003a094d8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3a094d8) #1 0x0000000003a071bc llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3a071bc) #2 0x0000000003950146 llvm::CrashRecoveryContext::HandleExit(int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3950146) #3 0x00000000039fe16e llvm::sys::Process::Exit(int, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x39fe16e) #4 0x0000000000c68b7a LLVMErrorHandler(void*, char const*, bool) cc1_main.cpp:0:0 #5 0x000000000395acb3 llvm::report_fatal_error(llvm::Twine const&, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x395acb3) #6 0x00000000025fc5e3 llvm::X86TargetLowering::getRegisterByName(char const*, llvm::LLT, llvm::MachineFunction const&) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x25fc5e3) #7 0x0000000004be902b llvm::SelectionDAGISel::Select_READ_REGISTER(llvm::SDNode*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4be902b) #8 0x0000000004bed3be llvm::SelectionDAGISel::SelectCodeCommon(llvm::SDNode*, unsigned char const*, unsigned int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4bed3be) #9 0x000000000256a461 (anonymous namespace)::X86DAGToDAGISel::Select(llvm::SDNode*) X86ISelDAGToDAG.cpp:0:0 #10 0x0000000004be732b llvm::SelectionDAGISel::DoInstructionSelection() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4be732b) #11 0x0000000004bf5f2a llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4bf5f2a) #12 0x0000000004bf905d llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4bf905d) #13 0x0000000004bfa5b8 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4bfa5b8) #14 0x0000000004beb7af llvm::SelectionDAGISelLegacy::runOnMachineFunction(llvm::MachineFunction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x4beb7af) #15 0x0000000002daecb9 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.0) MachineFunctionPass.cpp:0:0 #16 0x00000000033914e3 llvm::FPPassManager::runOnFunction(llvm::Function&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x33914e3) #17 0x0000000003391721 llvm::FPPassManager::runOnModule(llvm::Module&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3391721) #18 0x0000000003391f85 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3391f85) #19 0x0000000003ca6cad (anonymous namespace)::EmitAssemblyHelper::EmitAssembly(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) BackendUtil.cpp:0:0 #20 0x0000000003ca706b clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3ca706b) #21 0x00000000042e6e0c clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x42e6e0c) #22 0x000000000635e95c clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x635e95c) #23 0x00000000042e7248 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x42e7248) #24 0x000000000456c079 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x456c079) #25 0x00000000044f2e9e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x44f2e9e) #26 0x000000000465354e clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x465354e) #27 0x0000000000c6adcc cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xc6adcc) #28 0x0000000000c6412a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0 #29 0x000000000432a679 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0 #30 0x0000000003950084 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x3950084) #31 0x000000000432ac6f clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0 #32 0x00000000042f0b15 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x42f0b15) #33 0x00000000042f157d clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x42f157d) #34 0x00000000042f9275 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0x42f9275) #35 0x0000000000c682d5 clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xc682d5) #36 0x0000000000b41d14 main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xb41d14) #37 0x000076ca51a29d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90) #38 0x000076ca51a29e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40) #39 0x0000000000c63bde _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+0xc63bde) clang: error: clang frontend command failed with exit code 70 (use -v to see invocation) Compiler returned: 70 ```
J-MR-T commented 1 month ago

(shorter example that triggers the same error, for easier experimentation: https://godbolt.org/z/e75GP9Ezo)

This seems to be semi-intentional, X86TargetLowering::getRegisterByName simply throws this error if it encounters a frame pointer register variable in a function without a frame pointer. Also note that this only happens on -O1, not -O0, presumably because every function gets a frame pointer on -O0. I suppose the options for fixing this are:

  1. Somehow emit a normal user-facing error that doesn't look like a bug
  2. Require that a function has to have a frame pointer if it uses a register variable backed by a frame pointer register.
  3. Interestingly, GCC seems to handle this the exact opposite way, erroring on -O0, because the FP register is reserved by the compiler, but allowing it on -O1, because there, it's not. Personally, I think this is the most sensible option: I don't really see a use-case for allowing the user to use that register, if its already in use by the compiler.
e-kud commented 4 weeks ago

This is the same as #62984 and #26474.

Personally, I think this is the most sensible option: I don't really see a use-case for allowing the user to use that register, if its already in use by the compiler.

@J-MR-T Sometimes users indeed want to use rbp as it is a known frame pointer (embedded, some JIT tricks or custom unwinding etc.). I think we can't change such behavior easily.

J-MR-T commented 4 weeks ago

Ah thanks for pointing out this is a duplicate. If using rbp to manipulate the frame pointer manually is a supported use-case, maybe my 2nd suggestion would make sense then. Or again an actual error message that recommends setting -fno-omit-frame-pointer.