Index: lib/Target/ARM64/MCTargetDesc/ARM64AsmBackend.cpp =================================================================== --- lib/Target/ARM64/MCTargetDesc/ARM64AsmBackend.cpp +++ lib/Target/ARM64/MCTargetDesc/ARM64AsmBackend.cpp @@ -16,6 +16,7 @@ #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MachO.h" using namespace llvm; @@ -500,6 +501,9 @@ const MCFixup &Fixup, const MCFragment *DF, const MCValue &Target, uint64_t &Value, bool &IsResolved) override; + + void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value, bool IsPCRel) const override; }; void ELFARM64AsmBackend::processFixupValue(const MCAssembler &Asm, @@ -523,6 +527,23 @@ if ((uint32_t)Fixup.getKind() == ARM64::fixup_arm64_pcrel_adrp_imm21) IsResolved = false; } + +void ELFARM64AsmBackend::applyFixup(const MCFixup &Fixup, char *Data, + unsigned DataSize, uint64_t Value, + bool IsPCRel) const { + // store fixups in .eh_frame section in big endian order + if (!IsLittleEndian && Fixup.getKind() == FK_Data_4) { + const MCSection* Sec = Fixup.getValue()->FindAssociatedSection(); + const MCSectionELF *SecELF = static_cast(Sec); + if (SecELF->getSectionName() == ".eh_frame") { + const unsigned Offset = Fixup.getOffset(); + for (unsigned i = 0; i != 4; ++i) + Data[Offset + 3 - i] |= uint8_t((Value >> (i * 8)) & 0xff); + return; + } + } + ARM64AsmBackend::applyFixup (Fixup, Data, DataSize, Value, IsPCRel); +} } MCAsmBackend *llvm::createARM64leAsmBackend(const Target &T, Index: test/CodeGen/ARM64/big-endian-eh.ll =================================================================== --- test/CodeGen/ARM64/big-endian-eh.ll +++ test/CodeGen/ARM64/big-endian-eh.ll @@ -0,0 +1,73 @@ +; RUN: llc -mtriple arm64_be -filetype obj < %s | llvm-objdump -s - | FileCheck %s + +; ARM EHABI for big endian +; This test case checks whether CIE length record is laid out in big endian format. +; +; This is the LLVM assembly generated from following C++ code: +; +; extern void foo(int); +; void test(int a, int b) { +; try { +; foo(a); +; } catch (...) { +; foo(b); +; } +;} + +define void @_Z4testii(i32 %a, i32 %b) #0 { +entry: + invoke void @_Z3fooi(i32 %a) + to label %try.cont unwind label %lpad + +lpad: ; preds = %entry + %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* null + %1 = extractvalue { i8*, i32 } %0, 0 + %2 = tail call i8* @__cxa_begin_catch(i8* %1) #2 + invoke void @_Z3fooi(i32 %b) + to label %invoke.cont2 unwind label %lpad1 + +invoke.cont2: ; preds = %lpad + tail call void @__cxa_end_catch() + br label %try.cont + +try.cont: ; preds = %entry, %invoke.cont2 + ret void + +lpad1: ; preds = %lpad + %3 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + cleanup + invoke void @__cxa_end_catch() + to label %eh.resume unwind label %terminate.lpad + +eh.resume: ; preds = %lpad1 + resume { i8*, i32 } %3 + +terminate.lpad: ; preds = %lpad1 + %4 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + catch i8* null + %5 = extractvalue { i8*, i32 } %4, 0 + tail call void @__clang_call_terminate(i8* %5) #3 + unreachable +} + +declare void @_Z3fooi(i32) #0 + +declare i32 @__gxx_personality_v0(...) + +declare i8* @__cxa_begin_catch(i8*) + +declare void @__cxa_end_catch() + +; Function Attrs: noinline noreturn nounwind +define linkonce_odr hidden void @__clang_call_terminate(i8*) #1 { + %2 = tail call i8* @__cxa_begin_catch(i8* %0) #2 + tail call void @_ZSt9terminatev() #3 + unreachable +} + +declare void @_ZSt9terminatev() + +; CHECK-LABEL: Contents of section .eh_frame: +; CHECK-NEXT: 0000 0000001c +