Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===// | 1 //===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file implements the Cfg class, including constant pool | 10 // This file implements the Cfg class, including constant pool |
| 11 // management. | 11 // management. |
| 12 // | 12 // |
| 13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
| 14 | 14 |
| 15 #include "IceCfg.h" | 15 #include "IceCfg.h" |
| 16 #include "IceCfgNode.h" | 16 #include "IceCfgNode.h" |
| 17 #include "IceDefs.h" | 17 #include "IceDefs.h" |
| 18 #include "IceInst.h" | 18 #include "IceInst.h" |
| 19 #include "IceOperand.h" | 19 #include "IceOperand.h" |
| 20 #include "IceTargetLowering.h" | |
| 20 | 21 |
| 21 namespace Ice { | 22 namespace Ice { |
| 22 | 23 |
| 23 Cfg::Cfg(GlobalContext *Ctx) | 24 Cfg::Cfg(GlobalContext *Ctx) |
| 24 : Ctx(Ctx), FunctionName(""), ReturnType(IceType_void), | 25 : Ctx(Ctx), FunctionName(""), ReturnType(IceType_void), |
| 25 IsInternalLinkage(false), HasError(false), ErrorMessage(""), Entry(NULL), | 26 IsInternalLinkage(false), HasError(false), ErrorMessage(""), Entry(NULL), |
| 26 NextInstNumber(1), CurrentNode(NULL) {} | 27 NextInstNumber(1), |
| 28 Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)), | |
| 29 CurrentNode(NULL) {} | |
| 27 | 30 |
| 28 Cfg::~Cfg() {} | 31 Cfg::~Cfg() {} |
| 29 | 32 |
| 30 void Cfg::setError(const IceString &Message) { | 33 void Cfg::setError(const IceString &Message) { |
| 31 HasError = true; | 34 HasError = true; |
| 32 ErrorMessage = Message; | 35 ErrorMessage = Message; |
| 33 Ctx->getStrDump() << "ICE translation error: " << ErrorMessage << "\n"; | 36 Ctx->getStrDump() << "ICE translation error: " << ErrorMessage << "\n"; |
| 34 } | 37 } |
| 35 | 38 |
| 36 CfgNode *Cfg::makeNode(const IceString &Name) { | 39 CfgNode *Cfg::makeNode(const IceString &Name) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 47 SizeT Index = Variables.size(); | 50 SizeT Index = Variables.size(); |
| 48 Variables.push_back(Variable::create(this, Ty, Node, Index, Name)); | 51 Variables.push_back(Variable::create(this, Ty, Node, Index, Name)); |
| 49 return Variables[Index]; | 52 return Variables[Index]; |
| 50 } | 53 } |
| 51 | 54 |
| 52 void Cfg::addArg(Variable *Arg) { | 55 void Cfg::addArg(Variable *Arg) { |
| 53 Arg->setIsArg(this); | 56 Arg->setIsArg(this); |
| 54 Args.push_back(Arg); | 57 Args.push_back(Arg); |
| 55 } | 58 } |
| 56 | 59 |
| 60 // Returns whether the stack frame layout has been computed yet. This | |
| 61 // is used for dumping the stack frame location of Variables. | |
| 62 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); } | |
| 63 | |
| 64 void Cfg::translate() { | |
| 65 Ostream &Str = Ctx->getStrDump(); | |
| 66 if (hasError()) | |
| 67 return; | |
| 68 | |
| 69 if (Ctx->isVerbose()) | |
| 70 Str << "================ Initial CFG ================\n"; | |
| 71 dump(); | |
|
jvoung (off chromium)
2014/05/15 23:47:34
Is the dump() meant to be within the isVerbose() t
Jim Stichnoth
2014/05/17 14:14:32
It was intentional, but it looks like a good idea
| |
| 72 | |
| 73 Timer T_translate; | |
| 74 // The set of translation passes and their order are determined by | |
| 75 // the target. | |
| 76 getTarget()->translate(); | |
| 77 T_translate.printElapsedUs(getContext(), "translate()"); | |
| 78 | |
| 79 if (Ctx->isVerbose()) | |
| 80 Str << "================ Final output ================\n"; | |
| 81 dump(); | |
| 82 } | |
| 83 | |
| 57 void Cfg::computePredecessors() { | 84 void Cfg::computePredecessors() { |
| 58 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 85 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
| 59 (*I)->computePredecessors(); | 86 (*I)->computePredecessors(); |
| 60 } | 87 } |
| 61 } | 88 } |
| 62 | 89 |
| 90 // placePhiLoads() must be called before placePhiStores(). | |
| 91 void Cfg::placePhiLoads() { | |
| 92 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | |
| 93 (*I)->placePhiLoads(); | |
| 94 } | |
| 95 } | |
| 96 | |
| 97 // placePhiStores() must be called after placePhiLoads(). | |
| 98 void Cfg::placePhiStores() { | |
| 99 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | |
| 100 (*I)->placePhiStores(); | |
| 101 } | |
| 102 } | |
| 103 | |
| 104 void Cfg::deletePhis() { | |
| 105 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | |
| 106 (*I)->deletePhis(); | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 void Cfg::genCode() { | |
| 111 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | |
| 112 (*I)->genCode(); | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 // Compute the stack frame layout. | |
| 117 void Cfg::genFrame() { | |
| 118 getTarget()->addProlog(Entry); | |
| 119 // TODO: Consider folding epilog generation into the final | |
| 120 // emission/assembly pass to avoid an extra iteration over the node | |
| 121 // list. Or keep a separate list of exit nodes. | |
| 122 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | |
| 123 CfgNode *Node = *I; | |
| 124 if (Node->getHasReturn()) | |
| 125 getTarget()->addEpilog(Node); | |
| 126 } | |
| 127 } | |
| 128 | |
| 63 // ======================== Dump routines ======================== // | 129 // ======================== Dump routines ======================== // |
| 64 | 130 |
| 131 void Cfg::emit() { | |
| 132 Ostream &Str = Ctx->getStrEmit(); | |
| 133 Timer T_emit; | |
| 134 if (!Ctx->testAndSetHasEmittedFirstMethod()) { | |
| 135 // Print a helpful command for assembling the output. | |
| 136 // TODO: have the Target emit the header | |
| 137 // TODO: need a per-file emit in addition to per-CFG | |
| 138 Str << "# $LLVM_BIN_PATH/llvm-mc" | |
| 139 << " -arch=x86" | |
| 140 << " -x86-asm-syntax=intel" | |
| 141 << " -filetype=obj" | |
| 142 << " -o=MyObj.o" | |
| 143 << "\n\n"; | |
| 144 } | |
| 145 Str << "\t.text\n"; | |
| 146 if (!getInternal()) { | |
| 147 IceString MangledName = getContext()->mangleName(getFunctionName()); | |
| 148 Str << "\t.globl\t" << MangledName << "\n"; | |
| 149 Str << "\t.type\t" << MangledName << ",@function\n"; | |
| 150 } | |
| 151 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; | |
| 152 ++I) { | |
| 153 (*I)->emit(this); | |
| 154 } | |
| 155 Str << "\n"; | |
| 156 T_emit.printElapsedUs(Ctx, "emit()"); | |
| 157 } | |
| 158 | |
| 65 void Cfg::dump() { | 159 void Cfg::dump() { |
| 66 Ostream &Str = Ctx->getStrDump(); | 160 Ostream &Str = Ctx->getStrDump(); |
| 67 setCurrentNode(getEntryNode()); | 161 setCurrentNode(getEntryNode()); |
| 68 // Print function name+args | 162 // Print function name+args |
| 69 if (getContext()->isVerbose(IceV_Instructions)) { | 163 if (getContext()->isVerbose(IceV_Instructions)) { |
| 70 Str << "define "; | 164 Str << "define "; |
| 71 if (getInternal()) | 165 if (getInternal()) |
| 72 Str << "internal "; | 166 Str << "internal "; |
| 73 Str << ReturnType << " @" << getFunctionName() << "("; | 167 Str << ReturnType << " @" << getFunctionName() << "("; |
| 74 for (SizeT i = 0; i < Args.size(); ++i) { | 168 for (SizeT i = 0; i < Args.size(); ++i) { |
| 75 if (i > 0) | 169 if (i > 0) |
| 76 Str << ", "; | 170 Str << ", "; |
| 77 Str << Args[i]->getType() << " "; | 171 Str << Args[i]->getType() << " "; |
| 78 Args[i]->dump(this); | 172 Args[i]->dump(this); |
| 79 } | 173 } |
| 80 Str << ") {\n"; | 174 Str << ") {\n"; |
| 81 } | 175 } |
| 82 setCurrentNode(NULL); | 176 setCurrentNode(NULL); |
| 83 // Print each basic block | 177 // Print each basic block |
| 84 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; | 178 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; |
| 85 ++I) { | 179 ++I) { |
| 86 (*I)->dump(this); | 180 (*I)->dump(this); |
| 87 } | 181 } |
| 88 if (getContext()->isVerbose(IceV_Instructions)) { | 182 if (getContext()->isVerbose(IceV_Instructions)) { |
| 89 Str << "}\n"; | 183 Str << "}\n"; |
| 90 } | 184 } |
| 91 } | 185 } |
| 92 | 186 |
| 93 } // end of namespace Ice | 187 } // end of namespace Ice |
| OLD | NEW |