forked from OSchip/llvm-project
[WebAssembly] Add support for using a wasm global for the stack pointer.
This replaces the __stack_pointer variable which was allocated in linear memory. llvm-svn: 296201
This commit is contained in:
parent
8d543e2741
commit
82607f56bd
|
@ -15,6 +15,7 @@
|
|||
#ifndef LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H
|
||||
#define LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H
|
||||
|
||||
#include "llvm/CodeGen/ValueTypes.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
@ -75,6 +76,32 @@ public:
|
|||
SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
|
||||
};
|
||||
|
||||
/// MachineModuleInfoWasm - This is a MachineModuleInfoImpl implementation
|
||||
/// for Wasm targets.
|
||||
class MachineModuleInfoWasm : public MachineModuleInfoImpl {
|
||||
/// GVStubs - These stubs are used to materialize global addresses in PIC
|
||||
/// mode.
|
||||
std::vector<MVT> Globals;
|
||||
unsigned StackPointerGlobal;
|
||||
|
||||
virtual void anchor(); // Out of line virtual method.
|
||||
public:
|
||||
MachineModuleInfoWasm(const MachineModuleInfo &)
|
||||
: StackPointerGlobal(-1U) {}
|
||||
|
||||
void addGlobal(MVT VT) { Globals.push_back(VT); }
|
||||
const std::vector<MVT> &getGlobals() const { return Globals; }
|
||||
|
||||
bool hasStackPointerGlobal() const {
|
||||
return StackPointerGlobal != -1U;
|
||||
}
|
||||
unsigned getStackPointerGlobal() const {
|
||||
assert(hasStackPointerGlobal() && "Stack ptr global hasn't been set");
|
||||
return StackPointerGlobal;
|
||||
}
|
||||
void setStackPointerGlobal(unsigned Global) { StackPointerGlobal = Global; }
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,7 @@ using namespace llvm;
|
|||
// Out of line virtual method.
|
||||
void MachineModuleInfoMachO::anchor() {}
|
||||
void MachineModuleInfoELF::anchor() {}
|
||||
void MachineModuleInfoWasm::anchor() {}
|
||||
|
||||
static int SortSymbolPair(const void *LHS, const void *RHS) {
|
||||
typedef std::pair<MCSymbol*, MachineModuleInfoImpl::StubValueTy> PairTy;
|
||||
|
|
|
@ -504,6 +504,7 @@ static void WriteRelocations(
|
|||
|
||||
void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) {
|
||||
MCContext &Ctx = Asm.getContext();
|
||||
unsigned PtrType = is64Bit() ? wasm::WASM_TYPE_I64 : wasm::WASM_TYPE_I32;
|
||||
|
||||
// Collect information from the available symbols.
|
||||
|
@ -585,6 +586,29 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
|
|||
}
|
||||
}
|
||||
|
||||
// In the special .global_variables section, we've encoded global
|
||||
// variables used by the function. Translate them into the Globals
|
||||
// list.
|
||||
MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", 0, 0);
|
||||
if (!GlobalVars->getFragmentList().empty()) {
|
||||
if (GlobalVars->getFragmentList().size() != 1)
|
||||
report_fatal_error("only one .global_variables fragment supported");
|
||||
const MCFragment &Frag = *GlobalVars->begin();
|
||||
if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
|
||||
report_fatal_error("only data supported in .global_variables");
|
||||
const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag);
|
||||
if (!DataFrag.getFixups().empty())
|
||||
report_fatal_error("fixups not supported in .global_variables");
|
||||
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
|
||||
for (char p : Contents) {
|
||||
WasmGlobal G;
|
||||
G.Type = uint8_t(p);
|
||||
G.IsMutable = true;
|
||||
G.InitialValue = 0;
|
||||
Globals.push_back(G);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle defined symbols.
|
||||
for (const MCSymbol &S : Asm.symbols()) {
|
||||
// Ignore unnamed temporary symbols, which aren't ever exported, imported,
|
||||
|
|
|
@ -84,6 +84,13 @@ void WebAssemblyTargetAsmStreamer::emitLocal(ArrayRef<MVT> Types) {
|
|||
}
|
||||
}
|
||||
|
||||
void WebAssemblyTargetAsmStreamer::emitGlobal(ArrayRef<MVT> Types) {
|
||||
if (!Types.empty()) {
|
||||
OS << "\t.globalvar \t";
|
||||
PrintTypes(OS, Types);
|
||||
}
|
||||
}
|
||||
|
||||
void WebAssemblyTargetAsmStreamer::emitEndFunc() { OS << "\t.endfunc\n"; }
|
||||
|
||||
void WebAssemblyTargetAsmStreamer::emitIndirectFunctionType(
|
||||
|
@ -124,6 +131,10 @@ void WebAssemblyTargetELFStreamer::emitLocal(ArrayRef<MVT> Types) {
|
|||
Streamer.EmitIntValue(int64_t(WebAssembly::toValType(Type)), 1);
|
||||
}
|
||||
|
||||
void WebAssemblyTargetELFStreamer::emitGlobal(ArrayRef<MVT> Types) {
|
||||
llvm_unreachable(".globalvar encoding not yet implemented");
|
||||
}
|
||||
|
||||
void WebAssemblyTargetELFStreamer::emitEndFunc() {
|
||||
Streamer.EmitIntValue(WebAssembly::End, 1);
|
||||
}
|
||||
|
@ -185,6 +196,18 @@ void WebAssemblyTargetWasmStreamer::emitLocal(ArrayRef<MVT> Types) {
|
|||
}
|
||||
}
|
||||
|
||||
void WebAssemblyTargetWasmStreamer::emitGlobal(ArrayRef<MVT> Types) {
|
||||
// Encode the globals use by the funciton into the special .global_variables
|
||||
// section. This will later be decoded and turned into contents for the
|
||||
// Globals Section.
|
||||
Streamer.PushSection();
|
||||
Streamer.SwitchSection(Streamer.getContext()
|
||||
.getWasmSection(".global_variables", 0, 0));
|
||||
for (MVT Ty : Types)
|
||||
Streamer.EmitIntValue(uint64_t(WebAssembly::toValType(Ty)), 1);
|
||||
Streamer.PopSection();
|
||||
}
|
||||
|
||||
void WebAssemblyTargetWasmStreamer::emitEndFunc() {
|
||||
llvm_unreachable(".end_func is not needed for direct wasm output");
|
||||
}
|
||||
|
|
|
@ -36,6 +36,8 @@ public:
|
|||
virtual void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) = 0;
|
||||
/// .local
|
||||
virtual void emitLocal(ArrayRef<MVT> Types) = 0;
|
||||
/// .globalvar
|
||||
virtual void emitGlobal(ArrayRef<MVT> Types) = 0;
|
||||
/// .endfunc
|
||||
virtual void emitEndFunc() = 0;
|
||||
/// .functype
|
||||
|
@ -60,6 +62,7 @@ public:
|
|||
void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
|
||||
void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
|
||||
void emitLocal(ArrayRef<MVT> Types) override;
|
||||
void emitGlobal(ArrayRef<MVT> Types) override;
|
||||
void emitEndFunc() override;
|
||||
void emitIndirectFunctionType(StringRef name,
|
||||
SmallVectorImpl<MVT> &Params,
|
||||
|
@ -76,6 +79,7 @@ public:
|
|||
void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
|
||||
void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
|
||||
void emitLocal(ArrayRef<MVT> Types) override;
|
||||
void emitGlobal(ArrayRef<MVT> Types) override;
|
||||
void emitEndFunc() override;
|
||||
void emitIndirectFunctionType(StringRef name,
|
||||
SmallVectorImpl<MVT> &Params,
|
||||
|
@ -92,6 +96,7 @@ public:
|
|||
void emitParam(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
|
||||
void emitResult(MCSymbol *Symbol, ArrayRef<MVT> Types) override;
|
||||
void emitLocal(ArrayRef<MVT> Types) override;
|
||||
void emitGlobal(ArrayRef<MVT> Types) override;
|
||||
void emitEndFunc() override;
|
||||
void emitIndirectFunctionType(StringRef name,
|
||||
SmallVectorImpl<MVT> &Params,
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/GlobalVariable.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
|
@ -92,6 +93,11 @@ void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) {
|
|||
MCConstantExpr::create(Size, OutContext));
|
||||
}
|
||||
}
|
||||
|
||||
if (!TM.getTargetTriple().isOSBinFormatELF()) {
|
||||
MachineModuleInfoWasm &MMIW = MMI->getObjFileInfo<MachineModuleInfoWasm>();
|
||||
getTargetStreamer()->emitGlobal(MMIW.getGlobals());
|
||||
}
|
||||
}
|
||||
|
||||
void WebAssemblyAsmPrinter::EmitConstantPool() {
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
using namespace llvm;
|
||||
|
@ -102,25 +102,35 @@ static void writeSPToMemory(unsigned SrcReg, MachineFunction &MF,
|
|||
MachineBasicBlock::iterator &InsertAddr,
|
||||
MachineBasicBlock::iterator &InsertStore,
|
||||
const DebugLoc &DL) {
|
||||
const char *ES = "__stack_pointer";
|
||||
auto *SPSymbol = MF.createExternalSymbolName(ES);
|
||||
MachineRegisterInfo &MRI = MF.getRegInfo();
|
||||
const TargetRegisterClass *PtrRC =
|
||||
MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
|
||||
unsigned Zero = MRI.createVirtualRegister(PtrRC);
|
||||
const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
|
||||
|
||||
BuildMI(MBB, InsertAddr, DL, TII->get(WebAssembly::CONST_I32), Zero)
|
||||
.addImm(0);
|
||||
MachineMemOperand *MMO = MF.getMachineMemOperand(
|
||||
MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)),
|
||||
MachineMemOperand::MOStore, 4, 4);
|
||||
BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::STORE_I32))
|
||||
.addImm(2) // p2align
|
||||
.addExternalSymbol(SPSymbol)
|
||||
.addReg(Zero)
|
||||
.addReg(SrcReg)
|
||||
.addMemOperand(MMO);
|
||||
if (MF.getSubtarget<WebAssemblySubtarget>()
|
||||
.getTargetTriple().isOSBinFormatELF()) {
|
||||
const char *ES = "__stack_pointer";
|
||||
auto *SPSymbol = MF.createExternalSymbolName(ES);
|
||||
MachineRegisterInfo &MRI = MF.getRegInfo();
|
||||
const TargetRegisterClass *PtrRC =
|
||||
MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
|
||||
unsigned Zero = MRI.createVirtualRegister(PtrRC);
|
||||
|
||||
BuildMI(MBB, InsertAddr, DL, TII->get(WebAssembly::CONST_I32), Zero)
|
||||
.addImm(0);
|
||||
MachineMemOperand *MMO = MF.getMachineMemOperand(
|
||||
MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)),
|
||||
MachineMemOperand::MOStore, 4, 4);
|
||||
BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::STORE_I32))
|
||||
.addImm(2) // p2align
|
||||
.addExternalSymbol(SPSymbol)
|
||||
.addReg(Zero)
|
||||
.addReg(SrcReg)
|
||||
.addMemOperand(MMO);
|
||||
} else {
|
||||
MachineModuleInfoWasm &MMIW =
|
||||
MF.getMMI().getObjFileInfo<MachineModuleInfoWasm>();
|
||||
BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::SET_GLOBAL_I32))
|
||||
.addImm(MMIW.getStackPointerGlobal())
|
||||
.addReg(SrcReg);
|
||||
}
|
||||
}
|
||||
|
||||
MachineBasicBlock::iterator
|
||||
|
@ -158,23 +168,35 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
|
|||
|
||||
const TargetRegisterClass *PtrRC =
|
||||
MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
|
||||
unsigned Zero = MRI.createVirtualRegister(PtrRC);
|
||||
unsigned SPReg = WebAssembly::SP32;
|
||||
if (StackSize)
|
||||
SPReg = MRI.createVirtualRegister(PtrRC);
|
||||
const char *ES = "__stack_pointer";
|
||||
auto *SPSymbol = MF.createExternalSymbolName(ES);
|
||||
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), Zero)
|
||||
.addImm(0);
|
||||
MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
|
||||
MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)),
|
||||
MachineMemOperand::MOLoad, 4, 4);
|
||||
// Load the SP value.
|
||||
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::LOAD_I32), SPReg)
|
||||
.addImm(2) // p2align
|
||||
.addExternalSymbol(SPSymbol)
|
||||
.addReg(Zero) // addr
|
||||
.addMemOperand(LoadMMO);
|
||||
if (MF.getSubtarget<WebAssemblySubtarget>()
|
||||
.getTargetTriple().isOSBinFormatELF()) {
|
||||
const char *ES = "__stack_pointer";
|
||||
auto *SPSymbol = MF.createExternalSymbolName(ES);
|
||||
unsigned Zero = MRI.createVirtualRegister(PtrRC);
|
||||
|
||||
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), Zero)
|
||||
.addImm(0);
|
||||
MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
|
||||
MachinePointerInfo(MF.getPSVManager().getExternalSymbolCallEntry(ES)),
|
||||
MachineMemOperand::MOLoad, 4, 4);
|
||||
// Load the SP value.
|
||||
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::LOAD_I32), SPReg)
|
||||
.addImm(2) // p2align
|
||||
.addExternalSymbol(SPSymbol)
|
||||
.addReg(Zero) // addr
|
||||
.addMemOperand(LoadMMO);
|
||||
} else {
|
||||
auto &MMIW = MF.getMMI().getObjFileInfo<MachineModuleInfoWasm>();
|
||||
if (!MMIW.hasStackPointerGlobal()) {
|
||||
MMIW.setStackPointerGlobal(MMIW.getGlobals().size());
|
||||
MMIW.addGlobal(MVT::i32);
|
||||
}
|
||||
BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::GET_GLOBAL_I32), SPReg)
|
||||
.addImm(MMIW.getStackPointerGlobal());
|
||||
}
|
||||
|
||||
bool HasBP = hasBP(MF);
|
||||
if (HasBP) {
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
|
||||
#include "llvm/CodeGen/MachineDominators.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
|
@ -152,7 +153,7 @@ static void QueryCallee(const MachineInstr &MI, unsigned CalleeOpNo, bool &Read,
|
|||
}
|
||||
|
||||
// Determine whether MI reads memory, writes memory, has side effects,
|
||||
// and/or uses the __stack_pointer value.
|
||||
// and/or uses the stack pointer value.
|
||||
static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read,
|
||||
bool &Write, bool &Effects, bool &StackPointer) {
|
||||
assert(!MI.isPosition());
|
||||
|
@ -169,15 +170,28 @@ static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read,
|
|||
if (MI.mayStore()) {
|
||||
Write = true;
|
||||
|
||||
// Check for stores to __stack_pointer.
|
||||
for (auto MMO : MI.memoperands()) {
|
||||
const MachinePointerInfo &MPI = MMO->getPointerInfo();
|
||||
if (MPI.V.is<const PseudoSourceValue *>()) {
|
||||
auto PSV = MPI.V.get<const PseudoSourceValue *>();
|
||||
if (const ExternalSymbolPseudoSourceValue *EPSV =
|
||||
dyn_cast<ExternalSymbolPseudoSourceValue>(PSV))
|
||||
if (StringRef(EPSV->getSymbol()) == "__stack_pointer")
|
||||
StackPointer = true;
|
||||
const MachineFunction &MF = *MI.getParent()->getParent();
|
||||
if (MF.getSubtarget<WebAssemblySubtarget>()
|
||||
.getTargetTriple().isOSBinFormatELF()) {
|
||||
// Check for stores to __stack_pointer.
|
||||
for (auto MMO : MI.memoperands()) {
|
||||
const MachinePointerInfo &MPI = MMO->getPointerInfo();
|
||||
if (MPI.V.is<const PseudoSourceValue *>()) {
|
||||
auto PSV = MPI.V.get<const PseudoSourceValue *>();
|
||||
if (const ExternalSymbolPseudoSourceValue *EPSV =
|
||||
dyn_cast<ExternalSymbolPseudoSourceValue>(PSV))
|
||||
if (StringRef(EPSV->getSymbol()) == "__stack_pointer")
|
||||
StackPointer = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check for sets of the stack pointer.
|
||||
const MachineModuleInfoWasm &MMIW =
|
||||
MF.getMMI().getObjFileInfo<MachineModuleInfoWasm>();
|
||||
if ((MI.getOpcode() == WebAssembly::SET_LOCAL_I32 ||
|
||||
MI.getOpcode() == WebAssembly::SET_LOCAL_I64) &&
|
||||
MI.getOperand(0).getImm() == MMIW.getStackPointerGlobal()) {
|
||||
StackPointer = true;
|
||||
}
|
||||
}
|
||||
} else if (MI.hasOrderedMemoryRef()) {
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | FileCheck %s
|
||||
|
||||
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
||||
target triple = "wasm32-unknown-unknown"
|
||||
target triple = "wasm32-unknown-unknown-wasm"
|
||||
|
||||
declare void @somefunc(i32*)
|
||||
|
||||
; CHECK-LABEL: underalign:
|
||||
; CHECK: i32.load $push[[L1:.+]]=, __stack_pointer{{.+}}
|
||||
; CHECK: get_global $push[[L1:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: i32.const $push[[L2:.+]]=, 16
|
||||
; CHECK-NEXT: i32.sub $push[[L10:.+]]=, $pop[[L1]], $pop[[L2]]
|
||||
; CHECK-NEXT: tee_local $push{{.+}}=, $[[SP:.+]]=, $pop[[L10]]
|
||||
; CHECK-NEXT: tee_local $push{{.+}}=, [[SP:.+]], $pop[[L10]]
|
||||
|
||||
; CHECK: i32.add $push[[underaligned:.+]]=, $[[SP]], $pop{{.+}}
|
||||
; CHECK: get_local $push[[L3:.+]]=, [[SP]]{{$}}
|
||||
; CHECK: i32.add $push[[underaligned:.+]]=, $pop[[L3]], $pop{{.+}}
|
||||
; CHECK-NEXT: call somefunc@FUNCTION, $pop[[underaligned]]
|
||||
|
||||
; CHECK: i32.add $push[[L5:.+]]=, $[[SP]], $pop{{.+}}
|
||||
; CHECK-NEXT: i32.store __stack_pointer($pop{{.+}}), $pop[[L5]]
|
||||
; CHECK: get_local $push[[M4:.+]]=, [[SP]]{{$}}
|
||||
; CHECK: i32.add $push[[L5:.+]]=, $pop[[M4]], $pop{{.+}}
|
||||
; CHECK-NEXT: set_global 0, $pop[[L5]]
|
||||
define void @underalign() {
|
||||
entry:
|
||||
%underaligned = alloca i32, align 8
|
||||
|
@ -24,18 +26,19 @@ entry:
|
|||
}
|
||||
|
||||
; CHECK-LABEL: overalign:
|
||||
; CHECK: i32.load $push[[L10:.+]]=, __stack_pointer
|
||||
; CHECK-NEXT: tee_local $push[[L9:.+]]=, $[[BP:.+]]=, $pop[[L10]]
|
||||
; CHECK: get_global $push[[L10:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: tee_local $push[[L9:.+]]=, [[BP:.+]], $pop[[L10]]
|
||||
; CHECK-NEXT: i32.const $push[[L2:.+]]=, 32
|
||||
; CHECK-NEXT: i32.sub $push[[L8:.+]]=, $pop[[L9]], $pop[[L2]]
|
||||
; CHECK-NEXT: i32.const $push[[L3:.+]]=, -32
|
||||
; CHECK-NEXT: i32.and $push[[L7:.+]]=, $pop[[L8]], $pop[[L3]]
|
||||
; CHECK-NEXT: tee_local $push{{.+}}=, $[[SP:.+]]=, $pop[[L7]]
|
||||
; CHECK-NEXT: tee_local $push{{.+}}=, [[SP:.+]], $pop[[L7]]
|
||||
|
||||
; CHECK: call somefunc@FUNCTION, $[[SP]]
|
||||
; CHECK: get_local $push[[M5:.+]]=, [[SP]]{{$}}
|
||||
; CHECK: call somefunc@FUNCTION, $pop[[M5]]{{$}}
|
||||
|
||||
; CHECK: copy_local $push[[L5:.+]]=, $[[BP]]
|
||||
; CHECK-NEXT: i32.store __stack_pointer($pop{{.+}}), $pop[[L5]]
|
||||
; CHECK: get_local $push[[M6:.+]]=, [[BP]]{{$}}
|
||||
; CHECK-NEXT: set_global 0, $pop[[M6]]
|
||||
define void @overalign() {
|
||||
entry:
|
||||
%overaligned = alloca i32, align 32
|
||||
|
@ -44,19 +47,21 @@ entry:
|
|||
}
|
||||
|
||||
; CHECK-LABEL: over_and_normal_align:
|
||||
; CHECK: i32.load $push[[L14:.+]]=, __stack_pointer
|
||||
; CHECK-NEXT: tee_local $push[[L13:.+]]=, $[[BP:.+]]=, $pop[[L14]]
|
||||
; CHECK: get_global $push[[L14:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: tee_local $push[[L13:.+]]=, [[BP:.+]], $pop[[L14]]
|
||||
; CHECK: i32.sub $push[[L12:.+]]=, $pop[[L13]], $pop{{.+}}
|
||||
; CHECK: i32.and $push[[L11:.+]]=, $pop[[L12]], $pop{{.+}}
|
||||
; CHECK-NEXT: tee_local $push{{.+}}=, $[[SP]]=, $pop[[L11]]
|
||||
; CHECK-NEXT: tee_local $push{{.+}}=, [[SP:.+]], $pop[[L11]]
|
||||
|
||||
; CHECK: i32.add $push[[L6:.+]]=, $[[SP]], $pop{{.+}}
|
||||
; CHECK: get_local $push[[M6:.+]]=, [[SP]]{{$}}
|
||||
; CHECK: i32.add $push[[L6:.+]]=, $pop[[M6]], $pop{{.+}}
|
||||
; CHECK-NEXT: call somefunc@FUNCTION, $pop[[L6]]
|
||||
; CHECK: i32.add $push[[L8:.+]]=, $[[SP]], $pop{{.+}}
|
||||
; CHECK: get_local $push[[M7:.+]]=, [[SP]]{{$}}
|
||||
; CHECK: i32.add $push[[L8:.+]]=, $pop[[M7]], $pop{{.+}}
|
||||
; CHECK-NEXT: call somefunc@FUNCTION, $pop[[L8]]
|
||||
|
||||
; CHECK: copy_local $push[[L9:.+]]=, $[[BP]]
|
||||
; CHECK-NEXT: i32.store __stack_pointer({{.+}}), $pop[[L9]]
|
||||
; CHECK: get_local $push[[L6:.+]]=, [[BP]]{{$}}
|
||||
; CHECK-NEXT: set_global 0, $pop[[L6]]
|
||||
define void @over_and_normal_align() {
|
||||
entry:
|
||||
%over = alloca i32, align 32
|
||||
|
@ -67,14 +72,16 @@ entry:
|
|||
}
|
||||
|
||||
; CHECK-LABEL: dynamic_overalign:
|
||||
; CHECK: i32.load $push[[L18:.+]]=, __stack_pointer
|
||||
; CHECK-NEXT: tee_local $push[[L17:.+]]=, $[[SP:.+]]=, $pop[[L18]]
|
||||
; CHECK-NEXT: copy_local $[[BP:.+]]=, $pop[[L17]]
|
||||
; CHECK: tee_local $push{{.+}}=, $[[SP_2:.+]]=, $pop{{.+}}
|
||||
; CHECK: get_global $push[[L18:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: tee_local $push[[L17:.+]]=, [[SP:.+]], $pop[[L18]]
|
||||
; CHECK-NEXT: set_local [[BP:.+]], $pop[[L17]]
|
||||
; CHECK: tee_local $push{{.+}}=, [[SP_2:.+]], $pop{{.+}}
|
||||
|
||||
; CHECK: call somefunc@FUNCTION, $[[SP_2]]
|
||||
; CHECK: get_local $push[[M8:.+]]=, [[SP_2]]{{$}}
|
||||
; CHECK: call somefunc@FUNCTION, $pop[[M8]]
|
||||
|
||||
; CHECK: i32.store __stack_pointer($pop{{.+}}), $[[BP]]
|
||||
; CHECK: get_local $push[[M9:.+]]=, [[BP]]{{$}}
|
||||
; CHECK-NEXT: set_global 0, $pop[[M9]]
|
||||
define void @dynamic_overalign(i32 %num) {
|
||||
entry:
|
||||
%dynamic = alloca i32, i32 %num, align 32
|
||||
|
@ -83,20 +90,22 @@ entry:
|
|||
}
|
||||
|
||||
; CHECK-LABEL: overalign_and_dynamic:
|
||||
; CHECK: i32.load $push[[L21:.+]]=, __stack_pointer
|
||||
; CHECK-NEXT: tee_local $push[[L20:.+]]=, $[[BP:.+]]=, $pop[[L21]]
|
||||
; CHECK: get_global $push[[L21:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: tee_local $push[[L20:.+]]=, [[BP:.+]], $pop[[L21]]
|
||||
; CHECK: i32.sub $push[[L19:.+]]=, $pop[[L20]], $pop{{.+}}
|
||||
; CHECK: i32.and $push[[L18:.+]]=, $pop[[L19]], $pop{{.+}}
|
||||
; CHECK: tee_local $push{{.+}}=, $[[FP:.+]]=, $pop[[L18]]
|
||||
; CHECK: i32.sub $push[[L16:.+]]=, $[[FP]], $pop{{.+}}
|
||||
; CHECK-NEXT: tee_local $push{{.+}}=, $[[SP:.+]]=, $pop[[L16]]
|
||||
; CHECK: tee_local $push{{.+}}=, [[FP:.+]], $pop[[L18]]
|
||||
; CHECK: get_local $push[[M10:.+]]=, [[FP]]{{$}}
|
||||
; CHECK: i32.sub $push[[L16:.+]]=, $pop[[M10]], $pop{{.+}}
|
||||
; CHECK-NEXT: tee_local $push{{.+}}=, [[SP:.+]], $pop[[L16]]
|
||||
|
||||
; CHECK: copy_local $push[[over:.+]]=, $[[FP]]
|
||||
; CHECK: get_local $push[[over:.+]]=, [[FP]]
|
||||
; CHECK-NEXT: call somefunc@FUNCTION, $pop[[over]]
|
||||
; CHECK-NEXT: call somefunc@FUNCTION, $[[SP]]
|
||||
; CHECK: get_local $push[[another:.+]]=, [[SP]]
|
||||
; CHECK-NEXT: call somefunc@FUNCTION, $pop[[another]]
|
||||
|
||||
; CHECK: copy_local $push[[L12:.+]]=, $[[BP]]
|
||||
; CHECK-NEXT: i32.store __stack_pointer($pop{{.+}}), $pop[[L12]]
|
||||
; CHECK: get_local $push[[M11:.+]]=, [[BP]]{{$}}
|
||||
; CHECK-NEXT: set_global 0, $pop[[M11]]
|
||||
define void @overalign_and_dynamic(i32 %num) {
|
||||
entry:
|
||||
%over = alloca i32, align 32
|
||||
|
@ -107,24 +116,27 @@ entry:
|
|||
}
|
||||
|
||||
; CHECK-LABEL: overalign_static_and_dynamic:
|
||||
; CHECK: i32.load $push[[L26:.+]]=, __stack_pointer
|
||||
; CHECK-NEXT: tee_local $push[[L25:.+]]=, $[[BP:.+]]=, $pop[[L26]]
|
||||
; CHECK: get_global $push[[L26:.+]]=, 0{{$}}
|
||||
; CHECK-NEXT: tee_local $push[[L25:.+]]=, [[BP:.+]], $pop[[L26]]
|
||||
; CHECK: i32.sub $push[[L24:.+]]=, $pop[[L25]], $pop{{.+}}
|
||||
; CHECK: i32.and $push[[L23:.+]]=, $pop[[L24]], $pop{{.+}}
|
||||
; CHECK: tee_local $push{{.+}}=, $[[FP:.+]]=, $pop[[L23]]
|
||||
; CHECK: i32.sub $push[[L21:.+]]=, $[[FP]], $pop{{.+}}
|
||||
; CHECK-NEXT: tee_local $push{{.+}}=, $[[SP:.+]]=, $pop[[L21]]
|
||||
; CHECK: tee_local $push{{.+}}=, [[FP:.+]], $pop[[L23]]
|
||||
; CHECK: get_local $push[[M12:.+]]=, [[FP]]{{$}}
|
||||
; CHECK: i32.sub $push[[L21:.+]]=, $pop[[M12]], $pop{{.+}}
|
||||
; CHECK-NEXT: tee_local $push{{.+}}=, [[SP:.+]], $pop[[L21]]
|
||||
|
||||
; CHECK: copy_local $push[[L19:.+]]=, $[[FP]]
|
||||
; CHECK: tee_local $push[[L18:.+]]=, $[[FP_2:.+]]=, $pop[[L19]]
|
||||
; CHECK: get_local $push[[L19:.+]]=, [[FP]]
|
||||
; CHECK: tee_local $push[[L18:.+]]=, [[FP_2:.+]], $pop[[L19]]
|
||||
; CHECK: i32.add $push[[over:.+]]=, $pop[[L18]], $pop{{.+}}
|
||||
; CHECK-NEXT: call somefunc@FUNCTION, $pop[[over]]
|
||||
; CHECK: call somefunc@FUNCTION, $[[SP]]
|
||||
; CHECK: i32.add $push[[static:.+]]=, $[[FP_2]], $pop{{.+}}
|
||||
; CHECK: get_local $push[[M12:.+]]=, [[SP]]
|
||||
; CHECK: call somefunc@FUNCTION, $pop[[M12]]
|
||||
; CHECK: get_local $push[[M13:.+]]=, [[FP_2]]
|
||||
; CHECK: i32.add $push[[static:.+]]=, $pop[[M13]], $pop{{.+}}
|
||||
; CHECK-NEXT: call somefunc@FUNCTION, $pop[[static]]
|
||||
|
||||
; CHECK: copy_local $push[[L16:.+]]=, $[[BP]]
|
||||
; CHECK-NEXT: i32.store __stack_pointer({{.+}}), $pop[[L16]]
|
||||
; CHECK: get_local $push[[M14:.+]]=, [[BP]]{{$}}
|
||||
; CHECK-NEXT: set_global 0, $pop[[M14]]
|
||||
define void @overalign_static_and_dynamic(i32 %num) {
|
||||
entry:
|
||||
%over = alloca i32, align 32
|
||||
|
|
Loading…
Reference in New Issue