diff --git a/src/analyzer.fs b/src/analyzer.fs index e9b9c88d..910cd9b1 100644 --- a/src/analyzer.fs +++ b/src/analyzer.fs @@ -74,10 +74,10 @@ module private VariableInlining = if not ident.DoNotInline && not ident.ToBeInlined && not ident.VarDecl.Value.isEverWrittenAfterDecl then match localReferences.TryGetValue(def.Key), allReferences.TryGetValue(def.Key) with | (_, 1), (_, 1) when isConst -> - debug $"inlining local variable '{Printer.debugIdent ident}' because it's safe to inline (const) and used only once" + debug $"{ident.Loc}: inlining local variable '{Printer.debugIdent ident}' because it's safe to inline (const) and used only once" ident.ToBeInlined <- true | (_, 0), (_, 0) -> - debug $"inlining (removing) local variable '{Printer.debugIdent ident}' because it's safe to inline and unused" + debug $"{ident.Loc}: inlining (removing) local variable '{Printer.debugIdent ident}' because it's safe to inline and unused" ident.ToBeInlined <- true | _ -> () @@ -120,14 +120,14 @@ module private VariableInlining = // Top-level values are special, in particular in HLSL. Keep them for now. if not isTopLevel then // Never-written locals without init should be unused: inline (remove) them. - debug $"inlining (removing) unassigned local '{Printer.debugDecl def}'" + debug $"{def.name.Loc}: inlining (removing) unassigned local '{Printer.debugDecl def}'" def.name.ToBeInlined <- true | Some init -> if canBeInlined init then // Never-written locals and globals are inlined when their value is "simple enough". // This can increase non-compressed size but decreases compressed size. let varKind = if isTopLevel then "global" else "local" - debug $"inlining {varKind} variable '{Printer.debugDecl def}' because it's never written and has a 'simple' definition" + debug $"{def.name.Loc}: inlining {varKind} variable '{Printer.debugDecl def}' because it's never written and has a 'simple' definition" def.name.ToBeInlined <- true | _ -> () @@ -331,7 +331,7 @@ module private FunctionInlining = if not funcInfo.funcType.fName.DoNotInline && verifyArgsUses funcInfo.func callSites then // Mark both the call site (so that simplifyExpr can remove it) and the function (to remember to remove it). // We cannot simply rely on unused functions removal, because it might be disabled through its own flag. - debug $"inlining function '{funcInfo.funcType}' into {callSites.Length} call sites" + debug $"{funcInfo.funcType.fName.Loc}: inlining function '{Printer.debugFunc funcInfo.funcType}' into {callSites.Length} call sites" for callSite in callSites do callSite.ident.ToBeInlined <- true funcInfo.funcType.fName.ToBeInlined <- true diff --git a/src/api.fs b/src/api.fs index 1a7fabf2..aa203bfe 100644 --- a/src/api.fs +++ b/src/api.fs @@ -21,12 +21,13 @@ let private readFile file = stream.ReadToEnd() let minify (files: (string*string)[]) = - let names = files |> Array.map (fun (n,_) -> n) |> String.Concat in debug $"----- minifying {names}" + let names = String.Join(",", files |> Array.map (fun (n,c) -> $"'{n}' ({c.Length}b)")) in debug $"----- minifying {names}" vprintf "Input file size is: %d\n" (files |> Array.sumBy (fun (_, s) -> s.Length)) let shaders = files |> Array.map (fun (f, c) -> Parse.runParser f c) vprintf "File parsed. "; printSize shaders for shader in shaders do + if shaders.Length > 1 then debug $"---- {shader.filename}" if shader.reorderFunctions then shader.code <- Rewriter.reorderFunctions shader.code shader.code <- Rewriter.simplify shader.code diff --git a/src/ast.fs b/src/ast.fs index 4ec4f817..e5ba61d0 100644 --- a/src/ast.fs +++ b/src/ast.fs @@ -5,6 +5,7 @@ open Options.Globals [] type VarScope = Global | Local | Parameter +[] type Location = { line: int; col: int } type Ident(name: string) = diff --git a/src/printer.fs b/src/printer.fs index c116500f..2c0c9c02 100644 --- a/src/printer.fs +++ b/src/printer.fs @@ -297,6 +297,7 @@ type PrinterImpl(withLocations) = member _.ExprToS = exprToS member _.TypeToS = typeToS + member _.FunToS = funToS member _.PrintIndented tl = printIndented tl |> String.concat "" member _.WriteSymbols shader = let tlStrings = printIndented shader.code |> List.map stripIndentation @@ -336,3 +337,5 @@ let debugIdent (ident: Ident) = match ident.Declaration with | Declaration.Variable rv -> debugDecl rv.decl | _ -> ident.OldName.ToString() + +let debugFunc (funcType: FunctionType) = (new PrinterImpl(false)).FunToS funcType diff --git a/src/rewriter.fs b/src/rewriter.fs index 104547a6..c5b91582 100644 --- a/src/rewriter.fs +++ b/src/rewriter.fs @@ -604,7 +604,8 @@ module private RewriterImpl = |> List.contains funcInfo.funcType.prototype) // when in doubt wrt overload resolution, keep the function. canBeRenamed && not isCalled && not funcInfo.funcType.isExternal let unused = [for funcInfo in funcInfos do if isUnused funcInfo then yield funcInfo] - if not unused.IsEmpty then debug($"removing unused functions: " + String.Join(", ", unused |> List.map (fun fi -> fi.funcType))) + if not unused.IsEmpty then + debug($"removing unused functions: " + String.Join(", ", unused |> List.map (fun fi -> Printer.debugFunc fi.funcType))) let unused = unused |> List.map (fun fi -> fi.func) |> set let mutable edited = false let code = code |> List.filter (function @@ -671,7 +672,7 @@ module private ArgumentInlining = let argExprs = callSites |> List.map (fun c -> c.argExprs |> List.item argIndex) |> List.distinct match argExprs with | [argExpr] when isInlinableExpr argExpr -> // The argExpr must always be the same at all call sites. - debug $"inlining expression '{Printer.exprToS argExpr}' into argument '{Printer.debugDecl varDecl.decl}' of '{funcInfo.funcType}'" + debug $"{varDecl.decl.name.Loc}: inlining expression '{Printer.exprToS argExpr}' into argument '{Printer.debugDecl varDecl.decl}' of '{Printer.debugFunc funcInfo.funcType}'" argInlinings <- {func=funcInfo.func; argIndex=argIndex; varDecl=varDecl; argExpr=argExpr} :: argInlinings | _ -> () | _ -> ()