Generate subprogram debug info with -g.

Also take care of freeing memory at the right places.

llvm-svn: 51553
This commit is contained in:
Sanjiv Gupta 2008-05-25 05:15:42 +00:00
parent d042a969c9
commit 98070578bf
5 changed files with 443 additions and 87 deletions

View File

@ -133,6 +133,10 @@ public:
void addVolatile() { ThePtr |= Volatile; } void addVolatile() { ThePtr |= Volatile; }
void addRestrict() { ThePtr |= Restrict; } void addRestrict() { ThePtr |= Restrict; }
void removeConst() { ThePtr &= ~Const; }
void removeVolatile() { ThePtr &= ~Volatile; }
void removeRestrict() { ThePtr &= ~Restrict; }
QualType getQualifiedType(unsigned TQs) const { QualType getQualifiedType(unsigned TQs) const {
return QualType(getTypePtr(), TQs); return QualType(getTypePtr(), TQs);
} }

View File

@ -13,20 +13,20 @@
#include "CGDebugInfo.h" #include "CGDebugInfo.h"
#include "CodeGenModule.h" #include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
#include "llvm/Constants.h" #include "llvm/Constants.h"
#include "llvm/DerivedTypes.h" #include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h" #include "llvm/Instructions.h"
#include "llvm/Intrinsics.h" #include "llvm/Intrinsics.h"
#include "llvm/Module.h" #include "llvm/Module.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h"
#include "clang/Basic/SourceManager.h" #include "llvm/Support/Dwarf.h"
#include "clang/Basic/FileManager.h" #include "llvm/Support/IRBuilder.h"
#include "clang/AST/ASTContext.h" #include "llvm/Target/TargetMachine.h"
using namespace clang; using namespace clang;
using namespace clang::CodeGen; using namespace clang::CodeGen;
@ -35,13 +35,16 @@ CGDebugInfo::CGDebugInfo(CodeGenModule *m)
, CurLoc() , CurLoc()
, PrevLoc() , PrevLoc()
, CompileUnitCache() , CompileUnitCache()
, TypeCache()
, StopPointFn(NULL) , StopPointFn(NULL)
, CompileUnitAnchor(NULL) , FuncStartFn(NULL)
, SubProgramAnchor(NULL) , DeclareFn(NULL)
, RegionStartFn(NULL) , RegionStartFn(NULL)
, RegionEndFn(NULL) , RegionEndFn(NULL)
, FuncStartFn(NULL) , CompileUnitAnchor(NULL)
, CurFuncDesc(NULL) , SubprogramAnchor(NULL)
, RegionStack()
, Subprogram(NULL)
{ {
SR = new llvm::DISerializer(); SR = new llvm::DISerializer();
SR->setModule (&M->getModule()); SR->setModule (&M->getModule());
@ -50,19 +53,28 @@ CGDebugInfo::CGDebugInfo(CodeGenModule *m)
CGDebugInfo::~CGDebugInfo() CGDebugInfo::~CGDebugInfo()
{ {
delete SR; delete SR;
// Clean up allocated debug info; we can't do this until after the
// serializer is destroyed because it caches pointers to // Free CompileUnitCache.
// the debug info for (std::map<unsigned, llvm::CompileUnitDesc *>::iterator I
= CompileUnitCache.begin(); I != CompileUnitCache.end(); ++I) {
delete I->second;
}
CompileUnitCache.clear();
// Free TypeCache.
for (std::map<void *, llvm::TypeDesc *>::iterator I
= TypeCache.begin(); I != TypeCache.end(); ++I) {
delete I->second;
}
TypeCache.clear();
for (std::vector<llvm::DebugInfoDesc *>::iterator I
= RegionStack.begin(); I != RegionStack.end(); ++I) {
delete *I;
}
delete CompileUnitAnchor; delete CompileUnitAnchor;
delete SubProgramAnchor; delete SubprogramAnchor;
// Clean up compile unit descriptions
std::map<unsigned, llvm::CompileUnitDesc *>::iterator MI;
for (MI = CompileUnitCache.begin(); MI != CompileUnitCache.end(); ++MI)
delete MI->second;
// Clean up misc allocations
std::vector<llvm::DebugInfoDesc*>::iterator VI;
for (VI = DebugAllocationList.begin(); VI != DebugAllocationList.end(); ++VI)
delete *VI;
} }
@ -73,6 +85,12 @@ llvm::Value *CGDebugInfo::getCastValueFor(llvm::DebugInfoDesc *DD) {
SR->getEmptyStructPtrType()); SR->getEmptyStructPtrType());
} }
/// getValueFor - Return a llvm representation for a given debug information
/// descriptor.
llvm::Value *CGDebugInfo::getValueFor(llvm::DebugInfoDesc *DD) {
return SR->Serialize(DD);
}
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a new /// getOrCreateCompileUnit - Get the compile unit from the cache or create a new
/// one if necessary. /// one if necessary.
llvm::CompileUnitDesc llvm::CompileUnitDesc
@ -123,10 +141,313 @@ llvm::CompileUnitDesc
} }
void llvm::TypeDesc *
CGDebugInfo::EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder) { CGDebugInfo::getOrCreateCVRType(QualType type, llvm::CompileUnitDesc *Unit)
if (CurLoc.isInvalid() || CurLoc.isMacroID()) return; {
// We will create a Derived type.
llvm::DerivedTypeDesc *DTy = NULL;
llvm::TypeDesc *FromTy = NULL;
if (type.isConstQualified()) {
DTy = new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_const_type);
type.removeConst();
FromTy = getOrCreateType(type, Unit);
} else if (type.isVolatileQualified()) {
DTy = new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_volatile_type);
type.removeVolatile();
FromTy = getOrCreateType(type, Unit);
} else if (type.isRestrictQualified()) {
DTy = new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_restrict_type);
type.removeRestrict();
FromTy = getOrCreateType(type, Unit);
}
// No need to fill in the Name, Line, Size, Alignment, Offset in case of // CVR derived types.
DTy->setContext(Unit);
DTy->setFromType(FromTy);
return DTy;
}
/// getOrCreateType - Get the Basic type from the cache or create a new
/// one if necessary.
llvm::TypeDesc *
CGDebugInfo::getOrCreateBuiltinType(QualType type, llvm::CompileUnitDesc *Unit)
{
assert (type->getTypeClass() == Type::Builtin);
const BuiltinType *BT = type->getAsBuiltinType();
unsigned Encoding = 0;
switch (BT->getKind())
{
case BuiltinType::Void:
return NULL;
case BuiltinType::UChar:
case BuiltinType::Char_U:
Encoding = llvm::dwarf::DW_ATE_unsigned_char;
break;
case BuiltinType::Char_S:
case BuiltinType::SChar:
Encoding = llvm::dwarf::DW_ATE_signed_char;
break;
case BuiltinType::UShort:
case BuiltinType::UInt:
case BuiltinType::ULong:
case BuiltinType::ULongLong:
Encoding = llvm::dwarf::DW_ATE_unsigned;
break;
case BuiltinType::Short:
case BuiltinType::Int:
case BuiltinType::Long:
case BuiltinType::LongLong:
Encoding = llvm::dwarf::DW_ATE_signed;
break;
case BuiltinType::Bool:
Encoding = llvm::dwarf::DW_ATE_boolean;
break;
case BuiltinType::Float:
case BuiltinType::Double:
Encoding = llvm::dwarf::DW_ATE_float;
break;
default:
Encoding = llvm::dwarf::DW_ATE_signed;
break;
}
// Ty will have contain the resulting type.
llvm::BasicTypeDesc *BTy = new llvm::BasicTypeDesc();
// Get the name and location early to assist debugging.
const char *TyName = BT->getName();
// Bit size, align and offset of the type.
uint64_t Size = M->getContext().getTypeSize(type);
uint64_t Align = M->getContext().getTypeAlign(type);
uint64_t Offset = 0;
// If the type is defined, fill in the details.
if (BTy) {
BTy->setContext(Unit);
BTy->setName(TyName);
BTy->setSize(Size);
BTy->setAlign(Align);
BTy->setOffset(Offset);
BTy->setEncoding(Encoding);
}
return BTy;
}
llvm::TypeDesc *
CGDebugInfo::getOrCreatePointerType(QualType type, llvm::CompileUnitDesc *Unit)
{
// type*
llvm::DerivedTypeDesc *DTy =
new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_pointer_type);
// Handle the derived type.
const PointerType *PTRT = type->getAsPointerType();
llvm::TypeDesc *FromTy = getOrCreateType(PTRT->getPointeeType(), Unit);
// Get the name and location early to assist debugging.
SourceManager &SM = M->getContext().getSourceManager();
uint64_t Line = SM.getLogicalLineNumber(CurLoc);
// Bit size, align and offset of the type.
uint64_t Size = M->getContext().getTypeSize(type);
uint64_t Align = M->getContext().getTypeAlign(type);
uint64_t Offset = 0;
// If the type is defined, fill in the details.
if (DTy) {
DTy->setContext(Unit);
DTy->setLine(Line);
DTy->setSize(Size);
DTy->setAlign(Align);
DTy->setOffset(Offset);
DTy->setFromType(FromTy);
}
return DTy;
}
llvm::TypeDesc *
CGDebugInfo::getOrCreateTypedefType(QualType type, llvm::CompileUnitDesc *Unit)
{
// typedefs are derived from some other type.
llvm::DerivedTypeDesc *DTy =
new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_typedef);
// Handle derived type.
const TypedefType *TDT = type->getAsTypedefType();
llvm::TypeDesc *FromTy = getOrCreateType(TDT->LookThroughTypedefs(),
Unit);
// Get the name and location early to assist debugging.
const char *TyName = TDT->getDecl()->getName();
SourceManager &SM = M->getContext().getSourceManager();
uint64_t Line = SM.getLogicalLineNumber(TDT->getDecl()->getLocation());
// If the type is defined, fill in the details.
if (DTy) {
DTy->setContext(Unit);
DTy->setFile(getOrCreateCompileUnit(TDT->getDecl()->getLocation()));
DTy->setLine(Line);
DTy->setName(TyName);
DTy->setFromType(FromTy);
}
return DTy;
}
llvm::TypeDesc *
CGDebugInfo::getOrCreateFunctionType(QualType type, llvm::CompileUnitDesc *Unit)
{
llvm::CompositeTypeDesc *SubrTy =
new llvm::CompositeTypeDesc(llvm::dwarf::DW_TAG_subroutine_type);
// Prepare to add the arguments for the subroutine.
std::vector<llvm::DebugInfoDesc *> &Elements = SubrTy->getElements();
// Get result type.
const FunctionType *FT = type->getAsFunctionType();
llvm::TypeDesc *ArgTy = getOrCreateType(FT->getResultType(), Unit);
if (ArgTy) Elements.push_back(ArgTy);
// Set up remainder of arguments.
if (type->getTypeClass() == Type::FunctionProto) {
const FunctionTypeProto *FTPro = dyn_cast<FunctionTypeProto>(type);
for (unsigned int i =0; i < FTPro->getNumArgs(); i++) {
QualType ParamType = FTPro->getArgType(i);
ArgTy = getOrCreateType(ParamType, Unit);
if (ArgTy) Elements.push_back(ArgTy);
}
}
// FIXME: set other fields file, line here.
SubrTy->setContext(Unit);
return SubrTy;
}
/// getOrCreateType - Get the type from the cache or create a new
/// one if necessary.
llvm::TypeDesc *
CGDebugInfo::getOrCreateType(QualType type, llvm::CompileUnitDesc *Unit)
{
if (type.isNull())
return NULL;
// Check to see if the compile unit already has created this type.
llvm::TypeDesc *&Slot = TypeCache[type.getAsOpaquePtr()];
if (Slot) return Slot;
// We need to check for the CVR qualifiers as the first thing.
if (type.getCVRQualifiers()) {
Slot = getOrCreateCVRType (type, Unit);
return Slot;
}
// Work out details of type.
switch(type->getTypeClass()) {
case Type::Complex:
case Type::Reference:
case Type::ConstantArray:
case Type::VariableArray:
case Type::IncompleteArray:
case Type::Vector:
case Type::ExtVector:
case Type::Tagged:
case Type::ASQual:
case Type::ObjCInterface:
case Type::ObjCQualifiedInterface:
case Type::ObjCQualifiedId:
case Type::TypeOfExp:
case Type::TypeOfTyp:
default:
{
assert (0 && "Unsupported type");
return NULL;
}
case Type::TypeName:
Slot = getOrCreateTypedefType(type, Unit);
break;
case Type::FunctionProto:
case Type::FunctionNoProto:
Slot = getOrCreateFunctionType(type, Unit);
break;
case Type::Builtin:
Slot = getOrCreateBuiltinType(type, Unit);
break;
case Type::Pointer:
Slot = getOrCreatePointerType(type, Unit);
break;
}
return Slot;
}
/// EmitFunctionStart - Constructs the debug code for entering a function -
/// "llvm.dbg.func.start.".
void CGDebugInfo::EmitFunctionStart(const FunctionDecl *FnDecl,
llvm::Function *Fn,
llvm::IRBuilder &Builder)
{
// Create subprogram descriptor.
Subprogram = new llvm::SubprogramDesc();
// Make sure we have an anchor.
if (!SubprogramAnchor) {
SubprogramAnchor = new llvm::AnchorDesc(Subprogram);
}
// Get name information.
Subprogram->setName(FnDecl->getName());
Subprogram->setFullName(FnDecl->getName());
// Gather location information.
llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc);
SourceManager &SM = M->getContext().getSourceManager();
uint64_t Loc = SM.getLogicalLineNumber(CurLoc);
// Get Function Type.
QualType type = FnDecl->getResultType();
llvm::TypeDesc *SPTy = getOrCreateType(type, Unit);
Subprogram->setAnchor(SubprogramAnchor);
Subprogram->setContext(Unit);
Subprogram->setFile(Unit);
Subprogram->setLine(Loc);
Subprogram->setType(SPTy);
Subprogram->setIsStatic(Fn->hasInternalLinkage());
Subprogram->setIsDefinition(true);
// Lazily construct llvm.dbg.func.start.
if (!FuncStartFn)
FuncStartFn = llvm::Intrinsic::getDeclaration(&M->getModule(),
llvm::Intrinsic::dbg_func_start);
// Call llvm.dbg.func.start which also implicitly calls llvm.dbg.stoppoint.
Builder.CreateCall(FuncStartFn, getCastValueFor(Subprogram), "");
// Push function on region stack.
RegionStack.push_back(Subprogram);
}
void
CGDebugInfo::EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder)
{
if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;
// Don't bother if things are the same as last time. // Don't bother if things are the same as last time.
SourceManager &SM = M->getContext().getSourceManager(); SourceManager &SM = M->getContext().getSourceManager();
if (CurLoc == PrevLoc if (CurLoc == PrevLoc
@ -157,35 +478,25 @@ CGDebugInfo::EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder) {
/// EmitRegionStart- Constructs the debug code for entering a declarative /// EmitRegionStart- Constructs the debug code for entering a declarative
/// region - "llvm.dbg.region.start.". /// region - "llvm.dbg.region.start.".
void CGDebugInfo::EmitFunctionStart(llvm::Function *Fn, llvm::IRBuilder &Builder) void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, llvm::IRBuilder &Builder)
{ {
// Get the appropriate compile unit. llvm::BlockDesc *Block = new llvm::BlockDesc();
llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc); if (RegionStack.size() > 0)
Block->setContext(RegionStack.back());
RegionStack.push_back(Block);
llvm::SubprogramDesc* Block = new llvm::SubprogramDesc; // Lazily construct llvm.dbg.region.start function.
DebugAllocationList.push_back(Block); if (!RegionStartFn)
Block->setFile(Unit); RegionStartFn = llvm::Intrinsic::getDeclaration(&M->getModule(),
Block->setContext(Unit); llvm::Intrinsic::dbg_region_start);
if (!SubProgramAnchor) {
SubProgramAnchor = new llvm::AnchorDesc(Block); // Call llvm.dbg.func.start.
SR->Serialize(SubProgramAnchor); Builder.CreateCall(RegionStartFn, getCastValueFor(Block), "");
}
Block->setAnchor(SubProgramAnchor);
Block->setName(Fn->getName());
Block->setFullName(Fn->getName());
Block->setIsDefinition(true);
SourceManager &SM = M->getContext().getSourceManager();
Block->setLine(SM.getLogicalLineNumber(CurLoc));
CurFuncDesc = getCastValueFor(Block);
if (!FuncStartFn)
FuncStartFn = llvm::Intrinsic::getDeclaration(&M->getModule(),
llvm::Intrinsic::dbg_func_start);
Builder.CreateCall(FuncStartFn, CurFuncDesc);
} }
/// EmitRegionEnd - Constructs the debug code for exiting a declarative /// EmitRegionEnd - Constructs the debug code for exiting a declarative
/// region - "llvm.dbg.region.end." /// region - "llvm.dbg.region.end."
void CGDebugInfo::EmitFunctionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder) void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder)
{ {
// Lazily construct llvm.dbg.region.end function. // Lazily construct llvm.dbg.region.end function.
if (!RegionEndFn) if (!RegionEndFn)
@ -196,6 +507,8 @@ void CGDebugInfo::EmitFunctionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder)
EmitStopPoint(Fn, Builder); EmitStopPoint(Fn, Builder);
// Call llvm.dbg.func.end. // Call llvm.dbg.func.end.
Builder.CreateCall(RegionEndFn, CurFuncDesc, ""); llvm::DebugInfoDesc *DID = RegionStack.back();
Builder.CreateCall(RegionEndFn, getCastValueFor(DID), "");
RegionStack.pop_back();
} }

View File

@ -14,6 +14,7 @@
#ifndef CLANG_CODEGEN_CGDEBUGINFO_H #ifndef CLANG_CODEGEN_CGDEBUGINFO_H
#define CLANG_CODEGEN_CGDEBUGINFO_H #define CLANG_CODEGEN_CGDEBUGINFO_H
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceLocation.h"
#include <map> #include <map>
#include <vector> #include <vector>
@ -28,14 +29,18 @@ namespace llvm {
class AnchorDesc; class AnchorDesc;
class DebugInfoDesc; class DebugInfoDesc;
class Value; class Value;
class TypeDesc;
class SubprogramDesc;
} }
namespace clang { namespace clang {
class FunctionDecl;
namespace CodeGen { namespace CodeGen {
class CodeGenModule; class CodeGenModule;
/// DebugInfo - This class gathers all debug information during compilation and /// CGDebugInfo - This class gathers all debug information during compilation
/// is responsible for emitting to llvm globals or pass directly to the backend. /// and is responsible for emitting to llvm globals or pass directly to
/// the backend.
class CGDebugInfo { class CGDebugInfo {
private: private:
CodeGenModule *M; CodeGenModule *M;
@ -45,41 +50,70 @@ private:
/// CompileUnitCache - Cache of previously constructed CompileUnits. /// CompileUnitCache - Cache of previously constructed CompileUnits.
std::map<unsigned, llvm::CompileUnitDesc *> CompileUnitCache; std::map<unsigned, llvm::CompileUnitDesc *> CompileUnitCache;
std::vector<llvm::DebugInfoDesc*> DebugAllocationList;
/// TypeCache - Cache of previously constructed Types.
std::map<void *, llvm::TypeDesc *> TypeCache;
llvm::Function *StopPointFn; llvm::Function *StopPointFn;
llvm::AnchorDesc *CompileUnitAnchor; llvm::Function *FuncStartFn;
llvm::AnchorDesc *SubProgramAnchor; llvm::Function *DeclareFn;
llvm::Function *RegionStartFn; llvm::Function *RegionStartFn;
llvm::Function *RegionEndFn; llvm::Function *RegionEndFn;
llvm::Function *FuncStartFn; llvm::AnchorDesc *CompileUnitAnchor;
llvm::Value *CurFuncDesc; llvm::AnchorDesc *SubprogramAnchor;
std::vector<llvm::DebugInfoDesc *> RegionStack;
llvm::SubprogramDesc *Subprogram;
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a /// Helper functions for getOrCreateType.
/// new one if necessary. llvm::TypeDesc *getOrCreateCVRType(QualType type,
llvm::CompileUnitDesc *getOrCreateCompileUnit(SourceLocation loc); llvm::CompileUnitDesc *unit);
llvm::TypeDesc *getOrCreateBuiltinType(QualType type,
/// getCastValueFor - Return a llvm representation for a given debug llvm::CompileUnitDesc *unit);
/// information descriptor cast to an empty struct pointer. llvm::TypeDesc *getOrCreateTypedefType(QualType type,
llvm::Value *getCastValueFor(llvm::DebugInfoDesc *DD); llvm::CompileUnitDesc *unit);
llvm::TypeDesc *getOrCreatePointerType(QualType type,
llvm::CompileUnitDesc *unit);
llvm::TypeDesc *getOrCreateFunctionType(QualType type,
llvm::CompileUnitDesc *unit);
public: public:
CGDebugInfo(CodeGenModule *m); CGDebugInfo(CodeGenModule *m);
~CGDebugInfo(); ~CGDebugInfo();
void setLocation(SourceLocation loc) { CurLoc = loc; }; void setLocation(SourceLocation loc) { CurLoc = loc; }
/// EmitStopPoint - Emit a call to llvm.dbg.stoppoint to indicate a change of /// EmitStopPoint - Emit a call to llvm.dbg.stoppoint to indicate a change of
/// source line. /// source line.
void EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder); void EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder);
/// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate
/// start of a new function
void EmitFunctionStart(const FunctionDecl *FnDecl, llvm::Function *Fn,
llvm::IRBuilder &Builder);
/// EmitFunctionStart - Emit a call to llvm.dbg.func.start to indicate start /// EmitRegionStart - Emit a call to llvm.dbg.region.start to indicate start
/// of a new block. /// of a new block.
void EmitFunctionStart(llvm::Function *Fn, llvm::IRBuilder &Builder); void EmitRegionStart(llvm::Function *Fn, llvm::IRBuilder &Builder);
/// EmitFunctionEnd - Emit call to llvm.dbg.region.end to indicate end of a /// EmitRegionEnd - Emit call to llvm.dbg.region.end to indicate end of a
/// block. /// block.
void EmitFunctionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder); void EmitRegionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder);
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a
/// new one if necessary.
llvm::CompileUnitDesc *getOrCreateCompileUnit(SourceLocation loc);
/// getOrCreateType - Get the type from the cache or create a new type if
/// necessary.
llvm::TypeDesc *getOrCreateType(QualType type, llvm::CompileUnitDesc *unit);
/// getCastValueFor - Return a llvm representation for a given debug
/// information descriptor cast to an empty struct pointer.
llvm::Value *getCastValueFor(llvm::DebugInfoDesc *DD);
/// getValueFor - Return a llvm representation for a given debug information
/// descriptor.
llvm::Value *getValueFor(llvm::DebugInfoDesc *DD);
}; };
} // namespace CodeGen } // namespace CodeGen
} // namespace clang } // namespace clang

View File

@ -88,10 +88,25 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
// FIXME: handle vla's etc. // FIXME: handle vla's etc.
if (S.body_empty() || !isa<Expr>(S.body_back())) GetLast = false; if (S.body_empty() || !isa<Expr>(S.body_back())) GetLast = false;
CGDebugInfo *DI = CGM.getDebugInfo();
if (DI) {
if (S.getLBracLoc().isValid()) {
DI->setLocation(S.getLBracLoc());
}
DI->EmitRegionStart(CurFn, Builder);
}
for (CompoundStmt::const_body_iterator I = S.body_begin(), for (CompoundStmt::const_body_iterator I = S.body_begin(),
E = S.body_end()-GetLast; I != E; ++I) E = S.body_end()-GetLast; I != E; ++I)
EmitStmt(*I); EmitStmt(*I);
if (DI) {
if (S.getRBracLoc().isValid()) {
DI->setLocation(S.getRBracLoc());
}
DI->EmitRegionEnd(CurFn, Builder);
}
if (!GetLast) if (!GetLast)
return RValue::get(0); return RValue::get(0);
@ -368,15 +383,6 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
EmitAggExpr(RV, SRetPtr, false); EmitAggExpr(RV, SRetPtr, false);
} }
CGDebugInfo *DI = CGM.getDebugInfo();
if (DI) {
CompoundStmt* body = cast<CompoundStmt>(CurFuncDecl->getBody());
if (body->getRBracLoc().isValid()) {
DI->setLocation(body->getRBracLoc());
}
DI->EmitFunctionEnd(CurFn, Builder);
}
if (RetValue) { if (RetValue) {
Builder.CreateRet(RetValue); Builder.CreateRet(RetValue);
} else { } else {

View File

@ -205,7 +205,7 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
if (body->getLBracLoc().isValid()) { if (body->getLBracLoc().isValid()) {
DI->setLocation(body->getLBracLoc()); DI->setLocation(body->getLBracLoc());
} }
DI->EmitFunctionStart(CurFn, Builder); DI->EmitFunctionStart(FD, CurFn, Builder);
} }
// Emit allocs for param decls. Give the LLVM Argument nodes names. // Emit allocs for param decls. Give the LLVM Argument nodes names.
@ -225,21 +225,20 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
// Emit the function body. // Emit the function body.
EmitStmt(FD->getBody()); EmitStmt(FD->getBody());
if (DI) {
CompoundStmt* body = cast<CompoundStmt>(CurFuncDecl->getBody());
if (body->getRBracLoc().isValid()) {
DI->setLocation(body->getRBracLoc());
}
DI->EmitRegionEnd(CurFn, Builder);
}
// Emit a return for code that falls off the end. If insert point // Emit a return for code that falls off the end. If insert point
// is a dummy block with no predecessors then remove the block itself. // is a dummy block with no predecessors then remove the block itself.
llvm::BasicBlock *BB = Builder.GetInsertBlock(); llvm::BasicBlock *BB = Builder.GetInsertBlock();
if (isDummyBlock(BB)) if (isDummyBlock(BB))
BB->eraseFromParent(); BB->eraseFromParent();
else { else {
CGDebugInfo *DI = CGM.getDebugInfo();
if (DI) {
CompoundStmt* body = cast<CompoundStmt>(CurFuncDecl->getBody());
if (body->getRBracLoc().isValid()) {
DI->setLocation(body->getRBracLoc());
}
DI->EmitFunctionEnd(CurFn, Builder);
}
// FIXME: if this is C++ main, this should return 0. // FIXME: if this is C++ main, this should return 0.
if (CurFn->getReturnType() == llvm::Type::VoidTy) if (CurFn->getReturnType() == llvm::Type::VoidTy)
Builder.CreateRetVoid(); Builder.CreateRetVoid();