[lld] 3b29376 - [WebAssembly] Adding 64-bit version of R_WASM_MEMORY_ADDR_* relocs

Wouter van Oortmerssen via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 15 10:08:08 PDT 2020


Author: Wouter van Oortmerssen
Date: 2020-06-15T10:07:42-07:00
New Revision: 3b29376e3fca4305ea470ee142cad1296103297b

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

LOG: [WebAssembly] Adding 64-bit version of R_WASM_MEMORY_ADDR_* relocs

This adds 4 new reloc types.

A lot of code that previously assumed any memory or offset values could be contained in a uint32_t (and often truncated results from functions returning 64-bit values) have been upgraded to uint64_t. This is not comprehensive: it is only the values that come in contact with the new relocation values and their dependents.

A new tablegen mapping was added to automatically upgrade loads/stores in the assembler, which otherwise has no way to select for these instructions (since they are indentical other than for the offset immediate). It follows a similar technique to https://reviews.llvm.org/D53307

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

Added: 
    

Modified: 
    lld/wasm/InputChunks.cpp
    lld/wasm/InputFiles.cpp
    lld/wasm/InputFiles.h
    lld/wasm/Relocations.cpp
    lld/wasm/SymbolTable.cpp
    lld/wasm/SymbolTable.h
    lld/wasm/Symbols.cpp
    lld/wasm/Symbols.h
    lld/wasm/SyntheticSections.cpp
    lld/wasm/Writer.cpp
    lld/wasm/WriterUtils.cpp
    lld/wasm/WriterUtils.h
    llvm/include/llvm/BinaryFormat/Wasm.h
    llvm/include/llvm/BinaryFormat/WasmRelocs.def
    llvm/include/llvm/ObjectYAML/WasmYAML.h
    llvm/lib/BinaryFormat/Wasm.cpp
    llvm/lib/MC/WasmObjectWriter.cpp
    llvm/lib/Object/RelocationResolver.cpp
    llvm/lib/Object/WasmObjectFile.cpp
    llvm/lib/ObjectYAML/WasmEmitter.cpp
    llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
    llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
    llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
    llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.cpp
    llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.h
    llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td
    llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td
    llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
    llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
    llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
    llvm/test/MC/WebAssembly/wasm64.s
    llvm/tools/llvm-readobj/WasmDumper.cpp

Removed: 
    


################################################################################
diff  --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp
index 81ca83d40e39..abea11bd805b 100644
--- a/lld/wasm/InputChunks.cpp
+++ b/lld/wasm/InputChunks.cpp
@@ -46,9 +46,9 @@ StringRef InputChunk::getComdatName() const {
 
 void InputChunk::verifyRelocTargets() const {
   for (const WasmRelocation &rel : relocations) {
-    uint32_t existingValue;
+    uint64_t existingValue;
     unsigned bytesRead = 0;
-    uint32_t offset = rel.Offset - getInputSectionOffset();
+    auto offset = rel.Offset - getInputSectionOffset();
     const uint8_t *loc = data().data() + offset;
     switch (rel.Type) {
     case R_WASM_TYPE_INDEX_LEB:
@@ -56,20 +56,26 @@ void InputChunk::verifyRelocTargets() const {
     case R_WASM_GLOBAL_INDEX_LEB:
     case R_WASM_EVENT_INDEX_LEB:
     case R_WASM_MEMORY_ADDR_LEB:
+    case R_WASM_MEMORY_ADDR_LEB64:
       existingValue = decodeULEB128(loc, &bytesRead);
       break;
     case R_WASM_TABLE_INDEX_SLEB:
     case R_WASM_TABLE_INDEX_REL_SLEB:
     case R_WASM_MEMORY_ADDR_SLEB:
+    case R_WASM_MEMORY_ADDR_SLEB64:
     case R_WASM_MEMORY_ADDR_REL_SLEB:
-      existingValue = static_cast<uint32_t>(decodeSLEB128(loc, &bytesRead));
+    case R_WASM_MEMORY_ADDR_REL_SLEB64:
+      existingValue = static_cast<uint64_t>(decodeSLEB128(loc, &bytesRead));
       break;
     case R_WASM_TABLE_INDEX_I32:
     case R_WASM_MEMORY_ADDR_I32:
     case R_WASM_FUNCTION_OFFSET_I32:
     case R_WASM_SECTION_OFFSET_I32:
     case R_WASM_GLOBAL_INDEX_I32:
-      existingValue = static_cast<uint32_t>(read32le(loc));
+      existingValue = read32le(loc);
+      break;
+    case R_WASM_MEMORY_ADDR_I64:
+      existingValue = read64le(loc);
       break;
     default:
       llvm_unreachable("unknown relocation type");
@@ -80,7 +86,7 @@ void InputChunk::verifyRelocTargets() const {
 
     if (rel.Type != R_WASM_GLOBAL_INDEX_LEB &&
         rel.Type != R_WASM_GLOBAL_INDEX_I32) {
-      uint32_t expectedValue = file->calcExpectedValue(rel);
+      auto expectedValue = file->calcExpectedValue(rel);
       if (expectedValue != existingValue)
         warn("unexpected existing value for " + relocTypeToString(rel.Type) +
              ": existing=" + Twine(existingValue) +
@@ -108,7 +114,7 @@ void InputChunk::writeTo(uint8_t *buf) const {
 
   for (const WasmRelocation &rel : relocations) {
     uint8_t *loc = buf + rel.Offset + off;
-    uint32_t value = file->calcNewValue(rel);
+    auto value = file->calcNewValue(rel);
     LLVM_DEBUG(dbgs() << "apply reloc: type=" << relocTypeToString(rel.Type));
     if (rel.Type != R_WASM_TYPE_INDEX_LEB)
       LLVM_DEBUG(dbgs() << " sym=" << file->getSymbols()[rel.Index]->getName());
@@ -124,12 +130,19 @@ void InputChunk::writeTo(uint8_t *buf) const {
     case R_WASM_MEMORY_ADDR_LEB:
       encodeULEB128(value, loc, 5);
       break;
+    case R_WASM_MEMORY_ADDR_LEB64:
+      encodeULEB128(value, loc, 10);
+      break;
     case R_WASM_TABLE_INDEX_SLEB:
     case R_WASM_TABLE_INDEX_REL_SLEB:
     case R_WASM_MEMORY_ADDR_SLEB:
     case R_WASM_MEMORY_ADDR_REL_SLEB:
       encodeSLEB128(static_cast<int32_t>(value), loc, 5);
       break;
+    case R_WASM_MEMORY_ADDR_SLEB64:
+    case R_WASM_MEMORY_ADDR_REL_SLEB64:
+      encodeSLEB128(static_cast<int64_t>(value), loc, 10);
+      break;
     case R_WASM_TABLE_INDEX_I32:
     case R_WASM_MEMORY_ADDR_I32:
     case R_WASM_FUNCTION_OFFSET_I32:
@@ -137,6 +150,9 @@ void InputChunk::writeTo(uint8_t *buf) const {
     case R_WASM_GLOBAL_INDEX_I32:
       write32le(loc, value);
       break;
+    case R_WASM_MEMORY_ADDR_I64:
+      write64le(loc, value);
+      break;
     default:
       llvm_unreachable("unknown relocation type");
     }
@@ -181,17 +197,19 @@ void InputFunction::setTableIndex(uint32_t index) {
 // Write a relocation value without padding and return the number of bytes
 // witten.
 static unsigned writeCompressedReloc(uint8_t *buf, const WasmRelocation &rel,
-                                     uint32_t value) {
+                                     uint64_t value) {
   switch (rel.Type) {
   case R_WASM_TYPE_INDEX_LEB:
   case R_WASM_FUNCTION_INDEX_LEB:
   case R_WASM_GLOBAL_INDEX_LEB:
   case R_WASM_EVENT_INDEX_LEB:
   case R_WASM_MEMORY_ADDR_LEB:
+  case R_WASM_MEMORY_ADDR_LEB64:
     return encodeULEB128(value, buf);
   case R_WASM_TABLE_INDEX_SLEB:
   case R_WASM_MEMORY_ADDR_SLEB:
-    return encodeSLEB128(static_cast<int32_t>(value), buf);
+  case R_WASM_MEMORY_ADDR_SLEB64:
+    return encodeSLEB128(static_cast<int64_t>(value), buf);
   default:
     llvm_unreachable("unexpected relocation type");
   }
@@ -207,13 +225,16 @@ static unsigned getRelocWidthPadded(const WasmRelocation &rel) {
   case R_WASM_TABLE_INDEX_SLEB:
   case R_WASM_MEMORY_ADDR_SLEB:
     return 5;
+  case R_WASM_MEMORY_ADDR_LEB64:
+  case R_WASM_MEMORY_ADDR_SLEB64:
+    return 10;
   default:
     llvm_unreachable("unexpected relocation type");
   }
 }
 
-static unsigned getRelocWidth(const WasmRelocation &rel, uint32_t value) {
-  uint8_t buf[5];
+static unsigned getRelocWidth(const WasmRelocation &rel, uint64_t value) {
+  uint8_t buf[10];
   return writeCompressedReloc(buf, rel, value);
 }
 

diff  --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp
index 7390575242fc..d6f01578465f 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -101,12 +101,16 @@ uint32_t ObjFile::calcNewIndex(const WasmRelocation &reloc) const {
 
 // Relocations can contain addend for combined sections. This function takes a
 // relocation and returns updated addend by offset in the output section.
-uint32_t ObjFile::calcNewAddend(const WasmRelocation &reloc) const {
+uint64_t ObjFile::calcNewAddend(const WasmRelocation &reloc) const {
   switch (reloc.Type) {
   case R_WASM_MEMORY_ADDR_LEB:
+  case R_WASM_MEMORY_ADDR_LEB64:
+  case R_WASM_MEMORY_ADDR_SLEB64:
   case R_WASM_MEMORY_ADDR_SLEB:
   case R_WASM_MEMORY_ADDR_REL_SLEB:
+  case R_WASM_MEMORY_ADDR_REL_SLEB64:
   case R_WASM_MEMORY_ADDR_I32:
+  case R_WASM_MEMORY_ADDR_I64:
   case R_WASM_FUNCTION_OFFSET_I32:
     return reloc.Addend;
   case R_WASM_SECTION_OFFSET_I32:
@@ -119,7 +123,7 @@ uint32_t ObjFile::calcNewAddend(const WasmRelocation &reloc) const {
 // Calculate the value we expect to find at the relocation location.
 // This is used as a sanity check before applying a relocation to a given
 // location.  It is useful for catching bugs in the compiler and linker.
-uint32_t ObjFile::calcExpectedValue(const WasmRelocation &reloc) const {
+uint64_t ObjFile::calcExpectedValue(const WasmRelocation &reloc) const {
   switch (reloc.Type) {
   case R_WASM_TABLE_INDEX_I32:
   case R_WASM_TABLE_INDEX_SLEB: {
@@ -130,17 +134,27 @@ uint32_t ObjFile::calcExpectedValue(const WasmRelocation &reloc) const {
     const WasmSymbol &sym = wasmObj->syms()[reloc.Index];
     return tableEntriesRel[sym.Info.ElementIndex];
   }
+  case R_WASM_MEMORY_ADDR_LEB:
+  case R_WASM_MEMORY_ADDR_LEB64:
   case R_WASM_MEMORY_ADDR_SLEB:
+  case R_WASM_MEMORY_ADDR_SLEB64:
+  case R_WASM_MEMORY_ADDR_REL_SLEB:
+  case R_WASM_MEMORY_ADDR_REL_SLEB64:
   case R_WASM_MEMORY_ADDR_I32:
-  case R_WASM_MEMORY_ADDR_LEB:
-  case R_WASM_MEMORY_ADDR_REL_SLEB: {
+  case R_WASM_MEMORY_ADDR_I64: {
     const WasmSymbol &sym = wasmObj->syms()[reloc.Index];
     if (sym.isUndefined())
       return 0;
     const WasmSegment &segment =
         wasmObj->dataSegments()[sym.Info.DataRef.Segment];
-    return segment.Data.Offset.Value.Int32 + sym.Info.DataRef.Offset +
-           reloc.Addend;
+    if (segment.Data.Offset.Opcode == WASM_OPCODE_I32_CONST)
+      return segment.Data.Offset.Value.Int32 + sym.Info.DataRef.Offset +
+             reloc.Addend;
+    else if (segment.Data.Offset.Opcode == WASM_OPCODE_I64_CONST)
+      return segment.Data.Offset.Value.Int64 + sym.Info.DataRef.Offset +
+             reloc.Addend;
+    else
+      llvm_unreachable("unknown init expr opcode");
   }
   case R_WASM_FUNCTION_OFFSET_I32: {
     const WasmSymbol &sym = wasmObj->syms()[reloc.Index];
@@ -166,7 +180,7 @@ uint32_t ObjFile::calcExpectedValue(const WasmRelocation &reloc) const {
 }
 
 // Translate from the relocation's index into the final linked output value.
-uint32_t ObjFile::calcNewValue(const WasmRelocation &reloc) const {
+uint64_t ObjFile::calcNewValue(const WasmRelocation &reloc) const {
   const Symbol* sym = nullptr;
   if (reloc.Type != R_WASM_TYPE_INDEX_LEB) {
     sym = symbols[reloc.Index];
@@ -191,10 +205,14 @@ uint32_t ObjFile::calcNewValue(const WasmRelocation &reloc) const {
     return index;
 
   }
-  case R_WASM_MEMORY_ADDR_SLEB:
-  case R_WASM_MEMORY_ADDR_I32:
   case R_WASM_MEMORY_ADDR_LEB:
+  case R_WASM_MEMORY_ADDR_LEB64:
+  case R_WASM_MEMORY_ADDR_SLEB:
+  case R_WASM_MEMORY_ADDR_SLEB64:
   case R_WASM_MEMORY_ADDR_REL_SLEB:
+  case R_WASM_MEMORY_ADDR_REL_SLEB64:
+  case R_WASM_MEMORY_ADDR_I32:
+  case R_WASM_MEMORY_ADDR_I64:
     if (isa<UndefinedData>(sym) || sym->isUndefWeak())
       return 0;
     return cast<DefinedData>(sym)->getVirtualAddress() + reloc.Addend;
@@ -211,8 +229,8 @@ uint32_t ObjFile::calcNewValue(const WasmRelocation &reloc) const {
     return getEventSymbol(reloc.Index)->getEventIndex();
   case R_WASM_FUNCTION_OFFSET_I32: {
     auto *f = cast<DefinedFunction>(sym);
-    return f->function->outputOffset + f->function->getFunctionCodeOffset() +
-           reloc.Addend;
+    return f->function->outputOffset +
+           (f->function->getFunctionCodeOffset() + reloc.Addend);
   }
   case R_WASM_SECTION_OFFSET_I32:
     return getSectionSymbol(reloc.Index)->section->outputOffset + reloc.Addend;
@@ -272,12 +290,15 @@ void ObjFile::parse(bool ignoreComdats) {
   tableEntriesRel.resize(totalFunctions);
   tableEntries.resize(totalFunctions);
   for (const WasmElemSegment &seg : wasmObj->elements()) {
-    if (seg.Offset.Opcode != WASM_OPCODE_I32_CONST)
+    int64_t offset;
+    if (seg.Offset.Opcode == WASM_OPCODE_I32_CONST)
+      offset = seg.Offset.Value.Int32;
+    else if (seg.Offset.Opcode == WASM_OPCODE_I64_CONST)
+      offset = seg.Offset.Value.Int64;
+    else
       fatal(toString(this) + ": invalid table elements");
-    uint32_t offset = seg.Offset.Value.Int32;
-    for (uint32_t index = 0; index < seg.Functions.size(); index++) {
-
-      uint32_t functionIndex = seg.Functions[index];
+    for (size_t index = 0; index < seg.Functions.size(); index++) {
+      auto functionIndex = seg.Functions[index];
       tableEntriesRel[functionIndex] = index;
       tableEntries[functionIndex] = offset + index;
     }
@@ -411,8 +432,8 @@ Symbol *ObjFile::createDefined(const WasmSymbol &sym) {
   }
   case WASM_SYMBOL_TYPE_DATA: {
     InputSegment *seg = segments[sym.Info.DataRef.Segment];
-    uint32_t offset = sym.Info.DataRef.Offset;
-    uint32_t size = sym.Info.DataRef.Size;
+    auto offset = sym.Info.DataRef.Offset;
+    auto size = sym.Info.DataRef.Size;
     if (sym.isBindingLocal())
       return make<DefinedData>(name, flags, this, seg, offset, size);
     if (seg->discarded)

diff  --git a/lld/wasm/InputFiles.h b/lld/wasm/InputFiles.h
index 661aa8963e54..eb3205671af3 100644
--- a/lld/wasm/InputFiles.h
+++ b/lld/wasm/InputFiles.h
@@ -103,9 +103,9 @@ class ObjFile : public InputFile {
   void dumpInfo() const;
 
   uint32_t calcNewIndex(const WasmRelocation &reloc) const;
-  uint32_t calcNewValue(const WasmRelocation &reloc) const;
-  uint32_t calcNewAddend(const WasmRelocation &reloc) const;
-  uint32_t calcExpectedValue(const WasmRelocation &reloc) const;
+  uint64_t calcNewValue(const WasmRelocation &reloc) const;
+  uint64_t calcNewAddend(const WasmRelocation &reloc) const;
+  uint64_t calcExpectedValue(const WasmRelocation &reloc) const;
   Symbol *getSymbol(const WasmRelocation &reloc) const {
     return symbols[reloc.Index];
   };

diff  --git a/lld/wasm/Relocations.cpp b/lld/wasm/Relocations.cpp
index e49acec244c1..4cc4fff91cd9 100644
--- a/lld/wasm/Relocations.cpp
+++ b/lld/wasm/Relocations.cpp
@@ -88,6 +88,8 @@ void scanRelocations(InputChunk *chunk) {
       case R_WASM_TABLE_INDEX_SLEB:
       case R_WASM_MEMORY_ADDR_SLEB:
       case R_WASM_MEMORY_ADDR_LEB:
+      case R_WASM_MEMORY_ADDR_SLEB64:
+      case R_WASM_MEMORY_ADDR_LEB64:
         // Certain relocation types can't be used when building PIC output,
         // since they would require absolute symbol addresses at link time.
         error(toString(file) + ": relocation " + relocTypeToString(reloc.Type) +
@@ -96,6 +98,7 @@ void scanRelocations(InputChunk *chunk) {
         break;
       case R_WASM_TABLE_INDEX_I32:
       case R_WASM_MEMORY_ADDR_I32:
+      case R_WASM_MEMORY_ADDR_I64:
         // These relocation types are only present in the data section and
         // will be converted into code by `generateRelocationCode`.  This code
         // requires the symbols to have GOT entires.

diff  --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp
index 3933b7d96f73..f233646cbb65 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -327,7 +327,7 @@ Symbol *SymbolTable::addDefinedFunction(StringRef name, uint32_t flags,
 
 Symbol *SymbolTable::addDefinedData(StringRef name, uint32_t flags,
                                     InputFile *file, InputSegment *segment,
-                                    uint32_t address, uint32_t size) {
+                                    uint64_t address, uint64_t size) {
   LLVM_DEBUG(dbgs() << "addDefinedData:" << name << " addr:" << address
                     << "\n");
   Symbol *s;

diff  --git a/lld/wasm/SymbolTable.h b/lld/wasm/SymbolTable.h
index 522ea46b38bc..8d0ad7744829 100644
--- a/lld/wasm/SymbolTable.h
+++ b/lld/wasm/SymbolTable.h
@@ -53,8 +53,8 @@ class SymbolTable {
   Symbol *addDefinedFunction(StringRef name, uint32_t flags, InputFile *file,
                              InputFunction *function);
   Symbol *addDefinedData(StringRef name, uint32_t flags, InputFile *file,
-                         InputSegment *segment, uint32_t address,
-                         uint32_t size);
+                         InputSegment *segment, uint64_t address,
+                         uint64_t size);
   Symbol *addDefinedGlobal(StringRef name, uint32_t flags, InputFile *file,
                            InputGlobal *g);
   Symbol *addDefinedEvent(StringRef name, uint32_t flags, InputFile *file,

diff  --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp
index 7112db6b0826..33923fb3e9f4 100644
--- a/lld/wasm/Symbols.cpp
+++ b/lld/wasm/Symbols.cpp
@@ -252,7 +252,7 @@ DefinedFunction::DefinedFunction(StringRef name, uint32_t flags, InputFile *f,
                      function ? &function->signature : nullptr),
       function(function) {}
 
-uint32_t DefinedData::getVirtualAddress() const {
+uint64_t DefinedData::getVirtualAddress() const {
   LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
   if (segment) {
     // For thread local data, the symbol location is relative to the start of
@@ -265,18 +265,18 @@ uint32_t DefinedData::getVirtualAddress() const {
   return offset;
 }
 
-void DefinedData::setVirtualAddress(uint32_t value) {
+void DefinedData::setVirtualAddress(uint64_t value) {
   LLVM_DEBUG(dbgs() << "setVirtualAddress " << name << " -> " << value << "\n");
   assert(!segment);
   offset = value;
 }
 
-uint32_t DefinedData::getOutputSegmentOffset() const {
+uint64_t DefinedData::getOutputSegmentOffset() const {
   LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n");
   return segment->outputSegmentOffset + offset;
 }
 
-uint32_t DefinedData::getOutputSegmentIndex() const {
+uint64_t DefinedData::getOutputSegmentIndex() const {
   LLVM_DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n");
   return segment->outputSeg->index;
 }

diff  --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h
index 3400cde1c7e2..9588a5595206 100644
--- a/lld/wasm/Symbols.h
+++ b/lld/wasm/Symbols.h
@@ -264,7 +264,7 @@ class DefinedData : public DataSymbol {
 public:
   // Constructor for regular data symbols originating from input files.
   DefinedData(StringRef name, uint32_t flags, InputFile *f,
-              InputSegment *segment, uint32_t offset, uint32_t size)
+              InputSegment *segment, uint64_t offset, uint64_t size)
       : DataSymbol(name, DefinedDataKind, flags, f), segment(segment),
         offset(offset), size(size) {}
 
@@ -275,19 +275,19 @@ class DefinedData : public DataSymbol {
   static bool classof(const Symbol *s) { return s->kind() == DefinedDataKind; }
 
   // Returns the output virtual address of a defined data symbol.
-  uint32_t getVirtualAddress() const;
-  void setVirtualAddress(uint32_t va);
+  uint64_t getVirtualAddress() const;
+  void setVirtualAddress(uint64_t va);
 
   // Returns the offset of a defined data symbol within its OutputSegment.
-  uint32_t getOutputSegmentOffset() const;
-  uint32_t getOutputSegmentIndex() const;
-  uint32_t getSize() const { return size; }
+  uint64_t getOutputSegmentOffset() const;
+  uint64_t getOutputSegmentIndex() const;
+  uint64_t getSize() const { return size; }
 
   InputSegment *segment = nullptr;
 
 protected:
-  uint32_t offset = 0;
-  uint32_t size = 0;
+  uint64_t offset = 0;
+  uint64_t size = 0;
 };
 
 class UndefinedData : public DataSymbol {

diff  --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index 4e974c8e4c9d..0ed3ea273d70 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -287,6 +287,7 @@ void GlobalSection::writeBody() {
   writeUleb128(os, numGlobals(), "global count");
   for (InputGlobal *g : inputGlobals)
     writeGlobal(os, g->global);
+  // TODO(wvo): when do these need I64_CONST?
   for (const Symbol *sym : staticGotSymbols) {
     WasmGlobal global;
     global.Type = {WASM_TYPE_I32, false};

diff  --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 4947c3581467..8cfab837df56 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -224,6 +224,7 @@ void Writer::layoutMemory() {
     log("mem: stack base  = " + Twine(memoryPtr));
     memoryPtr += config->zStackSize;
     auto *sp = cast<DefinedGlobal>(WasmSym::stackPointer);
+    assert(sp->global->global.InitExpr.Opcode == WASM_OPCODE_I32_CONST);
     sp->global->global.InitExpr.Value.Int32 = memoryPtr;
     log("mem: stack top   = " + Twine(memoryPtr));
   };
@@ -256,10 +257,13 @@ void Writer::layoutMemory() {
 
     if (WasmSym::tlsSize && seg->name == ".tdata") {
       auto *tlsSize = cast<DefinedGlobal>(WasmSym::tlsSize);
+      assert(tlsSize->global->global.InitExpr.Opcode == WASM_OPCODE_I32_CONST);
       tlsSize->global->global.InitExpr.Value.Int32 = seg->size;
 
       auto *tlsAlign = cast<DefinedGlobal>(WasmSym::tlsAlign);
-      tlsAlign->global->global.InitExpr.Value.Int32 = 1U << seg->alignment;
+      assert(tlsAlign->global->global.InitExpr.Opcode == WASM_OPCODE_I32_CONST);
+      tlsAlign->global->global.InitExpr.Value.Int32 = int64_t{1}
+                                                      << seg->alignment;
     }
   }
 

diff  --git a/lld/wasm/WriterUtils.cpp b/lld/wasm/WriterUtils.cpp
index 30e6bdf92ac9..9b14da8e9f2e 100644
--- a/lld/wasm/WriterUtils.cpp
+++ b/lld/wasm/WriterUtils.cpp
@@ -67,12 +67,12 @@ void debugWrite(uint64_t offset, const Twine &msg) {
   LLVM_DEBUG(dbgs() << format("  | %08lld: ", offset) << msg << "\n");
 }
 
-void writeUleb128(raw_ostream &os, uint32_t number, const Twine &msg) {
+void writeUleb128(raw_ostream &os, uint64_t number, const Twine &msg) {
   debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]");
   encodeULEB128(number, os);
 }
 
-void writeSleb128(raw_ostream &os, int32_t number, const Twine &msg) {
+void writeSleb128(raw_ostream &os, int64_t number, const Twine &msg) {
   debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]");
   encodeSLEB128(number, os);
 }
@@ -127,12 +127,12 @@ void writeI32Const(raw_ostream &os, int32_t number, const Twine &msg) {
   writeSleb128(os, number, msg);
 }
 
-void writeI64Const(raw_ostream &os, int32_t number, const Twine &msg) {
+void writeI64Const(raw_ostream &os, int64_t number, const Twine &msg) {
   writeU8(os, WASM_OPCODE_I64_CONST, "i64.const");
   writeSleb128(os, number, msg);
 }
 
-void writeMemArg(raw_ostream &os, uint32_t alignment, uint32_t offset) {
+void writeMemArg(raw_ostream &os, uint32_t alignment, uint64_t offset) {
   writeUleb128(os, alignment, "alignment");
   writeUleb128(os, offset, "offset");
 }

diff  --git a/lld/wasm/WriterUtils.h b/lld/wasm/WriterUtils.h
index 635ef841bca2..86df768af5c6 100644
--- a/lld/wasm/WriterUtils.h
+++ b/lld/wasm/WriterUtils.h
@@ -18,9 +18,9 @@ namespace wasm {
 
 void debugWrite(uint64_t offset, const Twine &msg);
 
-void writeUleb128(raw_ostream &os, uint32_t number, const Twine &msg);
+void writeUleb128(raw_ostream &os, uint64_t number, const Twine &msg);
 
-void writeSleb128(raw_ostream &os, int32_t number, const Twine &msg);
+void writeSleb128(raw_ostream &os, int64_t number, const Twine &msg);
 
 void writeBytes(raw_ostream &os, const char *bytes, size_t count,
                 const Twine &msg);
@@ -38,9 +38,9 @@ void writeSig(raw_ostream &os, const llvm::wasm::WasmSignature &sig);
 
 void writeI32Const(raw_ostream &os, int32_t number, const Twine &msg);
 
-void writeI64Const(raw_ostream &os, int32_t number, const Twine &msg);
+void writeI64Const(raw_ostream &os, int64_t number, const Twine &msg);
 
-void writeMemArg(raw_ostream &os, uint32_t alignment, uint32_t offset);
+void writeMemArg(raw_ostream &os, uint32_t alignment, uint64_t offset);
 
 void writeInitExpr(raw_ostream &os, const llvm::wasm::WasmInitExpr &initExpr);
 

diff  --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h
index 21c5bac2c500..28635d79106f 100644
--- a/llvm/include/llvm/BinaryFormat/Wasm.h
+++ b/llvm/include/llvm/BinaryFormat/Wasm.h
@@ -159,8 +159,8 @@ struct WasmElemSegment {
 // the index of the segment, and the offset and size within the segment.
 struct WasmDataReference {
   uint32_t Segment;
-  uint32_t Offset;
-  uint32_t Size;
+  uint64_t Offset;
+  uint64_t Size;
 };
 
 struct WasmRelocation {

diff  --git a/llvm/include/llvm/BinaryFormat/WasmRelocs.def b/llvm/include/llvm/BinaryFormat/WasmRelocs.def
index 897d597c4b9e..05c5147e6314 100644
--- a/llvm/include/llvm/BinaryFormat/WasmRelocs.def
+++ b/llvm/include/llvm/BinaryFormat/WasmRelocs.def
@@ -2,17 +2,21 @@
 #error "WASM_RELOC must be defined"
 #endif
 
-WASM_RELOC(R_WASM_FUNCTION_INDEX_LEB,    0)
-WASM_RELOC(R_WASM_TABLE_INDEX_SLEB,      1)
-WASM_RELOC(R_WASM_TABLE_INDEX_I32,       2)
-WASM_RELOC(R_WASM_MEMORY_ADDR_LEB,       3)
-WASM_RELOC(R_WASM_MEMORY_ADDR_SLEB,      4)
-WASM_RELOC(R_WASM_MEMORY_ADDR_I32,       5)
-WASM_RELOC(R_WASM_TYPE_INDEX_LEB,        6)
-WASM_RELOC(R_WASM_GLOBAL_INDEX_LEB,      7)
-WASM_RELOC(R_WASM_FUNCTION_OFFSET_I32,   8)
-WASM_RELOC(R_WASM_SECTION_OFFSET_I32,    9)
-WASM_RELOC(R_WASM_EVENT_INDEX_LEB,      10)
-WASM_RELOC(R_WASM_MEMORY_ADDR_REL_SLEB, 11)
-WASM_RELOC(R_WASM_TABLE_INDEX_REL_SLEB, 12)
-WASM_RELOC(R_WASM_GLOBAL_INDEX_I32,     13)
+WASM_RELOC(R_WASM_FUNCTION_INDEX_LEB,      0)
+WASM_RELOC(R_WASM_TABLE_INDEX_SLEB,        1)
+WASM_RELOC(R_WASM_TABLE_INDEX_I32,         2)
+WASM_RELOC(R_WASM_MEMORY_ADDR_LEB,         3)
+WASM_RELOC(R_WASM_MEMORY_ADDR_SLEB,        4)
+WASM_RELOC(R_WASM_MEMORY_ADDR_I32,         5)
+WASM_RELOC(R_WASM_TYPE_INDEX_LEB,          6)
+WASM_RELOC(R_WASM_GLOBAL_INDEX_LEB,        7)
+WASM_RELOC(R_WASM_FUNCTION_OFFSET_I32,     8)
+WASM_RELOC(R_WASM_SECTION_OFFSET_I32,      9)
+WASM_RELOC(R_WASM_EVENT_INDEX_LEB,        10)
+WASM_RELOC(R_WASM_MEMORY_ADDR_REL_SLEB,   11)
+WASM_RELOC(R_WASM_TABLE_INDEX_REL_SLEB,   12)
+WASM_RELOC(R_WASM_GLOBAL_INDEX_I32,       13)
+WASM_RELOC(R_WASM_MEMORY_ADDR_LEB64,      14)
+WASM_RELOC(R_WASM_MEMORY_ADDR_SLEB64,     15)
+WASM_RELOC(R_WASM_MEMORY_ADDR_I64,        16)
+WASM_RELOC(R_WASM_MEMORY_ADDR_REL_SLEB64, 17)

diff  --git a/llvm/include/llvm/ObjectYAML/WasmYAML.h b/llvm/include/llvm/ObjectYAML/WasmYAML.h
index 3f9d6bf41ea6..bffb314e2d3b 100644
--- a/llvm/include/llvm/ObjectYAML/WasmYAML.h
+++ b/llvm/include/llvm/ObjectYAML/WasmYAML.h
@@ -107,8 +107,10 @@ struct Function {
 struct Relocation {
   RelocType Type;
   uint32_t Index;
+  // TODO(wvo): this would strictly be better as Hex64, but that will change
+  // all existing obj2yaml output.
   yaml::Hex32 Offset;
-  int32_t Addend;
+  int64_t Addend;
 };
 
 struct DataSegment {

diff  --git a/llvm/lib/BinaryFormat/Wasm.cpp b/llvm/lib/BinaryFormat/Wasm.cpp
index d46be481edb3..88608168783b 100644
--- a/llvm/lib/BinaryFormat/Wasm.cpp
+++ b/llvm/lib/BinaryFormat/Wasm.cpp
@@ -39,9 +39,13 @@ std::string llvm::wasm::relocTypetoString(uint32_t Type) {
 bool llvm::wasm::relocTypeHasAddend(uint32_t Type) {
   switch (Type) {
   case R_WASM_MEMORY_ADDR_LEB:
+  case R_WASM_MEMORY_ADDR_LEB64:
   case R_WASM_MEMORY_ADDR_SLEB:
+  case R_WASM_MEMORY_ADDR_SLEB64:
   case R_WASM_MEMORY_ADDR_REL_SLEB:
+  case R_WASM_MEMORY_ADDR_REL_SLEB64:
   case R_WASM_MEMORY_ADDR_I32:
+  case R_WASM_MEMORY_ADDR_I64:
   case R_WASM_FUNCTION_OFFSET_I32:
   case R_WASM_SECTION_OFFSET_I32:
     return true;

diff  --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index c6a27898d1f3..460f431b8563 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -185,21 +185,21 @@ raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
 
 // Write X as an (unsigned) LEB value at offset Offset in Stream, padded
 // to allow patching.
-static void writePatchableLEB(raw_pwrite_stream &Stream, uint32_t X,
-                              uint64_t Offset) {
-  uint8_t Buffer[5];
-  unsigned SizeLen = encodeULEB128(X, Buffer, 5);
-  assert(SizeLen == 5);
+template <int W>
+void writePatchableLEB(raw_pwrite_stream &Stream, uint64_t X, uint64_t Offset) {
+  uint8_t Buffer[W];
+  unsigned SizeLen = encodeULEB128(X, Buffer, W);
+  assert(SizeLen == W);
   Stream.pwrite((char *)Buffer, SizeLen, Offset);
 }
 
 // Write X as an signed LEB value at offset Offset in Stream, padded
 // to allow patching.
-static void writePatchableSLEB(raw_pwrite_stream &Stream, int32_t X,
-                               uint64_t Offset) {
-  uint8_t Buffer[5];
-  unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
-  assert(SizeLen == 5);
+template <int W>
+void writePatchableSLEB(raw_pwrite_stream &Stream, int64_t X, uint64_t Offset) {
+  uint8_t Buffer[W];
+  unsigned SizeLen = encodeSLEB128(X, Buffer, W);
+  assert(SizeLen == W);
   Stream.pwrite((char *)Buffer, SizeLen, Offset);
 }
 
@@ -210,6 +210,12 @@ static void patchI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
   Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
 }
 
+static void patchI64(raw_pwrite_stream &Stream, uint64_t X, uint64_t Offset) {
+  uint8_t Buffer[8];
+  support::endian::write64le(Buffer, X);
+  Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
+}
+
 class WasmObjectWriter : public MCObjectWriter {
   support::endian::Writer W;
 
@@ -347,7 +353,7 @@ class WasmObjectWriter : public MCObjectWriter {
   updateCustomSectionRelocations(const SmallVector<WasmFunction, 4> &Functions,
                                  const MCAsmLayout &Layout);
 
-  uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
+  uint64_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
   void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
                         uint64_t ContentsOffset);
 
@@ -410,8 +416,8 @@ void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
 
   // Write the final section size to the payload_len field, which follows
   // the section id byte.
-  writePatchableLEB(static_cast<raw_pwrite_stream &>(W.OS), Size,
-                    Section.SizeOffset);
+  writePatchableLEB<5>(static_cast<raw_pwrite_stream &>(W.OS), Size,
+                       Section.SizeOffset);
 }
 
 // Emit the Wasm header.
@@ -549,7 +555,7 @@ static const MCSymbolWasm *resolveSymbol(const MCSymbolWasm &Symbol) {
 // by RelEntry. This value isn't used by the static linker; it just serves
 // to make the object format more readable and more likely to be directly
 // useable.
-uint32_t
+uint64_t
 WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
   if ((RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB ||
        RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_I32) &&
@@ -587,9 +593,13 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
     return Section.getSectionOffset() + RelEntry.Addend;
   }
   case wasm::R_WASM_MEMORY_ADDR_LEB:
-  case wasm::R_WASM_MEMORY_ADDR_I32:
+  case wasm::R_WASM_MEMORY_ADDR_LEB64:
+  case wasm::R_WASM_MEMORY_ADDR_SLEB:
+  case wasm::R_WASM_MEMORY_ADDR_SLEB64:
   case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
-  case wasm::R_WASM_MEMORY_ADDR_SLEB: {
+  case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
+  case wasm::R_WASM_MEMORY_ADDR_I32:
+  case wasm::R_WASM_MEMORY_ADDR_I64: {
     // Provisional value is address of the global
     const MCSymbolWasm *Sym = resolveSymbol(*RelEntry.Symbol);
     // For undefined symbols, use zero
@@ -666,7 +676,7 @@ void WasmObjectWriter::applyRelocations(
                       RelEntry.Offset;
 
     LLVM_DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
-    uint32_t Value = getProvisionalValue(RelEntry);
+    auto Value = getProvisionalValue(RelEntry);
 
     switch (RelEntry.Type) {
     case wasm::R_WASM_FUNCTION_INDEX_LEB:
@@ -674,7 +684,10 @@ void WasmObjectWriter::applyRelocations(
     case wasm::R_WASM_GLOBAL_INDEX_LEB:
     case wasm::R_WASM_MEMORY_ADDR_LEB:
     case wasm::R_WASM_EVENT_INDEX_LEB:
-      writePatchableLEB(Stream, Value, Offset);
+      writePatchableLEB<5>(Stream, Value, Offset);
+      break;
+    case wasm::R_WASM_MEMORY_ADDR_LEB64:
+      writePatchableLEB<10>(Stream, Value, Offset);
       break;
     case wasm::R_WASM_TABLE_INDEX_I32:
     case wasm::R_WASM_MEMORY_ADDR_I32:
@@ -683,11 +696,18 @@ void WasmObjectWriter::applyRelocations(
     case wasm::R_WASM_GLOBAL_INDEX_I32:
       patchI32(Stream, Value, Offset);
       break;
+    case wasm::R_WASM_MEMORY_ADDR_I64:
+      patchI64(Stream, Value, Offset);
+      break;
     case wasm::R_WASM_TABLE_INDEX_SLEB:
     case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
     case wasm::R_WASM_MEMORY_ADDR_SLEB:
     case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
-      writePatchableSLEB(Stream, Value, Offset);
+      writePatchableSLEB<5>(Stream, Value, Offset);
+      break;
+    case wasm::R_WASM_MEMORY_ADDR_SLEB64:
+    case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
+      writePatchableSLEB<10>(Stream, Value, Offset);
       break;
     default:
       llvm_unreachable("invalid relocation type");
@@ -1420,9 +1440,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
       // For each data symbol, export it in the symtab as a reference to the
       // corresponding Wasm data segment.
       wasm::WasmDataReference Ref = wasm::WasmDataReference{
-          DataSection.getSegmentIndex(),
-          static_cast<uint32_t>(Layout.getSymbolOffset(WS)),
-          static_cast<uint32_t>(Size)};
+          DataSection.getSegmentIndex(), Layout.getSymbolOffset(WS),
+          static_cast<uint64_t>(Size)};
       DataLocations[&WS] = Ref;
       LLVM_DEBUG(dbgs() << "  -> segment index: " << Ref.Segment << "\n");
 

diff  --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp
index 132896b1ecc2..d45da76280dd 100644
--- a/llvm/lib/Object/RelocationResolver.cpp
+++ b/llvm/lib/Object/RelocationResolver.cpp
@@ -505,6 +505,17 @@ static bool supportsWasm32(uint64_t Type) {
   }
 }
 
+static bool supportsWasm64(uint64_t Type) {
+  switch (Type) {
+  case wasm::R_WASM_MEMORY_ADDR_LEB64:
+  case wasm::R_WASM_MEMORY_ADDR_SLEB64:
+  case wasm::R_WASM_MEMORY_ADDR_I64:
+    return true;
+  default:
+    return supportsWasm32(Type);
+  }
+}
+
 static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
   switch (R.getType()) {
   case wasm::R_WASM_FUNCTION_INDEX_LEB:
@@ -526,6 +537,18 @@ static uint64_t resolveWasm32(RelocationRef R, uint64_t S, uint64_t A) {
   }
 }
 
+static uint64_t resolveWasm64(RelocationRef R, uint64_t S, uint64_t A) {
+  switch (R.getType()) {
+  case wasm::R_WASM_MEMORY_ADDR_LEB64:
+  case wasm::R_WASM_MEMORY_ADDR_SLEB64:
+  case wasm::R_WASM_MEMORY_ADDR_I64:
+    // For wasm section, its offset at 0 -- ignoring Value
+    return A;
+  default:
+    return resolveWasm32(R, S, A);
+  }
+}
+
 std::pair<bool (*)(uint64_t), RelocationResolver>
 getRelocationResolver(const ObjectFile &Obj) {
   if (Obj.isCOFF()) {
@@ -607,6 +630,8 @@ getRelocationResolver(const ObjectFile &Obj) {
   } else if (Obj.isWasm()) {
     if (Obj.getArch() == Triple::wasm32)
       return {supportsWasm32, resolveWasm32};
+    if (Obj.getArch() == Triple::wasm64)
+      return {supportsWasm64, resolveWasm64};
     return {nullptr, nullptr};
   }
 

diff  --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index 573055b66591..023948e2046e 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -156,6 +156,10 @@ static int64_t readVarint64(WasmObjectFile::ReadContext &Ctx) {
   return readLEB128(Ctx);
 }
 
+static uint64_t readVaruint64(WasmObjectFile::ReadContext &Ctx) {
+  return readULEB128(Ctx);
+}
+
 static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) {
   return readUint8(Ctx);
 }
@@ -558,12 +562,12 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
     case wasm::WASM_SYMBOL_TYPE_DATA:
       Info.Name = readString(Ctx);
       if (IsDefined) {
-        uint32_t Index = readVaruint32(Ctx);
+        auto Index = readVaruint32(Ctx);
         if (Index >= DataSegments.size())
           return make_error<GenericBinaryError>("invalid data symbol index",
                                                 object_error::parse_failed);
-        uint32_t Offset = readVaruint32(Ctx);
-        uint32_t Size = readVaruint32(Ctx);
+        auto Offset = readVaruint64(Ctx);
+        auto Size = readVaruint64(Ctx);
         if (Offset + Size > DataSegments[Index].Data.Content.size())
           return make_error<GenericBinaryError>("invalid data symbol offset",
                                                 object_error::parse_failed);
@@ -818,6 +822,15 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
                                               object_error::parse_failed);
       Reloc.Addend = readVarint32(Ctx);
       break;
+    case wasm::R_WASM_MEMORY_ADDR_LEB64:
+    case wasm::R_WASM_MEMORY_ADDR_SLEB64:
+    case wasm::R_WASM_MEMORY_ADDR_I64:
+    case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
+      if (!isValidDataSymbol(Reloc.Index))
+        return make_error<GenericBinaryError>("Bad relocation data index",
+                                              object_error::parse_failed);
+      Reloc.Addend = readVarint64(Ctx);
+      break;
     case wasm::R_WASM_FUNCTION_OFFSET_I32:
       if (!isValidFunctionSymbol(Reloc.Index))
         return make_error<GenericBinaryError>("Bad relocation function index",
@@ -840,12 +853,18 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
     // also shouldn't overlap a function/element boundary, but we don't bother
     // to check that.
     uint64_t Size = 5;
+    if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_LEB64 ||
+        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_SLEB64 ||
+        Reloc.Type == wasm::R_WASM_MEMORY_ADDR_REL_SLEB64)
+      Size = 10;
     if (Reloc.Type == wasm::R_WASM_TABLE_INDEX_I32 ||
         Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I32 ||
         Reloc.Type == wasm::R_WASM_SECTION_OFFSET_I32 ||
         Reloc.Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
         Reloc.Type == wasm::R_WASM_GLOBAL_INDEX_I32)
       Size = 4;
+    if (Reloc.Type == wasm::R_WASM_MEMORY_ADDR_I64)
+      Size = 8;
     if (Reloc.Offset + Size > EndOffset)
       return make_error<GenericBinaryError>("Bad relocation offset",
                                             object_error::parse_failed);
@@ -1331,8 +1350,13 @@ uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
     // offset within the segment.
     uint32_t SegmentIndex = Sym.Info.DataRef.Segment;
     const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data;
-    assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST);
-    return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
+    if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST) {
+      return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
+    } else if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I64_CONST) {
+      return Segment.Offset.Value.Int64 + Sym.Info.DataRef.Offset;
+    } else {
+      llvm_unreachable("unknown init expr opcode");
+    }
   }
   case wasm::WASM_SYMBOL_TYPE_SECTION:
     return 0;

diff  --git a/llvm/lib/ObjectYAML/WasmEmitter.cpp b/llvm/lib/ObjectYAML/WasmEmitter.cpp
index ef54eaedfc0b..cbb062d87ae6 100644
--- a/llvm/lib/ObjectYAML/WasmEmitter.cpp
+++ b/llvm/lib/ObjectYAML/WasmEmitter.cpp
@@ -532,8 +532,11 @@ void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
     encodeULEB128(Reloc.Index, OS);
     switch (Reloc.Type) {
     case wasm::R_WASM_MEMORY_ADDR_LEB:
+    case wasm::R_WASM_MEMORY_ADDR_LEB64:
     case wasm::R_WASM_MEMORY_ADDR_SLEB:
+    case wasm::R_WASM_MEMORY_ADDR_SLEB64:
     case wasm::R_WASM_MEMORY_ADDR_I32:
+    case wasm::R_WASM_MEMORY_ADDR_I64:
     case wasm::R_WASM_FUNCTION_OFFSET_I32:
     case wasm::R_WASM_SECTION_OFFSET_I32:
       encodeULEB128(Reloc.Addend, OS);

diff  --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 4fbad613288a..111211652adf 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -846,6 +846,16 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
         if (Op0.getImm() == -1)
           Op0.setImm(Align);
       }
+      if (getSTI().getTargetTriple().isArch64Bit()) {
+        // Upgrade 32-bit loads/stores to 64-bit. These mostly 
diff er by having
+        // an offset64 arg instead of offset32, but to the assembler matcher
+        // they're both immediates so don't get selected for.
+        auto Opc64 = WebAssembly::getWasm64Opcode(
+            static_cast<uint16_t>(Inst.getOpcode()));
+        if (Opc64 >= 0) {
+          Inst.setOpcode(Opc64);
+        }
+      }
       Out.emitInstruction(Inst, getSTI());
       if (CurrentState == EndFunction) {
         onEndOfFunction();

diff  --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
index 37ea35983f4b..dfed3451e45b 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
@@ -101,9 +101,6 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
         case WebAssembly::OPERAND_I64IMM:
           encodeSLEB128(int64_t(MO.getImm()), OS);
           break;
-        case WebAssembly::OPERAND_OFFSET64:
-          encodeULEB128(uint64_t(MO.getImm()), OS);
-          break;
         case WebAssembly::OPERAND_SIGNATURE:
           OS << uint8_t(MO.getImm());
           break;
@@ -163,6 +160,7 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
         break;
       case WebAssembly::OPERAND_OFFSET64:
         FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i64);
+        PaddedSize = 10;
         break;
       default:
         llvm_unreachable("unexpected symbolic operand kind");

diff  --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
index 58676616d247..779e921c1d94 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
@@ -78,7 +78,8 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
       return wasm::R_WASM_TABLE_INDEX_REL_SLEB;
     case MCSymbolRefExpr::VK_WASM_MBREL:
       assert(SymA.isData());
-      return wasm::R_WASM_MEMORY_ADDR_REL_SLEB;
+      return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_REL_SLEB64
+                       : wasm::R_WASM_MEMORY_ADDR_REL_SLEB;
     case MCSymbolRefExpr::VK_WASM_TYPEINDEX:
       return wasm::R_WASM_TYPE_INDEX_LEB;
     default:
@@ -87,12 +88,13 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
 
   switch (unsigned(Fixup.getKind())) {
   case WebAssembly::fixup_sleb128_i32:
-  case WebAssembly::fixup_sleb128_i64:
     if (SymA.isFunction())
       return wasm::R_WASM_TABLE_INDEX_SLEB;
     return wasm::R_WASM_MEMORY_ADDR_SLEB;
+  case WebAssembly::fixup_sleb128_i64:
+    assert(SymA.isData());
+    return wasm::R_WASM_MEMORY_ADDR_SLEB64;
   case WebAssembly::fixup_uleb128_i32:
-  case WebAssembly::fixup_uleb128_i64:
     if (SymA.isGlobal())
       return wasm::R_WASM_GLOBAL_INDEX_LEB;
     if (SymA.isFunction())
@@ -100,6 +102,9 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
     if (SymA.isEvent())
       return wasm::R_WASM_EVENT_INDEX_LEB;
     return wasm::R_WASM_MEMORY_ADDR_LEB;
+  case WebAssembly::fixup_uleb128_i64:
+    assert(SymA.isData());
+    return wasm::R_WASM_MEMORY_ADDR_LEB64;
   case FK_Data_4:
     if (SymA.isFunction())
       return wasm::R_WASM_TABLE_INDEX_I32;
@@ -113,6 +118,9 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
         return wasm::R_WASM_SECTION_OFFSET_I32;
     }
     return wasm::R_WASM_MEMORY_ADDR_I32;
+  case FK_Data_8:
+    assert(SymA.isData());
+    return wasm::R_WASM_MEMORY_ADDR_I64;
   default:
     llvm_unreachable("unimplemented fixup kind");
   }

diff  --git a/llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.cpp b/llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.cpp
index 87317f8a7f1e..f9a96819905f 100644
--- a/llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.cpp
@@ -32,3 +32,9 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyTargetInfo() {
   RegisterTarget<Triple::wasm64> Y(getTheWebAssemblyTarget64(), "wasm64",
                                    "WebAssembly 64-bit", "WebAssembly");
 }
+
+// Defines llvm::WebAssembly::getWasm64Opcode llvm::WebAssembly::getStackOpcode
+// which have to be in a shared location between CodeGen and MC.
+#define GET_INSTRMAP_INFO 1
+#define GET_INSTRINFO_ENUM 1
+#include "WebAssemblyGenInstrInfo.inc"

diff  --git a/llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.h b/llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.h
index a7427f78c72c..be7a632331c8 100644
--- a/llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.h
+++ b/llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.h
@@ -21,6 +21,13 @@ class Target;
 Target &getTheWebAssemblyTarget32();
 Target &getTheWebAssemblyTarget64();
 
+namespace WebAssembly {
+
+int getStackOpcode(unsigned short Opcode);
+int getWasm64Opcode(unsigned short Opcode);
+
+} // namespace WebAssembly
+
 } // namespace llvm
 
 #endif // LLVM_LIB_TARGET_WEBASSEMBLY_TARGETINFO_WEBASSEMBLYTARGETINFO_H

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td
index 09b3da36ca01..256b77e33db9 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td
@@ -14,9 +14,10 @@
 let UseNamedOperandTable = 1 in
 multiclass ATOMIC_I<dag oops_r, dag iops_r, dag oops_s, dag iops_s,
                     list<dag> pattern_r, string asmstr_r,
-                    string asmstr_s, bits<32> atomic_op> {
+                    string asmstr_s, bits<32> atomic_op,
+                    string is64 = "false"> {
   defm "" : I<oops_r, iops_r, oops_s, iops_s, pattern_r, asmstr_r, asmstr_s,
-              !or(0xfe00, !and(0xff, atomic_op))>,
+              !or(0xfe00, !and(0xff, atomic_op)), is64>,
             Requires<[HasAtomics]>;
 }
 
@@ -37,13 +38,13 @@ defm ATOMIC_NOTIFY_A32 :
            (ins P2Align:$p2align, offset32_op:$off, I32:$addr, I32:$count),
            (outs), (ins P2Align:$p2align, offset32_op:$off), [],
            "atomic.notify \t$dst, ${off}(${addr})${p2align}, $count",
-           "atomic.notify \t${off}${p2align}", 0x00>;
+           "atomic.notify \t${off}${p2align}", 0x00, "false">;
 defm ATOMIC_NOTIFY_A64 :
   ATOMIC_I<(outs I32:$dst),
            (ins P2Align:$p2align, offset64_op:$off, I64:$addr, I32:$count),
            (outs), (ins P2Align:$p2align, offset64_op:$off), [],
            "atomic.notify \t$dst, ${off}(${addr})${p2align}, $count",
-           "atomic.notify \t${off}${p2align}", 0x00>;
+           "atomic.notify \t${off}${p2align}", 0x00, "true">;
 let mayLoad = 1 in {
 defm ATOMIC_WAIT_I32_A32 :
   ATOMIC_I<(outs I32:$dst),
@@ -51,28 +52,28 @@ defm ATOMIC_WAIT_I32_A32 :
                 I64:$timeout),
            (outs), (ins P2Align:$p2align, offset32_op:$off), [],
            "i32.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout",
-           "i32.atomic.wait \t${off}${p2align}", 0x01>;
+           "i32.atomic.wait \t${off}${p2align}", 0x01, "false">;
 defm ATOMIC_WAIT_I32_A64 :
   ATOMIC_I<(outs I32:$dst),
            (ins P2Align:$p2align, offset64_op:$off, I64:$addr, I32:$exp,
                 I64:$timeout),
            (outs), (ins P2Align:$p2align, offset64_op:$off), [],
            "i32.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout",
-           "i32.atomic.wait \t${off}${p2align}", 0x01>;
+           "i32.atomic.wait \t${off}${p2align}", 0x01, "true">;
 defm ATOMIC_WAIT_I64_A32 :
   ATOMIC_I<(outs I32:$dst),
            (ins P2Align:$p2align, offset32_op:$off, I32:$addr, I64:$exp,
                 I64:$timeout),
            (outs), (ins P2Align:$p2align, offset32_op:$off), [],
            "i64.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout",
-           "i64.atomic.wait \t${off}${p2align}", 0x02>;
+           "i64.atomic.wait \t${off}${p2align}", 0x02, "false">;
 defm ATOMIC_WAIT_I64_A64 :
   ATOMIC_I<(outs I32:$dst),
            (ins P2Align:$p2align, offset64_op:$off, I64:$addr, I64:$exp,
                 I64:$timeout),
            (outs), (ins P2Align:$p2align, offset64_op:$off), [],
            "i64.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout",
-           "i64.atomic.wait \t${off}${p2align}", 0x02>;
+           "i64.atomic.wait \t${off}${p2align}", 0x02, "true">;
 } // mayLoad = 1
 } // hasSideEffects = 1
 
@@ -350,8 +351,8 @@ defm : LoadPatGlobalAddrOffOnly<i64, sext_aload_16_64, "ATOMIC_LOAD16_U_I64">;
 //===----------------------------------------------------------------------===//
 
 multiclass AtomicStore<WebAssemblyRegClass rc, string name, int atomic_op> {
-  defm "" : WebAssemblyStore<rc, name, !or(0xfe00, !and(0xff, atomic_op))>,
-            Requires<[HasAtomics]>;
+  defm "" : WebAssemblyStore<rc, name, !or(0xfe00, !and(0xff, atomic_op)),
+                             [HasAtomics]>;
 }
 
 defm ATOMIC_STORE_I32 : AtomicStore<I32, "i32.atomic.store", 0x17>;
@@ -486,13 +487,13 @@ multiclass WebAssemblyBinRMW<WebAssemblyRegClass rc, string name,
              (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val),
              (outs), (ins P2Align:$p2align, offset32_op:$off), [],
              !strconcat(name, "\t$dst, ${off}(${addr})${p2align}, $val"),
-             !strconcat(name, "\t${off}${p2align}"), atomic_op>;
+             !strconcat(name, "\t${off}${p2align}"), atomic_op, "false">;
   defm "_A64" :
     ATOMIC_I<(outs rc:$dst),
              (ins P2Align:$p2align, offset64_op:$off, I64:$addr, rc:$val),
              (outs), (ins P2Align:$p2align, offset64_op:$off), [],
              !strconcat(name, "\t$dst, ${off}(${addr})${p2align}, $val"),
-             !strconcat(name, "\t${off}${p2align}"), atomic_op>;
+             !strconcat(name, "\t${off}${p2align}"), atomic_op, "true">;
 }
 
 defm ATOMIC_RMW_ADD_I32 : WebAssemblyBinRMW<I32, "i32.atomic.rmw.add", 0x1e>;
@@ -797,14 +798,14 @@ multiclass WebAssemblyTerRMW<WebAssemblyRegClass rc, string name,
                   rc:$new_),
              (outs), (ins P2Align:$p2align, offset32_op:$off), [],
              !strconcat(name, "\t$dst, ${off}(${addr})${p2align}, $exp, $new_"),
-             !strconcat(name, "\t${off}${p2align}"), atomic_op>;
+             !strconcat(name, "\t${off}${p2align}"), atomic_op, "false">;
   defm "_A64" :
     ATOMIC_I<(outs rc:$dst),
              (ins P2Align:$p2align, offset64_op:$off, I64:$addr, rc:$exp,
                   rc:$new_),
              (outs), (ins P2Align:$p2align, offset64_op:$off), [],
              !strconcat(name, "\t$dst, ${off}(${addr})${p2align}, $exp, $new_"),
-             !strconcat(name, "\t${off}${p2align}"), atomic_op>;
+             !strconcat(name, "\t${off}${p2align}"), atomic_op, "true">;
 }
 
 defm ATOMIC_RMW_CMPXCHG_I32 :

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td
index aff4d20d8d82..0a4289c4959b 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td
@@ -14,11 +14,13 @@
 // WebAssembly Instruction Format.
 // We instantiate 2 of these for every actual instruction (register based
 // and stack based), see below.
-class WebAssemblyInst<bits<32> inst, string asmstr, string stack> : StackRel,
-  Instruction {
+class WebAssemblyInst<bits<32> inst, string asmstr, string stack, string is64>
+  : StackRel, Wasm64Rel, Instruction {
   bits<32> Inst = inst; // Instruction encoding.
   string StackBased = stack;
   string BaseName = NAME;
+  string IsWasm64 = is64;
+  string Wasm32Name = !subst("_A64", "_A32", NAME);
   let Namespace   = "WebAssembly";
   let Pattern     = [];
   let AsmString   = asmstr;
@@ -29,8 +31,8 @@ class WebAssemblyInst<bits<32> inst, string asmstr, string stack> : StackRel,
 
 // Normal instructions. Default instantiation of a WebAssemblyInst.
 class NI<dag oops, dag iops, list<dag> pattern, string stack,
-         string asmstr = "", bits<32> inst = -1>
-    : WebAssemblyInst<inst, asmstr, stack> {
+         string asmstr = "", bits<32> inst = -1, string is64 = "false">
+    : WebAssemblyInst<inst, asmstr, stack, is64> {
   dag OutOperandList = oops;
   dag InOperandList  = iops;
   let Pattern        = pattern;
@@ -52,11 +54,11 @@ class NI<dag oops, dag iops, list<dag> pattern, string stack,
 // there is always an equivalent pair of instructions.
 multiclass I<dag oops_r, dag iops_r, dag oops_s, dag iops_s,
              list<dag> pattern_r, string asmstr_r = "", string asmstr_s = "",
-             bits<32> inst = -1> {
+             bits<32> inst = -1, string is64 = "false"> {
   let isCodeGenOnly = 1 in
-  def "" : NI<oops_r, iops_r, pattern_r, "false", asmstr_r, inst>;
+  def "" : NI<oops_r, iops_r, pattern_r, "false", asmstr_r, inst, is64>;
   let BaseName = NAME in
-  def _S : NI<oops_s, iops_s, [], "true", asmstr_s, inst>;
+  def _S : NI<oops_s, iops_s, [], "true", asmstr_s, inst, is64>;
 }
 
 // For instructions that have no register ops, so both sets are the same.

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
index 6a290b64e7cf..5ff0d73534a6 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
@@ -202,6 +202,19 @@ def getStackOpcode : InstrMapping {
   let ValueCols = [["true"]];
 }
 
+//===----------------------------------------------------------------------===//
+// WebAssembly 32 to 64-bit instruction mapping
+//===----------------------------------------------------------------------===//
+
+class Wasm64Rel;
+def getWasm64Opcode : InstrMapping {
+  let FilterClass = "Wasm64Rel";
+  let RowFields = ["Wasm32Name"];
+  let ColFields = ["IsWasm64"];
+  let KeyCol = ["false"];
+  let ValueCols = [["true"]];
+}
+
 //===----------------------------------------------------------------------===//
 // WebAssembly Instruction Format Definitions.
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
index b353520bb26c..686c017593c8 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
@@ -41,19 +41,19 @@ def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
 
 // Defines atomic and non-atomic loads, regular and extending.
 multiclass WebAssemblyLoad<WebAssemblyRegClass rc, string Name, int Opcode,
-                           list<Predicate> reqs> {
+                           list<Predicate> reqs = []> {
   let mayLoad = 1, UseNamedOperandTable = 1 in {
   defm "_A32": I<(outs rc:$dst),
                  (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
                  (outs), (ins P2Align:$p2align, offset32_op:$off),
                  [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"),
-                 !strconcat(Name, "\t${off}${p2align}"), Opcode>,
+                 !strconcat(Name, "\t${off}${p2align}"), Opcode, "false">,
                Requires<reqs>;
   defm "_A64": I<(outs rc:$dst),
                  (ins P2Align:$p2align, offset64_op:$off, I64:$addr),
                  (outs), (ins P2Align:$p2align, offset64_op:$off),
                  [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"),
-                 !strconcat(Name, "\t${off}${p2align}"), Opcode>,
+                 !strconcat(Name, "\t${off}${p2align}"), Opcode, "true">,
                Requires<reqs>;
   }
 }
@@ -236,21 +236,24 @@ defm : LoadPatGlobalAddrOffOnly<i64, extloadi16, "LOAD16_U_I64">;
 defm : LoadPatGlobalAddrOffOnly<i64, extloadi32, "LOAD32_U_I64">;
 
 // Defines atomic and non-atomic stores, regular and truncating
-multiclass WebAssemblyStore<WebAssemblyRegClass rc, string Name, int Opcode> {
+multiclass WebAssemblyStore<WebAssemblyRegClass rc, string Name, int Opcode,
+                            list<Predicate> reqs = []> {
   let mayStore = 1, UseNamedOperandTable = 1 in
   defm "_A32" : I<(outs),
                   (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val),
                   (outs),
                   (ins P2Align:$p2align, offset32_op:$off), [],
                   !strconcat(Name, "\t${off}(${addr})${p2align}, $val"),
-                  !strconcat(Name, "\t${off}${p2align}"), Opcode>;
+                  !strconcat(Name, "\t${off}${p2align}"), Opcode, "false">,
+                Requires<reqs>;
   let mayStore = 1, UseNamedOperandTable = 1 in
   defm "_A64" : I<(outs),
                   (ins P2Align:$p2align, offset64_op:$off, I64:$addr, rc:$val),
                   (outs),
                   (ins P2Align:$p2align, offset64_op:$off), [],
                   !strconcat(Name, "\t${off}(${addr})${p2align}, $val"),
-                  !strconcat(Name, "\t${off}${p2align}"), Opcode>;
+                  !strconcat(Name, "\t${off}${p2align}"), Opcode, "true">,
+                Requires<reqs>;
 }
 
 // Basic store.

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
index eedc2c0b8a98..07830c130d7a 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
@@ -13,10 +13,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "WebAssemblyMCInstLower.h"
+#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
+#include "TargetInfo/WebAssemblyTargetInfo.h"
 #include "WebAssemblyAsmPrinter.h"
 #include "WebAssemblyMachineFunctionInfo.h"
 #include "WebAssemblyRuntimeLibcallSignatures.h"
-#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/IR/Constants.h"
@@ -29,11 +30,6 @@
 #include "llvm/Support/raw_ostream.h"
 using namespace llvm;
 
-// Defines llvm::WebAssembly::getStackOpcode to convert register instructions to
-// stack instructions
-#define GET_INSTRMAP_INFO 1
-#include "WebAssemblyGenInstrInfo.inc"
-
 // This disables the removal of registers when lowering into MC, as required
 // by some current tests.
 cl::opt<bool>

diff  --git a/llvm/test/MC/WebAssembly/wasm64.s b/llvm/test/MC/WebAssembly/wasm64.s
index 9833345f979d..e31bfcf12387 100644
--- a/llvm/test/MC/WebAssembly/wasm64.s
+++ b/llvm/test/MC/WebAssembly/wasm64.s
@@ -1,6 +1,5 @@
 # RUN: llvm-mc -triple=wasm64-unknown-unknown -mattr=+atomics,+unimplemented-simd128,+nontrapping-fptoint,+exception-handling < %s | FileCheck %s
-# Check that it converts to .o without errors, but don't check any output:
-# RUN: llvm-mc -triple=wasm64-unknown-unknown -filetype=obj -mattr=+atomics,+unimplemented-simd128,+nontrapping-fptoint,+exception-handling -o %t.o < %s
+# RUN: llvm-mc -triple=wasm64-unknown-unknown -filetype=obj -mattr=+atomics,+unimplemented-simd128,+nontrapping-fptoint,+exception-handling -o - < %s | obj2yaml | FileCheck %s -check-prefix=BIN
 
 # Most of our other tests are for wasm32, this one adds some wasm64 specific tests.
 
@@ -18,14 +17,18 @@ test:
     f32.load    0
     drop
 
-#    i64.const   .L.str    # get i64 relocatable.
-#    f32.load    0
-#    drop
+    i64.const   .L.str    # get i64 relocatable.
+    f32.load    0
+    drop
 
     global.get  myglob64  # get i64 from global
     f32.load    0
     drop
 
+    i64.const   0
+    f32.load    .L.str    # relocatable offset!
+    drop
+
     ### basic stores
 
     f32.const   0.0
@@ -36,21 +39,27 @@ test:
     local.get   0         # get i64 from local.
     f32.store   0
 
-#    f32.const   0.0
-#    i64.const   .L.str    # get i64 relocatable.
-#    f32.store   0
+    f32.const   0.0
+    i64.const   .L.str    # get i64 relocatable.
+    f32.store   0
 
     f32.const   0.0
     global.get  myglob64  # get i64 from global
     f32.store   0
 
+    f32.const   0.0
+    i64.const   0
+    f32.store   .L.str    # relocatable offset!
+
     end_function
 
     .section    .rodata..L.str,"",@
     .hidden     .L.str
     .type       .L.str, at object
 .L.str:
-    .asciz      "Hello, World!"
+    .asciz      "Hello, World!!!"
+    .int64      .L.str    # relocatable inside data.
+    .size       .L.str, 24
 
     .globaltype myglob64, i64
 
@@ -68,14 +77,18 @@ test:
 # CHECK-NEXT:         f32.load        0
 # CHECK-NEXT:         drop
 
-# NCHECK:              i64.const       .L.str
-# NCHECK-NEXT:         f32.load        0
-# NCHECK-NEXT:         drop
+# CHECK:              i64.const       .L.str
+# CHECK-NEXT:         f32.load        0
+# CHECK-NEXT:         drop
 
 # CHECK:              global.get      myglob64
 # CHECK-NEXT:         f32.load        0
 # CHECK-NEXT:         drop
 
+# CHECK:              i64.const       0
+# CHECK-NEXT:         f32.load        .L.str
+# CHECK-NEXT:         drop
+
 
 # CHECK:              f32.const       0x0p0
 # CHECK-NEXT:         i64.const       0
@@ -85,14 +98,18 @@ test:
 # CHECK-NEXT:         local.get       0
 # CHECK-NEXT:         f32.store       0
 
-# NCHECK:              f32.const       0x0p0
-# NCHECK-NEXT:         i64.const       .L.str
-# NCHECK-NEXT:         f32.store       0
+# CHECK:              f32.const       0x0p0
+# CHECK-NEXT:         i64.const       .L.str
+# CHECK-NEXT:         f32.store       0
 
 # CHECK:              f32.const       0x0p0
 # CHECK-NEXT:         global.get      myglob64
 # CHECK-NEXT:         f32.store       0
 
+# CHECK:              f32.const       0x0p0
+# CHECK-NEXT:         i64.const       0
+# CHECK-NEXT:         f32.store       .L.str
+
 
 # CHECK:              end_function
 # CHECK-NEXT: .Ltmp0:
@@ -101,6 +118,108 @@ test:
 # CHECK:              .section        .rodata..L.str,"",@
 # CHECK-NEXT:         .hidden .L.str
 # CHECK-NEXT: .L.str:
-# CHECK-NEXT:         .asciz  "Hello, World!"
+# CHECK-NEXT:         .asciz  "Hello, World!!!"
+# CHECK-NEXT:         .int64      .L.str
+# CHECK-NEXT:         .size       .L.str, 24
 
 # CHECK:              .globaltype     myglob64, i64
+
+
+
+# BIN:      --- !WASM
+# BIN-NEXT: FileHeader:
+# BIN-NEXT:   Version:         0x00000001
+# BIN-NEXT: Sections:
+# BIN-NEXT:   - Type:            TYPE
+# BIN-NEXT:     Signatures:
+# BIN-NEXT:       - Index:           0
+# BIN-NEXT:         ParamTypes:
+# BIN-NEXT:           - I64
+# BIN-NEXT:         ReturnTypes:     []
+# BIN-NEXT:   - Type:            IMPORT
+# BIN-NEXT:     Imports:
+# BIN-NEXT:       - Module:          env
+# BIN-NEXT:         Field:           __linear_memory
+# BIN-NEXT:         Kind:            MEMORY
+# BIN-NEXT:         Memory:
+# BIN-NEXT:           Initial:         0x00000001
+# BIN-NEXT:       - Module:          env
+# BIN-NEXT:         Field:           __indirect_function_table
+# BIN-NEXT:         Kind:            TABLE
+# BIN-NEXT:         Table:
+# BIN-NEXT:           ElemType:        FUNCREF
+# BIN-NEXT:           Limits:
+# BIN-NEXT:             Initial:         0x00000000
+# BIN-NEXT:       - Module:          env
+# BIN-NEXT:         Field:           myglob64
+# BIN-NEXT:         Kind:            GLOBAL
+# BIN-NEXT:         GlobalType:      I64
+# BIN-NEXT:         GlobalMutable:   true
+# BIN-NEXT:   - Type:            FUNCTION
+# BIN-NEXT:     FunctionTypes:   [ 0 ]
+# BIN-NEXT:   - Type:            DATACOUNT
+# BIN-NEXT:     Count:           1
+# BIN-NEXT:   - Type:            CODE
+# BIN-NEXT:     Relocations:
+# BIN-NEXT:       - Type:            R_WASM_MEMORY_ADDR_SLEB64
+# BIN-NEXT:         Index:           1
+# BIN-NEXT:         Offset:          0x00000013
+# BIN-NEXT:       - Type:            R_WASM_GLOBAL_INDEX_LEB
+# BIN-NEXT:         Index:           2
+# BIN-NEXT:         Offset:          0x00000022
+# BIN-NEXT:       - Type:            R_WASM_MEMORY_ADDR_LEB64
+# BIN-NEXT:         Index:           1
+# BIN-NEXT:         Offset:          0x0000002F
+# BIN-NEXT:       - Type:            R_WASM_MEMORY_ADDR_SLEB64
+# BIN-NEXT:         Index:           1
+# BIN-NEXT:         Offset:          0x00000054
+# BIN-NEXT:       - Type:            R_WASM_GLOBAL_INDEX_LEB
+# BIN-NEXT:         Index:           2
+# BIN-NEXT:         Offset:          0x00000067
+# BIN-NEXT:       - Type:            R_WASM_MEMORY_ADDR_LEB64
+# BIN-NEXT:         Index:           1
+# BIN-NEXT:         Offset:          0x00000078
+# BIN-NEXT:     Functions:
+# BIN-NEXT:       - Index:           0
+# BIN-NEXT:         Locals:
+# BIN-NEXT:           - Type:            I64
+# BIN-NEXT:             Count:           1
+# BIN-NEXT:         Body:            42002A02001A20002A02001A42808080808080808080002A02001A2380808080002A02001A42002A02808080808080808080001A4300000000420038020043000000002000380200430000000042808080808080808080003802004300000000238080808000380200430000000042003802808080808080808080000B
+# BIN-NEXT:   - Type:            DATA
+# BIN-NEXT:     Relocations:
+# BIN-NEXT:       - Type:            R_WASM_MEMORY_ADDR_I64
+# BIN-NEXT:         Index:           1
+# BIN-NEXT:         Offset:          0x00000016
+# BIN-NEXT:     Segments:
+# BIN-NEXT:       - SectionOffset:   6
+# BIN-NEXT:         InitFlags:       0
+# BIN-NEXT:         Offset:
+# BIN-NEXT:           Opcode:          I32_CONST
+# BIN-NEXT:           Value:           0
+# BIN-NEXT:         Content:         48656C6C6F2C20576F726C64212121000000000000000000
+# BIN-NEXT:   - Type:            CUSTOM
+# BIN-NEXT:     Name:            linking
+# BIN-NEXT:     Version:         2
+# BIN-NEXT:     SymbolTable:
+# BIN-NEXT:       - Index:           0
+# BIN-NEXT:         Kind:            FUNCTION
+# BIN-NEXT:         Name:            test
+# BIN-NEXT:         Flags:           [ BINDING_LOCAL ]
+# BIN-NEXT:         Function:        0
+# BIN-NEXT:       - Index:           1
+# BIN-NEXT:         Kind:            DATA
+# BIN-NEXT:         Name:            .L.str
+# BIN-NEXT:         Flags:           [ BINDING_LOCAL, VISIBILITY_HIDDEN ]
+# BIN-NEXT:         Segment:         0
+# BIN-NEXT:         Size:            24
+# BIN-NEXT:       - Index:           2
+# BIN-NEXT:         Kind:            GLOBAL
+# BIN-NEXT:         Name:            myglob64
+# BIN-NEXT:         Flags:           [ UNDEFINED ]
+# BIN-NEXT:         Global:          0
+# BIN-NEXT:     SegmentInfo:
+# BIN-NEXT:       - Index:           0
+# BIN-NEXT:         Name:            .rodata..L.str
+# BIN-NEXT:         Alignment:       0
+# BIN-NEXT:         Flags:           [  ]
+# BIN-NEXT: ...

diff  --git a/llvm/tools/llvm-readobj/WasmDumper.cpp b/llvm/tools/llvm-readobj/WasmDumper.cpp
index 0964ffb77eae..a02dbb999826 100644
--- a/llvm/tools/llvm-readobj/WasmDumper.cpp
+++ b/llvm/tools/llvm-readobj/WasmDumper.cpp
@@ -182,6 +182,10 @@ void WasmDumper::printSectionHeaders() {
         W.printNumber("Size", static_cast<uint64_t>(Seg.Content.size()));
         if (Seg.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST)
           W.printNumber("Offset", Seg.Offset.Value.Int32);
+        else if (Seg.Offset.Opcode == wasm::WASM_OPCODE_I64_CONST)
+          W.printNumber("Offset", Seg.Offset.Value.Int64);
+        else
+          llvm_unreachable("unknown init expr opcode");
       }
       break;
     }


        


More information about the llvm-commits mailing list