[llvm] 2a3b257 - [JITLink][i386] Adds absolute and pc relative relocation support for ELF/i386.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Sun Oct 30 17:35:47 PDT 2022


Author: Kshitij Jain
Date: 2022-10-30T17:35:41-07:00
New Revision: 2a3b257a935aa49886ccd073695e75b385b3822f

URL: https://github.com/llvm/llvm-project/commit/2a3b257a935aa49886ccd073695e75b385b3822f
DIFF: https://github.com/llvm/llvm-project/commit/2a3b257a935aa49886ccd073695e75b385b3822f.diff

LOG: [JITLink][i386] Adds absolute and pc relative relocation support for ELF/i386.

This commit adds support for 32 bit absolute and pc relative relocations in
ELF/i386 objects, along with simple regression tests.

Reviewed By: sgraenitz, lhames

Differential Revision: https://reviews.llvm.org/D135523

Added: 
    llvm/test/ExecutionEngine/JITLink/i386/ELF_i386_absolute_relocations_32.s
    llvm/test/ExecutionEngine/JITLink/i386/ELF_i386_pc_relative_relocations_32.s

Modified: 
    llvm/include/llvm/ExecutionEngine/JITLink/i386.h
    llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
    llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
    llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp
    llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
    llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
    llvm/lib/ExecutionEngine/JITLink/i386.cpp
    llvm/test/ExecutionEngine/JITLink/i386/lit.local.cfg

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ExecutionEngine/JITLink/i386.h b/llvm/include/llvm/ExecutionEngine/JITLink/i386.h
index b8671168bd8a5..8698f0aad6238 100644
--- a/llvm/include/llvm/ExecutionEngine/JITLink/i386.h
+++ b/llvm/include/llvm/ExecutionEngine/JITLink/i386.h
@@ -14,25 +14,155 @@
 #define LLVM_EXECUTIONENGINE_JITLINK_I386_H
 
 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ExecutionEngine/JITLink/TableManager.h"
 
-namespace llvm {
-namespace jitlink {
-namespace i386 {
-
+namespace llvm::jitlink::i386 {
 /// Represets i386 fixups
 enum EdgeKind_i386 : Edge::Kind {
 
   /// None
   None = Edge::FirstRelocation,
 
+  /// A plain 32-bit pointer value relocation.
+  ///
+  /// Fixup expression:
+  ///   Fixup <- Target + Addend : uint32
+  ///
+  /// Errors:
+  ///   - The target must reside in the low 32-bits of the address space,
+  ///     otherwise an out-of-range error will be returned.
+  ///
+  Pointer32,
+
+  /// A 32-bit PC-relative relocation.
+  ///
+  /// Represents a data/control flow instruction using PC-relative addressing
+  /// to a target.
+  ///
+  /// The fixup expression for this kind includes an implicit offset to account
+  /// for the PC (unlike the Delta edges) so that a PCRel32 with a target
+  /// T and addend zero is a call/branch to the start (offset zero) of T.
+  ///
+  /// Fixup expression:
+  ///   Fixup <- Target - (Fixup + 4) + Addend : int32
+  ///
+  /// Errors:
+  ///   - The result of the fixup expression must fit into an int32, otherwise
+  ///     an out-of-range error will be returned.
+  ///
+  PCRel32,
+
+  /// A plain 16-bit pointer value relocation.
+  ///
+  /// Fixup expression:
+  ///   Fixup <- Target + Addend : uint16
+  ///
+  /// Errors:
+  ///   - The target must reside in the low 16-bits of the address space,
+  ///     otherwise an out-of-range error will be returned.
+  ///
+  Pointer16,
+
+  /// A 16-bit PC-relative relocation.
+  ///
+  /// Represents a data/control flow instruction using PC-relative addressing
+  /// to a target.
+  ///
+  /// The fixup expression for this kind includes an implicit offset to account
+  /// for the PC (unlike the Delta edges) so that a PCRel16 with a target
+  /// T and addend zero is a call/branch to the start (offset zero) of T.
+  ///
+  /// Fixup expression:
+  ///   Fixup <- Target - (Fixup + 4) + Addend : int16
+  ///
+  /// Errors:
+  ///   - The result of the fixup expression must fit into an int16, otherwise
+  ///     an out-of-range error will be returned.
+  ///
+  PCRel16,
+
+  /// A 64-bit GOT delta.
+  ///
+  /// Delta from the global offset table to the target.
+  ///
+  /// Fixup expression:
+  ///   Fixup <- Target - GOTSymbol + Addend : int32
+  ///
+  /// Errors:
+  ///   - *ASSERTION* Failure to a null pointer GOTSymbol, which the GOT section
+  ///     symbol was not been defined.
+  Delta32FromGOT,
 };
 
 /// Returns a string name for the given i386 edge. For debugging purposes
 /// only
 const char *getEdgeKindName(Edge::Kind K);
 
-} // namespace i386
-} // namespace jitlink
-} // namespace llvm
+/// Returns true if the given uint32_t value is in range for a uint16_t.
+inline bool isInRangeForImmU16(uint32_t Value) {
+  return Value <= std::numeric_limits<uint16_t>::max();
+}
+
+/// Returns true if the given int32_t value is in range for an int16_t.
+inline bool isInRangeForImmS16(int32_t Value) {
+  return (Value >= std::numeric_limits<int16_t>::min() &&
+          Value <= std::numeric_limits<int16_t>::max());
+}
+
+/// Apply fixup expression for edge to block content.
+inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E) {
+  using namespace i386;
+  using namespace llvm::support;
+
+  char *BlockWorkingMem = B.getAlreadyMutableContent().data();
+  char *FixupPtr = BlockWorkingMem + E.getOffset();
+  auto FixupAddress = B.getAddress() + E.getOffset();
+
+  switch (E.getKind()) {
+  case i386::None: {
+    break;
+  }
+
+  case i386::Pointer32: {
+    uint32_t Value = E.getTarget().getAddress().getValue() + E.getAddend();
+    *(ulittle32_t *)FixupPtr = Value;
+    break;
+  }
+
+  case i386::PCRel32: {
+    int32_t Value =
+        E.getTarget().getAddress() - (FixupAddress + 4) + E.getAddend();
+    *(little32_t *)FixupPtr = Value;
+    break;
+  }
+
+  case i386::Pointer16: {
+    uint32_t Value = E.getTarget().getAddress().getValue() + E.getAddend();
+    if (LLVM_LIKELY(isInRangeForImmU16(Value)))
+      *(ulittle16_t *)FixupPtr = Value;
+    else
+      return makeTargetOutOfRangeError(G, B, E);
+    break;
+  }
+
+  case i386::PCRel16: {
+    int32_t Value =
+        E.getTarget().getAddress() - (FixupAddress + 4) + E.getAddend();
+    if (LLVM_LIKELY(isInRangeForImmS16(Value)))
+      *(little16_t *)FixupPtr = Value;
+    else
+      return makeTargetOutOfRangeError(G, B, E);
+    break;
+  }
+
+  default:
+    return make_error<JITLinkError>(
+        "In graph " + G.getName() + ", section " + B.getSection().getName() +
+        "unsupported edge kind" + getEdgeKindName(E.getKind()));
+  }
+
+  return Error::success();
+}
+} // namespace llvm::jitlink::i386
 
 #endif // LLVM_EXECUTIONENGINE_JITLINK_I386_H

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
index 7f881966bcba2..8513283febc73 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/ELFLinkGraphBuilder.h
@@ -108,24 +108,49 @@ class ELFLinkGraphBuilder : public ELFLinkGraphBuilderBase {
   Error graphifySections();
   Error graphifySymbols();
 
-  /// Traverse all matching relocation records in the given section. The handler
-  /// function Func should be callable with this signature:
+  /// Traverse all matching ELFT::Rela relocation records in the given section.
+  /// The handler function Func should be callable with this signature:
   ///   Error(const typename ELFT::Rela &,
   ///         const typename ELFT::Shdr &, Section &)
   ///
-  template <typename RelocHandlerFunction>
-  Error forEachRelocation(const typename ELFT::Shdr &RelSect,
-                          RelocHandlerFunction &&Func,
-                          bool ProcessDebugSections = false);
+  template <typename RelocHandlerMethod>
+  Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
+                              RelocHandlerMethod &&Func,
+                              bool ProcessDebugSections = false);
+
+  /// Traverse all matching ELFT::Rel relocation records in the given section.
+  /// The handler function Func should be callable with this signature:
+  ///   Error(const typename ELFT::Rel &,
+  ///         const typename ELFT::Shdr &, Section &)
+  ///
+  template <typename RelocHandlerMethod>
+  Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
+                             RelocHandlerMethod &&Func,
+                             bool ProcessDebugSections = false);
+
+  /// Traverse all matching rela relocation records in the given section.
+  /// Convenience wrapper to allow passing a member function for the handler.
+  ///
+  template <typename ClassT, typename RelocHandlerMethod>
+  Error forEachRelaRelocation(const typename ELFT::Shdr &RelSect,
+                              ClassT *Instance, RelocHandlerMethod &&Method,
+                              bool ProcessDebugSections = false) {
+    return forEachRelaRelocation(
+        RelSect,
+        [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
+          return (Instance->*Method)(Rel, Target, GS);
+        },
+        ProcessDebugSections);
+  }
 
-  /// Traverse all matching relocation records in the given section. Convenience
-  /// wrapper to allow passing a member function for the handler.
+  /// Traverse all matching rel relocation records in the given section.
+  /// Convenience wrapper to allow passing a member function for the handler.
   ///
   template <typename ClassT, typename RelocHandlerMethod>
-  Error forEachRelocation(const typename ELFT::Shdr &RelSect, ClassT *Instance,
-                          RelocHandlerMethod &&Method,
-                          bool ProcessDebugSections = false) {
-    return forEachRelocation(
+  Error forEachRelRelocation(const typename ELFT::Shdr &RelSect,
+                             ClassT *Instance, RelocHandlerMethod &&Method,
+                             bool ProcessDebugSections = false) {
+    return forEachRelRelocation(
         RelSect,
         [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
           return (Instance->*Method)(Rel, Target, GS);
@@ -487,13 +512,12 @@ template <typename ELFT> Error ELFLinkGraphBuilder<ELFT>::graphifySymbols() {
 }
 
 template <typename ELFT>
-template <typename RelocHandlerFunction>
-Error ELFLinkGraphBuilder<ELFT>::forEachRelocation(
-    const typename ELFT::Shdr &RelSect, RelocHandlerFunction &&Func,
+template <typename RelocHandlerMethod>
+Error ELFLinkGraphBuilder<ELFT>::forEachRelaRelocation(
+    const typename ELFT::Shdr &RelSect, RelocHandlerMethod &&Func,
     bool ProcessDebugSections) {
-
   // Only look into sections that store relocation entries.
-  if (RelSect.sh_type != ELF::SHT_RELA && RelSect.sh_type != ELF::SHT_REL)
+  if (RelSect.sh_type != ELF::SHT_RELA)
     return Error::success();
 
   // sh_info contains the section header index of the target (FixupSection),
@@ -534,6 +558,53 @@ Error ELFLinkGraphBuilder<ELFT>::forEachRelocation(
   return Error::success();
 }
 
+template <typename ELFT>
+template <typename RelocHandlerMethod>
+Error ELFLinkGraphBuilder<ELFT>::forEachRelRelocation(
+    const typename ELFT::Shdr &RelSect, RelocHandlerMethod &&Func,
+    bool ProcessDebugSections) {
+  // Only look into sections that store relocation entries.
+  if (RelSect.sh_type != ELF::SHT_REL)
+    return Error::success();
+
+  // sh_info contains the section header index of the target (FixupSection),
+  // which is the section to which all relocations in RelSect apply.
+  auto FixupSection = Obj.getSection(RelSect.sh_info);
+  if (!FixupSection)
+    return FixupSection.takeError();
+
+  // Target sections have names in valid ELF object files.
+  Expected<StringRef> Name = Obj.getSectionName(**FixupSection);
+  if (!Name)
+    return Name.takeError();
+  LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");
+
+  // Consider skipping these relocations.
+  if (!ProcessDebugSections && isDwarfSection(*Name)) {
+    LLVM_DEBUG(dbgs() << "    skipped (dwarf section)\n\n");
+    return Error::success();
+  }
+
+  // Lookup the link-graph node corresponding to the target section name.
+  auto *BlockToFix = getGraphBlock(RelSect.sh_info);
+  if (!BlockToFix)
+    return make_error<StringError>(
+        "Refencing a section that wasn't added to the graph: " + *Name,
+        inconvertibleErrorCode());
+
+  auto RelEntries = Obj.rels(RelSect);
+  if (!RelEntries)
+    return RelEntries.takeError();
+
+  // Let the callee process relocation entries one by one.
+  for (const typename ELFT::Rel &R : *RelEntries)
+    if (Error Err = Func(R, **FixupSection, *BlockToFix))
+      return Err;
+
+  LLVM_DEBUG(dbgs() << "\n");
+  return Error::success();
+}
+
 } // end namespace jitlink
 } // end namespace llvm
 

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
index da998140a3fa5..a5548914f52d4 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
@@ -129,8 +129,8 @@ class ELFLinkGraphBuilder_aarch64 : public ELFLinkGraphBuilder<ELFT> {
     using Base = ELFLinkGraphBuilder<ELFT>;
     using Self = ELFLinkGraphBuilder_aarch64<ELFT>;
     for (const auto &RelSect : Base::Sections)
-      if (Error Err = Base::forEachRelocation(RelSect, this,
-                                              &Self::addSingleRelocation))
+      if (Error Err = Base::forEachRelaRelocation(RelSect, this,
+                                                  &Self::addSingleRelocation))
         return Err;
 
     return Error::success();

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp
index 3994c2223a7c7..a5c4d7e660bc5 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp
@@ -22,8 +22,7 @@
 using namespace llvm;
 using namespace llvm::jitlink;
 
-namespace llvm {
-namespace jitlink {
+namespace llvm::jitlink {
 
 class ELFJITLinker_i386 : public JITLinker<ELFJITLinker_i386> {
   friend class JITLinker<ELFJITLinker_i386>;
@@ -35,15 +34,7 @@ class ELFJITLinker_i386 : public JITLinker<ELFJITLinker_i386> {
 
 private:
   Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
-    using namespace i386;
-    using namespace llvm::support;
-
-    switch (E.getKind()) {
-    case i386::None: {
-      break;
-    }
-    }
-    return Error::success();
+    return i386::applyFixup(G, B, E);
   }
 };
 
@@ -55,6 +46,16 @@ class ELFLinkGraphBuilder_i386 : public ELFLinkGraphBuilder<ELFT> {
     switch (Type) {
     case ELF::R_386_NONE:
       return EdgeKind_i386::None;
+    case ELF::R_386_32:
+      return EdgeKind_i386::Pointer32;
+    case ELF::R_386_PC32:
+      return EdgeKind_i386::PCRel32;
+    case ELF::R_386_16:
+      return EdgeKind_i386::Pointer16;
+    case ELF::R_386_PC16:
+      return EdgeKind_i386::PCRel16;
+    case ELF::R_386_GOTPC:
+      return EdgeKind_i386::Delta32FromGOT;
     }
 
     return make_error<JITLinkError>("Unsupported i386 relocation:" +
@@ -63,6 +64,64 @@ class ELFLinkGraphBuilder_i386 : public ELFLinkGraphBuilder<ELFT> {
 
   Error addRelocations() override {
     LLVM_DEBUG(dbgs() << "Adding relocations\n");
+    using Base = ELFLinkGraphBuilder<ELFT>;
+    using Self = ELFLinkGraphBuilder_i386;
+
+    for (const auto &RelSect : Base::Sections) {
+      // Validate the section to read relocation entries from.
+      if (RelSect.sh_type == ELF::SHT_RELA)
+        return make_error<StringError>(
+            "No SHT_RELA in valid i386 ELF object files",
+            inconvertibleErrorCode());
+
+      if (Error Err = Base::forEachRelRelocation(RelSect, this,
+                                                 &Self::addSingleRelocation))
+        return Err;
+    }
+
+    return Error::success();
+  }
+
+  Error addSingleRelocation(const typename ELFT::Rel &Rel,
+                            const typename ELFT::Shdr &FixupSection,
+                            Block &BlockToFix) {
+    using Base = ELFLinkGraphBuilder<ELFT>;
+
+    uint32_t SymbolIndex = Rel.getSymbol(false);
+    auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
+    if (!ObjSymbol)
+      return ObjSymbol.takeError();
+
+    Symbol *GraphSymbol = Base::getGraphSymbol(SymbolIndex);
+    if (!GraphSymbol)
+      return make_error<StringError>(
+          formatv("Could not find symbol at given index, did you add it to "
+                  "JITSymbolTable? index: {0}, shndx: {1} Size of table: {2}",
+                  SymbolIndex, (*ObjSymbol)->st_shndx,
+                  Base::GraphSymbols.size()),
+          inconvertibleErrorCode());
+
+    Expected<i386::EdgeKind_i386> Kind = getRelocationKind(Rel.getType(false));
+    if (!Kind)
+      return Kind.takeError();
+
+    // TODO: To be removed when GOT relative relocations are supported.
+    if (*Kind == i386::EdgeKind_i386::Delta32FromGOT)
+      return Error::success();
+
+    int64_t Addend = 0;
+
+    auto FixupAddress = orc::ExecutorAddr(FixupSection.sh_addr) + Rel.r_offset;
+    Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
+    Edge GE(*Kind, Offset, *GraphSymbol, Addend);
+    LLVM_DEBUG({
+      dbgs() << "    ";
+      printEdge(dbgs(), BlockToFix, GE, i386::getEdgeKindName(*Kind));
+      dbgs() << "\n";
+    });
+
+    BlockToFix.addEdge(std::move(GE));
+
     return Error::success();
   }
 
@@ -110,5 +169,4 @@ void link_ELF_i386(std::unique_ptr<LinkGraph> G,
   ELFJITLinker_i386::link(std::move(Ctx), std::move(G), std::move(Config));
 }
 
-} // namespace jitlink
-} // namespace llvm
+} // namespace llvm::jitlink

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
index 36c736835a83c..740884fbcb276 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
@@ -482,8 +482,8 @@ class ELFLinkGraphBuilder_riscv : public ELFLinkGraphBuilder<ELFT> {
     using Base = ELFLinkGraphBuilder<ELFT>;
     using Self = ELFLinkGraphBuilder_riscv<ELFT>;
     for (const auto &RelSect : Base::Sections)
-      if (Error Err = Base::forEachRelocation(RelSect, this,
-                                              &Self::addSingleRelocation))
+      if (Error Err = Base::forEachRelaRelocation(RelSect, this,
+                                                  &Self::addSingleRelocation))
         return Err;
 
     return Error::success();

diff  --git a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
index a0d559b10bfbe..c9359522c2480 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
@@ -166,8 +166,8 @@ class ELFLinkGraphBuilder_x86_64 : public ELFLinkGraphBuilder<object::ELF64LE> {
             "No SHT_REL in valid x64 ELF object files",
             inconvertibleErrorCode());
 
-      if (Error Err = Base::forEachRelocation(RelSect, this,
-                                              &Self::addSingleRelocation))
+      if (Error Err = Base::forEachRelaRelocation(RelSect, this,
+                                                  &Self::addSingleRelocation))
         return Err;
     }
 

diff  --git a/llvm/lib/ExecutionEngine/JITLink/i386.cpp b/llvm/lib/ExecutionEngine/JITLink/i386.cpp
index c086830827fbe..e9e5ecc3754e5 100644
--- a/llvm/lib/ExecutionEngine/JITLink/i386.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/i386.cpp
@@ -14,17 +14,22 @@
 
 #define DEBUG_TYPE "jitlink"
 
-namespace llvm {
-namespace jitlink {
-namespace i386 {
+namespace llvm::jitlink::i386 {
 
 const char *getEdgeKindName(Edge::Kind K) {
   switch (K) {
   case None:
     return "None";
+  case Pointer32:
+    return "Pointer32";
+  case PCRel32:
+    return "PCRel32";
+  case Pointer16:
+    return "Pointer16";
+  case PCRel16:
+    return "PCRel16";
   }
   return getGenericEdgeKindName(K);
 }
-} // namespace i386
-} // namespace jitlink
-} // namespace llvm
+
+} // namespace llvm::jitlink::i386

diff  --git a/llvm/test/ExecutionEngine/JITLink/i386/ELF_i386_absolute_relocations_32.s b/llvm/test/ExecutionEngine/JITLink/i386/ELF_i386_absolute_relocations_32.s
new file mode 100644
index 0000000000000..40cb8d4147fd3
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/i386/ELF_i386_absolute_relocations_32.s
@@ -0,0 +1,25 @@
+# RUN: llvm-mc -triple=i386-unknown-linux-gnu -filetype=obj -o %t.o %s
+# RUN: llvm-jitlink -noexec %t.o
+
+        .text
+        .globl  main
+        .p2align        4
+        .type   main, at function
+main:
+    pushl   %ebp
+    movl    %esp, %ebp
+    pushl   %eax
+    movl    $0, -4(%ebp)
+    movl    a, %eax
+    addl    $4, %esp
+    popl    %ebp
+    retl
+
+        .size   main, .-main
+
+        .data
+        .p2align        2
+        .type   a, at object
+a:
+        .long   42
+        .size   a, 4
\ No newline at end of file

diff  --git a/llvm/test/ExecutionEngine/JITLink/i386/ELF_i386_pc_relative_relocations_32.s b/llvm/test/ExecutionEngine/JITLink/i386/ELF_i386_pc_relative_relocations_32.s
new file mode 100644
index 0000000000000..38be68a8d46b0
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/i386/ELF_i386_pc_relative_relocations_32.s
@@ -0,0 +1,31 @@
+# RUN: llvm-mc -triple=i386-unknown-linux-gnu -filetype=obj -o %t.o %s
+# RUN: llvm-jitlink -noexec %t.o
+
+        .text
+        .section        .text.main
+        .globl  main
+        .p2align        4
+        .type   main, at function
+main:
+    pushl   %ebp
+    movl    %esp, %ebp
+    subl    $8, %esp
+    movl    $0, -4(%ebp)
+    calll   foo
+    addl    $8, %esp
+    popl    %ebp
+    retl
+
+        .size   main, .-main
+
+        .section        .text.foo
+        .p2align        4
+        .type   foo, at function
+foo:
+    pushl   %ebp
+    movl    %esp, %ebp
+    movl    $42, %eax
+    popl    %ebp
+    retl
+
+    .size       foo, .-foo
\ No newline at end of file

diff  --git a/llvm/test/ExecutionEngine/JITLink/i386/lit.local.cfg b/llvm/test/ExecutionEngine/JITLink/i386/lit.local.cfg
index 88cde621da28c..afde89be896d4 100644
--- a/llvm/test/ExecutionEngine/JITLink/i386/lit.local.cfg
+++ b/llvm/test/ExecutionEngine/JITLink/i386/lit.local.cfg
@@ -1,2 +1,2 @@
-if not 'i386' in config.root.targets:
-  config.unsupported = True
\ No newline at end of file
+if not 'X86' in config.root.targets:
+  config.unsupported = True


        


More information about the llvm-commits mailing list