Index: lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp +++ lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp @@ -64,6 +64,11 @@ const MachineFrameInfo &MFI = MF.getFrameInfo(); int64_t FrameOffset = MFI.getStackSize() + MFI.getObjectOffset(FrameIndex); + assert(MFI.getObjectSize(FrameIndex) != 0 && + "We assume that variable-sized objects have already been lowered, " + "and don't have a frame index."); + unsigned FrameRegister = getFrameRegister(MF); + // If this is the address operand of a load or store, make it relative to SP // and fold the frame offset directly in. if (MI.mayLoadOrStore() && FIOperandNum == WebAssembly::MemOpAddressOperandNo) { @@ -73,7 +78,7 @@ if (static_cast(Offset) <= std::numeric_limits::max()) { MI.getOperand(FIOperandNum - 1).setImm(Offset); MI.getOperand(FIOperandNum) - .ChangeToRegister(WebAssembly::SP32, /*IsDef=*/false); + .ChangeToRegister(FrameRegister, /*IsDef=*/false); return; } } @@ -94,7 +99,7 @@ MachineOperand &ImmMO = Def->getOperand(1); ImmMO.setImm(ImmMO.getImm() + uint32_t(FrameOffset)); MI.getOperand(FIOperandNum) - .ChangeToRegister(WebAssembly::SP32, /*IsDef=*/false); + .ChangeToRegister(FrameRegister, /*IsDef=*/false); return; } } @@ -104,7 +109,7 @@ // Otherwise create an i32.add SP, offset and make it the operand. const auto *TII = MF.getSubtarget().getInstrInfo(); - unsigned FIRegOperand = WebAssembly::SP32; + unsigned FIRegOperand = FrameRegister; if (FrameOffset) { // Create i32.add SP, offset and make it the operand. const TargetRegisterClass *PtrRC = @@ -116,7 +121,7 @@ FIRegOperand = MRI.createVirtualRegister(PtrRC); BuildMI(MBB, *II, II->getDebugLoc(), TII->get(WebAssembly::ADD_I32), FIRegOperand) - .addReg(WebAssembly::SP32) + .addReg(FrameRegister) .addReg(OffsetOp); } MI.getOperand(FIOperandNum).ChangeToRegister(FIRegOperand, /*IsDef=*/false); Index: test/CodeGen/WebAssembly/userstack.ll =================================================================== --- test/CodeGen/WebAssembly/userstack.ll +++ test/CodeGen/WebAssembly/userstack.ll @@ -173,21 +173,53 @@ ; CHECK-LABEL: dynamic_static_alloca: define void @dynamic_static_alloca(i32 %alloc) noredzone { ; Decrement SP in the prolog by the static amount and writeback to memory. - ; CHECK: i32.const $push[[L11:.+]]=, 0{{$}} - ; CHECK: i32.const $push[[L8:.+]]=, 0{{$}} - ; CHECK-NEXT: i32.load $push[[L9:.+]]=, __stack_pointer($pop[[L8]]) - ; CHECK-NEXT: i32.const $push[[L10:.+]]=, 16 - ; CHECK-NEXT: i32.sub $push[[L20:.+]]=, $pop[[L9]], $pop[[L10]] - ; CHECK-NEXT: tee_local $push[[L19:.+]]=, $[[FP:.+]]=, $pop[[L20]] - ; CHECK: i32.store $drop=, __stack_pointer($pop{{.+}}), $pop{{.+}} + ; CHECK: i32.const $push[[L13:.+]]=, 0{{$}} + ; CHECK: i32.const $push[[L10:.+]]=, 0{{$}} + ; CHECK-NEXT: i32.load $push[[L11:.+]]=, __stack_pointer($pop[[L10]]) + ; CHECK-NEXT: i32.const $push[[L12:.+]]=, 16 + ; CHECK-NEXT: i32.sub $push[[L23:.+]]=, $pop[[L11]], $pop[[L12]] + ; CHECK: tee_local $push[[L22:.+]]=, $[[FP_temp:.+]]=, $pop[[L23]] + ; CHECK: i32.store $drop=, __stack_pointer($pop{{.+}}), $pop[[L22]] + + ; Alloc and write to a static alloca + ; Currently the store doesn't use FP directly, because it's a local that + ; hasn't received its final allocation yet. + ; CHECK: copy_local $push[[L21:.+]]=, $[[FP_temp]] + ; CHECK: tee_local $push[[pushedFP:.+]]=, $[[FP:.+]]=, $pop[[L21]] + ; CHECK: i32.const $push[[L0:.+]]=, 101 + ; CHECK: i32.store $drop=, [[static_offset:.+]]($pop[[pushedFP]]), $pop[[L0]] + %static = alloca i32 + store volatile i32 101, i32* %static + + ; Decrement SP in the body by the dynamic amount. + ; CHECK: i32.sub + ; CHECK: tee_local $push{{.+}}=, $[[dynamic_local:.+]]=, $pop{{.+}} + %dynamic = alloca i32, i32 %alloc + + ; CHECK: i32.const $push[[L7:.+]]=, 102 + ; CHECK: i32.store $drop=, [[static_offset]]($[[FP]]), $pop[[L7]] + ; CHECK: i32.const $push[[L8:.+]]=, 103 + ; CHECK: i32.store $drop=, 0($[[dynamic_local]]), $pop[[L8]] + store volatile i32 102, i32* %static + store volatile i32 103, i32* %dynamic + ; Decrement SP in the body by the dynamic amount. ; CHECK: i32.sub + ; CHECK: tee_local $push{{.+}}=, $[[dynamic2_local:.+]]=, $pop{{.+}} + %dynamic.2 = alloca i32, i32 %alloc + + ; CHECK: i32.const $push[[L9:.+]]=, 104 + ; CHECK: i32.store $drop=, [[static_offset]]($[[FP]]), $pop[[L9]] + ; CHECK: i32.const $push[[L10:.+]]=, 105 + ; CHECK: i32.store $drop=, 0($[[dynamic_local]]), $pop[[L10]] + ; CHECK: i32.const $push[[L11:.+]]=, 106 + ; CHECK: i32.store $drop=, 0($[[dynamic2_local]]), $pop[[L11]] + store volatile i32 104, i32* %static + store volatile i32 105, i32* %dynamic + store volatile i32 106, i32* %dynamic.2 + ; Writeback to memory. ; CHECK: i32.store $drop=, __stack_pointer($pop{{.+}}), $pop{{.+}} - %r1 = alloca i32 - %r = alloca i32, i32 %alloc - store i32 0, i32* %r - ; CHEC: i32.store $drop=, 0($pop{{.+}}), $pop{{.+}} ret void }