diff --git a/clang/test/Interpreter/simple-exception.cpp b/clang/test/Interpreter/simple-exception.cpp index 8741886a0a621..6749acd6e6bd2 100644 --- a/clang/test/Interpreter/simple-exception.cpp +++ b/clang/test/Interpreter/simple-exception.cpp @@ -1,7 +1,7 @@ // clang-format off // UNSUPPORTED: system-aix -// XFAIL for arm, arm64, riscv, or running on Windows. -// XFAIL: target={{(arm|riscv).*}}, system-windows +// XFAIL for arm and arm64, or running on Windows. +// XFAIL: target=arm{{.*}}, system-windows // RUN: cat %s | clang-repl | FileCheck %s // Incompatible with msan. It passes with -O3 but fail -Oz. Interpreter diff --git a/clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp b/clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp index 7b47d93446192..2f1c4efb381f0 100644 --- a/clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp +++ b/clang/unittests/Interpreter/ExceptionTests/InterpreterExceptionTest.cpp @@ -122,11 +122,6 @@ extern "C" int throw_exception() { Triple.getArch() == llvm::Triple::aarch64_32)) GTEST_SKIP(); - // FIXME: RISC-V fails as .eh_frame handling is not yet implemented in - // JITLink for RISC-V. See PR #66067. - if (Triple.isRISCV()) - GTEST_SKIP(); - llvm::cantFail(Interp->ParseAndExecute(ExceptionCode)); testing::internal::CaptureStdout(); auto ThrowException = diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h b/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h index cb66289180880..a31f7d73b099f 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/riscv.h @@ -214,6 +214,12 @@ enum EdgeKind_riscv : Edge::Kind { /// Linker relaxation will use this to ensure all code sequences are properly /// aligned and then remove these edges from the graph. AlignRelaxable, + + /// 32-bit negative delta. + /// + /// Fixup expression: + /// Fixup <- Fixup - Target + Addend + NegDelta32, }; /// Returns a string name for the given riscv edge. For debugging purposes diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp index 35816ea66cf9b..d0701ba08bd91 100644 --- a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp @@ -11,10 +11,12 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/JITLink/ELF_riscv.h" +#include "EHFrameSupportImpl.h" #include "ELFLinkGraphBuilder.h" #include "JITLinkGeneric.h" #include "PerGraphGOTAndPLTStubsBuilder.h" #include "llvm/BinaryFormat/ELF.h" +#include "llvm/ExecutionEngine/JITLink/DWARFRecordSectionSplitter.h" #include "llvm/ExecutionEngine/JITLink/JITLink.h" #include "llvm/ExecutionEngine/JITLink/riscv.h" #include "llvm/Object/ELF.h" @@ -456,6 +458,13 @@ class ELFJITLinker_riscv : public JITLinker { case AlignRelaxable: // Ignore when the relaxation pass did not run break; + case NegDelta32: { + int64_t Value = FixupAddress - E.getTarget().getAddress() + E.getAddend(); + if (LLVM_UNLIKELY(!isInRangeForImm(Value, 32))) + return makeTargetOutOfRangeError(G, B, E); + *(little32_t *)FixupPtr = static_cast(Value); + break; + } } return Error::success(); } @@ -958,6 +967,13 @@ void link_ELF_riscv(std::unique_ptr G, PassConfiguration Config; const Triple &TT = G->getTargetTriple(); if (Ctx->shouldAddDefaultTargetPasses(TT)) { + + Config.PrePrunePasses.push_back(DWARFRecordSectionSplitter(".eh_frame")); + Config.PrePrunePasses.push_back(EHFrameEdgeFixer( + ".eh_frame", G->getPointerSize(), Edge::Invalid, Edge::Invalid, + Edge::Invalid, Edge::Invalid, NegDelta32)); + Config.PrePrunePasses.push_back(EHFrameNullTerminator(".eh_frame")); + if (auto MarkLive = Ctx->getMarkLivePass(TT)) Config.PrePrunePasses.push_back(std::move(MarkLive)); else diff --git a/llvm/lib/ExecutionEngine/JITLink/riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/riscv.cpp index a78843b161479..a4e4daef97fb5 100644 --- a/llvm/lib/ExecutionEngine/JITLink/riscv.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/riscv.cpp @@ -82,6 +82,8 @@ const char *getEdgeKindName(Edge::Kind K) { return "CallRelaxable"; case AlignRelaxable: return "AlignRelaxable"; + case NegDelta32: + return "NegDelta32"; } return getGenericEdgeKindName(K); } diff --git a/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_ehframe.s b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_ehframe.s new file mode 100644 index 0000000000000..9173bf7c3d95e --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_ehframe.s @@ -0,0 +1,74 @@ +# REQUIRES: asserts + +# RUN: llvm-mc -triple=riscv32-linux-gnu -mattr=+relax -filetype=obj -o %t.32.o %s +# RUN: llvm-jitlink -noexec -phony-externals -debug-only=jitlink %t.32.o 2>&1 | \ +# RUN: FileCheck %s + +# RUN: llvm-mc -triple=riscv64-linux-gnu -mattr=+relax -filetype=obj -o %t.64.o %s +# RUN: llvm-jitlink -noexec -phony-externals -debug-only=jitlink %t.64.o 2>&1 | \ +# RUN: FileCheck %s + +# Check that splitting of eh-frame sections works. +# +# CHECK: DWARFRecordSectionSplitter: Processing .eh_frame... +# CHECK: Processing block at +# CHECK: Processing CFI record at +# CHECK: Extracted {{.*}} section = .eh_frame +# CHECK: Processing CFI record at +# CHECK: Extracted {{.*}} section = .eh_frame +# CHECK: EHFrameEdgeFixer: Processing .eh_frame in "{{.*}}"... +# CHECK: Processing block at +# CHECK: Record is CIE +# CHECK: Processing block at +# CHECK: Record is FDE +# CHECK: Adding edge at {{.*}} to CIE at: {{.*}} +# CHECK: Existing edge at {{.*}} to PC begin at {{.*}} +# CHECK: Adding keep-alive edge from target at {{.*}} to FDE at {{.*}} +# CHECK: Processing block at +# CHECK: Record is FDE +# CHECK: Adding edge at {{.*}} to CIE at: {{.*}} +# CHECK: Existing edge at {{.*}} to PC begin at {{.*}} +# CHECK: Adding keep-alive edge from target at {{.*}} to FDE at {{.*}} + +## This is "int main { throw 1; }" compiled for riscv32. We use the 32-bit +## version because it is also legal for riscv64. + .text + .globl main + .p2align 1 + .type main,@function +main: + .cfi_startproc + addi sp, sp, -16 + .cfi_def_cfa_offset 16 + sw ra, 12(sp) + .cfi_offset ra, -4 + li a0, 4 + call __cxa_allocate_exception + li a1, 1 + sw a1, 0(a0) + lga a1, _ZTIi + li a2, 0 + call __cxa_throw +.Lfunc_end0: + .size main, .Lfunc_end0-main + .cfi_endproc + + .globl dup + .p2align 1 + .type dup,@function +dup: + .cfi_startproc + addi sp, sp, -16 + .cfi_def_cfa_offset 16 + sw ra, 12(sp) + .cfi_offset ra, -4 + li a0, 4 + call __cxa_allocate_exception + li a1, 1 + sw a1, 0(a0) + lga a1, _ZTIi + li a2, 0 + call __cxa_throw +.Lfunc_end1: + .size dup, .Lfunc_end1-dup + .cfi_endproc diff --git a/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_ehframe.test b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_ehframe.test new file mode 100644 index 0000000000000..95666d2e232b7 --- /dev/null +++ b/llvm/test/ExecutionEngine/JITLink/RISCV/ELF_ehframe.test @@ -0,0 +1,104 @@ +# RUN: yaml2obj -DELFCLASS=ELFCLASS32 -o %t.32.o %s +# RUN: llvm-jitlink -noexec -check %s %t.32.o +# RUN: yaml2obj -DELFCLASS=ELFCLASS64 -o %t.64.o %s +# RUN: llvm-jitlink -noexec -check %s %t.64.o + +### Compiled from the following code with -mattr=+relax to force relocations for +### address_range and DW_CFA_advance_loc (both needed for .balign). +## .text +## .globl main +## .p2align 1 +## .type main,@function +## main: +## .cfi_startproc +## .balign 8 +## addi sp, sp, -16 +## cfa_advance_loc: +## .cfi_def_cfa_offset 16 +## nop +## main_end: +## .size main, main_end-main +## .cfi_endproc + +--- !ELF +FileHeader: + Class: [[ELFCLASS]] + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_RISCV + SectionHeaderStringTable: .strtab +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x8 + Content: 13000000130101FF13000000 + - Name: .eh_frame + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + AddressAlign: 0x8 + Content: 1000000000000000017A5200017801011B0C02001000000018000000000000000000000000400E10 + - Name: .rela.text + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .text + Relocations: + - Type: R_RISCV_ALIGN + Addend: 4 + - Name: .rela.eh_frame + Type: SHT_RELA + Flags: [ SHF_INFO_LINK ] + Link: .symtab + AddressAlign: 0x8 + Info: .eh_frame + Relocations: + - Offset: 0x1C + Symbol: main + Type: R_RISCV_32_PCREL + - Offset: 0x20 + Symbol: main_end + Type: R_RISCV_ADD32 + - Offset: 0x20 + Symbol: main + Type: R_RISCV_SUB32 + - Offset: 0x25 + Symbol: cfa_advance_loc + Type: R_RISCV_SET6 + - Offset: 0x25 + Symbol: main + Type: R_RISCV_SUB6 + - Type: SectionHeaderTable + Sections: + - Name: .strtab + - Name: .text + - Name: .rela.text + - Name: .eh_frame + - Name: .rela.eh_frame + - Name: .symtab +Symbols: + - Name: cfa_advance_loc + Section: .text + Value: 0x8 + - Name: main_end + Section: .text + Value: 0xC + - Name: main + Type: STT_FUNC + Section: .text + Binding: STB_GLOBAL + Size: 0xC + - Name: eh_frame + Type: STT_SECTION + Binding: STB_GLOBAL + Section: .eh_frame + Size: 0x28 +... + +## CIE_pointer +# jitlink-check: *{4}(eh_frame + 0x1c) = main - (eh_frame + 0x1c) +## address_range +# jitlink-check: *{4}(eh_frame + 0x20) = main_end - main +## DW_CFA_advance_loc +# jitlink-check: (*{1}(eh_frame + 0x25)) & 0x3f = cfa_advance_loc - main