[WebAssembly] Support non-legal argument and return types.
llvm-svn: 252687
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index d813367..899e768a 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -252,13 +252,8 @@
fail(DL, DAG, "WebAssembly doesn't support tail call yet");
CLI.IsTailCall = false;
- SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
- bool IsStructRet = (Outs.empty()) ? false : Outs[0].Flags.isSRet();
- if (IsStructRet)
- fail(DL, DAG, "WebAssembly doesn't support struct return yet");
-
SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
if (Ins.size() > 1)
fail(DL, DAG, "WebAssembly doesn't support more than 1 returned value yet");
@@ -316,6 +311,7 @@
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<SDValue> &OutVals, SDLoc DL,
SelectionDAG &DAG) const {
+ MachineFunction &MF = DAG.getMachineFunction();
assert(Outs.size() <= 1 && "WebAssembly can only return up to one value");
if (CallConv != CallingConv::C)
@@ -327,6 +323,33 @@
RetOps.append(OutVals.begin(), OutVals.end());
Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, RetOps);
+ // Record the number and types of the return values.
+ for (const ISD::OutputArg &Out : Outs) {
+ if (Out.Flags.isZExt())
+ fail(DL, DAG, "WebAssembly hasn't implemented zext results");
+ if (Out.Flags.isSExt())
+ fail(DL, DAG, "WebAssembly hasn't implemented sext results");
+ if (Out.Flags.isInReg())
+ fail(DL, DAG, "WebAssembly hasn't implemented inreg results");
+ if (Out.Flags.isSRet())
+ fail(DL, DAG, "WebAssembly hasn't implemented sret results");
+ if (Out.Flags.isByVal())
+ fail(DL, DAG, "WebAssembly hasn't implemented byval results");
+ if (Out.Flags.isInAlloca())
+ fail(DL, DAG, "WebAssembly hasn't implemented inalloca results");
+ if (Out.Flags.isNest())
+ fail(DL, DAG, "WebAssembly hasn't implemented nest results");
+ if (Out.Flags.isReturned())
+ fail(DL, DAG, "WebAssembly hasn't implemented returned results");
+ if (Out.Flags.isInConsecutiveRegs())
+ fail(DL, DAG, "WebAssembly hasn't implemented cons regs results");
+ if (Out.Flags.isInConsecutiveRegsLast())
+ fail(DL, DAG, "WebAssembly hasn't implemented cons regs last results");
+ if (!Out.IsFixed)
+ fail(DL, DAG, "WebAssembly doesn't support non-fixed results yet");
+ MF.getInfo<WebAssemblyFunctionInfo>()->addResult(Out.VT);
+ }
+
return Chain;
}
@@ -340,8 +363,6 @@
fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
if (IsVarArg)
fail(DL, DAG, "WebAssembly doesn't support varargs yet");
- if (MF.getFunction()->hasStructRetAttr())
- fail(DL, DAG, "WebAssembly doesn't support struct return yet");
unsigned ArgNo = 0;
for (const ISD::InputArg &In : Ins) {
@@ -365,21 +386,18 @@
fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
if (In.Flags.isInConsecutiveRegsLast())
fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
- if (In.Flags.isSplit())
- fail(DL, DAG, "WebAssembly hasn't implemented split arguments");
// FIXME Do something with In.getOrigAlign()?
InVals.push_back(
In.Used
? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
DAG.getTargetConstant(ArgNo, DL, MVT::i32))
: DAG.getNode(ISD::UNDEF, DL, In.VT));
+
+ // Record the number and types of arguments.
+ MF.getInfo<WebAssemblyFunctionInfo>()->addParam(In.VT);
++ArgNo;
}
- // Record the number of arguments, since argument indices and local variable
- // indices are in the same index space.
- MF.getInfo<WebAssemblyFunctionInfo>()->setNumArguments(ArgNo);
-
return Chain;
}