Skip to content
This repository was archived by the owner on Dec 8, 2025. It is now read-only.

Commit 029d770

Browse files
committed
emit size info in -dbg.json
1 parent a589e0d commit 029d770

File tree

5 files changed

+111
-37
lines changed

5 files changed

+111
-37
lines changed

compiler/src/compiler.ts

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,11 @@ import {
2727

2828
import {
2929
BinFmt,
30-
CellDebugInfo,
3130
ValueType,
32-
DebugInfo,
33-
FunctionDebugInfo,
3431
Host,
3532
OpCall,
3633
NumFmt,
3734
Op,
38-
RoleDebugInfo,
3935
SMap,
4036
ValueKind,
4137
JacsDiagnostic,
@@ -66,6 +62,13 @@ import {
6662
import { buildAST, formatDiagnostics, getProgramDiagnostics } from "./tsiface"
6763
import { preludeFiles } from "./specgen"
6864
import { jacdacDefaultSpecifications } from "./embedspecs"
65+
import {
66+
CellDebugInfo,
67+
RoleDebugInfo,
68+
FunctionDebugInfo,
69+
DebugInfo,
70+
SrcLocation,
71+
} from "./info"
6972

7073
export const JD_SERIAL_HEADER_SIZE = 16
7174
export const JD_SERIAL_MAX_PAYLOAD_SIZE = 236
@@ -80,6 +83,7 @@ export const DEVS_BYTECODE_FILE = `${DEVS_FILE_PREFIX}.devs`
8083
export const DEVS_LIB_FILE = `${DEVS_FILE_PREFIX}-lib.json`
8184
export const DEVS_BODY_FILE = `${DEVS_FILE_PREFIX}-body.json`
8285
export const DEVS_DBG_FILE = `${DEVS_FILE_PREFIX}-dbg.json`
86+
export const DEVS_SIZES_FILE = `${DEVS_FILE_PREFIX}-sizes.txts`
8387

8488
class Cell {
8589
_index: number
@@ -271,6 +275,18 @@ function cellKind(v: Value): ValueType {
271275
return v.valueType
272276
}
273277

278+
function toSrcLocation(n: ts.Node): SrcLocation {
279+
const f = n.getSourceFile()
280+
const pp = f.getLineAndCharacterOfPosition(n.pos)
281+
return {
282+
file: f.fileName,
283+
line: pp.line + 1,
284+
col: pp.character + 1,
285+
len: n.end - n.pos,
286+
pos: n.pos,
287+
}
288+
}
289+
274290
function idName(pat: ts.Expression | ts.DeclarationName) {
275291
if (ts.isIdentifier(pat)) return pat.text
276292
else return null
@@ -303,6 +319,8 @@ class Procedure {
303319
params: VariableScope
304320
locals: VariableScope
305321
methodSeqNo: Variable
322+
users: ts.Node[] = []
323+
skipAccounting = false
306324
constructor(public parent: Program, public name: string) {
307325
this.index = this.parent.procs.length
308326
this.writer = new OpWriter(parent, `${this.name}_F${this.index}`)
@@ -322,6 +340,10 @@ class Procedure {
322340
args() {
323341
return this.params.list.slice() as Variable[]
324342
}
343+
useFrom(node: ts.Node) {
344+
if (this.users.indexOf(node) >= 0) return
345+
this.users.push(node)
346+
}
325347
mkTempLocal(name: string, tp: ValueType) {
326348
const l = new Variable(null, this.locals, tp)
327349
l._name = name
@@ -333,6 +355,8 @@ class Procedure {
333355
return {
334356
name: this.name,
335357
srcmap: this.writer.srcmap,
358+
size: this.writer.size,
359+
users: this.users.map(toSrcLocation),
336360
locals: this.params.list
337361
.concat(this.locals.list)
338362
.map(v => v.debugInfo()),
@@ -439,6 +463,7 @@ class Program implements TopOpWriter {
439463
stringLiterals: (string | Uint8Array)[] = []
440464
writer: OpWriter
441465
proc: Procedure
466+
accountingProc: Procedure
442467
sysSpec: jdspec.ServiceSpec
443468
serviceSpecs: Record<string, jdspec.ServiceSpec>
444469
enums: Record<string, jdspec.EnumInfo> = {}
@@ -565,6 +590,7 @@ class Program implements TopOpWriter {
565590
private roleDispatcher(role: Role) {
566591
if (!role.dispatcher) {
567592
const proc = new Procedure(this, role.getName() + "_disp")
593+
proc.skipAccounting = true
568594
role.dispatcher = {
569595
proc,
570596
top: proc.writer.mkLabel("disp_top"),
@@ -702,13 +728,16 @@ class Program implements TopOpWriter {
702728
private withProcedure<T>(proc: Procedure, f: (wr: OpWriter) => T) {
703729
assert(!!proc)
704730
const prevProc = this.proc
731+
const prevAcc = this.accountingProc
705732
try {
706733
this.proc = proc
734+
if (!proc.skipAccounting) this.accountingProc = proc
707735
this.writer = proc.writer
708736
return f(proc.writer)
709737
} finally {
710738
this.proc = prevProc
711739
if (prevProc) this.writer = prevProc.writer
740+
this.accountingProc = prevAcc
712741
}
713742
}
714743

@@ -1082,6 +1111,12 @@ class Program implements TopOpWriter {
10821111
this.writer.assertNoTemps()
10831112
}
10841113

1114+
private uniqueProcName(base: string) {
1115+
let suff = 0
1116+
while (this.procs.some(p => p.name == base + "_" + suff)) suff++
1117+
return base + "_" + suff
1118+
}
1119+
10851120
private emitHandler(
10861121
name: string,
10871122
func: Expr,
@@ -1092,7 +1127,8 @@ class Program implements TopOpWriter {
10921127
): Procedure {
10931128
if (!ts.isArrowFunction(func))
10941129
throwError(func, "arrow function expected here")
1095-
const proc = new Procedure(this, name)
1130+
const proc = new Procedure(this, this.uniqueProcName(name))
1131+
proc.useFrom(func)
10961132
proc.writer.ret = proc.writer.mkLabel("ret")
10971133
if (func.parameters.length && !options.methodHandler)
10981134
throwError(func, "parameters not supported here")
@@ -1872,6 +1908,7 @@ class Program implements TopOpWriter {
18721908
) {
18731909
const wr = this.writer
18741910
const args = expr.arguments.slice()
1911+
proc.useFrom(expr)
18751912
if (isMember) {
18761913
this.requireArgs(expr, proc.numargs - 1)
18771914
if (ts.isPropertyAccessExpression(expr.expression))
@@ -2833,6 +2870,7 @@ class Program implements TopOpWriter {
28332870
}
28342871
this.host.write(DEVS_BODY_FILE, JSON.stringify(progJson, null, 4))
28352872
this.host.write(DEVS_DBG_FILE, JSON.stringify(dbg, null, 4))
2873+
this.host.write(DEVS_SIZES_FILE, computeSizes(dbg))
28362874

28372875
// write assembly again
28382876
if (this.numErrors == 0)
@@ -2988,3 +3026,23 @@ export function testCompiler(host: Host, code: string) {
29883026
}
29893027
}
29903028
}
3029+
3030+
export function computeSizes(dbg: DebugInfo) {
3031+
const funs = dbg.functions.slice()
3032+
funs.sort((a, b) => a.size - b.size || strcmp(a.name, b.name))
3033+
return (
3034+
"\n## Functions\n" +
3035+
funs.map(f => `${f.size}\t${f.name}\t${locs2str(f.users)}\n`).join("")
3036+
)
3037+
3038+
function loc2str(l: SrcLocation) {
3039+
return `${l.file}(${l.line},${l.col})`
3040+
}
3041+
3042+
function locs2str(ls: SrcLocation[]) {
3043+
const maxlen = 10
3044+
let r = ls.slice(0, maxlen).map(loc2str).join(", ")
3045+
if (ls.length > maxlen) r += "..."
3046+
return r
3047+
}
3048+
}

compiler/src/devicescript.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export * from "./disassemble"
55
export * from "./specgen"
66
export * from "./embedspecs"
77
export * from "./tsiface"
8+
export * from "./info"
89

910
import { compile } from "./compiler"
1011

compiler/src/format.ts

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
OP_TYPES,
1111
} from "./bytecode"
1212
import { toHex } from "./jdutil"
13+
import { DebugInfo } from "./info"
1314

1415
export * from "./bytecode"
1516
export * from "./type"
@@ -231,38 +232,6 @@ export function stringifyInstr(
231232
}
232233
}
233234

234-
export interface FunctionDebugInfo {
235-
name: string
236-
// format is (line-number, start, len)
237-
// start is offset in bytes from the start of the function
238-
// len is in bytes
239-
srcmap: number[]
240-
locals: CellDebugInfo[]
241-
}
242-
243-
export interface CellDebugInfo {
244-
name: string
245-
}
246-
247-
export interface RoleDebugInfo extends CellDebugInfo {
248-
serviceClass: number
249-
}
250-
251-
export interface DebugInfo {
252-
functions: FunctionDebugInfo[]
253-
roles: RoleDebugInfo[]
254-
globals: CellDebugInfo[]
255-
source: string
256-
}
257-
258-
export function emptyDebugInfo(): DebugInfo {
259-
return {
260-
functions: [],
261-
globals: [],
262-
roles: [],
263-
source: "",
264-
}
265-
}
266235

267236
export interface JacsDiagnostic extends ts.Diagnostic {
268237
filename: string

compiler/src/info.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
export interface SrcLocation {
2+
file: string
3+
line: number
4+
col: number
5+
len: number
6+
pos: number
7+
}
8+
9+
export interface FunctionDebugInfo {
10+
name: string
11+
size: number
12+
users: SrcLocation[]
13+
// format is (line-number, start, len)
14+
// start is offset in bytes from the start of the function
15+
// len is in bytes
16+
srcmap: number[]
17+
locals: CellDebugInfo[]
18+
}
19+
20+
export interface CellDebugInfo {
21+
name: string
22+
}
23+
24+
export interface RoleDebugInfo extends CellDebugInfo {
25+
serviceClass: number
26+
}
27+
28+
export interface DebugInfo {
29+
functions: FunctionDebugInfo[]
30+
roles: RoleDebugInfo[]
31+
globals: CellDebugInfo[]
32+
source: string
33+
}
34+
35+
export function emptyDebugInfo(): DebugInfo {
36+
return {
37+
functions: [],
38+
globals: [],
39+
roles: [],
40+
source: "",
41+
}
42+
}

compiler/src/opwriter.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ export class OpWriter {
183183
return this.binary.slice(0, this.binPtr)
184184
}
185185

186+
get size() {
187+
return this.binPtr
188+
}
189+
186190
finalizeDesc(off: number, numlocals: number, numargs: number) {
187191
const flags = 0
188192
const buf = new Uint8Array(4 * 4)

0 commit comments

Comments
 (0)