]> granicus.if.org Git - llvm/commitdiff
[WebAssembly] Initial linking metadata support
authorDan Gohman <dan433584@gmail.com>
Thu, 30 Mar 2017 23:58:19 +0000 (23:58 +0000)
committerDan Gohman <dan433584@gmail.com>
Thu, 30 Mar 2017 23:58:19 +0000 (23:58 +0000)
Add support for the new relocations and linking metadata section support in
https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md. In
particular, this allows LLVM to indicate which variable is the stack pointer,
so that it can be linked with other objects.

This also adds support for emitting type relocations for call_indirect
instructions.

Right now, this is mainly tested by using wabt and hexdump to examine the
output on selected testcases. We'll add more tests as the design stablizes
and more of the pieces are in place.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@299141 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/MachineModuleInfoImpls.h
include/llvm/Support/Wasm.h
include/llvm/Support/WasmRelocs/WebAssembly.def
lib/MC/WasmObjectWriter.cpp
lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.cpp
lib/Target/WebAssembly/InstPrinter/WebAssemblyInstPrinter.h
lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp

index 0dc190594c3bdc015a9565f04eb2110010ae0098..f28a79c5b5cca3c98b9c78dfd94b3ae267ade0a8 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "llvm/CodeGen/ValueTypes.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/Support/Wasm.h"
 
 namespace llvm {
 class MCSymbol;
@@ -79,9 +80,10 @@ public:
 /// MachineModuleInfoWasm - This is a MachineModuleInfoImpl implementation
 /// for Wasm targets.
 class MachineModuleInfoWasm : public MachineModuleInfoImpl {
-  /// GVStubs - These stubs are used to materialize global addresses in PIC
-  /// mode.
-  std::vector<MVT> Globals;
+  /// WebAssembly global variables defined by CodeGen.
+  std::vector<wasm::Global> Globals;
+
+  /// The WebAssembly global variable which is the stack pointer.
   unsigned StackPointerGlobal;
 
   virtual void anchor(); // Out of line virtual method.
@@ -89,8 +91,8 @@ public:
   MachineModuleInfoWasm(const MachineModuleInfo &)
     : StackPointerGlobal(-1U) {}
 
-  void addGlobal(MVT VT) { Globals.push_back(VT); }
-  const std::vector<MVT> &getGlobals() const { return Globals; }
+  void addGlobal(const wasm::Global &G) { Globals.push_back(G); }
+  const std::vector<wasm::Global> &getGlobals() const { return Globals; }
 
   bool hasStackPointerGlobal() const {
     return StackPointerGlobal != -1U;
index 99467ad3c63b1be32f60356ba538d7c496c82144..8e6c418c8189a3ca7b8a91787a2f0033149fc33e 100644 (file)
@@ -170,6 +170,11 @@ enum class ValType {
   F64 = WASM_TYPE_F64,
 };
 
+// Linking metadata kinds.
+enum : unsigned {
+  WASM_STACK_POINTER = 0x1,
+};
+
 #define WASM_RELOC(name, value) name = value,
 
 enum : unsigned {
@@ -178,6 +183,19 @@ enum : unsigned {
 
 #undef WASM_RELOC
 
+struct Global {
+  ValType Type;
+  bool Mutable;
+
+  // The initial value for this global is either the value of an imported
+  // global, in which case InitialModule and InitialName specify the global
+  // import, or a value, in which case InitialModule is empty and InitialValue
+  // holds the value.
+  StringRef InitialModule;
+  StringRef InitialName;
+  uint64_t InitialValue;
+};
+
 } // end namespace wasm
 } // end namespace llvm
 
index 798f74499fa30df447099aefd29253ca6556e8d9..da64e025478dee6077fffa0bedaea4b39852ade1 100644 (file)
@@ -9,3 +9,5 @@ WASM_RELOC(R_WEBASSEMBLY_TABLE_INDEX_I32,      2)
 WASM_RELOC(R_WEBASSEMBLY_GLOBAL_ADDR_LEB,      3)
 WASM_RELOC(R_WEBASSEMBLY_GLOBAL_ADDR_SLEB,     4)
 WASM_RELOC(R_WEBASSEMBLY_GLOBAL_ADDR_I32,      5)
+WASM_RELOC(R_WEBASSEMBLY_TYPE_INDEX_LEB,       6)
+WASM_RELOC(R_WEBASSEMBLY_GLOBAL_INDEX_LEB,     7)
index 0b703f4387b16a6a50e2fecdae9ffd4c48e87adf..548d99fe4b9e338353c707e7861f9dd060aa7fdb 100644 (file)
@@ -50,16 +50,6 @@ struct SectionBookkeeping {
   uint64_t ContentsOffset;
 };
 
-// This record records information about a call_indirect which needs its
-// type index fixed up once we've computed type indices.
-struct TypeIndexFixup {
-  uint64_t Offset;
-  const MCSymbolWasm *Symbol;
-  const MCSectionWasm *FixupSection;
-  TypeIndexFixup(uint64_t O, const MCSymbolWasm *S, MCSectionWasm *F)
-    : Offset(O), Symbol(S), FixupSection(F) {}
-};
-
 class WasmObjectWriter : public MCObjectWriter {
   /// Helper struct for containing some precomputed information on symbols.
   struct WasmSymbolData {
@@ -80,7 +70,7 @@ class WasmObjectWriter : public MCObjectWriter {
   std::vector<WasmRelocationEntry> DataRelocations;
 
   // Fixups for call_indirect type indices.
-  std::vector<TypeIndexFixup> TypeIndexFixups;
+  std::vector<WasmRelocationEntry> TypeIndexFixups;
 
   // Index values to use for fixing up call_indirect type indices.
   std::vector<uint32_t> TypeIndexFixupTypes;
@@ -269,8 +259,11 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
 
   if (RefA) {
     if (RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX) {
-      TypeIndexFixups.push_back(TypeIndexFixup(FixupOffset, SymA,
-                                               &FixupSection));
+      assert(C == 0);
+      WasmRelocationEntry Rec(FixupOffset, SymA, C,
+                              wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB,
+                              &FixupSection);
+      TypeIndexFixups.push_back(Rec);
       return;
     }
   }
@@ -358,7 +351,9 @@ struct WasmExport {
 struct WasmGlobal {
   wasm::ValType Type;
   bool IsMutable;
-  uint32_t InitialValue;
+  bool HasImport;
+  uint64_t InitialValue;
+  uint32_t ImportIndex;
 };
 
 } // end anonymous namespace
@@ -507,6 +502,29 @@ static void WriteRelocations(
   }
 }
 
+// Write out the the type relocation records that the linker will
+// need to handle.
+static void WriteTypeRelocations(
+    ArrayRef<WasmRelocationEntry> TypeIndexFixups,
+    ArrayRef<uint32_t> TypeIndexFixupTypes,
+    raw_pwrite_stream &Stream)
+{
+  for (size_t i = 0, e = TypeIndexFixups.size(); i < e; ++i) {
+    const WasmRelocationEntry &Fixup = TypeIndexFixups[i];
+    uint32_t Type = TypeIndexFixupTypes[i];
+
+    assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB);
+    assert(Fixup.Addend == 0);
+
+    uint64_t Offset = Fixup.Offset +
+                      Fixup.FixupSection->getSectionOffset();
+
+    encodeULEB128(Fixup.Type, Stream);
+    encodeULEB128(Offset, Stream);
+    encodeULEB128(Type, Stream);
+  }
+}
+
 void WasmObjectWriter::writeObject(MCAssembler &Asm,
                                    const MCAsmLayout &Layout) {
   MCContext &Ctx = Asm.getContext();
@@ -526,6 +544,8 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
   unsigned NumFuncImports = 0;
   unsigned NumGlobalImports = 0;
   SmallVector<char, 0> DataBytes;
+  uint32_t StackPointerGlobal = 0;
+  bool HasStackPointer = false;
 
   // Populate the IsAddressTaken set.
   for (WasmRelocationEntry RelEntry : CodeRelocations) {
@@ -605,15 +625,68 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
     if (!DataFrag.getFixups().empty())
       report_fatal_error("fixups not supported in .global_variables");
     const SmallVectorImpl<char> &Contents = DataFrag.getContents();
-    for (char p : Contents) {
+    for (const uint8_t *p = (const uint8_t *)Contents.data(),
+                     *end = (const uint8_t *)Contents.data() + Contents.size();
+         p != end; ) {
       WasmGlobal G;
-      G.Type = wasm::ValType(p);
-      G.IsMutable = true;
-      G.InitialValue = 0;
+      if (end - p < 3)
+        report_fatal_error("truncated global variable encoding");
+      G.Type = wasm::ValType(int8_t(*p++));
+      G.IsMutable = bool(*p++);
+      G.HasImport = bool(*p++);
+      if (G.HasImport) {
+        G.InitialValue = 0;
+
+        WasmImport Import;
+        Import.ModuleName = (const char *)p;
+        const uint8_t *nul = (const uint8_t *)memchr(p, '\0', end - p);
+        if (!nul)
+          report_fatal_error("global module name must be nul-terminated");
+        p = nul + 1;
+        nul = (const uint8_t *)memchr(p, '\0', end - p);
+        if (!nul)
+          report_fatal_error("global base name must be nul-terminated");
+        Import.FieldName = (const char *)p;
+        p = nul + 1;
+
+        Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
+        Import.Type = int32_t(G.Type);
+
+        G.ImportIndex = NumGlobalImports;
+        ++NumGlobalImports;
+
+        Imports.push_back(Import);
+      } else {
+        unsigned n;
+        G.InitialValue = decodeSLEB128(p, &n);
+        G.ImportIndex = 0;
+        if (n > end - p)
+          report_fatal_error("global initial value must be valid SLEB128");
+        p += n;
+      }
       Globals.push_back(G);
     }
   }
 
+  // In the special .stack_pointer section, we've encoded the stack pointer
+  // index.
+  MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", 0, 0);
+  if (!StackPtr->getFragmentList().empty()) {
+    if (StackPtr->getFragmentList().size() != 1)
+      report_fatal_error("only one .stack_pointer fragment supported");
+    const MCFragment &Frag = *StackPtr->begin();
+    if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
+      report_fatal_error("only data supported in .stack_pointer");
+    const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag);
+    if (!DataFrag.getFixups().empty())
+      report_fatal_error("fixups not supported in .stack_pointer");
+    const SmallVectorImpl<char> &Contents = DataFrag.getContents();
+    if (Contents.size() != 4)
+      report_fatal_error("only one entry supported in .stack_pointer");
+    HasStackPointer = true;
+    StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data();
+  }
+
   // Handle defined symbols.
   for (const MCSymbol &S : Asm.symbols()) {
     // Ignore unnamed temporary symbols, which aren't ever exported, imported,
@@ -712,7 +785,9 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
           WasmGlobal Global;
           Global.Type = PtrType;
           Global.IsMutable = false;
+          Global.HasImport = false;
           Global.InitialValue = DataSection.getSectionOffset();
+          Global.ImportIndex = 0;
           SymbolIndices[&WS] = Index;
           Globals.push_back(Global);
         }
@@ -736,7 +811,10 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
   }
 
   // Add types for indirect function calls.
-  for (const TypeIndexFixup &Fixup : TypeIndexFixups) {
+  for (const WasmRelocationEntry &Fixup : TypeIndexFixups) {
+    assert(Fixup.Addend == 0);
+    assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB);
+
     WasmFunctionType F;
     F.Returns = Fixup.Symbol->getReturns();
     F.Params = Fixup.Symbol->getParams();
@@ -793,7 +871,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
         encodeULEB128(Import.Type, getStream());
         break;
       case wasm::WASM_EXTERNAL_GLOBAL:
-        encodeSLEB128(Import.Type, getStream());
+        encodeSLEB128(int32_t(Import.Type), getStream());
         encodeULEB128(0, getStream()); // mutability
         break;
       default:
@@ -853,8 +931,15 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
       writeValueType(Global.Type);
       write8(Global.IsMutable);
 
-      write8(wasm::WASM_OPCODE_I32_CONST);
-      encodeSLEB128(Global.InitialValue, getStream()); // offset
+      if (Global.HasImport) {
+        assert(Global.InitialValue == 0);
+        write8(wasm::WASM_OPCODE_GET_GLOBAL);
+        encodeULEB128(Global.ImportIndex, getStream());
+      } else {
+        assert(Global.ImportIndex == 0);
+        write8(wasm::WASM_OPCODE_I32_CONST);
+        encodeSLEB128(Global.InitialValue, getStream()); // offset
+      }
       write8(wasm::WASM_OPCODE_END);
     }
 
@@ -944,7 +1029,9 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
       uint32_t Type = TypeIndexFixupTypes[i];
       unsigned Padding = PaddingFor5ByteULEB128(Type);
 
-      const TypeIndexFixup &Fixup = TypeIndexFixups[i];
+      const WasmRelocationEntry &Fixup = TypeIndexFixups[i];
+      assert(Fixup.Addend == 0);
+      assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB);
       uint64_t Offset = Fixup.Offset +
                         Fixup.FixupSection->getSectionOffset();
 
@@ -1021,6 +1108,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
     encodeULEB128(CodeRelocations.size(), getStream());
 
     WriteRelocations(CodeRelocations, getStream(), SymbolIndices);
+    WriteTypeRelocations(TypeIndexFixups, TypeIndexFixupTypes, getStream());
 
     endSection(Section);
   }
@@ -1038,6 +1126,18 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
     endSection(Section);
   }
 
+  // === Linking Metadata Section ==============================================
+  if (HasStackPointer) {
+    startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
+
+    encodeULEB128(1, getStream()); // count
+
+    encodeULEB128(wasm::WASM_STACK_POINTER, getStream()); // type
+    encodeULEB128(StackPointerGlobal, getStream()); // id
+
+    endSection(Section);
+  }
+
   // TODO: Translate the .comment section to the output.
 
   // TODO: Translate debug sections to the output.
index 0af13cffdb04a690b1075423722403276579a37e..26461e2728d880d9ed58d9fa2d77566462499681 100644 (file)
@@ -242,3 +242,18 @@ const char *llvm::WebAssembly::TypeToString(MVT Ty) {
     llvm_unreachable("unsupported type");
   }
 }
+
+const char *llvm::WebAssembly::TypeToString(wasm::ValType Type) {
+  switch (Type) {
+  case wasm::ValType::I32:
+    return "i32";
+  case wasm::ValType::I64:
+    return "i64";
+  case wasm::ValType::F32:
+    return "f32";
+  case wasm::ValType::F64:
+    return "f64";
+  default:
+    llvm_unreachable("unsupported type");
+  }
+}
index d11f99c1ff3912a0e0ede4abd1a6bb85b1d8d3fa..c6158720d62f1a4e62d8ef927ad2c2d31b7084d1 100644 (file)
@@ -18,6 +18,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/MachineValueType.h"
 #include "llvm/MC/MCInstPrinter.h"
+#include "llvm/Support/Wasm.h"
 
 namespace llvm {
 
@@ -50,6 +51,7 @@ public:
 namespace WebAssembly {
 
 const char *TypeToString(MVT Ty);
+const char *TypeToString(wasm::ValType Type);
 
 } // end namespace WebAssembly
 
index f3b6b100d65007eccbd1869b39eb7d0e50a7d6cb..ad59f2f405879e90cb8470c116b47243f1af3427 100644 (file)
@@ -25,7 +25,6 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Wasm.h"
 using namespace llvm;
 
 WebAssemblyTargetStreamer::WebAssemblyTargetStreamer(MCStreamer &S)
@@ -88,13 +87,31 @@ void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) {
   }
 }
 
-void WebAssemblyTargetAsmStreamer::emitGlobal(ArrayRef<MVT> Types) {
-  if (!Types.empty()) {
+void WebAssemblyTargetAsmStreamer::emitGlobal(
+    ArrayRef<wasm::Global> Globals) {
+  if (!Globals.empty()) {
     OS << "\t.globalvar  \t";
-    PrintTypes(OS, Types);
+
+    bool First = true;
+    for (const wasm::Global &G : Globals) {
+      if (First)
+        First = false;
+      else
+        OS << ", ";
+      OS << WebAssembly::TypeToString(G.Type);
+      if (!G.InitialModule.empty())
+        OS << '=' << G.InitialModule << ':' << G.InitialName;
+      else
+        OS << '=' << G.InitialValue;
+    }
+    OS << '\n';
   }
 }
 
+void WebAssemblyTargetAsmStreamer::emitStackPointer(uint32_t Index) {
+  OS << "\t.stack_pointer\t" << Index << '\n';
+}
+
 void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; }
 
 void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType(
@@ -135,10 +152,16 @@ void WebAssemblyTargetELFStreamer::emitLocal(ArrayRef<MVT> Types) {
     emitValueType(WebAssembly::toValType(Type));
 }
 
-void WebAssemblyTargetELFStreamer::emitGlobal(ArrayRef<MVT> Types) {
+void WebAssemblyTargetELFStreamer::emitGlobal(
+    ArrayRef<wasm::Global> Globals) {
   llvm_unreachable(".globalvar encoding not yet implemented");
 }
 
+void WebAssemblyTargetELFStreamer::emitStackPointer(
+    uint32_t Index) {
+  llvm_unreachable(".stack_pointer encoding not yet implemented");
+}
+
 void WebAssemblyTargetELFStreamer::emitEndFunc() {
   Streamer.EmitIntValue(WebAssembly::End, 1);
 }
@@ -190,15 +213,36 @@ void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<MVT> Types) {
   }
 }
 
-void WebAssemblyTargetWasmStreamer::emitGlobal(ArrayRef<MVT> Types) {
+void WebAssemblyTargetWasmStreamer::emitGlobal(
+    ArrayRef<wasm::Global> Globals) {
   // Encode the globals use by the funciton into the special .global_variables
   // section. This will later be decoded and turned into contents for the
   // Globals Section.
   Streamer.PushSection();
   Streamer.SwitchSection(Streamer.getContext()
                                  .getWasmSection(".global_variables", 0, 0));
-  for (MVT Ty : Types)
-    Streamer.EmitIntValue(int64_t(WebAssembly::toValType(Ty)), 1);
+  for (const wasm::Global &G : Globals) {
+    Streamer.EmitIntValue(int32_t(G.Type), 1);
+    Streamer.EmitIntValue(G.Mutable, 1);
+    if (G.InitialModule.empty()) {
+      Streamer.EmitIntValue(0, 1); // indicate that we have an int value
+      Streamer.EmitSLEB128IntValue(0);
+    } else {
+      Streamer.EmitIntValue(1, 1); // indicate that we have a module import
+      Streamer.EmitBytes(G.InitialModule);
+      Streamer.EmitIntValue(0, 1); // nul-terminate
+      Streamer.EmitBytes(G.InitialName);
+      Streamer.EmitIntValue(0, 1); // nul-terminate
+    }
+  }
+  Streamer.PopSection();
+}
+
+void WebAssemblyTargetWasmStreamer::emitStackPointer(uint32_t Index) {
+  Streamer.PushSection();
+  Streamer.SwitchSection(Streamer.getContext()
+                                 .getWasmSection(".stack_pointer", 0, 0));
+  Streamer.EmitIntValue(Index, 4);
   Streamer.PopSection();
 }
 
index bb9a9c90c3ab2f02ff9691b4ff535dda8360a751..68d6747298dfc537e8e4bfd6f6a759bc33b7f587 100644 (file)
@@ -38,7 +38,9 @@ public:
   /// .local
   virtual void emitLocal(ArrayRef<MVT> Types) = 0;
   /// .globalvar
-  virtual void emitGlobal(ArrayRef<MVT> Types) = 0;
+  virtual void emitGlobal(ArrayRef<wasm::Global> Globals) = 0;
+  /// .stack_pointer
+  virtual void emitStackPointer(uint32_t Index) = 0;
   /// .endfunc
   virtual void emitEndFunc() = 0;
   /// .functype
@@ -66,7 +68,8 @@ public:
   void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
   void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
   void emitLocal(ArrayRef<MVT> Types) override;
-  void emitGlobal(ArrayRef<MVT> Types) override;
+  void emitGlobal(ArrayRef<wasm::Global> Globals) override;
+  void emitStackPointer(uint32_t Index) override;
   void emitEndFunc() override;
   void emitIndirectFunctionType(StringRef name,
                                 SmallVectorImpl<MVT> &Params,
@@ -83,7 +86,8 @@ public:
   void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
   void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
   void emitLocal(ArrayRef<MVT> Types) override;
-  void emitGlobal(ArrayRef<MVT> Types) override;
+  void emitGlobal(ArrayRef<wasm::Global> Globals) override;
+  void emitStackPointer(uint32_t Index) override;
   void emitEndFunc() override;
   void emitIndirectFunctionType(StringRef name,
                                 SmallVectorImpl<MVT> &Params,
@@ -100,7 +104,8 @@ public:
   void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
   void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
   void emitLocal(ArrayRef<MVT> Types) override;
-  void emitGlobal(ArrayRef<MVT> Types) override;
+  void emitGlobal(ArrayRef<wasm::Global> Globals) override;
+  void emitStackPointer(uint32_t Index) override;
   void emitEndFunc() override;
   void emitIndirectFunctionType(StringRef name,
                                 SmallVectorImpl<MVT> &Params,
index c272eb4cbf57cedf7617408cf1e8213e8bd4c7fd..d9c2dba5bace33733cd095457d6a414a4be62fc3 100644 (file)
@@ -97,6 +97,8 @@ void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) {
   if (!TM.getTargetTriple().isOSBinFormatELF()) {
     MachineModuleInfoWasm &MMIW = MMI->getObjFileInfo<MachineModuleInfoWasm>();
     getTargetStreamer()->emitGlobal(MMIW.getGlobals());
+    if (MMIW.hasStackPointerGlobal())
+      getTargetStreamer()->emitStackPointer(MMIW.getStackPointerGlobal());
   }
 }
 
index 8b25285ad0d30704d3237e125f247f8d9422af34..4209bc333f230640d83efbc83a48743312defce1 100644 (file)
@@ -192,7 +192,16 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
     auto &MMIW = MF.getMMI().getObjFileInfo<MachineModuleInfoWasm>();
     if (!MMIW.hasStackPointerGlobal()) {
       MMIW.setStackPointerGlobal(MMIW.getGlobals().size());
-      MMIW.addGlobal(MVT::i32);
+
+      // Create the stack-pointer global. For now, just use the
+      // Emscripten/Binaryen ABI names.
+      wasm::Global G;
+      G.Type = wasm::ValType::I32;
+      G.Mutable = true;
+      G.InitialValue = 0;
+      G.InitialModule = "env";
+      G.InitialName = "STACKTOP";
+      MMIW.addGlobal(G);
     }
     BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::GET_GLOBAL_I32), SPReg)
         .addImm(MMIW.getStackPointerGlobal());