llvm.org GIT mirror llvm / 8f5a7d6
[WebAssembly] Add support for using a wasm global for the stack pointer. This replaces the __stack_pointer variable which was allocated in linear memory. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296201 91177308-0d34-0410-b5e6-96231b3b80d8 Dan Gohman 3 years ago
9 changed file(s) with 223 addition(s) and 89 deletion(s). Raw diff Collapse all Expand all
1414 #ifndef LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H
1515 #define LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H
1616
17 #include "llvm/CodeGen/ValueTypes.h"
1718 #include "llvm/CodeGen/MachineModuleInfo.h"
1819
1920 namespace llvm {
7475 SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
7576 };
7677
78 /// MachineModuleInfoWasm - This is a MachineModuleInfoImpl implementation
79 /// for Wasm targets.
80 class MachineModuleInfoWasm : public MachineModuleInfoImpl {
81 /// GVStubs - These stubs are used to materialize global addresses in PIC
82 /// mode.
83 std::vector Globals;
84 unsigned StackPointerGlobal;
85
86 virtual void anchor(); // Out of line virtual method.
87 public:
88 MachineModuleInfoWasm(const MachineModuleInfo &)
89 : StackPointerGlobal(-1U) {}
90
91 void addGlobal(MVT VT) { Globals.push_back(VT); }
92 const std::vector &getGlobals() const { return Globals; }
93
94 bool hasStackPointerGlobal() const {
95 return StackPointerGlobal != -1U;
96 }
97 unsigned getStackPointerGlobal() const {
98 assert(hasStackPointerGlobal() && "Stack ptr global hasn't been set");
99 return StackPointerGlobal;
100 }
101 void setStackPointerGlobal(unsigned Global) { StackPointerGlobal = Global; }
102 };
103
77104 } // end namespace llvm
78105
79106 #endif
2222 // Out of line virtual method.
2323 void MachineModuleInfoMachO::anchor() {}
2424 void MachineModuleInfoELF::anchor() {}
25 void MachineModuleInfoWasm::anchor() {}
2526
2627 static int SortSymbolPair(const void *LHS, const void *RHS) {
2728 typedef std::pair PairTy;
503503
504504 void WasmObjectWriter::writeObject(MCAssembler &Asm,
505505 const MCAsmLayout &Layout) {
506 MCContext &Ctx = Asm.getContext();
506507 unsigned PtrType = is64Bit() ? wasm::WASM_TYPE_I64 : wasm::WASM_TYPE_I32;
507508
508509 // Collect information from the available symbols.
581582 }
582583
583584 Imports.push_back(Import);
585 }
586 }
587
588 // In the special .global_variables section, we've encoded global
589 // variables used by the function. Translate them into the Globals
590 // list.
591 MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", 0, 0);
592 if (!GlobalVars->getFragmentList().empty()) {
593 if (GlobalVars->getFragmentList().size() != 1)
594 report_fatal_error("only one .global_variables fragment supported");
595 const MCFragment &Frag = *GlobalVars->begin();
596 if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
597 report_fatal_error("only data supported in .global_variables");
598 const MCDataFragment &DataFrag = cast(Frag);
599 if (!DataFrag.getFixups().empty())
600 report_fatal_error("fixups not supported in .global_variables");
601 const SmallVectorImpl &Contents = DataFrag.getContents();
602 for (char p : Contents) {
603 WasmGlobal G;
604 G.Type = uint8_t(p);
605 G.IsMutable = true;
606 G.InitialValue = 0;
607 Globals.push_back(G);
584608 }
585609 }
586610
8383 }
8484 }
8585
86 void WebAssemblyTargetAsmStreamer::emitGlobal(ArrayRef Types) {
87 if (!Types.empty()) {
88 OS << "\t.globalvar \t";
89 PrintTypes(OS, Types);
90 }
91 }
92
8693 void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; }
8794
8895 void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType(
123130 Streamer.EmitIntValue(int64_t(WebAssembly::toValType(Type)), 1);
124131 }
125132
133 void WebAssemblyTargetELFStreamer::emitGlobal(ArrayRef Types) {
134 llvm_unreachable(".globalvar encoding not yet implemented");
135 }
136
126137 void WebAssemblyTargetELFStreamer::emitEndFunc() {
127138 Streamer.EmitIntValue(WebAssembly::End, 1);
128139 }
184195 }
185196 }
186197
198 void WebAssemblyTargetWasmStreamer::emitGlobal(ArrayRef Types) {
199 // Encode the globals use by the funciton into the special .global_variables
200 // section. This will later be decoded and turned into contents for the
201 // Globals Section.
202 Streamer.PushSection();
203 Streamer.SwitchSection(Streamer.getContext()
204 .getWasmSection(".global_variables", 0, 0));
205 for (MVT Ty : Types)
206 Streamer.EmitIntValue(uint64_t(WebAssembly::toValType(Ty)), 1);
207 Streamer.PopSection();
208 }
209
187210 void WebAssemblyTargetWasmStreamer::emitEndFunc() {
188211 llvm_unreachable(".end_func is not needed for direct wasm output");
189212 }
3535 virtual void emitResult(MCSymbol *Symbol, ArrayRef Types) = 0;
3636 /// .local
3737 virtual void emitLocal(ArrayRef Types) = 0;
38 /// .globalvar
39 virtual void emitGlobal(ArrayRef Types) = 0;
3840 /// .endfunc
3941 virtual void emitEndFunc() = 0;
4042 /// .functype
5961 void emitParam(MCSymbol *Symbol, ArrayRef Types) override;
6062 void emitResult(MCSymbol *Symbol, ArrayRef Types) override;
6163 void emitLocal(ArrayRef Types) override;
64 void emitGlobal(ArrayRef Types) override;
6265 void emitEndFunc() override;
6366 void emitIndirectFunctionType(StringRef name,
6467 SmallVectorImpl &Params,
7578 void emitParam(MCSymbol *Symbol, ArrayRef Types) override;
7679 void emitResult(MCSymbol *Symbol, ArrayRef Types) override;
7780 void emitLocal(ArrayRef Types) override;
81 void emitGlobal(ArrayRef Types) override;
7882 void emitEndFunc() override;
7983 void emitIndirectFunctionType(StringRef name,
8084 SmallVectorImpl &Params,
9195 void emitParam(MCSymbol *Symbol, ArrayRef Types) override;
9296 void emitResult(MCSymbol *Symbol, ArrayRef Types) override;
9397 void emitLocal(ArrayRef Types) override;
98 void emitGlobal(ArrayRef Types) override;
9499 void emitEndFunc() override;
95100 void emitIndirectFunctionType(StringRef name,
96101 SmallVectorImpl &Params,
2626 #include "llvm/CodeGen/AsmPrinter.h"
2727 #include "llvm/CodeGen/MachineConstantPool.h"
2828 #include "llvm/CodeGen/MachineInstr.h"
29 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
2930 #include "llvm/IR/DataLayout.h"
3031 #include "llvm/IR/GlobalVariable.h"
3132 #include "llvm/MC/MCContext.h"
9091 OutStreamer->emitELFSize(getSymbol(&G),
9192 MCConstantExpr::create(Size, OutContext));
9293 }
94 }
95
96 if (!TM.getTargetTriple().isOSBinFormatELF()) {
97 MachineModuleInfoWasm &MMIW = MMI->getObjFileInfo();
98 getTargetStreamer()->emitGlobal(MMIW.getGlobals());
9399 }
94100 }
95101
2727 #include "llvm/CodeGen/MachineFrameInfo.h"
2828 #include "llvm/CodeGen/MachineFunction.h"
2929 #include "llvm/CodeGen/MachineInstrBuilder.h"
30 #include "llvm/CodeGen/MachineModuleInfo.h"
30 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
3131 #include "llvm/CodeGen/MachineRegisterInfo.h"
3232 #include "llvm/Support/Debug.h"
3333 using namespace llvm;
101101 MachineBasicBlock::iterator &InsertAddr,
102102 MachineBasicBlock::iterator &InsertStore,
103103 const DebugLoc &DL) {
104 const char *ES = "__stack_pointer";
105 auto *SPSymbol = MF.createExternalSymbolName(ES);
106 MachineRegisterInfo &MRI = MF.getRegInfo();
107 const TargetRegisterClass *PtrRC =
108 MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
109 unsigned Zero = MRI.createVirtualRegister(PtrRC);
110 const auto *TII = MF.getSubtarget().getInstrInfo();
111
112 BuildMI(MBB, InsertAddr, DL, TII->get(WebAssembly::CONST_I32), Zero)
113 .addImm(0);
114 MachineMemOperand *MMO = MF.getMachineMemOperand(
115 MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)),
116 MachineMemOperand::MOStore, 4, 4);
117 BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::STORE_I32))
118 .addImm(2) // p2align
119 .addExternalSymbol(SPSymbol)
120 .addReg(Zero)
121 .addReg(SrcReg)
122 .addMemOperand(MMO);
104 const auto *TII = MF.getSubtarget().getInstrInfo();
105
106 if (MF.getSubtarget()
107 .getTargetTriple().isOSBinFormatELF()) {
108 const char *ES = "__stack_pointer";
109 auto *SPSymbol = MF.createExternalSymbolName(ES);
110 MachineRegisterInfo &MRI = MF.getRegInfo();
111 const TargetRegisterClass *PtrRC =
112 MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
113 unsigned Zero = MRI.createVirtualRegister(PtrRC);
114
115 BuildMI(MBB, InsertAddr, DL, TII->get(WebAssembly::CONST_I32), Zero)
116 .addImm(0);
117 MachineMemOperand *MMO = MF.getMachineMemOperand(
118 MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)),
119 MachineMemOperand::MOStore, 4, 4);
120 BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::STORE_I32))
121 .addImm(2) // p2align
122 .addExternalSymbol(SPSymbol)
123 .addReg(Zero)
124 .addReg(SrcReg)
125 .addMemOperand(MMO);
126 } else {
127 MachineModuleInfoWasm &MMIW =
128 MF.getMMI().getObjFileInfo();
129 BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::SET_GLOBAL_I32))
130 .addImm(MMIW.getStackPointerGlobal())
131 .addReg(SrcReg);
132 }
123133 }
124134
125135 MachineBasicBlock::iterator
157167
158168 const TargetRegisterClass *PtrRC =
159169 MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
160 unsigned Zero = MRI.createVirtualRegister(PtrRC);
161170 unsigned SPReg = WebAssembly::SP32;
162171 if (StackSize)
163172 SPReg = MRI.createVirtualRegister(PtrRC);
164 const char *ES = "__stack_pointer";
165 auto *SPSymbol = MF.createExternalSymbolName(ES);
166 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), Zero)
167 .addImm(0);
168 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
169 MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)),
170 MachineMemOperand::MOLoad, 4, 4);
171 // Load the SP value.
172 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::LOAD_I32), SPReg)
173 .addImm(2) // p2align
174 .addExternalSymbol(SPSymbol)
175 .addReg(Zero) // addr
176 .addMemOperand(LoadMMO);
173 if (MF.getSubtarget()
174 .getTargetTriple().isOSBinFormatELF()) {
175 const char *ES = "__stack_pointer";
176 auto *SPSymbol = MF.createExternalSymbolName(ES);
177 unsigned Zero = MRI.createVirtualRegister(PtrRC);
178
179 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), Zero)
180 .addImm(0);
181 MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
182 MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)),
183 MachineMemOperand::MOLoad, 4, 4);
184 // Load the SP value.
185 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::LOAD_I32), SPReg)
186 .addImm(2) // p2align
187 .addExternalSymbol(SPSymbol)
188 .addReg(Zero) // addr
189 .addMemOperand(LoadMMO);
190 } else {
191 auto &MMIW = MF.getMMI().getObjFileInfo();
192 if (!MMIW.hasStackPointerGlobal()) {
193 MMIW.setStackPointerGlobal(MMIW.getGlobals().size());
194 MMIW.addGlobal(MVT::i32);
195 }
196 BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::GET_GLOBAL_I32), SPReg)
197 .addImm(MMIW.getStackPointerGlobal());
198 }
177199
178200 bool HasBP = hasBP(MF);
179201 if (HasBP) {
2929 #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
3030 #include "llvm/CodeGen/MachineDominators.h"
3131 #include "llvm/CodeGen/MachineInstrBuilder.h"
32 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
3233 #include "llvm/CodeGen/MachineRegisterInfo.h"
3334 #include "llvm/CodeGen/Passes.h"
3435 #include "llvm/Support/Debug.h"
151152 }
152153
153154 // Determine whether MI reads memory, writes memory, has side effects,
154 // and/or uses the __stack_pointer value.
155 // and/or uses the stack pointer value.
155156 static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read,
156157 bool &Write, bool &Effects, bool &StackPointer) {
157158 assert(!MI.isPosition());
168169 if (MI.mayStore()) {
169170 Write = true;
170171
171 // Check for stores to __stack_pointer.
172 for (auto MMO : MI.memoperands()) {
173 const MachinePointerInfo &MPI = MMO->getPointerInfo();
174 if (MPI.V.is()) {
175 auto PSV = MPI.V.get();
176 if (const ExternalSymbolPseudoSourceValue *EPSV =
177 dyn_cast(PSV))
178 if (StringRef(EPSV->getSymbol()) == "__stack_pointer")
179 StackPointer = true;
172 const MachineFunction &MF = *MI.getParent()->getParent();
173 if (MF.getSubtarget()
174 .getTargetTriple().isOSBinFormatELF()) {
175 // Check for stores to __stack_pointer.
176 for (auto MMO : MI.memoperands()) {
177 const MachinePointerInfo &MPI = MMO->getPointerInfo();
178 if (MPI.V.is()) {
179 auto PSV = MPI.V.get();
180 if (const ExternalSymbolPseudoSourceValue *EPSV =
181 dyn_cast(PSV))
182 if (StringRef(EPSV->getSymbol()) == "__stack_pointer")
183 StackPointer = true;
184 }
185 }
186 } else {
187 // Check for sets of the stack pointer.
188 const MachineModuleInfoWasm &MMIW =
189 MF.getMMI().getObjFileInfo();
190 if ((MI.getOpcode() == WebAssembly::SET_LOCAL_I32 ||
191 MI.getOpcode() == WebAssembly::SET_LOCAL_I64) &&
192 MI.getOperand(0).getImm() == MMIW.getStackPointerGlobal()) {
193 StackPointer = true;
180194 }
181195 }
182196 } else if (MI.hasOrderedMemoryRef()) {
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
11
22 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
3 target triple = "wasm32-unknown-unknown"
3 target triple = "wasm32-unknown-unknown-wasm"
44
55 declare void @somefunc(i32*)
66
77 ; CHECK-LABEL: underalign:
8 ; CHECK: i32.load $push[[L1:.+]]=, __stack_pointer{{.+}}
8 ; CHECK: get_global $push[[L1:.+]]=, 0{{$}}
99 ; CHECK-NEXT: i32.const $push[[L2:.+]]=, 16
1010 ; CHECK-NEXT: i32.sub $push[[L10:.+]]=, $pop[[L1]], $pop[[L2]]
11 ; CHECK-NEXT: tee_local $push{{.+}}=, $[[SP:.+]]=, $pop[[L10]]
11 ; CHECK-NEXT: tee_local $push{{.+}}=, [[SP:.+]], $pop[[L10]]
1212
13 ; CHECK: i32.add $push[[underaligned:.+]]=, $[[SP]], $pop{{.+}}
13 ; CHECK: get_local $push[[L3:.+]]=, [[SP]]{{$}}
14 ; CHECK: i32.add $push[[underaligned:.+]]=, $pop[[L3]], $pop{{.+}}
1415 ; CHECK-NEXT: call somefunc@FUNCTION, $pop[[underaligned]]
1516
16 ; CHECK: i32.add $push[[L5:.+]]=, $[[SP]], $pop{{.+}}
17 ; CHECK-NEXT: i32.store __stack_pointer($pop{{.+}}), $pop[[L5]]
17 ; CHECK: get_local $push[[M4:.+]]=, [[SP]]{{$}}
18 ; CHECK: i32.add $push[[L5:.+]]=, $pop[[M4]], $pop{{.+}}
19 ; CHECK-NEXT: set_global 0, $pop[[L5]]
1820 define void @underalign() {
1921 entry:
2022 %underaligned = alloca i32, align 8
2325 }
2426
2527 ; CHECK-LABEL: overalign:
26 ; CHECK: i32.load $push[[L10:.+]]=, __stack_pointer
27 ; CHECK-NEXT: tee_local $push[[L9:.+]]=, $[[BP:.+]]=, $pop[[L10]]
28 ; CHECK: get_global $push[[L10:.+]]=, 0{{$}}
29 ; CHECK-NEXT: tee_local $push[[L9:.+]]=, [[BP:.+]], $pop[[L10]]
2830 ; CHECK-NEXT: i32.const $push[[L2:.+]]=, 32
2931 ; CHECK-NEXT: i32.sub $push[[L8:.+]]=, $pop[[L9]], $pop[[L2]]
3032 ; CHECK-NEXT: i32.const $push[[L3:.+]]=, -32
3133 ; CHECK-NEXT: i32.and $push[[L7:.+]]=, $pop[[L8]], $pop[[L3]]
32 ; CHECK-NEXT: tee_local $push{{.+}}=, $[[SP:.+]]=, $pop[[L7]]
34 ; CHECK-NEXT: tee_local $push{{.+}}=, [[SP:.+]], $pop[[L7]]
3335
34 ; CHECK: call somefunc@FUNCTION, $[[SP]]
36 ; CHECK: get_local $push[[M5:.+]]=, [[SP]]{{$}}
37 ; CHECK: call somefunc@FUNCTION, $pop[[M5]]{{$}}
3538
36 ; CHECK: copy_local $push[[L5:.+]]=, $[[BP]]
37 ; CHECK-NEXT: i32.store __stack_pointer($pop{{.+}}), $pop[[L5]]
39 ; CHECK: get_local $push[[M6:.+]]=, [[BP]]{{$}}
40 ; CHECK-NEXT: set_global 0, $pop[[M6]]
3841 define void @overalign() {
3942 entry:
4043 %overaligned = alloca i32, align 32
4346 }
4447
4548 ; CHECK-LABEL: over_and_normal_align:
46 ; CHECK: i32.load $push[[L14:.+]]=, __stack_pointer
47 ; CHECK-NEXT: tee_local $push[[L13:.+]]=, $[[BP:.+]]=, $pop[[L14]]
49 ; CHECK: get_global $push[[L14:.+]]=, 0{{$}}
50 ; CHECK-NEXT: tee_local $push[[L13:.+]]=, [[BP:.+]], $pop[[L14]]
4851 ; CHECK: i32.sub $push[[L12:.+]]=, $pop[[L13]], $pop{{.+}}
4952 ; CHECK: i32.and $push[[L11:.+]]=, $pop[[L12]], $pop{{.+}}
50 ; CHECK-NEXT: tee_local $push{{.+}}=, $[[SP]]=, $pop[[L11]]
53 ; CHECK-NEXT: tee_local $push{{.+}}=, [[SP:.+]], $pop[[L11]]
5154
52 ; CHECK: i32.add $push[[L6:.+]]=, $[[SP]], $pop{{.+}}
55 ; CHECK: get_local $push[[M6:.+]]=, [[SP]]{{$}}
56 ; CHECK: i32.add $push[[L6:.+]]=, $pop[[M6]], $pop{{.+}}
5357 ; CHECK-NEXT: call somefunc@FUNCTION, $pop[[L6]]
54 ; CHECK: i32.add $push[[L8:.+]]=, $[[SP]], $pop{{.+}}
58 ; CHECK: get_local $push[[M7:.+]]=, [[SP]]{{$}}
59 ; CHECK: i32.add $push[[L8:.+]]=, $pop[[M7]], $pop{{.+}}
5560 ; CHECK-NEXT: call somefunc@FUNCTION, $pop[[L8]]
5661
57 ; CHECK: copy_local $push[[L9:.+]]=, $[[BP]]
58 ; CHECK-NEXT: i32.store __stack_pointer({{.+}}), $pop[[L9]]
62 ; CHECK: get_local $push[[L6:.+]]=, [[BP]]{{$}}
63 ; CHECK-NEXT: set_global 0, $pop[[L6]]
5964 define void @over_and_normal_align() {
6065 entry:
6166 %over = alloca i32, align 32
6671 }
6772
6873 ; CHECK-LABEL: dynamic_overalign:
69 ; CHECK: i32.load $push[[L18:.+]]=, __stack_pointer
70 ; CHECK-NEXT: tee_local $push[[L17:.+]]=, $[[SP:.+]]=, $pop[[L18]]
71 ; CHECK-NEXT: copy_local $[[BP:.+]]=, $pop[[L17]]
72 ; CHECK: tee_local $push{{.+}}=, $[[SP_2:.+]]=, $pop{{.+}}
74 ; CHECK: get_global $push[[L18:.+]]=, 0{{$}}
75 ; CHECK-NEXT: tee_local $push[[L17:.+]]=, [[SP:.+]], $pop[[L18]]
76 ; CHECK-NEXT: set_local [[BP:.+]], $pop[[L17]]
77 ; CHECK: tee_local $push{{.+}}=, [[SP_2:.+]], $pop{{.+}}
7378
74 ; CHECK: call somefunc@FUNCTION, $[[SP_2]]
79 ; CHECK: get_local $push[[M8:.+]]=, [[SP_2]]{{$}}
80 ; CHECK: call somefunc@FUNCTION, $pop[[M8]]
7581
76 ; CHECK: i32.store __stack_pointer($pop{{.+}}), $[[BP]]
82 ; CHECK: get_local $push[[M9:.+]]=, [[BP]]{{$}}
83 ; CHECK-NEXT: set_global 0, $pop[[M9]]
7784 define void @dynamic_overalign(i32 %num) {
7885 entry:
7986 %dynamic = alloca i32, i32 %num, align 32
8289 }
8390
8491 ; CHECK-LABEL: overalign_and_dynamic:
85 ; CHECK: i32.load $push[[L21:.+]]=, __stack_pointer
86 ; CHECK-NEXT: tee_local $push[[L20:.+]]=, $[[BP:.+]]=, $pop[[L21]]
92 ; CHECK: get_global $push[[L21:.+]]=, 0{{$}}
93 ; CHECK-NEXT: tee_local $push[[L20:.+]]=, [[BP:.+]], $pop[[L21]]
8794 ; CHECK: i32.sub $push[[L19:.+]]=, $pop[[L20]], $pop{{.+}}
8895 ; CHECK: i32.and $push[[L18:.+]]=, $pop[[L19]], $pop{{.+}}
89 ; CHECK: tee_local $push{{.+}}=, $[[FP:.+]]=, $pop[[L18]]
90 ; CHECK: i32.sub $push[[L16:.+]]=, $[[FP]], $pop{{.+}}
91 ; CHECK-NEXT: tee_local $push{{.+}}=, $[[SP:.+]]=, $pop[[L16]]
96 ; CHECK: tee_local $push{{.+}}=, [[FP:.+]], $pop[[L18]]
97 ; CHECK: get_local $push[[M10:.+]]=, [[FP]]{{$}}
98 ; CHECK: i32.sub $push[[L16:.+]]=, $pop[[M10]], $pop{{.+}}
99 ; CHECK-NEXT: tee_local $push{{.+}}=, [[SP:.+]], $pop[[L16]]
92100
93 ; CHECK: copy_local $push[[over:.+]]=, $[[FP]]
101 ; CHECK: get_local $push[[over:.+]]=, [[FP]]
94102 ; CHECK-NEXT: call somefunc@FUNCTION, $pop[[over]]
95 ; CHECK-NEXT: call somefunc@FUNCTION, $[[SP]]
103 ; CHECK: get_local $push[[another:.+]]=, [[SP]]
104 ; CHECK-NEXT: call somefunc@FUNCTION, $pop[[another]]
96105
97 ; CHECK: copy_local $push[[L12:.+]]=, $[[BP]]
98 ; CHECK-NEXT: i32.store __stack_pointer($pop{{.+}}), $pop[[L12]]
106 ; CHECK: get_local $push[[M11:.+]]=, [[BP]]{{$}}
107 ; CHECK-NEXT: set_global 0, $pop[[M11]]
99108 define void @overalign_and_dynamic(i32 %num) {
100109 entry:
101110 %over = alloca i32, align 32
106115 }
107116
108117 ; CHECK-LABEL: overalign_static_and_dynamic:
109 ; CHECK: i32.load $push[[L26:.+]]=, __stack_pointer
110 ; CHECK-NEXT: tee_local $push[[L25:.+]]=, $[[BP:.+]]=, $pop[[L26]]
118 ; CHECK: get_global $push[[L26:.+]]=, 0{{$}}
119 ; CHECK-NEXT: tee_local $push[[L25:.+]]=, [[BP:.+]], $pop[[L26]]
111120 ; CHECK: i32.sub $push[[L24:.+]]=, $pop[[L25]], $pop{{.+}}
112121 ; CHECK: i32.and $push[[L23:.+]]=, $pop[[L24]], $pop{{.+}}
113 ; CHECK: tee_local $push{{.+}}=, $[[FP:.+]]=, $pop[[L23]]
114 ; CHECK: i32.sub $push[[L21:.+]]=, $[[FP]], $pop{{.+}}
115 ; CHECK-NEXT: tee_local $push{{.+}}=, $[[SP:.+]]=, $pop[[L21]]
122 ; CHECK: tee_local $push{{.+}}=, [[FP:.+]], $pop[[L23]]
123 ; CHECK: get_local $push[[M12:.+]]=, [[FP]]{{$}}
124 ; CHECK: i32.sub $push[[L21:.+]]=, $pop[[M12]], $pop{{.+}}
125 ; CHECK-NEXT: tee_local $push{{.+}}=, [[SP:.+]], $pop[[L21]]
116126
117 ; CHECK: copy_local $push[[L19:.+]]=, $[[FP]]
118 ; CHECK: tee_local $push[[L18:.+]]=, $[[FP_2:.+]]=, $pop[[L19]]
127 ; CHECK: get_local $push[[L19:.+]]=, [[FP]]
128 ; CHECK: tee_local $push[[L18:.+]]=, [[FP_2:.+]], $pop[[L19]]
119129 ; CHECK: i32.add $push[[over:.+]]=, $pop[[L18]], $pop{{.+}}
120130 ; CHECK-NEXT: call somefunc@FUNCTION, $pop[[over]]
121 ; CHECK: call somefunc@FUNCTION, $[[SP]]
122 ; CHECK: i32.add $push[[static:.+]]=, $[[FP_2]], $pop{{.+}}
131 ; CHECK: get_local $push[[M12:.+]]=, [[SP]]
132 ; CHECK: call somefunc@FUNCTION, $pop[[M12]]
133 ; CHECK: get_local $push[[M13:.+]]=, [[FP_2]]
134 ; CHECK: i32.add $push[[static:.+]]=, $pop[[M13]], $pop{{.+}}
123135 ; CHECK-NEXT: call somefunc@FUNCTION, $pop[[static]]
124136
125 ; CHECK: copy_local $push[[L16:.+]]=, $[[BP]]
126 ; CHECK-NEXT: i32.store __stack_pointer({{.+}}), $pop[[L16]]
137 ; CHECK: get_local $push[[M14:.+]]=, [[BP]]{{$}}
138 ; CHECK-NEXT: set_global 0, $pop[[M14]]
127139 define void @overalign_static_and_dynamic(i32 %num) {
128140 entry:
129141 %over = alloca i32, align 32