Skip to content

[LoadableByAddress] Fix debug info holes when expanding alloc_stack. #15575

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
Mar 28, 2018
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
6 changes: 0 additions & 6 deletions include/swift/SIL/DebugUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,6 @@ inline bool isDebugInst(SILInstruction *Inst) {
return isa<DebugValueInst>(Inst) || isa<DebugValueAddrInst>(Inst);
}

/// Returns true if the instruction \p Inst is a maintenance instructions which
/// is relevant for debug information and does not get lowered to an instruction.
inline bool isMaintenanceInst(SILInstruction *Inst) {
return isDebugInst(Inst) || isa<AllocStackInst>(Inst);
}

/// Deletes all of the debug instructions that use \p Inst.
inline void deleteAllDebugUses(ValueBase *Inst) {
for (auto UI = Inst->use_begin(), E = Inst->use_end(); UI != E;) {
Expand Down
5 changes: 5 additions & 0 deletions include/swift/SIL/SILBasicBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,11 @@ public llvm::ilist_node<SILBasicBlock>, public SILAllocated<SILBasicBlock> {
/// Used by llvm::LoopInfo.
bool isLegalToHoistInto() const;

/// Returns the debug scope of the first non-meta instructions in the
/// basic block. SILBuilderWithScope uses this to correctly set up
/// the debug scope for newly created instructions.
const SILDebugScope *getScopeOfFirstNonMetaInstruction();

//===--------------------------------------------------------------------===//
// Debugging
//===--------------------------------------------------------------------===//
Expand Down
9 changes: 9 additions & 0 deletions include/swift/SIL/SILBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -2082,6 +2082,15 @@ class SILBuilderWithScope : public SILBuilder {
: SILBuilder(BB) {
inheritScopeFrom(InheritScopeFrom);
}

/// Creates a new SILBuilder with an insertion point at the
/// beginning of BB and the debug scope from the first
/// non-metainstruction in the BB.
explicit SILBuilderWithScope(SILBasicBlock *BB) : SILBuilder(BB->begin()) {
const SILDebugScope *DS = BB->getScopeOfFirstNonMetaInstruction();
assert(DS && "Instruction without debug scope associated!");
setCurrentDebugScope(DS);
}
};

class SavedInsertionPointRAII {
Expand Down
5 changes: 5 additions & 0 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,11 @@ class SILInstruction
/// you perform such optimizations like e.g. jump-threading.
bool isTriviallyDuplicatable() const;

/// Returns true if the instruction is a meta instruction which is
/// relevant for debug information and does not get lowered to a real
/// instruction.
bool isMetaInstruction() const;

/// Verify that all operands of this instruction have compatible ownership
/// with this instruction.
void verifyOperandOwnership() const;
Expand Down
17 changes: 9 additions & 8 deletions lib/IRGen/LoadableByAddress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ void LoadableStorageAllocation::replaceLoadWithCopyAddr(
LoadInst *optimizableLoad) {
SILValue value = optimizableLoad->getOperand();

SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
SILBuilderWithScope allocBuilder(&*pass.F->begin());
AllocStackInst *allocInstr =
allocBuilder.createAllocStack(value.getLoc(), value->getType());

Expand Down Expand Up @@ -1069,7 +1069,7 @@ void LoadableStorageAllocation::replaceLoadWithCopyAddrForModifiable(
}
SILValue value = unoptimizableLoad->getOperand();

SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
SILBuilderWithScope allocBuilder(&*pass.F->begin());
AllocStackInst *allocInstr =
allocBuilder.createAllocStack(value.getLoc(), value->getType());

Expand Down Expand Up @@ -1411,7 +1411,7 @@ void LoadableStorageAllocation::allocateForArg(SILValue value) {

assert(!ApplySite::isa(value) && "Unexpected instruction");

SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
SILBuilderWithScope allocBuilder(&*pass.F->begin());
AllocStackInst *allocInstr =
allocBuilder.createAllocStack(value.getLoc(), value->getType());

Expand All @@ -1438,7 +1438,7 @@ void LoadableStorageAllocation::allocateForArg(SILValue value) {
AllocStackInst *
LoadableStorageAllocation::allocateForApply(SILInstruction *apply,
SILType type) {
SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
SILBuilderWithScope allocBuilder(&*pass.F->begin());
auto *allocInstr = allocBuilder.createAllocStack(apply->getLoc(), type);

pass.largeLoadableArgs.push_back(allocInstr);
Expand Down Expand Up @@ -1524,7 +1524,7 @@ static void setInstrUsers(StructLoweringState &pass, AllocStackInst *allocInstr,
static void allocateAndSetForInstrOperand(StructLoweringState &pass,
SingleValueInstruction *instrOperand){
assert(instrOperand->getType().isObject());
SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
SILBuilderWithScope allocBuilder(&*pass.F->begin());
AllocStackInst *allocInstr = allocBuilder.createAllocStack(
instrOperand->getLoc(), instrOperand->getType());

Expand Down Expand Up @@ -1558,7 +1558,7 @@ static void allocateAndSetForArgumentOperand(StructLoweringState &pass,
auto *arg = dyn_cast<SILArgument>(value);
assert(arg && "non-instr operand must be an argument");

SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
SILBuilderWithScope allocBuilder(&*pass.F->begin());
AllocStackInst *allocInstr =
allocBuilder.createAllocStack(applyInst->getLoc(), value->getType());

Expand Down Expand Up @@ -1677,7 +1677,8 @@ static SILValue createCopyOfEnum(StructLoweringState &pass,
auto value = orig->getOperand();
auto type = value->getType();
if (type.isObject()) {
SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
SILBuilderWithScope allocBuilder(&*pass.F->begin());

// support for non-address operands / enums
auto *allocInstr = allocBuilder.createAllocStack(orig->getLoc(), type);
SILBuilderWithScope storeBuilder(orig);
Expand All @@ -1696,7 +1697,7 @@ static SILValue createCopyOfEnum(StructLoweringState &pass,
}
value = allocInstr;
}
SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
SILBuilderWithScope allocBuilder(&*pass.F->begin());
auto *allocInstr = allocBuilder.createAllocStack(value.getLoc(), type);

SILBuilderWithScope copyBuilder(orig);
Expand Down
8 changes: 8 additions & 0 deletions lib/SIL/SILBasicBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//

#include "llvm/ADT/STLExtras.h"
#include "swift/SIL/DebugUtils.h"
#include "swift/SIL/SILBasicBlock.h"
#include "swift/SIL/SILBuilder.h"
#include "swift/SIL/SILArgument.h"
Expand Down Expand Up @@ -380,3 +381,10 @@ bool SILBasicBlock::isTrampoline() const {
bool SILBasicBlock::isLegalToHoistInto() const {
return true;
}

const SILDebugScope *SILBasicBlock::getScopeOfFirstNonMetaInstruction() {
for (auto &Inst : *this)
if (Inst.isMetaInstruction())
return Inst.getDebugScope();
return begin()->getDebugScope();
}
14 changes: 14 additions & 0 deletions lib/SIL/SILInstruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,20 @@ bool SILInstruction::mayTrap() const {
}
}

bool SILInstruction::isMetaInstruction() const {
// Every instruction that implements getVarInfo() should be in this list.
switch (getKind()) {
case SILInstructionKind::AllocBoxInst:
case SILInstructionKind::AllocStackInst:
case SILInstructionKind::DebugValueInst:
case SILInstructionKind::DebugValueAddrInst:
return true;
default:
return false;
}
llvm_unreachable("Instruction not handled in isMetaInstruction()!");
}

//===----------------------------------------------------------------------===//
// Utilities
//===----------------------------------------------------------------------===//
Expand Down
4 changes: 2 additions & 2 deletions lib/SIL/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4545,14 +4545,14 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {

const SILDebugScope *LastSeenScope = nullptr;
for (SILInstruction &SI : *BB) {
if (isMaintenanceInst(&SI))
if (SI.isMetaInstruction())
continue;
LastSeenScope = SI.getDebugScope();
AlreadySeenScopes.insert(LastSeenScope);
break;
}
for (SILInstruction &SI : *BB) {
if (isMaintenanceInst(&SI))
if (SI.isMetaInstruction())
continue;

// If we haven't seen this debug scope yet, update the
Expand Down
49 changes: 49 additions & 0 deletions test/DebugInfo/LoadableByAddress-allockstack.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Check we don't crash when verifying debug info.
// Ideally this should print the output after loadable by address runs
// but there's no way of doing this in SIL (for IRGen passes).
// RUN: %target-swift-frontend -emit-sil %s -Onone \
// RUN: -sil-verify-all -Xllvm -verify-di-holes -emit-ir \
// RUN: -Xllvm -sil-print-debuginfo -g -o - | %FileCheck %s

struct m {
let major: Int
let minor: Int
let n: Int
let o: [String]
let p: [String]
init(major: Int, minor: Int, n: Int, o: [String], p: [String]) {
self.major = major
self.minor = minor
self.n = n
self.o = o
self.p = p
}
}

enum a {
case any
case b(m)
}

struct c<e> {
enum f {
case g(a)
}
}

struct h<i>{
typealias j = i
typealias d = j
typealias f = c<d>.f
subscript(identifier: d) -> f {
return .g(.any)
}
func k(l: f, identifier: d) -> h {
switch (l, self[identifier]) {
default:
return self
}
}
}

// CHECK: define linkonce_odr hidden %swift.opaque* @"$S4main1mVwCP"