blob: a328d21fccf4202e449fe5a7620fa0dacbb78eab [file] [log] [blame]
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001//===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Cfg class, including constant pool
11// management.
12//
13//===----------------------------------------------------------------------===//
14
15#include "IceCfg.h"
16#include "IceCfgNode.h"
Jim Stichnoth989a7032014-08-08 10:13:44 -070017#include "IceClFlags.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070018#include "IceDefs.h"
19#include "IceInst.h"
Jim Stichnothd97c7df2014-06-04 11:57:08 -070020#include "IceLiveness.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070021#include "IceOperand.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070022#include "IceTargetLowering.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070023
24namespace Ice {
25
26Cfg::Cfg(GlobalContext *Ctx)
27 : Ctx(Ctx), FunctionName(""), ReturnType(IceType_void),
Jim Stichnoth8363a062014-10-07 10:02:38 -070028 IsInternalLinkage(false), HasError(false), FocusedTiming(false),
Jim Stichnothe5b73e62014-12-15 09:58:51 -080029 ErrorMessage(""), Entry(NULL), NextInstNumber(Inst::NumberInitial),
30 Live(nullptr),
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070031 Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)),
Jan Voung8acded02014-09-22 18:02:25 -070032 VMetadata(new VariablesMetadata(this)),
33 TargetAssembler(
34 TargetLowering::createAssembler(Ctx->getTargetArch(), this)),
Karl Schimpf6fcbddd2014-11-06 09:49:24 -080035 CurrentNode(NULL) {
36 assert(!Ctx->isIRGenerationDisabled() &&
37 "Attempt to build cfg when IR generation disabled");
38}
Jim Stichnothf7c9a142014-04-29 10:52:43 -070039
40Cfg::~Cfg() {}
41
42void Cfg::setError(const IceString &Message) {
43 HasError = true;
44 ErrorMessage = Message;
45 Ctx->getStrDump() << "ICE translation error: " << ErrorMessage << "\n";
46}
47
Jim Stichnoth668a7a32014-12-10 15:32:25 -080048CfgNode *Cfg::makeNode() {
Jim Stichnothf7c9a142014-04-29 10:52:43 -070049 SizeT LabelIndex = Nodes.size();
Jim Stichnoth668a7a32014-12-10 15:32:25 -080050 CfgNode *Node = CfgNode::create(this, LabelIndex);
Jim Stichnothf7c9a142014-04-29 10:52:43 -070051 Nodes.push_back(Node);
52 return Node;
53}
54
Jim Stichnothf7c9a142014-04-29 10:52:43 -070055void Cfg::addArg(Variable *Arg) {
Jim Stichnoth144cdce2014-09-22 16:02:59 -070056 Arg->setIsArg();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070057 Args.push_back(Arg);
58}
59
Jim Stichnoth144cdce2014-09-22 16:02:59 -070060void Cfg::addImplicitArg(Variable *Arg) {
61 Arg->setIsImplicitArg();
62 ImplicitArgs.push_back(Arg);
63}
64
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070065// Returns whether the stack frame layout has been computed yet. This
66// is used for dumping the stack frame location of Variables.
67bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); }
68
69void Cfg::translate() {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070070 if (hasError())
71 return;
Jim Stichnoth1c44d812014-12-08 14:57:52 -080072 if (ALLOW_DUMP) {
73 const IceString &TimingFocusOn = getContext()->getFlags().TimingFocusOn;
74 if (TimingFocusOn == "*" || TimingFocusOn == getFunctionName()) {
75 setFocusedTiming();
76 getContext()->resetTimer(GlobalContext::TSK_Default);
77 getContext()->setTimerName(GlobalContext::TSK_Default, getFunctionName());
78 }
Jim Stichnothd14b1a02014-10-08 08:28:36 -070079 }
Jim Stichnoth8363a062014-10-07 10:02:38 -070080 TimerMarker T(TimerStack::TT_translate, this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070081
Jim Stichnothd97c7df2014-06-04 11:57:08 -070082 dump("Initial CFG");
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070083
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070084 // The set of translation passes and their order are determined by
85 // the target.
86 getTarget()->translate();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070087
Jim Stichnothd97c7df2014-06-04 11:57:08 -070088 dump("Final output");
Jim Stichnoth8363a062014-10-07 10:02:38 -070089 if (getFocusedTiming())
90 getContext()->dumpTimers();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070091}
92
Jim Stichnothf7c9a142014-04-29 10:52:43 -070093void Cfg::computePredecessors() {
Jim Stichnothf44f3712014-10-01 14:05:51 -070094 for (CfgNode *Node : Nodes)
95 Node->computePredecessors();
Jim Stichnothf7c9a142014-04-29 10:52:43 -070096}
97
Jim Stichnothd97c7df2014-06-04 11:57:08 -070098void Cfg::renumberInstructions() {
Jim Stichnoth8363a062014-10-07 10:02:38 -070099 TimerMarker T(TimerStack::TT_renumberInstructions, this);
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800100 NextInstNumber = Inst::NumberInitial;
Jim Stichnothf44f3712014-10-01 14:05:51 -0700101 for (CfgNode *Node : Nodes)
102 Node->renumberInstructions();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700103}
104
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700105// placePhiLoads() must be called before placePhiStores().
106void Cfg::placePhiLoads() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700107 TimerMarker T(TimerStack::TT_placePhiLoads, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700108 for (CfgNode *Node : Nodes)
109 Node->placePhiLoads();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700110}
111
112// placePhiStores() must be called after placePhiLoads().
113void Cfg::placePhiStores() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700114 TimerMarker T(TimerStack::TT_placePhiStores, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700115 for (CfgNode *Node : Nodes)
116 Node->placePhiStores();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700117}
118
119void Cfg::deletePhis() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700120 TimerMarker T(TimerStack::TT_deletePhis, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700121 for (CfgNode *Node : Nodes)
122 Node->deletePhis();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700123}
124
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700125void Cfg::advancedPhiLowering() {
126 TimerMarker T(TimerStack::TT_advancedPhiLowering, this);
127 // This splits edges and appends new nodes to the end of the node
128 // list. This can invalidate iterators, so don't use an iterator.
129 SizeT NumNodes = getNumNodes();
130 for (SizeT I = 0; I < NumNodes; ++I)
131 Nodes[I]->advancedPhiLowering();
132}
133
134// Find a reasonable placement for nodes that have not yet been
135// placed, while maintaining the same relative ordering among already
136// placed nodes.
137void Cfg::reorderNodes() {
138 typedef std::list<CfgNode *> PlacedList;
139 PlacedList Placed; // Nodes with relative placement locked down
140 PlacedList Unreachable; // Unreachable nodes
141 PlacedList::iterator NoPlace = Placed.end();
142 // Keep track of where each node has been tentatively placed so that
143 // we can manage insertions into the middle.
144 std::vector<PlacedList::iterator> PlaceIndex(Nodes.size(), NoPlace);
145 for (CfgNode *Node : Nodes) {
146 // The "do ... while(0);" construct is to factor out the
147 // --PlaceIndex and assert() statements before moving to the next
148 // node.
149 do {
150 if (!Node->needsPlacement()) {
151 // Add to the end of the Placed list.
152 Placed.push_back(Node);
153 PlaceIndex[Node->getIndex()] = Placed.end();
154 continue;
155 }
156 Node->setNeedsPlacement(false);
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800157 if (Node != getEntryNode() && Node->getInEdges().empty()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700158 // The node has essentially been deleted since it is not a
159 // successor of any other node.
160 Unreachable.push_back(Node);
161 PlaceIndex[Node->getIndex()] = Unreachable.end();
162 continue;
163 }
164 // Assume for now that the unplaced node is from edge-splitting
165 // and therefore has 1 in-edge and 1 out-edge (actually, possibly
166 // more than 1 in-edge if the predecessor node was contracted).
167 // If this changes in the future, rethink the strategy.
168 assert(Node->getInEdges().size() >= 1);
169 assert(Node->getOutEdges().size() == 1);
170
171 // If it's a (non-critical) edge where the successor has a single
172 // in-edge, then place it before the successor.
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800173 CfgNode *Succ = Node->getOutEdges().front();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700174 if (Succ->getInEdges().size() == 1 &&
175 PlaceIndex[Succ->getIndex()] != NoPlace) {
176 Placed.insert(PlaceIndex[Succ->getIndex()], Node);
177 PlaceIndex[Node->getIndex()] = PlaceIndex[Succ->getIndex()];
178 continue;
179 }
180
181 // Otherwise, place it after the (first) predecessor.
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800182 CfgNode *Pred = Node->getInEdges().front();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700183 auto PredPosition = PlaceIndex[Pred->getIndex()];
184 // It shouldn't be the case that PredPosition==NoPlace, but if
185 // that somehow turns out to be true, we just insert Node before
186 // PredPosition=NoPlace=Placed.end() .
187 if (PredPosition != NoPlace)
188 ++PredPosition;
189 Placed.insert(PredPosition, Node);
190 PlaceIndex[Node->getIndex()] = PredPosition;
191 } while (0);
192
193 --PlaceIndex[Node->getIndex()];
194 assert(*PlaceIndex[Node->getIndex()] == Node);
195 }
196
197 // Reorder Nodes according to the built-up lists.
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800198 SizeT OldSize = Nodes.size();
199 (void)OldSize;
200 Nodes.clear();
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700201 for (CfgNode *Node : Placed)
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800202 Nodes.push_back(Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700203 for (CfgNode *Node : Unreachable)
Jim Stichnothbfb410d2014-11-05 16:04:05 -0800204 Nodes.push_back(Node);
205 assert(Nodes.size() == OldSize);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700206}
207
Matt Wala45a06232014-07-09 16:33:22 -0700208void Cfg::doArgLowering() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700209 TimerMarker T(TimerStack::TT_doArgLowering, this);
Matt Wala45a06232014-07-09 16:33:22 -0700210 getTarget()->lowerArguments();
211}
212
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700213void Cfg::doAddressOpt() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700214 TimerMarker T(TimerStack::TT_doAddressOpt, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700215 for (CfgNode *Node : Nodes)
216 Node->doAddressOpt();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700217}
218
Matt Walac3302742014-08-15 16:21:56 -0700219void Cfg::doNopInsertion() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700220 TimerMarker T(TimerStack::TT_doNopInsertion, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700221 for (CfgNode *Node : Nodes)
222 Node->doNopInsertion();
Matt Walac3302742014-08-15 16:21:56 -0700223}
224
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700225void Cfg::genCode() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700226 TimerMarker T(TimerStack::TT_genCode, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700227 for (CfgNode *Node : Nodes)
228 Node->genCode();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700229}
230
231// Compute the stack frame layout.
232void Cfg::genFrame() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700233 TimerMarker T(TimerStack::TT_genFrame, this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700234 getTarget()->addProlog(Entry);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700235 for (CfgNode *Node : Nodes)
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700236 if (Node->getHasReturn())
237 getTarget()->addEpilog(Node);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700238}
239
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700240// This is a lightweight version of live-range-end calculation. Marks
241// the last use of only those variables whose definition and uses are
242// completely with a single block. It is a quick single pass and
243// doesn't need to iterate until convergence.
244void Cfg::livenessLightweight() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700245 TimerMarker T(TimerStack::TT_livenessLightweight, this);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700246 getVMetadata()->init(VMK_Uses);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700247 for (CfgNode *Node : Nodes)
248 Node->livenessLightweight();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700249}
250
251void Cfg::liveness(LivenessMode Mode) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700252 TimerMarker T(TimerStack::TT_liveness, this);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700253 Live.reset(new Liveness(this, Mode));
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700254 getVMetadata()->init(VMK_Uses);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700255 Live->init();
256 // Initialize with all nodes needing to be processed.
257 llvm::BitVector NeedToProcess(Nodes.size(), true);
258 while (NeedToProcess.any()) {
259 // Iterate in reverse topological order to speed up convergence.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700260 for (auto I = Nodes.rbegin(), E = Nodes.rend(); I != E; ++I) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700261 CfgNode *Node = *I;
262 if (NeedToProcess[Node->getIndex()]) {
263 NeedToProcess[Node->getIndex()] = false;
264 bool Changed = Node->liveness(getLiveness());
265 if (Changed) {
266 // If the beginning-of-block liveness changed since the last
267 // iteration, mark all in-edges as needing to be processed.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700268 for (CfgNode *Pred : Node->getInEdges())
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700269 NeedToProcess[Pred->getIndex()] = true;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700270 }
271 }
272 }
273 }
274 if (Mode == Liveness_Intervals) {
275 // Reset each variable's live range.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700276 for (Variable *Var : Variables)
277 Var->resetLiveRange();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700278 }
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800279 // Make a final pass over each node to delete dead instructions,
280 // collect the first and last instruction numbers, and add live
281 // range segments for that node.
282 for (CfgNode *Node : Nodes) {
283 InstNumberT FirstInstNum = Inst::NumberSentinel;
284 InstNumberT LastInstNum = Inst::NumberSentinel;
285 for (auto I = Node->getPhis().begin(), E = Node->getPhis().end(); I != E;
286 ++I) {
287 I->deleteIfDead();
288 if (Mode == Liveness_Intervals && !I->isDeleted()) {
289 if (FirstInstNum == Inst::NumberSentinel)
290 FirstInstNum = I->getNumber();
291 assert(I->getNumber() > LastInstNum);
292 LastInstNum = I->getNumber();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700293 }
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800294 }
295 for (auto I = Node->getInsts().begin(), E = Node->getInsts().end(); I != E;
296 ++I) {
297 I->deleteIfDead();
298 if (Mode == Liveness_Intervals && !I->isDeleted()) {
299 if (FirstInstNum == Inst::NumberSentinel)
300 FirstInstNum = I->getNumber();
301 assert(I->getNumber() > LastInstNum);
302 LastInstNum = I->getNumber();
303 }
304 }
305 if (Mode == Liveness_Intervals) {
306 // Special treatment for live in-args. Their liveness needs to
307 // extend beyond the beginning of the function, otherwise an arg
308 // whose only use is in the first instruction will end up having
309 // the trivial live range [2,2) and will *not* interfere with
310 // other arguments. So if the first instruction of the method
311 // is "r=arg1+arg2", both args may be assigned the same
312 // register. This is accomplished by extending the entry
313 // block's instruction range from [2,n) to [1,n) which will
314 // transform the problematic [2,2) live ranges into [1,2).
315 if (FirstInstNum == Inst::NumberInitial)
316 FirstInstNum = Inst::NumberExtended;
317 Node->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700318 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700319 }
320}
321
322// Traverse every Variable of every Inst and verify that it
323// appears within the Variable's computed live range.
324bool Cfg::validateLiveness() const {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700325 TimerMarker T(TimerStack::TT_validateLiveness, this);
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700326 bool Valid = true;
327 Ostream &Str = Ctx->getStrDump();
Jim Stichnothf44f3712014-10-01 14:05:51 -0700328 for (CfgNode *Node : Nodes) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700329 Inst *FirstInst = NULL;
Jim Stichnoth607e9f02014-11-06 13:32:05 -0800330 for (auto Inst = Node->getInsts().begin(), E = Node->getInsts().end();
331 Inst != E; ++Inst) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700332 if (Inst->isDeleted())
333 continue;
Jim Stichnoth47752552014-10-13 17:15:08 -0700334 if (FirstInst == NULL)
335 FirstInst = Inst;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700336 InstNumberT InstNumber = Inst->getNumber();
Jim Stichnoth47752552014-10-13 17:15:08 -0700337 if (Variable *Dest = Inst->getDest()) {
338 if (!Dest->getIgnoreLiveness()) {
339 bool Invalid = false;
340 const bool IsDest = true;
341 if (!Dest->getLiveRange().containsValue(InstNumber, IsDest))
342 Invalid = true;
343 // Check that this instruction actually *begins* Dest's live
344 // range, by checking that Dest is not live in the previous
345 // instruction. As a special exception, we don't check this
346 // for the first instruction of the block, because a Phi
347 // temporary may be live at the end of the previous block,
348 // and if it is also assigned in the first instruction of
349 // this block, the adjacent live ranges get merged.
Jim Stichnoth607e9f02014-11-06 13:32:05 -0800350 if (static_cast<class Inst *>(Inst) != FirstInst &&
351 !Inst->isDestNonKillable() &&
Jim Stichnoth47752552014-10-13 17:15:08 -0700352 Dest->getLiveRange().containsValue(InstNumber - 1, IsDest))
353 Invalid = true;
354 if (Invalid) {
355 Valid = false;
356 Str << "Liveness error: inst " << Inst->getNumber() << " dest ";
357 Dest->dump(this);
358 Str << " live range " << Dest->getLiveRange() << "\n";
359 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700360 }
361 }
362 for (SizeT I = 0; I < Inst->getSrcSize(); ++I) {
363 Operand *Src = Inst->getSrc(I);
364 SizeT NumVars = Src->getNumVars();
365 for (SizeT J = 0; J < NumVars; ++J) {
366 const Variable *Var = Src->getVar(J);
Jim Stichnoth47752552014-10-13 17:15:08 -0700367 const bool IsDest = false;
368 if (!Var->getIgnoreLiveness() &&
369 !Var->getLiveRange().containsValue(InstNumber, IsDest)) {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700370 Valid = false;
371 Str << "Liveness error: inst " << Inst->getNumber() << " var ";
372 Var->dump(this);
373 Str << " live range " << Var->getLiveRange() << "\n";
374 }
375 }
376 }
377 }
378 }
379 return Valid;
380}
381
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700382void Cfg::contractEmptyNodes() {
Jim Stichnoth3d44fe82014-11-01 10:10:18 -0700383 // If we're decorating the asm output with register liveness info,
384 // this information may become corrupted or incorrect after
385 // contracting nodes that contain only redundant assignments. As
386 // such, we disable this pass when DecorateAsm is specified. This
387 // may make the resulting code look more branchy, but it should have
388 // no effect on the register assignments.
389 if (Ctx->getFlags().DecorateAsm)
390 return;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700391 for (CfgNode *Node : Nodes) {
392 Node->contractIfEmpty();
393 }
394}
395
Jim Stichnothff9c7062014-09-18 04:50:49 -0700396void Cfg::doBranchOpt() {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700397 TimerMarker T(TimerStack::TT_doBranchOpt, this);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700398 for (auto I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
399 auto NextNode = I;
Jim Stichnothff9c7062014-09-18 04:50:49 -0700400 ++NextNode;
Jim Stichnothc4554d72014-09-30 16:49:38 -0700401 (*I)->doBranchOpt(NextNode == E ? NULL : *NextNode);
Jim Stichnothff9c7062014-09-18 04:50:49 -0700402 }
403}
404
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700405// ======================== Dump routines ======================== //
406
Jan Voung0faec4c2014-11-05 17:29:56 -0800407void Cfg::emitTextHeader(const IceString &MangledName) {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800408 // Note: Still used by emit IAS.
Jan Voung0faec4c2014-11-05 17:29:56 -0800409 Ostream &Str = Ctx->getStrEmit();
410 Str << "\t.text\n";
411 if (Ctx->getFlags().FunctionSections)
412 Str << "\t.section\t.text." << MangledName << ",\"ax\",@progbits\n";
413 if (!getInternal() || Ctx->getFlags().DisableInternal) {
414 Str << "\t.globl\t" << MangledName << "\n";
415 Str << "\t.type\t" << MangledName << ",@function\n";
416 }
Jan Voung08c3bcd2014-12-01 17:55:16 -0800417 Assembler *Asm = getAssembler<Assembler>();
418 Str << "\t.p2align " << Asm->getBundleAlignLog2Bytes() << ",0x";
419 for (uint8_t I : Asm->getNonExecBundlePadding())
Jan Voung0faec4c2014-11-05 17:29:56 -0800420 Str.write_hex(I);
421 Str << "\n";
422 Str << MangledName << ":\n";
423}
424
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700425void Cfg::emit() {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800426 if (!ALLOW_DUMP)
427 return;
Jim Stichnoth8363a062014-10-07 10:02:38 -0700428 TimerMarker T(TimerStack::TT_emit, this);
Jim Stichnoth3d44fe82014-11-01 10:10:18 -0700429 if (Ctx->getFlags().DecorateAsm) {
430 renumberInstructions();
431 getVMetadata()->init(VMK_Uses);
432 liveness(Liveness_Basic);
433 dump("After recomputing liveness for -decorate-asm");
434 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700435 Ostream &Str = Ctx->getStrEmit();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700436 if (!Ctx->testAndSetHasEmittedFirstMethod()) {
437 // Print a helpful command for assembling the output.
438 // TODO: have the Target emit the header
439 // TODO: need a per-file emit in addition to per-CFG
440 Str << "# $LLVM_BIN_PATH/llvm-mc"
441 << " -arch=x86"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700442 << " -filetype=obj"
443 << " -o=MyObj.o"
444 << "\n\n";
445 }
Jim Stichnoth989a7032014-08-08 10:13:44 -0700446 IceString MangledName = getContext()->mangleName(getFunctionName());
Jan Voung0faec4c2014-11-05 17:29:56 -0800447 emitTextHeader(MangledName);
Jim Stichnothf44f3712014-10-01 14:05:51 -0700448 for (CfgNode *Node : Nodes)
449 Node->emit(this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700450 Str << "\n";
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700451}
452
Jan Voung0faec4c2014-11-05 17:29:56 -0800453void Cfg::emitIAS() {
454 TimerMarker T(TimerStack::TT_emit, this);
455 assert(!Ctx->getFlags().DecorateAsm);
456 IceString MangledName = getContext()->mangleName(getFunctionName());
Jan Voung08c3bcd2014-12-01 17:55:16 -0800457 if (!Ctx->getFlags().UseELFWriter)
458 emitTextHeader(MangledName);
Jan Voung0faec4c2014-11-05 17:29:56 -0800459 for (CfgNode *Node : Nodes)
460 Node->emitIAS(this);
Jan Voung08c3bcd2014-12-01 17:55:16 -0800461 // Now write the function to the file and track.
462 if (Ctx->getFlags().UseELFWriter) {
463 getAssembler<Assembler>()->alignFunction();
464 // TODO(jvoung): Transfer remaining fixups too. They may need their
465 // offsets adjusted.
466 Ctx->getObjectWriter()->writeFunctionCode(
467 MangledName, getInternal(), getAssembler<Assembler>()->getBufferView());
468 } else {
469 getAssembler<Assembler>()->emitIASBytes(Ctx);
470 }
Jan Voung0faec4c2014-11-05 17:29:56 -0800471}
472
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700473// Dumps the IR with an optional introductory message.
474void Cfg::dump(const IceString &Message) {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800475 if (!ALLOW_DUMP)
476 return;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700477 if (!Ctx->isVerbose())
478 return;
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700479 Ostream &Str = Ctx->getStrDump();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700480 if (!Message.empty())
481 Str << "================ " << Message << " ================\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700482 setCurrentNode(getEntryNode());
483 // Print function name+args
484 if (getContext()->isVerbose(IceV_Instructions)) {
485 Str << "define ";
Jim Stichnoth088b2be2014-10-23 12:02:08 -0700486 if (getInternal() && !Ctx->getFlags().DisableInternal)
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700487 Str << "internal ";
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700488 Str << ReturnType << " @" << Ctx->mangleName(getFunctionName()) << "(";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700489 for (SizeT i = 0; i < Args.size(); ++i) {
490 if (i > 0)
491 Str << ", ";
492 Str << Args[i]->getType() << " ";
493 Args[i]->dump(this);
494 }
495 Str << ") {\n";
496 }
Jim Stichnoth800dab22014-09-20 12:25:02 -0700497 resetCurrentNode();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700498 if (getContext()->isVerbose(IceV_Liveness)) {
499 // Print summary info about variables
Jim Stichnothf44f3712014-10-01 14:05:51 -0700500 for (Variable *Var : Variables) {
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700501 Str << "// multiblock=";
502 if (getVMetadata()->isTracked(Var))
503 Str << getVMetadata()->isMultiBlock(Var);
504 else
505 Str << "?";
506 Str << " weight=" << Var->getWeight() << " ";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700507 Var->dump(this);
508 Str << " LIVE=" << Var->getLiveRange() << "\n";
509 }
510 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700511 // Print each basic block
Jim Stichnothf44f3712014-10-01 14:05:51 -0700512 for (CfgNode *Node : Nodes)
513 Node->dump(this);
514 if (getContext()->isVerbose(IceV_Instructions))
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700515 Str << "}\n";
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700516}
517
518} // end of namespace Ice