Jim Laskey | 6af5681 | 2006-01-04 13:36:38 +0000 | [diff] [blame] | 1 | //===-- 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 Laskey | 6af5681 | 2006-01-04 13:36:38 +0000 | [diff] [blame] | 9 | |
| 10 | #include "llvm/CodeGen/MachineDebugInfo.h" |
| 11 | |
Jim Laskey | b3e789a | 2006-01-26 20:21:46 +0000 | [diff] [blame] | 12 | #include "llvm/Constants.h" |
| 13 | #include "llvm/DerivedTypes.h" |
| 14 | #include "llvm/Intrinsics.h" |
| 15 | #include "llvm/Instructions.h" |
| 16 | #include "llvm/Module.h" |
| 17 | #include "llvm/Support/Dwarf.h" |
| 18 | |
Jim Laskey | 6af5681 | 2006-01-04 13:36:38 +0000 | [diff] [blame] | 19 | using namespace llvm; |
| 20 | |
| 21 | // Handle the Pass registration stuff necessary to use TargetData's. |
| 22 | namespace { |
Jim Laskey | b2efb85 | 2006-01-04 22:28:25 +0000 | [diff] [blame] | 23 | RegisterPass<MachineDebugInfo> X("machinedebuginfo", "Debug Information"); |
| 24 | } |
Jim Laskey | 063e765 | 2006-01-17 17:31:53 +0000 | [diff] [blame] | 25 | |
Jim Laskey | b3e789a | 2006-01-26 20:21:46 +0000 | [diff] [blame] | 26 | //===----------------------------------------------------------------------===// |
| 27 | |
| 28 | /// getGlobalVariablesUsing - Return all of the global variables which have the |
| 29 | /// specified value in their initializer somewhere. |
| 30 | static void |
| 31 | getGlobalVariablesUsing(Value *V, std::vector<GlobalVariable*> &Result) { |
| 32 | // Scan though value users. |
| 33 | for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) { |
| 34 | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I)) { |
| 35 | // If the user is a global variable then add to result. |
| 36 | Result.push_back(GV); |
| 37 | } else if (Constant *C = dyn_cast<Constant>(*I)) { |
| 38 | // If the user is a constant variable then scan its users |
| 39 | getGlobalVariablesUsing(C, Result); |
| 40 | } |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | /// getGlobalVariablesUsing - Return all of the global variables that use the |
| 45 | /// named global variable. |
| 46 | static std::vector<GlobalVariable*> |
| 47 | getGlobalVariablesUsing(Module &M, const std::string &RootName) { |
| 48 | std::vector<GlobalVariable*> Result; // Global variables matching criteria. |
| 49 | |
| 50 | // Get the global variable root. |
| 51 | GlobalVariable *UseRoot = M.getGlobalVariable(RootName, |
| 52 | StructType::get(std::vector<const Type*>())); |
| 53 | |
| 54 | // If present and linkonce then scan for users. |
| 55 | if (UseRoot && UseRoot->hasLinkOnceLinkage()) { |
| 56 | getGlobalVariablesUsing(UseRoot, Result); |
| 57 | } |
| 58 | |
| 59 | return Result; |
| 60 | } |
| 61 | |
| 62 | /// getStringValue - Turn an LLVM constant pointer that eventually points to a |
| 63 | /// global into a string value. Return an empty string if we can't do it. |
| 64 | /// |
| 65 | const static std::string getStringValue(Value *V, unsigned Offset = 0) { |
| 66 | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) { |
| 67 | if (GV->hasInitializer() && isa<ConstantArray>(GV->getInitializer())) { |
| 68 | ConstantArray *Init = cast<ConstantArray>(GV->getInitializer()); |
| 69 | if (Init->isString()) { |
| 70 | std::string Result = Init->getAsString(); |
| 71 | if (Offset < Result.size()) { |
| 72 | // If we are pointing INTO The string, erase the beginning... |
| 73 | Result.erase(Result.begin(), Result.begin()+Offset); |
| 74 | |
| 75 | // Take off the null terminator, and any string fragments after it. |
| 76 | std::string::size_type NullPos = Result.find_first_of((char)0); |
| 77 | if (NullPos != std::string::npos) |
| 78 | Result.erase(Result.begin()+NullPos, Result.end()); |
| 79 | return Result; |
| 80 | } |
| 81 | } |
| 82 | } |
| 83 | } else if (Constant *C = dyn_cast<Constant>(V)) { |
| 84 | if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) |
| 85 | return getStringValue(GV, Offset); |
| 86 | else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { |
| 87 | if (CE->getOpcode() == Instruction::GetElementPtr) { |
| 88 | // Turn a gep into the specified offset. |
| 89 | if (CE->getNumOperands() == 3 && |
| 90 | cast<Constant>(CE->getOperand(1))->isNullValue() && |
| 91 | isa<ConstantInt>(CE->getOperand(2))) { |
| 92 | return getStringValue(CE->getOperand(0), |
| 93 | Offset+cast<ConstantInt>(CE->getOperand(2))->getRawValue()); |
| 94 | } |
| 95 | } |
| 96 | } |
| 97 | } |
| 98 | return ""; |
| 99 | } |
Jim Laskey | b2efb85 | 2006-01-04 22:28:25 +0000 | [diff] [blame] | 100 | |
Jim Laskey | 063e765 | 2006-01-17 17:31:53 +0000 | [diff] [blame] | 101 | //===----------------------------------------------------------------------===// |
Jim Laskey | b3e789a | 2006-01-26 20:21:46 +0000 | [diff] [blame] | 102 | |
| 103 | DebugInfoWrapper::DebugInfoWrapper(GlobalVariable *G) |
| 104 | : GV(G) |
| 105 | , IC(dyn_cast<ConstantStruct>(GV->getInitializer())) { |
| 106 | assert(IC && "llvm.db.global is missing structured constant"); |
| 107 | } |
| 108 | |
| 109 | //===----------------------------------------------------------------------===// |
| 110 | |
| 111 | CompileUnitWrapper::CompileUnitWrapper(GlobalVariable *G) |
| 112 | : DebugInfoWrapper(G) |
| 113 | { |
| 114 | // FIXME - should probably ease up on the number of operands (version.) |
| 115 | assert(IC->getNumOperands() == 7 && |
| 116 | "Compile unit does not have correct number of operands"); |
| 117 | } |
| 118 | |
| 119 | /// getTag - Return the compile unit's tag number. Currently should be |
| 120 | /// DW_TAG_variable. |
| 121 | unsigned CompileUnitWrapper::getTag() const { |
| 122 | ConstantUInt *CI = dyn_cast<ConstantUInt>(IC->getOperand(0)); |
| 123 | assert(CI && "Compile unit tag not an unsigned integer"); |
| 124 | return CI->getValue(); |
| 125 | } |
| 126 | |
| 127 | /// isCorrectDebugVersion - Return true if is the correct llvm debug version. |
| 128 | /// Currently the value is 0 (zero.) If the value is is not correct then |
| 129 | /// ignore all debug information. |
| 130 | bool CompileUnitWrapper::isCorrectDebugVersion() const { |
| 131 | ConstantUInt *CI = dyn_cast<ConstantUInt>(IC->getOperand(1)); |
| 132 | assert(CI && "Compile unit debug version not an unsigned integer"); |
| 133 | return CI->getValue() == 0; |
| 134 | } |
| 135 | |
| 136 | /// getLanguage - Return the compile unit's language number (ex. DW_LANG_C89.) |
| 137 | /// |
| 138 | unsigned CompileUnitWrapper::getLanguage() const { |
| 139 | ConstantUInt *CI = dyn_cast<ConstantUInt>(IC->getOperand(2)); |
| 140 | assert(CI && "Compile unit language number not an unsigned integer"); |
| 141 | return CI->getValue(); |
| 142 | } |
| 143 | |
| 144 | /// getFileName - Return the compile unit's file name. |
| 145 | /// |
| 146 | const std::string CompileUnitWrapper::getFileName() const { |
| 147 | return getStringValue(IC->getOperand(3)); |
| 148 | } |
| 149 | |
| 150 | /// getDirectory - Return the compile unit's file directory. |
| 151 | /// |
| 152 | const std::string CompileUnitWrapper::getDirectory() const { |
| 153 | return getStringValue(IC->getOperand(4)); |
| 154 | } |
| 155 | |
| 156 | /// getProducer - Return the compile unit's generator name. |
| 157 | /// |
| 158 | const std::string CompileUnitWrapper::getProducer() const { |
| 159 | return getStringValue(IC->getOperand(5)); |
| 160 | } |
| 161 | |
| 162 | //===----------------------------------------------------------------------===// |
| 163 | |
| 164 | GlobalWrapper::GlobalWrapper(GlobalVariable *G) |
| 165 | : DebugInfoWrapper(G) |
| 166 | { |
| 167 | // FIXME - should probably ease up on the number of operands (version.) |
| 168 | assert(IC->getNumOperands() == 8 && |
| 169 | "Global does not have correct number of operands"); |
| 170 | } |
| 171 | |
| 172 | /// getTag - Return the global's tag number. Currently should be |
| 173 | /// DW_TAG_variable or DW_TAG_subprogram. |
| 174 | unsigned GlobalWrapper::getTag() const { |
| 175 | ConstantUInt *CI = dyn_cast<ConstantUInt>(IC->getOperand(0)); |
| 176 | assert(CI && "Global tag not an unsigned integer"); |
| 177 | return CI->getValue(); |
| 178 | } |
| 179 | |
| 180 | /// getContext - Return the "lldb.compile_unit" context global. |
| 181 | /// |
| 182 | GlobalVariable *GlobalWrapper::getContext() const { |
| 183 | return dyn_cast<GlobalVariable>(IC->getOperand(1)); |
| 184 | } |
| 185 | |
| 186 | /// getName - Return the name of the global. |
| 187 | /// |
| 188 | const std::string GlobalWrapper::getName() const { |
| 189 | return getStringValue(IC->getOperand(2)); |
| 190 | } |
| 191 | |
| 192 | /// getType - Return the type of the global. |
| 193 | /// |
| 194 | const GlobalVariable *GlobalWrapper::getType() const { |
| 195 | return dyn_cast<GlobalVariable>(IC->getOperand(4)); |
| 196 | } |
| 197 | |
| 198 | /// isStatic - Return true if the global is static. |
| 199 | /// |
| 200 | bool GlobalWrapper::isStatic() const { |
| 201 | ConstantBool *CB = dyn_cast<ConstantBool>(IC->getOperand(5)); |
| 202 | assert(CB && "Global static flag is not boolean"); |
| 203 | return CB->getValue(); |
| 204 | } |
| 205 | |
| 206 | /// isDefinition - Return true if the global is a definition. |
| 207 | /// |
| 208 | bool GlobalWrapper::isDefinition() const { |
| 209 | ConstantBool *CB = dyn_cast<ConstantBool>(IC->getOperand(6)); |
| 210 | assert(CB && "Global definition flag is not boolean"); |
| 211 | return CB->getValue(); |
| 212 | } |
| 213 | |
| 214 | /// getGlobalVariable - Return the global variable (tag == DW_TAG_variable.) |
| 215 | /// |
| 216 | GlobalVariable *GlobalWrapper::getGlobalVariable() const { |
| 217 | ConstantExpr *CE = dyn_cast<ConstantExpr>(IC->getOperand(7)); |
| 218 | assert(CE && CE->getOpcode() == Instruction::Cast && |
| 219 | "Global location is not a cast of GlobalVariable"); |
| 220 | GlobalVariable *GV = dyn_cast<GlobalVariable>(CE->getOperand(0)); |
| 221 | assert(GV && "Global location is not a cast of GlobalVariable"); |
| 222 | return GV; |
| 223 | } |
| 224 | |
| 225 | //===----------------------------------------------------------------------===// |
| 226 | |
| 227 | |
| 228 | MachineDebugInfo::MachineDebugInfo() |
| 229 | : CompileUnits() |
| 230 | , Directories() |
| 231 | , SourceFiles() |
| 232 | , Lines() |
| 233 | { |
| 234 | |
| 235 | } |
| 236 | MachineDebugInfo::~MachineDebugInfo() { |
| 237 | |
| 238 | } |
| 239 | |
Jim Laskey | b2efb85 | 2006-01-04 22:28:25 +0000 | [diff] [blame] | 240 | /// doInitialization - Initialize the debug state for a new module. |
| 241 | /// |
| 242 | bool MachineDebugInfo::doInitialization() { |
| 243 | return false; |
Jim Laskey | 6af5681 | 2006-01-04 13:36:38 +0000 | [diff] [blame] | 244 | } |
| 245 | |
Jim Laskey | b2efb85 | 2006-01-04 22:28:25 +0000 | [diff] [blame] | 246 | /// doFinalization - Tear down the debug state after completion of a module. |
| 247 | /// |
| 248 | bool MachineDebugInfo::doFinalization() { |
| 249 | return false; |
| 250 | } |
Jim Laskey | b3e789a | 2006-01-26 20:21:46 +0000 | [diff] [blame] | 251 | |
| 252 | /// AnalyzeModule - Scan the module for global debug information. |
| 253 | /// |
| 254 | void MachineDebugInfo::AnalyzeModule(Module &M) { |
| 255 | SetupCompileUnits(M); |
| 256 | } |
| 257 | |
| 258 | /// SetupCompileUnits - Set up the unique vector of compile units. |
| 259 | /// |
| 260 | void MachineDebugInfo::SetupCompileUnits(Module &M) { |
| 261 | // Get vector of all debug compile units. |
| 262 | std::vector<GlobalVariable*> Globals = |
| 263 | getGlobalVariablesUsing(M, "llvm.dbg.translation_units"); |
| 264 | |
| 265 | // Scan all compile unit globals. |
| 266 | for (unsigned i = 0, N = Globals.size(); i < N; ++i) { |
| 267 | // Create wrapper for compile unit. |
| 268 | CompileUnitWrapper CUI(Globals[i]); |
| 269 | // Add to result. |
| 270 | if (CUI.isCorrectDebugVersion()) CompileUnits.insert(CUI); |
| 271 | } |
| 272 | |
| 273 | // If there any bad compile units then suppress debug information |
| 274 | if (CompileUnits.size() != Globals.size()) CompileUnits.reset(); |
| 275 | } |
| 276 | |
| 277 | /// getGlobalVariables - Return a vector of debug global variables. |
| 278 | /// |
| 279 | std::vector<GlobalWrapper> MachineDebugInfo::getGlobalVariables(Module &M) { |
| 280 | // Get vector of all debug global objects. |
| 281 | std::vector<GlobalVariable*> Globals = |
| 282 | getGlobalVariablesUsing(M, "llvm.dbg.globals"); |
| 283 | |
| 284 | // Accumulation of global variables. |
| 285 | std::vector<GlobalWrapper> GlobalVariables; |
| 286 | |
| 287 | // FIXME - skip until globals have new format |
| 288 | #if 0 |
| 289 | // Scan all globals. |
| 290 | for (unsigned i = 0, N = Globals.size(); i < N; ++i) { |
| 291 | // Create wrapper for global. |
| 292 | GlobalWrapper GW(Globals[i]); |
| 293 | // If the global is a variable then add to result. |
| 294 | if (GW.getTag() == DW_TAG_variable) GlobalVariables.push_back(GW); |
| 295 | } |
| 296 | #endif |
| 297 | |
| 298 | return GlobalVariables; |
| 299 | } |
| 300 | |