[llvm] Partial work on JITLink ARM64-COFF (PR #89697)

Isaac David via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 22 18:29:12 PDT 2024


https://github.com/orion160 created https://github.com/llvm/llvm-project/pull/89697

CC @lhames @vgvassilev 

>From 9d72ad32e8c36c7a519513b6fac04ec654d2d9fd Mon Sep 17 00:00:00 2001
From: orion <idbl64 at outlook.com>
Date: Mon, 22 Apr 2024 20:25:51 -0500
Subject: [PATCH] Partial work on JITLink ARM64-COFF

---
 .../llvm/ExecutionEngine/JITLink/COFF_arm64.h |  38 ++
 .../llvm/ExecutionEngine/JITLink/aarch64.h    |   2 +
 .../ExecutionEngine/JITLink/CMakeLists.txt    |   1 +
 llvm/lib/ExecutionEngine/JITLink/COFF.cpp     |   7 +
 .../ExecutionEngine/JITLink/COFF_arm64.cpp    | 349 ++++++++++++++++++
 .../JITLink/AArch64/COFF_abs.s                |  26 ++
 .../JITLink/AArch64/COFF_adrp.s               |  32 ++
 .../JITLink/AArch64/COFF_bl_branch26.s        |  33 ++
 .../JITLink/AArch64/COFF_cbz_branch19.s       |  33 ++
 .../JITLink/Generic/sectcreate.test           |   3 -
 10 files changed, 521 insertions(+), 3 deletions(-)
 create mode 100644 llvm/include/llvm/ExecutionEngine/JITLink/COFF_arm64.h
 create mode 100644 llvm/lib/ExecutionEngine/JITLink/COFF_arm64.cpp
 create mode 100644 llvm/test/ExecutionEngine/JITLink/AArch64/COFF_abs.s
 create mode 100644 llvm/test/ExecutionEngine/JITLink/AArch64/COFF_adrp.s
 create mode 100644 llvm/test/ExecutionEngine/JITLink/AArch64/COFF_bl_branch26.s
 create mode 100644 llvm/test/ExecutionEngine/JITLink/AArch64/COFF_cbz_branch19.s

diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/COFF_arm64.h b/llvm/include/llvm/ExecutionEngine/JITLink/COFF_arm64.h
new file mode 100644
index 00000000000000..48580204ddd7e2
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/COFF_arm64.h
@@ -0,0 +1,38 @@
+//===--- COFF_arm64.h - JIT link functions for COFF/arm64 ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// jit-link functions for COFF/arm64.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_COFF_ARM64_H
+#define LLVM_EXECUTIONENGINE_JITLINK_COFF_ARM64_H
+
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+
+namespace llvm {
+namespace jitlink {
+
+/// Create a LinkGraph from an COFF/arm64 relocatable object.
+///
+/// Note: The graph does not take ownership of the underlying buffer, nor copy
+/// its contents. The caller is responsible for ensuring that the object buffer
+/// outlives the graph.
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromCOFFObject_arm64(MemoryBufferRef ObjectBuffer);
+
+/// jit-link the given object buffer, which must be a COFF arm64 object file.
+void link_COFF_arm64(std::unique_ptr<LinkGraph> G,
+                      std::unique_ptr<JITLinkContext> Ctx);
+
+/// Return the string name of the given COFF arm64 edge kind.
+const char *getCOFFARM64RelocationKindName(Edge::Kind R);
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_COFF_ARM64_H
diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
index 40b9339eb5316d..c8c2ae554fe9bc 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/aarch64.h
@@ -345,6 +345,8 @@ enum EdgeKind_aarch64 : Edge::Kind {
   ///     phase will result in an assert/unreachable during the fixup phase.
   ///
   RequestTLSDescEntryAndTransformToPageOffset12,
+  // First platform specific relocation.
+  FirstPlatformRelocation
 };
 
 /// Returns a string name for the given aarch64 edge. For debugging purposes
diff --git a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
index e5f5a99c39bc00..7e842fc65409a1 100644
--- a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
@@ -33,6 +33,7 @@ add_llvm_component_library(LLVMJITLink
   COFFDirectiveParser.cpp
   COFFLinkGraphBuilder.cpp
   COFF_x86_64.cpp
+  COFF_arm64.cpp
 
   # Architectures:
   aarch32.cpp
diff --git a/llvm/lib/ExecutionEngine/JITLink/COFF.cpp b/llvm/lib/ExecutionEngine/JITLink/COFF.cpp
index f4701bc830d664..5d8d5b2ca92907 100644
--- a/llvm/lib/ExecutionEngine/JITLink/COFF.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/COFF.cpp
@@ -14,9 +14,11 @@
 
 #include "llvm/BinaryFormat/COFF.h"
 #include "llvm/ExecutionEngine/JITLink/COFF_x86_64.h"
+#include "llvm/ExecutionEngine/JITLink/COFF_arm64.h"
 #include "llvm/Object/COFF.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/TargetParser/Triple.h"
 #include <cstring>
 
 using namespace llvm;
@@ -111,6 +113,8 @@ createLinkGraphFromCOFFObject(MemoryBufferRef ObjectBuffer) {
   switch (Machine) {
   case COFF::IMAGE_FILE_MACHINE_AMD64:
     return createLinkGraphFromCOFFObject_x86_64(ObjectBuffer);
+  case COFF::IMAGE_FILE_MACHINE_ARM64:
+      return createLinkGraphFromCOFFObject_arm64(ObjectBuffer);
   default:
     return make_error<JITLinkError>(
         "Unsupported target machine architecture in COFF object " +
@@ -124,6 +128,9 @@ void link_COFF(std::unique_ptr<LinkGraph> G,
   case Triple::x86_64:
     link_COFF_x86_64(std::move(G), std::move(Ctx));
     return;
+  case Triple::aarch64:
+    link_COFF_arm64(std::move(G), std::move(Ctx));
+    return;
   default:
     Ctx->notifyFailed(make_error<JITLinkError>(
         "Unsupported target machine architecture in COFF link graph " +
diff --git a/llvm/lib/ExecutionEngine/JITLink/COFF_arm64.cpp b/llvm/lib/ExecutionEngine/JITLink/COFF_arm64.cpp
new file mode 100644
index 00000000000000..4bf3d1c12134a5
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/COFF_arm64.cpp
@@ -0,0 +1,349 @@
+//===----- COFF_arm64.cpp - JIT linker implementation for COFF/arm64 ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// COFF/arm64 jit-link implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/COFF_arm64.h"
+#include "COFFLinkGraphBuilder.h"
+#include "SEHFrameSupport.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/ExecutionEngine/JITLink/aarch64.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Endian.h"
+
+#define DEBUG_TYPE "jitlink"
+
+using namespace llvm;
+using namespace llvm::jitlink;
+
+namespace {
+
+enum EdgeKind_coff_arm64 : Edge::Kind {
+  Pointer32 = aarch64::FirstPlatformRelocation,
+  Pointer32NB,
+  Branch26,
+  PageBase_Rel21,
+  Rel21,
+  PageOffset_12L,
+  Secrel,
+  Secrel_Low12A,
+  Secrel_High12A,
+  Secrel_Low12L,
+  Token,
+  Sec,
+  Pointer64,
+  Branch19,
+  Branch14,
+  Rel32
+};
+
+class COFFJITLinker_arm64 : public JITLinker<COFFJITLinker_arm64> {
+  friend class JITLinker<COFFJITLinker_arm64>;
+
+public:
+  COFFJITLinker_arm64(std::unique_ptr<JITLinkContext> Ctx,
+                      std::unique_ptr<LinkGraph> G,
+                      PassConfiguration PassConfig)
+      : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
+
+private:
+  Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
+    return aarch64::applyFixup(G, B, E);
+  }
+};
+
+class COFFLinkGraphBuilder_arm64 : public COFFLinkGraphBuilder {
+private:
+  Error addRelocations() override {
+    LLVM_DEBUG(dbgs() << "Processing relocations:\n");
+
+    for (const auto &RelSect : sections())
+      if (Error Err = COFFLinkGraphBuilder::forEachRelocation(
+              RelSect, this, &COFFLinkGraphBuilder_arm64::addSingleRelocation))
+        return Err;
+
+    return Error::success();
+  }
+
+#pragma optimize("", off)
+  Error addSingleRelocation(const object::RelocationRef &Rel,
+                            const object::SectionRef &FixupSect,
+                            Block &BlockToFix) {
+    const object::coff_relocation *COFFRel = getObject().getCOFFRelocation(Rel);
+    auto SymbolIt = Rel.getSymbol();
+    if (SymbolIt == getObject().symbol_end()) {
+      return make_error<StringError>(
+          formatv("Invalid symbol index in relocation entry. "
+                  "index: {0}, section: {1}",
+                  COFFRel->SymbolTableIndex, FixupSect.getIndex()),
+          inconvertibleErrorCode());
+    }
+
+    object::COFFSymbolRef COFFSymbol = getObject().getCOFFSymbol(*SymbolIt);
+    COFFSymbolIndex SymIndex = getObject().getSymbolIndex(COFFSymbol);
+
+    Symbol *GraphSymbol = getGraphSymbol(SymIndex);
+    if (!GraphSymbol)
+      return make_error<StringError>(
+          formatv("Could not find symbol at given index, did you add it to "
+                  "JITSymbolTable? index: {0}, section: {1}",
+                  SymIndex, FixupSect.getIndex()),
+          inconvertibleErrorCode());
+
+    int64_t Addend = 0;
+    orc::ExecutorAddr FixupAddress =
+        orc::ExecutorAddr(FixupSect.getAddress()) + Rel.getOffset();
+    Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
+
+    Edge::Kind Kind = Edge::Invalid;
+    const char *FixupPtr = BlockToFix.getContent().data() + Offset;
+
+    switch (Rel.getType()) {
+    case COFF::RelocationTypesARM64::IMAGE_REL_ARM64_ADDR32: {
+      Kind = EdgeKind_coff_arm64::Pointer32;
+      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
+      break;
+    }
+    case COFF::RelocationTypesARM64::IMAGE_REL_ARM64_ADDR32NB: {
+      Kind = EdgeKind_coff_arm64::Pointer32NB;
+      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
+      break;
+    }
+    case COFF::RelocationTypesARM64::IMAGE_REL_ARM64_BRANCH26: {
+      Kind = EdgeKind_coff_arm64::Branch26;
+      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr) >> 4;
+      break;
+    }
+    case COFF::RelocationTypesARM64::IMAGE_REL_ARM64_PAGEBASE_REL21: {
+      Kind = EdgeKind_coff_arm64::PageBase_Rel21;
+      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
+      break;
+    }
+    case COFF::RelocationTypesARM64::IMAGE_REL_ARM64_REL21: {
+      Kind = EdgeKind_coff_arm64::Rel21;
+      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
+      break;
+    }
+    case COFF::RelocationTypesARM64::IMAGE_REL_ARM64_BRANCH19: {
+      Kind = EdgeKind_coff_arm64::Branch19;
+      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr) >> 11;
+      break;
+    }
+    case COFF::RelocationTypesARM64::IMAGE_REL_ARM64_BRANCH14: {
+      Kind = EdgeKind_coff_arm64::Branch14;
+      Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr) >> 16;
+      break;
+    }
+    default: {
+      return make_error<JITLinkError>("Unsupported arm64 relocation:" +
+                                      formatv("{0:d}", Rel.getType()));
+    }
+    }
+
+    Edge GE(Kind, Offset, *GraphSymbol, Addend);
+    LLVM_DEBUG({
+      dbgs() << "    ";
+      printEdge(dbgs(), BlockToFix, GE, getCOFFARM64RelocationKindName(Kind));
+      dbgs() << "\n";
+    });
+
+    BlockToFix.addEdge(std::move(GE));
+
+    return Error::success();
+  }
+#pragma optimize("", on)
+
+public:
+  COFFLinkGraphBuilder_arm64(const object::COFFObjectFile &Obj, const Triple T,
+                             const SubtargetFeatures Features)
+      : COFFLinkGraphBuilder(Obj, std::move(T), std::move(Features),
+                             getCOFFARM64RelocationKindName) {}
+};
+
+class COFFLinkGraphLowering_arm64 {
+public:
+  // Lowers COFF arm64 specific edges to generic arm64 edges.
+  Error lowerCOFFRelocationEdges(LinkGraph &G, JITLinkContext &Ctx) {
+    for (auto *B : G.blocks()) {
+      for (auto &E : B->edges()) {
+        switch (E.getKind()) {
+        case EdgeKind_coff_arm64::Pointer32: {
+          E.setKind(aarch64::Pointer32);
+          break;
+        }
+        case EdgeKind_coff_arm64::Pointer32NB: {
+          E.setKind(aarch64::Pointer32);
+          break;
+        }
+        case EdgeKind_coff_arm64::Branch26: {
+          E.setKind(aarch64::Branch26PCRel);
+          break;
+        }
+        case EdgeKind_coff_arm64::PageBase_Rel21: {
+          E.setKind(aarch64::Page21);
+          break;
+        }
+        case EdgeKind_coff_arm64::Rel21: {
+          // TODO
+          break;
+        }
+        case EdgeKind_coff_arm64::PageOffset_12L: {
+          E.setKind(aarch64::PageOffset12);
+          break;
+        }
+        case EdgeKind_coff_arm64::Secrel: {
+          // TODO
+          break;
+        }
+        case EdgeKind_coff_arm64::Secrel_Low12A: {
+          // TODO
+          break;
+        }
+        case EdgeKind_coff_arm64::Secrel_High12A: {
+          // TODO
+          break;
+        }
+        case EdgeKind_coff_arm64::Secrel_Low12L: {
+          // TODO
+          break;
+        }
+        case EdgeKind_coff_arm64::Token: {
+          // TODO
+          break;
+        }
+        case EdgeKind_coff_arm64::Sec: {
+          // TODO
+          break;
+        }
+        case EdgeKind_coff_arm64::Pointer64: {
+          E.setKind(aarch64::Pointer64);
+          break;
+        }
+        case EdgeKind_coff_arm64::Branch19: {
+          E.setKind(aarch64::CondBranch19PCRel);
+          break;
+        }
+        case EdgeKind_coff_arm64::Branch14: {
+          E.setKind(aarch64::TestAndBranch14PCRel);
+          break;
+        }
+        case EdgeKind_coff_arm64::Rel32: {
+          // TODO
+          break;
+        }
+        default:
+          break;
+        }
+      }
+    }
+
+    return Error::success();
+  }
+};
+
+Error lowerEdges_COFF_arm64(LinkGraph &G, JITLinkContext *Ctx) {
+  LLVM_DEBUG(dbgs() << "Lowering to generic COFF arm64 edges:\n");
+  COFFLinkGraphLowering_arm64 GraphLowering;
+
+  if (auto Err = GraphLowering.lowerCOFFRelocationEdges(G, *Ctx))
+    return Err;
+
+  return Error::success();
+}
+} // namespace
+
+namespace llvm {
+namespace jitlink {
+
+/// Return the string name of the given COFF ARM64 edge kind.
+const char *getCOFFARM64RelocationKindName(Edge::Kind R) {
+  switch (R) {
+  case Pointer32:
+    return "Pointer32";
+  case Pointer32NB:
+    return "Pointer32NB";
+  case Branch26:
+    return "Branch26";
+  case PageBase_Rel21:
+    return "PageBase_Rel21";
+  case Rel21:
+    return "Rel21";
+  case PageOffset_12L:
+    return "PageOffset_12L";
+  case Secrel:
+    return "Secrel";
+  case Secrel_Low12A:
+    return "Secrel_Low12A";
+  case Secrel_High12A:
+    return "Secrel_High12A";
+  case Secrel_Low12L:
+    return "Secrel_Low12L";
+  case Token:
+    return "Token";
+  case Sec:
+    return "Section";
+  case Pointer64:
+    return "Pointer64";
+  case Branch19:
+    return "Branch19";
+  case Branch14:
+    return "Branch14";
+  case Rel32:
+    return "Rel32";
+  default:
+    return aarch64::getEdgeKindName(R);
+  }
+}
+
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromCOFFObject_arm64(MemoryBufferRef ObjectBuffer) {
+  LLVM_DEBUG({
+    dbgs() << "Building jitlink graph for new input "
+           << ObjectBuffer.getBufferIdentifier() << "...\n";
+  });
+
+  auto COFFObj = object::ObjectFile::createCOFFObjectFile(ObjectBuffer);
+  if (!COFFObj)
+    return COFFObj.takeError();
+
+  auto Features = (*COFFObj)->getFeatures();
+  if (!Features)
+    return Features.takeError();
+
+  return COFFLinkGraphBuilder_arm64(**COFFObj, (*COFFObj)->makeTriple(),
+                                    std::move(*Features))
+      .buildGraph();
+}
+
+void link_COFF_arm64(std::unique_ptr<LinkGraph> G,
+                     std::unique_ptr<JITLinkContext> Ctx) {
+  PassConfiguration Config;
+  const Triple &TT = G->getTargetTriple();
+  if (Ctx->shouldAddDefaultTargetPasses(TT)) {
+    // Add a mark-live pass.
+    if (auto MarkLive = Ctx->getMarkLivePass(TT)) {
+      Config.PrePrunePasses.push_back(std::move(MarkLive));
+      Config.PrePrunePasses.push_back(SEHFrameKeepAlivePass(".pdata"));
+    } else
+      Config.PrePrunePasses.push_back(markAllSymbolsLive);
+
+    // Add COFF edge lowering passes.
+    JITLinkContext *CtxPtr = Ctx.get();
+    Config.PreFixupPasses.push_back(
+        [CtxPtr](LinkGraph &G) { return lowerEdges_COFF_arm64(G, CtxPtr); });
+  }
+
+  if (auto Err = Ctx->modifyPassConfig(*G, Config))
+    return Ctx->notifyFailed(std::move(Err));
+
+  COFFJITLinker_arm64::link(std::move(Ctx), std::move(G), std::move(Config));
+}
+} // namespace jitlink
+} // namespace llvm
\ No newline at end of file
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/COFF_abs.s b/llvm/test/ExecutionEngine/JITLink/AArch64/COFF_abs.s
new file mode 100644
index 00000000000000..9c8efbc580897d
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/COFF_abs.s
@@ -0,0 +1,26 @@
+# REQUIRES: asserts
+# RUN: llvm-mc -filetype=obj -triple=aarch64-windows-msvc %s -o %t
+# RUN: llvm-jitlink --debug-only=jitlink -noexec %t 2>&1 | FileCheck %s
+#
+# Check absolute symbol is created with a correct value.
+#
+# CHECK: Creating graph symbols...
+# CHECK:   6: Creating defined graph symbol for COFF symbol "abs" in (absolute) (index: -1)
+# CHECK-NEXT:  0x53 (addressable + 0x00000000): size: 0x00000000, linkage: strong, scope: local, dead  -   abs
+
+	.text
+	.def	abs;
+	.scl	3;
+	.type	0;
+	.endef
+	.global  abs
+.set abs, 0x53
+
+	.def	main;
+	.scl	2;
+	.type	32;
+	.endef
+	.global	main
+	.p2align	2
+main:
+	ret
\ No newline at end of file
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/COFF_adrp.s b/llvm/test/ExecutionEngine/JITLink/AArch64/COFF_adrp.s
new file mode 100644
index 00000000000000..0712c2c87a8aa4
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/COFF_adrp.s
@@ -0,0 +1,32 @@
+# REQUIRES: asserts
+# RUN: llvm-mc -filetype=obj -triple=aarch64-windows-msvc %s -o %t
+# RUN: llvm-jitlink --debug-only=jitlink -noexec %t 2>&1 | FileCheck %s
+#
+# Check function  symbol is created with a correct value.
+#
+# CHECK: Creating graph symbols...
+# CHECK: 7: Creating defined graph symbol for COFF symbol "retv" in .bss (index: 3)
+# CHECK-NEXT: 0x0 (block + 0x00000000): size: 0x00000000, linkage: strong, scope: default, dead  -   retv
+#
+# CHECK: Processing relocations:
+# CHECK: .text:
+# CHECK-NEXT: edge at 0x0: 0x0 + 0x0 -- PageBase_Rel21 -> retv + -1879048184
+# CHECK-NEXT: edge at 0x4: 0x0 + 0x4 -- PageOffset_12L -> retv + -1186987776
+
+	.text
+	.def	main;
+	.scl	2;
+	.type	32;
+	.endef
+	.globl	main
+	.p2align	2
+main:
+	adrp	x8, retv
+	ldr	w0, [x8, :lo12:retv]
+	ret
+
+	.bss
+	.globl	retv
+	.p2align	2, 0x0
+retv:
+	.word	0
\ No newline at end of file
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/COFF_bl_branch26.s b/llvm/test/ExecutionEngine/JITLink/AArch64/COFF_bl_branch26.s
new file mode 100644
index 00000000000000..9939f27095e707
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/COFF_bl_branch26.s
@@ -0,0 +1,33 @@
+# REQUIRES: asserts
+# RUN: llvm-mc -filetype=obj -triple=aarch64-windows-msvc %s -o %t
+# RUN: llvm-jitlink --debug-only=jitlink -noexec %t 2>&1 | FileCheck %s
+#
+# Check function  symbol is created with a correct value.
+#
+# CHECK: Creating graph symbols...
+# CHECK: 6: Creating defined graph symbol for COFF symbol "foo" in .text (index: 1)
+# CHECK-NEXT: 0x0 (block + 0x00000000): size: 0x00000000, linkage: strong, scope: default, dead  -   foo
+#
+# CHECK: Processing relocations:
+# CHECK: .text:
+# CHECK-NEXT: edge at 0x4: 0x0 + 0x4 -- Branch26 -> foo + -1811939328
+
+	.text
+	.def	foo;
+	.scl	2;
+	.type	32;
+	.endef
+	.globl	foo
+	.p2align	2
+foo:
+	ret
+
+	.def	main;
+	.scl	2;
+	.type	32;
+	.endef
+	.globl	main
+	.p2align	2
+main:
+	bl	foo
+	ret
diff --git a/llvm/test/ExecutionEngine/JITLink/AArch64/COFF_cbz_branch19.s b/llvm/test/ExecutionEngine/JITLink/AArch64/COFF_cbz_branch19.s
new file mode 100644
index 00000000000000..8bb24fbf7676a8
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/AArch64/COFF_cbz_branch19.s
@@ -0,0 +1,33 @@
+# REQUIRES: asserts
+# RUN: llvm-mc -filetype=obj -triple=aarch64-windows-msvc %s -o %t
+# RUN: llvm-jitlink --debug-only=jitlink -noexec %t 2>&1 | FileCheck %s
+#
+# Check function  symbol is created with a correct value.
+#
+# CHECK: Creating graph symbols...
+# CHECK: 6: Creating defined graph symbol for COFF symbol "foo" in .text (index: 1)
+# CHECK-NEXT: 0x0 (block + 0x00000000): size: 0x00000000, linkage: strong, scope: default, dead  -   foo
+#
+# CHECK: Processing relocations:
+# CHECK: .text:
+# CHECK-NEXT:  edge at 0x4: 0x0 + 0x4 -- Branch19 -> foo + -622592
+
+    .text
+	.def	foo;
+	.scl	2;
+	.type	32;
+	.endef
+	.globl	foo
+	.p2align	2
+foo:
+	ret
+
+	.def	main;
+	.scl	2;
+	.type	32;
+	.endef
+	.globl	main
+	.p2align	2
+main:
+	cbz xzr, foo
+	ret
\ No newline at end of file
diff --git a/llvm/test/ExecutionEngine/JITLink/Generic/sectcreate.test b/llvm/test/ExecutionEngine/JITLink/Generic/sectcreate.test
index c09513a7d3707c..610cb7a14bc937 100644
--- a/llvm/test/ExecutionEngine/JITLink/Generic/sectcreate.test
+++ b/llvm/test/ExecutionEngine/JITLink/Generic/sectcreate.test
@@ -5,9 +5,6 @@
 #
 # Use -sectcreate to create a section from a data file.
 
-# Jitlink does not support ARM64 COFF files.
-# UNSUPPORTED: target=aarch64-pc-windows-{{.*}}
-
 # On MinGW targets, when compiling the main() function, it gets
 # an implicitly generated call to __main(), which is missing in
 # this context.



More information about the llvm-commits mailing list