Index: lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -78,40 +78,54 @@ //===----------------------------------------------------------------------===// void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) { - for (auto &It : OutContext.getSymbols()) { - // Emit a .globaltype and .eventtype declaration. - auto Sym = cast(It.getValue()); - if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_GLOBAL) - getTargetStreamer()->emitGlobalType(Sym); - else if (Sym->getType() == wasm::WASM_SYMBOL_TYPE_EVENT) - getTargetStreamer()->emitEventType(Sym); - } - for (const auto &F : M) { - // Emit function type info for all undefined functions - if (F.isDeclarationForLinker() && !F.isIntrinsic()) { + if (F.isDeclarationForLinker() && !F.isIntrinsic()) { SmallVector Results; SmallVector Params; ComputeSignatureVTs(F.getFunctionType(), F, TM, Params, Results); auto *Sym = cast(getSymbol(&F)); - if (!Sym->getSignature()) { + + if (Sym->getType() != wasm::WASM_SYMBOL_TYPE_FUNCTION) { + dbgs() << "Missing Sig: " << *Sym << "\n"; auto Signature = SignatureFromMVTs(Results, Params); + Sym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); Sym->setSignature(Signature.get()); addSignature(std::move(Signature)); + //assert(false); } - // FIXME: this was originally intended for post-linking and was only used - // for imports that were only called indirectly (i.e. s2wasm could not - // infer the type from a call). With object files it applies to all - // imports. so fix the names and the tests, or rethink how import - // delcarations work in asm files. - getTargetStreamer()->emitIndirectFunctionType(Sym); - if (TM.getTargetTriple().isOSBinFormatWasm() && - F.hasFnAttribute("wasm-import-module")) { + if (F.hasFnAttribute("wasm-import-module")) { + auto *Sym = cast(getSymbol(&F)); StringRef Name = F.getFnAttribute("wasm-import-module").getValueAsString(); getTargetStreamer()->emitImportModule(Sym, Name); } + } + } + + for (auto &It : OutContext.getSymbols()) { + // Emit a .globaltype/.eventtype/.functype declaration. + auto* Sym = cast(It.getValue()); + //dbgs() << "sym: " << *Sym << "\n"; + if (Sym->isVariable()) + continue; + switch (Sym->getType()) { + case wasm::WASM_SYMBOL_TYPE_GLOBAL: + getTargetStreamer()->emitGlobalType(Sym); + break; + case wasm::WASM_SYMBOL_TYPE_EVENT: + getTargetStreamer()->emitEventType(Sym); + break; + case wasm::WASM_SYMBOL_TYPE_FUNCTION: + // Defined symbols have this function type set at the declartion site + if (Sym->isDefined()) + continue; + assert(Sym->getSignature()); + getTargetStreamer()->emitIndirectFunctionType(Sym); + break; + case wasm::WASM_SYMBOL_TYPE_DATA: + case wasm::WASM_SYMBOL_TYPE_SECTION: + break; } } Index: lib/Target/WebAssembly/WebAssemblyFastISel.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ lib/Target/WebAssembly/WebAssemblyFastISel.cpp @@ -150,6 +150,7 @@ } bool computeAddress(const Value *Obj, Address &Addr); void materializeLoadStoreOperands(Address &Addr); + unsigned materializeGlobalAddrPIC(const GlobalValue *GV); void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB, MachineMemOperand *MMO); unsigned maskI1Value(unsigned Reg, const Value *V); @@ -373,16 +374,51 @@ return Addr.getReg() != 0; } +unsigned WebAssemblyFastISel::materializeGlobalAddrPIC(const GlobalValue *GV) { + unsigned Reg = + createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass + : &WebAssembly::I32RegClass); + assert(TLI.isPositionIndependent()); + // For PIC code, access all hidden globals via __memory_base. + if (GV->hasHiddenVisibility()) { + auto *MemBaseSymbol = + FuncInfo.MF->createExternalSymbolName("__memory_base"); + unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::GET_GLOBAL_I64 + : WebAssembly::GET_GLOBAL_I32; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg) + .addExternalSymbol(MemBaseSymbol, + WebAssemblyII::MO_SYMBOL_GLOBAL); + } else { + std::string getterName("g$"); + getterName += GV->getName(); + auto *getterSymName = + FuncInfo.MF->createExternalSymbolName(getterName); + unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CALL_I64 + : WebAssembly::CALL_I32; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg) + .addExternalSymbol(getterSymName, + WebAssemblyII::MO_SYMBOL_FUNCTION); + } + + return Reg; +} + void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) { if (Addr.isRegBase()) { unsigned Reg = Addr.getReg(); if (Reg == 0) { - Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass + const GlobalValue *GV = Addr.getGlobalValue(); + if (GV && TLI.isPositionIndependent()) { + Reg = materializeGlobalAddrPIC(GV); + } else { + Reg = + createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass : &WebAssembly::I32RegClass); - unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64 - : WebAssembly::CONST_I32; - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg) - .addImm(0); + unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64 + : WebAssembly::CONST_I32; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg) + .addImm(0); + } Addr.setReg(Reg); } } @@ -395,7 +431,14 @@ // TODO: Disable SetP2AlignOperands for FastISel and just do it here. MIB.addImm(0); - if (const GlobalValue *GV = Addr.getGlobalValue()) + const GlobalValue *GV = Addr.getGlobalValue(); + bool IncludeGlobalAddr = GV != nullptr; + + // Fir PIC code the global address in the stack already + if (GV && TLI.isPositionIndependent() && !GV->hasHiddenVisibility()) + IncludeGlobalAddr = false; + + if (IncludeGlobalAddr) MIB.addGlobalAddress(GV, Addr.getOffset()); else MIB.addImm(Addr.getOffset()); @@ -606,14 +649,18 @@ unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) { if (const GlobalValue *GV = dyn_cast(C)) { - unsigned ResultReg = - createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass - : &WebAssembly::I32RegClass); - unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64 - : WebAssembly::CONST_I32; - BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) - .addGlobalAddress(GV); - return ResultReg; + if (TLI.isPositionIndependent()) { + return materializeGlobalAddrPIC(GV); + } else { + unsigned ResultReg = + createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass + : &WebAssembly::I32RegClass); + unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64 + : WebAssembly::CONST_I32; + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) + .addGlobalAddress(GV); + return ResultReg; + } } // Let target-independent code handle it. @@ -742,9 +789,17 @@ return false; bool IsDirect = Func != nullptr; + if (!IsDirect && isa(Call->getCalledValue())) return false; + if (IsDirect && TLI.isPositionIndependent() && !Func->hasHiddenVisibility()) { + dbgs() << "XXX\n"; + dbgs() << *Func << "\n"; + dbgs() << "YYY\n"; + IsDirect = false; + } + FunctionType *FuncTy = Call->getFunctionType(); unsigned Opc; bool IsVoid = FuncTy->getReturnType()->isVoidTy(); Index: lib/Target/WebAssembly/WebAssemblyISelLowering.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -731,9 +731,10 @@ } InTys.push_back(MVT::Other); SDVTList InTyList = DAG.getVTList(InTys); - SDValue Res = - DAG.getNode(Ins.empty() ? WebAssemblyISD::CALL0 : WebAssemblyISD::CALL1, - DL, InTyList, Ops); + unsigned Opcode = Ins.empty() ? WebAssemblyISD::CALL0 : WebAssemblyISD::CALL1; + //if (isPositionIndependent() ) + //Opcode = Ins.empty() ? WebAssemblyISD::CALL_INDIRECT1 : WebAssemblyISD::CALL_INDIRECT1; + SDValue Res = DAG.getNode(Opcode, DL, InTyList, Ops); if (Ins.empty()) { Chain = Res; } else { @@ -964,11 +965,10 @@ EVT VT = Op.getValueType(); assert(ES->getTargetFlags() == 0 && "Unexpected target flags on generic ExternalSymbolSDNode"); - // Set the TargetFlags to 0x1 which indicates that this is a "function" - // symbol rather than a data symbol. We do this unconditionally even though - // we don't know anything about the symbol other than its name, because all - // external symbols used in target-independent SelectionDAG code are for - // functions. + // Set TargetFlags to WebAssemblyII::MO_SYMBOL_FUNCTION. We do this + // unconditionally even though we don't know anything about the symbol other + // than its name, because all external symbols used in target-independent + // SelectionDAG code are for functions. return DAG.getNode( WebAssemblyISD::Wrapper, DL, VT, DAG.getTargetExternalSymbol(ES->getSymbol(), VT, Index: lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp +++ lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp @@ -79,7 +79,7 @@ // other external symbols used by CodeGen are functions. It's OK to hardcode // knowledge of specific symbols here; this method is precisely there for // fetching the signatures of known Clang-provided symbols. - if (strcmp(Name, "__stack_pointer") == 0) { + if (strcmp(Name, "__stack_pointer") == 0 || strcmp(Name, "__memory_base") == 0) { WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL); WasmSym->setGlobalType(wasm::WasmGlobalType{ uint8_t(Subtarget.hasAddr64() ? wasm::WASM_TYPE_I64 @@ -108,6 +108,10 @@ // functions, exceptions are assumed to have void return type. Params.push_back(Subtarget.hasAddr64() ? wasm::ValType::I64 : wasm::ValType::I32); + } else if (strncmp(Name, "g$", 2) == 0) { + WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); + Returns.push_back(Subtarget.hasAddr64() ? wasm::ValType::I64 + : wasm::ValType::I32); } else { // Function symbols WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); GetLibcallSignature(Subtarget, Name, Returns, Params); Index: test/CodeGen/WebAssembly/address-offsets.ll =================================================================== --- test/CodeGen/WebAssembly/address-offsets.ll +++ test/CodeGen/WebAssembly/address-offsets.ll @@ -1,4 +1,6 @@ -; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s -check-prefixes=CHECK,NPIC +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -relocation-model=pic -fast-isel | FileCheck %s -check-prefixes=CHECK,PIC + ; Test folding constant offsets and symbols into load and store addresses under ; a variety of circumstances. @@ -9,9 +11,11 @@ @g = external global [0 x i32], align 4 ; CHECK-LABEL: load_test0: -; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 0{{$}} -; CHECK-NEXT: i32.load $push1=, g+40($pop0){{$}} +; CHECK-NEXT: .result i32{{$}} +; NPIC-NEXT: i32.const $push0=, 0{{$}} +; NPIC-NEXT: i32.load $push1=, g+40($pop0){{$}} +; PIC-NEXT: i32.call $push0=, g$g@FUNCTION +; PIC-NEXT: i32.load $push1=, 40($pop0) ; CHECK-NEXT: return $pop1{{$}} define i32 @load_test0() { %t = load i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), align 4 @@ -19,9 +23,11 @@ } ; CHECK-LABEL: load_test0_noinbounds: -; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 0{{$}} -; CHECK-NEXT: i32.load $push1=, g+40($pop0){{$}} +; CHECK-NEXT: .result i32{{$}} +; NPIC-NEXT: i32.const $push0=, 0{{$}} +; NPIC-NEXT: i32.load $push1=, g+40($pop0){{$}} +; PIC-NEXT: i32.call $push0=, g$g@FUNCTION{{$}} +; PIC-NEXT: i32.load $push1=, 40($pop0){{$}} ; CHECK-NEXT: return $pop1{{$}} define i32 @load_test0_noinbounds() { %t = load i32, i32* getelementptr ([0 x i32], [0 x i32]* @g, i32 0, i32 10), align 4 @@ -35,7 +41,7 @@ ; CHECK-LABEL: load_test1: ; CHECK-NEXT: param i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} ; CHECK-NEX T: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.load $push2=, g+40($pop1){{$}} ; CHECK-NEX T: return $pop2{{$}} @@ -49,7 +55,7 @@ ; CHECK-LABEL: load_test2: ; CHECK-NEXT: param i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} ; CHECK-NEX T: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.load $push2=, g+40($pop1){{$}} ; CHECK-NEX T: return $pop2{{$}} @@ -63,7 +69,7 @@ ; CHECK-LABEL: load_test3: ; CHECK-NEXT: param i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} ; CHECK-NEX T: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.load $push2=, g+40($pop1){{$}} ; CHECK-NEX T: return $pop2{{$}} @@ -77,7 +83,7 @@ ; CHECK-LABEL: load_test4: ; CHECK-NEXT: param i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} ; CHECK-NEX T: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.load $push2=, g+40($pop1){{$}} ; CHECK-NEX T: return $pop2{{$}} @@ -90,7 +96,7 @@ ; CHECK-LABEL: load_test5: ; CHECK-NEXT: param i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} ; CHECK-NEX T: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.load $push2=, g+40($pop1){{$}} ; CHECK-NEX T: return $pop2{{$}} @@ -103,7 +109,7 @@ ; CHECK-LABEL: load_test6: ; CHECK-NEXT: param i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} ; CHECK-NEX T: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.load $push2=, g+40($pop1){{$}} ; CHECK-NEX T: return $pop2{{$}} @@ -115,9 +121,9 @@ } ; CHECK-LABEL: load_test7: -; CHECK-NEXT: param i32{{$}} -; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} +; CHECK-NEXT: .param i32{{$}} +; CHECK-NEXT: .result i32{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} ; CHECK-NEX T: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.load $push2=, g+40($pop1){{$}} ; CHECK-NEX T: return $pop2{{$}} @@ -129,9 +135,9 @@ } ; CHECK-LABEL: load_test8: -; CHECK-NEXT: param i32{{$}} -; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} +; CHECK-NEXT: .param i32{{$}} +; CHECK-NEXT: .result i32{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} ; CHECK-NEX T: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.load $push2=, g+40($pop1){{$}} ; CHECK-NEX T: return $pop2{{$}} @@ -144,8 +150,10 @@ ; CHECK-LABEL: load_test9: ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 0{{$}} -; CHECK-NEXT: i32.load $push1=, g-40($pop0){{$}} +; PIC-NEXT: i32.call $push0=, g$g@FUNCTION +; PIC-NEXT: i32.load $push1=, 4294967256($pop0) +; NPIC-NEXT: i32.const $push0=, 0{{$}} +; NPIC-NEXT: i32.load $push1=, g-40($pop0){{$}} ; CHECK-NEXT: return $pop1{{$}} define i32 @load_test9() { %t = load i32, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 1073741814), align 4 @@ -155,12 +163,20 @@ ; CHECK-LABEL: load_test10: ; CHECK-NEXT: param i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $0, $pop0{{$}} -; CHECK-NEXT: i32.const $push2=, g-40{{$}} -; CHECK-NEXT: i32.add $push3=, $pop1, $pop2{{$}} -; CHECK-NEXT: i32.load $push4=, 0($pop3){{$}} -; CHECK-NEXT: return $pop4{{$}} +; PIC-NEXT: i32.call $push1=, g$g@FUNCTION +; PIC-NEXT: i32.const $push5=, -10 +; PIC-NEXT: i32.add $push6=, $0, $pop5 +; PIC-NEXT: i32.const $push2=, 2 +; PIC-NEXT: i32.shl $push3=, $pop6, $pop2 +; PIC-NEXT: i32.add $push4=, $pop1, $pop3 +; PIC-NEXT: i32.load $push0=, 0($pop4) +; PIC-NEXT: return $pop0{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $0, $pop0{{$}} +; NPIC-NEXT: i32.const $push2=, g-40{{$}} +; NPIC-NEXT: i32.add $push3=, $pop1, $pop2{{$}} +; NPIC-NEXT: i32.load $push4=, 0($pop3){{$}} +; NPIC-NEXT: return $pop4{{$}} define i32 @load_test10(i32 %n) { %add = add nsw i32 %n, -10 %arrayidx = getelementptr inbounds [0 x i32], [0 x i32]* @g, i32 0, i32 %add @@ -182,10 +198,10 @@ ; CHECK-LABEL: load_test11_noinbounds: ; CHECK-NEXT: param i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 40{{$}} -; CHECK-NEXT: i32.add $push1=, $0, $pop0{{$}} -; CHECK-NEXT: i32.load $push2=, 0($pop1){{$}} -; CHECK-NEXT: return $pop2{{$}} +; CHECK-NEXT: i32.const $push[[NUM:[0-9]+]]=, 40{{$}} +; CHECK-NEXT: i32.add $push[[NUM2:[0-9]+]]=, $0, $pop[[NUM]]{{$}} +; CHECK-NEXT: i32.load $push[[NUM3:[0-9]+]]=, 0($pop[[NUM2]]){{$}} +; CHECK-NEXT: return $pop[[NUM3]]{{$}} define i32 @load_test11_noinbounds(i32* %p) { %arrayidx = getelementptr i32, i32* %p, i32 10 %t = load i32, i32* %arrayidx, align 4 @@ -212,12 +228,12 @@ ; CHECK-LABEL: load_test13: ; CHECK-NEXT: param i32, i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.const $push3=, 40{{$}} -; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} -; CHECK-NEXT: i32.load $push5=, 0($pop4){{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.const $push3=, 40{{$}} +; NPIC-NEXT: i32.add $push4=, $pop2, $pop3{{$}} +; NPIC-NEXT: i32.load $push5=, 0($pop4){{$}} ; CHECK-NEXT: return $pop5{{$}} define i32 @load_test13(i32* %p, i32 %n) { %add = add nsw i32 10, %n @@ -229,10 +245,10 @@ ; CHECK-LABEL: load_test14: ; CHECK-NEXT: param i32, i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.load $push3=, 40($pop2){{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.load $push3=, 40($pop2){{$}} ; CHECK-NEXT: return $pop3{{$}} define i32 @load_test14(i32* %p, i32 %n) { %add.ptr = getelementptr inbounds i32, i32* %p, i32 %n @@ -244,12 +260,12 @@ ; CHECK-LABEL: load_test15: ; CHECK-NEXT: param i32, i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.const $push3=, 40{{$}} -; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} -; CHECK-NEXT: i32.load $push5=, 0($pop4){{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.const $push3=, 40{{$}} +; NPIC-NEXT: i32.add $push4=, $pop2, $pop3{{$}} +; NPIC-NEXT: i32.load $push5=, 0($pop4){{$}} ; CHECK-NEXT: return $pop5{{$}} define i32 @load_test15(i32* %p, i32 %n) { %add.ptr = getelementptr inbounds i32, i32* %p, i32 10 @@ -261,12 +277,12 @@ ; CHECK-LABEL: load_test16: ; CHECK-NEXT: param i32, i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.const $push3=, 40{{$}} -; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} -; CHECK-NEXT: i32.load $push5=, 0($pop4){{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.const $push3=, 40{{$}} +; NPIC-NEXT: i32.add $push4=, $pop2, $pop3{{$}} +; NPIC-NEXT: i32.load $push5=, 0($pop4){{$}} ; CHECK-NEXT: return $pop5{{$}} define i32 @load_test16(i32* %p, i32 %n) { %add.ptr = getelementptr inbounds i32, i32* %p, i32 10 @@ -278,12 +294,12 @@ ; CHECK-LABEL: load_test17: ; CHECK-NEXT: param i32, i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.const $push3=, 40{{$}} -; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} -; CHECK-NEXT: i32.load $push5=, 0($pop4){{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.const $push3=, 40{{$}} +; NPIC-NEXT: i32.add $push4=, $pop2, $pop3{{$}} +; NPIC-NEXT: i32.load $push5=, 0($pop4){{$}} ; CHECK-NEXT: return $pop5{{$}} define i32 @load_test17(i32* %p, i32 %n) { %add = add nsw i32 %n, 10 @@ -295,10 +311,10 @@ ; CHECK-LABEL: load_test18: ; CHECK-NEXT: param i32, i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.load $push3=, 40($pop2){{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.load $push3=, 40($pop2){{$}} ; CHECK-NEXT: return $pop3{{$}} define i32 @load_test18(i32* %p, i32 %n) { %add.ptr = getelementptr inbounds i32, i32* %p, i32 %n @@ -310,12 +326,12 @@ ; CHECK-LABEL: load_test19: ; CHECK-NEXT: param i32, i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.const $push3=, 40{{$}} -; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} -; CHECK-NEXT: i32.load $push5=, 0($pop4){{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.const $push3=, 40{{$}} +; NPIC-NEXT: i32.add $push4=, $pop2, $pop3{{$}} +; NPIC-NEXT: i32.load $push5=, 0($pop4){{$}} ; CHECK-NEXT: return $pop5{{$}} define i32 @load_test19(i32* %p, i32 %n) { %add = add nsw i32 10, %n @@ -327,9 +343,9 @@ ; CHECK-LABEL: load_test20: ; CHECK-NEXT: param i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, -40{{$}} -; CHECK-NEXT: i32.add $push1=, $0, $pop0{{$}} -; CHECK-NEXT: i32.load $push2=, 0($pop1){{$}} +; NPIC-NEXT: i32.const $push0=, -40{{$}} +; NPIC-NEXT: i32.add $push1=, $0, $pop0{{$}} +; NPIC-NEXT: i32.load $push2=, 0($pop1){{$}} ; CHECK-NEXT: return $pop2{{$}} define i32 @load_test20(i32* %p) { %arrayidx = getelementptr inbounds i32, i32* %p, i32 -10 @@ -340,12 +356,12 @@ ; CHECK-LABEL: load_test21: ; CHECK-NEXT: param i32, i32{{$}} ; CHECK-NEXT: result i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.const $push3=, -40{{$}} -; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} -; CHECK-NEXT: i32.load $push5=, 0($pop4){{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.const $push3=, -40{{$}} +; NPIC-NEXT: i32.add $push4=, $pop2, $pop3{{$}} +; NPIC-NEXT: i32.load $push5=, 0($pop4){{$}} ; CHECK-NEXT: return $pop5{{$}} define i32 @load_test21(i32* %p, i32 %n) { %add = add nsw i32 %n, -10 @@ -356,8 +372,8 @@ ; CHECK-LABEL: store_test0: ; CHECK-NEXT: param i32{{$}} -; CHECK-NEXT: i32.const $push0=, 0{{$}} -; CHECK-NEXT: i32.store g+40($pop0), $0{{$}} +; NPIC-NEXT: i32.const $push0=, 0{{$}} +; NPIC-NEXT: i32.store g+40($pop0), $0{{$}} ; CHECK-NEXT: return{{$}} define void @store_test0(i32 %i) { store i32 %i, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 10), align 4 @@ -366,8 +382,8 @@ ; CHECK-LABEL: store_test0_noinbounds: ; CHECK-NEXT: param i32{{$}} -; CHECK-NEXT: i32.const $push0=, 0{{$}} -; CHECK-NEXT: i32.store g+40($pop0), $0{{$}} +; NPIC-NEXT: i32.const $push0=, 0{{$}} +; NPIC-NEXT: i32.store g+40($pop0), $0{{$}} ; CHECK-NEXT: return{{$}} define void @store_test0_noinbounds(i32 %i) { store i32 %i, i32* getelementptr ([0 x i32], [0 x i32]* @g, i32 0, i32 10), align 4 @@ -376,8 +392,8 @@ ; CHECK-LABEL: store_test1: ; CHECK-NEXT: param i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $0, $pop0{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.store g+40($pop1), $1{{$}} ; CHECK-NEX T: return{{$}} define void @store_test1(i32 %n, i32 %i) { @@ -389,8 +405,8 @@ ; CHECK-LABEL: store_test2: ; CHECK-NEXT: param i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $0, $pop0{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.store g+40($pop1), $1{{$}} ; CHECK-NEX T: return{{$}} define void @store_test2(i32 %n, i32 %i) { @@ -402,8 +418,8 @@ ; CHECK-LABEL: store_test3: ; CHECK-NEXT: param i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $0, $pop0{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.store g+40($pop1), $1{{$}} ; CHECK-NEX T: return{{$}} define void @store_test3(i32 %n, i32 %i) { @@ -415,8 +431,8 @@ ; CHECK-LABEL: store_test4: ; CHECK-NEXT: param i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $0, $pop0{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.store g+40($pop1), $1{{$}} ; CHECK-NEX T: return{{$}} define void @store_test4(i32 %n, i32 %i) { @@ -427,8 +443,8 @@ ; CHECK-LABEL: store_test5: ; CHECK-NEXT: param i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $0, $pop0{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.store g+40($pop1), $1{{$}} ; CHECK-NEX T: return{{$}} define void @store_test5(i32 %n, i32 %i) { @@ -439,8 +455,8 @@ ; CHECK-LABEL: store_test6: ; CHECK-NEXT: param i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $0, $pop0{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.store g+40($pop1), $1{{$}} ; CHECK-NEX T: return{{$}} define void @store_test6(i32 %n, i32 %i) { @@ -452,8 +468,8 @@ ; CHECK-LABEL: store_test7: ; CHECK-NEXT: param i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $0, $pop0{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.store g+40($pop1), $1{{$}} ; CHECK-NEX T: return{{$}} define void @store_test7(i32 %n, i32 %i) { @@ -465,8 +481,8 @@ ; CHECK-LABEL: store_test8: ; CHECK-NEXT: param i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $0, $pop0{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $0, $pop0{{$}} ; CHECK-NEX T: i32.store g+40($pop1), $1{{$}} ; CHECK-NEX T: return{{$}} define void @store_test8(i32 %n, i32 %i) { @@ -478,8 +494,8 @@ ; CHECK-LABEL: store_test9: ; CHECK-NEXT: param i32{{$}} -; CHECK-NEXT: i32.const $push0=, 0{{$}} -; CHECK-NEXT: i32.store g-40($pop0), $0{{$}} +; NPIC-NEXT: i32.const $push0=, 0{{$}} +; NPIC-NEXT: i32.store g-40($pop0), $0{{$}} ; CHECK-NEXT: return{{$}} define void @store_test9(i32 %i) { store i32 %i, i32* getelementptr inbounds ([0 x i32], [0 x i32]* @g, i32 0, i32 1073741814), align 4 @@ -488,11 +504,11 @@ ; CHECK-LABEL: store_test10: ; CHECK-NEXT: param i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $0, $pop0{{$}} -; CHECK-NEXT: i32.const $push2=, g-40{{$}} -; CHECK-NEXT: i32.add $push3=, $pop1, $pop2{{$}} -; CHECK-NEXT: i32.store 0($pop3), $1{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $0, $pop0{{$}} +; NPIC-NEXT: i32.const $push2=, g-40{{$}} +; NPIC-NEXT: i32.add $push3=, $pop1, $pop2{{$}} +; NPIC-NEXT: i32.store 0($pop3), $1{{$}} ; CHECK-NEXT: return{{$}} define void @store_test10(i32 %n, i32 %i) { %add = add nsw i32 %n, -10 @@ -503,7 +519,7 @@ ; CHECK-LABEL: store_test11: ; CHECK-NEXT: param i32, i32{{$}} -; CHECK-NEXT: i32.store 40($0), $1{{$}} +; NPIC-NEXT: i32.store 40($0), $1{{$}} ; CHECK-NEXT: return{{$}} define void @store_test11(i32* %p, i32 %i) { %arrayidx = getelementptr inbounds i32, i32* %p, i32 10 @@ -513,9 +529,9 @@ ; CHECK-LABEL: store_test11_noinbounds: ; CHECK-NEXT: param i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 40{{$}} -; CHECK-NEXT: i32.add $push1=, $0, $pop0{{$}} -; CHECK-NEXT: i32.store 0($pop1), $1{{$}} +; NPIC-NEXT: i32.const $push0=, 40{{$}} +; NPIC-NEXT: i32.add $push1=, $0, $pop0{{$}} +; NPIC-NEXT: i32.store 0($pop1), $1{{$}} ; CHECK-NEXT: return{{$}} define void @store_test11_noinbounds(i32* %p, i32 %i) { %arrayidx = getelementptr i32, i32* %p, i32 10 @@ -525,12 +541,12 @@ ; CHECK-LABEL: store_test12: ; CHECK-NEXT: param i32, i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.const $push3=, 40{{$}} -; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} -; CHECK-NEXT: i32.store 0($pop4), $2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.const $push3=, 40{{$}} +; NPIC-NEXT: i32.add $push4=, $pop2, $pop3{{$}} +; NPIC-NEXT: i32.store 0($pop4), $2{{$}} ; CHECK-NEXT: return{{$}} define void @store_test12(i32* %p, i32 %n, i32 %i) { %add = add nsw i32 %n, 10 @@ -541,12 +557,12 @@ ; CHECK-LABEL: store_test13: ; CHECK-NEXT: param i32, i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.const $push3=, 40{{$}} -; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} -; CHECK-NEXT: i32.store 0($pop4), $2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.const $push3=, 40{{$}} +; NPIC-NEXT: i32.add $push4=, $pop2, $pop3{{$}} +; NPIC-NEXT: i32.store 0($pop4), $2{{$}} ; CHECK-NEXT: return{{$}} define void @store_test13(i32* %p, i32 %n, i32 %i) { %add = add nsw i32 10, %n @@ -557,10 +573,10 @@ ; CHECK-LABEL: store_test14: ; CHECK-NEXT: param i32, i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.store 40($pop2), $2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.store 40($pop2), $2{{$}} ; CHECK-NEXT: return{{$}} define void @store_test14(i32* %p, i32 %n, i32 %i) { %add.ptr = getelementptr inbounds i32, i32* %p, i32 %n @@ -571,12 +587,12 @@ ; CHECK-LABEL: store_test15: ; CHECK-NEXT: param i32, i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.const $push3=, 40{{$}} -; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} -; CHECK-NEXT: i32.store 0($pop4), $2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.const $push3=, 40{{$}} +; NPIC-NEXT: i32.add $push4=, $pop2, $pop3{{$}} +; NPIC-NEXT: i32.store 0($pop4), $2{{$}} ; CHECK-NEXT: return{{$}} define void @store_test15(i32* %p, i32 %n, i32 %i) { %add.ptr = getelementptr inbounds i32, i32* %p, i32 10 @@ -587,12 +603,12 @@ ; CHECK-LABEL: store_test16: ; CHECK-NEXT: param i32, i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.const $push3=, 40{{$}} -; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} -; CHECK-NEXT: i32.store 0($pop4), $2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.const $push3=, 40{{$}} +; NPIC-NEXT: i32.add $push4=, $pop2, $pop3{{$}} +; NPIC-NEXT: i32.store 0($pop4), $2{{$}} ; CHECK-NEXT: return{{$}} define void @store_test16(i32* %p, i32 %n, i32 %i) { %add.ptr = getelementptr inbounds i32, i32* %p, i32 10 @@ -603,12 +619,12 @@ ; CHECK-LABEL: store_test17: ; CHECK-NEXT: param i32, i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.const $push3=, 40{{$}} -; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} -; CHECK-NEXT: i32.store 0($pop4), $2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.const $push3=, 40{{$}} +; NPIC-NEXT: i32.add $push4=, $pop2, $pop3{{$}} +; NPIC-NEXT: i32.store 0($pop4), $2{{$}} ; CHECK-NEXT: return{{$}} define void @store_test17(i32* %p, i32 %n, i32 %i) { %add = add nsw i32 %n, 10 @@ -619,10 +635,10 @@ ; CHECK-LABEL: store_test18: ; CHECK-NEXT: param i32, i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.store 40($pop2), $2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.store 40($pop2), $2{{$}} ; CHECK-NEXT: return{{$}} define void @store_test18(i32* %p, i32 %n, i32 %i) { %add.ptr = getelementptr inbounds i32, i32* %p, i32 %n @@ -633,12 +649,12 @@ ; CHECK-LABEL: store_test19: ; CHECK-NEXT: param i32, i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.const $push3=, 40{{$}} -; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} -; CHECK-NEXT: i32.store 0($pop4), $2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.const $push3=, 40{{$}} +; NPIC-NEXT: i32.add $push4=, $pop2, $pop3{{$}} +; NPIC-NEXT: i32.store 0($pop4), $2{{$}} ; CHECK-NEXT: return{{$}} define void @store_test19(i32* %p, i32 %n, i32 %i) { %add = add nsw i32 10, %n @@ -649,9 +665,9 @@ ; CHECK-LABEL: store_test20: ; CHECK-NEXT: param i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, -40{{$}} -; CHECK-NEXT: i32.add $push1=, $0, $pop0{{$}} -; CHECK-NEXT: i32.store 0($pop1), $1{{$}} +; NPIC-NEXT: i32.const $push0=, -40{{$}} +; NPIC-NEXT: i32.add $push1=, $0, $pop0{{$}} +; NPIC-NEXT: i32.store 0($pop1), $1{{$}} ; CHECK-NEXT: return{{$}} define void @store_test20(i32* %p, i32 %i) { %arrayidx = getelementptr inbounds i32, i32* %p, i32 -10 @@ -661,12 +677,12 @@ ; CHECK-LABEL: store_test21: ; CHECK-NEXT: param i32, i32, i32{{$}} -; CHECK-NEXT: i32.const $push0=, 2{{$}} -; CHECK-NEXT: i32.shl $push1=, $1, $pop0{{$}} -; CHECK-NEXT: i32.add $push2=, $0, $pop1{{$}} -; CHECK-NEXT: i32.const $push3=, -40{{$}} -; CHECK-NEXT: i32.add $push4=, $pop2, $pop3{{$}} -; CHECK-NEXT: i32.store 0($pop4), $2{{$}} +; NPIC-NEXT: i32.const $push0=, 2{{$}} +; NPIC-NEXT: i32.shl $push1=, $1, $pop0{{$}} +; NPIC-NEXT: i32.add $push2=, $0, $pop1{{$}} +; NPIC-NEXT: i32.const $push3=, -40{{$}} +; NPIC-NEXT: i32.add $push4=, $pop2, $pop3{{$}} +; NPIC-NEXT: i32.store 0($pop4), $2{{$}} ; CHECK-NEXT: return{{$}} define void @store_test21(i32* %p, i32 %n, i32 %i) { %add = add nsw i32 %n, -10 Index: test/CodeGen/WebAssembly/global-pic.ll =================================================================== --- /dev/null +++ test/CodeGen/WebAssembly/global-pic.ll @@ -0,0 +1,85 @@ +; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s -check-prefixes=NON-PIC +; RUN: llc < %s -asm-verbose=false -relocation-model=pic -fast-isel -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s -check-prefixes=PIC + +; Test that globals assemble as expected with -fPIC + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +@hidden_global = external hidden global i32 + +declare i32 @foo(); + +; For hidden symbols PIC code needs to offset all loads and stores +; by the value of the __memory_base global + +define i32 @load_hidden_global() { +; PIC-LABEL: load_hidden_global: +; PIC: get_global $push0=, __memory_base@GLOBAL +; PIC-NEXT: i32.load $push1=, hidden_global($pop0) +; PIC-NEXT: end_function + +; NON-PIC-LABEL: load_hidden_global: +; NON-PIC: i32.const $push0=, 0 +; NON-PIC-NEXT: i32.load $push1=, hidden_global($pop0) +; NON-PIC-NEXT: end_function + + %1 = load i32, i32* @hidden_global + ret i32 %1 +} + +; Store to a hidden global + +define void @store_hidden_global(i32 %n) { +; PIC-LABEL: store_hidden_global: +; PIC: get_global $push0=, __memory_base@GLOBAL +; PIC-NEXT: i32.store hidden_global($pop0), $0 +; PIC-NEXT: end_function + +; NON-PIC-LABEL: store_hidden_global: +; NON-PIC: i32.const $push0=, 0 +; NON-PIC-NEXT: i32.store hidden_global($pop0), $0 +; NON-PIC-NEXT: end_function + + store i32 %n, i32* @hidden_global + ret void +} + +; For non-hidden globals PIC code needs to call special rtld-created 'g$' +; functions to find the runtime offset. + +@external_global = external global i32 + +define i32 @load_external_global() { +; PIC-LABEL: load_external_global: +; PIC: i32.call $push0=, g$external_global@FUNCTION +; PIC-NEXT: i32.load $push1=, 0($pop0) +; PIC-NEXT: end_function + +; NON-PIC-LABEL: load_external_global: +; NON-PIC: i32.const $push0=, 0 +; NON-PIC-NEXT: i32.load $push1=, external_global($pop0) +; NON-PIC-NEXT: end_function + + %1 = load i32, i32* @external_global + ret i32 %1 +} + +; Store to a non-hidden global + +define void @store_external_global(i32 %n) { +; PIC-LABEL: store_external_global: +; PIC: i32.call $push0=, g$external_global@FUNCTION +; PIC-NEXT: i32.store 0($pop0), $0 +; PIC-NEXT: end_function + +; NON-PIC-LABEL: store_external_global: +; NON-PIC: i32.const $push0=, 0 +; NON-PIC-NEXT: i32.store external_global($pop0), $0 +; NON-PIC-NEXT: end_function + + store i32 %n, i32* @external_global + ret void +} + +; CHECK-PIC: .globaltype __memory_base, i32 Index: test/CodeGen/WebAssembly/indirect-import.ll =================================================================== --- test/CodeGen/WebAssembly/indirect-import.ll +++ test/CodeGen/WebAssembly/indirect-import.ll @@ -70,10 +70,10 @@ attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } -; CHECK: .functype extern_fd, f32, f64 +; CHECK: .functype extern_sret, void, i32 ; CHECK: .functype extern_vj, void, i64 +; CHECK: .functype extern_i128ret, void, i32, i64 +; CHECK: .functype extern_struct, void, i32 ; CHECK: .functype extern_v, void ; CHECK: .functype extern_ijidf, i32, i64, i32, f64, f32 -; CHECK: .functype extern_struct, void, i32 -; CHECK: .functype extern_sret, void, i32 -; CHECK: .functype extern_i128ret, void, i32, i64 +; CHECK: .functype extern_fd, f32, f64