Skip to content

Commit 165b736

Browse files
authored
Improve Portable PDB debugging in FSharp.Private.Compiler.dll (#6383)
* Fix portable pdb writing * enable portable pdbs for fsharp.private.compiler.dll * feedback * Release build
1 parent 8dfc02f commit 165b736

File tree

4 files changed

+75
-42
lines changed

4 files changed

+75
-42
lines changed

src/absil/ilwritepdb.fs

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -369,36 +369,63 @@ let generatePortablePdb (embedAllSource: bool) (embedSourceList: string list) (s
369369
builder.WriteCompressedInteger( 0 )
370370
builder.WriteCompressedInteger( MetadataTokens.GetRowNumber(DocumentHandle.op_Implicit(getDocumentHandle (sps.[i].Document))) )
371371
else
372+
//=============================================================================================================================================
372373
// Sequence-point-record
373-
let offsetDelta =
374-
if i > 0 then sps.[i].Offset - sps.[i - 1].Offset // delta from previous offset
375-
else sps.[i].Offset // delta IL offset
376-
377-
if i < 1 || offsetDelta <> 0 then // ILOffset must not be 0
374+
// Validate these with magic numbers according to the portable pdb spec Sequence point dexcription:
375+
// https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PortablePdb-Metadata.md#methoddebuginformation-table-0x31
376+
//
377+
// So the spec is actually bit iffy!!!!! (More like guidelines really. )
378+
// It uses code similar to this to validate the values
379+
// if (result < 0 || result >= ushort.MaxValue) // be errorfull
380+
// Spec Says 0x10000 and value max = 0xFFFF but it can't even be = to maxvalue, and so the range is 0 .. 0xfffe inclusive
381+
//=============================================================================================================================================
382+
383+
let capValue v maxValue =
384+
if v < 0 then 0
385+
elif v > maxValue then maxValue
386+
else v
387+
388+
let capOffset v = capValue v 0xfffe
389+
let capLine v = capValue v 0x1ffffffe
390+
let capColumn v = capValue v 0xfffe
391+
392+
let offset = capOffset sps.[i].Offset
393+
let startLine = capLine sps.[i].Line
394+
let endLine = capLine sps.[i].EndLine
395+
let startColumn = capColumn sps.[i].Column
396+
let endColumn = capColumn sps.[i].EndColumn
397+
398+
let offsetDelta = // delta from previous offset
399+
if i > 0 then offset - capOffset sps.[i - 1].Offset
400+
else offset
401+
402+
if i < 1 || offsetDelta > 0 then
378403
builder.WriteCompressedInteger(offsetDelta)
379404

380-
if sps.[i].Line = 0xfeefee && sps.[i].EndLine = 0xfeefee then // Hidden-sequence-point-record
405+
// Hidden-sequence-point-record
406+
if startLine = 0xfeefee || endLine = 0xfeefee || (startColumn = 0 && endColumn = 0)
407+
then
381408
builder.WriteCompressedInteger(0)
382409
builder.WriteCompressedInteger(0)
383410
else // Non-hidden-sequence-point-record
384-
let deltaLines = sps.[i].EndLine - sps.[i].Line // lines
411+
let deltaLines = endLine - startLine // lines
385412
builder.WriteCompressedInteger(deltaLines)
386413

387-
let deltaColumns = sps.[i].EndColumn - sps.[i].Column // Columns
414+
let deltaColumns = endColumn - startColumn // Columns
388415
if deltaLines = 0 then
389416
builder.WriteCompressedInteger(deltaColumns)
390417
else
391418
builder.WriteCompressedSignedInteger(deltaColumns)
392419

393420
if previousNonHiddenStartLine < 0 then // delta Start Line & Column:
394-
builder.WriteCompressedInteger(sps.[i].Line)
395-
builder.WriteCompressedInteger(sps.[i].Column)
421+
builder.WriteCompressedInteger(startLine)
422+
builder.WriteCompressedInteger(startColumn)
396423
else
397-
builder.WriteCompressedSignedInteger(sps.[i].Line - previousNonHiddenStartLine)
398-
builder.WriteCompressedSignedInteger(sps.[i].Column - previousNonHiddenStartColumn)
424+
builder.WriteCompressedSignedInteger(startLine - previousNonHiddenStartLine)
425+
builder.WriteCompressedSignedInteger(startColumn - previousNonHiddenStartColumn)
399426

400-
previousNonHiddenStartLine <- sps.[i].Line
401-
previousNonHiddenStartColumn <- sps.[i].Column
427+
previousNonHiddenStartLine <- startLine
428+
previousNonHiddenStartColumn <- startColumn
402429

403430
getDocumentHandle singleDocumentIndex, metadata.GetOrAddBlob(builder)
404431

src/fsharp/FSharp.Compiler.Private/FSharp.Compiler.Private.fsproj

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,6 @@
1414
<OtherFlags>$(OtherFlags) --warnon:1182 --maxerrors:20 --extraoptimizationloops:1</OtherFlags>
1515
<UseAssetTargetFallback>true</UseAssetTargetFallback>
1616
<Tailcalls>true</Tailcalls> <!-- .tail annotations always emitted for this binary, even in debug mode -->
17-
<SkipPDBConversion>true</SkipPDBConversion>
18-
<NGenBinary>true</NGenBinary>
19-
</PropertyGroup>
20-
21-
<PropertyGroup Condition="'$(TargetFramework)' == 'net46' AND '$(OS)' == 'Windows_NT'">
22-
<!-- portable PDBs can't be properly generated for this assembly, see https://github.com/Microsoft/visualfsharp/issues/5976 -->
23-
<DebugType>full</DebugType>
24-
<EnableSourceLink>false</EnableSourceLink>
2517
</PropertyGroup>
2618

2719
<PropertyGroup Condition="$(TargetFramework.StartsWith('netstandard')) AND '$(OS)' == 'Windows_NT'">

src/fsharp/ast.fs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,10 @@ and
805805
/// Get the syntactic range of source code covered by this construct.
806806
member e.Range =
807807
match e with
808-
| SynExpr.Paren (range=m)
808+
| SynExpr.Paren (_, leftParenRange, rightParenRange, r) ->
809+
match rightParenRange with
810+
| Some rightParenRange when leftParenRange.FileIndex <> rightParenRange.FileIndex -> leftParenRange
811+
| _ -> r
809812
| SynExpr.Quote (range=m)
810813
| SynExpr.Const (range=m)
811814
| SynExpr.Typed (range=m)

src/utils/prim-parsing.fs

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -361,38 +361,49 @@ module internal Implementation =
361361
#if DEBUG
362362
if Flags.debug then Console.Write("reduce popping {0} values/states, lookahead {1}", n, report haveLookahead lookaheadToken)
363363
#endif
364-
for i = 0 to n - 1 do
364+
// For every range to reduce merge it
365+
for i = 0 to n - 1 do
365366
if valueStack.IsEmpty then failwith "empty symbol stack"
366-
let topVal = valueStack.Peep()
367+
let topVal = valueStack.Peep() // Grab topVal
367368
valueStack.Pop()
368369
stateStack.Pop()
369-
ruleValues.[(n-i)-1] <- topVal.value
370-
ruleStartPoss.[(n-i)-1] <- topVal.startPos
371-
ruleEndPoss.[(n-i)-1] <- topVal.endPos
372-
if i = 0 then lhsPos.[1] <- topVal.endPos
373-
if i = n - 1 then lhsPos.[0] <- topVal.startPos
374-
375-
// Use the lookahead token to populate the locations if the rhs is empty
376-
if n = 0 then
370+
371+
let ruleIndex = (n-i)-1
372+
ruleValues.[ruleIndex] <- topVal.value
373+
ruleStartPoss.[ruleIndex] <- topVal.startPos
374+
ruleEndPoss.[ruleIndex] <- topVal.endPos
375+
376+
if i = 0 then
377+
// Initial range
378+
lhsPos.[0] <- topVal.startPos
379+
lhsPos.[1] <- topVal.endPos
380+
elif topVal.startPos.FileIndex = lhsPos.[1].FileIndex && topVal.startPos.Line <= lhsPos.[1].Line then
381+
// Reduce range if same file as the initial end point
382+
lhsPos.[0] <- topVal.startPos
383+
384+
// Use the lookahead token to populate the locations if the rhs is empty
385+
if n = 0 then
377386
if haveLookahead then
378-
lhsPos.[0] <- lookaheadStartPos
379-
lhsPos.[1] <- lookaheadEndPos
387+
lhsPos.[0] <- lookaheadStartPos
388+
lhsPos.[1] <- lookaheadEndPos
380389
else
381390
lhsPos.[0] <- lexbuf.StartPos
382391
lhsPos.[1] <- lexbuf.EndPos
383-
try
384-
// printf "reduce %d\n" prod
385-
let redResult = reduction parseState
386-
valueStack.Push(ValueInfo(redResult, lhsPos.[0], lhsPos.[1]))
392+
try
393+
// printf "reduce %d\n" prod
394+
let redResult = reduction parseState
395+
let valueInfo = ValueInfo(redResult, lhsPos.[0], lhsPos.[1])
396+
valueStack.Push(valueInfo)
387397
let currState = stateStack.Peep()
388398
let newGotoState = gotoTable.Read(int tables.productionToNonTerminalTable.[prod], currState)
389399
stateStack.Push(newGotoState)
400+
390401
#if DEBUG
391402
if Flags.debug then Console.WriteLine(" goto state {0}", newGotoState)
392403
#endif
393-
with
394-
| Accept res ->
395-
finished <- true
404+
with
405+
| Accept res ->
406+
finished <- true
396407
valueStack.Push(ValueInfo(res, lhsPos.[0], lhsPos.[1]))
397408
| RecoverableParseError ->
398409
#if DEBUG

0 commit comments

Comments
 (0)