summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Korobeynikov <asl@math.spbu.ru>2007-03-07 16:25:09 +0000
committerAnton Korobeynikov <asl@math.spbu.ru>2007-03-07 16:25:09 +0000
commitd0b82b301d700217a716526f9329bb031e0d6578 (patch)
treefffc3171424b94fce8316c50e47fdbc6c8cfdb1f
parent6a143590b3e283321af981abc4336f35efea2fed (diff)
downloadllvm-d0b82b301d700217a716526f9329bb031e0d6578.tar.gz
llvm-d0b82b301d700217a716526f9329bb031e0d6578.tar.bz2
llvm-d0b82b301d700217a716526f9329bb031e0d6578.tar.xz
Refactoring of formal parameter flags. Enable properly use of
zext/sext/aext stuff. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35008 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/CodeGen/SelectionDAGISel.h16
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h17
-rw-r--r--include/llvm/Target/TargetLowering.h5
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp11
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp51
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp3
-rw-r--r--lib/Target/Alpha/AlphaISelLowering.cpp6
-rw-r--r--lib/Target/IA64/IA64ISelLowering.cpp6
-rw-r--r--lib/Target/Sparc/SparcISelDAGToDAG.cpp6
-rw-r--r--lib/Target/TargetCallingConv.td2
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp14
-rw-r--r--utils/TableGen/CallingConvEmitter.cpp8
12 files changed, 73 insertions, 72 deletions
diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h
index 492e877f19..8557702018 100644
--- a/include/llvm/CodeGen/SelectionDAGISel.h
+++ b/include/llvm/CodeGen/SelectionDAGISel.h
@@ -30,21 +30,7 @@ namespace llvm {
class TargetLowering;
class FunctionLoweringInfo;
class HazardRecognizer;
-
- namespace SDISelParamFlags {
- enum Flags {
- NoFlagSet = 0,
- Signed = 1<<0,
- SignedOffs = 0,
- InReg = 1<<1,
- InRegOffs = 1,
- StructReturn = 1<<2,
- StructReturnOffs = 2,
- OrigAlignment = 0x1F<<27,
- OrigAlignmentOffs = 27
- };
- }
-
+
/// SelectionDAGISel - This is the common base class used for SelectionDAG-based
/// pattern-matching instruction selectors.
class SelectionDAGISel : public FunctionPass {
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 336a9279cc..d76e4b0813 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -48,11 +48,26 @@ struct SDVTList {
unsigned short NumVTs;
};
-
/// ISD namespace - This namespace contains an enum which represents all of the
/// SelectionDAG node types and value types.
///
namespace ISD {
+ namespace ParamFlags {
+ enum Flags {
+ NoFlagSet = 0,
+ ZExt = 1<<0, ///< Parameter should be zero extended
+ ZExtOffs = 0,
+ SExt = 1<<1, ///< Parameter should be sign extended
+ SExtOffs = 1,
+ InReg = 1<<2, ///< Parameter should be passed in register
+ InRegOffs = 2,
+ StructReturn = 1<<3, ///< Hidden struct-return pointer
+ StructReturnOffs = 3,
+ OrigAlignment = 0x1F<<27,
+ OrigAlignmentOffs = 27
+ };
+ }
+
//===--------------------------------------------------------------------===//
/// ISD::NodeType enum - This enum defines all of the operators valid in a
/// SelectionDAG.
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 5aae2583ce..fa67e0cb89 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -765,11 +765,12 @@ public:
struct ArgListEntry {
SDOperand Node;
const Type* Ty;
- bool isSigned;
+ bool isSExt;
+ bool isZExt;
bool isInReg;
bool isSRet;
- ArgListEntry():isSigned(false), isInReg(false), isSRet(false) { };
+ ArgListEntry():isSExt(false), isZExt(false), isInReg(false), isSRet(false) { };
};
typedef std::vector<ArgListEntry> ArgListTy;
virtual std::pair<SDOperand, SDOperand>
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 8c90cfb6da..0e1f0b9687 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -2242,8 +2242,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
const char *FnName = 0;
if (Node->getOpcode() == ISD::MEMSET) {
- Entry.Node = Tmp2; Entry.isSigned = false; Entry.Ty = IntPtrTy;
- Entry.isInReg = false; Entry.isSRet = false;
+ Entry.Node = Tmp2; Entry.Ty = IntPtrTy;
Args.push_back(Entry);
// Extend the (previously legalized) ubyte argument to be an int value
// for the call.
@@ -2251,17 +2250,15 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
Tmp3 = DAG.getNode(ISD::TRUNCATE, MVT::i32, Tmp3);
else
Tmp3 = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Tmp3);
- Entry.Node = Tmp3; Entry.Ty = Type::Int32Ty; Entry.isSigned = true;
- Entry.isInReg = false; Entry.isSRet = false;
+ Entry.Node = Tmp3; Entry.Ty = Type::Int32Ty; Entry.isSExt = true;
Args.push_back(Entry);
- Entry.Node = Tmp4; Entry.Ty = IntPtrTy; Entry.isSigned = false;
+ Entry.Node = Tmp4; Entry.Ty = IntPtrTy; Entry.isSExt = false;
Args.push_back(Entry);
FnName = "memset";
} else if (Node->getOpcode() == ISD::MEMCPY ||
Node->getOpcode() == ISD::MEMMOVE) {
Entry.Ty = IntPtrTy;
- Entry.isSigned = false; Entry.isInReg = false; Entry.isSRet = false;
Entry.Node = Tmp2; Args.push_back(Entry);
Entry.Node = Tmp3; Args.push_back(Entry);
Entry.Node = Tmp4; Args.push_back(Entry);
@@ -4228,7 +4225,7 @@ SDOperand SelectionDAGLegalize::ExpandLibCall(const char *Name, SDNode *Node,
MVT::ValueType ArgVT = Node->getOperand(i).getValueType();
const Type *ArgTy = MVT::getTypeForValueType(ArgVT);
Entry.Node = Node->getOperand(i); Entry.Ty = ArgTy;
- Entry.isSigned = isSigned; Entry.isInReg = false; Entry.isSRet = false;
+ Entry.isSExt = isSigned;
Args.push_back(Entry);
}
SDOperand Callee = DAG.getExternalSymbol(Name, TLI.getPointerTy());
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index f302202f56..f833c12504 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -2279,7 +2279,8 @@ void SelectionDAGLowering::LowerCallTo(Instruction &I,
Value *Arg = I.getOperand(i);
SDOperand ArgNode = getValue(Arg);
Entry.Node = ArgNode; Entry.Ty = Arg->getType();
- Entry.isSigned = FTy->paramHasAttr(i, FunctionType::SExtAttribute);
+ Entry.isSExt = FTy->paramHasAttr(i, FunctionType::SExtAttribute);
+ Entry.isZExt = FTy->paramHasAttr(i, FunctionType::ZExtAttribute);
Entry.isInReg = FTy->paramHasAttr(i, FunctionType::InRegAttribute);
Entry.isSRet = FTy->paramHasAttr(i, FunctionType::StructRetAttribute);
Args.push_back(Entry);
@@ -2983,9 +2984,6 @@ void SelectionDAGLowering::visitMalloc(MallocInst &I) {
TargetLowering::ArgListEntry Entry;
Entry.Node = Src;
Entry.Ty = TLI.getTargetData()->getIntPtrType();
- Entry.isSigned = false;
- Entry.isInReg = false;
- Entry.isSRet = false;
Args.push_back(Entry);
std::pair<SDOperand,SDOperand> Result =
@@ -3001,9 +2999,6 @@ void SelectionDAGLowering::visitFree(FreeInst &I) {
TargetLowering::ArgListEntry Entry;
Entry.Node = getValue(I.getOperand(0));
Entry.Ty = TLI.getTargetData()->getIntPtrType();
- Entry.isSigned = false;
- Entry.isInReg = false;
- Entry.isSRet = false;
Args.push_back(Entry);
MVT::ValueType IntPtr = TLI.getPointerTy();
std::pair<SDOperand,SDOperand> Result =
@@ -3099,21 +3094,21 @@ TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end();
I != E; ++I, ++j) {
MVT::ValueType VT = getValueType(I->getType());
- unsigned Flags = SDISelParamFlags::NoFlagSet;
+ unsigned Flags = ISD::ParamFlags::NoFlagSet;
unsigned OriginalAlignment =
getTargetData()->getABITypeAlignment(I->getType());
// FIXME: Distinguish between a formal with no [sz]ext attribute from one
// that is zero extended!
if (FTy->paramHasAttr(j, FunctionType::ZExtAttribute))
- Flags &= ~(SDISelParamFlags::Signed);
+ Flags &= ~(ISD::ParamFlags::SExt);
if (FTy->paramHasAttr(j, FunctionType::SExtAttribute))
- Flags |= SDISelParamFlags::Signed;
+ Flags |= ISD::ParamFlags::SExt;
if (FTy->paramHasAttr(j, FunctionType::InRegAttribute))
- Flags |= SDISelParamFlags::InReg;
+ Flags |= ISD::ParamFlags::InReg;
if (FTy->paramHasAttr(j, FunctionType::StructRetAttribute))
- Flags |= SDISelParamFlags::StructReturn;
- Flags |= (OriginalAlignment << SDISelParamFlags::OrigAlignmentOffs);
+ Flags |= ISD::ParamFlags::StructReturn;
+ Flags |= (OriginalAlignment << ISD::ParamFlags::OrigAlignmentOffs);
switch (getTypeAction(VT)) {
default: assert(0 && "Unknown type action!");
@@ -3136,8 +3131,8 @@ TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
RetVals.push_back(NVT);
// if it isn't first piece, alignment must be 1
if (i > 0)
- Flags = (Flags & (~SDISelParamFlags::OrigAlignment)) |
- (1 << SDISelParamFlags::OrigAlignmentOffs);
+ Flags = (Flags & (~ISD::ParamFlags::OrigAlignment)) |
+ (1 << ISD::ParamFlags::OrigAlignmentOffs);
Ops.push_back(DAG.getConstant(Flags, MVT::i32));
}
} else {
@@ -3246,8 +3241,8 @@ static void ExpandScalarCallArgs(MVT::ValueType VT, SDOperand Arg,
if (TLI.getTypeAction(VT) != TargetLowering::Expand) {
// if it isn't first piece, alignment must be 1
if (!isFirst)
- Flags = (Flags & (~SDISelParamFlags::OrigAlignment)) |
- (1 << SDISelParamFlags::OrigAlignmentOffs);
+ Flags = (Flags & (~ISD::ParamFlags::OrigAlignment)) |
+ (1 << ISD::ParamFlags::OrigAlignmentOffs);
Ops.push_back(Arg);
Ops.push_back(DAG.getConstant(Flags, MVT::i32));
return;
@@ -3294,17 +3289,19 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
MVT::ValueType VT = getValueType(Args[i].Ty);
SDOperand Op = Args[i].Node;
- unsigned Flags = SDISelParamFlags::NoFlagSet;
+ unsigned Flags = ISD::ParamFlags::NoFlagSet;
unsigned OriginalAlignment =
getTargetData()->getABITypeAlignment(Args[i].Ty);
- if (Args[i].isSigned)
- Flags |= SDISelParamFlags::Signed;
+ if (Args[i].isSExt)
+ Flags |= ISD::ParamFlags::SExt;
+ if (Args[i].isZExt)
+ Flags |= ISD::ParamFlags::ZExt;
if (Args[i].isInReg)
- Flags |= SDISelParamFlags::InReg;
+ Flags |= ISD::ParamFlags::InReg;
if (Args[i].isSRet)
- Flags |= SDISelParamFlags::StructReturn;
- Flags |= OriginalAlignment << SDISelParamFlags::OrigAlignmentOffs;
+ Flags |= ISD::ParamFlags::StructReturn;
+ Flags |= OriginalAlignment << ISD::ParamFlags::OrigAlignmentOffs;
switch (getTypeAction(VT)) {
default: assert(0 && "Unknown type action!");
@@ -3314,7 +3311,13 @@ TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
break;
case Promote:
if (MVT::isInteger(VT)) {
- unsigned ExtOp = Args[i].isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
+ unsigned ExtOp;
+ if (Args[i].isSExt)
+ ExtOp = ISD::SIGN_EXTEND;
+ else if (Args[i].isZExt)
+ ExtOp = ISD::ZERO_EXTEND;
+ else
+ ExtOp = ISD::ANY_EXTEND;
Op = DAG.getNode(ExtOp, getTypeToTransformTo(VT), Op);
} else {
assert(MVT::isFloatingPoint(VT) && "Not int or FP?");
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index 88c6ad01d1..f111d8786b 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -27,7 +27,6 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/SelectionDAG.h"
-#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/ADT/VectorExtras.h"
@@ -347,7 +346,7 @@ HowToPassArgument(MVT::ValueType ObjectVT, unsigned NumGPRs,
NeededGPRs = 0;
StackPad = 0;
GPRPad = 0;
- unsigned align = (Flags >> SDISelParamFlags::OrigAlignmentOffs);
+ unsigned align = (Flags >> ISD::ParamFlags::OrigAlignmentOffs);
GPRPad = NumGPRs % ((align + 3)/4);
StackPad = StackOffset % align;
unsigned firstGPR = NumGPRs + GPRPad;
diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp
index 1e7c79f982..e8ae5a3e35 100644
--- a/lib/Target/Alpha/AlphaISelLowering.cpp
+++ b/lib/Target/Alpha/AlphaISelLowering.cpp
@@ -337,10 +337,12 @@ AlphaTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
case MVT::i32:
// Promote the integer to 64 bits. If the input type is signed use a
// sign extend, otherwise use a zero extend.
- if (Args[i].isSigned)
+ if (Args[i].isSExt)
Args[i].Node = DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].Node);
- else
+ else if (Args[i].isZExt)
Args[i].Node = DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].Node);
+ else
+ Args[i].Node = DAG.getNode(ISD::ANY_EXTEND, MVT::i64, Args[i].Node);
break;
case MVT::i64:
case MVT::f64:
diff --git a/lib/Target/IA64/IA64ISelLowering.cpp b/lib/Target/IA64/IA64ISelLowering.cpp
index 1c7c51db0d..4bd7cba4b3 100644
--- a/lib/Target/IA64/IA64ISelLowering.cpp
+++ b/lib/Target/IA64/IA64ISelLowering.cpp
@@ -341,9 +341,11 @@ IA64TargetLowering::LowerCallTo(SDOperand Chain,
case MVT::i32: {
//promote to 64-bits, sign/zero extending based on type
//of the argument
- ISD::NodeType ExtendKind = ISD::ZERO_EXTEND;
- if (Args[i].isSigned)
+ ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
+ if (Args[i].isSExt)
ExtendKind = ISD::SIGN_EXTEND;
+ else if (Args[i].isZExt)
+ ExtendKind = ISD::ZERO_EXTEND;
Val = DAG.getNode(ExtendKind, MVT::i64, Val);
// XXX: fall through
}
diff --git a/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/lib/Target/Sparc/SparcISelDAGToDAG.cpp
index 647007e86b..7275ce652a 100644
--- a/lib/Target/Sparc/SparcISelDAGToDAG.cpp
+++ b/lib/Target/Sparc/SparcISelDAGToDAG.cpp
@@ -516,9 +516,11 @@ SparcTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
case MVT::i16: {
// Promote the integer to 32-bits. If the input type is signed, use a
// sign extend, otherwise use a zero extend.
- ISD::NodeType ExtendKind = ISD::ZERO_EXTEND;
- if (Args[i].isSigned)
+ ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
+ if (Args[i].isSExt)
ExtendKind = ISD::SIGN_EXTEND;
+ else if (Args[i].isZExt)
+ ExtendKind = ISD::ZERO_EXTEND;
Val = DAG.getNode(ExtendKind, MVT::i32, Val);
// FALL THROUGH
}
diff --git a/lib/Target/TargetCallingConv.td b/lib/Target/TargetCallingConv.td
index 3f71a1de2b..b91627ed2b 100644
--- a/lib/Target/TargetCallingConv.td
+++ b/lib/Target/TargetCallingConv.td
@@ -38,7 +38,7 @@ class CCIfCC<string CC, CCAction A>
/// CCIfInReg - If this argument is marked with the 'inreg' attribute, apply
/// the specified action.
-class CCIfInReg<CCAction A> : CCIf<"ArgFlags & SDISelParamFlags::InReg", A> {}
+class CCIfInReg<CCAction A> : CCIf<"ArgFlags & ISD::ParamFlags::InReg", A> {}
/// CCAssignToReg - This action matches if there is a register in the specified
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 9bcff7acb1..1d2c623216 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -29,7 +29,6 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/SelectionDAG.h"
-#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetOptions.h"
@@ -677,7 +676,7 @@ SDOperand X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG,
// If this is an sret function, the return should pop the hidden pointer.
if (NumArgs &&
(cast<ConstantSDNode>(Op.getOperand(3))->getValue() &
- SDISelParamFlags::StructReturn))
+ ISD::ParamFlags::StructReturn))
BytesToPopOnReturn = 4;
BytesCallerReserves = StackSize;
@@ -751,7 +750,7 @@ SDOperand X86TargetLowering::LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG,
// If the first argument is an sret pointer, remember it.
bool isSRet = NumOps &&
(cast<ConstantSDNode>(Op.getOperand(6))->getValue() &
- SDISelParamFlags::StructReturn);
+ ISD::ParamFlags::StructReturn);
if (!MemOpChains.empty())
Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
@@ -3408,16 +3407,10 @@ SDOperand X86TargetLowering::LowerMEMSET(SDOperand Op, SelectionDAG &DAG) {
TargetLowering::ArgListEntry Entry;
Entry.Node = Op.getOperand(1);
Entry.Ty = IntPtrTy;
- Entry.isSigned = false;
- Entry.isInReg = false;
- Entry.isSRet = false;
Args.push_back(Entry);
// Extend the unsigned i8 argument to be an int value for the call.
Entry.Node = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Op.getOperand(2));
Entry.Ty = IntPtrTy;
- Entry.isSigned = false;
- Entry.isInReg = false;
- Entry.isSRet = false;
Args.push_back(Entry);
Entry.Node = Op.getOperand(3);
Args.push_back(Entry);
@@ -3568,9 +3561,6 @@ SDOperand X86TargetLowering::LowerMEMCPY(SDOperand Op, SelectionDAG &DAG) {
TargetLowering::ArgListTy Args;
TargetLowering::ArgListEntry Entry;
Entry.Ty = getTargetData()->getIntPtrType();
- Entry.isSigned = false;
- Entry.isInReg = false;
- Entry.isSRet = false;
Entry.Node = Op.getOperand(1); Args.push_back(Entry);
Entry.Node = Op.getOperand(2); Args.push_back(Entry);
Entry.Node = Op.getOperand(3); Args.push_back(Entry);
diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp
index 97eeeb3527..ae7dc91fc7 100644
--- a/utils/TableGen/CallingConvEmitter.cpp
+++ b/utils/TableGen/CallingConvEmitter.cpp
@@ -123,8 +123,12 @@ void CallingConvEmitter::EmitAction(Record *Action,
} else if (Action->isSubClassOf("CCPromoteToType")) {
Record *DestTy = Action->getValueAsDef("DestTy");
O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
- O << IndentStr << "LocInfo = (ArgFlags & SDISelParamFlags::Signed) ? \n"
- << IndentStr << IndentStr << "CCValAssign::SExt : CCValAssign::ZExt;\n";
+ O << IndentStr << "if (ArgFlags & ISD::ParamFlags::SExt)\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n"
+ << IndentStr << "else if (ArgFlags & ISD::ParamFlags::ZExt)\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n"
+ << IndentStr << "else\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n";
} else {
Action->dump();
throw "Unknown CCAction!";