Skip to content

Debug Info: Encode let-bindings using DW_TAG_const_type. #27345

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5056,6 +5056,10 @@ bool VarDecl::isSettable(const DeclContext *UseDC,
if (!isLet())
return supportsMutation();

// Debugger expression 'let's are initialized through a side-channel.
if (isDebuggerVar())
return false;

// We have a 'let'; we must be checking settability from a specific
// DeclContext to go on further.
if (UseDC == nullptr)
Expand Down
43 changes: 25 additions & 18 deletions lib/IRGen/IRGenDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
void emitVariableDeclaration(IRBuilder &Builder,
ArrayRef<llvm::Value *> Storage,
DebugTypeInfo Ty, const SILDebugScope *DS,
ValueDecl *VarDecl, StringRef Name,
unsigned ArgNo = 0,
ValueDecl *VarDecl, SILDebugVariable VarInfo,
IndirectionKind = DirectValue,
ArtificialKind = RealValue);
void emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,
Expand Down Expand Up @@ -2145,7 +2144,7 @@ void IRGenDebugInfoImpl::emitArtificialFunction(IRBuilder &Builder,

void IRGenDebugInfoImpl::emitVariableDeclaration(
IRBuilder &Builder, ArrayRef<llvm::Value *> Storage, DebugTypeInfo DbgTy,
const SILDebugScope *DS, ValueDecl *VarDecl, StringRef Name, unsigned ArgNo,
const SILDebugScope *DS, ValueDecl *VarDecl, SILDebugVariable VarInfo,
IndirectionKind Indirection, ArtificialKind Artificial) {
assert(DS && "variable has no scope");

Expand All @@ -2165,19 +2164,21 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(

// FIXME: this should be the scope of the type's declaration.
// If this is an argument, attach it to the current function scope.
if (ArgNo > 0) {
if (VarInfo.ArgNo > 0) {
while (isa<llvm::DILexicalBlock>(Scope))
Scope = cast<llvm::DILexicalBlock>(Scope)->getScope();
}
assert(Scope && isa<llvm::DIScope>(Scope) && "variable has no scope");
llvm::DIFile *Unit = getFile(Scope);
llvm::DIType *DITy = getOrCreateType(DbgTy);
assert(DITy && "could not determine debug type of variable");
if (VarInfo.Constant)
DITy = DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_const_type, DITy);

unsigned Line = Loc.Line;

// Self is always an artificial argument, so are variables without location.
if (!Line || (ArgNo > 0 && Name == IGM.Context.Id_self.str()))
if (!Line || (VarInfo.ArgNo > 0 && VarInfo.Name == IGM.Context.Id_self.str()))
Artificial = ArtificialValue;

llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
Expand All @@ -2188,10 +2189,11 @@ void IRGenDebugInfoImpl::emitVariableDeclaration(
bool Optimized = false;
// Create the descriptor for the variable.
llvm::DILocalVariable *Var =
(ArgNo > 0) ? DBuilder.createParameterVariable(
Scope, Name, ArgNo, Unit, Line, DITy, Optimized, Flags)
: DBuilder.createAutoVariable(Scope, Name, Unit, Line, DITy,
Optimized, Flags);
(VarInfo.ArgNo > 0)
? DBuilder.createParameterVariable(Scope, VarInfo.Name, VarInfo.ArgNo,
Unit, Line, DITy, Optimized, Flags)
: DBuilder.createAutoVariable(Scope, VarInfo.Name, Unit, Line, DITy,
Optimized, Flags);

// Running variables for the current/previous piece.
bool IsPiece = Storage.size() > 1;
Expand Down Expand Up @@ -2275,16 +2277,22 @@ void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
if (Opts.DebugInfoLevel <= IRGenDebugInfoLevel::LineTables)
return;

llvm::DIType *Ty = getOrCreateType(DbgTy);
if (Ty->isArtificial() || Ty == InternalType || !Loc)
llvm::DIType *DITy = getOrCreateType(DbgTy);
VarDecl *VD = nullptr;
if (Loc)
VD = dyn_cast_or_null<VarDecl>(Loc->getAsASTNode<Decl>());
if (!VD || VD->isLet())
DITy = DBuilder.createQualifiedType(llvm::dwarf::DW_TAG_const_type, DITy);

if (DITy->isArtificial() || DITy == InternalType || !Loc)
// FIXME: Really these should be marked as artificial, but LLVM
// currently has no support for flags to be put on global
// variables. In the mean time, elide these variables, they
// would confuse both the user and LLDB.
return;

if (InFixedBuffer)
Ty = createFixedValueBufferStruct(Ty);
DITy = createFixedValueBufferStruct(DITy);

auto L = getStartLocation(Loc);
auto File = getOrCreateFile(L.Filename);
Expand All @@ -2294,7 +2302,7 @@ void IRGenDebugInfoImpl::emitGlobalVariableDeclaration(
if (!Var)
Expr = DBuilder.createConstantValueExpression(0);
auto *GV = DBuilder.createGlobalVariableExpression(
MainModule, Name, LinkageName, File, L.Line, Ty, IsLocalToUnit, Expr);
MainModule, Name, LinkageName, File, L.Line, DITy, IsLocalToUnit, Expr);
if (Var)
Var->addDebugInfo(GV);
}
Expand All @@ -2320,7 +2328,7 @@ void IRGenDebugInfoImpl::emitTypeMetadata(IRGenFunction &IGF,
Metadata->getType(), Size(CI.getTargetInfo().getPointerWidth(0)),
Alignment(CI.getTargetInfo().getPointerAlign(0)));
emitVariableDeclaration(IGF.Builder, Metadata, DbgTy, IGF.getDebugScope(),
nullptr, OS.str().str(), 0,
nullptr, {OS.str().str(), 0, false},
// swift.type is already a pointer type,
// having a shadow copy doesn't add another
// layer of indirection.
Expand Down Expand Up @@ -2419,11 +2427,10 @@ void IRGenDebugInfo::emitArtificialFunction(IRBuilder &Builder,

void IRGenDebugInfo::emitVariableDeclaration(
IRBuilder &Builder, ArrayRef<llvm::Value *> Storage, DebugTypeInfo Ty,
const SILDebugScope *DS, ValueDecl *VarDecl, StringRef Name,
unsigned ArgNo, IndirectionKind Indirection,
ArtificialKind Artificial) {
const SILDebugScope *DS, ValueDecl *VarDecl, SILDebugVariable VarInfo,
IndirectionKind Indirection, ArtificialKind Artificial) {
static_cast<IRGenDebugInfoImpl *>(this)->emitVariableDeclaration(
Builder, Storage, Ty, DS, VarDecl, Name, ArgNo, Indirection, Artificial);
Builder, Storage, Ty, DS, VarDecl, VarInfo, Indirection, Artificial);
}

void IRGenDebugInfo::emitDbgIntrinsic(IRBuilder &Builder, llvm::Value *Storage,
Expand Down
4 changes: 2 additions & 2 deletions lib/IRGen/IRGenDebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef SWIFT_IRGEN_DEBUGINFO_H
#define SWIFT_IRGEN_DEBUGINFO_H

#include <swift/SIL/SILInstruction.h>
#include "DebugTypeInfo.h"
#include "IRGenFunction.h"

Expand Down Expand Up @@ -133,8 +134,7 @@ class IRGenDebugInfo {
void emitVariableDeclaration(IRBuilder &Builder,
ArrayRef<llvm::Value *> Storage,
DebugTypeInfo Ty, const SILDebugScope *DS,
ValueDecl *VarDecl, StringRef Name,
unsigned ArgNo = 0,
ValueDecl *VarDecl, SILDebugVariable VarInfo,
IndirectionKind Indirection = DirectValue,
ArtificialKind Artificial = RealValue);

Expand Down
88 changes: 42 additions & 46 deletions lib/IRGen/IRGenSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,13 +761,14 @@ class IRGenSILFunction :

/// Unconditionally emit a stack shadow copy of an \c llvm::Value.
llvm::Value *emitShadowCopy(llvm::Value *Storage, const SILDebugScope *Scope,
StringRef Name, unsigned ArgNo, Alignment Align) {
SILDebugVariable VarInfo, Alignment Align) {
if (Align.isZero())
Align = IGM.getPointerAlignment();

auto &Alloca = ShadowStackSlots[{ArgNo, {Scope, Name}}];
unsigned ArgNo = VarInfo.ArgNo;
auto &Alloca = ShadowStackSlots[{ArgNo, {Scope, VarInfo.Name}}];
if (!Alloca.isValid())
Alloca = createAlloca(Storage->getType(), Align, Name+".debug");
Alloca = createAlloca(Storage->getType(), Align, VarInfo.Name + ".debug");
zeroInit(cast<llvm::AllocaInst>(Alloca.getAddress()));

ArtificialLocation AutoRestore(Scope, IGM.DebugInfo.get(), Builder);
Expand All @@ -781,7 +782,7 @@ class IRGenSILFunction :
/// shadow copies, we lose the precise lifetime.
llvm::Value *emitShadowCopyIfNeeded(llvm::Value *Storage,
const SILDebugScope *Scope,
StringRef Name, unsigned ArgNo,
SILDebugVariable VarInfo,
bool IsAnonymous,
Alignment Align = Alignment(0)) {
// Never emit shadow copies when optimizing, or if already on the stack.
Expand All @@ -792,7 +793,7 @@ class IRGenSILFunction :
return Storage;

// Always emit shadow copies for function arguments.
if (ArgNo == 0)
if (VarInfo.ArgNo == 0)
// Otherwise only if debug value range extension is not feasible.
if (!needsShadowCopy(Storage)) {
// Mark for debug value range extension unless this is a constant, or
Expand All @@ -809,22 +810,22 @@ class IRGenSILFunction :

return Storage;
}
return emitShadowCopy(Storage, Scope, Name, ArgNo, Align);
return emitShadowCopy(Storage, Scope, VarInfo, Align);
}

/// Like \c emitShadowCopyIfNeeded() but takes an \c Address instead of an
/// \c llvm::Value.
llvm::Value *emitShadowCopyIfNeeded(Address Storage,
const SILDebugScope *Scope,
StringRef Name, unsigned ArgNo,
SILDebugVariable VarInfo,
bool IsAnonymous) {
return emitShadowCopyIfNeeded(Storage.getAddress(), Scope, Name, ArgNo,
return emitShadowCopyIfNeeded(Storage.getAddress(), Scope, VarInfo,
IsAnonymous, Storage.getAlignment());
}

/// Like \c emitShadowCopyIfNeeded() but takes an exploded value.
void emitShadowCopyIfNeeded(SILValue &SILVal, const SILDebugScope *Scope,
StringRef Name, unsigned ArgNo, bool IsAnonymous,
SILDebugVariable VarInfo, bool IsAnonymous,
llvm::SmallVectorImpl<llvm::Value *> &copy) {
Explosion e = getLoweredExplosion(SILVal);

Expand All @@ -840,13 +841,13 @@ class IRGenSILFunction :
auto vals = e.claimAll();
for (auto val : vals)
copy.push_back(
emitShadowCopyIfNeeded(val, Scope, Name, ArgNo, IsAnonymous));
emitShadowCopyIfNeeded(val, Scope, VarInfo, IsAnonymous));
return;
}

SILType Type = SILVal->getType();
auto &LTI = cast<LoadableTypeInfo>(IGM.getTypeInfo(Type));
auto Alloca = LTI.allocateStack(*this, Type, Name+".debug");
auto Alloca = LTI.allocateStack(*this, Type, VarInfo.Name + ".debug");
zeroInit(cast<llvm::AllocaInst>(Alloca.getAddress().getAddress()));
ArtificialLocation AutoRestore(Scope, IGM.DebugInfo.get(), Builder);
LTI.initialize(*this, e, Alloca.getAddress(), false /* isOutlined */);
Expand All @@ -867,22 +868,18 @@ class IRGenSILFunction :

/// Emit debug info for a function argument or a local variable.
template <typename StorageType>
void emitDebugVariableDeclaration(StorageType Storage,
DebugTypeInfo Ty,
SILType SILTy,
const SILDebugScope *DS,
VarDecl *VarDecl,
StringRef Name,
unsigned ArgNo = 0,
void emitDebugVariableDeclaration(StorageType Storage, DebugTypeInfo Ty,
SILType SILTy, const SILDebugScope *DS,
VarDecl *VarDecl, SILDebugVariable VarInfo,
IndirectionKind Indirection = DirectValue) {
assert(IGM.DebugInfo && "debug info not enabled");
if (ArgNo) {
if (VarInfo.ArgNo) {
PrologueLocation AutoRestore(IGM.DebugInfo.get(), Builder);
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, Ty, DS, VarDecl,
Name, ArgNo, Indirection);
VarInfo, Indirection);
} else
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, Ty, DS, VarDecl,
Name, 0, Indirection);
VarInfo, Indirection);
}

void emitFailBB() {
Expand Down Expand Up @@ -3649,17 +3646,16 @@ void IRGenSILFunction::emitErrorResultVar(SILResultInfo ErrorInfo,
auto ErrorResultSlot = getErrorResultSlot(IGM.silConv.getSILType(ErrorInfo));
auto Var = DbgValue->getVarInfo();
assert(Var && "error result without debug info");
auto Storage =
emitShadowCopyIfNeeded(ErrorResultSlot.getAddress(), getDebugScope(),
Var->Name, Var->ArgNo, false);
auto Storage = emitShadowCopyIfNeeded(ErrorResultSlot.getAddress(),
getDebugScope(), *Var, false);
if (!IGM.DebugInfo)
return;
auto DbgTy = DebugTypeInfo::getErrorResult(
ErrorInfo.getType(), ErrorResultSlot->getType(), IGM.getPointerSize(),
IGM.getPointerAlignment());
IGM.DebugInfo->emitVariableDeclaration(
Builder, Storage, DbgTy, getDebugScope(), nullptr, Var->Name, Var->ArgNo,
IndirectValue, ArtificialValue);
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, DbgTy,
getDebugScope(), nullptr, *Var,
IndirectValue, ArtificialValue);
}

void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
Expand All @@ -3680,30 +3676,30 @@ void IRGenSILFunction::visitDebugValueInst(DebugValueInst *i) {
}

bool IsAnonymous = false;
StringRef Name = getVarName(i, IsAnonymous);
VarInfo->Name = getVarName(i, IsAnonymous);
DebugTypeInfo DbgTy;
SILType SILTy = SILVal->getType();
auto RealTy = SILVal->getType().getASTType();
if (VarDecl *Decl = i->getDecl()) {
DbgTy = DebugTypeInfo::getLocalVariable(
Decl, RealTy, getTypeInfo(SILVal->getType()));
} else if (i->getFunction()->isBare() &&
!SILTy.hasArchetype() && !Name.empty()) {
!SILTy.hasArchetype() && !VarInfo->Name.empty()) {
// Preliminary support for .sil debug information.
DbgTy = DebugTypeInfo::getFromTypeInfo(RealTy, getTypeInfo(SILTy));
} else
return;

// Put the value into a stack slot at -Onone.
llvm::SmallVector<llvm::Value *, 8> Copy;
emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), Name, VarInfo->ArgNo,
IsAnonymous, Copy);
emitShadowCopyIfNeeded(SILVal, i->getDebugScope(), *VarInfo, IsAnonymous,
Copy);
bindArchetypes(DbgTy.getType());
if (!IGM.DebugInfo)
return;

emitDebugVariableDeclaration(Copy, DbgTy, SILTy, i->getDebugScope(),
i->getDecl(), Name, VarInfo->ArgNo);
i->getDecl(), *VarInfo);
}

void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) {
Expand All @@ -3722,7 +3718,7 @@ void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) {
assert(VarInfo && "debug_value_addr without debug info");
bool IsAnonymous = false;
bool IsLoadablyByAddress = isa<AllocStackInst>(SILVal);
StringRef Name = getVarName(i, IsAnonymous);
VarInfo->Name = getVarName(i, IsAnonymous);
auto Addr = getLoweredAddress(SILVal).getAddress();
SILType SILTy = SILVal->getType();
auto RealType = SILTy.getASTType();
Expand All @@ -3736,9 +3732,8 @@ void IRGenSILFunction::visitDebugValueAddrInst(DebugValueAddrInst *i) {
// Put the value's address into a stack slot at -Onone and emit a debug
// intrinsic.
emitDebugVariableDeclaration(
emitShadowCopyIfNeeded(Addr, i->getDebugScope(), Name, VarInfo->ArgNo,
IsAnonymous),
DbgTy, SILType(), i->getDebugScope(), Decl, Name, VarInfo->ArgNo,
emitShadowCopyIfNeeded(Addr, i->getDebugScope(), *VarInfo, IsAnonymous),
DbgTy, SILType(), i->getDebugScope(), Decl, *VarInfo,
(IsLoadablyByAddress) ? DirectValue : IndirectValue);
}

Expand Down Expand Up @@ -4001,7 +3996,7 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
return;

bool IsAnonymous = false;
StringRef Name = getVarName(i, IsAnonymous);
VarInfo->Name = getVarName(i, IsAnonymous);

// At this point addr must be an alloca or an undef.
assert(isa<llvm::AllocaInst>(addr) || isa<llvm::UndefValue>(addr) ||
Expand All @@ -4012,8 +4007,7 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,
if (auto *Alloca = dyn_cast<llvm::AllocaInst>(addr))
if (!Alloca->isStaticAlloca()) {
// Store the address of the dynamic alloca on the stack.
addr = emitShadowCopy(addr, DS, Name, VarInfo->ArgNo,
IGM.getPointerAlignment());
addr = emitShadowCopy(addr, DS, *VarInfo, IGM.getPointerAlignment());
Indirection = IndirectValue;
}

Expand All @@ -4032,8 +4026,8 @@ void IRGenSILFunction::emitDebugInfoForAllocStack(AllocStackInst *i,

bindArchetypes(DbgTy.getType());
if (IGM.DebugInfo)
emitDebugVariableDeclaration(addr, DbgTy, SILTy, DS, Decl, Name,
VarInfo->ArgNo, Indirection);
emitDebugVariableDeclaration(addr, DbgTy, SILTy, DS, Decl, *VarInfo,
Indirection);
}

void IRGenSILFunction::visitAllocStackInst(swift::AllocStackInst *i) {
Expand Down Expand Up @@ -4233,16 +4227,18 @@ void IRGenSILFunction::visitAllocBoxInst(swift::AllocBoxInst *i) {
auto RealType = SILTy.getASTType();
auto DbgTy = DebugTypeInfo::getLocalVariable(Decl, RealType, type);

auto VarInfo = i->getVarInfo();
assert(VarInfo && "debug_value without debug info");

auto Storage = emitShadowCopyIfNeeded(
boxWithAddr.getAddress(), i->getDebugScope(), Name, 0, IsAnonymous);
boxWithAddr.getAddress(), i->getDebugScope(), *VarInfo, IsAnonymous);

if (!IGM.DebugInfo)
return;

IGM.DebugInfo->emitVariableDeclaration(
Builder,
Storage,
DbgTy, i->getDebugScope(), Decl, Name, 0, IndirectValue);
IGM.DebugInfo->emitVariableDeclaration(Builder, Storage, DbgTy,
i->getDebugScope(), Decl, *VarInfo,
IndirectValue);
}

void IRGenSILFunction::visitProjectBoxInst(swift::ProjectBoxInst *i) {
Expand Down
Loading