From 9bcde422e918cbc1e7578a1d751ea03a3450d05d Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Tue, 10 Sep 2024 16:22:58 -0700 Subject: [PATCH 1/6] [CHERI-RISC-V] Baseline test for function entry directives We are emitting the local function symbol alias in a slightly weird order, which will be fixed in the following commits. --- .../RISCV/cheri/function-start-directives.ll | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll diff --git a/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll b/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll new file mode 100644 index 000000000000..2f3e5548eb76 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll @@ -0,0 +1,59 @@ +;; Check that the directives at the start of the function are emitted in a sensible order +; RUN: %riscv64_cheri_purecap_llc -relocation-model=pic < %s | FileCheck %s --check-prefixes=PIC,CHECK +; RUN: %riscv64_cheri_purecap_llc -relocation-model=static < %s | FileCheck %s --check-prefixes=CHECK + +target triple = "riscv64-unknown-freebsd13" + +define dso_local noundef signext i32 @_Z4testv() local_unnamed_addr addrspace(200) uwtable personality ptr addrspace(200) @__gxx_personality_v0 { +entry: + %call = invoke noundef signext i32 @_Z3foov(ptr addrspace(200) @_Z4testv) + to label %return unwind label %lpad + +lpad: ; preds = %entry + %0 = landingpad { ptr addrspace(200), i32 } + catch ptr addrspace(200) null + %1 = extractvalue { ptr addrspace(200), i32 } %0, 0 + %2 = tail call ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200) %1) #2 + tail call void @__cxa_end_catch() + br label %return + +return: ; preds = %entry, %lpad + %retval.0 = phi i32 [ 3, %lpad ], [ %call, %entry ] + ret i32 %retval.0 +} + +declare dso_local noundef signext i32 @_Z3foov(ptr addrspace(200)) local_unnamed_addr addrspace(200) + +declare dso_local i32 @__gxx_personality_v0(...) addrspace(200) + +declare dso_local ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200)) local_unnamed_addr addrspace(200) + +declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) + +; CHECK: .text +; CHECK-NEXT: .attribute 4, 16 +; CHECK-NEXT: .attribute 5, "rv64i2p0_xcheri0p0" +; CHECK-NEXT: .file "" +; CHECK-NEXT: .globl _Z4testv # -- Begin function _Z4testv +; CHECK-NEXT: .p2align 2 +; CHECK-NEXT: .type _Z4testv,@function +; CHECK-NEXT: .type .L_Z4testv$eh_alias,@function +; CHECK-NEXT: _Z4testv: # @_Z4testv +; PIC-NEXT: .L_Z4testv$local: +; PIC-NEXT: .type .L_Z4testv$local,@function +; CHECK-NEXT: .L_Z4testv$eh_alias: +; CHECK-NEXT: .Lfunc_begin0: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: .cfi_personality 155, DW.ref.__gxx_personality_v0 +; CHECK-NEXT: .cfi_lsda 27, .Lexception0 +; CHECK-NEXT: # %bb.0: # %entry + +; CHECK: .Lfunc_end0: +; CHECK-NEXT: .size _Z4testv, .Lfunc_end0-_Z4testv +; CHECK-NEXT: .size .L_Z4testv$eh_alias, .Lfunc_end0-_Z4testv +; PIC-NEXT: .size .L_Z4testv$local, .Lfunc_end0-_Z4testv +; CHECK-NEXT: .cfi_endproc + +; CHECK: .section .gcc_except_table +; CHECK: .word 12 # (landing pad is a capability) +; CHECK-NEXT: .chericap .L_Z4testv$eh_alias + .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2 From 032e35604a0b4c2b269c78e83f8a832575d7a73f Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Tue, 10 Sep 2024 16:31:20 -0700 Subject: [PATCH 2/6] [CHERI-Generic] Update landingpad tests to use opaque pointers --- .../Inputs/landingpad-non-preemptible.ll | 32 +++++++++-------- .../MIPS/landingpad-non-preemptible.ll | 34 ++++++++++--------- .../RISCV32/landingpad-non-preemptible.ll | 32 +++++++++-------- .../RISCV64/landingpad-non-preemptible.ll | 32 +++++++++-------- 4 files changed, 69 insertions(+), 61 deletions(-) diff --git a/llvm/test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll b/llvm/test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll index 0ceb97efb41c..3632154a94a3 100644 --- a/llvm/test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll +++ b/llvm/test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll @@ -19,30 +19,32 @@ ; CHECK: .type .L_Z8do_catchv$eh_alias,@function ; UTC_ARGS: --enable -@_ZTIi = external dso_local addrspace(200) constant i8 addrspace(200)* -define dso_local i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) uwtable personality i8 addrspace(200)* bitcast (i32 (...) addrspace(200)* @__gxx_personality_v0 to i8 addrspace(200)*) { +@_ZTIi = external dso_local addrspace(200) constant ptr addrspace(200) +define dso_local noundef signext i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) #0 personality ptr addrspace(200) @__gxx_personality_v0 { entry: - %call = invoke i32 @_Z3foov() to label %return unwind label %lpad -lpad: - %0 = landingpad { i8 addrspace(200)*, i32 } - catch i8 addrspace(200)* bitcast (i8 addrspace(200)* addrspace(200)* @_ZTIi to i8 addrspace(200)*) - catch i8 addrspace(200)* null - %1 = extractvalue { i8 addrspace(200)*, i32 } %0, 0 - %2 = extractvalue { i8 addrspace(200)*, i32 } %0, 1 - %3 = tail call i32 @llvm.eh.typeid.for(i8* addrspacecast (i8 addrspace(200)* bitcast (i8 addrspace(200)* addrspace(200)* @_ZTIi to i8 addrspace(200)*) to i8*)) + %call = invoke noundef signext i32 @_Z3foov() + to label %return unwind label %lpad + +lpad: ; preds = %entry + %0 = landingpad { ptr addrspace(200), i32 } + catch ptr addrspace(200) @_ZTIi + catch ptr addrspace(200) null + %1 = extractvalue { ptr addrspace(200), i32 } %0, 0 + %2 = extractvalue { ptr addrspace(200), i32 } %0, 1 + %3 = tail call i32 @llvm.eh.typeid.for(ptr addrspacecast (ptr addrspace(200) @_ZTIi to ptr)) nounwind %matches = icmp eq i32 %2, %3 - %4 = tail call i8 addrspace(200)* @__cxa_begin_catch(i8 addrspace(200)* %1) nounwind + %4 = tail call ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200) %1) nounwind br i1 %matches, label %catch1, label %catch -catch1: +catch1: ; preds = %lpad tail call void @__cxa_end_catch() nounwind br label %return -catch: +catch: ; preds = %lpad tail call void @__cxa_end_catch() br label %return -return: +return: ; preds = %entry, %catch1, %catch %retval.0 = phi i32 [ 1, %catch1 ], [ 2, %catch ], [ %call, %entry ] ret i32 %retval.0 } @@ -53,7 +55,7 @@ declare dso_local i32 @__gxx_personality_v0(...) addrspace(200) declare i32 @llvm.eh.typeid.for(i8*) addrspace(200) nounwind readnone -declare dso_local i8 addrspace(200)* @__cxa_begin_catch(i8 addrspace(200)*) local_unnamed_addr addrspace(200) +declare dso_local ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200)) local_unnamed_addr addrspace(200) declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) diff --git a/llvm/test/CodeGen/CHERI-Generic/MIPS/landingpad-non-preemptible.ll b/llvm/test/CodeGen/CHERI-Generic/MIPS/landingpad-non-preemptible.ll index 2f1bc5521e3f..fc56caaaf147 100644 --- a/llvm/test/CodeGen/CHERI-Generic/MIPS/landingpad-non-preemptible.ll +++ b/llvm/test/CodeGen/CHERI-Generic/MIPS/landingpad-non-preemptible.ll @@ -21,8 +21,8 @@ ; CHECK: .type .L_Z8do_catchv$eh_alias,@function ; UTC_ARGS: --enable -@_ZTIi = external dso_local addrspace(200) constant i8 addrspace(200)* -define dso_local i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) uwtable personality i8 addrspace(200)* bitcast (i32 (...) addrspace(200)* @__gxx_personality_v0 to i8 addrspace(200)*) { +@_ZTIi = external dso_local addrspace(200) constant ptr addrspace(200) +define dso_local noundef signext i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) #0 personality ptr addrspace(200) @__gxx_personality_v0 { ; CHECK-LABEL: _Z8do_catchv: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: cincoffset $c11, $c11, -48 @@ -46,7 +46,7 @@ define dso_local i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) uwtable p ; CHECK-NEXT: # %bb.1: ; CHECK-NEXT: move $16, $2 ; CHECK-NEXT: .LBB0_2: # %return -; CHECK-NEXT: move $2, $16 +; CHECK-NEXT: sll $2, $16, 0 ; CHECK-NEXT: clc $c17, $zero, 0($c11) # 16-byte Folded Reload ; CHECK-NEXT: clc $c18, $zero, 16($c11) # 16-byte Folded Reload ; CHECK-NEXT: cld $16, $zero, 32($c11) # 8-byte Folded Reload @@ -75,27 +75,29 @@ define dso_local i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) uwtable p ; CHECK-NEXT: b .LBB0_2 ; CHECK-NEXT: nop entry: - %call = invoke i32 @_Z3foov() to label %return unwind label %lpad -lpad: - %0 = landingpad { i8 addrspace(200)*, i32 } - catch i8 addrspace(200)* bitcast (i8 addrspace(200)* addrspace(200)* @_ZTIi to i8 addrspace(200)*) - catch i8 addrspace(200)* null - %1 = extractvalue { i8 addrspace(200)*, i32 } %0, 0 - %2 = extractvalue { i8 addrspace(200)*, i32 } %0, 1 - %3 = tail call i32 @llvm.eh.typeid.for(i8* addrspacecast (i8 addrspace(200)* bitcast (i8 addrspace(200)* addrspace(200)* @_ZTIi to i8 addrspace(200)*) to i8*)) + %call = invoke noundef signext i32 @_Z3foov() + to label %return unwind label %lpad + +lpad: ; preds = %entry + %0 = landingpad { ptr addrspace(200), i32 } + catch ptr addrspace(200) @_ZTIi + catch ptr addrspace(200) null + %1 = extractvalue { ptr addrspace(200), i32 } %0, 0 + %2 = extractvalue { ptr addrspace(200), i32 } %0, 1 + %3 = tail call i32 @llvm.eh.typeid.for(ptr addrspacecast (ptr addrspace(200) @_ZTIi to ptr)) nounwind %matches = icmp eq i32 %2, %3 - %4 = tail call i8 addrspace(200)* @__cxa_begin_catch(i8 addrspace(200)* %1) nounwind + %4 = tail call ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200) %1) nounwind br i1 %matches, label %catch1, label %catch -catch1: +catch1: ; preds = %lpad tail call void @__cxa_end_catch() nounwind br label %return -catch: +catch: ; preds = %lpad tail call void @__cxa_end_catch() br label %return -return: +return: ; preds = %entry, %catch1, %catch %retval.0 = phi i32 [ 1, %catch1 ], [ 2, %catch ], [ %call, %entry ] ret i32 %retval.0 } @@ -106,7 +108,7 @@ declare dso_local i32 @__gxx_personality_v0(...) addrspace(200) declare i32 @llvm.eh.typeid.for(i8*) addrspace(200) nounwind readnone -declare dso_local i8 addrspace(200)* @__cxa_begin_catch(i8 addrspace(200)*) local_unnamed_addr addrspace(200) +declare dso_local ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200)) local_unnamed_addr addrspace(200) declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) diff --git a/llvm/test/CodeGen/CHERI-Generic/RISCV32/landingpad-non-preemptible.ll b/llvm/test/CodeGen/CHERI-Generic/RISCV32/landingpad-non-preemptible.ll index 241535ecc0dd..1329d6f50fc9 100644 --- a/llvm/test/CodeGen/CHERI-Generic/RISCV32/landingpad-non-preemptible.ll +++ b/llvm/test/CodeGen/CHERI-Generic/RISCV32/landingpad-non-preemptible.ll @@ -21,8 +21,8 @@ ; CHECK: .type .L_Z8do_catchv$eh_alias,@function ; UTC_ARGS: --enable -@_ZTIi = external dso_local addrspace(200) constant i8 addrspace(200)* -define dso_local i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) uwtable personality i8 addrspace(200)* bitcast (i32 (...) addrspace(200)* @__gxx_personality_v0 to i8 addrspace(200)*) { +@_ZTIi = external dso_local addrspace(200) constant ptr addrspace(200) +define dso_local noundef signext i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) #0 personality ptr addrspace(200) @__gxx_personality_v0 { ; CHECK-LABEL: _Z8do_catchv: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: cincoffset csp, csp, -32 @@ -59,27 +59,29 @@ define dso_local i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) uwtable p ; CHECK-NEXT: ccall __cxa_end_catch ; CHECK-NEXT: j .LBB0_2 entry: - %call = invoke i32 @_Z3foov() to label %return unwind label %lpad -lpad: - %0 = landingpad { i8 addrspace(200)*, i32 } - catch i8 addrspace(200)* bitcast (i8 addrspace(200)* addrspace(200)* @_ZTIi to i8 addrspace(200)*) - catch i8 addrspace(200)* null - %1 = extractvalue { i8 addrspace(200)*, i32 } %0, 0 - %2 = extractvalue { i8 addrspace(200)*, i32 } %0, 1 - %3 = tail call i32 @llvm.eh.typeid.for(i8* addrspacecast (i8 addrspace(200)* bitcast (i8 addrspace(200)* addrspace(200)* @_ZTIi to i8 addrspace(200)*) to i8*)) + %call = invoke noundef signext i32 @_Z3foov() + to label %return unwind label %lpad + +lpad: ; preds = %entry + %0 = landingpad { ptr addrspace(200), i32 } + catch ptr addrspace(200) @_ZTIi + catch ptr addrspace(200) null + %1 = extractvalue { ptr addrspace(200), i32 } %0, 0 + %2 = extractvalue { ptr addrspace(200), i32 } %0, 1 + %3 = tail call i32 @llvm.eh.typeid.for(ptr addrspacecast (ptr addrspace(200) @_ZTIi to ptr)) nounwind %matches = icmp eq i32 %2, %3 - %4 = tail call i8 addrspace(200)* @__cxa_begin_catch(i8 addrspace(200)* %1) nounwind + %4 = tail call ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200) %1) nounwind br i1 %matches, label %catch1, label %catch -catch1: +catch1: ; preds = %lpad tail call void @__cxa_end_catch() nounwind br label %return -catch: +catch: ; preds = %lpad tail call void @__cxa_end_catch() br label %return -return: +return: ; preds = %entry, %catch1, %catch %retval.0 = phi i32 [ 1, %catch1 ], [ 2, %catch ], [ %call, %entry ] ret i32 %retval.0 } @@ -90,7 +92,7 @@ declare dso_local i32 @__gxx_personality_v0(...) addrspace(200) declare i32 @llvm.eh.typeid.for(i8*) addrspace(200) nounwind readnone -declare dso_local i8 addrspace(200)* @__cxa_begin_catch(i8 addrspace(200)*) local_unnamed_addr addrspace(200) +declare dso_local ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200)) local_unnamed_addr addrspace(200) declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) diff --git a/llvm/test/CodeGen/CHERI-Generic/RISCV64/landingpad-non-preemptible.ll b/llvm/test/CodeGen/CHERI-Generic/RISCV64/landingpad-non-preemptible.ll index b88428cecd03..fd9dfa15bb0d 100644 --- a/llvm/test/CodeGen/CHERI-Generic/RISCV64/landingpad-non-preemptible.ll +++ b/llvm/test/CodeGen/CHERI-Generic/RISCV64/landingpad-non-preemptible.ll @@ -21,8 +21,8 @@ ; CHECK: .type .L_Z8do_catchv$eh_alias,@function ; UTC_ARGS: --enable -@_ZTIi = external dso_local addrspace(200) constant i8 addrspace(200)* -define dso_local i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) uwtable personality i8 addrspace(200)* bitcast (i32 (...) addrspace(200)* @__gxx_personality_v0 to i8 addrspace(200)*) { +@_ZTIi = external dso_local addrspace(200) constant ptr addrspace(200) +define dso_local noundef signext i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) #0 personality ptr addrspace(200) @__gxx_personality_v0 { ; CHECK-LABEL: _Z8do_catchv: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: cincoffset csp, csp, -48 @@ -59,27 +59,29 @@ define dso_local i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) uwtable p ; CHECK-NEXT: ccall __cxa_end_catch ; CHECK-NEXT: j .LBB0_2 entry: - %call = invoke i32 @_Z3foov() to label %return unwind label %lpad -lpad: - %0 = landingpad { i8 addrspace(200)*, i32 } - catch i8 addrspace(200)* bitcast (i8 addrspace(200)* addrspace(200)* @_ZTIi to i8 addrspace(200)*) - catch i8 addrspace(200)* null - %1 = extractvalue { i8 addrspace(200)*, i32 } %0, 0 - %2 = extractvalue { i8 addrspace(200)*, i32 } %0, 1 - %3 = tail call i32 @llvm.eh.typeid.for(i8* addrspacecast (i8 addrspace(200)* bitcast (i8 addrspace(200)* addrspace(200)* @_ZTIi to i8 addrspace(200)*) to i8*)) + %call = invoke noundef signext i32 @_Z3foov() + to label %return unwind label %lpad + +lpad: ; preds = %entry + %0 = landingpad { ptr addrspace(200), i32 } + catch ptr addrspace(200) @_ZTIi + catch ptr addrspace(200) null + %1 = extractvalue { ptr addrspace(200), i32 } %0, 0 + %2 = extractvalue { ptr addrspace(200), i32 } %0, 1 + %3 = tail call i32 @llvm.eh.typeid.for(ptr addrspacecast (ptr addrspace(200) @_ZTIi to ptr)) nounwind %matches = icmp eq i32 %2, %3 - %4 = tail call i8 addrspace(200)* @__cxa_begin_catch(i8 addrspace(200)* %1) nounwind + %4 = tail call ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200) %1) nounwind br i1 %matches, label %catch1, label %catch -catch1: +catch1: ; preds = %lpad tail call void @__cxa_end_catch() nounwind br label %return -catch: +catch: ; preds = %lpad tail call void @__cxa_end_catch() br label %return -return: +return: ; preds = %entry, %catch1, %catch %retval.0 = phi i32 [ 1, %catch1 ], [ 2, %catch ], [ %call, %entry ] ret i32 %retval.0 } @@ -90,7 +92,7 @@ declare dso_local i32 @__gxx_personality_v0(...) addrspace(200) declare i32 @llvm.eh.typeid.for(i8*) addrspace(200) nounwind readnone -declare dso_local i8 addrspace(200)* @__cxa_begin_catch(i8 addrspace(200)*) local_unnamed_addr addrspace(200) +declare dso_local ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200)) local_unnamed_addr addrspace(200) declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) From b92e04d6ec0be57c38da2babf400723a2b7663f4 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Tue, 10 Sep 2024 16:39:13 -0700 Subject: [PATCH 3/6] [CHERI] Emit $eh_alias label .type directive in correct location Match the .L$local: approach and emit it after the symbol. --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 19 ++++++++++++------- .../Inputs/landingpad-non-preemptible.ll | 4 ---- .../MIPS/landingpad-non-preemptible.ll | 4 ---- .../RISCV32/landingpad-non-preemptible.ll | 4 ---- .../RISCV64/landingpad-non-preemptible.ll | 4 ---- .../RISCV/cheri/function-start-directives.ll | 2 +- 6 files changed, 13 insertions(+), 24 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 3f2c30e6bc0b..59c4a7ffb64a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -928,9 +928,6 @@ void AsmPrinter::emitFunctionHeader() { if (MAI->hasDotTypeDotSizeDirective()) { OutStreamer->emitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction); - if (CurrentFnBeginForEH) - OutStreamer->emitSymbolAttribute(CurrentFnBeginForEH, - MCSA_ELF_TypeFunction); } if (F.hasFnAttribute(Attribute::Cold)) @@ -1011,14 +1008,22 @@ void AsmPrinter::emitFunctionHeader() { if (MAI->useAssignmentForEHBegin()) { MCSymbol *CurPos = OutContext.createTempSymbol(); OutStreamer->emitLabel(CurPos); - if (CurrentFnBeginForEH) - OutStreamer->emitAssignment(CurrentFnBeginForEH, - MCSymbolRefExpr::create(CurPos, OutContext)); + if (CurrentFnBeginForEH) { + OutStreamer->emitAssignment( + CurrentFnBeginForEH, MCSymbolRefExpr::create(CurPos, OutContext)); + if (MAI->hasDotTypeDotSizeDirective()) + OutStreamer->emitSymbolAttribute(CurrentFnBeginForEH, + MCSA_ELF_TypeFunction); + } OutStreamer->emitAssignment(CurrentFnBegin, MCSymbolRefExpr::create(CurPos, OutContext)); } else { - if (CurrentFnBeginForEH) + if (CurrentFnBeginForEH) { OutStreamer->emitLabel(CurrentFnBeginForEH); + if (MAI->hasDotTypeDotSizeDirective()) + OutStreamer->emitSymbolAttribute(CurrentFnBeginForEH, + MCSA_ELF_TypeFunction); + } OutStreamer->emitLabel(CurrentFnBegin); } } diff --git a/llvm/test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll b/llvm/test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll index 3632154a94a3..187bb9a01d9f 100644 --- a/llvm/test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll +++ b/llvm/test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll @@ -15,10 +15,6 @@ ; } ; } -; UTC_ARGS: --disable -; CHECK: .type .L_Z8do_catchv$eh_alias,@function -; UTC_ARGS: --enable - @_ZTIi = external dso_local addrspace(200) constant ptr addrspace(200) define dso_local noundef signext i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) #0 personality ptr addrspace(200) @__gxx_personality_v0 { entry: diff --git a/llvm/test/CodeGen/CHERI-Generic/MIPS/landingpad-non-preemptible.ll b/llvm/test/CodeGen/CHERI-Generic/MIPS/landingpad-non-preemptible.ll index fc56caaaf147..ac642e3b8c49 100644 --- a/llvm/test/CodeGen/CHERI-Generic/MIPS/landingpad-non-preemptible.ll +++ b/llvm/test/CodeGen/CHERI-Generic/MIPS/landingpad-non-preemptible.ll @@ -17,10 +17,6 @@ ; } ; } -; UTC_ARGS: --disable -; CHECK: .type .L_Z8do_catchv$eh_alias,@function -; UTC_ARGS: --enable - @_ZTIi = external dso_local addrspace(200) constant ptr addrspace(200) define dso_local noundef signext i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) #0 personality ptr addrspace(200) @__gxx_personality_v0 { ; CHECK-LABEL: _Z8do_catchv: diff --git a/llvm/test/CodeGen/CHERI-Generic/RISCV32/landingpad-non-preemptible.ll b/llvm/test/CodeGen/CHERI-Generic/RISCV32/landingpad-non-preemptible.ll index 1329d6f50fc9..817c6feb6abb 100644 --- a/llvm/test/CodeGen/CHERI-Generic/RISCV32/landingpad-non-preemptible.ll +++ b/llvm/test/CodeGen/CHERI-Generic/RISCV32/landingpad-non-preemptible.ll @@ -17,10 +17,6 @@ ; } ; } -; UTC_ARGS: --disable -; CHECK: .type .L_Z8do_catchv$eh_alias,@function -; UTC_ARGS: --enable - @_ZTIi = external dso_local addrspace(200) constant ptr addrspace(200) define dso_local noundef signext i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) #0 personality ptr addrspace(200) @__gxx_personality_v0 { ; CHECK-LABEL: _Z8do_catchv: diff --git a/llvm/test/CodeGen/CHERI-Generic/RISCV64/landingpad-non-preemptible.ll b/llvm/test/CodeGen/CHERI-Generic/RISCV64/landingpad-non-preemptible.ll index fd9dfa15bb0d..bc71946a4fe6 100644 --- a/llvm/test/CodeGen/CHERI-Generic/RISCV64/landingpad-non-preemptible.ll +++ b/llvm/test/CodeGen/CHERI-Generic/RISCV64/landingpad-non-preemptible.ll @@ -17,10 +17,6 @@ ; } ; } -; UTC_ARGS: --disable -; CHECK: .type .L_Z8do_catchv$eh_alias,@function -; UTC_ARGS: --enable - @_ZTIi = external dso_local addrspace(200) constant ptr addrspace(200) define dso_local noundef signext i32 @_Z8do_catchv() local_unnamed_addr addrspace(200) #0 personality ptr addrspace(200) @__gxx_personality_v0 { ; CHECK-LABEL: _Z8do_catchv: diff --git a/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll b/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll index 2f3e5548eb76..4f5fae952aef 100644 --- a/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll +++ b/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll @@ -37,11 +37,11 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; CHECK-NEXT: .globl _Z4testv # -- Begin function _Z4testv ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: .type _Z4testv,@function -; CHECK-NEXT: .type .L_Z4testv$eh_alias,@function ; CHECK-NEXT: _Z4testv: # @_Z4testv ; PIC-NEXT: .L_Z4testv$local: ; PIC-NEXT: .type .L_Z4testv$local,@function ; CHECK-NEXT: .L_Z4testv$eh_alias: +; CHECK-NEXT: .type .L_Z4testv$eh_alias,@function ; CHECK-NEXT: .Lfunc_begin0: ; CHECK-NEXT: .cfi_startproc ; CHECK-NEXT: .cfi_personality 155, DW.ref.__gxx_personality_v0 From fd7d104f7ad641a087180f70312f70d50ffd55ef Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Wed, 11 Sep 2024 13:18:06 -0700 Subject: [PATCH 4/6] [CHERI] Reuse the $local function symbol for landing pads There is no need to define our own non-preemptible local symbol since upstream now has the $local non-preemptible symbol. Since the latest merge it also includes my upstreamed fixes to always have the right type and size attributes, so it is safe to use here. --- lld/test/ELF/cheri/exception-table.cpp | 16 ++++---- llvm/include/llvm/CodeGen/AsmPrinter.h | 10 ++--- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 38 +++++-------------- .../CodeGen/AsmPrinter/AsmPrinterDwarf.cpp | 4 +- llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 2 +- .../Inputs/landingpad-non-preemptible.ll | 14 +++---- .../MIPS/landingpad-non-preemptible.ll | 12 +++--- .../RISCV32/landingpad-non-preemptible.ll | 12 +++--- .../RISCV64/landingpad-non-preemptible.ll | 12 +++--- .../RISCV/cheri/function-start-directives.ll | 15 +++----- llvm/utils/UpdateTestChecks/asm.py | 3 +- 11 files changed, 59 insertions(+), 79 deletions(-) diff --git a/lld/test/ELF/cheri/exception-table.cpp b/lld/test/ELF/cheri/exception-table.cpp index a604bb760052..451a753fb86e 100644 --- a/lld/test/ELF/cheri/exception-table.cpp +++ b/lld/test/ELF/cheri/exception-table.cpp @@ -4,20 +4,20 @@ // RUN: llvm-readobj -r %t-riscv64.o | FileCheck %s --check-prefix=RV64-OBJ-RELOCS /// Should have two relocations against a local alias for _Z4testll // MIPS-OBJ-RELOCS: Section ({{.+}}) .rela.gcc_except_table { -// MIPS-OBJ-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z4testll$eh_alias -// MIPS-OBJ-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z4testll$eh_alias +// MIPS-OBJ-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z4testll$local +// MIPS-OBJ-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z4testll$local // MIPS-OBJ-RELOCS-NEXT: } // RV64-OBJ-RELOCS: Section ({{.+}}) .rela.gcc_except_table { // RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 // RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 // RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 // RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z4testll$eh_alias +// RV64-OBJ-RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z4testll$local // RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 // RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 // RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 // RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z4testll$eh_alias +// RV64-OBJ-RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z4testll$local // RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 // RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 // RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 @@ -73,16 +73,16 @@ /// Local relocations for exception handling: // MIPS-RELOCS-NEXT: CHERI __cap_relocs [ -// MIPS-RELOCS-NEXT: 0x02{{.+}} Base: 0x1{{.+}} (.L_Z4testll$eh_alias+132) Length: 164 Perms: Function -// MIPS-RELOCS-NEXT: 0x02{{.+}} Base: 0x1{{.+}} (.L_Z4testll$eh_alias+100) Length: 164 Perms: Function +// MIPS-RELOCS-NEXT: 0x02{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+132) Length: 164 Perms: Function +// MIPS-RELOCS-NEXT: 0x02{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+100) Length: 164 Perms: Function // MIPS-RELOCS-NEXT: ] /// Should also emit __cap_relocs for RISC-V: // RUN: ld.lld -shared %t-riscv64.o -o %t.so // RUN: llvm-readelf -r --cap-relocs %t.so | FileCheck %s --check-prefixes=RV64-RELOCS // RV64-RELOCS: CHERI __cap_relocs [ -// RV64-RELOCS-NEXT: 0x002{{.+}} Base: 0x1{{.+}} (.L_Z4testll$eh_alias+96) Length: 120 Perms: Function -// RV64-RELOCS-NEXT: 0x002{{.+}} Base: 0x1{{.+}} (.L_Z4testll$eh_alias+72) Length: 120 Perms: Function +// RV64-RELOCS-NEXT: 0x002{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+96) Length: 120 Perms: Function +// RV64-RELOCS-NEXT: 0x002{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+72) Length: 120 Perms: Function // RV64-RELOCS-NEXT: ] long external_fn(long arg); diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h index 9e4dbef0bc21..1103b0c42805 100644 --- a/llvm/include/llvm/CodeGen/AsmPrinter.h +++ b/llvm/include/llvm/CodeGen/AsmPrinter.h @@ -199,11 +199,8 @@ class AsmPrinter : public MachineFunctionPass { protected: MCSymbol *CurrentFnBegin = nullptr; - /// The symbol used to represent the start of the current function for the - /// purpose of exception handling for pure-capability CHERI targets. - MCSymbol *CurrentFnBeginForEH = nullptr; - /// For dso_local functions, the current $local alias for the function. + /// Also used for exception handling for pure-capability CHERI targets. MCSymbol *CurrentFnBeginLocal = nullptr; /// A vector of all debug/EH info emitters we should use. This vector @@ -329,7 +326,10 @@ class AsmPrinter : public MachineFunctionPass { /// Similar to getSymbol() but preferred for references. On ELF, this uses a /// local symbol if a reference to GV is guaranteed to be resolved to the /// definition in the same module. - MCSymbol *getSymbolPreferLocal(const GlobalValue &GV) const; + /// If \p Force is set to true, return a local alias if possible even if the + /// normal heuristics say it is not beneficial. + MCSymbol *getSymbolPreferLocal(const GlobalValue &GV, + bool Force = false) const; bool doesDwarfUseRelocationsAcrossSections() const { return DwarfUsesRelocationsAcrossSections; diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 59c4a7ffb64a..6031e5f61300 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -646,7 +646,8 @@ MCSymbol *AsmPrinter::getSymbol(const GlobalValue *GV) const { return TM.getSymbol(GV); } -MCSymbol *AsmPrinter::getSymbolPreferLocal(const GlobalValue &GV) const { +MCSymbol *AsmPrinter::getSymbolPreferLocal(const GlobalValue &GV, + bool Force) const { // On ELF, use .Lfoo$local if GV is a non-interposable GlobalObject with an // exact definion (intersection of GlobalValue::hasExactDefinition() and // !isInterposable()). These linkages include: external, appending, internal, @@ -656,8 +657,8 @@ MCSymbol *AsmPrinter::getSymbolPreferLocal(const GlobalValue &GV) const { // assumed it. if (TM.getTargetTriple().isOSBinFormatELF() && GV.canBenefitFromLocalAlias()) { const Module &M = *GV.getParent(); - if (TM.getRelocationModel() != Reloc::Static && - M.getPIELevel() == PIELevel::Default && GV.isDSOLocal()) + if (Force || (TM.getRelocationModel() != Reloc::Static && + M.getPIELevel() == PIELevel::Default && GV.isDSOLocal())) return getSymbolWithGlobalValueBase(&GV, "$local"); } return TM.getSymbol(&GV); @@ -1008,22 +1009,9 @@ void AsmPrinter::emitFunctionHeader() { if (MAI->useAssignmentForEHBegin()) { MCSymbol *CurPos = OutContext.createTempSymbol(); OutStreamer->emitLabel(CurPos); - if (CurrentFnBeginForEH) { - OutStreamer->emitAssignment( - CurrentFnBeginForEH, MCSymbolRefExpr::create(CurPos, OutContext)); - if (MAI->hasDotTypeDotSizeDirective()) - OutStreamer->emitSymbolAttribute(CurrentFnBeginForEH, - MCSA_ELF_TypeFunction); - } OutStreamer->emitAssignment(CurrentFnBegin, MCSymbolRefExpr::create(CurPos, OutContext)); } else { - if (CurrentFnBeginForEH) { - OutStreamer->emitLabel(CurrentFnBeginForEH); - if (MAI->hasDotTypeDotSizeDirective()) - OutStreamer->emitSymbolAttribute(CurrentFnBeginForEH, - MCSA_ELF_TypeFunction); - } OutStreamer->emitLabel(CurrentFnBegin); } } @@ -1063,6 +1051,8 @@ void AsmPrinter::emitFunctionHeader() { } } +static bool needFuncLabelsForEH(const MachineFunction &MF); + /// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the /// function. This can be overridden by targets as required to do custom stuff. void AsmPrinter::emitFunctionEntryLabel() { @@ -1077,7 +1067,10 @@ void AsmPrinter::emitFunctionEntryLabel() { OutStreamer->emitLabel(CurrentFnSym); if (TM.getTargetTriple().isOSBinFormatELF()) { - MCSymbol *Sym = getSymbolPreferLocal(MF->getFunction()); + // For CHERI purecap exception handling, we always have to use a local + // alias even if the function is not dso_local. + bool ForceLocal = MAI->isCheriPurecapABI() && needFuncLabelsForEH(*MF); + MCSymbol *Sym = getSymbolPreferLocal(MF->getFunction(), ForceLocal); if (Sym != CurrentFnSym) { cast(Sym)->setType(ELF::STT_FUNC); CurrentFnBeginLocal = Sym; @@ -1850,8 +1843,6 @@ void AsmPrinter::emitFunctionBody() { MCSymbolRefExpr::create(CurrentFnEnd, OutContext), MCSymbolRefExpr::create(CurrentFnSymForSize, OutContext), OutContext); OutStreamer->emitELFSize(CurrentFnSym, SizeExp); - if (CurrentFnBeginForEH) - OutStreamer->emitELFSize(CurrentFnBeginForEH, SizeExp); if (CurrentFnBeginLocal) OutStreamer->emitELFSize(CurrentFnBeginLocal, SizeExp); } @@ -2430,7 +2421,6 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { CurrentFnSymForSize = CurrentFnSym; CurrentFnBegin = nullptr; - CurrentFnBeginForEH = nullptr; CurrentFnBeginLocal = nullptr; CurrentSectionBeginSym = nullptr; MBBSectionRanges.clear(); @@ -2444,14 +2434,6 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) { CurrentFnBegin = createTempSymbol("func_begin"); if (NeedsLocalForSize) CurrentFnSymForSize = CurrentFnBegin; - // In the pure-capability ABI we have to create dynamic relocations for the - // landing pads. To avoid creating an (unnecessary and incorrect) dynamic - // relocation with a non-zero addend, we need to ensure that the target - // symbol is non-preemptible by creating a local alias for the function. - // See https://github.com/CTSRD-CHERI/llvm-project/issues/512. - // TODO: could probably omit this for !F.isInterposable()? - if (MAI->isCheriPurecapABI() && needFuncLabelsForEH(MF)) - CurrentFnBeginForEH = getSymbolWithGlobalValueBase(&F, "$eh_alias"); } ORE = &getAnalysis().getORE(); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index a84dbc91789b..48fdd7076c4f 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -236,8 +236,8 @@ void AsmPrinter::emitCallSiteCheriCapability(const MCSymbol *Hi, // this would result in EmitCheriCapability() creating a relocation against // section plus offset rather than function + offset. We need the right // bounds and permissions info and need to use a non-preemptible alias. - assert(CurrentFnBeginForEH && "Missing local function entry alias for EH!"); - OutStreamer->EmitCheriCapability(CurrentFnBeginForEH, DiffToStart, + assert(CurrentFnBeginLocal && "Missing local function entry alias for EH!"); + OutStreamer->EmitCheriCapability(CurrentFnBeginLocal, DiffToStart, TLOF.getCheriCapabilitySize(TM)); } diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index 4e9c63728432..1373e1144b20 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -428,7 +428,7 @@ void MipsAsmPrinter::emitFunctionEntryLabel() { TS.emitDirectiveSetNoMips16(); TS.emitDirectiveEnt(*CurrentFnSym); - OutStreamer->emitLabel(CurrentFnSym); + AsmPrinter::emitFunctionEntryLabel(); } /// EmitFunctionBodyStart - Targets can override this to emit stuff before diff --git a/llvm/test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll b/llvm/test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll index 187bb9a01d9f..d916394a5b40 100644 --- a/llvm/test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll +++ b/llvm/test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll @@ -1,5 +1,5 @@ -; RUN: llc @PURECAP_HARDFLOAT_ARGS@ < %s -o - | FileCheck %s -; RUN: llc @PURECAP_HARDFLOAT_ARGS@ < %s -o - -filetype=obj | llvm-readobj --relocs --symbols - | FileCheck %s --check-prefix=RELOCS +; RUN: llc @PURECAP_HARDFLOAT_ARGS@ --relocation-model=pic < %s -o - | FileCheck %s +; RUN: llc @PURECAP_HARDFLOAT_ARGS@ --relocation-model=pic < %s -o - -filetype=obj | llvm-readobj --relocs --symbols - | FileCheck %s --check-prefix=RELOCS ; Capabilities for exception landing pads were using preemptible relocations such as ; .chericap foo + .Ltmp - .Lfunc_begin instead of using a local alias. ; https://github.com/CTSRD-CHERI/llvm-project/issues/512 @@ -58,7 +58,7 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; UTC_ARGS: --disable ; CHECK: .Lfunc_end0: ; CHECK-NEXT: .size _Z8do_catchv, .Lfunc_end0-_Z8do_catchv -; CHECK-NEXT: .size .L_Z8do_catchv$eh_alias, .Lfunc_end0-_Z8do_catchv +; CHECK-NEXT: .size .L_Z8do_catchv$local, .Lfunc_end0-_Z8do_catchv ; CHECK: GCC_except_table0: ; CHECK-NEXT: .Lexception0: @@ -76,7 +76,7 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; Note: RISC-V uses DW_EH_PE_udata4, so the 0xc marker uses 4 bytes instead of 1 ; CHECK-NEXT: [[SMALL_CS_DIRECTIVE:(\.byte)|(\.word)]] 12 # (landing pad is a capability) ; Note: the following line should not be using _Z8do_catchv, but a local alias -; CHECK-NEXT: .chericap .L_Z8do_catchv$eh_alias + .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2 +; CHECK-NEXT: .chericap .L_Z8do_catchv$local + .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2 ; CHECK-NEXT: .byte 3 # On action: 2 ; CHECK-NEXT: [[CS_DIRECTIVE]] .Ltmp1-.Lfunc_begin0 # >> Call Site 2 << ; CHECK-NEXT: [[CS_DIRECTIVE]] .Lfunc_end0-.Ltmp1 # Call between .Ltmp1 and .Lfunc_end0 @@ -103,13 +103,13 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; RELOCS-LABEL: Relocations [ ; RELOCS-LABEL: Section ({{.+}}) .rela.gcc_except_table { -@IF-MIPS@; RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z8do_catchv$eh_alias 0x4C +@IF-MIPS@; RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z8do_catchv$local 0x4C @IF-MIPS@; RELOCS-NEXT: R_MIPS_PC32/R_MIPS_NONE/R_MIPS_NONE .L_ZTIi.DW.stub 0x0 @IF-RISCV@; RELOCS-NEXT: R_RISCV_ADD32 - 0x0 @IF-RISCV@; RELOCS-NEXT: R_RISCV_SUB32 - 0x0 @IF-RISCV@; RELOCS-NEXT: R_RISCV_ADD32 - 0x0 @IF-RISCV@; RELOCS-NEXT: R_RISCV_SUB32 - 0x0 -@IF-RISCV@; RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z8do_catchv$eh_alias 0x34 +@IF-RISCV@; RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z8do_catchv$local 0x34 @IF-RISCV@; RELOCS-NEXT: R_RISCV_ADD32 - 0x0 @IF-RISCV@; RELOCS-NEXT: R_RISCV_SUB32 - 0x0 @IF-RISCV@; RELOCS-NEXT: R_RISCV_ADD32 - 0x0 @@ -119,7 +119,7 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; The local alias should have the same type and non-zero size as the real function: ; RELOCS: Symbol { -; RELOCS-LABEL: Name: .L_Z8do_catchv$eh_alias ( +; RELOCS-LABEL: Name: .L_Z8do_catchv$local ( ; RELOCS-NEXT: Value: 0x0 ; RELOCS-NEXT: Size: [[FN_SIZE:[1-9][0-9]*]] ; RELOCS-NEXT: Binding: Local (0x0) diff --git a/llvm/test/CodeGen/CHERI-Generic/MIPS/landingpad-non-preemptible.ll b/llvm/test/CodeGen/CHERI-Generic/MIPS/landingpad-non-preemptible.ll index ac642e3b8c49..9b0d6d6ccd70 100644 --- a/llvm/test/CodeGen/CHERI-Generic/MIPS/landingpad-non-preemptible.ll +++ b/llvm/test/CodeGen/CHERI-Generic/MIPS/landingpad-non-preemptible.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes ; DO NOT EDIT -- This file was generated from test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll -; RUN: llc -mtriple=mips64 -mcpu=cheri128 -mattr=+cheri128 --relocation-model=pic -target-abi purecap < %s -o - | FileCheck %s -; RUN: llc -mtriple=mips64 -mcpu=cheri128 -mattr=+cheri128 --relocation-model=pic -target-abi purecap < %s -o - -filetype=obj | llvm-readobj --relocs --symbols - | FileCheck %s --check-prefix=RELOCS +; RUN: llc -mtriple=mips64 -mcpu=cheri128 -mattr=+cheri128 --relocation-model=pic -target-abi purecap --relocation-model=pic < %s -o - | FileCheck %s +; RUN: llc -mtriple=mips64 -mcpu=cheri128 -mattr=+cheri128 --relocation-model=pic -target-abi purecap --relocation-model=pic < %s -o - -filetype=obj | llvm-readobj --relocs --symbols - | FileCheck %s --check-prefix=RELOCS ; Capabilities for exception landing pads were using preemptible relocations such as ; .chericap foo + .Ltmp - .Lfunc_begin instead of using a local alias. ; https://github.com/CTSRD-CHERI/llvm-project/issues/512 @@ -111,7 +111,7 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; UTC_ARGS: --disable ; CHECK: .Lfunc_end0: ; CHECK-NEXT: .size _Z8do_catchv, .Lfunc_end0-_Z8do_catchv -; CHECK-NEXT: .size .L_Z8do_catchv$eh_alias, .Lfunc_end0-_Z8do_catchv +; CHECK-NEXT: .size .L_Z8do_catchv$local, .Lfunc_end0-_Z8do_catchv ; CHECK: GCC_except_table0: ; CHECK-NEXT: .Lexception0: @@ -128,7 +128,7 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; Note: RISC-V uses DW_EH_PE_udata4, so the 0xc marker uses 4 bytes instead of 1 ; CHECK-NEXT: [[SMALL_CS_DIRECTIVE:(\.byte)|(\.word)]] 12 # (landing pad is a capability) ; Note: the following line should not be using _Z8do_catchv, but a local alias -; CHECK-NEXT: .chericap .L_Z8do_catchv$eh_alias + .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2 +; CHECK-NEXT: .chericap .L_Z8do_catchv$local + .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2 ; CHECK-NEXT: .byte 3 # On action: 2 ; CHECK-NEXT: [[CS_DIRECTIVE]] .Ltmp1-.Lfunc_begin0 # >> Call Site 2 << ; CHECK-NEXT: [[CS_DIRECTIVE]] .Lfunc_end0-.Ltmp1 # Call between .Ltmp1 and .Lfunc_end0 @@ -155,13 +155,13 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; RELOCS-LABEL: Relocations [ ; RELOCS-LABEL: Section ({{.+}}) .rela.gcc_except_table { -; RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z8do_catchv$eh_alias 0x4C +; RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z8do_catchv$local 0x4C ; RELOCS-NEXT: R_MIPS_PC32/R_MIPS_NONE/R_MIPS_NONE .L_ZTIi.DW.stub 0x0 ; RELOCS-NEXT: } ; The local alias should have the same type and non-zero size as the real function: ; RELOCS: Symbol { -; RELOCS-LABEL: Name: .L_Z8do_catchv$eh_alias ( +; RELOCS-LABEL: Name: .L_Z8do_catchv$local ( ; RELOCS-NEXT: Value: 0x0 ; RELOCS-NEXT: Size: [[FN_SIZE:[1-9][0-9]*]] ; RELOCS-NEXT: Binding: Local (0x0) diff --git a/llvm/test/CodeGen/CHERI-Generic/RISCV32/landingpad-non-preemptible.ll b/llvm/test/CodeGen/CHERI-Generic/RISCV32/landingpad-non-preemptible.ll index 817c6feb6abb..03440ca884bd 100644 --- a/llvm/test/CodeGen/CHERI-Generic/RISCV32/landingpad-non-preemptible.ll +++ b/llvm/test/CodeGen/CHERI-Generic/RISCV32/landingpad-non-preemptible.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes ; DO NOT EDIT -- This file was generated from test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll -; RUN: llc -mtriple=riscv32 --relocation-model=pic -target-abi il32pc64f -mattr=+xcheri,+cap-mode,+f < %s -o - | FileCheck %s -; RUN: llc -mtriple=riscv32 --relocation-model=pic -target-abi il32pc64f -mattr=+xcheri,+cap-mode,+f < %s -o - -filetype=obj | llvm-readobj --relocs --symbols - | FileCheck %s --check-prefix=RELOCS +; RUN: llc -mtriple=riscv32 --relocation-model=pic -target-abi il32pc64f -mattr=+xcheri,+cap-mode,+f --relocation-model=pic < %s -o - | FileCheck %s +; RUN: llc -mtriple=riscv32 --relocation-model=pic -target-abi il32pc64f -mattr=+xcheri,+cap-mode,+f --relocation-model=pic < %s -o - -filetype=obj | llvm-readobj --relocs --symbols - | FileCheck %s --check-prefix=RELOCS ; Capabilities for exception landing pads were using preemptible relocations such as ; .chericap foo + .Ltmp - .Lfunc_begin instead of using a local alias. ; https://github.com/CTSRD-CHERI/llvm-project/issues/512 @@ -95,7 +95,7 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; UTC_ARGS: --disable ; CHECK: .Lfunc_end0: ; CHECK-NEXT: .size _Z8do_catchv, .Lfunc_end0-_Z8do_catchv -; CHECK-NEXT: .size .L_Z8do_catchv$eh_alias, .Lfunc_end0-_Z8do_catchv +; CHECK-NEXT: .size .L_Z8do_catchv$local, .Lfunc_end0-_Z8do_catchv ; CHECK: GCC_except_table0: ; CHECK-NEXT: .Lexception0: @@ -112,7 +112,7 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; Note: RISC-V uses DW_EH_PE_udata4, so the 0xc marker uses 4 bytes instead of 1 ; CHECK-NEXT: [[SMALL_CS_DIRECTIVE:(\.byte)|(\.word)]] 12 # (landing pad is a capability) ; Note: the following line should not be using _Z8do_catchv, but a local alias -; CHECK-NEXT: .chericap .L_Z8do_catchv$eh_alias + .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2 +; CHECK-NEXT: .chericap .L_Z8do_catchv$local + .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2 ; CHECK-NEXT: .byte 3 # On action: 2 ; CHECK-NEXT: [[CS_DIRECTIVE]] .Ltmp1-.Lfunc_begin0 # >> Call Site 2 << ; CHECK-NEXT: [[CS_DIRECTIVE]] .Lfunc_end0-.Ltmp1 # Call between .Ltmp1 and .Lfunc_end0 @@ -143,7 +143,7 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; RELOCS-NEXT: R_RISCV_SUB32 - 0x0 ; RELOCS-NEXT: R_RISCV_ADD32 - 0x0 ; RELOCS-NEXT: R_RISCV_SUB32 - 0x0 -; RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z8do_catchv$eh_alias 0x34 +; RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z8do_catchv$local 0x34 ; RELOCS-NEXT: R_RISCV_ADD32 - 0x0 ; RELOCS-NEXT: R_RISCV_SUB32 - 0x0 ; RELOCS-NEXT: R_RISCV_ADD32 - 0x0 @@ -153,7 +153,7 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; The local alias should have the same type and non-zero size as the real function: ; RELOCS: Symbol { -; RELOCS-LABEL: Name: .L_Z8do_catchv$eh_alias ( +; RELOCS-LABEL: Name: .L_Z8do_catchv$local ( ; RELOCS-NEXT: Value: 0x0 ; RELOCS-NEXT: Size: [[FN_SIZE:[1-9][0-9]*]] ; RELOCS-NEXT: Binding: Local (0x0) diff --git a/llvm/test/CodeGen/CHERI-Generic/RISCV64/landingpad-non-preemptible.ll b/llvm/test/CodeGen/CHERI-Generic/RISCV64/landingpad-non-preemptible.ll index bc71946a4fe6..5f3adda5e789 100644 --- a/llvm/test/CodeGen/CHERI-Generic/RISCV64/landingpad-non-preemptible.ll +++ b/llvm/test/CodeGen/CHERI-Generic/RISCV64/landingpad-non-preemptible.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes ; DO NOT EDIT -- This file was generated from test/CodeGen/CHERI-Generic/Inputs/landingpad-non-preemptible.ll -; RUN: llc -mtriple=riscv64 --relocation-model=pic -target-abi l64pc128d -mattr=+xcheri,+cap-mode,+f,+d < %s -o - | FileCheck %s -; RUN: llc -mtriple=riscv64 --relocation-model=pic -target-abi l64pc128d -mattr=+xcheri,+cap-mode,+f,+d < %s -o - -filetype=obj | llvm-readobj --relocs --symbols - | FileCheck %s --check-prefix=RELOCS +; RUN: llc -mtriple=riscv64 --relocation-model=pic -target-abi l64pc128d -mattr=+xcheri,+cap-mode,+f,+d --relocation-model=pic < %s -o - | FileCheck %s +; RUN: llc -mtriple=riscv64 --relocation-model=pic -target-abi l64pc128d -mattr=+xcheri,+cap-mode,+f,+d --relocation-model=pic < %s -o - -filetype=obj | llvm-readobj --relocs --symbols - | FileCheck %s --check-prefix=RELOCS ; Capabilities for exception landing pads were using preemptible relocations such as ; .chericap foo + .Ltmp - .Lfunc_begin instead of using a local alias. ; https://github.com/CTSRD-CHERI/llvm-project/issues/512 @@ -95,7 +95,7 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; UTC_ARGS: --disable ; CHECK: .Lfunc_end0: ; CHECK-NEXT: .size _Z8do_catchv, .Lfunc_end0-_Z8do_catchv -; CHECK-NEXT: .size .L_Z8do_catchv$eh_alias, .Lfunc_end0-_Z8do_catchv +; CHECK-NEXT: .size .L_Z8do_catchv$local, .Lfunc_end0-_Z8do_catchv ; CHECK: GCC_except_table0: ; CHECK-NEXT: .Lexception0: @@ -112,7 +112,7 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; Note: RISC-V uses DW_EH_PE_udata4, so the 0xc marker uses 4 bytes instead of 1 ; CHECK-NEXT: [[SMALL_CS_DIRECTIVE:(\.byte)|(\.word)]] 12 # (landing pad is a capability) ; Note: the following line should not be using _Z8do_catchv, but a local alias -; CHECK-NEXT: .chericap .L_Z8do_catchv$eh_alias + .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2 +; CHECK-NEXT: .chericap .L_Z8do_catchv$local + .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2 ; CHECK-NEXT: .byte 3 # On action: 2 ; CHECK-NEXT: [[CS_DIRECTIVE]] .Ltmp1-.Lfunc_begin0 # >> Call Site 2 << ; CHECK-NEXT: [[CS_DIRECTIVE]] .Lfunc_end0-.Ltmp1 # Call between .Ltmp1 and .Lfunc_end0 @@ -143,7 +143,7 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; RELOCS-NEXT: R_RISCV_SUB32 - 0x0 ; RELOCS-NEXT: R_RISCV_ADD32 - 0x0 ; RELOCS-NEXT: R_RISCV_SUB32 - 0x0 -; RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z8do_catchv$eh_alias 0x34 +; RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z8do_catchv$local 0x34 ; RELOCS-NEXT: R_RISCV_ADD32 - 0x0 ; RELOCS-NEXT: R_RISCV_SUB32 - 0x0 ; RELOCS-NEXT: R_RISCV_ADD32 - 0x0 @@ -153,7 +153,7 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; The local alias should have the same type and non-zero size as the real function: ; RELOCS: Symbol { -; RELOCS-LABEL: Name: .L_Z8do_catchv$eh_alias ( +; RELOCS-LABEL: Name: .L_Z8do_catchv$local ( ; RELOCS-NEXT: Value: 0x0 ; RELOCS-NEXT: Size: [[FN_SIZE:[1-9][0-9]*]] ; RELOCS-NEXT: Binding: Local (0x0) diff --git a/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll b/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll index 4f5fae952aef..c91c12c537db 100644 --- a/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll +++ b/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll @@ -1,6 +1,6 @@ ;; Check that the directives at the start of the function are emitted in a sensible order -; RUN: %riscv64_cheri_purecap_llc -relocation-model=pic < %s | FileCheck %s --check-prefixes=PIC,CHECK -; RUN: %riscv64_cheri_purecap_llc -relocation-model=static < %s | FileCheck %s --check-prefixes=CHECK +; RUN: %riscv64_cheri_purecap_llc -relocation-model=pic < %s | FileCheck %s +; RUN: %riscv64_cheri_purecap_llc -relocation-model=static < %s | FileCheck %s target triple = "riscv64-unknown-freebsd13" @@ -38,10 +38,8 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: .type _Z4testv,@function ; CHECK-NEXT: _Z4testv: # @_Z4testv -; PIC-NEXT: .L_Z4testv$local: -; PIC-NEXT: .type .L_Z4testv$local,@function -; CHECK-NEXT: .L_Z4testv$eh_alias: -; CHECK-NEXT: .type .L_Z4testv$eh_alias,@function +; CHECK-NEXT: .L_Z4testv$local: +; CHECK-NEXT: .type .L_Z4testv$local,@function ; CHECK-NEXT: .Lfunc_begin0: ; CHECK-NEXT: .cfi_startproc ; CHECK-NEXT: .cfi_personality 155, DW.ref.__gxx_personality_v0 @@ -50,10 +48,9 @@ declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) ; CHECK: .Lfunc_end0: ; CHECK-NEXT: .size _Z4testv, .Lfunc_end0-_Z4testv -; CHECK-NEXT: .size .L_Z4testv$eh_alias, .Lfunc_end0-_Z4testv -; PIC-NEXT: .size .L_Z4testv$local, .Lfunc_end0-_Z4testv +; CHECK-NEXT: .size .L_Z4testv$local, .Lfunc_end0-_Z4testv ; CHECK-NEXT: .cfi_endproc ; CHECK: .section .gcc_except_table ; CHECK: .word 12 # (landing pad is a capability) -; CHECK-NEXT: .chericap .L_Z4testv$eh_alias + .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2 +; CHECK-NEXT: .chericap .L_Z4testv$local + .Ltmp2-.Lfunc_begin0 # jumps to .Ltmp2 diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py index 102afdc6a980..1fda18f69f66 100644 --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -69,6 +69,8 @@ class string: ASM_FUNCTION_MIPS_RE = re.compile( r'^_?(?P[^:]+):[ \t]*#+[ \t]*@"?(?P=func)"?\n[^:]*?' # f: (name of func) + r'(?:\s*\.?L(?P=func)\$local:\n)?' # optional .L$local: due to -fno-semantic-interposition + r'(?:\s*\.type\s+\.?L(?P=func)\$local,@function\n)?' # optional .type .L$local r'(?:\s*\.?Ltmp[^:\n]*:\n)?[^:]*?' # optional .Ltmp for EH r'(?:^[ \t]+\.(frame|f?mask|set).*?\n)+' # Mips+LLVM standard asm prologue r'(?P.*?)\n' # (body of the function) @@ -103,7 +105,6 @@ class string: ASM_FUNCTION_RISCV_RE = re.compile( r'^_?(?P[^:]+):[ \t]*#+[ \t]*@"?(?P=func)"?\n' - r'(?:\s*\.?L(?P=func)\$eh_alias:\n)?' # optional .L$eh_alias: due to CHERI EH r'(?:\s*\.?L(?P=func)\$jump_table_base:\n)?' # optional .L$jump_table_base: due to CHERI jump tables r'(?:\s*\.?L(?P=func)\$local:\n)?' # optional .L$local: due to -fno-semantic-interposition r'(?:\s*\.type\s+\.?L(?P=func)\$local,@function\n)?' # optional .type .L$local From 6205600f0c2a36222ddf52fc4e3c7fecea061bfc Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Wed, 11 Sep 2024 15:01:58 -0700 Subject: [PATCH 5/6] [ELF][CHERI] Rewrite exception-table test in LLVM IR This avoids one dependency on clang and will hopefully allow removing it entirely soon. Ideally this would be written as an assembly test but adding the right directives for EH tables is tedious, so I went for IR instead. --- lld/test/ELF/cheri/exception-table.cpp | 104 ------------ lld/test/ELF/cheri/exception-table.ll | 215 +++++++++++++++++++++++++ lld/test/ELF/cheri/lit.local.cfg | 3 +- 3 files changed, 217 insertions(+), 105 deletions(-) delete mode 100644 lld/test/ELF/cheri/exception-table.cpp create mode 100644 lld/test/ELF/cheri/exception-table.ll diff --git a/lld/test/ELF/cheri/exception-table.cpp b/lld/test/ELF/cheri/exception-table.cpp deleted file mode 100644 index 451a753fb86e..000000000000 --- a/lld/test/ELF/cheri/exception-table.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// RUN: %cheri_purecap_cc1 -O2 -mframe-pointer=none -fcxx-exceptions -fexceptions %s -emit-obj -o %t.o -// RUN: llvm-readobj -r %t.o | FileCheck %s --check-prefix=MIPS-OBJ-RELOCS -// RUN: %riscv64_cheri_purecap_cc1 -O2 -mframe-pointer=none -fcxx-exceptions -fexceptions %s -emit-obj -o %t-riscv64.o -// RUN: llvm-readobj -r %t-riscv64.o | FileCheck %s --check-prefix=RV64-OBJ-RELOCS -/// Should have two relocations against a local alias for _Z4testll -// MIPS-OBJ-RELOCS: Section ({{.+}}) .rela.gcc_except_table { -// MIPS-OBJ-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z4testll$local -// MIPS-OBJ-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z4testll$local -// MIPS-OBJ-RELOCS-NEXT: } -// RV64-OBJ-RELOCS: Section ({{.+}}) .rela.gcc_except_table { -// RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z4testll$local -// RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z4testll$local -// RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 -// RV64-OBJ-RELOCS-NEXT: } - -/// This should work with both -z text and -z notext -/// Check that .gcc_except_table ends up in the relro section and the relocations are correct -// RUN: ld.lld -shared %t.o -o %t.so -z notext -// RUN: llvm-readelf -r --section-mapping --sections --program-headers --cap-relocs %t.so | FileCheck %s --check-prefixes=HEADERS,MIPS-RELOCS -// RUN: ld.lld -shared %t.o -o %t.so -z text -// RUN: llvm-readelf -r --section-mapping %t.so -// RUN: llvm-readelf -r --section-mapping --sections --program-headers --cap-relocs %t.so | FileCheck %s --check-prefixes=HEADERS,MIPS-RELOCS - -// HEADERS-LABEL: There are 10 program headers, starting at -// HEADERS-EMPTY: -// HEADERS-NEXT: Program Headers: -// HEADERS-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align -// HEADERS-NEXT: PHDR 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x8 -// HEADERS-NEXT: LOAD 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x10000 -// HEADERS-NEXT: LOAD 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R E 0x10000 -// HEADERS-NEXT: LOAD 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} RW 0x10000 -// HEADERS-NEXT: LOAD 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} RW 0x10000 -// HEADERS-NEXT: DYNAMIC 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x8 -// HEADERS-NEXT: GNU_RELRO 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x1 -// HEADERS-NEXT: GNU_STACK 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} RW 0x0 -// HEADERS-NEXT: OPTIONS 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x8 -// HEADERS-NEXT: ABIFLAGS 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x8 -// HEADERS-EMPTY: -// HEADERS-NEXT: Section to Segment mapping: -// HEADERS-NEXT: Segment Sections... -// HEADERS-NEXT: 00 -// HEADERS-NEXT: 01 .MIPS.abiflags .MIPS.options .dynsym .hash .dynamic .dynstr .rel.dyn .rel.plt .eh_frame __cap_relocs {{$}} -// HEADERS-NEXT: 02 .text -// HEADERS-NEXT: 03 .gcc_except_table -// HEADERS-NEXT: 04 .data .captable .got -// HEADERS-NEXT: 05 .dynamic -// HEADERS-NEXT: 06 .gcc_except_table -// HEADERS-NEXT: 07 -// HEADERS-NEXT: 08 .MIPS.options -// HEADERS-NEXT: 09 .MIPS.abiflags -// HEADERS-NEXT: None .bss .mdebug.abi64 .pdr .comment .symtab .shstrtab .strtab - -// MIPS-RELOCS-LABEL: Relocation section '.rel.dyn' {{.+}} contains 1 entries: -// MIPS-RELOCS-NEXT: Offset Info Type Symbol's Value Symbol's Name -// MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 __gxx_personality_v0 -// MIPS-RELOCS-EMPTY: -// MIPS-RELOCS-NEXT: Relocation section '.rel.plt' at offset {{.+}} contains 3 entries: -// MIPS-RELOCS-NEXT: Offset Info Type Symbol's Value Symbol's Name -// MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY_CALL/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 _Z11external_fnl -// MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY_CALL/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 __cxa_begin_catch -// MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY_CALL/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 __cxa_end_catch - -/// Local relocations for exception handling: -// MIPS-RELOCS-NEXT: CHERI __cap_relocs [ -// MIPS-RELOCS-NEXT: 0x02{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+132) Length: 164 Perms: Function -// MIPS-RELOCS-NEXT: 0x02{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+100) Length: 164 Perms: Function -// MIPS-RELOCS-NEXT: ] - -/// Should also emit __cap_relocs for RISC-V: -// RUN: ld.lld -shared %t-riscv64.o -o %t.so -// RUN: llvm-readelf -r --cap-relocs %t.so | FileCheck %s --check-prefixes=RV64-RELOCS -// RV64-RELOCS: CHERI __cap_relocs [ -// RV64-RELOCS-NEXT: 0x002{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+96) Length: 120 Perms: Function -// RV64-RELOCS-NEXT: 0x002{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+72) Length: 120 Perms: Function -// RV64-RELOCS-NEXT: ] - -long external_fn(long arg); - -long test(long arg, long arg2) { - int a = 0; - int b = 0; - try { - a = external_fn(arg); - } catch (...) { - return -1; - } - try { - b = external_fn(arg2); - } catch (...) { - return a; - } - return a + b; -} diff --git a/lld/test/ELF/cheri/exception-table.ll b/lld/test/ELF/cheri/exception-table.ll new file mode 100644 index 000000000000..e1cce9d9c35c --- /dev/null +++ b/lld/test/ELF/cheri/exception-table.ll @@ -0,0 +1,215 @@ +; RUN: %cheri_purecap_llc --relocation-model=pic < %s -filetype=obj -o %t.o +; RUN: llvm-readobj -r %t.o | FileCheck %s --check-prefix=MIPS-OBJ-RELOCS +; RUN: %riscv64_cheri_purecap_llc --relocation-model=pic < %s -filetype=obj -o %t-riscv64.o +; RUN: llvm-readobj -r %t-riscv64.o | FileCheck %s --check-prefix=RV64-OBJ-RELOCS +;; Should have two relocations against a local alias for _Z4testll +; MIPS-OBJ-RELOCS: Section ({{.+}}) .rela.gcc_except_table { +; MIPS-OBJ-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z4testll$local 0x80 +; MIPS-OBJ-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z4testll$local 0x60 +; MIPS-OBJ-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE .L_Z5test2ll$local 0x60 +; MIPS-OBJ-RELOCS-NEXT: R_MIPS_PC32/R_MIPS_NONE/R_MIPS_NONE .L_ZTIl.DW.stub 0x0 +; MIPS-OBJ-RELOCS-NEXT: } +; RV64-OBJ-RELOCS: Section ({{.+}}) .rela.gcc_except_table { +; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z4testll$local 0x5C +; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z4testll$local 0x48 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_CHERI_CAPABILITY .L_Z5test2ll$local 0x48 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_ADD32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_SUB32 - 0x0 +; RV64-OBJ-RELOCS-NEXT: R_RISCV_32_PCREL .L_ZTIl.DW.stub 0x0 +; RV64-OBJ-RELOCS-NEXT: } + +;; This should work with both -z text and -z notext +;; Check that .gcc_except_table ends up in the relro section and the relocations are correct +; RUN: ld.lld -shared %t.o -o %t.so -z notext +; RUN: llvm-readelf -r --section-mapping --sections --program-headers --cap-relocs %t.so | FileCheck %s --check-prefixes=HEADERS,MIPS-RELOCS +; RUN: ld.lld -shared %t.o -o %t.so -z text +; RUN: llvm-readelf -r --section-mapping %t.so +; RUN: llvm-readelf -r --section-mapping --sections --program-headers --cap-relocs %t.so | FileCheck %s --check-prefixes=HEADERS,MIPS-RELOCS + +; HEADERS-LABEL: There are 10 program headers, starting at +; HEADERS-EMPTY: +; HEADERS-NEXT: Program Headers: +; HEADERS-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align +; HEADERS-NEXT: PHDR 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x8 +; HEADERS-NEXT: LOAD 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x10000 +; HEADERS-NEXT: LOAD 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R E 0x10000 +; HEADERS-NEXT: LOAD 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} RW 0x10000 +; HEADERS-NEXT: LOAD 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} RW 0x10000 +; HEADERS-NEXT: DYNAMIC 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x8 +; HEADERS-NEXT: GNU_RELRO 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x1 +; HEADERS-NEXT: GNU_STACK 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} RW 0x0 +; HEADERS-NEXT: OPTIONS 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x8 +; HEADERS-NEXT: ABIFLAGS 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} 0x{{.+}} R 0x8 +; HEADERS-EMPTY: +; HEADERS-NEXT: Section to Segment mapping: +; HEADERS-NEXT: Segment Sections... +; HEADERS-NEXT: 00 +; HEADERS-NEXT: 01 .MIPS.abiflags .MIPS.options .dynsym .hash .dynamic .dynstr .rel.dyn .rel.plt .eh_frame __cap_relocs {{$}} +; HEADERS-NEXT: 02 .text +; HEADERS-NEXT: 03 .gcc_except_table +; HEADERS-NEXT: 04 .data .captable .got +; HEADERS-NEXT: 05 .dynamic +; HEADERS-NEXT: 06 .gcc_except_table +; HEADERS-NEXT: 07 +; HEADERS-NEXT: 08 .MIPS.options +; HEADERS-NEXT: 09 .MIPS.abiflags +; HEADERS-NEXT: None .bss .mdebug.abi64 .pdr .comment .symtab .shstrtab .strtab + +; MIPS-RELOCS-LABEL: Relocation section '.rel.dyn' {{.+}} contains 2 entries: +; MIPS-RELOCS-NEXT: Offset Info Type Symbol's Value Symbol's Name +; MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 _ZTIl +; MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 __gxx_personality_v0 +; MIPS-RELOCS-EMPTY: +; MIPS-RELOCS-NEXT: Relocation section '.rel.plt' at offset {{.+}} contains 3 entries: +; MIPS-RELOCS-NEXT: Offset Info Type Symbol's Value Symbol's Name +; MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY_CALL/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 _Z11external_fnl +; MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY_CALL/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 __cxa_begin_catch +; MIPS-RELOCS-NEXT: R_MIPS_CHERI_CAPABILITY_CALL/R_MIPS_NONE/R_MIPS_NONE 0000000000000000 __cxa_end_catch + +;; Local relocations for exception handling: +; MIPS-RELOCS-NEXT: CHERI __cap_relocs [ +; MIPS-RELOCS-NEXT: 0x02{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+128) Length: 160 Perms: Function +; MIPS-RELOCS-NEXT: 0x02{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+96) Length: 160 Perms: Function +; MIPS-RELOCS-NEXT: 0x02{{.+}} Base: 0x1{{.+}} (.L_Z5test2ll$local+96) Length: 168 Perms: Function +; MIPS-RELOCS-NEXT: ] + +;; Should also emit __cap_relocs for RISC-V: +; RUN: ld.lld -shared %t-riscv64.o -o %t.so +; RUN: llvm-readelf -r --cap-relocs %t.so | FileCheck %s --check-prefixes=RV64-RELOCS +; RV64-RELOCS: CHERI __cap_relocs [ +; RV64-RELOCS-NEXT: 0x002{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+92) Length: 116 Perms: Function +; RV64-RELOCS-NEXT: 0x002{{.+}} Base: 0x1{{.+}} (.L_Z4testll$local+72) Length: 116 Perms: Function +; RV64-RELOCS-NEXT: 0x002{{.+}} Base: 0x1{{.+}} (.L_Z5test2ll$local+72) Length: 124 Perms: Function +; RV64-RELOCS-NEXT: ] + +; IR was generated from the following code: +; long external_fn(long arg); +; +; long test(long arg, long arg2) { +; long a = 0; +; long b = 0; +; try { +; a = external_fn(arg); +; } catch (...) { +; return -1; +; } +; try { +; b = external_fn(arg2); +; } catch (...) { +; return a; +; } +; return a + b; +; } +; +; long test2(long arg, long arg2) { +; try { +; return external_fn(arg) - external_fn(arg2); +; } catch (long &err) { +; return err; +; } catch (...) { +; return -1; +; } +; } + +@_ZTIl = external dso_local addrspace(200) constant ptr addrspace(200) + +define dso_local noundef i64 @_Z4testll(i64 noundef %arg, i64 noundef %arg2) local_unnamed_addr addrspace(200) uwtable personality ptr addrspace(200) @__gxx_personality_v0 { +entry: + %call = invoke noundef i64 @_Z11external_fnl(i64 noundef %arg) + to label %invoke.cont unwind label %lpad + +invoke.cont: + %call3 = invoke noundef i64 @_Z11external_fnl(i64 noundef %arg2) + to label %invoke.cont2 unwind label %lpad1 + +lpad: + %0 = landingpad { ptr addrspace(200), i32 } + catch ptr addrspace(200) null + %1 = extractvalue { ptr addrspace(200), i32 } %0, 0 + %2 = tail call ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200) %1) nounwind + tail call void @__cxa_end_catch() + br label %cleanup + +invoke.cont2: + %add = add nsw i64 %call3, %call + br label %cleanup + +lpad1: + %3 = landingpad { ptr addrspace(200), i32 } + catch ptr addrspace(200) null + %4 = extractvalue { ptr addrspace(200), i32 } %3, 0 + %5 = tail call ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200) %4) nounwind + tail call void @__cxa_end_catch() + br label %cleanup + +cleanup: + %retval.0 = phi i64 [ %add, %invoke.cont2 ], [ %call, %lpad1 ], [ -1, %lpad ] + ret i64 %retval.0 +} + +declare dso_local noundef i64 @_Z11external_fnl(i64 noundef) local_unnamed_addr addrspace(200) + +declare dso_local i32 @__gxx_personality_v0(...) addrspace(200) + +declare dso_local ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200)) local_unnamed_addr addrspace(200) + +declare dso_local void @__cxa_end_catch() local_unnamed_addr addrspace(200) + +; Function Attrs: mustprogress uwtable +define dso_local noundef i64 @_Z5test2ll(i64 noundef %arg, i64 noundef %arg2) local_unnamed_addr addrspace(200) #0 personality ptr addrspace(200) @__gxx_personality_v0 { +entry: + %call = invoke noundef i64 @_Z11external_fnl(i64 noundef %arg) + to label %invoke.cont unwind label %lpad + +invoke.cont: + %call2 = invoke noundef i64 @_Z11external_fnl(i64 noundef %arg2) + to label %invoke.cont1 unwind label %lpad + +invoke.cont1: + %sub = sub nsw i64 %call, %call2 + br label %return + +lpad: + %0 = landingpad { ptr addrspace(200), i32 } + catch ptr addrspace(200) @_ZTIl + catch ptr addrspace(200) null + %1 = extractvalue { ptr addrspace(200), i32 } %0, 0 + %2 = extractvalue { ptr addrspace(200), i32 } %0, 1 + %3 = tail call i32 @llvm.eh.typeid.for(ptr addrspacecast (ptr addrspace(200) @_ZTIl to ptr)) nounwind + %matches = icmp eq i32 %2, %3 + %4 = tail call ptr addrspace(200) @__cxa_begin_catch(ptr addrspace(200) %1) nounwind + br i1 %matches, label %catch3, label %catch + +catch3: + %5 = load i64, ptr addrspace(200) %4, align 8 + tail call void @__cxa_end_catch() nounwind + br label %return + +catch: + tail call void @__cxa_end_catch() + br label %return + +return: + %retval.0 = phi i64 [ %sub, %invoke.cont1 ], [ %5, %catch3 ], [ -1, %catch ] + ret i64 %retval.0 +} + +declare i32 @llvm.eh.typeid.for(ptr) addrspace(200) diff --git a/lld/test/ELF/cheri/lit.local.cfg b/lld/test/ELF/cheri/lit.local.cfg index d6da5e3f9c44..6c91db14db14 100644 --- a/lld/test/ELF/cheri/lit.local.cfg +++ b/lld/test/ELF/cheri/lit.local.cfg @@ -26,7 +26,8 @@ config.lld = lit.util.which('ld.lld', config.llvm_tools_dir) # These substitutions rely on %clang, etc. so must come before even if clang isn't found add_sub('%clang_link_purecap ', '%cheri_purecap_clang ' + '-fuse-ld=' + config.lld + ' -nostdlib -Wl,-melf64btsmip_cheri_fbsd ') -local_llvm_config.add_cheri_tool_substitutions(['llvm-mc']) +local_llvm_config.use_llvm_tool("llc") +local_llvm_config.add_cheri_tool_substitutions(['llvm-mc', 'llc']) local_llvm_config.use_clang(required=False) if config.clang: if lit_config.debug: From 6951ec71b9f54d698348e8bd6ab15e5181369b8c Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Tue, 17 Sep 2024 10:54:53 -0700 Subject: [PATCH 6/6] [CHERI] Ensure we always emit the $local symbol for exception handling Without it, we would crash if GV.canBenefitFromLocalAlias() returns false (e.g. when the function is not dso_local). --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 9 ++++++--- .../CodeGen/RISCV/cheri/function-start-directives.ll | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 6031e5f61300..ee9223da88e0 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -655,10 +655,13 @@ MCSymbol *AsmPrinter::getSymbolPreferLocal(const GlobalValue &GV, // assembler would otherwise be conservative and assume a global default // visibility symbol can be interposable, even if the code generator already // assumed it. - if (TM.getTargetTriple().isOSBinFormatELF() && GV.canBenefitFromLocalAlias()) { + if (Force) + return getSymbolWithGlobalValueBase(&GV, "$local"); + if (TM.getTargetTriple().isOSBinFormatELF() && + GV.canBenefitFromLocalAlias()) { const Module &M = *GV.getParent(); - if (Force || (TM.getRelocationModel() != Reloc::Static && - M.getPIELevel() == PIELevel::Default && GV.isDSOLocal())) + if (TM.getRelocationModel() != Reloc::Static && + M.getPIELevel() == PIELevel::Default && GV.isDSOLocal()) return getSymbolWithGlobalValueBase(&GV, "$local"); } return TM.getSymbol(&GV); diff --git a/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll b/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll index c91c12c537db..30d361e7bfb9 100644 --- a/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll +++ b/llvm/test/CodeGen/RISCV/cheri/function-start-directives.ll @@ -4,7 +4,7 @@ target triple = "riscv64-unknown-freebsd13" -define dso_local noundef signext i32 @_Z4testv() local_unnamed_addr addrspace(200) uwtable personality ptr addrspace(200) @__gxx_personality_v0 { +define noundef signext i32 @_Z4testv() local_unnamed_addr addrspace(200) uwtable personality ptr addrspace(200) @__gxx_personality_v0 { entry: %call = invoke noundef signext i32 @_Z3foov(ptr addrspace(200) @_Z4testv) to label %return unwind label %lpad