diff --git a/lib/builtin.ml b/lib/builtin.ml index 2ec76f69..61630696 100644 --- a/lib/builtin.ml +++ b/lib/builtin.ml @@ -27,7 +27,7 @@ type t = | Mod | Array_get | Array_length - | Array_drop_back + | Unsafe_array_pop_back | Array_data | Array_capacity | Fixed_array_get @@ -157,9 +157,9 @@ let tbl = Simple ) ); Hashtbl.add tbl "__array_length" (Array_length, Tfun ([ { p with pt = tarray (Qvar "0") } ], tint, Simple)); - Hashtbl.add tbl "__array_drop_back" - ( Array_drop_back, - Tfun ([ { pt = tarray (Qvar "0"); pattr = Dmut } ], tunit, Simple) ); + Hashtbl.add tbl "__unsafe_array_pop_back" + ( Unsafe_array_pop_back, + Tfun ([ { pt = tarray (Qvar "0"); pattr = Dmut } ], Qvar "0", Simple) ); Hashtbl.add tbl "__array_data" ( Array_data, Tfun ([ { p with pt = tarray (Qvar "0") } ], traw_ptr (Qvar "0"), Simple) diff --git a/lib/codegen/arr.ml b/lib/codegen/arr.ml index 88d9b5b9..f09a86c3 100644 --- a/lib/codegen/arr.ml +++ b/lib/codegen/arr.ml @@ -195,7 +195,9 @@ struct { dummy_fn_value with lltyp = unit_t } - let array_drop_back param args = + let unsafe_array_pop_back param args allocref = + (* We assume there is at least one item, and don't actually check the size. + But we do decrease the size of the array by one. *) let arr = match args with | [ arr ] -> arr @@ -206,31 +208,21 @@ struct let dst = Llvm.build_gep int_t arr.value [| ci 0 |] "size" builder in let sz = Llvm.build_load int_t dst "size" builder in - let start_bb = Llvm.insertion_block builder in - let parent = Llvm.block_parent start_bb in - - let drop_last_bb = Llvm.append_block context "drop_last" parent in - let cont_bb = Llvm.append_block context "cont" parent in - - let cmp = Llvm.(build_icmp Icmp.Sgt) sz (ci 0) "" builder in - ignore (Llvm.build_cond_br cmp drop_last_bb cont_bb builder); - - Llvm.position_at_end drop_last_bb builder; let index = Llvm.build_sub sz (ci 1) "" builder in + ignore (Llvm.build_store index dst builder); + let ptr = data_get arr.value arr.typ (Idyn index) in let item_typ = item_type arr.typ in let llitem_typ = get_lltype_def item_typ in - Auto.free param - { value = ptr; kind = Ptr; typ = item_typ; lltyp = llitem_typ }; + let v = { value = ptr; kind = Ptr; lltyp = llitem_typ; typ = item_typ } in + let src = bring_default_var v in - ignore (Llvm.build_store index dst builder); - ignore (Llvm.build_br cont_bb builder); + let dst = get_prealloc !allocref param llitem_typ "" in - Llvm.position_at_end cont_bb builder; - - { dummy_fn_value with lltyp = unit_t } + store_or_copy ~src ~dst; + { v with value = dst; kind = Ptr } let array_data args = let arr = diff --git a/lib/codegen/arr_intf.ml b/lib/codegen/arr_intf.ml index 2db9ad83..ace9b3a1 100644 --- a/lib/codegen/arr_intf.ml +++ b/lib/codegen/arr_intf.ml @@ -22,7 +22,10 @@ module type S = sig val array_length : unsafe:bool -> llvar list -> llvar val array_capacity : llvar list -> llvar val array_realloc : llvar list -> llvar - val array_drop_back : param -> llvar list -> llvar + + val unsafe_array_pop_back : + param -> llvar list -> Monomorph_tree.alloca -> llvar + val array_data : llvar list -> llvar val unsafe_array_create : diff --git a/lib/codegen/codegen.ml b/lib/codegen/codegen.ml index 6c702ab6..8a141b6f 100644 --- a/lib/codegen/codegen.ml +++ b/lib/codegen/codegen.ml @@ -750,7 +750,7 @@ end = struct | Array_get -> array_get args fnc.ret | Array_length -> array_length ~unsafe:false args | Unsafe_array_length -> array_length ~unsafe:true args - | Array_drop_back -> array_drop_back param args + | Unsafe_array_pop_back -> unsafe_array_pop_back param args allocref | Array_data -> array_data args | Array_capacity -> array_capacity args | Fixed_array_get -> ( diff --git a/lib/map_module.ml b/lib/map_module.ml index 8865718f..3b23e4b0 100644 --- a/lib/map_module.ml +++ b/lib/map_module.ml @@ -10,7 +10,7 @@ module type Map_tree = sig val map_decl : mname:Path.t -> string -> sub -> type_decl -> sub * type_decl val absolute_module_name : mname:Path.t -> string -> string - val map_type : sub -> typ -> sub * typ + val map_type : mname:Path.t -> sub -> typ -> sub * typ end module Canonize = struct @@ -69,7 +69,7 @@ end module Make (C : Map_tree) = struct let rec map_body mname nsub sub (e : Typed_tree.typed_expr) = - let sub, typ = C.map_type sub e.typ in + let sub, typ = C.map_type ~mname sub e.typ in let sub, expr = map_expr mname nsub sub e.expr in (sub, Typed_tree.{ e with typ; expr }) @@ -116,7 +116,7 @@ module Make (C : Map_tree) = struct let sub, fs = List.fold_left_map (fun sub (n, u, t) -> - let sub, t = C.map_type sub t in + let sub, t = C.map_type ~mname sub t in (sub, (n, u, t))) sub fs in @@ -188,11 +188,11 @@ module Make (C : Map_tree) = struct let sub, tparams = List.fold_left_map (fun sub p -> - let sub, pt = C.map_type sub p.pt in + let sub, pt = C.map_type ~mname sub p.pt in (sub, { p with pt })) sub abs.func.tparams in - let sub, ret = C.map_type sub abs.func.ret in + let sub, ret = C.map_type ~mname sub abs.func.ret in let sub, kind = match abs.func.kind with | Simple -> (sub, Simple) @@ -200,7 +200,7 @@ module Make (C : Map_tree) = struct let sub, l = List.fold_left_map (fun sub c -> - let sub, cltyp = C.map_type sub c.cltyp in + let sub, cltyp = C.map_type ~mname sub c.cltyp in let clname, clmname = C.change_var ~mname c.clname c.clmname sub in @@ -212,7 +212,7 @@ module Make (C : Map_tree) = struct let sub, touched = List.fold_left_map (fun sub t -> - let sub, ttyp = C.map_type sub Typed_tree.(t.ttyp) in + let sub, ttyp = C.map_type ~mname sub Typed_tree.(t.ttyp) in (sub, { t with ttyp })) sub abs.func.touched in @@ -247,7 +247,7 @@ module Make (C : Map_tree) = struct let sub, decls = List.fold_left_map (fun sub (n, u, t) -> - let sub, t = C.map_type sub t in + let sub, t = C.map_type ~mname sub t in (sub, (n, u, t))) sub decls in @@ -261,10 +261,10 @@ module Make (C : Map_tree) = struct let sub, decl = C.map_decl ~mname n sub decl in ((sub, nsub), Mtype (l, n, decl)) | Mfun (l, t, n) -> - let a, t = C.map_type sub t in + let a, t = C.map_type ~mname sub t in ((a, nsub), Mfun (l, t, n)) | Mext (l, t, n, c) -> - let a, t = C.map_type sub t in + let a, t = C.map_type ~mname sub t in ((a, nsub), Mext (l, t, n, c)) | Mpoly_fun (l, abs, n, u) -> (* Change Var-nodes in body here *) @@ -277,7 +277,7 @@ module Make (C : Map_tree) = struct let (a, nsub), decls = List.fold_left_map (fun (sub, nsub) (l, n, u, t) -> - let a, t = C.map_type sub t in + let a, t = C.map_type ~mname sub t in ((a, nsub), (l, n, u, t))) (sub, nsub) decls in @@ -323,7 +323,7 @@ module Make (C : Map_tree) = struct let sub, decl = C.map_decl ~mname n sub decl in (sub, Mtypedef decl) | Mvalue (typ, cn) -> - let sub, typ = C.map_type sub typ in + let sub, typ = C.map_type ~mname sub typ in (sub, Mvalue (typ, cn)) and map_intf mname sub intf = diff --git a/lib/module.ml b/lib/module.ml index 4e3ef5e8..926a4b95 100644 --- a/lib/module.ml +++ b/lib/module.ml @@ -145,7 +145,7 @@ module Map_canon : Map_module.Map_tree = struct | None | Some _ -> ()); (id, m) - let map_decl ~mname _ sub decl = + let load_type ~mname typ = let rec load_type = function | Tconstr (name, _) -> ( match Path.rm_head name with @@ -158,6 +158,10 @@ module Map_canon : Map_module.Map_tree = struct load_type ret | Ttuple ts -> List.iter load_type ts in + load_type typ + + let map_decl ~mname _ sub decl = + let load_type = load_type ~mname in let rec map_kind = function | Dalias typ -> load_type typ @@ -172,7 +176,10 @@ module Map_canon : Map_module.Map_tree = struct (sub, decl) let absolute_module_name = absolute_module_name - let map_type = Map_module.Canonize.canonize + + let map_type ~mname sub typ = + load_type ~mname typ; + Map_module.Canonize.canonize sub typ end module Canon = Map_module.Make (Map_canon) diff --git a/lib/typing/exclusivity.ml b/lib/typing/exclusivity.ml index 035074d0..732728e9 100644 --- a/lib/typing/exclusivity.ml +++ b/lib/typing/exclusivity.ml @@ -23,7 +23,12 @@ module Contains_allocation = struct false ts) then (* Unparameterized types can also contain allocations *) - let decl = get_decl name in + let decl = + try get_decl name + with Not_found -> + print_endline (Path.show name); + failwith "med" + in let sub = map_params ~inst:ts ~params:decl.params in let rec check_decl decl_kind = match decl_kind with diff --git a/lib/typing/typing.ml b/lib/typing/typing.ml index d6182c32..52d27a9d 100644 --- a/lib/typing/typing.ml +++ b/lib/typing/typing.ml @@ -1416,7 +1416,7 @@ struct let sub, fields = Array.fold_left_map (fun sub f -> - let sub, ftyp = map_type sub f.ftyp in + let sub, ftyp = map_type ~mname sub f.ftyp in (sub, { f with ftyp })) sub fields in @@ -1427,7 +1427,7 @@ struct (fun sub ct -> match ct.ctyp with | Some typ -> - let sub, ctyp = map_type sub typ in + let sub, ctyp = map_type ~mname sub typ in (sub, { ct with ctyp = Some ctyp }) | None -> (sub, ct)) sub ctors @@ -1441,7 +1441,7 @@ struct in (sub, Dabstract (Some Types.(decl.kind))) | Dalias typ -> - let sub, typ = map_type sub typ in + let sub, typ = map_type ~mname sub typ in (sub, Dalias typ) | Dabstract None -> (sub, Dabstract None) in @@ -1476,7 +1476,7 @@ module Subst_functor_impl (* : Map_module.Map_tree *) = struct let absolute_module_name = Module.absolute_module_name - let map_type (find_type, subs, decls) typ = + let map_type ~mname:_ (find_type, subs, decls) typ = let typ = List.fold_left (fun typ { base; with_ } -> apply_pathsub ~base ~with_ typ) @@ -1506,7 +1506,7 @@ module Resolve_aliases_impl (* : Map_module.Map_tree *) = struct let absolute_module_name = Module.absolute_module_name - let map_type (find_type, subs, decls) typ = + let map_type ~mname:_ (find_type, subs, decls) typ = (* Use aliases if they are available *) let typ = resolve_alias (find_type decls) typ in ((find_type, subs, decls), typ) diff --git a/std/array.smu b/std/array.smu index 0fc4bba5..8ba63a18 100644 --- a/std/array.smu +++ b/std/array.smu @@ -1,7 +1,7 @@ +import option import prelude let data = __array_data -let drop_back = __array_drop_back let length = __array_length use prelude @@ -95,6 +95,16 @@ fun map(arr, f) { inner(!ret, 0) } +fun pop_back(arr&) { + use option + if length(arr) == 0 { + #none + } + else { + #some(__unsafe_array_pop_back(&arr)) + } +} + fun swap_items(arr&, i, j) { if not (i == j) { let itmp = !arr.[i] @@ -108,7 +118,7 @@ fun clear(arr&) { if 0 == length(arr) { () } else { - drop_back(&arr) + pop_back(&arr).ignore() inner() } } diff --git a/std/dune b/std/dune index b8553cd9..f6725f59 100644 --- a/std/dune +++ b/std/dune @@ -7,7 +7,7 @@ (rule (targets array.o array.smi) - (deps %{bin:schmu} array.smu prelude.smi) + (deps %{bin:schmu} array.smu prelude.smi option.smi) (action (progn (run schmu -m --no-std array.smu)))) diff --git a/std/string.smu b/std/string.smu index 1cdc6782..3f7f7e47 100644 --- a/std/string.smu +++ b/std/string.smu @@ -68,7 +68,7 @@ fun concat(delim, strings) { append(&ret, str) }) array/push(&ret, !'\000') - array/drop_back(&ret) + array/pop_back(&ret).ignore() ret } diff --git a/test/functions.t/closure_inference.smu b/test/functions.t/closure_inference.smu index fa5ae55f..f4eef39d 100644 --- a/test/functions.t/closure_inference.smu +++ b/test/functions.t/closure_inference.smu @@ -20,7 +20,7 @@ fun string_of_view(view) { array/push(&ret, !string/get(view.pbuf, c)) }) array/push(&ret, !'\000') - array/drop_back(&ret) + array/pop_back(&ret).ignore() ret } diff --git a/test/functions.t/polymorphic_lambda_argument.smu b/test/functions.t/polymorphic_lambda_argument.smu index dbb5f05b..4473da51 100644 --- a/test/functions.t/polymorphic_lambda_argument.smu +++ b/test/functions.t/polymorphic_lambda_argument.smu @@ -3,7 +3,7 @@ let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] fun string_add_null(str&) { string/modify_buf(&str, fun(arr&) { array/push(&arr, !0u8) - array/drop_back(&arr) + array/pop_back(&arr).ignore() }) } diff --git a/test/functions.t/run.t b/test/functions.t/run.t index 2e841cd2..89a548ce 100644 --- a/test/functions.t/run.t +++ b/test/functions.t/run.t @@ -1655,6 +1655,7 @@ The lamba passed as array-iter argument is polymorphic target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" %closure = type { ptr, ptr } + %option.tc_ = type { i32, i8 } @schmu_arr = global ptr null, align 8 @0 = private unnamed_addr constant { i64, i64, [4 x i8] } { i64 3, i64 3, [4 x i8] c"%li\00" } @@ -1719,6 +1720,37 @@ The lamba passed as array-iter argument is polymorphic ret void } + define linkonce_odr i64 @__array_pop_back_ac_rvc__(ptr noalias %arr) { + entry: + %0 = load ptr, ptr %arr, align 8 + %1 = load i64, ptr %0, align 8 + %eq = icmp eq i64 %1, 0 + br i1 %eq, label %then, label %else + + then: ; preds = %entry + %t = alloca %option.tc_, align 8 + store %option.tc_ { i32 1, i8 undef }, ptr %t, align 4 + br label %ifcont + + else: ; preds = %entry + %t1 = alloca %option.tc_, align 8 + store i32 0, ptr %t1, align 4 + %data = getelementptr inbounds %option.tc_, ptr %t1, i32 0, i32 1 + %2 = sub i64 %1, 1 + store i64 %2, ptr %0, align 8 + %3 = getelementptr i8, ptr %0, i64 16 + %4 = getelementptr i8, ptr %3, i64 %2 + %5 = load i8, ptr %4, align 1 + store i8 %5, ptr %data, align 1 + store i8 %5, ptr %data, align 1 + br label %ifcont + + ifcont: ; preds = %else, %then + %iftmp = phi ptr [ %t, %then ], [ %t1, %else ] + %unbox = load i64, ptr %iftmp, align 8 + ret i64 %unbox + } + define linkonce_odr void @__array_push_ac_c_(ptr noalias %arr, i8 %value) { entry: %0 = load ptr, ptr %arr, align 8 @@ -1762,19 +1794,9 @@ The lamba passed as array-iter argument is polymorphic define void @__fun_schmu0(ptr noalias %arr) { entry: tail call void @__array_push_ac_c_(ptr %arr, i8 0) - %0 = load ptr, ptr %arr, align 8 - %size1 = load i64, ptr %0, align 8 - %1 = icmp sgt i64 %size1, 0 - br i1 %1, label %drop_last, label %cont - - drop_last: ; preds = %entry - %2 = sub i64 %size1, 1 - %3 = getelementptr i8, ptr %0, i64 16 - %4 = getelementptr i8, ptr %3, i64 %2 - store i64 %2, ptr %0, align 8 - br label %cont - - cont: ; preds = %drop_last, %entry + %ret = alloca %option.tc_, align 8 + %0 = tail call i64 @__array_pop_back_ac_rvc__(ptr %arr) + store i64 %0, ptr %ret, align 8 ret void } diff --git a/test/misc.t/array_drop_back.smu b/test/misc.t/array_drop_back.smu index b4f8c91a..8d3627f5 100644 --- a/test/misc.t/array_drop_back.smu +++ b/test/misc.t/array_drop_back.smu @@ -1,8 +1,8 @@ let nested& = [[0, 1], [2, 3]] println(fmt(array/length(nested))) -array/drop_back(&nested) +match array/pop_back(&nested) { #some(_): println("some") | #none: () } println(fmt(array/length(nested))) -array/drop_back(&nested) +array/pop_back(&nested).ignore() println(fmt(array/length(nested))) -array/drop_back(&nested) +match array/pop_back(&nested){ #some(_): () | #none: println("none") } println(fmt(array/length(nested))) diff --git a/test/misc.t/m2.smu b/test/misc.t/m2.smu index 50221ed7..539b5830 100644 --- a/test/misc.t/m2.smu +++ b/test/misc.t/m2.smu @@ -17,7 +17,7 @@ and odd(i) { fun rec pop(arr&) { println("pop") - array/drop_back(&arr) + array/pop_back(&arr).ignore() pop_all(&arr) } and pop_all(arr&) { diff --git a/test/misc.t/polymorphic_mutual_rec.smu b/test/misc.t/polymorphic_mutual_rec.smu index 385019cd..f6736d28 100644 --- a/test/misc.t/polymorphic_mutual_rec.smu +++ b/test/misc.t/polymorphic_mutual_rec.smu @@ -14,7 +14,7 @@ m2/{ fun rec pop(arr&) { println("pop") - array/drop_back(&arr) + array/pop_back(&arr).ignore() pop_all(&arr) } and pop_all(arr&) { diff --git a/test/misc.t/run.t b/test/misc.t/run.t index 2005ba9d..66aad68d 100644 --- a/test/misc.t/run.t +++ b/test/misc.t/run.t @@ -2012,8 +2012,45 @@ Drop last element source_filename = "context" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + %option.tal__ = type { i32, ptr } + @schmu_nested = global ptr null, align 8 @0 = private unnamed_addr constant { i64, i64, [5 x i8] } { i64 4, i64 4, [5 x i8] c"%li\0A\00" } + @1 = private unnamed_addr constant { i64, i64, [5 x i8] } { i64 4, i64 4, [5 x i8] c"some\00" } + @2 = private unnamed_addr constant { i64, i64, [5 x i8] } { i64 4, i64 4, [5 x i8] c"none\00" } + + declare void @string_println(ptr %0) + + define linkonce_odr { i32, i64 } @__array_pop_back_2al2_rval2__(ptr noalias %arr) { + entry: + %0 = load ptr, ptr %arr, align 8 + %1 = load i64, ptr %0, align 8 + %eq = icmp eq i64 %1, 0 + br i1 %eq, label %then, label %else + + then: ; preds = %entry + %t = alloca %option.tal__, align 8 + store %option.tal__ { i32 1, ptr undef }, ptr %t, align 8 + br label %ifcont + + else: ; preds = %entry + %t1 = alloca %option.tal__, align 8 + store i32 0, ptr %t1, align 4 + %data = getelementptr inbounds %option.tal__, ptr %t1, i32 0, i32 1 + %2 = sub i64 %1, 1 + store i64 %2, ptr %0, align 8 + %3 = getelementptr i8, ptr %0, i64 16 + %4 = getelementptr ptr, ptr %3, i64 %2 + %5 = load ptr, ptr %4, align 8 + store ptr %5, ptr %data, align 8 + store ptr %5, ptr %data, align 8 + br label %ifcont + + ifcont: ; preds = %else, %then + %iftmp = phi ptr [ %t, %then ], [ %t1, %else ] + %unbox = load { i32, i64 }, ptr %iftmp, align 8 + ret { i32, i64 } %unbox + } define i64 @main(i64 %arg) { entry: @@ -2045,64 +2082,51 @@ Drop last element %6 = load ptr, ptr @schmu_nested, align 8 %7 = load i64, ptr %6, align 8 tail call void (ptr, ...) @printf(ptr getelementptr (i8, ptr @0, i64 16), i64 %7) - %8 = load ptr, ptr @schmu_nested, align 8 - %size10 = load i64, ptr %8, align 8 - %9 = icmp sgt i64 %size10, 0 - br i1 %9, label %drop_last, label %cont - - drop_last: ; preds = %entry - %10 = sub i64 %size10, 1 - %11 = getelementptr i8, ptr %8, i64 16 - %12 = getelementptr ptr, ptr %11, i64 %10 - tail call void @__free_al_(ptr %12) - store i64 %10, ptr %8, align 8 - %.pre = load ptr, ptr @schmu_nested, align 8 - %.pre22 = load i64, ptr %.pre, align 8 - br label %cont + %ret = alloca %option.tal__, align 8 + %8 = tail call { i32, i64 } @__array_pop_back_2al2_rval2__(ptr @schmu_nested) + store { i32, i64 } %8, ptr %ret, align 8 + %index = load i32, ptr %ret, align 4 + %eq = icmp eq i32 %index, 0 + br i1 %eq, label %then, label %ifcont + + then: ; preds = %entry + %data = getelementptr inbounds %option.tal__, ptr %ret, i32 0, i32 1 + tail call void @string_println(ptr @1) + br label %ifcont - cont: ; preds = %drop_last, %entry - %13 = phi i64 [ %.pre22, %drop_last ], [ %size10, %entry ] - %14 = phi ptr [ %.pre, %drop_last ], [ %8, %entry ] + ifcont: ; preds = %entry, %then + %9 = load ptr, ptr @schmu_nested, align 8 + %10 = load i64, ptr %9, align 8 + tail call void (ptr, ...) @printf(ptr getelementptr (i8, ptr @0, i64 16), i64 %10) + %ret10 = alloca %option.tal__, align 8 + %11 = tail call { i32, i64 } @__array_pop_back_2al2_rval2__(ptr @schmu_nested) + store { i32, i64 } %11, ptr %ret10, align 8 + %12 = load ptr, ptr @schmu_nested, align 8 + %13 = load i64, ptr %12, align 8 tail call void (ptr, ...) @printf(ptr getelementptr (i8, ptr @0, i64 16), i64 %13) + %ret12 = alloca %option.tal__, align 8 + %14 = tail call { i32, i64 } @__array_pop_back_2al2_rval2__(ptr @schmu_nested) + store { i32, i64 } %14, ptr %ret12, align 8 + %index14 = load i32, ptr %ret12, align 4 + %eq15 = icmp eq i32 %index14, 0 + br i1 %eq15, label %then16, label %else18 + + then16: ; preds = %ifcont + %data17 = getelementptr inbounds %option.tal__, ptr %ret12, i32 0, i32 1 + br label %ifcont19 + + else18: ; preds = %ifcont + tail call void @string_println(ptr @2) + br label %ifcont19 + + ifcont19: ; preds = %else18, %then16 %15 = load ptr, ptr @schmu_nested, align 8 - %size13 = load i64, ptr %15, align 8 - %16 = icmp sgt i64 %size13, 0 - br i1 %16, label %drop_last14, label %cont15 - - drop_last14: ; preds = %cont - %17 = sub i64 %size13, 1 - %18 = getelementptr i8, ptr %15, i64 16 - %19 = getelementptr ptr, ptr %18, i64 %17 - tail call void @__free_al_(ptr %19) - store i64 %17, ptr %15, align 8 - %.pre23 = load ptr, ptr @schmu_nested, align 8 - %.pre24 = load i64, ptr %.pre23, align 8 - br label %cont15 - - cont15: ; preds = %drop_last14, %cont - %20 = phi i64 [ %.pre24, %drop_last14 ], [ %size13, %cont ] - %21 = phi ptr [ %.pre23, %drop_last14 ], [ %15, %cont ] - tail call void (ptr, ...) @printf(ptr getelementptr (i8, ptr @0, i64 16), i64 %20) - %22 = load ptr, ptr @schmu_nested, align 8 - %size18 = load i64, ptr %22, align 8 - %23 = icmp sgt i64 %size18, 0 - br i1 %23, label %drop_last19, label %cont20 - - drop_last19: ; preds = %cont15 - %24 = sub i64 %size18, 1 - %25 = getelementptr i8, ptr %22, i64 16 - %26 = getelementptr ptr, ptr %25, i64 %24 - tail call void @__free_al_(ptr %26) - store i64 %24, ptr %22, align 8 - %.pre25 = load ptr, ptr @schmu_nested, align 8 - %.pre26 = load i64, ptr %.pre25, align 8 - br label %cont20 - - cont20: ; preds = %drop_last19, %cont15 - %27 = phi i64 [ %.pre26, %drop_last19 ], [ %size18, %cont15 ] - %28 = phi ptr [ %.pre25, %drop_last19 ], [ %22, %cont15 ] - tail call void (ptr, ...) @printf(ptr getelementptr (i8, ptr @0, i64 16), i64 %27) - tail call void @__free_2al2_(ptr @schmu_nested) + %16 = load i64, ptr %15, align 8 + tail call void (ptr, ...) @printf(ptr getelementptr (i8, ptr @0, i64 16), i64 %16) + call void @__free_val2_(ptr %ret12) + call void @__free_val2_(ptr %ret10) + call void @__free_val2_(ptr %ret) + call void @__free_2al2_(ptr @schmu_nested) ret i64 0 } @@ -2117,6 +2141,22 @@ Drop last element ret void } + define linkonce_odr void @__free_val2_(ptr %0) { + entry: + %tag1 = bitcast ptr %0 to ptr + %index = load i32, ptr %tag1, align 4 + %1 = icmp eq i32 %index, 0 + br i1 %1, label %match, label %cont + + match: ; preds = %entry + %data = getelementptr inbounds %option.tal__, ptr %0, i32 0, i32 1 + call void @__free_al_(ptr %data) + br label %cont + + cont: ; preds = %match, %entry + ret void + } + define linkonce_odr void @__free_2al2_(ptr %0) { entry: %1 = load ptr, ptr %0, align 8 @@ -2146,8 +2186,10 @@ Drop last element declare void @free(ptr %0) 2 + some 1 0 + none 0 Global lets with expressions