compiler: free a string an expression made once it has been used
The left half of a + chain, a template's pieces and holes, a number's text and a side made only to be compared are marked fresh and freed after the +, ==, != or print that reads them. lp_int_str and lp_long_str move their digits to the start of the buffer, so the pointer they return is the one malloc gave. Reseeded. examples/lang/string_temps.ludic: kept intermediates stay good, and 20,000 rounds grow the heap 0 bytes (2.9 MB before). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2fe4018d28
commit
9660587e10
10 changed files with 56019 additions and 48735 deletions
|
|
@ -133,9 +133,17 @@ function to_long(v: Val) -> pointer {
|
|||
function emit_str_op(op: pointer, a: Val, b: Val) -> Val {
|
||||
g_uses_str = true
|
||||
if (op == ("+")) {
|
||||
return val(emit_bind(`call ptr @lp_str_concat(ptr {a.code}, ptr {b.code})`), "string")
|
||||
let r = fresh_val(emit_bind(`call ptr @lp_str_concat(ptr {a.code}, ptr {b.code})`), "string")
|
||||
# a half this expression made is copied now and held by nothing: `a + "/" + b` and every
|
||||
# template's pieces once left one string behind per `+`
|
||||
if a.fresh { emit(` call void @free(ptr {a.code})\n`) }
|
||||
if b.fresh and b.code != a.code { emit(` call void @free(ptr {b.code})\n`) }
|
||||
return r
|
||||
}
|
||||
let r = emit_bind(`call i32 @lp_str_eq(ptr {a.code}, ptr {b.code})`)
|
||||
# a side made just to be compared is held by nothing once it has been: `` `{x}` == "..." ``
|
||||
if a.fresh { emit(` call void @free(ptr {a.code})\n`) }
|
||||
if b.fresh and b.code != a.code { emit(` call void @free(ptr {b.code})\n`) }
|
||||
if (op == ("!=")) {
|
||||
let c = emit_bind(`icmp eq i32 {r}, 0`)
|
||||
return val(emit_bind(`zext i1 {c} to i32`), "bool")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue