Index: lld/test/wasm/data-layout.s =================================================================== --- lld/test/wasm/data-layout.s +++ lld/test/wasm/data-layout.s @@ -1,12 +1,12 @@ # RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/hello.s -o %t.hello32.o # RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t32.o # RUN: wasm-ld -m wasm32 -no-gc-sections --export=__data_end --export=__heap_base --allow-undefined --no-entry -o %t32.wasm %t32.o %t.hello32.o -# RUN: obj2yaml %t32.wasm | FileCheck --check-prefixes CHECK,CHK32 %s +# RUN: obj2yaml %t32.wasm | FileCheck -DPTR=I32 %s # # RUN: llvm-mc -filetype=obj -triple=wasm64-unknown-unknown %p/Inputs/hello.s -o %t.hello64.o # RUN: llvm-mc -filetype=obj -triple=wasm64-unknown-unknown %s -o %t64.o # RUN: wasm-ld -m wasm64 -no-gc-sections --export=__data_end --export=__heap_base --allow-undefined --no-entry -o %t64.wasm %t64.o %t.hello64.o -# RUN: obj2yaml %t64.wasm | FileCheck --check-prefixes CHECK,CHK64 %s +# RUN: obj2yaml %t64.wasm | FileCheck --check-prefixes CHECK,CHK64 -DPTR=I64 %s .section .data.foo,"",@ .globl foo @@ -59,24 +59,22 @@ # CHECK-NEXT: - Type: GLOBAL # CHECK-NEXT: Globals: # CHECK-NEXT: - Index: 0 -# CHK32-NEXT: Type: I32 -# CHK64-NEXT: Type: I64 +# CHECK-NEXT: Type: [[PTR]] # CHECK-NEXT: Mutable: true # CHECK-NEXT: InitExpr: -# CHK32-NEXT: Opcode: I32_CONST -# CHK64-NEXT: Opcode: I64_CONST +# CHECK-NEXT: Opcode: [[PTR]]_CONST # CHECK-NEXT: Value: 66624 # CHECK-NEXT: - Index: 1 -# CHECK-NEXT: Type: I32 +# CHECK-NEXT: Type: [[PTR]] # CHECK-NEXT: Mutable: false # CHECK-NEXT: InitExpr: -# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Opcode: [[PTR]]_CONST # CHECK-NEXT: Value: 1080 # CHECK-NEXT: - Index: 2 -# CHECK-NEXT: Type: I32 +# CHECK-NEXT: Type: [[PTR]] # CHECK-NEXT: Mutable: false # CHECK-NEXT: InitExpr: -# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Opcode: [[PTR]]_CONST # CHECK-NEXT: Value: 66624 # CHECK: - Type: DATA @@ -84,15 +82,13 @@ # CHECK-NEXT: - SectionOffset: 7 # CHECK-NEXT: InitFlags: 0 # CHECK-NEXT: Offset: -# CHK32-NEXT: Opcode: I32_CONST -# CHK64-NEXT: Opcode: I64_CONST +# CHECK-NEXT: Opcode: [[PTR]]_CONST # CHECK-NEXT: Value: 1024 # CHECK-NEXT: Content: 68656C6C6F0A00 # CHECK-NEXT: - SectionOffset: 20 # CHECK-NEXT: InitFlags: 0 # CHECK-NEXT: Offset: -# CHK32-NEXT: Opcode: I32_CONST -# CHK64-NEXT: Opcode: I64_CONST +# CHECK-NEXT: Opcode: [[PTR]]_CONST # CHECK-NEXT: Value: 1040 Index: lld/test/wasm/shared.ll =================================================================== --- lld/test/wasm/shared.ll +++ lld/test/wasm/shared.ll @@ -1,8 +1,9 @@ -; RUN: llc -relocation-model=pic -mattr=+mutable-globals -filetype=obj %s -o %t.o +; RUN: llc --mtriple=wasm32-unknown-emscripten -relocation-model=pic -mattr=+mutable-globals -filetype=obj %s -o %t.o ; RUN: wasm-ld --experimental-pic -shared -o %t.wasm %t.o -; RUN: obj2yaml %t.wasm | FileCheck %s - -target triple = "wasm32-unknown-emscripten" +; RUN: obj2yaml %t.wasm | FileCheck --check-prefixes=CHECK,CHK32 -DPTR=I32 %s +; RUN: llc --mtriple=wasm64-unknown-emscripten -relocation-model=pic -mattr=+mutable-globals -filetype=obj %s -o %t.o +; RUN: wasm-ld -mwasm64 --experimental-pic -shared -o %t.wasm %t.o +; RUN: obj2yaml %t.wasm | FileCheck --check-prefixes=CHECK,CHK64 -DPTR=I64 %s @data = hidden global i32 2, align 4 @data_external = external global i32 @@ -52,8 +53,10 @@ ; CHECK: Sections: ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: dylink -; CHECK-NEXT: MemorySize: 24 -; CHECK-NEXT: MemoryAlignment: 2 +; CHK32-NEXT: MemorySize: 24 +; CHK64-NEXT: MemorySize: 48 +; CHK32-NEXT: MemoryAlignment: 2 +; CHK64-NEXT: MemoryAlignment: 3 ; CHECK-NEXT: TableSize: 2 ; CHECK-NEXT: TableAlignment: 0 ; CHECK-NEXT: Needed: [] @@ -67,6 +70,7 @@ ; CHECK-NEXT: Field: memory ; CHECK-NEXT: Kind: MEMORY ; CHECK-NEXT: Memory: +; CHK64-NEXT: Flags: [ IS_64 ] ; CHECK-NEXT: Minimum: 0x1 ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: __indirect_function_table @@ -79,18 +83,23 @@ ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: __stack_pointer ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: GlobalType: I32 +; CHECK-NEXT: GlobalType: [[PTR]] ; CHECK-NEXT: GlobalMutable: true ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: __memory_base ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: GlobalType: I32 +; CHECK-NEXT: GlobalType: [[PTR]] ; CHECK-NEXT: GlobalMutable: false ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: __table_base ; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: GlobalType: I32 +; CHECK-NEXT: GlobalType: [[PTR]] ; CHECK-NEXT: GlobalMutable: false +; CHK64-NEXT: - Module: env +; CHK64-NEXT: Field: __table_base32 +; CHK64-NEXT: Kind: GLOBAL +; CHK64-NEXT: GlobalType: I32 +; CHK64-NEXT: GlobalMutable: false ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: func_external ; CHECK-NEXT: Kind: FUNCTION @@ -129,7 +138,8 @@ ; CHECK-NEXT: Segments: ; CHECK-NEXT: - Offset: ; CHECK-NEXT: Opcode: GLOBAL_GET -; CHECK-NEXT: Index: 2 +; CHK32-NEXT: Index: 2 +; CHK64-NEXT: Index: 3 ; CHECK-NEXT: Functions: [ 4, 3 ] ; check the generated code in __wasm_call_ctors and __wasm_apply_data_relocs functions @@ -142,7 +152,8 @@ ; CHECK-NEXT: Body: 10020B ; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Locals: [] -; CHECK-NEXT: Body: 230141046A230241016A360200230141086A23043602002301410C6A230141006A360200230141106A2305360200230141146A230641046A3602000B +; CHK32-NEXT: Body: 230141046A230241016A360200230141086A23043602002301410C6A230141006A360200230141106A2305360200230141146A230641046A3602000B +; CHK64-NEXT: Body: 230142087C230241016A360200230142107C2305360200230142187C230142007C370200230142207C2306370200230142287C230742047C3702000B ; check the data segment initialized with __memory_base global as offset @@ -153,4 +164,5 @@ ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: GLOBAL_GET ; CHECK-NEXT: Index: 1 -; CHECK-NEXT: Content: '020000000100000000000000000000000000000000000000' +; CHK32-NEXT: Content: '020000000100000000000000000000000000000000000000' +; CHK64-NEXT: Content: '020000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000' Index: lld/wasm/Driver.cpp =================================================================== --- lld/wasm/Driver.cpp +++ lld/wasm/Driver.cpp @@ -584,15 +584,9 @@ static InputGlobal *createGlobal(StringRef name, bool isMutable) { llvm::wasm::WasmGlobal wasmGlobal; - if (config->is64.getValueOr(false)) { - wasmGlobal.Type = {WASM_TYPE_I64, isMutable}; - wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I64_CONST; - wasmGlobal.InitExpr.Value.Int64 = 0; - } else { - wasmGlobal.Type = {WASM_TYPE_I32, isMutable}; - wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST; - wasmGlobal.InitExpr.Value.Int32 = 0; - } + bool is64 = config->is64.getValueOr(false); + wasmGlobal.Type = {uint8_t(is64 ? WASM_TYPE_I64 : WASM_TYPE_I32), isMutable}; + wasmGlobal.InitExpr = intConst(0, is64); wasmGlobal.SymbolName = name; return make(wasmGlobal, nullptr); } @@ -635,12 +629,19 @@ // which to load our static data and function table. // See: // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md - WasmSym::memoryBase = createUndefinedGlobal( - "__memory_base", - config->is64.getValueOr(false) ? &globalTypeI64 : &globalTypeI32); - WasmSym::tableBase = createUndefinedGlobal("__table_base", &globalTypeI32); + bool is64 = config->is64.getValueOr(false); + auto *globalType = is64 ? &globalTypeI64 : &globalTypeI32; + WasmSym::memoryBase = createUndefinedGlobal("__memory_base", globalType); + WasmSym::tableBase = createUndefinedGlobal("__table_base", globalType); WasmSym::memoryBase->markLive(); WasmSym::tableBase->markLive(); + if (is64) { + WasmSym::tableBase32 = + createUndefinedGlobal("__table_base32", &globalTypeI32); + WasmSym::tableBase32->markLive(); + } else { + WasmSym::tableBase32 = nullptr; + } } else { // For non-PIC code WasmSym::stackPointer = createGlobalVariable("__stack_pointer", true); @@ -673,6 +674,9 @@ WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base"); WasmSym::definedMemoryBase = symtab->addOptionalDataSymbol("__memory_base"); WasmSym::definedTableBase = symtab->addOptionalDataSymbol("__table_base"); + if (config->is64.getValueOr(false)) + WasmSym::definedTableBase32 = + symtab->addOptionalDataSymbol("__table_base32"); } // For non-shared memory programs we still need to define __tls_base since we Index: lld/wasm/InputChunks.cpp =================================================================== --- lld/wasm/InputChunks.cpp +++ lld/wasm/InputChunks.cpp @@ -84,6 +84,7 @@ existingValue = static_cast(decodeSLEB128(loc, &bytesRead)); break; case R_WASM_TABLE_INDEX_SLEB64: + case R_WASM_TABLE_INDEX_REL_SLEB64: case R_WASM_MEMORY_ADDR_SLEB64: case R_WASM_MEMORY_ADDR_REL_SLEB64: existingValue = static_cast(decodeSLEB128(loc, &bytesRead)); @@ -168,6 +169,7 @@ encodeSLEB128(static_cast(value), loc, 5); break; case R_WASM_TABLE_INDEX_SLEB64: + case R_WASM_TABLE_INDEX_REL_SLEB64: case R_WASM_MEMORY_ADDR_SLEB64: case R_WASM_MEMORY_ADDR_REL_SLEB64: encodeSLEB128(static_cast(value), loc, 10); Index: lld/wasm/InputElement.h =================================================================== --- lld/wasm/InputElement.h +++ lld/wasm/InputElement.h @@ -42,6 +42,18 @@ llvm::Optional assignedIndex; }; +inline WasmInitExpr intConst(uint64_t value, bool is64) { + WasmInitExpr ie; + if (is64) { + ie.Opcode = llvm::wasm::WASM_OPCODE_I64_CONST; + ie.Value.Int64 = static_cast(value); + } else { + ie.Opcode = llvm::wasm::WASM_OPCODE_I32_CONST; + ie.Value.Int32 = static_cast(value); + } + return ie; +} + class InputGlobal : public InputElement { public: InputGlobal(const WasmGlobal &g, ObjFile *f) @@ -51,13 +63,7 @@ const WasmInitExpr &getInitExpr() const { return initExpr; } void setPointerValue(uint64_t value) { - if (config->is64.getValueOr(false)) { - assert(initExpr.Opcode == llvm::wasm::WASM_OPCODE_I64_CONST); - initExpr.Value.Int64 = value; - } else { - assert(initExpr.Opcode == llvm::wasm::WASM_OPCODE_I32_CONST); - initExpr.Value.Int32 = value; - } + initExpr = intConst(value, config->is64.getValueOr(false)); } private: Index: lld/wasm/InputFiles.cpp =================================================================== --- lld/wasm/InputFiles.cpp +++ lld/wasm/InputFiles.cpp @@ -147,7 +147,8 @@ const WasmSymbol &sym = wasmObj->syms()[reloc.Index]; return tableEntries[sym.Info.ElementIndex]; } - case R_WASM_TABLE_INDEX_REL_SLEB: { + case R_WASM_TABLE_INDEX_REL_SLEB: + case R_WASM_TABLE_INDEX_REL_SLEB64: { const WasmSymbol &sym = wasmObj->syms()[reloc.Index]; return tableEntriesRel[sym.Info.ElementIndex]; } @@ -221,14 +222,15 @@ case R_WASM_TABLE_INDEX_I64: case R_WASM_TABLE_INDEX_SLEB: case R_WASM_TABLE_INDEX_SLEB64: - case R_WASM_TABLE_INDEX_REL_SLEB: { + case R_WASM_TABLE_INDEX_REL_SLEB: + case R_WASM_TABLE_INDEX_REL_SLEB64: { if (!getFunctionSymbol(reloc.Index)->hasTableIndex()) return 0; uint32_t index = getFunctionSymbol(reloc.Index)->getTableIndex(); - if (reloc.Type == R_WASM_TABLE_INDEX_REL_SLEB) + if (reloc.Type == R_WASM_TABLE_INDEX_REL_SLEB || + reloc.Type == R_WASM_TABLE_INDEX_REL_SLEB64) index -= config->tableBase; return index; - } case R_WASM_MEMORY_ADDR_LEB: case R_WASM_MEMORY_ADDR_LEB64: Index: lld/wasm/OutputSections.cpp =================================================================== --- lld/wasm/OutputSections.cpp +++ lld/wasm/OutputSections.cpp @@ -8,6 +8,7 @@ #include "OutputSections.h" #include "InputChunks.h" +#include "InputElement.h" #include "InputFiles.h" #include "OutputSegment.h" #include "WriterUtils.h" @@ -161,12 +162,8 @@ if (config->isPic) { initExpr.Opcode = WASM_OPCODE_GLOBAL_GET; initExpr.Value.Global = WasmSym::memoryBase->getGlobalIndex(); - } else if (config->is64.getValueOr(false)) { - initExpr.Opcode = WASM_OPCODE_I64_CONST; - initExpr.Value.Int64 = static_cast(segment->startVA); } else { - initExpr.Opcode = WASM_OPCODE_I32_CONST; - initExpr.Value.Int32 = static_cast(segment->startVA); + initExpr = intConst(segment->startVA, config->is64.getValueOr(false)); } writeInitExpr(os, initExpr); } Index: lld/wasm/Relocations.cpp =================================================================== --- lld/wasm/Relocations.cpp +++ lld/wasm/Relocations.cpp @@ -104,6 +104,7 @@ case R_WASM_TABLE_INDEX_SLEB: case R_WASM_TABLE_INDEX_SLEB64: case R_WASM_TABLE_INDEX_REL_SLEB: + case R_WASM_TABLE_INDEX_REL_SLEB64: if (requiresGOTAccess(sym)) break; out.elemSec->addEntry(cast(sym)); Index: lld/wasm/Symbols.h =================================================================== --- lld/wasm/Symbols.h +++ lld/wasm/Symbols.h @@ -563,6 +563,11 @@ // Used in PIC code for offset of indirect function table static UndefinedGlobal *tableBase; static DefinedData *definedTableBase; + // 32-bit copy in wasm64 to work around init expr limitations. + // These can potentially be removed again once we have + // https://github.com/WebAssembly/extended-const + static UndefinedGlobal *tableBase32; + static DefinedData *definedTableBase32; // __memory_base // Used in PIC code for offset of global data Index: lld/wasm/Symbols.cpp =================================================================== --- lld/wasm/Symbols.cpp +++ lld/wasm/Symbols.cpp @@ -87,6 +87,8 @@ GlobalSymbol *WasmSym::tlsAlign; UndefinedGlobal *WasmSym::tableBase; DefinedData *WasmSym::definedTableBase; +UndefinedGlobal *WasmSym::tableBase32; +DefinedData *WasmSym::definedTableBase32; UndefinedGlobal *WasmSym::memoryBase; DefinedData *WasmSym::definedMemoryBase; TableSymbol *WasmSym::indirectFunctionTable; Index: lld/wasm/SyntheticSections.cpp =================================================================== --- lld/wasm/SyntheticSections.cpp +++ lld/wasm/SyntheticSections.cpp @@ -362,33 +362,30 @@ writeGlobalType(os, g->getType()); writeInitExpr(os, g->getInitExpr()); } - // TODO(wvo): when do these need I64_CONST? + bool is64 = config->is64.getValueOr(false); + uint8_t itype = is64 ? WASM_TYPE_I64 : WASM_TYPE_I32; for (const Symbol *sym : internalGotSymbols) { // In the case of dynamic linking, internal GOT entries // need to be mutable since they get updated to the correct // runtime value during `__wasm_apply_global_relocs`. bool mutable_ = config->isPic & !sym->isStub; - WasmGlobalType type{WASM_TYPE_I32, mutable_}; + WasmGlobalType type{itype, mutable_}; WasmInitExpr initExpr; - initExpr.Opcode = WASM_OPCODE_I32_CONST; if (auto *d = dyn_cast(sym)) - initExpr.Value.Int32 = d->getVA(); + initExpr = intConst(d->getVA(), is64); else if (auto *f = dyn_cast(sym)) - initExpr.Value.Int32 = f->isStub ? 0 : f->getTableIndex(); + initExpr = intConst(f->isStub ? 0 : f->getTableIndex(), is64); else { assert(isa(sym)); - initExpr.Value.Int32 = 0; + initExpr = intConst(0, is64); } writeGlobalType(os, type); writeInitExpr(os, initExpr); } for (const DefinedData *sym : dataAddressGlobals) { - WasmGlobalType type{WASM_TYPE_I32, false}; - WasmInitExpr initExpr; - initExpr.Opcode = WASM_OPCODE_I32_CONST; - initExpr.Value.Int32 = sym->getVA(); + WasmGlobalType type{itype, false}; writeGlobalType(os, type); - writeInitExpr(os, initExpr); + writeInitExpr(os, intConst(sym->getVA(), is64)); } } @@ -443,7 +440,10 @@ WasmInitExpr initExpr; if (config->isPic) { initExpr.Opcode = WASM_OPCODE_GLOBAL_GET; - initExpr.Value.Global = WasmSym::tableBase->getGlobalIndex(); + initExpr.Value.Global = + (config->is64.getValueOr(false) ? WasmSym::tableBase32 + : WasmSym::tableBase) + ->getGlobalIndex(); } else { initExpr.Opcode = WASM_OPCODE_I32_CONST; initExpr.Value.Int32 = config->tableBase; Index: lld/wasm/Writer.cpp =================================================================== --- lld/wasm/Writer.cpp +++ lld/wasm/Writer.cpp @@ -1380,6 +1380,8 @@ config->tableBase = 1; if (WasmSym::definedTableBase) WasmSym::definedTableBase->setVA(config->tableBase); + if (WasmSym::definedTableBase32) + WasmSym::definedTableBase32->setVA(config->tableBase); } log("-- createOutputSegments"); Index: llvm/include/llvm/BinaryFormat/WasmRelocs.def =================================================================== --- llvm/include/llvm/BinaryFormat/WasmRelocs.def +++ llvm/include/llvm/BinaryFormat/WasmRelocs.def @@ -26,3 +26,4 @@ WASM_RELOC(R_WASM_MEMORY_ADDR_TLS_SLEB, 21) WASM_RELOC(R_WASM_FUNCTION_OFFSET_I64, 22) WASM_RELOC(R_WASM_MEMORY_ADDR_LOCREL_I32, 23) +WASM_RELOC(R_WASM_TABLE_INDEX_REL_SLEB64, 24) Index: llvm/lib/MC/WasmObjectWriter.cpp =================================================================== --- llvm/lib/MC/WasmObjectWriter.cpp +++ llvm/lib/MC/WasmObjectWriter.cpp @@ -528,6 +528,7 @@ } if (Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB || + Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64 || Type == wasm::R_WASM_TABLE_INDEX_SLEB || Type == wasm::R_WASM_TABLE_INDEX_SLEB64 || Type == wasm::R_WASM_TABLE_INDEX_I32 || @@ -590,6 +591,7 @@ switch (RelEntry.Type) { case wasm::R_WASM_TABLE_INDEX_REL_SLEB: + case wasm::R_WASM_TABLE_INDEX_REL_SLEB64: case wasm::R_WASM_TABLE_INDEX_SLEB: case wasm::R_WASM_TABLE_INDEX_SLEB64: case wasm::R_WASM_TABLE_INDEX_I32: @@ -598,7 +600,8 @@ const MCSymbolWasm *Base = cast(Layout.getBaseSymbol(*RelEntry.Symbol)); assert(Base->isFunction()); - if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB) + if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB || + RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64) return TableIndices[Base] - InitialTableOffset; else return TableIndices[Base]; @@ -742,6 +745,7 @@ writePatchableSLEB<5>(Stream, Value, Offset); break; case wasm::R_WASM_TABLE_INDEX_SLEB64: + case wasm::R_WASM_TABLE_INDEX_REL_SLEB64: case wasm::R_WASM_MEMORY_ADDR_SLEB64: case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64: writePatchableSLEB<10>(Stream, Value, Offset); @@ -1757,7 +1761,8 @@ Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 && Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB && Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 && - Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB) + Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB && + Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64) return; assert(Rel.Symbol->isFunction()); const MCSymbolWasm *Base = Index: llvm/lib/Object/WasmObjectFile.cpp =================================================================== --- llvm/lib/Object/WasmObjectFile.cpp +++ llvm/lib/Object/WasmObjectFile.cpp @@ -867,6 +867,7 @@ case wasm::R_WASM_TABLE_INDEX_I32: case wasm::R_WASM_TABLE_INDEX_I64: case wasm::R_WASM_TABLE_INDEX_REL_SLEB: + case wasm::R_WASM_TABLE_INDEX_REL_SLEB64: if (!isValidFunctionSymbol(Reloc.Index)) return make_error( "invalid relocation function index", object_error::parse_failed); Index: llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp =================================================================== --- llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp +++ llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp @@ -76,7 +76,8 @@ return wasm::R_WASM_GLOBAL_INDEX_LEB; case MCSymbolRefExpr::VK_WASM_TBREL: assert(SymA.isFunction()); - return wasm::R_WASM_TABLE_INDEX_REL_SLEB; + return is64Bit() ? wasm::R_WASM_TABLE_INDEX_REL_SLEB64 + : wasm::R_WASM_TABLE_INDEX_REL_SLEB; case MCSymbolRefExpr::VK_WASM_TLSREL: return wasm::R_WASM_MEMORY_ADDR_TLS_SLEB; case MCSymbolRefExpr::VK_WASM_MBREL: Index: llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp +++ llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp @@ -86,9 +86,8 @@ strcmp(Name, "__stack_pointer") == 0 || strcmp(Name, "__tls_base") == 0; WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL); WasmSym->setGlobalType(wasm::WasmGlobalType{ - uint8_t(Subtarget.hasAddr64() && strcmp(Name, "__table_base") != 0 - ? wasm::WASM_TYPE_I64 - : wasm::WASM_TYPE_I32), + uint8_t(Subtarget.hasAddr64() ? wasm::WASM_TYPE_I64 + : wasm::WASM_TYPE_I32), Mutable}); return WasmSym; } Index: llvm/test/MC/WebAssembly/reloc-pic64.s =================================================================== --- /dev/null +++ llvm/test/MC/WebAssembly/reloc-pic64.s @@ -0,0 +1,209 @@ +# RUN: llvm-mc -triple=wasm64-unknown-unknown -filetype=obj < %s | obj2yaml | FileCheck %s +# RUN: llvm-mc -triple=wasm64-unknown-unknown -mattr=+reference-types -filetype=obj < %s | obj2yaml | FileCheck --check-prefix=REF %s + +# Verify that @GOT relocation entries result in R_WASM_GLOBAL_INDEX_LEB against +# against the corrsponding function or data symbol and that the corresponding +# data symbols are imported as a wasm globals. + +load_default_data: + .functype load_default_data () -> (i32) + global.get default_data@GOT + i32.load 0 + end_function + +load_default_func: + .functype load_default_func () -> (i32) + global.get default_func@GOT + i32.load 0 + end_function + +load_hidden_data: + .functype load_hidden_data () -> (i64) + global.get __memory_base + i64.const .L.hidden_data@MBREL + i64.add + end_function + +load_hidden_func: + .functype load_hidden_func () -> (i64) + global.get __table_base + i64.const hidden_func@TBREL + i64.add + end_function + +hidden_func: + .functype hidden_func () -> (i32) + i32.const 0 + end_function + +.section .rodata.hidden_data,"",@ +.L.hidden_data: + .int8 100 + .size .L.hidden_data, 1 + +#.hidden hidden_func +#.hidden hidden_data +.size default_data, 4 +.functype default_func () -> (i32) + +# CHECK: --- !WASM +# CHECK-NEXT: FileHeader: +# CHECK-NEXT: Version: 0x1 +# CHECK-NEXT: Sections: +# CHECK-NEXT: - Type: TYPE +# CHECK-NEXT: Signatures: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: ParamTypes: [] +# CHECK-NEXT: ReturnTypes: +# CHECK-NEXT: - I32 +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: ParamTypes: [] +# CHECK-NEXT: ReturnTypes: +# CHECK-NEXT: - I64 +# CHECK-NEXT: - Type: IMPORT +# CHECK-NEXT: Imports: +# CHECK-NEXT: - Module: env +# CHECK-NEXT: Field: __linear_memory +# CHECK-NEXT: Kind: MEMORY +# CHECK-NEXT: Memory: +# CHECK-NEXT: Flags: [ IS_64 ] +# CHECK-NEXT: Minimum: 0x1 +# CHECK-NEXT: - Module: env +# CHECK-NEXT: Field: default_func +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: SigIndex: 0 +# CHECK-NEXT: - Module: env +# CHECK-NEXT: Field: __indirect_function_table +# CHECK-NEXT: Kind: TABLE +# CHECK-NEXT: Table: +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: ElemType: FUNCREF +# CHECK-NEXT: Limits: +# CHECK-NEXT: Minimum: 0x1 +# CHECK-NEXT: - Module: GOT.mem +# CHECK-NEXT: Field: default_data +# CHECK-NEXT: Kind: GLOBAL +# CHECK-NEXT: GlobalType: I32 +# CHECK-NEXT: GlobalMutable: true +# CHECK-NEXT: - Module: GOT.func +# CHECK-NEXT: Field: default_func +# CHECK-NEXT: Kind: GLOBAL +# CHECK-NEXT: GlobalType: I32 +# CHECK-NEXT: GlobalMutable: true +# CHECK-NEXT: - Type: FUNCTION +# CHECK-NEXT: FunctionTypes: [ 0, 0, 1, 1, 0 ] +# CHECK-NEXT: - Type: ELEM +# CHECK-NEXT: Segments: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Value: 1 +# CHECK-NEXT: Functions: [ 5 ] +# CHECK-NEXT: - Type: DATACOUNT +# CHECK-NEXT: Count: 1 +# CHECK-NEXT: - Type: CODE +# CHECK-NEXT: Relocations: +# CHECK-NEXT: - Type: R_WASM_GLOBAL_INDEX_LEB +# CHECK-NEXT: Index: 1 +# CHECK-NEXT: Offset: 0x4 +# CHECK-NEXT: - Type: R_WASM_GLOBAL_INDEX_LEB +# CHECK-NEXT: Index: 3 +# CHECK-NEXT: Offset: 0x10 +# CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB +# CHECK-NEXT: Index: 5 +# CHECK-NEXT: Offset: 0x1C +# CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_REL_SLEB +# CHECK-NEXT: Index: 6 +# CHECK-NEXT: Offset: 0x22 +# CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB +# CHECK-NEXT: Index: 8 +# CHECK-NEXT: Offset: 0x31 +# CHECK-NEXT: - Type: R_WASM_TABLE_INDEX_REL_SLEB +# CHECK-NEXT: Index: 9 +# CHECK-NEXT: Offset: 0x37 +# CHECK-NEXT: Functions: +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: Locals: [] +# CHECK-NEXT: Body: 2380808080002802000B +# CHECK-NEXT: - Index: 2 +# CHECK-NEXT: Locals: [] +# CHECK-NEXT: Body: 2381808080002802000B +# CHECK-NEXT: - Index: 3 +# CHECK-NEXT: Locals: [] +# CHECK-NEXT: Body: 23808080800042808080808080808080007C0B +# CHECK-NEXT: - Index: 4 +# CHECK-NEXT: Locals: [] +# CHECK-NEXT: Body: 23808080800042808080808080808080007C0B +# CHECK-NEXT: - Index: 5 +# CHECK-NEXT: Locals: [] +# CHECK-NEXT: Body: 41000B +# CHECK-NEXT: - Type: DATA +# CHECK-NEXT: Segments: +# CHECK-NEXT: - SectionOffset: 6 +# CHECK-NEXT: InitFlags: 0 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Opcode: I64_CONST +# CHECK-NEXT: Value: 0 +# CHECK-NEXT: Content: '64' +# CHECK-NEXT: - Type: CUSTOM +# CHECK-NEXT: Name: linking +# CHECK-NEXT: Version: 2 +# CHECK-NEXT: SymbolTable: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Name: load_default_data +# CHECK-NEXT: Flags: [ BINDING_LOCAL ] +# CHECK-NEXT: Function: 1 +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: Kind: DATA +# CHECK-NEXT: Name: default_data +# CHECK-NEXT: Flags: [ UNDEFINED ] +# CHECK-NEXT: - Index: 2 +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Name: load_default_func +# CHECK-NEXT: Flags: [ BINDING_LOCAL ] +# CHECK-NEXT: Function: 2 +# CHECK-NEXT: - Index: 3 +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Name: default_func +# CHECK-NEXT: Flags: [ UNDEFINED ] +# CHECK-NEXT: Function: 0 +# CHECK-NEXT: - Index: 4 +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Name: load_hidden_data +# CHECK-NEXT: Flags: [ BINDING_LOCAL ] +# CHECK-NEXT: Function: 3 +# CHECK-NEXT: - Index: 5 +# CHECK-NEXT: Kind: DATA +# CHECK-NEXT: Name: __memory_base +# CHECK-NEXT: Flags: [ UNDEFINED ] +# CHECK-NEXT: - Index: 6 +# CHECK-NEXT: Kind: DATA +# CHECK-NEXT: Name: .L.hidden_data +# CHECK-NEXT: Flags: [ BINDING_LOCAL ] +# CHECK-NEXT: Segment: 0 +# CHECK-NEXT: Size: 1 +# CHECK-NEXT: - Index: 7 +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Name: load_hidden_func +# CHECK-NEXT: Flags: [ BINDING_LOCAL ] +# CHECK-NEXT: Function: 4 +# CHECK-NEXT: - Index: 8 +# CHECK-NEXT: Kind: DATA +# CHECK-NEXT: Name: __table_base +# CHECK-NEXT: Flags: [ UNDEFINED ] +# CHECK-NEXT: - Index: 9 +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT: Name: hidden_func +# CHECK-NEXT: Flags: [ BINDING_LOCAL ] +# CHECK-NEXT: Function: 5 +# REF: - Index: 10 +# REF-NEXT: Kind: TABLE +# REF-NEXT: Name: __indirect_function_table +# REF-NEXT: Flags: [ UNDEFINED, NO_STRIP ] +# REF-NEXT: Table: 0 +# CHECK-NEXT: SegmentInfo: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Name: .rodata.hidden_data +# CHECK-NEXT: Alignment: 0 +# CHECK-NEXT: Flags: [ ] +# CHECK-NEXT: ...