@scriptc/compiler 0.2.2 → 0.2.4

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.
Files changed (243) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +99 -27
  2. package/dist/backend/cycle-analysis.js +63 -50
  3. package/dist/backend/cycle-analysis.js.map +1 -1
  4. package/dist/backend/cycle-analysis.test.js +51 -0
  5. package/dist/backend/cycle-analysis.test.js.map +1 -1
  6. package/dist/backend/llvm/borrowed-inputs.d.ts +15 -0
  7. package/dist/backend/llvm/borrowed-inputs.js +28 -0
  8. package/dist/backend/llvm/borrowed-inputs.js.map +1 -0
  9. package/dist/backend/llvm/borrowed-receivers.d.ts +9 -0
  10. package/dist/backend/llvm/borrowed-receivers.js +58 -0
  11. package/dist/backend/llvm/borrowed-receivers.js.map +1 -0
  12. package/dist/backend/llvm/byte-numbers.d.ts +10 -0
  13. package/dist/backend/llvm/byte-numbers.js +235 -0
  14. package/dist/backend/llvm/byte-numbers.js.map +1 -0
  15. package/dist/backend/llvm/bytes-bounds.d.ts +9 -0
  16. package/dist/backend/llvm/bytes-bounds.js +189 -0
  17. package/dist/backend/llvm/bytes-bounds.js.map +1 -0
  18. package/dist/backend/llvm/call-lifetimes.d.ts +27 -0
  19. package/dist/backend/llvm/call-lifetimes.js +199 -0
  20. package/dist/backend/llvm/call-lifetimes.js.map +1 -0
  21. package/dist/backend/llvm/call-lifetimes.test.d.ts +1 -0
  22. package/dist/backend/llvm/call-lifetimes.test.js +259 -0
  23. package/dist/backend/llvm/call-lifetimes.test.js.map +1 -0
  24. package/dist/backend/llvm/checked-value-lifetimes.d.ts +9 -0
  25. package/dist/backend/llvm/checked-value-lifetimes.js +35 -0
  26. package/dist/backend/llvm/checked-value-lifetimes.js.map +1 -0
  27. package/dist/backend/llvm/counted-loops.d.ts +6 -0
  28. package/dist/backend/llvm/counted-loops.js +28 -0
  29. package/dist/backend/llvm/counted-loops.js.map +1 -0
  30. package/dist/backend/llvm/dyn.d.ts +2 -2
  31. package/dist/backend/llvm/dyn.js +79 -35
  32. package/dist/backend/llvm/dyn.js.map +1 -1
  33. package/dist/backend/llvm/emitter.d.ts +56 -7
  34. package/dist/backend/llvm/emitter.js +310 -37
  35. package/dist/backend/llvm/emitter.js.map +1 -1
  36. package/dist/backend/llvm/emitter.test.js +24 -5
  37. package/dist/backend/llvm/emitter.test.js.map +1 -1
  38. package/dist/backend/llvm/expr-async.js +4 -3
  39. package/dist/backend/llvm/expr-async.js.map +1 -1
  40. package/dist/backend/llvm/expr-bytes.d.ts +4 -4
  41. package/dist/backend/llvm/expr-bytes.js +68 -35
  42. package/dist/backend/llvm/expr-bytes.js.map +1 -1
  43. package/dist/backend/llvm/expr-calls.js +50 -5
  44. package/dist/backend/llvm/expr-calls.js.map +1 -1
  45. package/dist/backend/llvm/expr-containers.d.ts +2 -1
  46. package/dist/backend/llvm/expr-containers.js +136 -57
  47. package/dist/backend/llvm/expr-containers.js.map +1 -1
  48. package/dist/backend/llvm/expr-context.d.ts +11 -0
  49. package/dist/backend/llvm/expr-control.js +26 -5
  50. package/dist/backend/llvm/expr-control.js.map +1 -1
  51. package/dist/backend/llvm/expr-dynamic.js +33 -31
  52. package/dist/backend/llvm/expr-dynamic.js.map +1 -1
  53. package/dist/backend/llvm/expr-primitives.js +61 -27
  54. package/dist/backend/llvm/expr-primitives.js.map +1 -1
  55. package/dist/backend/llvm/expr-records.js +9 -3
  56. package/dist/backend/llvm/expr-records.js.map +1 -1
  57. package/dist/backend/llvm/expr-stream-bridges.js +5 -10
  58. package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
  59. package/dist/backend/llvm/integer-values.d.ts +10 -0
  60. package/dist/backend/llvm/integer-values.js +41 -0
  61. package/dist/backend/llvm/integer-values.js.map +1 -0
  62. package/dist/backend/llvm/integer-views.d.ts +7 -0
  63. package/dist/backend/llvm/integer-views.js +67 -0
  64. package/dist/backend/llvm/integer-views.js.map +1 -0
  65. package/dist/backend/llvm/integer-views.test.d.ts +1 -0
  66. package/dist/backend/llvm/integer-views.test.js +34 -0
  67. package/dist/backend/llvm/integer-views.test.js.map +1 -0
  68. package/dist/backend/llvm/lib-dispatch.js +3 -1
  69. package/dist/backend/llvm/lib-dispatch.js.map +1 -1
  70. package/dist/backend/llvm/lib-filesystem.js +5 -5
  71. package/dist/backend/llvm/lib-filesystem.js.map +1 -1
  72. package/dist/backend/llvm/lib-shared.js +35 -1
  73. package/dist/backend/llvm/lib-shared.js.map +1 -1
  74. package/dist/backend/llvm/local-array-reads.d.ts +42 -0
  75. package/dist/backend/llvm/local-array-reads.js +226 -0
  76. package/dist/backend/llvm/local-array-reads.js.map +1 -0
  77. package/dist/backend/llvm/local-array-reads.test.d.ts +1 -0
  78. package/dist/backend/llvm/local-array-reads.test.js +446 -0
  79. package/dist/backend/llvm/local-array-reads.test.js.map +1 -0
  80. package/dist/backend/llvm/map-read-lifetimes.d.ts +36 -0
  81. package/dist/backend/llvm/map-read-lifetimes.js +128 -0
  82. package/dist/backend/llvm/map-read-lifetimes.js.map +1 -0
  83. package/dist/backend/llvm/map-read-lifetimes.test.d.ts +1 -0
  84. package/dist/backend/llvm/map-read-lifetimes.test.js +127 -0
  85. package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -0
  86. package/dist/backend/llvm/reference-effects.d.ts +22 -0
  87. package/dist/backend/llvm/reference-effects.js +148 -0
  88. package/dist/backend/llvm/reference-effects.js.map +1 -0
  89. package/dist/backend/llvm/reference-effects.test.d.ts +1 -0
  90. package/dist/backend/llvm/reference-effects.test.js +74 -0
  91. package/dist/backend/llvm/reference-effects.test.js.map +1 -0
  92. package/dist/backend/llvm/shapes.d.ts +7 -4
  93. package/dist/backend/llvm/shapes.js +24 -6
  94. package/dist/backend/llvm/shapes.js.map +1 -1
  95. package/dist/backend/llvm/split.js +15 -5
  96. package/dist/backend/llvm/split.js.map +1 -1
  97. package/dist/backend/llvm/split.test.js +17 -0
  98. package/dist/backend/llvm/split.test.js.map +1 -1
  99. package/dist/backend/llvm/stack-unions.d.ts +20 -0
  100. package/dist/backend/llvm/stack-unions.js +61 -0
  101. package/dist/backend/llvm/stack-unions.js.map +1 -0
  102. package/dist/backend/llvm/stack-unions.test.d.ts +1 -0
  103. package/dist/backend/llvm/stack-unions.test.js +262 -0
  104. package/dist/backend/llvm/stack-unions.test.js.map +1 -0
  105. package/dist/backend/llvm/string-construction.d.ts +10 -0
  106. package/dist/backend/llvm/string-construction.js +38 -0
  107. package/dist/backend/llvm/string-construction.js.map +1 -0
  108. package/dist/backend/llvm/string-construction.test.d.ts +1 -0
  109. package/dist/backend/llvm/string-construction.test.js +65 -0
  110. package/dist/backend/llvm/string-construction.test.js.map +1 -0
  111. package/dist/backend/llvm/string-lifetimes.d.ts +12 -0
  112. package/dist/backend/llvm/string-lifetimes.js +72 -0
  113. package/dist/backend/llvm/string-lifetimes.js.map +1 -0
  114. package/dist/backend/llvm/string-lifetimes.test.d.ts +1 -0
  115. package/dist/backend/llvm/string-lifetimes.test.js +239 -0
  116. package/dist/backend/llvm/string-lifetimes.test.js.map +1 -0
  117. package/dist/backend/mangle.d.ts +2 -0
  118. package/dist/backend/mangle.js +4 -0
  119. package/dist/backend/mangle.js.map +1 -1
  120. package/dist/backend/may-throw.js +67 -29
  121. package/dist/backend/may-throw.js.map +1 -1
  122. package/dist/backend/may-throw.test.js +104 -1
  123. package/dist/backend/may-throw.test.js.map +1 -1
  124. package/dist/backend/native-toolchain.d.ts +2 -2
  125. package/dist/backend/native-toolchain.js +2 -0
  126. package/dist/backend/native-toolchain.js.map +1 -1
  127. package/dist/frontend/input-tracker.js +3 -3
  128. package/dist/frontend/input-tracker.js.map +1 -1
  129. package/dist/frontend/input-tracker.test.js +38 -2
  130. package/dist/frontend/input-tracker.test.js.map +1 -1
  131. package/dist/frontend/lowering/collection-ingestion.d.ts +31 -0
  132. package/dist/frontend/lowering/collection-ingestion.js +224 -0
  133. package/dist/frontend/lowering/collection-ingestion.js.map +1 -0
  134. package/dist/frontend/lowering/containers/bytes.js +2 -0
  135. package/dist/frontend/lowering/containers/bytes.js.map +1 -1
  136. package/dist/frontend/lowering/containers/string-and-regexp.js +6 -0
  137. package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
  138. package/dist/frontend/lowering/import-meta.d.ts +10 -0
  139. package/dist/frontend/lowering/import-meta.js +52 -0
  140. package/dist/frontend/lowering/import-meta.js.map +1 -0
  141. package/dist/frontend/lowering/lower-assert.js +105 -41
  142. package/dist/frontend/lowering/lower-assert.js.map +1 -1
  143. package/dist/frontend/lowering/lower-builtin-values.d.ts +2 -0
  144. package/dist/frontend/lowering/lower-builtin-values.js +22 -1
  145. package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
  146. package/dist/frontend/lowering/lower-builtins.d.ts +3 -13
  147. package/dist/frontend/lowering/lower-builtins.js +152 -46
  148. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  149. package/dist/frontend/lowering/lower-calls.js +6 -3
  150. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  151. package/dist/frontend/lowering/lower-classes.js +7 -7
  152. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  153. package/dist/frontend/lowering/lower-containers.d.ts +5 -1
  154. package/dist/frontend/lowering/lower-containers.js +52 -37
  155. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  156. package/dist/frontend/lowering/lower-exprs.js +47 -43
  157. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  158. package/dist/frontend/lowering/lower-inspect.js +43 -0
  159. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  160. package/dist/frontend/lowering/lower-stmts.js +72 -68
  161. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  162. package/dist/frontend/lowering/lower-system-errors.d.ts +6 -0
  163. package/dist/frontend/lowering/lower-system-errors.js +29 -0
  164. package/dist/frontend/lowering/lower-system-errors.js.map +1 -0
  165. package/dist/frontend/lowering/lowerer.d.ts +4 -3
  166. package/dist/frontend/lowering/lowerer.js +60 -25
  167. package/dist/frontend/lowering/lowerer.js.map +1 -1
  168. package/dist/frontend/lowering/surfaces.d.ts +2 -2
  169. package/dist/frontend/lowering/surfaces.js +69 -21
  170. package/dist/frontend/lowering/surfaces.js.map +1 -1
  171. package/dist/frontend/module-syntax.d.ts +1 -1
  172. package/dist/frontend/module-syntax.js +8 -1
  173. package/dist/frontend/module-syntax.js.map +1 -1
  174. package/dist/frontend/module-syntax.test.js +10 -0
  175. package/dist/frontend/module-syntax.test.js.map +1 -1
  176. package/dist/frontend/npm.d.ts +4 -0
  177. package/dist/frontend/npm.js +86 -33
  178. package/dist/frontend/npm.js.map +1 -1
  179. package/dist/frontend/npm.test.js +103 -0
  180. package/dist/frontend/npm.test.js.map +1 -1
  181. package/dist/frontend/pipeline-native.js +2 -1
  182. package/dist/frontend/pipeline-native.js.map +1 -1
  183. package/dist/frontend/services-node.js +3 -2
  184. package/dist/frontend/services-node.js.map +1 -1
  185. package/dist/frontend/services.d.ts +5 -1
  186. package/dist/frontend/services.js +9 -1
  187. package/dist/frontend/services.js.map +1 -1
  188. package/dist/frontend/services.test.js +21 -0
  189. package/dist/frontend/services.test.js.map +1 -1
  190. package/dist/frontend/ts7/ast-node.d.ts +2 -0
  191. package/dist/frontend/ts7/ast-node.js +30 -4
  192. package/dist/frontend/ts7/ast-node.js.map +1 -1
  193. package/dist/frontend/ts7/ast-node.test.js +60 -1
  194. package/dist/frontend/ts7/ast-node.test.js.map +1 -1
  195. package/dist/frontend/type-mapper.js +8 -2
  196. package/dist/frontend/type-mapper.js.map +1 -1
  197. package/dist/index.js +3 -2
  198. package/dist/index.js.map +1 -1
  199. package/dist/ir/analysis.js +4 -1
  200. package/dist/ir/analysis.js.map +1 -1
  201. package/dist/ir/byte-numbers.d.ts +20 -0
  202. package/dist/ir/byte-numbers.js +65 -0
  203. package/dist/ir/byte-numbers.js.map +1 -0
  204. package/dist/ir/byte-numbers.test.d.ts +1 -0
  205. package/dist/ir/byte-numbers.test.js +42 -0
  206. package/dist/ir/byte-numbers.test.js.map +1 -0
  207. package/dist/ir/integer-loops.d.ts +26 -0
  208. package/dist/ir/integer-loops.js +130 -1
  209. package/dist/ir/integer-loops.js.map +1 -1
  210. package/dist/ir/integer-loops.test.d.ts +1 -0
  211. package/dist/ir/integer-loops.test.js +91 -0
  212. package/dist/ir/integer-loops.test.js.map +1 -0
  213. package/dist/ir/integer-ranges.d.ts +8 -6
  214. package/dist/ir/integer-ranges.js +343 -89
  215. package/dist/ir/integer-ranges.js.map +1 -1
  216. package/dist/ir/integer-ranges.test.js +54 -3
  217. package/dist/ir/integer-ranges.test.js.map +1 -1
  218. package/dist/ir/ir.d.ts +29 -22
  219. package/dist/ir/ir.js +59 -14
  220. package/dist/ir/ir.js.map +1 -1
  221. package/dist/ir/ir.test.js +18 -0
  222. package/dist/ir/ir.test.js.map +1 -1
  223. package/dist/ir/validate.js +208 -105
  224. package/dist/ir/validate.js.map +1 -1
  225. package/dist/ir/validate.test.js +247 -0
  226. package/dist/ir/validate.test.js.map +1 -1
  227. package/dist/library/fence-eval.js +9 -2
  228. package/dist/library/fence-eval.js.map +1 -1
  229. package/dist/library/fence-eval.test.d.ts +1 -0
  230. package/dist/library/fence-eval.test.js +21 -0
  231. package/dist/library/fence-eval.test.js.map +1 -0
  232. package/dist/native/runtime-typescript.d.ts +4 -0
  233. package/dist/native/runtime-typescript.js +61 -0
  234. package/dist/native/runtime-typescript.js.map +1 -0
  235. package/dist/native/runtime-typescript.test.d.ts +1 -0
  236. package/dist/native/runtime-typescript.test.js +41 -0
  237. package/dist/native/runtime-typescript.test.js.map +1 -0
  238. package/dist/native/toolchain.js +6 -3
  239. package/dist/native/toolchain.js.map +1 -1
  240. package/dist/native/toolchain.test.js +43 -5
  241. package/dist/native/toolchain.test.js.map +1 -1
  242. package/package.json +20 -20
  243. package/surface-manifest.json +271 -17
@@ -0,0 +1,262 @@
1
+ import { expect, test } from "vitest";
2
+ import { BOOL, F64, STRING, VOID, UNDEFINED_T, NULL_T, funcOf } from "../../ir/ir.js";
3
+ import { validateModule } from "../../ir/validate.js";
4
+ import { emitLlvmModule } from "./emitter.js";
5
+ import { canStackUnion } from "./stack-unions.js";
6
+ const loc = { file: "stack-unions.ts", start: 0, end: 0 };
7
+ const record = { kind: "record", shapeId: "cell" };
8
+ const optional = { kind: "union", unionId: "optional" };
9
+ const ref = (localId, type = optional) => ({ kind: "varRef", localId, type, loc });
10
+ const num = (value = 1) => ({ kind: "numLit", value, type: F64, loc });
11
+ const ret = (value) => ({ kind: "return", value, loc });
12
+ const call = (callee, args, type = F64) => ({ kind: "call", callee, args, type, loc });
13
+ const wrap = (value, tag = 0) => ({ kind: "unionWrap", value, tag, unionId: "optional", type: optional, loc });
14
+ const narrow = (value, type) => ({ kind: "unionNarrow", value, unionId: "optional", tag: 0, type, loc });
15
+ const effect = (expr) => ({ kind: "exprStmt", expr, loc });
16
+ const fresh = () => ({ kind: "recordLit", fields: [{ name: "x", value: num(7) }], type: record, loc });
17
+ function fixture(arm = record) {
18
+ const reader = {
19
+ name: "read", params: [{ localId: "value", name: "value", type: optional }], returnType: arm, loc,
20
+ locals: [{ id: "value", name: "value", type: optional, mutable: true }],
21
+ body: [ret(narrow(ref("value"), arm))],
22
+ };
23
+ return {
24
+ irVersion: 13, sourceFile: loc.file, entry: "main",
25
+ records: [{ id: "cell", fields: [{ name: "x", type: F64 }] }],
26
+ unions: [{ id: "optional", arms: [arm, UNDEFINED_T, NULL_T] }],
27
+ functions: [{ name: "main", params: [], returnType: VOID, locals: [], body: [], loc }, reader],
28
+ };
29
+ }
30
+ function body(ir, name) {
31
+ const found = new RegExp(`^define internal [^\\n]*@${name}\\([^]*?^}`, "m").exec(ir);
32
+ expect(found, name).not.toBeNull();
33
+ return found[0];
34
+ }
35
+ function emit(mod, pointerBits = 64) {
36
+ expect(validateModule(mod)).toEqual([]);
37
+ return emitLlvmModule(mod, { pointerBits });
38
+ }
39
+ function declareLocal(mod, init) {
40
+ const fn = mod.functions[0];
41
+ fn.locals.push({ id: "item", name: "item", type: optional, mutable: false });
42
+ fn.body.push({ kind: "varDecl", localId: "item", init, loc });
43
+ }
44
+ test("reference arguments use a private box and keep an independent payload owner", () => {
45
+ const mod = fixture();
46
+ mod.functions[0].body.push(effect(call("read", [wrap(fresh())], record)));
47
+ for (const width of [32, 64]) {
48
+ const ir = emit(mod, width), main = body(ir, "sc_f_main");
49
+ expect(main).toContain("alloca %ScrUnion");
50
+ expect(main).toContain("@sc_bf_read(");
51
+ expect(main).not.toContain("@scr_union_new_ref");
52
+ expect(main).not.toContain("@scr_union_release");
53
+ expect(main).toContain("@sc_rrelease_");
54
+ const reader = body(ir, "sc_bf_read");
55
+ expect(reader).not.toContain("@scr_union_release");
56
+ expect(reader).toContain("@sc_rretain_");
57
+ }
58
+ });
59
+ test("owned adapters release borrowed parameters while preserving returned payloads", () => {
60
+ const mod = fixture();
61
+ const ir = emit(mod);
62
+ const adapter = body(ir, "sc_f_read");
63
+ expect(adapter).toContain("%result = call ptr @sc_bf_read(ptr %p0)");
64
+ expect(adapter).toContain("call void @scr_union_release(ptr %p0)");
65
+ expect(adapter).toContain("ret ptr %result");
66
+ expect(adapter.indexOf("@sc_bf_read")).toBeLessThan(adapter.indexOf("@scr_union_release"));
67
+ });
68
+ test("plain function values retain the owned ABI", () => {
69
+ const mod = fixture();
70
+ mod.functions[0].body.push(effect({ kind: "closure", fnName: "read", captures: [], type: funcOf([optional], record), loc }));
71
+ const ir = emit(mod);
72
+ const wrapper = body(ir, "sc_w_read");
73
+ expect(wrapper).toContain("@sc_f_read(");
74
+ expect(wrapper).not.toContain("@sc_bf_read(");
75
+ });
76
+ test("local construction releases its payload at lexical exit without freeing the stack box", () => {
77
+ const mod = fixture();
78
+ declareLocal(mod, wrap(fresh()));
79
+ mod.functions[0].body.push(effect(call("read", [ref("item")], record)));
80
+ const main = body(emit(mod), "sc_f_main");
81
+ expect(main).toContain("alloca %ScrUnion");
82
+ expect(main).not.toMatch(/@scr_union_(?:new|retain|release)/);
83
+ expect(main).toContain("@sc_rrelease_");
84
+ });
85
+ test.each(["return", "alias", "capture", "store", "mutable"])("keeps a %s consumer on the ordinary heap path", (reason) => {
86
+ const mod = fixture();
87
+ const work = { name: "work", params: [], locals: [], body: [], returnType: VOID, loc };
88
+ mod.functions.unshift(work);
89
+ declareLocal(mod, wrap(fresh()));
90
+ if (reason === "return") {
91
+ work.returnType = optional;
92
+ work.body.push(ret(ref("item")));
93
+ }
94
+ if (reason === "alias") {
95
+ work.locals.push({ id: "alias", name: "alias", type: optional, mutable: false });
96
+ work.body.push({ kind: "varDecl", localId: "alias", init: ref("item"), loc });
97
+ }
98
+ if (reason === "capture") {
99
+ work.locals[0].boxed = true;
100
+ mod.functions.push({ name: "lifted", captures: [{ localId: "item", name: "item", type: optional }], params: [],
101
+ locals: [{ id: "item", name: "item", type: optional, mutable: false, boxed: true }], body: [ret(ref("item"))], returnType: optional, loc });
102
+ work.body.push(effect({ kind: "closure", fnName: "lifted", captures: ["item"], type: funcOf([], optional), loc }));
103
+ }
104
+ if (reason === "store") {
105
+ mod.globals = [{ id: "%g.saved", name: "saved", type: optional, mutable: true }];
106
+ work.body.push({ kind: "assign", localId: "%g.saved", value: ref("item"), loc });
107
+ }
108
+ if (reason === "mutable")
109
+ work.locals[0].mutable = true;
110
+ expect(body(emit(mod), "sc_f_work")).toContain("@scr_union_new_ref");
111
+ });
112
+ test("forwarded parameters never retain or release a borrowed stack box", () => {
113
+ const mod = fixture();
114
+ const outer = {
115
+ name: "outer", params: [{ localId: "value", name: "value", type: optional }],
116
+ locals: [{ id: "value", name: "value", type: optional, mutable: true }],
117
+ body: [ret(call("read", [ref("value")], record))], returnType: record, loc,
118
+ };
119
+ mod.functions.push(outer);
120
+ const ir = emit(mod), forwarded = body(ir, "sc_bf_outer");
121
+ expect(forwarded).toContain("@sc_bf_read(");
122
+ expect(forwarded).not.toMatch(/@scr_union_(?:retain|release)/);
123
+ expect(body(ir, "sc_f_outer")).toContain("@scr_union_release");
124
+ });
125
+ test("mixed signatures transfer owned arguments and retain only borrowed snapshots", () => {
126
+ const mod = fixture();
127
+ const fn = mod.functions[1];
128
+ fn.params.push({ localId: "saved", name: "saved", type: optional });
129
+ fn.locals.push({ id: "saved", name: "saved", type: optional, mutable: true });
130
+ fn.returnType = optional;
131
+ fn.body = [effect(narrow(ref("value"), record)),
132
+ { kind: "assign", localId: "saved", value: wrap(fresh()), loc }, ret(ref("saved"))];
133
+ mod.functions[0].body.push(effect(call("read", [wrap(fresh()), wrap(fresh())], optional)));
134
+ const ir = emit(mod), main = body(ir, "sc_f_main"), adapter = body(ir, "sc_f_read");
135
+ expect(main.match(/call ptr @scr_union_new_ref/g)).toHaveLength(1);
136
+ expect(main).toContain("alloca %ScrUnion");
137
+ expect(adapter).toContain("@scr_union_release(ptr %p0)");
138
+ expect(adapter).not.toContain("@scr_union_release(ptr %p1)");
139
+ expect(body(ir, "sc_bf_read")).toContain("@scr_union_release");
140
+ });
141
+ test("a shared argument expression gets a stack box only at a projection-only position", () => {
142
+ const mod = fixture(), fn = mod.functions[1];
143
+ fn.params.push({ localId: "saved", name: "saved", type: optional });
144
+ fn.locals.push({ id: "saved", name: "saved", type: optional, mutable: true });
145
+ fn.returnType = optional;
146
+ fn.body = [effect(narrow(ref("value"), record)), ret(ref("saved"))];
147
+ const argument = wrap(fresh());
148
+ mod.functions[0].body.push(effect(call("read", [argument, argument], optional)));
149
+ const ir = emit(mod), main = body(ir, "sc_f_main");
150
+ expect(main.match(/call ptr @scr_union_new_ref/g)).toHaveLength(1);
151
+ expect(main.match(/alloca %ScrUnion/g)).toHaveLength(1);
152
+ expect(body(ir, "sc_bf_read")).toContain("@scr_union_retain_v");
153
+ expect(body(ir, "sc_bf_read")).not.toContain("@scr_union_release");
154
+ expect(body(ir, "sc_f_read")).toContain("@scr_union_release(ptr %p1)");
155
+ });
156
+ test("mutable caller bindings take owned snapshots before later arguments", () => {
157
+ const mod = fixture();
158
+ declareLocal(mod, wrap(fresh()));
159
+ mod.functions[0].locals[0].mutable = true;
160
+ const fn = mod.functions[1];
161
+ fn.params.push({ localId: "count", name: "count", type: F64 });
162
+ fn.locals.push({ id: "count", name: "count", type: F64, mutable: true });
163
+ const second = { kind: "seqExpr", type: F64, loc,
164
+ stmts: [{ kind: "assign", localId: "item", value: wrap(fresh()), loc }], result: num() };
165
+ mod.functions[0].body.push(effect(call("read", [ref("item"), second], record)));
166
+ const main = body(emit(mod), "sc_f_main");
167
+ expect(main).toContain("@scr_union_retain_v");
168
+ expect(main.indexOf("@scr_union_retain_v")).toBeLessThan(main.indexOf("@sc_bf_read"));
169
+ expect(main.lastIndexOf("@scr_union_release")).toBeGreaterThan(main.indexOf("@sc_bf_read"));
170
+ });
171
+ test("globals borrow across preserving calls and snapshot across mutations", () => {
172
+ const mod = fixture();
173
+ mod.globals = [{ id: "%g.item", name: "item", type: optional, mutable: false }];
174
+ mod.functions[0].body.push(effect(call("read", [ref("%g.item")], record)));
175
+ expect(body(emit(mod), "sc_f_main")).not.toContain("@scr_union_retain_v");
176
+ mod.globals[0].mutable = true;
177
+ mod.functions[1].body.unshift({ kind: "assign", localId: "%g.item", value: wrap(fresh()), loc });
178
+ const main = body(emit(mod), "sc_f_main");
179
+ expect(main).toContain("@scr_union_retain_v");
180
+ expect(main).toContain("@scr_union_release");
181
+ });
182
+ test("scalar payloads initialize their complete ABI slot on both pointer widths", () => {
183
+ for (const value of [num(-0), { kind: "boolLit", value: true, type: BOOL, loc }]) {
184
+ const mod = fixture(value.type);
185
+ mod.functions[0].body.push(effect(call("read", [wrap(value)], value.type)));
186
+ for (const width of [32, 64]) {
187
+ const main = body(emit(mod, width), "sc_f_main");
188
+ expect(main).toContain("alloca %ScrUnion");
189
+ expect(main).not.toMatch(/@scr_union_new_(?:bool|f64)/);
190
+ expect(main).toContain(value.type.kind === "bool" ? "store i64" : "store double");
191
+ }
192
+ }
193
+ });
194
+ test("unit arms initialize tags and slots without acquiring payload ownership", () => {
195
+ for (const [unit, type, tag] of [["undefined", UNDEFINED_T, 1], ["null", NULL_T, 2]]) {
196
+ const mod = fixture();
197
+ mod.functions[1].returnType = BOOL;
198
+ mod.functions[1].body = [ret({ kind: "unionIsTag", value: ref("value"), unionId: "optional", tag, negated: false, type: BOOL, loc })];
199
+ mod.functions[0].body.push(effect(call("read", [wrap({ kind: "unitLit", unit, type, loc }, tag)], BOOL)));
200
+ const main = body(emit(mod), "sc_f_main");
201
+ expect(main).toContain("store i64 0");
202
+ expect(main).toContain(`store i32 ${tag}`);
203
+ expect(main).not.toMatch(/@scr_union_(?:new|retain|release)/);
204
+ }
205
+ });
206
+ test("checked payload errors retain caller cleanup and owned adapter cleanup", () => {
207
+ const mod = fixture();
208
+ const reader = mod.functions[1];
209
+ reader.body.unshift(effect({ kind: "libCall", fn: "error.nodeThrow", type: record, loc, args: [num(),
210
+ { kind: "strLit", value: "", type: STRING, loc }, { kind: "strLit", value: "failure", type: STRING, loc }] }));
211
+ mod.functions[0].body.push(effect(call("read", [wrap(fresh())], record)));
212
+ const ir = emit(mod), main = body(ir, "sc_f_main");
213
+ expect(main).toContain("@scr_exc_pending");
214
+ expect(main).toMatch(/exc\.u\d+:\n\s+call void @sc_rrelease_/);
215
+ expect(main).toContain("@sc_rrelease_");
216
+ expect(body(ir, "sc_bf_read")).not.toContain("@scr_union_release");
217
+ expect(body(ir, "sc_f_read")).toContain("@scr_union_release");
218
+ });
219
+ test("representation matching rejects absent, mismatched and effectful unit arms", () => {
220
+ const mod = fixture();
221
+ const unions = new Map(mod.unions.map((union) => [union.id, union]));
222
+ expect(canStackUnion(wrap(fresh()), unions)).toBe(true);
223
+ expect(canStackUnion(wrap(num()), unions)).toBe(false);
224
+ expect(canStackUnion(wrap(fresh(), 9), unions)).toBe(false);
225
+ expect(canStackUnion(ref("value"), unions)).toBe(false);
226
+ expect(canStackUnion(wrap(fresh()), new Map())).toBe(false);
227
+ const effectful = { kind: "seqExpr", stmts: [effect(num())],
228
+ result: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: UNDEFINED_T, loc };
229
+ expect(canStackUnion(wrap(effectful, 1), unions)).toBe(false);
230
+ });
231
+ test("adjacent throwing calls release argument snapshots before the next call", () => {
232
+ const mod = fixture();
233
+ const reader = mod.functions[1];
234
+ reader.returnType = F64;
235
+ reader.body = [ret({ kind: "recordGet", obj: narrow(ref("value"), record), shapeId: "cell", field: "x", type: F64, loc })];
236
+ reader.body.unshift(effect({ kind: "libCall", fn: "error.nodeThrow", type: record, loc, args: [num(),
237
+ { kind: "strLit", value: "", type: STRING, loc }, { kind: "strLit", value: "failure", type: STRING, loc }] }));
238
+ mod.globals = [{ id: "%g.item", name: "item", type: optional, mutable: true }];
239
+ reader.body.unshift({ kind: "assign", localId: "%g.item", value: wrap(fresh()), loc });
240
+ const calls = Array.from({ length: 80 }, () => call("read", [ref("%g.item")], F64));
241
+ mod.functions[0].body = [effect({ kind: "arrayLit", elems: calls, type: { kind: "array", elem: F64 }, loc })];
242
+ const main = body(emit(mod), "sc_f_main");
243
+ expect(main.match(/call ptr @scr_union_retain_v/g)).toHaveLength(calls.length);
244
+ // Each snapshot has one normal release and one exceptional release.
245
+ // Earlier calls must not add owners to every later exception edge.
246
+ expect(main.match(/call void @scr_union_release/g)).toHaveLength(calls.length * 2);
247
+ const first = main.indexOf("@sc_bf_read"), second = main.indexOf("@sc_bf_read", first + 1);
248
+ expect(main.slice(first, second)).toContain("@scr_union_release");
249
+ });
250
+ test("a borrowed call returns a new owner before releasing argument snapshots", () => {
251
+ const mod = fixture();
252
+ mod.functions[1].body.unshift({ kind: "assign", localId: "%g.item", value: wrap(fresh()), loc });
253
+ mod.globals = [{ id: "%g.item", name: "item", type: optional, mutable: true }];
254
+ mod.functions[0].body.push(effect(call("read", [ref("%g.item")], record)));
255
+ const main = body(emit(mod), "sc_f_main");
256
+ const callAt = main.indexOf("@sc_bf_read"), unionReleaseAt = main.indexOf("@scr_union_release");
257
+ const payloadReleaseAt = main.indexOf("@sc_rrelease_");
258
+ expect(callAt).toBeLessThan(unionReleaseAt);
259
+ expect(unionReleaseAt).toBeLessThan(payloadReleaseAt);
260
+ expect(main.match(/call void @sc_rrelease_/g)).toHaveLength(1);
261
+ });
262
+ //# sourceMappingURL=stack-unions.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stack-unions.test.js","sourceRoot":"","sources":["../../../src/backend/llvm/stack-unions.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { IrExpr } from "../../ir/ir.js";
2
+ import type { LlValue, LlvmEmitterContext } from "./expr-context.js";
3
+ /** Flatten only string concatenation, preserving conversion and operand
4
+ * order. Larger trees remain operands of bounded groups, so each call uses
5
+ * at most sixteen stack slots and does not need a heap argument array. */
6
+ export declare function stringParts(value: IrExpr): IrExpr[];
7
+ /** The runtime borrows every part without mutating it. Earlier operands
8
+ * therefore borrow only when their owners survive all later evaluations;
9
+ * other operands retain ordinary snapshots and exception cleanup. */
10
+ export declare function emitStringParts(host: LlvmEmitterContext, parts: readonly IrExpr[]): LlValue;
@@ -0,0 +1,38 @@
1
+ import { emitStringInputs } from "./string-lifetimes.js";
2
+ const MAX_PARTS = 16;
3
+ /** Flatten only string concatenation, preserving conversion and operand
4
+ * order. Larger trees remain operands of bounded groups, so each call uses
5
+ * at most sixteen stack slots and does not need a heap argument array. */
6
+ export function stringParts(value) {
7
+ const pending = [value];
8
+ const parts = [];
9
+ while (pending.length > 0) {
10
+ const part = pending.pop();
11
+ if (part.kind === "strConcat" && parts.length + pending.length < MAX_PARTS - 1) {
12
+ pending.push(part.right, part.left);
13
+ }
14
+ else {
15
+ parts.push(part);
16
+ }
17
+ }
18
+ return parts;
19
+ }
20
+ /** The runtime borrows every part without mutating it. Earlier operands
21
+ * therefore borrow only when their owners survive all later evaluations;
22
+ * other operands retain ordinary snapshots and exception cleanup. */
23
+ export function emitStringParts(host, parts) {
24
+ const values = emitStringInputs(host, parts);
25
+ const B = host.B;
26
+ const storage = B.slot();
27
+ B.entryAllocas.push(`${storage} = alloca [${parts.length} x ptr]`);
28
+ for (let i = 0; i < values.length; i++) {
29
+ const slot = B.tmp();
30
+ B.line(`${slot} = getelementptr [${parts.length} x ptr], ptr ${storage}, i32 0, i32 ${i}`);
31
+ B.line(`store ptr ${values[i].name}, ptr ${slot}`);
32
+ }
33
+ host.declare(`declare ptr @scr_str_concat_parts(ptr, ${host.sizeType})`);
34
+ const result = B.tmp();
35
+ B.line(`${result} = call ptr @scr_str_concat_parts(ptr ${storage}, ${host.sizeType} ${parts.length})`);
36
+ return host.own({ name: result, type: parts[0].type });
37
+ }
38
+ //# sourceMappingURL=string-construction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string-construction.js","sourceRoot":"","sources":["../../../src/backend/llvm/string-construction.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB;;0EAE0E;AAC1E,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;IACxB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAG,CAAC;QAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,GAAG,CAAC,EAAE,CAAC;YAC/E,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;qEAEqE;AACrE,MAAM,UAAU,eAAe,CAAC,IAAwB,EAAE,KAAwB;IAChF,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;IACjB,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,OAAO,cAAc,KAAK,CAAC,MAAM,SAAS,CAAC,CAAC;IACnE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QACrB,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,qBAAqB,KAAK,CAAC,MAAM,gBAAgB,OAAO,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAC3F,CAAC,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,CAAC,CAAE,CAAC,IAAI,SAAS,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,0CAA0C,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;IACvB,CAAC,CAAC,IAAI,CAAC,GAAG,MAAM,yCAAyC,OAAO,KAAK,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IACvG,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC,CAAC;AAC1D,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,65 @@
1
+ import { expect, test } from "vitest";
2
+ import { STRING, VOID } from "../../ir/ir.js";
3
+ import { validateModule } from "../../ir/validate.js";
4
+ import { emitLlvmModule } from "./emitter.js";
5
+ import { stringParts } from "./string-construction.js";
6
+ const loc = { file: "construction.ts", start: 0, end: 1 };
7
+ const text = (value) => ({ kind: "strLit", value, type: STRING, loc });
8
+ const ref = (localId) => ({ kind: "varRef", localId, type: STRING, loc });
9
+ const concat = (left, right) => ({ kind: "strConcat", left, right, type: STRING, loc });
10
+ function module(value) {
11
+ return { irVersion: 13, sourceFile: loc.file, entry: "main", functions: [
12
+ { name: "main", loc, params: [], locals: [], returnType: VOID, body: [] },
13
+ { name: "assemble", loc, params: [{ name: "value", localId: "value", type: STRING }],
14
+ locals: [{ id: "value", name: "value", type: STRING, mutable: true }],
15
+ returnType: STRING, body: [{ kind: "return", value, loc }] },
16
+ ] };
17
+ }
18
+ test("concat grouping bounds each stack vector and preserves leaf order", () => {
19
+ const leaves = Array.from({ length: 100 }, (_, i) => text(String(i)));
20
+ for (const tree of [leaves.reduce(concat), leaves.reduceRight((right, left) => concat(left, right))]) {
21
+ const seen = [];
22
+ const walk = (value) => {
23
+ if (value.kind !== "strConcat") {
24
+ seen.push(value);
25
+ return;
26
+ }
27
+ const parts = stringParts(value);
28
+ expect(parts.length).toBeGreaterThanOrEqual(2);
29
+ expect(parts.length).toBeLessThanOrEqual(16);
30
+ for (const part of parts)
31
+ walk(part);
32
+ };
33
+ walk(tree);
34
+ expect(seen).toEqual(leaves);
35
+ }
36
+ });
37
+ test.each([32, 64])("concat uses a borrowed stack vector with %i-bit size_t", (bits) => {
38
+ const mod = module(concat(concat(text("<"), ref("value")), text(">")));
39
+ expect(validateModule(mod)).toEqual([]);
40
+ const ir = emitLlvmModule(mod, { pointerBits: bits });
41
+ const body = /^define internal [^\n]*@sc_bf_assemble\([^]*?^}/m.exec(ir)[0];
42
+ expect(body).toContain("alloca [3 x ptr]");
43
+ expect(body).toMatch(new RegExp(`call ptr @scr_str_concat_parts\\(ptr %[^,]+, i${bits} 3\\)`));
44
+ expect(body).not.toContain("@scr_str_retain_v");
45
+ expect(body).not.toContain("@scr_str_release");
46
+ });
47
+ test("later writes preserve an owned snapshot of earlier string parts", () => {
48
+ const changed = { kind: "assignExpr", localId: "value", value: text("new"), type: STRING, loc };
49
+ const mod = module(concat(concat(ref("value"), changed), ref("value")));
50
+ expect(validateModule(mod)).toEqual([]);
51
+ const body = /^define internal [^\n]*@sc_f_assemble\([^]*?^}/m.exec(emitLlvmModule(mod))[0];
52
+ const retain = body.indexOf("@scr_str_retain_v");
53
+ const release = body.indexOf("@scr_str_release");
54
+ const assemble = body.indexOf("@scr_str_concat_parts");
55
+ expect(retain).toBeGreaterThanOrEqual(0);
56
+ expect(retain).toBeLessThan(release);
57
+ expect(release).toBeLessThan(assemble);
58
+ expect(body.slice(assemble)).toContain("@scr_str_release");
59
+ });
60
+ test("two-part concatenation keeps the existing append path", () => {
61
+ const ir = emitLlvmModule(module(concat(ref("value"), text("suffix"))));
62
+ expect(ir).toContain("call ptr @scr_str_concat(");
63
+ expect(ir).not.toContain("@scr_str_concat_parts");
64
+ });
65
+ //# sourceMappingURL=string-construction.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string-construction.test.js","sourceRoot":"","sources":["../../../src/backend/llvm/string-construction.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { IrExpr, IrStrIntrinsicMethod } from "../../ir/ir.js";
2
+ import type { LlValue, LlvmEmitterContext } from "./expr-context.js";
3
+ /** These methods consume string pointers only for the duration of their
4
+ * runtime call. Reference results carry their own owner, even when the
5
+ * runtime returns an unchanged input. Keep new methods conservative until
6
+ * their ownership contract has been checked. */
7
+ export declare function borrowsStringInputs(method: IrStrIntrinsicMethod): boolean;
8
+ /** Evaluate left to right. An immutable local or immortal literal owns its
9
+ * value across later operands. A writable binding needs a snapshot unless
10
+ * the remaining expressions preserve it. Projections also require those
11
+ * expressions to preserve every reference edge; other values keep ownership. */
12
+ export declare function emitStringInputs(host: LlvmEmitterContext, inputs: readonly IrExpr[]): LlValue[];
@@ -0,0 +1,72 @@
1
+ import { isStableReceiverOperand } from "../../ir/analysis.js";
2
+ import { borrowableInputs } from "./borrowed-inputs.js";
3
+ /** These methods consume string pointers only for the duration of their
4
+ * runtime call. Reference results carry their own owner, even when the
5
+ * runtime returns an unchanged input. Keep new methods conservative until
6
+ * their ownership contract has been checked. */
7
+ export function borrowsStringInputs(method) {
8
+ switch (method) {
9
+ case "length":
10
+ case "charCodeAt":
11
+ case "charAt":
12
+ case "indexOf":
13
+ case "includes":
14
+ case "startsWith":
15
+ case "endsWith":
16
+ case "slice":
17
+ case "substring":
18
+ case "repeat":
19
+ case "trim":
20
+ case "trimStart":
21
+ case "trimEnd":
22
+ case "split":
23
+ case "padStart":
24
+ case "padEnd":
25
+ case "toLowerCase":
26
+ case "toUpperCase":
27
+ case "normalize":
28
+ case "isWellFormed":
29
+ case "toWellFormed":
30
+ case "cpAt": return true;
31
+ default: return false;
32
+ }
33
+ }
34
+ /** No callback, suspension or reference write can invalidate an earlier
35
+ * borrowed string during these expressions. Numeric assignment is handled
36
+ * by the receiver proof; string assignment deliberately stays on the owned
37
+ * path. A future expression kind does not inherit this guarantee. */
38
+ function preservesStringInputs(value, localId) {
39
+ if (isStableReceiverOperand(value, localId))
40
+ return true;
41
+ switch (value.kind) {
42
+ case "strLit": return true;
43
+ case "strEq":
44
+ case "strCmp":
45
+ case "strConcat":
46
+ return preservesStringInputs(value.left, localId) && preservesStringInputs(value.right, localId);
47
+ case "strIntrinsic":
48
+ return borrowsStringInputs(value.method) && preservesStringInputs(value.receiver, localId) &&
49
+ value.args.every((arg) => preservesStringInputs(arg, localId));
50
+ default: return false;
51
+ }
52
+ }
53
+ /** Evaluate left to right. An immutable local or immortal literal owns its
54
+ * value across later operands. A writable binding needs a snapshot unless
55
+ * the remaining expressions preserve it. Projections also require those
56
+ * expressions to preserve every reference edge; other values keep ownership. */
57
+ export function emitStringInputs(host, inputs) {
58
+ const borrowed = borrowableInputs(host, inputs);
59
+ return inputs.map((value, index) => {
60
+ if (value.type.kind !== "string")
61
+ return host.emitExpr(value);
62
+ if (value.kind === "strLit")
63
+ return { name: host.internLiteral(value.value), type: value.type };
64
+ if (borrowed[index])
65
+ return host.emitReadReceiver(value);
66
+ if (value.kind === "varRef" && inputs.slice(index + 1).every((next) => preservesStringInputs(next, value.localId))) {
67
+ return host.emitReadReceiver(value);
68
+ }
69
+ return host.emitExpr(value);
70
+ });
71
+ }
72
+ //# sourceMappingURL=string-lifetimes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string-lifetimes.js","sourceRoot":"","sources":["../../../src/backend/llvm/string-lifetimes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};