summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGBlocks.cpp32
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp202
-rw-r--r--lib/CodeGen/CGDebugInfo.h12
3 files changed, 246 insertions, 0 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index daeeee56f9..e9648251d2 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "CGDebugInfo.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/AST/DeclObjC.h"
@@ -661,9 +662,40 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
StartFunction(BD, ResultType, Fn, Args,
BExpr->getBody()->getLocEnd());
+
+ // Save a spot to insert the debug information for all the BlockDeclRefDecls.
+ llvm::BasicBlock *entry = Builder.GetInsertBlock();
+ llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint();
+
CurFuncDecl = OuterFuncDecl;
CurCodeDecl = BD;
EmitStmt(BExpr->getBody());
+
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ llvm::BasicBlock *end = Builder.GetInsertBlock();
+ llvm::BasicBlock::iterator end_ptr = Builder.GetInsertPoint();
+
+ // Emit debug information for all the BlockDeclRefDecls.
+ // First, go back to the entry...
+ Builder.SetInsertPoint(entry, entry_ptr);
+
+ // And then insert the debug information..
+ for (unsigned i=0; i < BlockDeclRefDecls.size(); ++i) {
+ const Expr *E = BlockDeclRefDecls[i];
+ const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
+ if (BDRE) {
+ const ValueDecl *D = BDRE->getDecl();
+ DI->setLocation(D->getLocation());
+ DI->EmitDeclareOfBlockDeclRefVariable(BDRE,
+ LocalDeclMap[getBlockStructDecl()],
+ Builder, this);
+ }
+ }
+
+ // Then go back to the end, and we're done.
+ Builder.SetInsertPoint(end, end_ptr);
+ }
+
FinishFunction(cast<CompoundStmt>(BExpr->getBody())->getRBracLoc());
// The runtime needs a minimum alignment of a void *.
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 8dc2ac8d1f..645125667c 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "CGDebugInfo.h"
+#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
@@ -1076,12 +1077,213 @@ void CGDebugInfo::EmitDeclare(const VarDecl *Decl, unsigned Tag,
DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock());
}
+/// EmitDeclare - Emit local variable declaration debug info.
+void CGDebugInfo::EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag,
+ llvm::Value *Storage, CGBuilderTy &Builder,
+ CodeGenFunction *CGF) {
+ const ValueDecl *Decl = BDRE->getDecl();
+ assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
+
+ // Do not emit variable debug information while generating optimized code.
+ // The llvm optimizer and code generator are not yet ready to support
+ // optimized code debugging.
+ const CompileOptions &CO = M->getCompileOpts();
+ if (CO.OptimizationLevel)
+ return;
+
+ uint64_t XOffset = 0;
+ llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation());
+ QualType Type = Decl->getType();
+ llvm::DIType Ty = getOrCreateType(Type, Unit);
+ if (Decl->hasAttr<BlocksAttr>()) {
+ llvm::DICompileUnit DefUnit;
+ unsigned Tag = llvm::dwarf::DW_TAG_structure_type;
+
+ llvm::SmallVector<llvm::DIDescriptor, 5> EltTys;
+
+ llvm::DIType FieldTy;
+
+ QualType FType;
+ uint64_t FieldSize, FieldOffset;
+ unsigned FieldAlign;
+
+ llvm::DIArray Elements;
+ llvm::DIType EltTy;
+
+ // Build up structure for the byref. See BuildByRefType.
+ FieldOffset = 0;
+ FType = M->getContext().getPointerType(M->getContext().VoidTy);
+ FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
+ FieldSize = M->getContext().getTypeSize(FType);
+ FieldAlign = M->getContext().getTypeAlign(FType);
+ FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
+ "__isa", DefUnit,
+ 0, FieldSize, FieldAlign,
+ FieldOffset, 0, FieldTy);
+ EltTys.push_back(FieldTy);
+ FieldOffset += FieldSize;
+
+ FType = M->getContext().getPointerType(M->getContext().VoidTy);
+ FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
+ FieldSize = M->getContext().getTypeSize(FType);
+ FieldAlign = M->getContext().getTypeAlign(FType);
+ FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
+ "__forwarding", DefUnit,
+ 0, FieldSize, FieldAlign,
+ FieldOffset, 0, FieldTy);
+ EltTys.push_back(FieldTy);
+ FieldOffset += FieldSize;
+
+ FType = M->getContext().getFixedWidthIntType(32, true); // Int32Ty;
+ FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
+ FieldSize = M->getContext().getTypeSize(FType);
+ FieldAlign = M->getContext().getTypeAlign(FType);
+ FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
+ "__flags", DefUnit,
+ 0, FieldSize, FieldAlign,
+ FieldOffset, 0, FieldTy);
+ EltTys.push_back(FieldTy);
+ FieldOffset += FieldSize;
+
+ FType = M->getContext().getFixedWidthIntType(32, true); // Int32Ty;
+ FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
+ FieldSize = M->getContext().getTypeSize(FType);
+ FieldAlign = M->getContext().getTypeAlign(FType);
+ FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
+ "__size", DefUnit,
+ 0, FieldSize, FieldAlign,
+ FieldOffset, 0, FieldTy);
+ EltTys.push_back(FieldTy);
+ FieldOffset += FieldSize;
+
+ bool HasCopyAndDispose = M->BlockRequiresCopying(Type);
+ if (HasCopyAndDispose) {
+ FType = M->getContext().getPointerType(M->getContext().VoidTy);
+ FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
+ FieldSize = M->getContext().getTypeSize(FType);
+ FieldAlign = M->getContext().getTypeAlign(FType);
+ FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
+ "__copy_helper", DefUnit,
+ 0, FieldSize, FieldAlign,
+ FieldOffset, 0, FieldTy);
+ EltTys.push_back(FieldTy);
+ FieldOffset += FieldSize;
+
+ FType = M->getContext().getPointerType(M->getContext().VoidTy);
+ FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
+ FieldSize = M->getContext().getTypeSize(FType);
+ FieldAlign = M->getContext().getTypeAlign(FType);
+ FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
+ "__destroy_helper", DefUnit,
+ 0, FieldSize, FieldAlign,
+ FieldOffset, 0, FieldTy);
+ EltTys.push_back(FieldTy);
+ FieldOffset += FieldSize;
+ }
+
+ unsigned Align = M->getContext().getDeclAlignInBytes(Decl);
+ if (Align > M->getContext().Target.getPointerAlign(0) / 8) {
+ unsigned AlignedOffsetInBytes
+ = llvm::RoundUpToAlignment(FieldOffset/8, Align);
+ unsigned NumPaddingBytes
+ = AlignedOffsetInBytes - FieldOffset/8;
+
+ if (NumPaddingBytes > 0) {
+ llvm::APInt pad(32, NumPaddingBytes);
+ FType = M->getContext().getConstantArrayType(M->getContext().CharTy,
+ pad, ArrayType::Normal, 0);
+ FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
+ FieldSize = M->getContext().getTypeSize(FType);
+ FieldAlign = M->getContext().getTypeAlign(FType);
+ FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member,
+ Unit, "", DefUnit,
+ 0, FieldSize, FieldAlign,
+ FieldOffset, 0, FieldTy);
+ EltTys.push_back(FieldTy);
+ FieldOffset += FieldSize;
+ }
+ }
+
+ FType = Type;
+ FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
+ FieldSize = M->getContext().getTypeSize(FType);
+ FieldAlign = Align*8;
+ std::string Name = Decl->getNameAsString();
+
+ XOffset = FieldOffset;
+ FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
+ Name, DefUnit,
+ 0, FieldSize, FieldAlign,
+ FieldOffset, 0, FieldTy);
+ EltTys.push_back(FieldTy);
+ FieldOffset += FieldSize;
+
+ Elements = DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size());
+
+ unsigned Flags = llvm::DIType::FlagBlockByrefStruct;
+
+ Ty = DebugFactory.CreateCompositeType(Tag, Unit, "",
+ llvm::DICompileUnit(),
+ 0, FieldOffset, 0, 0, Flags,
+ llvm::DIType(), Elements);
+ }
+
+ // Get location information.
+ SourceManager &SM = M->getContext().getSourceManager();
+ PresumedLoc PLoc = SM.getPresumedLoc(Decl->getLocation());
+ unsigned Line = 0;
+ if (!PLoc.isInvalid())
+ Line = PLoc.getLine();
+ else
+ Unit = llvm::DICompileUnit();
+
+ uint64_t offset = CGF->BlockDecls[Decl];
+ llvm::SmallVector<llvm::Value *, 9> addr;
+ llvm::LLVMContext &VMContext = M->getLLVMContext();
+ addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ llvm::DIFactory::OpDeref));
+ addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ llvm::DIFactory::OpPlus));
+ addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ offset));
+ if (BDRE->isByRef()) {
+ addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ llvm::DIFactory::OpDeref));
+ addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ llvm::DIFactory::OpPlus));
+ offset = CGF->LLVMPointerWidth/8; // offset of __forwarding field
+ addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ offset));
+ addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ llvm::DIFactory::OpDeref));
+ addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ llvm::DIFactory::OpPlus));
+ offset = XOffset/8; // offset of x field
+ addr.push_back(llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
+ offset));
+ }
+
+ // Create the descriptor for the variable.
+ llvm::DIVariable D =
+ DebugFactory.CreateComplexVariable(Tag, RegionStack.back(),
+ Decl->getNameAsString(), Unit, Line, Ty,
+ addr);
+ // Insert an llvm.dbg.declare into the current block.
+ DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock());
+}
+
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *Decl,
llvm::Value *Storage,
CGBuilderTy &Builder) {
EmitDeclare(Decl, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder);
}
+void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(
+ const BlockDeclRefExpr *BDRE, llvm::Value *Storage, CGBuilderTy &Builder,
+ CodeGenFunction *CGF) {
+ EmitDeclare(BDRE, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder, CGF);
+}
+
/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
/// variable declaration.
void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index dc256003f6..17237ddfc6 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -15,6 +15,7 @@
#define CLANG_CODEGEN_CGDEBUGINFO_H
#include "clang/AST/Type.h"
+#include "clang/AST/Expr.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Analysis/DebugInfo.h"
@@ -33,6 +34,7 @@ namespace clang {
namespace CodeGen {
class CodeGenModule;
+ class CodeGenFunction;
/// CGDebugInfo - This class gathers all debug information during compilation
/// and is responsible for emitting to llvm globals or pass directly to
@@ -102,6 +104,13 @@ public:
void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI,
CGBuilderTy &Builder);
+ /// EmitDeclareOfBlockDeclRefVariable - Emit call to llvm.dbg.declare for an
+ /// imported variable declaration in a block.
+ void EmitDeclareOfBlockDeclRefVariable(const BlockDeclRefExpr *BDRE,
+ llvm::Value *AI,
+ CGBuilderTy &Builder,
+ CodeGenFunction *CGF);
+
/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
/// variable declaration.
void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
@@ -118,6 +127,9 @@ private:
void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,
CGBuilderTy &Builder);
+ /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration.
+ void EmitDeclare(const BlockDeclRefExpr *BDRE, unsigned Tag, llvm::Value *AI,
+ CGBuilderTy &Builder, CodeGenFunction *CGF);
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a
/// new one if necessary.