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); + 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)); + 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-relative.ll b/llvm/test/MC/WebAssembly/alias-relative.ll new file mode 100644 --- /dev/null +++ b/llvm/test/MC/WebAssembly/alias-relative.ll @@ -0,0 +1,34 @@ +; RUN: llc -filetype=obj %s -o - | obj2yaml | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +define void @f() { + ret void +} + +@0 = private constant { [2 x i8*] } { [2 x i8*] [i8* null, i8* bitcast (void ()* @f to i8*)] }, align 4 + +@alias_f = private alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @0, i32 0, i32 0, i32 1) + +define void @_start() { + store i8* null, i8** getelementptr inbounds (i8*, i8** @alias_f, i32 0), align 4 + ret void +} + +; CHECK: - Type: DATACOUNT +; CHECK-NEXT: Count: 1 +; CHECK-NEXT: - Type: CODE +; CHECK-NEXT: Relocations: +; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB +; CHECK-NEXT: Index: 2 +; CHECK-NEXT: Offset: 0x0000000C +; CHECK-NEXT: Functions: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Locals: [] +; CHECK-NEXT: Body: 0B +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Locals: [] +; CHECK-NEXT: Body: 41004100360284808080000B + +; incorrect code will generate 41004100360280808080000B +; wasm-ld: warning: unexpected existing value for R_WASM_MEMORY_ADDR_LEB: existing=0 expected=4