[llvm] f1fcd06 - [JITLink][COFF] Implement include/alternatename linker directive.

Sunho Kim via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 29 00:48:37 PDT 2022


Author: Sunho Kim
Date: 2022-07-29T16:48:29+09:00
New Revision: f1fcd06a2a29fc534cb9f365cb4a01559f3378ce

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

LOG: [JITLink][COFF] Implement include/alternatename linker directive.

Implements include/alternatename linker directive. Alternatename is used by static msvc runtime library. Alias symbol is technically incorrect (we have to search for external definition) but we don't have a way to represent this in jitlink/orc yet, this is solved in the following up patch.

Inlcude linker directive is used in ucrt to forcelly lookup the static initializer symbols so that they will be emitted. It's implemented as extenral symbols with live flag on that cause the lookup of these symbols.

Reviewed By: lhames

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

Added: 
    llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
    llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.h
    llvm/lib/ExecutionEngine/JITLink/COFFOptions.td
    llvm/test/ExecutionEngine/JITLink/X86/COFF_directive_alternatename.s
    llvm/test/ExecutionEngine/JITLink/X86/COFF_directive_alternatename_fail.s
    llvm/test/ExecutionEngine/JITLink/X86/COFF_directive_include.s

Modified: 
    llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
    llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp
    llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h

Removed: 
    


################################################################################
diff  --git a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
index 87892c080af25..a1dbb8a908752 100644
--- a/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/JITLink/CMakeLists.txt
@@ -1,3 +1,7 @@
+set(LLVM_TARGET_DEFINITIONS COFFOptions.td)
+tablegen(LLVM COFFOptions.inc -gen-opt-parser-defs)
+add_public_tablegen_target(JITLinkTableGen)
+
 add_llvm_component_library(LLVMJITLink
   DWARFRecordSectionSplitter.cpp
   EHFrameSupport.cpp
@@ -23,6 +27,7 @@ add_llvm_component_library(LLVMJITLink
 
   # COFF
   COFF.cpp
+  COFFDirectiveParser.cpp
   COFFLinkGraphBuilder.cpp
   COFF_x86_64.cpp
 
@@ -36,10 +41,12 @@ add_llvm_component_library(LLVMJITLink
 
   DEPENDS
   intrinsics_gen
+  JITLinkTableGen
 
   LINK_COMPONENTS
   BinaryFormat
   Object
+  Option
   OrcTargetProcess
   Support
   )

diff  --git a/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp b/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
new file mode 100644
index 0000000000000..b1247f7f8ba9f
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.cpp
@@ -0,0 +1,75 @@
+//===-- COFFDirectiveParser.cpp - JITLink coff directive parser --*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// MSVC COFF directive parser
+//
+//===----------------------------------------------------------------------===//
+
+#include "COFFDirectiveParser.h"
+
+using namespace llvm;
+using namespace jitlink;
+
+#define DEBUG_TYPE "jitlink"
+
+// Create prefix string literals used in Options.td
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "COFFOptions.inc"
+#undef PREFIX
+
+// Create table mapping all options defined in COFFOptions.td
+static const opt::OptTable::Info infoTable[] = {
+#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12)      \
+  {X1,                                                                         \
+   X2,                                                                         \
+   X10,                                                                        \
+   X11,                                                                        \
+   COFF_OPT_##ID,                                                              \
+   opt::Option::KIND##Class,                                                   \
+   X9,                                                                         \
+   X8,                                                                         \
+   COFF_OPT_##GROUP,                                                           \
+   COFF_OPT_##ALIAS,                                                           \
+   X7,                                                                         \
+   X12},
+#include "COFFOptions.inc"
+#undef OPTION
+};
+
+class COFFOptTable : public opt::OptTable {
+public:
+  COFFOptTable() : OptTable(infoTable, true) {}
+};
+
+static COFFOptTable optTable;
+
+Expected<opt::InputArgList> COFFDirectiveParser::parse(StringRef Str) {
+  SmallVector<StringRef, 16> Tokens;
+  SmallVector<const char *, 16> Buffer;
+  cl::TokenizeWindowsCommandLineNoCopy(Str, saver, Tokens);
+  for (StringRef Tok : Tokens) {
+    bool HasNul = Tok.end() != Str.end() && Tok.data()[Tok.size()] == '\0';
+    Buffer.push_back(HasNul ? Tok.data() : saver.save(Tok).data());
+  }
+
+  unsigned missingIndex;
+  unsigned missingCount;
+
+  auto Result = optTable.ParseArgs(Buffer, missingIndex, missingCount);
+
+  if (missingCount)
+    return make_error<JITLinkError>(Twine("COFF directive parsing failed: ") +
+                                    Result.getArgString(missingIndex) +
+                                    " missing argument");
+  LLVM_DEBUG({
+    for (auto *arg : Result.filtered(COFF_OPT_UNKNOWN))
+      dbgs() << "Unknown coff option argument: " << arg->getAsString(Result)
+             << "\n";
+  });
+  return Result;
+}

diff  --git a/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.h b/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.h
new file mode 100644
index 0000000000000..3e4eedc63d6b7
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/COFFDirectiveParser.h
@@ -0,0 +1,48 @@
+//===--- COFFDirectiveParser.h - JITLink coff directive parser --*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// MSVC COFF directive parser
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_COFFDIRECTIVEPARSER_H
+#define LLVM_EXECUTIONENGINE_JITLINK_COFFDIRECTIVEPARSER_H
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/StringSaver.h"
+
+namespace llvm {
+namespace jitlink {
+
+enum {
+  COFF_OPT_INVALID = 0,
+#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) COFF_OPT_##ID,
+#include "COFFOptions.inc"
+#undef OPTION
+};
+
+/// Parser for the MSVC specific preprocessor directives.
+/// https://docs.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp?view=msvc-160
+class COFFDirectiveParser {
+public:
+  Expected<opt::InputArgList> parse(StringRef Str);
+
+private:
+  llvm::BumpPtrAllocator bAlloc;
+  llvm::StringSaver saver{bAlloc};
+};
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_COFFDIRECTIVEPARSER_H
\ No newline at end of file

diff  --git a/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp
index 8fd644d3c3b05..76d1b4305b847 100644
--- a/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp
@@ -170,11 +170,16 @@ Error COFFLinkGraphBuilder::graphifySections() {
       if (auto Err = Obj.getSectionContents(*Sec, Data))
         return Err;
 
+      auto CharData = ArrayRef<char>(
+          reinterpret_cast<const char *>(Data.data()), Data.size());
+
+      if (SectionName == getDirectiveSectionName())
+        if (auto Err = handleDirectiveSection(
+                StringRef(CharData.data(), CharData.size())))
+          return Err;
+
       B = &G->createContentBlock(
-          *GraphSec,
-          ArrayRef<char>(reinterpret_cast<const char *>(Data.data()),
-                         Data.size()),
-          orc::ExecutorAddr(getSectionAddress(Obj, *Sec)),
+          *GraphSec, CharData, orc::ExecutorAddr(getSectionAddress(Obj, *Sec)),
           (*Sec)->getAlignment(), 0);
     }
 
@@ -224,30 +229,17 @@ Error COFFLinkGraphBuilder::graphifySymbols() {
                << " (index: " << SectionIndex << ") \n";
       });
     else if (Sym->isUndefined()) {
-      auto CreateExternalSymbol = [&](StringRef SymbolName) {
-        if (!ExternalSymbols.count(SymbolName))
-          ExternalSymbols[SymbolName] = &G->addExternalSymbol(
-              SymbolName, Sym->getValue(), Linkage::Strong);
-
-        LLVM_DEBUG({
-          dbgs() << "    " << SymIndex
-                 << ": Creating external graph symbol for COFF symbol \""
-                 << SymbolName << "\" in "
-                 << getCOFFSectionName(SectionIndex, Sec, *Sym)
-                 << " (index: " << SectionIndex << ") \n";
-        });
-        return ExternalSymbols[SymbolName];
-      };
       if (SymbolName.startswith(getDLLImportStubPrefix())) {
         if (Sym->getValue() != 0)
           return make_error<JITLinkError>(
               "DLL import symbol has non-zero offset");
 
-        auto ExternalSym = CreateExternalSymbol(
-            SymbolName.drop_front(getDLLImportStubPrefix().size()));
+        auto ExternalSym = createExternalSymbol(
+            SymIndex, SymbolName.drop_front(getDLLImportStubPrefix().size()),
+            *Sym, Sec);
         GSym = &createDLLImportEntry(SymbolName, *ExternalSym);
       } else
-        GSym = CreateExternalSymbol(SymbolName);
+        GSym = createExternalSymbol(SymIndex, SymbolName, *Sym, Sec);
     } else if (Sym->isWeakExternal()) {
       auto *WeakExternal = Sym->getAux<object::coff_aux_weak_external>();
       COFFSymbolIndex TagIndex = WeakExternal->TagIndex;
@@ -281,12 +273,52 @@ Error COFFLinkGraphBuilder::graphifySymbols() {
   if (auto Err = flushWeakAliasRequests())
     return Err;
 
+  if (auto Err = handleAlternateNames())
+    return Err;
+
   if (auto Err = calculateImplicitSizeOfSymbols())
     return Err;
 
   return Error::success();
 }
 
+Error COFFLinkGraphBuilder::handleDirectiveSection(StringRef Str) {
+  auto Parsed = DirectiveParser.parse(Str);
+  if (!Parsed)
+    return Parsed.takeError();
+  for (auto *Arg : *Parsed) {
+    StringRef S = Arg->getValue();
+    switch (Arg->getOption().getID()) {
+    case COFF_OPT_alternatename: {
+      StringRef From, To;
+      std::tie(From, To) = S.split('=');
+      if (From.empty() || To.empty())
+        return make_error<JITLinkError>(
+            "Invalid COFF /alternatename directive");
+      AlternateNames[From] = To;
+      break;
+    }
+    case COFF_OPT_incl: {
+      auto DataCopy = G->allocateString(S);
+      StringRef StrCopy(DataCopy.data(), DataCopy.size());
+      ExternalSymbols[StrCopy] =
+          &G->addExternalSymbol(StrCopy, 0, Linkage::Strong);
+      ExternalSymbols[StrCopy]->setLive(true);
+      break;
+    }
+    case COFF_OPT_export:
+      break;
+    default: {
+      LLVM_DEBUG({
+        dbgs() << "Unknown coff directive: " << Arg->getSpelling() << "\n";
+      });
+      break;
+    }
+    }
+  }
+  return Error::success();
+}
+
 Error COFFLinkGraphBuilder::flushWeakAliasRequests() {
   // Export the weak external symbols and alias it
   for (auto &WeakExternal : WeakExternalRequests) {
@@ -303,22 +335,18 @@ Error COFFLinkGraphBuilder::flushWeakAliasRequests() {
               ? Scope::Default
               : Scope::Local;
 
-      // FIXME: Support this when there's a way to handle this.
-      if (!Target->isDefined())
-        return make_error<JITLinkError>("Weak external symbol with external "
-                                        "symbol as alternative not supported.");
-
-      jitlink::Symbol *NewSymbol = &G->addDefinedSymbol(
-          Target->getBlock(), Target->getOffset(), WeakExternal.SymbolName,
-          Target->getSize(), Linkage::Weak, S, Target->isCallable(), false);
+      auto NewSymbol =
+          createAliasSymbol(WeakExternal.SymbolName, Linkage::Weak, S, *Target);
+      if (!NewSymbol)
+        return NewSymbol.takeError();
       setGraphSymbol(AliasSymbol->getSectionNumber(), WeakExternal.Alias,
-                     *NewSymbol);
+                     **NewSymbol);
       LLVM_DEBUG({
         dbgs() << "    " << WeakExternal.Alias
                << ": Creating weak external symbol for COFF symbol \""
                << WeakExternal.SymbolName << "\" in section "
                << AliasSymbol->getSectionNumber() << "\n";
-        dbgs() << "      " << *NewSymbol << "\n";
+        dbgs() << "      " << **NewSymbol << "\n";
       });
     } else
       return make_error<JITLinkError>("Weak symbol alias requested but actual "
@@ -328,6 +356,49 @@ Error COFFLinkGraphBuilder::flushWeakAliasRequests() {
   return Error::success();
 }
 
+Error COFFLinkGraphBuilder::handleAlternateNames() {
+  // FIXME: Use proper alias
+  for (auto &KeyValue : AlternateNames)
+    if (DefinedSymbols.count(KeyValue.second) &&
+        ExternalSymbols.count(KeyValue.first)) {
+      auto *Target = DefinedSymbols[KeyValue.second];
+      auto *Alias = ExternalSymbols[KeyValue.first];
+      G->makeDefined(*Alias, Target->getBlock(), Target->getOffset(),
+                     Target->getSize(), Linkage::Weak, Scope::Local, false);
+    }
+  return Error::success();
+}
+
+Symbol *COFFLinkGraphBuilder::createExternalSymbol(
+    COFFSymbolIndex SymIndex, StringRef SymbolName,
+    object::COFFSymbolRef Symbol, const object::coff_section *Section) {
+  if (!ExternalSymbols.count(SymbolName))
+    ExternalSymbols[SymbolName] =
+        &G->addExternalSymbol(SymbolName, Symbol.getValue(), Linkage::Strong);
+
+  LLVM_DEBUG({
+    dbgs() << "    " << SymIndex
+           << ": Creating external graph symbol for COFF symbol \""
+           << SymbolName << "\" in "
+           << getCOFFSectionName(Symbol.getSectionNumber(), Section, Symbol)
+           << " (index: " << Symbol.getSectionNumber() << ") \n";
+  });
+  return ExternalSymbols[SymbolName];
+}
+
+Expected<Symbol *> COFFLinkGraphBuilder::createAliasSymbol(StringRef SymbolName,
+                                                           Linkage L, Scope S,
+                                                           Symbol &Target) {
+  if (!Target.isDefined()) {
+    // FIXME: Support this when there's a way to handle this.
+    return make_error<JITLinkError>("Weak external symbol with external "
+                                    "symbol as alternative not supported.");
+  }
+  return &G->addDefinedSymbol(Target.getBlock(), Target.getOffset(), SymbolName,
+                              Target.getSize(), L, S, Target.isCallable(),
+                              false);
+}
+
 // In COFF, most of the defined symbols don't contain the size information.
 // Hence, we calculate the "implicit" size of symbol by taking the delta of
 // offsets of consecutive symbols within a block. We maintain a balanced tree
@@ -426,10 +497,11 @@ Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(
   if (Symbol.isExternal()) {
     // This is not a comdat sequence, export the symbol as it is
     if (!isComdatSection(Section)) {
-
-      return &G->addDefinedSymbol(
+      auto GSym = &G->addDefinedSymbol(
           *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Default,
           Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
+      DefinedSymbols[SymbolName] = GSym;
+      return GSym;
     } else {
       if (!PendingComdatExports[Symbol.getSectionNumber()])
         return make_error<JITLinkError>("No pending COMDAT export for symbol " +
@@ -557,8 +629,9 @@ COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex,
     dbgs() << "      " << *Target << "\n";
   });
   PendingComdatExport = None;
+  DefinedSymbols[SymbolName] = Target;
   return Target;
 }
 
 } // namespace jitlink
-} // namespace llvm
+} // namespace llvm
\ No newline at end of file

diff  --git a/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
index a571e5e6f4fe7..1fd881c595581 100644
--- a/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
+++ b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
@@ -18,6 +18,7 @@
 #include "llvm/ExecutionEngine/JITLink/JITLink.h"
 #include "llvm/Object/COFF.h"
 
+#include "COFFDirectiveParser.h"
 #include "EHFrameSupportImpl.h"
 #include "JITLinkGeneric.h"
 
@@ -133,6 +134,11 @@ class COFFLinkGraphBuilder {
 
   Section &getCommonSection();
 
+  Symbol *createExternalSymbol(COFFSymbolIndex SymIndex, StringRef SymbolName,
+                               object::COFFSymbolRef Symbol,
+                               const object::coff_section *Section);
+  Expected<Symbol *> createAliasSymbol(StringRef SymbolName, Linkage L, Scope S,
+                                       Symbol &Target);
   Expected<Symbol *> createDefinedSymbol(COFFSymbolIndex SymIndex,
                                          StringRef SymbolName,
                                          object::COFFSymbolRef Symbol,
@@ -143,7 +149,10 @@ class COFFLinkGraphBuilder {
   Expected<Symbol *> exportCOMDATSymbol(COFFSymbolIndex SymIndex,
                                         StringRef SymbolName,
                                         object::COFFSymbolRef Symbol);
+
+  Error handleDirectiveSection(StringRef Str);
   Error flushWeakAliasRequests();
+  Error handleAlternateNames();
   Error calculateImplicitSizeOfSymbols();
 
   static uint64_t getSectionAddress(const object::COFFObjectFile &Obj,
@@ -154,18 +163,22 @@ class COFFLinkGraphBuilder {
   static unsigned getPointerSize(const object::COFFObjectFile &Obj);
   static support::endianness getEndianness(const object::COFFObjectFile &Obj);
   static StringRef getDLLImportStubPrefix() { return "__imp_"; }
+  static StringRef getDirectiveSectionName() { return ".drectve"; }
   StringRef getCOFFSectionName(COFFSectionIndex SectionIndex,
                                const object::coff_section *Sec,
                                object::COFFSymbolRef Sym);
 
   const object::COFFObjectFile &Obj;
   std::unique_ptr<LinkGraph> G;
+  COFFDirectiveParser DirectiveParser;
 
   Section *CommonSection = nullptr;
   std::vector<Block *> GraphBlocks;
   std::vector<Symbol *> GraphSymbols;
 
+  DenseMap<StringRef, StringRef> AlternateNames;
   DenseMap<StringRef, Symbol *> ExternalSymbols;
+  DenseMap<StringRef, Symbol *> DefinedSymbols;
 };
 
 template <typename RelocHandlerFunction>

diff  --git a/llvm/lib/ExecutionEngine/JITLink/COFFOptions.td b/llvm/lib/ExecutionEngine/JITLink/COFFOptions.td
new file mode 100644
index 0000000000000..0a0ce2fc76dde
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/COFFOptions.td
@@ -0,0 +1,21 @@
+include "llvm/Option/OptParser.td"
+
+// link.exe accepts options starting with either a dash or a slash.
+
+// Flag that takes no arguments.
+class F<string name> : Flag<["/", "-", "/?", "-?"], name>;
+
+// Flag that takes one argument after ":".
+class P<string name> :
+      Joined<["/", "-", "/?", "-?"], name#":">;
+
+// Boolean flag which can be suffixed by ":no". Using it unsuffixed turns the
+// flag on and using it suffixed by ":no" turns it off.
+multiclass B_priv<string name> {
+  def "" : F<name>;
+  def _no : F<name#":no">;
+}
+
+def export  : P<"export">;
+def alternatename : P<"alternatename">;
+def incl : Joined<["/", "-", "/?", "-?"], "include:">;
\ No newline at end of file

diff  --git a/llvm/test/ExecutionEngine/JITLink/X86/COFF_directive_alternatename.s b/llvm/test/ExecutionEngine/JITLink/X86/COFF_directive_alternatename.s
new file mode 100644
index 0000000000000..3b24141ecd7b7
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/X86/COFF_directive_alternatename.s
@@ -0,0 +1,30 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc %s -o %t
+# RUN: llvm-jitlink --debug-only=jitlink -noexec %t
+#
+# Check object with alternatename directive does not fail, because
+# foo external symbol was resolved to foo_def.
+#
+
+	.text
+	
+	.def	 foo_def;
+	.scl	2;
+	.type	32;
+	.endef
+	.globl	foo_def
+	.p2align	4, 0x90
+foo_def:
+	retq
+
+	.def	main;
+	.scl	2;
+	.type	32;
+	.endef
+	.globl	main
+	.p2align	4, 0x90
+main:
+	callq foo
+	retq
+
+.section .drectve,"yn"
+.ascii "/alternatename:foo=foo_def"

diff  --git a/llvm/test/ExecutionEngine/JITLink/X86/COFF_directive_alternatename_fail.s b/llvm/test/ExecutionEngine/JITLink/X86/COFF_directive_alternatename_fail.s
new file mode 100644
index 0000000000000..4d10d9b767533
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/X86/COFF_directive_alternatename_fail.s
@@ -0,0 +1,30 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc %s -o %t
+# RUN: not llvm-jitlink --debug-only=jitlink -noexec %t 2>&1 | FileCheck %s
+#
+# Check object without alternatename directive fails because of
+# external symbol not found error.
+#
+# CHECK: error: Symbols not found: [ foo ]
+	.text
+	
+	.def	 foo_def;
+	.scl	2;
+	.type	32;
+	.endef
+	.globl	foo_def
+	.p2align	4, 0x90
+foo_def:
+	retq
+
+	.def	main;
+	.scl	2;
+	.type	32;
+	.endef
+	.globl	main
+	.p2align	4, 0x90
+main:
+	callq foo
+	retq
+
+
+

diff  --git a/llvm/test/ExecutionEngine/JITLink/X86/COFF_directive_include.s b/llvm/test/ExecutionEngine/JITLink/X86/COFF_directive_include.s
new file mode 100644
index 0000000000000..53819cd796586
--- /dev/null
+++ b/llvm/test/ExecutionEngine/JITLink/X86/COFF_directive_include.s
@@ -0,0 +1,22 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc %s -o %t
+# RUN: not llvm-jitlink --debug-only=jitlink -noexec %t 2>&1 | FileCheck %s
+#
+# Check an external symbol "foo" is generated and not dead-stripped
+# because of include directive which turned into symbol not found error.
+#
+# CHECK: error: Symbols not found: [ foo ]
+
+	.text
+
+	.def	main;
+	.scl	2;
+	.type	32;
+	.endef
+	.globl	main
+	.p2align	4, 0x90
+main:
+	retq
+
+	.section .drectve,"yn"
+	.ascii "/include:foo"
+


        


More information about the llvm-commits mailing list