@gasm-compiler/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +17 -0
- package/README.md +720 -0
- package/dist/browser-executor.d.ts +76 -0
- package/dist/browser-executor.js +1 -0
- package/dist/browser.d.ts +20 -0
- package/dist/browser.js +1 -0
- package/dist/chunk-BRCWMQF4.js +5 -0
- package/dist/chunk-G6YRZSKB.js +1 -0
- package/dist/chunk-LC4DBTKT.js +5 -0
- package/dist/chunk-STDXBN5E.js +1 -0
- package/dist/compiler.d.ts +45 -0
- package/dist/compiler.js +1 -0
- package/dist/executor.d.ts +75 -0
- package/dist/executor.js +1 -0
- package/dist/mod.d.ts +91 -0
- package/dist/mod.js +1 -0
- package/dist/parser-Q0YamOJY.d.ts +390 -0
- package/package.json +72 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{A as ee,B as te,C as ne,a as w,c as q,d as P,e as D,f as U,g as N,i as z,j as W,m as R,o as j,p as H,q as J,r as K,s as Q,x as X,y as Y,z as Z}from"./chunk-BRCWMQF4.js";import{a as g}from"./chunk-STDXBN5E.js";import{resolve as de}from"path";import{stat as fe,readFile as De,writeFile as ze,unlink as We,mkdir as Ge}from"fs/promises";import{spawn as Te}from"child_process";import{dirname as qe}from"path";function re(e){let r=e.functions.map(n=>!("parallelLoopInfo"in n)||!n.parallelLoopInfo?n:he(n));return{...e,functions:r}}function he(e){let r=e.parallelLoopInfo.loopLocalIndex,{writes:n}=ge(e.body,r);if(n>0){let t=$(e.body,r);return{...e,body:t}}return e}function ge(e,r){let n=0,t=0;function o(s){switch(s.kind){case"simple":if(s.instructions)for(let i of s.instructions)i.opcode==="local.get"&&i.immediates?.[0]===r&&n++,(i.opcode==="local.set"||i.opcode==="local.tee")&&i.immediates?.[0]===r&&t++;break;case"block":for(let i of s.children)o(i);break;case"loop":o(s.body);break;case"if":o(s.thenBranch),s.elseBranch&&o(s.elseBranch);break;case"parallel_loop":o(s.body),s.epilogue&&o(s.epilogue);break;case"return":case"break":case"continue":break}}return o(e),{reads:n,writes:t}}function $(e,r){switch(e.kind){case"simple":{if(!e.instructions)return e;let n=e.instructions.filter(t=>!((t.opcode==="local.set"||t.opcode==="local.tee")&&t.immediates?.[0]===r));return n.length===0?{kind:"block",children:[]}:{...e,instructions:n}}case"block":{let n=e.children.map(t=>$(t,r)).filter(t=>!ye(t));return{...e,children:n}}case"loop":return{...e,body:$(e.body,r)};case"if":return{...e,thenBranch:$(e.thenBranch,r),elseBranch:e.elseBranch?$(e.elseBranch,r):void 0};case"parallel_loop":return{...e,body:$(e.body,r),epilogue:e.epilogue?$(e.epilogue,r):void 0};case"return":case"break":case"continue":return e}}function ye(e){return e.kind==="block"&&e.children.length===0||e.kind==="simple"&&(!e.instructions||e.instructions.length===0)}function oe(e){let r=e.functions.map(n=>be(n));return{...e,functions:r}}function be(e){let r=k(e.body,e);return{...e,body:r}}function k(e,r){switch(e.kind){case"loop":{let n=Se(e.body),t=[],o=ie(e.body,n,t,r);return t.length===0?{...e,body:k(e.body,r)}:{kind:"block",children:[{kind:"simple",instructions:t},{...e,body:k(o,r)}],label:void 0}}case"block":return{...e,children:e.children.map(n=>k(n,r))};case"if":return{...e,thenBranch:k(e.thenBranch,r),elseBranch:e.elseBranch?k(e.elseBranch,r):void 0};case"simple":return e;default:return e}}function Se(e){let r=new Set;function n(t){if(t.kind==="simple"&&t.instructions){for(let o of t.instructions)if(o.id!==void 0&&r.add(o.id),(o.opcode==="local.set"||o.opcode==="local.tee")&&o.immediates){let s=o.immediates[0];r.add(-s-1)}}t.kind==="block"&&t.children.forEach(n),t.kind==="loop"&&n(t.body),t.kind==="if"&&(n(t.thenBranch),t.elseBranch&&n(t.elseBranch))}return n(e),r}function ie(e,r,n,t){switch(e.kind){case"simple":{if(!e.instructions||e.instructions.length===0)return e;let o=[],s=new Set;for(let i of e.instructions)we(i,r,s)?(n.push(i),i.id!==void 0&&s.add(i.id)):(o.push(i),i.id!==void 0&&s.add(i.id));return{...e,instructions:o}}case"block":{let o=e.children.map(s=>ie(s,r,n,t));return{...e,children:o}}case"loop":return e;case"if":return e;default:return e}}function we(e,r,n){if(!Ie(e.opcode))return!1;if(e.opcode==="local.get"&&e.immediates){let o=-e.immediates[0]-1;if(r.has(o))return!1}if(e.args){for(let t of e.args)if(r.has(t))return!1}return!0}function Ie(e){return new Set(["i32.const","i64.const","f32.const","f64.const","local.get","i32.add","i32.sub","i32.mul","i32.div_s","i32.div_u","i32.rem_s","i32.rem_u","i64.add","i64.sub","i64.mul","i64.div_s","i64.div_u","i64.rem_s","i64.rem_u","f32.add","f32.sub","f32.mul","f32.div","f64.add","f64.sub","f64.mul","f64.div","i32.and","i32.or","i32.xor","i32.shl","i32.shr_s","i32.shr_u","i32.rotl","i32.rotr","i64.and","i64.or","i64.xor","i64.shl","i64.shr_s","i64.shr_u","i64.rotl","i64.rotr","i32.eqz","i32.eq","i32.ne","i32.lt_s","i32.lt_u","i32.gt_s","i32.gt_u","i32.le_s","i32.le_u","i32.ge_s","i32.ge_u","i64.eqz","i64.eq","i64.ne","i64.lt_s","i64.lt_u","i64.gt_s","i64.gt_u","i64.le_s","i64.le_u","i64.ge_s","i64.ge_u","f32.eq","f32.ne","f32.lt","f32.gt","f32.le","f32.ge","f64.eq","f64.ne","f64.lt","f64.gt","f64.le","f64.ge","i32.wrap_i64","i64.extend_i32_s","i64.extend_i32_u","f32.convert_i32_s","f32.convert_i32_u","f32.convert_i64_s","f32.convert_i64_u","f32.demote_f64","f64.convert_i32_s","f64.convert_i32_u","f64.convert_i64_s","f64.convert_i64_u","f64.promote_f32","i32.reinterpret_f32","i64.reinterpret_f64","f32.reinterpret_i32","f64.reinterpret_i64","i32.clz","i32.ctz","i32.popcnt","i64.clz","i64.ctz","i64.popcnt","f32.abs","f32.neg","f32.ceil","f32.floor","f32.trunc","f32.nearest","f32.sqrt","f64.abs","f64.neg","f64.ceil","f64.floor","f64.trunc","f64.nearest","f64.sqrt","f32.min","f32.max","f32.copysign","f64.min","f64.max","f64.copysign"]).has(e)}function se(e){for(let r of e.functions)ve(r);return e}function ve(e){x(e.body,e)}function x(e,r){switch(e.kind){case"simple":$e(e,r);break;case"block":for(let n of e.children)x(n,r);break;case"loop":x(e.body,r);break;case"if":x(e.thenBranch,r),e.elseBranch&&x(e.elseBranch,r);break;case"parallel_loop":x(e.body,r),e.epilogue&&x(e.epilogue,r);break}}function $e(e,r){let n=_e(e.instructions,r);n.length>0&&ke(e,r,n);let t=Ae(e.instructions,r);t.length>0&&Ee(e,r,t)}function ae(e,r){let n=O(e,r);if(!n)return null;if(n.opcode==="i32.shr_u"&&n.args.length===2){if(L(n.args[1],r)!==2)return null;let o=n.args[0];return xe(o,r)}return Me(e,r)}function xe(e,r){let n=O(e,r);if(!n)return{baseVar:e,wordOffset:0};if(n.opcode==="i32.add"&&n.args.length===2){let t=L(n.args[1],r);if(t!==null&&t>=0&&t%4===0)return{baseVar:n.args[0],wordOffset:t/4};let o=L(n.args[0],r);return o!==null&&o>=0&&o%4===0?{baseVar:n.args[1],wordOffset:o/4}:null}return{baseVar:e,wordOffset:0}}function Me(e,r){let n=O(e,r);if(!n)return{baseVar:e,wordOffset:0};if(n.opcode==="i32.add"&&n.args.length===2){let t=L(n.args[1],r);if(t!==null&&t>=0)return{baseVar:n.args[0],wordOffset:t}}return{baseVar:e,wordOffset:0}}function O(e,r){if(r.inlinedExpressionMap){let n=r.inlinedExpressionMap.get(e);if(n)return n}return M(r.body,e)}function M(e,r){switch(e.kind){case"simple":for(let n of e.instructions)if(n.id===r)return n;return null;case"block":for(let n of e.children){let t=M(n,r);if(t)return t}return null;case"loop":return M(e.body,r);case"if":{let n=M(e.thenBranch,r);return n||(e.elseBranch?M(e.elseBranch,r):null)}case"parallel_loop":{let n=M(e.body,r);return n||(e.epilogue?M(e.epilogue,r):null)}default:return null}}function L(e,r){let n=O(e,r);return n&&n.opcode==="i32.const"&&n.immediates&&n.immediates.length>0?n.immediates[0]:null}function _e(e,r){let n=[],t=[];for(let s=0;s<e.length;s++){let i=e[s];if(i.opcode==="wgsl.store_f32"&&i.args.length===2){let a=ae(i.args[0],r);a&&t.push({index:s,addr:a,valueArg:i.args[1]})}}let o=new Map;for(let s of t){let i=o.get(s.addr.baseVar)||[];i.push(s),o.set(s.addr.baseVar,i)}for(let[s,i]of o){if(i.length<3)continue;i.sort((c,u)=>c.addr.wordOffset-u.addr.wordOffset);let a=0;for(;a<i.length;){let c=a;for(;c+1<i.length&&i[c+1].addr.wordOffset===i[c].addr.wordOffset+1;)c++;let u=c-a+1;if(u>=3){let p=u>=4?4:3,d=i.slice(a,a+p),m=d.map(h=>h.index);ce(m,e)&&n.push({instrIndices:m,baseVar:s,valueArgs:d.map(h=>h.valueArg),components:p})}a=c+1}}return n}function Ae(e,r){let n=[],t=[];for(let s=0;s<e.length;s++){let i=e[s];if(i.opcode==="wgsl.load_f32"&&i.args.length===1&&i.id!==void 0){let a=ae(i.args[0],r);a&&t.push({index:s,addr:a,resultVar:i.id})}}let o=new Map;for(let s of t){let i=o.get(s.addr.baseVar)||[];i.push(s),o.set(s.addr.baseVar,i)}for(let[s,i]of o){if(i.length<3)continue;i.sort((c,u)=>c.addr.wordOffset-u.addr.wordOffset);let a=0;for(;a<i.length;){let c=a;for(;c+1<i.length&&i[c+1].addr.wordOffset===i[c].addr.wordOffset+1;)c++;let u=c-a+1;if(u>=3){let p=u>=4?4:3,d=i.slice(a,a+p),m=d.map(h=>h.index);ce(m,e)&&n.push({instrIndices:m,baseVar:s,resultVars:d.map(h=>h.resultVar),components:p})}a=c+1}}return n}function ce(e,r){if(e.length<3)return!1;let n=Math.min(...e),t=Math.max(...e),o=e.length*4;if(t-n>=o)return!1;for(let s=n;s<=t;s++)if(r[s].opcode.startsWith("wgsl.store")&&!e.includes(s))return!1;return!0}function ke(e,r,n){n.sort((t,o)=>o.instrIndices[0]-t.instrIndices[0]);for(let t of n){let o=t.components===4?"wgsl.store_vec4f":"wgsl.store_vec3f",s=e.instructions[t.instrIndices[0]].args[0],i={type:"instr",opcode:o,args:[s,...t.valueArgs],synthetic:!0},a=[...t.instrIndices].sort((c,u)=>c-u);for(let c=a.length-1;c>=0;c--)e.instructions.splice(a[c],1);e.instructions.splice(a[0],0,i)}}function Ee(e,r,n){n.sort((t,o)=>o.instrIndices[0]-t.instrIndices[0]);for(let t of n){let o=t.components===4?"wgsl.load_vec4f":"wgsl.load_vec3f",s=0;for(let d of r.vars.keys())d>s&&(s=d);let i=s+1;r.vars.set(i,{id:i,type:"v128"});let a=e.instructions[t.instrIndices[0]].args[0],c={type:"instr",id:i,opcode:o,args:[a],synthetic:!0},u=t.resultVars.map((d,m)=>({type:"instr",id:d,opcode:"wgsl.extract_f32",args:[i],immediates:[m],synthetic:!0})),p=[...t.instrIndices].sort((d,m)=>d-m);for(let d=p.length-1;d>=0;d--)e.instructions.splice(p[d],1);e.instructions.splice(p[0],0,c,...u)}}function ue(e,r){let n={valid:!0,mathImports:[],errors:[],requiredLevel:null},t=r===!0||r==="M0"||r==="M1"||r==="M2",o=r===!0?"M2":r==="M0"||r==="M1"||r==="M2"?r:null,s=["M0","M1","M2"],i=0;for(let a of e.imports){if(a.kind!=="func")continue;let c=i++;if(!z(a.module,a.name))continue;let u=a.typeIndex;if(u===void 0){n.errors.push(w(`Math import ${a.name} has no type index`,{functionName:a.name})),n.valid=!1;continue}let p=e.types[u];if(!p){n.errors.push(w(`Math import ${a.name} references invalid type index ${u}`,{functionName:a.name})),n.valid=!1;continue}let d=W(a.name);if(!d){n.errors.push(w(`Unknown math intrinsic: ${a.name}`,{functionName:a.name})),n.valid=!1;continue}let m={funcIndex:c,module:a.module,name:a.name,level:d.level,params:p.params,results:p.results};if(n.mathImports.push(m),(n.requiredLevel===null||s.indexOf(d.level)>s.indexOf(n.requiredLevel))&&(n.requiredLevel=d.level),!t){n.errors.push(w(`Math intrinsic ${a.name} requires mathExtension option to be enabled`,{functionName:a.name})),n.valid=!1;continue}if(o&&!R(a.name,o)){n.errors.push(w(`Math intrinsic ${a.name} requires level ${d.level}, but only ${o} is enabled`,{functionName:a.name})),n.valid=!1;continue}let h=j(a.name,p.params,p.results);h&&(n.errors.push(w(h,{functionName:a.name})),n.valid=!1)}return n}var le={};for(let[e,r]of Object.entries(q))le[r]=e.replace(/_/g,".");function Ve(e){let r=[];r.push("(module");for(let t of e.memories)r.push(` (memory ${t.min}${t.max!==void 0?` ${t.max}`:""})`);for(let t of e.imports)if(t.kind==="func"&&t.typeIndex!==void 0){let o=e.types[t.typeIndex];if(o){let s=o.params.map((a,c)=>`(param $${c} ${a})`).join(" "),i=o.results.map(a=>`(result ${a})`).join(" ");r.push(` (import "${t.module}" "${t.name}" (func ${s}${i?" "+i:""}))`)}}let n=new Set;for(let t of e.globals){if(t.kind==="import")continue;let o=t.mutable?"(mut ":"",s=t.mutable?")":"",i="";t.initValue!==void 0&&(t.type==="i32"||t.type==="i64"?i=`${t.type}.const ${t.initValue}`:(t.type==="f32"||t.type==="f64")&&(i=`${t.type}.const ${t.initValue}`)),r.push(` (global $${t.index} ${o}${t.type}${s} ${i?`(${i})`:""})`)}for(let t of e.data){let o=Array.from(t.data.slice(0,Math.min(32,t.data.length))).map(i=>`\\${i.toString(16).padStart(2,"0")}`).join(""),s=t.data.length>32?"...":"";r.push(` (data (i32.const ${t.memoryIndex}) "${o}${s}") ;; ${t.data.length} bytes`)}for(let t of e.functions)r.push(""),r.push(...Ce(t,e));if(e.exports.length>0){r.push("");for(let t of e.exports)t.kind==="func"?r.push(` (export "${t.name}" (func $${t.index}))`):t.kind==="mem"?r.push(` (export "${t.name}" (memory ${t.index}))`):t.kind==="global"&&r.push(` (export "${t.name}" (global ${t.index}))`)}return e.startFunctionIndex!==void 0&&r.push(` (start $${e.startFunctionIndex})`),r.push(")"),r.join(`
|
|
2
|
+
`)}function Ce(e,r){let n=[],t=e.params.map((i,a)=>`(param $${a} ${i})`).join(" "),o=e.results.map(i=>`(result ${i})`).join(" ");if(n.push(` (func $${e.index} ${t}${o?" "+o:""}`),e.locals.length>0){let i=new Map;for(let a of e.locals)i.set(a.type,(i.get(a.type)||0)+1);for(let[a,c]of i)n.push(` (local ${a} (;${c}x;))`)}let s=Be(e.body,2);return n.push(...s),n.push(" )"),n}function Be(e,r){let n=[],t=" ".repeat(r);for(let o of e){let s=Le(o,r);n.push(`${t}${s}`)}return n}function Le(e,r){if(!e||typeof e!="object")return";; Error: Invalid instruction";let{opcode:n,immediates:t}=e,o=le[n]||`unknown_0x${n.toString(16)}`;if(!t||t.length===0)return o;switch(o){case"local.get":case"local.set":case"local.tee":return`${o} $${t[0]}`;case"global.get":case"global.set":return`${o} $${t[0]}`;case"i32.const":case"i64.const":return`${o} ${t[0]}`;case"f32.const":case"f64.const":return`${o} ${t[0]}`;case"call":return`${o} $${t[0]}`;case"call_indirect":return`${o} (type ${t[0]})`;case"br":case"br_if":return`${o} ${t[0]}`;case"br_table":let s=t[0].join(" "),i=t[1];return`${o} ${s} ${i}`;case"if":case"block":case"loop":let a=t[0];return`${o} ${a!==void 0&&a!=="void"?`(result ${a})`:""}`;case"i32.load":case"i64.load":case"f32.load":case"f64.load":case"i32.load8_s":case"i32.load8_u":case"i32.load16_s":case"i32.load16_u":case"i64.load8_s":case"i64.load8_u":case"i64.load16_s":case"i64.load16_u":case"i64.load32_s":case"i64.load32_u":case"i32.store":case"i64.store":case"f32.store":case"f64.store":case"i32.store8":case"i32.store16":case"i64.store8":case"i64.store16":case"i64.store32":let c=t[0],u=t[1],p=[];return u!==0&&p.push(`offset=${u}`),c!==void 0&&p.push(`align=${1<<c}`),`${o}${p.length>0?" "+p.join(" "):""}`;case"memory.size":case"memory.grow":return o;default:if(o.startsWith("v128.")){if(o.includes("load")||o.includes("store")){let d=t[0],m=t[1],h=[];return m!==0&&h.push(`offset=${m}`),d!==void 0&&h.push(`align=${1<<d}`),`${o}${h.length>0?" "+h.join(" "):""}`}if(o.includes("const")){let d=t.join(" ");return`${o} ${d}`}return o.includes("extract_lane")||o.includes("replace_lane")?`${o} ${t[0]}`:`${o}${t.length>0?" "+t.join(" "):""}`}return`${o}${t.length>0?" "+t.join(" "):""}`}}var it=globalThis.gpu,Oe=globalThis.navigator?.gpu,G=class{constructor(r={}){this.config=r}device=null;queue=null;initialized=!1;buffers=new Map;async ensureInitialized(){if(!this.initialized)try{let r=await Oe?.requestAdapter?.();if(!r)throw new g("No GPU adapter available","compilation","navigator.gpu.requestAdapter() returned null");if(this.device=await r.requestDevice?.(),!this.device)throw new g("Failed to request GPU device","compilation","adapter.requestDevice() returned null");this.queue=this.device.queue,this.initialized=!0}catch(r){throw r instanceof g?r:new g(`GPU initialization failed: ${r instanceof Error?r.message:String(r)}`,"compilation",String(r))}}createBuffer(r,n,t){if(!this.device)throw new g("Device not initialized","binding","Call ensureInitialized() first");let o=this.device.createBuffer({label:r,size:n.byteLength,usage:t});return this.queue.writeBuffer(o,0,n.buffer,n.byteOffset,n.byteLength),o}async readBuffer(r,n,t){if(!this.device||!this.queue)throw new g("Device not initialized","readback","Call ensureInitialized() first");let o=Math.max(4,Math.ceil(n/4)*4),s=this.device.createBuffer({size:o,usage:9}),i=this.device.createCommandEncoder();i.copyBufferToBuffer(r,0,s,0,Math.min(n,o)),this.queue.submit([i.finish()]);try{await s.mapAsync(1)}catch(u){throw s.destroy(),new g(`Failed to map staging buffer: ${u instanceof Error?u.message:String(u)}`,"readback",String(u))}let a=s.getMappedRange(),c;return t==="f32"?c=new Float32Array(new Uint8Array(a).buffer).slice():t==="i32"?c=new Int32Array(new Uint8Array(a).buffer).slice():c=new Uint32Array(new Uint8Array(a).buffer).slice(),s.unmap(),s.destroy(),{data:c,type:t}}async execute(r,n,t,o={}){let s=o.workgroupSize??[1,1,1],i=o.workgroupCount??[1,1,1],a=o.timeout??5e3;if(await this.ensureInitialized(),!this.device||!this.queue)throw new g("Device initialization failed","compilation");try{let c;try{let l=o.shaderLabel||"Gasm Compiler Compute Shader";c=this.device.createShaderModule({code:r,label:l});let f=await c.getCompilationInfo?.();if(f&&f.messages.length>0){let y=f.messages.filter(b=>b.type==="error");if(y.length>0){let b=y.map(I=>`${I.message} at ${I.lineNum}:${I.linePos}`).join("; ");throw new g(`WGSL compilation failed: ${b}`,"compilation")}}}catch(l){throw l instanceof g?l:new g(`Failed to create shader module: ${l instanceof Error?l.message:String(l)}`,"compilation",String(l))}let u=[],p=0,d=new Map,m=Object.entries(n).sort((l,f)=>l[0]==="memory"?-1:f[0]==="memory"?1:l[0].localeCompare(f[0]));for(let[l,{data:f,type:y}]of m){let b=this.createBuffer(`input_${l}`,f,140);d.set(l,b),u.push({binding:p++,resource:{buffer:b}})}let h=new Map,v=new Map;for(let l of t){if(d.has(l)){let me=d.get(l),T=n[l];h.set(l,me),v.set(l,{size:T.data.byteLength,type:T.type});continue}let f=o.outputBuffers?.[l]??{type:"f32",size:1},y=f.size??1,b=y*4,I=this.device.createBuffer({label:`output_${l}`,size:b,usage:132}),A;f.type==="f32"?A=new Float32Array(y).fill(0):f.type==="i32"?A=new Int32Array(y).fill(0):A=new Uint32Array(y).fill(0),this.queue.writeBuffer(I,0,A.buffer,A.byteOffset,A.byteLength),h.set(l,I),v.set(l,{size:b,type:f.type}),u.push({binding:p++,resource:{buffer:I}})}let _=Object.keys(n).length,E=this.device.createBindGroupLayout({entries:u.map((l,f)=>{let y=f===0&&n.memory!==void 0,b=f>=_;return{binding:f,visibility:4,buffer:{type:!y&&!b?"read-only-storage":"storage"}}})}),S=this.device.createBindGroup({layout:E,entries:u}),V=this.device.createPipelineLayout({bindGroupLayouts:[E]}),C;try{C=this.device.createComputePipeline({layout:V,compute:{module:c,entryPoint:"main"}})}catch(l){throw new g(`Failed to create compute pipeline: ${l instanceof Error?l.message:String(l)}`,"binding",String(l))}try{let l=this.device.createCommandEncoder(),f=l.beginComputePass();f.setPipeline(C),f.setBindGroup(0,S),f.dispatchWorkgroups(i[0],i[1],i[2]),f.end(),this.queue.submit([l.finish()])}catch(l){throw new g(`Compute shader dispatch failed: ${l instanceof Error?l.message:String(l)}`,"dispatch",String(l))}let B={};try{for(let l of t){let f=h.get(l),y=v.get(l);if(!f||!y)throw new g(`Output buffer "${l}" not found`,"readback");B[l]=await this.readBuffer(f,y.size,y.type)}}catch(l){throw l instanceof g?l:new g(`Failed to read back results: ${l instanceof Error?l.message:String(l)}`,"readback",String(l))}finally{let l=new Set;d.forEach(f=>{f.destroy(),l.add(f)}),h.forEach(f=>{l.has(f)||f.destroy()})}return B}catch(c){throw c instanceof g?c:new g(`Unexpected error during execution: ${c instanceof Error?c.message:String(c)}`,"dispatch",String(c))}}async destroy(){this.buffers.forEach(r=>r.destroy()),this.buffers.clear(),this.device&&typeof this.device.destroy=="function"&&this.device.destroy(),this.device=null,this.queue=null,this.initialized=!1}};function F(e,r={}){let n=te(),t=P(e);if(D(t))return n.errors.push({severity:"error",code:"ERR_PARSE",message:t.message,functionName:t.functionName}),{ok:!1,diagnostics:n};let o=t,s=U(o,{strictConformance:r.strictConformance});if(N(s))return n.errors.push({severity:"error",code:"ERR_VALIDATION",message:s.message,functionName:s.functionName}),{ok:!1,diagnostics:n};let i=s;if(r.mathExtension){let m=ue(o,r.mathExtension);if(!m.valid){for(let h of m.errors)n.errors.push({severity:"error",code:"ERR_MATH_VALIDATION",message:h.message,functionName:h.functionName});return{ok:!1,diagnostics:n}}}let a=ne(i,r);if(n.warnings.push(...a.diagnostics.warnings),n.errors.push(...a.diagnostics.errors),n.demotions.push(...a.diagnostics.demotions),n.featuresUsed=a.diagnostics.featuresUsed,n.errors.length>0)return{ok:!1,diagnostics:n};let c=X(i);r.optimize!==!1&&(c=Z(c,{verbose:r.verbose??!1}));let u=ee(c);u=H(u),r.optimize!==!1&&(u=J(u)),r.vectorPromotion&&(u=se(u));let p=K();if(r.optimize!==!1){let m=Q(u);u=m.module,p=m.dispatchInfo,u=re(u),u=oe(u)}return{ok:!0,wgsl:Y(u,r,e,p),diagnostics:n,dispatchInfo:p}}function Lt(e,r={}){let n=F(e,r);if(!n.ok){let t=n.diagnostics.errors[0];throw w(t?.message??"Compilation failed",{functionName:t?.functionName,instructionName:t?.code})}return n.wgsl}function pe(e,r){for(let n of e.warnings){let t=n.functionName?` (${n.functionName})`:"";console.error(`warning${t}: ${n.message}`)}if(r&&e.demotions.length>0){let n=new Map;for(let o of e.demotions)n.set(o.kind,(n.get(o.kind)??0)+1);let t=[...n.entries()].map(([o,s])=>`${o} (${s})`);console.error(`demotions: ${t.join(", ")}`)}}function Ue(e,r){return new Promise(n=>{let t=Te(e,r,{stdio:["ignore","pipe","pipe"]}),o="",s="";t.stdout.on("data",i=>{o+=String(i)}),t.stderr.on("data",i=>{s+=String(i)}),t.on("close",i=>{n({success:i===0,stdout:o,stderr:s})}),t.on("error",i=>{n({success:!1,stdout:o,stderr:`${s}
|
|
3
|
+
${i.message}`})})})}async function Fe(e,r={}){let{output:n,verbose:t=!1,keepWasm:o=!1,optimize:s=!1,denyF64Demotion:i=!1,allowI64Demotion:a=!1,warningsAsErrors:c=!1}=r;try{t&&console.log(`[1/4] Validating input file: ${e}`);let u=de(e);if(!(await fe(u)).isFile())throw new Error(`Not a file: ${e}`);let d=u.endsWith(".wasm");!d&&!u.endsWith(".as")&&!u.endsWith(".ts")&&console.warn("Warning: Input file does not have .as, .ts, or .wasm extension");let m=u.replace(/\.(as|ts)$/,".wasm");if(d)t&&console.log("[2/4] Input is WASM, skipping compilation..."),m=u;else{t&&console.log("[2/4] Compiling AssemblyScript to WASM...");let S=await Ne(),{success:V,stdout:C,stderr:B}=await Ue(S,[u,"-o",m]);if(!V)throw new Error(`AssemblyScript compilation failed:
|
|
4
|
+
${B}`);t&&C&&console.log(C)}t&&console.log("[3/4] Reading WASM binary...");let h=await De(m);t&&(console.log(` WASM size: ${h.length} bytes`),console.log("[4/4] Compiling WASM to WGSL using Gasm..."));let v={};i&&(v.f64="deny"),a&&(v.i64="allow-lossy");let _=F(h,{optimize:s,demotionPolicy:v,warningsAsErrors:c});if(pe(_.diagnostics,t),!_.ok){let S=_.diagnostics.errors[0];throw new Error(S?.message??"Compilation failed")}let E=_.wgsl;if(n){let S=de(n),V=qe(S);await Ge(V,{recursive:!0}),await ze(S,E,"utf-8"),console.log(t?`
|
|
5
|
+
\u2713 Successfully compiled to: ${S}`:`\u2713 Compiled to: ${n}`)}if(!o&&!d)try{await We(m),t&&console.log(" Cleaned up intermediate WASM file")}catch{}return E}catch(u){throw u instanceof Error?u:new Error(`Unknown error: ${String(u)}`)}}function Pe(e,r={}){let{verbose:n=!1,optimize:t=!1,denyF64Demotion:o=!1,allowI64Demotion:s=!1,warningsAsErrors:i=!1}=r,a={};o&&(a.f64="deny"),s&&(a.i64="allow-lossy");let c=F(e,{optimize:t,demotionPolicy:a,warningsAsErrors:i});if(pe(c.diagnostics,n),!c.ok){let u=c.diagnostics.errors[0];throw new Error(u?.message??"Compilation failed")}return c.wgsl}async function Ne(){let e=["node_modules/.bin/asc","./examples/node_modules/.bin/asc","../app/node_modules/.bin/asc","./node_modules/assemblyscript/bin/asc.js"];for(let r of e)try{if((await fe(r)).isFile())return r}catch{}return"asc"}export{Ve as a,G as b,Fe as c,Pe as d,F as e,Lt as f};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=class extends Error{constructor(t,i,o){super(t);this.phase=i;this.details=o;this.name="ExecutionError"}};function u(r){return r instanceof e}export{e as a,u as b};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gasm Compiler - Node.js Compiler
|
|
3
|
+
*
|
|
4
|
+
* Node.js-compatible compilation orchestration for external packages.
|
|
5
|
+
* Handles the compilation pipeline:
|
|
6
|
+
* AssemblyScript → WASM → Gasm Validation → IR → WGSL
|
|
7
|
+
*/
|
|
8
|
+
interface CompileOptions {
|
|
9
|
+
output?: string;
|
|
10
|
+
verbose?: boolean;
|
|
11
|
+
keepWasm?: boolean;
|
|
12
|
+
optimize?: boolean;
|
|
13
|
+
denyF64Demotion?: boolean;
|
|
14
|
+
allowI64Demotion?: boolean;
|
|
15
|
+
warningsAsErrors?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Compiles an AssemblyScript file to WGSL using the Gasm compiler.
|
|
19
|
+
*
|
|
20
|
+
* Pipeline:
|
|
21
|
+
* 1. Validate input file exists
|
|
22
|
+
* 2. Compile AssemblyScript to WASM using asc
|
|
23
|
+
* 3. Read WASM binary
|
|
24
|
+
* 4. Compile WASM to WGSL using Gasm
|
|
25
|
+
* 5. Write output to file or return as string
|
|
26
|
+
*
|
|
27
|
+
* @param inputFile - Path to .as file
|
|
28
|
+
* @param options - Compilation options
|
|
29
|
+
* @returns WGSL code as string
|
|
30
|
+
*/
|
|
31
|
+
declare function compileAssemblyScriptToWGSL(inputFile: string, options?: CompileOptions): Promise<string>;
|
|
32
|
+
/**
|
|
33
|
+
* Compiles raw WASM bytes to WGSL using the Gasm compiler.
|
|
34
|
+
*
|
|
35
|
+
* This is a lower-level API that doesn't handle AssemblyScript compilation
|
|
36
|
+
* or file I/O. Useful for programmatic usage where WASM bytes are already
|
|
37
|
+
* available.
|
|
38
|
+
*
|
|
39
|
+
* @param wasmBytes - WebAssembly binary
|
|
40
|
+
* @param options - Compilation options
|
|
41
|
+
* @returns WGSL code as string
|
|
42
|
+
*/
|
|
43
|
+
declare function compileWasmToWGSL(wasmBytes: Uint8Array, options?: Omit<CompileOptions, "output" | "keepWasm">): string;
|
|
44
|
+
|
|
45
|
+
export { type CompileOptions, compileAssemblyScriptToWGSL, compileWasmToWGSL };
|
package/dist/compiler.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as a,d as b}from"./chunk-LC4DBTKT.js";import"./chunk-BRCWMQF4.js";import"./chunk-G6YRZSKB.js";import"./chunk-STDXBN5E.js";export{a as compileAssemblyScriptToWGSL,b as compileWasmToWGSL};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GPU Executor Abstraction Layer
|
|
3
|
+
*
|
|
4
|
+
* Provides a platform-agnostic interface for executing WGSL compute shaders
|
|
5
|
+
* with input/output buffer management.
|
|
6
|
+
*
|
|
7
|
+
* Supported implementations:
|
|
8
|
+
* - DenoGPUExecutor: Uses native WebGPU via Deno
|
|
9
|
+
* - BrowserGPUExecutor: Uses browser navigator.gpu (future)
|
|
10
|
+
*/
|
|
11
|
+
type GPUDevice = any;
|
|
12
|
+
interface BufferData {
|
|
13
|
+
data: Float32Array | Int32Array | Uint32Array;
|
|
14
|
+
type: "f32" | "i32" | "u32";
|
|
15
|
+
}
|
|
16
|
+
interface ExecutorConfig {
|
|
17
|
+
/** GPU device to use. If not provided, will request adapter and device. */
|
|
18
|
+
device?: GPUDevice;
|
|
19
|
+
/** Maximum iterations for execution safety (prevents infinite loops) */
|
|
20
|
+
maxIterations?: number;
|
|
21
|
+
}
|
|
22
|
+
interface OutputBufferSpec {
|
|
23
|
+
/** Buffer element type */
|
|
24
|
+
type: "f32" | "i32" | "u32";
|
|
25
|
+
/** Number of elements in the buffer. Default: 1 */
|
|
26
|
+
size?: number;
|
|
27
|
+
}
|
|
28
|
+
interface ExecuteOptions {
|
|
29
|
+
/** Workgroup dimensions [x, y, z]. Default: [1, 1, 1] */
|
|
30
|
+
workgroupSize?: [number, number, number];
|
|
31
|
+
/** Number of workgroups to dispatch [x, y, z]. Default: [1, 1, 1] */
|
|
32
|
+
workgroupCount?: [number, number, number];
|
|
33
|
+
/** Timeout in milliseconds. Default: 5000ms */
|
|
34
|
+
timeout?: number;
|
|
35
|
+
/** Output buffer specifications (type and size). If not provided, defaults to single f32 */
|
|
36
|
+
outputBuffers?: Record<string, OutputBufferSpec>;
|
|
37
|
+
/** Name of the entry point function. Default: "main" */
|
|
38
|
+
entryPoint?: string;
|
|
39
|
+
/** Label for the shader module (useful for debugging). If not provided, uses a default label */
|
|
40
|
+
shaderLabel?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Core GPU executor abstraction.
|
|
44
|
+
*
|
|
45
|
+
* Implementations handle shader compilation, buffer management,
|
|
46
|
+
* and result readback from the GPU.
|
|
47
|
+
*/
|
|
48
|
+
interface IGPUExecutor {
|
|
49
|
+
/**
|
|
50
|
+
* Execute a WGSL compute shader with the provided inputs.
|
|
51
|
+
*
|
|
52
|
+
* @param wgslCode - Valid WGSL compute shader source code
|
|
53
|
+
* @param inputs - Mapping of variable names to input buffers
|
|
54
|
+
* @param outputs - List of output variable names to capture
|
|
55
|
+
* @param options - Execution configuration (workgroup size, count, timeout)
|
|
56
|
+
* @returns Promise resolving to output buffers by name
|
|
57
|
+
* @throws ExecutionError if shader fails to compile or execute
|
|
58
|
+
*/
|
|
59
|
+
execute(wgslCode: string, inputs: Record<string, BufferData>, outputs: string[], options?: ExecuteOptions): Promise<Record<string, BufferData>>;
|
|
60
|
+
/**
|
|
61
|
+
* Release GPU resources. Call when done with executor.
|
|
62
|
+
*/
|
|
63
|
+
destroy(): Promise<void>;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Execution error with detailed diagnostic information.
|
|
67
|
+
*/
|
|
68
|
+
declare class ExecutionError extends Error {
|
|
69
|
+
phase: "compilation" | "binding" | "dispatch" | "readback";
|
|
70
|
+
details?: string | undefined;
|
|
71
|
+
constructor(message: string, phase: "compilation" | "binding" | "dispatch" | "readback", details?: string | undefined);
|
|
72
|
+
}
|
|
73
|
+
declare function isExecutionError(error: unknown): error is ExecutionError;
|
|
74
|
+
|
|
75
|
+
export { type BufferData, type ExecuteOptions, ExecutionError, type ExecutorConfig, type GPUDevice, type IGPUExecutor, type OutputBufferSpec, isExecutionError };
|
package/dist/executor.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a,b}from"./chunk-STDXBN5E.js";export{a as ExecutionError,b as isExecutionError};
|
package/dist/mod.d.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { W as WasmModule, C as CompileDiagnostics, D as DispatchInfo, a as CompileOptions } from './parser-Q0YamOJY.js';
|
|
2
|
+
export { b as CompileError, n as DebugInfo, f as MATH_INTRINSICS, e as MathIntrinsicSpec, M as MathLevel, m as SourceLanguage, S as SourceMappingLevel, V as VectorDimension, p as detectSourceLanguage, o as extractDebugInfo, l as getIntrinsicsAtLevel, h as getMathSpec, k as getVectorDimension, j as getWgslMapping, i as isCompileError, g as isMathIntrinsic, d as isParseError, q as parseNamesSection, r as parseProducersSection, c as parseWasmModule } from './parser-Q0YamOJY.js';
|
|
3
|
+
import { IGPUExecutor, ExecutorConfig, BufferData, ExecuteOptions } from './executor.js';
|
|
4
|
+
export { ExecutionError, OutputBufferSpec, isExecutionError } from './executor.js';
|
|
5
|
+
export { BrowserGPUExecutor } from './browser-executor.js';
|
|
6
|
+
export { CompileOptions as NodeCompilerOptions, compileAssemblyScriptToWGSL, compileWasmToWGSL } from './compiler.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* WAT Disassembler
|
|
10
|
+
*
|
|
11
|
+
* Converts WebAssembly binary format to WebAssembly Text (WAT) format.
|
|
12
|
+
* This provides a human-readable representation of the compiled WebAssembly module.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Disassemble a parsed WebAssembly module to WAT format.
|
|
17
|
+
*/
|
|
18
|
+
declare function disassembleToWAT(module: WasmModule): string;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Deno WebGPU Executor Implementation
|
|
22
|
+
*
|
|
23
|
+
* Executes WGSL compute shaders using Deno's native WebGPU support.
|
|
24
|
+
* Handles shader compilation, buffer management, and result readback.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* DenoGPUExecutor: Executes WGSL shaders using Deno's WebGPU API.
|
|
29
|
+
*
|
|
30
|
+
* Features:
|
|
31
|
+
* - Automatic GPU adapter/device initialization
|
|
32
|
+
* - Efficient buffer pooling for inputs/outputs
|
|
33
|
+
* - Type-safe buffer management (f32, i32, u32)
|
|
34
|
+
* - Comprehensive error reporting with execution phase tracking
|
|
35
|
+
* - Automatic cleanup of GPU resources
|
|
36
|
+
*
|
|
37
|
+
* Example usage:
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const executor = new DenoGPUExecutor();
|
|
40
|
+
* const result = await executor.execute(
|
|
41
|
+
* wgslCode,
|
|
42
|
+
* { input: { data: new Float32Array([1.0, 2.0]), type: "f32" } },
|
|
43
|
+
* ["output"],
|
|
44
|
+
* { workgroupSize: [64, 1, 1], workgroupCount: [1, 1, 1] }
|
|
45
|
+
* );
|
|
46
|
+
* console.log(result.output.data); // Float32Array
|
|
47
|
+
* await executor.destroy();
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
declare class DenoGPUExecutor implements IGPUExecutor {
|
|
51
|
+
private config;
|
|
52
|
+
private device;
|
|
53
|
+
private queue;
|
|
54
|
+
private initialized;
|
|
55
|
+
private buffers;
|
|
56
|
+
constructor(config?: ExecutorConfig);
|
|
57
|
+
/**
|
|
58
|
+
* Initialize GPU device and queue (lazy initialization).
|
|
59
|
+
*/
|
|
60
|
+
private ensureInitialized;
|
|
61
|
+
/**
|
|
62
|
+
* Create or reuse a GPU buffer for a given data array.
|
|
63
|
+
*/
|
|
64
|
+
private createBuffer;
|
|
65
|
+
/**
|
|
66
|
+
* Read buffer contents from GPU to CPU.
|
|
67
|
+
*/
|
|
68
|
+
private readBuffer;
|
|
69
|
+
/**
|
|
70
|
+
* Execute a WGSL compute shader with the provided inputs.
|
|
71
|
+
*/
|
|
72
|
+
execute(wgslCode: string, inputs: Record<string, BufferData>, outputs: string[], options?: ExecuteOptions): Promise<Record<string, BufferData>>;
|
|
73
|
+
/**
|
|
74
|
+
* Cleanup GPU resources.
|
|
75
|
+
*/
|
|
76
|
+
destroy(): Promise<void>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
type CompileWithDiagnosticsResult = {
|
|
80
|
+
ok: true;
|
|
81
|
+
wgsl: string;
|
|
82
|
+
diagnostics: CompileDiagnostics;
|
|
83
|
+
dispatchInfo: DispatchInfo;
|
|
84
|
+
} | {
|
|
85
|
+
ok: false;
|
|
86
|
+
diagnostics: CompileDiagnostics;
|
|
87
|
+
};
|
|
88
|
+
declare function compileWithDiagnostics(wasmBytes: Uint8Array, options?: CompileOptions): CompileWithDiagnosticsResult;
|
|
89
|
+
declare function compile(wasmBytes: Uint8Array, options?: CompileOptions): string;
|
|
90
|
+
|
|
91
|
+
export { BufferData, CompileDiagnostics, CompileOptions, type CompileWithDiagnosticsResult, DenoGPUExecutor, DispatchInfo, ExecuteOptions, ExecutorConfig, IGPUExecutor, compile, compileWithDiagnostics, disassembleToWAT };
|
package/dist/mod.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as n,b as r,c as s,d as t,e as u,f as v}from"./chunk-LC4DBTKT.js";import{b as a,d as b,e as c,h as d,i as e,j as f,k as g,l as h,n as i,t as j,u as k,v as l,w as m}from"./chunk-BRCWMQF4.js";import{a as q}from"./chunk-G6YRZSKB.js";import{a as o,b as p}from"./chunk-STDXBN5E.js";export{q as BrowserGPUExecutor,r as DenoGPUExecutor,o as ExecutionError,d as MATH_INTRINSICS,v as compile,s as compileAssemblyScriptToWGSL,t as compileWasmToWGSL,u as compileWithDiagnostics,l as detectSourceLanguage,n as disassembleToWAT,m as extractDebugInfo,i as getIntrinsicsAtLevel,f as getMathSpec,h as getVectorDimension,g as getWgslMapping,a as isCompileError,p as isExecutionError,e as isMathIntrinsic,c as isParseError,j as parseNamesSection,k as parseProducersSection,b as parseWasmModule};
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
type ValueType = "i32" | "i64" | "f32" | "f64" | "v128" | "funcref" | "externref";
|
|
2
|
+
interface Instruction {
|
|
3
|
+
opcode: number;
|
|
4
|
+
name: string;
|
|
5
|
+
immediates: (number | bigint | string | number[])[];
|
|
6
|
+
offset: number;
|
|
7
|
+
}
|
|
8
|
+
interface Local {
|
|
9
|
+
index: number;
|
|
10
|
+
type: ValueType;
|
|
11
|
+
mutable: boolean;
|
|
12
|
+
}
|
|
13
|
+
interface WasmFunction {
|
|
14
|
+
index: number;
|
|
15
|
+
name?: string;
|
|
16
|
+
params: ValueType[];
|
|
17
|
+
results: ValueType[];
|
|
18
|
+
locals: Local[];
|
|
19
|
+
body: Instruction[];
|
|
20
|
+
}
|
|
21
|
+
interface ImportedGlobal {
|
|
22
|
+
kind: "import";
|
|
23
|
+
index: number;
|
|
24
|
+
module: string;
|
|
25
|
+
name: string;
|
|
26
|
+
type: ValueType;
|
|
27
|
+
}
|
|
28
|
+
interface DefinedGlobal {
|
|
29
|
+
kind: "definition";
|
|
30
|
+
index: number;
|
|
31
|
+
type: ValueType;
|
|
32
|
+
mutable: boolean;
|
|
33
|
+
initExpr: Instruction[];
|
|
34
|
+
initValue?: number | bigint;
|
|
35
|
+
}
|
|
36
|
+
type Global = ImportedGlobal | DefinedGlobal;
|
|
37
|
+
interface WasmMemory {
|
|
38
|
+
index: number;
|
|
39
|
+
min: number;
|
|
40
|
+
max?: number;
|
|
41
|
+
}
|
|
42
|
+
interface WasmDataSegment {
|
|
43
|
+
memoryIndex: number;
|
|
44
|
+
offset: Instruction[];
|
|
45
|
+
data: Uint8Array;
|
|
46
|
+
}
|
|
47
|
+
interface WasmExport {
|
|
48
|
+
name: string;
|
|
49
|
+
kind: "func" | "table" | "mem" | "global";
|
|
50
|
+
index: number;
|
|
51
|
+
}
|
|
52
|
+
interface WasmImport {
|
|
53
|
+
module: string;
|
|
54
|
+
name: string;
|
|
55
|
+
kind: "func" | "table" | "mem" | "global";
|
|
56
|
+
typeIndex?: number;
|
|
57
|
+
}
|
|
58
|
+
interface WasmType {
|
|
59
|
+
params: ValueType[];
|
|
60
|
+
results: ValueType[];
|
|
61
|
+
}
|
|
62
|
+
interface WasmModule {
|
|
63
|
+
types: WasmType[];
|
|
64
|
+
functions: WasmFunction[];
|
|
65
|
+
globals: Global[];
|
|
66
|
+
memories: WasmMemory[];
|
|
67
|
+
data: WasmDataSegment[];
|
|
68
|
+
exports: WasmExport[];
|
|
69
|
+
imports: WasmImport[];
|
|
70
|
+
startFunctionIndex?: number;
|
|
71
|
+
/** Custom sections from the WebAssembly module (for graphics extension metadata) */
|
|
72
|
+
customSections?: CustomSection[];
|
|
73
|
+
}
|
|
74
|
+
interface CompileError extends Error {
|
|
75
|
+
functionName?: string;
|
|
76
|
+
instructionName?: string;
|
|
77
|
+
offset?: number;
|
|
78
|
+
}
|
|
79
|
+
declare function createCompileError(message: string, context?: {
|
|
80
|
+
functionName?: string;
|
|
81
|
+
instructionName?: string;
|
|
82
|
+
offset?: number;
|
|
83
|
+
}): CompileError;
|
|
84
|
+
declare function isCompileError$1(error: unknown): error is CompileError;
|
|
85
|
+
/** Custom section from WebAssembly module */
|
|
86
|
+
interface CustomSection {
|
|
87
|
+
/** Section name */
|
|
88
|
+
name: string;
|
|
89
|
+
/** Raw section data */
|
|
90
|
+
data: Uint8Array;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Automatic Parallelization Phase
|
|
95
|
+
*
|
|
96
|
+
* Detects canonical loops that can be parallelized on the GPU and transforms
|
|
97
|
+
* them to use the GPU's parallel execution model.
|
|
98
|
+
*
|
|
99
|
+
* A parallelizable loop has the pattern:
|
|
100
|
+
* - Initialization: local_i = 0
|
|
101
|
+
* - Condition: local_i < LIMIT
|
|
102
|
+
* - Increment: local_i = local_i + 1
|
|
103
|
+
* - Body: Uses local_i as an index, writes to memory[f(local_i)]
|
|
104
|
+
*
|
|
105
|
+
* Transformation:
|
|
106
|
+
* - The loop is replaced with an if guard: if (global_id.x < LIMIT)
|
|
107
|
+
* - local_i is mapped to global_invocation_id.x
|
|
108
|
+
* - @workgroup_size is set to an optimal value (e.g., 64 or 256)
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Metadata about how to dispatch the compute shader
|
|
113
|
+
*/
|
|
114
|
+
interface DispatchInfo {
|
|
115
|
+
/** Number of work items in X dimension */
|
|
116
|
+
workItemsX: number;
|
|
117
|
+
/** Number of work items in Y dimension */
|
|
118
|
+
workItemsY: number;
|
|
119
|
+
/** Number of work items in Z dimension */
|
|
120
|
+
workItemsZ: number;
|
|
121
|
+
/** Workgroup size in X dimension */
|
|
122
|
+
workgroupSizeX: number;
|
|
123
|
+
/** Workgroup size in Y dimension */
|
|
124
|
+
workgroupSizeY: number;
|
|
125
|
+
/** Workgroup size in Z dimension */
|
|
126
|
+
workgroupSizeZ: number;
|
|
127
|
+
/** Whether parallelization was applied */
|
|
128
|
+
isParallelized: boolean;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Source Mapping Module
|
|
133
|
+
*
|
|
134
|
+
* Generates source mapping comments in WGSL output to help with debugging
|
|
135
|
+
* and understanding the generated code. Maps generated WGSL back to original
|
|
136
|
+
* WebAssembly instructions and optionally to higher-level source languages.
|
|
137
|
+
*/
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Source mapping verbosity levels.
|
|
141
|
+
* - "none": No source mapping comments
|
|
142
|
+
* - "minimal": Only function and loop headers
|
|
143
|
+
* - "normal": Basic instruction mapping
|
|
144
|
+
* - "detailed": Full instruction mapping with Wasm offsets
|
|
145
|
+
* - "verbose": Everything including IR info
|
|
146
|
+
*/
|
|
147
|
+
type SourceMappingLevel = "none" | "minimal" | "normal" | "detailed" | "verbose";
|
|
148
|
+
/**
|
|
149
|
+
* Detected source language of the WebAssembly module.
|
|
150
|
+
*/
|
|
151
|
+
type SourceLanguage = "wat" | "assemblyscript" | "c" | "rust" | "unknown";
|
|
152
|
+
/**
|
|
153
|
+
* Debug information extracted from a WebAssembly module.
|
|
154
|
+
*/
|
|
155
|
+
interface DebugInfo {
|
|
156
|
+
/** Source language detected */
|
|
157
|
+
language: SourceLanguage;
|
|
158
|
+
/** Quality of debug information */
|
|
159
|
+
quality: "high" | "medium" | "low";
|
|
160
|
+
/** Function names (index -> name) */
|
|
161
|
+
functionNames: Map<number, string>;
|
|
162
|
+
/** Local variable names (funcIndex -> (localIndex -> name)) */
|
|
163
|
+
localNames: Map<number, Map<number, string>>;
|
|
164
|
+
/** Global variable names (index -> name) */
|
|
165
|
+
globalNames: Map<number, string>;
|
|
166
|
+
/** Block/loop labels (funcIndex -> (blockIndex -> label)) */
|
|
167
|
+
blockLabels: Map<number, Map<number, string>>;
|
|
168
|
+
/** Producer/toolchain information */
|
|
169
|
+
producers?: ProducerInfo;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Producer metadata from the "producers" custom section.
|
|
173
|
+
*/
|
|
174
|
+
interface ProducerInfo {
|
|
175
|
+
languages?: string[];
|
|
176
|
+
processedBy?: string[];
|
|
177
|
+
sdks?: string[];
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Names section data.
|
|
181
|
+
*/
|
|
182
|
+
interface NamesSection {
|
|
183
|
+
moduleName?: string;
|
|
184
|
+
functionNames: Map<number, string>;
|
|
185
|
+
localNames: Map<number, Map<number, string>>;
|
|
186
|
+
globalNames: Map<number, string>;
|
|
187
|
+
labelNames: Map<number, Map<number, string>>;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Parse the Names custom section from a WebAssembly binary.
|
|
191
|
+
* Returns null if the section is not present.
|
|
192
|
+
*/
|
|
193
|
+
declare function parseNamesSection(wasmBytes: Uint8Array): NamesSection | null;
|
|
194
|
+
/**
|
|
195
|
+
* Parse the "producers" custom section from a WebAssembly binary.
|
|
196
|
+
*/
|
|
197
|
+
declare function parseProducersSection(wasmBytes: Uint8Array): ProducerInfo | null;
|
|
198
|
+
/**
|
|
199
|
+
* Detect the source language of a WebAssembly module.
|
|
200
|
+
*/
|
|
201
|
+
declare function detectSourceLanguage(wasmBytes: Uint8Array, namesSection: NamesSection | null, producers: ProducerInfo | null): SourceLanguage;
|
|
202
|
+
/**
|
|
203
|
+
* Extract debug information from a WebAssembly binary.
|
|
204
|
+
*/
|
|
205
|
+
declare function extractDebugInfo(wasmBytes: Uint8Array): DebugInfo;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Gasm Math Extension Intrinsics Registry
|
|
209
|
+
*
|
|
210
|
+
* Defines all 70+ math functions for M0/M1/M2 levels with signatures,
|
|
211
|
+
* WGSL mappings, vector dimensions, and validation specs.
|
|
212
|
+
*
|
|
213
|
+
* Functions are imported from the "gasm" module with names like:
|
|
214
|
+
* - "sin" (scalar f32 -> f32)
|
|
215
|
+
* - "sin_v2f32" (vector vec2<f32> -> vec2<f32>)
|
|
216
|
+
* - "sin_v3f32" (vector vec3<f32> -> vec3<f32>)
|
|
217
|
+
* - "sin_v4f32" (vector vec4<f32> -> vec4<f32>, default for vector ops)
|
|
218
|
+
*/
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Math extension conformance levels
|
|
222
|
+
*/
|
|
223
|
+
type MathLevel = "M0" | "M1" | "M2";
|
|
224
|
+
/**
|
|
225
|
+
* Vector dimension (2, 3, or 4 components)
|
|
226
|
+
*/
|
|
227
|
+
type VectorDimension = 2 | 3 | 4;
|
|
228
|
+
/**
|
|
229
|
+
* Wasm type for math function parameters/results
|
|
230
|
+
*/
|
|
231
|
+
type MathWasmType = "f32" | "i32" | "v128";
|
|
232
|
+
/**
|
|
233
|
+
* Specification for a math intrinsic function
|
|
234
|
+
*/
|
|
235
|
+
interface MathIntrinsicSpec {
|
|
236
|
+
/** Base function name (e.g., "sin", "abs") */
|
|
237
|
+
name: string;
|
|
238
|
+
/** Math extension level required */
|
|
239
|
+
level: MathLevel;
|
|
240
|
+
/** Wasm parameter types for scalar version */
|
|
241
|
+
wasmParams: MathWasmType[];
|
|
242
|
+
/** Wasm result types for scalar version */
|
|
243
|
+
wasmResults: MathWasmType[];
|
|
244
|
+
/** WGSL built-in function name */
|
|
245
|
+
wgslBuiltin: string;
|
|
246
|
+
/** Whether this function supports vector overloads */
|
|
247
|
+
supportsVector: boolean;
|
|
248
|
+
/** Description of the function */
|
|
249
|
+
description: string;
|
|
250
|
+
/** Special handling flags */
|
|
251
|
+
flags?: {
|
|
252
|
+
/** Returns a struct type in WGSL (modf, frexp) */
|
|
253
|
+
returnsStruct?: boolean;
|
|
254
|
+
/** Struct result type name for WGSL */
|
|
255
|
+
structTypeName?: string;
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Registry of all math intrinsics by base name
|
|
260
|
+
*/
|
|
261
|
+
declare const MATH_INTRINSICS: Map<string, MathIntrinsicSpec>;
|
|
262
|
+
/**
|
|
263
|
+
* Check if an import name is a math intrinsic
|
|
264
|
+
* @param module Import module name
|
|
265
|
+
* @param name Import function name
|
|
266
|
+
* @returns true if this is a gasm math intrinsic
|
|
267
|
+
*/
|
|
268
|
+
declare function isMathIntrinsic(module: string, name: string): boolean;
|
|
269
|
+
/**
|
|
270
|
+
* Get the math intrinsic specification for a function
|
|
271
|
+
* @param name Function name (with or without vector suffix)
|
|
272
|
+
* @returns The intrinsic spec or undefined if not found
|
|
273
|
+
*/
|
|
274
|
+
declare function getMathSpec(name: string): MathIntrinsicSpec | undefined;
|
|
275
|
+
/**
|
|
276
|
+
* Get the WGSL built-in function mapping
|
|
277
|
+
* @param name Function name
|
|
278
|
+
* @returns WGSL built-in name
|
|
279
|
+
*/
|
|
280
|
+
declare function getWgslMapping(name: string): string | undefined;
|
|
281
|
+
/**
|
|
282
|
+
* Get the vector dimension from a function name suffix
|
|
283
|
+
* @param name Function name (e.g., "sin_v2f32" -> 2, "sin_v3f32" -> 3, "sin" -> 4)
|
|
284
|
+
* @returns Vector dimension (2, 3, or 4), defaults to 4 for scalar names
|
|
285
|
+
*/
|
|
286
|
+
declare function getVectorDimension(name: string): VectorDimension;
|
|
287
|
+
/**
|
|
288
|
+
* Get all math intrinsics available at a given level
|
|
289
|
+
* @param level Math extension level
|
|
290
|
+
*/
|
|
291
|
+
declare function getIntrinsicsAtLevel(level: MathLevel): MathIntrinsicSpec[];
|
|
292
|
+
|
|
293
|
+
type DemotionPolicyDecision = "allow" | "deny";
|
|
294
|
+
type I64DemotionPolicyDecision = "deny" | "allow-lossy";
|
|
295
|
+
interface DemotionPolicy {
|
|
296
|
+
f64: DemotionPolicyDecision;
|
|
297
|
+
i64: I64DemotionPolicyDecision;
|
|
298
|
+
}
|
|
299
|
+
interface CompileOptions {
|
|
300
|
+
workgroupSize?: [number, number, number];
|
|
301
|
+
optimize?: boolean;
|
|
302
|
+
verbose?: boolean;
|
|
303
|
+
demotionPolicy?: Partial<DemotionPolicy>;
|
|
304
|
+
warningsAsErrors?: boolean;
|
|
305
|
+
compilerMetadata?: string;
|
|
306
|
+
/**
|
|
307
|
+
* Enable source mapping comments in generated WGSL.
|
|
308
|
+
* - false or "none": No source mapping comments (default)
|
|
309
|
+
* - true or "normal": Basic instruction mapping
|
|
310
|
+
* - "minimal": Only function and loop headers
|
|
311
|
+
* - "detailed": Full instruction mapping with Wasm offsets
|
|
312
|
+
* - "verbose": Everything including IR info
|
|
313
|
+
*/
|
|
314
|
+
sourceMapping?: boolean | SourceMappingLevel;
|
|
315
|
+
/**
|
|
316
|
+
* Strip all source mapping comments from output.
|
|
317
|
+
* Useful for production builds where file size matters.
|
|
318
|
+
* Default: false (comments are included)
|
|
319
|
+
*/
|
|
320
|
+
stripComments?: boolean;
|
|
321
|
+
/**
|
|
322
|
+
* Alias for stripComments. Enables release mode optimizations.
|
|
323
|
+
* Default: false
|
|
324
|
+
*/
|
|
325
|
+
releaseMode?: boolean;
|
|
326
|
+
/**
|
|
327
|
+
* Inline memory load/store operations instead of using helper functions.
|
|
328
|
+
* Produces slightly different code but avoids function call overhead.
|
|
329
|
+
* Default: false
|
|
330
|
+
*/
|
|
331
|
+
inlineMemoryOps?: boolean;
|
|
332
|
+
/**
|
|
333
|
+
* Enable the gasm:math extension for math built-in imports.
|
|
334
|
+
* - false or undefined: Math extension disabled (default)
|
|
335
|
+
* - true or "M2": All math levels enabled (M0, M1, M2)
|
|
336
|
+
* - "M0": Core scalar functions only
|
|
337
|
+
* - "M1": Core + vector functions
|
|
338
|
+
* - "M2": All functions including advanced (modf, frexp, etc.)
|
|
339
|
+
*/
|
|
340
|
+
mathExtension?: boolean | MathLevel;
|
|
341
|
+
/**
|
|
342
|
+
* Enable scalar-to-vector promotion pass.
|
|
343
|
+
* Detects consecutive f32 memory loads/stores to contiguous addresses
|
|
344
|
+
* and collapses them into vec3/vec4 operations.
|
|
345
|
+
* Default: false (opt-in)
|
|
346
|
+
*/
|
|
347
|
+
vectorPromotion?: boolean;
|
|
348
|
+
/**
|
|
349
|
+
* Enable strict Gasm conformance validation.
|
|
350
|
+
* When true, enforces module-level rules:
|
|
351
|
+
* - M001: Exactly one memory required
|
|
352
|
+
* - M006: Only "gasm" module imports allowed
|
|
353
|
+
* - M007: At least one exported () -> () entry point
|
|
354
|
+
* Default: false (lenient — only instruction-level checks)
|
|
355
|
+
*/
|
|
356
|
+
strictConformance?: boolean;
|
|
357
|
+
}
|
|
358
|
+
type DiagnosticSeverity = "warning" | "error";
|
|
359
|
+
interface Diagnostic {
|
|
360
|
+
severity: DiagnosticSeverity;
|
|
361
|
+
code: string;
|
|
362
|
+
message: string;
|
|
363
|
+
functionIndex?: number;
|
|
364
|
+
functionName?: string;
|
|
365
|
+
}
|
|
366
|
+
interface DemotionEvent {
|
|
367
|
+
kind: "f64->f32" | "i64->i32-lossy";
|
|
368
|
+
functionIndex?: number;
|
|
369
|
+
functionName?: string;
|
|
370
|
+
}
|
|
371
|
+
interface FeaturesUsed {
|
|
372
|
+
usesF64: boolean;
|
|
373
|
+
usesI64: boolean;
|
|
374
|
+
usesF64Memory: boolean;
|
|
375
|
+
usesI64Memory: boolean;
|
|
376
|
+
usesSimdF64x2: boolean;
|
|
377
|
+
usesSimdI64x2: boolean;
|
|
378
|
+
usesSimdEmulation: boolean;
|
|
379
|
+
}
|
|
380
|
+
interface CompileDiagnostics {
|
|
381
|
+
warnings: Diagnostic[];
|
|
382
|
+
errors: Diagnostic[];
|
|
383
|
+
demotions: DemotionEvent[];
|
|
384
|
+
featuresUsed: FeaturesUsed;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
declare function compile(wasmBytes: Uint8Array): WasmModule | ReturnType<typeof createCompileError>;
|
|
388
|
+
declare function isCompileError(error: unknown): error is ReturnType<typeof createCompileError>;
|
|
389
|
+
|
|
390
|
+
export { type CompileDiagnostics as C, type DispatchInfo as D, type MathLevel as M, type SourceMappingLevel as S, type VectorDimension as V, type WasmModule as W, type CompileOptions as a, type CompileError as b, compile as c, isCompileError as d, type MathIntrinsicSpec as e, MATH_INTRINSICS as f, isMathIntrinsic as g, getMathSpec as h, isCompileError$1 as i, getWgslMapping as j, getVectorDimension as k, getIntrinsicsAtLevel as l, type SourceLanguage as m, type DebugInfo as n, extractDebugInfo as o, detectSourceLanguage as p, parseNamesSection as q, parseProducersSection as r };
|