[llvm] 79231a8 - [ORC-RT][LoongArch] Add initial support for loongarch64 in ELFNixPlatform (#123575)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 20 22:25:07 PST 2025


Author: Ami-zhang
Date: 2025-01-21T14:25:03+08:00
New Revision: 79231a86846b7dff09497fc58ea1e82e892052bd

URL: https://github.com/llvm/llvm-project/commit/79231a86846b7dff09497fc58ea1e82e892052bd
DIFF: https://github.com/llvm/llvm-project/commit/79231a86846b7dff09497fc58ea1e82e892052bd.diff

LOG: [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.

Added: 
    compiler-rt/test/orc/TestCases/Linux/loongarch64/ehframe-default.cpp
    compiler-rt/test/orc/TestCases/Linux/loongarch64/ehframe-libunwind.cpp
    compiler-rt/test/orc/TestCases/Linux/loongarch64/lit.local.cfg.py
    compiler-rt/test/orc/TestCases/Linux/loongarch64/lljit-ehframe.cpp
    compiler-rt/test/orc/TestCases/Linux/loongarch64/lljit-initialize-deinitialize.ll
    compiler-rt/test/orc/TestCases/Linux/loongarch64/priority-static-initializer.S
    compiler-rt/test/orc/TestCases/Linux/loongarch64/trivial-atexit.S
    compiler-rt/test/orc/TestCases/Linux/loongarch64/trivial-cxa-atexit.S
    compiler-rt/test/orc/TestCases/Linux/loongarch64/trivial-static-initializer.S

Modified: 
    compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
    llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
index ab5d55a9a35c04..ee5be276f3df7d 100644
--- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
+++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
@@ -110,7 +110,7 @@ set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64})
 
 if (UNIX)
   if (OS_NAME MATCHES "Linux")
-    set(ALL_ORC_SUPPORTED_ARCH ${X86_64} ${ARM64} ${ARM32} ${PPC64})
+    set(ALL_ORC_SUPPORTED_ARCH ${X86_64} ${ARM64} ${ARM32} ${PPC64} ${LOONGARCH64})
   else()
     set(ALL_ORC_SUPPORTED_ARCH ${X86_64} ${ARM64} ${ARM32})
   endif()

diff  --git a/compiler-rt/test/orc/TestCases/Linux/loongarch64/ehframe-default.cpp b/compiler-rt/test/orc/TestCases/Linux/loongarch64/ehframe-default.cpp
new file mode 100644
index 00000000000000..0f7dcec4b5a5b5
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Linux/loongarch64/ehframe-default.cpp
@@ -0,0 +1,14 @@
+// RUN: %clangxx -fexceptions -fPIC -c -o %t %s
+// RUN: %llvm_jitlink %t
+
+extern "C" void llvm_jitlink_setTestResultOverride(long Value);
+
+int main(int argc, char *argv[]) {
+  llvm_jitlink_setTestResultOverride(1);
+  try {
+    throw 0;
+  } catch (int X) {
+    llvm_jitlink_setTestResultOverride(X);
+  }
+  return 0;
+}

diff  --git a/compiler-rt/test/orc/TestCases/Linux/loongarch64/ehframe-libunwind.cpp b/compiler-rt/test/orc/TestCases/Linux/loongarch64/ehframe-libunwind.cpp
new file mode 100644
index 00000000000000..f56aa8fba950f9
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Linux/loongarch64/ehframe-libunwind.cpp
@@ -0,0 +1,15 @@
+// REQUIRES: libunwind-available
+// RUN: %clangxx -fexceptions -fPIC -c -o %t %s
+// RUN: env LD_PRELOAD=%shared_libunwind %llvm_jitlink %t
+
+extern "C" void llvm_jitlink_setTestResultOverride(long Value);
+
+int main(int argc, char *argv[]) {
+  llvm_jitlink_setTestResultOverride(1);
+  try {
+    throw 0;
+  } catch (int X) {
+    llvm_jitlink_setTestResultOverride(X);
+  }
+  return 0;
+}

diff  --git a/compiler-rt/test/orc/TestCases/Linux/loongarch64/lit.local.cfg.py b/compiler-rt/test/orc/TestCases/Linux/loongarch64/lit.local.cfg.py
new file mode 100644
index 00000000000000..b8a5a418ec2511
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Linux/loongarch64/lit.local.cfg.py
@@ -0,0 +1,5 @@
+if config.root.host_arch != "loongarch64":
+    config.unsupported = True
+
+if config.target_arch != "loongarch64":
+    config.unsupported = True

diff  --git a/compiler-rt/test/orc/TestCases/Linux/loongarch64/lljit-ehframe.cpp b/compiler-rt/test/orc/TestCases/Linux/loongarch64/lljit-ehframe.cpp
new file mode 100644
index 00000000000000..b73ec2387028ed
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Linux/loongarch64/lljit-ehframe.cpp
@@ -0,0 +1,15 @@
+// RUN: %clangxx -fPIC -emit-llvm -c -o %t %s
+// RUN: %lli_orc_jitlink -relocation-model=pic %t | FileCheck %s
+
+// CHECK: catch
+
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+  try {
+    throw 0;
+  } catch (int X) {
+    puts("catch");
+  }
+  return 0;
+}

diff  --git a/compiler-rt/test/orc/TestCases/Linux/loongarch64/lljit-initialize-deinitialize.ll b/compiler-rt/test/orc/TestCases/Linux/loongarch64/lljit-initialize-deinitialize.ll
new file mode 100644
index 00000000000000..34bfc10b9d8973
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Linux/loongarch64/lljit-initialize-deinitialize.ll
@@ -0,0 +1,32 @@
+; RUN: %lli_orc_jitlink %s | FileCheck %s
+
+; CHECK: constructor
+; CHECK-NEXT: main
+; CHECK-NEXT: destructor
+
+ at __dso_handle = external hidden global i8
+ at .str = private unnamed_addr constant [5 x i8] c"main\00", align 1
+ at .str.1 = private unnamed_addr constant [12 x i8] c"constructor\00", align 1
+ at .str.2 = private unnamed_addr constant [11 x i8] c"destructor\00", align 1
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @constructor, i8* null }]
+
+define dso_local void @destructor(i8* %0) {
+  %2 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0))
+  ret void
+}
+
+declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
+
+; Function Attrs: nofree norecurse nounwind uwtable
+define dso_local i32 @main(i32 %0, i8** nocapture readnone %1) local_unnamed_addr #2 {
+  %3 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0))
+  ret i32 0
+}
+
+declare i32 @puts(i8* nocapture readonly)
+
+define internal void @constructor() {
+  %1 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str.1, i64 0, i64 0)) #5
+  %2 = tail call i32 @__cxa_atexit(void (i8*)* @destructor, i8* null, i8* nonnull @__dso_handle) #5
+  ret void
+}

diff  --git a/compiler-rt/test/orc/TestCases/Linux/loongarch64/priority-static-initializer.S b/compiler-rt/test/orc/TestCases/Linux/loongarch64/priority-static-initializer.S
new file mode 100644
index 00000000000000..9e2ce7a20a1f92
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Linux/loongarch64/priority-static-initializer.S
@@ -0,0 +1,126 @@
+// Test that ELF static initializers with 
diff erent constructor priorities work
+// and are executed in the proper order.
+//
+// RUN: %clang -c -o %t %s
+// RUN: %llvm_jitlink %t | FileCheck %s
+
+// CHECK: constructor 100
+// CHECK-NEXT: constructor 200
+// CHECK-NEXT: constructor 65535
+// CHECK-NEXT: main
+// CHECK-NEXT: destructor
+
+    .text
+    .globl    destructor
+    .p2align    2
+    .type    destructor, at function
+destructor:
+.Ldestructor$local:
+
+    pcalau12i    $a0, %pc_hi20(.L.str.2)
+    addi.d    $a0, $a0, %pc_lo12(.L.str.2)
+    b    %plt(puts)
+
+    .globl    main
+    .p2align    2
+    .type    main, at function
+main:
+
+    addi.d    $sp, $sp, -16
+    st.d    $ra, $sp, 8                     # 8-byte Folded Spill
+    pcalau12i    $a0, %pc_hi20(.L.str)
+    addi.d    $a0, $a0, %pc_lo12(.L.str)
+    bl    %plt(puts)
+    move    $a0, $zero
+    ld.d    $ra, $sp, 8                     # 8-byte Folded Reload
+    addi.d    $sp, $sp, 16
+    ret
+
+    .p2align    2
+    .type    constructor.65535, at function
+constructor.65535:
+
+    addi.d    $sp, $sp, -16
+    st.d    $ra, $sp, 8                     # 8-byte Folded Spill
+    pcalau12i    $a0, %pc_hi20(.L.str.65535)
+    addi.d    $a0, $a0, %pc_lo12(.L.str.65535)
+    bl    %plt(puts)
+    pcalau12i    $a0, %got_pc_hi20(__dso_handle)
+    ld.d    $a0, $a0, %got_pc_lo12(__dso_handle)
+    ld.d    $a2, $a0, 0
+    pcalau12i    $a0, %pc_hi20(.Ldestructor$local)
+    addi.d    $a0, $a0, %pc_lo12(.Ldestructor$local)
+    move    $a1, $zero
+    ld.d    $ra, $sp, 8                     # 8-byte Folded Reload
+    addi.d    $sp, $sp, 16
+    b    %plt(__cxa_atexit)
+
+    .p2align    2
+    .type    constructor.100, at function
+constructor.100:
+
+    addi.d    $sp, $sp, -16
+    st.d    $ra, $sp, 8                     # 8-byte Folded Spill
+    st.d    $fp, $sp, 0                     # 8-byte Folded Spill
+    addi.d    $fp, $sp, 16
+    pcalau12i    $a0, %pc_hi20(.L.str.100)
+    addi.d    $a0, $a0, %pc_lo12(.L.str.100)
+    bl    %plt(puts)
+    ld.d    $fp, $sp, 0                     # 8-byte Folded Reload
+    ld.d    $ra, $sp, 8                     # 8-byte Folded Reload
+    addi.d    $sp, $sp, 16
+    ret
+
+    .p2align    2
+    .type    constructor.200, at function
+constructor.200:
+
+    addi.d    $sp, $sp, -16
+    st.d    $ra, $sp, 8                     # 8-byte Folded Spill
+    st.d    $fp, $sp, 0                     # 8-byte Folded Spill
+    addi.d    $fp, $sp, 16
+    pcalau12i    $a0, %pc_hi20(.L.str.200)
+    addi.d    $a0, $a0, %pc_lo12(.L.str.200)
+    bl    %plt(puts)
+    ld.d    $fp, $sp, 0                     # 8-byte Folded Reload
+    ld.d    $ra, $sp, 8                     # 8-byte Folded Reload
+    addi.d    $sp, $sp, 16
+    ret
+
+    .hidden    __dso_handle
+    .type    .L.str, at object
+    .section    .rodata.str1.1,"aMS", at progbits,1
+.L.str:
+    .asciz    "main"
+    .size    .L.str, 5
+
+    .type    .L.str.100, at object
+.L.str.100:
+    .asciz    "constructor 100"
+    .size    .L.str.100, 16
+
+    .type    .L.str.200, at object
+.L.str.200:
+    .asciz    "constructor 200"
+    .size    .L.str.200, 16
+
+    .type    .L.str.65535, at object
+.L.str.65535:
+    .asciz    "constructor 65535"
+    .size    .L.str.65535, 18
+
+
+    .type    .L.str.2, at object
+.L.str.2:
+    .asciz    "destructor"
+    .size    .L.str.2, 11
+
+    .section    .init_array.100,"aw", at init_array
+    .p2align    3
+    .dword    constructor.100
+    .section    .init_array.200,"aw", at init_array
+    .p2align    3
+    .dword    constructor.200
+    .section    .init_array,"aw", at init_array
+    .p2align    3
+    .dword    constructor.65535

diff  --git a/compiler-rt/test/orc/TestCases/Linux/loongarch64/trivial-atexit.S b/compiler-rt/test/orc/TestCases/Linux/loongarch64/trivial-atexit.S
new file mode 100644
index 00000000000000..38a388b19ba4c2
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Linux/loongarch64/trivial-atexit.S
@@ -0,0 +1,42 @@
+// Test that the runtime correctly interposes atexit.
+//
+// REQUIRES: disabled
+//   This test is disabled until a proper atexit interpose can be implemented:
+//   the current one assumes that atexit is defined in the dylib that calls it,
+//   which is not true in general. See
+//   https://github.com/llvm/llvm-project/issues/74641
+//
+// RUN: %clang -c -o %t %s
+// RUN: %llvm_jitlink %t
+
+    .text
+// OnExit destructor resets the test result override to zero.
+    .globl    on_exit
+    .p2align    2
+    .type    on_exit, at function
+on_exit:
+
+    move    $a0, $zero
+    b    %plt(llvm_jitlink_setTestResultOverride)
+.Lfunc_end0:
+    .size    on_exit, .Lfunc_end0-on_exit
+
+// main registers the atexit and sets the test result to one.
+    .globl    main
+    .p2align    2
+    .type    main, at function
+main:
+
+    addi.d    $sp, $sp, -16
+    st.d    $ra, $sp, 8                     # 8-byte Folded Spill
+    pcalau12i    $a0, %pc_hi20(on_exit)
+    addi.d    $a0, $a0, %pc_lo12(on_exit)
+    bl    %plt(atexit)
+    ori    $a0, $zero, 1
+    bl    %plt(llvm_jitlink_setTestResultOverride)
+    move    $a0, $zero
+    ld.d    $ra, $sp, 8                     # 8-byte Folded Reload
+    addi.d    $sp, $sp, 16
+    ret
+.Lfunc_end1:
+    .size    main, .Lfunc_end1-main

diff  --git a/compiler-rt/test/orc/TestCases/Linux/loongarch64/trivial-cxa-atexit.S b/compiler-rt/test/orc/TestCases/Linux/loongarch64/trivial-cxa-atexit.S
new file mode 100644
index 00000000000000..f2a6a7624cdbd2
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Linux/loongarch64/trivial-cxa-atexit.S
@@ -0,0 +1,40 @@
+// Test that the runtime correctly interposes ___cxa_atexit.
+//
+// RUN: %clang -c -o %t %s
+// RUN: %llvm_jitlink %t
+
+    .text
+// Destructor resets the test result override to zero.
+    .globl    on_exit
+    .p2align    2
+    .type    on_exit, at function
+on_exit:
+
+    move    $a0, $zero
+    b    %plt(llvm_jitlink_setTestResultOverride)
+.Lfunc_end0:
+    .size    on_exit, .Lfunc_end0-on_exit
+
+// main registers the atexit and sets the test result to one.
+    .globl    main
+    .p2align    2
+    .type    main, at function
+main:
+
+    addi.d    $sp, $sp, -16
+    st.d    $ra, $sp, 8                     # 8-byte Folded Spill
+    pcalau12i    $a0, %got_pc_hi20(__dso_handle)
+    ld.d    $a0, $a0, %got_pc_lo12(__dso_handle)
+    ld.d    $a2, $a0, 0
+    pcalau12i    $a0, %pc_hi20(on_exit)
+    addi.d    $a0, $a0, %pc_lo12(on_exit)
+    move    $a1, $zero
+    bl    %plt(__cxa_atexit)
+    ori    $a0, $zero, 1
+    bl    %plt(llvm_jitlink_setTestResultOverride)
+    move    $a0, $zero
+    ld.d    $ra, $sp, 8                     # 8-byte Folded Reload
+    addi.d    $sp, $sp, 16
+    ret
+.Lfunc_end1:
+    .size    main, .Lfunc_end1-main

diff  --git a/compiler-rt/test/orc/TestCases/Linux/loongarch64/trivial-static-initializer.S b/compiler-rt/test/orc/TestCases/Linux/loongarch64/trivial-static-initializer.S
new file mode 100644
index 00000000000000..20fa0cc2bcd47b
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Linux/loongarch64/trivial-static-initializer.S
@@ -0,0 +1,45 @@
+// Test that basic ELF static initializers work. The main function in this
+// test returns the value of 'x', which is initially 1 in the data section,
+// and reset to 0 if the _static_init function is run. If the static initializer
+// does not run then main will return 1, causing the test to be treated as a
+// failure.
+//
+// RUN: %clang -c -o %t %s
+// RUN: %llvm_jitlink %t
+
+    .text
+    .globl    main
+    .p2align    2
+    .type    main, at function
+main:
+
+    pcalau12i    $a0, %pc_hi20(x)
+    ld.w    $a0, $a0, %pc_lo12(x)
+    ret
+.Lfunc_end0:
+    .size    main, .Lfunc_end0-main
+
+// static initializer sets the value of 'x' to zero.
+
+    .section    .text.startup,"ax", at progbits
+    .p2align    2
+    .type    static_init, at function
+static_init:
+
+    pcalau12i    $a0, %pc_hi20(x)
+    st.w    $zero, $a0, %pc_lo12(x)
+    ret
+.Lfunc_end1:
+    .size    static_init, .Lfunc_end1-static_init
+
+    .type    x, at object
+    .data
+    .globl    x
+    .p2align    2
+x:
+    .word    1
+    .size    x, 4
+
+    .section    .init_array,"aw", at init_array
+    .p2align    3
+    .dword    static_init

diff  --git a/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
index 8aa517a27d9972..aae7369fc29c4c 100644
--- a/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
@@ -10,6 +10,7 @@
 #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
 
 #include "llvm/ExecutionEngine/JITLink/aarch64.h"
+#include "llvm/ExecutionEngine/JITLink/loongarch.h"
 #include "llvm/ExecutionEngine/JITLink/ppc64.h"
 #include "llvm/ExecutionEngine/JITLink/x86_64.h"
 #include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
@@ -150,6 +151,9 @@ class DSOHandleMaterializationUnit : public MaterializationUnit {
     case Triple::ppc64le:
       EdgeKind = jitlink::ppc64::Pointer64;
       break;
+    case Triple::loongarch64:
+      EdgeKind = jitlink::loongarch::Pointer64;
+      break;
     default:
       llvm_unreachable("Unrecognized architecture");
     }
@@ -363,6 +367,7 @@ bool ELFNixPlatform::supportedTarget(const Triple &TT) {
   // FIXME: jitlink for ppc64 hasn't been well tested, leave it unsupported
   // right now.
   case Triple::ppc64le:
+  case Triple::loongarch64:
     return true;
   default:
     return false;


        


More information about the llvm-commits mailing list