[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