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 { | |
| 63 return getTarget()->hasComputedFrame(); | |
| 64 } | |
| 65 | |
| 66 void Cfg::translate() { | |
| 67 Ostream &Str = Ctx->getStrDump(); | |
| 68 if (hasError()) | |
| 69 return; | |
| 70 | |
| 71 if (Ctx->isVerbose()) | |
| 72 Str << "================ Initial CFG ================\n"; | |
| 73 dump(); | |
| 74 | |
| 75 Timer T_translate; | |
| 76 // The set of translation passes and their order are determined by | |
| 77 // the target. | |
| 78 getTarget()->translate(); | |
| 79 T_translate.printElapsedUs(getContext(), "translate()"); | |
| 80 | |
| 81 if (Ctx->isVerbose()) | |
| 82 Str << "================ Final output ================\n"; | |
| 83 dump(); | |
| 84 } | |
| 85 | |
| 57 void Cfg::computePredecessors() { | 86 void Cfg::computePredecessors() { |
| 58 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | 87 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { |
| 59 (*I)->computePredecessors(); | 88 (*I)->computePredecessors(); |
| 60 } | 89 } |
| 61 } | 90 } |
| 62 | 91 |
| 92 // placePhiLoads() must be called before placePhiStores(). | |
|
JF
2014/05/04 23:54:58
Are they always called one after the other? Could
Jim Stichnoth
2014/05/05 07:03:55
I assume you mean a single loop over Nodes, with l
| |
| 93 void Cfg::placePhiLoads() { | |
| 94 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | |
| 95 (*I)->placePhiLoads(); | |
| 96 } | |
| 97 } | |
| 98 | |
| 99 // placePhiStores() must be called after placePhiLoads(). | |
| 100 void Cfg::placePhiStores() { | |
| 101 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | |
| 102 (*I)->placePhiStores(); | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 void Cfg::deletePhis() { | |
| 107 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | |
| 108 (*I)->deletePhis(); | |
| 109 } | |
| 110 } | |
| 111 | |
| 112 void Cfg::genCode() { | |
| 113 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | |
| 114 (*I)->genCode(); | |
| 115 } | |
| 116 } | |
| 117 | |
| 118 // Compute the stack frame layout. | |
| 119 void Cfg::genFrame() { | |
| 120 getTarget()->addProlog(Entry); | |
| 121 // TODO: Consider folding epilog generation into the final | |
| 122 // emission/assembly pass to avoid an extra iteration over the node | |
| 123 // list. Or keep a separate list of exit nodes. | |
| 124 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { | |
| 125 CfgNode *Node = *I; | |
| 126 if (Node->getHasReturn()) | |
| 127 getTarget()->addEpilog(Node); | |
| 128 } | |
| 129 } | |
| 130 | |
| 63 // ======================== Dump routines ======================== // | 131 // ======================== Dump routines ======================== // |
| 64 | 132 |
| 133 void Cfg::emit() { | |
| 134 Ostream &Str = Ctx->getStrEmit(); | |
| 135 Timer T_emit; | |
| 136 if (!Ctx->testAndSetHasEmittedFirstMethod()) { | |
| 137 // Print a helpful command for assembling the output. | |
| 138 // TODO: have the Target emit the header | |
| 139 // TODO: need a per-file emit in addition to per-CFG | |
| 140 Str << "# $LLVM_BIN_PATH/llvm-mc" | |
| 141 << " -arch=x86" | |
| 142 << " -x86-asm-syntax=intel" | |
| 143 << " -filetype=obj" | |
| 144 << " -o=MyObj.o" | |
| 145 << "\n\n"; | |
| 146 } | |
| 147 Str << "\t.text\n"; | |
| 148 if (!getInternal()) { | |
| 149 IceString MangledName = getContext()->mangleName(getFunctionName()); | |
| 150 Str << "\t.globl\t" << MangledName << "\n"; | |
| 151 Str << "\t.type\t" << MangledName | |
| 152 << ",@function\n"; | |
| 153 } | |
| 154 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; | |
| 155 ++I) { | |
| 156 (*I)->emit(this); | |
| 157 } | |
| 158 Str << "\n"; | |
| 159 T_emit.printElapsedUs(Ctx, "emit()"); | |
| 160 } | |
| 161 | |
| 65 void Cfg::dump() { | 162 void Cfg::dump() { |
| 66 Ostream &Str = Ctx->getStrDump(); | 163 Ostream &Str = Ctx->getStrDump(); |
| 67 setCurrentNode(getEntryNode()); | 164 setCurrentNode(getEntryNode()); |
| 68 // Print function name+args | 165 // Print function name+args |
| 69 if (getContext()->isVerbose(IceV_Instructions)) { | 166 if (getContext()->isVerbose(IceV_Instructions)) { |
| 70 Str << "define "; | 167 Str << "define "; |
| 71 if (getInternal()) | 168 if (getInternal()) |
| 72 Str << "internal "; | 169 Str << "internal "; |
| 73 Str << ReturnType << " @" << getFunctionName() << "("; | 170 Str << ReturnType << " @" << getFunctionName() << "("; |
| 74 for (SizeT i = 0; i < Args.size(); ++i) { | 171 for (SizeT i = 0; i < Args.size(); ++i) { |
| 75 if (i > 0) | 172 if (i > 0) |
| 76 Str << ", "; | 173 Str << ", "; |
| 77 Str << Args[i]->getType() << " "; | 174 Str << Args[i]->getType() << " "; |
| 78 Args[i]->dump(this); | 175 Args[i]->dump(this); |
| 79 } | 176 } |
| 80 Str << ") {\n"; | 177 Str << ") {\n"; |
| 81 } | 178 } |
| 82 setCurrentNode(NULL); | 179 setCurrentNode(NULL); |
| 83 // Print each basic block | 180 // Print each basic block |
| 84 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; | 181 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; |
| 85 ++I) { | 182 ++I) { |
| 86 (*I)->dump(this); | 183 (*I)->dump(this); |
| 87 } | 184 } |
| 88 if (getContext()->isVerbose(IceV_Instructions)) { | 185 if (getContext()->isVerbose(IceV_Instructions)) { |
| 89 Str << "}\n"; | 186 Str << "}\n"; |
| 90 } | 187 } |
| 91 } | 188 } |
| 92 | 189 |
| 93 } // end of namespace Ice | 190 } // end of namespace Ice |
| OLD | NEW |