Serialize debug scope and location info in the SIL assembler language.

At the moment it is only possible to test the effects that SIL
optimization passes have on debug information by observing the
effects of a full .swift -> LLVM IR compilation. This change enable us
to write targeted testcases for single SIL optimization passes.

The new syntax is as follows:

 sil-scope-ref ::= 'scope' [0-9]+
 sil-scope ::= 'sil_scope' [0-9]+ '{'
                 sil-loc
                 'parent' scope-parent
                 ('inlined_at' sil-scope-ref )?
               '}'
 scope-parent ::= sil-function-name ':' sil-type
 scope-parent ::= sil-scope-ref
 sil-loc ::= 'loc' string-literal ':' [0-9]+ ':' [0-9]+

Each instruction may have a debug location and a SIL scope reference
at the end.  Debug locations consist of a filename, a line number, and
a column number.  If the debug location is omitted, it defaults to the
location in the SIL source file.  SIL scopes describe the position
inside the lexical scope structure that the Swift expression a SIL
instruction was generated from had originally. SIL scopes also hold
inlining information.

<rdar://problem/22706994>
This commit is contained in:
Adrian Prantl
2016-02-26 10:33:54 -08:00
parent dfaaebc0a0
commit c9927f66f0
59 changed files with 881 additions and 453 deletions

View File

@@ -85,7 +85,7 @@ public:
};
typedef struct {
unsigned Line = 0, Col = 0;
unsigned Line = 0, Column = 0;
const char *Filename = nullptr;
} DebugLoc;
@@ -94,6 +94,7 @@ protected:
UnderlyingLocation() : DebugInfoLoc({}) {}
UnderlyingLocation(ASTNodeTy N) : ASTNode(N) {}
UnderlyingLocation(SourceLoc L) : SILFileLoc(L) {}
UnderlyingLocation(DebugLoc D) : DebugInfoLoc(D) {}
struct ASTNodeLoc {
ASTNodeLoc(ASTNodeTy N) : Primary(N) {}
/// Primary AST location, always used for diagnostics.
@@ -200,6 +201,12 @@ protected:
setStorageKind(SILFileKind);
assert(isSILFile());
}
SILLocation(DebugLoc L, LocationKind K, unsigned Flags = 0)
: Loc(L), KindData(K | Flags) {
setStorageKind(DebugInfoKind);
assert(isDebugInfoLoc());
}
/// @}
private:
@@ -261,6 +268,9 @@ public:
/// Return whether this location came from a SIL file.
bool isSILFile() const { return getStorageKind() == SILFileKind; }
/// Return whether this location came from a textual SIL file.
bool isDebugInfoLoc() const { return getStorageKind() == DebugInfoKind; }
/// Marks the location as coming from auto-generated body.
void markAutoGenerated() { KindData |= (1 << AutoGeneratedBit); }
@@ -309,6 +319,12 @@ public:
return isASTNode() && !Loc.ASTNode.ForDebugger.isNull();
}
/// Populate this empty SILLocation with a DebugLoc.
void setDebugInfoLoc(DebugLoc L) {
Loc.DebugInfoLoc = L;
setStorageKind(DebugInfoKind);
}
/// Check if the corresponding source code location definitely points
/// to the start of the AST node.
bool alwaysPointsToStart() const { return KindData & (1 << PointsToStartBit);}
@@ -386,7 +402,7 @@ public:
/// Fingerprint a DebugLoc for use in a DenseMap.
typedef std::pair<std::pair<unsigned, unsigned>, const void *> DebugLocKey;
struct DebugLocHash : public DebugLocKey {
DebugLocHash(DebugLoc L) : DebugLocKey({{L.Line, L.Col}, L.Filename}) {}
DebugLocHash(DebugLoc L) : DebugLocKey({{L.Line, L.Column}, L.Filename}) {}
};
/// Extract the line, column, and filename.
@@ -394,7 +410,8 @@ public:
/// Return the decoded debug location.
DebugLoc decodeDebugLoc(const SourceManager &SM) const {
return decode(getDebugSourceLoc(), SM);
return isDebugInfoLoc() ? Loc.DebugInfoLoc
: decode(getDebugSourceLoc(), SM);
}
/// Pretty-print the value.
@@ -430,6 +447,7 @@ public:
RegularLocation(Decl *D) : SILLocation(D, RegularKind) {}
RegularLocation(Pattern *P) : SILLocation(P, RegularKind) {}
RegularLocation(SourceLoc L) : SILLocation(L, RegularKind) {}
RegularLocation(DebugLoc L) : SILLocation(L, RegularKind) {}
/// Returns a location representing the module.
static RegularLocation getModuleLocation() {