blob: 2339e45f07e11e9fb447121bcad4fbf6d491cd86 [file] [log] [blame]
Jim Laskey6af56812006-01-04 13:36:38 +00001//===-- llvm/CodeGen/MachineDebugInfo.cpp -----------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by James M. Laskey and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Jim Laskey6af56812006-01-04 13:36:38 +00009
10#include "llvm/CodeGen/MachineDebugInfo.h"
11
Jim Laskeyb3e789a2006-01-26 20:21:46 +000012#include "llvm/Constants.h"
13#include "llvm/DerivedTypes.h"
Jim Laskey86cbdba2006-02-06 15:33:21 +000014#include "llvm/GlobalVariable.h"
Jim Laskeyb3e789a2006-01-26 20:21:46 +000015#include "llvm/Intrinsics.h"
16#include "llvm/Instructions.h"
17#include "llvm/Module.h"
18#include "llvm/Support/Dwarf.h"
19
Jim Laskey86cbdba2006-02-06 15:33:21 +000020#include <iostream>
21
Jim Laskey6af56812006-01-04 13:36:38 +000022using namespace llvm;
23
24// Handle the Pass registration stuff necessary to use TargetData's.
25namespace {
Jim Laskeyb2efb852006-01-04 22:28:25 +000026 RegisterPass<MachineDebugInfo> X("machinedebuginfo", "Debug Information");
27}
Jim Laskey063e7652006-01-17 17:31:53 +000028
Jim Laskeyb3e789a2006-01-26 20:21:46 +000029//===----------------------------------------------------------------------===//
30
Jim Laskey86cbdba2006-02-06 15:33:21 +000031/// getGlobalVariablesUsing - Return all of the GlobalVariables which have the
Jim Laskeyb3e789a2006-01-26 20:21:46 +000032/// specified value in their initializer somewhere.
33static void
34getGlobalVariablesUsing(Value *V, std::vector<GlobalVariable*> &Result) {
35 // Scan though value users.
36 for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) {
37 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I)) {
Jim Laskey86cbdba2006-02-06 15:33:21 +000038 // If the user is a GlobalVariable then add to result.
Jim Laskeyb3e789a2006-01-26 20:21:46 +000039 Result.push_back(GV);
40 } else if (Constant *C = dyn_cast<Constant>(*I)) {
41 // If the user is a constant variable then scan its users
42 getGlobalVariablesUsing(C, Result);
43 }
44 }
45}
46
Jim Laskey86cbdba2006-02-06 15:33:21 +000047/// getGlobalVariablesUsing - Return all of the GlobalVariables that use the
48/// named GlobalVariable.
Jim Laskeyb3e789a2006-01-26 20:21:46 +000049static std::vector<GlobalVariable*>
50getGlobalVariablesUsing(Module &M, const std::string &RootName) {
Jim Laskey86cbdba2006-02-06 15:33:21 +000051 std::vector<GlobalVariable*> Result; // GlobalVariables matching criteria.
Jim Laskeyce72b172006-02-11 01:01:30 +000052
53 std::vector<const Type*> FieldTypes;
54 FieldTypes.push_back(Type::UIntTy);
55 FieldTypes.push_back(PointerType::get(Type::SByteTy));
Jim Laskeyb3e789a2006-01-26 20:21:46 +000056
Jim Laskey86cbdba2006-02-06 15:33:21 +000057 // Get the GlobalVariable root.
Jim Laskeyb3e789a2006-01-26 20:21:46 +000058 GlobalVariable *UseRoot = M.getGlobalVariable(RootName,
Jim Laskeyce72b172006-02-11 01:01:30 +000059 StructType::get(FieldTypes));
Jim Laskeyb3e789a2006-01-26 20:21:46 +000060
61 // If present and linkonce then scan for users.
62 if (UseRoot && UseRoot->hasLinkOnceLinkage()) {
63 getGlobalVariablesUsing(UseRoot, Result);
64 }
65
66 return Result;
67}
68
69/// getStringValue - Turn an LLVM constant pointer that eventually points to a
70/// global into a string value. Return an empty string if we can't do it.
71///
Chris Lattner22760af2006-01-27 17:31:30 +000072static const std::string getStringValue(Value *V, unsigned Offset = 0) {
Jim Laskeyb3e789a2006-01-26 20:21:46 +000073 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
74 if (GV->hasInitializer() && isa<ConstantArray>(GV->getInitializer())) {
75 ConstantArray *Init = cast<ConstantArray>(GV->getInitializer());
76 if (Init->isString()) {
77 std::string Result = Init->getAsString();
78 if (Offset < Result.size()) {
79 // If we are pointing INTO The string, erase the beginning...
80 Result.erase(Result.begin(), Result.begin()+Offset);
81
82 // Take off the null terminator, and any string fragments after it.
83 std::string::size_type NullPos = Result.find_first_of((char)0);
84 if (NullPos != std::string::npos)
85 Result.erase(Result.begin()+NullPos, Result.end());
86 return Result;
87 }
88 }
89 }
90 } else if (Constant *C = dyn_cast<Constant>(V)) {
91 if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
92 return getStringValue(GV, Offset);
93 else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
94 if (CE->getOpcode() == Instruction::GetElementPtr) {
95 // Turn a gep into the specified offset.
96 if (CE->getNumOperands() == 3 &&
97 cast<Constant>(CE->getOperand(1))->isNullValue() &&
98 isa<ConstantInt>(CE->getOperand(2))) {
99 return getStringValue(CE->getOperand(0),
100 Offset+cast<ConstantInt>(CE->getOperand(2))->getRawValue());
101 }
102 }
103 }
104 }
105 return "";
106}
Jim Laskeyd8f77ba2006-01-27 15:20:54 +0000107
Jim Laskey86cbdba2006-02-06 15:33:21 +0000108/// isStringValue - Return true if the given value can be coerced to a string.
109///
110static bool isStringValue(Value *V) {
111 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
112 if (GV->hasInitializer() && isa<ConstantArray>(GV->getInitializer())) {
113 ConstantArray *Init = cast<ConstantArray>(GV->getInitializer());
114 return Init->isString();
115 }
116 } else if (Constant *C = dyn_cast<Constant>(V)) {
117 if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
118 return isStringValue(GV);
119 else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
120 if (CE->getOpcode() == Instruction::GetElementPtr) {
121 if (CE->getNumOperands() == 3 &&
122 cast<Constant>(CE->getOperand(1))->isNullValue() &&
123 isa<ConstantInt>(CE->getOperand(2))) {
124 return isStringValue(CE->getOperand(0));
125 }
126 }
127 }
128 }
129 return false;
130}
131
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000132/// getGlobalVariable - Return either a direct or cast Global value.
Jim Laskeyd8f77ba2006-01-27 15:20:54 +0000133///
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000134static GlobalVariable *getGlobalVariable(Value *V) {
Jim Laskeyd8f77ba2006-01-27 15:20:54 +0000135 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
136 return GV;
137 } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
Jim Laskey86cbdba2006-02-06 15:33:21 +0000138 if (CE->getOpcode() == Instruction::Cast) {
139 return dyn_cast<GlobalVariable>(CE->getOperand(0));
140 }
Jim Laskeyd8f77ba2006-01-27 15:20:54 +0000141 }
142 return NULL;
143}
144
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000145/// isGlobalVariable - Return true if the given value can be coerced to a
Jim Laskey86cbdba2006-02-06 15:33:21 +0000146/// GlobalVariable.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000147static bool isGlobalVariable(Value *V) {
Jim Laskey86cbdba2006-02-06 15:33:21 +0000148 if (isa<GlobalVariable>(V) || isa<ConstantPointerNull>(V)) {
149 return true;
150 } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) {
151 if (CE->getOpcode() == Instruction::Cast) {
152 return isa<GlobalVariable>(CE->getOperand(0));
153 }
154 }
155 return false;
156}
157
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000158/// getUIntOperand - Return ith operand if it is an unsigned integer.
Jim Laskey86cbdba2006-02-06 15:33:21 +0000159///
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000160static ConstantUInt *getUIntOperand(GlobalVariable *GV, unsigned i) {
Jim Laskey86cbdba2006-02-06 15:33:21 +0000161 // Make sure the GlobalVariable has an initializer.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000162 if (!GV->hasInitializer()) return NULL;
Jim Laskeyb2efb852006-01-04 22:28:25 +0000163
Jim Laskey86cbdba2006-02-06 15:33:21 +0000164 // Get the initializer constant.
165 ConstantStruct *CI = dyn_cast<ConstantStruct>(GV->getInitializer());
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000166 if (!CI) return NULL;
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000167
Jim Laskey86cbdba2006-02-06 15:33:21 +0000168 // Check if there is at least i + 1 operands.
169 unsigned N = CI->getNumOperands();
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000170 if (i >= N) return NULL;
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000171
Jim Laskey86cbdba2006-02-06 15:33:21 +0000172 // Check constant.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000173 return dyn_cast<ConstantUInt>(CI->getOperand(i));
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000174}
Jim Laskey86cbdba2006-02-06 15:33:21 +0000175//===----------------------------------------------------------------------===//
176
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000177/// ApplyToFields - Target the visitor to each field of the debug information
Jim Laskey86cbdba2006-02-06 15:33:21 +0000178/// descriptor.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000179void DIVisitor::ApplyToFields(DebugInfoDesc *DD) {
Jim Laskey86cbdba2006-02-06 15:33:21 +0000180 DD->ApplyToFields(this);
181}
182
183//===----------------------------------------------------------------------===//
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000184/// DICountVisitor - This DIVisitor counts all the fields in the supplied debug
185/// the supplied DebugInfoDesc.
186class DICountVisitor : public DIVisitor {
Jim Laskey86cbdba2006-02-06 15:33:21 +0000187private:
188 unsigned Count; // Running count of fields.
189
190public:
Jim Laskeyce72b172006-02-11 01:01:30 +0000191 DICountVisitor() : DIVisitor(), Count(0) {}
Jim Laskey86cbdba2006-02-06 15:33:21 +0000192
193 // Accessors.
194 unsigned getCount() const { return Count; }
195
196 /// Apply - Count each of the fields.
197 ///
198 virtual void Apply(int &Field) { ++Count; }
199 virtual void Apply(unsigned &Field) { ++Count; }
200 virtual void Apply(bool &Field) { ++Count; }
201 virtual void Apply(std::string &Field) { ++Count; }
202 virtual void Apply(DebugInfoDesc *&Field) { ++Count; }
203 virtual void Apply(GlobalVariable *&Field) { ++Count; }
204};
205
206//===----------------------------------------------------------------------===//
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000207/// DIDeserializeVisitor - This DIVisitor deserializes all the fields in the
208/// supplied DebugInfoDesc.
209class DIDeserializeVisitor : public DIVisitor {
Jim Laskey86cbdba2006-02-06 15:33:21 +0000210private:
211 DIDeserializer &DR; // Active deserializer.
212 unsigned I; // Current operand index.
213 ConstantStruct *CI; // GlobalVariable constant initializer.
214
215public:
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000216 DIDeserializeVisitor(DIDeserializer &D, GlobalVariable *GV)
217 : DIVisitor()
Jim Laskey86cbdba2006-02-06 15:33:21 +0000218 , DR(D)
Jim Laskeyce72b172006-02-11 01:01:30 +0000219 , I(0)
Jim Laskey86cbdba2006-02-06 15:33:21 +0000220 , CI(cast<ConstantStruct>(GV->getInitializer()))
221 {}
222
223 /// Apply - Set the value of each of the fields.
224 ///
225 virtual void Apply(int &Field) {
226 Constant *C = CI->getOperand(I++);
227 Field = cast<ConstantSInt>(C)->getValue();
228 }
229 virtual void Apply(unsigned &Field) {
230 Constant *C = CI->getOperand(I++);
231 Field = cast<ConstantUInt>(C)->getValue();
232 }
233 virtual void Apply(bool &Field) {
234 Constant *C = CI->getOperand(I++);
235 Field = cast<ConstantBool>(C)->getValue();
236 }
237 virtual void Apply(std::string &Field) {
238 Constant *C = CI->getOperand(I++);
239 Field = getStringValue(C);
240 }
241 virtual void Apply(DebugInfoDesc *&Field) {
242 Constant *C = CI->getOperand(I++);
243 Field = DR.Deserialize(C);
244 }
245 virtual void Apply(GlobalVariable *&Field) {
246 Constant *C = CI->getOperand(I++);
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000247 Field = getGlobalVariable(C);
Jim Laskey86cbdba2006-02-06 15:33:21 +0000248 }
249};
250
251//===----------------------------------------------------------------------===//
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000252/// DISerializeVisitor - This DIVisitor serializes all the fields in
Jim Laskey86cbdba2006-02-06 15:33:21 +0000253/// the supplied DebugInfoDesc.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000254class DISerializeVisitor : public DIVisitor {
Jim Laskey86cbdba2006-02-06 15:33:21 +0000255private:
256 DISerializer &SR; // Active serializer.
257 std::vector<Constant*> &Elements; // Element accumulator.
258
259public:
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000260 DISerializeVisitor(DISerializer &S, std::vector<Constant*> &E)
261 : DIVisitor()
Jim Laskey86cbdba2006-02-06 15:33:21 +0000262 , SR(S)
263 , Elements(E)
264 {}
265
266 /// Apply - Set the value of each of the fields.
267 ///
268 virtual void Apply(int &Field) {
Jim Laskeyce72b172006-02-11 01:01:30 +0000269 Elements.push_back(ConstantSInt::get(Type::IntTy, Field));
Jim Laskey86cbdba2006-02-06 15:33:21 +0000270 }
271 virtual void Apply(unsigned &Field) {
272 Elements.push_back(ConstantUInt::get(Type::UIntTy, Field));
273 }
274 virtual void Apply(bool &Field) {
275 Elements.push_back(ConstantBool::get(Field));
276 }
277 virtual void Apply(std::string &Field) {
278 Elements.push_back(SR.getString(Field));
279 }
280 virtual void Apply(DebugInfoDesc *&Field) {
281 GlobalVariable *GV = NULL;
282
283 // If non-NULL the convert to global.
284 if (Field) GV = SR.Serialize(Field);
285
286 // FIXME - At some point should use specific type.
287 const PointerType *EmptyTy = SR.getEmptyStructPtrType();
288
289 if (GV) {
290 // Set to pointer to global.
291 Elements.push_back(ConstantExpr::getCast(GV, EmptyTy));
292 } else {
293 // Use NULL.
294 Elements.push_back(ConstantPointerNull::get(EmptyTy));
295 }
296 }
297 virtual void Apply(GlobalVariable *&Field) {
298 const PointerType *EmptyTy = SR.getEmptyStructPtrType();
Jim Laskeyce72b172006-02-11 01:01:30 +0000299 if (Field) {
300 Elements.push_back(ConstantExpr::getCast(Field, EmptyTy));
301 } else {
302 Elements.push_back(ConstantPointerNull::get(EmptyTy));
303 }
Jim Laskey86cbdba2006-02-06 15:33:21 +0000304 }
305};
306
307//===----------------------------------------------------------------------===//
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000308/// DIGetTypesVisitor - This DIVisitor gathers all the field types in
Jim Laskey86cbdba2006-02-06 15:33:21 +0000309/// the supplied DebugInfoDesc.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000310class DIGetTypesVisitor : public DIVisitor {
Jim Laskey86cbdba2006-02-06 15:33:21 +0000311private:
312 DISerializer &SR; // Active serializer.
313 std::vector<const Type*> &Fields; // Type accumulator.
314
315public:
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000316 DIGetTypesVisitor(DISerializer &S, std::vector<const Type*> &F)
317 : DIVisitor()
Jim Laskey86cbdba2006-02-06 15:33:21 +0000318 , SR(S)
319 , Fields(F)
320 {}
321
322 /// Apply - Set the value of each of the fields.
323 ///
324 virtual void Apply(int &Field) {
325 Fields.push_back(Type::IntTy);
326 }
327 virtual void Apply(unsigned &Field) {
328 Fields.push_back(Type::UIntTy);
329 }
330 virtual void Apply(bool &Field) {
331 Fields.push_back(Type::BoolTy);
332 }
333 virtual void Apply(std::string &Field) {
334 Fields.push_back(SR.getStrPtrType());
335 }
336 virtual void Apply(DebugInfoDesc *&Field) {
337 // FIXME - At some point should use specific type.
338 const PointerType *EmptyTy = SR.getEmptyStructPtrType();
339 Fields.push_back(EmptyTy);
340 }
341 virtual void Apply(GlobalVariable *&Field) {
342 const PointerType *EmptyTy = SR.getEmptyStructPtrType();
343 Fields.push_back(EmptyTy);
344 }
345};
346
347//===----------------------------------------------------------------------===//
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000348/// DIVerifyVisitor - This DIVisitor verifies all the field types against
Jim Laskey86cbdba2006-02-06 15:33:21 +0000349/// a constant initializer.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000350class DIVerifyVisitor : public DIVisitor {
Jim Laskey86cbdba2006-02-06 15:33:21 +0000351private:
352 DIVerifier &VR; // Active verifier.
353 bool IsValid; // Validity status.
354 unsigned I; // Current operand index.
355 ConstantStruct *CI; // GlobalVariable constant initializer.
356
357public:
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000358 DIVerifyVisitor(DIVerifier &V, GlobalVariable *GV)
359 : DIVisitor()
Jim Laskey86cbdba2006-02-06 15:33:21 +0000360 , VR(V)
361 , IsValid(true)
Jim Laskeyce72b172006-02-11 01:01:30 +0000362 , I(0)
Jim Laskey86cbdba2006-02-06 15:33:21 +0000363 , CI(cast<ConstantStruct>(GV->getInitializer()))
364 {
365 }
366
367 // Accessors.
368 bool isValid() const { return IsValid; }
369
370 /// Apply - Set the value of each of the fields.
371 ///
372 virtual void Apply(int &Field) {
373 Constant *C = CI->getOperand(I++);
374 IsValid = IsValid && isa<ConstantInt>(C);
375 }
376 virtual void Apply(unsigned &Field) {
377 Constant *C = CI->getOperand(I++);
378 IsValid = IsValid && isa<ConstantInt>(C);
379 }
380 virtual void Apply(bool &Field) {
381 Constant *C = CI->getOperand(I++);
382 IsValid = IsValid && isa<ConstantBool>(C);
383 }
384 virtual void Apply(std::string &Field) {
385 Constant *C = CI->getOperand(I++);
386 IsValid = IsValid && isStringValue(C);
387 }
388 virtual void Apply(DebugInfoDesc *&Field) {
389 // FIXME - Prepare the correct descriptor.
390 Constant *C = CI->getOperand(I++);
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000391 IsValid = IsValid && isGlobalVariable(C);
Jim Laskey86cbdba2006-02-06 15:33:21 +0000392 }
393 virtual void Apply(GlobalVariable *&Field) {
394 Constant *C = CI->getOperand(I++);
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000395 IsValid = IsValid && isGlobalVariable(C);
Jim Laskey86cbdba2006-02-06 15:33:21 +0000396 }
397};
398
Jim Laskeyce72b172006-02-11 01:01:30 +0000399
Jim Laskey86cbdba2006-02-06 15:33:21 +0000400//===----------------------------------------------------------------------===//
401
Jim Laskeyce72b172006-02-11 01:01:30 +0000402/// TagFromGlobal - Returns the Tag number from a debug info descriptor
403/// GlobalVariable.
404unsigned DebugInfoDesc::TagFromGlobal(GlobalVariable *GV) {
405 ConstantUInt *C = getUIntOperand(GV, 0);
406 return C ? (unsigned)C->getValue() : (unsigned)DIInvalid;
407}
408
409/// DescFactory - Create an instance of debug info descriptor based on Tag.
410/// Return NULL if not a recognized Tag.
411DebugInfoDesc *DebugInfoDesc::DescFactory(unsigned Tag) {
412 switch (Tag) {
413 case DI_TAG_anchor: return new AnchorDesc();
414 case DI_TAG_compile_unit: return new CompileUnitDesc();
415 case DI_TAG_global_variable: return new GlobalVariableDesc();
416 case DI_TAG_subprogram: return new SubprogramDesc();
417 default: break;
418 }
419 return NULL;
420}
421
422/// getLinkage - get linkage appropriate for this type of descriptor.
423///
424GlobalValue::LinkageTypes DebugInfoDesc::getLinkage() const {
425 return GlobalValue::InternalLinkage;
426}
427
428/// ApplyToFields - Target the vistor to the fields of the descriptor.
429///
430void DebugInfoDesc::ApplyToFields(DIVisitor *Visitor) {
431 Visitor->Apply(Tag);
432}
433
434//===----------------------------------------------------------------------===//
435
436/// getLinkage - get linkage appropriate for this type of descriptor.
437///
438GlobalValue::LinkageTypes AnchorDesc::getLinkage() const {
439 return GlobalValue::LinkOnceLinkage;
440}
441
442/// ApplyToFields - Target the visitor to the fields of the TransUnitDesc.
443///
444void AnchorDesc::ApplyToFields(DIVisitor *Visitor) {
445 DebugInfoDesc::ApplyToFields(Visitor);
446
447 Visitor->Apply(Name);
448}
449
450/// getDescString - Return a string used to compose global names and labels.
451///
452const char *AnchorDesc::getDescString() const {
453 return Name.c_str();
454}
455
456/// getTypeString - Return a string used to label this descriptors type.
457///
458const char *AnchorDesc::getTypeString() const {
459 return "llvm.dbg.anchor.type";
460}
461
462#ifndef NDEBUG
463void AnchorDesc::dump() {
464 std::cerr << getDescString() << " "
465 << "Tag(" << getTag() << "), "
466 << "Name(" << Name << ")\n";
467}
468#endif
469
470//===----------------------------------------------------------------------===//
471
472AnchoredDesc::AnchoredDesc(unsigned T)
473: DebugInfoDesc(T)
474, Anchor(NULL)
475{}
476
477/// ApplyToFields - Target the visitor to the fields of the AnchoredDesc.
478///
479void AnchoredDesc::ApplyToFields(DIVisitor *Visitor) {
480 DebugInfoDesc::ApplyToFields(Visitor);
481
482 Visitor->Apply((DebugInfoDesc *&)Anchor);
483}
484
485//===----------------------------------------------------------------------===//
486
487CompileUnitDesc::CompileUnitDesc()
488: AnchoredDesc(DI_TAG_compile_unit)
489, DebugVersion(LLVMDebugVersion)
490, Language(0)
491, FileName("")
492, Directory("")
493, Producer("")
494{}
495
Jim Laskey86cbdba2006-02-06 15:33:21 +0000496/// DebugVersionFromGlobal - Returns the version number from a compile unit
497/// GlobalVariable.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000498unsigned CompileUnitDesc::DebugVersionFromGlobal(GlobalVariable *GV) {
Jim Laskeyce72b172006-02-11 01:01:30 +0000499 ConstantUInt *C = getUIntOperand(GV, 2);
Jim Laskeyf60c2412006-02-06 21:54:05 +0000500 return C ? (unsigned)C->getValue() : (unsigned)DIInvalid;
Jim Laskey86cbdba2006-02-06 15:33:21 +0000501}
502
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000503/// ApplyToFields - Target the visitor to the fields of the CompileUnitDesc.
504///
505void CompileUnitDesc::ApplyToFields(DIVisitor *Visitor) {
Jim Laskeyce72b172006-02-11 01:01:30 +0000506 AnchoredDesc::ApplyToFields(Visitor);
507
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000508 Visitor->Apply(DebugVersion);
509 Visitor->Apply(Language);
510 Visitor->Apply(FileName);
511 Visitor->Apply(Directory);
512 Visitor->Apply(Producer);
Jim Laskey86cbdba2006-02-06 15:33:21 +0000513}
514
Jim Laskeyce72b172006-02-11 01:01:30 +0000515/// getDescString - Return a string used to compose global names and labels.
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000516///
Jim Laskeyce72b172006-02-11 01:01:30 +0000517const char *CompileUnitDesc::getDescString() const {
518 return "llvm.dbg.compile_unit";
519}
520
521/// getTypeString - Return a string used to label this descriptors type.
522///
523const char *CompileUnitDesc::getTypeString() const {
524 return "llvm.dbg.compile_unit.type";
525}
526
527/// getAnchorString - Return a string used to label this descriptor's anchor.
528///
529const char *CompileUnitDesc::getAnchorString() const {
530 return "llvm.dbg.compile_units";
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000531}
532
Jim Laskey86cbdba2006-02-06 15:33:21 +0000533#ifndef NDEBUG
534void CompileUnitDesc::dump() {
Jim Laskeyce72b172006-02-11 01:01:30 +0000535 std::cerr << getDescString() << " "
Jim Laskey86cbdba2006-02-06 15:33:21 +0000536 << "Tag(" << getTag() << "), "
Jim Laskeyce72b172006-02-11 01:01:30 +0000537 << "Anchor(" << getAnchor() << "), "
538 << "DebugVersion(" << DebugVersion << "), "
Jim Laskey86cbdba2006-02-06 15:33:21 +0000539 << "Language(" << Language << "), "
540 << "FileName(\"" << FileName << "\"), "
541 << "Directory(\"" << Directory << "\"), "
542 << "Producer(\"" << Producer << "\")\n";
543}
544#endif
545
546//===----------------------------------------------------------------------===//
547
Jim Laskeyce72b172006-02-11 01:01:30 +0000548GlobalDesc::GlobalDesc(unsigned T)
549: AnchoredDesc(T)
550, Context(0)
551, Name("")
552, TyDesc(NULL)
553, IsStatic(false)
554, IsDefinition(false)
555{}
556
557/// ApplyToFields - Target the visitor to the fields of the global.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000558///
Jim Laskeyce72b172006-02-11 01:01:30 +0000559void GlobalDesc::ApplyToFields(DIVisitor *Visitor) {
560 AnchoredDesc::ApplyToFields(Visitor);
561
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000562 Visitor->Apply(Context);
563 Visitor->Apply(Name);
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000564 Visitor->Apply(TyDesc);
565 Visitor->Apply(IsStatic);
566 Visitor->Apply(IsDefinition);
Jim Laskeyce72b172006-02-11 01:01:30 +0000567}
568
569//===----------------------------------------------------------------------===//
570
571GlobalVariableDesc::GlobalVariableDesc()
572: GlobalDesc(DI_TAG_global_variable)
573, Global(NULL)
574{}
575
576/// ApplyToFields - Target the visitor to the fields of the GlobalVariableDesc.
577///
578void GlobalVariableDesc::ApplyToFields(DIVisitor *Visitor) {
579 GlobalDesc::ApplyToFields(Visitor);
580
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000581 Visitor->Apply(Global);
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000582}
583
Jim Laskeyce72b172006-02-11 01:01:30 +0000584/// getDescString - Return a string used to compose global names and labels.
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000585///
Jim Laskeyce72b172006-02-11 01:01:30 +0000586const char *GlobalVariableDesc::getDescString() const {
587 return "llvm.dbg.global_variable";
588}
589
590/// getTypeString - Return a string used to label this descriptors type.
591///
592const char *GlobalVariableDesc::getTypeString() const {
593 return "llvm.dbg.global_variable.type";
594}
595
596/// getAnchorString - Return a string used to label this descriptor's anchor.
597///
598const char *GlobalVariableDesc::getAnchorString() const {
599 return "llvm.dbg.global_variables";
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000600}
601
Jim Laskey86cbdba2006-02-06 15:33:21 +0000602#ifndef NDEBUG
603void GlobalVariableDesc::dump() {
Jim Laskeyce72b172006-02-11 01:01:30 +0000604 std::cerr << getDescString() << " "
Jim Laskey86cbdba2006-02-06 15:33:21 +0000605 << "Tag(" << getTag() << "), "
Jim Laskeyce72b172006-02-11 01:01:30 +0000606 << "Anchor(" << getAnchor() << "), "
607 << "Name(\"" << getName() << "\"), "
608 << "IsStatic(" << (isStatic() ? "true" : "false") << "), "
609 << "IsDefinition(" << (isDefinition() ? "true" : "false") << "), "
Jim Laskey86cbdba2006-02-06 15:33:21 +0000610 << "Global(" << Global << ")\n";
611}
612#endif
613
614//===----------------------------------------------------------------------===//
615
Jim Laskeyce72b172006-02-11 01:01:30 +0000616SubprogramDesc::SubprogramDesc()
617: GlobalDesc(DI_TAG_subprogram)
618{}
619
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000620/// ApplyToFields - Target the visitor to the fields of the
Jim Laskey86cbdba2006-02-06 15:33:21 +0000621/// SubprogramDesc.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000622void SubprogramDesc::ApplyToFields(DIVisitor *Visitor) {
Jim Laskeyce72b172006-02-11 01:01:30 +0000623 GlobalDesc::ApplyToFields(Visitor);
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000624}
625
Jim Laskeyce72b172006-02-11 01:01:30 +0000626/// getDescString - Return a string used to compose global names and labels.
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000627///
Jim Laskeyce72b172006-02-11 01:01:30 +0000628const char *SubprogramDesc::getDescString() const {
629 return "llvm.dbg.subprogram";
630}
631
632/// getTypeString - Return a string used to label this descriptors type.
633///
634const char *SubprogramDesc::getTypeString() const {
635 return "llvm.dbg.subprogram.type";
636}
637
638/// getAnchorString - Return a string used to label this descriptor's anchor.
639///
640const char *SubprogramDesc::getAnchorString() const {
641 return "llvm.dbg.subprograms";
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000642}
643
Jim Laskey86cbdba2006-02-06 15:33:21 +0000644#ifndef NDEBUG
645void SubprogramDesc::dump() {
Jim Laskeyce72b172006-02-11 01:01:30 +0000646 std::cerr << getDescString() << " "
Jim Laskey86cbdba2006-02-06 15:33:21 +0000647 << "Tag(" << getTag() << "), "
Jim Laskeyce72b172006-02-11 01:01:30 +0000648 << "Anchor(" << getAnchor() << "), "
649 << "Name(\"" << getName() << "\"), "
650 << "IsStatic(" << (isStatic() ? "true" : "false") << "), "
651 << "IsDefinition(" << (isDefinition() ? "true" : "false") << ")\n";
Jim Laskey86cbdba2006-02-06 15:33:21 +0000652}
653#endif
654
655//===----------------------------------------------------------------------===//
656
657DebugInfoDesc *DIDeserializer::Deserialize(Value *V) {
Jim Laskeyce72b172006-02-11 01:01:30 +0000658 return Deserialize(getGlobalVariable(V));
Jim Laskey86cbdba2006-02-06 15:33:21 +0000659}
660DebugInfoDesc *DIDeserializer::Deserialize(GlobalVariable *GV) {
Jim Laskeyce72b172006-02-11 01:01:30 +0000661 // Handle NULL.
662 if (!GV) return NULL;
663
Jim Laskey86cbdba2006-02-06 15:33:21 +0000664 // Check to see if it has been already deserialized.
665 DebugInfoDesc *&Slot = GlobalDescs[GV];
666 if (Slot) return Slot;
667
668 // Get the Tag from the global.
669 unsigned Tag = DebugInfoDesc::TagFromGlobal(GV);
670
671 // Get the debug version if a compile unit.
672 if (Tag == DI_TAG_compile_unit) {
673 DebugVersion = CompileUnitDesc::DebugVersionFromGlobal(GV);
674 }
675
676 // Create an empty instance of the correct sort.
677 Slot = DebugInfoDesc::DescFactory(Tag);
678 assert(Slot && "Unknown Tag");
679
680 // Deserialize the fields.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000681 DIDeserializeVisitor DRAM(*this, GV);
Jim Laskey86cbdba2006-02-06 15:33:21 +0000682 DRAM.ApplyToFields(Slot);
683
684 return Slot;
685}
686
687//===----------------------------------------------------------------------===//
688
689/// getStrPtrType - Return a "sbyte *" type.
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000690///
Jim Laskey86cbdba2006-02-06 15:33:21 +0000691const PointerType *DISerializer::getStrPtrType() {
692 // If not already defined.
693 if (!StrPtrTy) {
694 // Construct the pointer to signed bytes.
695 StrPtrTy = PointerType::get(Type::SByteTy);
696 }
697
698 return StrPtrTy;
699}
700
701/// getEmptyStructPtrType - Return a "{ }*" type.
702///
703const PointerType *DISerializer::getEmptyStructPtrType() {
704 // If not already defined.
705 if (!EmptyStructPtrTy) {
706 // Construct the empty structure type.
707 const StructType *EmptyStructTy =
708 StructType::get(std::vector<const Type*>());
709 // Construct the pointer to empty structure type.
710 EmptyStructPtrTy = PointerType::get(EmptyStructTy);
711 }
712
713 return EmptyStructPtrTy;
714}
715
716/// getTagType - Return the type describing the specified descriptor (via tag.)
717///
718const StructType *DISerializer::getTagType(DebugInfoDesc *DD) {
719 // Attempt to get the previously defined type.
720 StructType *&Ty = TagTypes[DD->getTag()];
721
722 // If not already defined.
723 if (!Ty) {
Jim Laskey86cbdba2006-02-06 15:33:21 +0000724 // Set up fields vector.
725 std::vector<const Type*> Fields;
Jim Laskeyce72b172006-02-11 01:01:30 +0000726 // Get types of fields.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000727 DIGetTypesVisitor GTAM(*this, Fields);
Jim Laskey86cbdba2006-02-06 15:33:21 +0000728 GTAM.ApplyToFields(DD);
729
730 // Construct structured type.
731 Ty = StructType::get(Fields);
732
Jim Laskey86cbdba2006-02-06 15:33:21 +0000733 // Register type name with module.
Jim Laskeyce72b172006-02-11 01:01:30 +0000734 M->addTypeName(DD->getTypeString(), Ty);
Jim Laskey86cbdba2006-02-06 15:33:21 +0000735 }
736
737 return Ty;
738}
739
740/// getString - Construct the string as constant string global.
741///
Jim Laskeyce72b172006-02-11 01:01:30 +0000742Constant *DISerializer::getString(const std::string &String) {
Jim Laskey86cbdba2006-02-06 15:33:21 +0000743 // Check string cache for previous edition.
Jim Laskeyce72b172006-02-11 01:01:30 +0000744 Constant *&Slot = StringCache[String];
745 // return Constant if previously defined.
Jim Laskey86cbdba2006-02-06 15:33:21 +0000746 if (Slot) return Slot;
Jim Laskeyce72b172006-02-11 01:01:30 +0000747 // Construct string as an llvm constant.
Jim Laskey86cbdba2006-02-06 15:33:21 +0000748 Constant *ConstStr = ConstantArray::get(String);
749 // Otherwise create and return a new string global.
Jim Laskeyce72b172006-02-11 01:01:30 +0000750 GlobalVariable *StrGV = new GlobalVariable(ConstStr->getType(), true,
751 GlobalVariable::InternalLinkage,
752 ConstStr, "str", M);
753 // Convert to generic string pointer.
754 Slot = ConstantExpr::getCast(StrGV, getStrPtrType());
755 return Slot;
756
Jim Laskey86cbdba2006-02-06 15:33:21 +0000757}
758
759/// Serialize - Recursively cast the specified descriptor into a GlobalVariable
760/// so that it can be serialized to a .bc or .ll file.
761GlobalVariable *DISerializer::Serialize(DebugInfoDesc *DD) {
762 // Check if the DebugInfoDesc is already in the map.
763 GlobalVariable *&Slot = DescGlobals[DD];
764
765 // See if DebugInfoDesc exists, if so return prior GlobalVariable.
766 if (Slot) return Slot;
767
Jim Laskey86cbdba2006-02-06 15:33:21 +0000768 // Get the type associated with the Tag.
769 const StructType *Ty = getTagType(DD);
770
771 // Create the GlobalVariable early to prevent infinite recursion.
Jim Laskeyce72b172006-02-11 01:01:30 +0000772 GlobalVariable *GV = new GlobalVariable(Ty, true, DD->getLinkage(),
773 NULL, DD->getDescString(), M);
Jim Laskey86cbdba2006-02-06 15:33:21 +0000774
775 // Insert new GlobalVariable in DescGlobals map.
776 Slot = GV;
777
778 // Set up elements vector
779 std::vector<Constant*> Elements;
Jim Laskeyce72b172006-02-11 01:01:30 +0000780 // Add fields.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000781 DISerializeVisitor SRAM(*this, Elements);
Jim Laskey86cbdba2006-02-06 15:33:21 +0000782 SRAM.ApplyToFields(DD);
783
784 // Set the globals initializer.
785 GV->setInitializer(ConstantStruct::get(Ty, Elements));
786
787 return GV;
788}
789
790//===----------------------------------------------------------------------===//
791
792/// markVisited - Return true if the GlobalVariable hase been "seen" before.
793/// Mark visited otherwise.
794bool DIVerifier::markVisited(GlobalVariable *GV) {
795 // Check if the GlobalVariable is already in the Visited set.
796 std::set<GlobalVariable *>::iterator VI = Visited.lower_bound(GV);
797
798 // See if GlobalVariable exists.
799 bool Exists = VI != Visited.end() && *VI == GV;
800
801 // Insert in set.
802 if (!Exists) Visited.insert(VI, GV);
803
804 return Exists;
805}
806
807/// Verify - Return true if the GlobalVariable appears to be a valid
808/// serialization of a DebugInfoDesc.
Jim Laskeyce72b172006-02-11 01:01:30 +0000809bool DIVerifier::Verify(Value *V) {
810 return Verify(getGlobalVariable(V));
811}
Jim Laskey86cbdba2006-02-06 15:33:21 +0000812bool DIVerifier::Verify(GlobalVariable *GV) {
813 // Check if seen before.
814 if (markVisited(GV)) return true;
815
816 // Get the Tag
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000817 unsigned Tag = DebugInfoDesc::TagFromGlobal(GV);
Jim Laskeyf60c2412006-02-06 21:54:05 +0000818 if (Tag == DIInvalid) return false;
Jim Laskey86cbdba2006-02-06 15:33:21 +0000819
820 // If a compile unit we need the debug version.
821 if (Tag == DI_TAG_compile_unit) {
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000822 DebugVersion = CompileUnitDesc::DebugVersionFromGlobal(GV);
Jim Laskeyf60c2412006-02-06 21:54:05 +0000823 if (DebugVersion == DIInvalid) return false;
Jim Laskey86cbdba2006-02-06 15:33:21 +0000824 }
825
826 // Construct an empty DebugInfoDesc.
827 DebugInfoDesc *DD = DebugInfoDesc::DescFactory(Tag);
828 if (!DD) return false;
829
830 // Get the initializer constant.
831 ConstantStruct *CI = cast<ConstantStruct>(GV->getInitializer());
832
833 // Get the operand count.
834 unsigned N = CI->getNumOperands();
835
836 // Get the field count.
837 unsigned &Slot = Counts[Tag];
838 if (!Slot) {
839 // Check the operand count to the field count
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000840 DICountVisitor CTAM;
Jim Laskey86cbdba2006-02-06 15:33:21 +0000841 CTAM.ApplyToFields(DD);
842 Slot = CTAM.getCount();
843 }
844
845 // Field count must equal operand count.
846 if (Slot != N) {
847 delete DD;
848 return false;
849 }
850
851 // Check each field for valid type.
Jim Laskeyc2f0c8d2006-02-06 19:12:02 +0000852 DIVerifyVisitor VRAM(*this, GV);
Jim Laskey86cbdba2006-02-06 15:33:21 +0000853 VRAM.ApplyToFields(DD);
854
855 // Release empty DebugInfoDesc.
856 delete DD;
857
858 // Return result of field tests.
859 return VRAM.isValid();
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000860}
861
862//===----------------------------------------------------------------------===//
863
864
865MachineDebugInfo::MachineDebugInfo()
Jim Laskeyce72b172006-02-11 01:01:30 +0000866: DR()
Jim Laskey86cbdba2006-02-06 15:33:21 +0000867, CompileUnits()
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000868, Directories()
869, SourceFiles()
870, Lines()
871{
872
873}
874MachineDebugInfo::~MachineDebugInfo() {
875
876}
877
Jim Laskeyb2efb852006-01-04 22:28:25 +0000878/// doInitialization - Initialize the debug state for a new module.
879///
880bool MachineDebugInfo::doInitialization() {
881 return false;
Jim Laskey6af56812006-01-04 13:36:38 +0000882}
883
Jim Laskeyb2efb852006-01-04 22:28:25 +0000884/// doFinalization - Tear down the debug state after completion of a module.
885///
886bool MachineDebugInfo::doFinalization() {
887 return false;
888}
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000889
Jim Laskeyd96185a2006-02-13 12:50:39 +0000890/// getDescFor - Convert a Value to a debug information descriptor.
Jim Laskeyce72b172006-02-11 01:01:30 +0000891///
Jim Laskeyd96185a2006-02-13 12:50:39 +0000892// FIXME - use new Value type when available.
893DebugInfoDesc *MachineDebugInfo::getDescFor(Value *V) {
Jim Laskeyce72b172006-02-11 01:01:30 +0000894 return DR.Deserialize(V);
895}
896
897/// Verify - Verify that a Value is debug information descriptor.
898///
899bool MachineDebugInfo::Verify(Value *V) {
900 DIVerifier VR;
901 return VR.Verify(V);
902}
903
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000904/// AnalyzeModule - Scan the module for global debug information.
905///
906void MachineDebugInfo::AnalyzeModule(Module &M) {
907 SetupCompileUnits(M);
908}
909
910/// SetupCompileUnits - Set up the unique vector of compile units.
911///
912void MachineDebugInfo::SetupCompileUnits(Module &M) {
913 // Get vector of all debug compile units.
Jim Laskeyce72b172006-02-11 01:01:30 +0000914 CompileUnitDesc CompileUnit;
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000915 std::vector<GlobalVariable*> Globals =
Jim Laskeyce72b172006-02-11 01:01:30 +0000916 getGlobalVariablesUsing(M, CompileUnit.getAnchorString());
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000917
918 // Scan all compile unit globals.
919 for (unsigned i = 0, N = Globals.size(); i < N; ++i) {
Jim Laskey86cbdba2006-02-06 15:33:21 +0000920 // Add compile unit to result.
921 CompileUnits.insert(
922 static_cast<CompileUnitDesc *>(DR.Deserialize(Globals[i])));
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000923 }
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000924}
925
Jim Laskey6e87c0e2006-01-26 21:22:49 +0000926/// getCompileUnits - Return a vector of debug compile units.
927///
Jim Laskey86cbdba2006-02-06 15:33:21 +0000928const UniqueVector<CompileUnitDesc *> MachineDebugInfo::getCompileUnits()const{
Jim Laskey6e87c0e2006-01-26 21:22:49 +0000929 return CompileUnits;
930}
931
Jim Laskey86cbdba2006-02-06 15:33:21 +0000932/// getGlobalVariables - Return a vector of debug GlobalVariables.
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000933///
Jim Laskey86cbdba2006-02-06 15:33:21 +0000934std::vector<GlobalVariableDesc *>
935MachineDebugInfo::getGlobalVariables(Module &M) {
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000936 // Get vector of all debug global objects.
Jim Laskeyce72b172006-02-11 01:01:30 +0000937 GlobalVariableDesc Global;
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000938 std::vector<GlobalVariable*> Globals =
Jim Laskeyce72b172006-02-11 01:01:30 +0000939 getGlobalVariablesUsing(M, Global.getAnchorString());
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000940
Jim Laskey86cbdba2006-02-06 15:33:21 +0000941 // Accumulation of GlobalVariables.
942 std::vector<GlobalVariableDesc *> GlobalVariables;
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000943
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000944 // Scan all globals.
945 for (unsigned i = 0, N = Globals.size(); i < N; ++i) {
Jim Laskey86cbdba2006-02-06 15:33:21 +0000946 GlobalVariable *GV = Globals[i];
Jim Laskeyce72b172006-02-11 01:01:30 +0000947 GlobalVariableDesc *GVD =
948 static_cast<GlobalVariableDesc *>(DR.Deserialize(GV));
949 GlobalVariables.push_back(GVD);
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000950 }
Jim Laskeyb3e789a2006-01-26 20:21:46 +0000951
952 return GlobalVariables;
953}
954