Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions examples/large-record-literal.ilo
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-- Large record literals work at any size. Once a record literal would
-- exceed the VM 255-register-per-frame budget for the consecutive-slot
-- layout, the compiler falls back to OP_RECNEW_EMPTY + per-field
-- OP_RECSETFIELD emission. From the persona view, big-record literals
-- with hundreds of fields just work, no chunking via `with` or
-- builder helpers required.

type big{f0:n;f1:n;f2:n;f3:n;f4:n;f5:n;f6:n;f7:n;f8:n;f9:n;f10:n;f11:n;f12:n;f13:n;f14:n;f15:n;f16:n;f17:n;f18:n;f19:n;f20:n;f21:n;f22:n;f23:n;f24:n;f25:n;f26:n;f27:n;f28:n;f29:n;f30:n;f31:n;f32:n;f33:n;f34:n;f35:n;f36:n;f37:n;f38:n;f39:n;f40:n;f41:n;f42:n;f43:n;f44:n;f45:n;f46:n;f47:n;f48:n;f49:n;f50:n;f51:n;f52:n;f53:n;f54:n;f55:n;f56:n;f57:n;f58:n;f59:n;f60:n;f61:n;f62:n;f63:n;f64:n;f65:n;f66:n;f67:n;f68:n;f69:n;f70:n;f71:n;f72:n;f73:n;f74:n;f75:n;f76:n;f77:n;f78:n;f79:n;f80:n;f81:n;f82:n;f83:n;f84:n;f85:n;f86:n;f87:n;f88:n;f89:n;f90:n;f91:n;f92:n;f93:n;f94:n;f95:n;f96:n;f97:n;f98:n;f99:n;f100:n;f101:n;f102:n;f103:n;f104:n;f105:n;f106:n;f107:n;f108:n;f109:n;f110:n;f111:n;f112:n;f113:n;f114:n;f115:n;f116:n;f117:n;f118:n;f119:n;f120:n;f121:n;f122:n;f123:n;f124:n;f125:n;f126:n;f127:n;f128:n;f129:n;f130:n;f131:n;f132:n;f133:n;f134:n;f135:n;f136:n;f137:n;f138:n;f139:n;f140:n;f141:n;f142:n;f143:n;f144:n;f145:n;f146:n;f147:n;f148:n;f149:n}

-- 150-field record literal, big enough to defeat the consecutive-slot
-- fast path. Read one field back at the far end of the record to
-- prove the per-field emission landed in the right slots.
hit-f140>n;r=big f0:0 f1:1 f2:2 f3:3 f4:4 f5:5 f6:6 f7:7 f8:8 f9:9 f10:10 f11:11 f12:12 f13:13 f14:14 f15:15 f16:16 f17:17 f18:18 f19:19 f20:20 f21:21 f22:22 f23:23 f24:24 f25:25 f26:26 f27:27 f28:28 f29:29 f30:30 f31:31 f32:32 f33:33 f34:34 f35:35 f36:36 f37:37 f38:38 f39:39 f40:40 f41:41 f42:42 f43:43 f44:44 f45:45 f46:46 f47:47 f48:48 f49:49 f50:50 f51:51 f52:52 f53:53 f54:54 f55:55 f56:56 f57:57 f58:58 f59:59 f60:60 f61:61 f62:62 f63:63 f64:64 f65:65 f66:66 f67:67 f68:68 f69:69 f70:70 f71:71 f72:72 f73:73 f74:74 f75:75 f76:76 f77:77 f78:78 f79:79 f80:80 f81:81 f82:82 f83:83 f84:84 f85:85 f86:86 f87:87 f88:88 f89:89 f90:90 f91:91 f92:92 f93:93 f94:94 f95:95 f96:96 f97:97 f98:98 f99:99 f100:100 f101:101 f102:102 f103:103 f104:104 f105:105 f106:106 f107:107 f108:108 f109:109 f110:110 f111:111 f112:112 f113:113 f114:114 f115:115 f116:116 f117:117 f118:118 f119:119 f120:120 f121:121 f122:122 f123:123 f124:124 f125:125 f126:126 f127:127 f128:128 f129:129 f130:130 f131:131 f132:132 f133:133 f134:134 f135:135 f136:136 f137:137 f138:138 f139:139 f140:140 f141:141 f142:142 f143:143 f144:144 f145:145 f146:146 f147:147 f148:148 f149:149;r.f140

-- Aggregate across multiple fields to confirm every slot is reachable.
sum-3>n;r=big f0:0 f1:1 f2:2 f3:3 f4:4 f5:5 f6:6 f7:7 f8:8 f9:9 f10:10 f11:11 f12:12 f13:13 f14:14 f15:15 f16:16 f17:17 f18:18 f19:19 f20:20 f21:21 f22:22 f23:23 f24:24 f25:25 f26:26 f27:27 f28:28 f29:29 f30:30 f31:31 f32:32 f33:33 f34:34 f35:35 f36:36 f37:37 f38:38 f39:39 f40:40 f41:41 f42:42 f43:43 f44:44 f45:45 f46:46 f47:47 f48:48 f49:49 f50:50 f51:51 f52:52 f53:53 f54:54 f55:55 f56:56 f57:57 f58:58 f59:59 f60:60 f61:61 f62:62 f63:63 f64:64 f65:65 f66:66 f67:67 f68:68 f69:69 f70:70 f71:71 f72:72 f73:73 f74:74 f75:75 f76:76 f77:77 f78:78 f79:79 f80:80 f81:81 f82:82 f83:83 f84:84 f85:85 f86:86 f87:87 f88:88 f89:89 f90:90 f91:91 f92:92 f93:93 f94:94 f95:95 f96:96 f97:97 f98:98 f99:99 f100:100 f101:101 f102:102 f103:103 f104:104 f105:105 f106:106 f107:107 f108:108 f109:109 f110:110 f111:111 f112:112 f113:113 f114:114 f115:115 f116:116 f117:117 f118:118 f119:119 f120:120 f121:121 f122:122 f123:123 f124:124 f125:125 f126:126 f127:127 f128:128 f129:129 f130:130 f131:131 f132:132 f133:133 f134:134 f135:135 f136:136 f137:137 f138:138 f139:139 f140:140 f141:141 f142:142 f143:143 f144:144 f145:145 f146:146 f147:147 f148:148 f149:149;+r.f0 +r.f75 r.f149

-- run: hit-f140
-- out: 140
-- run: sum-3
-- out: 224
18 changes: 18 additions & 0 deletions examples/large-record-with.ilo
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-- Large `with` updates work at any size. When the consecutive-slot
-- layout used by OP_RECWITH would exceed the 255-reg frame budget,
-- the compiler falls back to OP_RECCOPY + per-update OP_RECSETFIELD
-- emission. Companion to large-record-literal.ilo for the update path.

type big{f0:n;f1:n;f2:n;f3:n;f4:n;f5:n;f6:n;f7:n;f8:n;f9:n;f10:n;f11:n;f12:n;f13:n;f14:n;f15:n;f16:n;f17:n;f18:n;f19:n;f20:n;f21:n;f22:n;f23:n;f24:n;f25:n;f26:n;f27:n;f28:n;f29:n;f30:n;f31:n;f32:n;f33:n;f34:n;f35:n;f36:n;f37:n;f38:n;f39:n;f40:n;f41:n;f42:n;f43:n;f44:n;f45:n;f46:n;f47:n;f48:n;f49:n;f50:n;f51:n;f52:n;f53:n;f54:n;f55:n;f56:n;f57:n;f58:n;f59:n;f60:n;f61:n;f62:n;f63:n;f64:n;f65:n;f66:n;f67:n;f68:n;f69:n;f70:n;f71:n;f72:n;f73:n;f74:n;f75:n;f76:n;f77:n;f78:n;f79:n;f80:n;f81:n;f82:n;f83:n;f84:n;f85:n;f86:n;f87:n;f88:n;f89:n;f90:n;f91:n;f92:n;f93:n;f94:n;f95:n;f96:n;f97:n;f98:n;f99:n;f100:n;f101:n;f102:n;f103:n;f104:n;f105:n;f106:n;f107:n;f108:n;f109:n;f110:n;f111:n;f112:n;f113:n;f114:n;f115:n;f116:n;f117:n;f118:n;f119:n;f120:n;f121:n;f122:n;f123:n;f124:n;f125:n;f126:n;f127:n;f128:n;f129:n;f130:n;f131:n;f132:n;f133:n;f134:n;f135:n;f136:n;f137:n;f138:n;f139:n;f140:n;f141:n;f142:n;f143:n;f144:n;f145:n;f146:n;f147:n;f148:n;f149:n}

-- All-zero record, then with-update every field to its index. Reads
-- f140 back to prove updates landed in the right slots.
upd-f140>n;r=big f0:0 f1:0 f2:0 f3:0 f4:0 f5:0 f6:0 f7:0 f8:0 f9:0 f10:0 f11:0 f12:0 f13:0 f14:0 f15:0 f16:0 f17:0 f18:0 f19:0 f20:0 f21:0 f22:0 f23:0 f24:0 f25:0 f26:0 f27:0 f28:0 f29:0 f30:0 f31:0 f32:0 f33:0 f34:0 f35:0 f36:0 f37:0 f38:0 f39:0 f40:0 f41:0 f42:0 f43:0 f44:0 f45:0 f46:0 f47:0 f48:0 f49:0 f50:0 f51:0 f52:0 f53:0 f54:0 f55:0 f56:0 f57:0 f58:0 f59:0 f60:0 f61:0 f62:0 f63:0 f64:0 f65:0 f66:0 f67:0 f68:0 f69:0 f70:0 f71:0 f72:0 f73:0 f74:0 f75:0 f76:0 f77:0 f78:0 f79:0 f80:0 f81:0 f82:0 f83:0 f84:0 f85:0 f86:0 f87:0 f88:0 f89:0 f90:0 f91:0 f92:0 f93:0 f94:0 f95:0 f96:0 f97:0 f98:0 f99:0 f100:0 f101:0 f102:0 f103:0 f104:0 f105:0 f106:0 f107:0 f108:0 f109:0 f110:0 f111:0 f112:0 f113:0 f114:0 f115:0 f116:0 f117:0 f118:0 f119:0 f120:0 f121:0 f122:0 f123:0 f124:0 f125:0 f126:0 f127:0 f128:0 f129:0 f130:0 f131:0 f132:0 f133:0 f134:0 f135:0 f136:0 f137:0 f138:0 f139:0 f140:0 f141:0 f142:0 f143:0 f144:0 f145:0 f146:0 f147:0 f148:0 f149:0;q=r with f0:0 f1:1 f2:2 f3:3 f4:4 f5:5 f6:6 f7:7 f8:8 f9:9 f10:10 f11:11 f12:12 f13:13 f14:14 f15:15 f16:16 f17:17 f18:18 f19:19 f20:20 f21:21 f22:22 f23:23 f24:24 f25:25 f26:26 f27:27 f28:28 f29:29 f30:30 f31:31 f32:32 f33:33 f34:34 f35:35 f36:36 f37:37 f38:38 f39:39 f40:40 f41:41 f42:42 f43:43 f44:44 f45:45 f46:46 f47:47 f48:48 f49:49 f50:50 f51:51 f52:52 f53:53 f54:54 f55:55 f56:56 f57:57 f58:58 f59:59 f60:60 f61:61 f62:62 f63:63 f64:64 f65:65 f66:66 f67:67 f68:68 f69:69 f70:70 f71:71 f72:72 f73:73 f74:74 f75:75 f76:76 f77:77 f78:78 f79:79 f80:80 f81:81 f82:82 f83:83 f84:84 f85:85 f86:86 f87:87 f88:88 f89:89 f90:90 f91:91 f92:92 f93:93 f94:94 f95:95 f96:96 f97:97 f98:98 f99:99 f100:100 f101:101 f102:102 f103:103 f104:104 f105:105 f106:106 f107:107 f108:108 f109:109 f110:110 f111:111 f112:112 f113:113 f114:114 f115:115 f116:116 f117:117 f118:118 f119:119 f120:120 f121:121 f122:122 f123:123 f124:124 f125:125 f126:126 f127:127 f128:128 f129:129 f130:130 f131:131 f132:132 f133:133 f134:134 f135:135 f136:136 f137:137 f138:138 f139:139 f140:140 f141:141 f142:142 f143:143 f144:144 f145:145 f146:146 f147:147 f148:148 f149:149;q.f140

-- Confirm the original is untouched after the with-update.
orig-untouched>n;r=big f0:0 f1:0 f2:0 f3:0 f4:0 f5:0 f6:0 f7:0 f8:0 f9:0 f10:0 f11:0 f12:0 f13:0 f14:0 f15:0 f16:0 f17:0 f18:0 f19:0 f20:0 f21:0 f22:0 f23:0 f24:0 f25:0 f26:0 f27:0 f28:0 f29:0 f30:0 f31:0 f32:0 f33:0 f34:0 f35:0 f36:0 f37:0 f38:0 f39:0 f40:0 f41:0 f42:0 f43:0 f44:0 f45:0 f46:0 f47:0 f48:0 f49:0 f50:0 f51:0 f52:0 f53:0 f54:0 f55:0 f56:0 f57:0 f58:0 f59:0 f60:0 f61:0 f62:0 f63:0 f64:0 f65:0 f66:0 f67:0 f68:0 f69:0 f70:0 f71:0 f72:0 f73:0 f74:0 f75:0 f76:0 f77:0 f78:0 f79:0 f80:0 f81:0 f82:0 f83:0 f84:0 f85:0 f86:0 f87:0 f88:0 f89:0 f90:0 f91:0 f92:0 f93:0 f94:0 f95:0 f96:0 f97:0 f98:0 f99:0 f100:0 f101:0 f102:0 f103:0 f104:0 f105:0 f106:0 f107:0 f108:0 f109:0 f110:0 f111:0 f112:0 f113:0 f114:0 f115:0 f116:0 f117:0 f118:0 f119:0 f120:0 f121:0 f122:0 f123:0 f124:0 f125:0 f126:0 f127:0 f128:0 f129:0 f130:0 f131:0 f132:0 f133:0 f134:0 f135:0 f136:0 f137:0 f138:0 f139:0 f140:0 f141:0 f142:0 f143:0 f144:0 f145:0 f146:0 f147:0 f148:0 f149:0;q=r with f0:0 f1:1 f2:2 f3:3 f4:4 f5:5 f6:6 f7:7 f8:8 f9:9 f10:10 f11:11 f12:12 f13:13 f14:14 f15:15 f16:16 f17:17 f18:18 f19:19 f20:20 f21:21 f22:22 f23:23 f24:24 f25:25 f26:26 f27:27 f28:28 f29:29 f30:30 f31:31 f32:32 f33:33 f34:34 f35:35 f36:36 f37:37 f38:38 f39:39 f40:40 f41:41 f42:42 f43:43 f44:44 f45:45 f46:46 f47:47 f48:48 f49:49 f50:50 f51:51 f52:52 f53:53 f54:54 f55:55 f56:56 f57:57 f58:58 f59:59 f60:60 f61:61 f62:62 f63:63 f64:64 f65:65 f66:66 f67:67 f68:68 f69:69 f70:70 f71:71 f72:72 f73:73 f74:74 f75:75 f76:76 f77:77 f78:78 f79:79 f80:80 f81:81 f82:82 f83:83 f84:84 f85:85 f86:86 f87:87 f88:88 f89:89 f90:90 f91:91 f92:92 f93:93 f94:94 f95:95 f96:96 f97:97 f98:98 f99:99 f100:100 f101:101 f102:102 f103:103 f104:104 f105:105 f106:106 f107:107 f108:108 f109:109 f110:110 f111:111 f112:112 f113:113 f114:114 f115:115 f116:116 f117:117 f118:118 f119:119 f120:120 f121:121 f122:122 f123:123 f124:124 f125:125 f126:126 f127:127 f128:128 f129:129 f130:130 f131:131 f132:132 f133:133 f134:134 f135:135 f136:136 f137:137 f138:138 f139:139 f140:140 f141:141 f142:142 f143:143 f144:144 f145:145 f146:146 f147:147 f148:148 f149:149;r.f140

-- run: upd-f140
-- out: 140
-- run: orig-untouched
-- out: 0
68 changes: 61 additions & 7 deletions src/vm/compile_cranelift.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ struct HelperFuncs {
recfld: FuncId,
recfld_name: FuncId,
recnew: FuncId,
recnew_empty: FuncId,
reccopy: FuncId,
recsetfield: FuncId,
recwith: FuncId,
listnew: FuncId,
listget: FuncId,
Expand Down Expand Up @@ -279,6 +282,9 @@ fn declare_all_helpers(module: &mut ObjectModule) -> HelperFuncs {
recfld: declare_helper(module, "jit_recfld", 2, 1),
recfld_name: declare_helper(module, "jit_recfld_name", 3, 1),
recnew: declare_helper(module, "jit_recnew", 4, 1),
recnew_empty: declare_helper(module, "jit_recnew_empty", 3, 1),
reccopy: declare_helper(module, "jit_reccopy", 3, 1),
recsetfield: declare_helper(module, "jit_recsetfield", 3, 0),
recwith: declare_helper(module, "jit_recwith", 4, 1),
listnew: declare_helper(module, "jit_listnew", 2, 1),
listget: declare_helper(module, "jit_listget", 2, 1),
Expand Down Expand Up @@ -1016,13 +1022,13 @@ fn compile_function_body(
| OP_SRT | OP_SRTDESC | OP_SLC | OP_TAKE | OP_DROP | OP_SPL | OP_CAT | OP_GET
| OP_POST | OP_GETH | OP_POSTH | OP_GETMANY | OP_ENV | OP_JPTH | OP_JDMP
| OP_JPAR | OP_RDJL | OP_MAPNEW | OP_MGET | OP_MSET | OP_MDEL | OP_MKEYS
| OP_MVALS | OP_LISTNEW | OP_LISTAPPEND | OP_RECNEW | OP_RECWITH | OP_PRT
| OP_RD | OP_RDL | OP_WR | OP_WRL | OP_TRM | OP_UPR | OP_LWR | OP_CAP | OP_PADL
| OP_PADR | OP_CHR | OP_CHARS | OP_UNQ | OP_UNIQBY | OP_PARTITION | OP_FRQ
| OP_NUM | OP_RGXSUB | OP_ZIP | OP_ENUMERATE | OP_RANGE | OP_WINDOW | OP_CHUNKS
| OP_CUMSUM | OP_SETUNION | OP_SETINTER | OP_SETDIFF | OP_FFT | OP_IFFT
| OP_TRANSPOSE | OP_MATMUL | OP_INV | OP_SOLVE | OP_DTFMT | OP_DTPARSE
| OP_CALL_BUILTIN_TREE => {
| OP_MVALS | OP_LISTNEW | OP_LISTAPPEND | OP_RECNEW | OP_RECWITH
| OP_RECNEW_EMPTY | OP_RECCOPY | OP_PRT | OP_RD | OP_RDL | OP_WR | OP_WRL
| OP_TRM | OP_UPR | OP_LWR | OP_CAP | OP_PADL | OP_PADR | OP_CHR | OP_CHARS
| OP_UNQ | OP_UNIQBY | OP_PARTITION | OP_FRQ | OP_NUM | OP_RGXSUB | OP_ZIP
| OP_ENUMERATE | OP_RANGE | OP_WINDOW | OP_CHUNKS | OP_CUMSUM | OP_SETUNION
| OP_SETINTER | OP_SETDIFF | OP_FFT | OP_IFFT | OP_TRANSPOSE | OP_MATMUL
| OP_INV | OP_SOLVE | OP_DTFMT | OP_DTPARSE | OP_CALL_BUILTIN_TREE => {
non_num_write[a] = true;
non_bool_write[a] = true;
}
Expand Down Expand Up @@ -2620,6 +2626,54 @@ fn compile_function_body(
let result = builder.inst_results(call_inst)[0];
builder.def_var(vars[a_idx], result);
}
// ── Record creation (oversized-literal fallback) ──
OP_RECNEW_EMPTY => {
// Companion to OP_RECNEW for the fallback path the compiler
// emits when the consecutive-register layout would exceed
// the 255-reg frame ceiling. Cold path → simple helper call.
let type_id = (inst & 0xFFFF) as i64;
let fref_arena = get_func_ref(&mut builder, module, helpers.get_arena_ptr);
let arena_call = builder.ins().call(fref_arena, &[]);
let arena_ptr_val = builder.inst_results(arena_call)[0];
let fref_reg = get_func_ref(&mut builder, module, helpers.get_registry_ptr);
let reg_call = builder.ins().call(fref_reg, &[]);
let registry_ptr_val = builder.inst_results(reg_call)[0];
let type_id_val = builder.ins().iconst(I64, type_id);
let fref = get_func_ref(&mut builder, module, helpers.recnew_empty);
let call_inst = builder
.ins()
.call(fref, &[arena_ptr_val, type_id_val, registry_ptr_val]);
let result = builder.inst_results(call_inst)[0];
builder.def_var(vars[a_idx], result);
}
// ── Record copy (oversized-with fallback) ──
OP_RECCOPY => {
let b_idx = ((inst >> 8) & 0xFF) as usize;
let src = builder.use_var(vars[b_idx]);
let fref_arena = get_func_ref(&mut builder, module, helpers.get_arena_ptr);
let arena_call = builder.ins().call(fref_arena, &[]);
let arena_ptr_val = builder.inst_results(arena_call)[0];
let fref_reg = get_func_ref(&mut builder, module, helpers.get_registry_ptr);
let reg_call = builder.ins().call(fref_reg, &[]);
let registry_ptr_val = builder.inst_results(reg_call)[0];
let fref = get_func_ref(&mut builder, module, helpers.reccopy);
let call_inst = builder
.ins()
.call(fref, &[src, arena_ptr_val, registry_ptr_val]);
let result = builder.inst_results(call_inst)[0];
builder.def_var(vars[a_idx], result);
}
// ── Record set-field (in-place mutate, freshly-allocated only) ──
OP_RECSETFIELD => {
let b_idx = ((inst >> 8) & 0xFF) as usize;
let c = (inst & 0xFF) as i64;
let rec_val = builder.use_var(vars[a_idx]);
let val_val = builder.use_var(vars[b_idx]);
let idx_val = builder.ins().iconst(I64, c);
let fref = get_func_ref(&mut builder, module, helpers.recsetfield);
builder.ins().call(fref, &[rec_val, val_val, idx_val]);
// No result — R[A] still points to the same (now-mutated) record.
}
// ── List creation ──
OP_LISTNEW => {
let n = (inst & 0xFFFF) as usize;
Expand Down
Loading
Loading