Skip to content

Commit 8870f99

Browse files
minokiclaude
andcommitted
Add BACKEND_WASM and enable CpsBoxing pass for WasmGC target
Add wasm_output datatype (WASM_BINARY/WASM_TEXT) and BACKEND_WASM constructor to the backend type. Define WasmGC TargetInfo (I32/W32/ STRING8/32-bit). Add --wasm and --wasm-wat CLI flags. Enable CpsBoxing pass conditionally for BACKEND_WASM and disable CPS type checks after boxing. Update all backend pattern matches for exhaustiveness (nested.sml, main.sml emit/exportAsRecord/pathMap). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 2f7f751 commit 8870f99

File tree

3 files changed

+54
-16
lines changed

3 files changed

+54
-16
lines changed

src/backend.sml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,20 @@ structure Backend:
66
sig
77
datatype lua_runtime = LUA_PLAIN | LUA_CONTINUATIONS
88
datatype code_style = DIRECT_STYLE | CPS
9+
datatype wasm_output = WASM_BINARY | WASM_TEXT
910
datatype backend =
1011
BACKEND_LUA of lua_runtime
1112
| BACKEND_LUAJIT
1213
| BACKEND_JS of {style: code_style, os: string, default_ext: string}
14+
| BACKEND_WASM of {output: wasm_output}
1315
end =
1416
struct
1517
(*
1618
* Our possible TARGET_OS:
1719
* * lua
1820
* * node
1921
* * web
22+
* * wasm
2023
*
2124
* MLton's TARGET_OS:
2225
* * aix
@@ -36,8 +39,10 @@ struct
3639
LUA_PLAIN
3740
| LUA_CONTINUATIONS
3841
datatype code_style = DIRECT_STYLE | CPS
42+
datatype wasm_output = WASM_BINARY | WASM_TEXT
3943
datatype backend =
4044
BACKEND_LUA of lua_runtime
4145
| BACKEND_LUAJIT
4246
| BACKEND_JS of {style: code_style, os: string, default_ext: string}
47+
| BACKEND_WASM of {output: wasm_output}
4348
end;

src/main.sml

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ struct
4040
\ --nodejs-cps Produce JavaScript code for Node.js (CPS mode).\n\
4141
\ --webjs Produce JavaScript code for Web.\n\
4242
\ --webjs-cps Produce JavaScript code for Web (CPS mode).\n\
43+
\ --wasm Produce WebAssembly binary (.wasm).\n\
44+
\ --wasm-wat Produce WebAssembly text format (.wat).\n\
4345
\ -h,--help Show this message.\n\
4446
\ -v,--version Show version information.\n\
4547
\ --dump Dump intermediate code.\n\
@@ -94,6 +96,14 @@ struct
9496
, minInt = SOME TargetInfo.minInt54
9597
, maxInt = SOME TargetInfo.maxInt54
9698
, wordSize = 32
99+
}
100+
| BACKEND_WASM _ =>
101+
{ defaultInt = Primitives.I32
102+
, defaultWord = Primitives.W32
103+
, datatypeTag = TargetInfo.STRING8
104+
, minInt = SOME TargetInfo.minInt32
105+
, maxInt = SOME TargetInfo.maxInt32
106+
, wordSize = 32
97107
})
98108
fun optimizeCps
99109
(_: {nextTyVar: int ref, nextVId: int ref, printTimings: bool}) _ cexp 0 =
@@ -361,6 +371,8 @@ struct
361371
in
362372
()
363373
end
374+
| emit ({backend = BACKEND_WASM _, ...}: options) _ _ _ _ _ _ =
375+
raise Fail "Wasm code generation is not yet implemented"
364376
structure CheckFInit =
365377
struct
366378
fun toFTy (TypedSyntax.TyVar (_, tv)) = FSyntax.TyVar tv
@@ -456,12 +468,14 @@ struct
456468
| BACKEND_LUAJIT => "luajit"
457469
| BACKEND_JS {style = Backend.DIRECT_STYLE, ...} => "js"
458470
| BACKEND_JS {style = Backend.CPS, ...} => "js-cps"
471+
| BACKEND_WASM _ => "wasm"
459472
)
460473
, ( "TARGET_OS"
461474
, case #backend opts of
462475
BACKEND_LUA _ => "lua"
463476
| BACKEND_LUAJIT => "lua"
464477
| BACKEND_JS {os, ...} => os
478+
| BACKEND_WASM _ => "wasm"
465479
)
466480
, ( "DELIMITED_CONTINUATIONS"
467481
, case #backend opts of
@@ -718,6 +732,7 @@ struct
718732
| BACKEND_LUAJIT => true
719733
| BACKEND_JS {style = Backend.DIRECT_STYLE, ...} => false
720734
| BACKEND_JS {style = Backend.CPS, ...} => true
735+
| BACKEND_WASM _ => true
721736
val fexp =
722737
case targetInfo of
723738
{defaultInt = Primitives.INT, defaultWord = Primitives.WORD, ...} =>
@@ -878,34 +893,40 @@ struct
878893
CpsErasePoly.transform (context, cexp)
879894
end
880895
val () = checkCpsAfterErasure ("after erasePoly", cexp)
881-
(* Boxing pass: only for WasmGC backend (not yet implemented).
882-
When enabled, disable CPS type checks after boxing since the checker
883-
doesn't fully support BoxedType boundaries.
884896
val cexp =
885-
let
886-
val context =
887-
{ nextTyVar = nextTyVar
888-
, nextVId = nextId
889-
, simplificationOccurred = ref false
890-
}
891-
in
892-
CpsBoxing.transform (context, cexp)
893-
end
894-
*)
897+
case #backend opts of
898+
BACKEND_WASM _ =>
899+
let
900+
val context =
901+
{ nextTyVar = nextTyVar
902+
, nextVId = nextId
903+
, simplificationOccurred = ref false
904+
}
905+
in
906+
CpsBoxing.transform (context, cexp)
907+
end
908+
| _ => cexp
909+
(* After boxing, disable CPS type checks since the checker
910+
doesn't fully support BoxedType boundaries. *)
911+
val checkCpsAfterBoxing =
912+
case #backend opts of
913+
BACKEND_WASM _ => (fn _ => ())
914+
| _ => checkCpsAfterErasure
915+
val () = checkCpsAfterBoxing ("after boxing", cexp)
895916
val cexp =
896917
optimizeCps
897918
{ nextTyVar = nextTyVar
898919
, nextVId = nextId
899920
, printTimings = #printTimings opts
900-
} checkCpsAfterErasure cexp (3 * (#optimizationLevel opts + 3))
901-
val () = checkCpsAfterErasure ("optimization #3", cexp)
921+
} checkCpsAfterBoxing cexp (3 * (#optimizationLevel opts + 3))
922+
val () = checkCpsAfterBoxing ("optimization #3", cexp)
902923
val ctx' =
903924
{ nextTyVar = nextTyVar
904925
, nextVId = nextId
905926
, simplificationOccurred = ref false
906927
}
907928
val cexp = CpsDeadCodeElimination.goStat (ctx', true, cexp)
908-
val () = checkCpsAfterErasure ("after final DCE", cexp)
929+
val () = checkCpsAfterBoxing ("after final DCE", cexp)
909930
val optTime = Time.toMicroseconds (#usr (Timer.checkCPUTimer timer))
910931
val () =
911932
if #printTimings opts then
@@ -1024,6 +1045,8 @@ struct
10241045
| OPT_TARGET_NODEJS_CPS (* --nodejs-cps *)
10251046
| OPT_TARGET_WEBJS (* --webjs *)
10261047
| OPT_TARGET_WEBJS_CPS (* --webjs-cps *)
1048+
| OPT_TARGET_WASM (* --wasm *)
1049+
| OPT_TARGET_WASM_WAT (* --wasm-wat *)
10271050
| OPT_HELP (* -h,--help *)
10281051
| OPT_VERSION (* -v,--version *)
10291052
| OPT_STOP (* -- *)
@@ -1048,6 +1071,8 @@ struct
10481071
, (LONG "--nodejs-cps", SIMPLE OPT_TARGET_NODEJS_CPS)
10491072
, (LONG "--webjs", SIMPLE OPT_TARGET_WEBJS)
10501073
, (LONG "--webjs-cps", SIMPLE OPT_TARGET_WEBJS_CPS)
1074+
, (LONG "--wasm", SIMPLE OPT_TARGET_WASM)
1075+
, (LONG "--wasm-wat", SIMPLE OPT_TARGET_WASM_WAT)
10511076
, (SHORT "-h", SIMPLE OPT_HELP)
10521077
, (LONG "--help", SIMPLE OPT_HELP)
10531078
, (SHORT "-v", SIMPLE OPT_VERSION)
@@ -1117,6 +1142,13 @@ struct
11171142
(S.set.backend
11181143
(BACKEND_JS {style = Backend.CPS, os = "web", default_ext = ".js"})
11191144
opts) args
1145+
| SOME (OPT_TARGET_WASM, args) =>
1146+
parseArgs
1147+
(S.set.backend (BACKEND_WASM {output = Backend.WASM_BINARY}) opts)
1148+
args
1149+
| SOME (OPT_TARGET_WASM_WAT, args) =>
1150+
parseArgs
1151+
(S.set.backend (BACKEND_WASM {output = Backend.WASM_TEXT}) opts) args
11201152
| SOME (OPT_HELP, _) => (showHelp (); OS.Process.exit OS.Process.success)
11211153
| SOME (OPT_VERSION, _) =>
11221154
(showVersion (); OS.Process.exit OS.Process.success)

src/nested.sml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ struct
386386
Backend.BACKEND_LUA _ => canInlineLua
387387
| Backend.BACKEND_LUAJIT => canInlineLua
388388
| Backend.BACKEND_JS _ => canInlineJs
389+
| Backend.BACKEND_WASM _ => canInlineJs
389390
fun goExp (e as Value _) = e
390391
| goExp (PrimOp {primOp, tyargs, args}) =
391392
PrimOp

0 commit comments

Comments
 (0)