@@ -16,6 +16,8 @@ import (
16
16
"context"
17
17
"fmt"
18
18
"html"
19
+ "io"
20
+ "net/http"
19
21
"regexp"
20
22
"strconv"
21
23
"strings"
@@ -26,39 +28,33 @@ import (
26
28
27
29
// AssemblyHTML returns an HTML document containing an assembly listing of the selected function.
28
30
//
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.
34
34
inv , cleanupInvocation , err := snapshot .GoCommandInvocation (cache .NoNetwork , pkg .Metadata ().CompiledGoFiles [0 ].DirPath (), "build" , []string {"-gcflags=-S" , "." })
35
35
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
37
39
}
38
40
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 ()
44
41
45
42
escape := html .EscapeString
46
43
47
- // Produce the report.
44
+ // Emit the start of the report.
48
45
title := fmt .Sprintf ("%s assembly for %s" ,
49
46
escape (snapshot .View ().GOARCH ()),
50
47
escape (symbol ))
51
- var buf bytes.Buffer
52
- buf .WriteString (`<!DOCTYPE html>
48
+ io .WriteString (w , `<!DOCTYPE html>
53
49
<html>
54
50
<head>
55
51
<meta charset="UTF-8">
56
- <title>` + escape (title ) + `</title>
52
+ <title>` + escape (title )+ `</title>
57
53
<link rel="stylesheet" href="/assets/common.css">
58
54
<script src="/assets/common.js"></script>
59
55
</head>
60
56
<body>
61
- <h1>` + title + `</h1>
57
+ <h1>` + title + `</h1>
62
58
<p>
63
59
<a href='https://go.dev/doc/asm'>A Quick Guide to Go's Assembler</a>
64
60
</p>
@@ -69,11 +65,23 @@ func AssemblyHTML(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Pack
69
65
Click on a source line marker <code>L1234</code> to navigate your editor there.
70
66
(VS Code users: please upvote <a href='https://github.com/microsoft/vscode/issues/208093'>#208093</a>)
71
67
</p>
72
- <p>
73
- Reload the page to recompile.
74
- </p>
68
+ <p id='compiling'>Compiling...</p>
75
69
<pre>
76
70
` )
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 ()
77
85
78
86
// insnRx matches an assembly instruction line.
79
87
// 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
88
96
//
89
97
// Allow matches of symbol, symbol.func1, symbol.deferwrap, etc.
90
98
on := false
91
- for _ , line := range strings .Split (content , "\n " ) {
99
+ var buf bytes.Buffer
100
+ for line := range strings .SplitSeq (content , "\n " ) {
92
101
// start of function symbol?
93
102
if strings .Contains (line , " STEXT " ) {
94
103
on = strings .HasPrefix (line , symbol ) &&
@@ -116,5 +125,14 @@ func AssemblyHTML(ctx context.Context, snapshot *cache.Snapshot, pkg *cache.Pack
116
125
}
117
126
buf .WriteByte ('\n' )
118
127
}
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 ())
120
138
}
0 commit comments