Skip to content

Commit 095385e

Browse files
authored
feat(compiler)!: Stack-allocated Chars (#1103)
1 parent 2d43b28 commit 095385e

File tree

150 files changed

+550
-945
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

150 files changed

+550
-945
lines changed

compiler/src/codegen/compcore.re

Lines changed: 25 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1679,59 +1679,11 @@ let allocate_bytes_uninitialized = (wasm_mod, env, size) => {
16791679
);
16801680
};
16811681

1682-
let allocate_char = (wasm_mod, env, char) => {
1683-
// Copy bytes into a fresh buffer so we can guarantee a copy of a full word
1684-
let bytes = Bytes.make(4, Char.chr(0));
1685-
// OCaml String#length is byte length, not Unicode character length
1686-
// Guaranteed not to be longer than 4 bytes by well-formedness
1687-
Bytes.blit_string(char, 0, bytes, 0, String.length(char));
1688-
let value = Bytes.get_int32_le(bytes, 0);
1689-
1690-
let get_swap = () => get_swap(wasm_mod, env, 0);
1691-
let tee_swap = tee_swap(wasm_mod, env, 0);
1692-
Expression.Block.make(
1693-
wasm_mod,
1694-
gensym_label("allocate_char"),
1695-
[
1696-
store(
1697-
~offset=0,
1698-
wasm_mod,
1699-
tee_swap(heap_allocate(wasm_mod, env, 2)),
1700-
Expression.Const.make(
1701-
wasm_mod,
1702-
const_int32(tag_val_of_heap_tag_type(CharType)),
1703-
),
1704-
),
1705-
store(
1706-
~offset=4,
1707-
wasm_mod,
1708-
get_swap(),
1709-
Expression.Const.make(wasm_mod, wrap_int32(value)),
1710-
),
1711-
get_swap(),
1712-
],
1713-
);
1714-
};
1715-
1716-
let allocate_char_uninitialized = (wasm_mod, env) => {
1717-
let get_swap = () => get_swap(wasm_mod, env, 0);
1718-
let tee_swap = tee_swap(wasm_mod, env, 0);
1719-
Expression.Block.make(
1720-
wasm_mod,
1721-
gensym_label("allocate_char_uninitialized"),
1722-
[
1723-
store(
1724-
~offset=0,
1725-
wasm_mod,
1726-
tee_swap(heap_allocate(wasm_mod, env, 2)),
1727-
Expression.Const.make(
1728-
wasm_mod,
1729-
const_int32(tag_val_of_heap_tag_type(CharType)),
1730-
),
1731-
),
1732-
get_swap(),
1733-
],
1734-
);
1682+
let create_char = (wasm_mod, env, char) => {
1683+
let uchar = List.hd @@ Utf8.decodeUtf8String(char);
1684+
let uchar_int: int = Utf8__Uchar.toInt(uchar);
1685+
let grain_char = uchar_int lsl 3 lor 0b010;
1686+
Expression.Const.make(wasm_mod, const_int32(grain_char));
17351687
};
17361688

17371689
let allocate_closure =
@@ -2261,7 +2213,6 @@ let allocate_rational = (wasm_mod, env, n, d) => {
22612213

22622214
let compile_prim0 = (wasm_mod, env, p0): Expression.t => {
22632215
switch (p0) {
2264-
| AllocateChar => allocate_char_uninitialized(wasm_mod, env)
22652216
| AllocateInt32 => allocate_number_uninitialized(wasm_mod, env, BoxedInt32)
22662217
| AllocateInt64 => allocate_number_uninitialized(wasm_mod, env, BoxedInt64)
22672218
| AllocateFloat32 =>
@@ -2307,6 +2258,25 @@ let compile_prim1 = (wasm_mod, env, p1, arg, loc): Expression.t => {
23072258
compiled_arg,
23082259
Expression.Const.make(wasm_mod, const_int32(0x1)),
23092260
)
2261+
| TagChar =>
2262+
Expression.Binary.make(
2263+
wasm_mod,
2264+
Op.xor_int32,
2265+
Expression.Binary.make(
2266+
wasm_mod,
2267+
Op.shl_int32,
2268+
compiled_arg,
2269+
Expression.Const.make(wasm_mod, const_int32(0x3)),
2270+
),
2271+
Expression.Const.make(wasm_mod, const_int32(0b10)),
2272+
)
2273+
| UntagChar =>
2274+
Expression.Binary.make(
2275+
wasm_mod,
2276+
Op.shr_s_int32,
2277+
compiled_arg,
2278+
Expression.Const.make(wasm_mod, const_int32(0x3)),
2279+
)
23102280
| Not =>
23112281
/* Flip the first bit */
23122282
Expression.Binary.make(
@@ -2691,7 +2661,7 @@ let compile_allocation = (wasm_mod, env, alloc_type) =>
26912661
| MRecord(ttag, elts) => allocate_record(wasm_mod, env, ttag, elts)
26922662
| MBytes(bytes) => allocate_bytes(wasm_mod, env, bytes)
26932663
| MString(str) => allocate_string(wasm_mod, env, str)
2694-
| MChar(char) => allocate_char(wasm_mod, env, char)
2664+
| MChar(char) => create_char(wasm_mod, env, char)
26952665
| MADT(ttag, vtag, elts) => allocate_adt(wasm_mod, env, ttag, vtag, elts)
26962666
| MInt32(i) =>
26972667
allocate_int32(

compiler/src/codegen/mashtree.re

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ type wasm_op =
172172

173173
type prim0 =
174174
Parsetree.prim0 =
175-
| AllocateChar
176175
| AllocateInt32
177176
| AllocateInt64
178177
| AllocateFloat32
@@ -194,6 +193,8 @@ type prim1 =
194193
| BytesSize
195194
| TagSimpleNumber
196195
| UntagSimpleNumber
196+
| TagChar
197+
| UntagChar
197198
| Not
198199
| Box
199200
| Unbox

compiler/src/codegen/value_tags.re

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ open Sexplib.Conv;
44
[@deriving sexp]
55
type heap_tag_type =
66
| StringType
7-
| CharType
87
| ADTType
98
| RecordType
109
| ArrayType
@@ -16,26 +15,24 @@ type heap_tag_type =
1615
let tag_val_of_heap_tag_type =
1716
fun
1817
| StringType => 1
19-
| CharType => 2
20-
| ADTType => 3
21-
| RecordType => 4
22-
| ArrayType => 5
23-
| BoxedNumberType => 6
24-
| LambdaType => 7
25-
| TupleType => 8
26-
| BytesType => 9;
18+
| ADTType => 2
19+
| RecordType => 3
20+
| ArrayType => 4
21+
| BoxedNumberType => 5
22+
| LambdaType => 6
23+
| TupleType => 7
24+
| BytesType => 8;
2725

2826
let heap_tag_type_of_tag_val =
2927
fun
3028
| 1 => StringType
31-
| 2 => CharType
32-
| 3 => ADTType
33-
| 4 => RecordType
34-
| 5 => ArrayType
35-
| 6 => BoxedNumberType
36-
| 7 => LambdaType
37-
| 8 => TupleType
38-
| 9 => BytesType
29+
| 2 => ADTType
30+
| 3 => RecordType
31+
| 4 => ArrayType
32+
| 5 => BoxedNumberType
33+
| 6 => LambdaType
34+
| 7 => TupleType
35+
| 8 => BytesType
3936
| x => failwith(Printf.sprintf("Unknown tag type: %d", x));
4037

4138
[@deriving sexp]
@@ -67,18 +64,5 @@ let boxed_number_tag_type_of_tag_val =
6764
type tag_type =
6865
| NumberTagType
6966
| ConstTagType
67+
| CharTagType
7068
| GenericHeapType(option(heap_tag_type));
71-
72-
let and_mask_of_tag_type =
73-
fun
74-
| NumberTagType => 0b0001
75-
| ConstTagType => 0b0111
76-
| GenericHeapType(_) => 0b0111;
77-
78-
let tag_val_of_tag_type =
79-
fun
80-
| NumberTagType => 0b0001
81-
| ConstTagType => 0b0110
82-
| GenericHeapType(_) => 0b0000;
83-
84-
let shift_amount_of_tag_type = tt => 31 - tag_val_of_tag_type(tt);

compiler/src/middle_end/analyze_purity.re

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@ let rec analyze_comp_expression =
4444
| CImmExpr({imm_desc: ImmTrap}) => false
4545
| CImmExpr(_) => true
4646
| CPrim0(
47-
AllocateChar | AllocateInt32 | AllocateInt64 | AllocateFloat32 |
48-
AllocateFloat64 |
47+
AllocateInt32 | AllocateInt64 | AllocateFloat32 | AllocateFloat64 |
4948
AllocateRational,
5049
) =>
5150
true
@@ -60,6 +59,8 @@ let rec analyze_comp_expression =
6059
BytesSize |
6160
TagSimpleNumber |
6261
UntagSimpleNumber |
62+
TagChar |
63+
UntagChar |
6364
Not |
6465
Box |
6566
Unbox |

compiler/src/middle_end/anftree.re

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@ type wasm_op =
158158

159159
type prim0 =
160160
Parsetree.prim0 =
161-
| AllocateChar
162161
| AllocateInt32
163162
| AllocateInt64
164163
| AllocateFloat32
@@ -180,6 +179,8 @@ type prim1 =
180179
| BytesSize
181180
| TagSimpleNumber
182181
| UntagSimpleNumber
182+
| TagChar
183+
| UntagChar
183184
| Not
184185
| Box
185186
| Unbox

compiler/src/middle_end/anftree.rei

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ type wasm_op =
159159

160160
type prim0 =
161161
Parsetree.prim0 =
162-
| AllocateChar
163162
| AllocateInt32
164163
| AllocateInt64
165164
| AllocateFloat32
@@ -181,6 +180,8 @@ type prim1 =
181180
| BytesSize
182181
| TagSimpleNumber
183182
| UntagSimpleNumber
183+
| TagChar
184+
| UntagChar
184185
| Not
185186
| Box
186187
| Unbox

compiler/src/parsing/parsetree.re

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,6 @@ type wasm_op =
303303
/** Zero-argument operators */
304304
[@deriving (sexp, yojson)]
305305
type prim0 =
306-
| AllocateChar
307306
| AllocateInt32
308307
| AllocateInt64
309308
| AllocateFloat32
@@ -326,6 +325,8 @@ type prim1 =
326325
| BytesSize
327326
| TagSimpleNumber
328327
| UntagSimpleNumber
328+
| TagChar
329+
| UntagChar
329330
| Not
330331
| Box
331332
| Unbox

compiler/src/typed/builtin_types.re

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ let initial_env = (add_type, empty_env) =>
174174
|> add_type(ident_bool, decl_bool)
175175
|> add_type(ident_box, decl_box)
176176
|> add_type(ident_string, decl_abstr(path_string))
177-
|> add_type(ident_char, decl_abstr(path_char))
177+
|> add_type(ident_char, decl_abstr_imm(WasmI32, path_char))
178178
|> add_type(ident_void, decl_void)
179179
|> add_type(ident_array, decl_array)
180180
|> add_type(ident_fd, decl_abstr(path_fd))

compiler/src/typed/translprim.re

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ let prim_map =
4444
("@heap.base", PrimitiveConstant(HeapBase)),
4545
("@heap.start", PrimitiveConstant(HeapStart)),
4646
("@heap.type_metadata", PrimitiveConstant(HeapTypeMetadata)),
47-
("@allocate.char", Primitive0(AllocateChar)),
4847
("@allocate.int32", Primitive0(AllocateInt32)),
4948
("@allocate.int64", Primitive0(AllocateInt64)),
5049
("@allocate.float32", Primitive0(AllocateFloat32)),
@@ -63,6 +62,8 @@ let prim_map =
6362
("@bytes.size", Primitive1(BytesSize)),
6463
("@tag.simple_number", Primitive1(TagSimpleNumber)),
6564
("@untag.simple_number", Primitive1(UntagSimpleNumber)),
65+
("@tag.char", Primitive1(TagChar)),
66+
("@untag.char", Primitive1(UntagChar)),
6667
("@not", Primitive1(Not)),
6768
("@box", Primitive1(Box)),
6869
("@unbox", Primitive1(Unbox)),
@@ -1499,8 +1500,7 @@ let transl_prim = (env, desc) => {
14991500
(Exp.constant(~loc, ~attributes=disable_gc, value), attrs);
15001501
| Primitive0(
15011502
(
1502-
AllocateChar | AllocateInt32 | AllocateInt64 | AllocateFloat32 |
1503-
AllocateFloat64 |
1503+
AllocateInt32 | AllocateInt64 | AllocateFloat32 | AllocateFloat64 |
15041504
AllocateRational
15051505
) as p,
15061506
) => (

compiler/src/typed/typecore.re

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ let grain_type_of_wasm_prim_type =
100100

101101
let prim0_type =
102102
fun
103-
| AllocateChar
104103
| AllocateInt32
105104
| AllocateInt64
106105
| AllocateFloat32
@@ -125,6 +124,8 @@ let prim1_type =
125124
Builtin_types.type_number,
126125
Builtin_types.type_wasmi32,
127126
)
127+
| TagChar => (Builtin_types.type_wasmi32, Builtin_types.type_char)
128+
| UntagChar => (Builtin_types.type_char, Builtin_types.type_wasmi32)
128129
| Not => (Builtin_types.type_bool, Builtin_types.type_bool)
129130
| Box
130131
| BoxBind => {

0 commit comments

Comments
 (0)