diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -592,16 +592,17 @@ 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 + // Provisional value is address of the global plus the offset const MCSymbolWasm *Base = cast(Layout.getBaseSymbol(*RelEntry.Symbol)); // For undefined symbols, use zero if (!Base->isDefined()) return 0; - const wasm::WasmDataReference &Ref = DataLocations[Base]; - const WasmDataSegment &Segment = DataSegments[Ref.Segment]; + const wasm::WasmDataReference &BaseRef = DataLocations[Base]; + const wasm::WasmDataReference &SymRef = DataLocations[RelEntry.Symbol]; + const WasmDataSegment &Segment = DataSegments[BaseRef.Segment]; // Ignore overflow. LLVM allows address arithmetic to silently wrap. - return Segment.Offset + Ref.Offset + RelEntry.Addend; + return Segment.Offset + BaseRef.Offset + SymRef.Offset + RelEntry.Addend; } default: llvm_unreachable("invalid relocation type"); @@ -1225,8 +1226,11 @@ // Register types for all functions, including those with private linkage // (because wasm always needs a type signature). if (WS.isFunction()) { - const MCSymbolWasm *Base = cast(Layout.getBaseSymbol(S)); - registerFunctionType(*Base); + const auto *BS = Layout.getBaseSymbol(S); + if (!BS) + report_fatal_error(Twine(S.getName()) + + ": absolute addressing not supported!"); + registerFunctionType(*cast(BS)); } if (WS.isEvent()) @@ -1516,7 +1520,11 @@ assert(S.isDefined()); - const MCSymbolWasm *Base = cast(Layout.getBaseSymbol(S)); + const auto *BS = Layout.getBaseSymbol(S); + if (!BS) + report_fatal_error(Twine(S.getName()) + + ": absolute addressing not supported!"); + const MCSymbolWasm *Base = cast(BS); // Find the target symbol of this weak alias and export that index const auto &WS = static_cast(S); diff --git a/llvm/test/MC/WebAssembly/alias-offset.s b/llvm/test/MC/WebAssembly/alias-offset.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/WebAssembly/alias-offset.s @@ -0,0 +1,32 @@ +# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj %s | llvm-objdump --triple=wasm32-unknown-unknown -d -t - | FileCheck %s + + .section .data,"",@ +foo: + .int32 0 + .size foo, 4 +sym_a: + .int32 1 + .int32 2 + .size sym_a, 8 + +.set sym_b, sym_a + 4 + +# CHECK-LABEL: SYMBOL TABLE: +# CHECK-NEXT: 00000000 l O DATA foo +# CHECK-NEXT: 00000004 l O DATA sym_a +# CHECK-NEXT: 00000008 l O DATA sym_b +# CHECK-NEXT: 00000001 l F CODE main + + .text + .section .text,"",@ +main: + .functype main () -> () + i32.const sym_a + i32.store sym_b + end_function + +# CHECK-LABEL:
: +# CHECK-EMPTY: +# CHECK-NEXT: 3: 41 88 80 80 80 00 i32.const 8 +# CHECK-NEXT: 9: 36 02 8c 80 80 80 00 i32.store 12 +# CHECK-NEXT: 10: 0b end diff --git a/llvm/test/MC/WebAssembly/offset.s b/llvm/test/MC/WebAssembly/offset.s deleted file mode 100644 --- a/llvm/test/MC/WebAssembly/offset.s +++ /dev/null @@ -1,16 +0,0 @@ -# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj %s | llvm-objdump -t - | FileCheck %s - -.section .data,"",@ -foo: - .int32 0 - .size foo, 4 -sym_a: - .int32 1 - .int32 2 - .size sym_a, 8 - -.set sym_b, sym_a + 4 - -# CHECK: 00000000 l O DATA foo -# CHECK: 00000004 l O DATA sym_a -# CHECK: 00000008 l O DATA sym_b