mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 20:28:02 +00:00
Merge pull request #5335 from JTeeuwissen/drop_specialization
Drop specialization
This commit is contained in:
commit
5183bf0196
62 changed files with 2248 additions and 886 deletions
|
@ -30,18 +30,19 @@ ROC_WORKSPACE_DIR = { value = "", relative = true }
|
|||
|
||||
# Debug flags. Keep this up-to-date with compiler/debug_flags/src/lib.rs.
|
||||
# Set = "1" to turn a debug flag on.
|
||||
ROC_PRETTY_PRINT_ALIAS_CONTENTS = "0"
|
||||
ROC_PRINT_UNIFICATIONS = "0"
|
||||
ROC_PRINT_UNDERIVABLE = "0"
|
||||
ROC_TRACE_COMPACTION = "0"
|
||||
ROC_PRINT_UNIFICATIONS_DERIVED = "0"
|
||||
ROC_PRINT_MISMATCHES = "0"
|
||||
ROC_VERIFY_RIGID_LET_GENERALIZED = "0"
|
||||
ROC_CHECK_MONO_IR = "0"
|
||||
ROC_PRINT_IR_AFTER_SPECIALIZATION = "0"
|
||||
ROC_PRINT_IR_AFTER_RESET_REUSE = "0"
|
||||
ROC_PRINT_IR_AFTER_REFCOUNT = "0"
|
||||
ROC_PRINT_RUNTIME_ERROR_GEN = "0"
|
||||
ROC_DEBUG_ALIAS_ANALYSIS = "0"
|
||||
ROC_PRINT_LLVM_FN_VERIFICATION = "0"
|
||||
ROC_PRINT_LOAD_LOG = "0"
|
||||
ROC_PRETTY_PRINT_ALIAS_CONTENTS = "0"
|
||||
ROC_PRINT_UNIFICATIONS = "0"
|
||||
ROC_PRINT_UNDERIVABLE = "0"
|
||||
ROC_TRACE_COMPACTION = "0"
|
||||
ROC_PRINT_UNIFICATIONS_DERIVED = "0"
|
||||
ROC_PRINT_MISMATCHES = "0"
|
||||
ROC_VERIFY_RIGID_LET_GENERALIZED = "0"
|
||||
ROC_CHECK_MONO_IR = "0"
|
||||
ROC_PRINT_IR_AFTER_SPECIALIZATION = "0"
|
||||
ROC_PRINT_IR_AFTER_RESET_REUSE = "0"
|
||||
ROC_PRINT_IR_AFTER_DROP_SPECIALIZATION = "0"
|
||||
ROC_PRINT_IR_AFTER_REFCOUNT = "0"
|
||||
ROC_PRINT_RUNTIME_ERROR_GEN = "0"
|
||||
ROC_DEBUG_ALIAS_ANALYSIS = "0"
|
||||
ROC_PRINT_LLVM_FN_VERIFICATION = "0"
|
||||
ROC_PRINT_LOAD_LOG = "0"
|
||||
|
|
|
@ -974,7 +974,7 @@ test "listConcat: non-unique with unique overlapping" {
|
|||
var bytes: [*]u8 = @ptrCast([*]u8, nonUnique.bytes);
|
||||
const ptr_width = @sizeOf(usize);
|
||||
const refcount_ptr = @ptrCast([*]isize, @alignCast(ptr_width, bytes) - ptr_width);
|
||||
utils.increfC(&refcount_ptr[0], 1);
|
||||
utils.increfRcPtrC(&refcount_ptr[0], 1);
|
||||
defer nonUnique.decref(@sizeOf(u8)); // listConcat will dec the other refcount
|
||||
|
||||
var unique = RocList.fromSlice(u8, ([_]u8{ 2, 3, 4 })[0..]);
|
||||
|
|
|
@ -173,8 +173,11 @@ comptime {
|
|||
// Utils
|
||||
comptime {
|
||||
exportUtilsFn(utils.test_panic, "test_panic");
|
||||
exportUtilsFn(utils.increfC, "incref");
|
||||
exportUtilsFn(utils.decrefC, "decref");
|
||||
exportUtilsFn(utils.increfRcPtrC, "incref_rc_ptr");
|
||||
exportUtilsFn(utils.decrefRcPtrC, "decref_rc_ptr");
|
||||
exportUtilsFn(utils.increfDataPtrC, "incref_data_ptr");
|
||||
exportUtilsFn(utils.decrefDataPtrC, "decref_data_ptr");
|
||||
exportUtilsFn(utils.isUnique, "is_unique");
|
||||
exportUtilsFn(utils.decrefCheckNullC, "decref_check_null");
|
||||
exportUtilsFn(utils.allocateWithRefcountC, "allocate_with_refcount");
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ pub const RocStr = extern struct {
|
|||
const ref_ptr = self.getRefcountPtr();
|
||||
if (ref_ptr != null) {
|
||||
const isizes: [*]isize = @ptrCast([*]isize, @alignCast(@alignOf(isize), ref_ptr));
|
||||
utils.increfC(@ptrCast(*isize, isizes - 1), @intCast(isize, n));
|
||||
utils.increfRcPtrC(@ptrCast(*isize, isizes - 1), @intCast(isize, n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ const Refcount = enum {
|
|||
|
||||
const RC_TYPE = Refcount.normal;
|
||||
|
||||
pub fn increfC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void {
|
||||
pub fn increfRcPtrC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void {
|
||||
if (RC_TYPE == Refcount.none) return;
|
||||
// Ensure that the refcount is not whole program lifetime.
|
||||
if (ptr_to_refcount.* != REFCOUNT_MAX_ISIZE) {
|
||||
|
@ -165,7 +165,7 @@ pub fn increfC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn decrefC(
|
||||
pub fn decrefRcPtrC(
|
||||
bytes_or_null: ?[*]isize,
|
||||
alignment: u32,
|
||||
) callconv(.C) void {
|
||||
|
@ -188,6 +188,36 @@ pub fn decrefCheckNullC(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn decrefDataPtrC(
|
||||
bytes_or_null: ?[*]isize,
|
||||
alignment: u32,
|
||||
) callconv(.C) void {
|
||||
var bytes = bytes_or_null orelse return;
|
||||
|
||||
const ptr = @ptrToInt(bytes);
|
||||
const tag_mask: usize = if (@sizeOf(usize) == 8) 0b111 else 0b11;
|
||||
const masked_ptr = ptr & ~tag_mask;
|
||||
|
||||
const isizes: [*]isize = @intToPtr([*]isize, masked_ptr);
|
||||
|
||||
return decrefRcPtrC(isizes - 1, alignment);
|
||||
}
|
||||
|
||||
pub fn increfDataPtrC(
|
||||
bytes_or_null: ?[*]isize,
|
||||
inc_amount: isize,
|
||||
) callconv(.C) void {
|
||||
var bytes = bytes_or_null orelse return;
|
||||
|
||||
const ptr = @ptrToInt(bytes);
|
||||
const tag_mask: usize = if (@sizeOf(usize) == 8) 0b111 else 0b11;
|
||||
const masked_ptr = ptr & ~tag_mask;
|
||||
|
||||
const isizes: *isize = @intToPtr(*isize, masked_ptr - @sizeOf(usize));
|
||||
|
||||
return increfRcPtrC(isizes, inc_amount);
|
||||
}
|
||||
|
||||
pub fn decref(
|
||||
bytes_or_null: ?[*]u8,
|
||||
data_bytes: usize,
|
||||
|
@ -231,6 +261,22 @@ inline fn decref_ptr_to_refcount(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn isUnique(
|
||||
bytes_or_null: ?[*]u8,
|
||||
) callconv(.C) bool {
|
||||
var bytes = bytes_or_null orelse return true;
|
||||
|
||||
const ptr = @ptrToInt(bytes);
|
||||
const tag_mask: usize = if (@sizeOf(usize) == 8) 0b111 else 0b11;
|
||||
const masked_ptr = ptr & ~tag_mask;
|
||||
|
||||
const isizes: [*]isize = @intToPtr([*]isize, masked_ptr);
|
||||
|
||||
const refcount = (isizes - 1)[0];
|
||||
|
||||
return refcount == REFCOUNT_ONE_ISIZE;
|
||||
}
|
||||
|
||||
// We follow roughly the [fbvector](https://github.com/facebook/folly/blob/main/folly/docs/FBVector.md) when it comes to growing a RocList.
|
||||
// Here is [their growth strategy](https://github.com/facebook/folly/blob/3e0525988fd444201b19b76b390a5927c15cb697/folly/FBVector.h#L1128) for push_back:
|
||||
//
|
||||
|
@ -347,13 +393,13 @@ pub const UpdateMode = enum(u8) {
|
|||
test "increfC, refcounted data" {
|
||||
var mock_rc: isize = REFCOUNT_ONE_ISIZE + 17;
|
||||
var ptr_to_refcount: *isize = &mock_rc;
|
||||
increfC(ptr_to_refcount, 2);
|
||||
increfRcPtrC(ptr_to_refcount, 2);
|
||||
try std.testing.expectEqual(mock_rc, REFCOUNT_ONE_ISIZE + 19);
|
||||
}
|
||||
|
||||
test "increfC, static data" {
|
||||
var mock_rc: isize = REFCOUNT_MAX_ISIZE;
|
||||
var ptr_to_refcount: *isize = &mock_rc;
|
||||
increfC(ptr_to_refcount, 2);
|
||||
increfRcPtrC(ptr_to_refcount, 2);
|
||||
try std.testing.expectEqual(mock_rc, REFCOUNT_MAX_ISIZE);
|
||||
}
|
||||
|
|
|
@ -376,8 +376,11 @@ pub const DEC_MUL_SATURATED: &str = "roc_builtins.dec.mul_saturated";
|
|||
|
||||
pub const UTILS_TEST_PANIC: &str = "roc_builtins.utils.test_panic";
|
||||
pub const UTILS_ALLOCATE_WITH_REFCOUNT: &str = "roc_builtins.utils.allocate_with_refcount";
|
||||
pub const UTILS_INCREF: &str = "roc_builtins.utils.incref";
|
||||
pub const UTILS_DECREF: &str = "roc_builtins.utils.decref";
|
||||
pub const UTILS_INCREF_RC_PTR: &str = "roc_builtins.utils.incref_rc_ptr";
|
||||
pub const UTILS_DECREF_RC_PTR: &str = "roc_builtins.utils.decref_rc_ptr";
|
||||
pub const UTILS_INCREF_DATA_PTR: &str = "roc_builtins.utils.incref_data_ptr";
|
||||
pub const UTILS_DECREF_DATA_PTR: &str = "roc_builtins.utils.decref_data_ptr";
|
||||
pub const UTILS_IS_UNIQUE: &str = "roc_builtins.utils.is_unique";
|
||||
pub const UTILS_DECREF_CHECK_NULL: &str = "roc_builtins.utils.decref_check_null";
|
||||
|
||||
pub const UTILS_EXPECT_FAILED_START_SHARED_BUFFER: &str =
|
||||
|
|
|
@ -86,8 +86,11 @@ macro_rules! map_symbol_to_lowlevel_and_arity {
|
|||
LowLevel::Hash => unimplemented!(),
|
||||
LowLevel::PtrCast => unimplemented!(),
|
||||
LowLevel::PtrWrite => unimplemented!(),
|
||||
LowLevel::RefCountInc => unimplemented!(),
|
||||
LowLevel::RefCountDec => unimplemented!(),
|
||||
LowLevel::RefCountIncRcPtr => unimplemented!(),
|
||||
LowLevel::RefCountDecRcPtr=> unimplemented!(),
|
||||
LowLevel::RefCountIncDataPtr => unimplemented!(),
|
||||
LowLevel::RefCountDecDataPtr=> unimplemented!(),
|
||||
LowLevel::RefCountIsUnique => unimplemented!(),
|
||||
|
||||
// these are not implemented, not sure why
|
||||
LowLevel::StrFromInt => unimplemented!(),
|
||||
|
|
|
@ -133,6 +133,10 @@ flags! {
|
|||
/// instructions.
|
||||
ROC_PRINT_IR_AFTER_REFCOUNT
|
||||
|
||||
/// Writes a pretty-printed mono IR to stderr after performing dropspecialization.
|
||||
/// Which inlines drop functions to remove pairs of alloc/dealloc instructions of its children.
|
||||
ROC_PRINT_IR_AFTER_DROP_SPECIALIZATION
|
||||
|
||||
/// Prints debug information during the alias analysis pass.
|
||||
ROC_DEBUG_ALIAS_ANALYSIS
|
||||
|
||||
|
|
|
@ -2083,11 +2083,10 @@ impl<
|
|||
}
|
||||
|
||||
fn build_ptr_cast(&mut self, dst: &Symbol, src: &Symbol) {
|
||||
let src_reg = self.storage_manager.load_to_general_reg(&mut self.buf, src);
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
self.storage_manager
|
||||
.ensure_symbol_on_stack(&mut self.buf, src);
|
||||
let (offset, _) = self.storage_manager.stack_offset_and_size(src);
|
||||
ASM::add_reg64_reg64_imm32(&mut self.buf, dst_reg, CC::BASE_PTR_REG, offset);
|
||||
|
||||
ASM::mov_reg64_reg64(&mut self.buf, dst_reg, src_reg)
|
||||
}
|
||||
|
||||
fn create_empty_array(&mut self, sym: &Symbol) {
|
||||
|
|
|
@ -1111,16 +1111,37 @@ trait Backend<'a> {
|
|||
|
||||
self.build_ptr_write(*sym, args[0], args[1], element_layout);
|
||||
}
|
||||
LowLevel::RefCountDec => self.build_fn_call(
|
||||
LowLevel::RefCountDecRcPtr => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::UTILS_DECREF.to_string(),
|
||||
bitcode::UTILS_DECREF_RC_PTR.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::RefCountInc => self.build_fn_call(
|
||||
LowLevel::RefCountIncRcPtr => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::UTILS_INCREF.to_string(),
|
||||
bitcode::UTILS_INCREF_RC_PTR.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::RefCountDecDataPtr => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::UTILS_DECREF_DATA_PTR.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::RefCountIncDataPtr => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::UTILS_INCREF_DATA_PTR.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::RefCountIsUnique => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::UTILS_IS_UNIQUE.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
|
|
|
@ -3,7 +3,6 @@ use crate::llvm::build::{
|
|||
allocate_with_refcount_help, cast_basic_basic, Env, RocFunctionCall, Scope,
|
||||
};
|
||||
use crate::llvm::convert::basic_type_from_layout;
|
||||
use crate::llvm::refcounting::increment_refcount_layout;
|
||||
use inkwell::builder::Builder;
|
||||
use inkwell::types::{BasicType, PointerType};
|
||||
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
|
||||
|
@ -125,7 +124,6 @@ pub(crate) fn list_with_capacity<'a, 'ctx>(
|
|||
pub(crate) fn list_get_unsafe<'a, 'ctx>(
|
||||
env: &Env<'a, 'ctx, '_>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
element_layout: InLayout<'a>,
|
||||
elem_index: IntValue<'ctx>,
|
||||
wrapper_struct: StructValue<'ctx>,
|
||||
|
@ -148,17 +146,13 @@ pub(crate) fn list_get_unsafe<'a, 'ctx>(
|
|||
)
|
||||
};
|
||||
|
||||
let result = load_roc_value(
|
||||
load_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
element_layout,
|
||||
elem_ptr,
|
||||
"list_get_load_element",
|
||||
);
|
||||
|
||||
increment_refcount_layout(env, layout_interner, layout_ids, 1, result, element_layout);
|
||||
|
||||
result
|
||||
)
|
||||
}
|
||||
|
||||
/// List.reserve : List elem, Nat -> List elem
|
||||
|
|
|
@ -25,7 +25,7 @@ use crate::llvm::{
|
|||
},
|
||||
build::{
|
||||
complex_bitcast_check_size, create_entry_block_alloca, function_value_by_func_spec,
|
||||
load_roc_value, roc_function_call, BuilderExt, RocReturn,
|
||||
load_roc_value, roc_function_call, tag_pointer_clear_tag_id, BuilderExt, RocReturn,
|
||||
},
|
||||
build_list::{
|
||||
list_append_unsafe, list_concat, list_drop_at, list_get_unsafe, list_len, list_map,
|
||||
|
@ -42,6 +42,7 @@ use crate::llvm::{
|
|||
LLVM_LOG, LLVM_MUL_WITH_OVERFLOW, LLVM_POW, LLVM_ROUND, LLVM_SIN, LLVM_SQRT,
|
||||
LLVM_SUB_SATURATED, LLVM_SUB_WITH_OVERFLOW,
|
||||
},
|
||||
refcounting::PointerToRefcount,
|
||||
};
|
||||
|
||||
use super::{build::throw_internal_exception, convert::zig_with_overflow_roc_dec};
|
||||
|
@ -807,7 +808,6 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
list_get_unsafe(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
list_element_layout!(layout_interner, list_layout),
|
||||
element_index.into_int_value(),
|
||||
wrapper_struct.into_struct_value(),
|
||||
|
@ -1247,10 +1247,34 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
|||
unreachable!("The {:?} operation is turned into mono Expr", op)
|
||||
}
|
||||
|
||||
PtrCast | PtrWrite | RefCountInc | RefCountDec => {
|
||||
PtrCast | PtrWrite | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr
|
||||
| RefCountDecDataPtr => {
|
||||
unreachable!("Not used in LLVM backend: {:?}", op);
|
||||
}
|
||||
|
||||
RefCountIsUnique => {
|
||||
arguments_with_layouts!((data_ptr, data_layout));
|
||||
|
||||
let ptr = env.builder.build_pointer_cast(
|
||||
data_ptr.into_pointer_value(),
|
||||
env.context.i8_type().ptr_type(AddressSpace::default()),
|
||||
"cast_to_i8_ptr",
|
||||
);
|
||||
|
||||
let value_ptr = match layout_interner.get(data_layout) {
|
||||
Layout::Union(union_layout)
|
||||
if union_layout.stores_tag_id_in_pointer(env.target_info) =>
|
||||
{
|
||||
tag_pointer_clear_tag_id(env, ptr)
|
||||
}
|
||||
_ => ptr,
|
||||
};
|
||||
|
||||
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, value_ptr);
|
||||
|
||||
BasicValueEnum::IntValue(refcount_ptr.is_1(env))
|
||||
}
|
||||
|
||||
Unreachable => match RocReturn::from_layout(env, layout_interner, layout) {
|
||||
RocReturn::Return => {
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
|
|
@ -212,7 +212,7 @@ fn incref_pointer<'ctx>(
|
|||
.into(),
|
||||
amount.into(),
|
||||
],
|
||||
roc_builtins::bitcode::UTILS_INCREF,
|
||||
roc_builtins::bitcode::UTILS_INCREF_RC_PTR,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -230,7 +230,7 @@ fn decref_pointer<'ctx>(env: &Env<'_, 'ctx, '_>, pointer: PointerValue<'ctx>, al
|
|||
.into(),
|
||||
alignment.into(),
|
||||
],
|
||||
roc_builtins::bitcode::UTILS_DECREF,
|
||||
roc_builtins::bitcode::UTILS_DECREF_RC_PTR,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -874,7 +874,14 @@ fn modify_refcount_boxed<'a, 'ctx>(
|
|||
let basic_type = basic_type_from_layout(env, layout_interner, boxed_layout);
|
||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||
|
||||
modify_refcount_box_help(env, layout_interner, mode, inner_layout, function_value);
|
||||
modify_refcount_box_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
inner_layout,
|
||||
function_value,
|
||||
);
|
||||
|
||||
function_value
|
||||
}
|
||||
|
@ -889,6 +896,7 @@ fn modify_refcount_boxed<'a, 'ctx>(
|
|||
fn modify_refcount_box_help<'a, 'ctx>(
|
||||
env: &Env<'a, 'ctx, '_>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
inner_layout: InLayout<'a>,
|
||||
fn_val: FunctionValue<'ctx>,
|
||||
|
@ -912,10 +920,49 @@ fn modify_refcount_box_help<'a, 'ctx>(
|
|||
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, boxed);
|
||||
let call_mode = mode_to_call_mode(fn_val, mode);
|
||||
let boxed_layout = layout_interner.insert(Layout::Boxed(inner_layout));
|
||||
refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner);
|
||||
|
||||
// this function returns void
|
||||
builder.build_return(None);
|
||||
match mode {
|
||||
Mode::Inc => {
|
||||
refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner);
|
||||
builder.build_return(None);
|
||||
}
|
||||
Mode::Dec => {
|
||||
// if the box is unique, also decrement its inner value
|
||||
let do_recurse_block = env.context.append_basic_block(fn_val, "do_recurse");
|
||||
let no_recurse_block = env.context.append_basic_block(fn_val, "no_recurse");
|
||||
|
||||
builder.build_conditional_branch(
|
||||
refcount_ptr.is_1(env),
|
||||
do_recurse_block,
|
||||
no_recurse_block,
|
||||
);
|
||||
|
||||
{
|
||||
env.builder.position_at_end(do_recurse_block);
|
||||
|
||||
let inner = load_roc_value(env, layout_interner, inner_layout, boxed, "inner");
|
||||
|
||||
modify_refcount_layout(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
call_mode,
|
||||
inner,
|
||||
inner_layout,
|
||||
);
|
||||
|
||||
refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner);
|
||||
env.builder.build_return(None);
|
||||
}
|
||||
|
||||
{
|
||||
env.builder.position_at_end(no_recurse_block);
|
||||
|
||||
refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner);
|
||||
env.builder.build_return(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Build an increment or decrement function for a specific layout
|
||||
|
|
|
@ -1947,8 +1947,15 @@ impl<'a> LowLevelCall<'a> {
|
|||
self.load_args(backend);
|
||||
backend.code_builder.i32_eqz();
|
||||
}
|
||||
RefCountInc => self.load_args_and_call_zig(backend, bitcode::UTILS_INCREF),
|
||||
RefCountDec => self.load_args_and_call_zig(backend, bitcode::UTILS_DECREF),
|
||||
RefCountIncRcPtr => self.load_args_and_call_zig(backend, bitcode::UTILS_INCREF_RC_PTR),
|
||||
RefCountDecRcPtr => self.load_args_and_call_zig(backend, bitcode::UTILS_DECREF_RC_PTR),
|
||||
RefCountIncDataPtr => {
|
||||
self.load_args_and_call_zig(backend, bitcode::UTILS_INCREF_DATA_PTR)
|
||||
}
|
||||
RefCountDecDataPtr => {
|
||||
self.load_args_and_call_zig(backend, bitcode::UTILS_DECREF_DATA_PTR)
|
||||
}
|
||||
RefCountIsUnique => self.load_args_and_call_zig(backend, bitcode::UTILS_IS_UNIQUE),
|
||||
|
||||
PtrCast => {
|
||||
let code_builder = &mut backend.code_builder;
|
||||
|
|
|
@ -19,8 +19,8 @@ use roc_constrain::module::constrain_module;
|
|||
use roc_debug_flags::dbg_do;
|
||||
#[cfg(debug_assertions)]
|
||||
use roc_debug_flags::{
|
||||
ROC_CHECK_MONO_IR, ROC_PRINT_IR_AFTER_REFCOUNT, ROC_PRINT_IR_AFTER_RESET_REUSE,
|
||||
ROC_PRINT_IR_AFTER_SPECIALIZATION, ROC_PRINT_LOAD_LOG,
|
||||
ROC_CHECK_MONO_IR, ROC_PRINT_IR_AFTER_DROP_SPECIALIZATION, ROC_PRINT_IR_AFTER_REFCOUNT,
|
||||
ROC_PRINT_IR_AFTER_RESET_REUSE, ROC_PRINT_IR_AFTER_SPECIALIZATION, ROC_PRINT_LOAD_LOG,
|
||||
};
|
||||
use roc_derive::SharedDerivedModule;
|
||||
use roc_error_macros::internal_error;
|
||||
|
@ -30,7 +30,6 @@ use roc_module::symbol::{
|
|||
IdentIds, IdentIdsByModule, Interns, ModuleId, ModuleIds, PQModuleName, PackageModuleIds,
|
||||
PackageQualified, Symbol,
|
||||
};
|
||||
use roc_mono::inc_dec;
|
||||
use roc_mono::ir::{
|
||||
CapturedSymbols, ExternalSpecializations, GlueLayouts, LambdaSetId, PartialProc, Proc,
|
||||
ProcLayout, Procs, ProcsBase, UpdateModeIds,
|
||||
|
@ -40,6 +39,7 @@ use roc_mono::layout::{
|
|||
GlobalLayoutInterner, LambdaName, Layout, LayoutCache, LayoutProblem, Niche, STLayoutInterner,
|
||||
};
|
||||
use roc_mono::reset_reuse;
|
||||
use roc_mono::{drop_specialization, inc_dec};
|
||||
use roc_packaging::cache::RocCacheDir;
|
||||
use roc_parse::ast::{
|
||||
self, CommentOrNewline, Defs, Expr, ExtractSpaces, Pattern, Spaced, StrLiteral, TypeAnnotation,
|
||||
|
@ -3121,6 +3121,21 @@ fn update<'a>(
|
|||
|
||||
debug_print_ir!(state, &layout_interner, ROC_PRINT_IR_AFTER_RESET_REUSE);
|
||||
|
||||
drop_specialization::specialize_drops(
|
||||
arena,
|
||||
&mut layout_interner,
|
||||
module_id,
|
||||
ident_ids,
|
||||
state.target_info,
|
||||
&mut state.procedures,
|
||||
);
|
||||
|
||||
debug_print_ir!(
|
||||
state,
|
||||
&layout_interner,
|
||||
ROC_PRINT_IR_AFTER_DROP_SPECIALIZATION
|
||||
);
|
||||
|
||||
// This is not safe with the new non-recursive RC updates that we do for tag unions
|
||||
//
|
||||
// Proc::optimize_refcount_operations(
|
||||
|
|
|
@ -116,8 +116,11 @@ pub enum LowLevel {
|
|||
Hash,
|
||||
PtrCast,
|
||||
PtrWrite,
|
||||
RefCountInc,
|
||||
RefCountDec,
|
||||
RefCountIncRcPtr,
|
||||
RefCountDecRcPtr,
|
||||
RefCountIncDataPtr,
|
||||
RefCountDecDataPtr,
|
||||
RefCountIsUnique,
|
||||
BoxExpr,
|
||||
UnboxExpr,
|
||||
Unreachable,
|
||||
|
@ -155,6 +158,7 @@ impl LowLevel {
|
|||
/// Some wrapper functions can just be replaced by lowlevels in the backend for performance.
|
||||
/// For example, Num.add should be an instruction, not a function call.
|
||||
/// Variant names are chosen to help explain what to do when adding new lowlevels
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum LowLevelWrapperType {
|
||||
/// This wrapper function contains no logic and we can remove it in code gen
|
||||
CanBeReplacedBy(LowLevel),
|
||||
|
@ -221,8 +225,11 @@ macro_rules! map_symbol_to_lowlevel {
|
|||
LowLevel::Hash => unimplemented!(),
|
||||
LowLevel::PtrCast => unimplemented!(),
|
||||
LowLevel::PtrWrite => unimplemented!(),
|
||||
LowLevel::RefCountInc => unimplemented!(),
|
||||
LowLevel::RefCountDec => unimplemented!(),
|
||||
LowLevel::RefCountIncRcPtr => unimplemented!(),
|
||||
LowLevel::RefCountDecRcPtr=> unimplemented!(),
|
||||
LowLevel::RefCountIncDataPtr => unimplemented!(),
|
||||
LowLevel::RefCountDecDataPtr=> unimplemented!(),
|
||||
LowLevel::RefCountIsUnique => unimplemented!(),
|
||||
|
||||
// these are not implemented, not sure why
|
||||
LowLevel::StrFromInt => unimplemented!(),
|
||||
|
|
|
@ -1031,7 +1031,8 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[Ownership] {
|
|||
unreachable!("These lowlevel operations are turned into mono Expr's")
|
||||
}
|
||||
|
||||
PtrCast | PtrWrite | RefCountInc | RefCountDec => {
|
||||
PtrCast | PtrWrite | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr
|
||||
| RefCountDecDataPtr | RefCountIsUnique => {
|
||||
unreachable!("Only inserted *after* borrow checking: {:?}", op);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -642,6 +642,7 @@ fn eq_boxed<'a>(
|
|||
}
|
||||
|
||||
/// List equality
|
||||
/// TODO, ListGetUnsafe no longer increments the refcount, so we can use it here.
|
||||
/// We can't use `ListGetUnsafe` because it increments the refcount, and we don't want that.
|
||||
/// Another way to dereference a heap pointer is to use `Expr::UnionAtIndex`.
|
||||
/// To achieve this we use `PtrCast` to cast the element pointer to a "Box" layout.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::collections::CollectIn;
|
||||
use bumpalo::Bump;
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
||||
|
@ -40,6 +41,10 @@ impl HelperOp {
|
|||
fn is_decref(&self) -> bool {
|
||||
matches!(self, Self::DecRef(_))
|
||||
}
|
||||
|
||||
fn is_dec(&self) -> bool {
|
||||
matches!(self, Self::Dec)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -80,7 +85,6 @@ pub struct CodeGenHelp<'a> {
|
|||
home: ModuleId,
|
||||
target_info: TargetInfo,
|
||||
layout_isize: InLayout<'a>,
|
||||
union_refcount: UnionLayout<'a>,
|
||||
specializations: Vec<'a, Specialization<'a>>,
|
||||
debug_recursion_depth: usize,
|
||||
}
|
||||
|
@ -89,15 +93,11 @@ impl<'a> CodeGenHelp<'a> {
|
|||
pub fn new(arena: &'a Bump, target_info: TargetInfo, home: ModuleId) -> Self {
|
||||
let layout_isize = Layout::isize(target_info);
|
||||
|
||||
// Refcount is a boxed isize. TODO: use the new Box layout when dev backends support it
|
||||
let union_refcount = UnionLayout::NonNullableUnwrapped(arena.alloc([layout_isize]));
|
||||
|
||||
CodeGenHelp {
|
||||
arena,
|
||||
home,
|
||||
target_info,
|
||||
layout_isize,
|
||||
union_refcount,
|
||||
specializations: Vec::with_capacity_in(16, arena),
|
||||
debug_recursion_depth: 0,
|
||||
}
|
||||
|
@ -538,46 +538,44 @@ impl<'a> CodeGenHelp<'a> {
|
|||
|
||||
fn union_tail_recursion_fields(
|
||||
&self,
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
union_in_layout: InLayout<'a>,
|
||||
union: UnionLayout<'a>,
|
||||
) -> (bool, Vec<'a, Option<usize>>) {
|
||||
) -> Option<Vec<'a, Option<usize>>> {
|
||||
use UnionLayout::*;
|
||||
match union {
|
||||
NonRecursive(_) => (false, bumpalo::vec![in self.arena]),
|
||||
NonRecursive(_) => None,
|
||||
|
||||
Recursive(tags) => self.union_tail_recursion_fields_help(layout_interner, tags),
|
||||
Recursive(tags) => self.union_tail_recursion_fields_help(union_in_layout, tags),
|
||||
|
||||
NonNullableUnwrapped(field_layouts) => {
|
||||
self.union_tail_recursion_fields_help(layout_interner, &[field_layouts])
|
||||
self.union_tail_recursion_fields_help(union_in_layout, &[field_layouts])
|
||||
}
|
||||
|
||||
NullableWrapped {
|
||||
other_tags: tags, ..
|
||||
} => self.union_tail_recursion_fields_help(layout_interner, tags),
|
||||
} => self.union_tail_recursion_fields_help(union_in_layout, tags),
|
||||
|
||||
NullableUnwrapped { other_fields, .. } => {
|
||||
self.union_tail_recursion_fields_help(layout_interner, &[other_fields])
|
||||
self.union_tail_recursion_fields_help(union_in_layout, &[other_fields])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn union_tail_recursion_fields_help(
|
||||
&self,
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
in_layout: InLayout<'a>,
|
||||
tags: &[&'a [InLayout<'a>]],
|
||||
) -> (bool, Vec<'a, Option<usize>>) {
|
||||
let mut can_use_tailrec = false;
|
||||
let mut tailrec_indices = Vec::with_capacity_in(tags.len(), self.arena);
|
||||
) -> Option<Vec<'a, Option<usize>>> {
|
||||
let tailrec_indices = tags
|
||||
.iter()
|
||||
.map(|fields| fields.iter().position(|f| *f == in_layout))
|
||||
.collect_in::<Vec<_>>(self.arena);
|
||||
|
||||
for fields in tags.iter() {
|
||||
let found_index = fields
|
||||
.iter()
|
||||
.position(|f| matches!(layout_interner.get(*f), Layout::RecursivePointer(_)));
|
||||
tailrec_indices.push(found_index);
|
||||
can_use_tailrec |= found_index.is_some();
|
||||
if tailrec_indices.iter().any(|i| i.is_some()) {
|
||||
None
|
||||
} else {
|
||||
Some(tailrec_indices)
|
||||
}
|
||||
|
||||
(can_use_tailrec, tailrec_indices)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -186,6 +186,51 @@ pub fn refcount_generic<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
fn if_unique<'a>(
|
||||
root: &mut CodeGenHelp<'a>,
|
||||
ident_ids: &mut IdentIds,
|
||||
value: Symbol,
|
||||
when_unique: impl FnOnce(JoinPointId) -> Stmt<'a>,
|
||||
when_done: Stmt<'a>,
|
||||
) -> Stmt<'a> {
|
||||
// joinpoint f =
|
||||
// <when_done>
|
||||
// in
|
||||
// if is_unique <value> then
|
||||
// <when_unique>(f)
|
||||
// else
|
||||
// jump f
|
||||
|
||||
let joinpoint = root.create_symbol(ident_ids, "is_unique_joinpoint");
|
||||
let joinpoint = JoinPointId(joinpoint);
|
||||
|
||||
let is_unique = root.create_symbol(ident_ids, "is_unique");
|
||||
|
||||
let mut stmt = Stmt::if_then_else(
|
||||
root.arena,
|
||||
is_unique,
|
||||
Layout::UNIT,
|
||||
when_unique(joinpoint),
|
||||
root.arena.alloc(Stmt::Jump(joinpoint, &[])),
|
||||
);
|
||||
|
||||
stmt = Stmt::Join {
|
||||
id: joinpoint,
|
||||
parameters: &[],
|
||||
body: root.arena.alloc(when_done),
|
||||
remainder: root.arena.alloc(stmt),
|
||||
};
|
||||
|
||||
let_lowlevel(
|
||||
root.arena,
|
||||
root.layout_isize,
|
||||
is_unique,
|
||||
LowLevel::RefCountIsUnique,
|
||||
&[value],
|
||||
root.arena.alloc(stmt),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn refcount_reset_proc_body<'a>(
|
||||
root: &mut CodeGenHelp<'a>,
|
||||
ident_ids: &mut IdentIds,
|
||||
|
@ -291,24 +336,15 @@ pub fn refcount_reset_proc_body<'a>(
|
|||
.unwrap();
|
||||
let decrement_stmt = |next| Stmt::Let(decrement_unit, decrement_expr, LAYOUT_UNIT, next);
|
||||
|
||||
// Zero
|
||||
let zero = root.create_symbol(ident_ids, "zero");
|
||||
let zero_expr = Expr::Literal(Literal::Int(0i128.to_ne_bytes()));
|
||||
let zero_stmt = |next| Stmt::Let(zero, zero_expr, root.layout_isize, next);
|
||||
|
||||
// Null pointer with union layout
|
||||
let null = root.create_symbol(ident_ids, "null");
|
||||
let null_stmt =
|
||||
|next| let_lowlevel(root.arena, root.layout_isize, null, PtrCast, &[zero], next);
|
||||
let null_stmt = |next| Stmt::Let(null, Expr::NullPointer, layout, next);
|
||||
|
||||
decrement_stmt(root.arena.alloc(
|
||||
//
|
||||
zero_stmt(root.arena.alloc(
|
||||
null_stmt(root.arena.alloc(
|
||||
//
|
||||
null_stmt(root.arena.alloc(
|
||||
//
|
||||
Stmt::Ret(null),
|
||||
)),
|
||||
Stmt::Ret(null),
|
||||
)),
|
||||
))
|
||||
};
|
||||
|
@ -348,12 +384,8 @@ pub fn refcount_reset_proc_body<'a>(
|
|||
);
|
||||
|
||||
// Refcount value
|
||||
let rc_expr = Expr::UnionAtIndex {
|
||||
structure: rc_ptr,
|
||||
tag_id: 0,
|
||||
union_layout: root.union_refcount,
|
||||
index: 0,
|
||||
};
|
||||
let rc_expr = Expr::ExprUnbox { symbol: rc_ptr };
|
||||
|
||||
let rc_stmt = Stmt::Let(
|
||||
rc,
|
||||
rc_expr,
|
||||
|
@ -361,6 +393,9 @@ pub fn refcount_reset_proc_body<'a>(
|
|||
root.arena.alloc(refcount_1_stmt),
|
||||
);
|
||||
|
||||
// a Box never masks bits
|
||||
let mask_lower_bits = false;
|
||||
|
||||
// Refcount pointer
|
||||
let rc_ptr_stmt = {
|
||||
rc_ptr_from_data_ptr_help(
|
||||
|
@ -368,7 +403,7 @@ pub fn refcount_reset_proc_body<'a>(
|
|||
ident_ids,
|
||||
structure,
|
||||
rc_ptr,
|
||||
union_layout.stores_tag_id_in_pointer(root.target_info),
|
||||
mask_lower_bits,
|
||||
root.arena.alloc(rc_stmt),
|
||||
addr,
|
||||
recursion_ptr,
|
||||
|
@ -403,39 +438,7 @@ pub fn refcount_resetref_proc_body<'a>(
|
|||
let recursion_ptr = layout_interner.insert(Layout::RecursivePointer(layout));
|
||||
|
||||
// Reset structure is unique. Return a pointer to the allocation.
|
||||
let then_stmt = {
|
||||
let alignment = root.create_symbol(ident_ids, "alignment");
|
||||
let alignment_int = layout_interner
|
||||
.get(layout)
|
||||
.allocation_alignment_bytes(layout_interner, root.target_info);
|
||||
let alignment_expr = Expr::Literal(Literal::Int((alignment_int as i128).to_ne_bytes()));
|
||||
let alloc_addr = root.create_symbol(ident_ids, "alloc_addr");
|
||||
let alloc_addr_expr = Expr::Call(Call {
|
||||
call_type: CallType::LowLevel {
|
||||
op: LowLevel::NumSubWrap,
|
||||
update_mode: UpdateModeId::BACKEND_DUMMY,
|
||||
},
|
||||
arguments: root.arena.alloc([addr, alignment]),
|
||||
});
|
||||
|
||||
Stmt::Let(
|
||||
alignment,
|
||||
alignment_expr,
|
||||
root.layout_isize,
|
||||
root.arena.alloc(
|
||||
//
|
||||
Stmt::Let(
|
||||
alloc_addr,
|
||||
alloc_addr_expr,
|
||||
root.layout_isize,
|
||||
root.arena.alloc(
|
||||
//
|
||||
Stmt::Ret(alloc_addr),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
};
|
||||
let then_stmt = Stmt::Ret(addr);
|
||||
|
||||
// Reset structure is not unique. Decrement it and return a NULL pointer.
|
||||
let else_stmt = {
|
||||
|
@ -451,35 +454,26 @@ pub fn refcount_resetref_proc_body<'a>(
|
|||
.unwrap();
|
||||
let decrement_stmt = |next| Stmt::Let(decrement_unit, decrement_expr, LAYOUT_UNIT, next);
|
||||
|
||||
// Zero
|
||||
let zero = root.create_symbol(ident_ids, "zero");
|
||||
let zero_expr = Expr::Literal(Literal::Int(0i128.to_ne_bytes()));
|
||||
let zero_stmt = |next| Stmt::Let(zero, zero_expr, root.layout_isize, next);
|
||||
|
||||
// Null pointer with union layout
|
||||
let null = root.create_symbol(ident_ids, "null");
|
||||
let null_stmt =
|
||||
|next| let_lowlevel(root.arena, root.layout_isize, null, PtrCast, &[zero], next);
|
||||
let null_stmt = |next| Stmt::Let(null, Expr::NullPointer, layout, next);
|
||||
|
||||
decrement_stmt(root.arena.alloc(
|
||||
//
|
||||
zero_stmt(root.arena.alloc(
|
||||
null_stmt(root.arena.alloc(
|
||||
//
|
||||
null_stmt(root.arena.alloc(
|
||||
//
|
||||
Stmt::Ret(null),
|
||||
)),
|
||||
Stmt::Ret(null),
|
||||
)),
|
||||
))
|
||||
};
|
||||
|
||||
let if_stmt = Stmt::Switch {
|
||||
cond_symbol: is_unique,
|
||||
cond_layout: LAYOUT_BOOL,
|
||||
branches: root.arena.alloc([(1, BranchInfo::None, then_stmt)]),
|
||||
default_branch: (BranchInfo::None, root.arena.alloc(else_stmt)),
|
||||
ret_layout: layout,
|
||||
};
|
||||
let if_stmt = Stmt::if_then_else(
|
||||
root.arena,
|
||||
is_unique,
|
||||
layout,
|
||||
then_stmt,
|
||||
root.arena.alloc(else_stmt),
|
||||
);
|
||||
|
||||
// Uniqueness test
|
||||
let is_unique_stmt = {
|
||||
|
@ -508,12 +502,8 @@ pub fn refcount_resetref_proc_body<'a>(
|
|||
);
|
||||
|
||||
// Refcount value
|
||||
let rc_expr = Expr::UnionAtIndex {
|
||||
structure: rc_ptr,
|
||||
tag_id: 0,
|
||||
union_layout: root.union_refcount,
|
||||
index: 0,
|
||||
};
|
||||
let rc_expr = Expr::ExprUnbox { symbol: rc_ptr };
|
||||
|
||||
let rc_stmt = Stmt::Let(
|
||||
rc,
|
||||
rc_expr,
|
||||
|
@ -521,6 +511,9 @@ pub fn refcount_resetref_proc_body<'a>(
|
|||
root.arena.alloc(refcount_1_stmt),
|
||||
);
|
||||
|
||||
// a Box never masks bits
|
||||
let mask_lower_bits = false;
|
||||
|
||||
// Refcount pointer
|
||||
let rc_ptr_stmt = {
|
||||
rc_ptr_from_data_ptr_help(
|
||||
|
@ -528,7 +521,7 @@ pub fn refcount_resetref_proc_body<'a>(
|
|||
ident_ids,
|
||||
structure,
|
||||
rc_ptr,
|
||||
union_layout.stores_tag_id_in_pointer(root.target_info),
|
||||
mask_lower_bits,
|
||||
root.arena.alloc(rc_stmt),
|
||||
addr,
|
||||
recursion_ptr,
|
||||
|
@ -561,33 +554,7 @@ fn refcount_args<'a>(root: &CodeGenHelp<'a>, ctx: &Context<'a>, structure: Symbo
|
|||
}
|
||||
}
|
||||
|
||||
// Subtract a constant from a pointer to find the refcount
|
||||
// Also does some type casting, so that we have different Symbols and Layouts
|
||||
// for the 'pointer' and 'integer' versions of the address.
|
||||
// This helps to avoid issues with the backends Symbol->Layout mapping.
|
||||
pub fn rc_ptr_from_data_ptr<'a>(
|
||||
root: &CodeGenHelp<'a>,
|
||||
ident_ids: &mut IdentIds,
|
||||
structure: Symbol,
|
||||
rc_ptr_sym: Symbol,
|
||||
mask_lower_bits: bool,
|
||||
following: &'a Stmt<'a>,
|
||||
recursive_layout: InLayout<'a>,
|
||||
) -> Stmt<'a> {
|
||||
let addr_sym = root.create_symbol(ident_ids, "addr");
|
||||
rc_ptr_from_data_ptr_help(
|
||||
root,
|
||||
ident_ids,
|
||||
structure,
|
||||
rc_ptr_sym,
|
||||
mask_lower_bits,
|
||||
following,
|
||||
addr_sym,
|
||||
recursive_layout,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn rc_ptr_from_data_ptr_help<'a>(
|
||||
fn rc_ptr_from_data_ptr_help<'a>(
|
||||
root: &CodeGenHelp<'a>,
|
||||
ident_ids: &mut IdentIds,
|
||||
structure: Symbol,
|
||||
|
@ -700,7 +667,7 @@ fn modify_refcount<'a>(
|
|||
root: &CodeGenHelp<'a>,
|
||||
ident_ids: &mut IdentIds,
|
||||
ctx: &mut Context<'a>,
|
||||
rc_ptr: Symbol,
|
||||
data_ptr: Symbol,
|
||||
alignment: u32,
|
||||
following: &'a Stmt<'a>,
|
||||
) -> Stmt<'a> {
|
||||
|
@ -710,10 +677,10 @@ fn modify_refcount<'a>(
|
|||
HelperOp::Inc => {
|
||||
let zig_call_expr = Expr::Call(Call {
|
||||
call_type: CallType::LowLevel {
|
||||
op: LowLevel::RefCountInc,
|
||||
op: LowLevel::RefCountIncDataPtr,
|
||||
update_mode: UpdateModeId::BACKEND_DUMMY,
|
||||
},
|
||||
arguments: root.arena.alloc([rc_ptr, Symbol::ARG_2]),
|
||||
arguments: root.arena.alloc([data_ptr, Symbol::ARG_2]),
|
||||
});
|
||||
Stmt::Let(zig_call_result, zig_call_expr, LAYOUT_UNIT, following)
|
||||
}
|
||||
|
@ -726,10 +693,10 @@ fn modify_refcount<'a>(
|
|||
|
||||
let zig_call_expr = Expr::Call(Call {
|
||||
call_type: CallType::LowLevel {
|
||||
op: LowLevel::RefCountDec,
|
||||
op: LowLevel::RefCountDecDataPtr,
|
||||
update_mode: UpdateModeId::BACKEND_DUMMY,
|
||||
},
|
||||
arguments: root.arena.alloc([rc_ptr, alignment_sym]),
|
||||
arguments: root.arena.alloc([data_ptr, alignment_sym]),
|
||||
});
|
||||
let zig_call_stmt = Stmt::Let(zig_call_result, zig_call_expr, LAYOUT_UNIT, following);
|
||||
|
||||
|
@ -782,7 +749,7 @@ fn refcount_str<'a>(
|
|||
let is_big_str_stmt = |next| Stmt::Let(is_big_str, is_big_str_expr, LAYOUT_BOOL, next);
|
||||
|
||||
// Get the pointer to the string elements
|
||||
let elements = root.create_symbol(ident_ids, "elements");
|
||||
let elements = root.create_symbol(ident_ids, "characters");
|
||||
let elements_expr = Expr::StructAtIndex {
|
||||
index: 0,
|
||||
field_layouts,
|
||||
|
@ -791,7 +758,6 @@ fn refcount_str<'a>(
|
|||
let elements_stmt = |next| Stmt::Let(elements, elements_expr, layout_isize, next);
|
||||
|
||||
// A pointer to the refcount value itself
|
||||
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
|
||||
let alignment = root.target_info.ptr_width() as u32;
|
||||
|
||||
let ret_unit_stmt = rc_return_stmt(root, ident_ids, ctx);
|
||||
|
@ -799,38 +765,21 @@ fn refcount_str<'a>(
|
|||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
rc_ptr,
|
||||
elements,
|
||||
alignment,
|
||||
root.arena.alloc(ret_unit_stmt),
|
||||
);
|
||||
|
||||
// Generate an `if` to skip small strings but modify big strings
|
||||
let then_branch = elements_stmt(root.arena.alloc(
|
||||
//
|
||||
rc_ptr_from_data_ptr(
|
||||
root,
|
||||
ident_ids,
|
||||
elements,
|
||||
rc_ptr,
|
||||
false,
|
||||
root.arena.alloc(
|
||||
//
|
||||
mod_rc_stmt,
|
||||
),
|
||||
Layout::OPAQUE_PTR,
|
||||
),
|
||||
));
|
||||
let then_branch = elements_stmt(root.arena.alloc(mod_rc_stmt));
|
||||
|
||||
let if_stmt = Stmt::Switch {
|
||||
cond_symbol: is_big_str,
|
||||
cond_layout: LAYOUT_BOOL,
|
||||
branches: root.arena.alloc([(1, BranchInfo::None, then_branch)]),
|
||||
default_branch: (
|
||||
BranchInfo::None,
|
||||
root.arena.alloc(rc_return_stmt(root, ident_ids, ctx)),
|
||||
),
|
||||
ret_layout: LAYOUT_UNIT,
|
||||
};
|
||||
let if_stmt = Stmt::if_then_else(
|
||||
root.arena,
|
||||
is_big_str,
|
||||
Layout::UNIT,
|
||||
then_branch,
|
||||
root.arena.alloc(rc_return_stmt(root, ident_ids, ctx)),
|
||||
);
|
||||
|
||||
// Combine the statements in sequence
|
||||
last_word_stmt(root.arena.alloc(
|
||||
|
@ -896,7 +845,6 @@ fn refcount_list<'a>(
|
|||
// (elements first, to avoid use-after-free for Dec)
|
||||
//
|
||||
|
||||
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
|
||||
let alignment = Ord::max(
|
||||
root.target_info.ptr_width() as u32,
|
||||
layout_interner.alignment_bytes(elem_layout),
|
||||
|
@ -907,23 +855,13 @@ fn refcount_list<'a>(
|
|||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
rc_ptr,
|
||||
elements,
|
||||
alignment,
|
||||
arena.alloc(ret_stmt),
|
||||
);
|
||||
|
||||
let get_rc_and_modify_list = rc_ptr_from_data_ptr(
|
||||
root,
|
||||
ident_ids,
|
||||
elements,
|
||||
rc_ptr,
|
||||
false,
|
||||
arena.alloc(modify_list),
|
||||
Layout::OPAQUE_PTR,
|
||||
);
|
||||
|
||||
let modify_elems_and_list =
|
||||
if layout_interner.get(elem_layout).is_refcounted() && !ctx.op.is_decref() {
|
||||
if layout_interner.get(elem_layout).is_refcounted() && ctx.op.is_dec() {
|
||||
refcount_list_elems(
|
||||
root,
|
||||
ident_ids,
|
||||
|
@ -934,10 +872,10 @@ fn refcount_list<'a>(
|
|||
box_layout,
|
||||
len,
|
||||
elements,
|
||||
get_rc_and_modify_list,
|
||||
modify_list,
|
||||
)
|
||||
} else {
|
||||
get_rc_and_modify_list
|
||||
modify_list
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -952,15 +890,13 @@ fn refcount_list<'a>(
|
|||
)),
|
||||
);
|
||||
|
||||
let if_stmt = Stmt::Switch {
|
||||
cond_symbol: is_empty,
|
||||
cond_layout: LAYOUT_BOOL,
|
||||
branches: root
|
||||
.arena
|
||||
.alloc([(1, BranchInfo::None, rc_return_stmt(root, ident_ids, ctx))]),
|
||||
default_branch: (BranchInfo::None, non_empty_branch),
|
||||
ret_layout: LAYOUT_UNIT,
|
||||
};
|
||||
let if_stmt = Stmt::if_then_else(
|
||||
root.arena,
|
||||
is_empty,
|
||||
Layout::UNIT,
|
||||
rc_return_stmt(root, ident_ids, ctx),
|
||||
non_empty_branch,
|
||||
);
|
||||
|
||||
len_stmt(arena.alloc(
|
||||
//
|
||||
|
@ -1179,7 +1115,7 @@ fn refcount_union<'a>(
|
|||
ident_ids: &mut IdentIds,
|
||||
ctx: &mut Context<'a>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout: InLayout<'a>,
|
||||
union_in_layout: InLayout<'a>,
|
||||
union: UnionLayout<'a>,
|
||||
structure: Symbol,
|
||||
) -> Stmt<'a> {
|
||||
|
@ -1202,8 +1138,8 @@ fn refcount_union<'a>(
|
|||
),
|
||||
|
||||
Recursive(tags) => {
|
||||
let (is_tailrec, tail_idx) = root.union_tail_recursion_fields(layout_interner, union);
|
||||
if is_tailrec && !ctx.op.is_decref() {
|
||||
let tailrec_idx = root.union_tail_recursion_fields(union_in_layout, union);
|
||||
if let (Some(tail_idx), true) = (tailrec_idx, ctx.op.is_dec()) {
|
||||
refcount_union_tailrec(
|
||||
root,
|
||||
ident_ids,
|
||||
|
@ -1216,7 +1152,6 @@ fn refcount_union<'a>(
|
|||
structure,
|
||||
)
|
||||
} else {
|
||||
let recursive_ptr = layout_interner.insert(Layout::RecursivePointer(layout));
|
||||
refcount_union_rec(
|
||||
root,
|
||||
ident_ids,
|
||||
|
@ -1225,7 +1160,6 @@ fn refcount_union<'a>(
|
|||
union,
|
||||
tags,
|
||||
None,
|
||||
recursive_ptr,
|
||||
structure,
|
||||
)
|
||||
}
|
||||
|
@ -1237,7 +1171,6 @@ fn refcount_union<'a>(
|
|||
// a direct RecursionPointer is only possible if there's at least one non-recursive variant.
|
||||
// This nesting makes it harder to do tail recursion, so we just don't.
|
||||
let tags = root.arena.alloc([field_layouts]);
|
||||
let recursive_ptr = layout_interner.insert(Layout::RecursivePointer(layout));
|
||||
refcount_union_rec(
|
||||
root,
|
||||
ident_ids,
|
||||
|
@ -1246,7 +1179,6 @@ fn refcount_union<'a>(
|
|||
union,
|
||||
tags,
|
||||
None,
|
||||
recursive_ptr,
|
||||
structure,
|
||||
)
|
||||
}
|
||||
|
@ -1256,8 +1188,8 @@ fn refcount_union<'a>(
|
|||
nullable_id,
|
||||
} => {
|
||||
let null_id = Some(nullable_id);
|
||||
let (is_tailrec, tail_idx) = root.union_tail_recursion_fields(layout_interner, union);
|
||||
if is_tailrec && !ctx.op.is_decref() {
|
||||
let tailrec_idx = root.union_tail_recursion_fields(union_in_layout, union);
|
||||
if let (Some(tail_idx), true) = (tailrec_idx, ctx.op.is_dec()) {
|
||||
refcount_union_tailrec(
|
||||
root,
|
||||
ident_ids,
|
||||
|
@ -1270,7 +1202,6 @@ fn refcount_union<'a>(
|
|||
structure,
|
||||
)
|
||||
} else {
|
||||
let recursive_ptr = layout_interner.insert(Layout::RecursivePointer(layout));
|
||||
refcount_union_rec(
|
||||
root,
|
||||
ident_ids,
|
||||
|
@ -1279,7 +1210,6 @@ fn refcount_union<'a>(
|
|||
union,
|
||||
tags,
|
||||
null_id,
|
||||
recursive_ptr,
|
||||
structure,
|
||||
)
|
||||
}
|
||||
|
@ -1291,8 +1221,8 @@ fn refcount_union<'a>(
|
|||
} => {
|
||||
let null_id = Some(nullable_id as TagIdIntType);
|
||||
let tags = root.arena.alloc([other_fields]);
|
||||
let (is_tailrec, tail_idx) = root.union_tail_recursion_fields(layout_interner, union);
|
||||
if is_tailrec && !ctx.op.is_decref() {
|
||||
let tailrec_idx = root.union_tail_recursion_fields(union_in_layout, union);
|
||||
if let (Some(tail_idx), true) = (tailrec_idx, ctx.op.is_dec()) {
|
||||
refcount_union_tailrec(
|
||||
root,
|
||||
ident_ids,
|
||||
|
@ -1305,7 +1235,6 @@ fn refcount_union<'a>(
|
|||
structure,
|
||||
)
|
||||
} else {
|
||||
let recursive_ptr = layout_interner.insert(Layout::RecursivePointer(layout));
|
||||
refcount_union_rec(
|
||||
root,
|
||||
ident_ids,
|
||||
|
@ -1314,7 +1243,6 @@ fn refcount_union<'a>(
|
|||
union,
|
||||
tags,
|
||||
null_id,
|
||||
recursive_ptr,
|
||||
structure,
|
||||
)
|
||||
}
|
||||
|
@ -1391,17 +1319,12 @@ fn refcount_union_contents<'a>(
|
|||
if let Some(id) = null_id {
|
||||
let ret = rc_return_stmt(root, ident_ids, ctx);
|
||||
tag_branches.push((id as u64, BranchInfo::None, ret));
|
||||
}
|
||||
|
||||
let mut tag_id: TagIdIntType = 0;
|
||||
for field_layouts in tag_layouts.iter() {
|
||||
match null_id {
|
||||
Some(id) if id == tag_id => {
|
||||
tag_id += 1;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
|
||||
for (field_layouts, tag_id) in tag_layouts
|
||||
.iter()
|
||||
.zip((0..).filter(|tag_id| !matches!(null_id, Some(id) if tag_id == &id)))
|
||||
{
|
||||
// After refcounting the fields, jump to modify the union itself
|
||||
// (Order is important, to avoid use-after-free for Dec)
|
||||
let following = Stmt::Jump(jp_contents_modified, &[]);
|
||||
|
@ -1426,8 +1349,6 @@ fn refcount_union_contents<'a>(
|
|||
);
|
||||
|
||||
tag_branches.push((tag_id as u64, BranchInfo::None, fields_stmt));
|
||||
|
||||
tag_id += 1;
|
||||
}
|
||||
|
||||
let default_stmt: Stmt<'a> = tag_branches.pop().unwrap().2;
|
||||
|
@ -1440,11 +1361,39 @@ fn refcount_union_contents<'a>(
|
|||
ret_layout: LAYOUT_UNIT,
|
||||
};
|
||||
|
||||
Stmt::Join {
|
||||
id: jp_contents_modified,
|
||||
parameters: &[],
|
||||
body: root.arena.alloc(next_stmt),
|
||||
remainder: root.arena.alloc(tag_id_switch),
|
||||
if let UnionLayout::NonRecursive(_) = union_layout {
|
||||
Stmt::Join {
|
||||
id: jp_contents_modified,
|
||||
parameters: &[],
|
||||
body: root.arena.alloc(next_stmt),
|
||||
remainder: root.arena.alloc(tag_id_switch),
|
||||
}
|
||||
} else {
|
||||
let is_unique = root.create_symbol(ident_ids, "is_unique");
|
||||
|
||||
let switch_with_unique_check = Stmt::if_then_else(
|
||||
root.arena,
|
||||
is_unique,
|
||||
Layout::UNIT,
|
||||
tag_id_switch,
|
||||
root.arena.alloc(Stmt::Jump(jp_contents_modified, &[])),
|
||||
);
|
||||
|
||||
let switch_with_unique_check_and_let = let_lowlevel(
|
||||
root.arena,
|
||||
Layout::BOOL,
|
||||
is_unique,
|
||||
LowLevel::RefCountIsUnique,
|
||||
&[structure],
|
||||
root.arena.alloc(switch_with_unique_check),
|
||||
);
|
||||
|
||||
Stmt::Join {
|
||||
id: jp_contents_modified,
|
||||
parameters: &[],
|
||||
body: root.arena.alloc(next_stmt),
|
||||
remainder: root.arena.alloc(switch_with_unique_check_and_let),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1456,7 +1405,6 @@ fn refcount_union_rec<'a>(
|
|||
union_layout: UnionLayout<'a>,
|
||||
tag_layouts: &'a [&'a [InLayout<'a>]],
|
||||
null_id: Option<TagIdIntType>,
|
||||
recursion_ptr: InLayout<'a>,
|
||||
structure: Symbol,
|
||||
) -> Stmt<'a> {
|
||||
let tag_id_layout = union_layout.tag_id_layout();
|
||||
|
@ -1475,34 +1423,21 @@ fn refcount_union_rec<'a>(
|
|||
};
|
||||
|
||||
let rc_structure_stmt = {
|
||||
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
|
||||
|
||||
let alignment = Layout::Union(union_layout)
|
||||
.allocation_alignment_bytes(layout_interner, root.target_info);
|
||||
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
|
||||
let modify_structure_stmt = modify_refcount(
|
||||
|
||||
modify_refcount(
|
||||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
rc_ptr,
|
||||
structure,
|
||||
alignment,
|
||||
root.arena.alloc(ret_stmt),
|
||||
);
|
||||
|
||||
rc_ptr_from_data_ptr(
|
||||
root,
|
||||
ident_ids,
|
||||
structure,
|
||||
rc_ptr,
|
||||
union_layout.stores_tag_id_in_pointer(root.target_info),
|
||||
root.arena.alloc(modify_structure_stmt),
|
||||
recursion_ptr,
|
||||
)
|
||||
};
|
||||
|
||||
let rc_contents_then_structure = if ctx.op.is_decref() {
|
||||
rc_structure_stmt
|
||||
} else {
|
||||
let rc_contents_then_structure = if ctx.op.is_dec() {
|
||||
refcount_union_contents(
|
||||
root,
|
||||
ident_ids,
|
||||
|
@ -1516,6 +1451,8 @@ fn refcount_union_rec<'a>(
|
|||
tag_id_layout,
|
||||
rc_structure_stmt,
|
||||
)
|
||||
} else {
|
||||
rc_structure_stmt
|
||||
};
|
||||
|
||||
if ctx.op.is_decref() && null_id.is_none() {
|
||||
|
@ -1544,7 +1481,6 @@ fn refcount_union_tailrec<'a>(
|
|||
let current = root.create_symbol(ident_ids, "current");
|
||||
let next_ptr = root.create_symbol(ident_ids, "next_ptr");
|
||||
let layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
let recursion_ptr = layout_interner.insert(Layout::RecursivePointer(layout));
|
||||
|
||||
let tag_id_layout = union_layout.tag_id_layout();
|
||||
|
||||
|
@ -1565,7 +1501,6 @@ fn refcount_union_tailrec<'a>(
|
|||
// In the control flow, this comes *after* refcounting the fields
|
||||
// It receives a `next` parameter to pass through to the outer joinpoint
|
||||
let rc_structure_stmt = {
|
||||
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
|
||||
let next_addr = root.create_symbol(ident_ids, "next_addr");
|
||||
|
||||
let exit_stmt = rc_return_stmt(root, ident_ids, ctx);
|
||||
|
@ -1590,23 +1525,13 @@ fn refcount_union_tailrec<'a>(
|
|||
};
|
||||
|
||||
let alignment = layout_interner.allocation_alignment_bytes(layout);
|
||||
let modify_structure_stmt = modify_refcount(
|
||||
modify_refcount(
|
||||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
rc_ptr,
|
||||
current,
|
||||
alignment,
|
||||
root.arena.alloc(loop_or_exit_based_on_next_addr),
|
||||
);
|
||||
|
||||
rc_ptr_from_data_ptr(
|
||||
root,
|
||||
ident_ids,
|
||||
current,
|
||||
rc_ptr,
|
||||
union_layout.stores_tag_id_in_pointer(root.target_info),
|
||||
root.arena.alloc(modify_structure_stmt),
|
||||
recursion_ptr,
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -1620,15 +1545,11 @@ fn refcount_union_tailrec<'a>(
|
|||
tag_branches.push((id as u64, BranchInfo::None, ret));
|
||||
}
|
||||
|
||||
let mut tag_id: TagIdIntType = 0;
|
||||
for (field_layouts, opt_tailrec_index) in tag_layouts.iter().zip(tailrec_indices) {
|
||||
match null_id {
|
||||
Some(id) if id == tag_id => {
|
||||
tag_id += 1;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
for ((field_layouts, opt_tailrec_index), tag_id) in tag_layouts
|
||||
.iter()
|
||||
.zip(tailrec_indices)
|
||||
.zip((0..).filter(|tag_id| !matches!(null_id, Some(id) if tag_id == &id)))
|
||||
{
|
||||
// After refcounting the fields, jump to modify the union itself.
|
||||
// The loop param is a pointer to the next union. It gets passed through two jumps.
|
||||
let (non_tailrec_fields, jump_to_modify_union) =
|
||||
|
@ -1655,20 +1576,12 @@ fn refcount_union_tailrec<'a>(
|
|||
|
||||
(filtered.into_bump_slice(), tail_stmt.unwrap())
|
||||
} else {
|
||||
let zero = root.create_symbol(ident_ids, "zero");
|
||||
let zero_expr = Expr::Literal(Literal::Int(0i128.to_ne_bytes()));
|
||||
let zero_stmt = |next| Stmt::Let(zero, zero_expr, root.layout_isize, next);
|
||||
|
||||
let null = root.create_symbol(ident_ids, "null");
|
||||
let null_stmt =
|
||||
|next| let_lowlevel(root.arena, layout, null, PtrCast, &[zero], next);
|
||||
let null_stmt = |next| Stmt::Let(null, Expr::NullPointer, layout, next);
|
||||
|
||||
let tail_stmt = zero_stmt(root.arena.alloc(
|
||||
let tail_stmt = null_stmt(root.arena.alloc(
|
||||
//
|
||||
null_stmt(root.arena.alloc(
|
||||
//
|
||||
Stmt::Jump(jp_modify_union, root.arena.alloc([null])),
|
||||
)),
|
||||
Stmt::Jump(jp_modify_union, root.arena.alloc([null])),
|
||||
));
|
||||
|
||||
let field_layouts = field_layouts
|
||||
|
@ -1694,8 +1607,6 @@ fn refcount_union_tailrec<'a>(
|
|||
);
|
||||
|
||||
tag_branches.push((tag_id as u64, BranchInfo::None, fields_stmt));
|
||||
|
||||
tag_id += 1;
|
||||
}
|
||||
|
||||
let default_stmt: Stmt<'a> = tag_branches.pop().unwrap().2;
|
||||
|
@ -1708,6 +1619,36 @@ fn refcount_union_tailrec<'a>(
|
|||
ret_layout: LAYOUT_UNIT,
|
||||
};
|
||||
|
||||
let is_unique = root.create_symbol(ident_ids, "is_unique");
|
||||
let null_pointer = root.create_symbol(ident_ids, "null_pointer");
|
||||
|
||||
let jump_with_null_ptr = Stmt::Let(
|
||||
null_pointer,
|
||||
Expr::NullPointer,
|
||||
layout_interner.insert(Layout::Union(union_layout)),
|
||||
root.arena.alloc(Stmt::Jump(
|
||||
jp_modify_union,
|
||||
root.arena.alloc([null_pointer]),
|
||||
)),
|
||||
);
|
||||
|
||||
let switch_with_unique_check = Stmt::if_then_else(
|
||||
root.arena,
|
||||
is_unique,
|
||||
Layout::UNIT,
|
||||
tag_id_switch,
|
||||
root.arena.alloc(jump_with_null_ptr),
|
||||
);
|
||||
|
||||
let switch_with_unique_check_and_let = let_lowlevel(
|
||||
root.arena,
|
||||
Layout::BOOL,
|
||||
is_unique,
|
||||
LowLevel::RefCountIsUnique,
|
||||
&[current],
|
||||
root.arena.alloc(switch_with_unique_check),
|
||||
);
|
||||
|
||||
let jp_param = Param {
|
||||
symbol: next_ptr,
|
||||
ownership: Ownership::Borrowed,
|
||||
|
@ -1718,7 +1659,7 @@ fn refcount_union_tailrec<'a>(
|
|||
id: jp_modify_union,
|
||||
parameters: root.arena.alloc([jp_param]),
|
||||
body: root.arena.alloc(rc_structure_stmt),
|
||||
remainder: root.arena.alloc(tag_id_switch),
|
||||
remainder: root.arena.alloc(switch_with_unique_check_and_let),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1804,29 +1745,19 @@ fn refcount_boxed<'a>(
|
|||
// We're defining statements in reverse, so define outer first
|
||||
//
|
||||
|
||||
let rc_ptr = root.create_symbol(ident_ids, "rc_ptr");
|
||||
let alignment = layout_interner.allocation_alignment_bytes(layout);
|
||||
let ret_stmt = rc_return_stmt(root, ident_ids, ctx);
|
||||
let modify_outer = modify_refcount(
|
||||
root,
|
||||
ident_ids,
|
||||
ctx,
|
||||
rc_ptr,
|
||||
outer,
|
||||
alignment,
|
||||
arena.alloc(ret_stmt),
|
||||
);
|
||||
|
||||
let get_rc_and_modify_outer = rc_ptr_from_data_ptr(
|
||||
root,
|
||||
ident_ids,
|
||||
outer,
|
||||
rc_ptr,
|
||||
false,
|
||||
arena.alloc(modify_outer),
|
||||
Layout::OPAQUE_PTR,
|
||||
);
|
||||
|
||||
if layout_interner.is_refcounted(inner_layout) && !ctx.op.is_decref() {
|
||||
// decrement the inner value if the operation is a decrement and the box itself is unique
|
||||
if layout_interner.is_refcounted(inner_layout) && ctx.op.is_dec() {
|
||||
let inner = root.create_symbol(ident_ids, "inner");
|
||||
let inner_expr = Expr::ExprUnbox { symbol: outer };
|
||||
|
||||
|
@ -1842,18 +1773,26 @@ fn refcount_boxed<'a>(
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
Stmt::Let(
|
||||
inner,
|
||||
inner_expr,
|
||||
inner_layout,
|
||||
arena.alloc(Stmt::Let(
|
||||
mod_inner_unit,
|
||||
mod_inner_expr,
|
||||
LAYOUT_UNIT,
|
||||
arena.alloc(get_rc_and_modify_outer),
|
||||
)),
|
||||
if_unique(
|
||||
root,
|
||||
ident_ids,
|
||||
outer,
|
||||
|id| {
|
||||
Stmt::Let(
|
||||
inner,
|
||||
inner_expr,
|
||||
inner_layout,
|
||||
arena.alloc(Stmt::Let(
|
||||
mod_inner_unit,
|
||||
mod_inner_expr,
|
||||
LAYOUT_UNIT,
|
||||
arena.alloc(Stmt::Jump(id, &[])),
|
||||
)),
|
||||
)
|
||||
},
|
||||
modify_outer,
|
||||
)
|
||||
} else {
|
||||
get_rc_and_modify_outer
|
||||
modify_outer
|
||||
}
|
||||
}
|
||||
|
|
1266
crates/compiler/mono/src/drop_specialization.rs
Normal file
1266
crates/compiler/mono/src/drop_specialization.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -10,6 +10,7 @@ use std::{collections::HashMap, hash::BuildHasherDefault};
|
|||
use bumpalo::collections::{CollectIn, Vec};
|
||||
use bumpalo::Bump;
|
||||
use roc_collections::{all::WyHash, MutMap, MutSet};
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::{low_level::LowLevelWrapperType, symbol::Symbol};
|
||||
|
||||
use crate::{
|
||||
|
@ -70,8 +71,8 @@ Implemented as two sets for efficiency.
|
|||
*/
|
||||
#[derive(Clone, Default)]
|
||||
struct SymbolRcTypes {
|
||||
owned: MutSet<Symbol>,
|
||||
borrowed: MutSet<Symbol>,
|
||||
reference_counted: MutSet<Symbol>,
|
||||
not_reference_counted: MutSet<Symbol>,
|
||||
}
|
||||
|
||||
impl SymbolRcTypes {
|
||||
|
@ -81,10 +82,10 @@ impl SymbolRcTypes {
|
|||
fn insert(&mut self, symbol: Symbol, var_rc_type: VarRcType) {
|
||||
match var_rc_type {
|
||||
VarRcType::ReferenceCounted => {
|
||||
self.owned.insert(symbol);
|
||||
self.reference_counted.insert(symbol);
|
||||
}
|
||||
VarRcType::NotReferenceCounted => {
|
||||
self.borrowed.insert(symbol);
|
||||
self.not_reference_counted.insert(symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -93,10 +94,10 @@ impl SymbolRcTypes {
|
|||
Get the reference count type of a symbol.
|
||||
*/
|
||||
fn get(&self, symbol: &Symbol) -> Option<VarRcType> {
|
||||
if self.owned.contains(symbol) {
|
||||
debug_assert!(!self.borrowed.contains(symbol));
|
||||
if self.reference_counted.contains(symbol) {
|
||||
debug_assert!(!self.not_reference_counted.contains(symbol));
|
||||
Some(VarRcType::ReferenceCounted)
|
||||
} else if self.borrowed.contains(symbol) {
|
||||
} else if self.not_reference_counted.contains(symbol) {
|
||||
Some(VarRcType::NotReferenceCounted)
|
||||
} else {
|
||||
None
|
||||
|
@ -177,15 +178,13 @@ impl<'a, 'i> SymbolRcTypesEnv<'a, 'i> {
|
|||
.map(|(_branch, info, stmt)| (info, stmt))
|
||||
.chain([(&default_branch.0, default_branch.1)])
|
||||
{
|
||||
match info {
|
||||
BranchInfo::None => (),
|
||||
BranchInfo::Constructor {
|
||||
scrutinee,
|
||||
layout,
|
||||
tag_id: _,
|
||||
} => {
|
||||
self.insert_symbol_layout_rc_type(scrutinee, layout);
|
||||
}
|
||||
if let BranchInfo::Constructor {
|
||||
scrutinee,
|
||||
layout,
|
||||
tag_id: _,
|
||||
} = info
|
||||
{
|
||||
self.insert_symbol_layout_rc_type(scrutinee, layout);
|
||||
}
|
||||
|
||||
self.insert_symbols_rc_type_stmt(stmt);
|
||||
|
@ -860,7 +859,7 @@ fn insert_refcount_operations_binding<'a>(
|
|||
stmt: &'a Stmt<'a>,
|
||||
) -> &'a Stmt<'a> {
|
||||
macro_rules! dec_borrowed {
|
||||
($symbols:expr,$stmt:expr) => {
|
||||
($symbols:expr, $stmt:expr) => {
|
||||
// Insert decrement operations for borrowed symbols if they are currently owned.
|
||||
consume_and_insert_dec_stmts(
|
||||
arena,
|
||||
|
@ -894,170 +893,7 @@ fn insert_refcount_operations_binding<'a>(
|
|||
// Literals, empty arrays, and runtime errors are not (and have nothing) reference counted.
|
||||
new_let!(stmt)
|
||||
}
|
||||
Expr::Call(Call {
|
||||
arguments,
|
||||
call_type,
|
||||
}) => match call_type {
|
||||
// A by name call refers to a normal function call.
|
||||
// Normal functions take all their parameters as owned, so we can mark them all as such.
|
||||
CallType::ByName { name, .. } => {
|
||||
// Lowlevels are wrapped in another function in order to add type signatures which help with inference.
|
||||
// But the reference counting algorithm inserts reference counting operations in the wrapper function.
|
||||
// But in a later stage, calls to the wrapper function were replaced by calls to the lowlevel function.
|
||||
// Effectively removing the inserted reference counting operations.
|
||||
// Thus to prevent that, we inline the operations here already.
|
||||
if let LowLevelWrapperType::CanBeReplacedBy(op) =
|
||||
LowLevelWrapperType::from_symbol(name.name())
|
||||
{
|
||||
let borrow_signature = lowlevel_borrow_signature(arena, op);
|
||||
let arguments_with_borrow_signature = arguments
|
||||
.iter()
|
||||
.copied()
|
||||
.zip(borrow_signature.iter().copied());
|
||||
let owned_arguments = arguments_with_borrow_signature
|
||||
.clone()
|
||||
.filter_map(|(symbol, ownership)| ownership.is_owned().then_some(symbol));
|
||||
let borrowed_arguments =
|
||||
arguments_with_borrow_signature.filter_map(|(symbol, ownership)| {
|
||||
ownership.is_borrowed().then_some(symbol)
|
||||
});
|
||||
|
||||
let new_stmt = dec_borrowed!(borrowed_arguments, stmt);
|
||||
|
||||
let new_let = new_let!(new_stmt);
|
||||
|
||||
inc_owned!(owned_arguments, new_let)
|
||||
} else {
|
||||
let new_let = new_let!(stmt);
|
||||
|
||||
inc_owned!(arguments.iter().copied(), new_let)
|
||||
}
|
||||
}
|
||||
CallType::Foreign { .. } => {
|
||||
// Foreign functions should be responsible for their own memory management.
|
||||
// But previously they were assumed to be called with borrowed parameters, so we do the same now.
|
||||
let new_stmt = dec_borrowed!(arguments.iter().copied(), stmt);
|
||||
|
||||
new_let!(new_stmt)
|
||||
}
|
||||
// Doesn't include higher order
|
||||
CallType::LowLevel {
|
||||
op: operator,
|
||||
update_mode: _,
|
||||
} => {
|
||||
let borrow_signature = lowlevel_borrow_signature(arena, *operator);
|
||||
let arguments_with_borrow_signature = arguments
|
||||
.iter()
|
||||
.copied()
|
||||
.zip(borrow_signature.iter().copied());
|
||||
let owned_arguments = arguments_with_borrow_signature
|
||||
.clone()
|
||||
.filter_map(|(symbol, ownership)| ownership.is_owned().then_some(symbol));
|
||||
let borrowed_arguments = arguments_with_borrow_signature
|
||||
.filter_map(|(symbol, ownership)| ownership.is_borrowed().then_some(symbol));
|
||||
|
||||
let new_stmt = dec_borrowed!(borrowed_arguments, stmt);
|
||||
|
||||
let new_let = new_let!(new_stmt);
|
||||
|
||||
inc_owned!(owned_arguments, new_let)
|
||||
}
|
||||
CallType::HigherOrder(HigherOrderLowLevel {
|
||||
op: operator,
|
||||
|
||||
closure_env_layout: _,
|
||||
|
||||
/// update mode of the higher order lowlevel itself
|
||||
update_mode: _,
|
||||
|
||||
passed_function,
|
||||
}) => {
|
||||
// Functions always take their arguments as owned.
|
||||
// (Except lowlevels, but those are wrapped in functions that take their arguments as owned and perform rc.)
|
||||
|
||||
// This should always be true, not sure where this could be set to false.
|
||||
debug_assert!(passed_function.owns_captured_environment);
|
||||
|
||||
// define macro that inserts a decref statement for a symbol amount of symbols
|
||||
macro_rules! decref_lists {
|
||||
($stmt:expr, $symbol:expr) => {
|
||||
arena.alloc(Stmt::Refcounting(ModifyRc::DecRef($symbol), $stmt))
|
||||
};
|
||||
|
||||
($stmt:expr, $symbol:expr, $($symbols:expr),+) => {{
|
||||
decref_lists!(decref_lists!($stmt, $symbol), $($symbols),+)
|
||||
}};
|
||||
}
|
||||
|
||||
match operator {
|
||||
HigherOrder::ListMap { xs } => {
|
||||
if let [_xs_symbol, _function_symbol, closure_symbol] = &arguments {
|
||||
let new_stmt = dec_borrowed!([*closure_symbol], stmt);
|
||||
let new_stmt = decref_lists!(new_stmt, *xs);
|
||||
|
||||
let new_let = new_let!(new_stmt);
|
||||
|
||||
inc_owned!([*xs].into_iter(), new_let)
|
||||
} else {
|
||||
panic!("ListMap should have 3 arguments");
|
||||
}
|
||||
}
|
||||
HigherOrder::ListMap2 { xs, ys } => {
|
||||
if let [_xs_symbol, _ys_symbol, _function_symbol, closure_symbol] =
|
||||
&arguments
|
||||
{
|
||||
let new_stmt = dec_borrowed!([*closure_symbol], stmt);
|
||||
let new_stmt = decref_lists!(new_stmt, *xs, *ys);
|
||||
|
||||
let new_let = new_let!(new_stmt);
|
||||
|
||||
inc_owned!([*xs, *ys].into_iter(), new_let)
|
||||
} else {
|
||||
panic!("ListMap2 should have 4 arguments");
|
||||
}
|
||||
}
|
||||
HigherOrder::ListMap3 { xs, ys, zs } => {
|
||||
if let [_xs_symbol, _ys_symbol, _zs_symbol, _function_symbol, closure_symbol] =
|
||||
&arguments
|
||||
{
|
||||
let new_stmt = dec_borrowed!([*closure_symbol], stmt);
|
||||
let new_stmt = decref_lists!(new_stmt, *xs, *ys, *zs);
|
||||
|
||||
let new_let = new_let!(new_stmt);
|
||||
|
||||
inc_owned!([*xs, *ys, *zs].into_iter(), new_let)
|
||||
} else {
|
||||
panic!("ListMap3 should have 5 arguments");
|
||||
}
|
||||
}
|
||||
HigherOrder::ListMap4 { xs, ys, zs, ws } => {
|
||||
if let [_xs_symbol, _ys_symbol, _zs_symbol, _ws_symbol, _function_symbol, closure_symbol] =
|
||||
&arguments
|
||||
{
|
||||
let new_stmt = dec_borrowed!([*closure_symbol], stmt);
|
||||
let new_stmt = decref_lists!(new_stmt, *xs, *ys, *zs, *ws);
|
||||
|
||||
let new_let = new_let!(new_stmt);
|
||||
|
||||
inc_owned!([*xs, *ys, *zs, *ws].into_iter(), new_let)
|
||||
} else {
|
||||
panic!("ListMap4 should have 6 arguments");
|
||||
}
|
||||
}
|
||||
HigherOrder::ListSortWith { xs } => {
|
||||
// TODO if non-unique, elements have been consumed, must still consume the list itself
|
||||
if let [_xs_symbol, _function_symbol, closure_symbol] = &arguments {
|
||||
let new_stmt = dec_borrowed!([*closure_symbol], stmt);
|
||||
let new_let = new_let!(new_stmt);
|
||||
|
||||
inc_owned!([*xs].into_iter(), new_let)
|
||||
} else {
|
||||
panic!("ListSortWith should have 3 arguments");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Expr::Tag { arguments, .. } | Expr::Struct(arguments) => {
|
||||
let new_let = new_let!(stmt);
|
||||
|
||||
|
@ -1068,13 +904,13 @@ fn insert_refcount_operations_binding<'a>(
|
|||
|
||||
inc_owned!([*symbol], new_let)
|
||||
}
|
||||
|
||||
Expr::GetTagId { structure, .. }
|
||||
| Expr::StructAtIndex { structure, .. }
|
||||
| Expr::UnionAtIndex { structure, .. }
|
||||
| Expr::ExprUnbox { symbol: structure } => {
|
||||
// All structures are alive at this point and don't have to be copied in order to take an index out/get tag id/copy values to the stack.
|
||||
// But we do want to make sure to decrement this item if it is the last reference.
|
||||
|
||||
let new_stmt = dec_borrowed!([*structure], stmt);
|
||||
|
||||
// Add an increment operation for the binding if it is reference counted and if the expression creates a new reference to a value.
|
||||
|
@ -1114,6 +950,164 @@ fn insert_refcount_operations_binding<'a>(
|
|||
new_let
|
||||
)
|
||||
}
|
||||
Expr::Call(Call {
|
||||
arguments,
|
||||
call_type,
|
||||
}) => {
|
||||
match call_type.clone().replace_lowlevel_wrapper() {
|
||||
// A by name call refers to a normal function call.
|
||||
// Normal functions take all their parameters as owned, so we can mark them all as such.
|
||||
CallType::ByName { .. } => {
|
||||
let new_let = new_let!(stmt);
|
||||
|
||||
inc_owned!(arguments.iter().copied(), new_let)
|
||||
}
|
||||
CallType::Foreign { .. } => {
|
||||
// Foreign functions should be responsible for their own memory management.
|
||||
// But previously they were assumed to be called with borrowed parameters, so we do the same now.
|
||||
let new_stmt = dec_borrowed!(arguments.iter().copied(), stmt);
|
||||
|
||||
new_let!(new_stmt)
|
||||
}
|
||||
// Doesn't include higher order
|
||||
CallType::LowLevel {
|
||||
op: operator,
|
||||
update_mode: _,
|
||||
} => match operator {
|
||||
// List get unsafe is a special case, because it returns a reference to the list element.
|
||||
// This means that we have to increment the reference count of this element.
|
||||
LowLevel::ListGetUnsafe => {
|
||||
let structure = match arguments {
|
||||
[structure, _index] => *structure,
|
||||
_ => unreachable!("List get should have two arguments"),
|
||||
};
|
||||
let new_stmt = dec_borrowed!([structure], stmt);
|
||||
let newer_stmt = if matches!(
|
||||
environment.get_symbol_rc_type(binding),
|
||||
VarRcType::ReferenceCounted
|
||||
) {
|
||||
insert_inc_stmt(arena, *binding, 1, new_stmt)
|
||||
} else {
|
||||
new_stmt
|
||||
};
|
||||
new_let!(newer_stmt)
|
||||
}
|
||||
// Otherwise, perform regular reference counting using the lowlevel borrow signature.
|
||||
_ => {
|
||||
let borrow_signature = lowlevel_borrow_signature(arena, operator);
|
||||
let arguments_with_borrow_signature = arguments
|
||||
.iter()
|
||||
.copied()
|
||||
.zip(borrow_signature.iter().copied());
|
||||
let owned_arguments = arguments_with_borrow_signature.clone().filter_map(
|
||||
|(symbol, ownership)| ownership.is_owned().then_some(symbol),
|
||||
);
|
||||
let borrowed_arguments =
|
||||
arguments_with_borrow_signature.filter_map(|(symbol, ownership)| {
|
||||
ownership.is_borrowed().then_some(symbol)
|
||||
});
|
||||
let new_stmt = dec_borrowed!(borrowed_arguments, stmt);
|
||||
let new_let = new_let!(new_stmt);
|
||||
inc_owned!(owned_arguments, new_let)
|
||||
}
|
||||
},
|
||||
CallType::HigherOrder(HigherOrderLowLevel {
|
||||
op: operator,
|
||||
|
||||
closure_env_layout: _,
|
||||
|
||||
/// update mode of the higher order lowlevel itself
|
||||
update_mode: _,
|
||||
|
||||
passed_function,
|
||||
}) => {
|
||||
// Functions always take their arguments as owned.
|
||||
// (Except lowlevels, but those are wrapped in functions that take their arguments as owned and perform rc.)
|
||||
|
||||
// This should always be true, not sure where this could be set to false.
|
||||
debug_assert!(passed_function.owns_captured_environment);
|
||||
|
||||
// define macro that inserts a decref statement for a symbol amount of symbols
|
||||
macro_rules! decref_lists {
|
||||
($stmt:expr, $symbol:expr) => {
|
||||
arena.alloc(Stmt::Refcounting(ModifyRc::DecRef($symbol), $stmt))
|
||||
};
|
||||
|
||||
($stmt:expr, $symbol:expr, $($symbols:expr),+) => {{
|
||||
decref_lists!(decref_lists!($stmt, $symbol), $($symbols),+)
|
||||
}};
|
||||
}
|
||||
|
||||
match operator {
|
||||
HigherOrder::ListMap { xs } => {
|
||||
if let [_xs_symbol, _function_symbol, closure_symbol] = &arguments {
|
||||
let new_stmt = dec_borrowed!([*closure_symbol], stmt);
|
||||
let new_stmt = decref_lists!(new_stmt, *xs);
|
||||
|
||||
let new_let = new_let!(new_stmt);
|
||||
|
||||
inc_owned!([*xs].into_iter(), new_let)
|
||||
} else {
|
||||
panic!("ListMap should have 3 arguments");
|
||||
}
|
||||
}
|
||||
HigherOrder::ListMap2 { xs, ys } => {
|
||||
if let [_xs_symbol, _ys_symbol, _function_symbol, closure_symbol] =
|
||||
&arguments
|
||||
{
|
||||
let new_stmt = dec_borrowed!([*closure_symbol], stmt);
|
||||
let new_stmt = decref_lists!(new_stmt, *xs, *ys);
|
||||
|
||||
let new_let = new_let!(new_stmt);
|
||||
|
||||
inc_owned!([*xs, *ys].into_iter(), new_let)
|
||||
} else {
|
||||
panic!("ListMap2 should have 4 arguments");
|
||||
}
|
||||
}
|
||||
HigherOrder::ListMap3 { xs, ys, zs } => {
|
||||
if let [_xs_symbol, _ys_symbol, _zs_symbol, _function_symbol, closure_symbol] =
|
||||
&arguments
|
||||
{
|
||||
let new_stmt = dec_borrowed!([*closure_symbol], stmt);
|
||||
let new_stmt = decref_lists!(new_stmt, *xs, *ys, *zs);
|
||||
|
||||
let new_let = new_let!(new_stmt);
|
||||
|
||||
inc_owned!([*xs, *ys, *zs].into_iter(), new_let)
|
||||
} else {
|
||||
panic!("ListMap3 should have 5 arguments");
|
||||
}
|
||||
}
|
||||
HigherOrder::ListMap4 { xs, ys, zs, ws } => {
|
||||
if let [_xs_symbol, _ys_symbol, _zs_symbol, _ws_symbol, _function_symbol, closure_symbol] =
|
||||
&arguments
|
||||
{
|
||||
let new_stmt = dec_borrowed!([*closure_symbol], stmt);
|
||||
let new_stmt = decref_lists!(new_stmt, *xs, *ys, *zs, *ws);
|
||||
|
||||
let new_let = new_let!(new_stmt);
|
||||
|
||||
inc_owned!([*xs, *ys, *zs, *ws].into_iter(), new_let)
|
||||
} else {
|
||||
panic!("ListMap4 should have 6 arguments");
|
||||
}
|
||||
}
|
||||
HigherOrder::ListSortWith { xs } => {
|
||||
// TODO if non-unique, elements have been consumed, must still consume the list itself
|
||||
if let [_xs_symbol, _function_symbol, closure_symbol] = &arguments {
|
||||
let new_stmt = dec_borrowed!([*closure_symbol], stmt);
|
||||
let new_let = new_let!(new_stmt);
|
||||
|
||||
inc_owned!([*xs].into_iter(), new_let)
|
||||
} else {
|
||||
panic!("ListSortWith should have 3 arguments");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Expr::Reuse { .. } | Expr::Reset { .. } | Expr::ResetRef { .. } => {
|
||||
unreachable!("Reset(ref) and reuse should not exist at this point")
|
||||
}
|
||||
|
|
|
@ -17,15 +17,15 @@ use roc_collections::VecMap;
|
|||
use roc_debug_flags::dbg_do;
|
||||
#[cfg(debug_assertions)]
|
||||
use roc_debug_flags::{
|
||||
ROC_PRINT_IR_AFTER_REFCOUNT, ROC_PRINT_IR_AFTER_RESET_REUSE, ROC_PRINT_IR_AFTER_SPECIALIZATION,
|
||||
ROC_PRINT_RUNTIME_ERROR_GEN,
|
||||
ROC_PRINT_IR_AFTER_DROP_SPECIALIZATION, ROC_PRINT_IR_AFTER_REFCOUNT,
|
||||
ROC_PRINT_IR_AFTER_RESET_REUSE, ROC_PRINT_IR_AFTER_SPECIALIZATION, ROC_PRINT_RUNTIME_ERROR_GEN,
|
||||
};
|
||||
use roc_derive::SharedDerivedModule;
|
||||
use roc_error_macros::{internal_error, todo_abilities};
|
||||
use roc_late_solve::storage::{ExternalModuleStorage, ExternalModuleStorageSnapshot};
|
||||
use roc_late_solve::{resolve_ability_specialization, AbilitiesView, Resolved, UnificationFailed};
|
||||
use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::low_level::{LowLevel, LowLevelWrapperType};
|
||||
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
||||
use roc_problem::can::{RuntimeError, ShadowKind};
|
||||
use roc_region::all::{Loc, Region};
|
||||
|
@ -57,6 +57,9 @@ pub fn pretty_print_ir_symbols() -> bool {
|
|||
dbg_do!(ROC_PRINT_IR_AFTER_REFCOUNT, {
|
||||
return true;
|
||||
});
|
||||
dbg_do!(ROC_PRINT_IR_AFTER_DROP_SPECIALIZATION, {
|
||||
return true;
|
||||
});
|
||||
false
|
||||
}
|
||||
|
||||
|
@ -1595,6 +1598,10 @@ pub enum BranchInfo<'a> {
|
|||
layout: InLayout<'a>,
|
||||
tag_id: TagIdIntType,
|
||||
},
|
||||
List {
|
||||
scrutinee: Symbol,
|
||||
len: u64,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'a> BranchInfo<'a> {
|
||||
|
@ -1783,6 +1790,24 @@ pub enum CallType<'a> {
|
|||
HigherOrder(&'a HigherOrderLowLevel<'a>),
|
||||
}
|
||||
|
||||
impl<'a> CallType<'a> {
|
||||
/**
|
||||
Replace calls to wrappers of lowlevel functions with the lowlevel function itself
|
||||
*/
|
||||
pub fn replace_lowlevel_wrapper(self) -> Self {
|
||||
match self {
|
||||
CallType::ByName { name, .. } => match LowLevelWrapperType::from_symbol(name.name()) {
|
||||
LowLevelWrapperType::CanBeReplacedBy(lowlevel) => CallType::LowLevel {
|
||||
op: lowlevel,
|
||||
update_mode: UpdateModeId::BACKEND_DUMMY,
|
||||
},
|
||||
LowLevelWrapperType::NotALowLevelWrapper => self,
|
||||
},
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct PassedFunction<'a> {
|
||||
/// name of the top-level function that is passed as an argument
|
||||
|
|
|
@ -1699,7 +1699,7 @@ fn test_to_comparison<'a>(
|
|||
(
|
||||
stores,
|
||||
(lhs_symbol, Comparator::Eq, rhs_symbol),
|
||||
Some(ConstructorKnown::OnlyPass {
|
||||
Some(ConstructorKnown::OneTag {
|
||||
scrutinee: path_symbol,
|
||||
layout: *cond_layout,
|
||||
tag_id,
|
||||
|
@ -1855,7 +1855,7 @@ fn compile_test<'a>(
|
|||
) -> Stmt<'a> {
|
||||
compile_test_help(
|
||||
env,
|
||||
ConstructorKnown::Neither,
|
||||
ConstructorKnown::None,
|
||||
ret_layout,
|
||||
stores,
|
||||
lhs,
|
||||
|
@ -1885,7 +1885,7 @@ fn compile_test_help<'a>(
|
|||
let (pass_info, fail_info) = {
|
||||
use ConstructorKnown::*;
|
||||
match branch_info {
|
||||
Both {
|
||||
BothTags {
|
||||
scrutinee,
|
||||
layout,
|
||||
pass,
|
||||
|
@ -1905,7 +1905,7 @@ fn compile_test_help<'a>(
|
|||
(pass_info, fail_info)
|
||||
}
|
||||
|
||||
OnlyPass {
|
||||
OneTag {
|
||||
scrutinee,
|
||||
layout,
|
||||
tag_id,
|
||||
|
@ -1919,7 +1919,13 @@ fn compile_test_help<'a>(
|
|||
(pass_info, BranchInfo::None)
|
||||
}
|
||||
|
||||
Neither => (BranchInfo::None, BranchInfo::None),
|
||||
ListLen { scrutinee, len } => {
|
||||
let pass_info = BranchInfo::List { scrutinee, len };
|
||||
|
||||
(pass_info, BranchInfo::None)
|
||||
}
|
||||
|
||||
None => (BranchInfo::None, BranchInfo::None),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1981,18 +1987,22 @@ fn compile_tests<'a>(
|
|||
|
||||
#[derive(Debug)]
|
||||
enum ConstructorKnown<'a> {
|
||||
Both {
|
||||
BothTags {
|
||||
scrutinee: Symbol,
|
||||
layout: InLayout<'a>,
|
||||
pass: TagIdIntType,
|
||||
fail: TagIdIntType,
|
||||
},
|
||||
OnlyPass {
|
||||
OneTag {
|
||||
scrutinee: Symbol,
|
||||
layout: InLayout<'a>,
|
||||
tag_id: TagIdIntType,
|
||||
},
|
||||
Neither,
|
||||
ListLen {
|
||||
scrutinee: Symbol,
|
||||
len: u64,
|
||||
},
|
||||
None,
|
||||
}
|
||||
|
||||
impl<'a> ConstructorKnown<'a> {
|
||||
|
@ -2006,23 +2016,30 @@ impl<'a> ConstructorKnown<'a> {
|
|||
Test::IsCtor { tag_id, union, .. } if path.is_empty() => {
|
||||
if union.alternatives.len() == 2 {
|
||||
// excluded middle: we also know the tag_id in the fail branch
|
||||
ConstructorKnown::Both {
|
||||
ConstructorKnown::BothTags {
|
||||
layout: cond_layout,
|
||||
scrutinee: cond_symbol,
|
||||
pass: *tag_id,
|
||||
fail: (*tag_id == 0) as _,
|
||||
}
|
||||
} else {
|
||||
ConstructorKnown::OnlyPass {
|
||||
ConstructorKnown::OneTag {
|
||||
layout: cond_layout,
|
||||
scrutinee: cond_symbol,
|
||||
tag_id: *tag_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => ConstructorKnown::Neither,
|
||||
Test::IsListLen {
|
||||
bound: ListLenBound::Exact,
|
||||
len,
|
||||
} if path.is_empty() => ConstructorKnown::ListLen {
|
||||
scrutinee: cond_symbol,
|
||||
len: *len,
|
||||
},
|
||||
_ => ConstructorKnown::None,
|
||||
},
|
||||
_ => ConstructorKnown::Neither,
|
||||
_ => ConstructorKnown::None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2255,18 +2272,31 @@ fn decide_to_branching<'a>(
|
|||
};
|
||||
|
||||
// branch info is only useful for refcounted values
|
||||
let branch_info = if let Test::IsCtor { tag_id, union, .. } = test {
|
||||
tag_id_sum -= tag_id as i64;
|
||||
union_size = union.alternatives.len() as i64;
|
||||
let branch_info = match test {
|
||||
Test::IsCtor { tag_id, union, .. } => {
|
||||
tag_id_sum -= tag_id as i64;
|
||||
union_size = union.alternatives.len() as i64;
|
||||
|
||||
BranchInfo::Constructor {
|
||||
scrutinee: inner_cond_symbol,
|
||||
layout: inner_cond_layout,
|
||||
tag_id,
|
||||
BranchInfo::Constructor {
|
||||
scrutinee: inner_cond_symbol,
|
||||
layout: inner_cond_layout,
|
||||
tag_id,
|
||||
}
|
||||
}
|
||||
Test::IsListLen {
|
||||
bound: ListLenBound::Exact,
|
||||
len,
|
||||
} => {
|
||||
tag_id_sum = -1;
|
||||
BranchInfo::List {
|
||||
scrutinee: inner_cond_symbol,
|
||||
len,
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
tag_id_sum = -1;
|
||||
BranchInfo::None
|
||||
}
|
||||
} else {
|
||||
tag_id_sum = -1;
|
||||
BranchInfo::None
|
||||
};
|
||||
|
||||
branches.push((tag, branch_info, branch));
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
pub mod borrow;
|
||||
pub mod code_gen_help;
|
||||
pub mod drop_specialization;
|
||||
pub mod inc_dec;
|
||||
pub mod ir;
|
||||
pub mod layout;
|
||||
|
|
|
@ -3296,7 +3296,6 @@ fn box_num() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
#[ignore = "triggers some UB somewhere in at least the llvm and dev backends"]
|
||||
fn box_str() {
|
||||
assert_evals_to!(
|
||||
"Box.box \"short\"",
|
||||
|
|
|
@ -96,7 +96,7 @@ fn list_str_inc() {
|
|||
),
|
||||
RocList<RocList<RocStr>>,
|
||||
&[
|
||||
Live(6), // s
|
||||
Live(3), // s
|
||||
Live(2), // list
|
||||
Live(1) // result
|
||||
]
|
||||
|
@ -228,8 +228,8 @@ fn union_recursive_inc() {
|
|||
),
|
||||
(Pointer, Pointer),
|
||||
&[
|
||||
Live(4), // s
|
||||
Live(4), // sym
|
||||
Live(1), // s
|
||||
Live(2), // x
|
||||
Live(2), // e
|
||||
]
|
||||
);
|
||||
|
@ -294,7 +294,7 @@ fn refcount_different_rosetrees_inc() {
|
|||
),
|
||||
(Pointer, Pointer),
|
||||
&[
|
||||
Live(2), // s
|
||||
Live(1), // s
|
||||
Live(3), // i1
|
||||
Live(2), // s1
|
||||
Live(1), // [i1, i1]
|
||||
|
@ -364,10 +364,10 @@ fn union_linked_list_inc() {
|
|||
),
|
||||
(Pointer, Pointer),
|
||||
&[
|
||||
Live(6), // s
|
||||
Live(2), // Cons
|
||||
Live(2), // Cons
|
||||
Live(2), // Cons
|
||||
Live(3), // s
|
||||
Live(1), // inner-most Cons
|
||||
Live(1), // middle Cons
|
||||
Live(2), // linked
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -468,7 +468,7 @@ fn boxed_str_inc() {
|
|||
),
|
||||
(Pointer, Pointer),
|
||||
&[
|
||||
Live(2), // s
|
||||
Live(1), // s
|
||||
Live(2), // b
|
||||
]
|
||||
);
|
||||
|
|
|
@ -7,6 +7,7 @@ procedure List.2 (List.96, List.97):
|
|||
let List.504 : Int1 = CallByName Num.22 List.97 List.508;
|
||||
if List.504 then
|
||||
let List.506 : Str = CallByName List.66 List.96 List.97;
|
||||
inc List.506;
|
||||
dec List.96;
|
||||
let List.505 : [C {}, C Str] = TagId(1) List.506;
|
||||
ret List.505;
|
||||
|
@ -37,8 +38,6 @@ procedure List.9 (List.287):
|
|||
let List.500 : Int1 = lowlevel Eq List.498 List.499;
|
||||
if List.500 then
|
||||
let List.288 : Str = UnionAtIndex (Id 1) (Index 0) List.494;
|
||||
inc List.288;
|
||||
dec List.494;
|
||||
let List.495 : [C {}, C Str] = TagId(1) List.288;
|
||||
ret List.495;
|
||||
else
|
||||
|
@ -58,8 +57,6 @@ procedure Result.5 (Result.12, Result.13):
|
|||
if Result.41 then
|
||||
dec Result.13;
|
||||
let Result.14 : Str = UnionAtIndex (Id 1) (Index 0) Result.12;
|
||||
inc Result.14;
|
||||
dec Result.12;
|
||||
ret Result.14;
|
||||
else
|
||||
dec Result.12;
|
||||
|
@ -81,26 +78,42 @@ procedure Test.2 (Test.6):
|
|||
let Test.31 : Int1 = lowlevel Eq Test.29 Test.30;
|
||||
if Test.31 then
|
||||
let Test.7 : [<r>C List *self, C *self] = UnionAtIndex (Id 1) (Index 0) Test.6;
|
||||
inc Test.7;
|
||||
dec Test.6;
|
||||
let Test.8 : Str = CallByName Test.2 Test.7;
|
||||
let Test.18 : Int1 = CallByName Bool.1;
|
||||
if Test.18 then
|
||||
ret Test.8;
|
||||
joinpoint #Derived_gen.2:
|
||||
let Test.8 : Str = CallByName Test.2 Test.7;
|
||||
let Test.18 : Int1 = CallByName Bool.1;
|
||||
if Test.18 then
|
||||
ret Test.8;
|
||||
else
|
||||
dec Test.8;
|
||||
let Test.17 : Str = "foo";
|
||||
ret Test.17;
|
||||
in
|
||||
let #Derived_gen.3 : Int1 = lowlevel RefCountIsUnique Test.6;
|
||||
if #Derived_gen.3 then
|
||||
decref Test.6;
|
||||
jump #Derived_gen.2;
|
||||
else
|
||||
dec Test.8;
|
||||
let Test.17 : Str = "foo";
|
||||
ret Test.17;
|
||||
inc Test.7;
|
||||
decref Test.6;
|
||||
jump #Derived_gen.2;
|
||||
else
|
||||
let Test.9 : List [<r>C List *self, C *self] = UnionAtIndex (Id 0) (Index 0) Test.6;
|
||||
inc Test.9;
|
||||
dec Test.6;
|
||||
let Test.24 : {} = Struct {};
|
||||
let Test.23 : List Str = CallByName List.5 Test.9 Test.24;
|
||||
let Test.21 : [C {}, C Str] = CallByName List.9 Test.23;
|
||||
let Test.22 : Str = "foo";
|
||||
let Test.20 : Str = CallByName Result.5 Test.21 Test.22;
|
||||
ret Test.20;
|
||||
joinpoint #Derived_gen.4:
|
||||
let Test.24 : {} = Struct {};
|
||||
let Test.23 : List Str = CallByName List.5 Test.9 Test.24;
|
||||
let Test.21 : [C {}, C Str] = CallByName List.9 Test.23;
|
||||
let Test.22 : Str = "foo";
|
||||
let Test.20 : Str = CallByName Result.5 Test.21 Test.22;
|
||||
ret Test.20;
|
||||
in
|
||||
let #Derived_gen.5 : Int1 = lowlevel RefCountIsUnique Test.6;
|
||||
if #Derived_gen.5 then
|
||||
decref Test.6;
|
||||
jump #Derived_gen.4;
|
||||
else
|
||||
inc Test.9;
|
||||
decref Test.6;
|
||||
jump #Derived_gen.4;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.32 : List [<r>C List *self, C *self] = Array [];
|
||||
|
|
|
@ -58,33 +58,41 @@ procedure Test.11 (Test.53, Test.54):
|
|||
joinpoint Test.27 Test.12 #Attr.12:
|
||||
let Test.8 : Int1 = UnionAtIndex (Id 2) (Index 1) #Attr.12;
|
||||
let Test.7 : [<rnw><null>, C *self Int1, C *self Int1] = UnionAtIndex (Id 2) (Index 0) #Attr.12;
|
||||
inc Test.7;
|
||||
dec #Attr.12;
|
||||
joinpoint Test.31 Test.29:
|
||||
let Test.30 : U8 = GetTagId Test.7;
|
||||
switch Test.30:
|
||||
joinpoint #Derived_gen.5:
|
||||
joinpoint Test.31 Test.29:
|
||||
let Test.30 : U8 = GetTagId Test.7;
|
||||
switch Test.30:
|
||||
case 0:
|
||||
dec Test.7;
|
||||
let Test.28 : Str = CallByName Test.2 Test.29;
|
||||
ret Test.28;
|
||||
|
||||
case 1:
|
||||
let Test.28 : Str = CallByName Test.9 Test.29 Test.7;
|
||||
ret Test.28;
|
||||
|
||||
default:
|
||||
jump Test.27 Test.29 Test.7;
|
||||
|
||||
in
|
||||
switch Test.8:
|
||||
case 0:
|
||||
dec Test.7;
|
||||
let Test.28 : Str = CallByName Test.2 Test.29;
|
||||
ret Test.28;
|
||||
|
||||
case 1:
|
||||
let Test.28 : Str = CallByName Test.9 Test.29 Test.7;
|
||||
ret Test.28;
|
||||
let Test.32 : Str = CallByName Test.3 Test.12;
|
||||
jump Test.31 Test.32;
|
||||
|
||||
default:
|
||||
jump Test.27 Test.29 Test.7;
|
||||
let Test.32 : Str = CallByName Test.4 Test.12;
|
||||
jump Test.31 Test.32;
|
||||
|
||||
in
|
||||
switch Test.8:
|
||||
case 0:
|
||||
let Test.32 : Str = CallByName Test.3 Test.12;
|
||||
jump Test.31 Test.32;
|
||||
|
||||
default:
|
||||
let Test.32 : Str = CallByName Test.4 Test.12;
|
||||
jump Test.31 Test.32;
|
||||
|
||||
let #Derived_gen.6 : Int1 = lowlevel RefCountIsUnique #Attr.12;
|
||||
if #Derived_gen.6 then
|
||||
decref #Attr.12;
|
||||
jump #Derived_gen.5;
|
||||
else
|
||||
inc Test.7;
|
||||
decref #Attr.12;
|
||||
jump #Derived_gen.5;
|
||||
in
|
||||
jump Test.27 Test.53 Test.54;
|
||||
|
||||
|
@ -117,34 +125,42 @@ procedure Test.6 (Test.7, Test.8, Test.5):
|
|||
procedure Test.9 (Test.10, #Attr.12):
|
||||
let Test.8 : Int1 = UnionAtIndex (Id 1) (Index 1) #Attr.12;
|
||||
let Test.7 : [<rnw><null>, C *self Int1, C *self Int1] = UnionAtIndex (Id 1) (Index 0) #Attr.12;
|
||||
inc Test.7;
|
||||
dec #Attr.12;
|
||||
let Test.37 : U8 = GetTagId Test.7;
|
||||
joinpoint Test.38 Test.36:
|
||||
switch Test.8:
|
||||
joinpoint #Derived_gen.3:
|
||||
let Test.37 : U8 = GetTagId Test.7;
|
||||
joinpoint Test.38 Test.36:
|
||||
switch Test.8:
|
||||
case 0:
|
||||
let Test.35 : Str = CallByName Test.3 Test.36;
|
||||
ret Test.35;
|
||||
|
||||
default:
|
||||
let Test.35 : Str = CallByName Test.4 Test.36;
|
||||
ret Test.35;
|
||||
|
||||
in
|
||||
switch Test.37:
|
||||
case 0:
|
||||
let Test.35 : Str = CallByName Test.3 Test.36;
|
||||
ret Test.35;
|
||||
dec Test.7;
|
||||
let Test.39 : Str = CallByName Test.2 Test.10;
|
||||
jump Test.38 Test.39;
|
||||
|
||||
case 1:
|
||||
let Test.39 : Str = CallByName Test.9 Test.10 Test.7;
|
||||
jump Test.38 Test.39;
|
||||
|
||||
default:
|
||||
let Test.35 : Str = CallByName Test.4 Test.36;
|
||||
ret Test.35;
|
||||
let Test.39 : Str = CallByName Test.11 Test.10 Test.7;
|
||||
jump Test.38 Test.39;
|
||||
|
||||
in
|
||||
switch Test.37:
|
||||
case 0:
|
||||
dec Test.7;
|
||||
let Test.39 : Str = CallByName Test.2 Test.10;
|
||||
jump Test.38 Test.39;
|
||||
|
||||
case 1:
|
||||
let Test.39 : Str = CallByName Test.9 Test.10 Test.7;
|
||||
jump Test.38 Test.39;
|
||||
|
||||
default:
|
||||
let Test.39 : Str = CallByName Test.11 Test.10 Test.7;
|
||||
jump Test.38 Test.39;
|
||||
|
||||
let #Derived_gen.4 : Int1 = lowlevel RefCountIsUnique #Attr.12;
|
||||
if #Derived_gen.4 then
|
||||
decref #Attr.12;
|
||||
jump #Derived_gen.3;
|
||||
else
|
||||
inc Test.7;
|
||||
decref #Attr.12;
|
||||
jump #Derived_gen.3;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.41 : Int1 = false;
|
||||
|
|
|
@ -4,7 +4,6 @@ procedure Test.1 (Test.2):
|
|||
let Test.12 : Int1 = lowlevel Eq Test.10 Test.11;
|
||||
if Test.12 then
|
||||
let Test.3 : U64 = UnionAtIndex (Id 1) (Index 0) Test.2;
|
||||
dec Test.2;
|
||||
ret Test.3;
|
||||
else
|
||||
dec Test.2;
|
||||
|
|
|
@ -16,7 +16,12 @@ procedure Dict.34 ():
|
|||
|
||||
procedure Dict.4 (Dict.504):
|
||||
let Dict.85 : U64 = StructAtIndex 3 Dict.504;
|
||||
dec Dict.504;
|
||||
let #Derived_gen.2 : List {[], []} = StructAtIndex 0 Dict.504;
|
||||
dec #Derived_gen.2;
|
||||
let #Derived_gen.1 : List U64 = StructAtIndex 1 Dict.504;
|
||||
dec #Derived_gen.1;
|
||||
let #Derived_gen.0 : List I8 = StructAtIndex 2 Dict.504;
|
||||
dec #Derived_gen.0;
|
||||
ret Dict.85;
|
||||
|
||||
procedure List.11 (List.115, List.116):
|
||||
|
|
|
@ -89,8 +89,6 @@ procedure Json.118 (Json.119, Json.486, Json.117):
|
|||
let Json.495 : {} = Struct {};
|
||||
let Json.493 : {List U8, U64} = CallByName List.18 Json.117 Json.494 Json.495;
|
||||
let Json.123 : List U8 = StructAtIndex 0 Json.493;
|
||||
inc Json.123;
|
||||
dec Json.493;
|
||||
let Json.492 : I64 = 125i64;
|
||||
let Json.491 : U8 = CallByName Num.127 Json.492;
|
||||
let Json.490 : List U8 = CallByName List.4 Json.123 Json.491;
|
||||
|
@ -105,8 +103,6 @@ procedure Json.118 (Json.119, Json.486, Json.117):
|
|||
let Json.535 : {} = Struct {};
|
||||
let Json.533 : {List U8, U64} = CallByName List.18 Json.117 Json.534 Json.535;
|
||||
let Json.123 : List U8 = StructAtIndex 0 Json.533;
|
||||
inc Json.123;
|
||||
dec Json.533;
|
||||
let Json.532 : I64 = 125i64;
|
||||
let Json.531 : U8 = CallByName Num.127 Json.532;
|
||||
let Json.530 : List U8 = CallByName List.4 Json.123 Json.531;
|
||||
|
@ -114,14 +110,9 @@ procedure Json.118 (Json.119, Json.486, Json.117):
|
|||
|
||||
procedure Json.120 (Json.488, Json.489):
|
||||
let Json.126 : Str = StructAtIndex 0 Json.489;
|
||||
inc Json.126;
|
||||
let Json.127 : Str = StructAtIndex 1 Json.489;
|
||||
inc Json.127;
|
||||
dec Json.489;
|
||||
let Json.124 : List U8 = StructAtIndex 0 Json.488;
|
||||
inc Json.124;
|
||||
let Json.125 : U64 = StructAtIndex 1 Json.488;
|
||||
dec Json.488;
|
||||
let Json.516 : I64 = 34i64;
|
||||
let Json.515 : U8 = CallByName Num.127 Json.516;
|
||||
let Json.513 : List U8 = CallByName List.4 Json.124 Json.515;
|
||||
|
@ -153,14 +144,9 @@ procedure Json.120 (Json.488, Json.489):
|
|||
|
||||
procedure Json.120 (Json.488, Json.489):
|
||||
let Json.126 : Str = StructAtIndex 0 Json.489;
|
||||
inc Json.126;
|
||||
let Json.127 : Str = StructAtIndex 1 Json.489;
|
||||
inc Json.127;
|
||||
dec Json.489;
|
||||
let Json.124 : List U8 = StructAtIndex 0 Json.488;
|
||||
inc Json.124;
|
||||
let Json.125 : U64 = StructAtIndex 1 Json.488;
|
||||
dec Json.488;
|
||||
let Json.556 : I64 = 34i64;
|
||||
let Json.555 : U8 = CallByName Num.127 Json.556;
|
||||
let Json.553 : List U8 = CallByName List.4 Json.124 Json.555;
|
||||
|
@ -261,6 +247,7 @@ procedure List.80 (List.547, List.548, List.549, List.550, List.551):
|
|||
let List.524 : Int1 = CallByName Num.22 List.436 List.437;
|
||||
if List.524 then
|
||||
let List.531 : {Str, Str} = CallByName List.66 List.433 List.436;
|
||||
inc List.531;
|
||||
let List.525 : {List U8, U64} = CallByName List.139 List.434 List.531 List.435;
|
||||
let List.528 : U64 = 1i64;
|
||||
let List.527 : U64 = CallByName Num.19 List.436 List.528;
|
||||
|
@ -276,6 +263,7 @@ procedure List.80 (List.621, List.622, List.623, List.624, List.625):
|
|||
let List.597 : Int1 = CallByName Num.22 List.436 List.437;
|
||||
if List.597 then
|
||||
let List.604 : {Str, Str} = CallByName List.66 List.433 List.436;
|
||||
inc List.604;
|
||||
let List.598 : {List U8, U64} = CallByName List.139 List.434 List.604 List.435;
|
||||
let List.601 : U64 = 1i64;
|
||||
let List.600 : U64 = CallByName Num.19 List.436 List.601;
|
||||
|
@ -333,14 +321,13 @@ procedure Str.9 (Str.79):
|
|||
let Str.302 : Int1 = StructAtIndex 2 Str.80;
|
||||
if Str.302 then
|
||||
let Str.304 : Str = StructAtIndex 1 Str.80;
|
||||
inc Str.304;
|
||||
dec Str.80;
|
||||
let Str.303 : [C {U64, U8}, C Str] = TagId(1) Str.304;
|
||||
ret Str.303;
|
||||
else
|
||||
let Str.300 : U8 = StructAtIndex 3 Str.80;
|
||||
let Str.301 : U64 = StructAtIndex 0 Str.80;
|
||||
dec Str.80;
|
||||
let #Derived_gen.28 : Str = StructAtIndex 1 Str.80;
|
||||
dec #Derived_gen.28;
|
||||
let Str.299 : {U64, U8} = Struct {Str.301, Str.300};
|
||||
let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299;
|
||||
ret Str.298;
|
||||
|
@ -355,8 +342,6 @@ procedure Test.0 ():
|
|||
let Test.7 : Int1 = lowlevel Eq Test.5 Test.6;
|
||||
if Test.7 then
|
||||
let Test.2 : Str = UnionAtIndex (Id 1) (Index 0) Test.1;
|
||||
inc Test.2;
|
||||
dec Test.1;
|
||||
ret Test.2;
|
||||
else
|
||||
dec Test.1;
|
||||
|
|
|
@ -62,8 +62,6 @@ procedure Json.118 (Json.119, Json.486, Json.117):
|
|||
let Json.495 : {} = Struct {};
|
||||
let Json.493 : {List U8, U64} = CallByName List.18 Json.117 Json.494 Json.495;
|
||||
let Json.123 : List U8 = StructAtIndex 0 Json.493;
|
||||
inc Json.123;
|
||||
dec Json.493;
|
||||
let Json.492 : I64 = 125i64;
|
||||
let Json.491 : U8 = CallByName Num.127 Json.492;
|
||||
let Json.490 : List U8 = CallByName List.4 Json.123 Json.491;
|
||||
|
@ -71,14 +69,9 @@ procedure Json.118 (Json.119, Json.486, Json.117):
|
|||
|
||||
procedure Json.120 (Json.488, Json.489):
|
||||
let Json.126 : Str = StructAtIndex 0 Json.489;
|
||||
inc Json.126;
|
||||
let Json.127 : Str = StructAtIndex 1 Json.489;
|
||||
inc Json.127;
|
||||
dec Json.489;
|
||||
let Json.124 : List U8 = StructAtIndex 0 Json.488;
|
||||
inc Json.124;
|
||||
let Json.125 : U64 = StructAtIndex 1 Json.488;
|
||||
dec Json.488;
|
||||
let Json.516 : I64 = 34i64;
|
||||
let Json.515 : U8 = CallByName Num.127 Json.516;
|
||||
let Json.513 : List U8 = CallByName List.4 Json.124 Json.515;
|
||||
|
@ -159,6 +152,7 @@ procedure List.80 (List.554, List.555, List.556, List.557, List.558):
|
|||
let List.530 : Int1 = CallByName Num.22 List.436 List.437;
|
||||
if List.530 then
|
||||
let List.537 : {Str, Str} = CallByName List.66 List.433 List.436;
|
||||
inc List.537;
|
||||
let List.531 : {List U8, U64} = CallByName List.139 List.434 List.537 List.435;
|
||||
let List.534 : U64 = 1i64;
|
||||
let List.533 : U64 = CallByName Num.19 List.436 List.534;
|
||||
|
@ -210,14 +204,13 @@ procedure Str.9 (Str.79):
|
|||
let Str.302 : Int1 = StructAtIndex 2 Str.80;
|
||||
if Str.302 then
|
||||
let Str.304 : Str = StructAtIndex 1 Str.80;
|
||||
inc Str.304;
|
||||
dec Str.80;
|
||||
let Str.303 : [C {U64, U8}, C Str] = TagId(1) Str.304;
|
||||
ret Str.303;
|
||||
else
|
||||
let Str.300 : U8 = StructAtIndex 3 Str.80;
|
||||
let Str.301 : U64 = StructAtIndex 0 Str.80;
|
||||
dec Str.80;
|
||||
let #Derived_gen.14 : Str = StructAtIndex 1 Str.80;
|
||||
dec #Derived_gen.14;
|
||||
let Str.299 : {U64, U8} = Struct {Str.301, Str.300};
|
||||
let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299;
|
||||
ret Str.298;
|
||||
|
@ -232,8 +225,6 @@ procedure Test.0 ():
|
|||
let Test.7 : Int1 = lowlevel Eq Test.5 Test.6;
|
||||
if Test.7 then
|
||||
let Test.2 : Str = UnionAtIndex (Id 1) (Index 0) Test.1;
|
||||
inc Test.2;
|
||||
dec Test.1;
|
||||
ret Test.2;
|
||||
else
|
||||
dec Test.1;
|
||||
|
|
|
@ -10,8 +10,7 @@ procedure #Derived.2 (#Derived.3, #Derived.4, #Derived.1):
|
|||
let #Derived_gen.6 : {Str, Str} = Struct {#Derived_gen.11, #Derived_gen.12};
|
||||
let #Derived_gen.8 : Str = "b";
|
||||
let #Derived_gen.10 : Str = StructAtIndex 1 #Derived.1;
|
||||
inc #Derived_gen.10;
|
||||
dec #Derived.1;
|
||||
dec #Derived_gen.13;
|
||||
let #Derived_gen.9 : Str = CallByName Json.18 #Derived_gen.10;
|
||||
let #Derived_gen.7 : {Str, Str} = Struct {#Derived_gen.8, #Derived_gen.9};
|
||||
let #Derived_gen.5 : List {Str, Str} = Array [#Derived_gen.6, #Derived_gen.7];
|
||||
|
@ -70,8 +69,6 @@ procedure Json.118 (Json.119, Json.486, Json.117):
|
|||
let Json.495 : {} = Struct {};
|
||||
let Json.493 : {List U8, U64} = CallByName List.18 Json.117 Json.494 Json.495;
|
||||
let Json.123 : List U8 = StructAtIndex 0 Json.493;
|
||||
inc Json.123;
|
||||
dec Json.493;
|
||||
let Json.492 : I64 = 125i64;
|
||||
let Json.491 : U8 = CallByName Num.127 Json.492;
|
||||
let Json.490 : List U8 = CallByName List.4 Json.123 Json.491;
|
||||
|
@ -79,14 +76,9 @@ procedure Json.118 (Json.119, Json.486, Json.117):
|
|||
|
||||
procedure Json.120 (Json.488, Json.489):
|
||||
let Json.126 : Str = StructAtIndex 0 Json.489;
|
||||
inc Json.126;
|
||||
let Json.127 : Str = StructAtIndex 1 Json.489;
|
||||
inc Json.127;
|
||||
dec Json.489;
|
||||
let Json.124 : List U8 = StructAtIndex 0 Json.488;
|
||||
inc Json.124;
|
||||
let Json.125 : U64 = StructAtIndex 1 Json.488;
|
||||
dec Json.488;
|
||||
let Json.516 : I64 = 34i64;
|
||||
let Json.515 : U8 = CallByName Num.127 Json.516;
|
||||
let Json.513 : List U8 = CallByName List.4 Json.124 Json.515;
|
||||
|
@ -167,6 +159,7 @@ procedure List.80 (List.554, List.555, List.556, List.557, List.558):
|
|||
let List.530 : Int1 = CallByName Num.22 List.436 List.437;
|
||||
if List.530 then
|
||||
let List.537 : {Str, Str} = CallByName List.66 List.433 List.436;
|
||||
inc List.537;
|
||||
let List.531 : {List U8, U64} = CallByName List.139 List.434 List.537 List.435;
|
||||
let List.534 : U64 = 1i64;
|
||||
let List.533 : U64 = CallByName Num.19 List.436 List.534;
|
||||
|
@ -218,14 +211,13 @@ procedure Str.9 (Str.79):
|
|||
let Str.302 : Int1 = StructAtIndex 2 Str.80;
|
||||
if Str.302 then
|
||||
let Str.304 : Str = StructAtIndex 1 Str.80;
|
||||
inc Str.304;
|
||||
dec Str.80;
|
||||
let Str.303 : [C {U64, U8}, C Str] = TagId(1) Str.304;
|
||||
ret Str.303;
|
||||
else
|
||||
let Str.300 : U8 = StructAtIndex 3 Str.80;
|
||||
let Str.301 : U64 = StructAtIndex 0 Str.80;
|
||||
dec Str.80;
|
||||
let #Derived_gen.18 : Str = StructAtIndex 1 Str.80;
|
||||
dec #Derived_gen.18;
|
||||
let Str.299 : {U64, U8} = Struct {Str.301, Str.300};
|
||||
let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299;
|
||||
ret Str.298;
|
||||
|
@ -242,8 +234,6 @@ procedure Test.0 ():
|
|||
let Test.7 : Int1 = lowlevel Eq Test.5 Test.6;
|
||||
if Test.7 then
|
||||
let Test.2 : Str = UnionAtIndex (Id 1) (Index 0) Test.1;
|
||||
inc Test.2;
|
||||
dec Test.1;
|
||||
ret Test.2;
|
||||
else
|
||||
dec Test.1;
|
||||
|
|
|
@ -71,14 +71,13 @@ procedure Str.9 (Str.79):
|
|||
let Str.302 : Int1 = StructAtIndex 2 Str.80;
|
||||
if Str.302 then
|
||||
let Str.304 : Str = StructAtIndex 1 Str.80;
|
||||
inc Str.304;
|
||||
dec Str.80;
|
||||
let Str.303 : [C {U64, U8}, C Str] = TagId(1) Str.304;
|
||||
ret Str.303;
|
||||
else
|
||||
let Str.300 : U8 = StructAtIndex 3 Str.80;
|
||||
let Str.301 : U64 = StructAtIndex 0 Str.80;
|
||||
dec Str.80;
|
||||
let #Derived_gen.0 : Str = StructAtIndex 1 Str.80;
|
||||
dec #Derived_gen.0;
|
||||
let Str.299 : {U64, U8} = Struct {Str.301, Str.300};
|
||||
let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299;
|
||||
ret Str.298;
|
||||
|
@ -93,8 +92,6 @@ procedure Test.0 ():
|
|||
let Test.7 : Int1 = lowlevel Eq Test.5 Test.6;
|
||||
if Test.7 then
|
||||
let Test.2 : Str = UnionAtIndex (Id 1) (Index 0) Test.1;
|
||||
inc Test.2;
|
||||
dec Test.1;
|
||||
ret Test.2;
|
||||
else
|
||||
dec Test.1;
|
||||
|
|
|
@ -57,10 +57,7 @@ procedure Json.102 (Json.103, Json.527, Json.101):
|
|||
|
||||
procedure Json.144 (Json.145, Json.486, #Attr.12):
|
||||
let Json.143 : List Str = StructAtIndex 1 #Attr.12;
|
||||
inc Json.143;
|
||||
let Json.142 : Str = StructAtIndex 0 #Attr.12;
|
||||
inc Json.142;
|
||||
dec #Attr.12;
|
||||
let Json.524 : I64 = 123i64;
|
||||
let Json.523 : U8 = CallByName Num.127 Json.524;
|
||||
let Json.520 : List U8 = CallByName List.4 Json.145 Json.523;
|
||||
|
@ -83,8 +80,6 @@ procedure Json.144 (Json.145, Json.486, #Attr.12):
|
|||
let Json.497 : {} = Struct {};
|
||||
let Json.495 : {List U8, U64} = CallByName List.18 Json.143 Json.496 Json.497;
|
||||
let Json.149 : List U8 = StructAtIndex 0 Json.495;
|
||||
inc Json.149;
|
||||
dec Json.495;
|
||||
let Json.494 : I64 = 93i64;
|
||||
let Json.493 : U8 = CallByName Num.127 Json.494;
|
||||
let Json.490 : List U8 = CallByName List.4 Json.149 Json.493;
|
||||
|
@ -95,9 +90,7 @@ procedure Json.144 (Json.145, Json.486, #Attr.12):
|
|||
|
||||
procedure Json.146 (Json.488, Json.152):
|
||||
let Json.150 : List U8 = StructAtIndex 0 Json.488;
|
||||
inc Json.150;
|
||||
let Json.151 : U64 = StructAtIndex 1 Json.488;
|
||||
dec Json.488;
|
||||
let Json.507 : {} = Struct {};
|
||||
let Json.153 : List U8 = CallByName Encode.24 Json.150 Json.152 Json.507;
|
||||
joinpoint Json.502 Json.154:
|
||||
|
@ -168,6 +161,7 @@ procedure List.80 (List.560, List.561, List.562, List.563, List.564):
|
|||
let List.536 : Int1 = CallByName Num.22 List.436 List.437;
|
||||
if List.536 then
|
||||
let List.543 : Str = CallByName List.66 List.433 List.436;
|
||||
inc List.543;
|
||||
let List.537 : {List U8, U64} = CallByName List.139 List.434 List.543 List.435;
|
||||
let List.540 : U64 = 1i64;
|
||||
let List.539 : U64 = CallByName Num.19 List.436 List.540;
|
||||
|
@ -219,14 +213,13 @@ procedure Str.9 (Str.79):
|
|||
let Str.302 : Int1 = StructAtIndex 2 Str.80;
|
||||
if Str.302 then
|
||||
let Str.304 : Str = StructAtIndex 1 Str.80;
|
||||
inc Str.304;
|
||||
dec Str.80;
|
||||
let Str.303 : [C {U64, U8}, C Str] = TagId(1) Str.304;
|
||||
ret Str.303;
|
||||
else
|
||||
let Str.300 : U8 = StructAtIndex 3 Str.80;
|
||||
let Str.301 : U64 = StructAtIndex 0 Str.80;
|
||||
dec Str.80;
|
||||
let #Derived_gen.14 : Str = StructAtIndex 1 Str.80;
|
||||
dec #Derived_gen.14;
|
||||
let Str.299 : {U64, U8} = Struct {Str.301, Str.300};
|
||||
let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299;
|
||||
ret Str.298;
|
||||
|
@ -241,8 +234,6 @@ procedure Test.0 ():
|
|||
let Test.9 : Int1 = lowlevel Eq Test.7 Test.8;
|
||||
if Test.9 then
|
||||
let Test.4 : Str = UnionAtIndex (Id 1) (Index 0) Test.2;
|
||||
inc Test.4;
|
||||
dec Test.2;
|
||||
ret Test.4;
|
||||
else
|
||||
dec Test.2;
|
||||
|
|
|
@ -8,10 +8,7 @@ procedure #Derived.4 (#Derived.5, #Derived.6, #Derived.1):
|
|||
ret #Derived_gen.3;
|
||||
in
|
||||
let #Derived.2 : Str = StructAtIndex 0 #Derived.1;
|
||||
inc #Derived.2;
|
||||
let #Derived.3 : Str = StructAtIndex 1 #Derived.1;
|
||||
inc #Derived.3;
|
||||
dec #Derived.1;
|
||||
let #Derived_gen.7 : Str = "A";
|
||||
let #Derived_gen.9 : Str = CallByName Json.18 #Derived.2;
|
||||
let #Derived_gen.10 : Str = CallByName Json.18 #Derived.3;
|
||||
|
@ -63,10 +60,7 @@ procedure Json.102 (Json.103, Json.527, Json.101):
|
|||
|
||||
procedure Json.144 (Json.145, Json.486, #Attr.12):
|
||||
let Json.143 : List Str = StructAtIndex 1 #Attr.12;
|
||||
inc Json.143;
|
||||
let Json.142 : Str = StructAtIndex 0 #Attr.12;
|
||||
inc Json.142;
|
||||
dec #Attr.12;
|
||||
let Json.524 : I64 = 123i64;
|
||||
let Json.523 : U8 = CallByName Num.127 Json.524;
|
||||
let Json.520 : List U8 = CallByName List.4 Json.145 Json.523;
|
||||
|
@ -89,8 +83,6 @@ procedure Json.144 (Json.145, Json.486, #Attr.12):
|
|||
let Json.497 : {} = Struct {};
|
||||
let Json.495 : {List U8, U64} = CallByName List.18 Json.143 Json.496 Json.497;
|
||||
let Json.149 : List U8 = StructAtIndex 0 Json.495;
|
||||
inc Json.149;
|
||||
dec Json.495;
|
||||
let Json.494 : I64 = 93i64;
|
||||
let Json.493 : U8 = CallByName Num.127 Json.494;
|
||||
let Json.490 : List U8 = CallByName List.4 Json.149 Json.493;
|
||||
|
@ -101,9 +93,7 @@ procedure Json.144 (Json.145, Json.486, #Attr.12):
|
|||
|
||||
procedure Json.146 (Json.488, Json.152):
|
||||
let Json.150 : List U8 = StructAtIndex 0 Json.488;
|
||||
inc Json.150;
|
||||
let Json.151 : U64 = StructAtIndex 1 Json.488;
|
||||
dec Json.488;
|
||||
let Json.507 : {} = Struct {};
|
||||
let Json.153 : List U8 = CallByName Encode.24 Json.150 Json.152 Json.507;
|
||||
joinpoint Json.502 Json.154:
|
||||
|
@ -174,6 +164,7 @@ procedure List.80 (List.560, List.561, List.562, List.563, List.564):
|
|||
let List.536 : Int1 = CallByName Num.22 List.436 List.437;
|
||||
if List.536 then
|
||||
let List.543 : Str = CallByName List.66 List.433 List.436;
|
||||
inc List.543;
|
||||
let List.537 : {List U8, U64} = CallByName List.139 List.434 List.543 List.435;
|
||||
let List.540 : U64 = 1i64;
|
||||
let List.539 : U64 = CallByName Num.19 List.436 List.540;
|
||||
|
@ -225,14 +216,13 @@ procedure Str.9 (Str.79):
|
|||
let Str.302 : Int1 = StructAtIndex 2 Str.80;
|
||||
if Str.302 then
|
||||
let Str.304 : Str = StructAtIndex 1 Str.80;
|
||||
inc Str.304;
|
||||
dec Str.80;
|
||||
let Str.303 : [C {U64, U8}, C Str] = TagId(1) Str.304;
|
||||
ret Str.303;
|
||||
else
|
||||
let Str.300 : U8 = StructAtIndex 3 Str.80;
|
||||
let Str.301 : U64 = StructAtIndex 0 Str.80;
|
||||
dec Str.80;
|
||||
let #Derived_gen.15 : Str = StructAtIndex 1 Str.80;
|
||||
dec #Derived_gen.15;
|
||||
let Str.299 : {U64, U8} = Struct {Str.301, Str.300};
|
||||
let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299;
|
||||
ret Str.298;
|
||||
|
@ -249,8 +239,6 @@ procedure Test.0 ():
|
|||
let Test.9 : Int1 = lowlevel Eq Test.7 Test.8;
|
||||
if Test.9 then
|
||||
let Test.4 : Str = UnionAtIndex (Id 1) (Index 0) Test.2;
|
||||
inc Test.4;
|
||||
dec Test.2;
|
||||
ret Test.4;
|
||||
else
|
||||
dec Test.2;
|
||||
|
|
|
@ -6,11 +6,7 @@ procedure Test.0 ():
|
|||
let Test.10 : Int1 = lowlevel Eq Test.8 Test.9;
|
||||
if Test.10 then
|
||||
let Test.3 : Str = UnionAtIndex (Id 1) (Index 0) Test.11;
|
||||
inc Test.3;
|
||||
dec Test.11;
|
||||
ret Test.3;
|
||||
else
|
||||
let Test.4 : Str = UnionAtIndex (Id 0) (Index 0) Test.11;
|
||||
inc Test.4;
|
||||
dec Test.11;
|
||||
ret Test.4;
|
||||
|
|
|
@ -13,9 +13,14 @@ procedure Test.2 (Test.19):
|
|||
ret Test.14;
|
||||
else
|
||||
let Test.5 : [<rnu><null>, C *self] = UnionAtIndex (Id 0) (Index 0) Test.7;
|
||||
inc Test.5;
|
||||
dec Test.7;
|
||||
jump Test.13 Test.5;
|
||||
let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.7;
|
||||
if #Derived_gen.1 then
|
||||
decref Test.7;
|
||||
jump Test.13 Test.5;
|
||||
else
|
||||
inc Test.5;
|
||||
decref Test.7;
|
||||
jump Test.13 Test.5;
|
||||
in
|
||||
jump Test.13 Test.19;
|
||||
|
||||
|
|
|
@ -41,10 +41,7 @@ procedure Decode.26 (Decode.105, Decode.106):
|
|||
procedure Decode.27 (Decode.107, Decode.108):
|
||||
let Decode.122 : {List U8, [C {}, C Str]} = CallByName Decode.26 Decode.107 Decode.108;
|
||||
let Decode.110 : List U8 = StructAtIndex 0 Decode.122;
|
||||
inc Decode.110;
|
||||
let Decode.109 : [C {}, C Str] = StructAtIndex 1 Decode.122;
|
||||
inc Decode.109;
|
||||
dec Decode.122;
|
||||
inc Decode.110;
|
||||
let Decode.125 : Int1 = CallByName List.1 Decode.110;
|
||||
if Decode.125 then
|
||||
|
@ -54,8 +51,6 @@ procedure Decode.27 (Decode.107, Decode.108):
|
|||
let Decode.131 : Int1 = lowlevel Eq Decode.129 Decode.130;
|
||||
if Decode.131 then
|
||||
let Decode.111 : Str = UnionAtIndex (Id 1) (Index 0) Decode.109;
|
||||
inc Decode.111;
|
||||
dec Decode.109;
|
||||
let Decode.126 : [C [C List U8, C ], C Str] = TagId(1) Decode.111;
|
||||
ret Decode.126;
|
||||
else
|
||||
|
@ -72,10 +67,7 @@ procedure Decode.27 (Decode.107, Decode.108):
|
|||
procedure Json.160 (Json.570, Json.571):
|
||||
joinpoint Json.508 Json.505 Json.159:
|
||||
let Json.162 : List U8 = StructAtIndex 0 Json.505;
|
||||
inc Json.162;
|
||||
let Json.161 : List U8 = StructAtIndex 1 Json.505;
|
||||
inc Json.161;
|
||||
dec Json.505;
|
||||
joinpoint Json.546:
|
||||
let Json.543 : {List U8, List U8} = Struct {Json.162, Json.161};
|
||||
ret Json.543;
|
||||
|
@ -199,10 +191,7 @@ procedure Json.42 (Json.298):
|
|||
inc Json.298;
|
||||
let Json.563 : {List U8, List U8} = CallByName List.52 Json.298 Json.564;
|
||||
let Json.299 : List U8 = StructAtIndex 0 Json.563;
|
||||
inc Json.299;
|
||||
let Json.301 : List U8 = StructAtIndex 1 Json.563;
|
||||
inc Json.301;
|
||||
dec Json.563;
|
||||
let Json.562 : U8 = 34i64;
|
||||
let Json.561 : List U8 = Array [Json.562];
|
||||
let Json.491 : Int1 = CallByName Bool.11 Json.299 Json.561;
|
||||
|
@ -213,23 +202,18 @@ procedure Json.42 (Json.298):
|
|||
let Json.504 : {} = Struct {};
|
||||
let Json.503 : {List U8, List U8} = CallByName Json.24 Json.301 Json.504;
|
||||
let Json.304 : List U8 = StructAtIndex 0 Json.503;
|
||||
inc Json.304;
|
||||
let Json.303 : List U8 = StructAtIndex 1 Json.503;
|
||||
inc Json.303;
|
||||
dec Json.503;
|
||||
let Json.492 : [C {U64, U8}, C Str] = CallByName Str.9 Json.303;
|
||||
let Json.500 : U8 = 1i64;
|
||||
let Json.501 : U8 = GetTagId Json.492;
|
||||
let Json.502 : Int1 = lowlevel Eq Json.500 Json.501;
|
||||
if Json.502 then
|
||||
let Json.307 : Str = UnionAtIndex (Id 1) (Index 0) Json.492;
|
||||
inc Json.307;
|
||||
dec Json.492;
|
||||
let Json.496 : U64 = 1i64;
|
||||
let Json.495 : {List U8, List U8} = CallByName List.52 Json.304 Json.496;
|
||||
let Json.309 : List U8 = StructAtIndex 1 Json.495;
|
||||
inc Json.309;
|
||||
dec Json.495;
|
||||
let #Derived_gen.0 : List U8 = StructAtIndex 0 Json.495;
|
||||
dec #Derived_gen.0;
|
||||
let Json.494 : [C {}, C Str] = TagId(1) Json.307;
|
||||
let Json.493 : {List U8, [C {}, C Str]} = Struct {Json.309, Json.494};
|
||||
ret Json.493;
|
||||
|
@ -358,14 +342,13 @@ procedure Str.9 (Str.79):
|
|||
let Str.302 : Int1 = StructAtIndex 2 Str.80;
|
||||
if Str.302 then
|
||||
let Str.304 : Str = StructAtIndex 1 Str.80;
|
||||
inc Str.304;
|
||||
dec Str.80;
|
||||
let Str.303 : [C {U64, U8}, C Str] = TagId(1) Str.304;
|
||||
ret Str.303;
|
||||
else
|
||||
let Str.300 : U8 = StructAtIndex 3 Str.80;
|
||||
let Str.301 : U64 = StructAtIndex 0 Str.80;
|
||||
dec Str.80;
|
||||
let #Derived_gen.1 : Str = StructAtIndex 1 Str.80;
|
||||
dec #Derived_gen.1;
|
||||
let Str.299 : {U64, U8} = Struct {Str.301, Str.300};
|
||||
let Str.298 : [C {U64, U8}, C Str] = TagId(0) Str.299;
|
||||
ret Str.298;
|
||||
|
|
|
@ -45,10 +45,7 @@ procedure Decode.26 (Decode.105, Decode.106):
|
|||
procedure Json.160 (Json.570, Json.571):
|
||||
joinpoint Json.508 Json.505 Json.159:
|
||||
let Json.162 : List U8 = StructAtIndex 0 Json.505;
|
||||
inc Json.162;
|
||||
let Json.161 : List U8 = StructAtIndex 1 Json.505;
|
||||
inc Json.161;
|
||||
dec Json.505;
|
||||
joinpoint Json.546:
|
||||
let Json.543 : {List U8, List U8} = Struct {Json.162, Json.161};
|
||||
ret Json.543;
|
||||
|
@ -172,10 +169,7 @@ procedure Json.42 (Json.298):
|
|||
inc Json.298;
|
||||
let Json.563 : {List U8, List U8} = CallByName List.52 Json.298 Json.564;
|
||||
let Json.299 : List U8 = StructAtIndex 0 Json.563;
|
||||
inc Json.299;
|
||||
let Json.301 : List U8 = StructAtIndex 1 Json.563;
|
||||
inc Json.301;
|
||||
dec Json.563;
|
||||
let Json.562 : U8 = 34i64;
|
||||
let Json.561 : List U8 = Array [Json.562];
|
||||
let Json.491 : Int1 = CallByName Bool.11 Json.299 Json.561;
|
||||
|
@ -186,23 +180,18 @@ procedure Json.42 (Json.298):
|
|||
let Json.504 : {} = Struct {};
|
||||
let Json.503 : {List U8, List U8} = CallByName Json.24 Json.301 Json.504;
|
||||
let Json.304 : List U8 = StructAtIndex 0 Json.503;
|
||||
inc Json.304;
|
||||
let Json.303 : List U8 = StructAtIndex 1 Json.503;
|
||||
inc Json.303;
|
||||
dec Json.503;
|
||||
let Json.492 : [C {U64, U8}, C Str] = CallByName Str.9 Json.303;
|
||||
let Json.500 : U8 = 1i64;
|
||||
let Json.501 : U8 = GetTagId Json.492;
|
||||
let Json.502 : Int1 = lowlevel Eq Json.500 Json.501;
|
||||
if Json.502 then
|
||||
let Json.307 : Str = UnionAtIndex (Id 1) (Index 0) Json.492;
|
||||
inc Json.307;
|
||||
dec Json.492;
|
||||
let Json.496 : U64 = 1i64;
|
||||
let Json.495 : {List U8, List U8} = CallByName List.52 Json.304 Json.496;
|
||||
let Json.309 : List U8 = StructAtIndex 1 Json.495;
|
||||
inc Json.309;
|
||||
dec Json.495;
|
||||
let #Derived_gen.0 : List U8 = StructAtIndex 0 Json.495;
|
||||
dec #Derived_gen.0;
|
||||
let Json.494 : [C {}, C Str] = TagId(1) Json.307;
|
||||
let Json.493 : {List U8, [C {}, C Str]} = Struct {Json.309, Json.494};
|
||||
ret Json.493;
|
||||
|
@ -351,14 +340,13 @@ procedure Str.9 (Str.79):
|
|||
let Str.316 : Int1 = StructAtIndex 2 Str.80;
|
||||
if Str.316 then
|
||||
let Str.318 : Str = StructAtIndex 1 Str.80;
|
||||
inc Str.318;
|
||||
dec Str.80;
|
||||
let Str.317 : [C {U64, U8}, C Str] = TagId(1) Str.318;
|
||||
ret Str.317;
|
||||
else
|
||||
let Str.314 : U8 = StructAtIndex 3 Str.80;
|
||||
let Str.315 : U64 = StructAtIndex 0 Str.80;
|
||||
dec Str.80;
|
||||
let #Derived_gen.1 : Str = StructAtIndex 1 Str.80;
|
||||
dec #Derived_gen.1;
|
||||
let Str.313 : {U64, U8} = Struct {Str.315, Str.314};
|
||||
let Str.312 : [C {U64, U8}, C Str] = TagId(0) Str.313;
|
||||
ret Str.312;
|
||||
|
@ -369,17 +357,12 @@ procedure Test.0 ():
|
|||
let Test.36 : {} = CallByName Json.2;
|
||||
let Test.34 : {List U8, [C {}, C Str]} = CallByName Decode.26 Test.35 Test.36;
|
||||
let Test.2 : List U8 = StructAtIndex 0 Test.34;
|
||||
inc Test.2;
|
||||
let Test.1 : [C {}, C Str] = StructAtIndex 1 Test.34;
|
||||
inc Test.1;
|
||||
dec Test.34;
|
||||
let Test.31 : U8 = 1i64;
|
||||
let Test.32 : U8 = GetTagId Test.1;
|
||||
let Test.33 : Int1 = lowlevel Eq Test.31 Test.32;
|
||||
if Test.33 then
|
||||
let Test.3 : Str = UnionAtIndex (Id 1) (Index 0) Test.1;
|
||||
inc Test.3;
|
||||
dec Test.1;
|
||||
let Test.19 : [C {}, C I64] = CallByName Str.27 Test.3;
|
||||
let Test.25 : U8 = 1i64;
|
||||
let Test.26 : U8 = GetTagId Test.19;
|
||||
|
|
|
@ -12,20 +12,16 @@ procedure Test.2 (Test.7):
|
|||
|
||||
procedure Test.6 (Test.17, #Attr.12):
|
||||
let Test.5 : U64 = UnionAtIndex (Id 1) (Index 0) #Attr.12;
|
||||
dec #Attr.12;
|
||||
let Test.31 : Str = "";
|
||||
ret Test.31;
|
||||
|
||||
procedure Test.6 (Test.17, #Attr.12):
|
||||
let Test.5 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12;
|
||||
dec #Attr.12;
|
||||
let Test.19 : Str = "";
|
||||
ret Test.19;
|
||||
|
||||
procedure Test.8 (Test.23, #Attr.12):
|
||||
let Test.7 : Str = UnionAtIndex (Id 2) (Index 0) #Attr.12;
|
||||
inc Test.7;
|
||||
dec #Attr.12;
|
||||
ret Test.7;
|
||||
|
||||
procedure Test.0 ():
|
||||
|
|
|
@ -19,6 +19,7 @@ procedure List.80 (List.517, List.518, List.519, List.520, List.521):
|
|||
let List.502 : Int1 = CallByName Num.22 List.436 List.437;
|
||||
if List.502 then
|
||||
let List.509 : [<rnu>C *self, <null>] = CallByName List.66 List.433 List.436;
|
||||
inc List.509;
|
||||
let List.503 : [<rnu><null>, C {[<rnu>C *self, <null>], *self}] = CallByName List.139 List.434 List.509 List.435;
|
||||
let List.506 : U64 = 1i64;
|
||||
let List.505 : U64 = CallByName Num.19 List.436 List.506;
|
||||
|
|
|
@ -3,6 +3,4 @@ procedure Test.0 ():
|
|||
let Test.5 : Float64 = 3.14f64;
|
||||
let Test.3 : {List I64, Float64} = Struct {Test.4, Test.5};
|
||||
let Test.1 : List I64 = StructAtIndex 0 Test.3;
|
||||
inc Test.1;
|
||||
dec Test.3;
|
||||
ret Test.1;
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
procedure List.3 (List.104, List.105, List.106):
|
||||
let List.497 : {List I64, I64} = CallByName List.64 List.104 List.105 List.106;
|
||||
let List.496 : List I64 = StructAtIndex 0 List.497;
|
||||
inc List.496;
|
||||
dec List.497;
|
||||
ret List.496;
|
||||
|
||||
procedure List.6 (#Attr.2):
|
||||
|
|
|
@ -3,6 +3,7 @@ procedure List.2 (List.96, List.97):
|
|||
let List.496 : Int1 = CallByName Num.22 List.97 List.500;
|
||||
if List.496 then
|
||||
let List.498 : Str = CallByName List.66 List.96 List.97;
|
||||
inc List.498;
|
||||
dec List.96;
|
||||
let List.497 : [C {}, C Str] = TagId(1) List.498;
|
||||
ret List.497;
|
||||
|
@ -66,8 +67,6 @@ procedure Test.0 ():
|
|||
let Test.11 : Int1 = lowlevel Eq Test.9 Test.10;
|
||||
if Test.11 then
|
||||
let Test.5 : Str = UnionAtIndex (Id 1) (Index 0) Test.6;
|
||||
inc Test.5;
|
||||
dec Test.6;
|
||||
ret Test.5;
|
||||
else
|
||||
dec Test.6;
|
||||
|
|
|
@ -3,6 +3,7 @@ procedure List.2 (List.96, List.97):
|
|||
let List.496 : Int1 = CallByName Num.22 List.97 List.500;
|
||||
if List.496 then
|
||||
let List.498 : Str = CallByName List.66 List.96 List.97;
|
||||
inc List.498;
|
||||
dec List.96;
|
||||
let List.497 : [C {}, C Str] = TagId(1) List.498;
|
||||
ret List.497;
|
||||
|
@ -62,8 +63,6 @@ procedure Test.0 ():
|
|||
let Test.11 : Int1 = lowlevel Eq Test.9 Test.10;
|
||||
if Test.11 then
|
||||
let Test.5 : Str = UnionAtIndex (Id 1) (Index 0) Test.6;
|
||||
inc Test.5;
|
||||
dec Test.6;
|
||||
ret Test.5;
|
||||
else
|
||||
dec Test.6;
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
procedure List.3 (List.104, List.105, List.106):
|
||||
let List.495 : {List I64, I64} = CallByName List.64 List.104 List.105 List.106;
|
||||
let List.494 : List I64 = StructAtIndex 0 List.495;
|
||||
inc List.494;
|
||||
dec List.495;
|
||||
ret List.494;
|
||||
|
||||
procedure List.6 (#Attr.2):
|
||||
|
|
|
@ -4,13 +4,9 @@ procedure Test.2 (Test.4):
|
|||
let Test.12 : Int1 = lowlevel Eq Test.10 Test.11;
|
||||
if Test.12 then
|
||||
let Test.5 : Str = UnionAtIndex (Id 0) (Index 0) Test.4;
|
||||
inc Test.5;
|
||||
dec Test.4;
|
||||
ret Test.5;
|
||||
else
|
||||
let Test.6 : Str = UnionAtIndex (Id 1) (Index 0) Test.4;
|
||||
inc Test.6;
|
||||
dec Test.4;
|
||||
ret Test.6;
|
||||
|
||||
procedure Test.0 ():
|
||||
|
|
|
@ -17,21 +17,17 @@ procedure Test.0 ():
|
|||
let Test.19 : {I64, Str} = CallByName Test.1;
|
||||
let Test.5 : {{I64, Str}, {}} = Struct {Test.19, Test.18};
|
||||
let Test.14 : {I64, Str} = StructAtIndex 0 Test.5;
|
||||
inc Test.14;
|
||||
let Test.15 : I64 = StructAtIndex 0 Test.14;
|
||||
dec Test.14;
|
||||
let Test.16 : I64 = 42i64;
|
||||
let Test.17 : Int1 = lowlevel Eq Test.16 Test.15;
|
||||
if Test.17 then
|
||||
let Test.13 : {I64, Str} = StructAtIndex 0 Test.5;
|
||||
inc Test.13;
|
||||
dec Test.5;
|
||||
let Test.7 : {I64, Str} = CallByName Test.1;
|
||||
let Test.6 : Int1 = CallByName Bool.11 Test.7 Test.13;
|
||||
dec Test.13;
|
||||
dec Test.7;
|
||||
ret Test.6;
|
||||
else
|
||||
dec Test.5;
|
||||
dec Test.14;
|
||||
let Test.11 : Int1 = CallByName Bool.1;
|
||||
ret Test.11;
|
||||
|
|
|
@ -21,9 +21,11 @@ procedure Test.0 ():
|
|||
let Test.6 : {I64, Str} = CallByName Test.1;
|
||||
let Test.5 : Int1 = CallByName Bool.11 Test.6 Test.4;
|
||||
dec Test.6;
|
||||
dec Test.4;
|
||||
let #Derived_gen.0 : Str = StructAtIndex 1 Test.4;
|
||||
dec #Derived_gen.0;
|
||||
ret Test.5;
|
||||
else
|
||||
dec Test.4;
|
||||
let #Derived_gen.1 : Str = StructAtIndex 1 Test.4;
|
||||
dec #Derived_gen.1;
|
||||
let Test.10 : Int1 = CallByName Bool.1;
|
||||
ret Test.10;
|
||||
|
|
|
@ -8,19 +8,26 @@ procedure Test.0 ():
|
|||
let Test.18 : Int1 = lowlevel Eq Test.16 Test.17;
|
||||
if Test.18 then
|
||||
let Test.12 : [<rnu><null>, C *self] = UnionAtIndex (Id 0) (Index 0) Test.2;
|
||||
inc Test.12;
|
||||
dec Test.2;
|
||||
let Test.13 : U8 = 0i64;
|
||||
let Test.14 : U8 = GetTagId Test.12;
|
||||
dec Test.12;
|
||||
let Test.15 : Int1 = lowlevel Eq Test.13 Test.14;
|
||||
if Test.15 then
|
||||
let Test.8 : I64 = 1i64;
|
||||
ret Test.8;
|
||||
joinpoint #Derived_gen.2:
|
||||
let Test.13 : U8 = 0i64;
|
||||
let Test.14 : U8 = GetTagId Test.12;
|
||||
dec Test.12;
|
||||
let Test.15 : Int1 = lowlevel Eq Test.13 Test.14;
|
||||
if Test.15 then
|
||||
let Test.8 : I64 = 1i64;
|
||||
ret Test.8;
|
||||
else
|
||||
let Test.9 : I64 = 0i64;
|
||||
ret Test.9;
|
||||
in
|
||||
let #Derived_gen.3 : Int1 = lowlevel RefCountIsUnique Test.2;
|
||||
if #Derived_gen.3 then
|
||||
decref Test.2;
|
||||
jump #Derived_gen.2;
|
||||
else
|
||||
let Test.9 : I64 = 0i64;
|
||||
ret Test.9;
|
||||
inc Test.12;
|
||||
decref Test.2;
|
||||
jump #Derived_gen.2;
|
||||
else
|
||||
dec Test.2;
|
||||
let Test.10 : I64 = 0i64;
|
||||
ret Test.10;
|
||||
|
|
|
@ -20,8 +20,6 @@ procedure Test.1 (Test.24, Test.25, Test.26):
|
|||
let Test.21 : {I64, List I64} = Struct {Test.22, Test.23};
|
||||
let Test.5 : I64 = StructAtIndex 0 Test.21;
|
||||
let Test.6 : List I64 = StructAtIndex 1 Test.21;
|
||||
inc Test.6;
|
||||
dec Test.21;
|
||||
let Test.20 : I64 = 1i64;
|
||||
let Test.19 : I64 = CallByName Num.20 Test.5 Test.20;
|
||||
let Test.16 : List I64 = CallByName Test.1 Test.6 Test.3 Test.19;
|
||||
|
|
|
@ -15,8 +15,6 @@ procedure List.2 (List.96, List.97):
|
|||
procedure List.3 (List.104, List.105, List.106):
|
||||
let List.503 : {List I64, I64} = CallByName List.64 List.104 List.105 List.106;
|
||||
let List.502 : List I64 = StructAtIndex 0 List.503;
|
||||
inc List.502;
|
||||
dec List.503;
|
||||
ret List.502;
|
||||
|
||||
procedure List.6 (#Attr.2):
|
||||
|
|
|
@ -26,21 +26,29 @@ procedure Test.3 (Test.7):
|
|||
|
||||
procedure Test.6 (Test.16, #Attr.12):
|
||||
let Test.5 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12;
|
||||
dec #Attr.12;
|
||||
let Test.19 : {} = Struct {};
|
||||
let Test.22 : Str = "foobar";
|
||||
let Test.20 : [<rnu><null>, C {}] = CallByName Test.8 Test.22 Test.5;
|
||||
let Test.21 : U8 = GetTagId Test.20;
|
||||
switch Test.21:
|
||||
case 0:
|
||||
let Test.18 : Str = CallByName Test.6 Test.19 Test.20;
|
||||
ret Test.18;
|
||||
|
||||
default:
|
||||
dec Test.20;
|
||||
let Test.18 : Str = CallByName Test.11 Test.19;
|
||||
ret Test.18;
|
||||
|
||||
joinpoint #Derived_gen.0:
|
||||
let Test.19 : {} = Struct {};
|
||||
let Test.22 : Str = "foobar";
|
||||
let Test.20 : [<rnu><null>, C {}] = CallByName Test.8 Test.22 Test.5;
|
||||
let Test.21 : U8 = GetTagId Test.20;
|
||||
switch Test.21:
|
||||
case 0:
|
||||
let Test.18 : Str = CallByName Test.6 Test.19 Test.20;
|
||||
ret Test.18;
|
||||
|
||||
default:
|
||||
dec Test.20;
|
||||
let Test.18 : Str = CallByName Test.11 Test.19;
|
||||
ret Test.18;
|
||||
|
||||
in
|
||||
let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique #Attr.12;
|
||||
if #Derived_gen.1 then
|
||||
decref #Attr.12;
|
||||
jump #Derived_gen.0;
|
||||
else
|
||||
decref #Attr.12;
|
||||
jump #Derived_gen.0;
|
||||
|
||||
procedure Test.8 (Test.9, Test.7):
|
||||
let Test.24 : [<rnu><null>, C {}] = CallByName Test.10 Test.9;
|
||||
|
|
|
@ -39,19 +39,27 @@ procedure Test.4 (Test.28, Test.29):
|
|||
joinpoint Test.15 Test.5 #Attr.12:
|
||||
let Test.2 : U8 = UnionAtIndex (Id 0) (Index 1) #Attr.12;
|
||||
let Test.3 : [<rnu><null>, C *self U8] = UnionAtIndex (Id 0) (Index 0) #Attr.12;
|
||||
inc Test.3;
|
||||
dec #Attr.12;
|
||||
let Test.17 : U8 = CallByName Num.21 Test.2 Test.5;
|
||||
let Test.18 : U8 = GetTagId Test.3;
|
||||
switch Test.18:
|
||||
case 0:
|
||||
jump Test.15 Test.17 Test.3;
|
||||
|
||||
default:
|
||||
dec Test.3;
|
||||
let Test.16 : U8 = CallByName Test.6 Test.17;
|
||||
ret Test.16;
|
||||
|
||||
joinpoint #Derived_gen.1:
|
||||
let Test.17 : U8 = CallByName Num.21 Test.2 Test.5;
|
||||
let Test.18 : U8 = GetTagId Test.3;
|
||||
switch Test.18:
|
||||
case 0:
|
||||
jump Test.15 Test.17 Test.3;
|
||||
|
||||
default:
|
||||
dec Test.3;
|
||||
let Test.16 : U8 = CallByName Test.6 Test.17;
|
||||
ret Test.16;
|
||||
|
||||
in
|
||||
let #Derived_gen.2 : Int1 = lowlevel RefCountIsUnique #Attr.12;
|
||||
if #Derived_gen.2 then
|
||||
decref #Attr.12;
|
||||
jump #Derived_gen.1;
|
||||
else
|
||||
inc Test.3;
|
||||
decref #Attr.12;
|
||||
jump #Derived_gen.1;
|
||||
in
|
||||
jump Test.15 Test.28 Test.29;
|
||||
|
||||
|
|
|
@ -8,8 +8,13 @@ procedure Str.3 (#Attr.2, #Attr.3):
|
|||
|
||||
procedure Test.11 (Test.29, #Attr.12):
|
||||
let Test.10 : {} = UnionAtIndex (Id 0) (Index 0) #Attr.12;
|
||||
dec #Attr.12;
|
||||
ret Test.10;
|
||||
let #Derived_gen.2 : Int1 = lowlevel RefCountIsUnique #Attr.12;
|
||||
if #Derived_gen.2 then
|
||||
decref #Attr.12;
|
||||
ret Test.10;
|
||||
else
|
||||
decref #Attr.12;
|
||||
ret Test.10;
|
||||
|
||||
procedure Test.11 (Test.29, Test.10):
|
||||
ret Test.10;
|
||||
|
@ -18,20 +23,28 @@ procedure Test.14 (Test.62, Test.63):
|
|||
joinpoint Test.37 Test.36 #Attr.12:
|
||||
let Test.12 : {} = UnionAtIndex (Id 1) (Index 1) #Attr.12;
|
||||
let Test.13 : I64 = UnionAtIndex (Id 1) (Index 0) #Attr.12;
|
||||
dec #Attr.12;
|
||||
let Test.43 : {} = Struct {};
|
||||
let Test.42 : {} = CallByName Test.11 Test.43 Test.12;
|
||||
let Test.38 : [<r>C {}, C I64 {}] = CallByName Test.9 Test.42 Test.13;
|
||||
let Test.40 : {} = Struct {};
|
||||
let Test.41 : U8 = GetTagId Test.38;
|
||||
switch Test.41:
|
||||
case 0:
|
||||
let Test.39 : {} = CallByName Test.11 Test.40 Test.38;
|
||||
ret Test.39;
|
||||
|
||||
default:
|
||||
jump Test.37 Test.40 Test.38;
|
||||
|
||||
joinpoint #Derived_gen.0:
|
||||
let Test.43 : {} = Struct {};
|
||||
let Test.42 : {} = CallByName Test.11 Test.43 Test.12;
|
||||
let Test.38 : [<r>C {}, C I64 {}] = CallByName Test.9 Test.42 Test.13;
|
||||
let Test.40 : {} = Struct {};
|
||||
let Test.41 : U8 = GetTagId Test.38;
|
||||
switch Test.41:
|
||||
case 0:
|
||||
let Test.39 : {} = CallByName Test.11 Test.40 Test.38;
|
||||
ret Test.39;
|
||||
|
||||
default:
|
||||
jump Test.37 Test.40 Test.38;
|
||||
|
||||
in
|
||||
let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique #Attr.12;
|
||||
if #Derived_gen.1 then
|
||||
decref #Attr.12;
|
||||
jump #Derived_gen.0;
|
||||
else
|
||||
decref #Attr.12;
|
||||
jump #Derived_gen.0;
|
||||
in
|
||||
jump Test.37 Test.62 Test.63;
|
||||
|
||||
|
|
|
@ -15,8 +15,6 @@ procedure List.2 (List.96, List.97):
|
|||
procedure List.3 (List.104, List.105, List.106):
|
||||
let List.503 : {List I64, I64} = CallByName List.64 List.104 List.105 List.106;
|
||||
let List.502 : List I64 = StructAtIndex 0 List.503;
|
||||
inc List.502;
|
||||
dec List.503;
|
||||
ret List.502;
|
||||
|
||||
procedure List.6 (#Attr.2):
|
||||
|
|
|
@ -46,10 +46,7 @@ procedure Json.102 (Json.103, Json.530, Json.101):
|
|||
|
||||
procedure Json.144 (Json.145, Json.486, #Attr.12):
|
||||
let Json.143 : List Str = StructAtIndex 1 #Attr.12;
|
||||
inc Json.143;
|
||||
let Json.142 : Str = StructAtIndex 0 #Attr.12;
|
||||
inc Json.142;
|
||||
dec #Attr.12;
|
||||
let Json.524 : I64 = 123i64;
|
||||
let Json.523 : U8 = CallByName Num.127 Json.524;
|
||||
let Json.520 : List U8 = CallByName List.4 Json.145 Json.523;
|
||||
|
@ -72,8 +69,6 @@ procedure Json.144 (Json.145, Json.486, #Attr.12):
|
|||
let Json.497 : {} = Struct {};
|
||||
let Json.495 : {List U8, U64} = CallByName List.18 Json.143 Json.496 Json.497;
|
||||
let Json.149 : List U8 = StructAtIndex 0 Json.495;
|
||||
inc Json.149;
|
||||
dec Json.495;
|
||||
let Json.494 : I64 = 93i64;
|
||||
let Json.493 : U8 = CallByName Num.127 Json.494;
|
||||
let Json.490 : List U8 = CallByName List.4 Json.149 Json.493;
|
||||
|
@ -84,9 +79,7 @@ procedure Json.144 (Json.145, Json.486, #Attr.12):
|
|||
|
||||
procedure Json.146 (Json.488, Json.152):
|
||||
let Json.150 : List U8 = StructAtIndex 0 Json.488;
|
||||
inc Json.150;
|
||||
let Json.151 : U64 = StructAtIndex 1 Json.488;
|
||||
dec Json.488;
|
||||
let Json.507 : {} = Struct {};
|
||||
let Json.153 : List U8 = CallByName Encode.24 Json.150 Json.152 Json.507;
|
||||
joinpoint Json.502 Json.154:
|
||||
|
@ -153,6 +146,7 @@ procedure List.80 (List.558, List.559, List.560, List.561, List.562):
|
|||
let List.534 : Int1 = CallByName Num.22 List.436 List.437;
|
||||
if List.534 then
|
||||
let List.541 : Str = CallByName List.66 List.433 List.436;
|
||||
inc List.541;
|
||||
let List.535 : {List U8, U64} = CallByName List.139 List.434 List.541 List.435;
|
||||
let List.538 : U64 = 1i64;
|
||||
let List.537 : U64 = CallByName Num.19 List.436 List.538;
|
||||
|
@ -212,8 +206,8 @@ procedure Test.5 (Test.6, Test.7, Test.4):
|
|||
if Test.25 then
|
||||
let Test.26 : Str = "A";
|
||||
let Test.29 : Str = StructAtIndex 0 Test.4;
|
||||
inc Test.29;
|
||||
dec Test.4;
|
||||
let #Derived_gen.0 : Str = StructAtIndex 1 Test.4;
|
||||
dec #Derived_gen.0;
|
||||
let Test.28 : Str = CallByName Json.18 Test.29;
|
||||
let Test.27 : List Str = Array [Test.28];
|
||||
let Test.19 : {Str, List Str} = CallByName Json.22 Test.26 Test.27;
|
||||
|
@ -221,8 +215,8 @@ procedure Test.5 (Test.6, Test.7, Test.4):
|
|||
else
|
||||
let Test.21 : Str = "B";
|
||||
let Test.24 : Str = StructAtIndex 1 Test.4;
|
||||
inc Test.24;
|
||||
dec Test.4;
|
||||
let #Derived_gen.1 : Str = StructAtIndex 0 Test.4;
|
||||
dec #Derived_gen.1;
|
||||
let Test.23 : Str = CallByName Json.18 Test.24;
|
||||
let Test.22 : List Str = Array [Test.23];
|
||||
let Test.19 : {Str, List Str} = CallByName Json.22 Test.21 Test.22;
|
||||
|
|
|
@ -54,14 +54,13 @@ procedure Test.43 (Test.44, Test.42):
|
|||
let Test.75 : Int1 = CallByName Bool.2;
|
||||
if Test.75 then
|
||||
let Test.77 : Str = StructAtIndex 0 Test.42;
|
||||
inc Test.77;
|
||||
dec Test.42;
|
||||
let Test.76 : Int1 = CallByName Test.16 Test.77;
|
||||
let Test.61 : Int1 = CallByName Test.14 Test.76;
|
||||
jump Test.62 Test.61;
|
||||
else
|
||||
let Test.69 : U8 = StructAtIndex 1 Test.42;
|
||||
dec Test.42;
|
||||
let #Derived_gen.0 : Str = StructAtIndex 0 Test.42;
|
||||
dec #Derived_gen.0;
|
||||
let Test.63 : Int1 = CallByName Test.15 Test.69;
|
||||
let Test.61 : Int1 = CallByName Test.14 Test.63;
|
||||
jump Test.62 Test.61;
|
||||
|
|
|
@ -87,10 +87,7 @@ procedure Json.1 ():
|
|||
|
||||
procedure Json.144 (Json.145, Json.486, #Attr.12):
|
||||
let Json.143 : List [C {}, C {}] = StructAtIndex 1 #Attr.12;
|
||||
inc Json.143;
|
||||
let Json.142 : Str = StructAtIndex 0 #Attr.12;
|
||||
inc Json.142;
|
||||
dec #Attr.12;
|
||||
let Json.524 : I64 = 123i64;
|
||||
let Json.523 : U8 = CallByName Num.127 Json.524;
|
||||
let Json.520 : List U8 = CallByName List.4 Json.145 Json.523;
|
||||
|
@ -113,8 +110,6 @@ procedure Json.144 (Json.145, Json.486, #Attr.12):
|
|||
let Json.497 : {} = Struct {};
|
||||
let Json.495 : {List U8, U64} = CallByName List.18 Json.143 Json.496 Json.497;
|
||||
let Json.149 : List U8 = StructAtIndex 0 Json.495;
|
||||
inc Json.149;
|
||||
dec Json.495;
|
||||
let Json.494 : I64 = 93i64;
|
||||
let Json.493 : U8 = CallByName Num.127 Json.494;
|
||||
let Json.490 : List U8 = CallByName List.4 Json.149 Json.493;
|
||||
|
@ -125,10 +120,7 @@ procedure Json.144 (Json.145, Json.486, #Attr.12):
|
|||
|
||||
procedure Json.144 (Json.145, Json.486, #Attr.12):
|
||||
let Json.143 : List [] = StructAtIndex 1 #Attr.12;
|
||||
inc Json.143;
|
||||
let Json.142 : Str = StructAtIndex 0 #Attr.12;
|
||||
inc Json.142;
|
||||
dec #Attr.12;
|
||||
let Json.574 : I64 = 123i64;
|
||||
let Json.573 : U8 = CallByName Num.127 Json.574;
|
||||
let Json.570 : List U8 = CallByName List.4 Json.145 Json.573;
|
||||
|
@ -151,8 +143,6 @@ procedure Json.144 (Json.145, Json.486, #Attr.12):
|
|||
let Json.547 : {} = Struct {};
|
||||
let Json.545 : {List U8, U64} = CallByName List.18 Json.143 Json.546 Json.547;
|
||||
let Json.149 : List U8 = StructAtIndex 0 Json.545;
|
||||
inc Json.149;
|
||||
dec Json.545;
|
||||
let Json.544 : I64 = 93i64;
|
||||
let Json.543 : U8 = CallByName Num.127 Json.544;
|
||||
let Json.540 : List U8 = CallByName List.4 Json.149 Json.543;
|
||||
|
@ -163,9 +153,7 @@ procedure Json.144 (Json.145, Json.486, #Attr.12):
|
|||
|
||||
procedure Json.146 (Json.488, Json.152):
|
||||
let Json.150 : List U8 = StructAtIndex 0 Json.488;
|
||||
inc Json.150;
|
||||
let Json.151 : U64 = StructAtIndex 1 Json.488;
|
||||
dec Json.488;
|
||||
let Json.507 : {} = Struct {};
|
||||
let Json.153 : List U8 = CallByName Encode.24 Json.150 Json.152 Json.507;
|
||||
joinpoint Json.502 Json.154:
|
||||
|
@ -186,9 +174,7 @@ procedure Json.146 (Json.488, Json.152):
|
|||
|
||||
procedure Json.146 (Json.488, Json.152):
|
||||
let Json.150 : List U8 = StructAtIndex 0 Json.488;
|
||||
inc Json.150;
|
||||
let Json.151 : U64 = StructAtIndex 1 Json.488;
|
||||
dec Json.488;
|
||||
let Json.557 : {} = Struct {};
|
||||
let Json.153 : List U8 = CallByName Encode.24 Json.150 Json.152 Json.557;
|
||||
joinpoint Json.552 Json.154:
|
||||
|
|
|
@ -26,7 +26,7 @@ procedure Test.0 ():
|
|||
let Test.3 : Str = "http://www.example.com";
|
||||
let Test.4 : {Str, Str} = CallByName Dep.0;
|
||||
let Test.2 : Str = StructAtIndex 0 Test.4;
|
||||
inc Test.2;
|
||||
dec Test.4;
|
||||
let #Derived_gen.0 : Str = StructAtIndex 1 Test.4;
|
||||
dec #Derived_gen.0;
|
||||
let Test.1 : {Str, Str} = Struct {Test.2, Test.3};
|
||||
ret Test.1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue