зеркало из https://github.com/microsoft/clang-1.git
Improve debugging information for BlockDeclRefExpr. WIP. Given this
scheme, we can switch the previous scheme over to using this code path. There's a bit of simplifications yet to do as well. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83138 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
432887fadd
Коммит
b1a6e68796
|
@ -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 *.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче