/src/keystone/llvm/lib/MC/MCFragment.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- lib/MC/MCFragment.cpp - Assembler Fragment Implementation ----------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | |
10 | | #include "llvm/MC/MCFragment.h" |
11 | | #include "llvm/ADT/StringExtras.h" |
12 | | #include "llvm/ADT/Twine.h" |
13 | | #include "llvm/MC/MCAsmBackend.h" |
14 | | #include "llvm/MC/MCAsmInfo.h" |
15 | | #include "llvm/MC/MCAsmLayout.h" |
16 | | #include "llvm/MC/MCContext.h" |
17 | | #include "llvm/MC/MCDwarf.h" |
18 | | #include "llvm/MC/MCExpr.h" |
19 | | #include "llvm/MC/MCFixupKindInfo.h" |
20 | | #include "llvm/MC/MCSection.h" |
21 | | #include "llvm/MC/MCSectionELF.h" |
22 | | #include "llvm/MC/MCSymbol.h" |
23 | | #include "llvm/MC/MCValue.h" |
24 | | #include "llvm/Support/ErrorHandling.h" |
25 | | #include "llvm/Support/LEB128.h" |
26 | | #include "llvm/Support/TargetRegistry.h" |
27 | | #include "llvm/Support/raw_ostream.h" |
28 | | #include <tuple> |
29 | | using namespace llvm_ks; |
30 | | |
31 | | MCAsmLayout::MCAsmLayout(MCAssembler &Asm) |
32 | 57.9k | : Assembler(Asm), LastValidFragment() |
33 | 57.9k | { |
34 | | // Compute the section layout order. Virtual sections must go last. |
35 | 57.9k | for (MCSection &Sec : Asm) |
36 | 59.9k | if (!Sec.isVirtualSection()) |
37 | 59.8k | SectionOrder.push_back(&Sec); |
38 | 57.9k | for (MCSection &Sec : Asm) |
39 | 59.9k | if (Sec.isVirtualSection()) |
40 | 175 | SectionOrder.push_back(&Sec); |
41 | 57.9k | } |
42 | | |
43 | 2.45M | bool MCAsmLayout::isFragmentValid(const MCFragment *F) const { |
44 | 2.45M | const MCSection *Sec = F->getParent(); |
45 | 2.45M | const MCFragment *LastValid = LastValidFragment.lookup(Sec); |
46 | 2.45M | if (!LastValid) |
47 | 120k | return false; |
48 | 2.33M | assert(LastValid->getParent() == Sec); |
49 | 2.33M | return F->getLayoutOrder() <= LastValid->getLayoutOrder(); |
50 | 2.33M | } |
51 | | |
52 | 529 | void MCAsmLayout::invalidateFragmentsFrom(MCFragment *F) { |
53 | | // If this fragment wasn't already valid, we don't need to do anything. |
54 | 529 | if (!isFragmentValid(F)) |
55 | 2 | return; |
56 | | |
57 | | // Otherwise, reset the last valid fragment to the previous fragment |
58 | | // (if this is the first fragment, it will be NULL). |
59 | 527 | LastValidFragment[F->getParent()] = F->getPrevNode(); |
60 | 527 | } |
61 | | |
62 | | bool MCAsmLayout::ensureValid(const MCFragment *F) const |
63 | 1.05M | { |
64 | 1.05M | MCSection *Sec = F->getParent(); |
65 | 1.05M | MCSection::iterator I; |
66 | 1.05M | if (MCFragment *Cur = LastValidFragment[Sec]) |
67 | 999k | I = ++MCSection::iterator(Cur); |
68 | 60.3k | else |
69 | 60.3k | I = Sec->begin(); |
70 | | |
71 | | // Advance the layout position until the fragment is valid. |
72 | 1.51M | while (!isFragmentValid(F)) { |
73 | | //assert(I != Sec->end() && "Layout bookkeeping error"); |
74 | 507k | if (I == Sec->end()) |
75 | 10.6k | return false; |
76 | 496k | if (const_cast<MCAsmLayout *>(this)->layoutFragment(&*I)) |
77 | 38.0k | return false; |
78 | 458k | ++I; |
79 | 458k | } |
80 | | |
81 | 1.01M | return true; |
82 | 1.05M | } |
83 | | |
84 | | uint64_t MCAsmLayout::getFragmentOffset(const MCFragment *F, bool &valid) const |
85 | 1.05M | { |
86 | 1.05M | valid = true; |
87 | 1.05M | if (!ensureValid(F)) { |
88 | 48.7k | valid = false; |
89 | 48.7k | return 0; |
90 | 48.7k | } |
91 | | //assert(F->Offset != ~UINT64_C(0) && "Address not set!"); |
92 | 1.01M | if (F->Offset == ~UINT64_C(0)) { |
93 | 229 | valid = false; |
94 | 229 | return 0; |
95 | 229 | } |
96 | | |
97 | 1.01M | return F->Offset; |
98 | 1.01M | } |
99 | | |
100 | | // Simple getSymbolOffset helper for the non-varibale case. |
101 | | static bool getLabelOffset(const MCAsmLayout &Layout, const MCSymbol &S, |
102 | | bool ReportError, uint64_t &Val) |
103 | 301k | { |
104 | 301k | if (!S.getFragment()) { |
105 | 7.19k | if (ReportError) |
106 | 0 | report_fatal_error("unable to evaluate offset to undefined symbol '" + |
107 | 0 | S.getName() + "'"); |
108 | 7.19k | return false; |
109 | 7.19k | } |
110 | | |
111 | 294k | bool valid; |
112 | 294k | Val = Layout.getFragmentOffset(S.getFragment(), valid) + S.getOffset(); |
113 | | |
114 | 294k | return valid; |
115 | 301k | } |
116 | | |
117 | | static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S, |
118 | | bool ReportError, uint64_t &Val, bool &valid) |
119 | 303k | { |
120 | 303k | valid = true; |
121 | 303k | if (!S.isVariable()) |
122 | 279k | return getLabelOffset(Layout, S, ReportError, Val); |
123 | | |
124 | | // If SD is a variable, evaluate it. |
125 | 24.1k | MCValue Target; |
126 | 24.1k | if (!S.getVariableValue()->evaluateAsValue(Target, Layout)) { |
127 | | //report_fatal_error("unable to evaluate offset for variable '" + |
128 | | // S.getName() + "'"); |
129 | 2.12k | valid = false; |
130 | 2.12k | return false; |
131 | 2.12k | } |
132 | | |
133 | 22.0k | uint64_t Offset = Target.getConstant(); |
134 | | |
135 | 22.0k | const MCSymbolRefExpr *A = Target.getSymA(); |
136 | 22.0k | if (A) { |
137 | 17.7k | uint64_t ValA; |
138 | 17.7k | if (!getLabelOffset(Layout, A->getSymbol(), ReportError, ValA)) |
139 | 3.54k | return false; |
140 | 14.1k | Offset += ValA; |
141 | 14.1k | } |
142 | | |
143 | 18.5k | const MCSymbolRefExpr *B = Target.getSymB(); |
144 | 18.5k | if (B) { |
145 | 4.35k | uint64_t ValB; |
146 | 4.35k | if (!getLabelOffset(Layout, B->getSymbol(), ReportError, ValB)) |
147 | 415 | return false; |
148 | 3.93k | Offset -= ValB; |
149 | 3.93k | } |
150 | | |
151 | 18.0k | Val = Offset; |
152 | 18.0k | return true; |
153 | 18.5k | } |
154 | | |
155 | | bool MCAsmLayout::getSymbolOffset(const MCSymbol &S, uint64_t &Val, bool &valid) const |
156 | 19.9k | { |
157 | 19.9k | return getSymbolOffsetImpl(*this, S, false, Val, valid); |
158 | 19.9k | } |
159 | | |
160 | | uint64_t MCAsmLayout::getSymbolOffset(const MCSymbol &S, bool &valid) const |
161 | 283k | { |
162 | 283k | uint64_t Val; |
163 | 283k | getSymbolOffsetImpl(*this, S, true, Val, valid); |
164 | 283k | return Val; |
165 | 283k | } |
166 | | |
167 | 0 | const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { |
168 | 0 | if (!Symbol.isVariable()) |
169 | 0 | return &Symbol; |
170 | | |
171 | 0 | const MCExpr *Expr = Symbol.getVariableValue(); |
172 | 0 | MCValue Value; |
173 | 0 | if (!Expr->evaluateAsValue(Value, *this)) { |
174 | 0 | Assembler.getContext().reportError( |
175 | 0 | SMLoc(), "expression could not be evaluated"); |
176 | 0 | return nullptr; |
177 | 0 | } |
178 | | |
179 | 0 | const MCSymbolRefExpr *RefB = Value.getSymB(); |
180 | 0 | if (RefB) { |
181 | 0 | Assembler.getContext().reportError( |
182 | 0 | SMLoc(), Twine("symbol '") + RefB->getSymbol().getName() + |
183 | 0 | "' could not be evaluated in a subtraction expression"); |
184 | 0 | return nullptr; |
185 | 0 | } |
186 | | |
187 | 0 | const MCSymbolRefExpr *A = Value.getSymA(); |
188 | 0 | if (!A) |
189 | 0 | return nullptr; |
190 | | |
191 | 0 | const MCSymbol &ASym = A->getSymbol(); |
192 | 0 | const MCAssembler &Asm = getAssembler(); |
193 | 0 | if (ASym.isCommon()) { |
194 | | // FIXME: we should probably add a SMLoc to MCExpr. |
195 | 0 | Asm.getContext().reportError(SMLoc(), |
196 | 0 | "Common symbol '" + ASym.getName() + |
197 | 0 | "' cannot be used in assignment expr"); |
198 | 0 | return nullptr; |
199 | 0 | } |
200 | | |
201 | 0 | return &ASym; |
202 | 0 | } |
203 | | |
204 | | uint64_t MCAsmLayout::getSectionAddressSize(const MCSection *Sec) const |
205 | 0 | { |
206 | | // The size is the last fragment's end offset. |
207 | 0 | const MCFragment &F = Sec->getFragmentList().back(); |
208 | 0 | bool valid, valid2; |
209 | 0 | return getFragmentOffset(&F, valid2) + getAssembler().computeFragmentSize(*this, F, valid); |
210 | 0 | } |
211 | | |
212 | 174 | uint64_t MCAsmLayout::getSectionFileSize(const MCSection *Sec) const { |
213 | | // Virtual sections have no file size. |
214 | 174 | if (Sec->isVirtualSection()) |
215 | 174 | return 0; |
216 | | |
217 | | // Otherwise, the file size is the same as the address space size. |
218 | 0 | return getSectionAddressSize(Sec); |
219 | 174 | } |
220 | | |
221 | | uint64_t llvm_ks::computeBundlePadding(const MCAssembler &Assembler, |
222 | | const MCFragment *F, |
223 | 0 | uint64_t FOffset, uint64_t FSize) { |
224 | 0 | uint64_t BundleSize = Assembler.getBundleAlignSize(); |
225 | 0 | assert(BundleSize > 0 && |
226 | 0 | "computeBundlePadding should only be called if bundling is enabled"); |
227 | 0 | uint64_t BundleMask = BundleSize - 1; |
228 | 0 | uint64_t OffsetInBundle = FOffset & BundleMask; |
229 | 0 | uint64_t EndOfFragment = OffsetInBundle + FSize; |
230 | | |
231 | | // There are two kinds of bundling restrictions: |
232 | | // |
233 | | // 1) For alignToBundleEnd(), add padding to ensure that the fragment will |
234 | | // *end* on a bundle boundary. |
235 | | // 2) Otherwise, check if the fragment would cross a bundle boundary. If it |
236 | | // would, add padding until the end of the bundle so that the fragment |
237 | | // will start in a new one. |
238 | 0 | if (F->alignToBundleEnd()) { |
239 | | // Three possibilities here: |
240 | | // |
241 | | // A) The fragment just happens to end at a bundle boundary, so we're good. |
242 | | // B) The fragment ends before the current bundle boundary: pad it just |
243 | | // enough to reach the boundary. |
244 | | // C) The fragment ends after the current bundle boundary: pad it until it |
245 | | // reaches the end of the next bundle boundary. |
246 | | // |
247 | | // Note: this code could be made shorter with some modulo trickery, but it's |
248 | | // intentionally kept in its more explicit form for simplicity. |
249 | 0 | if (EndOfFragment == BundleSize) |
250 | 0 | return 0; |
251 | 0 | else if (EndOfFragment < BundleSize) |
252 | 0 | return BundleSize - EndOfFragment; |
253 | 0 | else { // EndOfFragment > BundleSize |
254 | 0 | return 2 * BundleSize - EndOfFragment; |
255 | 0 | } |
256 | 0 | } else if (OffsetInBundle > 0 && EndOfFragment > BundleSize) |
257 | 0 | return BundleSize - OffsetInBundle; |
258 | 0 | else |
259 | 0 | return 0; |
260 | 0 | } |
261 | | |
262 | | /* *** */ |
263 | | |
264 | 648k | void ilist_node_traits<MCFragment>::deleteNode(MCFragment *V) { |
265 | 648k | V->destroy(); |
266 | 648k | } |
267 | | |
268 | 135k | MCFragment::MCFragment() : Kind(FragmentType(~0)), HasInstructions(false), |
269 | 135k | AlignToBundleEnd(false), BundlePadding(0) { |
270 | 135k | } |
271 | | |
272 | 6.55M | MCFragment::~MCFragment() { } |
273 | | |
274 | | MCFragment::MCFragment(FragmentType Kind, bool HasInstructions, |
275 | | uint8_t BundlePadding, MCSection *Parent) |
276 | 6.41M | : Kind(Kind), HasInstructions(HasInstructions), AlignToBundleEnd(false), |
277 | 6.41M | BundlePadding(BundlePadding), Parent(Parent), Atom(nullptr), |
278 | 6.41M | Offset(~UINT64_C(0)) { |
279 | 6.41M | if (Parent && !isDummy()) |
280 | 0 | Parent->getFragmentList().push_back(this); |
281 | 6.41M | } |
282 | | |
283 | 648k | void MCFragment::destroy() { |
284 | | // First check if we are the sentinal. |
285 | 648k | if (Kind == FragmentType(~0)) { |
286 | 0 | delete this; |
287 | 0 | return; |
288 | 0 | } |
289 | | |
290 | 648k | switch (Kind) { |
291 | 97.5k | case FT_Align: |
292 | 97.5k | delete cast<MCAlignFragment>(this); |
293 | 97.5k | return; |
294 | 140k | case FT_Data: |
295 | 140k | delete cast<MCDataFragment>(this); |
296 | 140k | return; |
297 | 0 | case FT_CompactEncodedInst: |
298 | 0 | delete cast<MCCompactEncodedInstFragment>(this); |
299 | 0 | return; |
300 | 47.3k | case FT_Fill: |
301 | 47.3k | delete cast<MCFillFragment>(this); |
302 | 47.3k | return; |
303 | 32.7k | case FT_Relaxable: |
304 | 32.7k | delete cast<MCRelaxableFragment>(this); |
305 | 32.7k | return; |
306 | 330k | case FT_Org: |
307 | 330k | delete cast<MCOrgFragment>(this); |
308 | 330k | return; |
309 | 0 | case FT_Dwarf: |
310 | 0 | delete cast<MCDwarfLineAddrFragment>(this); |
311 | 0 | return; |
312 | 0 | case FT_DwarfFrame: |
313 | 0 | delete cast<MCDwarfCallFrameFragment>(this); |
314 | 0 | return; |
315 | 0 | case FT_LEB: |
316 | 0 | delete cast<MCLEBFragment>(this); |
317 | 0 | return; |
318 | 0 | case FT_SafeSEH: |
319 | 0 | delete cast<MCSafeSEHFragment>(this); |
320 | 0 | return; |
321 | 0 | case FT_Dummy: |
322 | 0 | delete cast<MCDummyFragment>(this); |
323 | 0 | return; |
324 | 648k | } |
325 | 648k | } |
326 | | |
327 | | /* *** */ |
328 | | |
329 | | // Debugging methods |
330 | | |
331 | | namespace llvm_ks { |
332 | | |
333 | 0 | raw_ostream &operator<<(raw_ostream &OS, const MCFixup &AF) { |
334 | 0 | OS << "<MCFixup" << " Offset:" << AF.getOffset() |
335 | 0 | << " Value:" << *AF.getValue() |
336 | 0 | << " Kind:" << AF.getKind() << ">"; |
337 | 0 | return OS; |
338 | 0 | } |
339 | | |
340 | | } |
341 | | |
342 | | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
343 | 0 | LLVM_DUMP_METHOD void MCFragment::dump() { |
344 | 0 | raw_ostream &OS = llvm_ks::errs(); |
345 | |
|
346 | 0 | OS << "<"; |
347 | 0 | switch (getKind()) { |
348 | 0 | case MCFragment::FT_Align: OS << "MCAlignFragment"; break; |
349 | 0 | case MCFragment::FT_Data: OS << "MCDataFragment"; break; |
350 | 0 | case MCFragment::FT_CompactEncodedInst: |
351 | 0 | OS << "MCCompactEncodedInstFragment"; break; |
352 | 0 | case MCFragment::FT_Fill: OS << "MCFillFragment"; break; |
353 | 0 | case MCFragment::FT_Relaxable: OS << "MCRelaxableFragment"; break; |
354 | 0 | case MCFragment::FT_Org: OS << "MCOrgFragment"; break; |
355 | 0 | case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break; |
356 | 0 | case MCFragment::FT_DwarfFrame: OS << "MCDwarfCallFrameFragment"; break; |
357 | 0 | case MCFragment::FT_LEB: OS << "MCLEBFragment"; break; |
358 | 0 | case MCFragment::FT_SafeSEH: OS << "MCSafeSEHFragment"; break; |
359 | 0 | case MCFragment::FT_Dummy: |
360 | 0 | OS << "MCDummyFragment"; |
361 | 0 | break; |
362 | 0 | } |
363 | | |
364 | 0 | OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder |
365 | 0 | << " Offset:" << Offset |
366 | 0 | << " HasInstructions:" << hasInstructions() |
367 | 0 | << " BundlePadding:" << static_cast<unsigned>(getBundlePadding()) << ">"; |
368 | |
|
369 | 0 | switch (getKind()) { |
370 | 0 | case MCFragment::FT_Align: { |
371 | 0 | const MCAlignFragment *AF = cast<MCAlignFragment>(this); |
372 | 0 | if (AF->hasEmitNops()) |
373 | 0 | OS << " (emit nops)"; |
374 | 0 | OS << "\n "; |
375 | 0 | OS << " Alignment:" << AF->getAlignment() |
376 | 0 | << " Value:" << AF->getValue() << " ValueSize:" << AF->getValueSize() |
377 | 0 | << " MaxBytesToEmit:" << AF->getMaxBytesToEmit() << ">"; |
378 | 0 | break; |
379 | 0 | } |
380 | 0 | case MCFragment::FT_Data: { |
381 | 0 | const MCDataFragment *DF = cast<MCDataFragment>(this); |
382 | 0 | OS << "\n "; |
383 | 0 | OS << " Contents:["; |
384 | 0 | const SmallVectorImpl<char> &Contents = DF->getContents(); |
385 | 0 | for (unsigned i = 0, e = Contents.size(); i != e; ++i) { |
386 | 0 | if (i) OS << ","; |
387 | 0 | OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF); |
388 | 0 | } |
389 | 0 | OS << "] (" << Contents.size() << " bytes)"; |
390 | |
|
391 | 0 | if (DF->fixup_begin() != DF->fixup_end()) { |
392 | 0 | OS << ",\n "; |
393 | 0 | OS << " Fixups:["; |
394 | 0 | for (MCDataFragment::const_fixup_iterator it = DF->fixup_begin(), |
395 | 0 | ie = DF->fixup_end(); it != ie; ++it) { |
396 | 0 | if (it != DF->fixup_begin()) OS << ",\n "; |
397 | 0 | OS << *it; |
398 | 0 | } |
399 | 0 | OS << "]"; |
400 | 0 | } |
401 | 0 | break; |
402 | 0 | } |
403 | 0 | case MCFragment::FT_CompactEncodedInst: { |
404 | 0 | const MCCompactEncodedInstFragment *CEIF = |
405 | 0 | cast<MCCompactEncodedInstFragment>(this); |
406 | 0 | OS << "\n "; |
407 | 0 | OS << " Contents:["; |
408 | 0 | const SmallVectorImpl<char> &Contents = CEIF->getContents(); |
409 | 0 | for (unsigned i = 0, e = Contents.size(); i != e; ++i) { |
410 | 0 | if (i) OS << ","; |
411 | 0 | OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF); |
412 | 0 | } |
413 | 0 | OS << "] (" << Contents.size() << " bytes)"; |
414 | 0 | break; |
415 | 0 | } |
416 | 0 | case MCFragment::FT_Fill: { |
417 | 0 | const MCFillFragment *FF = cast<MCFillFragment>(this); |
418 | 0 | OS << " Value:" << FF->getValue() << " Size:" << FF->getSize(); |
419 | 0 | break; |
420 | 0 | } |
421 | 0 | case MCFragment::FT_Relaxable: { |
422 | | // const MCRelaxableFragment *F = cast<MCRelaxableFragment>(this); |
423 | 0 | OS << "\n "; |
424 | 0 | OS << " Inst:"; |
425 | 0 | break; |
426 | 0 | } |
427 | 0 | case MCFragment::FT_Org: { |
428 | 0 | const MCOrgFragment *OF = cast<MCOrgFragment>(this); |
429 | 0 | OS << "\n "; |
430 | 0 | OS << " Offset:" << OF->getOffset() << " Value:" << OF->getValue(); |
431 | 0 | break; |
432 | 0 | } |
433 | 0 | case MCFragment::FT_Dwarf: { |
434 | 0 | const MCDwarfLineAddrFragment *OF = cast<MCDwarfLineAddrFragment>(this); |
435 | 0 | OS << "\n "; |
436 | 0 | OS << " AddrDelta:" << OF->getAddrDelta() |
437 | 0 | << " LineDelta:" << OF->getLineDelta(); |
438 | 0 | break; |
439 | 0 | } |
440 | 0 | case MCFragment::FT_DwarfFrame: { |
441 | 0 | const MCDwarfCallFrameFragment *CF = cast<MCDwarfCallFrameFragment>(this); |
442 | 0 | OS << "\n "; |
443 | 0 | OS << " AddrDelta:" << CF->getAddrDelta(); |
444 | 0 | break; |
445 | 0 | } |
446 | 0 | case MCFragment::FT_LEB: { |
447 | 0 | const MCLEBFragment *LF = cast<MCLEBFragment>(this); |
448 | 0 | OS << "\n "; |
449 | 0 | OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned(); |
450 | 0 | break; |
451 | 0 | } |
452 | 0 | case MCFragment::FT_SafeSEH: { |
453 | 0 | const MCSafeSEHFragment *F = cast<MCSafeSEHFragment>(this); |
454 | 0 | OS << "\n "; |
455 | 0 | OS << " Sym:" << F->getSymbol(); |
456 | 0 | break; |
457 | 0 | } |
458 | 0 | case MCFragment::FT_Dummy: |
459 | 0 | break; |
460 | 0 | } |
461 | 0 | OS << ">"; |
462 | 0 | } |
463 | | |
464 | 0 | LLVM_DUMP_METHOD void MCAssembler::dump() { |
465 | 0 | raw_ostream &OS = llvm_ks::errs(); |
466 | |
|
467 | 0 | OS << "<MCAssembler\n"; |
468 | 0 | OS << " Sections:[\n "; |
469 | 0 | for (iterator it = begin(), ie = end(); it != ie; ++it) { |
470 | 0 | if (it != begin()) OS << ",\n "; |
471 | 0 | it->dump(); |
472 | 0 | } |
473 | 0 | OS << "],\n"; |
474 | 0 | OS << " Symbols:["; |
475 | |
|
476 | 0 | for (symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) { |
477 | 0 | if (it != symbol_begin()) OS << ",\n "; |
478 | 0 | OS << "("; |
479 | 0 | it->dump(); |
480 | 0 | OS << ", Index:" << it->getIndex() << ", "; |
481 | 0 | OS << ")"; |
482 | 0 | } |
483 | 0 | OS << "]>\n"; |
484 | 0 | } |
485 | | #endif |