@@ -16,6 +16,8 @@ import (
1616 "context"
1717 "fmt"
1818 "html"
19+ "io"
20+ "net/http"
1921 "regexp"
2022 "strconv"
2123 "strings"
@@ -26,39 +28,33 @@ import (
2628
2729// AssemblyHTML returns an HTML document containing an assembly listing of the selected function.
2830//
29- // TODO(adonovan):
30- // - display a "Compiling..." message as a cold build can be slow.
31- // - cross-link jumps and block labels, like github.com/aclements/objbrowse.
32- func AssemblyHTML (ctx context.Context , snapshot * cache.Snapshot , pkg * cache.Package , symbol string , web Web ) ([]byte , error ) {
33- // Compile the package with -S, and capture its stderr stream.
31+ // TODO(adonovan): cross-link jumps and block labels, like github.com/aclements/objbrowse.
32+ func AssemblyHTML (ctx context.Context , snapshot * cache.Snapshot , w http.ResponseWriter , pkg * cache.Package , symbol string , web Web ) {
33+ // Prepare to compile the package with -S, and capture its stderr stream.
3434 inv , cleanupInvocation , err := snapshot .GoCommandInvocation (cache .NoNetwork , pkg .Metadata ().CompiledGoFiles [0 ].DirPath (), "build" , []string {"-gcflags=-S" , "." })
3535 if err != nil {
36- return nil , err // e.g. failed to write overlays (rare)
36+ // e.g. failed to write overlays (rare)
37+ http .Error (w , err .Error (), http .StatusInternalServerError )
38+ return
3739 }
3840 defer cleanupInvocation ()
39- _ , stderr , err , _ := snapshot .View ().GoCommandRunner ().RunRaw (ctx , * inv )
40- if err != nil {
41- return nil , err // e.g. won't compile
42- }
43- content := stderr .String ()
4441
4542 escape := html .EscapeString
4643
47- // Produce the report.
44+ // Emit the start of the report.
4845 title := fmt .Sprintf ("%s assembly for %s" ,
4946 escape (snapshot .View ().GOARCH ()),
5047 escape (symbol ))
51- var buf bytes.Buffer
52- buf .WriteString (`<!DOCTYPE html>
48+ io .WriteString (w , `<!DOCTYPE html>
5349<html>
5450<head>
5551 <meta charset="UTF-8">
56- <title>` + escape (title ) + `</title>
52+ <title>` + escape (title )+ `</title>
5753 <link rel="stylesheet" href="/assets/common.css">
5854 <script src="/assets/common.js"></script>
5955</head>
6056<body>
61- <h1>` + title + `</h1>
57+ <h1>` + title + `</h1>
6258<p>
6359 <a href='https://go.dev/doc/asm'>A Quick Guide to Go's Assembler</a>
6460</p>
@@ -69,11 +65,23 @@ func AssemblyHTML(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Pack
6965 Click on a source line marker <code>L1234</code> to navigate your editor there.
7066 (VS Code users: please upvote <a href='https://github.com/microsoft/vscode/issues/208093'>#208093</a>)
7167</p>
72- <p>
73- Reload the page to recompile.
74- </p>
68+ <p id='compiling'>Compiling...</p>
7569<pre>
7670` )
71+ if flusher , ok := w .(http.Flusher ); ok {
72+ flusher .Flush ()
73+ }
74+
75+ // Compile the package.
76+ _ , stderr , err , _ := snapshot .View ().GoCommandRunner ().RunRaw (ctx , * inv )
77+ if err != nil {
78+ // e.g. won't compile
79+ http .Error (w , err .Error (), http .StatusInternalServerError )
80+ return
81+ }
82+
83+ // Write the rest of the report.
84+ content := stderr .String ()
7785
7886 // insnRx matches an assembly instruction line.
7987 // Submatch groups are: (offset-hex-dec, file-line-column, instruction).
@@ -88,7 +96,8 @@ func AssemblyHTML(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Pack
8896 //
8997 // Allow matches of symbol, symbol.func1, symbol.deferwrap, etc.
9098 on := false
91- for _ , line := range strings .Split (content , "\n " ) {
99+ var buf bytes.Buffer
100+ for line := range strings .SplitSeq (content , "\n " ) {
92101 // start of function symbol?
93102 if strings .Contains (line , " STEXT " ) {
94103 on = strings .HasPrefix (line , symbol ) &&
@@ -116,5 +125,14 @@ func AssemblyHTML(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Pack
116125 }
117126 buf .WriteByte ('\n' )
118127 }
119- return buf .Bytes (), nil
128+
129+ // Update the "Compiling..." message.
130+ buf .WriteString (`
131+ </pre>
132+ <script>
133+ document.getElementById('compiling').innerText = 'Reload the page to recompile.';
134+ </script>
135+ </body>` )
136+
137+ w .Write (buf .Bytes ())
120138}
0 commit comments