Skip to content

[debug-info] Add DIExpr to SILDebugVariable::operator== for real. #41294

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
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
78 changes: 78 additions & 0 deletions include/swift/SIL/SILDebugVariable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//===--- SILDebugVariable.h -----------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_SIL_SILDEBUGVARIABLE_H
#define SWIFT_SIL_SILDEBUGVARIABLE_H

#include "swift/Basic/LLVM.h"
#include "swift/SIL/SILDebugInfoExpression.h"
#include "swift/SIL/SILLocation.h"
#include "swift/SIL/SILType.h"
#include "llvm/ADT/StringRef.h"

namespace swift {

class AllocationInst;

/// Holds common debug information about local variables and function
/// arguments that are needed by DebugValueInst, AllocStackInst,
/// and AllocBoxInst.
struct SILDebugVariable {
StringRef Name;
unsigned ArgNo : 16;
unsigned Constant : 1;
unsigned Implicit : 1;
Optional<SILType> Type;
Optional<SILLocation> Loc;
const SILDebugScope *Scope;
SILDebugInfoExpression DIExpr;

// Use vanilla copy ctor / operator
SILDebugVariable(const SILDebugVariable &) = default;
SILDebugVariable &operator=(const SILDebugVariable &) = default;

SILDebugVariable()
: ArgNo(0), Constant(false), Implicit(false), Scope(nullptr) {}
SILDebugVariable(bool Constant, uint16_t ArgNo)
: ArgNo(ArgNo), Constant(Constant), Implicit(false), Scope(nullptr) {}
SILDebugVariable(StringRef Name, bool Constant, unsigned ArgNo,
bool IsImplicit = false, Optional<SILType> AuxType = {},
Optional<SILLocation> DeclLoc = {},
const SILDebugScope *DeclScope = nullptr,
llvm::ArrayRef<SILDIExprElement> ExprElements = {})
: Name(Name), ArgNo(ArgNo), Constant(Constant), Implicit(IsImplicit),
Type(AuxType), Loc(DeclLoc), Scope(DeclScope), DIExpr(ExprElements) {}

/// Created from either AllocStack or AllocBox instruction
static Optional<SILDebugVariable>
createFromAllocation(const AllocationInst *AI);

bool operator==(const SILDebugVariable &V) {
return ArgNo == V.ArgNo && Constant == V.Constant && Name == V.Name &&
Implicit == V.Implicit && Type == V.Type && Loc == V.Loc &&
Scope == V.Scope && DIExpr == V.DIExpr;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the main change... DIExpr == DIExpr -> DIExpr == V.DIExpr.

}

SILDebugVariable withoutDIExpr() const {
auto result = *this;
result.DIExpr = {};
return result;
}

bool isLet() const { return Name.size() && Constant; }

bool isVar() const { return Name.size() && !Constant; }
};

} // namespace swift

#endif
45 changes: 1 addition & 44 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "swift/SIL/SILAllocated.h"
#include "swift/SIL/SILArgumentArrayRef.h"
#include "swift/SIL/SILDebugInfoExpression.h"
#include "swift/SIL/SILDebugVariable.h"
#include "swift/SIL/SILDeclRef.h"
#include "swift/SIL/SILFunctionConventions.h"
#include "swift/SIL/SILLocation.h"
Expand Down Expand Up @@ -1775,50 +1776,6 @@ class UnaryInstructionWithTypeDependentOperandsBase
}
};

/// Holds common debug information about local variables and function
/// arguments that are needed by DebugValueInst, AllocStackInst,
/// and AllocBoxInst.
struct SILDebugVariable {
StringRef Name;
unsigned ArgNo : 16;
unsigned Constant : 1;
unsigned Implicit : 1;
Optional<SILType> Type;
Optional<SILLocation> Loc;
const SILDebugScope *Scope;
SILDebugInfoExpression DIExpr;

// Use vanilla copy ctor / operator
SILDebugVariable(const SILDebugVariable &) = default;
SILDebugVariable &operator=(const SILDebugVariable &) = default;

SILDebugVariable()
: ArgNo(0), Constant(false), Implicit(false), Scope(nullptr) {}
SILDebugVariable(bool Constant, uint16_t ArgNo)
: ArgNo(ArgNo), Constant(Constant), Implicit(false), Scope(nullptr) {}
SILDebugVariable(StringRef Name, bool Constant, unsigned ArgNo,
bool IsImplicit = false, Optional<SILType> AuxType = {},
Optional<SILLocation> DeclLoc = {},
const SILDebugScope *DeclScope = nullptr,
llvm::ArrayRef<SILDIExprElement> ExprElements = {})
: Name(Name), ArgNo(ArgNo), Constant(Constant), Implicit(IsImplicit),
Type(AuxType), Loc(DeclLoc), Scope(DeclScope), DIExpr(ExprElements) {}

/// Created from either AllocStack or AllocBox instruction
static Optional<SILDebugVariable>
createFromAllocation(const AllocationInst *AI);

bool operator==(const SILDebugVariable &V) {
return ArgNo == V.ArgNo && Constant == V.Constant && Name == V.Name &&
Implicit == V.Implicit && Type == V.Type && Loc == V.Loc &&
Scope == V.Scope && DIExpr == DIExpr;
}

bool isLet() const { return Name.size() && Constant; }

bool isVar() const { return Name.size() && !Constant; }
};

/// A DebugVariable where storage for the strings has been
/// tail-allocated following the parent SILInstruction.
class TailAllocatedDebugVariable {
Expand Down
26 changes: 16 additions & 10 deletions lib/SILOptimizer/Transforms/SILMem2Reg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,30 +167,36 @@ static void promoteDebugValueAddr(DebugValueInst *dvai, SILValue value,
assert(dvai->getOperand()->getType().isLoadable(*dvai->getFunction()) &&
"Unexpected promotion of address-only type!");
assert(value && "Expected valid value");

// Avoid inserting the same debug_value twice.
//
// We remove the di expression when comparing since:
//
// 1. dvai is on will always have the deref diexpr since it is on addresses.
//
// 2. We are only trying to delete debug_var that are on values... values will
// never have an op_deref meaning that the comparison will always fail and
// not serve out purpose here.
auto dvaiWithoutDIExpr = dvai->getVarInfo()->withoutDIExpr();
for (auto *use : value->getUses()) {
if (auto *dvi = dyn_cast<DebugValueInst>(use->getUser())) {
// Since we're not comparing di-expression in
// SILDebugVariable::operator==(), it's necessary to distinguish
// debug_value w/ normal values from that with address-type values.
if (!dvi->hasAddrVal() &&
*dvi->getVarInfo() == *dvai->getVarInfo()) {
if (!dvi->hasAddrVal() && *dvi->getVarInfo() == dvaiWithoutDIExpr) {
deleter.forceDelete(dvai);
return;
}
}
}

auto VarInfo = *dvai->getVarInfo();
// Drop op_deref if dvai is actually a debug_value instruction
auto varInfo = *dvai->getVarInfo();
if (isa<DebugValueInst>(dvai)) {
auto &DIExpr = VarInfo.DIExpr;
if (DIExpr)
DIExpr.eraseElement(DIExpr.element_begin());
auto &diExpr = varInfo.DIExpr;
if (diExpr)
diExpr.eraseElement(diExpr.element_begin());
}

SILBuilderWithScope b(dvai, ctx);
b.createDebugValue(dvai->getLoc(), value, std::move(VarInfo));
b.createDebugValue(dvai->getLoc(), value, std::move(varInfo));
deleter.forceDelete(dvai);
}

Expand Down