[clang] b9a539c - [WebAssembly] Adding 64-bit versions of __stack_pointer and other globals
Wouter van Oortmerssen via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 25 15:53:40 PDT 2020
Author: Wouter van Oortmerssen
Date: 2020-06-25T15:52:44-07:00
New Revision: b9a539c01084a572e406579c326a0da1e22e286f
URL: https://github.com/llvm/llvm-project/commit/b9a539c01084a572e406579c326a0da1e22e286f
DIFF: https://github.com/llvm/llvm-project/commit/b9a539c01084a572e406579c326a0da1e22e286f.diff
LOG: [WebAssembly] Adding 64-bit versions of __stack_pointer and other globals
We have 6 globals, all of which except for __table_base are 64-bit under wasm64.
Differential Revision: https://reviews.llvm.org/D82130
Added:
Modified:
clang/lib/Driver/ToolChains/WebAssembly.cpp
lld/wasm/Config.h
lld/wasm/Driver.cpp
lld/wasm/InputChunks.cpp
lld/wasm/Options.td
llvm/include/llvm/BinaryFormat/Wasm.h
llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h
llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
llvm/test/CodeGen/WebAssembly/stack-alignment.ll
llvm/test/CodeGen/WebAssembly/userstack.ll
llvm/test/MC/WebAssembly/stack-ptr.ll
llvm/test/MC/WebAssembly/wasm64.s
Removed:
################################################################################
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 48f9a9b603db..13d713dfb54e 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -62,6 +62,12 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
const char *Linker = Args.MakeArgString(getLinkerPath(Args));
ArgStringList CmdArgs;
+ CmdArgs.push_back("-m");
+ if (getToolChain().getTriple().isArch64Bit())
+ CmdArgs.push_back("wasm64");
+ else
+ CmdArgs.push_back("wasm32");
+
if (Args.hasArg(options::OPT_s))
CmdArgs.push_back("--strip-all");
diff --git a/lld/wasm/Config.h b/lld/wasm/Config.h
index 1ba28899e64d..4a1f7a69d079 100644
--- a/lld/wasm/Config.h
+++ b/lld/wasm/Config.h
@@ -36,6 +36,7 @@ struct Configuration {
bool importMemory;
bool sharedMemory;
bool importTable;
+ bool is64;
bool mergeDataSegments;
bool pie;
bool printGcSections;
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp
index c6036111ec79..636aa6509b25 100644
--- a/lld/wasm/Driver.cpp
+++ b/lld/wasm/Driver.cpp
@@ -378,6 +378,18 @@ static void readConfigs(opt::InputArgList &args) {
config->exportDynamic =
args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, config->shared);
+ // Parse wasm32/64.
+ config->is64 = false;
+ if (auto *arg = args.getLastArg(OPT_m)) {
+ StringRef s = arg->getValue();
+ if (s == "wasm32")
+ config->is64 = false;
+ else if (s == "wasm64")
+ config->is64 = true;
+ else
+ error("invalid target architecture: " + s);
+ }
+
// --threads= takes a positive integer and provides the default value for
// --thinlto-jobs=.
if (auto *arg = args.getLastArg(OPT_threads)) {
@@ -498,9 +510,15 @@ createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
static GlobalSymbol *createGlobalVariable(StringRef name, bool isMutable,
int value) {
llvm::wasm::WasmGlobal wasmGlobal;
- wasmGlobal.Type = {WASM_TYPE_I32, isMutable};
- wasmGlobal.InitExpr.Value.Int32 = value;
- wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
+ if (config->is64) {
+ wasmGlobal.Type = {WASM_TYPE_I64, isMutable};
+ wasmGlobal.InitExpr.Value.Int64 = value;
+ wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I64_CONST;
+ } else {
+ wasmGlobal.Type = {WASM_TYPE_I32, isMutable};
+ wasmGlobal.InitExpr.Value.Int32 = value;
+ wasmGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
+ }
wasmGlobal.SymbolName = name;
return symtab->addSyntheticGlobal(name, WASM_SYMBOL_VISIBILITY_HIDDEN,
make<InputGlobal>(wasmGlobal, nullptr));
@@ -513,9 +531,13 @@ static void createSyntheticSymbols() {
static WasmSignature nullSignature = {{}, {}};
static WasmSignature i32ArgSignature = {{}, {ValType::I32}};
+ static WasmSignature i64ArgSignature = {{}, {ValType::I64}};
static llvm::wasm::WasmGlobalType globalTypeI32 = {WASM_TYPE_I32, false};
+ static llvm::wasm::WasmGlobalType globalTypeI64 = {WASM_TYPE_I64, false};
static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {WASM_TYPE_I32,
true};
+ static llvm::wasm::WasmGlobalType mutableGlobalTypeI64 = {WASM_TYPE_I64,
+ true};
WasmSym::callCtors = symtab->addSyntheticFunction(
"__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
make<SyntheticFunction>(nullSignature, "__wasm_call_ctors"));
@@ -530,15 +552,16 @@ static void createSyntheticSymbols() {
if (config->isPic) {
- WasmSym::stackPointer =
- createUndefinedGlobal("__stack_pointer", &mutableGlobalTypeI32);
+ WasmSym::stackPointer = createUndefinedGlobal(
+ "__stack_pointer",
+ config->is64 ? &mutableGlobalTypeI64 : &mutableGlobalTypeI32);
// For PIC code, we import two global variables (__memory_base and
// __table_base) from the environment and use these as the offset at
// which to load our static data and function table.
// See:
// https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
- WasmSym::memoryBase =
- createUndefinedGlobal("__memory_base", &globalTypeI32);
+ WasmSym::memoryBase = createUndefinedGlobal(
+ "__memory_base", config->is64 ? &globalTypeI64 : &globalTypeI32);
WasmSym::tableBase = createUndefinedGlobal("__table_base", &globalTypeI32);
WasmSym::memoryBase->markLive();
WasmSym::tableBase->markLive();
@@ -563,7 +586,9 @@ static void createSyntheticSymbols() {
WasmSym::tlsAlign = createGlobalVariable("__tls_align", false, 1);
WasmSym::initTLS = symtab->addSyntheticFunction(
"__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
- make<SyntheticFunction>(i32ArgSignature, "__wasm_init_tls"));
+ make<SyntheticFunction>(config->is64 ? i64ArgSignature
+ : i32ArgSignature,
+ "__wasm_init_tls"));
}
}
diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp
index abea11bd805b..7f06e61a4b5a 100644
--- a/lld/wasm/InputChunks.cpp
+++ b/lld/wasm/InputChunks.cpp
@@ -32,6 +32,18 @@ StringRef relocTypeToString(uint8_t relocType) {
llvm_unreachable("unknown reloc type");
}
+bool relocIs64(uint8_t relocType) {
+ switch (relocType) {
+ case R_WASM_MEMORY_ADDR_LEB64:
+ case R_WASM_MEMORY_ADDR_SLEB64:
+ case R_WASM_MEMORY_ADDR_REL_SLEB64:
+ case R_WASM_MEMORY_ADDR_I64:
+ return true;
+ default:
+ return false;
+ }
+}
+
std::string toString(const wasm::InputChunk *c) {
return (toString(c->file) + ":(" + c->getName() + ")").str();
}
@@ -323,12 +335,17 @@ void InputSegment::generateRelocationCode(raw_ostream &os) const {
LLVM_DEBUG(dbgs() << "generating runtime relocations: " << getName()
<< " count=" << relocations.size() << "\n");
+ unsigned opcode_ptr_const =
+ config->is64 ? WASM_OPCODE_I64_CONST : WASM_OPCODE_I32_CONST;
+ unsigned opcode_ptr_add =
+ config->is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD;
+
// TODO(sbc): Encode the relocations in the data section and write a loop
// here to apply them.
uint32_t segmentVA = outputSeg->startVA + outputSegmentOffset;
for (const WasmRelocation &rel : relocations) {
- uint32_t offset = rel.Offset - getInputSectionOffset();
- uint32_t outputOffset = segmentVA + offset;
+ uint64_t offset = rel.Offset - getInputSectionOffset();
+ uint64_t outputOffset = segmentVA + offset;
LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(rel.Type)
<< " addend=" << rel.Addend << " index=" << rel.Index
@@ -339,9 +356,17 @@ void InputSegment::generateRelocationCode(raw_ostream &os) const {
writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(), "memory_base");
// Add the offset of the relocation
- writeU8(os, WASM_OPCODE_I32_CONST, "I32_CONST");
+ writeU8(os, opcode_ptr_const, "CONST");
writeSleb128(os, outputOffset, "offset");
- writeU8(os, WASM_OPCODE_I32_ADD, "ADD");
+ writeU8(os, opcode_ptr_add, "ADD");
+
+ bool is64 = relocIs64(rel.Type);
+ unsigned opcode_reloc_const =
+ is64 ? WASM_OPCODE_I64_CONST : WASM_OPCODE_I32_CONST;
+ unsigned opcode_reloc_add =
+ is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD;
+ unsigned opcode_reloc_store =
+ is64 ? WASM_OPCODE_I64_STORE : WASM_OPCODE_I32_STORE;
Symbol *sym = file->getSymbol(rel);
// Now figure out what we want to store
@@ -349,9 +374,9 @@ void InputSegment::generateRelocationCode(raw_ostream &os) const {
writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
writeUleb128(os, sym->getGOTIndex(), "global index");
if (rel.Addend) {
- writeU8(os, WASM_OPCODE_I32_CONST, "CONST");
+ writeU8(os, opcode_reloc_const, "CONST");
writeSleb128(os, rel.Addend, "addend");
- writeU8(os, WASM_OPCODE_I32_ADD, "ADD");
+ writeU8(os, opcode_reloc_add, "ADD");
}
} else {
const GlobalSymbol* baseSymbol = WasmSym::memoryBase;
@@ -359,13 +384,13 @@ void InputSegment::generateRelocationCode(raw_ostream &os) const {
baseSymbol = WasmSym::tableBase;
writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
writeUleb128(os, baseSymbol->getGlobalIndex(), "base");
- writeU8(os, WASM_OPCODE_I32_CONST, "CONST");
+ writeU8(os, opcode_reloc_const, "CONST");
writeSleb128(os, file->calcNewValue(rel), "offset");
- writeU8(os, WASM_OPCODE_I32_ADD, "ADD");
+ writeU8(os, opcode_reloc_add, "ADD");
}
// Store that value at the virtual address
- writeU8(os, WASM_OPCODE_I32_STORE, "I32_STORE");
+ writeU8(os, opcode_reloc_store, "I32_STORE");
writeUleb128(os, 2, "align");
writeUleb128(os, 0, "offset");
}
diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td
index 0910a74660f3..241050922ea8 100644
--- a/lld/wasm/Options.td
+++ b/lld/wasm/Options.td
@@ -62,6 +62,8 @@ def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">,
def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
HelpText<"Add a directory to the library search path">;
+def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">;
+
def mllvm: S<"mllvm">, HelpText<"Options to pass to LLVM">;
def no_color_diagnostics: F<"no-color-diagnostics">,
@@ -179,7 +181,6 @@ def: JoinedOrSeparate<["-"], "e">, Alias<entry>;
def: J<"entry=">, Alias<entry>;
def: Flag<["-"], "E">, Alias<export_dynamic>, HelpText<"Alias for --export-dynamic">;
def: Flag<["-"], "i">, Alias<initial_memory>;
-def: Flag<["-"], "m">, Alias<max_memory>;
def: Flag<["-"], "r">, Alias<relocatable>;
def: Flag<["-"], "s">, Alias<strip_all>, HelpText<"Alias for --strip-all">;
def: Flag<["-"], "S">, Alias<strip_debug>, HelpText<"Alias for --strip-debug">;
diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h
index 49ef3e69f3ec..b8d3b3f4d66f 100644
--- a/llvm/include/llvm/BinaryFormat/Wasm.h
+++ b/llvm/include/llvm/BinaryFormat/Wasm.h
@@ -254,11 +254,13 @@ enum : unsigned {
WASM_OPCODE_GLOBAL_GET = 0x23,
WASM_OPCODE_GLOBAL_SET = 0x24,
WASM_OPCODE_I32_STORE = 0x36,
+ WASM_OPCODE_I64_STORE = 0x37,
WASM_OPCODE_I32_CONST = 0x41,
WASM_OPCODE_I64_CONST = 0x42,
WASM_OPCODE_F32_CONST = 0x43,
WASM_OPCODE_F64_CONST = 0x44,
WASM_OPCODE_I32_ADD = 0x6a,
+ WASM_OPCODE_I64_ADD = 0x7c,
WASM_OPCODE_REF_NULL = 0xd0,
};
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 8fdc0201327a..c04d9f7ebc18 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -434,9 +434,12 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {
// GetExternalSymbolSymbol does, since if there's no code that
// refers to this symbol, we have to set it here.
SPSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
- // FIXME: need to check subtarget to see if its wasm64, but we
- // can't cast to WebAssemblySubtarget here.
- SPSym->setGlobalType(wasm::WasmGlobalType{wasm::WASM_TYPE_I32, true});
+ SPSym->setGlobalType(wasm::WasmGlobalType{
+ uint8_t(Asm->getSubtargetInfo().getTargetTriple().getArch() ==
+ Triple::wasm64
+ ? wasm::WASM_TYPE_I64
+ : wasm::WASM_TYPE_I32),
+ true});
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_WASM_location);
addSInt(*Loc, dwarf::DW_FORM_sdata, FrameBase.Location.WasmLoc.Kind);
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
index 30647fd6c5bb..95669932e73f 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.cpp
@@ -87,8 +87,8 @@ bool WebAssemblyFrameLowering::needsSPForLocalFrame(
}
// In function with EH pads, we need to make a copy of the value of
-// __stack_pointer global in SP32 register, in order to use it when restoring
-// __stack_pointer after an exception is caught.
+// __stack_pointer global in SP32/64 register, in order to use it when
+// restoring __stack_pointer after an exception is caught.
bool WebAssemblyFrameLowering::needsPrologForEH(
const MachineFunction &MF) const {
auto EHType = MF.getTarget().getMCAsmInfo()->getExceptionHandlingType();
@@ -123,6 +123,57 @@ bool WebAssemblyFrameLowering::needsSPWriteback(
return needsSPForLocalFrame(MF) && !CanUseRedZone;
}
+unsigned WebAssemblyFrameLowering::getSPReg(const MachineFunction &MF) {
+ return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64()
+ ? WebAssembly::SP64
+ : WebAssembly::SP32;
+}
+
+unsigned WebAssemblyFrameLowering::getFPReg(const MachineFunction &MF) {
+ return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64()
+ ? WebAssembly::FP64
+ : WebAssembly::FP32;
+}
+
+unsigned
+WebAssemblyFrameLowering::getOpcConst(const MachineFunction &MF) {
+ return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64()
+ ? WebAssembly::CONST_I64
+ : WebAssembly::CONST_I32;
+}
+
+unsigned WebAssemblyFrameLowering::getOpcAdd(const MachineFunction &MF) {
+ return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64()
+ ? WebAssembly::ADD_I64
+ : WebAssembly::ADD_I32;
+}
+
+unsigned WebAssemblyFrameLowering::getOpcSub(const MachineFunction &MF) {
+ return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64()
+ ? WebAssembly::SUB_I64
+ : WebAssembly::SUB_I32;
+}
+
+unsigned WebAssemblyFrameLowering::getOpcAnd(const MachineFunction &MF) {
+ return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64()
+ ? WebAssembly::AND_I64
+ : WebAssembly::AND_I32;
+}
+
+unsigned
+WebAssemblyFrameLowering::getOpcGlobGet(const MachineFunction &MF) {
+ return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64()
+ ? WebAssembly::GLOBAL_GET_I64
+ : WebAssembly::GLOBAL_GET_I32;
+}
+
+unsigned
+WebAssemblyFrameLowering::getOpcGlobSet(const MachineFunction &MF) {
+ return MF.getSubtarget<WebAssemblySubtarget>().hasAddr64()
+ ? WebAssembly::GLOBAL_SET_I64
+ : WebAssembly::GLOBAL_SET_I32;
+}
+
void WebAssemblyFrameLowering::writeSPToGlobal(
unsigned SrcReg, MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator &InsertStore, const DebugLoc &DL) const {
@@ -130,7 +181,8 @@ void WebAssemblyFrameLowering::writeSPToGlobal(
const char *ES = "__stack_pointer";
auto *SPSymbol = MF.createExternalSymbolName(ES);
- BuildMI(MBB, InsertStore, DL, TII->get(WebAssembly::GLOBAL_SET_I32))
+
+ BuildMI(MBB, InsertStore, DL, TII->get(getOpcGlobSet(MF)))
.addExternalSymbol(SPSymbol)
.addReg(SrcReg);
}
@@ -141,11 +193,12 @@ WebAssemblyFrameLowering::eliminateCallFramePseudoInstr(
MachineBasicBlock::iterator I) const {
assert(!I->getOperand(0).getImm() && (hasFP(MF) || hasBP(MF)) &&
"Call frame pseudos should only be used for dynamic stack adjustment");
- const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
+ auto &ST = MF.getSubtarget<WebAssemblySubtarget>();
+ const auto *TII = ST.getInstrInfo();
if (I->getOpcode() == TII->getCallFrameDestroyOpcode() &&
needsSPWriteback(MF)) {
DebugLoc DL = I->getDebugLoc();
- writeSPToGlobal(WebAssembly::SP32, MF, MBB, I, DL);
+ writeSPToGlobal(getSPReg(MF), MF, MBB, I, DL);
}
return MBB.erase(I);
}
@@ -161,7 +214,8 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
return;
uint64_t StackSize = MFI.getStackSize();
- const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
+ auto &ST = MF.getSubtarget<WebAssemblySubtarget>();
+ const auto *TII = ST.getInstrInfo();
auto &MRI = MF.getRegInfo();
auto InsertPt = MBB.begin();
@@ -172,13 +226,13 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
const TargetRegisterClass *PtrRC =
MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
- unsigned SPReg = WebAssembly::SP32;
+ unsigned SPReg = getSPReg(MF);
if (StackSize)
SPReg = MRI.createVirtualRegister(PtrRC);
const char *ES = "__stack_pointer";
auto *SPSymbol = MF.createExternalSymbolName(ES);
- BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::GLOBAL_GET_I32), SPReg)
+ BuildMI(MBB, InsertPt, DL, TII->get(getOpcGlobGet(MF)), SPReg)
.addExternalSymbol(SPSymbol);
bool HasBP = hasBP(MF);
@@ -192,32 +246,30 @@ void WebAssemblyFrameLowering::emitPrologue(MachineFunction &MF,
if (StackSize) {
// Subtract the frame size
Register OffsetReg = MRI.createVirtualRegister(PtrRC);
- BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg)
+ BuildMI(MBB, InsertPt, DL, TII->get(getOpcConst(MF)), OffsetReg)
.addImm(StackSize);
- BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::SUB_I32),
- WebAssembly::SP32)
+ BuildMI(MBB, InsertPt, DL, TII->get(getOpcSub(MF)), getSPReg(MF))
.addReg(SPReg)
.addReg(OffsetReg);
}
if (HasBP) {
Register BitmaskReg = MRI.createVirtualRegister(PtrRC);
Align Alignment = MFI.getMaxAlign();
- BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), BitmaskReg)
- .addImm((int)~(Alignment.value() - 1));
- BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::AND_I32),
- WebAssembly::SP32)
- .addReg(WebAssembly::SP32)
+ BuildMI(MBB, InsertPt, DL, TII->get(getOpcConst(MF)), BitmaskReg)
+ .addImm((int64_t) ~(Alignment.value() - 1));
+ BuildMI(MBB, InsertPt, DL, TII->get(getOpcAnd(MF)), getSPReg(MF))
+ .addReg(getSPReg(MF))
.addReg(BitmaskReg);
}
if (hasFP(MF)) {
// Unlike most conventional targets (where FP points to the saved FP),
// FP points to the bottom of the fixed-size locals, so we can use positive
// offsets in load/store instructions.
- BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), WebAssembly::FP32)
- .addReg(WebAssembly::SP32);
+ BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::COPY), getFPReg(MF))
+ .addReg(getSPReg(MF));
}
if (StackSize && needsSPWriteback(MF)) {
- writeSPToGlobal(WebAssembly::SP32, MF, MBB, InsertPt, DL);
+ writeSPToGlobal(getSPReg(MF), MF, MBB, InsertPt, DL);
}
}
@@ -226,7 +278,8 @@ void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
uint64_t StackSize = MF.getFrameInfo().getStackSize();
if (!needsSP(MF) || !needsSPWriteback(MF))
return;
- const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
+ auto &ST = MF.getSubtarget<WebAssemblySubtarget>();
+ const auto *TII = ST.getInstrInfo();
auto &MRI = MF.getRegInfo();
auto InsertPt = MBB.getFirstTerminator();
DebugLoc DL;
@@ -237,6 +290,7 @@ void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
// Restore the stack pointer. If we had fixed-size locals, add the offset
// subtracted in the prolog.
unsigned SPReg = 0;
+ unsigned SPFPReg = hasFP(MF) ? getFPReg(MF) : getSPReg(MF);
if (hasBP(MF)) {
auto FI = MF.getInfo<WebAssemblyFunctionInfo>();
SPReg = FI->getBasePointerVreg();
@@ -244,16 +298,17 @@ void WebAssemblyFrameLowering::emitEpilogue(MachineFunction &MF,
const TargetRegisterClass *PtrRC =
MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
Register OffsetReg = MRI.createVirtualRegister(PtrRC);
- BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::CONST_I32), OffsetReg)
+ BuildMI(MBB, InsertPt, DL, TII->get(getOpcConst(MF)), OffsetReg)
.addImm(StackSize);
- // In the epilog we don't need to write the result back to the SP32 physreg
- // because it won't be used again. We can use a stackified register instead.
+ // In the epilog we don't need to write the result back to the SP32/64
+ // physreg because it won't be used again. We can use a stackified register
+ // instead.
SPReg = MRI.createVirtualRegister(PtrRC);
- BuildMI(MBB, InsertPt, DL, TII->get(WebAssembly::ADD_I32), SPReg)
- .addReg(hasFP(MF) ? WebAssembly::FP32 : WebAssembly::SP32)
+ BuildMI(MBB, InsertPt, DL, TII->get(getOpcAdd(MF)), SPReg)
+ .addReg(SPFPReg)
.addReg(OffsetReg);
} else {
- SPReg = hasFP(MF) ? WebAssembly::FP32 : WebAssembly::SP32;
+ SPReg = SPFPReg;
}
writeSPToGlobal(SPReg, MF, MBB, InsertPt, DL);
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h
index cf57247b3878..e16f639ff22b 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyFrameLowering.h
@@ -53,6 +53,15 @@ class WebAssemblyFrameLowering final : public TargetFrameLowering {
MachineBasicBlock::iterator &InsertStore,
const DebugLoc &DL) const;
+ static unsigned getSPReg(const MachineFunction &MF);
+ static unsigned getFPReg(const MachineFunction &MF);
+ static unsigned getOpcConst(const MachineFunction &MF);
+ static unsigned getOpcAdd(const MachineFunction &MF);
+ static unsigned getOpcSub(const MachineFunction &MF);
+ static unsigned getOpcAnd(const MachineFunction &MF);
+ static unsigned getOpcGlobGet(const MachineFunction &MF);
+ static unsigned getOpcGlobSet(const MachineFunction &MF);
+
private:
bool hasBP(const MachineFunction &MF) const;
bool needsSPForLocalFrame(const MachineFunction &MF) const;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
index 510e7e80cc1a..d1a696f854f8 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelDAGToDAG.cpp
@@ -77,6 +77,13 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
return;
}
+ MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
+ auto GlobalGetIns = PtrVT == MVT::i64 ? WebAssembly::GLOBAL_GET_I64
+ : WebAssembly::GLOBAL_GET_I32;
+ auto ConstIns =
+ PtrVT == MVT::i64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
+ auto AddIns = PtrVT == MVT::i64 ? WebAssembly::ADD_I64 : WebAssembly::ADD_I32;
+
// Few custom selection stuff.
SDLoc DL(Node);
MachineFunction &MF = CurDAG->getMachineFunction();
@@ -140,20 +147,16 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
false);
}
- MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
- assert(PtrVT == MVT::i32 && "only wasm32 is supported for now");
-
SDValue TLSBaseSym = CurDAG->getTargetExternalSymbol("__tls_base", PtrVT);
SDValue TLSOffsetSym = CurDAG->getTargetGlobalAddress(
GA->getGlobal(), DL, PtrVT, GA->getOffset(), 0);
- MachineSDNode *TLSBase = CurDAG->getMachineNode(WebAssembly::GLOBAL_GET_I32,
- DL, MVT::i32, TLSBaseSym);
- MachineSDNode *TLSOffset = CurDAG->getMachineNode(
- WebAssembly::CONST_I32, DL, MVT::i32, TLSOffsetSym);
- MachineSDNode *TLSAddress =
- CurDAG->getMachineNode(WebAssembly::ADD_I32, DL, MVT::i32,
- SDValue(TLSBase, 0), SDValue(TLSOffset, 0));
+ MachineSDNode *TLSBase =
+ CurDAG->getMachineNode(GlobalGetIns, DL, PtrVT, TLSBaseSym);
+ MachineSDNode *TLSOffset =
+ CurDAG->getMachineNode(ConstIns, DL, PtrVT, TLSOffsetSym);
+ MachineSDNode *TLSAddress = CurDAG->getMachineNode(
+ AddIns, DL, PtrVT, SDValue(TLSBase, 0), SDValue(TLSOffset, 0));
ReplaceNode(Node, TLSAddress);
return;
}
@@ -162,22 +165,16 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(0))->getZExtValue();
switch (IntNo) {
case Intrinsic::wasm_tls_size: {
- MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
- assert(PtrVT == MVT::i32 && "only wasm32 is supported for now");
-
MachineSDNode *TLSSize = CurDAG->getMachineNode(
- WebAssembly::GLOBAL_GET_I32, DL, PtrVT,
- CurDAG->getTargetExternalSymbol("__tls_size", MVT::i32));
+ GlobalGetIns, DL, PtrVT,
+ CurDAG->getTargetExternalSymbol("__tls_size", PtrVT));
ReplaceNode(Node, TLSSize);
return;
}
case Intrinsic::wasm_tls_align: {
- MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
- assert(PtrVT == MVT::i32 && "only wasm32 is supported for now");
-
MachineSDNode *TLSAlign = CurDAG->getMachineNode(
- WebAssembly::GLOBAL_GET_I32, DL, PtrVT,
- CurDAG->getTargetExternalSymbol("__tls_align", MVT::i32));
+ GlobalGetIns, DL, PtrVT,
+ CurDAG->getTargetExternalSymbol("__tls_align", PtrVT));
ReplaceNode(Node, TLSAlign);
return;
}
@@ -188,11 +185,8 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
switch (IntNo) {
case Intrinsic::wasm_tls_base: {
- MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
- assert(PtrVT == MVT::i32 && "only wasm32 is supported for now");
-
MachineSDNode *TLSBase = CurDAG->getMachineNode(
- WebAssembly::GLOBAL_GET_I32, DL, MVT::i32, MVT::Other,
+ GlobalGetIns, DL, PtrVT, MVT::Other,
CurDAG->getTargetExternalSymbol("__tls_base", PtrVT),
Node->getOperand(0));
ReplaceNode(Node, TLSBase);
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index 6d4e6dc36a9b..b71a98c09a8c 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -209,6 +209,7 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVTPtr, Expand);
setOperationAction(ISD::FrameIndex, MVT::i32, Custom);
+ setOperationAction(ISD::FrameIndex, MVT::i64, Custom);
setOperationAction(ISD::CopyToReg, MVT::Other, Custom);
// Expand these forms; we pattern-match the forms that we can handle in isel.
@@ -613,7 +614,11 @@ EVT WebAssemblyTargetLowering::getSetCCResultType(const DataLayout &DL,
if (VT.isVector())
return VT.changeVectorElementTypeToInteger();
- return TargetLowering::getSetCCResultType(DL, C, VT);
+ // So far, all branch instructions in Wasm take an I32 condition.
+ // The default TargetLowering::getSetCCResultType returns the pointer size,
+ // which would be useful to reduce instruction counts when testing
+ // against 64-bit pointers/values if at some point Wasm supports that.
+ return EVT::getIntegerVT(C, 32);
}
bool WebAssemblyTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
index 2280ec38e5b9..346938daf1aa 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp
@@ -408,8 +408,8 @@ bool WebAssemblyLateEHPrepare::restoreStackPointer(MachineFunction &MF) {
++InsertPos;
if (InsertPos->getOpcode() == WebAssembly::CATCH)
++InsertPos;
- FrameLowering->writeSPToGlobal(WebAssembly::SP32, MF, MBB, InsertPos,
- MBB.begin()->getDebugLoc());
+ FrameLowering->writeSPToGlobal(FrameLowering->getSPReg(MF), MF, MBB,
+ InsertPos, MBB.begin()->getDebugLoc());
}
return Changed;
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
index 07830c130d7a..304dca2ebfe4 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
@@ -81,8 +81,9 @@ MCSymbol *WebAssemblyMCInstLower::GetExternalSymbolSymbol(
strcmp(Name, "__stack_pointer") == 0 || strcmp(Name, "__tls_base") == 0;
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
WasmSym->setGlobalType(wasm::WasmGlobalType{
- uint8_t(Subtarget.hasAddr64() ? wasm::WASM_TYPE_I64
- : wasm::WASM_TYPE_I32),
+ uint8_t(Subtarget.hasAddr64() && strcmp(Name, "__table_base") != 0
+ ? wasm::WASM_TYPE_I64
+ : wasm::WASM_TYPE_I32),
Mutable});
return WasmSym;
}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
index 8011f6a6e956..1d4e2e3a8f9e 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
@@ -248,7 +248,8 @@ static void query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read,
}
// Check for writes to __stack_pointer global.
- if (MI.getOpcode() == WebAssembly::GLOBAL_SET_I32 &&
+ if ((MI.getOpcode() == WebAssembly::GLOBAL_SET_I32 ||
+ MI.getOpcode() == WebAssembly::GLOBAL_SET_I64) &&
strcmp(MI.getOperand(0).getSymbolName(), "__stack_pointer") == 0)
StackPointer = true;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
index 205fb6e834e9..130589c9df8c 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
@@ -88,16 +88,17 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
// If this is an address being added to a constant, fold the frame offset
// into the constant.
- if (MI.getOpcode() == WebAssembly::ADD_I32) {
+ if (MI.getOpcode() == WebAssemblyFrameLowering::getOpcAdd(MF)) {
MachineOperand &OtherMO = MI.getOperand(3 - FIOperandNum);
if (OtherMO.isReg()) {
Register OtherMOReg = OtherMO.getReg();
if (Register::isVirtualRegister(OtherMOReg)) {
MachineInstr *Def = MF.getRegInfo().getUniqueVRegDef(OtherMOReg);
// TODO: For now we just opportunistically do this in the case where
- // the CONST_I32 happens to have exactly one def and one use. We
+ // the CONST_I32/64 happens to have exactly one def and one use. We
// should generalize this to optimize in more cases.
- if (Def && Def->getOpcode() == WebAssembly::CONST_I32 &&
+ if (Def && Def->getOpcode() ==
+ WebAssemblyFrameLowering::getOpcConst(MF) &&
MRI.hasOneNonDBGUse(Def->getOperand(0).getReg())) {
MachineOperand &ImmMO = Def->getOperand(1);
ImmMO.setImm(ImmMO.getImm() + uint32_t(FrameOffset));
@@ -109,20 +110,22 @@ void WebAssemblyRegisterInfo::eliminateFrameIndex(
}
}
- // Otherwise create an i32.add SP, offset and make it the operand.
+ // Otherwise create an i32/64.add SP, offset and make it the operand.
const auto *TII = MF.getSubtarget<WebAssemblySubtarget>().getInstrInfo();
unsigned FIRegOperand = FrameRegister;
if (FrameOffset) {
- // Create i32.add SP, offset and make it the operand.
+ // Create i32/64.add SP, offset and make it the operand.
const TargetRegisterClass *PtrRC =
MRI.getTargetRegisterInfo()->getPointerRegClass(MF);
Register OffsetOp = MRI.createVirtualRegister(PtrRC);
- BuildMI(MBB, *II, II->getDebugLoc(), TII->get(WebAssembly::CONST_I32),
+ BuildMI(MBB, *II, II->getDebugLoc(),
+ TII->get(WebAssemblyFrameLowering::getOpcConst(MF)),
OffsetOp)
.addImm(FrameOffset);
FIRegOperand = MRI.createVirtualRegister(PtrRC);
- BuildMI(MBB, *II, II->getDebugLoc(), TII->get(WebAssembly::ADD_I32),
+ BuildMI(MBB, *II, II->getDebugLoc(),
+ TII->get(WebAssemblyFrameLowering::getOpcAdd(MF)),
FIRegOperand)
.addReg(FrameRegister)
.addReg(OffsetOp);
diff --git a/llvm/test/CodeGen/WebAssembly/stack-alignment.ll b/llvm/test/CodeGen/WebAssembly/stack-alignment.ll
index 770dfea78a26..229843ed4190 100644
--- a/llvm/test/CodeGen/WebAssembly/stack-alignment.ll
+++ b/llvm/test/CodeGen/WebAssembly/stack-alignment.ll
@@ -1,22 +1,20 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
-
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
-target triple = "wasm32-unknown-unknown"
+; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck -DPTR=32 %s
+; RUN: llc < %s --mtriple=wasm64-unknown-unknown -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck -DPTR=64 %s
declare void @somefunc(i32*)
; CHECK-LABEL: underalign:
; CHECK: global.get $push[[L1:.+]]=, __stack_pointer{{$}}
-; CHECK-NEXT: i32.const $push[[L2:.+]]=, 16
-; CHECK-NEXT: i32.sub $push[[L10:.+]]=, $pop[[L1]], $pop[[L2]]
+; CHECK-NEXT: i[[PTR]].const $push[[L2:.+]]=, 16
+; CHECK-NEXT: i[[PTR]].sub $push[[L10:.+]]=, $pop[[L1]], $pop[[L2]]
; CHECK-NEXT: local.tee $push{{.+}}=, [[SP:.+]], $pop[[L10]]
; CHECK: local.get $push[[L3:.+]]=, [[SP]]{{$}}
-; CHECK: i32.add $push[[underaligned:.+]]=, $pop[[L3]], $pop{{.+}}
-; CHECK-NEXT: call somefunc, $pop[[underaligned]]
+; CHECK: i[[PTR]].add $push[[underaligned:.+]]=, $pop[[L3]], $pop{{.+}}
+; CHECK-NEXT: call somefunc, $pop[[underaligned]]
; CHECK: local.get $push[[M4:.+]]=, [[SP]]{{$}}
-; CHECK: i32.add $push[[L5:.+]]=, $pop[[M4]], $pop{{.+}}
+; CHECK: i[[PTR]].add $push[[L5:.+]]=, $pop[[M4]], $pop{{.+}}
; CHECK-NEXT: global.set __stack_pointer, $pop[[L5]]
define void @underalign() {
entry:
@@ -27,17 +25,17 @@ entry:
; CHECK-LABEL: overalign:
; CHECK: global.get $push[[L10:.+]]=, __stack_pointer{{$}}
-; CHECK-NEXT: local.tee $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: local.tee $push{{.+}}=, [[SP:.+]], $pop[[L7]]
+; CHECK-NEXT: local.tee $push[[L9:.+]]=, [[BP:.+]], $pop[[L10]]
+; CHECK-NEXT: i[[PTR]].const $push[[L2:.+]]=, 32
+; CHECK-NEXT: i[[PTR]].sub $push[[L8:.+]]=, $pop[[L9]], $pop[[L2]]
+; CHECK-NEXT: i[[PTR]].const $push[[L3:.+]]=, -32
+; CHECK-NEXT: i[[PTR]].and $push[[L7:.+]]=, $pop[[L8]], $pop[[L3]]
+; CHECK-NEXT: local.tee $push{{.+}}=, [[SP:.+]], $pop[[L7]]
-; CHECK: local.get $push[[M5:.+]]=, [[SP]]{{$}}
-; CHECK: call somefunc, $pop[[M5]]{{$}}
+; CHECK: local.get $push[[M5:.+]]=, [[SP]]{{$}}
+; CHECK: call somefunc, $pop[[M5]]{{$}}
-; CHECK: local.get $push[[M6:.+]]=, [[BP]]{{$}}
+; CHECK: local.get $push[[M6:.+]]=, [[BP]]{{$}}
; CHECK-NEXT: global.set __stack_pointer, $pop[[M6]]
define void @overalign() {
entry:
@@ -48,19 +46,19 @@ entry:
; CHECK-LABEL: over_and_normal_align:
; CHECK: global.get $push[[L14:.+]]=, __stack_pointer{{$}}
-; CHECK-NEXT: local.tee $push[[L13:.+]]=, [[BP:.+]], $pop[[L14]]
-; CHECK: i32.sub $push[[L12:.+]]=, $pop[[L13]], $pop{{.+}}
-; CHECK: i32.and $push[[L11:.+]]=, $pop[[L12]], $pop{{.+}}
-; CHECK-NEXT: local.tee $push{{.+}}=, [[SP:.+]], $pop[[L11]]
+; CHECK-NEXT: local.tee $push[[L13:.+]]=, [[BP:.+]], $pop[[L14]]
+; CHECK: i[[PTR]].sub $push[[L12:.+]]=, $pop[[L13]], $pop{{.+}}
+; CHECK: i[[PTR]].and $push[[L11:.+]]=, $pop[[L12]], $pop{{.+}}
+; CHECK-NEXT: local.tee $push{{.+}}=, [[SP:.+]], $pop[[L11]]
; CHECK: local.get $push[[M6:.+]]=, [[SP]]{{$}}
-; CHECK: i32.add $push[[L6:.+]]=, $pop[[M6]], $pop{{.+}}
-; CHECK-NEXT: call somefunc, $pop[[L6]]
-; CHECK: local.get $push[[M7:.+]]=, [[SP]]{{$}}
-; CHECK: i32.add $push[[L8:.+]]=, $pop[[M7]], $pop{{.+}}
-; CHECK-NEXT: call somefunc, $pop[[L8]]
+; CHECK: i[[PTR]].add $push[[L6:.+]]=, $pop[[M6]], $pop{{.+}}
+; CHECK-NEXT: call somefunc, $pop[[L6]]
+; CHECK: local.get $push[[M7:.+]]=, [[SP]]{{$}}
+; CHECK: i[[PTR]].add $push[[L8:.+]]=, $pop[[M7]], $pop{{.+}}
+; CHECK-NEXT: call somefunc, $pop[[L8]]
-; CHECK: local.get $push[[L6:.+]]=, [[BP]]{{$}}
+; CHECK: local.get $push[[L6:.+]]=, [[BP]]{{$}}
; CHECK-NEXT: global.set __stack_pointer, $pop[[L6]]
define void @over_and_normal_align() {
entry:
@@ -73,14 +71,14 @@ entry:
; CHECK-LABEL: dynamic_overalign:
; CHECK: global.get $push[[L18:.+]]=, __stack_pointer{{$}}
-; CHECK-NEXT: local.tee $push[[L17:.+]]=, [[SP:.+]], $pop[[L18]]
-; CHECK-NEXT: local.set [[BP:.+]], $pop[[L17]]
-; CHECK: local.tee $push{{.+}}=, [[SP_2:.+]], $pop{{.+}}
+; CHECK-NEXT: local.tee $push[[L17:.+]]=, [[SP:.+]], $pop[[L18]]
+; CHECK-NEXT: local.set [[BP:.+]], $pop[[L17]]
+; CHECK: local.tee $push{{.+}}=, [[SP_2:.+]], $pop{{.+}}
-; CHECK: local.get $push[[M8:.+]]=, [[SP_2]]{{$}}
-; CHECK: call somefunc, $pop[[M8]]
+; CHECK: local.get $push[[M8:.+]]=, [[SP_2]]{{$}}
+; CHECK: call somefunc, $pop[[M8]]
-; CHECK: local.get $push[[M9:.+]]=, [[BP]]{{$}}
+; CHECK: local.get $push[[M9:.+]]=, [[BP]]{{$}}
; CHECK-NEXT: global.set __stack_pointer, $pop[[M9]]
define void @dynamic_overalign(i32 %num) {
entry:
@@ -91,18 +89,18 @@ entry:
; CHECK-LABEL: overalign_and_dynamic:
; CHECK: global.get $push[[L21:.+]]=, __stack_pointer{{$}}
-; CHECK-NEXT: local.tee $push[[L20:.+]]=, [[BP:.+]], $pop[[L21]]
-; CHECK: i32.sub $push[[L19:.+]]=, $pop[[L20]], $pop{{.+}}
-; CHECK: i32.and $push[[L18:.+]]=, $pop[[L19]], $pop{{.+}}
-; CHECK: local.tee $push{{.+}}=, [[FP:.+]], $pop[[L18]]
-; CHECK: local.get $push[[M10:.+]]=, [[FP]]{{$}}
-; CHECK: i32.sub $push[[L16:.+]]=, $pop[[M10]], $pop{{.+}}
-; CHECK-NEXT: local.tee $push{{.+}}=, [[SP:.+]], $pop[[L16]]
-
-; CHECK: local.get $push[[over:.+]]=, [[FP]]
-; CHECK-NEXT: call somefunc, $pop[[over]]
-; CHECK: local.get $push[[another:.+]]=, [[SP]]
-; CHECK-NEXT: call somefunc, $pop[[another]]
+; CHECK-NEXT: local.tee $push[[L20:.+]]=, [[BP:.+]], $pop[[L21]]
+; CHECK: i[[PTR]].sub $push[[L19:.+]]=, $pop[[L20]], $pop{{.+}}
+; CHECK: i[[PTR]].and $push[[L18:.+]]=, $pop[[L19]], $pop{{.+}}
+; CHECK: local.tee $push{{.+}}=, [[FP:.+]], $pop[[L18]]
+; CHECK: local.get $push[[M10:.+]]=, [[FP]]{{$}}
+; CHECK: i[[PTR]].sub $push[[L16:.+]]=, $pop[[M10]], $pop{{.+}}
+; CHECK-NEXT: local.tee $push{{.+}}=, [[SP:.+]], $pop[[L16]]
+
+; CHECK: local.get $push[[over:.+]]=, [[FP]]
+; CHECK-NEXT: call somefunc, $pop[[over]]
+; CHECK: local.get $push[[another:.+]]=, [[SP]]
+; CHECK-NEXT: call somefunc, $pop[[another]]
; CHECK: local.get $push[[M11:.+]]=, [[BP]]{{$}}
; CHECK-NEXT: global.set __stack_pointer, $pop[[M11]]
@@ -117,23 +115,23 @@ entry:
; CHECK-LABEL: overalign_static_and_dynamic:
; CHECK: global.get $push[[L26:.+]]=, __stack_pointer{{$}}
-; CHECK-NEXT: local.tee $push[[L25:.+]]=, [[BP:.+]], $pop[[L26]]
-; CHECK: i32.sub $push[[L24:.+]]=, $pop[[L25]], $pop{{.+}}
-; CHECK: i32.and $push[[L23:.+]]=, $pop[[L24]], $pop{{.+}}
-; CHECK: local.tee $push{{.+}}=, [[FP:.+]], $pop[[L23]]
-; CHECK: local.get $push[[M12:.+]]=, [[FP]]{{$}}
-; CHECK: i32.sub $push[[L21:.+]]=, $pop[[M12]], $pop{{.+}}
-; CHECK-NEXT: local.tee $push{{.+}}=, [[SP:.+]], $pop[[L21]]
-
-; CHECK: local.get $push[[L19:.+]]=, [[FP]]
-; CHECK: local.tee $push[[L18:.+]]=, [[FP_2:.+]], $pop[[L19]]
-; CHECK: i32.add $push[[over:.+]]=, $pop[[L18]], $pop{{.+}}
-; CHECK-NEXT: call somefunc, $pop[[over]]
-; CHECK: local.get $push[[M12:.+]]=, [[SP]]
-; CHECK: call somefunc, $pop[[M12]]
-; CHECK: local.get $push[[M13:.+]]=, [[FP_2]]
-; CHECK: i32.add $push[[static:.+]]=, $pop[[M13]], $pop{{.+}}
-; CHECK-NEXT: call somefunc, $pop[[static]]
+; CHECK-NEXT: local.tee $push[[L25:.+]]=, [[BP:.+]], $pop[[L26]]
+; CHECK: i[[PTR]].sub $push[[L24:.+]]=, $pop[[L25]], $pop{{.+}}
+; CHECK: i[[PTR]].and $push[[L23:.+]]=, $pop[[L24]], $pop{{.+}}
+; CHECK: local.tee $push{{.+}}=, [[FP:.+]], $pop[[L23]]
+; CHECK: local.get $push[[M12:.+]]=, [[FP]]{{$}}
+; CHECK: i[[PTR]].sub $push[[L21:.+]]=, $pop[[M12]], $pop{{.+}}
+; CHECK-NEXT: local.tee $push{{.+}}=, [[SP:.+]], $pop[[L21]]
+
+; CHECK: local.get $push[[L19:.+]]=, [[FP]]
+; CHECK: local.tee $push[[L18:.+]]=, [[FP_2:.+]], $pop[[L19]]
+; CHECK: i[[PTR]].add $push[[over:.+]]=, $pop[[L18]], $pop{{.+}}
+; CHECK-NEXT: call somefunc, $pop[[over]]
+; CHECK: local.get $push[[M12:.+]]=, [[SP]]
+; CHECK: call somefunc, $pop[[M12]]
+; CHECK: local.get $push[[M13:.+]]=, [[FP_2]]
+; CHECK: i[[PTR]].add $push[[static:.+]]=, $pop[[M13]], $pop{{.+}}
+; CHECK-NEXT: call somefunc, $pop[[static]]
; CHECK: local.get $push[[M14:.+]]=, [[BP]]{{$}}
; CHECK-NEXT: global.set __stack_pointer, $pop[[M14]]
diff --git a/llvm/test/CodeGen/WebAssembly/userstack.ll b/llvm/test/CodeGen/WebAssembly/userstack.ll
index dd73c2ed9a47..dec202ea6af9 100644
--- a/llvm/test/CodeGen/WebAssembly/userstack.ll
+++ b/llvm/test/CodeGen/WebAssembly/userstack.ll
@@ -1,18 +1,16 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
-
-target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
-target triple = "wasm32-unknown-unknown"
+; RUN: llc < %s --mtriple=wasm32-unknown-unknown -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck -DPTR=32 %s
+; RUN: llc < %s --mtriple=wasm64-unknown-unknown -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck -DPTR=64 %s
declare void @ext_func(i64* %ptr)
declare void @ext_func_i32(i32* %ptr)
; CHECK-LABEL: alloca32:
; Check that there is an extra local for the stack pointer.
-; CHECK: .local i32{{$}}
+; CHECK: .local i[[PTR]]{{$}}
define void @alloca32() noredzone {
; CHECK-NEXT: global.get $push[[L2:.+]]=, __stack_pointer{{$}}
- ; CHECK-NEXT: i32.const $push[[L3:.+]]=, 16
- ; CHECK-NEXT: i32.sub $push[[L9:.+]]=, $pop[[L2]], $pop[[L3]]
+ ; CHECK-NEXT: i[[PTR]].const $push[[L3:.+]]=, 16
+ ; CHECK-NEXT: i[[PTR]].sub $push[[L9:.+]]=, $pop[[L2]], $pop[[L3]]
; CHECK-NEXT: local.tee $push[[L8:.+]]=, [[SP:.+]], $pop[[L9]]{{$}}
; CHECK-NEXT: global.set __stack_pointer, $pop[[L8]]{{$}}
%retval = alloca i32
@@ -21,18 +19,18 @@ define void @alloca32() noredzone {
; CHECK: i32.store 12($pop[[L4]]), $pop[[L0]]
store i32 0, i32* %retval
; CHECK: local.get $push[[L6:.+]]=, [[SP]]{{$}}
- ; CHECK-NEXT: i32.const $push[[L5:.+]]=, 16
- ; CHECK-NEXT: i32.add $push[[L7:.+]]=, $pop[[L6]], $pop[[L5]]
+ ; CHECK-NEXT: i[[PTR]].const $push[[L5:.+]]=, 16
+ ; CHECK-NEXT: i[[PTR]].add $push[[L7:.+]]=, $pop[[L6]], $pop[[L5]]
; CHECK-NEXT: global.set __stack_pointer, $pop[[L7]]
ret void
}
; CHECK-LABEL: alloca3264:
-; CHECK: .local i32{{$}}
+; CHECK: .local i[[PTR]]{{$}}
define void @alloca3264() {
; CHECK: global.get $push[[L3:.+]]=, __stack_pointer{{$}}
- ; CHECK-NEXT: i32.const $push[[L4:.+]]=, 16
- ; CHECK-NEXT: i32.sub $push[[L6:.+]]=, $pop[[L3]], $pop[[L4]]
+ ; CHECK-NEXT: i[[PTR]].const $push[[L4:.+]]=, 16
+ ; CHECK-NEXT: i[[PTR]].sub $push[[L6:.+]]=, $pop[[L3]], $pop[[L4]]
; CHECK-NEXT: local.tee $push[[L5:.+]]=, [[SP:.+]], $pop[[L6]]
%r1 = alloca i32
%r2 = alloca double
@@ -48,17 +46,17 @@ define void @alloca3264() {
}
; CHECK-LABEL: allocarray:
-; CHECK: .local i32{{$}}
+; CHECK: .local i[[PTR]]{{$}}
define void @allocarray() {
; CHECK-NEXT: global.get $push[[L4:.+]]=, __stack_pointer{{$}}
- ; CHECK-NEXT: i32.const $push[[L5:.+]]=, 144{{$}}
- ; CHECK-NEXT: i32.sub $push[[L12:.+]]=, $pop[[L4]], $pop[[L5]]
+ ; CHECK-NEXT: i[[PTR]].const $push[[L5:.+]]=, 144{{$}}
+ ; CHECK-NEXT: i[[PTR]].sub $push[[L12:.+]]=, $pop[[L4]], $pop[[L5]]
; CHECK-NEXT: local.tee $push[[L11:.+]]=, 0, $pop[[L12]]
; CHECK-NEXT: global.set __stack_pointer, $pop[[L11]]
%r = alloca [33 x i32]
- ; CHECK: i32.const $push{{.+}}=, 24
- ; CHECK-NEXT: i32.add $push[[L3:.+]]=, $pop{{.+}}, $pop{{.+}}
+ ; CHECK: i[[PTR]].const $push{{.+}}=, 24
+ ; CHECK-NEXT: i[[PTR]].add $push[[L3:.+]]=, $pop{{.+}}, $pop{{.+}}
; CHECK-NEXT: i32.const $push[[L1:.+]]=, 1{{$}}
; CHECK-NEXT: i32.store 0($pop[[L3]]), $pop[[L1]]{{$}}
; CHECK-NEXT: local.get $push[[L4:.+]]=, 0{{$}}
@@ -70,16 +68,16 @@ define void @allocarray() {
store i32 1, i32* %p2
; CHECK-NEXT: local.get $push[[L2:.+]]=, [[SP]]{{$}}
- ; CHECK-NEXT: i32.const $push[[L7:.+]]=, 144
- ; CHECK-NEXT: i32.add $push[[L8:.+]]=, $pop[[L2]], $pop[[L7]]
+ ; CHECK-NEXT: i[[PTR]].const $push[[L7:.+]]=, 144
+ ; CHECK-NEXT: i[[PTR]].add $push[[L8:.+]]=, $pop[[L2]], $pop[[L7]]
; CHECK-NEXT: global.set __stack_pointer, $pop[[L8]]
ret void
}
; CHECK-LABEL: non_mem_use
define void @non_mem_use(i8** %addr) {
- ; CHECK: i32.const $push[[L2:.+]]=, 48
- ; CHECK-NEXT: i32.sub $push[[L12:.+]]=, {{.+}}, $pop[[L2]]
+ ; CHECK: i[[PTR]].const $push[[L2:.+]]=, 48
+ ; CHECK-NEXT: i[[PTR]].sub $push[[L12:.+]]=, {{.+}}, $pop[[L2]]
; CHECK-NEXT: local.tee $push[[L11:.+]]=, [[SP:.+]], $pop[[L12]]
; CHECK-NEXT: global.set __stack_pointer, $pop[[L11]]
%buf = alloca [27 x i8], align 16
@@ -87,8 +85,8 @@ define void @non_mem_use(i8** %addr) {
%r2 = alloca i64
; %r is at SP+8
; CHECK: local.get $push[[L3:.+]]=, [[SP]]
- ; CHECK: i32.const $push[[OFF:.+]]=, 8
- ; CHECK-NEXT: i32.add $push[[ARG1:.+]]=, $pop[[L3]], $pop[[OFF]]
+ ; CHECK: i[[PTR]].const $push[[OFF:.+]]=, 8
+ ; CHECK-NEXT: i[[PTR]].add $push[[ARG1:.+]]=, $pop[[L3]], $pop[[OFF]]
; CHECK-NEXT: call ext_func, $pop[[ARG1]]
call void @ext_func(i64* %r)
; %r2 is at SP+0, no add needed
@@ -98,20 +96,20 @@ define void @non_mem_use(i8** %addr) {
; Use as a value, but in a store
; %buf is at SP+16
; CHECK: local.get $push[[L5:.+]]=, [[SP]]
- ; CHECK: i32.const $push[[OFF:.+]]=, 16
- ; CHECK-NEXT: i32.add $push[[VAL:.+]]=, $pop[[L5]], $pop[[OFF]]
- ; CHECK-NEXT: i32.store 0($pop{{.+}}), $pop[[VAL]]
+ ; CHECK: i[[PTR]].const $push[[OFF:.+]]=, 16
+ ; CHECK-NEXT: i[[PTR]].add $push[[VAL:.+]]=, $pop[[L5]], $pop[[OFF]]
+ ; CHECK-NEXT: i[[PTR]].store 0($pop{{.+}}), $pop[[VAL]]
%gep = getelementptr inbounds [27 x i8], [27 x i8]* %buf, i32 0, i32 0
store i8* %gep, i8** %addr
ret void
}
; CHECK-LABEL: allocarray_inbounds:
-; CHECK: .local i32{{$}}
+; CHECK: .local i[[PTR]]{{$}}
define void @allocarray_inbounds() {
; CHECK: global.get $push[[L3:.+]]=, __stack_pointer{{$}}
- ; CHECK-NEXT: i32.const $push[[L4:.+]]=, 32{{$}}
- ; CHECK-NEXT: i32.sub $push[[L11:.+]]=, $pop[[L3]], $pop[[L4]]
+ ; CHECK-NEXT: i[[PTR]].const $push[[L4:.+]]=, 32{{$}}
+ ; CHECK-NEXT: i[[PTR]].sub $push[[L11:.+]]=, $pop[[L3]], $pop[[L4]]
; CHECK-NEXT: local.tee $push[[L10:.+]]=, [[SP:.+]], $pop[[L11]]
; CHECK-NEXT: global.set __stack_pointer, $pop[[L10]]{{$}}
%r = alloca [5 x i32]
@@ -125,8 +123,8 @@ define void @allocarray_inbounds() {
store i32 1, i32* %p2
call void @ext_func(i64* null);
; CHECK: call ext_func
- ; CHECK: i32.const $push[[L5:.+]]=, 32{{$}}
- ; CHECK-NEXT: i32.add $push[[L7:.+]]=, ${{.+}}, $pop[[L5]]
+ ; CHECK: i[[PTR]].const $push[[L5:.+]]=, 32{{$}}
+ ; CHECK-NEXT: i[[PTR]].add $push[[L7:.+]]=, ${{.+}}, $pop[[L5]]
; CHECK-NEXT: global.set __stack_pointer, $pop[[L7]]
ret void
}
@@ -136,7 +134,7 @@ define void @dynamic_alloca(i32 %alloc) {
; CHECK: global.get $push[[L13:.+]]=, __stack_pointer{{$}}
; CHECK-NEXT: local.tee $push[[L12:.+]]=, [[SP:.+]], $pop[[L13]]{{$}}
; Target independent codegen bumps the stack pointer.
- ; CHECK: i32.sub
+ ; CHECK: i[[PTR]].sub
; Check that SP is written back to memory after decrement
; CHECK: global.set __stack_pointer,
%r = alloca i32, i32 %alloc
@@ -152,12 +150,12 @@ define void @dynamic_alloca_redzone(i32 %alloc) {
; CHECK: global.get $push[[L13:.+]]=, __stack_pointer{{$}}
; CHECK-NEXT: local.tee $push[[L12:.+]]=, [[SP:.+]], $pop[[L13]]{{$}}
; Target independent codegen bumps the stack pointer
- ; CHECK: i32.sub
+ ; CHECK: i[[PTR]].sub
%r = alloca i32, i32 %alloc
- ; CHECK-NEXT: local.tee $push[[L8:.+]]=, {{.+}}, $pop
- ; CHECK: local.get $push[[L7:.+]]=, 0{{$}}
- ; CHECK-NEXT: i32.const $push[[L6:.+]]=, 0{{$}}
- ; CHECK-NEXT: i32.store 0($pop[[L7]]), $pop[[L6]]{{$}}
+ ; CHECK-NEXT: local.tee $push[[L8:.+]]=, [[SP2:.+]], $pop
+ ; CHECK: local.get $push[[L7:.+]]=, [[SP2]]{{$}}
+ ; CHECK-NEXT: i32.const $push[[L6:.+]]=, 0{{$}}
+ ; CHECK-NEXT: i32.store 0($pop[[L7]]), $pop[[L6]]{{$}}
store i32 0, i32* %r
; CHECK-NEXT: return
ret void
@@ -167,8 +165,8 @@ define void @dynamic_alloca_redzone(i32 %alloc) {
define void @dynamic_static_alloca(i32 %alloc) noredzone {
; Decrement SP in the prolog by the static amount and writeback to memory.
; CHECK: global.get $push[[L11:.+]]=, __stack_pointer{{$}}
- ; CHECK-NEXT: i32.const $push[[L12:.+]]=, 16
- ; CHECK-NEXT: i32.sub $push[[L23:.+]]=, $pop[[L11]], $pop[[L12]]
+ ; CHECK-NEXT: i[[PTR]].const $push[[L12:.+]]=, 16
+ ; CHECK-NEXT: i[[PTR]].sub $push[[L23:.+]]=, $pop[[L11]], $pop[[L12]]
; CHECK-NEXT: local.tee $push[[L22:.+]]=, [[SP:.+]], $pop[[L23]]
; CHECK-NEXT: global.set __stack_pointer, $pop[[L22]]
@@ -181,7 +179,7 @@ define void @dynamic_static_alloca(i32 %alloc) noredzone {
store volatile i32 101, i32* %static
; Decrement SP in the body by the dynamic amount.
- ; CHECK: i32.sub
+ ; CHECK: i[[PTR]].sub
; CHECK: local.tee $push[[L16:.+]]=, [[dynamic_local:.+]], $pop{{.+}}
; CHECK: local.tee $push[[L15:.+]]=, [[other:.+]], $pop[[L16]]{{$}}
; CHECK: global.set __stack_pointer, $pop[[L15]]{{$}}
@@ -201,7 +199,7 @@ define void @dynamic_static_alloca(i32 %alloc) noredzone {
store volatile i32 103, i32* %dynamic
; Decrement SP in the body by the dynamic amount.
- ; CHECK: i32.sub
+ ; CHECK: i[[PTR]].sub
; CHECK: local.tee $push{{.+}}=, [[dynamic2_local:.+]], $pop{{.+}}
%dynamic.2 = alloca i32, i32 %alloc
@@ -224,8 +222,8 @@ define void @dynamic_static_alloca(i32 %alloc) noredzone {
; Writeback to memory.
; CHECK: local.get $push[[L24:.+]]=, [[FP]]{{$}}
- ; CHECK: i32.const $push[[L18:.+]]=, 16
- ; CHECK-NEXT: i32.add $push[[L19:.+]]=, $pop[[L24]], $pop[[L18]]
+ ; CHECK: i[[PTR]].const $push[[L18:.+]]=, 16
+ ; CHECK-NEXT: i[[PTR]].add $push[[L19:.+]]=, $pop[[L24]], $pop[[L18]]
; CHECK-NEXT: global.set __stack_pointer, $pop[[L19]]
ret void
}
@@ -273,11 +271,11 @@ define void @dynamic_alloca_nouse(i32 %alloc) noredzone {
; CHECK-LABEL: copytoreg_fi:
define void @copytoreg_fi(i1 %cond, i32* %b) {
entry:
- ; CHECK: i32.const $push[[L1:.+]]=, 16
- ; CHECK-NEXT: i32.sub $push[[L3:.+]]=, {{.+}}, $pop[[L1]]
+ ; CHECK: i[[PTR]].const $push[[L1:.+]]=, 16
+ ; CHECK-NEXT: i[[PTR]].sub $push[[L3:.+]]=, {{.+}}, $pop[[L1]]
%addr = alloca i32
- ; CHECK: i32.const $push[[OFF:.+]]=, 12
- ; CHECK-NEXT: i32.add $push[[ADDR:.+]]=, $pop[[L3]], $pop[[OFF]]
+ ; CHECK: i[[PTR]].const $push[[OFF:.+]]=, 12
+ ; CHECK-NEXT: i[[PTR]].add $push[[ADDR:.+]]=, $pop[[L3]], $pop[[OFF]]
; CHECK-NEXT: local.set [[COPY:.+]], $pop[[ADDR]]
br label %body
body:
@@ -309,7 +307,7 @@ define void @frameaddress_0() {
; Test __builtin_frame_address(1).
; CHECK-LABEL: frameaddress_1:
-; CHECK: i32.const $push0=, 0{{$}}
+; CHECK: i[[PTR]].const $push0=, 0{{$}}
; CHECK-NEXT: call use_i8_star, $pop0{{$}}
; CHECK-NEXT: return{{$}}
define void @frameaddress_1() {
@@ -330,6 +328,6 @@ define void @inline_asm() {
ret void
}
-; CHECK: .globaltype __stack_pointer, i32{{$}}
+; CHECK: .globaltype __stack_pointer, i[[PTR]]{{$}}
; TODO: test over-aligned alloca
diff --git a/llvm/test/MC/WebAssembly/stack-ptr.ll b/llvm/test/MC/WebAssembly/stack-ptr.ll
index 147f04ffec15..b92c773c085f 100644
--- a/llvm/test/MC/WebAssembly/stack-ptr.ll
+++ b/llvm/test/MC/WebAssembly/stack-ptr.ll
@@ -1,6 +1,5 @@
-; RUN: llc -filetype=obj %s -o - | obj2yaml | FileCheck %s
-
-target triple = "wasm32-unknown-unknown"
+; RUN: llc --mtriple=wasm32-unknown-unknown -filetype=obj %s -o - | obj2yaml | FileCheck --check-prefixes CHECK,CHK32 %s
+; RUN: llc --mtriple=wasm64-unknown-unknown -filetype=obj %s -o - | obj2yaml | FileCheck --check-prefixes CHECK,CHK64 %s
; Function that uses explict stack, and should generate a reference to
; __stack_pointer, along with the corresponding reloction entry.
@@ -15,7 +14,8 @@ entry:
; CHECK: - Module: env
; CHECK: Field: __stack_pointer
; CHECK: Kind: GLOBAL
-; CHECK: GlobalType: I32
+; CHK32: GlobalType: I32
+; CHK64: GlobalType: I64
; CHECK: GlobalMutable: true
; CHECK: - Type: CODE
; CHECK: Relocations:
diff --git a/llvm/test/MC/WebAssembly/wasm64.s b/llvm/test/MC/WebAssembly/wasm64.s
index e31bfcf12387..2ec331f751d6 100644
--- a/llvm/test/MC/WebAssembly/wasm64.s
+++ b/llvm/test/MC/WebAssembly/wasm64.s
@@ -51,6 +51,11 @@ test:
i64.const 0
f32.store .L.str # relocatable offset!
+ ### 64-bit SP
+
+ global.get __stack_pointer
+ drop
+
end_function
.section .rodata..L.str,"",@
@@ -62,7 +67,7 @@ test:
.size .L.str, 24
.globaltype myglob64, i64
-
+ .globaltype __stack_pointer, i64
# CHECK: .functype test (i64) -> ()
@@ -155,6 +160,11 @@ test:
# BIN-NEXT: Kind: GLOBAL
# BIN-NEXT: GlobalType: I64
# BIN-NEXT: GlobalMutable: true
+# BIN-NEXT: - Module: env
+# BIN-NEXT: Field: __stack_pointer
+# BIN-NEXT: Kind: GLOBAL
+# BIN-NEXT: GlobalType: I64
+# BIN-NEXT: GlobalMutable: true
# BIN-NEXT: - Type: FUNCTION
# BIN-NEXT: FunctionTypes: [ 0 ]
# BIN-NEXT: - Type: DATACOUNT
@@ -179,12 +189,15 @@ test:
# BIN-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB64
# BIN-NEXT: Index: 1
# BIN-NEXT: Offset: 0x00000078
+# BIN-NEXT: - Type: R_WASM_GLOBAL_INDEX_LEB
+# BIN-NEXT: Index: 3
+# BIN-NEXT: Offset: 0x00000083
# BIN-NEXT: Functions:
# BIN-NEXT: - Index: 0
# BIN-NEXT: Locals:
# BIN-NEXT: - Type: I64
# BIN-NEXT: Count: 1
-# BIN-NEXT: Body: 42002A02001A20002A02001A42808080808080808080002A02001A2380808080002A02001A42002A02808080808080808080001A4300000000420038020043000000002000380200430000000042808080808080808080003802004300000000238080808000380200430000000042003802808080808080808080000B
+# BIN-NEXT: Body: 42002A02001A20002A02001A42808080808080808080002A02001A2380808080002A02001A42002A02808080808080808080001A4300000000420038020043000000002000380200430000000042808080808080808080003802004300000000238080808000380200430000000042003802808080808080808080002381808080001A0B
# BIN-NEXT: - Type: DATA
# BIN-NEXT: Relocations:
# BIN-NEXT: - Type: R_WASM_MEMORY_ADDR_I64
@@ -217,6 +230,11 @@ test:
# BIN-NEXT: Name: myglob64
# BIN-NEXT: Flags: [ UNDEFINED ]
# BIN-NEXT: Global: 0
+# BIN-NEXT: - Index: 3
+# BIN-NEXT: Kind: GLOBAL
+# BIN-NEXT: Name: __stack_pointer
+# BIN-NEXT: Flags: [ UNDEFINED ]
+# BIN-NEXT: Global: 1
# BIN-NEXT: SegmentInfo:
# BIN-NEXT: - Index: 0
# BIN-NEXT: Name: .rodata..L.str
More information about the cfe-commits
mailing list