blob: faf4590b43ee60dffdb1917eca28b2be405579e2 [file] [log] [blame]
Sanjiv Guptaa57bc3b2009-05-22 13:58:45 +00001//===-- PIC16DebugInfo.cpp - Implementation for PIC16 Debug Information ======//
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// This file contains the helper functions for representing debug information.
11//
12//===----------------------------------------------------------------------===//
13
14#include "PIC16.h"
15#include "PIC16DebugInfo.h"
16#include "llvm/GlobalVariable.h"
Sanjiv Guptadd4694b2009-05-28 18:24:11 +000017#include "llvm/Support/raw_ostream.h"
Sanjiv Guptaa57bc3b2009-05-22 13:58:45 +000018
19using namespace llvm;
20
Sanjiv Guptadd4694b2009-05-28 18:24:11 +000021PIC16DbgInfo::~PIC16DbgInfo() {
22 for(std::map<std::string, DISubprogram *>::iterator i = FunctNameMap.begin();
23 i!=FunctNameMap.end(); i++)
24 delete i->second;
25 FunctNameMap.clear();
26}
27
Sanjiv Guptaa57bc3b2009-05-22 13:58:45 +000028void PIC16DbgInfo::PopulateDebugInfo(DIType Ty, unsigned short &TypeNo,
29 bool &HasAux, int Aux[],
30 std::string &TypeName) {
31 if (Ty.isBasicType(Ty.getTag())) {
32 std::string Name = "";
33 Ty.getName(Name);
34 unsigned short BaseTy = GetTypeDebugNumber(Name);
35 TypeNo = TypeNo << PIC16Dbg::S_BASIC;
36 TypeNo = TypeNo | (0xffff & BaseTy);
37 }
38 else if (Ty.isDerivedType(Ty.getTag())) {
39 switch(Ty.getTag())
40 {
41 case dwarf::DW_TAG_pointer_type:
42 TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
43 TypeNo = TypeNo | PIC16Dbg::DT_PTR;
44 break;
45 default:
46 TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
47 }
48 DIType BaseType = DIDerivedType(Ty.getGV()).getTypeDerivedFrom();
49 PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TypeName);
50 }
51 else if (Ty.isCompositeType(Ty.getTag())) {
52 switch (Ty.getTag()) {
53 case dwarf::DW_TAG_array_type: {
54 DICompositeType CTy = DICompositeType(Ty.getGV());
55 DIArray Elements = CTy.getTypeArray();
56 unsigned short size = 1;
57 unsigned short Dimension[4]={0,0,0,0};
58 for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
59 DIDescriptor Element = Elements.getElement(i);
60 if (Element.getTag() == dwarf::DW_TAG_subrange_type) {
61 TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
62 TypeNo = TypeNo | PIC16Dbg::DT_ARY;
63 DISubrange SubRange = DISubrange(Element.getGV());
64 Dimension[i] = SubRange.getHi() - SubRange.getLo() + 1;
65 // Each dimension is represented by 2 bytes starting at byte 9.
66 Aux[8+i*2+0] = Dimension[i];
67 Aux[8+i*2+1] = Dimension[i] >> 8;
68 size = size * Dimension[i];
69 }
70 }
71 HasAux = true;
72 // In auxillary entry for array, 7th and 8th byte represent array size.
73 Aux[6] = size;
74 Aux[7] = size >> 8;
75 DIType BaseType = CTy.getTypeDerivedFrom();
76 PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TypeName);
77
78 break;
79 }
80 case dwarf:: DW_TAG_union_type:
81 case dwarf::DW_TAG_structure_type: {
82 DICompositeType CTy = DICompositeType(Ty.getGV());
83 TypeNo = TypeNo << PIC16Dbg::S_BASIC;
84 if (Ty.getTag() == dwarf::DW_TAG_structure_type)
85 TypeNo = TypeNo | PIC16Dbg::T_STRUCT;
86 else
87 TypeNo = TypeNo | PIC16Dbg::T_UNION;
88 CTy.getName(TypeName);
89 unsigned size = CTy.getSizeInBits()/8;
90 // 7th and 8th byte represent size.
91 HasAux = true;
92 Aux[6] = size;
93 Aux[7] = size >> 8;
94 break;
95 }
96 case dwarf::DW_TAG_enumeration_type: {
97 TypeNo = TypeNo << PIC16Dbg::S_BASIC;
98 TypeNo = TypeNo | PIC16Dbg::T_ENUM;
99 break;
100 }
101 default:
102 TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
103 }
104 }
105 else {
106 TypeNo = PIC16Dbg::T_NULL;
107 HasAux = false;
108 }
109 return;
110}
111
112
113unsigned PIC16DbgInfo::GetTypeDebugNumber(std::string &type) {
114 if (type == "char")
115 return PIC16Dbg::T_CHAR;
116 else if (type == "short")
117 return PIC16Dbg::T_SHORT;
118 else if (type == "int")
119 return PIC16Dbg::T_INT;
120 else if (type == "long")
121 return PIC16Dbg::T_LONG;
122 else if (type == "unsigned char")
123 return PIC16Dbg::T_UCHAR;
124 else if (type == "unsigned short")
125 return PIC16Dbg::T_USHORT;
126 else if (type == "unsigned int")
127 return PIC16Dbg::T_UINT;
128 else if (type == "unsigned long")
129 return PIC16Dbg::T_ULONG;
130 else
131 return 0;
132}
133
134short PIC16DbgInfo::getClass(DIGlobalVariable DIGV) {
135 short ClassNo;
136 if (PAN::isLocalName(DIGV.getGlobal()->getName())) {
137 // Generating C_AUTO here fails due to error in linker. Change it once
138 // linker is fixed.
139 ClassNo = PIC16Dbg::C_STAT;
140 }
141 else if (DIGV.isLocalToUnit())
142 ClassNo = PIC16Dbg::C_STAT;
143 else
144 ClassNo = PIC16Dbg::C_EXT;
145 return ClassNo;
146}
Sanjiv Guptadd4694b2009-05-28 18:24:11 +0000147
148void PIC16DbgInfo::PopulateFunctsDI(Module &M) {
149 GlobalVariable *Root = M.getGlobalVariable("llvm.dbg.subprograms");
150 if (!Root)
151 return;
152 Constant *RootC = cast<Constant>(*Root->use_begin());
153
154 for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
155 UI != UE; ++UI)
156 for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
157 UUI != UUE; ++UUI) {
158 GlobalVariable *GVSP = cast<GlobalVariable>(*UUI);
159 DISubprogram *SP = new DISubprogram(GVSP);
160 std::string Name;
161 SP->getLinkageName(Name);
162 FunctNameMap[Name] = SP;
163 }
164 return;
165}
166
167DISubprogram* PIC16DbgInfo::getFunctDI(std::string FunctName) {
168 return FunctNameMap[FunctName];
169}
170
171void PIC16DbgInfo::EmitFunctBeginDI(const Function *F) {
172 std::string FunctName = F->getName();
173 DISubprogram *SP = getFunctDI(FunctName);
174 if (SP) {
175 std::string FunctBeginSym = ".bf." + FunctName;
176 std::string BlockBeginSym = ".bb." + FunctName;
177
178 int FunctBeginLine = SP->getLineNumber();
179 int BFAux[PIC16Dbg::AuxSize] = {0};
180 BFAux[4] = FunctBeginLine;
181 BFAux[5] = FunctBeginLine >> 8;
182 // Emit debug directives for beginning of function.
183 EmitSymbol(FunctBeginSym, PIC16Dbg::C_FCN);
184 EmitAuxEntry(FunctBeginSym, BFAux, PIC16Dbg::AuxSize);
185 EmitSymbol(BlockBeginSym, PIC16Dbg::C_BLOCK);
186 EmitAuxEntry(BlockBeginSym, BFAux, PIC16Dbg::AuxSize);
187 }
188}
189
190void PIC16DbgInfo::EmitFunctEndDI(const Function *F, unsigned Line) {
191 std::string FunctName = F->getName();
192 DISubprogram *SP = getFunctDI(FunctName);
193 if (SP) {
194 std::string FunctEndSym = ".ef." + FunctName;
195 std::string BlockEndSym = ".eb." + FunctName;
196
197 // Emit debug directives for end of function.
198 EmitSymbol(BlockEndSym, PIC16Dbg::C_BLOCK);
199 int EFAux[PIC16Dbg::AuxSize] = {0};
200 // 5th and 6th byte stand for line number.
201 EFAux[4] = Line;
202 EFAux[5] = Line >> 8;
203 EmitAuxEntry(BlockEndSym, EFAux, PIC16Dbg::AuxSize);
204 EmitSymbol(FunctEndSym, PIC16Dbg::C_FCN);
205 EmitAuxEntry(FunctEndSym, EFAux, PIC16Dbg::AuxSize);
206 }
207}
208
209/// EmitAuxEntry - Emit Auxiliary debug information.
210///
211void PIC16DbgInfo::EmitAuxEntry(const std::string VarName, int Aux[], int num) {
212 O << "\n\t.dim " << VarName << ", 1" ;
213 for (int i = 0; i<num; i++)
214 O << "," << Aux[i];
215}
216
217void PIC16DbgInfo::EmitSymbol(std::string Name, int Class) {
218 O << "\n\t" << ".def "<< Name << ", debug, class = " << Class;
219}
220
221void PIC16DbgInfo::EmitVarDebugInfo(Module &M) {
222 GlobalVariable *Root = M.getGlobalVariable("llvm.dbg.global_variables");
223 if (!Root)
224 return;
225
226 Constant *RootC = cast<Constant>(*Root->use_begin());
227 for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end();
228 UI != UE; ++UI) {
229 for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end();
230 UUI != UUE; ++UUI) {
231 DIGlobalVariable DIGV(cast<GlobalVariable>(*UUI));
232 DIType Ty = DIGV.getType();
233 unsigned short TypeNo = 0;
234 bool HasAux = false;
235 int Aux[PIC16Dbg::AuxSize] = { 0 };
236 std::string TypeName = "";
237 std::string VarName = TAI->getGlobalPrefix()+DIGV.getGlobal()->getName();
238 PopulateDebugInfo(Ty, TypeNo, HasAux, Aux, TypeName);
239 // Emit debug info only if type information is availaible.
240 if (TypeNo != PIC16Dbg::T_NULL) {
241 O << "\n\t.type " << VarName << ", " << TypeNo;
242 short ClassNo = getClass(DIGV);
243 O << "\n\t.class " << VarName << ", " << ClassNo;
244 if (HasAux) {
245 if (TypeName != "") {
246 // Emit debug info for structure and union objects after
247 // .dim directive supports structure/union tag name in aux entry.
248 /* O << "\n\t.dim " << VarName << ", 1," << TypeName;
249 for (int i = 0; i<PIC16Dbg::AuxSize; i++)
250 O << "," << Aux[i];*/
251 }
252 else {
253 EmitAuxEntry(VarName, Aux, PIC16Dbg::AuxSize);
254 }
255 }
256 }
257 }
258 }
259 O << "\n";
260}
261
262void PIC16DbgInfo::EmitFileDirective(Module &M) {
263 GlobalVariable *CU = M.getNamedGlobal("llvm.dbg.compile_unit");
264 if (CU) {
265 DICompileUnit DIUnit(CU);
266 std::string Dir, FN;
Sanjiv Gupta3fc7e532009-06-03 16:27:49 +0000267 std::string File = DIUnit.getDirectory(Dir) + "/" + DIUnit.getFilename(FN);
268 O << "\n\t.file\t\"" << File << "\"\n" ;
269 CurFile = File;
Sanjiv Guptadd4694b2009-05-28 18:24:11 +0000270 }
271}
Sanjiv Gupta3fc7e532009-06-03 16:27:49 +0000272
273void PIC16DbgInfo::EmitFileDirective(const Function *F) {
274 std::string FunctName = F->getName();
275 DISubprogram *SP = getFunctDI(FunctName);
276 if (SP) {
277 std::string Dir, FN;
278 DICompileUnit CU = SP->getCompileUnit();
279 std::string File = CU.getDirectory(Dir) + "/" + CU.getFilename(FN);
280 if ( File != CurFile) {
281 EmitEOF();
282 O << "\n\t.file\t\"" << File << "\"\n" ;
283 CurFile = File;
284 }
285 }
286}
287
288void PIC16DbgInfo::EmitEOF() {
289 if (CurFile != "")
290 O << "\n\t.EOF";
291}
292