setCondCodeAction(CC, T, Expand);
// Expand floating-point library function operators.
for (auto Op : {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOWI, ISD::FPOW,
- ISD::FREM})
+ ISD::FREM, ISD::FMA})
setOperationAction(Op, T, Expand);
// Note supported floating-point library function operators that otherwise
// default to expand.
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVTPtr, Expand);
+ setOperationAction(ISD::FrameIndex, MVT::i32, Custom);
+
// Expand these forms; we pattern-match the forms that we can handle in isel.
for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
for (auto Op : {ISD::BR_CC, ISD::SELECT_CC})
// - Floating-point extending loads.
// - Floating-point truncating stores.
// - i1 extending loads.
- setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f64, Expand);
+ setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
setTruncStoreAction(MVT::f64, MVT::f32, Expand);
for (auto T : MVT::integer_valuetypes())
for (auto Ext : {ISD::EXTLOAD, ISD::ZEXTLOAD, ISD::SEXTLOAD})
unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
if (BitWidth > 1 && BitWidth < 8)
BitWidth = 8;
+
+ if (BitWidth > 64) {
+ BitWidth = 64;
+ assert(BitWidth >= Log2_32_Ceil(VT.getSizeInBits()) &&
+ "64-bit shift counts ought to be enough for anyone");
+ }
+
MVT Result = MVT::getIntegerVT(BitWidth);
assert(Result != MVT::INVALID_SIMPLE_VALUE_TYPE &&
"Unable to represent scalar shift amount type");
return true;
}
+bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
+ const AddrMode &AM,
+ Type *Ty,
+ unsigned AS) const {
+ // WebAssembly offsets are added as unsigned without wrapping. The
+ // isLegalAddressingMode gives us no way to determine if wrapping could be
+ // happening, so we approximate this by accepting only non-negative offsets.
+ if (AM.BaseOffs < 0)
+ return false;
+
+ // WebAssembly has no scale register operands.
+ if (AM.Scale != 0)
+ return false;
+
+ // Everything else is legal.
+ return true;
+}
+
//===----------------------------------------------------------------------===//
// WebAssembly Lowering private implementation.
//===----------------------------------------------------------------------===//
unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
- auto NB = DAG.getConstant(NumBytes, DL, PtrVT, true);
- Chain = DAG.getCALLSEQ_START(Chain, NB, DL);
+ SDValue NB;
+ if (NumBytes) {
+ NB = DAG.getConstant(NumBytes, DL, PtrVT, true);
+ Chain = DAG.getCALLSEQ_START(Chain, NB, DL);
+ }
if (IsVarArg) {
// For non-fixed arguments, next emit stores to store the argument values
if (In.Flags.isInConsecutiveRegs())
fail(DL, DAG, "WebAssembly hasn't implemented cons regs return values");
if (In.Flags.isInConsecutiveRegsLast())
- fail(DL, DAG, "WebAssembly hasn't implemented cons regs last return values");
+ fail(DL, DAG,
+ "WebAssembly hasn't implemented cons regs last return values");
// Ignore In.getOrigAlign() because all our arguments are passed in
// registers.
Tys.push_back(In.VT);
Chain = Res.getValue(1);
}
- SDValue Unused = DAG.getUNDEF(PtrVT);
- Chain = DAG.getCALLSEQ_END(Chain, NB, Unused, SDValue(), DL);
+ if (NumBytes) {
+ SDValue Unused = DAG.getTargetConstant(0, DL, PtrVT);
+ Chain = DAG.getCALLSEQ_END(Chain, NB, Unused, SDValue(), DL);
+ }
return Chain;
}
default:
llvm_unreachable("unimplemented operation lowering");
return SDValue();
+ case ISD::FrameIndex:
+ return LowerFrameIndex(Op, DAG);
case ISD::GlobalAddress:
return LowerGlobalAddress(Op, DAG);
case ISD::ExternalSymbol:
}
}
+SDValue WebAssemblyTargetLowering::LowerFrameIndex(SDValue Op,
+ SelectionDAG &DAG) const {
+ int FI = cast<FrameIndexSDNode>(Op)->getIndex();
+ return DAG.getTargetFrameIndex(FI, Op.getValueType());
+}
+
SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
assert(GA->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
if (GA->getAddressSpace() != 0)
fail(DL, DAG, "WebAssembly only expects the 0 address space");
- return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
- DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT,
- GA->getOffset()));
+ return DAG.getNode(
+ WebAssemblyISD::Wrapper, DL, VT,
+ DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset()));
}
SDValue