From 22570ee4e52c7e1f9c1f17de29429a57150d3369 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Sun, 24 Jun 2018 22:52:40 -0600 Subject: [PATCH] refactoring workermain to support multiple files and build steps --- doc/notes.txt | 36 ++- src/worker/nodemain.js | 9 +- src/worker/workermain.js | 571 ++++++++++++++++++++++-------------- test/cli/testworker.js | 32 +- test/cli/workertestutils.js | 6 +- 5 files changed, 414 insertions(+), 240 deletions(-) diff --git a/doc/notes.txt b/doc/notes.txt index 70409560..70493bf5 100644 --- a/doc/notes.txt +++ b/doc/notes.txt @@ -1,13 +1,11 @@ TODO: -- download ROM file - NaN in cycle count for macros - debugging of scan line overflow - confuse code/data in listing - show memory locations hovering over lines - don't play sound when debugging -- coalesce compile events - don't check against ROM signatures - better errors when ROM format wrong - debugging inside of bank switching??? relocated segs? @@ -17,12 +15,38 @@ TODO: - show other TIA internal values - case sensisitvity looking for mismatch variables - remove pulldown when no preset? -- some units test maybe - can't step after reset (or when funky frame; TIA frame is out of sync) - break on BRK/illegal opcode? -- last used filename for each platform -- skeleton for each platform/tool -- disassembler/debugger - multiple breakpoints, expression breakpoints +- cc65 listing file parsing +- better disasm/listing selection +- disasm for z80 +- projects w/ include files +- watchpoints +- breakpoints +- debug inspector +- MAME single step (?) +- step over +- slowdown beam for all platforms? +- kbd shortcuts + +WEB WORKER FORMAT + +{code,platform,tool,dependencies} +{preload} + +new: + +{infiles,buildsteps} +[{filepath,platform,tool}] + +implicit rules +- push/shift build steps +- preprocessor, compile, assemble, link +- access to intermediate files + +only build files that have changed + +build options diff --git a/src/worker/nodemain.js b/src/worker/nodemain.js index 86d2d074..7d7b04b6 100644 --- a/src/worker/nodemain.js +++ b/src/worker/nodemain.js @@ -34,7 +34,7 @@ function Blob(blob) { global.XMLHttpRequest = function() { this.open = function(a,b,c) { if (this.responseType == 'json') { - var txt = fs.readFileSync(',/'+b); + var txt = fs.readFileSync('./'+b); this.response = JSON.parse(txt); } else if (this.responseType == 'blob') { var data = fs.readFileSync('./'+b, {encoding:'binary'}); @@ -66,6 +66,9 @@ global.ab2str = function(buf) { if (require.main == module) { var data = fs.readFileSync(process.argv[2]); - var result = handleMessage(JSON.parse(data)); - console.log(result); + var msgs = JSON.parse(data); + for (var i=0; i in line 1 of main.asm null @@ -816,17 +871,30 @@ function assemblelinkSDASZ80(code, platform) { printErr:match_asm_fn, }); var FS = ASZ80['FS']; - FS.writeFile("main.asm", code, {encoding:'utf8'}); - starttime(); - ASZ80.callMain(['-plosgffwy', 'main.asm']); - endtime("assemble"); + populateFiles(step, FS, { + mainFilePath:"main.asm" + }); + execMain(step, ASZ80, ['-plosgffwy', step.path]); if (errors.length) { return {errors:errors}; } - objout = FS.readFile("main.rel", {encoding:'utf8'}); - lstout = FS.readFile("main.lst", {encoding:'utf8'}); + objout = FS.readFile(step.prefix+".rel", {encoding:'utf8'}); + lstout = FS.readFile(step.prefix+".lst", {encoding:'utf8'}); + putWorkFile(step.prefix+".rel", objout); + putWorkFile(step.prefix+".lst", lstout); + return { + linktool:"sdldz80", + files:[step.prefix+".rel", step.prefix+".lst"], + args:[step.prefix+".rel"] + }; //symout = FS.readFile("main.sym", {encoding:'utf8'}); - }{ + } +} + +function linkSDLDZ80(step) +{ + loadNative("sdldz80"); + var errors = []; //?ASlink-Warning-Undefined Global '__divsint' referenced by module 'main' var match_aslink_re = /\?ASlink-(\w+)-(.+)/; function match_aslink_fn(s) { @@ -838,7 +906,8 @@ function assemblelinkSDASZ80(code, platform) { }); } } - var updateListing = !params.extra_link_args; + var params = step.params; + var updateListing = !params.extra_link_args; // TODO var LDZ80 = sdldz80({ wasmBinary: wasmBlob['sdldz80'], noInitialRun:true, @@ -848,32 +917,32 @@ function assemblelinkSDASZ80(code, platform) { }); var FS = LDZ80['FS']; setupFS(FS, 'sdcc'); - FS.writeFile("main.rel", objout, {encoding:'utf8'}); - if (updateListing) { - FS.writeFile("main.lst", lstout, {encoding:'utf8'}); - } + populateFiles(step, FS); var args = ['-mjwxy'+(updateListing?'u':''), - '-i', 'main.ihx', + '-i', 'main.ihx', // TODO: main? '-b', '_CODE=0x'+params.code_start.toString(16), '-b', '_DATA=0x'+params.data_start.toString(16), '-k', '/share/lib/z80', '-l', 'z80']; if (params.extra_link_args) { + // TODO? what this for? args.push.apply(args, params.extra_link_args); } else { - args.push('main.rel'); + args.push.apply(args, step.args); } - starttime(); - LDZ80.callMain(args); - endtime("link"); + execMain(step, LDZ80, args); var hexout = FS.readFile("main.ihx", {encoding:'utf8'}); var mapout = FS.readFile("main.noi", {encoding:'utf8'}); - var rstout = updateListing ? FS.readFile("main.rst", {encoding:'utf8'}) : lstout; + var rstout; + if (updateListing) + rstout = FS.readFile("main.rst", {encoding:'utf8'}); // TODO: could be different filename + else + rstout = FS.readFile("main.lst", {encoding:'utf8'}); // TODO: could be different filename //var dbgout = FS.readFile("main.cdb", {encoding:'utf8'}); // 0000 21 02 00 [10] 52 ld hl, #2 // TODO: use map to find code_offset - var asmlines = parseListing(lstout, /^\s*([0-9A-F]+)\s+([0-9A-F][0-9A-F r]*[0-9A-F])\s+\[([0-9 ]+)\]\s+(\d+) (.*)/i, 4, 1, 2, params.code_offset); //, 5, 3); - var srclines = parseSourceLines(lstout, /^\s+\d+ ;:(\d+):/i, /^\s*([0-9A-F]{4})/i, params.code_offset); + var asmlines = parseListing(rstout, /^\s*([0-9A-F]+)\s+([0-9A-F][0-9A-F r]*[0-9A-F])\s+\[([0-9 ]+)\]\s+(\d+) (.*)/i, 4, 1, 2, params.code_offset); //, 5, 3); + var srclines = parseSourceLines(rstout, /^\s+\d+ ;:(\d+):/i, /^\s*([0-9A-F]{4})/i, params.code_offset); // parse symbol map var symbolmap = {}; for (var s of mapout.split("\n")) { @@ -884,24 +953,19 @@ function assemblelinkSDASZ80(code, platform) { } return { output:parseIHX(hexout, params.rom_start?params.rom_start:params.code_start, params.rom_size), - lines:asmlines, - srclines:srclines, + asmlines:srclines.length?asmlines:null, + lines:srclines.length?srclines:asmlines, errors:errors, // TODO? symbolmap:symbolmap, intermediate:{listing:rstout}, }; - } } var sdcc; -function compileSDCC(code, platform) { - var preproc = preprocessMCPP(code, platform); - if (preproc.errors) return preproc; - else code = preproc.code; - - var params = PLATFORM_PARAMS[platform]; - if (!params) throw Error("Platform not supported: " + platform); +function compileSDCC(step) { + var errors = []; + var params = step.params; loadNative('sdcc'); var SDCC = sdcc({ @@ -913,9 +977,17 @@ function compileSDCC(code, platform) { TOTAL_MEMORY:256*1024*1024, }); var FS = SDCC['FS']; + populateFiles(step, FS, { + mainFilePath:"main.c" // not used + }); + // load source file and preprocess + var code = workfs[step.path].data; // TODO + var preproc = preprocessMCPP(code, step.platform); + if (preproc.errors) return preproc; + else code = preproc.code; + // pipe file to stdin setupStdin(FS, code); setupFS(FS, 'sdcc'); - //FS.writeFile("main.c", code, {encoding:'utf8'}); var args = ['--vc', '--std-sdcc99', '-mz80', //'-Wall', '--c1mode', // '--debug', //'-S', 'main.c', @@ -927,36 +999,24 @@ function compileSDCC(code, platform) { //'--oldralloc', // TODO: does this make it fater? //'--cyclomatic', //'--nooverlay','--nogcse','--nolabelopt','--noinvariant','--noinduction','--nojtbound','--noloopreverse','--no-peep','--nolospre', - '-o', 'main.asm']; + '-o', step.prefix+'.asm']; if (params.extra_compile_args) { args.push.apply(args, params.extra_compile_args); } - starttime(); - SDCC.callMain(args); - endtime("compile"); + execMain(step, SDCC, args); // TODO: preprocessor errors w/ correct file if (errors.length /* && nwarnings < msvc_errors.length*/) { return {errors:errors}; } - try { - var asmout = FS.readFile("main.asm", {encoding:'utf8'}); - asmout = " .area _HOME\n .area _CODE\n .area _INITIALIZER\n .area _DATA\n .area _INITIALIZED\n .area _BSEG\n .area _BSS\n .area _HEAP\n" + asmout; - //asmout = asmout.replace(".area _INITIALIZER",".area _CODE"); - } catch (e) { - errors.push({line:1, msg:e+""}); - return {errors:errors}; - } - var warnings = errors; - try { - var result = assemblelinkSDASZ80(asmout, platform, true); - } catch (e) { - errors.push({line:1, msg:e+""}); - return {errors:errors}; - } - result.asmlines = result.lines; - result.lines = result.srclines; - result.srclines = null; - return result; + // massage the asm output + var asmout = FS.readFile(step.prefix+".asm", {encoding:'utf8'}); + asmout = " .area _HOME\n .area _CODE\n .area _INITIALIZER\n .area _DATA\n .area _INITIALIZED\n .area _BSEG\n .area _BSS\n .area _HEAP\n" + asmout; + putWorkFile(step.prefix+".asm", asmout); + return { + nexttool:"sdasz80", + path:step.prefix+".asm", + args:[step.prefix+".asm"] + }; } function assembleXASM6809(code, platform) { @@ -990,19 +1050,17 @@ function assembleXASM6809(code, platform) { //setupFS(FS); FS.writeFile("main.asm", code); Module.callMain(["-c", "-l", "-s", "-y", "-o=main.bin", "main.asm"]); - try { - var aout = FS.readFile("main.bin", {encoding:'binary'}); - // 00001 0000 [ 2] 1048 asld - var asmlines = parseListing(alst, /^\s*([0-9A-F]+)\s+([0-9A-F]+)\s+\[([0-9 ]+)\]\s+(\d+) (.*)/i, 1, 2, 4, params.code_offset); //, 5, 3); - return { + if (errors.length) + return {errors:errors}; + var aout = FS.readFile("main.bin", {encoding:'binary'}); + // 00001 0000 [ 2] 1048 asld + var asmlines = parseListing(alst, /^\s*([0-9A-F]+)\s+([0-9A-F]+)\s+\[([0-9 ]+)\]\s+(\d+) (.*)/i, 1, 2, 4, params.code_offset); //, 5, 3); + return { output:aout, errors:errors, lines:asmlines, intermediate:{listing:alst}, - }; - } catch(e) { - return {errors:errors}; // TODO - } + }; } function preprocessMCPP(code, platform) { @@ -1021,6 +1079,7 @@ function preprocessMCPP(code, platform) { var FS = MCPP['FS']; setupFS(FS, 'sdcc'); FS.writeFile("main.c", code, {encoding:'utf8'}); + // TODO: make configurable by other compilers var args = [ "-D", "__8BITWORKSHOP__", "-D", platform.toUpperCase().replace('-','_'), @@ -1032,12 +1091,10 @@ function preprocessMCPP(code, platform) { args.push.apply(args, params.extra_preproc_args); } MCPP.callMain(args); - try { - var iout = FS.readFile("main.i", {encoding:'utf8'}); - iout = iout.replace(/^#line /gm,'\n# '); - } catch (e) { - errors.push({line:1, msg:e+""}); - } + if (errors.length) + return {errors:errors}; + var iout = FS.readFile("main.i", {encoding:'utf8'}); + iout = iout.replace(/^#line /gm,'\n# '); try { var errout = FS.readFile("mcpp.err", {encoding:'utf8'}); if (errout.length) { @@ -1068,21 +1125,19 @@ function assembleNAKEN(code, platform) { //setupFS(FS); FS.writeFile("main.asm", code); Module.callMain(["-l", "-b", "main.asm"]); - try { - var aout = FS.readFile("out.bin", {encoding:'binary'}); - var alst = FS.readFile("out.lst", {encoding:'utf8'}); - //console.log(alst); - // 0x0000: 77 ld (hl),a cycles: 4 - var asmlines = parseListing(alst, /^0x([0-9a-f]+):\s+([0-9a-f]+)\s+(.+)cycles: (\d+)/i, 0, 1, 2); //, 3); - return { - output:aout, - errors:errors, - lines:asmlines, - intermediate:{listing:alst}, - }; - } catch(e) { + if (errors.length) return {errors:errors}; - } + var aout = FS.readFile("out.bin", {encoding:'binary'}); + var alst = FS.readFile("out.lst", {encoding:'utf8'}); + //console.log(alst); + // 0x0000: 77 ld (hl),a cycles: 4 + var asmlines = parseListing(alst, /^0x([0-9a-f]+):\s+([0-9a-f]+)\s+(.+)cycles: (\d+)/i, 0, 1, 2); //, 3); + return { + output:aout, + errors:errors, + lines:asmlines, + intermediate:{listing:alst}, + }; } function detectModuleName(code) { @@ -1159,20 +1214,15 @@ function compileCASPR(code, platform, options) { var arch = code.match(/^[.]arch\s+(\w+)/m); var deps = [{prefix:'verilog',filename:arch[1]+'.cfg'}]; // TODO: parse file for ".arch femto8" writeDependencies(deps, FS, errors); - try { - starttime(); - caspr_mod.callMain(["main.asm"]); - endtime("compile"); - var miffile = FS.readFile("main.mif", {encoding:'utf8'}); - return { - errors:errors, - output:parseMIF(miffile), - intermediate:{listing:miffile}, - lines:[]}; - } catch(e) { - errors.push({line:0,msg:e.message}); - return {errors:errors}; // TODO - } + starttime(); + caspr_mod.callMain(["main.asm"]); + endtime("compile"); + var miffile = FS.readFile("main.mif", {encoding:'utf8'}); + return { + errors:errors, + output:parseMIF(miffile), + intermediate:{listing:miffile}, + lines:[]}; } var jsasm_module_top; @@ -1347,15 +1397,17 @@ var TOOLS = { 'acme': assembleACME, 'plasm': compilePLASMA, 'cc65': compileCC65, - 'ca65': assemblelinkCA65, + 'ca65': assembleCA65, + 'ld65': linkLD65, 'z80asm': assembleZ80ASM, - 'sdasz80': assemblelinkSDASZ80, + 'sdasz80': assembleSDASZ80, + 'sdldz80': linkSDLDZ80, 'sdcc': compileSDCC, - 'xasm6809': assembleXASM6809, - 'naken': assembleNAKEN, + //'xasm6809': assembleXASM6809, + //'naken': assembleNAKEN, 'verilator': compileVerilator, 'yosys': compileYosys, - 'caspr': compileCASPR, + //'caspr': compileCASPR, 'jsasm': compileJSASM, } @@ -1373,6 +1425,7 @@ var TOOL_PRELOADFS = { } function handleMessage(data) { + // preload file system if (data.preload) { var fs = TOOL_PRELOADFS[data.preload]; if (!fs && data.platform) @@ -1381,15 +1434,85 @@ function handleMessage(data) { loadFilesystem(fs); return; } - // (code,platform,tool) - var code = data.code; - var platform = data.platform; - var toolfn = TOOLS[data.tool]; - if (!toolfn) throw "no tool named " + data.tool; - var dependencies = data.dependencies; - var result = toolfn(code, platform, data); - result.params = PLATFORM_PARAMS[platform]; - return result; + // (code,platform,tool,dependencies) + buildsteps = []; + // file updates + if (data.updates) { + for (var i=0; i