blob: e28020fa37bcdc38af02e6cccce97a2a211d653c [file] [log] [blame]
Jim Laskeye5032892005-12-21 19:48:16 +00001//===-- llvm/CodeGen/DwarfWriter.cpp - Dwarf Framework ----------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by James M. Laskey and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains support for writing dwarf debug info into asm files.
11//
12//===----------------------------------------------------------------------===//
Jim Laskey3ea0e0e2006-01-27 18:32:41 +000013
Jim Laskeyb2efb852006-01-04 22:28:25 +000014#include "llvm/CodeGen/DwarfWriter.h"
Jim Laskeye5032892005-12-21 19:48:16 +000015
Jim Laskey063e7652006-01-17 17:31:53 +000016#include "llvm/ADT/StringExtras.h"
Jim Laskey52060a02006-01-24 00:49:18 +000017#include "llvm/Module.h"
18#include "llvm/Type.h"
Jim Laskeya7cea6f2006-01-04 13:52:30 +000019#include "llvm/CodeGen/AsmPrinter.h"
Jim Laskeyb2efb852006-01-04 22:28:25 +000020#include "llvm/CodeGen/MachineDebugInfo.h"
Jim Laskeyb3e789a2006-01-26 20:21:46 +000021#include "llvm/Support/Dwarf.h"
Jim Laskeya7cea6f2006-01-04 13:52:30 +000022#include "llvm/Support/CommandLine.h"
Jim Laskey52060a02006-01-24 00:49:18 +000023#include "llvm/Support/Mangler.h"
24#include "llvm/Target/TargetMachine.h"
Jim Laskeya7cea6f2006-01-04 13:52:30 +000025
Jim Laskeyb2efb852006-01-04 22:28:25 +000026#include <iostream>
Jim Laskeya7cea6f2006-01-04 13:52:30 +000027
Jim Laskeyb2efb852006-01-04 22:28:25 +000028using namespace llvm;
Jim Laskey9a777a32006-02-27 22:37:23 +000029using namespace llvm::dwarf;
Jim Laskeya7cea6f2006-01-04 13:52:30 +000030
31static cl::opt<bool>
32DwarfVerbose("dwarf-verbose", cl::Hidden,
Jim Laskey063e7652006-01-17 17:31:53 +000033 cl::desc("Add comments to Dwarf directives."));
34
Jim Laskey0d086af2006-02-27 12:43:29 +000035namespace llvm {
36
Jim Laskey063e7652006-01-17 17:31:53 +000037//===----------------------------------------------------------------------===//
Jim Laskey0d086af2006-02-27 12:43:29 +000038// Forward declarations.
39//
40class CompileUnit;
41class DIE;
Jim Laskey063e7652006-01-17 17:31:53 +000042
Jim Laskey0d086af2006-02-27 12:43:29 +000043//===----------------------------------------------------------------------===//
Jim Laskeyf01e5472006-03-03 15:06:57 +000044// CompileUnit - This dwarf writer support class manages information associate
45// with a source file.
Jim Laskeybd761842006-02-27 17:27:12 +000046class CompileUnit {
47private:
48 CompileUnitDesc *Desc; // Compile unit debug descriptor.
49 unsigned ID; // File ID for source.
50 DIE *Die; // Compile unit die.
51 std::map<std::string, DIE *> Globals; // A map of globally visible named
52 // entities for this unit.
53
54public:
55 CompileUnit(CompileUnitDesc *CUD, unsigned I, DIE *D)
56 : Desc(CUD)
57 , ID(I)
58 , Die(D)
59 , Globals()
60 {}
61
62 ~CompileUnit();
63
64 // Accessors.
65 CompileUnitDesc *getDesc() const { return Desc; }
66 unsigned getID() const { return ID; }
67 DIE* getDie() const { return Die; }
68 std::map<std::string, DIE *> &getGlobals() { return Globals; }
69
70 /// hasContent - Return true if this compile unit has something to write out.
71 ///
72 bool hasContent() const;
73
74 /// AddGlobal - Add a new global entity to the compile unit.
75 ///
76 void AddGlobal(const std::string &Name, DIE *Die);
77
78};
79
80//===----------------------------------------------------------------------===//
Jim Laskey0d086af2006-02-27 12:43:29 +000081// DIEAbbrevData - Dwarf abbreviation data, describes the one attribute of a
82// Dwarf abbreviation.
83class DIEAbbrevData {
84private:
85 unsigned Attribute; // Dwarf attribute code.
86 unsigned Form; // Dwarf form code.
87
88public:
89 DIEAbbrevData(unsigned A, unsigned F)
90 : Attribute(A)
91 , Form(F)
92 {}
93
Jim Laskeybd761842006-02-27 17:27:12 +000094 // Accessors.
Jim Laskey0d086af2006-02-27 12:43:29 +000095 unsigned getAttribute() const { return Attribute; }
96 unsigned getForm() const { return Form; }
97
98 /// operator== - Used by DIEAbbrev to locate entry.
99 ///
100 bool operator==(const DIEAbbrevData &DAD) const {
101 return Attribute == DAD.Attribute && Form == DAD.Form;
Jim Laskey063e7652006-01-17 17:31:53 +0000102 }
Jim Laskey063e7652006-01-17 17:31:53 +0000103
Jim Laskey0d086af2006-02-27 12:43:29 +0000104 /// operator!= - Used by DIEAbbrev to locate entry.
105 ///
106 bool operator!=(const DIEAbbrevData &DAD) const {
107 return Attribute != DAD.Attribute || Form != DAD.Form;
Jim Laskey063e7652006-01-17 17:31:53 +0000108 }
Jim Laskey0d086af2006-02-27 12:43:29 +0000109
110 /// operator< - Used by DIEAbbrev to locate entry.
111 ///
112 bool operator<(const DIEAbbrevData &DAD) const {
113 return Attribute < DAD.Attribute ||
114 (Attribute == DAD.Attribute && Form < DAD.Form);
115 }
116};
Jim Laskey063e7652006-01-17 17:31:53 +0000117
Jim Laskey0d086af2006-02-27 12:43:29 +0000118//===----------------------------------------------------------------------===//
119// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug
120// information object.
121class DIEAbbrev {
122private:
123 unsigned Tag; // Dwarf tag code.
124 unsigned ChildrenFlag; // Dwarf children flag.
125 std::vector<DIEAbbrevData> Data; // Raw data bytes for abbreviation.
Jim Laskey063e7652006-01-17 17:31:53 +0000126
Jim Laskey0d086af2006-02-27 12:43:29 +0000127public:
Jim Laskey063e7652006-01-17 17:31:53 +0000128
Jim Laskey0d086af2006-02-27 12:43:29 +0000129 DIEAbbrev(unsigned T, unsigned C)
130 : Tag(T)
131 , ChildrenFlag(C)
132 , Data()
133 {}
134 ~DIEAbbrev() {}
135
Jim Laskeybd761842006-02-27 17:27:12 +0000136 // Accessors.
Jim Laskey0d086af2006-02-27 12:43:29 +0000137 unsigned getTag() const { return Tag; }
138 unsigned getChildrenFlag() const { return ChildrenFlag; }
139 const std::vector<DIEAbbrevData> &getData() const { return Data; }
140 void setChildrenFlag(unsigned CF) { ChildrenFlag = CF; }
Jim Laskey063e7652006-01-17 17:31:53 +0000141
Jim Laskey0d086af2006-02-27 12:43:29 +0000142 /// operator== - Used by UniqueVector to locate entry.
143 ///
144 bool operator==(const DIEAbbrev &DA) const;
Jim Laskey063e7652006-01-17 17:31:53 +0000145
Jim Laskey0d086af2006-02-27 12:43:29 +0000146 /// operator< - Used by UniqueVector to locate entry.
147 ///
148 bool operator<(const DIEAbbrev &DA) const;
Jim Laskey063e7652006-01-17 17:31:53 +0000149
Jim Laskey0d086af2006-02-27 12:43:29 +0000150 /// AddAttribute - Adds another set of attribute information to the
151 /// abbreviation.
152 void AddAttribute(unsigned Attribute, unsigned Form) {
153 Data.push_back(DIEAbbrevData(Attribute, Form));
Jim Laskey063e7652006-01-17 17:31:53 +0000154 }
Jim Laskey0d086af2006-02-27 12:43:29 +0000155
156 /// Emit - Print the abbreviation using the specified Dwarf writer.
157 ///
158 void Emit(const DwarfWriter &DW) const;
159
160#ifndef NDEBUG
161 void print(std::ostream &O);
162 void dump();
163#endif
164};
Jim Laskey063e7652006-01-17 17:31:53 +0000165
Jim Laskey0d086af2006-02-27 12:43:29 +0000166//===----------------------------------------------------------------------===//
167// DIEValue - A debug information entry value.
168//
169class DIEValue {
170public:
171 enum {
172 isInteger,
173 isString,
174 isLabel,
175 isAsIsLabel,
176 isDelta,
177 isEntry
178 };
179
180 unsigned Type; // Type of the value
181
182 DIEValue(unsigned T) : Type(T) {}
183 virtual ~DIEValue() {}
184
185 // Implement isa/cast/dyncast.
186 static bool classof(const DIEValue *) { return true; }
187
188 /// EmitValue - Emit value via the Dwarf writer.
189 ///
190 virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const = 0;
191
192 /// SizeOf - Return the size of a value in bytes.
193 ///
194 virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const = 0;
195};
Jim Laskey063e7652006-01-17 17:31:53 +0000196
Jim Laskey0d086af2006-02-27 12:43:29 +0000197//===----------------------------------------------------------------------===//
198// DWInteger - An integer value DIE.
199//
200class DIEInteger : public DIEValue {
201private:
202 uint64_t Integer;
203
204public:
205 DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {}
Jim Laskey063e7652006-01-17 17:31:53 +0000206
Jim Laskey0d086af2006-02-27 12:43:29 +0000207 // Implement isa/cast/dyncast.
208 static bool classof(const DIEInteger *) { return true; }
209 static bool classof(const DIEValue *I) { return I->Type == isInteger; }
210
211 /// EmitValue - Emit integer of appropriate size.
212 ///
213 virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
214
215 /// SizeOf - Determine size of integer value in bytes.
216 ///
217 virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
218};
Jim Laskey063e7652006-01-17 17:31:53 +0000219
Jim Laskey0d086af2006-02-27 12:43:29 +0000220//===----------------------------------------------------------------------===//
221// DIEString - A string value DIE.
222//
223struct DIEString : public DIEValue {
224 const std::string String;
225
226 DIEString(const std::string &S) : DIEValue(isString), String(S) {}
Jim Laskey063e7652006-01-17 17:31:53 +0000227
Jim Laskey0d086af2006-02-27 12:43:29 +0000228 // Implement isa/cast/dyncast.
229 static bool classof(const DIEString *) { return true; }
230 static bool classof(const DIEValue *S) { return S->Type == isString; }
231
232 /// EmitValue - Emit string value.
233 ///
234 virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
235
236 /// SizeOf - Determine size of string value in bytes.
237 ///
238 virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
239};
Jim Laskey063e7652006-01-17 17:31:53 +0000240
Jim Laskey0d086af2006-02-27 12:43:29 +0000241//===----------------------------------------------------------------------===//
242// DIEDwarfLabel - A Dwarf internal label expression DIE.
243//
244struct DIEDwarfLabel : public DIEValue {
245 const DWLabel Label;
246
247 DIEDwarfLabel(const DWLabel &L) : DIEValue(isLabel), Label(L) {}
Jim Laskey063e7652006-01-17 17:31:53 +0000248
Jim Laskey0d086af2006-02-27 12:43:29 +0000249 // Implement isa/cast/dyncast.
250 static bool classof(const DIEDwarfLabel *) { return true; }
251 static bool classof(const DIEValue *L) { return L->Type == isLabel; }
252
253 /// EmitValue - Emit label value.
254 ///
255 virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
256
257 /// SizeOf - Determine size of label value in bytes.
258 ///
259 virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
260};
Jim Laskey063e7652006-01-17 17:31:53 +0000261
Jim Laskey063e7652006-01-17 17:31:53 +0000262
Jim Laskey0d086af2006-02-27 12:43:29 +0000263//===----------------------------------------------------------------------===//
264// DIEObjectLabel - A label to an object in code or data.
265//
266struct DIEObjectLabel : public DIEValue {
267 const std::string Label;
268
269 DIEObjectLabel(const std::string &L) : DIEValue(isAsIsLabel), Label(L) {}
Jim Laskey063e7652006-01-17 17:31:53 +0000270
Jim Laskey0d086af2006-02-27 12:43:29 +0000271 // Implement isa/cast/dyncast.
272 static bool classof(const DIEObjectLabel *) { return true; }
273 static bool classof(const DIEValue *L) { return L->Type == isAsIsLabel; }
274
275 /// EmitValue - Emit label value.
276 ///
277 virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
278
279 /// SizeOf - Determine size of label value in bytes.
280 ///
281 virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
282};
Jim Laskey063e7652006-01-17 17:31:53 +0000283
Jim Laskey0d086af2006-02-27 12:43:29 +0000284//===----------------------------------------------------------------------===//
285// DIEDelta - A simple label difference DIE.
286//
287struct DIEDelta : public DIEValue {
288 const DWLabel LabelHi;
289 const DWLabel LabelLo;
290
291 DIEDelta(const DWLabel &Hi, const DWLabel &Lo)
292 : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {}
Jim Laskey063e7652006-01-17 17:31:53 +0000293
Jim Laskey0d086af2006-02-27 12:43:29 +0000294 // Implement isa/cast/dyncast.
295 static bool classof(const DIEDelta *) { return true; }
296 static bool classof(const DIEValue *D) { return D->Type == isDelta; }
297
298 /// EmitValue - Emit delta value.
299 ///
300 virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
301
302 /// SizeOf - Determine size of delta value in bytes.
303 ///
304 virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
305};
Jim Laskey063e7652006-01-17 17:31:53 +0000306
Jim Laskey0d086af2006-02-27 12:43:29 +0000307//===----------------------------------------------------------------------===//
308// DIEntry - A pointer to a debug information entry.
309//
310struct DIEntry : public DIEValue {
311 DIE *Entry;
312
313 DIEntry(DIE *E) : DIEValue(isEntry), Entry(E) {}
314
315 // Implement isa/cast/dyncast.
316 static bool classof(const DIEntry *) { return true; }
317 static bool classof(const DIEValue *E) { return E->Type == isEntry; }
318
319 /// EmitValue - Emit delta value.
320 ///
321 virtual void EmitValue(const DwarfWriter &DW, unsigned Form) const;
322
323 /// SizeOf - Determine size of delta value in bytes.
324 ///
325 virtual unsigned SizeOf(const DwarfWriter &DW, unsigned Form) const;
326};
327
328//===----------------------------------------------------------------------===//
329// DIE - A structured debug information entry. Has an abbreviation which
330// describes it's organization.
331class DIE {
332private:
333 DIEAbbrev *Abbrev; // Temporary buffer for abbreviation.
334 unsigned AbbrevID; // Decribing abbreviation ID.
335 unsigned Offset; // Offset in debug info section.
336 unsigned Size; // Size of instance + children.
337 std::vector<DIE *> Children; // Children DIEs.
338 std::vector<DIEValue *> Values; // Attributes values.
339
340public:
341 DIE(unsigned Tag);
342 ~DIE();
343
Jim Laskeybd761842006-02-27 17:27:12 +0000344 // Accessors.
Jim Laskey0d086af2006-02-27 12:43:29 +0000345 unsigned getAbbrevID() const { return AbbrevID; }
346 unsigned getOffset() const { return Offset; }
347 unsigned getSize() const { return Size; }
348 const std::vector<DIE *> &getChildren() const { return Children; }
349 const std::vector<DIEValue *> &getValues() const { return Values; }
350 void setOffset(unsigned O) { Offset = O; }
351 void setSize(unsigned S) { Size = S; }
352
353 /// SiblingOffset - Return the offset of the debug information entry's
354 /// sibling.
355 unsigned SiblingOffset() const { return Offset + Size; }
356
357 /// AddUInt - Add an unsigned integer attribute data and value.
358 ///
359 void AddUInt(unsigned Attribute, unsigned Form, uint64_t Integer);
360
361 /// AddSInt - Add an signed integer attribute data and value.
362 ///
363 void AddSInt(unsigned Attribute, unsigned Form, int64_t Integer);
364
365 /// AddString - Add a std::string attribute data and value.
366 ///
367 void AddString(unsigned Attribute, unsigned Form,
368 const std::string &String);
369
370 /// AddLabel - Add a Dwarf label attribute data and value.
371 ///
372 void AddLabel(unsigned Attribute, unsigned Form, const DWLabel &Label);
373
374 /// AddObjectLabel - Add a non-Dwarf label attribute data and value.
375 ///
376 void AddObjectLabel(unsigned Attribute, unsigned Form,
377 const std::string &Label);
378
379 /// AddDelta - Add a label delta attribute data and value.
380 ///
381 void AddDelta(unsigned Attribute, unsigned Form,
382 const DWLabel &Hi, const DWLabel &Lo);
383
384 /// AddDIEntry - Add a DIE attribute data and value.
385 ///
386 void AddDIEntry(unsigned Attribute, unsigned Form, DIE *Entry);
387
388 /// Complete - Indicate that all attributes have been added and
389 /// ready to get an abbreviation ID.
390 ///
391 void Complete(DwarfWriter &DW);
392
393 /// AddChild - Add a child to the DIE.
394 void AddChild(DIE *Child);
395};
396
397} // End of namespace llvm
Jim Laskey063e7652006-01-17 17:31:53 +0000398
399//===----------------------------------------------------------------------===//
400
Jim Laskeybd761842006-02-27 17:27:12 +0000401CompileUnit::~CompileUnit() {
402 delete Die;
403}
404
405/// hasContent - Return true if this compile unit has something to write out.
406///
407bool CompileUnit::hasContent() const {
408 return !Die->getChildren().empty();
409}
410
411/// AddGlobal - Add a new global entity to the compile unit.
412///
413void CompileUnit::AddGlobal(const std::string &Name, DIE *Die) {
414 Globals[Name] = Die;
415}
416
417//===----------------------------------------------------------------------===//
418
Jim Laskeyd18e2892006-01-20 20:34:06 +0000419/// operator== - Used by UniqueVector to locate entry.
420///
421bool DIEAbbrev::operator==(const DIEAbbrev &DA) const {
422 if (Tag != DA.Tag) return false;
423 if (ChildrenFlag != DA.ChildrenFlag) return false;
424 if (Data.size() != DA.Data.size()) return false;
425
Jim Laskey52060a02006-01-24 00:49:18 +0000426 for (unsigned i = 0, N = Data.size(); i < N; ++i) {
Jim Laskey63ae85f2006-01-21 01:13:18 +0000427 if (Data[i] != DA.Data[i]) return false;
Jim Laskeyd18e2892006-01-20 20:34:06 +0000428 }
429
430 return true;
431}
432
433/// operator< - Used by UniqueVector to locate entry.
434///
435bool DIEAbbrev::operator<(const DIEAbbrev &DA) const {
436 if (Tag != DA.Tag) return Tag < DA.Tag;
437 if (ChildrenFlag != DA.ChildrenFlag) return ChildrenFlag < DA.ChildrenFlag;
438 if (Data.size() != DA.Data.size()) return Data.size() < DA.Data.size();
439
Jim Laskey52060a02006-01-24 00:49:18 +0000440 for (unsigned i = 0, N = Data.size(); i < N; ++i) {
Jim Laskey63ae85f2006-01-21 01:13:18 +0000441 if (Data[i] != DA.Data[i]) return Data[i] < DA.Data[i];
Jim Laskeyd18e2892006-01-20 20:34:06 +0000442 }
443
444 return false;
445}
446
447/// Emit - Print the abbreviation using the specified Dwarf writer.
448///
449void DIEAbbrev::Emit(const DwarfWriter &DW) const {
450 // Emit its Dwarf tag type.
451 DW.EmitULEB128Bytes(Tag);
452 DW.EOL(TagString(Tag));
453
454 // Emit whether it has children DIEs.
455 DW.EmitULEB128Bytes(ChildrenFlag);
456 DW.EOL(ChildrenString(ChildrenFlag));
457
458 // For each attribute description.
Jim Laskey52060a02006-01-24 00:49:18 +0000459 for (unsigned i = 0, N = Data.size(); i < N; ++i) {
Jim Laskeyd18e2892006-01-20 20:34:06 +0000460 const DIEAbbrevData &AttrData = Data[i];
461
462 // Emit attribute type.
463 DW.EmitULEB128Bytes(AttrData.getAttribute());
464 DW.EOL(AttributeString(AttrData.getAttribute()));
465
466 // Emit form type.
467 DW.EmitULEB128Bytes(AttrData.getForm());
468 DW.EOL(FormEncodingString(AttrData.getForm()));
469 }
470
471 // Mark end of abbreviation.
472 DW.EmitULEB128Bytes(0); DW.EOL("EOM(1)");
473 DW.EmitULEB128Bytes(0); DW.EOL("EOM(2)");
474}
475
476#ifndef NDEBUG
477 void DIEAbbrev::print(std::ostream &O) {
478 O << "Abbreviation @"
Jeff Cohen05ebc8d2006-01-25 17:18:50 +0000479 << std::hex << (intptr_t)this << std::dec
Jim Laskeyd18e2892006-01-20 20:34:06 +0000480 << " "
481 << TagString(Tag)
482 << " "
483 << ChildrenString(ChildrenFlag)
484 << "\n";
485
Jim Laskey52060a02006-01-24 00:49:18 +0000486 for (unsigned i = 0, N = Data.size(); i < N; ++i) {
Jim Laskeyd18e2892006-01-20 20:34:06 +0000487 O << " "
488 << AttributeString(Data[i].getAttribute())
489 << " "
490 << FormEncodingString(Data[i].getForm())
491 << "\n";
492 }
493 }
494 void DIEAbbrev::dump() { print(std::cerr); }
495#endif
496
497//===----------------------------------------------------------------------===//
498
Jim Laskey063e7652006-01-17 17:31:53 +0000499/// EmitValue - Emit integer of appropriate size.
500///
501void DIEInteger::EmitValue(const DwarfWriter &DW, unsigned Form) const {
502 switch (Form) {
Jim Laskey40020172006-01-20 21:02:36 +0000503 case DW_FORM_flag: // Fall thru
Jim Laskeyda427fa2006-01-27 20:31:25 +0000504 case DW_FORM_data1: DW.EmitInt8(Integer); break;
505 case DW_FORM_data2: DW.EmitInt16(Integer); break;
506 case DW_FORM_data4: DW.EmitInt32(Integer); break;
507 case DW_FORM_data8: DW.EmitInt64(Integer); break;
Jim Laskey40020172006-01-20 21:02:36 +0000508 case DW_FORM_udata: DW.EmitULEB128Bytes(Integer); break;
509 case DW_FORM_sdata: DW.EmitSLEB128Bytes(Integer); break;
Jim Laskeyf01e5472006-03-03 15:06:57 +0000510 // FIXME - Punting on field offsets.
511 case DW_FORM_block1: {
512 DW.EmitInt8(1 + DW.SizeULEB128(Integer)); DW.EOL("Form1 Size");
513 DW.EmitInt8(DW_OP_plus_uconst); DW.EOL("DW_OP_plus_uconst");
514 DW.EmitULEB128Bytes(Integer);
515 break;
516 }
Jim Laskey063e7652006-01-17 17:31:53 +0000517 default: assert(0 && "DIE Value form not supported yet"); break;
518 }
519}
520
521/// SizeOf - Determine size of integer value in bytes.
522///
523unsigned DIEInteger::SizeOf(const DwarfWriter &DW, unsigned Form) const {
524 switch (Form) {
Jim Laskeyd18e2892006-01-20 20:34:06 +0000525 case DW_FORM_flag: // Fall thru
Jim Laskey063e7652006-01-17 17:31:53 +0000526 case DW_FORM_data1: return sizeof(int8_t);
527 case DW_FORM_data2: return sizeof(int16_t);
528 case DW_FORM_data4: return sizeof(int32_t);
Jim Laskeyd8f77ba2006-01-27 15:20:54 +0000529 case DW_FORM_data8: return sizeof(int64_t);
Jim Laskey40020172006-01-20 21:02:36 +0000530 case DW_FORM_udata: return DW.SizeULEB128(Integer);
531 case DW_FORM_sdata: return DW.SizeSLEB128(Integer);
Jim Laskeyf01e5472006-03-03 15:06:57 +0000532 // FIXME - Punting on field offsets.
533 case DW_FORM_block1: return 2 + DW.SizeULEB128(Integer);
Jim Laskey063e7652006-01-17 17:31:53 +0000534 default: assert(0 && "DIE Value form not supported yet"); break;
535 }
536 return 0;
537}
538
539//===----------------------------------------------------------------------===//
540
541/// EmitValue - Emit string value.
542///
543void DIEString::EmitValue(const DwarfWriter &DW, unsigned Form) const {
Jim Laskeyd18e2892006-01-20 20:34:06 +0000544 DW.EmitString(String);
Jim Laskey063e7652006-01-17 17:31:53 +0000545}
546
547/// SizeOf - Determine size of string value in bytes.
548///
549unsigned DIEString::SizeOf(const DwarfWriter &DW, unsigned Form) const {
Jim Laskey40020172006-01-20 21:02:36 +0000550 return String.size() + sizeof(char); // sizeof('\0');
Jim Laskey063e7652006-01-17 17:31:53 +0000551}
552
553//===----------------------------------------------------------------------===//
554
555/// EmitValue - Emit label value.
556///
Jim Laskey52060a02006-01-24 00:49:18 +0000557void DIEDwarfLabel::EmitValue(const DwarfWriter &DW, unsigned Form) const {
Jim Laskeyd18e2892006-01-20 20:34:06 +0000558 DW.EmitReference(Label);
Jim Laskey063e7652006-01-17 17:31:53 +0000559}
560
561/// SizeOf - Determine size of label value in bytes.
562///
Jim Laskey52060a02006-01-24 00:49:18 +0000563unsigned DIEDwarfLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
Jim Laskey063e7652006-01-17 17:31:53 +0000564 return DW.getAddressSize();
565}
566
567//===----------------------------------------------------------------------===//
568
Jim Laskeyd18e2892006-01-20 20:34:06 +0000569/// EmitValue - Emit label value.
570///
Jim Laskey52060a02006-01-24 00:49:18 +0000571void DIEObjectLabel::EmitValue(const DwarfWriter &DW, unsigned Form) const {
Jim Laskeyda427fa2006-01-27 20:31:25 +0000572 DW.EmitInt8(sizeof(int8_t) + DW.getAddressSize());
Jim Laskey52060a02006-01-24 00:49:18 +0000573 DW.EOL("DW_FORM_block1 length");
574
Jim Laskeyda427fa2006-01-27 20:31:25 +0000575 DW.EmitInt8(DW_OP_addr);
Jim Laskey52060a02006-01-24 00:49:18 +0000576 DW.EOL("DW_OP_addr");
577
Jim Laskeyd18e2892006-01-20 20:34:06 +0000578 DW.EmitReference(Label);
579}
580
581/// SizeOf - Determine size of label value in bytes.
582///
Jim Laskey52060a02006-01-24 00:49:18 +0000583unsigned DIEObjectLabel::SizeOf(const DwarfWriter &DW, unsigned Form) const {
584 return sizeof(int8_t) + sizeof(int8_t) + DW.getAddressSize();
Jim Laskeyd18e2892006-01-20 20:34:06 +0000585}
586
587//===----------------------------------------------------------------------===//
588
Jim Laskey063e7652006-01-17 17:31:53 +0000589/// EmitValue - Emit delta value.
590///
591void DIEDelta::EmitValue(const DwarfWriter &DW, unsigned Form) const {
Jim Laskeyd18e2892006-01-20 20:34:06 +0000592 DW.EmitDifference(LabelHi, LabelLo);
Jim Laskey063e7652006-01-17 17:31:53 +0000593}
594
595/// SizeOf - Determine size of delta value in bytes.
596///
597unsigned DIEDelta::SizeOf(const DwarfWriter &DW, unsigned Form) const {
598 return DW.getAddressSize();
599}
600
601//===----------------------------------------------------------------------===//
Jim Laskeyd18e2892006-01-20 20:34:06 +0000602/// EmitValue - Emit extry offset.
603///
604void DIEntry::EmitValue(const DwarfWriter &DW, unsigned Form) const {
Jim Laskeyda427fa2006-01-27 20:31:25 +0000605 DW.EmitInt32(Entry->getOffset());
Jim Laskeyd18e2892006-01-20 20:34:06 +0000606}
607
608/// SizeOf - Determine size of label value in bytes.
609///
610unsigned DIEntry::SizeOf(const DwarfWriter &DW, unsigned Form) const {
611 return sizeof(int32_t);
612}
613
614//===----------------------------------------------------------------------===//
615
Jim Laskey0420f2a2006-02-22 19:02:11 +0000616DIE::DIE(unsigned Tag)
617: Abbrev(new DIEAbbrev(Tag, DW_CHILDREN_no))
Jim Laskeyd18e2892006-01-20 20:34:06 +0000618, AbbrevID(0)
619, Offset(0)
620, Size(0)
Jim Laskeyd18e2892006-01-20 20:34:06 +0000621, Children()
622, Values()
623{}
624
625DIE::~DIE() {
626 if (Abbrev) delete Abbrev;
627
Jim Laskey52060a02006-01-24 00:49:18 +0000628 for (unsigned i = 0, N = Children.size(); i < N; ++i) {
Jim Laskeyd18e2892006-01-20 20:34:06 +0000629 delete Children[i];
630 }
631
Jim Laskey52060a02006-01-24 00:49:18 +0000632 for (unsigned j = 0, M = Values.size(); j < M; ++j) {
Jim Laskeyd18e2892006-01-20 20:34:06 +0000633 delete Values[j];
634 }
Jim Laskeyd18e2892006-01-20 20:34:06 +0000635}
636
Jim Laskeyd8f77ba2006-01-27 15:20:54 +0000637/// AddUInt - Add an unsigned integer attribute data and value.
Jim Laskeyd18e2892006-01-20 20:34:06 +0000638///
Jim Laskeyd8f77ba2006-01-27 15:20:54 +0000639void DIE::AddUInt(unsigned Attribute, unsigned Form, uint64_t Integer) {
Jim Laskey40020172006-01-20 21:02:36 +0000640 if (Form == 0) {
Jim Laskey40020172006-01-20 21:02:36 +0000641 if ((unsigned char)Integer == Integer) Form = DW_FORM_data1;
642 else if ((unsigned short)Integer == Integer) Form = DW_FORM_data2;
Jim Laskeyd8f77ba2006-01-27 15:20:54 +0000643 else if ((unsigned int)Integer == Integer) Form = DW_FORM_data4;
644 else Form = DW_FORM_data8;
645 }
646 Abbrev->AddAttribute(Attribute, Form);
647 Values.push_back(new DIEInteger(Integer));
648}
649
650/// AddSInt - Add an signed integer attribute data and value.
651///
652void DIE::AddSInt(unsigned Attribute, unsigned Form, int64_t Integer) {
653 if (Form == 0) {
654 if ((char)Integer == Integer) Form = DW_FORM_data1;
655 else if ((short)Integer == Integer) Form = DW_FORM_data2;
656 else if ((int)Integer == Integer) Form = DW_FORM_data4;
657 else Form = DW_FORM_data8;
Jim Laskey40020172006-01-20 21:02:36 +0000658 }
Jim Laskeyd18e2892006-01-20 20:34:06 +0000659 Abbrev->AddAttribute(Attribute, Form);
660 Values.push_back(new DIEInteger(Integer));
661}
662
663/// AddString - Add a std::string attribute data and value.
664///
665void DIE::AddString(unsigned Attribute, unsigned Form,
666 const std::string &String) {
667 Abbrev->AddAttribute(Attribute, Form);
668 Values.push_back(new DIEString(String));
669}
670
671/// AddLabel - Add a Dwarf label attribute data and value.
672///
673void DIE::AddLabel(unsigned Attribute, unsigned Form,
674 const DWLabel &Label) {
675 Abbrev->AddAttribute(Attribute, Form);
Jim Laskey52060a02006-01-24 00:49:18 +0000676 Values.push_back(new DIEDwarfLabel(Label));
Jim Laskeyd18e2892006-01-20 20:34:06 +0000677}
678
Jim Laskey52060a02006-01-24 00:49:18 +0000679/// AddObjectLabel - Add an non-Dwarf label attribute data and value.
Jim Laskeyd18e2892006-01-20 20:34:06 +0000680///
Jim Laskey52060a02006-01-24 00:49:18 +0000681void DIE::AddObjectLabel(unsigned Attribute, unsigned Form,
682 const std::string &Label) {
Jim Laskeyd18e2892006-01-20 20:34:06 +0000683 Abbrev->AddAttribute(Attribute, Form);
Jim Laskey52060a02006-01-24 00:49:18 +0000684 Values.push_back(new DIEObjectLabel(Label));
Jim Laskeyd18e2892006-01-20 20:34:06 +0000685}
686
687/// AddDelta - Add a label delta attribute data and value.
688///
689void DIE::AddDelta(unsigned Attribute, unsigned Form,
690 const DWLabel &Hi, const DWLabel &Lo) {
691 Abbrev->AddAttribute(Attribute, Form);
692 Values.push_back(new DIEDelta(Hi, Lo));
693}
694
695/// AddDIEntry - Add a DIE attribute data and value.
696///
697void DIE::AddDIEntry(unsigned Attribute,
698 unsigned Form, DIE *Entry) {
699 Abbrev->AddAttribute(Attribute, Form);
700 Values.push_back(new DIEntry(Entry));
701}
702
703/// Complete - Indicate that all attributes have been added and ready to get an
704/// abbreviation ID.
705void DIE::Complete(DwarfWriter &DW) {
706 AbbrevID = DW.NewAbbreviation(Abbrev);
707 delete Abbrev;
708 Abbrev = NULL;
709}
710
711/// AddChild - Add a child to the DIE.
712///
713void DIE::AddChild(DIE *Child) {
Jim Laskey0420f2a2006-02-22 19:02:11 +0000714 assert(Abbrev && "Adding children without an abbreviation");
715 Abbrev->setChildrenFlag(DW_CHILDREN_yes);
Jim Laskeyd18e2892006-01-20 20:34:06 +0000716 Children.push_back(Child);
717}
718
719//===----------------------------------------------------------------------===//
720
Jim Laskey0420f2a2006-02-22 19:02:11 +0000721/// DWContext
Jim Laskeyd18e2892006-01-20 20:34:06 +0000722
723//===----------------------------------------------------------------------===//
Jim Laskey063e7652006-01-17 17:31:53 +0000724
725/// PrintHex - Print a value as a hexidecimal value.
726///
727void DwarfWriter::PrintHex(int Value) const {
728 O << "0x" << std::hex << Value << std::dec;
729}
730
731/// EOL - Print a newline character to asm stream. If a comment is present
732/// then it will be printed first. Comments should not contain '\n'.
733void DwarfWriter::EOL(const std::string &Comment) const {
734 if (DwarfVerbose) {
735 O << "\t"
736 << Asm->CommentString
737 << " "
738 << Comment;
739 }
740 O << "\n";
741}
Jim Laskeya7cea6f2006-01-04 13:52:30 +0000742
743/// EmitULEB128Bytes - Emit an assembler byte data directive to compose an
Jim Laskey063e7652006-01-17 17:31:53 +0000744/// unsigned leb128 value.
745void DwarfWriter::EmitULEB128Bytes(unsigned Value) const {
Jim Laskeya7cea6f2006-01-04 13:52:30 +0000746 if (hasLEB128) {
747 O << "\t.uleb128\t"
748 << Value;
749 } else {
Jim Laskeyb2efb852006-01-04 22:28:25 +0000750 O << Asm->Data8bitsDirective;
Jim Laskey063e7652006-01-17 17:31:53 +0000751 PrintULEB128(Value);
Jim Laskeya7cea6f2006-01-04 13:52:30 +0000752 }
Jim Laskeya7cea6f2006-01-04 13:52:30 +0000753}
754
755/// EmitSLEB128Bytes - Emit an assembler byte data directive to compose a
Jim Laskey063e7652006-01-17 17:31:53 +0000756/// signed leb128 value.
757void DwarfWriter::EmitSLEB128Bytes(int Value) const {
Jim Laskeya7cea6f2006-01-04 13:52:30 +0000758 if (hasLEB128) {
759 O << "\t.sleb128\t"
760 << Value;
761 } else {
Jim Laskeyb2efb852006-01-04 22:28:25 +0000762 O << Asm->Data8bitsDirective;
Jim Laskey063e7652006-01-17 17:31:53 +0000763 PrintSLEB128(Value);
Jim Laskeya7cea6f2006-01-04 13:52:30 +0000764 }
Jim Laskeya7cea6f2006-01-04 13:52:30 +0000765}
766
Jim Laskey063e7652006-01-17 17:31:53 +0000767/// PrintULEB128 - Print a series of hexidecimal values (separated by commas)
Jim Laskeyb2efb852006-01-04 22:28:25 +0000768/// representing an unsigned leb128 value.
Jim Laskey063e7652006-01-17 17:31:53 +0000769void DwarfWriter::PrintULEB128(unsigned Value) const {
Jim Laskeyb2efb852006-01-04 22:28:25 +0000770 do {
771 unsigned Byte = Value & 0x7f;
772 Value >>= 7;
773 if (Value) Byte |= 0x80;
Jim Laskey063e7652006-01-17 17:31:53 +0000774 PrintHex(Byte);
Jim Laskeyb2efb852006-01-04 22:28:25 +0000775 if (Value) O << ", ";
776 } while (Value);
777}
778
Jim Laskey063e7652006-01-17 17:31:53 +0000779/// SizeULEB128 - Compute the number of bytes required for an unsigned leb128
780/// value.
781unsigned DwarfWriter::SizeULEB128(unsigned Value) {
782 unsigned Size = 0;
783 do {
784 Value >>= 7;
785 Size += sizeof(int8_t);
786 } while (Value);
787 return Size;
788}
789
790/// PrintSLEB128 - Print a series of hexidecimal values (separated by commas)
Jim Laskeyb2efb852006-01-04 22:28:25 +0000791/// representing a signed leb128 value.
Jim Laskey063e7652006-01-17 17:31:53 +0000792void DwarfWriter::PrintSLEB128(int Value) const {
Jim Laskeyb2efb852006-01-04 22:28:25 +0000793 int Sign = Value >> (8 * sizeof(Value) - 1);
794 bool IsMore;
Jim Laskeya7cea6f2006-01-04 13:52:30 +0000795
Jim Laskeyb2efb852006-01-04 22:28:25 +0000796 do {
797 unsigned Byte = Value & 0x7f;
798 Value >>= 7;
799 IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
800 if (IsMore) Byte |= 0x80;
Jim Laskey063e7652006-01-17 17:31:53 +0000801 PrintHex(Byte);
Jim Laskeyb2efb852006-01-04 22:28:25 +0000802 if (IsMore) O << ", ";
803 } while (IsMore);
804}
805
Jim Laskey063e7652006-01-17 17:31:53 +0000806/// SizeSLEB128 - Compute the number of bytes required for a signed leb128
807/// value.
808unsigned DwarfWriter::SizeSLEB128(int Value) {
809 unsigned Size = 0;
810 int Sign = Value >> (8 * sizeof(Value) - 1);
811 bool IsMore;
812
813 do {
814 unsigned Byte = Value & 0x7f;
815 Value >>= 7;
816 IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
817 Size += sizeof(int8_t);
818 } while (IsMore);
819 return Size;
820}
821
Jim Laskeyda427fa2006-01-27 20:31:25 +0000822/// EmitInt8 - Emit a byte directive and value.
Jim Laskeyb2efb852006-01-04 22:28:25 +0000823///
Jim Laskeyda427fa2006-01-27 20:31:25 +0000824void DwarfWriter::EmitInt8(int Value) const {
Jim Laskey063e7652006-01-17 17:31:53 +0000825 O << Asm->Data8bitsDirective;
Jim Laskey0420f2a2006-02-22 19:02:11 +0000826 PrintHex(Value & 0xFF);
Jim Laskey063e7652006-01-17 17:31:53 +0000827}
828
Jim Laskeyda427fa2006-01-27 20:31:25 +0000829/// EmitInt16 - Emit a short directive and value.
Jim Laskey063e7652006-01-17 17:31:53 +0000830///
Jim Laskeyda427fa2006-01-27 20:31:25 +0000831void DwarfWriter::EmitInt16(int Value) const {
Jim Laskey063e7652006-01-17 17:31:53 +0000832 O << Asm->Data16bitsDirective;
Jim Laskey0420f2a2006-02-22 19:02:11 +0000833 PrintHex(Value & 0xFFFF);
Jim Laskey063e7652006-01-17 17:31:53 +0000834}
835
Jim Laskeyda427fa2006-01-27 20:31:25 +0000836/// EmitInt32 - Emit a long directive and value.
Jim Laskey063e7652006-01-17 17:31:53 +0000837///
Jim Laskeyda427fa2006-01-27 20:31:25 +0000838void DwarfWriter::EmitInt32(int Value) const {
Jim Laskey063e7652006-01-17 17:31:53 +0000839 O << Asm->Data32bitsDirective;
840 PrintHex(Value);
841}
842
Jim Laskeyda427fa2006-01-27 20:31:25 +0000843/// EmitInt64 - Emit a long long directive and value.
Jim Laskeyd8f77ba2006-01-27 15:20:54 +0000844///
Jim Laskeyda427fa2006-01-27 20:31:25 +0000845void DwarfWriter::EmitInt64(uint64_t Value) const {
Jim Laskeyd8f77ba2006-01-27 15:20:54 +0000846 if (Asm->Data64bitsDirective) {
847 O << Asm->Data64bitsDirective << "0x" << std::hex << Value << std::dec;
848 } else {
849 const TargetData &TD = Asm->TM.getTargetData();
850
851 if (TD.isBigEndian()) {
Jim Laskeyda427fa2006-01-27 20:31:25 +0000852 EmitInt32(unsigned(Value >> 32)); O << "\n";
853 EmitInt32(unsigned(Value));
Jim Laskeyd8f77ba2006-01-27 15:20:54 +0000854 } else {
Jim Laskeyda427fa2006-01-27 20:31:25 +0000855 EmitInt32(unsigned(Value)); O << "\n";
856 EmitInt32(unsigned(Value >> 32));
Jim Laskeyd8f77ba2006-01-27 15:20:54 +0000857 }
858 }
859}
860
Jim Laskey063e7652006-01-17 17:31:53 +0000861/// EmitString - Emit a string with quotes and a null terminator.
862/// Special characters are emitted properly. (Eg. '\t')
863void DwarfWriter::EmitString(const std::string &String) const {
864 O << Asm->AsciiDirective
865 << "\"";
Jim Laskey52060a02006-01-24 00:49:18 +0000866 for (unsigned i = 0, N = String.size(); i < N; ++i) {
Jim Laskey063e7652006-01-17 17:31:53 +0000867 unsigned char C = String[i];
868
869 if (!isascii(C) || iscntrl(C)) {
870 switch(C) {
871 case '\b': O << "\\b"; break;
872 case '\f': O << "\\f"; break;
873 case '\n': O << "\\n"; break;
874 case '\r': O << "\\r"; break;
875 case '\t': O << "\\t"; break;
876 default:
877 O << '\\';
878 O << char('0' + (C >> 6));
879 O << char('0' + (C >> 3));
880 O << char('0' + (C >> 0));
881 break;
882 }
883 } else if (C == '\"') {
884 O << "\\\"";
885 } else if (C == '\'') {
886 O << "\\\'";
887 } else {
888 O << C;
889 }
890 }
891 O << "\\0\"";
892}
893
894/// PrintLabelName - Print label name in form used by Dwarf writer.
895///
896void DwarfWriter::PrintLabelName(const char *Tag, unsigned Number) const {
Jim Laskeyb2efb852006-01-04 22:28:25 +0000897 O << Asm->PrivateGlobalPrefix
898 << "debug_"
Jim Laskey0420f2a2006-02-22 19:02:11 +0000899 << Tag;
900 if (Number) O << Number;
Jim Laskeyb2efb852006-01-04 22:28:25 +0000901}
902
Jim Laskey063e7652006-01-17 17:31:53 +0000903/// EmitLabel - Emit location label for internal use by Dwarf.
Jim Laskeyb2efb852006-01-04 22:28:25 +0000904///
Jim Laskey063e7652006-01-17 17:31:53 +0000905void DwarfWriter::EmitLabel(const char *Tag, unsigned Number) const {
906 PrintLabelName(Tag, Number);
Jim Laskeyb2efb852006-01-04 22:28:25 +0000907 O << ":\n";
908}
909
Jim Laskeye719a7c2006-01-18 16:54:26 +0000910/// EmitReference - Emit a reference to a label.
Jim Laskey063e7652006-01-17 17:31:53 +0000911///
Jim Laskeye719a7c2006-01-18 16:54:26 +0000912void DwarfWriter::EmitReference(const char *Tag, unsigned Number) const {
Jim Laskey063e7652006-01-17 17:31:53 +0000913 if (AddressSize == 4)
914 O << Asm->Data32bitsDirective;
915 else
916 O << Asm->Data64bitsDirective;
917
918 PrintLabelName(Tag, Number);
919}
Jim Laskey73683212006-01-21 00:59:54 +0000920void DwarfWriter::EmitReference(const std::string &Name) const {
Jim Laskeyd18e2892006-01-20 20:34:06 +0000921 if (AddressSize == 4)
922 O << Asm->Data32bitsDirective;
923 else
924 O << Asm->Data64bitsDirective;
925
926 O << Name;
927}
Jim Laskey063e7652006-01-17 17:31:53 +0000928
929/// EmitDifference - Emit an label difference as sizeof(pointer) value. Some
930/// assemblers do not accept absolute expressions with data directives, so there
931/// is an option (needsSet) to use an intermediary 'set' expression.
Jim Laskeyd18e2892006-01-20 20:34:06 +0000932void DwarfWriter::EmitDifference(const char *TagHi, unsigned NumberHi,
933 const char *TagLo, unsigned NumberLo) const {
Jim Laskey063e7652006-01-17 17:31:53 +0000934 if (needsSet) {
935 static unsigned SetCounter = 0;
Jim Laskeyd18e2892006-01-20 20:34:06 +0000936
Jim Laskey063e7652006-01-17 17:31:53 +0000937 O << "\t.set\t";
938 PrintLabelName("set", SetCounter);
939 O << ",";
Jim Laskeyd18e2892006-01-20 20:34:06 +0000940 PrintLabelName(TagHi, NumberHi);
Jim Laskey063e7652006-01-17 17:31:53 +0000941 O << "-";
Jim Laskeyd18e2892006-01-20 20:34:06 +0000942 PrintLabelName(TagLo, NumberLo);
Jim Laskey063e7652006-01-17 17:31:53 +0000943 O << "\n";
944
945 if (AddressSize == sizeof(int32_t))
946 O << Asm->Data32bitsDirective;
947 else
948 O << Asm->Data64bitsDirective;
949
950 PrintLabelName("set", SetCounter);
951
Jim Laskey52060a02006-01-24 00:49:18 +0000952 ++SetCounter;
Jim Laskey063e7652006-01-17 17:31:53 +0000953 } else {
954 if (AddressSize == sizeof(int32_t))
955 O << Asm->Data32bitsDirective;
956 else
957 O << Asm->Data64bitsDirective;
958
Jim Laskeyd18e2892006-01-20 20:34:06 +0000959 PrintLabelName(TagHi, NumberHi);
Jim Laskey063e7652006-01-17 17:31:53 +0000960 O << "-";
Jim Laskeyd18e2892006-01-20 20:34:06 +0000961 PrintLabelName(TagLo, NumberLo);
Jim Laskey063e7652006-01-17 17:31:53 +0000962 }
963}
964
Jim Laskeyd18e2892006-01-20 20:34:06 +0000965/// NewAbbreviation - Add the abbreviation to the Abbreviation vector.
Jim Laskey063e7652006-01-17 17:31:53 +0000966///
Jim Laskeyd18e2892006-01-20 20:34:06 +0000967unsigned DwarfWriter::NewAbbreviation(DIEAbbrev *Abbrev) {
968 return Abbreviations.insert(*Abbrev);
969}
970
971/// NewString - Add a string to the constant pool and returns a label.
972///
973DWLabel DwarfWriter::NewString(const std::string &String) {
974 unsigned StringID = StringPool.insert(String);
975 return DWLabel("string", StringID);
976}
977
Jim Laskey0420f2a2006-02-22 19:02:11 +0000978/// NewBasicType - Creates a new basic type if necessary, then adds to the
979/// owner.
980/// FIXME - Should never be needed.
Jim Laskey92ae7402006-03-01 18:20:30 +0000981DIE *DwarfWriter::NewBasicType(DIE *Context, Type *Ty) {
Jim Laskey0420f2a2006-02-22 19:02:11 +0000982 DIE *&Slot = TypeToDieMap[Ty];
983 if (Slot) return Slot;
984
985 const char *Name;
986 unsigned Size;
987 unsigned Encoding = 0;
988
989 switch (Ty->getTypeID()) {
990 case Type::UByteTyID:
991 Name = "unsigned char";
992 Size = 1;
993 Encoding = DW_ATE_unsigned_char;
994 break;
995 case Type::SByteTyID:
996 Name = "char";
997 Size = 1;
998 Encoding = DW_ATE_signed_char;
999 break;
1000 case Type::UShortTyID:
1001 Name = "unsigned short";
1002 Size = 2;
1003 Encoding = DW_ATE_unsigned;
1004 break;
1005 case Type::ShortTyID:
1006 Name = "short";
1007 Size = 2;
1008 Encoding = DW_ATE_signed;
1009 break;
1010 case Type::UIntTyID:
1011 Name = "unsigned int";
1012 Size = 4;
1013 Encoding = DW_ATE_unsigned;
1014 break;
1015 case Type::IntTyID:
1016 Name = "int";
1017 Size = 4;
1018 Encoding = DW_ATE_signed;
1019 break;
1020 case Type::ULongTyID:
1021 Name = "unsigned long long";
1022 Size = 7;
1023 Encoding = DW_ATE_unsigned;
1024 break;
1025 case Type::LongTyID:
1026 Name = "long long";
1027 Size = 7;
1028 Encoding = DW_ATE_signed;
1029 break;
1030 case Type::FloatTyID:
1031 Name = "float";
1032 Size = 4;
1033 Encoding = DW_ATE_float;
1034 break;
1035 case Type::DoubleTyID:
1036 Name = "double";
1037 Size = 8;
1038 Encoding = DW_ATE_float;
1039 break;
1040 default:
1041 // FIXME - handle more complex types.
1042 Name = "unknown";
1043 Size = 1;
1044 Encoding = DW_ATE_address;
1045 break;
1046 }
1047
1048 // construct the type DIE.
1049 Slot = new DIE(DW_TAG_base_type);
1050 Slot->AddString(DW_AT_name, DW_FORM_string, Name);
1051 Slot->AddUInt (DW_AT_byte_size, 0, Size);
1052 Slot->AddUInt (DW_AT_encoding, DW_FORM_data1, Encoding);
1053
Jim Laskey92ae7402006-03-01 18:20:30 +00001054 // Add to context.
1055 Context->AddChild(Slot);
Jim Laskey0420f2a2006-02-22 19:02:11 +00001056
1057 return Slot;
1058}
1059
Jim Laskeyf4afdd92006-02-23 16:58:18 +00001060/// NewType - Create a new type DIE.
1061///
Jim Laskey92ae7402006-03-01 18:20:30 +00001062DIE *DwarfWriter::NewType(DIE *Context, TypeDesc *TyDesc) {
Jim Laskey69906002006-02-24 16:46:40 +00001063 // FIXME - hack to get around NULL types short term.
Jim Laskey92ae7402006-03-01 18:20:30 +00001064 if (!TyDesc) return NewBasicType(Context, Type::IntTy);
1065
1066 // FIXME - Should handle other contexts that compile units.
Jim Laskey69906002006-02-24 16:46:40 +00001067
Jim Laskeyf4afdd92006-02-23 16:58:18 +00001068 // Check for pre-existence.
1069 DIE *&Slot = DescToDieMap[TyDesc];
1070 if (Slot) return Slot;
1071
1072 // Get core information.
1073 const std::string &Name = TyDesc->getName();
Jim Laskey288fe0f2006-03-01 18:13:05 +00001074 uint64_t Size = TyDesc->getSize() >> 3;
Jim Laskeyf4afdd92006-02-23 16:58:18 +00001075
Jim Laskey434b40b2006-02-23 22:37:30 +00001076 DIE *Ty = NULL;
Jim Laskeyf4afdd92006-02-23 16:58:18 +00001077
Jim Laskey434b40b2006-02-23 22:37:30 +00001078 if (BasicTypeDesc *BasicTy = dyn_cast<BasicTypeDesc>(TyDesc)) {
Jim Laskey69906002006-02-24 16:46:40 +00001079 // Fundamental types like int, float, bool
Jim Laskey434b40b2006-02-23 22:37:30 +00001080 Slot = Ty = new DIE(DW_TAG_base_type);
1081 unsigned Encoding = BasicTy->getEncoding();
1082 Ty->AddUInt (DW_AT_encoding, DW_FORM_data1, Encoding);
Jim Laskey69906002006-02-24 16:46:40 +00001083 } else if (DerivedTypeDesc *DerivedTy = dyn_cast<DerivedTypeDesc>(TyDesc)) {
Jim Laskey69906002006-02-24 16:46:40 +00001084 // Create specific DIE.
Jim Laskey9c4447a2006-03-01 20:39:36 +00001085 Slot = Ty = new DIE(DerivedTy->getTag());
Jim Laskey69906002006-02-24 16:46:40 +00001086
1087 // Map to main type, void will not have a type.
1088 if (TypeDesc *FromTy = DerivedTy->getFromType()) {
Jim Laskey92ae7402006-03-01 18:20:30 +00001089 Ty->AddDIEntry(DW_AT_type, DW_FORM_ref4, NewType(Context, FromTy));
Jim Laskey69906002006-02-24 16:46:40 +00001090 }
Jim Laskeyf8913f12006-03-01 17:53:02 +00001091 } else if (CompositeTypeDesc *CompTy = dyn_cast<CompositeTypeDesc>(TyDesc)) {
Jim Laskeyf8913f12006-03-01 17:53:02 +00001092 // Create specific DIE.
Jim Laskey9c4447a2006-03-01 20:39:36 +00001093 Slot = Ty = new DIE(CompTy->getTag());
Jim Laskeyf8913f12006-03-01 17:53:02 +00001094 std::vector<DebugInfoDesc *> &Elements = CompTy->getElements();
1095
1096 switch (CompTy->getTag()) {
Jim Laskey9c4447a2006-03-01 20:39:36 +00001097 case DW_TAG_array_type: {
Jim Laskeyf8913f12006-03-01 17:53:02 +00001098 // Add element type.
1099 if (TypeDesc *FromTy = CompTy->getFromType()) {
Jim Laskey92ae7402006-03-01 18:20:30 +00001100 Ty->AddDIEntry(DW_AT_type, DW_FORM_ref4, NewType(Context, FromTy));
Jim Laskeyf8913f12006-03-01 17:53:02 +00001101 }
1102 // Don't emit size attribute.
1103 Size = 0;
1104
1105 // Construct an anonymous type for index type.
1106 DIE *IndexTy = new DIE(DW_TAG_base_type);
1107 IndexTy->AddUInt(DW_AT_byte_size, 0, 4);
1108 IndexTy->AddUInt(DW_AT_encoding, DW_FORM_data1, DW_ATE_signed);
1109 // Add to context.
Jim Laskey92ae7402006-03-01 18:20:30 +00001110 Context->AddChild(IndexTy);
Jim Laskeyf8913f12006-03-01 17:53:02 +00001111
1112 // Add subranges to array type.
1113 for(unsigned i = 0, N = Elements.size(); i < N; ++i) {
1114 SubrangeDesc *SRD = cast<SubrangeDesc>(Elements[i]);
1115 int64_t Lo = SRD->getLo();
1116 int64_t Hi = SRD->getHi();
1117 DIE *Subrange = new DIE(DW_TAG_subrange_type);
1118
1119 // If a range is available.
1120 if (Lo != Hi) {
1121 Subrange->AddDIEntry(DW_AT_type, DW_FORM_ref4, IndexTy);
1122 // Only add low if non-zero.
Jim Laskey6a3eb012006-03-01 23:52:37 +00001123 if (Lo) Subrange->AddSInt(DW_AT_lower_bound, 0, Lo);
1124 Subrange->AddSInt(DW_AT_upper_bound, 0, Hi);
Jim Laskeyf8913f12006-03-01 17:53:02 +00001125 }
1126 Ty->AddChild(Subrange);
1127 }
1128
1129 break;
1130 }
Jim Laskeyf01e5472006-03-03 15:06:57 +00001131 case DW_TAG_structure_type:
Jim Laskey9c4447a2006-03-01 20:39:36 +00001132 case DW_TAG_union_type: {
Jim Laskeyf01e5472006-03-03 15:06:57 +00001133 // FIXME - this is just the basics.
1134 // Add elements to structure type.
1135 for(unsigned i = 0, N = Elements.size(); i < N; ++i) {
1136 DerivedTypeDesc *MemberDesc = cast<DerivedTypeDesc>(Elements[i]);
1137 const std::string &Name = MemberDesc->getName();
1138 unsigned Line = MemberDesc->getLine();
1139 TypeDesc *MemTy = MemberDesc->getFromType();
1140 uint64_t Size = MemberDesc->getSize();
1141 uint64_t Offset = MemberDesc->getOffset();
1142
1143 DIE *Member = new DIE(DW_TAG_member);
1144 if (!Name.empty()) Member->AddString(DW_AT_name, DW_FORM_string, Name);
1145 if (CompileUnitDesc *File = MemberDesc->getFile()) {
1146 CompileUnit *FileUnit = FindCompileUnit(File);
1147 unsigned FileID = FileUnit->getID();
1148 int Line = TyDesc->getLine();
1149 Member->AddUInt(DW_AT_decl_file, 0, FileID);
1150 Member->AddUInt(DW_AT_decl_line, 0, Line);
1151 }
1152 if (TypeDesc *FromTy = MemberDesc->getFromType()) {
1153 Member->AddDIEntry(DW_AT_type, DW_FORM_ref4,
1154 NewType(Context, FromTy));
1155 }
1156 // FIXME - Punt on the Address.
1157 Member->AddUInt(DW_AT_data_member_location, DW_FORM_block1,
1158 Offset >> 3);
1159 Ty->AddChild(Member);
1160 }
Jim Laskeyf8913f12006-03-01 17:53:02 +00001161 break;
1162 }
Jim Laskey9c4447a2006-03-01 20:39:36 +00001163 case DW_TAG_enumeration_type: {
Jim Laskey6a3eb012006-03-01 23:52:37 +00001164 // Add enumerators to enumeration type.
1165 for(unsigned i = 0, N = Elements.size(); i < N; ++i) {
1166 EnumeratorDesc *ED = cast<EnumeratorDesc>(Elements[i]);
1167 const std::string &Name = ED->getName();
1168 int64_t Value = ED->getValue();
1169 DIE *Enumerator = new DIE(DW_TAG_enumerator);
1170 Enumerator->AddString(DW_AT_name, DW_FORM_string, Name);
1171 Enumerator->AddSInt(DW_AT_const_value, DW_FORM_sdata, Value);
1172 Ty->AddChild(Enumerator);
1173 }
1174
Jim Laskeyf8913f12006-03-01 17:53:02 +00001175 break;
1176 }
1177 default: break;
1178 }
Jim Laskeyf4afdd92006-02-23 16:58:18 +00001179 }
Jim Laskey434b40b2006-02-23 22:37:30 +00001180
1181 assert(Ty && "Type not supported yet");
Jim Laskeyf4afdd92006-02-23 16:58:18 +00001182
Jim Laskey69906002006-02-24 16:46:40 +00001183 // Add size if non-zero (derived types don't have a size.)
Jim Laskey434b40b2006-02-23 22:37:30 +00001184 if (Size) Ty->AddUInt(DW_AT_byte_size, 0, Size);
Jim Laskey69906002006-02-24 16:46:40 +00001185 // Add name if not anonymous or intermediate type.
Jim Laskey434b40b2006-02-23 22:37:30 +00001186 if (!Name.empty()) Ty->AddString(DW_AT_name, DW_FORM_string, Name);
Jim Laskey69906002006-02-24 16:46:40 +00001187 // Add source line info if present.
1188 if (CompileUnitDesc *File = TyDesc->getFile()) {
Jim Laskeybd761842006-02-27 17:27:12 +00001189 CompileUnit *FileUnit = FindCompileUnit(File);
1190 unsigned FileID = FileUnit->getID();
Jim Laskey69906002006-02-24 16:46:40 +00001191 int Line = TyDesc->getLine();
1192 Ty->AddUInt(DW_AT_decl_file, 0, FileID);
1193 Ty->AddUInt(DW_AT_decl_line, 0, Line);
1194 }
Jim Laskey434b40b2006-02-23 22:37:30 +00001195
Jim Laskeyf4afdd92006-02-23 16:58:18 +00001196 // Add to context owner.
Jim Laskey92ae7402006-03-01 18:20:30 +00001197 Context->AddChild(Ty);
Jim Laskeyf4afdd92006-02-23 16:58:18 +00001198
1199 return Slot;
1200}
1201
Jim Laskeybd761842006-02-27 17:27:12 +00001202/// NewCompileUnit - Create new compile unit and it's die.
Jim Laskey063e7652006-01-17 17:31:53 +00001203///
Jim Laskeybd761842006-02-27 17:27:12 +00001204CompileUnit *DwarfWriter::NewCompileUnit(CompileUnitDesc *UnitDesc,
1205 unsigned ID) {
1206 // Construct debug information entry.
1207 DIE *Die = new DIE(DW_TAG_compile_unit);
1208 Die->AddLabel (DW_AT_stmt_list, DW_FORM_data4, DWLabel("line", 0));
1209 Die->AddLabel (DW_AT_high_pc, DW_FORM_addr, DWLabel("text_end", 0));
1210 Die->AddLabel (DW_AT_low_pc, DW_FORM_addr, DWLabel("text_begin", 0));
1211 Die->AddString(DW_AT_producer, DW_FORM_string, UnitDesc->getProducer());
1212 Die->AddUInt (DW_AT_language, DW_FORM_data1, UnitDesc->getLanguage());
1213 Die->AddString(DW_AT_name, DW_FORM_string, UnitDesc->getFileName());
1214 Die->AddString(DW_AT_comp_dir, DW_FORM_string, UnitDesc->getDirectory());
1215
1216 // Add die to descriptor map.
1217 DescToDieMap[UnitDesc] = Die;
1218
1219 // Construct compile unit.
1220 CompileUnit *Unit = new CompileUnit(UnitDesc, ID, Die);
1221
1222 // Add Unit to compile unit map.
1223 DescToUnitMap[UnitDesc] = Unit;
1224
1225 return Unit;
1226}
Jim Laskey0420f2a2006-02-22 19:02:11 +00001227
Jim Laskeybd761842006-02-27 17:27:12 +00001228/// FindCompileUnit - Get the compile unit for the given descriptor.
1229///
1230CompileUnit *DwarfWriter::FindCompileUnit(CompileUnitDesc *UnitDesc) {
1231 CompileUnit *Unit = DescToUnitMap[UnitDesc];
1232 assert(Unit && "Missing compile unit.");
Jim Laskeyd18e2892006-01-20 20:34:06 +00001233 return Unit;
Jim Laskey063e7652006-01-17 17:31:53 +00001234}
1235
Jim Laskey0420f2a2006-02-22 19:02:11 +00001236/// NewGlobalVariable - Add a new global variable DIE.
1237///
1238DIE *DwarfWriter::NewGlobalVariable(GlobalVariableDesc *GVD) {
1239 // Check for pre-existence.
1240 DIE *&Slot = DescToDieMap[GVD];
1241 if (Slot) return Slot;
1242
1243 // Get the compile unit context.
Jim Laskeybd761842006-02-27 17:27:12 +00001244 CompileUnitDesc *UnitDesc = static_cast<CompileUnitDesc *>(GVD->getContext());
1245 CompileUnit *Unit = FindCompileUnit(UnitDesc);
Jim Laskey0420f2a2006-02-22 19:02:11 +00001246 // Get the global variable itself.
1247 GlobalVariable *GV = GVD->getGlobalVariable();
1248 // Generate the mangled name.
1249 std::string MangledName = Asm->Mang->getValueName(GV);
1250
1251 // Gather the details (simplify add attribute code.)
1252 const std::string &Name = GVD->getName();
Jim Laskeybd761842006-02-27 17:27:12 +00001253 unsigned FileID = Unit->getID();
Jim Laskey0420f2a2006-02-22 19:02:11 +00001254 unsigned Line = GVD->getLine();
1255
Jim Laskeyf4afdd92006-02-23 16:58:18 +00001256 // Get the global's type.
Jim Laskey92ae7402006-03-01 18:20:30 +00001257 DIE *Type = NewType(Unit->getDie(), GVD->getTypeDesc());
Jim Laskeyf4afdd92006-02-23 16:58:18 +00001258
1259 // Create the globale variable DIE.
Jim Laskey0420f2a2006-02-22 19:02:11 +00001260 DIE *VariableDie = new DIE(DW_TAG_variable);
1261 VariableDie->AddString (DW_AT_name, DW_FORM_string, Name);
1262 VariableDie->AddUInt (DW_AT_decl_file, 0, FileID);
1263 VariableDie->AddUInt (DW_AT_decl_line, 0, Line);
1264 VariableDie->AddDIEntry (DW_AT_type, DW_FORM_ref4, Type);
1265 VariableDie->AddUInt (DW_AT_external, DW_FORM_flag, 1);
1266 // FIXME - needs to be a proper expression.
1267 VariableDie->AddObjectLabel(DW_AT_location, DW_FORM_block1, MangledName);
1268
1269 // Add to map.
1270 Slot = VariableDie;
1271
1272 // Add to context owner.
Jim Laskeybd761842006-02-27 17:27:12 +00001273 Unit->getDie()->AddChild(VariableDie);
Jim Laskey0420f2a2006-02-22 19:02:11 +00001274
1275 // Expose as global.
Jim Laskeybd761842006-02-27 17:27:12 +00001276 // FIXME - need to check external flag.
1277 Unit->AddGlobal(Name, VariableDie);
Jim Laskey0420f2a2006-02-22 19:02:11 +00001278
1279 return VariableDie;
1280}
1281
1282/// NewSubprogram - Add a new subprogram DIE.
1283///
1284DIE *DwarfWriter::NewSubprogram(SubprogramDesc *SPD) {
1285 // Check for pre-existence.
1286 DIE *&Slot = DescToDieMap[SPD];
1287 if (Slot) return Slot;
1288
1289 // Get the compile unit context.
Jim Laskeybd761842006-02-27 17:27:12 +00001290 CompileUnitDesc *UnitDesc = static_cast<CompileUnitDesc *>(SPD->getContext());
1291 CompileUnit *Unit = FindCompileUnit(UnitDesc);
Jim Laskey0420f2a2006-02-22 19:02:11 +00001292
1293 // Gather the details (simplify add attribute code.)
1294 const std::string &Name = SPD->getName();
Jim Laskeybd761842006-02-27 17:27:12 +00001295 unsigned FileID = Unit->getID();
Jim Laskey0420f2a2006-02-22 19:02:11 +00001296 // FIXME - faking the line for the time being.
1297 unsigned Line = 1;
1298
1299 // FIXME - faking the type for the time being.
Jim Laskey92ae7402006-03-01 18:20:30 +00001300 DIE *Type = NewBasicType(Unit->getDie(), Type::IntTy);
Jim Laskey0420f2a2006-02-22 19:02:11 +00001301
Jim Laskey8a8e9752006-02-27 20:37:42 +00001302 DIE *SubprogramDie = new DIE(DW_TAG_subprogram);
Jim Laskey0420f2a2006-02-22 19:02:11 +00001303 SubprogramDie->AddString (DW_AT_name, DW_FORM_string, Name);
1304 SubprogramDie->AddUInt (DW_AT_decl_file, 0, FileID);
1305 SubprogramDie->AddUInt (DW_AT_decl_line, 0, Line);
1306 SubprogramDie->AddDIEntry (DW_AT_type, DW_FORM_ref4, Type);
1307 SubprogramDie->AddUInt (DW_AT_external, DW_FORM_flag, 1);
1308
1309 // Add to map.
1310 Slot = SubprogramDie;
1311
1312 // Add to context owner.
Jim Laskeybd761842006-02-27 17:27:12 +00001313 Unit->getDie()->AddChild(SubprogramDie);
Jim Laskey0420f2a2006-02-22 19:02:11 +00001314
1315 // Expose as global.
Jim Laskeybd761842006-02-27 17:27:12 +00001316 Unit->AddGlobal(Name, SubprogramDie);
Jim Laskey0420f2a2006-02-22 19:02:11 +00001317
1318 return SubprogramDie;
1319}
1320
Jim Laskey063e7652006-01-17 17:31:53 +00001321/// EmitInitial - Emit initial Dwarf declarations. This is necessary for cc
1322/// tools to recognize the object file contains Dwarf information.
Jim Laskeyb2efb852006-01-04 22:28:25 +00001323///
1324void DwarfWriter::EmitInitial() const {
Jim Laskey063e7652006-01-17 17:31:53 +00001325 // Dwarf sections base addresses.
Jim Laskey0420f2a2006-02-22 19:02:11 +00001326 Asm->SwitchSection(DwarfFrameSection, 0);
1327 EmitLabel("section_frame", 0);
Jim Laskeya7cea6f2006-01-04 13:52:30 +00001328 Asm->SwitchSection(DwarfInfoSection, 0);
Jim Laskey0420f2a2006-02-22 19:02:11 +00001329 EmitLabel("section_info", 0);
Jim Laskeya7cea6f2006-01-04 13:52:30 +00001330 EmitLabel("info", 0);
Jim Laskey0420f2a2006-02-22 19:02:11 +00001331 Asm->SwitchSection(DwarfAbbrevSection, 0);
1332 EmitLabel("section_abbrev", 0);
1333 EmitLabel("abbrev", 0);
1334 Asm->SwitchSection(DwarfARangesSection, 0);
1335 EmitLabel("section_aranges", 0);
1336 Asm->SwitchSection(DwarfMacInfoSection, 0);
1337 EmitLabel("section_macinfo", 0);
Jim Laskeya7cea6f2006-01-04 13:52:30 +00001338 Asm->SwitchSection(DwarfLineSection, 0);
Jim Laskey0420f2a2006-02-22 19:02:11 +00001339 EmitLabel("section_line", 0);
Jim Laskeya7cea6f2006-01-04 13:52:30 +00001340 EmitLabel("line", 0);
Jim Laskey0420f2a2006-02-22 19:02:11 +00001341 Asm->SwitchSection(DwarfLocSection, 0);
1342 EmitLabel("section_loc", 0);
1343 Asm->SwitchSection(DwarfPubNamesSection, 0);
1344 EmitLabel("section_pubnames", 0);
1345 Asm->SwitchSection(DwarfStrSection, 0);
1346 EmitLabel("section_str", 0);
1347 Asm->SwitchSection(DwarfRangesSection, 0);
1348 EmitLabel("section_ranges", 0);
1349
Jim Laskey063e7652006-01-17 17:31:53 +00001350 Asm->SwitchSection(TextSection, 0);
1351 EmitLabel("text_begin", 0);
1352 Asm->SwitchSection(DataSection, 0);
1353 EmitLabel("data_begin", 0);
Jim Laskeya7cea6f2006-01-04 13:52:30 +00001354}
1355
Jim Laskey063e7652006-01-17 17:31:53 +00001356/// EmitDIE - Recusively Emits a debug information entry.
1357///
1358void DwarfWriter::EmitDIE(DIE *Die) const {
1359 // Get the abbreviation for this DIE.
1360 unsigned AbbrevID = Die->getAbbrevID();
1361 const DIEAbbrev &Abbrev = Abbreviations[AbbrevID];
Jim Laskey0d086af2006-02-27 12:43:29 +00001362
1363 O << "\n";
Jim Laskey063e7652006-01-17 17:31:53 +00001364
1365 // Emit the code (index) for the abbreviation.
1366 EmitULEB128Bytes(AbbrevID);
1367 EOL(std::string("Abbrev [" +
1368 utostr(AbbrevID) +
Jim Laskey0d086af2006-02-27 12:43:29 +00001369 "] 0x" + utohexstr(Die->getOffset()) +
1370 ":0x" + utohexstr(Die->getSize()) + " " +
1371 TagString(Abbrev.getTag())));
Jim Laskey063e7652006-01-17 17:31:53 +00001372
1373 const std::vector<DIEValue *> &Values = Die->getValues();
Jim Laskeyd18e2892006-01-20 20:34:06 +00001374 const std::vector<DIEAbbrevData> &AbbrevData = Abbrev.getData();
Jim Laskey063e7652006-01-17 17:31:53 +00001375
1376 // Emit the DIE attribute values.
Jim Laskey52060a02006-01-24 00:49:18 +00001377 for (unsigned i = 0, N = Values.size(); i < N; ++i) {
Jim Laskeyd18e2892006-01-20 20:34:06 +00001378 unsigned Attr = AbbrevData[i].getAttribute();
1379 unsigned Form = AbbrevData[i].getForm();
Jim Laskey063e7652006-01-17 17:31:53 +00001380 assert(Form && "Too many attributes for DIE (check abbreviation)");
1381
1382 switch (Attr) {
1383 case DW_AT_sibling: {
Jim Laskeyda427fa2006-01-27 20:31:25 +00001384 EmitInt32(Die->SiblingOffset());
Jim Laskey063e7652006-01-17 17:31:53 +00001385 break;
1386 }
1387 default: {
1388 // Emit an attribute using the defined form.
1389 Values[i]->EmitValue(*this, Form);
1390 break;
1391 }
1392 }
1393
1394 EOL(AttributeString(Attr));
1395 }
1396
1397 // Emit the DIE children if any.
1398 if (Abbrev.getChildrenFlag() == DW_CHILDREN_yes) {
1399 const std::vector<DIE *> &Children = Die->getChildren();
1400
Jim Laskey52060a02006-01-24 00:49:18 +00001401 for (unsigned j = 0, M = Children.size(); j < M; ++j) {
Jim Laskey063e7652006-01-17 17:31:53 +00001402 // FIXME - handle sibling offsets.
1403 // FIXME - handle all DIE types.
1404 EmitDIE(Children[j]);
1405 }
1406
Jim Laskeyda427fa2006-01-27 20:31:25 +00001407 EmitInt8(0); EOL("End Of Children Mark");
Jim Laskey063e7652006-01-17 17:31:53 +00001408 }
1409}
1410
1411/// SizeAndOffsetDie - Compute the size and offset of a DIE.
1412///
Jim Laskey0420f2a2006-02-22 19:02:11 +00001413unsigned DwarfWriter::SizeAndOffsetDie(DIE *Die, unsigned Offset) {
1414 // Record the abbreviation.
1415 Die->Complete(*this);
1416
Jim Laskey063e7652006-01-17 17:31:53 +00001417 // Get the abbreviation for this DIE.
1418 unsigned AbbrevID = Die->getAbbrevID();
1419 const DIEAbbrev &Abbrev = Abbreviations[AbbrevID];
1420
1421 // Set DIE offset
1422 Die->setOffset(Offset);
1423
1424 // Start the size with the size of abbreviation code.
1425 Offset += SizeULEB128(AbbrevID);
1426
1427 const std::vector<DIEValue *> &Values = Die->getValues();
Jim Laskeyd18e2892006-01-20 20:34:06 +00001428 const std::vector<DIEAbbrevData> &AbbrevData = Abbrev.getData();
Jim Laskey063e7652006-01-17 17:31:53 +00001429
1430 // Emit the DIE attribute values.
Jim Laskey52060a02006-01-24 00:49:18 +00001431 for (unsigned i = 0, N = Values.size(); i < N; ++i) {
Jim Laskey063e7652006-01-17 17:31:53 +00001432 // Size attribute value.
Jim Laskeyd18e2892006-01-20 20:34:06 +00001433 Offset += Values[i]->SizeOf(*this, AbbrevData[i].getForm());
Jim Laskey063e7652006-01-17 17:31:53 +00001434 }
1435
1436 // Emit the DIE children if any.
1437 if (Abbrev.getChildrenFlag() == DW_CHILDREN_yes) {
1438 const std::vector<DIE *> &Children = Die->getChildren();
1439
Jim Laskey52060a02006-01-24 00:49:18 +00001440 for (unsigned j = 0, M = Children.size(); j < M; ++j) {
Jim Laskey063e7652006-01-17 17:31:53 +00001441 // FIXME - handle sibling offsets.
1442 // FIXME - handle all DIE types.
1443 Offset = SizeAndOffsetDie(Children[j], Offset);
1444 }
1445
1446 // End of children marker.
1447 Offset += sizeof(int8_t);
1448 }
1449
1450 Die->setSize(Offset - Die->getOffset());
1451 return Offset;
1452}
1453
1454/// SizeAndOffsets - Compute the size and offset of all the DIEs.
1455///
1456void DwarfWriter::SizeAndOffsets() {
Jim Laskey063e7652006-01-17 17:31:53 +00001457
1458 // Process each compile unit.
Jim Laskey52060a02006-01-24 00:49:18 +00001459 for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) {
Jim Laskeybd761842006-02-27 17:27:12 +00001460 CompileUnit *Unit = CompileUnits[i];
1461 if (Unit->hasContent()) {
1462 // Compute size of compile unit header
1463 unsigned Offset = sizeof(int32_t) + // Length of Compilation Unit Info
1464 sizeof(int16_t) + // DWARF version number
1465 sizeof(int32_t) + // Offset Into Abbrev. Section
1466 sizeof(int8_t); // Pointer Size (in bytes)
1467
1468 SizeAndOffsetDie(Unit->getDie(), Offset);
1469 }
Jim Laskey063e7652006-01-17 17:31:53 +00001470 }
1471}
1472
1473/// EmitDebugInfo - Emit the debug info section.
1474///
1475void DwarfWriter::EmitDebugInfo() const {
1476 // Start debug info section.
1477 Asm->SwitchSection(DwarfInfoSection, 0);
1478
Jim Laskeybd761842006-02-27 17:27:12 +00001479 // Process each compile unit.
1480 for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) {
1481 CompileUnit *Unit = CompileUnits[i];
1482
1483 if (Unit->hasContent()) {
1484 DIE *Die = Unit->getDie();
Jim Laskey0d086af2006-02-27 12:43:29 +00001485 // Emit the compile units header.
Jim Laskeybd761842006-02-27 17:27:12 +00001486 EmitLabel("info_begin", Unit->getID());
Jim Laskey0d086af2006-02-27 12:43:29 +00001487 // Emit size of content not including length itself
Jim Laskeybd761842006-02-27 17:27:12 +00001488 unsigned ContentSize = Die->getSize() +
Jim Laskey0d086af2006-02-27 12:43:29 +00001489 sizeof(int16_t) + // DWARF version number
1490 sizeof(int32_t) + // Offset Into Abbrev. Section
1491 sizeof(int8_t); // Pointer Size (in bytes)
1492
1493 EmitInt32(ContentSize); EOL("Length of Compilation Unit Info");
1494 EmitInt16(DWARF_VERSION); EOL("DWARF version number");
1495 EmitReference("abbrev_begin", 0); EOL("Offset Into Abbrev. Section");
1496 EmitInt8(AddressSize); EOL("Address Size (in bytes)");
1497
Jim Laskeybd761842006-02-27 17:27:12 +00001498 EmitDIE(Die);
1499 EmitLabel("info_end", Unit->getID());
Jim Laskey063e7652006-01-17 17:31:53 +00001500 }
Jim Laskey0d086af2006-02-27 12:43:29 +00001501
1502 O << "\n";
Jim Laskey063e7652006-01-17 17:31:53 +00001503 }
1504}
1505
1506/// EmitAbbreviations - Emit the abbreviation section.
1507///
1508void DwarfWriter::EmitAbbreviations() const {
Jim Laskeyd18e2892006-01-20 20:34:06 +00001509 // Check to see if it is worth the effort.
1510 if (!Abbreviations.empty()) {
1511 // Start the debug abbrev section.
1512 Asm->SwitchSection(DwarfAbbrevSection, 0);
Jim Laskey063e7652006-01-17 17:31:53 +00001513
Jim Laskeyd18e2892006-01-20 20:34:06 +00001514 EmitLabel("abbrev_begin", 0);
Jim Laskey063e7652006-01-17 17:31:53 +00001515
Jim Laskeyd18e2892006-01-20 20:34:06 +00001516 // For each abbrevation.
1517 for (unsigned AbbrevID = 1, NAID = Abbreviations.size();
Jim Laskey52060a02006-01-24 00:49:18 +00001518 AbbrevID <= NAID; ++AbbrevID) {
Jim Laskeyd18e2892006-01-20 20:34:06 +00001519 // Get abbreviation data
1520 const DIEAbbrev &Abbrev = Abbreviations[AbbrevID];
Jim Laskey063e7652006-01-17 17:31:53 +00001521
Jim Laskeyd18e2892006-01-20 20:34:06 +00001522 // Emit the abbrevations code (base 1 index.)
1523 EmitULEB128Bytes(AbbrevID); EOL("Abbreviation Code");
Jim Laskey063e7652006-01-17 17:31:53 +00001524
Jim Laskeyd18e2892006-01-20 20:34:06 +00001525 // Emit the abbreviations data.
1526 Abbrev.Emit(*this);
Jim Laskey0d086af2006-02-27 12:43:29 +00001527
1528 O << "\n";
Jim Laskey063e7652006-01-17 17:31:53 +00001529 }
Jim Laskeyd18e2892006-01-20 20:34:06 +00001530
1531 EmitLabel("abbrev_end", 0);
Jim Laskey0d086af2006-02-27 12:43:29 +00001532
1533 O << "\n";
Jim Laskey063e7652006-01-17 17:31:53 +00001534 }
1535}
1536
1537/// EmitDebugLines - Emit source line information.
1538///
1539void DwarfWriter::EmitDebugLines() const {
1540 // Minimum line delta, thus ranging from -10..(255-10).
1541 const int MinLineDelta = -(DW_LNS_fixed_advance_pc + 1);
1542 // Maximum line delta, thus ranging from -10..(255-10).
1543 const int MaxLineDelta = 255 + MinLineDelta;
1544
1545 // Start the dwarf line section.
1546 Asm->SwitchSection(DwarfLineSection, 0);
1547
1548 // Construct the section header.
1549
1550 EmitDifference("line_end", 0, "line_begin", 0);
1551 EOL("Length of Source Line Info");
1552 EmitLabel("line_begin", 0);
1553
Jim Laskeyda427fa2006-01-27 20:31:25 +00001554 EmitInt16(DWARF_VERSION); EOL("DWARF version number");
Jim Laskey063e7652006-01-17 17:31:53 +00001555
1556 EmitDifference("line_prolog_end", 0, "line_prolog_begin", 0);
1557 EOL("Prolog Length");
1558 EmitLabel("line_prolog_begin", 0);
1559
Jim Laskeyda427fa2006-01-27 20:31:25 +00001560 EmitInt8(1); EOL("Minimum Instruction Length");
Jim Laskey063e7652006-01-17 17:31:53 +00001561
Jim Laskeyda427fa2006-01-27 20:31:25 +00001562 EmitInt8(1); EOL("Default is_stmt_start flag");
Jim Laskey063e7652006-01-17 17:31:53 +00001563
Jim Laskeyda427fa2006-01-27 20:31:25 +00001564 EmitInt8(MinLineDelta); EOL("Line Base Value (Special Opcodes)");
Jim Laskey063e7652006-01-17 17:31:53 +00001565
Jim Laskeyda427fa2006-01-27 20:31:25 +00001566 EmitInt8(MaxLineDelta); EOL("Line Range Value (Special Opcodes)");
Jim Laskey063e7652006-01-17 17:31:53 +00001567
Jim Laskeyda427fa2006-01-27 20:31:25 +00001568 EmitInt8(-MinLineDelta); EOL("Special Opcode Base");
Jim Laskey063e7652006-01-17 17:31:53 +00001569
1570 // Line number standard opcode encodings argument count
Jim Laskeyda427fa2006-01-27 20:31:25 +00001571 EmitInt8(0); EOL("DW_LNS_copy arg count");
1572 EmitInt8(1); EOL("DW_LNS_advance_pc arg count");
1573 EmitInt8(1); EOL("DW_LNS_advance_line arg count");
1574 EmitInt8(1); EOL("DW_LNS_set_file arg count");
1575 EmitInt8(1); EOL("DW_LNS_set_column arg count");
1576 EmitInt8(0); EOL("DW_LNS_negate_stmt arg count");
1577 EmitInt8(0); EOL("DW_LNS_set_basic_block arg count");
1578 EmitInt8(0); EOL("DW_LNS_const_add_pc arg count");
1579 EmitInt8(1); EOL("DW_LNS_fixed_advance_pc arg count");
Jim Laskey063e7652006-01-17 17:31:53 +00001580
1581 const UniqueVector<std::string> &Directories = DebugInfo->getDirectories();
1582 const UniqueVector<SourceFileInfo> &SourceFiles = DebugInfo->getSourceFiles();
1583
1584 // Emit directories.
1585 for (unsigned DirectoryID = 1, NDID = Directories.size();
Jim Laskey52060a02006-01-24 00:49:18 +00001586 DirectoryID <= NDID; ++DirectoryID) {
Jim Laskey063e7652006-01-17 17:31:53 +00001587 EmitString(Directories[DirectoryID]); EOL("Directory");
1588 }
Jim Laskeyda427fa2006-01-27 20:31:25 +00001589 EmitInt8(0); EOL("End of directories");
Jim Laskey063e7652006-01-17 17:31:53 +00001590
1591 // Emit files.
1592 for (unsigned SourceID = 1, NSID = SourceFiles.size();
Jim Laskey52060a02006-01-24 00:49:18 +00001593 SourceID <= NSID; ++SourceID) {
Jim Laskey063e7652006-01-17 17:31:53 +00001594 const SourceFileInfo &SourceFile = SourceFiles[SourceID];
1595 EmitString(SourceFile.getName()); EOL("Source");
1596 EmitULEB128Bytes(SourceFile.getDirectoryID()); EOL("Directory #");
1597 EmitULEB128Bytes(0); EOL("Mod date");
1598 EmitULEB128Bytes(0); EOL("File size");
1599 }
Jim Laskeyda427fa2006-01-27 20:31:25 +00001600 EmitInt8(0); EOL("End of files");
Jim Laskey063e7652006-01-17 17:31:53 +00001601
1602 EmitLabel("line_prolog_end", 0);
1603
1604 // Emit line information
1605 const std::vector<SourceLineInfo *> &LineInfos = DebugInfo->getSourceLines();
1606
1607 // Dwarf assumes we start with first line of first source file.
1608 unsigned Source = 1;
1609 unsigned Line = 1;
1610
1611 // Construct rows of the address, source, line, column matrix.
Jim Laskey52060a02006-01-24 00:49:18 +00001612 for (unsigned i = 0, N = LineInfos.size(); i < N; ++i) {
Jim Laskey063e7652006-01-17 17:31:53 +00001613 SourceLineInfo *LineInfo = LineInfos[i];
Jim Laskey0420f2a2006-02-22 19:02:11 +00001614
1615 if (DwarfVerbose) {
1616 unsigned SourceID = LineInfo->getSourceID();
1617 const SourceFileInfo &SourceFile = SourceFiles[SourceID];
1618 unsigned DirectoryID = SourceFile.getDirectoryID();
1619 O << "\t"
1620 << Asm->CommentString << " "
1621 << Directories[DirectoryID]
1622 << SourceFile.getName() << ":"
1623 << LineInfo->getLine() << "\n";
1624 }
Jim Laskey063e7652006-01-17 17:31:53 +00001625
1626 // Define the line address.
Jim Laskeyda427fa2006-01-27 20:31:25 +00001627 EmitInt8(0); EOL("Extended Op");
1628 EmitInt8(4 + 1); EOL("Op size");
1629 EmitInt8(DW_LNE_set_address); EOL("DW_LNE_set_address");
Jim Laskeye719a7c2006-01-18 16:54:26 +00001630 EmitReference("loc", i + 1); EOL("Location label");
Jim Laskey063e7652006-01-17 17:31:53 +00001631
1632 // If change of source, then switch to the new source.
1633 if (Source != LineInfo->getSourceID()) {
1634 Source = LineInfo->getSourceID();
Jim Laskeyda427fa2006-01-27 20:31:25 +00001635 EmitInt8(DW_LNS_set_file); EOL("DW_LNS_set_file");
Jim Laskeybd761842006-02-27 17:27:12 +00001636 EmitULEB128Bytes(Source); EOL("New Source");
Jim Laskey063e7652006-01-17 17:31:53 +00001637 }
1638
1639 // If change of line.
1640 if (Line != LineInfo->getLine()) {
1641 // Determine offset.
1642 int Offset = LineInfo->getLine() - Line;
1643 int Delta = Offset - MinLineDelta;
1644
1645 // Update line.
1646 Line = LineInfo->getLine();
1647
1648 // If delta is small enough and in range...
1649 if (Delta >= 0 && Delta < (MaxLineDelta - 1)) {
1650 // ... then use fast opcode.
Jim Laskeyda427fa2006-01-27 20:31:25 +00001651 EmitInt8(Delta - MinLineDelta); EOL("Line Delta");
Jim Laskey063e7652006-01-17 17:31:53 +00001652 } else {
1653 // ... otherwise use long hand.
Jim Laskeyda427fa2006-01-27 20:31:25 +00001654 EmitInt8(DW_LNS_advance_line); EOL("DW_LNS_advance_line");
Jim Laskey063e7652006-01-17 17:31:53 +00001655 EmitSLEB128Bytes(Offset); EOL("Line Offset");
Jim Laskeyda427fa2006-01-27 20:31:25 +00001656 EmitInt8(DW_LNS_copy); EOL("DW_LNS_copy");
Jim Laskey063e7652006-01-17 17:31:53 +00001657 }
1658 } else {
1659 // Copy the previous row (different address or source)
Jim Laskeyda427fa2006-01-27 20:31:25 +00001660 EmitInt8(DW_LNS_copy); EOL("DW_LNS_copy");
Jim Laskey063e7652006-01-17 17:31:53 +00001661 }
1662 }
1663
Jim Laskey0420f2a2006-02-22 19:02:11 +00001664 // Define last address.
1665 EmitInt8(0); EOL("Extended Op");
1666 EmitInt8(4 + 1); EOL("Op size");
1667 EmitInt8(DW_LNE_set_address); EOL("DW_LNE_set_address");
1668 EmitReference("text_end", 0); EOL("Location label");
1669
Jim Laskey063e7652006-01-17 17:31:53 +00001670 // Mark end of matrix.
Jim Laskeyda427fa2006-01-27 20:31:25 +00001671 EmitInt8(0); EOL("DW_LNE_end_sequence");
Jim Laskey063e7652006-01-17 17:31:53 +00001672 EmitULEB128Bytes(1); O << "\n";
Jim Laskeyda427fa2006-01-27 20:31:25 +00001673 EmitInt8(1); O << "\n";
Jim Laskey063e7652006-01-17 17:31:53 +00001674
1675 EmitLabel("line_end", 0);
Jim Laskey0d086af2006-02-27 12:43:29 +00001676
1677 O << "\n";
Jim Laskey063e7652006-01-17 17:31:53 +00001678}
Jim Laskey19ef4ef2006-01-17 20:41:40 +00001679
1680/// EmitDebugFrame - Emit visible names into a debug frame section.
1681///
1682void DwarfWriter::EmitDebugFrame() {
Jim Laskeye719a7c2006-01-18 16:54:26 +00001683 // FIXME - Should be per frame
Jim Laskey19ef4ef2006-01-17 20:41:40 +00001684}
1685
1686/// EmitDebugPubNames - Emit visible names into a debug pubnames section.
1687///
1688void DwarfWriter::EmitDebugPubNames() {
Jim Laskeybd761842006-02-27 17:27:12 +00001689 // Start the dwarf pubnames section.
1690 Asm->SwitchSection(DwarfPubNamesSection, 0);
Jim Laskeyd18e2892006-01-20 20:34:06 +00001691
Jim Laskeybd761842006-02-27 17:27:12 +00001692 // Process each compile unit.
1693 for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) {
1694 CompileUnit *Unit = CompileUnits[i];
Jim Laskeyd18e2892006-01-20 20:34:06 +00001695
Jim Laskeybd761842006-02-27 17:27:12 +00001696 if (Unit->hasContent()) {
1697 EmitDifference("pubnames_end", Unit->getID(),
1698 "pubnames_begin", Unit->getID());
1699 EOL("Length of Public Names Info");
1700
1701 EmitLabel("pubnames_begin", Unit->getID());
1702
1703 EmitInt16(DWARF_VERSION); EOL("DWARF Version");
1704
1705 EmitReference("info_begin", Unit->getID());
1706 EOL("Offset of Compilation Unit Info");
Jim Laskeyd18e2892006-01-20 20:34:06 +00001707
Jim Laskeybd761842006-02-27 17:27:12 +00001708 EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID());
1709 EOL("Compilation Unit Length");
1710
1711 std::map<std::string, DIE *> &Globals = Unit->getGlobals();
1712
1713 for (std::map<std::string, DIE *>::iterator GI = Globals.begin(),
1714 GE = Globals.end();
1715 GI != GE; ++GI) {
1716 const std::string &Name = GI->first;
1717 DIE * Entity = GI->second;
1718
1719 EmitInt32(Entity->getOffset()); EOL("DIE offset");
1720 EmitString(Name); EOL("External Name");
1721 }
Jim Laskeyd18e2892006-01-20 20:34:06 +00001722
Jim Laskeybd761842006-02-27 17:27:12 +00001723 EmitInt32(0); EOL("End Mark");
1724 EmitLabel("pubnames_end", Unit->getID());
1725
1726 O << "\n";
Jim Laskeyd18e2892006-01-20 20:34:06 +00001727 }
Jim Laskeyd18e2892006-01-20 20:34:06 +00001728 }
Jim Laskey19ef4ef2006-01-17 20:41:40 +00001729}
1730
1731/// EmitDebugStr - Emit visible names into a debug str section.
1732///
1733void DwarfWriter::EmitDebugStr() {
Jim Laskeyd18e2892006-01-20 20:34:06 +00001734 // Check to see if it is worth the effort.
1735 if (!StringPool.empty()) {
1736 // Start the dwarf str section.
1737 Asm->SwitchSection(DwarfStrSection, 0);
1738
1739 // For each of strings in teh string pool.
1740 for (unsigned StringID = 1, N = StringPool.size();
Jim Laskey52060a02006-01-24 00:49:18 +00001741 StringID <= N; ++StringID) {
Jim Laskeyd18e2892006-01-20 20:34:06 +00001742 // Emit a label for reference from debug information entries.
1743 EmitLabel("string", StringID);
1744 // Emit the string itself.
1745 const std::string &String = StringPool[StringID];
1746 EmitString(String); O << "\n";
1747 }
Jim Laskey0d086af2006-02-27 12:43:29 +00001748
1749 O << "\n";
Jim Laskeyd18e2892006-01-20 20:34:06 +00001750 }
Jim Laskey19ef4ef2006-01-17 20:41:40 +00001751}
1752
1753/// EmitDebugLoc - Emit visible names into a debug loc section.
1754///
1755void DwarfWriter::EmitDebugLoc() {
Jim Laskeye719a7c2006-01-18 16:54:26 +00001756 // Start the dwarf loc section.
1757 Asm->SwitchSection(DwarfLocSection, 0);
Jim Laskey0d086af2006-02-27 12:43:29 +00001758
1759 O << "\n";
Jim Laskey19ef4ef2006-01-17 20:41:40 +00001760}
1761
1762/// EmitDebugARanges - Emit visible names into a debug aranges section.
1763///
1764void DwarfWriter::EmitDebugARanges() {
Jim Laskeye719a7c2006-01-18 16:54:26 +00001765 // Start the dwarf aranges section.
1766 Asm->SwitchSection(DwarfARangesSection, 0);
1767
1768 // FIXME - Mock up
Jim Laskeybd761842006-02-27 17:27:12 +00001769#if 0
1770 // Process each compile unit.
1771 for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) {
1772 CompileUnit *Unit = CompileUnits[i];
1773
1774 if (Unit->hasContent()) {
1775 // Don't include size of length
1776 EmitInt32(0x1c); EOL("Length of Address Ranges Info");
1777
1778 EmitInt16(DWARF_VERSION); EOL("Dwarf Version");
1779
1780 EmitReference("info_begin", Unit->getID());
1781 EOL("Offset of Compilation Unit Info");
Jim Laskeye719a7c2006-01-18 16:54:26 +00001782
Jim Laskeybd761842006-02-27 17:27:12 +00001783 EmitInt8(AddressSize); EOL("Size of Address");
Jim Laskeye719a7c2006-01-18 16:54:26 +00001784
Jim Laskeybd761842006-02-27 17:27:12 +00001785 EmitInt8(0); EOL("Size of Segment Descriptor");
Jim Laskeye719a7c2006-01-18 16:54:26 +00001786
Jim Laskeybd761842006-02-27 17:27:12 +00001787 EmitInt16(0); EOL("Pad (1)");
1788 EmitInt16(0); EOL("Pad (2)");
Jim Laskeye719a7c2006-01-18 16:54:26 +00001789
Jim Laskeybd761842006-02-27 17:27:12 +00001790 // Range 1
1791 EmitReference("text_begin", 0); EOL("Address");
1792 EmitDifference("text_end", 0, "text_begin", 0); EOL("Length");
Jim Laskeye719a7c2006-01-18 16:54:26 +00001793
Jim Laskeybd761842006-02-27 17:27:12 +00001794 EmitInt32(0); EOL("EOM (1)");
1795 EmitInt32(0); EOL("EOM (2)");
1796
1797 O << "\n";
1798 }
1799 }
1800#endif
Jim Laskey19ef4ef2006-01-17 20:41:40 +00001801}
1802
1803/// EmitDebugRanges - Emit visible names into a debug ranges section.
1804///
1805void DwarfWriter::EmitDebugRanges() {
Jim Laskeye719a7c2006-01-18 16:54:26 +00001806 // Start the dwarf ranges section.
1807 Asm->SwitchSection(DwarfRangesSection, 0);
Jim Laskey0d086af2006-02-27 12:43:29 +00001808
1809 O << "\n";
Jim Laskey19ef4ef2006-01-17 20:41:40 +00001810}
1811
1812/// EmitDebugMacInfo - Emit visible names into a debug macinfo section.
1813///
1814void DwarfWriter::EmitDebugMacInfo() {
Jim Laskeye719a7c2006-01-18 16:54:26 +00001815 // Start the dwarf macinfo section.
1816 Asm->SwitchSection(DwarfMacInfoSection, 0);
Jim Laskey0d086af2006-02-27 12:43:29 +00001817
1818 O << "\n";
Jim Laskey19ef4ef2006-01-17 20:41:40 +00001819}
Jim Laskey063e7652006-01-17 17:31:53 +00001820
Jim Laskey52060a02006-01-24 00:49:18 +00001821/// ConstructCompileUnitDIEs - Create a compile unit DIE for each source and
1822/// header file.
1823void DwarfWriter::ConstructCompileUnitDIEs() {
Jim Laskey86cbdba2006-02-06 15:33:21 +00001824 const UniqueVector<CompileUnitDesc *> CUW = DebugInfo->getCompileUnits();
Jim Laskey6e87c0e2006-01-26 21:22:49 +00001825
1826 for (unsigned i = 1, N = CUW.size(); i <= N; ++i) {
Jim Laskeybd761842006-02-27 17:27:12 +00001827 CompileUnit *Unit = NewCompileUnit(CUW[i], i);
Jim Laskey52060a02006-01-24 00:49:18 +00001828 CompileUnits.push_back(Unit);
1829 }
1830}
1831
1832/// ConstructGlobalDIEs - Create DIEs for each of the externally visible global
1833/// variables.
1834void DwarfWriter::ConstructGlobalDIEs(Module &M) {
Jim Laskey86cbdba2006-02-06 15:33:21 +00001835 std::vector<GlobalVariableDesc *> GlobalVariables =
Jim Laskey0420f2a2006-02-22 19:02:11 +00001836 DebugInfo->getAnchoredDescriptors<GlobalVariableDesc>(M);
Jim Laskeyb3e789a2006-01-26 20:21:46 +00001837
1838 for (unsigned i = 0, N = GlobalVariables.size(); i < N; ++i) {
Jim Laskey86cbdba2006-02-06 15:33:21 +00001839 GlobalVariableDesc *GVD = GlobalVariables[i];
Jim Laskey0420f2a2006-02-22 19:02:11 +00001840 NewGlobalVariable(GVD);
Jim Laskey52060a02006-01-24 00:49:18 +00001841 }
1842}
1843
Jim Laskey0420f2a2006-02-22 19:02:11 +00001844/// ConstructSubprogramDIEs - Create DIEs for each of the externally visible
1845/// subprograms.
1846void DwarfWriter::ConstructSubprogramDIEs(Module &M) {
1847 std::vector<SubprogramDesc *> Subprograms =
1848 DebugInfo->getAnchoredDescriptors<SubprogramDesc>(M);
1849
1850 for (unsigned i = 0, N = Subprograms.size(); i < N; ++i) {
1851 SubprogramDesc *SPD = Subprograms[i];
1852 NewSubprogram(SPD);
1853 }
1854}
Jim Laskey52060a02006-01-24 00:49:18 +00001855
Jim Laskey063e7652006-01-17 17:31:53 +00001856/// ShouldEmitDwarf - Determine if Dwarf declarations should be made.
Jim Laskeyb2efb852006-01-04 22:28:25 +00001857///
1858bool DwarfWriter::ShouldEmitDwarf() {
1859 // Check if debug info is present.
1860 if (!DebugInfo || !DebugInfo->hasInfo()) return false;
1861
1862 // Make sure initial declarations are made.
1863 if (!didInitial) {
1864 EmitInitial();
1865 didInitial = true;
1866 }
1867
1868 // Okay to emit.
1869 return true;
1870}
1871
Jim Laskey063e7652006-01-17 17:31:53 +00001872//===----------------------------------------------------------------------===//
Jim Laskeyd18e2892006-01-20 20:34:06 +00001873// Main entry points.
Jim Laskey063e7652006-01-17 17:31:53 +00001874//
Jim Laskey52060a02006-01-24 00:49:18 +00001875
1876DwarfWriter::DwarfWriter(std::ostream &OS, AsmPrinter *A)
1877: O(OS)
1878, Asm(A)
1879, DebugInfo(NULL)
1880, didInitial(false)
1881, CompileUnits()
1882, Abbreviations()
Jim Laskey52060a02006-01-24 00:49:18 +00001883, StringPool()
Jim Laskeybd761842006-02-27 17:27:12 +00001884, DescToUnitMap()
Jim Laskey0420f2a2006-02-22 19:02:11 +00001885, DescToDieMap()
1886, TypeToDieMap()
Jim Laskey52060a02006-01-24 00:49:18 +00001887, AddressSize(sizeof(int32_t))
1888, hasLEB128(false)
1889, hasDotLoc(false)
1890, hasDotFile(false)
1891, needsSet(false)
1892, DwarfAbbrevSection(".debug_abbrev")
1893, DwarfInfoSection(".debug_info")
1894, DwarfLineSection(".debug_line")
1895, DwarfFrameSection(".debug_frame")
1896, DwarfPubNamesSection(".debug_pubnames")
1897, DwarfPubTypesSection(".debug_pubtypes")
1898, DwarfStrSection(".debug_str")
1899, DwarfLocSection(".debug_loc")
1900, DwarfARangesSection(".debug_aranges")
1901, DwarfRangesSection(".debug_ranges")
1902, DwarfMacInfoSection(".debug_macinfo")
1903, TextSection(".text")
1904, DataSection(".data")
1905{}
1906DwarfWriter::~DwarfWriter() {
1907 for (unsigned i = 0, N = CompileUnits.size(); i < N; ++i) {
1908 delete CompileUnits[i];
Jim Laskey063e7652006-01-17 17:31:53 +00001909 }
Jim Laskey52060a02006-01-24 00:49:18 +00001910}
Jim Laskey063e7652006-01-17 17:31:53 +00001911
1912/// BeginModule - Emit all Dwarf sections that should come prior to the content.
Jim Laskeyb2efb852006-01-04 22:28:25 +00001913///
Jim Laskey52060a02006-01-24 00:49:18 +00001914void DwarfWriter::BeginModule(Module &M) {
Jim Laskeyb2efb852006-01-04 22:28:25 +00001915 if (!ShouldEmitDwarf()) return;
Jim Laskey063e7652006-01-17 17:31:53 +00001916 EOL("Dwarf Begin Module");
Jim Laskeyb2efb852006-01-04 22:28:25 +00001917}
1918
Jim Laskey063e7652006-01-17 17:31:53 +00001919/// EndModule - Emit all Dwarf sections that should come after the content.
Jim Laskeya7cea6f2006-01-04 13:52:30 +00001920///
Jim Laskey52060a02006-01-24 00:49:18 +00001921void DwarfWriter::EndModule(Module &M) {
Jim Laskeyb2efb852006-01-04 22:28:25 +00001922 if (!ShouldEmitDwarf()) return;
Jim Laskey063e7652006-01-17 17:31:53 +00001923 EOL("Dwarf End Module");
1924
1925 // Standard sections final addresses.
Jim Laskeye719a7c2006-01-18 16:54:26 +00001926 Asm->SwitchSection(TextSection, 0);
Jim Laskey063e7652006-01-17 17:31:53 +00001927 EmitLabel("text_end", 0);
Jim Laskeye719a7c2006-01-18 16:54:26 +00001928 Asm->SwitchSection(DataSection, 0);
Jim Laskey063e7652006-01-17 17:31:53 +00001929 EmitLabel("data_end", 0);
Jim Laskeyd18e2892006-01-20 20:34:06 +00001930
Jim Laskey52060a02006-01-24 00:49:18 +00001931 // Create all the compile unit DIEs.
1932 ConstructCompileUnitDIEs();
1933
1934 // Create DIEs for each of the externally visible global variables.
1935 ConstructGlobalDIEs(M);
Jim Laskey063e7652006-01-17 17:31:53 +00001936
Jim Laskey0420f2a2006-02-22 19:02:11 +00001937 // Create DIEs for each of the externally visible subprograms.
1938 ConstructSubprogramDIEs(M);
1939
Jim Laskey063e7652006-01-17 17:31:53 +00001940 // Compute DIE offsets and sizes.
1941 SizeAndOffsets();
1942
1943 // Emit all the DIEs into a debug info section
1944 EmitDebugInfo();
1945
1946 // Corresponding abbreviations into a abbrev section.
1947 EmitAbbreviations();
1948
1949 // Emit source line correspondence into a debug line section.
1950 EmitDebugLines();
Jim Laskey19ef4ef2006-01-17 20:41:40 +00001951
1952 // Emit info into a debug frame section.
Jim Laskey0d086af2006-02-27 12:43:29 +00001953 // EmitDebugFrame();
Jim Laskey19ef4ef2006-01-17 20:41:40 +00001954
1955 // Emit info into a debug pubnames section.
1956 EmitDebugPubNames();
1957
Jim Laskey19ef4ef2006-01-17 20:41:40 +00001958 // Emit info into a debug str section.
1959 EmitDebugStr();
1960
1961 // Emit info into a debug loc section.
1962 EmitDebugLoc();
1963
1964 // Emit info into a debug aranges section.
1965 EmitDebugARanges();
1966
1967 // Emit info into a debug ranges section.
1968 EmitDebugRanges();
1969
1970 // Emit info into a debug macinfo section.
1971 EmitDebugMacInfo();
Jim Laskeya7cea6f2006-01-04 13:52:30 +00001972}
1973
Jim Laskeye719a7c2006-01-18 16:54:26 +00001974/// BeginFunction - Gather pre-function debug information.
Jim Laskeya7cea6f2006-01-04 13:52:30 +00001975///
Jim Laskey52060a02006-01-24 00:49:18 +00001976void DwarfWriter::BeginFunction(MachineFunction &MF) {
Jim Laskeyb2efb852006-01-04 22:28:25 +00001977 if (!ShouldEmitDwarf()) return;
Jim Laskey063e7652006-01-17 17:31:53 +00001978 EOL("Dwarf Begin Function");
Jim Laskeya7cea6f2006-01-04 13:52:30 +00001979}
1980
Jim Laskeye719a7c2006-01-18 16:54:26 +00001981/// EndFunction - Gather and emit post-function debug information.
Jim Laskeya7cea6f2006-01-04 13:52:30 +00001982///
Jim Laskey52060a02006-01-24 00:49:18 +00001983void DwarfWriter::EndFunction(MachineFunction &MF) {
Jim Laskeyb2efb852006-01-04 22:28:25 +00001984 if (!ShouldEmitDwarf()) return;
Jim Laskey063e7652006-01-17 17:31:53 +00001985 EOL("Dwarf End Function");
Jim Laskeya7cea6f2006-01-04 13:52:30 +00001986}