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 |