tooling improvements
This commit is contained in:
160
streamline.ce
160
streamline.ce
@@ -1,6 +1,10 @@
|
||||
// streamline.ce — run the full compile + optimize pipeline, output JSON
|
||||
// streamline.ce — run the full compile + optimize pipeline
|
||||
//
|
||||
// Usage: ./cell --core . streamline.ce <file.ce|file.cm>
|
||||
// Usage:
|
||||
// pit streamline <file> Full optimized IR as JSON (default)
|
||||
// pit streamline --stats <file> Summary stats per function
|
||||
// pit streamline --ir <file> Human-readable IR
|
||||
// pit streamline --check <file> Warnings only (e.g. high slot count)
|
||||
|
||||
var fd = use("fd")
|
||||
var json = use("json")
|
||||
@@ -9,11 +13,159 @@ var parse = use("parse")
|
||||
var fold = use("fold")
|
||||
var mcode = use("mcode")
|
||||
var streamline = use("streamline")
|
||||
var filename = args[0]
|
||||
|
||||
var show_stats = false
|
||||
var show_ir = false
|
||||
var show_check = false
|
||||
var filename = null
|
||||
var i = 0
|
||||
|
||||
for (i = 0; i < length(args); i++) {
|
||||
if (args[i] == '--stats') {
|
||||
show_stats = true
|
||||
} else if (args[i] == '--ir') {
|
||||
show_ir = true
|
||||
} else if (args[i] == '--check') {
|
||||
show_check = true
|
||||
} else if (!starts_with(args[i], '-')) {
|
||||
filename = args[i]
|
||||
}
|
||||
}
|
||||
|
||||
if (!filename) {
|
||||
print("usage: pit streamline [--stats] [--ir] [--check] <file>")
|
||||
$stop()
|
||||
}
|
||||
|
||||
var src = text(fd.slurp(filename))
|
||||
var result = tokenize(src, filename)
|
||||
var ast = parse(result.tokens, src, filename, tokenize)
|
||||
var folded = fold(ast)
|
||||
var compiled = mcode(folded)
|
||||
|
||||
// Deep copy for before snapshot (needed by --stats)
|
||||
var before = null
|
||||
if (show_stats) {
|
||||
before = json.decode(json.encode(compiled))
|
||||
}
|
||||
|
||||
var optimized = streamline(compiled)
|
||||
print(json.encode(optimized, true))
|
||||
|
||||
// If no flags, default to full JSON output
|
||||
if (!show_stats && !show_ir && !show_check) {
|
||||
print(json.encode(optimized, true))
|
||||
$stop()
|
||||
}
|
||||
|
||||
// --- Helpers ---
|
||||
|
||||
var ir_stats = use("ir_stats")
|
||||
|
||||
var pad_right = function(s, w) {
|
||||
var r = s
|
||||
while (length(r) < w) {
|
||||
r = r + " "
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
var count_nops = function(func) {
|
||||
var instrs = func.instructions
|
||||
var nops = 0
|
||||
var i = 0
|
||||
if (instrs == null) return 0
|
||||
while (i < length(instrs)) {
|
||||
if (is_text(instrs[i]) && starts_with(instrs[i], "_nop_")) {
|
||||
nops = nops + 1
|
||||
}
|
||||
i = i + 1
|
||||
}
|
||||
return nops
|
||||
}
|
||||
|
||||
var print_func_stats = function(func, before_func, name) {
|
||||
var nr_args = func.nr_args != null ? func.nr_args : 0
|
||||
var nr_slots = func.nr_slots != null ? func.nr_slots : 0
|
||||
var nr_close = func.nr_close_slots != null ? func.nr_close_slots : 0
|
||||
var stats = ir_stats.detailed_stats(func)
|
||||
var nops = count_nops(func)
|
||||
var before_stats = before_func ? ir_stats.detailed_stats(before_func) : null
|
||||
var before_total = before_stats ? before_stats.instr : stats.instr
|
||||
|
||||
print(` ${name}`)
|
||||
print(` args=${text(nr_args)} slots=${text(nr_slots)} close_slots=${text(nr_close)}`)
|
||||
print(` instructions: ${text(stats.instr)} total, ${text(nops)} nops eliminated`)
|
||||
if (before_stats) {
|
||||
print(` before: ${text(before_total)} after: ${text(stats.instr - nops)}`)
|
||||
}
|
||||
print(` load=${text(stats.load)} store=${text(stats.store)} branch=${text(stats.branch)} call=${text(stats.call)}`)
|
||||
print(` guard=${text(stats.guard)} arith=${text(stats.arith)} move=${text(stats.move)} const=${text(stats.const)}`)
|
||||
|
||||
if (nr_slots > 200) {
|
||||
print(` WARNING: nr_slots=${text(nr_slots)} approaching 255 limit`)
|
||||
}
|
||||
}
|
||||
|
||||
var print_func_ir = function(func, name) {
|
||||
var ir_text = ir_stats.canonical_ir(func, name, {show_nops: true})
|
||||
print(ir_text)
|
||||
}
|
||||
|
||||
var check_func = function(func, name) {
|
||||
var nr_slots = func.nr_slots != null ? func.nr_slots : 0
|
||||
if (nr_slots > 200) {
|
||||
print(`WARNING: ${name} has ${text(nr_slots)} slots (approaching 255 limit)`)
|
||||
}
|
||||
}
|
||||
|
||||
// --- Process functions ---
|
||||
|
||||
var main_name = optimized.name != null ? optimized.name : "<main>"
|
||||
var fi = 0
|
||||
var func = null
|
||||
var bfunc = null
|
||||
var fname = null
|
||||
|
||||
if (show_stats) {
|
||||
print(`\n--- Stats for ${filename} ---`)
|
||||
}
|
||||
|
||||
// Main function
|
||||
if (optimized.main != null) {
|
||||
if (show_stats) {
|
||||
print_func_stats(optimized.main, before ? before.main : null, main_name)
|
||||
}
|
||||
if (show_ir) {
|
||||
print_func_ir(optimized.main, main_name)
|
||||
}
|
||||
if (show_check) {
|
||||
check_func(optimized.main, main_name)
|
||||
}
|
||||
}
|
||||
|
||||
// Sub-functions
|
||||
if (optimized.functions != null) {
|
||||
fi = 0
|
||||
while (fi < length(optimized.functions)) {
|
||||
func = optimized.functions[fi]
|
||||
bfunc = before ? before.functions[fi] : null
|
||||
fname = func.name != null ? func.name : `<func_${text(fi)}>`
|
||||
|
||||
if (show_stats) {
|
||||
print_func_stats(func, bfunc, fname)
|
||||
}
|
||||
if (show_ir) {
|
||||
print_func_ir(func, fname)
|
||||
}
|
||||
if (show_check) {
|
||||
check_func(func, fname)
|
||||
}
|
||||
fi = fi + 1
|
||||
}
|
||||
}
|
||||
|
||||
if (show_stats) {
|
||||
print('---')
|
||||
}
|
||||
|
||||
$stop()
|
||||
|
||||
Reference in New Issue
Block a user