Closed
Description
Consider the following IR:
@g = external global i32
define ptr @test_global_big_offset_zero_disc() {
ret ptr ptrauth (ptr getelementptr (i8, ptr @g, i64 add (i64 2147483648, i64 65537)), i32 2)
}
When compiling to an object file via the following command:
llc -mtriple aarch64-elf -mattr=+pauth -filetype=obj test.ll
We get the following assertion triggered:
llc: /path/to/llvm-project/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp:290: uint32_t {anonymous}::AArch64MCCodeEmitter::getAddSubImmOpValue(const llvm::MCInst&, unsigned int, llvm::SmallVectorImpl<llvm::MCFixup>&, const llvm::MCSubtargetInfo&) const: Assertion `(ShiftVal == 0 || ShiftVal == 12) && "unexpected shift value for add/sub immediate"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0. Program arguments: ./.build/rel-with-deb-info/bin/llc -mtriple aarch64-elf -mattr=+pauth -filetype=obj /path/to/test.ll
1. Running pass 'Function Pass Manager' on module '/path/to/test.ll'.
2. Running pass 'AArch64 Assembly Printer' on function '@test_global_big_offset_zero_disc'
#0 0x000065856e30ee1c llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) /path/to/llvm-project/llvm/lib/Support/Unix/Signals.inc:727:3
#1 0x000065856e30bf44 llvm::sys::RunSignalHandlers() /path/to/llvm-project/llvm/lib/Support/Signals.cpp:105:20
#2 0x000065856e30d445 SignalHandler(int) /path/to/llvm-project/llvm/lib/Support/Unix/Signals.inc:403:31
#3 0x000065856ee50ae0 (/usr/lib/libc.so.6+0x3cae0)
#4 0x000065856eea8e44 (/usr/lib/libc.so.6+0x94e44)
#5 0x000065856ee50a30 raise (/usr/lib/libc.so.6+0x3ca30)
#6 0x000065856ee384c3 abort (/usr/lib/libc.so.6+0x244c3)
#7 0x000065856ee383df (/usr/lib/libc.so.6+0x243df)
#8 0x000065856ee48c67 (/usr/lib/libc.so.6+0x34c67)
#9 0x0000658572863ae0 (anonymous namespace)::AArch64MCCodeEmitter::getAddSubImmOpValue(llvm::MCInst const&, unsigned int, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const (.constprop.0) /path/to/llvm-project/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp:313:1
#10 0x000065857286a73f (anonymous namespace)::AArch64MCCodeEmitter::getBinaryCodeForInstr(llvm::MCInst const&, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const (.isra.0) /path/to/llvm-project/.build/rel-with-deb-info/lib/Target/AArch64/AArch64GenMCCodeEmitter.inc:12694:10
#11 0x000065857287e29a llvm::SmallVectorBase<unsigned long>::size() const /path/to/llvm-project/llvm/include/llvm/ADT/SmallVector.h:91:32
#12 0x000065857287e29a llvm::SmallVectorTemplateCommon<char, void>::assertSafeToAdd(void const*, unsigned long) /path/to/llvm-project/llvm/include/llvm/ADT/SmallVector.h:210:59
#13 0x000065857287e29a llvm::SmallVectorTemplateCommon<char, void>::assertSafeToAddRange(char const*, char const*) /path/to/llvm-project/llvm/include/llvm/ADT/SmallVector.h:230:26
#14 0x000065857287e29a llvm::SmallVectorTemplateCommon<char, void>::assertSafeToAddRange(char const*, char const*) /path/to/llvm-project/llvm/include/llvm/ADT/SmallVector.h:227:8
#15 0x000065857287e29a void llvm::SmallVectorImpl<char>::append<char const*, void>(char const*, char const*) /path/to/llvm-project/llvm/include/llvm/ADT/SmallVector.h:697:31
#16 0x000065857287e29a void llvm::support::endian::write<unsigned int>(llvm::SmallVectorImpl<char>&, unsigned int, llvm::endianness) /path/to/llvm-project/llvm/include/llvm/Support/EndianStream.h:63:13
#17 0x000065857287e29a (anonymous namespace)::AArch64MCCodeEmitter::encodeInstruction(llvm::MCInst const&, llvm::SmallVectorImpl<char>&, llvm::SmallVectorImpl<llvm::MCFixup>&, llvm::MCSubtargetInfo const&) const /path/to/llvm-project/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp:717:35
#18 0x000065856ed33536 llvm::SmallVectorBase<unsigned int>::size() const /path/to/llvm-project/llvm/include/llvm/ADT/SmallVector.h:91:32
#19 0x000065856ed33536 llvm::SmallVectorTemplateCommon<llvm::MCFixup, void>::end() /path/to/llvm-project/llvm/include/llvm/ADT/SmallVector.h:282:41
#20 0x000065856ed33536 llvm::MCELFStreamer::emitInstToData(llvm::MCInst const&, llvm::MCSubtargetInfo const&) /path/to/llvm-project/llvm/lib/MC/MCELFStreamer.cpp:556:22
#21 0x000065856ed5810c std::__uniq_ptr_impl<llvm::MCAssembler, std::default_delete<llvm::MCAssembler>>::_M_ptr() const /usr/include/c++/14.1.1/bits/unique_ptr.h:193:67
#22 0x000065856ed5810c std::unique_ptr<llvm::MCAssembler, std::default_delete<llvm::MCAssembler>>::get() const /usr/include/c++/14.1.1/bits/unique_ptr.h:464:27
#23 0x000065856ed5810c std::unique_ptr<llvm::MCAssembler, std::default_delete<llvm::MCAssembler>>::operator*() const /usr/include/c++/14.1.1/bits/unique_ptr.h:447:2
#24 0x000065856ed5810c llvm::MCObjectStreamer::getAssembler() /path/to/llvm-project/llvm/include/llvm/MC/MCObjectStreamer.h:128:41
#25 0x000065856ed5810c llvm::MCObjectStreamer::emitInstruction(llvm::MCInst const&, llvm::MCSubtargetInfo const&) /path/to/llvm-project/llvm/lib/MC/MCObjectStreamer.cpp:429:15
#26 0x0000658573397edb llvm::SmallVectorTemplateCommon<llvm::MCOperand, void>::isSmall() const /path/to/llvm-project/llvm/include/llvm/ADT/SmallVector.h:156:39
#27 0x0000658573397edb llvm::SmallVectorImpl<llvm::MCOperand>::~SmallVectorImpl() /path/to/llvm-project/llvm/include/llvm/ADT/SmallVector.h:616:23
#28 0x0000658573397edb llvm::SmallVector<llvm::MCOperand, 6u>::~SmallVector() /path/to/llvm-project/llvm/include/llvm/ADT/SmallVector.h:1216:3
#29 0x0000658573397edb llvm::MCInst::~MCInst() /path/to/llvm-project/llvm/include/llvm/MC/MCInst.h:184:7
#30 0x0000658573397edb llvm::MCInstBuilder::~MCInstBuilder() /path/to/llvm-project/llvm/include/llvm/MC/MCInstBuilder.h:21:0
#31 0x0000658573397edb LowerMOVaddrPAC /path/to/llvm-project/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp:1708:0
#32 0x0000658573397edb (anonymous namespace)::AArch64AsmPrinter::emitInstruction(llvm::MachineInstr const*) /path/to/llvm-project/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp:1941:0
#33 0x000065857231f3ff llvm::AsmPrinter::emitFunctionBody() /path/to/llvm-project/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp:1856:9
#34 0x000065857338972b (anonymous namespace)::AArch64AsmPrinter::runOnMachineFunction(llvm::MachineFunction&) /path/to/llvm-project/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp:180:0
#35 0x00006585712143b8 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.0) /path/to/llvm-project/llvm/lib/CodeGen/MachineFunctionPass.cpp:93:33
#36 0x000065856e92ea35 llvm::FPPassManager::runOnFunction(llvm::Function&) /path/to/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1441:40
#37 0x000065856e92eca1 llvm::ilist_node_base<true>::getNext() const /path/to/llvm-project/llvm/include/llvm/ADT/ilist_node_base.h:43:45
#38 0x000065856e92eca1 llvm::ilist_node_impl<llvm::ilist_detail::node_options<llvm::Function, true, false, void, false>>::getNext() /path/to/llvm-project/llvm/include/llvm/ADT/ilist_node.h:94:66
#39 0x000065856e92eca1 llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Function, true, false, void, false>, false, false>::operator++() /path/to/llvm-project/llvm/include/llvm/ADT/ilist_iterator.h:157:25
#40 0x000065856e92eca1 llvm::FPPassManager::runOnModule(llvm::Module&) /path/to/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1486:22
#41 0x000065856e92fd26 runOnModule /path/to/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:1556:38
#42 0x000065856e92fd26 llvm::legacy::PassManagerImpl::run(llvm::Module&) /path/to/llvm-project/llvm/lib/IR/LegacyPassManager.cpp:541:55
#43 0x00000bff11c4305f compileModule(char**, llvm::LLVMContext&) /path/to/llvm-project/llvm/tools/llc/llc.cpp:742:34
#44 0x00000bff11c444b7 main /path/to/llvm-project/llvm/tools/llc/llc.cpp:409:35
#45 0x000065856ee39c88 (/usr/lib/libc.so.6+0x25c88)
#46 0x000065856ee39d4c __libc_start_main (/usr/lib/libc.so.6+0x25d4c)
#47 0x00000bff11c33f95 _start (./.build/rel-with-deb-info/bin/llc+0x16f95)
We try to emit "add immediate" instruction with 24-bit shift of the immediate while only 0 or 12 bits are allowed. See https://developer.arm.com/documentation/ddi0602/2023-09/Base-Instructions/ADD--immediate---Add--immediate--?lang=en.
According to comments in code, it's intended to support offsets as wide as 32-bit unsigned integers. Doing that with just add operation with a shift is not feasible since 24-bit shifts are not allowed.
For wide offsets, we should use a temporary register for storing the immediate and a sequence from movz/movk/movn instructions to fill this register.