mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Annotate low-level usages
This commit is contained in:
parent
52dfb75dc0
commit
cad0a1421e
3 changed files with 75 additions and 89 deletions
|
@ -1044,22 +1044,6 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
BasicValueEnum::IntValue(int_val)
|
BasicValueEnum::IntValue(int_val)
|
||||||
}
|
}
|
||||||
Symbol::LIST_LEN => {
|
|
||||||
debug_assert!(args.len() == 1);
|
|
||||||
|
|
||||||
BasicValueEnum::IntValue(load_list_len(env.builder, args[0].0.into_struct_value()))
|
|
||||||
}
|
|
||||||
Symbol::LIST_IS_EMPTY => {
|
|
||||||
debug_assert!(args.len() == 1);
|
|
||||||
|
|
||||||
let list_struct = args[0].0.into_struct_value();
|
|
||||||
let builder = env.builder;
|
|
||||||
let list_len = load_list_len(builder, list_struct);
|
|
||||||
let zero = env.ptr_int().const_zero();
|
|
||||||
let answer = builder.build_int_compare(IntPredicate::EQ, list_len, zero, "is_zero");
|
|
||||||
|
|
||||||
BasicValueEnum::IntValue(answer)
|
|
||||||
}
|
|
||||||
Symbol::INT_REM_UNSAFE => {
|
Symbol::INT_REM_UNSAFE => {
|
||||||
debug_assert!(args.len() == 2);
|
debug_assert!(args.len() == 2);
|
||||||
|
|
||||||
|
@ -1446,12 +1430,24 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
ListLen => {
|
ListLen => {
|
||||||
debug_assert!(args.len() == 1);
|
debug_assert_eq!(args.len(), 1);
|
||||||
|
|
||||||
let arg = build_expr(env, layout_ids, scope, parent, &args[0].0);
|
let arg = build_expr(env, layout_ids, scope, parent, &args[0].0);
|
||||||
|
|
||||||
BasicValueEnum::IntValue(load_list_len(env.builder, arg.into_struct_value()))
|
BasicValueEnum::IntValue(load_list_len(env.builder, arg.into_struct_value()))
|
||||||
}
|
}
|
||||||
|
ListIsEmpty => {
|
||||||
|
debug_assert_eq!(args.len(), 1);
|
||||||
|
|
||||||
|
let arg = build_expr(env, layout_ids, scope, parent, &args[0].0);
|
||||||
|
let list_struct = arg.into_struct_value();
|
||||||
|
let builder = env.builder;
|
||||||
|
let list_len = load_list_len(builder, list_struct);
|
||||||
|
let zero = env.ptr_int().const_zero();
|
||||||
|
let answer = builder.build_int_compare(IntPredicate::EQ, list_len, zero, "is_zero");
|
||||||
|
|
||||||
|
BasicValueEnum::IntValue(answer)
|
||||||
|
}
|
||||||
NumAdd | NumSub | NumMul | NumLt | NumLte | NumGt | NumGte => {
|
NumAdd | NumSub | NumMul | NumLt | NumLte | NumGt | NumGte => {
|
||||||
debug_assert_eq!(args.len(), 2);
|
debug_assert_eq!(args.len(), 2);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ pub enum LowLevel {
|
||||||
ListLen,
|
ListLen,
|
||||||
ListGetUnsafe,
|
ListGetUnsafe,
|
||||||
ListSetUnsafe,
|
ListSetUnsafe,
|
||||||
|
ListIsEmpty,
|
||||||
NumAdd,
|
NumAdd,
|
||||||
NumSub,
|
NumSub,
|
||||||
NumMul,
|
NumMul,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use roc_can::expr::Expr;
|
use roc_can::expr::Expr;
|
||||||
use roc_collections::all::{ImMap, ImSet};
|
use roc_collections::all::{ImMap, ImSet};
|
||||||
use roc_module::ident::Lowercase;
|
use roc_module::ident::Lowercase;
|
||||||
|
use roc_module::low_level::LowLevel;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_region::all::Located;
|
|
||||||
use roc_types::subs::Variable;
|
use roc_types::subs::Variable;
|
||||||
|
|
||||||
// fake field names for container elements
|
// fake field names for container elements
|
||||||
|
@ -618,25 +618,27 @@ pub fn annotate_usage(expr: &Expr, usage: &mut VarUsage) {
|
||||||
annotate_usage(&loc_expr.value, usage);
|
annotate_usage(&loc_expr.value, usage);
|
||||||
}
|
}
|
||||||
Call(fun, loc_args, _) => {
|
Call(fun, loc_args, _) => {
|
||||||
if let Var(symbol) = fun.1.value {
|
match fun.1.value {
|
||||||
// call by name
|
Var(symbol) => {
|
||||||
special_case_builtins(usage, symbol, loc_args);
|
// call by name
|
||||||
} else {
|
usage.register_unique(symbol);
|
||||||
// unknown call
|
|
||||||
annotate_usage(&fun.1.value, usage);
|
|
||||||
|
|
||||||
for (_, arg) in loc_args {
|
for (_, arg) in loc_args {
|
||||||
annotate_usage(&arg.value, usage);
|
annotate_usage(&arg.value, usage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// unknown call
|
||||||
|
annotate_usage(&fun.1.value, usage);
|
||||||
|
|
||||||
|
for (_, arg) in loc_args {
|
||||||
|
annotate_usage(&arg.value, usage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RunLowLevel { op, args, ret_var } => {
|
RunLowLevel { op, args, ret_var } => {
|
||||||
todo!(
|
annotate_low_level_usage(usage, *op, args, *ret_var);
|
||||||
"TODO implement UNIQ RunLowLevel for {:?}({:?}) -> {:?}",
|
|
||||||
op,
|
|
||||||
args,
|
|
||||||
ret_var
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Closure(_, _, _, _, body) => {
|
Closure(_, _, _, _, body) => {
|
||||||
annotate_usage(&body.0.value, usage);
|
annotate_usage(&body.0.value, usage);
|
||||||
|
@ -701,75 +703,62 @@ fn get_access_chain<'a>(expr: &'a Expr, chain: &mut Vec<Lowercase>) -> Option<&'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn special_case_builtins(
|
fn annotate_low_level_usage(
|
||||||
usage: &mut VarUsage,
|
usage: &mut VarUsage,
|
||||||
symbol: Symbol,
|
op: LowLevel,
|
||||||
loc_args: &[(Variable, Located<Expr>)],
|
args: &[(Variable, Expr)],
|
||||||
|
_ret_var: Variable,
|
||||||
) {
|
) {
|
||||||
use Expr::Var;
|
use Expr::Var;
|
||||||
|
use LowLevel::*;
|
||||||
use Mark::*;
|
use Mark::*;
|
||||||
use Usage::*;
|
use Usage::*;
|
||||||
match symbol {
|
|
||||||
Symbol::LIST_GET => {
|
|
||||||
debug_assert!(loc_args.len() == 2);
|
|
||||||
|
|
||||||
let loc_list = &loc_args[0].1;
|
match op {
|
||||||
let loc_index = &loc_args[1].1;
|
ListLen | ListIsEmpty | ListGetUnsafe => {
|
||||||
|
match &args[0].1 {
|
||||||
if let Var(list_var) = loc_list.value {
|
Var(list_var) => {
|
||||||
usage.register_with(
|
usage.register_with(
|
||||||
list_var,
|
*list_var,
|
||||||
&Access(Container::List, Seen, FieldAccess::list_access()),
|
&Access(Container::List, Seen, FieldAccess::list_seen()),
|
||||||
);
|
);
|
||||||
} else {
|
}
|
||||||
annotate_usage(&loc_list.value, usage);
|
list => {
|
||||||
|
annotate_usage(list, usage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
annotate_usage(&loc_index.value, usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
Symbol::LIST_SET => {
|
for (_, arg) in &args[1..] {
|
||||||
debug_assert!(loc_args.len() == 3);
|
annotate_usage(arg, usage);
|
||||||
|
|
||||||
let loc_list = &loc_args[0].1;
|
|
||||||
let loc_index = &loc_args[1].1;
|
|
||||||
let loc_value = &loc_args[2].1;
|
|
||||||
|
|
||||||
if let Var(list_var) = loc_list.value {
|
|
||||||
usage.register_with(
|
|
||||||
list_var,
|
|
||||||
&Update(
|
|
||||||
Container::List,
|
|
||||||
ImSet::default(),
|
|
||||||
FieldAccess::list_update(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
annotate_usage(&loc_list.value, usage);
|
|
||||||
}
|
|
||||||
annotate_usage(&loc_index.value, usage);
|
|
||||||
annotate_usage(&loc_value.value, usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
Symbol::LIST_IS_EMPTY | Symbol::LIST_LEN => {
|
|
||||||
debug_assert!(loc_args.len() == 1);
|
|
||||||
|
|
||||||
let loc_list = &loc_args[0].1;
|
|
||||||
|
|
||||||
if let Var(list_var) = loc_list.value {
|
|
||||||
usage.register_with(
|
|
||||||
list_var,
|
|
||||||
&Access(Container::List, Seen, FieldAccess::list_seen()),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
annotate_usage(&loc_list.value, usage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
ListSetUnsafe => {
|
||||||
usage.register_unique(symbol);
|
match &args[0].1 {
|
||||||
|
Var(list_var) => {
|
||||||
|
usage.register_with(
|
||||||
|
*list_var,
|
||||||
|
&Update(
|
||||||
|
Container::List,
|
||||||
|
ImSet::default(),
|
||||||
|
FieldAccess::list_update(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
list => {
|
||||||
|
annotate_usage(list, usage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (_, arg) in loc_args {
|
for (_, arg) in &args[1..] {
|
||||||
annotate_usage(&arg.value, usage);
|
annotate_usage(arg, usage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NumAdd | NumSub | NumMul | NumGt | NumGte | NumLt | NumLte | Eq | NotEq | And | Or
|
||||||
|
| Not => {
|
||||||
|
for (_, arg) in args {
|
||||||
|
annotate_usage(&arg, usage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue