From a57bc3ba02a470ee8cf70f50389489aa80c703cb Mon Sep 17 00:00:00 2001 From: Sanjiv Gupta Date: Fri, 22 May 2009 13:58:45 +0000 Subject: [PATCH] Emit debug information for globals (which include automatic variables as well because on PIC16 they are emitted as globals by the frontend). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72262 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PIC16/PIC16AsmPrinter.cpp | 47 +++++++++ lib/Target/PIC16/PIC16AsmPrinter.h | 4 + lib/Target/PIC16/PIC16DebugInfo.cpp | 138 +++++++++++++++++++++++++++ lib/Target/PIC16/PIC16DebugInfo.h | 93 ++++++++++++++++++ 4 files changed, 282 insertions(+) create mode 100644 lib/Target/PIC16/PIC16DebugInfo.cpp create mode 100644 lib/Target/PIC16/PIC16DebugInfo.h diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp index 3e8ac016edc..738723bbb5e 100644 --- a/lib/Target/PIC16/PIC16AsmPrinter.cpp +++ b/lib/Target/PIC16/PIC16AsmPrinter.cpp @@ -273,6 +273,8 @@ void PIC16AsmPrinter::EmitRomData (Module &M) bool PIC16AsmPrinter::doFinalization(Module &M) { printLibcallDecls(); + EmitVarDebugInfo(M); + O << "\t" << ".EOF\n"; O << "\t" << "END\n"; bool Result = AsmPrinter::doFinalization(M); return Result; @@ -384,3 +386,48 @@ void PIC16AsmPrinter::EmitAutos (Module &M) } } } + +void PIC16AsmPrinter::EmitVarDebugInfo(Module &M) { + GlobalVariable *Root = M.getGlobalVariable("llvm.dbg.global_variables"); + if (!Root) + return; + + O << TAI->getCommentString() << " Debug Information:"; + Constant *RootC = cast(*Root->use_begin()); + for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end(); + UI != UE; ++UI) { + for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end(); + UUI != UUE; ++UUI) { + DIGlobalVariable DIGV(cast(*UUI)); + DIType Ty = DIGV.getType(); + unsigned short TypeNo = 0; + bool HasAux = false; + int Aux[20] = { 0 }; + std::string TypeName = ""; + std::string VarName = TAI->getGlobalPrefix()+DIGV.getGlobal()->getName(); + DbgInfo.PopulateDebugInfo(Ty, TypeNo, HasAux, Aux, TypeName); + // Emit debug info only if type information is availaible. + if (TypeNo != PIC16Dbg::T_NULL) { + O << "\n\t.type " << VarName << ", " << TypeNo; + short ClassNo = DbgInfo.getClass(DIGV); + O << "\n\t.class " << VarName << ", " << ClassNo; + if (HasAux) { + if (TypeName != "") { + // Emit debug info for structure and union objects after + // .dim directive supports structure/union tag name in aux entry. + /* O << "\n\t.dim " << VarName << ", 1," << TypeName; + for (int i = 0; i<20; i++) + O << "," << Aux[i];*/ + } + else { + O << "\n\t.dim " << VarName << ", 1" ; + for (int i = 0; i<20; i++) + O << "," << Aux[i]; + } + } + } + } + } + O << "\n"; +} + diff --git a/lib/Target/PIC16/PIC16AsmPrinter.h b/lib/Target/PIC16/PIC16AsmPrinter.h index 32a2ebdca91..adcd64d44ea 100644 --- a/lib/Target/PIC16/PIC16AsmPrinter.h +++ b/lib/Target/PIC16/PIC16AsmPrinter.h @@ -17,6 +17,8 @@ #include "PIC16.h" #include "PIC16TargetMachine.h" +#include "PIC16DebugInfo.h" +#include "llvm/Analysis/DebugInfo.h" #include "PIC16TargetAsmInfo.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/Support/CommandLine.h" @@ -53,6 +55,7 @@ namespace llvm { void EmitRomData (Module &M); void emitFunctionData(MachineFunction &MF); void printLibcallDecls(void); + void EmitVarDebugInfo (Module &M); protected: bool doInitialization(Module &M); @@ -60,6 +63,7 @@ namespace llvm { private: PIC16TargetLowering *PTLI; + PIC16DbgInfo DbgInfo; const PIC16TargetAsmInfo *PTAI; std::list LibcallDecls; // List of extern decls. }; diff --git a/lib/Target/PIC16/PIC16DebugInfo.cpp b/lib/Target/PIC16/PIC16DebugInfo.cpp new file mode 100644 index 00000000000..166d96e9f65 --- /dev/null +++ b/lib/Target/PIC16/PIC16DebugInfo.cpp @@ -0,0 +1,138 @@ +//===-- PIC16DebugInfo.cpp - Implementation for PIC16 Debug Information ======// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the helper functions for representing debug information. +// +//===----------------------------------------------------------------------===// + +#include "PIC16.h" +#include "PIC16DebugInfo.h" +#include "llvm/GlobalVariable.h" + +using namespace llvm; + +void PIC16DbgInfo::PopulateDebugInfo(DIType Ty, unsigned short &TypeNo, + bool &HasAux, int Aux[], + std::string &TypeName) { + if (Ty.isBasicType(Ty.getTag())) { + std::string Name = ""; + Ty.getName(Name); + unsigned short BaseTy = GetTypeDebugNumber(Name); + TypeNo = TypeNo << PIC16Dbg::S_BASIC; + TypeNo = TypeNo | (0xffff & BaseTy); + } + else if (Ty.isDerivedType(Ty.getTag())) { + switch(Ty.getTag()) + { + case dwarf::DW_TAG_pointer_type: + TypeNo = TypeNo << PIC16Dbg::S_DERIVED; + TypeNo = TypeNo | PIC16Dbg::DT_PTR; + break; + default: + TypeNo = TypeNo << PIC16Dbg::S_DERIVED; + } + DIType BaseType = DIDerivedType(Ty.getGV()).getTypeDerivedFrom(); + PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TypeName); + } + else if (Ty.isCompositeType(Ty.getTag())) { + switch (Ty.getTag()) { + case dwarf::DW_TAG_array_type: { + DICompositeType CTy = DICompositeType(Ty.getGV()); + DIArray Elements = CTy.getTypeArray(); + unsigned short size = 1; + unsigned short Dimension[4]={0,0,0,0}; + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + if (Element.getTag() == dwarf::DW_TAG_subrange_type) { + TypeNo = TypeNo << PIC16Dbg::S_DERIVED; + TypeNo = TypeNo | PIC16Dbg::DT_ARY; + DISubrange SubRange = DISubrange(Element.getGV()); + Dimension[i] = SubRange.getHi() - SubRange.getLo() + 1; + // Each dimension is represented by 2 bytes starting at byte 9. + Aux[8+i*2+0] = Dimension[i]; + Aux[8+i*2+1] = Dimension[i] >> 8; + size = size * Dimension[i]; + } + } + HasAux = true; + // In auxillary entry for array, 7th and 8th byte represent array size. + Aux[6] = size; + Aux[7] = size >> 8; + DIType BaseType = CTy.getTypeDerivedFrom(); + PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TypeName); + + break; + } + case dwarf:: DW_TAG_union_type: + case dwarf::DW_TAG_structure_type: { + DICompositeType CTy = DICompositeType(Ty.getGV()); + TypeNo = TypeNo << PIC16Dbg::S_BASIC; + if (Ty.getTag() == dwarf::DW_TAG_structure_type) + TypeNo = TypeNo | PIC16Dbg::T_STRUCT; + else + TypeNo = TypeNo | PIC16Dbg::T_UNION; + CTy.getName(TypeName); + unsigned size = CTy.getSizeInBits()/8; + // 7th and 8th byte represent size. + HasAux = true; + Aux[6] = size; + Aux[7] = size >> 8; + break; + } + case dwarf::DW_TAG_enumeration_type: { + TypeNo = TypeNo << PIC16Dbg::S_BASIC; + TypeNo = TypeNo | PIC16Dbg::T_ENUM; + break; + } + default: + TypeNo = TypeNo << PIC16Dbg::S_DERIVED; + } + } + else { + TypeNo = PIC16Dbg::T_NULL; + HasAux = false; + } + return; +} + + +unsigned PIC16DbgInfo::GetTypeDebugNumber(std::string &type) { + if (type == "char") + return PIC16Dbg::T_CHAR; + else if (type == "short") + return PIC16Dbg::T_SHORT; + else if (type == "int") + return PIC16Dbg::T_INT; + else if (type == "long") + return PIC16Dbg::T_LONG; + else if (type == "unsigned char") + return PIC16Dbg::T_UCHAR; + else if (type == "unsigned short") + return PIC16Dbg::T_USHORT; + else if (type == "unsigned int") + return PIC16Dbg::T_UINT; + else if (type == "unsigned long") + return PIC16Dbg::T_ULONG; + else + return 0; +} + +short PIC16DbgInfo::getClass(DIGlobalVariable DIGV) { + short ClassNo; + if (PAN::isLocalName(DIGV.getGlobal()->getName())) { + // Generating C_AUTO here fails due to error in linker. Change it once + // linker is fixed. + ClassNo = PIC16Dbg::C_STAT; + } + else if (DIGV.isLocalToUnit()) + ClassNo = PIC16Dbg::C_STAT; + else + ClassNo = PIC16Dbg::C_EXT; + return ClassNo; +} diff --git a/lib/Target/PIC16/PIC16DebugInfo.h b/lib/Target/PIC16/PIC16DebugInfo.h new file mode 100644 index 00000000000..582d821eb30 --- /dev/null +++ b/lib/Target/PIC16/PIC16DebugInfo.h @@ -0,0 +1,93 @@ +//===-- PIC16DebugInfo.h - Interfaces for PIC16 Debug Information ============// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the helper functions for representing debug information. +// +//===----------------------------------------------------------------------===// + +#ifndef PIC16DBG_H +#define PIC16DBG_H + +#include "llvm/Analysis/DebugInfo.h" + +namespace llvm { + namespace PIC16Dbg { + enum VarType { + T_NULL, + T_VOID, + T_CHAR, + T_SHORT, + T_INT, + T_LONG, + T_FLOAT, + T_DOUBLE, + T_STRUCT, + T_UNION, + T_ENUM, + T_MOE, + T_UCHAR, + T_USHORT, + T_UINT, + T_ULONG + }; + enum DerivedType { + DT_NONE, + DT_PTR, + DT_FCN, + DT_ARY + }; + enum TypeSize { + S_BASIC = 5, + S_DERIVED = 3 + }; + enum DbgClass { + C_NULL, + C_AUTO, + C_EXT, + C_STAT, + C_REG, + C_EXTDEF, + C_LABEL, + C_ULABEL, + C_MOS, + C_ARG, + C_STRTAG, + C_MOU, + C_UNTAG, + C_TPDEF, + C_USTATIC, + C_ENTAG, + C_MOE, + C_REGPARM, + C_FIELD, + C_AUTOARG, + C_LASTENT, + C_BLOCK = 100, + C_FCN, + C_EOS, + C_FILE, + C_LINE, + C_ALIAS, + C_HIDDEN, + C_EOF, + C_LIST, + C_SECTION, + C_EFCN = 255 + }; + } + + class PIC16DbgInfo { + public: + void PopulateDebugInfo(DIType Ty, unsigned short &TypeNo, bool &HasAux, + int Aux[], std::string &TypeName); + unsigned GetTypeDebugNumber(std::string &type); + short getClass(DIGlobalVariable DIGV); + }; +} // end namespace llvm; +#endif