Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp @@ -23,9 +23,11 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/raw_ostream.h" + using namespace llvm; #define DEBUG_TYPE "mccodeemitter" @@ -60,6 +62,7 @@ const MCSubtargetInfo &STI) const { uint64_t Start = OS.tell(); + DEBUG(dbgs() << "encodeInstruction: " << MI << "\n"); uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); if (Binary <= UINT8_MAX) { OS << uint8_t(Binary); @@ -86,8 +89,11 @@ assert(Desc.TSFlags == 0 && "WebAssembly non-variable_ops don't use TSFlags"); const MCOperandInfo &Info = Desc.OpInfo[i]; + DEBUG(dbgs() << "Encoding immediate: type=" << int(Info.OperandType) << "\n"); if (Info.OperandType == WebAssembly::OPERAND_I32IMM) { encodeSLEB128(int32_t(MO.getImm()), OS); + } else if (Info.OperandType == WebAssembly::OPERAND_OFFSET32) { + encodeULEB128(uint32_t(MO.getImm()), OS); } else if (Info.OperandType == WebAssembly::OPERAND_I64IMM) { encodeSLEB128(int64_t(MO.getImm()), OS); } else if (Info.OperandType == WebAssembly::OPERAND_GLOBAL) { Index: test/CodeGen/WebAssembly/offset.ll =================================================================== --- test/CodeGen/WebAssembly/offset.ll +++ test/CodeGen/WebAssembly/offset.ll @@ -277,6 +277,17 @@ ret i32 %t } +; When loading from a fixed address, offsets are coerced into u32 range + +; CHECK-LABEL: load_i32_from_negative_address +; CHECK: i32.const $push0=, 0{{$}} +; CHECK: i32.load $push1=, 4294967295($pop0){{$}} +define i32 @load_i32_from_negative_address() { + %s = inttoptr i32 -1 to i32* + %t = load i32, i32* %s + ret i32 %t +} + ; CHECK-LABEL: load_i32_from_global_address ; CHECK: i32.const $push0=, 0{{$}} ; CHECK: i32.load $push1=, gv($pop0){{$}}