Skip to content

Commit 79231a8

Browse files
authored
[ORC-RT][LoongArch] Add initial support for loongarch64 in ELFNixPlatform (#123575)
Enable ELFNixPlatform support for loongarch64. These are few simple changes, but it allows us to use the orc runtime in ELF/LoongArch64 backend. This change adds test cases targeting the LoongArch64 Linux platform to the ORC runtime integration test suite. Since jitlink for loongarch64 is ready for general use, and ELF-based platforms support defining multiple static initializer table sections with differing priorities, some relevant test cases in compiler-rt for ELFNixPlatform support can be enabled.
1 parent f07e516 commit 79231a8

File tree

11 files changed

+340
-1
lines changed

11 files changed

+340
-1
lines changed

compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64})
110110

111111
if (UNIX)
112112
if (OS_NAME MATCHES "Linux")
113-
set(ALL_ORC_SUPPORTED_ARCH ${X86_64} ${ARM64} ${ARM32} ${PPC64})
113+
set(ALL_ORC_SUPPORTED_ARCH ${X86_64} ${ARM64} ${ARM32} ${PPC64} ${LOONGARCH64})
114114
else()
115115
set(ALL_ORC_SUPPORTED_ARCH ${X86_64} ${ARM64} ${ARM32})
116116
endif()
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %clangxx -fexceptions -fPIC -c -o %t %s
2+
// RUN: %llvm_jitlink %t
3+
4+
extern "C" void llvm_jitlink_setTestResultOverride(long Value);
5+
6+
int main(int argc, char *argv[]) {
7+
llvm_jitlink_setTestResultOverride(1);
8+
try {
9+
throw 0;
10+
} catch (int X) {
11+
llvm_jitlink_setTestResultOverride(X);
12+
}
13+
return 0;
14+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// REQUIRES: libunwind-available
2+
// RUN: %clangxx -fexceptions -fPIC -c -o %t %s
3+
// RUN: env LD_PRELOAD=%shared_libunwind %llvm_jitlink %t
4+
5+
extern "C" void llvm_jitlink_setTestResultOverride(long Value);
6+
7+
int main(int argc, char *argv[]) {
8+
llvm_jitlink_setTestResultOverride(1);
9+
try {
10+
throw 0;
11+
} catch (int X) {
12+
llvm_jitlink_setTestResultOverride(X);
13+
}
14+
return 0;
15+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
if config.root.host_arch != "loongarch64":
2+
config.unsupported = True
3+
4+
if config.target_arch != "loongarch64":
5+
config.unsupported = True
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %clangxx -fPIC -emit-llvm -c -o %t %s
2+
// RUN: %lli_orc_jitlink -relocation-model=pic %t | FileCheck %s
3+
4+
// CHECK: catch
5+
6+
#include <stdio.h>
7+
8+
int main(int argc, char *argv[]) {
9+
try {
10+
throw 0;
11+
} catch (int X) {
12+
puts("catch");
13+
}
14+
return 0;
15+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
; RUN: %lli_orc_jitlink %s | FileCheck %s
2+
3+
; CHECK: constructor
4+
; CHECK-NEXT: main
5+
; CHECK-NEXT: destructor
6+
7+
@__dso_handle = external hidden global i8
8+
@.str = private unnamed_addr constant [5 x i8] c"main\00", align 1
9+
@.str.1 = private unnamed_addr constant [12 x i8] c"constructor\00", align 1
10+
@.str.2 = private unnamed_addr constant [11 x i8] c"destructor\00", align 1
11+
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @constructor, i8* null }]
12+
13+
define dso_local void @destructor(i8* %0) {
14+
%2 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0))
15+
ret void
16+
}
17+
18+
declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
19+
20+
; Function Attrs: nofree norecurse nounwind uwtable
21+
define dso_local i32 @main(i32 %0, i8** nocapture readnone %1) local_unnamed_addr #2 {
22+
%3 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0))
23+
ret i32 0
24+
}
25+
26+
declare i32 @puts(i8* nocapture readonly)
27+
28+
define internal void @constructor() {
29+
%1 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str.1, i64 0, i64 0)) #5
30+
%2 = tail call i32 @__cxa_atexit(void (i8*)* @destructor, i8* null, i8* nonnull @__dso_handle) #5
31+
ret void
32+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Test that ELF static initializers with different constructor priorities work
2+
// and are executed in the proper order.
3+
//
4+
// RUN: %clang -c -o %t %s
5+
// RUN: %llvm_jitlink %t | FileCheck %s
6+
7+
// CHECK: constructor 100
8+
// CHECK-NEXT: constructor 200
9+
// CHECK-NEXT: constructor 65535
10+
// CHECK-NEXT: main
11+
// CHECK-NEXT: destructor
12+
13+
.text
14+
.globl destructor
15+
.p2align 2
16+
.type destructor,@function
17+
destructor:
18+
.Ldestructor$local:
19+
20+
pcalau12i $a0, %pc_hi20(.L.str.2)
21+
addi.d $a0, $a0, %pc_lo12(.L.str.2)
22+
b %plt(puts)
23+
24+
.globl main
25+
.p2align 2
26+
.type main,@function
27+
main:
28+
29+
addi.d $sp, $sp, -16
30+
st.d $ra, $sp, 8 # 8-byte Folded Spill
31+
pcalau12i $a0, %pc_hi20(.L.str)
32+
addi.d $a0, $a0, %pc_lo12(.L.str)
33+
bl %plt(puts)
34+
move $a0, $zero
35+
ld.d $ra, $sp, 8 # 8-byte Folded Reload
36+
addi.d $sp, $sp, 16
37+
ret
38+
39+
.p2align 2
40+
.type constructor.65535,@function
41+
constructor.65535:
42+
43+
addi.d $sp, $sp, -16
44+
st.d $ra, $sp, 8 # 8-byte Folded Spill
45+
pcalau12i $a0, %pc_hi20(.L.str.65535)
46+
addi.d $a0, $a0, %pc_lo12(.L.str.65535)
47+
bl %plt(puts)
48+
pcalau12i $a0, %got_pc_hi20(__dso_handle)
49+
ld.d $a0, $a0, %got_pc_lo12(__dso_handle)
50+
ld.d $a2, $a0, 0
51+
pcalau12i $a0, %pc_hi20(.Ldestructor$local)
52+
addi.d $a0, $a0, %pc_lo12(.Ldestructor$local)
53+
move $a1, $zero
54+
ld.d $ra, $sp, 8 # 8-byte Folded Reload
55+
addi.d $sp, $sp, 16
56+
b %plt(__cxa_atexit)
57+
58+
.p2align 2
59+
.type constructor.100,@function
60+
constructor.100:
61+
62+
addi.d $sp, $sp, -16
63+
st.d $ra, $sp, 8 # 8-byte Folded Spill
64+
st.d $fp, $sp, 0 # 8-byte Folded Spill
65+
addi.d $fp, $sp, 16
66+
pcalau12i $a0, %pc_hi20(.L.str.100)
67+
addi.d $a0, $a0, %pc_lo12(.L.str.100)
68+
bl %plt(puts)
69+
ld.d $fp, $sp, 0 # 8-byte Folded Reload
70+
ld.d $ra, $sp, 8 # 8-byte Folded Reload
71+
addi.d $sp, $sp, 16
72+
ret
73+
74+
.p2align 2
75+
.type constructor.200,@function
76+
constructor.200:
77+
78+
addi.d $sp, $sp, -16
79+
st.d $ra, $sp, 8 # 8-byte Folded Spill
80+
st.d $fp, $sp, 0 # 8-byte Folded Spill
81+
addi.d $fp, $sp, 16
82+
pcalau12i $a0, %pc_hi20(.L.str.200)
83+
addi.d $a0, $a0, %pc_lo12(.L.str.200)
84+
bl %plt(puts)
85+
ld.d $fp, $sp, 0 # 8-byte Folded Reload
86+
ld.d $ra, $sp, 8 # 8-byte Folded Reload
87+
addi.d $sp, $sp, 16
88+
ret
89+
90+
.hidden __dso_handle
91+
.type .L.str,@object
92+
.section .rodata.str1.1,"aMS",@progbits,1
93+
.L.str:
94+
.asciz "main"
95+
.size .L.str, 5
96+
97+
.type .L.str.100,@object
98+
.L.str.100:
99+
.asciz "constructor 100"
100+
.size .L.str.100, 16
101+
102+
.type .L.str.200,@object
103+
.L.str.200:
104+
.asciz "constructor 200"
105+
.size .L.str.200, 16
106+
107+
.type .L.str.65535,@object
108+
.L.str.65535:
109+
.asciz "constructor 65535"
110+
.size .L.str.65535, 18
111+
112+
113+
.type .L.str.2,@object
114+
.L.str.2:
115+
.asciz "destructor"
116+
.size .L.str.2, 11
117+
118+
.section .init_array.100,"aw",@init_array
119+
.p2align 3
120+
.dword constructor.100
121+
.section .init_array.200,"aw",@init_array
122+
.p2align 3
123+
.dword constructor.200
124+
.section .init_array,"aw",@init_array
125+
.p2align 3
126+
.dword constructor.65535
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Test that the runtime correctly interposes atexit.
2+
//
3+
// REQUIRES: disabled
4+
// This test is disabled until a proper atexit interpose can be implemented:
5+
// the current one assumes that atexit is defined in the dylib that calls it,
6+
// which is not true in general. See
7+
// https://github.com/llvm/llvm-project/issues/74641
8+
//
9+
// RUN: %clang -c -o %t %s
10+
// RUN: %llvm_jitlink %t
11+
12+
.text
13+
// OnExit destructor resets the test result override to zero.
14+
.globl on_exit
15+
.p2align 2
16+
.type on_exit,@function
17+
on_exit:
18+
19+
move $a0, $zero
20+
b %plt(llvm_jitlink_setTestResultOverride)
21+
.Lfunc_end0:
22+
.size on_exit, .Lfunc_end0-on_exit
23+
24+
// main registers the atexit and sets the test result to one.
25+
.globl main
26+
.p2align 2
27+
.type main,@function
28+
main:
29+
30+
addi.d $sp, $sp, -16
31+
st.d $ra, $sp, 8 # 8-byte Folded Spill
32+
pcalau12i $a0, %pc_hi20(on_exit)
33+
addi.d $a0, $a0, %pc_lo12(on_exit)
34+
bl %plt(atexit)
35+
ori $a0, $zero, 1
36+
bl %plt(llvm_jitlink_setTestResultOverride)
37+
move $a0, $zero
38+
ld.d $ra, $sp, 8 # 8-byte Folded Reload
39+
addi.d $sp, $sp, 16
40+
ret
41+
.Lfunc_end1:
42+
.size main, .Lfunc_end1-main
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Test that the runtime correctly interposes ___cxa_atexit.
2+
//
3+
// RUN: %clang -c -o %t %s
4+
// RUN: %llvm_jitlink %t
5+
6+
.text
7+
// Destructor resets the test result override to zero.
8+
.globl on_exit
9+
.p2align 2
10+
.type on_exit,@function
11+
on_exit:
12+
13+
move $a0, $zero
14+
b %plt(llvm_jitlink_setTestResultOverride)
15+
.Lfunc_end0:
16+
.size on_exit, .Lfunc_end0-on_exit
17+
18+
// main registers the atexit and sets the test result to one.
19+
.globl main
20+
.p2align 2
21+
.type main,@function
22+
main:
23+
24+
addi.d $sp, $sp, -16
25+
st.d $ra, $sp, 8 # 8-byte Folded Spill
26+
pcalau12i $a0, %got_pc_hi20(__dso_handle)
27+
ld.d $a0, $a0, %got_pc_lo12(__dso_handle)
28+
ld.d $a2, $a0, 0
29+
pcalau12i $a0, %pc_hi20(on_exit)
30+
addi.d $a0, $a0, %pc_lo12(on_exit)
31+
move $a1, $zero
32+
bl %plt(__cxa_atexit)
33+
ori $a0, $zero, 1
34+
bl %plt(llvm_jitlink_setTestResultOverride)
35+
move $a0, $zero
36+
ld.d $ra, $sp, 8 # 8-byte Folded Reload
37+
addi.d $sp, $sp, 16
38+
ret
39+
.Lfunc_end1:
40+
.size main, .Lfunc_end1-main
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Test that basic ELF static initializers work. The main function in this
2+
// test returns the value of 'x', which is initially 1 in the data section,
3+
// and reset to 0 if the _static_init function is run. If the static initializer
4+
// does not run then main will return 1, causing the test to be treated as a
5+
// failure.
6+
//
7+
// RUN: %clang -c -o %t %s
8+
// RUN: %llvm_jitlink %t
9+
10+
.text
11+
.globl main
12+
.p2align 2
13+
.type main,@function
14+
main:
15+
16+
pcalau12i $a0, %pc_hi20(x)
17+
ld.w $a0, $a0, %pc_lo12(x)
18+
ret
19+
.Lfunc_end0:
20+
.size main, .Lfunc_end0-main
21+
22+
// static initializer sets the value of 'x' to zero.
23+
24+
.section .text.startup,"ax",@progbits
25+
.p2align 2
26+
.type static_init,@function
27+
static_init:
28+
29+
pcalau12i $a0, %pc_hi20(x)
30+
st.w $zero, $a0, %pc_lo12(x)
31+
ret
32+
.Lfunc_end1:
33+
.size static_init, .Lfunc_end1-static_init
34+
35+
.type x,@object
36+
.data
37+
.globl x
38+
.p2align 2
39+
x:
40+
.word 1
41+
.size x, 4
42+
43+
.section .init_array,"aw",@init_array
44+
.p2align 3
45+
.dword static_init

llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
1111

1212
#include "llvm/ExecutionEngine/JITLink/aarch64.h"
13+
#include "llvm/ExecutionEngine/JITLink/loongarch.h"
1314
#include "llvm/ExecutionEngine/JITLink/ppc64.h"
1415
#include "llvm/ExecutionEngine/JITLink/x86_64.h"
1516
#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
@@ -150,6 +151,9 @@ class DSOHandleMaterializationUnit : public MaterializationUnit {
150151
case Triple::ppc64le:
151152
EdgeKind = jitlink::ppc64::Pointer64;
152153
break;
154+
case Triple::loongarch64:
155+
EdgeKind = jitlink::loongarch::Pointer64;
156+
break;
153157
default:
154158
llvm_unreachable("Unrecognized architecture");
155159
}
@@ -363,6 +367,7 @@ bool ELFNixPlatform::supportedTarget(const Triple &TT) {
363367
// FIXME: jitlink for ppc64 hasn't been well tested, leave it unsupported
364368
// right now.
365369
case Triple::ppc64le:
370+
case Triple::loongarch64:
366371
return true;
367372
default:
368373
return false;

0 commit comments

Comments
 (0)