| Index: IceInst.cpp
|
| diff --git a/IceInst.cpp b/IceInst.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..467153fb4080c2e818289762a8802c94ae469413
|
| --- /dev/null
|
| +++ b/IceInst.cpp
|
| @@ -0,0 +1,535 @@
|
| +/* Copyright 2014 The Native Client Authors. All rights reserved.
|
| + * Use of this source code is governed by a BSD-style license that can
|
| + * be found in the LICENSE file.
|
| + */
|
| +
|
| +#include "IceCfg.h"
|
| +#include "IceCfgNode.h"
|
| +#include "IceInst.h"
|
| +#include "IceOperand.h"
|
| +
|
| +IceInst::IceInst(IceCfg *Cfg, InstKind Kind, uint32_t MaxSrcs,
|
| + IceVariable *Dest)
|
| + : Kind(Kind), Deleted(false), HasSideEffects(false), Dest(Dest),
|
| + MaxSrcs(MaxSrcs), NumSrcs(0) {
|
| + Number = Cfg->newInstNumber();
|
| + Srcs = Cfg->allocateArrayOf<IceOperand *>(MaxSrcs);
|
| +}
|
| +
|
| +void IceInst::updateVars(IceCfgNode *Node) {
|
| + if (Dest)
|
| + Dest->setDefinition(this, Node);
|
| + for (uint32_t I = 0; I < getSrcSize(); ++I) {
|
| + getSrc(I)->setUse(this, Node);
|
| + }
|
| +}
|
| +
|
| +IceInstAlloca::IceInstAlloca(IceCfg *Cfg, IceOperand *ByteCount, uint32_t Align,
|
| + IceVariable *Dest)
|
| + : IceInst(Cfg, IceInst::Alloca, 1, Dest), Align(Align) {
|
| + addSource(ByteCount);
|
| +}
|
| +
|
| +IceInstArithmetic::IceInstArithmetic(IceCfg *Cfg, OpKind Op, IceVariable *Dest,
|
| + IceOperand *Source1, IceOperand *Source2)
|
| + : IceInst(Cfg, IceInst::Arithmetic, 2, Dest), Op(Op) {
|
| + addSource(Source1);
|
| + addSource(Source2);
|
| +}
|
| +
|
| +bool IceInstArithmetic::isCommutative(void) const {
|
| + switch (getOp()) {
|
| + case Add:
|
| + case Fadd:
|
| + case Mul:
|
| + case Fmul:
|
| + case And:
|
| + case Or:
|
| + case Xor:
|
| + return true;
|
| + default:
|
| + return false;
|
| + }
|
| +}
|
| +
|
| +IceInstAssign::IceInstAssign(IceCfg *Cfg, IceVariable *Dest, IceOperand *Source)
|
| + : IceInst(Cfg, IceInst::Assign, 1, Dest) {
|
| + addSource(Source);
|
| +}
|
| +
|
| +// If TargetTrue==TargetFalse, we turn it into an unconditional
|
| +// branch. This ensures that, along with the 'switch' instruction
|
| +// semantics, there is at most one edge from one node to another.
|
| +IceInstBr::IceInstBr(IceCfg *Cfg, IceOperand *Source, IceCfgNode *TargetTrue,
|
| + IceCfgNode *TargetFalse)
|
| + : IceInst(Cfg, IceInst::Br, 1, NULL), TargetFalse(TargetFalse),
|
| + TargetTrue(TargetTrue) {
|
| + if (TargetTrue == TargetFalse) {
|
| + TargetTrue = NULL; // turn into unconditional version
|
| + } else {
|
| + addSource(Source);
|
| + }
|
| +}
|
| +
|
| +IceInstBr::IceInstBr(IceCfg *Cfg, IceCfgNode *Target)
|
| + : IceInst(Cfg, IceInst::Br, 0, NULL), TargetFalse(Target),
|
| + TargetTrue(NULL) {}
|
| +
|
| +IceNodeList IceInstBr::getTerminatorEdges(void) const {
|
| + IceNodeList OutEdges;
|
| + OutEdges.push_back(TargetFalse);
|
| + if (TargetTrue)
|
| + OutEdges.push_back(TargetTrue);
|
| + return OutEdges;
|
| +}
|
| +
|
| +IceInstCast::IceInstCast(IceCfg *Cfg, OpKind CastKind, IceVariable *Dest,
|
| + IceOperand *Source)
|
| + : IceInst(Cfg, IceInst::Cast, 1, Dest), CastKind(CastKind) {
|
| + addSource(Source);
|
| +}
|
| +
|
| +IceInstFcmp::IceInstFcmp(IceCfg *Cfg, FCond Condition, IceVariable *Dest,
|
| + IceOperand *Source1, IceOperand *Source2)
|
| + : IceInst(Cfg, IceInst::Fcmp, 2, Dest), Condition(Condition) {
|
| + addSource(Source1);
|
| + addSource(Source2);
|
| +}
|
| +
|
| +IceInstIcmp::IceInstIcmp(IceCfg *Cfg, ICond Condition, IceVariable *Dest,
|
| + IceOperand *Source1, IceOperand *Source2)
|
| + : IceInst(Cfg, IceInst::Icmp, 2, Dest), Condition(Condition) {
|
| + addSource(Source1);
|
| + addSource(Source2);
|
| +}
|
| +
|
| +IceInstLoad::IceInstLoad(IceCfg *Cfg, IceVariable *Dest, IceOperand *SourceAddr)
|
| + : IceInst(Cfg, IceInst::Load, 1, Dest) {
|
| + addSource(SourceAddr);
|
| +}
|
| +
|
| +IceInstPhi::IceInstPhi(IceCfg *Cfg, uint32_t MaxSrcs, IceVariable *Dest)
|
| + : IceInst(Cfg, Phi, MaxSrcs, Dest) {
|
| + Labels = Cfg->allocateArrayOf<IceCfgNode *>(MaxSrcs);
|
| +}
|
| +
|
| +// TODO: A Switch instruction (and maybe others) can add duplicate
|
| +// edges. We may want to de-dup Phis and validate consistency (i.e.,
|
| +// the source operands are the same for duplicate edges), though it
|
| +// seems the current lowering code is OK with this situation.
|
| +void IceInstPhi::addArgument(IceOperand *Source, IceCfgNode *Label) {
|
| + Labels[getSrcSize()] = Label;
|
| + addSource(Source);
|
| +}
|
| +
|
| +IceInstRet::IceInstRet(IceCfg *Cfg, IceOperand *Source)
|
| + : IceInst(Cfg, Ret, Source ? 1 : 0, NULL) {
|
| + if (Source)
|
| + addSource(Source);
|
| +}
|
| +
|
| +IceInstSelect::IceInstSelect(IceCfg *Cfg, IceVariable *Dest,
|
| + IceOperand *Condition, IceOperand *SourceTrue,
|
| + IceOperand *SourceFalse)
|
| + : IceInst(Cfg, IceInst::Select, 3, Dest) {
|
| + assert(Condition->getType() == IceType_i1);
|
| + addSource(Condition);
|
| + addSource(SourceTrue);
|
| + addSource(SourceFalse);
|
| +}
|
| +
|
| +IceInstStore::IceInstStore(IceCfg *Cfg, IceOperand *Data, IceOperand *Addr)
|
| + : IceInst(Cfg, IceInst::Store, 2, NULL) {
|
| + addSource(Data);
|
| + addSource(Addr);
|
| +}
|
| +
|
| +IceInstSwitch::IceInstSwitch(IceCfg *Cfg, uint32_t NumCases, IceOperand *Source,
|
| + IceCfgNode *LabelDefault)
|
| + : IceInst(Cfg, IceInst::Switch, 1, NULL), LabelDefault(LabelDefault),
|
| + NumCases(NumCases) {
|
| + addSource(Source);
|
| + Values = Cfg->allocateArrayOf<uint64_t>(NumCases);
|
| + Labels = Cfg->allocateArrayOf<IceCfgNode *>(NumCases);
|
| + // Initialize in case buggy code doesn't set all entries
|
| + for (uint32_t I = 0; I < NumCases; ++I) {
|
| + Values[I] = 0;
|
| + Labels[I] = NULL;
|
| + }
|
| +}
|
| +
|
| +void IceInstSwitch::addBranch(uint32_t CaseIndex, uint64_t Value,
|
| + IceCfgNode *Label) {
|
| + assert(CaseIndex < NumCases);
|
| + Values[CaseIndex] = Value;
|
| + Labels[CaseIndex] = Label;
|
| +}
|
| +
|
| +IceNodeList IceInstSwitch::getTerminatorEdges(void) const {
|
| + IceNodeList OutEdges;
|
| + OutEdges.push_back(LabelDefault);
|
| + for (uint32_t I = 0; I < NumCases; ++I) {
|
| + OutEdges.push_back(Labels[I]);
|
| + }
|
| + return OutEdges;
|
| +}
|
| +
|
| +// ======================== Dump routines ======================== //
|
| +
|
| +IceOstream &operator<<(IceOstream &Str, const IceInst *I) {
|
| + if (!Str.isVerbose(IceV_Deleted) && (I->isDeleted()))
|
| + return Str;
|
| + if (Str.isVerbose(IceV_InstNumbers)) {
|
| + char buf[30];
|
| + int32_t Number = I->getNumber();
|
| + if (Number < 0)
|
| + sprintf(buf, "[XXX]");
|
| + else
|
| + sprintf(buf, "[%3d]", I->getNumber());
|
| + Str << buf;
|
| + }
|
| + Str << " ";
|
| + if (I->isDeleted())
|
| + Str << " //";
|
| + I->dump(Str);
|
| + Str << "\n";
|
| + return Str;
|
| +}
|
| +
|
| +void IceInst::dump(IceOstream &Str) const {
|
| + dumpDest(Str);
|
| + Str << " =~ ";
|
| + dumpSources(Str);
|
| +}
|
| +
|
| +void IceInst::dumpSources(IceOstream &Str) const {
|
| + for (uint32_t I = 0; I < getSrcSize(); ++I) {
|
| + if (I > 0)
|
| + Str << ", ";
|
| + Str << getSrc(I);
|
| + }
|
| +}
|
| +
|
| +void IceInst::dumpDest(IceOstream &Str) const {
|
| + if (getDest())
|
| + Str << getDest();
|
| +}
|
| +
|
| +void IceInstAlloca::dump(IceOstream &Str) const {
|
| + dumpDest(Str);
|
| + Str << " = alloca i8, i32 ";
|
| + Str << getSrc(0) << ", align " << Align;
|
| +}
|
| +
|
| +void IceInstArithmetic::dump(IceOstream &Str) const {
|
| + dumpDest(Str);
|
| + Str << " = ";
|
| + switch (getOp()) {
|
| + case Add:
|
| + Str << "add";
|
| + break;
|
| + case Fadd:
|
| + Str << "fadd";
|
| + break;
|
| + case Sub:
|
| + Str << "sub";
|
| + break;
|
| + case Fsub:
|
| + Str << "fsub";
|
| + break;
|
| + case Mul:
|
| + Str << "mul";
|
| + break;
|
| + case Fmul:
|
| + Str << "fmul";
|
| + break;
|
| + case Udiv:
|
| + Str << "udiv";
|
| + break;
|
| + case Sdiv:
|
| + Str << "sdiv";
|
| + break;
|
| + case Fdiv:
|
| + Str << "fdiv";
|
| + break;
|
| + case Urem:
|
| + Str << "urem";
|
| + break;
|
| + case Srem:
|
| + Str << "srem";
|
| + break;
|
| + case Frem:
|
| + Str << "frem";
|
| + break;
|
| + case Shl:
|
| + Str << "shl";
|
| + break;
|
| + case Lshr:
|
| + Str << "lshr";
|
| + break;
|
| + case Ashr:
|
| + Str << "ashr";
|
| + break;
|
| + case And:
|
| + Str << "and";
|
| + break;
|
| + case Or:
|
| + Str << "or";
|
| + break;
|
| + case Xor:
|
| + Str << "xor";
|
| + break;
|
| + }
|
| + Str << " " << getDest()->getType() << " ";
|
| + dumpSources(Str);
|
| +}
|
| +
|
| +void IceInstAssign::dump(IceOstream &Str) const {
|
| + dumpDest(Str);
|
| + Str << " = " << getDest()->getType() << " ";
|
| + dumpSources(Str);
|
| +}
|
| +
|
| +void IceInstBr::dump(IceOstream &Str) const {
|
| + dumpDest(Str);
|
| + Str << "br ";
|
| + if (!isUnconditional()) {
|
| + Str << "i1 " << getSrc(0) << ", label %" << getTargetTrue()->getName()
|
| + << ", ";
|
| + }
|
| + Str << "label %" << getTargetFalse()->getName();
|
| +}
|
| +
|
| +void IceInstCall::dump(IceOstream &Str) const {
|
| + if (getDest()) {
|
| + dumpDest(Str);
|
| + Str << " = ";
|
| + }
|
| + if (Tail)
|
| + Str << "tail ";
|
| + Str << "call ";
|
| + if (getDest())
|
| + Str << getDest()->getType();
|
| + else
|
| + Str << "void";
|
| + Str << " " << getCallTarget() << "(";
|
| + for (uint32_t I = 0; I < getNumArgs(); ++I) {
|
| + if (I > 0)
|
| + Str << ", ";
|
| + Str << getArg(I)->getType() << " " << getArg(I);
|
| + }
|
| + Str << ")";
|
| +}
|
| +
|
| +void IceInstCast::dump(IceOstream &Str) const {
|
| + dumpDest(Str);
|
| + Str << " = ";
|
| + switch (getCastKind()) {
|
| + default:
|
| + Str << "UNKNOWN";
|
| + assert(0);
|
| + break;
|
| + case Trunc:
|
| + Str << "trunc";
|
| + break;
|
| + case Zext:
|
| + Str << "zext";
|
| + break;
|
| + case Sext:
|
| + Str << "sext";
|
| + break;
|
| + case Fptrunc:
|
| + Str << "fptrunc";
|
| + break;
|
| + case Fpext:
|
| + Str << "fpext";
|
| + break;
|
| + case Fptoui:
|
| + Str << "fptoui";
|
| + break;
|
| + case Fptosi:
|
| + Str << "fptosi";
|
| + break;
|
| + case Uitofp:
|
| + Str << "uitofp";
|
| + break;
|
| + case Sitofp:
|
| + Str << "sitofp";
|
| + break;
|
| + }
|
| + Str << " " << getSrc(0)->getType() << " ";
|
| + dumpSources(Str);
|
| + Str << " to " << getDest()->getType();
|
| +}
|
| +
|
| +void IceInstIcmp::dump(IceOstream &Str) const {
|
| + dumpDest(Str);
|
| + Str << " = icmp ";
|
| + switch (getCondition()) {
|
| + case Eq:
|
| + Str << "eq";
|
| + break;
|
| + case Ne:
|
| + Str << "ne";
|
| + break;
|
| + case Ugt:
|
| + Str << "ugt";
|
| + break;
|
| + case Uge:
|
| + Str << "uge";
|
| + break;
|
| + case Ult:
|
| + Str << "ult";
|
| + break;
|
| + case Ule:
|
| + Str << "ule";
|
| + break;
|
| + case Sgt:
|
| + Str << "sgt";
|
| + break;
|
| + case Sge:
|
| + Str << "sge";
|
| + break;
|
| + case Slt:
|
| + Str << "slt";
|
| + break;
|
| + case Sle:
|
| + Str << "sle";
|
| + break;
|
| + }
|
| + Str << " " << getSrc(0)->getType() << " ";
|
| + dumpSources(Str);
|
| +}
|
| +
|
| +void IceInstFcmp::dump(IceOstream &Str) const {
|
| + dumpDest(Str);
|
| + Str << " = fcmp ";
|
| +
|
| + switch (getCondition()) {
|
| + case False:
|
| + Str << "false";
|
| + break;
|
| + case Oeq:
|
| + Str << "oeq";
|
| + break;
|
| + case Ogt:
|
| + Str << "ogt";
|
| + break;
|
| + case Oge:
|
| + Str << "oge";
|
| + break;
|
| + case Olt:
|
| + Str << "olt";
|
| + break;
|
| + case Ole:
|
| + Str << "ole";
|
| + break;
|
| + case One:
|
| + Str << "one";
|
| + break;
|
| + case Ord:
|
| + Str << "ord";
|
| + break;
|
| + case Ueq:
|
| + Str << "ueq";
|
| + break;
|
| + case Ugt:
|
| + Str << "ugt";
|
| + break;
|
| + case Uge:
|
| + Str << "uge";
|
| + break;
|
| + case Ult:
|
| + Str << "ult";
|
| + break;
|
| + case Ule:
|
| + Str << "ule";
|
| + break;
|
| + case Une:
|
| + Str << "une";
|
| + break;
|
| + case Uno:
|
| + Str << "uno";
|
| + break;
|
| + case True:
|
| + Str << "true";
|
| + break;
|
| + }
|
| + Str << " " << getSrc(0)->getType() << " ";
|
| + dumpSources(Str);
|
| +}
|
| +
|
| +void IceInstLoad::dump(IceOstream &Str) const {
|
| + dumpDest(Str);
|
| + IceType Type = getDest()->getType();
|
| + Str << " = load " << Type << "* ";
|
| + dumpSources(Str);
|
| + switch (Type) {
|
| + case IceType_f32:
|
| + Str << ", align 4";
|
| + break;
|
| + case IceType_f64:
|
| + Str << ", align 8";
|
| + break;
|
| + default:
|
| + Str << ", align 1";
|
| + break;
|
| + }
|
| +}
|
| +
|
| +void IceInstStore::dump(IceOstream &Str) const {
|
| + IceType Type = getData()->getType();
|
| + Str << "store " << Type << " " << getData() << ", " << Type << "* "
|
| + << getAddr() << ", align ";
|
| + switch (Type) {
|
| + case IceType_f32:
|
| + Str << "4";
|
| + break;
|
| + case IceType_f64:
|
| + Str << "8";
|
| + break;
|
| + default:
|
| + Str << "1";
|
| + break;
|
| + }
|
| +}
|
| +
|
| +void IceInstSwitch::dump(IceOstream &Str) const {
|
| + IceType Type = getSrc(0)->getType();
|
| + Str << "switch " << Type << " " << getSrc(0) << ", label %"
|
| + << getLabelDefault()->getName() << " [\n";
|
| + for (uint32_t I = 0; I < getNumCases(); ++I) {
|
| + Str << " " << Type << " " << getValue(I) << ", label %"
|
| + << getLabel(I)->getName() << "\n";
|
| + }
|
| + Str << " ]";
|
| +}
|
| +
|
| +void IceInstPhi::dump(IceOstream &Str) const {
|
| + dumpDest(Str);
|
| + Str << " = phi " << getDest()->getType() << " ";
|
| + for (uint32_t I = 0; I < getSrcSize(); ++I) {
|
| + if (I > 0)
|
| + Str << ", ";
|
| + Str << "[ " << getSrc(I) << ", %" << Labels[I]->getName() << " ]";
|
| + }
|
| +}
|
| +
|
| +void IceInstRet::dump(IceOstream &Str) const {
|
| + IceType Type = getSrcSize() == 0 ? IceType_void : getSrc(0)->getType();
|
| + Str << "ret " << Type;
|
| + if (getSrcSize()) {
|
| + Str << " ";
|
| + dumpSources(Str);
|
| + }
|
| +}
|
| +
|
| +void IceInstSelect::dump(IceOstream &Str) const {
|
| + dumpDest(Str);
|
| + IceOperand *Condition = getCondition();
|
| + IceOperand *TrueOp = getTrueOperand();
|
| + IceOperand *FalseOp = getFalseOperand();
|
| + Str << " = select " << Condition->getType() << " " << Condition << ", "
|
| + << TrueOp->getType() << " " << TrueOp << ", " << FalseOp->getType() << " "
|
| + << FalseOp;
|
| +}
|
|
|