mirror of
https://github.com/roc-lang/roc.git
synced 2025-11-25 05:33:14 +00:00
Merge branch 'main' into drop_specialization
Signed-off-by: J Teeuwissen <jelleteeuwissen@hotmail.nl>
This commit is contained in:
commit
7439ee0c8c
229 changed files with 3602 additions and 2412 deletions
|
|
@ -487,9 +487,9 @@ impl<'a> Env<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn apply_refcount_operation<'a>(
|
||||
fn apply_refcount_operation(
|
||||
builder: &mut FuncDefBuilder,
|
||||
env: &mut Env<'a>,
|
||||
env: &mut Env<'_>,
|
||||
block: BlockId,
|
||||
modify_rc: &ModifyRc,
|
||||
) -> Result<()> {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::target::{arch_str, target_zig_str};
|
||||
use libloading::{Error, Library};
|
||||
use roc_command_utils::{cargo, clang, get_lib_path, rustup, zig};
|
||||
use roc_command_utils::{cargo, clang, rustup, zig};
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_mono::ir::OptLevel;
|
||||
use std::collections::HashMap;
|
||||
|
|
@ -63,31 +63,57 @@ pub fn legacy_host_filename(target: &Triple) -> Option<String> {
|
|||
)
|
||||
}
|
||||
|
||||
fn find_zig_str_path() -> PathBuf {
|
||||
// First try using the lib path relative to the executable location.
|
||||
let lib_path_opt = get_lib_path();
|
||||
// Attempts to find a file that is stored relative to the roc executable.
|
||||
// Since roc is built in target/debug/roc, we may need to drop that path to find the file.
|
||||
// This is used to avoid depending on the current working directory.
|
||||
pub fn get_relative_path(sub_path: &Path) -> Option<PathBuf> {
|
||||
if sub_path.is_absolute() {
|
||||
internal_error!(
|
||||
"get_relative_path requires sub_path to be relative, instead got {:?}",
|
||||
sub_path
|
||||
);
|
||||
}
|
||||
let exe_relative_str_path_opt = std::env::current_exe().ok();
|
||||
|
||||
if let Some(lib_path) = lib_path_opt {
|
||||
let zig_str_path = lib_path.join("str.zig");
|
||||
if let Some(exe_relative_str_path) = exe_relative_str_path_opt {
|
||||
#[cfg(windows)]
|
||||
let exe_relative_str_path = roc_command_utils::strip_windows_prefix(&exe_relative_str_path);
|
||||
|
||||
if std::path::Path::exists(&zig_str_path) {
|
||||
return zig_str_path;
|
||||
let mut curr_parent_opt = exe_relative_str_path.parent();
|
||||
|
||||
// We need to support paths like ./roc, ./bin/roc, ./target/debug/roc and tests like ./target/debug/deps/valgrind-63c787aa176d1277
|
||||
// This requires dropping up to 3 directories.
|
||||
for _ in 0..=3 {
|
||||
if let Some(curr_parent) = curr_parent_opt {
|
||||
let potential_path = curr_parent.join(sub_path);
|
||||
|
||||
if std::path::Path::exists(&potential_path) {
|
||||
return Some(potential_path);
|
||||
} else {
|
||||
curr_parent_opt = curr_parent.parent();
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let zig_str_path = PathBuf::from("crates/compiler/builtins/bitcode/src/str.zig");
|
||||
None
|
||||
}
|
||||
|
||||
if std::path::Path::exists(&zig_str_path) {
|
||||
return zig_str_path;
|
||||
fn find_zig_glue_path() -> PathBuf {
|
||||
// First try using the repo path relative to the executable location.
|
||||
let path = get_relative_path(Path::new("crates/compiler/builtins/bitcode/src/glue.zig"));
|
||||
if let Some(path) = path {
|
||||
return path;
|
||||
}
|
||||
// Fallback on a lib path relative to the executable location.
|
||||
let path = get_relative_path(Path::new("lib/glue.zig"));
|
||||
if let Some(path) = path {
|
||||
return path;
|
||||
}
|
||||
|
||||
// when running the tests, we start in the /cli directory
|
||||
let zig_str_path = PathBuf::from("../compiler/builtins/bitcode/src/str.zig");
|
||||
if std::path::Path::exists(&zig_str_path) {
|
||||
return zig_str_path;
|
||||
}
|
||||
|
||||
internal_error!("cannot find `str.zig`. Check the source code in find_zig_str_path() to show all the paths I tried.")
|
||||
internal_error!("cannot find `glue.zig`. Check the source code in find_zig_glue_path() to show all the paths I tried.")
|
||||
}
|
||||
|
||||
fn find_wasi_libc_path() -> PathBuf {
|
||||
|
|
@ -107,7 +133,6 @@ pub fn build_zig_host_native(
|
|||
env_home: &str,
|
||||
emit_bin: &str,
|
||||
zig_host_src: &str,
|
||||
zig_str_path: &str,
|
||||
target: &str,
|
||||
opt_level: OptLevel,
|
||||
shared_lib_path: Option<&Path>,
|
||||
|
|
@ -138,8 +163,8 @@ pub fn build_zig_host_native(
|
|||
zig_host_src,
|
||||
&format!("-femit-bin={}", emit_bin),
|
||||
"--pkg-begin",
|
||||
"str",
|
||||
zig_str_path,
|
||||
"glue",
|
||||
find_zig_glue_path().to_str().unwrap(),
|
||||
"--pkg-end",
|
||||
// include libc
|
||||
"-lc",
|
||||
|
|
@ -180,7 +205,6 @@ pub fn build_zig_host_native(
|
|||
env_home: &str,
|
||||
emit_bin: &str,
|
||||
zig_host_src: &str,
|
||||
zig_str_path: &str,
|
||||
target: &str,
|
||||
opt_level: OptLevel,
|
||||
shared_lib_path: Option<&Path>,
|
||||
|
|
@ -211,8 +235,8 @@ pub fn build_zig_host_native(
|
|||
zig_host_src,
|
||||
&format!("-femit-bin={}", emit_bin),
|
||||
"--pkg-begin",
|
||||
"str",
|
||||
zig_str_path,
|
||||
"glue",
|
||||
find_zig_glue_path().to_str().unwrap(),
|
||||
"--pkg-end",
|
||||
// include the zig runtime
|
||||
// "-fcompiler-rt", compiler-rt causes segfaults on windows; investigate why
|
||||
|
|
@ -240,7 +264,6 @@ pub fn build_zig_host_native(
|
|||
env_home: &str,
|
||||
emit_bin: &str,
|
||||
zig_host_src: &str,
|
||||
zig_str_path: &str,
|
||||
_target: &str,
|
||||
opt_level: OptLevel,
|
||||
shared_lib_path: Option<&Path>,
|
||||
|
|
@ -306,8 +329,8 @@ pub fn build_zig_host_native(
|
|||
zig_host_src,
|
||||
&format!("-femit-bin={}", emit_bin),
|
||||
"--pkg-begin",
|
||||
"str",
|
||||
zig_str_path,
|
||||
"glue",
|
||||
find_zig_glue_path().to_str().unwrap(),
|
||||
"--pkg-end",
|
||||
// include the zig runtime
|
||||
"--pkg-begin",
|
||||
|
|
@ -332,7 +355,6 @@ pub fn build_zig_host_wasm32(
|
|||
env_home: &str,
|
||||
emit_bin: &str,
|
||||
zig_host_src: &str,
|
||||
zig_str_path: &str,
|
||||
opt_level: OptLevel,
|
||||
shared_lib_path: Option<&Path>,
|
||||
) -> Command {
|
||||
|
|
@ -356,31 +378,30 @@ pub fn build_zig_host_wasm32(
|
|||
//
|
||||
// https://github.com/ziglang/zig/issues/9414
|
||||
let mut zig_cmd = zig();
|
||||
let args = &[
|
||||
"build-obj",
|
||||
zig_host_src,
|
||||
emit_bin,
|
||||
"--pkg-begin",
|
||||
"str",
|
||||
zig_str_path,
|
||||
"--pkg-end",
|
||||
// include the zig runtime
|
||||
// "-fcompiler-rt",
|
||||
// include libc
|
||||
"--library",
|
||||
"c",
|
||||
"-target",
|
||||
zig_target,
|
||||
// "-femit-llvm-ir=/home/folkertdev/roc/roc/crates/cli_testing_examples/benchmarks/platform/host.ll",
|
||||
"-fPIC",
|
||||
"--strip",
|
||||
];
|
||||
|
||||
zig_cmd
|
||||
.env_clear()
|
||||
.env("PATH", env_path)
|
||||
.env("HOME", env_home)
|
||||
.args(args);
|
||||
.args([
|
||||
"build-obj",
|
||||
zig_host_src,
|
||||
emit_bin,
|
||||
"--pkg-begin",
|
||||
"glue",
|
||||
find_zig_glue_path().to_str().unwrap(),
|
||||
"--pkg-end",
|
||||
// include the zig runtime
|
||||
// "-fcompiler-rt",
|
||||
// include libc
|
||||
"--library",
|
||||
"c",
|
||||
"-target",
|
||||
zig_target,
|
||||
// "-femit-llvm-ir=/home/folkertdev/roc/roc/crates/cli_testing_examples/benchmarks/platform/host.ll",
|
||||
"-fPIC",
|
||||
"--strip",
|
||||
]);
|
||||
|
||||
if matches!(opt_level, OptLevel::Optimize) {
|
||||
zig_cmd.args(["-O", "ReleaseSafe"]);
|
||||
|
|
@ -424,7 +445,6 @@ pub fn build_c_host_native(
|
|||
env_home,
|
||||
dest,
|
||||
sources[0],
|
||||
find_zig_str_path().to_str().unwrap(),
|
||||
get_target_str(target),
|
||||
opt_level,
|
||||
Some(shared_lib_path),
|
||||
|
|
@ -558,15 +578,6 @@ pub fn rebuild_host(
|
|||
|
||||
if zig_host_src.exists() {
|
||||
// Compile host.zig
|
||||
|
||||
let zig_str_path = find_zig_str_path();
|
||||
|
||||
debug_assert!(
|
||||
std::path::Path::exists(&zig_str_path),
|
||||
"Cannot find str.zig, looking at {:?}",
|
||||
&zig_str_path
|
||||
);
|
||||
|
||||
let zig_cmd = match target.architecture {
|
||||
Architecture::Wasm32 => {
|
||||
let emit_bin = if matches!(opt_level, OptLevel::Development) {
|
||||
|
|
@ -579,7 +590,6 @@ pub fn rebuild_host(
|
|||
&env_home,
|
||||
&emit_bin,
|
||||
zig_host_src.to_str().unwrap(),
|
||||
zig_str_path.to_str().unwrap(),
|
||||
opt_level,
|
||||
shared_lib_path,
|
||||
)
|
||||
|
|
@ -589,7 +599,6 @@ pub fn rebuild_host(
|
|||
&env_home,
|
||||
host_dest.to_str().unwrap(),
|
||||
zig_host_src.to_str().unwrap(),
|
||||
zig_str_path.to_str().unwrap(),
|
||||
get_target_str(target),
|
||||
opt_level,
|
||||
shared_lib_path,
|
||||
|
|
@ -600,7 +609,6 @@ pub fn rebuild_host(
|
|||
&env_home,
|
||||
host_dest.to_str().unwrap(),
|
||||
zig_host_src.to_str().unwrap(),
|
||||
zig_str_path.to_str().unwrap(),
|
||||
"i386-linux-musl",
|
||||
opt_level,
|
||||
shared_lib_path,
|
||||
|
|
@ -611,7 +619,6 @@ pub fn rebuild_host(
|
|||
&env_home,
|
||||
host_dest.to_str().unwrap(),
|
||||
zig_host_src.to_str().unwrap(),
|
||||
zig_str_path.to_str().unwrap(),
|
||||
target_zig_str(target),
|
||||
opt_level,
|
||||
shared_lib_path,
|
||||
|
|
@ -719,7 +726,7 @@ pub fn rebuild_host(
|
|||
if matches!(opt_level, OptLevel::Optimize) {
|
||||
rustc_cmd.arg("-O");
|
||||
} else if matches!(opt_level, OptLevel::Size) {
|
||||
rustc_cmd.arg("-C opt-level=s");
|
||||
rustc_cmd.args(["-C", "opt-level=s"]);
|
||||
}
|
||||
|
||||
run_build_command(rustc_cmd, "host.rs", 0);
|
||||
|
|
@ -1100,7 +1107,7 @@ fn link_linux(
|
|||
// Keep NIX_ env vars
|
||||
.envs(
|
||||
env::vars()
|
||||
.filter(|&(ref k, _)| k.starts_with("NIX_"))
|
||||
.filter(|(k, _)| k.starts_with("NIX_"))
|
||||
.collect::<HashMap<String, String>>(),
|
||||
)
|
||||
.args([
|
||||
|
|
@ -1273,7 +1280,6 @@ fn link_wasm32(
|
|||
input_paths: &[&str],
|
||||
_link_type: LinkType,
|
||||
) -> io::Result<(Child, PathBuf)> {
|
||||
let zig_str_path = find_zig_str_path();
|
||||
let wasi_libc_path = find_wasi_libc_path();
|
||||
|
||||
let child = zig()
|
||||
|
|
@ -1289,8 +1295,8 @@ fn link_wasm32(
|
|||
"-target",
|
||||
"wasm32-wasi-musl",
|
||||
"--pkg-begin",
|
||||
"str",
|
||||
zig_str_path.to_str().unwrap(),
|
||||
"glue",
|
||||
find_zig_glue_path().to_str().unwrap(),
|
||||
"--pkg-end",
|
||||
"--strip",
|
||||
"-O",
|
||||
|
|
@ -1309,8 +1315,6 @@ fn link_windows(
|
|||
input_paths: &[&str],
|
||||
link_type: LinkType,
|
||||
) -> io::Result<(Child, PathBuf)> {
|
||||
let zig_str_path = find_zig_str_path();
|
||||
|
||||
match link_type {
|
||||
LinkType::Dylib => {
|
||||
let child = zig()
|
||||
|
|
@ -1322,8 +1326,8 @@ fn link_windows(
|
|||
"-target",
|
||||
"native",
|
||||
"--pkg-begin",
|
||||
"str",
|
||||
zig_str_path.to_str().unwrap(),
|
||||
"glue",
|
||||
find_zig_glue_path().to_str().unwrap(),
|
||||
"--pkg-end",
|
||||
"--strip",
|
||||
"-O",
|
||||
|
|
|
|||
7
crates/compiler/builtins/bitcode/src/glue.zig
Normal file
7
crates/compiler/builtins/bitcode/src/glue.zig
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
// This is a glue package that just re-exports other libs useful for zig hosts.
|
||||
// Long term, a slimmed down version of these libraries without all of the roc builtins should be create via `roc glue`.
|
||||
// We also should make RocList use comptime types in order to make it nice to use in zig.
|
||||
|
||||
pub const dec = @import("dec.zig");
|
||||
pub const list = @import("list.zig");
|
||||
pub const str = @import("str.zig");
|
||||
|
|
@ -133,6 +133,7 @@ comptime {
|
|||
exportStrFn(str.countSegments, "count_segments");
|
||||
exportStrFn(str.countGraphemeClusters, "count_grapheme_clusters");
|
||||
exportStrFn(str.countUtf8Bytes, "count_utf8_bytes");
|
||||
exportStrFn(str.isEmpty, "is_empty");
|
||||
exportStrFn(str.getCapacity, "capacity");
|
||||
exportStrFn(str.startsWith, "starts_with");
|
||||
exportStrFn(str.startsWithScalar, "starts_with_scalar");
|
||||
|
|
|
|||
|
|
@ -1525,6 +1525,10 @@ pub fn countUtf8Bytes(string: RocStr) callconv(.C) usize {
|
|||
return string.len();
|
||||
}
|
||||
|
||||
pub fn isEmpty(string: RocStr) callconv(.C) bool {
|
||||
return string.isEmpty();
|
||||
}
|
||||
|
||||
pub fn getCapacity(string: RocStr) callconv(.C) usize {
|
||||
return string.getCapacity();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ interface Num
|
|||
Binary32,
|
||||
Binary64,
|
||||
abs,
|
||||
absDiff,
|
||||
neg,
|
||||
add,
|
||||
sub,
|
||||
|
|
@ -643,6 +644,27 @@ toFrac : Num * -> Frac *
|
|||
## Calling this on an unsigned integer (like [U32] or [U64]) never does anything.
|
||||
abs : Num a -> Num a
|
||||
|
||||
## Return the absolute difference between two numbers.
|
||||
##
|
||||
## ```
|
||||
## Num.absDiff 5 3
|
||||
##
|
||||
## Num.absDiff -3 5
|
||||
##
|
||||
## Num.absDiff 3.0 5.0
|
||||
## ```
|
||||
##
|
||||
## If the answer to this operation can't fit in the return value (e.g. an
|
||||
## [I8] answer that's higher than 127 or lower than -128), the result is an
|
||||
## *overflow*. For [F64] and [F32], overflow results in an answer of either
|
||||
## ∞ or -∞. For all other number types, overflow results in a panic.
|
||||
absDiff : Num a, Num a -> Num a
|
||||
absDiff = \a, b ->
|
||||
if a > b then
|
||||
a - b
|
||||
else
|
||||
b - a
|
||||
|
||||
## Return a negative number when given a positive one, and vice versa.
|
||||
## ```
|
||||
## Num.neg 5
|
||||
|
|
|
|||
|
|
@ -308,6 +308,7 @@ pub const STR_SPLIT: &str = "roc_builtins.str.str_split";
|
|||
pub const STR_TO_SCALARS: &str = "roc_builtins.str.to_scalars";
|
||||
pub const STR_COUNT_GRAPEHEME_CLUSTERS: &str = "roc_builtins.str.count_grapheme_clusters";
|
||||
pub const STR_COUNT_UTF8_BYTES: &str = "roc_builtins.str.count_utf8_bytes";
|
||||
pub const STR_IS_EMPTY: &str = "roc_builtins.str.is_empty";
|
||||
pub const STR_CAPACITY: &str = "roc_builtins.str.capacity";
|
||||
pub const STR_STARTS_WITH: &str = "roc_builtins.str.starts_with";
|
||||
pub const STR_STARTS_WITH_SCALAR: &str = "roc_builtins.str.starts_with_scalar";
|
||||
|
|
|
|||
|
|
@ -1134,7 +1134,7 @@ fn canonicalize_has_clause(
|
|||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn can_extension_type<'a>(
|
||||
fn can_extension_type(
|
||||
env: &mut Env,
|
||||
pol: CanPolarity,
|
||||
scope: &mut Scope,
|
||||
|
|
@ -1142,7 +1142,7 @@ fn can_extension_type<'a>(
|
|||
introduced_variables: &mut IntroducedVariables,
|
||||
local_aliases: &mut VecMap<Symbol, Alias>,
|
||||
references: &mut VecSet<Symbol>,
|
||||
opt_ext: &Option<&Loc<TypeAnnotation<'a>>>,
|
||||
opt_ext: &Option<&Loc<TypeAnnotation<'_>>>,
|
||||
ext_problem_kind: roc_problem::can::ExtensionTypeKind,
|
||||
) -> (Type, ExtImplicitOpenness) {
|
||||
fn valid_record_ext_type(typ: &Type) -> bool {
|
||||
|
|
@ -1451,10 +1451,10 @@ fn can_assigned_fields<'a>(
|
|||
|
||||
// TODO trim down these arguments!
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn can_assigned_tuple_elems<'a>(
|
||||
fn can_assigned_tuple_elems(
|
||||
env: &mut Env,
|
||||
pol: CanPolarity,
|
||||
elems: &&[Loc<TypeAnnotation<'a>>],
|
||||
elems: &&[Loc<TypeAnnotation<'_>>],
|
||||
scope: &mut Scope,
|
||||
var_store: &mut VarStore,
|
||||
introduced_variables: &mut IntroducedVariables,
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ macro_rules! map_symbol_to_lowlevel_and_arity {
|
|||
// these are used internally and not tied to a symbol
|
||||
LowLevel::Hash => unimplemented!(),
|
||||
LowLevel::PtrCast => unimplemented!(),
|
||||
LowLevel::PtrWrite => unimplemented!(),
|
||||
LowLevel::RefCountInc => unimplemented!(),
|
||||
LowLevel::RefCountDec => unimplemented!(),
|
||||
LowLevel::RefCountIsUnique => unimplemented!(),
|
||||
|
|
|
|||
|
|
@ -1050,9 +1050,7 @@ fn canonicalize_value_defs<'a>(
|
|||
let mut symbol_to_index: Vec<(IdentId, u32)> = Vec::with_capacity(pending_value_defs.len());
|
||||
|
||||
for (def_index, pending_def) in pending_value_defs.iter().enumerate() {
|
||||
let mut new_bindings = BindingsFromPattern::new(pending_def.loc_pattern())
|
||||
.into_iter()
|
||||
.peekable();
|
||||
let mut new_bindings = BindingsFromPattern::new(pending_def.loc_pattern()).peekable();
|
||||
|
||||
if new_bindings.peek().is_none() {
|
||||
env.problem(Problem::NoIdentifiersIntroduced(
|
||||
|
|
@ -1339,8 +1337,8 @@ fn canonicalize_type_defs<'a>(
|
|||
|
||||
/// Resolve all pending abilities, to add them to scope.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn resolve_abilities<'a>(
|
||||
env: &mut Env<'a>,
|
||||
fn resolve_abilities(
|
||||
env: &mut Env<'_>,
|
||||
output: &mut Output,
|
||||
var_store: &mut VarStore,
|
||||
scope: &mut Scope,
|
||||
|
|
@ -2813,8 +2811,8 @@ fn to_pending_value_def<'a>(
|
|||
}
|
||||
|
||||
/// Make aliases recursive
|
||||
fn correct_mutual_recursive_type_alias<'a>(
|
||||
env: &mut Env<'a>,
|
||||
fn correct_mutual_recursive_type_alias(
|
||||
env: &mut Env<'_>,
|
||||
original_aliases: VecMap<Symbol, Alias>,
|
||||
var_store: &mut VarStore,
|
||||
) -> VecMap<Symbol, Alias> {
|
||||
|
|
@ -3022,8 +3020,8 @@ fn correct_mutual_recursive_type_alias<'a>(
|
|||
unsafe { VecMap::zip(symbols_introduced, aliases) }
|
||||
}
|
||||
|
||||
fn make_tag_union_of_alias_recursive<'a>(
|
||||
env: &mut Env<'a>,
|
||||
fn make_tag_union_of_alias_recursive(
|
||||
env: &mut Env<'_>,
|
||||
alias_name: Symbol,
|
||||
alias: &mut Alias,
|
||||
others: Vec<Symbol>,
|
||||
|
|
@ -3215,8 +3213,8 @@ fn make_tag_union_recursive_help<'a, 'b>(
|
|||
}
|
||||
}
|
||||
|
||||
fn mark_cyclic_alias<'a>(
|
||||
env: &mut Env<'a>,
|
||||
fn mark_cyclic_alias(
|
||||
env: &mut Env<'_>,
|
||||
typ: &mut Type,
|
||||
symbol: Symbol,
|
||||
alias_kind: AliasKind,
|
||||
|
|
|
|||
|
|
@ -1378,31 +1378,31 @@ pub fn canonicalize_expr<'a>(
|
|||
// Below this point, we shouln't see any of these nodes anymore because
|
||||
// operator desugaring should have removed them!
|
||||
bad_expr @ ast::Expr::ParensAround(_) => {
|
||||
panic!(
|
||||
internal_error!(
|
||||
"A ParensAround did not get removed during operator desugaring somehow: {:#?}",
|
||||
bad_expr
|
||||
);
|
||||
}
|
||||
bad_expr @ ast::Expr::SpaceBefore(_, _) => {
|
||||
panic!(
|
||||
internal_error!(
|
||||
"A SpaceBefore did not get removed during operator desugaring somehow: {:#?}",
|
||||
bad_expr
|
||||
);
|
||||
}
|
||||
bad_expr @ ast::Expr::SpaceAfter(_, _) => {
|
||||
panic!(
|
||||
internal_error!(
|
||||
"A SpaceAfter did not get removed during operator desugaring somehow: {:#?}",
|
||||
bad_expr
|
||||
);
|
||||
}
|
||||
bad_expr @ ast::Expr::BinOps { .. } => {
|
||||
panic!(
|
||||
internal_error!(
|
||||
"A binary operator chain did not get desugared somehow: {:#?}",
|
||||
bad_expr
|
||||
);
|
||||
}
|
||||
bad_expr @ ast::Expr::UnaryOp(_, _) => {
|
||||
panic!(
|
||||
internal_error!(
|
||||
"A unary operator did not get desugared somehow: {:#?}",
|
||||
bad_expr
|
||||
);
|
||||
|
|
@ -1814,7 +1814,7 @@ fn canonicalize_field<'a>(
|
|||
|
||||
// A label with no value, e.g. `{ name }` (this is sugar for { name: name })
|
||||
LabelOnly(_) => {
|
||||
panic!("Somehow a LabelOnly record field was not desugared!");
|
||||
internal_error!("Somehow a LabelOnly record field was not desugared!");
|
||||
}
|
||||
|
||||
SpaceBefore(sub_field, _) | SpaceAfter(sub_field, _) => {
|
||||
|
|
@ -1822,7 +1822,7 @@ fn canonicalize_field<'a>(
|
|||
}
|
||||
|
||||
Malformed(_string) => {
|
||||
panic!("TODO canonicalize malformed record field");
|
||||
internal_error!("TODO canonicalize malformed record field");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -195,11 +195,11 @@ enum GeneratedInfo {
|
|||
}
|
||||
|
||||
impl GeneratedInfo {
|
||||
fn from_header_type<'a>(
|
||||
fn from_header_type(
|
||||
env: &mut Env,
|
||||
scope: &mut Scope,
|
||||
var_store: &mut VarStore,
|
||||
header_type: &HeaderType<'a>,
|
||||
header_type: &HeaderType<'_>,
|
||||
) -> Self {
|
||||
match header_type {
|
||||
HeaderType::Hosted {
|
||||
|
|
@ -338,7 +338,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
can_exposed_imports.insert(symbol, region);
|
||||
}
|
||||
Err((_shadowed_symbol, _region)) => {
|
||||
panic!("TODO gracefully handle shadowing in imports.")
|
||||
internal_error!("TODO gracefully handle shadowing in imports.")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -359,7 +359,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
// here we do nothing special
|
||||
}
|
||||
Err((shadowed_symbol, _region)) => {
|
||||
panic!(
|
||||
internal_error!(
|
||||
"TODO gracefully handle shadowing in imports, {:?} is shadowed.",
|
||||
shadowed_symbol
|
||||
)
|
||||
|
|
@ -523,7 +523,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
GeneratedInfo::Builtin => {
|
||||
match crate::builtins::builtin_defs_map(*symbol, var_store) {
|
||||
None => {
|
||||
panic!("A builtin module contains a signature without implementation for {:?}", symbol)
|
||||
internal_error!("A builtin module contains a signature without implementation for {:?}", symbol)
|
||||
}
|
||||
Some(replacement_def) => {
|
||||
declarations.update_builtin_def(index, replacement_def);
|
||||
|
|
@ -581,7 +581,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
GeneratedInfo::Builtin => {
|
||||
match crate::builtins::builtin_defs_map(*symbol, var_store) {
|
||||
None => {
|
||||
panic!("A builtin module contains a signature without implementation for {:?}", symbol)
|
||||
internal_error!("A builtin module contains a signature without implementation for {:?}", symbol)
|
||||
}
|
||||
Some(replacement_def) => {
|
||||
declarations.update_builtin_def(index, replacement_def);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::called_via::BinOp::Pizza;
|
||||
use roc_module::called_via::{BinOp, CalledVia};
|
||||
use roc_module::ident::ModuleName;
|
||||
|
|
@ -592,7 +593,7 @@ fn binop_step<'a>(
|
|||
//
|
||||
// By design, Roc neither allows custom operators nor has any built-in operators with
|
||||
// the same precedence and different associativity, so this should never happen!
|
||||
panic!("BinOps had the same associativity, but different precedence. This should never happen!");
|
||||
internal_error!("BinOps had the same associativity, but different precedence. This should never happen!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -321,8 +321,8 @@ pub fn canonicalize_def_header_pattern<'a>(
|
|||
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||
pub struct PermitShadows(pub bool);
|
||||
|
||||
fn canonicalize_pattern_symbol<'a>(
|
||||
env: &mut Env<'a>,
|
||||
fn canonicalize_pattern_symbol(
|
||||
env: &mut Env<'_>,
|
||||
scope: &mut Scope,
|
||||
output: &mut Output,
|
||||
region: Region,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use roc_collections::{VecMap, VecSet};
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::ident::Ident;
|
||||
use roc_module::symbol::{IdentId, IdentIds, ModuleId, Symbol};
|
||||
use roc_problem::can::RuntimeError;
|
||||
|
|
@ -470,9 +471,13 @@ pub fn create_alias(
|
|||
}
|
||||
|
||||
if !hidden.is_empty() {
|
||||
panic!(
|
||||
internal_error!(
|
||||
"Found unbound type variables {:?} \n in type alias {:?} {:?} {:?} : {:?}",
|
||||
hidden, name, &vars, &infer_ext_in_output_variables, &typ
|
||||
hidden,
|
||||
name,
|
||||
&vars,
|
||||
&infer_ext_in_output_variables,
|
||||
&typ
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// use bumpalo::collections::string::String;
|
||||
// use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_parse::ast::Expr;
|
||||
// use roc_parse::ast::{Attempting, Expr};
|
||||
// use roc_parse::ident;
|
||||
|
|
@ -12,7 +13,7 @@ use roc_region::all::Region;
|
|||
// use std::iter::Peekable;
|
||||
|
||||
pub fn canonical_string_literal<'a>(_arena: &Bump, _raw: &'a str, _region: Region) -> Expr<'a> {
|
||||
panic!("TODO restore canonicalization");
|
||||
internal_error!("TODO restore canonicalization");
|
||||
}
|
||||
// let mut problems = std::vec::Vec::new();
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ pub fn walk_decls<V: Visitor>(visitor: &mut V, decls: &Declarations) {
|
|||
None => Pattern::Identifier(loc_symbol.value),
|
||||
};
|
||||
|
||||
let function_def = &decls.function_bodies[function_index.index() as usize];
|
||||
let function_def = &decls.function_bodies[function_index.index()];
|
||||
|
||||
DeclarationInfo::Function {
|
||||
loc_symbol,
|
||||
|
|
@ -133,7 +133,7 @@ pub fn walk_decls<V: Visitor>(visitor: &mut V, decls: &Declarations) {
|
|||
}
|
||||
}
|
||||
Destructure(destructure_index) => {
|
||||
let destructure = &decls.destructs[destructure_index.index() as usize];
|
||||
let destructure = &decls.destructs[destructure_index.index()];
|
||||
let loc_pattern = &destructure.loc_pattern;
|
||||
|
||||
let loc_expr = &decls.expressions[index];
|
||||
|
|
|
|||
|
|
@ -2600,7 +2600,7 @@ pub fn constrain_decls(
|
|||
cycle_mark,
|
||||
);
|
||||
|
||||
index += length as usize;
|
||||
index += length;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ pub(crate) fn derive_to_encoder(
|
|||
// Generalized tuple var so we can reuse this impl between many tuples:
|
||||
// if arity = n, this is (t1, ..., tn) for fresh t1, ..., tn.
|
||||
let flex_elems = (0..arity)
|
||||
.into_iter()
|
||||
.map(|idx| (idx as usize, env.subs.fresh_unnamed_flex_var()))
|
||||
.collect::<Vec<_>>();
|
||||
let elems = TupleElems::insert_into_subs(env.subs, flex_elems);
|
||||
|
|
|
|||
|
|
@ -131,7 +131,6 @@ fn hash_tuple(env: &mut Env<'_>, fn_name: Symbol, arity: u32) -> (Variable, Expr
|
|||
// TODO: avoid an allocation here by pre-allocating the indices and variables `TupleElems`
|
||||
// will be instantiated with.
|
||||
let flex_elems: Vec<_> = (0..arity)
|
||||
.into_iter()
|
||||
.map(|i| (i as usize, env.subs.fresh_unnamed_flex_var()))
|
||||
.collect();
|
||||
let elems = TupleElems::insert_into_subs(env.subs, flex_elems);
|
||||
|
|
|
|||
|
|
@ -65,15 +65,15 @@ impl Newlines {
|
|||
pub trait Formattable {
|
||||
fn is_multiline(&self) -> bool;
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
_newlines: Newlines,
|
||||
indent: u16,
|
||||
);
|
||||
|
||||
fn format<'buf>(&self, buf: &mut Buf<'buf>, indent: u16) {
|
||||
fn format(&self, buf: &mut Buf<'_>, indent: u16) {
|
||||
self.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
|
||||
}
|
||||
}
|
||||
|
|
@ -87,9 +87,9 @@ where
|
|||
(*self).is_multiline()
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -97,7 +97,7 @@ where
|
|||
(*self).format_with_options(buf, parens, newlines, indent)
|
||||
}
|
||||
|
||||
fn format<'buf>(&self, buf: &mut Buf<'buf>, indent: u16) {
|
||||
fn format(&self, buf: &mut Buf<'_>, indent: u16) {
|
||||
(*self).format(buf, indent)
|
||||
}
|
||||
}
|
||||
|
|
@ -120,9 +120,9 @@ where
|
|||
self.value.is_multiline()
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -131,7 +131,7 @@ where
|
|||
.format_with_options(buf, parens, newlines, indent)
|
||||
}
|
||||
|
||||
fn format<'buf>(&self, buf: &mut Buf<'buf>, indent: u16) {
|
||||
fn format(&self, buf: &mut Buf<'_>, indent: u16) {
|
||||
self.value.format(buf, indent)
|
||||
}
|
||||
}
|
||||
|
|
@ -141,9 +141,9 @@ impl<'a> Formattable for UppercaseIdent<'a> {
|
|||
false
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
_newlines: Newlines,
|
||||
_indent: u16,
|
||||
|
|
@ -206,9 +206,9 @@ impl<'a> Formattable for TypeAnnotation<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -424,9 +424,9 @@ impl<'a> Formattable for AssignedField<'a, TypeAnnotation<'a>> {
|
|||
is_multiline_assigned_field_help(self)
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -441,9 +441,9 @@ impl<'a> Formattable for AssignedField<'a, Expr<'a>> {
|
|||
is_multiline_assigned_field_help(self)
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -466,9 +466,9 @@ fn is_multiline_assigned_field_help<T: Formattable>(afield: &AssignedField<'_, T
|
|||
}
|
||||
}
|
||||
|
||||
fn format_assigned_field_help<'a, 'buf, T>(
|
||||
zelf: &AssignedField<'a, T>,
|
||||
buf: &mut Buf<'buf>,
|
||||
fn format_assigned_field_help<T>(
|
||||
zelf: &AssignedField<'_, T>,
|
||||
buf: &mut Buf<'_>,
|
||||
indent: u16,
|
||||
separator_spaces: usize,
|
||||
is_multiline: bool,
|
||||
|
|
@ -545,9 +545,9 @@ impl<'a> Formattable for Tag<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
_newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -592,9 +592,9 @@ impl<'a> Formattable for HasClause<'a> {
|
|||
false
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -623,9 +623,9 @@ impl<'a> Formattable for HasImpls<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -662,9 +662,9 @@ impl<'a> Formattable for HasAbility<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -703,9 +703,9 @@ impl<'a> Formattable for HasAbilities<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ impl<'a> Formattable for Defs<'a> {
|
|||
!self.tags.is_empty()
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
_newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -57,9 +57,9 @@ impl<'a> Formattable for TypeDef<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -171,9 +171,9 @@ impl<'a> Formattable for TypeHeader<'a> {
|
|||
self.vars.iter().any(|v| v.is_multiline())
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
_newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -205,9 +205,9 @@ impl<'a> Formattable for ValueDef<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -314,8 +314,8 @@ fn should_outdent(mut rhs: &TypeAnnotation) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn fmt_dbg_in_def<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_dbg_in_def<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
condition: &'a Loc<Expr<'a>>,
|
||||
is_multiline: bool,
|
||||
indent: u16,
|
||||
|
|
@ -335,8 +335,8 @@ fn fmt_dbg_in_def<'a, 'buf>(
|
|||
condition.format(buf, return_indent);
|
||||
}
|
||||
|
||||
fn fmt_expect<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_expect<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
condition: &'a Loc<Expr<'a>>,
|
||||
is_multiline: bool,
|
||||
indent: u16,
|
||||
|
|
@ -356,8 +356,8 @@ fn fmt_expect<'a, 'buf>(
|
|||
condition.format(buf, return_indent);
|
||||
}
|
||||
|
||||
fn fmt_expect_fx<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_expect_fx<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
condition: &'a Loc<Expr<'a>>,
|
||||
is_multiline: bool,
|
||||
indent: u16,
|
||||
|
|
@ -377,28 +377,19 @@ fn fmt_expect_fx<'a, 'buf>(
|
|||
condition.format(buf, return_indent);
|
||||
}
|
||||
|
||||
pub fn fmt_value_def<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
def: &roc_parse::ast::ValueDef<'a>,
|
||||
indent: u16,
|
||||
) {
|
||||
pub fn fmt_value_def(buf: &mut Buf<'_>, def: &roc_parse::ast::ValueDef<'_>, indent: u16) {
|
||||
def.format(buf, indent);
|
||||
}
|
||||
|
||||
pub fn fmt_type_def<'a, 'buf>(buf: &mut Buf<'buf>, def: &roc_parse::ast::TypeDef<'a>, indent: u16) {
|
||||
pub fn fmt_type_def(buf: &mut Buf<'_>, def: &roc_parse::ast::TypeDef<'_>, indent: u16) {
|
||||
def.format(buf, indent);
|
||||
}
|
||||
|
||||
pub fn fmt_defs<'a, 'buf>(buf: &mut Buf<'buf>, defs: &Defs<'a>, indent: u16) {
|
||||
pub fn fmt_defs(buf: &mut Buf<'_>, defs: &Defs<'_>, indent: u16) {
|
||||
defs.format(buf, indent);
|
||||
}
|
||||
|
||||
pub fn fmt_body<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
pattern: &'a Pattern<'a>,
|
||||
body: &'a Expr<'a>,
|
||||
indent: u16,
|
||||
) {
|
||||
pub fn fmt_body<'a>(buf: &mut Buf<'_>, pattern: &'a Pattern<'a>, body: &'a Expr<'a>, indent: u16) {
|
||||
pattern.format_with_options(buf, Parens::InApply, Newlines::No, indent);
|
||||
buf.indent(indent);
|
||||
buf.push_str(" =");
|
||||
|
|
@ -462,9 +453,9 @@ impl<'a> Formattable for AbilityMember<'a> {
|
|||
self.name.value.is_multiline() || self.typ.is_multiline()
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
_newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
|
|||
|
|
@ -103,9 +103,9 @@ impl<'a> Formattable for Expr<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -551,7 +551,7 @@ fn starts_with_newline(expr: &Expr) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_str_segment<'a, 'buf>(seg: &StrSegment<'a>, buf: &mut Buf<'buf>, indent: u16) {
|
||||
fn format_str_segment(seg: &StrSegment<'_>, buf: &mut Buf<'_>, indent: u16) {
|
||||
use StrSegment::*;
|
||||
|
||||
match seg {
|
||||
|
|
@ -614,7 +614,7 @@ fn push_op(buf: &mut Buf, op: BinOp) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn fmt_str_literal<'buf>(buf: &mut Buf<'buf>, literal: StrLiteral, indent: u16) {
|
||||
pub fn fmt_str_literal(buf: &mut Buf<'_>, literal: StrLiteral, indent: u16) {
|
||||
use roc_parse::ast::StrLiteral::*;
|
||||
|
||||
match literal {
|
||||
|
|
@ -673,8 +673,8 @@ pub fn fmt_str_literal<'buf>(buf: &mut Buf<'buf>, literal: StrLiteral, indent: u
|
|||
}
|
||||
}
|
||||
|
||||
fn fmt_binops<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_binops<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
lefts: &'a [(Loc<Expr<'a>>, Loc<BinOp>)],
|
||||
loc_right_side: &'a Loc<Expr<'a>>,
|
||||
part_of_multi_line_binops: bool,
|
||||
|
|
@ -704,9 +704,9 @@ fn fmt_binops<'a, 'buf>(
|
|||
loc_right_side.format_with_options(buf, Parens::InOperator, Newlines::Yes, indent);
|
||||
}
|
||||
|
||||
fn format_spaces<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
spaces: &[CommentOrNewline<'a>],
|
||||
fn format_spaces(
|
||||
buf: &mut Buf<'_>,
|
||||
spaces: &[CommentOrNewline<'_>],
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
) {
|
||||
|
|
@ -738,8 +738,8 @@ fn is_when_patterns_multiline(when_branch: &WhenBranch) -> bool {
|
|||
is_multiline_patterns
|
||||
}
|
||||
|
||||
fn fmt_when<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_when<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
loc_condition: &'a Loc<Expr<'a>>,
|
||||
branches: &[&'a WhenBranch<'a>],
|
||||
indent: u16,
|
||||
|
|
@ -920,8 +920,8 @@ fn fmt_when<'a, 'buf>(
|
|||
}
|
||||
}
|
||||
|
||||
fn fmt_dbg<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_dbg<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
condition: &'a Loc<Expr<'a>>,
|
||||
continuation: &'a Loc<Expr<'a>>,
|
||||
is_multiline: bool,
|
||||
|
|
@ -947,8 +947,8 @@ fn fmt_dbg<'a, 'buf>(
|
|||
continuation.format(buf, indent);
|
||||
}
|
||||
|
||||
fn fmt_expect<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_expect<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
condition: &'a Loc<Expr<'a>>,
|
||||
continuation: &'a Loc<Expr<'a>>,
|
||||
is_multiline: bool,
|
||||
|
|
@ -974,8 +974,8 @@ fn fmt_expect<'a, 'buf>(
|
|||
continuation.format(buf, indent);
|
||||
}
|
||||
|
||||
fn fmt_if<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_if<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
branches: &'a [(Loc<Expr<'a>>, Loc<Expr<'a>>)],
|
||||
final_else: &'a Loc<Expr<'a>>,
|
||||
is_multiline: bool,
|
||||
|
|
@ -1123,8 +1123,8 @@ fn fmt_if<'a, 'buf>(
|
|||
final_else.format(buf, return_indent);
|
||||
}
|
||||
|
||||
fn fmt_closure<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_closure<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
loc_patterns: &'a [Loc<Pattern<'a>>],
|
||||
loc_ret: &'a Loc<Expr<'a>>,
|
||||
indent: u16,
|
||||
|
|
@ -1224,8 +1224,8 @@ fn fmt_closure<'a, 'buf>(
|
|||
}
|
||||
}
|
||||
|
||||
fn fmt_backpassing<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_backpassing<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
loc_patterns: &'a [Loc<Pattern<'a>>],
|
||||
loc_body: &'a Loc<Expr<'a>>,
|
||||
loc_ret: &'a Loc<Expr<'a>>,
|
||||
|
|
@ -1312,8 +1312,8 @@ fn pattern_needs_parens_when_backpassing(pat: &Pattern) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn fmt_record<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_record<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
update: Option<&'a Loc<Expr<'a>>>,
|
||||
fields: Collection<'a, Loc<AssignedField<'a, Expr<'a>>>>,
|
||||
indent: u16,
|
||||
|
|
@ -1404,9 +1404,9 @@ fn fmt_record<'a, 'buf>(
|
|||
}
|
||||
}
|
||||
|
||||
fn format_field_multiline<'a, 'buf, T>(
|
||||
buf: &mut Buf<'buf>,
|
||||
field: &AssignedField<'a, T>,
|
||||
fn format_field_multiline<T>(
|
||||
buf: &mut Buf<'_>,
|
||||
field: &AssignedField<'_, T>,
|
||||
indent: u16,
|
||||
separator_prefix: &str,
|
||||
) where
|
||||
|
|
|
|||
|
|
@ -44,9 +44,9 @@ macro_rules! keywords {
|
|||
false
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: crate::annotation::Parens,
|
||||
_newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -86,9 +86,9 @@ impl<V: Formattable> Formattable for Option<V> {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
parens: crate::annotation::Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -111,9 +111,9 @@ impl<'a> Formattable for ProvidesTo<'a> {
|
|||
|| self.to_keyword.is_multiline()
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: crate::annotation::Parens,
|
||||
_newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -130,9 +130,9 @@ impl<'a> Formattable for PlatformRequires<'a> {
|
|||
is_collection_multiline(&self.rigids) || self.signature.is_multiline()
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: crate::annotation::Parens,
|
||||
_newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -146,9 +146,9 @@ impl<'a, V: Formattable> Formattable for Spaces<'a, V> {
|
|||
!self.before.is_empty() || !self.after.is_empty() || self.item.is_multiline()
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
parens: crate::annotation::Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -164,9 +164,9 @@ impl<'a, K: Formattable, V: Formattable> Formattable for KeywordItem<'a, K, V> {
|
|||
self.keyword.is_multiline() || self.item.is_multiline()
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -177,7 +177,7 @@ impl<'a, K: Formattable, V: Formattable> Formattable for KeywordItem<'a, K, V> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn fmt_interface_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a InterfaceHeader<'a>) {
|
||||
pub fn fmt_interface_header<'a>(buf: &mut Buf<'_>, header: &'a InterfaceHeader<'a>) {
|
||||
buf.indent(0);
|
||||
buf.push_str("interface");
|
||||
let indent = INDENT;
|
||||
|
|
@ -193,7 +193,7 @@ pub fn fmt_interface_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a Interface
|
|||
fmt_imports(buf, header.imports.item, indent);
|
||||
}
|
||||
|
||||
pub fn fmt_hosted_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a HostedHeader<'a>) {
|
||||
pub fn fmt_hosted_header<'a>(buf: &mut Buf<'_>, header: &'a HostedHeader<'a>) {
|
||||
buf.indent(0);
|
||||
buf.push_str("hosted");
|
||||
let indent = INDENT;
|
||||
|
|
@ -210,7 +210,7 @@ pub fn fmt_hosted_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a HostedHeader
|
|||
fmt_exposes(buf, header.generates_with.item, indent);
|
||||
}
|
||||
|
||||
pub fn fmt_app_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a AppHeader<'a>) {
|
||||
pub fn fmt_app_header<'a>(buf: &mut Buf<'_>, header: &'a AppHeader<'a>) {
|
||||
buf.indent(0);
|
||||
buf.push_str("app");
|
||||
let indent = INDENT;
|
||||
|
|
@ -229,7 +229,7 @@ pub fn fmt_app_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a AppHeader<'a>)
|
|||
header.provides.format(buf, indent);
|
||||
}
|
||||
|
||||
pub fn fmt_package_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a PackageHeader<'a>) {
|
||||
pub fn fmt_package_header<'a>(buf: &mut Buf<'_>, header: &'a PackageHeader<'a>) {
|
||||
buf.indent(0);
|
||||
buf.push_str("package");
|
||||
let indent = INDENT;
|
||||
|
|
@ -243,7 +243,7 @@ pub fn fmt_package_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a PackageHead
|
|||
fmt_packages(buf, header.packages.item, indent);
|
||||
}
|
||||
|
||||
pub fn fmt_platform_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a PlatformHeader<'a>) {
|
||||
pub fn fmt_platform_header<'a>(buf: &mut Buf<'_>, header: &'a PlatformHeader<'a>) {
|
||||
buf.indent(0);
|
||||
buf.push_str("platform");
|
||||
let indent = INDENT;
|
||||
|
|
@ -262,7 +262,7 @@ pub fn fmt_platform_header<'a, 'buf>(buf: &mut Buf<'buf>, header: &'a PlatformHe
|
|||
fmt_provides(buf, header.provides.item, None, indent);
|
||||
}
|
||||
|
||||
fn fmt_requires<'a, 'buf>(buf: &mut Buf<'buf>, requires: &PlatformRequires<'a>, indent: u16) {
|
||||
fn fmt_requires(buf: &mut Buf<'_>, requires: &PlatformRequires<'_>, indent: u16) {
|
||||
fmt_collection(buf, indent, Braces::Curly, requires.rigids, Newlines::No);
|
||||
|
||||
buf.push_str(" {");
|
||||
|
|
@ -276,9 +276,9 @@ impl<'a> Formattable for TypedIdent<'a> {
|
|||
false
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
_newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -293,7 +293,7 @@ impl<'a> Formattable for TypedIdent<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn fmt_package_name<'buf>(buf: &mut Buf<'buf>, name: PackageName, indent: u16) {
|
||||
fn fmt_package_name(buf: &mut Buf<'_>, name: PackageName, indent: u16) {
|
||||
buf.indent(indent);
|
||||
buf.push('"');
|
||||
buf.push_str_allow_spaces(name.to_str());
|
||||
|
|
@ -312,9 +312,9 @@ impl<'a, T: Formattable> Formattable for Spaced<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
parens: crate::annotation::Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -335,16 +335,16 @@ impl<'a, T: Formattable> Formattable for Spaced<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
fn fmt_imports<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_imports<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
loc_entries: Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
|
||||
indent: u16,
|
||||
) {
|
||||
fmt_collection(buf, indent, Braces::Square, loc_entries, Newlines::No)
|
||||
}
|
||||
|
||||
fn fmt_provides<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_provides<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
loc_exposed_names: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
|
||||
loc_provided_types: Option<Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>>,
|
||||
indent: u16,
|
||||
|
|
@ -356,7 +356,7 @@ fn fmt_provides<'a, 'buf>(
|
|||
}
|
||||
}
|
||||
|
||||
fn fmt_to<'buf>(buf: &mut Buf<'buf>, to: To, indent: u16) {
|
||||
fn fmt_to(buf: &mut Buf<'_>, to: To, indent: u16) {
|
||||
match to {
|
||||
To::ExistingPackage(name) => {
|
||||
buf.push_str(name);
|
||||
|
|
@ -365,8 +365,8 @@ fn fmt_to<'buf>(buf: &mut Buf<'buf>, to: To, indent: u16) {
|
|||
}
|
||||
}
|
||||
|
||||
fn fmt_exposes<'buf, N: Formattable + Copy + core::fmt::Debug>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_exposes<N: Formattable + Copy + core::fmt::Debug>(
|
||||
buf: &mut Buf<'_>,
|
||||
loc_entries: Collection<'_, Loc<Spaced<'_, N>>>,
|
||||
indent: u16,
|
||||
) {
|
||||
|
|
@ -374,17 +374,17 @@ fn fmt_exposes<'buf, N: Formattable + Copy + core::fmt::Debug>(
|
|||
}
|
||||
|
||||
pub trait FormatName {
|
||||
fn format<'buf>(&self, buf: &mut Buf<'buf>);
|
||||
fn format(&self, buf: &mut Buf<'_>);
|
||||
}
|
||||
|
||||
impl<'a> FormatName for &'a str {
|
||||
fn format<'buf>(&self, buf: &mut Buf<'buf>) {
|
||||
fn format(&self, buf: &mut Buf<'_>) {
|
||||
buf.push_str(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FormatName for ModuleName<'a> {
|
||||
fn format<'buf>(&self, buf: &mut Buf<'buf>) {
|
||||
fn format(&self, buf: &mut Buf<'_>) {
|
||||
buf.push_str(self.as_str());
|
||||
}
|
||||
}
|
||||
|
|
@ -394,9 +394,9 @@ impl<'a> Formattable for ModuleName<'a> {
|
|||
false
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
_newlines: Newlines,
|
||||
_indent: u16,
|
||||
|
|
@ -410,9 +410,9 @@ impl<'a> Formattable for ExposedName<'a> {
|
|||
false
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
_newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -423,13 +423,13 @@ impl<'a> Formattable for ExposedName<'a> {
|
|||
}
|
||||
|
||||
impl<'a> FormatName for ExposedName<'a> {
|
||||
fn format<'buf>(&self, buf: &mut Buf<'buf>) {
|
||||
fn format(&self, buf: &mut Buf<'_>) {
|
||||
buf.push_str(self.as_str());
|
||||
}
|
||||
}
|
||||
|
||||
fn fmt_packages<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
fn fmt_packages<'a>(
|
||||
buf: &mut Buf<'_>,
|
||||
loc_entries: Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>,
|
||||
indent: u16,
|
||||
) {
|
||||
|
|
@ -441,9 +441,9 @@ impl<'a> Formattable for PackageEntry<'a> {
|
|||
false
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
_newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -457,9 +457,9 @@ impl<'a> Formattable for ImportsEntry<'a> {
|
|||
false
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
_newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -467,14 +467,14 @@ impl<'a> Formattable for ImportsEntry<'a> {
|
|||
fmt_imports_entry(buf, self, indent);
|
||||
}
|
||||
}
|
||||
fn fmt_packages_entry<'a, 'buf>(buf: &mut Buf<'buf>, entry: &PackageEntry<'a>, indent: u16) {
|
||||
fn fmt_packages_entry(buf: &mut Buf<'_>, entry: &PackageEntry<'_>, indent: u16) {
|
||||
buf.push_str(entry.shorthand);
|
||||
buf.push(':');
|
||||
fmt_default_spaces(buf, entry.spaces_after_shorthand, indent);
|
||||
fmt_package_name(buf, entry.package_name.value, indent);
|
||||
}
|
||||
|
||||
fn fmt_imports_entry<'a, 'buf>(buf: &mut Buf<'buf>, entry: &ImportsEntry<'a>, indent: u16) {
|
||||
fn fmt_imports_entry(buf: &mut Buf<'_>, entry: &ImportsEntry<'_>, indent: u16) {
|
||||
use roc_parse::header::ImportsEntry::*;
|
||||
|
||||
buf.indent(indent);
|
||||
|
|
|
|||
|
|
@ -4,12 +4,7 @@ use crate::spaces::{fmt_comments_only, fmt_spaces, NewlineAt, INDENT};
|
|||
use crate::Buf;
|
||||
use roc_parse::ast::{Base, CommentOrNewline, Pattern, PatternAs};
|
||||
|
||||
pub fn fmt_pattern<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
pattern: &'a Pattern<'a>,
|
||||
indent: u16,
|
||||
parens: Parens,
|
||||
) {
|
||||
pub fn fmt_pattern<'a>(buf: &mut Buf<'_>, pattern: &'a Pattern<'a>, indent: u16, parens: Parens) {
|
||||
pattern.format_with_options(buf, parens, Newlines::No, indent);
|
||||
}
|
||||
|
||||
|
|
@ -18,9 +13,9 @@ impl<'a> Formattable for PatternAs<'a> {
|
|||
self.spaces_before.iter().any(|s| s.is_comment())
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
_parens: Parens,
|
||||
_newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
@ -85,9 +80,9 @@ impl<'a> Formattable for Pattern<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn format_with_options<'buf>(
|
||||
fn format_with_options(
|
||||
&self,
|
||||
buf: &mut Buf<'buf>,
|
||||
buf: &mut Buf<'_>,
|
||||
parens: Parens,
|
||||
newlines: Newlines,
|
||||
indent: u16,
|
||||
|
|
|
|||
|
|
@ -21,22 +21,14 @@ use crate::{Ast, Buf};
|
|||
/// The number of spaces to indent.
|
||||
pub const INDENT: u16 = 4;
|
||||
|
||||
pub fn fmt_default_spaces<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
spaces: &[CommentOrNewline<'a>],
|
||||
indent: u16,
|
||||
) {
|
||||
pub fn fmt_default_spaces(buf: &mut Buf<'_>, spaces: &[CommentOrNewline<'_>], indent: u16) {
|
||||
if spaces.is_empty() {
|
||||
buf.spaces(1);
|
||||
} else {
|
||||
fmt_spaces(buf, spaces.iter(), indent);
|
||||
}
|
||||
}
|
||||
pub fn fmt_default_newline<'a, 'buf>(
|
||||
buf: &mut Buf<'buf>,
|
||||
spaces: &[CommentOrNewline<'a>],
|
||||
indent: u16,
|
||||
) {
|
||||
pub fn fmt_default_newline(buf: &mut Buf<'_>, spaces: &[CommentOrNewline<'_>], indent: u16) {
|
||||
if spaces.is_empty() {
|
||||
buf.newline();
|
||||
} else {
|
||||
|
|
@ -153,7 +145,7 @@ pub fn fmt_comments_only<'a, 'buf, I>(
|
|||
}
|
||||
}
|
||||
|
||||
fn fmt_comment<'buf>(buf: &mut Buf<'buf>, comment: &str) {
|
||||
fn fmt_comment(buf: &mut Buf<'_>, comment: &str) {
|
||||
// The '#' in a comment should always be preceded by a newline or a space,
|
||||
// unless it's the very beginning of the buffer.
|
||||
if !buf.is_empty() && !buf.ends_with_space() && !buf.ends_with_newline() {
|
||||
|
|
@ -192,7 +184,7 @@ where
|
|||
count
|
||||
}
|
||||
|
||||
fn fmt_docs<'buf>(buf: &mut Buf<'buf>, docs: &str) {
|
||||
fn fmt_docs(buf: &mut Buf<'_>, docs: &str) {
|
||||
// The "##" in a doc comment should always be preceded by a newline or a space,
|
||||
// unless it's the very beginning of the buffer.
|
||||
if !buf.is_empty() && !buf.ends_with_space() && !buf.ends_with_newline() {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -7,13 +7,15 @@ use roc_builtins::bitcode::{self, FloatWidth, IntWidth};
|
|||
use roc_collections::all::MutMap;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||
use roc_mono::code_gen_help::CodeGenHelp;
|
||||
use roc_mono::code_gen_help::{CallerProc, CodeGenHelp, HelperOp};
|
||||
use roc_mono::ir::{
|
||||
BranchInfo, JoinPointId, ListLiteralElement, Literal, Param, ProcLayout, SelfRecursive, Stmt,
|
||||
BranchInfo, HigherOrderLowLevel, JoinPointId, ListLiteralElement, Literal, Param, ProcLayout,
|
||||
SelfRecursive, Stmt,
|
||||
};
|
||||
use roc_mono::layout::{
|
||||
Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout,
|
||||
};
|
||||
use roc_mono::low_level::HigherOrder;
|
||||
use roc_target::TargetInfo;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
|
@ -62,15 +64,15 @@ pub trait CallConv<GeneralReg: RegTrait, FloatReg: RegTrait, ASM: Assembler<Gene
|
|||
!Self::float_callee_saved(reg)
|
||||
}
|
||||
|
||||
fn setup_stack<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
fn setup_stack(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
general_saved_regs: &[GeneralReg],
|
||||
float_saved_regs: &[FloatReg],
|
||||
requested_stack_size: i32,
|
||||
fn_call_stack_size: i32,
|
||||
) -> i32;
|
||||
fn cleanup_stack<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
fn cleanup_stack(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
general_saved_regs: &[GeneralReg],
|
||||
float_saved_regs: &[FloatReg],
|
||||
aligned_stack_size: i32,
|
||||
|
|
@ -78,9 +80,9 @@ pub trait CallConv<GeneralReg: RegTrait, FloatReg: RegTrait, ASM: Assembler<Gene
|
|||
);
|
||||
|
||||
/// load_args updates the storage manager to know where every arg is stored.
|
||||
fn load_args<'a, 'r>(
|
||||
fn load_args<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, Self>,
|
||||
storage_manager: &mut StorageManager<'a, '_, GeneralReg, FloatReg, ASM, Self>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
args: &'a [(InLayout<'a>, Symbol)],
|
||||
// ret_layout is needed because if it is a complex type, we pass a pointer as the first arg.
|
||||
|
|
@ -89,9 +91,9 @@ pub trait CallConv<GeneralReg: RegTrait, FloatReg: RegTrait, ASM: Assembler<Gene
|
|||
|
||||
/// store_args stores the args in registers and on the stack for function calling.
|
||||
/// It also updates the amount of temporary stack space needed in the storage manager.
|
||||
fn store_args<'a, 'r>(
|
||||
fn store_args<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, Self>,
|
||||
storage_manager: &mut StorageManager<'a, '_, GeneralReg, FloatReg, ASM, Self>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
dst: &Symbol,
|
||||
args: &[Symbol],
|
||||
|
|
@ -102,9 +104,9 @@ pub trait CallConv<GeneralReg: RegTrait, FloatReg: RegTrait, ASM: Assembler<Gene
|
|||
|
||||
/// return_complex_symbol returns the specified complex/non-primative symbol.
|
||||
/// It uses the layout to determine how the data should be returned.
|
||||
fn return_complex_symbol<'a, 'r>(
|
||||
fn return_complex_symbol<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, Self>,
|
||||
storage_manager: &mut StorageManager<'a, '_, GeneralReg, FloatReg, ASM, Self>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
sym: &Symbol,
|
||||
layout: &InLayout<'a>,
|
||||
|
|
@ -112,9 +114,9 @@ pub trait CallConv<GeneralReg: RegTrait, FloatReg: RegTrait, ASM: Assembler<Gene
|
|||
|
||||
/// load_returned_complex_symbol loads a complex symbol that was returned from a function call.
|
||||
/// It uses the layout to determine how the data should be loaded into the symbol.
|
||||
fn load_returned_complex_symbol<'a, 'r>(
|
||||
fn load_returned_complex_symbol<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, Self>,
|
||||
storage_manager: &mut StorageManager<'a, '_, GeneralReg, FloatReg, ASM, Self>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
sym: &Symbol,
|
||||
layout: &InLayout<'a>,
|
||||
|
|
@ -184,9 +186,9 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
|||
src2: GeneralReg,
|
||||
);
|
||||
|
||||
fn shl_reg64_reg64_reg64<'a, 'r, ASM, CC>(
|
||||
fn shl_reg64_reg64_reg64<'a, ASM, CC>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
|
||||
storage_manager: &mut StorageManager<'a, '_, GeneralReg, FloatReg, ASM, CC>,
|
||||
dst: GeneralReg,
|
||||
src1: GeneralReg,
|
||||
src2: GeneralReg,
|
||||
|
|
@ -194,9 +196,9 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
|||
ASM: Assembler<GeneralReg, FloatReg>,
|
||||
CC: CallConv<GeneralReg, FloatReg, ASM>;
|
||||
|
||||
fn shr_reg64_reg64_reg64<'a, 'r, ASM, CC>(
|
||||
fn shr_reg64_reg64_reg64<'a, ASM, CC>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
|
||||
storage_manager: &mut StorageManager<'a, '_, GeneralReg, FloatReg, ASM, CC>,
|
||||
dst: GeneralReg,
|
||||
src1: GeneralReg,
|
||||
src2: GeneralReg,
|
||||
|
|
@ -204,9 +206,9 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
|||
ASM: Assembler<GeneralReg, FloatReg>,
|
||||
CC: CallConv<GeneralReg, FloatReg, ASM>;
|
||||
|
||||
fn sar_reg64_reg64_reg64<'a, 'r, ASM, CC>(
|
||||
fn sar_reg64_reg64_reg64<'a, ASM, CC>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
|
||||
storage_manager: &mut StorageManager<'a, '_, GeneralReg, FloatReg, ASM, CC>,
|
||||
dst: GeneralReg,
|
||||
src1: GeneralReg,
|
||||
src2: GeneralReg,
|
||||
|
|
@ -216,6 +218,13 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
|||
|
||||
fn call(buf: &mut Vec<'_, u8>, relocs: &mut Vec<'_, Relocation>, fn_name: String);
|
||||
|
||||
fn function_pointer(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
relocs: &mut Vec<'_, Relocation>,
|
||||
fn_name: String,
|
||||
dst: GeneralReg,
|
||||
);
|
||||
|
||||
/// Jumps by an offset of offset bytes unconditionally.
|
||||
/// It should always generate the same number of bytes to enable replacement if offset changes.
|
||||
/// It returns the base offset to calculate the jump from (generally the instruction after the jump).
|
||||
|
|
@ -359,9 +368,9 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
|||
src1: GeneralReg,
|
||||
src2: GeneralReg,
|
||||
);
|
||||
fn umul_reg64_reg64_reg64<'a, 'r, ASM, CC>(
|
||||
fn umul_reg64_reg64_reg64<'a, ASM, CC>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
|
||||
storage_manager: &mut StorageManager<'a, '_, GeneralReg, FloatReg, ASM, CC>,
|
||||
dst: GeneralReg,
|
||||
src1: GeneralReg,
|
||||
src2: GeneralReg,
|
||||
|
|
@ -369,18 +378,18 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
|||
ASM: Assembler<GeneralReg, FloatReg>,
|
||||
CC: CallConv<GeneralReg, FloatReg, ASM>;
|
||||
|
||||
fn idiv_reg64_reg64_reg64<'a, 'r, ASM, CC>(
|
||||
fn idiv_reg64_reg64_reg64<'a, ASM, CC>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
|
||||
storage_manager: &mut StorageManager<'a, '_, GeneralReg, FloatReg, ASM, CC>,
|
||||
dst: GeneralReg,
|
||||
src1: GeneralReg,
|
||||
src2: GeneralReg,
|
||||
) where
|
||||
ASM: Assembler<GeneralReg, FloatReg>,
|
||||
CC: CallConv<GeneralReg, FloatReg, ASM>;
|
||||
fn udiv_reg64_reg64_reg64<'a, 'r, ASM, CC>(
|
||||
fn udiv_reg64_reg64_reg64<'a, ASM, CC>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
|
||||
storage_manager: &mut StorageManager<'a, '_, GeneralReg, FloatReg, ASM, CC>,
|
||||
dst: GeneralReg,
|
||||
src1: GeneralReg,
|
||||
src2: GeneralReg,
|
||||
|
|
@ -447,20 +456,6 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
|
|||
|
||||
fn to_float_freg64_freg32(buf: &mut Vec<'_, u8>, dst: FloatReg, src: FloatReg);
|
||||
|
||||
fn lte_reg64_reg64_reg64(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
dst: GeneralReg,
|
||||
src1: GeneralReg,
|
||||
src2: GeneralReg,
|
||||
);
|
||||
|
||||
fn gte_reg64_reg64_reg64(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
dst: GeneralReg,
|
||||
src1: GeneralReg,
|
||||
src2: GeneralReg,
|
||||
);
|
||||
|
||||
fn set_if_overflow(buf: &mut Vec<'_, u8>, dst: GeneralReg);
|
||||
|
||||
fn ret(buf: &mut Vec<'_, u8>);
|
||||
|
|
@ -489,6 +484,7 @@ pub struct Backend64Bit<
|
|||
interns: &'r mut Interns,
|
||||
helper_proc_gen: CodeGenHelp<'a>,
|
||||
helper_proc_symbols: Vec<'a, (Symbol, ProcLayout<'a>)>,
|
||||
caller_procs: Vec<'a, CallerProc<'a>>,
|
||||
buf: Vec<'a, u8>,
|
||||
relocs: Vec<'a, Relocation>,
|
||||
proc_name: Option<String>,
|
||||
|
|
@ -526,6 +522,7 @@ pub fn new_backend_64bit<
|
|||
layout_interner,
|
||||
helper_proc_gen: CodeGenHelp::new(env.arena, target_info, env.module_id),
|
||||
helper_proc_symbols: bumpalo::vec![in env.arena],
|
||||
caller_procs: bumpalo::vec![in env.arena],
|
||||
proc_name: None,
|
||||
is_self_recursive: None,
|
||||
buf: bumpalo::vec![in env.arena],
|
||||
|
|
@ -567,6 +564,9 @@ impl<
|
|||
fn interns(&self) -> &Interns {
|
||||
self.interns
|
||||
}
|
||||
fn interns_mut(&mut self) -> &mut Interns {
|
||||
self.interns
|
||||
}
|
||||
fn interner(&self) -> &STLayoutInterner<'a> {
|
||||
self.layout_interner
|
||||
}
|
||||
|
|
@ -577,12 +577,14 @@ impl<
|
|||
&mut STLayoutInterner<'a>,
|
||||
&mut Interns,
|
||||
&mut CodeGenHelp<'a>,
|
||||
&mut Vec<'a, CallerProc<'a>>,
|
||||
) {
|
||||
(
|
||||
self.env.module_id,
|
||||
self.layout_interner,
|
||||
self.interns,
|
||||
&mut self.helper_proc_gen,
|
||||
&mut self.caller_procs,
|
||||
)
|
||||
}
|
||||
fn helper_proc_gen_mut(&mut self) -> &mut CodeGenHelp<'a> {
|
||||
|
|
@ -738,6 +740,12 @@ impl<
|
|||
(out.into_bump_slice(), offset)
|
||||
}
|
||||
|
||||
fn build_fn_pointer(&mut self, dst: &Symbol, fn_name: String) {
|
||||
let reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
|
||||
ASM::function_pointer(&mut self.buf, &mut self.relocs, fn_name, reg)
|
||||
}
|
||||
|
||||
fn build_fn_call(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
|
|
@ -746,11 +754,6 @@ impl<
|
|||
arg_layouts: &[InLayout<'a>],
|
||||
ret_layout: &InLayout<'a>,
|
||||
) {
|
||||
if let Some(SelfRecursive::SelfRecursive(id)) = self.is_self_recursive {
|
||||
if &fn_name == self.proc_name.as_ref().unwrap() && self.join_map.contains_key(&id) {
|
||||
return self.build_jump(&id, args, arg_layouts, ret_layout);
|
||||
}
|
||||
}
|
||||
// Save used caller saved regs.
|
||||
self.storage_manager
|
||||
.push_used_caller_saved_regs_to_stack(&mut self.buf);
|
||||
|
|
@ -1221,6 +1224,9 @@ impl<
|
|||
.load_to_general_reg(&mut self.buf, src2);
|
||||
ASM::eq_reg64_reg64_reg64(&mut self.buf, width, dst_reg, src1_reg, src2_reg);
|
||||
}
|
||||
Layout::F32 => todo!("NumEq: layout, {:?}", self.layout_interner.dbg(Layout::F32)),
|
||||
Layout::F64 => todo!("NumEq: layout, {:?}", self.layout_interner.dbg(Layout::F64)),
|
||||
Layout::DEC => todo!("NumEq: layout, {:?}", self.layout_interner.dbg(Layout::DEC)),
|
||||
Layout::STR => {
|
||||
// use a zig call
|
||||
self.build_fn_call(
|
||||
|
|
@ -1241,7 +1247,33 @@ impl<
|
|||
let dst_reg = self.storage_manager.load_to_general_reg(&mut self.buf, dst);
|
||||
ASM::eq_reg64_reg64_reg64(&mut self.buf, width, dst_reg, dst_reg, tmp_reg);
|
||||
}
|
||||
x => todo!("NumEq: layout, {:?}", x),
|
||||
other => {
|
||||
let ident_ids = self
|
||||
.interns
|
||||
.all_ident_ids
|
||||
.get_mut(&self.env.module_id)
|
||||
.unwrap();
|
||||
|
||||
// generate a proc
|
||||
|
||||
let (eq_symbol, eq_linker_data) = self.helper_proc_gen.gen_refcount_proc(
|
||||
ident_ids,
|
||||
self.layout_interner,
|
||||
other,
|
||||
HelperOp::Eq,
|
||||
);
|
||||
|
||||
let fn_name = self.function_symbol_to_string(
|
||||
eq_symbol,
|
||||
[other, other].into_iter(),
|
||||
None,
|
||||
Layout::U8,
|
||||
);
|
||||
|
||||
self.helper_proc_symbols.extend(eq_linker_data);
|
||||
|
||||
self.build_fn_call(dst, fn_name, &[*src1, *src2], &[other, other], &Layout::U8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1304,126 +1336,6 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
fn build_num_lt(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src1: &Symbol,
|
||||
src2: &Symbol,
|
||||
arg_layout: &InLayout<'a>,
|
||||
) {
|
||||
match self.layout_interner.get(*arg_layout) {
|
||||
Layout::Builtin(Builtin::Int(IntWidth::I64)) => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, src1);
|
||||
let src2_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, src2);
|
||||
ASM::signed_compare_reg64(
|
||||
&mut self.buf,
|
||||
RegisterWidth::W64,
|
||||
CompareOperation::LessThan,
|
||||
dst_reg,
|
||||
src1_reg,
|
||||
src2_reg,
|
||||
);
|
||||
}
|
||||
Layout::Builtin(Builtin::Int(IntWidth::U64)) => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, src1);
|
||||
let src2_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, src2);
|
||||
ASM::unsigned_compare_reg64(
|
||||
&mut self.buf,
|
||||
RegisterWidth::W64,
|
||||
CompareOperation::LessThan,
|
||||
dst_reg,
|
||||
src1_reg,
|
||||
src2_reg,
|
||||
);
|
||||
}
|
||||
Layout::Builtin(Builtin::Float(width)) => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
|
||||
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
|
||||
|
||||
ASM::cmp_freg_freg_reg64(
|
||||
&mut self.buf,
|
||||
dst_reg,
|
||||
src1_reg,
|
||||
src2_reg,
|
||||
width,
|
||||
CompareOperation::LessThan,
|
||||
);
|
||||
}
|
||||
x => todo!("NumLt: layout, {:?}", x),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_num_gt(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src1: &Symbol,
|
||||
src2: &Symbol,
|
||||
arg_layout: &InLayout<'a>,
|
||||
) {
|
||||
match self.layout_interner.get(*arg_layout) {
|
||||
Layout::Builtin(Builtin::Int(IntWidth::I64)) => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, src1);
|
||||
let src2_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, src2);
|
||||
ASM::signed_compare_reg64(
|
||||
&mut self.buf,
|
||||
RegisterWidth::W64,
|
||||
CompareOperation::GreaterThan,
|
||||
dst_reg,
|
||||
src1_reg,
|
||||
src2_reg,
|
||||
);
|
||||
}
|
||||
Layout::Builtin(Builtin::Int(IntWidth::U64)) => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, src1);
|
||||
let src2_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, src2);
|
||||
ASM::unsigned_compare_reg64(
|
||||
&mut self.buf,
|
||||
RegisterWidth::W64,
|
||||
CompareOperation::GreaterThan,
|
||||
dst_reg,
|
||||
src1_reg,
|
||||
src2_reg,
|
||||
);
|
||||
}
|
||||
Layout::Builtin(Builtin::Float(width)) => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
|
||||
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
|
||||
|
||||
ASM::cmp_freg_freg_reg64(
|
||||
&mut self.buf,
|
||||
dst_reg,
|
||||
src1_reg,
|
||||
src2_reg,
|
||||
width,
|
||||
CompareOperation::GreaterThan,
|
||||
);
|
||||
}
|
||||
x => todo!("NumGt: layout, {:?}", x),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_num_to_frac(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
|
|
@ -1482,6 +1394,26 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
fn build_num_lt(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src1: &Symbol,
|
||||
src2: &Symbol,
|
||||
arg_layout: &InLayout<'a>,
|
||||
) {
|
||||
self.compare(CompareOperation::LessThan, dst, src1, src2, arg_layout)
|
||||
}
|
||||
|
||||
fn build_num_gt(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src1: &Symbol,
|
||||
src2: &Symbol,
|
||||
arg_layout: &InLayout<'a>,
|
||||
) {
|
||||
self.compare(CompareOperation::GreaterThan, dst, src1, src2, arg_layout)
|
||||
}
|
||||
|
||||
fn build_num_lte(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
|
|
@ -1489,39 +1421,13 @@ impl<
|
|||
src2: &Symbol,
|
||||
arg_layout: &InLayout<'a>,
|
||||
) {
|
||||
match *arg_layout {
|
||||
single_register_int_builtins!() => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, src1);
|
||||
let src2_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, src2);
|
||||
ASM::lte_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||
}
|
||||
Layout::F64 | Layout::F32 => {
|
||||
let width = if *arg_layout == Layout::F64 {
|
||||
FloatWidth::F64
|
||||
} else {
|
||||
FloatWidth::F32
|
||||
};
|
||||
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
|
||||
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
|
||||
|
||||
ASM::cmp_freg_freg_reg64(
|
||||
&mut self.buf,
|
||||
dst_reg,
|
||||
src1_reg,
|
||||
src2_reg,
|
||||
width,
|
||||
CompareOperation::LessThanOrEqual,
|
||||
);
|
||||
}
|
||||
x => todo!("NumLte: layout, {:?}", x),
|
||||
}
|
||||
self.compare(
|
||||
CompareOperation::LessThanOrEqual,
|
||||
dst,
|
||||
src1,
|
||||
src2,
|
||||
arg_layout,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_num_gte(
|
||||
|
|
@ -1531,38 +1437,178 @@ impl<
|
|||
src2: &Symbol,
|
||||
arg_layout: &InLayout<'a>,
|
||||
) {
|
||||
match *arg_layout {
|
||||
single_register_int_builtins!() => {
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, src1);
|
||||
let src2_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, src2);
|
||||
ASM::gte_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
|
||||
}
|
||||
Layout::F64 | Layout::F32 => {
|
||||
let width = if *arg_layout == Layout::F64 {
|
||||
FloatWidth::F64
|
||||
} else {
|
||||
FloatWidth::F32
|
||||
};
|
||||
self.compare(
|
||||
CompareOperation::GreaterThanOrEqual,
|
||||
dst,
|
||||
src1,
|
||||
src2,
|
||||
arg_layout,
|
||||
)
|
||||
}
|
||||
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
|
||||
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
|
||||
fn build_higher_order_lowlevel(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
higher_order: &HigherOrderLowLevel<'a>,
|
||||
ret_layout: InLayout<'a>,
|
||||
) {
|
||||
let ident_ids = self
|
||||
.interns
|
||||
.all_ident_ids
|
||||
.get_mut(&self.env.module_id)
|
||||
.unwrap();
|
||||
|
||||
ASM::cmp_freg_freg_reg64(
|
||||
&mut self.buf,
|
||||
dst_reg,
|
||||
src1_reg,
|
||||
src2_reg,
|
||||
width,
|
||||
CompareOperation::GreaterThanOrEqual,
|
||||
let (inc_n_data_symbol, inc_n_data_linker_data) = self.helper_proc_gen.gen_refcount_proc(
|
||||
ident_ids,
|
||||
self.layout_interner,
|
||||
Layout::UNIT,
|
||||
HelperOp::Inc,
|
||||
);
|
||||
|
||||
let caller_proc = CallerProc::new(
|
||||
self.env.arena,
|
||||
self.env.module_id,
|
||||
ident_ids,
|
||||
self.layout_interner,
|
||||
&higher_order.passed_function,
|
||||
higher_order.closure_env_layout,
|
||||
);
|
||||
|
||||
match higher_order.op {
|
||||
HigherOrder::ListMap { xs } => {
|
||||
let old_element_layout = higher_order.passed_function.argument_layouts[0];
|
||||
let new_element_layout = higher_order.passed_function.return_layout;
|
||||
|
||||
let input_list_layout = Layout::Builtin(Builtin::List(old_element_layout));
|
||||
let input_list_in_layout = self.layout_interner.insert(input_list_layout);
|
||||
|
||||
let caller = self.debug_symbol("caller");
|
||||
let data = self.debug_symbol("data");
|
||||
let alignment = self.debug_symbol("alignment");
|
||||
let old_element_width = self.debug_symbol("old_element_width");
|
||||
let new_element_width = self.debug_symbol("new_element_width");
|
||||
|
||||
self.load_layout_alignment(new_element_layout, alignment);
|
||||
|
||||
self.load_layout_stack_size(old_element_layout, old_element_width);
|
||||
self.load_layout_stack_size(new_element_layout, new_element_width);
|
||||
|
||||
self.helper_proc_symbols.extend(inc_n_data_linker_data);
|
||||
self.helper_proc_symbols
|
||||
.extend([(caller_proc.proc_symbol, caller_proc.proc_layout)]);
|
||||
|
||||
let inc_n_data_string = self.function_symbol_to_string(
|
||||
inc_n_data_symbol,
|
||||
std::iter::empty(),
|
||||
None,
|
||||
Layout::UNIT,
|
||||
);
|
||||
|
||||
let caller_string = self.function_symbol_to_string(
|
||||
caller_proc.proc_symbol,
|
||||
std::iter::empty(),
|
||||
None,
|
||||
Layout::UNIT,
|
||||
);
|
||||
|
||||
self.caller_procs.push(caller_proc);
|
||||
|
||||
let inc_n_data = Symbol::DEV_TMP5;
|
||||
self.build_fn_pointer(&inc_n_data, inc_n_data_string);
|
||||
|
||||
self.build_fn_pointer(&caller, caller_string);
|
||||
|
||||
if let Some(_closure_data_layout) = higher_order.closure_env_layout {
|
||||
let data_symbol = higher_order.passed_function.captured_environment;
|
||||
self.storage_manager
|
||||
.ensure_symbol_on_stack(&mut self.buf, &data_symbol);
|
||||
let (new_elem_offset, _) =
|
||||
self.storage_manager.stack_offset_and_size(&data_symbol);
|
||||
|
||||
// Load address of output element into register.
|
||||
let reg = self.storage_manager.claim_general_reg(&mut self.buf, &data);
|
||||
ASM::add_reg64_reg64_imm32(
|
||||
&mut self.buf,
|
||||
reg,
|
||||
CC::BASE_PTR_REG,
|
||||
new_elem_offset,
|
||||
);
|
||||
} else {
|
||||
// use a null pointer
|
||||
self.load_literal(&data, &Layout::U64, &Literal::Int(0u128.to_be_bytes()));
|
||||
}
|
||||
|
||||
self.load_literal(
|
||||
&Symbol::DEV_TMP3,
|
||||
&Layout::BOOL,
|
||||
&Literal::Bool(higher_order.passed_function.owns_captured_environment),
|
||||
);
|
||||
|
||||
// list: RocList,
|
||||
// caller: Caller1,
|
||||
// data: Opaque,
|
||||
// inc_n_data: IncN,
|
||||
// data_is_owned: bool,
|
||||
// alignment: u32,
|
||||
// old_element_width: usize,
|
||||
// new_element_width: usize,
|
||||
|
||||
let arguments = [
|
||||
xs,
|
||||
caller,
|
||||
data,
|
||||
inc_n_data,
|
||||
Symbol::DEV_TMP3,
|
||||
alignment,
|
||||
old_element_width,
|
||||
new_element_width,
|
||||
];
|
||||
|
||||
let ptr = Layout::U64;
|
||||
let usize_ = Layout::U64;
|
||||
|
||||
let layouts = [
|
||||
input_list_in_layout,
|
||||
ptr,
|
||||
ptr,
|
||||
ptr,
|
||||
Layout::BOOL,
|
||||
Layout::U32,
|
||||
usize_,
|
||||
usize_,
|
||||
];
|
||||
|
||||
// Setup the return location.
|
||||
let base_offset = self
|
||||
.storage_manager
|
||||
.claim_stack_area(dst, self.layout_interner.stack_size(ret_layout));
|
||||
|
||||
self.build_fn_call(
|
||||
&Symbol::DEV_TMP4,
|
||||
bitcode::LIST_MAP.to_string(),
|
||||
&arguments,
|
||||
&layouts,
|
||||
&ret_layout,
|
||||
);
|
||||
|
||||
self.free_symbol(&Symbol::DEV_TMP3);
|
||||
self.free_symbol(&Symbol::DEV_TMP5);
|
||||
|
||||
// Return list value from fn call
|
||||
self.storage_manager.copy_symbol_to_stack_offset(
|
||||
self.layout_interner,
|
||||
&mut self.buf,
|
||||
base_offset,
|
||||
&Symbol::DEV_TMP4,
|
||||
&ret_layout,
|
||||
);
|
||||
|
||||
self.free_symbol(&Symbol::DEV_TMP4);
|
||||
}
|
||||
x => todo!("NumGte: layout, {:?}", x),
|
||||
HigherOrder::ListMap2 { .. } => todo!(),
|
||||
HigherOrder::ListMap3 { .. } => todo!(),
|
||||
HigherOrder::ListMap4 { .. } => todo!(),
|
||||
HigherOrder::ListSortWith { .. } => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1589,14 +1635,13 @@ impl<
|
|||
.storage_manager
|
||||
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
|
||||
|
||||
let lowlevel_args = bumpalo::vec![
|
||||
in self.env.arena;
|
||||
let lowlevel_args = [
|
||||
capacity,
|
||||
// alignment
|
||||
Symbol::DEV_TMP,
|
||||
// element_width
|
||||
Symbol::DEV_TMP2,
|
||||
];
|
||||
];
|
||||
let lowlevel_arg_layouts = [capacity_layout, Layout::U32, Layout::U64];
|
||||
|
||||
self.build_fn_call(
|
||||
|
|
@ -1727,14 +1772,13 @@ impl<
|
|||
.storage_manager
|
||||
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
|
||||
|
||||
let lowlevel_args = bumpalo::vec![
|
||||
in self.env.arena;
|
||||
let lowlevel_args = [
|
||||
list,
|
||||
// element
|
||||
Symbol::DEV_TMP,
|
||||
// element_width
|
||||
Symbol::DEV_TMP2
|
||||
];
|
||||
Symbol::DEV_TMP2,
|
||||
];
|
||||
let lowlevel_arg_layouts = [list_layout, Layout::U64, Layout::U64];
|
||||
|
||||
self.build_fn_call(
|
||||
|
|
@ -1776,7 +1820,7 @@ impl<
|
|||
self.storage_manager.with_tmp_general_reg(
|
||||
&mut self.buf,
|
||||
|storage_manager, buf, list_ptr| {
|
||||
ASM::mov_reg64_base32(buf, list_ptr, base_offset as i32);
|
||||
ASM::mov_reg64_base32(buf, list_ptr, base_offset);
|
||||
storage_manager.with_tmp_general_reg(buf, |storage_manager, buf, tmp| {
|
||||
// calculate `element_width * index`
|
||||
ASM::mov_reg64_imm64(buf, tmp, ret_stack_size as i64);
|
||||
|
|
@ -2004,8 +2048,7 @@ impl<
|
|||
.storage_manager
|
||||
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
|
||||
|
||||
let lowlevel_args = bumpalo::vec![
|
||||
in self.env.arena;
|
||||
let lowlevel_args = [
|
||||
list,
|
||||
// alignment
|
||||
Symbol::DEV_TMP,
|
||||
|
|
@ -2013,7 +2056,7 @@ impl<
|
|||
Symbol::DEV_TMP2,
|
||||
// element_width
|
||||
Symbol::DEV_TMP3,
|
||||
];
|
||||
];
|
||||
let lowlevel_arg_layouts = [list_layout, Layout::U32, Layout::U64, Layout::U64];
|
||||
|
||||
self.build_fn_call(
|
||||
|
|
@ -2195,27 +2238,16 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
fn expr_box(&mut self, sym: Symbol, value: Symbol, element_layout: InLayout<'a>) {
|
||||
let element_width_symbol = Symbol::DEV_TMP;
|
||||
self.load_layout_stack_size(element_layout, element_width_symbol);
|
||||
|
||||
// Load allocation alignment (u32)
|
||||
let element_alignment_symbol = Symbol::DEV_TMP2;
|
||||
self.load_layout_alignment(Layout::U32, element_alignment_symbol);
|
||||
|
||||
self.allocate_with_refcount(
|
||||
Symbol::DEV_TMP3,
|
||||
element_width_symbol,
|
||||
element_alignment_symbol,
|
||||
);
|
||||
|
||||
self.free_symbol(&element_width_symbol);
|
||||
self.free_symbol(&element_alignment_symbol);
|
||||
|
||||
// Fill pointer with the value
|
||||
fn build_ptr_write(
|
||||
&mut self,
|
||||
sym: Symbol,
|
||||
ptr: Symbol,
|
||||
value: Symbol,
|
||||
element_layout: InLayout<'a>,
|
||||
) {
|
||||
let ptr_reg = self
|
||||
.storage_manager
|
||||
.load_to_general_reg(&mut self.buf, &Symbol::DEV_TMP3);
|
||||
.load_to_general_reg(&mut self.buf, &ptr);
|
||||
|
||||
let element_width = self.layout_interner.stack_size(element_layout) as u64;
|
||||
let element_offset = 0;
|
||||
|
|
@ -2237,6 +2269,26 @@ impl<
|
|||
// box is just a pointer on the stack
|
||||
let base_offset = self.storage_manager.claim_stack_area(&sym, 8);
|
||||
ASM::mov_base32_reg64(&mut self.buf, base_offset, ptr_reg);
|
||||
}
|
||||
|
||||
fn expr_box(&mut self, sym: Symbol, value: Symbol, element_layout: InLayout<'a>) {
|
||||
let element_width_symbol = Symbol::DEV_TMP;
|
||||
self.load_layout_stack_size(element_layout, element_width_symbol);
|
||||
|
||||
// Load allocation alignment (u32)
|
||||
let element_alignment_symbol = Symbol::DEV_TMP2;
|
||||
self.load_layout_alignment(Layout::U32, element_alignment_symbol);
|
||||
|
||||
self.allocate_with_refcount(
|
||||
Symbol::DEV_TMP3,
|
||||
element_width_symbol,
|
||||
element_alignment_symbol,
|
||||
);
|
||||
|
||||
self.free_symbol(&element_width_symbol);
|
||||
self.free_symbol(&element_alignment_symbol);
|
||||
|
||||
self.build_ptr_write(sym, Symbol::DEV_TMP3, value, element_layout);
|
||||
|
||||
self.free_symbol(&Symbol::DEV_TMP3);
|
||||
}
|
||||
|
|
@ -2662,6 +2714,28 @@ impl<
|
|||
FloatWidth::F64 => ASM::sqrt_freg64_freg64(buf, dst_reg, src_reg),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_num_int_cast(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src: &Symbol,
|
||||
source: IntWidth,
|
||||
target: IntWidth,
|
||||
) {
|
||||
let buf = &mut self.buf;
|
||||
|
||||
let dst_reg = self.storage_manager.claim_general_reg(buf, dst);
|
||||
let src_reg = self.storage_manager.load_to_general_reg(buf, src);
|
||||
|
||||
if source.stack_size() == target.stack_size() {
|
||||
match source.stack_size() {
|
||||
8 => ASM::mov_reg64_reg64(buf, dst_reg, src_reg),
|
||||
_ => todo!("int cast from {source:?} to {target:?}"),
|
||||
}
|
||||
} else {
|
||||
todo!("int cast from {source:?} to {target:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This impl block is for ir related instructions that need backend specific information.
|
||||
|
|
@ -2675,6 +2749,61 @@ impl<
|
|||
CC: CallConv<GeneralReg, FloatReg, ASM>,
|
||||
> Backend64Bit<'a, 'r, GeneralReg, FloatReg, ASM, CC>
|
||||
{
|
||||
fn compare(
|
||||
&mut self,
|
||||
op: CompareOperation,
|
||||
dst: &Symbol,
|
||||
src1: &Symbol,
|
||||
src2: &Symbol,
|
||||
arg_layout: &InLayout<'a>,
|
||||
) {
|
||||
match *arg_layout {
|
||||
single_register_integers!() => {
|
||||
let buf = &mut self.buf;
|
||||
|
||||
let dst = self.storage_manager.claim_general_reg(buf, dst);
|
||||
let src1 = self.storage_manager.load_to_general_reg(buf, src1);
|
||||
let src2 = self.storage_manager.load_to_general_reg(buf, src2);
|
||||
|
||||
let int_width = arg_layout.try_int_width().unwrap();
|
||||
let register_width = match int_width.stack_size() {
|
||||
8 => RegisterWidth::W64,
|
||||
4 => RegisterWidth::W32,
|
||||
2 => RegisterWidth::W16,
|
||||
1 => RegisterWidth::W8,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if int_width.is_signed() {
|
||||
ASM::signed_compare_reg64(buf, register_width, op, dst, src1, src2)
|
||||
} else {
|
||||
ASM::unsigned_compare_reg64(buf, register_width, op, dst, src1, src2)
|
||||
}
|
||||
}
|
||||
Layout::F32 | Layout::F64 => {
|
||||
let float_width = match *arg_layout {
|
||||
Layout::F32 => FloatWidth::F32,
|
||||
Layout::F64 => FloatWidth::F64,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
|
||||
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
|
||||
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
|
||||
|
||||
ASM::cmp_freg_freg_reg64(
|
||||
&mut self.buf,
|
||||
dst_reg,
|
||||
src1_reg,
|
||||
src2_reg,
|
||||
float_width,
|
||||
op,
|
||||
);
|
||||
}
|
||||
x => todo!("NumLt: layout, {:?}", x),
|
||||
}
|
||||
}
|
||||
|
||||
fn allocate_with_refcount(
|
||||
&mut self,
|
||||
dst: Symbol,
|
||||
|
|
@ -2709,6 +2838,62 @@ impl<
|
|||
ASM::mov_base32_reg64(buf, base_offset + 16, tmp_reg);
|
||||
}
|
||||
|
||||
fn unbox_to_stack(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
|
||||
dst: Symbol,
|
||||
stack_size: u32,
|
||||
ptr_reg: GeneralReg,
|
||||
tmp_reg: GeneralReg,
|
||||
) {
|
||||
let mut copied = 0;
|
||||
let size = stack_size as i32;
|
||||
|
||||
let base_offset = storage_manager.claim_stack_area(&dst, stack_size);
|
||||
|
||||
if size - copied >= 8 {
|
||||
for _ in (0..(size - copied)).step_by(8) {
|
||||
ASM::mov_reg64_mem64_offset32(buf, tmp_reg, ptr_reg, copied);
|
||||
ASM::mov_base32_reg64(buf, base_offset, tmp_reg);
|
||||
|
||||
copied += 8;
|
||||
}
|
||||
}
|
||||
|
||||
if size - copied > 0 {
|
||||
panic!("value only partially copied");
|
||||
}
|
||||
|
||||
/*
|
||||
if size - copied >= 4 {
|
||||
for _ in (0..(size - copied)).step_by(4) {
|
||||
ASM::mov_reg32_base32(buf, reg, from_offset + copied);
|
||||
ASM::mov_base32_reg32(buf, to_offset + copied, reg);
|
||||
|
||||
copied += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if size - copied >= 2 {
|
||||
for _ in (0..(size - copied)).step_by(2) {
|
||||
ASM::mov_reg16_base32(buf, reg, from_offset + copied);
|
||||
ASM::mov_base32_reg16(buf, to_offset + copied, reg);
|
||||
|
||||
copied += 2;
|
||||
}
|
||||
}
|
||||
|
||||
if size - copied >= 1 {
|
||||
for _ in (0..(size - copied)).step_by(1) {
|
||||
ASM::mov_reg8_base32(buf, reg, from_offset + copied);
|
||||
ASM::mov_base32_reg8(buf, to_offset + copied, reg);
|
||||
|
||||
copied += 1;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
fn ptr_read(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
|
||||
|
|
@ -2766,6 +2951,15 @@ impl<
|
|||
ASM::mov_reg64_mem64_offset32(buf, dst_reg, ptr_reg, 0);
|
||||
}
|
||||
|
||||
Layout::Struct { .. } => {
|
||||
// put it on the stack
|
||||
let stack_size = layout_interner.stack_size(element_in_layout);
|
||||
|
||||
storage_manager.with_tmp_general_reg(buf, |storage_manager, buf, tmp_reg| {
|
||||
Self::unbox_to_stack(buf, storage_manager, dst, stack_size, ptr_reg, tmp_reg);
|
||||
});
|
||||
}
|
||||
|
||||
_ => todo!("unboxing of {:?}", layout_interner.dbg(element_in_layout)),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -654,7 +654,15 @@ impl<
|
|||
}
|
||||
let base_offset = self.claim_stack_area(sym, struct_size);
|
||||
|
||||
if let Layout::Struct { field_layouts, .. } = layout_interner.get(*layout) {
|
||||
let mut in_layout = *layout;
|
||||
let layout = loop {
|
||||
match layout_interner.get(in_layout) {
|
||||
Layout::LambdaSet(inner) => in_layout = inner.runtime_representation(),
|
||||
other => break other,
|
||||
}
|
||||
};
|
||||
|
||||
if let Layout::Struct { field_layouts, .. } = layout {
|
||||
let mut current_offset = base_offset;
|
||||
for (field, field_layout) in fields.iter().zip(field_layouts.iter()) {
|
||||
self.copy_symbol_to_stack_offset(
|
||||
|
|
@ -670,7 +678,13 @@ impl<
|
|||
} else {
|
||||
// This is a single element struct. Just copy the single field to the stack.
|
||||
debug_assert_eq!(fields.len(), 1);
|
||||
self.copy_symbol_to_stack_offset(layout_interner, buf, base_offset, &fields[0], layout);
|
||||
self.copy_symbol_to_stack_offset(
|
||||
layout_interner,
|
||||
buf,
|
||||
base_offset,
|
||||
&fields[0],
|
||||
&in_layout,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -216,8 +216,8 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn setup_stack<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
fn setup_stack(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
saved_general_regs: &[X86_64GeneralReg],
|
||||
saved_float_regs: &[X86_64FloatReg],
|
||||
requested_stack_size: i32,
|
||||
|
|
@ -233,8 +233,8 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn cleanup_stack<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
fn cleanup_stack(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
saved_general_regs: &[X86_64GeneralReg],
|
||||
saved_float_regs: &[X86_64FloatReg],
|
||||
aligned_stack_size: i32,
|
||||
|
|
@ -250,11 +250,11 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn load_args<'a, 'r>(
|
||||
fn load_args<'a>(
|
||||
_buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<
|
||||
'a,
|
||||
'r,
|
||||
'_,
|
||||
X86_64GeneralReg,
|
||||
X86_64FloatReg,
|
||||
X86_64Assembler,
|
||||
|
|
@ -284,11 +284,11 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn store_args<'a, 'r>(
|
||||
fn store_args<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<
|
||||
'a,
|
||||
'r,
|
||||
'_,
|
||||
X86_64GeneralReg,
|
||||
X86_64FloatReg,
|
||||
X86_64Assembler,
|
||||
|
|
@ -330,11 +330,11 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
storage_manager.update_fn_call_stack_size(state.tmp_stack_offset as u32);
|
||||
}
|
||||
|
||||
fn return_complex_symbol<'a, 'r>(
|
||||
fn return_complex_symbol<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<
|
||||
'a,
|
||||
'r,
|
||||
'_,
|
||||
X86_64GeneralReg,
|
||||
X86_64FloatReg,
|
||||
X86_64Assembler,
|
||||
|
|
@ -388,11 +388,11 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
}
|
||||
}
|
||||
|
||||
fn load_returned_complex_symbol<'a, 'r>(
|
||||
fn load_returned_complex_symbol<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<
|
||||
'a,
|
||||
'r,
|
||||
'_,
|
||||
X86_64GeneralReg,
|
||||
X86_64FloatReg,
|
||||
X86_64Assembler,
|
||||
|
|
@ -447,10 +447,10 @@ impl X64_64SystemVStoreArgs {
|
|||
const FLOAT_PARAM_REGS: &'static [X86_64FloatReg] = X86_64SystemV::FLOAT_PARAM_REGS;
|
||||
const FLOAT_RETURN_REGS: &'static [X86_64FloatReg] = X86_64SystemV::FLOAT_RETURN_REGS;
|
||||
|
||||
fn store_arg<'a, 'r>(
|
||||
fn store_arg<'a>(
|
||||
&mut self,
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64SystemV>,
|
||||
storage_manager: &mut X86_64StorageManager<'a, '_, X86_64SystemV>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
sym: Symbol,
|
||||
in_layout: InLayout<'a>,
|
||||
|
|
@ -537,10 +537,10 @@ impl X64_64SystemVStoreArgs {
|
|||
}
|
||||
}
|
||||
|
||||
fn store_arg_general<'a, 'r>(
|
||||
fn store_arg_general<'a>(
|
||||
&mut self,
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64SystemV>,
|
||||
storage_manager: &mut X86_64StorageManager<'a, '_, X86_64SystemV>,
|
||||
sym: Symbol,
|
||||
) {
|
||||
if self.general_i < Self::GENERAL_PARAM_REGS.len() {
|
||||
|
|
@ -562,10 +562,10 @@ impl X64_64SystemVStoreArgs {
|
|||
}
|
||||
}
|
||||
|
||||
fn store_arg_float<'a, 'r>(
|
||||
fn store_arg_float<'a>(
|
||||
&mut self,
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64SystemV>,
|
||||
storage_manager: &mut X86_64StorageManager<'a, '_, X86_64SystemV>,
|
||||
sym: Symbol,
|
||||
) {
|
||||
if self.float_i < Self::FLOAT_PARAM_REGS.len() {
|
||||
|
|
@ -598,9 +598,9 @@ type X86_64StorageManager<'a, 'r, CallConv> =
|
|||
StorageManager<'a, 'r, X86_64GeneralReg, X86_64FloatReg, X86_64Assembler, CallConv>;
|
||||
|
||||
impl X64_64SystemVLoadArgs {
|
||||
fn load_arg<'a, 'r>(
|
||||
fn load_arg<'a>(
|
||||
&mut self,
|
||||
storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64SystemV>,
|
||||
storage_manager: &mut X86_64StorageManager<'a, '_, X86_64SystemV>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
sym: Symbol,
|
||||
in_layout: InLayout<'a>,
|
||||
|
|
@ -645,9 +645,9 @@ impl X64_64SystemVLoadArgs {
|
|||
}
|
||||
}
|
||||
|
||||
fn load_arg_general<'a, 'r>(
|
||||
fn load_arg_general(
|
||||
&mut self,
|
||||
storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64SystemV>,
|
||||
storage_manager: &mut X86_64StorageManager<'_, '_, X86_64SystemV>,
|
||||
sym: Symbol,
|
||||
) {
|
||||
if self.general_i < X86_64SystemV::GENERAL_PARAM_REGS.len() {
|
||||
|
|
@ -660,9 +660,9 @@ impl X64_64SystemVLoadArgs {
|
|||
}
|
||||
}
|
||||
|
||||
fn load_arg_float<'a, 'r>(
|
||||
fn load_arg_float(
|
||||
&mut self,
|
||||
storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64SystemV>,
|
||||
storage_manager: &mut X86_64StorageManager<'_, '_, X86_64SystemV>,
|
||||
sym: Symbol,
|
||||
) {
|
||||
if self.general_i < X86_64SystemV::GENERAL_PARAM_REGS.len() {
|
||||
|
|
@ -783,8 +783,8 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn setup_stack<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
fn setup_stack(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
saved_general_regs: &[X86_64GeneralReg],
|
||||
saved_float_regs: &[X86_64FloatReg],
|
||||
requested_stack_size: i32,
|
||||
|
|
@ -800,8 +800,8 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn cleanup_stack<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
fn cleanup_stack(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
saved_general_regs: &[X86_64GeneralReg],
|
||||
saved_float_regs: &[X86_64FloatReg],
|
||||
aligned_stack_size: i32,
|
||||
|
|
@ -817,9 +817,9 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn load_args<'a, 'r>(
|
||||
fn load_args<'a>(
|
||||
_buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut X86_64StorageManager<'a, 'r, X86_64WindowsFastcall>,
|
||||
storage_manager: &mut X86_64StorageManager<'a, '_, X86_64WindowsFastcall>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
args: &'a [(InLayout<'a>, Symbol)],
|
||||
ret_layout: &InLayout<'a>,
|
||||
|
|
@ -861,11 +861,11 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn store_args<'a, 'r>(
|
||||
fn store_args<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<
|
||||
'a,
|
||||
'r,
|
||||
'_,
|
||||
X86_64GeneralReg,
|
||||
X86_64FloatReg,
|
||||
X86_64Assembler,
|
||||
|
|
@ -938,11 +938,11 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
|||
storage_manager.update_fn_call_stack_size(tmp_stack_offset as u32);
|
||||
}
|
||||
|
||||
fn return_complex_symbol<'a, 'r>(
|
||||
fn return_complex_symbol<'a>(
|
||||
_buf: &mut Vec<'a, u8>,
|
||||
_storage_manager: &mut StorageManager<
|
||||
'a,
|
||||
'r,
|
||||
'_,
|
||||
X86_64GeneralReg,
|
||||
X86_64FloatReg,
|
||||
X86_64Assembler,
|
||||
|
|
@ -955,11 +955,11 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Windo
|
|||
todo!("Returning complex symbols for X86_64");
|
||||
}
|
||||
|
||||
fn load_returned_complex_symbol<'a, 'r>(
|
||||
fn load_returned_complex_symbol<'a>(
|
||||
_buf: &mut Vec<'a, u8>,
|
||||
_storage_manager: &mut StorageManager<
|
||||
'a,
|
||||
'r,
|
||||
'_,
|
||||
X86_64GeneralReg,
|
||||
X86_64FloatReg,
|
||||
X86_64Assembler,
|
||||
|
|
@ -985,8 +985,8 @@ impl X86_64WindowsFastcall {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn x86_64_generic_setup_stack<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
fn x86_64_generic_setup_stack(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
saved_general_regs: &[X86_64GeneralReg],
|
||||
saved_float_regs: &[X86_64FloatReg],
|
||||
requested_stack_size: i32,
|
||||
|
|
@ -1042,8 +1042,8 @@ fn x86_64_generic_setup_stack<'a>(
|
|||
|
||||
#[inline(always)]
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
fn x86_64_generic_cleanup_stack<'a>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
fn x86_64_generic_cleanup_stack(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
saved_general_regs: &[X86_64GeneralReg],
|
||||
saved_float_regs: &[X86_64FloatReg],
|
||||
aligned_stack_size: i32,
|
||||
|
|
@ -1172,6 +1172,21 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
});
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn function_pointer(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
relocs: &mut Vec<'_, Relocation>,
|
||||
fn_name: String,
|
||||
dst: X86_64GeneralReg,
|
||||
) {
|
||||
lea_reg64(buf, dst);
|
||||
|
||||
relocs.push(Relocation::LinkedFunction {
|
||||
offset: buf.len() as u64 - 4,
|
||||
name: fn_name,
|
||||
});
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn imul_reg64_reg64_reg64(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
|
|
@ -1183,9 +1198,9 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
imul_reg64_reg64(buf, dst, src2);
|
||||
}
|
||||
|
||||
fn umul_reg64_reg64_reg64<'a, 'r, ASM, CC>(
|
||||
fn umul_reg64_reg64_reg64<'a, ASM, CC>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, X86_64GeneralReg, X86_64FloatReg, ASM, CC>,
|
||||
storage_manager: &mut StorageManager<'a, '_, X86_64GeneralReg, X86_64FloatReg, ASM, CC>,
|
||||
dst: X86_64GeneralReg,
|
||||
src1: X86_64GeneralReg,
|
||||
src2: X86_64GeneralReg,
|
||||
|
|
@ -1267,9 +1282,9 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
}
|
||||
}
|
||||
|
||||
fn idiv_reg64_reg64_reg64<'a, 'r, ASM, CC>(
|
||||
fn idiv_reg64_reg64_reg64<'a, ASM, CC>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, X86_64GeneralReg, X86_64FloatReg, ASM, CC>,
|
||||
storage_manager: &mut StorageManager<'a, '_, X86_64GeneralReg, X86_64FloatReg, ASM, CC>,
|
||||
dst: X86_64GeneralReg,
|
||||
src1: X86_64GeneralReg,
|
||||
src2: X86_64GeneralReg,
|
||||
|
|
@ -1287,9 +1302,9 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
mov_reg64_reg64(buf, dst, X86_64GeneralReg::RAX);
|
||||
}
|
||||
|
||||
fn udiv_reg64_reg64_reg64<'a, 'r, ASM, CC>(
|
||||
fn udiv_reg64_reg64_reg64<'a, ASM, CC>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, X86_64GeneralReg, X86_64FloatReg, ASM, CC>,
|
||||
storage_manager: &mut StorageManager<'a, '_, X86_64GeneralReg, X86_64FloatReg, ASM, CC>,
|
||||
dst: X86_64GeneralReg,
|
||||
src1: X86_64GeneralReg,
|
||||
src2: X86_64GeneralReg,
|
||||
|
|
@ -1607,17 +1622,13 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
src1: X86_64GeneralReg,
|
||||
src2: X86_64GeneralReg,
|
||||
) {
|
||||
cmp_reg64_reg64(buf, register_width, src1, src2);
|
||||
|
||||
match operation {
|
||||
CompareOperation::LessThan => {
|
||||
cmp_reg64_reg64(buf, register_width, src1, src2);
|
||||
setl_reg64(buf, dst);
|
||||
}
|
||||
CompareOperation::LessThanOrEqual => todo!(),
|
||||
CompareOperation::GreaterThan => {
|
||||
cmp_reg64_reg64(buf, register_width, src1, src2);
|
||||
setg_reg64(buf, dst);
|
||||
}
|
||||
CompareOperation::GreaterThanOrEqual => todo!(),
|
||||
CompareOperation::LessThan => setl_reg64(buf, dst),
|
||||
CompareOperation::LessThanOrEqual => setle_reg64(buf, dst),
|
||||
CompareOperation::GreaterThan => setg_reg64(buf, dst),
|
||||
CompareOperation::GreaterThanOrEqual => setge_reg64(buf, dst),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1629,18 +1640,13 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
src1: X86_64GeneralReg,
|
||||
src2: X86_64GeneralReg,
|
||||
) {
|
||||
match operation {
|
||||
CompareOperation::LessThan => {
|
||||
cmp_reg64_reg64(buf, register_width, src1, src2);
|
||||
setb_reg64(buf, dst);
|
||||
}
|
||||
CompareOperation::LessThanOrEqual => todo!(),
|
||||
CompareOperation::GreaterThan => {
|
||||
cmp_reg64_reg64(buf, register_width, src1, src2);
|
||||
seta_reg64(buf, dst);
|
||||
}
|
||||
cmp_reg64_reg64(buf, register_width, src1, src2);
|
||||
|
||||
CompareOperation::GreaterThanOrEqual => todo!(),
|
||||
match operation {
|
||||
CompareOperation::LessThan => setb_reg64(buf, dst),
|
||||
CompareOperation::LessThanOrEqual => setbe_reg64(buf, dst),
|
||||
CompareOperation::GreaterThan => seta_reg64(buf, dst),
|
||||
CompareOperation::GreaterThanOrEqual => setae_reg64(buf, dst),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1691,28 +1697,6 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
cvtsi2sd_freg64_reg64(buf, dst, src);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn lte_reg64_reg64_reg64(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
dst: X86_64GeneralReg,
|
||||
src1: X86_64GeneralReg,
|
||||
src2: X86_64GeneralReg,
|
||||
) {
|
||||
cmp_reg64_reg64(buf, RegisterWidth::W64, src1, src2);
|
||||
setle_reg64(buf, dst);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn gte_reg64_reg64_reg64(
|
||||
buf: &mut Vec<'_, u8>,
|
||||
dst: X86_64GeneralReg,
|
||||
src1: X86_64GeneralReg,
|
||||
src2: X86_64GeneralReg,
|
||||
) {
|
||||
cmp_reg64_reg64(buf, RegisterWidth::W64, src1, src2);
|
||||
setge_reg64(buf, dst);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn ret(buf: &mut Vec<'_, u8>) {
|
||||
ret(buf);
|
||||
|
|
@ -1734,9 +1718,9 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
binop_move_src_to_dst_reg64(buf, xor_reg64_reg64, dst, src1, src2)
|
||||
}
|
||||
|
||||
fn shl_reg64_reg64_reg64<'a, 'r, ASM, CC>(
|
||||
fn shl_reg64_reg64_reg64<'a, ASM, CC>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, X86_64GeneralReg, X86_64FloatReg, ASM, CC>,
|
||||
storage_manager: &mut StorageManager<'a, '_, X86_64GeneralReg, X86_64FloatReg, ASM, CC>,
|
||||
dst: X86_64GeneralReg,
|
||||
src1: X86_64GeneralReg,
|
||||
src2: X86_64GeneralReg,
|
||||
|
|
@ -1747,9 +1731,9 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
shift_reg64_reg64_reg64(buf, storage_manager, shl_reg64_reg64, dst, src1, src2)
|
||||
}
|
||||
|
||||
fn shr_reg64_reg64_reg64<'a, 'r, ASM, CC>(
|
||||
fn shr_reg64_reg64_reg64<'a, ASM, CC>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, X86_64GeneralReg, X86_64FloatReg, ASM, CC>,
|
||||
storage_manager: &mut StorageManager<'a, '_, X86_64GeneralReg, X86_64FloatReg, ASM, CC>,
|
||||
dst: X86_64GeneralReg,
|
||||
src1: X86_64GeneralReg,
|
||||
src2: X86_64GeneralReg,
|
||||
|
|
@ -1760,9 +1744,9 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
|
|||
shift_reg64_reg64_reg64(buf, storage_manager, shr_reg64_reg64, dst, src1, src2)
|
||||
}
|
||||
|
||||
fn sar_reg64_reg64_reg64<'a, 'r, ASM, CC>(
|
||||
fn sar_reg64_reg64_reg64<'a, ASM, CC>(
|
||||
buf: &mut Vec<'a, u8>,
|
||||
storage_manager: &mut StorageManager<'a, 'r, X86_64GeneralReg, X86_64FloatReg, ASM, CC>,
|
||||
storage_manager: &mut StorageManager<'a, '_, X86_64GeneralReg, X86_64FloatReg, ASM, CC>,
|
||||
dst: X86_64GeneralReg,
|
||||
src1: X86_64GeneralReg,
|
||||
src2: X86_64GeneralReg,
|
||||
|
|
@ -2398,6 +2382,25 @@ fn mov_reg64_imm64(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg, imm: i64) {
|
|||
}
|
||||
}
|
||||
|
||||
/// `LEA r64, m` -> Store effective address for m in register r64.
|
||||
#[inline(always)]
|
||||
fn lea_reg64(buf: &mut Vec<'_, u8>, dst: X86_64GeneralReg) {
|
||||
let rex = add_opcode_extension(dst, REX_W);
|
||||
let rex = add_reg_extension(dst, rex);
|
||||
let dst_mod = dst as u8 % 8;
|
||||
|
||||
#[allow(clippy::unusual_byte_groupings)]
|
||||
buf.extend([
|
||||
rex,
|
||||
0x8d,
|
||||
0b00_000_101 | (dst_mod << 3),
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
])
|
||||
}
|
||||
|
||||
/// `MOV r/m64,r64` -> Move r64 to r/m64.
|
||||
/// This will not generate anything if dst and src are the same.
|
||||
#[inline(always)]
|
||||
|
|
@ -2959,7 +2962,13 @@ fn setae_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
|
|||
set_reg64_help(0x93, buf, reg);
|
||||
}
|
||||
|
||||
/// `SETLE r/m64` -> Set byte if less or equal (ZF=1 or SF≠ OF).
|
||||
/// `SETBE r/m64` -> Set byte if below or equal (CF=1 or ZF=1).
|
||||
#[inline(always)]
|
||||
fn setbe_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
|
||||
set_reg64_help(0x96, buf, reg);
|
||||
}
|
||||
|
||||
/// `SETLE r/m64` -> Set byte if less or equal (ZF=1 or SF ≠ OF).
|
||||
#[inline(always)]
|
||||
fn setle_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
|
||||
set_reg64_help(0x9e, buf, reg);
|
||||
|
|
@ -3413,6 +3422,15 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lea_reg64() {
|
||||
disassembler_test!(
|
||||
lea_reg64,
|
||||
|reg| format!("lea {}, [rip]", reg),
|
||||
ALL_GENERAL_REGS
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mov_reg64_reg64() {
|
||||
disassembler_test!(
|
||||
|
|
@ -3764,8 +3782,8 @@ mod tests {
|
|||
cmp_reg64_reg64,
|
||||
|_, dst: X86_64GeneralReg, src: X86_64GeneralReg| format!(
|
||||
"cmp {}, {}",
|
||||
dbg!(dst.low_16bits_string()),
|
||||
dbg!(src.low_16bits_string())
|
||||
dst.low_16bits_string(),
|
||||
src.low_16bits_string()
|
||||
),
|
||||
[RegisterWidth::W16],
|
||||
ALL_GENERAL_REGS,
|
||||
|
|
@ -3776,8 +3794,8 @@ mod tests {
|
|||
cmp_reg64_reg64,
|
||||
|_, dst: X86_64GeneralReg, src: X86_64GeneralReg| format!(
|
||||
"cmp {}, {}",
|
||||
dbg!(dst.low_32bits_string()),
|
||||
dbg!(src.low_32bits_string())
|
||||
dst.low_32bits_string(),
|
||||
src.low_32bits_string()
|
||||
),
|
||||
[RegisterWidth::W32],
|
||||
ALL_GENERAL_REGS,
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ use roc_error_macros::internal_error;
|
|||
use roc_module::ident::ModuleName;
|
||||
use roc_module::low_level::{LowLevel, LowLevelWrapperType};
|
||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||
use roc_mono::code_gen_help::CodeGenHelp;
|
||||
use roc_mono::code_gen_help::{CallerProc, CodeGenHelp};
|
||||
use roc_mono::ir::{
|
||||
BranchInfo, CallType, Expr, JoinPointId, ListLiteralElement, Literal, Param, Proc, ProcLayout,
|
||||
SelfRecursive, Stmt,
|
||||
BranchInfo, CallType, Expr, HigherOrderLowLevel, JoinPointId, ListLiteralElement, Literal,
|
||||
Param, Proc, ProcLayout, SelfRecursive, Stmt,
|
||||
};
|
||||
use roc_mono::layout::{
|
||||
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, TagIdIntType,
|
||||
|
|
@ -65,8 +65,21 @@ pub enum Relocation {
|
|||
trait Backend<'a> {
|
||||
fn env(&self) -> &Env<'a>;
|
||||
fn interns(&self) -> &Interns;
|
||||
fn interns_mut(&mut self) -> &mut Interns;
|
||||
fn interner(&self) -> &STLayoutInterner<'a>;
|
||||
|
||||
fn debug_symbol(&mut self, name: &str) -> Symbol {
|
||||
let module_id = self.env().module_id;
|
||||
let ident_ids = self
|
||||
.interns_mut()
|
||||
.all_ident_ids
|
||||
.get_mut(&module_id)
|
||||
.unwrap();
|
||||
|
||||
let ident_id = ident_ids.add_str(name);
|
||||
Symbol::new(self.env().module_id, ident_id)
|
||||
}
|
||||
|
||||
// This method is suboptimal, but it seems to be the only way to make rust understand
|
||||
// that all of these values can be mutable at the same time. By returning them together,
|
||||
// rust understands that they are part of a single use of mutable self.
|
||||
|
|
@ -77,6 +90,7 @@ trait Backend<'a> {
|
|||
&mut STLayoutInterner<'a>,
|
||||
&mut Interns,
|
||||
&mut CodeGenHelp<'a>,
|
||||
&mut Vec<'a, CallerProc<'a>>,
|
||||
);
|
||||
|
||||
fn function_symbol_to_string<'b, I>(
|
||||
|
|
@ -201,7 +215,7 @@ trait Backend<'a> {
|
|||
// If this layout requires a new RC proc, we get enough info to create a linker symbol
|
||||
// for it. Here we don't create linker symbols at this time, but in Wasm backend, we do.
|
||||
let (rc_stmt, new_specializations) = {
|
||||
let (module_id, layout_interner, interns, rc_proc_gen) =
|
||||
let (module_id, layout_interner, interns, rc_proc_gen, _) =
|
||||
self.module_interns_helpers_mut();
|
||||
let ident_ids = interns.all_ident_ids.get_mut(&module_id).unwrap();
|
||||
|
||||
|
|
@ -329,7 +343,7 @@ trait Backend<'a> {
|
|||
arg_layouts,
|
||||
ret_layout,
|
||||
);
|
||||
} else if sym.is_builtin() {
|
||||
} else if func_sym.name().is_builtin() {
|
||||
// These builtins can be built through `build_fn_call` as well, but the
|
||||
// implementation in `build_builtin` inlines some of the symbols.
|
||||
return self.build_builtin(
|
||||
|
|
@ -373,6 +387,9 @@ trait Backend<'a> {
|
|||
layout,
|
||||
)
|
||||
}
|
||||
CallType::HigherOrder(higher_order) => {
|
||||
self.build_higher_order_lowlevel(sym, higher_order, *layout)
|
||||
}
|
||||
x => todo!("the call type, {:?}", x),
|
||||
}
|
||||
}
|
||||
|
|
@ -486,6 +503,22 @@ trait Backend<'a> {
|
|||
);
|
||||
self.build_num_add(sym, &args[0], &args[1], ret_layout)
|
||||
}
|
||||
LowLevel::NumAddWrap => {
|
||||
debug_assert_eq!(
|
||||
2,
|
||||
args.len(),
|
||||
"NumAdd: expected to have exactly two argument"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
arg_layouts[0], arg_layouts[1],
|
||||
"NumAdd: expected all arguments of to have the same layout"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
arg_layouts[0], *ret_layout,
|
||||
"NumAdd: expected to have the same argument and return layout"
|
||||
);
|
||||
self.build_num_add(sym, &args[0], &args[1], ret_layout)
|
||||
}
|
||||
LowLevel::NumAddChecked => {
|
||||
self.build_num_add_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout)
|
||||
}
|
||||
|
|
@ -1070,6 +1103,14 @@ trait Backend<'a> {
|
|||
);
|
||||
self.build_ptr_cast(sym, &args[0])
|
||||
}
|
||||
LowLevel::PtrWrite => {
|
||||
let element_layout = match self.interner().get(*ret_layout) {
|
||||
Layout::Boxed(boxed) => boxed,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
self.build_ptr_write(*sym, args[0], args[1], element_layout);
|
||||
}
|
||||
LowLevel::RefCountDec => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::UTILS_DECREF.to_string(),
|
||||
|
|
@ -1084,6 +1125,34 @@ trait Backend<'a> {
|
|||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::NumToStr => {
|
||||
let arg_layout = arg_layouts[0];
|
||||
let intrinsic = match self.interner().get(arg_layout) {
|
||||
Layout::Builtin(Builtin::Int(width)) => &bitcode::STR_FROM_INT[width],
|
||||
Layout::Builtin(Builtin::Float(width)) => &bitcode::STR_FROM_FLOAT[width],
|
||||
Layout::Builtin(Builtin::Decimal) => bitcode::DEC_TO_STR,
|
||||
x => internal_error!("NumToStr is not defined for {:?}", x),
|
||||
};
|
||||
|
||||
self.build_fn_call(sym, intrinsic.to_string(), args, arg_layouts, ret_layout)
|
||||
}
|
||||
LowLevel::StrIsEmpty => {
|
||||
let intrinsic = bitcode::STR_IS_EMPTY.to_string();
|
||||
self.build_fn_call(sym, intrinsic, args, arg_layouts, ret_layout);
|
||||
}
|
||||
LowLevel::NumIntCast => {
|
||||
let source_width = match self.interner().get(arg_layouts[0]) {
|
||||
Layout::Builtin(Builtin::Int(width)) => width,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let target_width = match self.interner().get(*ret_layout) {
|
||||
Layout::Builtin(Builtin::Int(width)) => width,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
self.build_num_int_cast(sym, &args[0], source_width, target_width)
|
||||
}
|
||||
x => todo!("low level, {:?}", x),
|
||||
}
|
||||
}
|
||||
|
|
@ -1133,16 +1202,24 @@ trait Backend<'a> {
|
|||
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
|
||||
}
|
||||
Symbol::BOOL_TRUE => {
|
||||
let bool_layout = Layout::BOOL;
|
||||
self.load_literal(&Symbol::DEV_TMP, &bool_layout, &Literal::Bool(true));
|
||||
self.return_symbol(&Symbol::DEV_TMP, &bool_layout);
|
||||
self.free_symbol(&Symbol::DEV_TMP)
|
||||
const LITERAL: &Literal<'static> = &Literal::Bool(true);
|
||||
const BOOL_LAYOUT: &InLayout<'static> = &Layout::BOOL;
|
||||
|
||||
if self.env().lazy_literals {
|
||||
self.literal_map().insert(*sym, (LITERAL, BOOL_LAYOUT));
|
||||
} else {
|
||||
self.load_literal(sym, BOOL_LAYOUT, LITERAL);
|
||||
}
|
||||
}
|
||||
Symbol::BOOL_FALSE => {
|
||||
let bool_layout = Layout::BOOL;
|
||||
self.load_literal(&Symbol::DEV_TMP, &bool_layout, &Literal::Bool(false));
|
||||
self.return_symbol(&Symbol::DEV_TMP, &bool_layout);
|
||||
self.free_symbol(&Symbol::DEV_TMP)
|
||||
const LITERAL: &Literal<'static> = &Literal::Bool(false);
|
||||
const BOOL_LAYOUT: &InLayout<'static> = &Layout::BOOL;
|
||||
|
||||
if self.env().lazy_literals {
|
||||
self.literal_map().insert(*sym, (LITERAL, BOOL_LAYOUT));
|
||||
} else {
|
||||
self.load_literal(sym, BOOL_LAYOUT, LITERAL);
|
||||
}
|
||||
}
|
||||
Symbol::STR_IS_VALID_SCALAR => {
|
||||
// just call the function
|
||||
|
|
@ -1184,9 +1261,20 @@ trait Backend<'a> {
|
|||
ret_layout: &InLayout<'a>,
|
||||
);
|
||||
|
||||
fn build_fn_pointer(&mut self, dst: &Symbol, fn_name: String);
|
||||
|
||||
/// Move a returned value into `dst`
|
||||
fn move_return_value(&mut self, dst: &Symbol, ret_layout: &InLayout<'a>);
|
||||
|
||||
/// build_num_abs stores the absolute value of src into dst.
|
||||
fn build_num_int_cast(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src: &Symbol,
|
||||
source: IntWidth,
|
||||
target: IntWidth,
|
||||
);
|
||||
|
||||
/// build_num_abs stores the absolute value of src into dst.
|
||||
fn build_num_abs(&mut self, dst: &Symbol, src: &Symbol, layout: &InLayout<'a>);
|
||||
|
||||
|
|
@ -1348,6 +1436,14 @@ trait Backend<'a> {
|
|||
/// build_list_len returns the length of a list.
|
||||
fn build_list_len(&mut self, dst: &Symbol, list: &Symbol);
|
||||
|
||||
/// generate a call to a higher-order lowlevel
|
||||
fn build_higher_order_lowlevel(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
holl: &HigherOrderLowLevel<'a>,
|
||||
ret_layout: InLayout<'a>,
|
||||
);
|
||||
|
||||
/// build_list_with_capacity creates and returns a list with the given capacity.
|
||||
fn build_list_with_capacity(
|
||||
&mut self,
|
||||
|
|
@ -1416,6 +1512,14 @@ trait Backend<'a> {
|
|||
/// build_refcount_getptr loads the pointer to the reference count of src into dst.
|
||||
fn build_ptr_cast(&mut self, dst: &Symbol, src: &Symbol);
|
||||
|
||||
fn build_ptr_write(
|
||||
&mut self,
|
||||
sym: Symbol,
|
||||
ptr: Symbol,
|
||||
value: Symbol,
|
||||
element_layout: InLayout<'a>,
|
||||
);
|
||||
|
||||
/// literal_map gets the map from symbol to literal and layout, used for lazy loading and literal folding.
|
||||
fn literal_map(&mut self) -> &mut MutMap<Symbol, (*const Literal<'a>, *const InLayout<'a>)>;
|
||||
|
||||
|
|
|
|||
|
|
@ -246,10 +246,16 @@ fn build_object<'a, B: Backend<'a>>(
|
|||
|
||||
// Generate IR for specialized helper procs (refcounting & equality)
|
||||
let helper_procs = {
|
||||
let (module_id, _interner, interns, helper_proc_gen) = backend.module_interns_helpers_mut();
|
||||
let (module_id, _interner, interns, helper_proc_gen, caller_procs) =
|
||||
backend.module_interns_helpers_mut();
|
||||
|
||||
let mut owned_caller_procs = bumpalo::collections::Vec::new_in(arena);
|
||||
std::mem::swap(caller_procs, &mut owned_caller_procs);
|
||||
|
||||
let ident_ids = interns.all_ident_ids.get_mut(&module_id).unwrap();
|
||||
let helper_procs = helper_proc_gen.take_procs();
|
||||
let mut helper_procs = helper_proc_gen.take_procs();
|
||||
|
||||
helper_procs.extend(owned_caller_procs.into_iter().map(|cp| cp.proc));
|
||||
module_id.register_debug_idents(ident_ids);
|
||||
|
||||
helper_procs
|
||||
|
|
|
|||
|
|
@ -1247,7 +1247,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
unreachable!("The {:?} operation is turned into mono Expr", op)
|
||||
}
|
||||
|
||||
PtrCast | RefCountInc | RefCountDec => {
|
||||
PtrCast | PtrWrite | RefCountInc | RefCountDec => {
|
||||
unreachable!("Not used in LLVM backend: {:?}", op);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -885,7 +885,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
self.code_builder.f32_eq();
|
||||
}
|
||||
ValueType::F64 => {
|
||||
self.code_builder.f64_const(f64::from_bits(*value as u64));
|
||||
self.code_builder.f64_const(f64::from_bits(*value));
|
||||
self.code_builder.f64_eq();
|
||||
}
|
||||
}
|
||||
|
|
@ -1114,7 +1114,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> {
|
|||
match storage {
|
||||
StoredValue::VirtualMachineStack { value_type, .. } => {
|
||||
match (lit, value_type) {
|
||||
(Literal::Float(x), ValueType::F64) => self.code_builder.f64_const(*x as f64),
|
||||
(Literal::Float(x), ValueType::F64) => self.code_builder.f64_const(*x),
|
||||
(Literal::Float(x), ValueType::F32) => self.code_builder.f32_const(*x as f32),
|
||||
(Literal::Int(x), ValueType::I64) => {
|
||||
self.code_builder.i64_const(i128::from_ne_bytes(*x) as i64)
|
||||
|
|
|
|||
|
|
@ -506,7 +506,7 @@ impl<'a> CodeBuilder<'a> {
|
|||
stack_size
|
||||
);
|
||||
|
||||
let new_len = stack_size - pops as usize;
|
||||
let new_len = stack_size - pops;
|
||||
current_stack.truncate(new_len);
|
||||
if push {
|
||||
current_stack.push(Symbol::WASM_TMP);
|
||||
|
|
|
|||
|
|
@ -1956,6 +1956,8 @@ impl<'a> LowLevelCall<'a> {
|
|||
backend.storage.load_symbols(code_builder, self.arguments);
|
||||
}
|
||||
|
||||
PtrWrite => todo!("{:?}", self.lowlevel),
|
||||
|
||||
Hash => todo!("{:?}", self.lowlevel),
|
||||
|
||||
Eq | NotEq => self.eq_or_neq(backend),
|
||||
|
|
|
|||
|
|
@ -2347,8 +2347,8 @@ macro_rules! debug_check_ir {
|
|||
}
|
||||
|
||||
/// Report modules that are imported, but from which nothing is used
|
||||
fn report_unused_imported_modules<'a>(
|
||||
state: &mut State<'a>,
|
||||
fn report_unused_imported_modules(
|
||||
state: &mut State<'_>,
|
||||
module_id: ModuleId,
|
||||
constrained_module: &ConstrainedModule,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ pub enum LowLevel {
|
|||
Not,
|
||||
Hash,
|
||||
PtrCast,
|
||||
PtrWrite,
|
||||
RefCountInc,
|
||||
RefCountDec,
|
||||
RefCountIsUnique,
|
||||
|
|
@ -220,6 +221,7 @@ macro_rules! map_symbol_to_lowlevel {
|
|||
// these are used internally and not tied to a symbol
|
||||
LowLevel::Hash => unimplemented!(),
|
||||
LowLevel::PtrCast => unimplemented!(),
|
||||
LowLevel::PtrWrite => unimplemented!(),
|
||||
LowLevel::RefCountInc => unimplemented!(),
|
||||
LowLevel::RefCountDec => unimplemented!(),
|
||||
LowLevel::RefCountIsUnique => unimplemented!(),
|
||||
|
|
|
|||
|
|
@ -1253,6 +1253,7 @@ define_builtins! {
|
|||
152 NUM_COUNT_LEADING_ZERO_BITS: "countLeadingZeroBits"
|
||||
153 NUM_COUNT_TRAILING_ZERO_BITS: "countTrailingZeroBits"
|
||||
154 NUM_COUNT_ONE_BITS: "countOneBits"
|
||||
155 NUM_ABS_DIFF: "absDiff"
|
||||
}
|
||||
4 BOOL: "Bool" => {
|
||||
0 BOOL_BOOL: "Bool" exposed_type=true // the Bool.Bool type alias
|
||||
|
|
|
|||
|
|
@ -1031,7 +1031,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[Ownership] {
|
|||
unreachable!("These lowlevel operations are turned into mono Expr's")
|
||||
}
|
||||
|
||||
PtrCast | RefCountInc | RefCountDec | RefCountIsUnique => {
|
||||
PtrCast | PtrWrite | RefCountInc | RefCountDec | RefCountIsUnique => {
|
||||
unreachable!("Only inserted *after* borrow checking: {:?}", op);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
|||
use roc_target::TargetInfo;
|
||||
|
||||
use crate::ir::{
|
||||
Call, CallSpecId, CallType, Expr, HostExposedLayouts, JoinPointId, ModifyRc, Proc, ProcLayout,
|
||||
SelfRecursive, Stmt, UpdateModeId,
|
||||
Call, CallSpecId, CallType, Expr, HostExposedLayouts, JoinPointId, ModifyRc, PassedFunction,
|
||||
Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId,
|
||||
};
|
||||
use crate::layout::{
|
||||
Builtin, InLayout, LambdaName, Layout, LayoutInterner, Niche, STLayoutInterner, UnionLayout,
|
||||
|
|
@ -21,6 +21,7 @@ const LAYOUT_UNIT: InLayout = Layout::UNIT;
|
|||
|
||||
const ARG_1: Symbol = Symbol::ARG_1;
|
||||
const ARG_2: Symbol = Symbol::ARG_2;
|
||||
const ARG_3: Symbol = Symbol::ARG_3;
|
||||
|
||||
/// "Infinite" reference count, for static values
|
||||
/// Ref counts are encoded as negative numbers where isize::MIN represents 1
|
||||
|
|
@ -584,6 +585,175 @@ impl<'a> CodeGenHelp<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct CallerProc<'a> {
|
||||
pub proc_symbol: Symbol,
|
||||
pub proc_layout: ProcLayout<'a>,
|
||||
pub proc: Proc<'a>,
|
||||
}
|
||||
|
||||
impl<'a> CallerProc<'a> {
|
||||
fn create_symbol(home: ModuleId, ident_ids: &mut IdentIds, debug_name: &str) -> Symbol {
|
||||
let ident_id = ident_ids.add_str(debug_name);
|
||||
Symbol::new(home, ident_id)
|
||||
}
|
||||
|
||||
fn create_caller_proc_symbol(
|
||||
home: ModuleId,
|
||||
ident_ids: &mut IdentIds,
|
||||
operation: &str,
|
||||
wrapped_function: Symbol,
|
||||
) -> Symbol {
|
||||
let debug_name = format!("#help_{}_{}_{:?}", "caller", operation, wrapped_function,);
|
||||
|
||||
Self::create_symbol(home, ident_ids, &debug_name)
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
arena: &'a Bump,
|
||||
home: ModuleId,
|
||||
ident_ids: &mut IdentIds,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
passed_function: &PassedFunction<'a>,
|
||||
capture_layout: Option<InLayout<'a>>,
|
||||
) -> Self {
|
||||
let mut ctx = Context {
|
||||
new_linker_data: Vec::new_in(arena),
|
||||
recursive_union: None,
|
||||
op: HelperOp::Eq,
|
||||
};
|
||||
|
||||
let box_capture_layout = if let Some(capture_layout) = capture_layout {
|
||||
layout_interner.insert(Layout::Boxed(capture_layout))
|
||||
} else {
|
||||
layout_interner.insert(Layout::Boxed(Layout::UNIT))
|
||||
};
|
||||
|
||||
let box_argument_layout =
|
||||
layout_interner.insert(Layout::Boxed(passed_function.argument_layouts[0]));
|
||||
|
||||
let box_return_layout =
|
||||
layout_interner.insert(Layout::Boxed(passed_function.return_layout));
|
||||
|
||||
let proc_layout = ProcLayout {
|
||||
arguments: arena.alloc([box_capture_layout, box_argument_layout, box_return_layout]),
|
||||
result: Layout::UNIT,
|
||||
niche: Niche::NONE,
|
||||
};
|
||||
|
||||
let proc_symbol =
|
||||
Self::create_caller_proc_symbol(home, ident_ids, "map", passed_function.name.name());
|
||||
|
||||
ctx.new_linker_data.push((proc_symbol, proc_layout));
|
||||
|
||||
let unbox_capture = Expr::ExprUnbox {
|
||||
symbol: Symbol::ARG_1,
|
||||
};
|
||||
|
||||
let unbox_argument = Expr::ExprUnbox {
|
||||
symbol: Symbol::ARG_2,
|
||||
};
|
||||
|
||||
let unboxed_capture = Self::create_symbol(home, ident_ids, "unboxed_capture");
|
||||
let unboxed_argument = Self::create_symbol(home, ident_ids, "unboxed_argument");
|
||||
let call_result = Self::create_symbol(home, ident_ids, "call_result");
|
||||
let unit_symbol = Self::create_symbol(home, ident_ids, "unit_symbol");
|
||||
let ignored = Self::create_symbol(home, ident_ids, "ignored");
|
||||
|
||||
let call = Expr::Call(Call {
|
||||
call_type: CallType::ByName {
|
||||
name: passed_function.name,
|
||||
ret_layout: passed_function.return_layout,
|
||||
arg_layouts: passed_function.argument_layouts,
|
||||
specialization_id: passed_function.specialization_id,
|
||||
},
|
||||
arguments: if capture_layout.is_some() {
|
||||
arena.alloc([unboxed_argument, unboxed_capture])
|
||||
} else {
|
||||
arena.alloc([unboxed_argument])
|
||||
},
|
||||
});
|
||||
|
||||
let ptr_write = Expr::Call(Call {
|
||||
call_type: CallType::LowLevel {
|
||||
op: LowLevel::PtrWrite,
|
||||
update_mode: UpdateModeId::BACKEND_DUMMY,
|
||||
},
|
||||
arguments: arena.alloc([Symbol::ARG_3, call_result]),
|
||||
});
|
||||
|
||||
let mut body = Stmt::Let(
|
||||
unboxed_argument,
|
||||
unbox_argument,
|
||||
passed_function.argument_layouts[0],
|
||||
arena.alloc(Stmt::Let(
|
||||
call_result,
|
||||
call,
|
||||
passed_function.return_layout,
|
||||
arena.alloc(Stmt::Let(
|
||||
ignored,
|
||||
ptr_write,
|
||||
box_return_layout,
|
||||
arena.alloc(Stmt::Let(
|
||||
unit_symbol,
|
||||
Expr::Struct(&[]),
|
||||
Layout::UNIT,
|
||||
arena.alloc(Stmt::Ret(unit_symbol)),
|
||||
)),
|
||||
)),
|
||||
)),
|
||||
);
|
||||
|
||||
if let Some(capture_layout) = capture_layout {
|
||||
body = Stmt::Let(
|
||||
unboxed_capture,
|
||||
unbox_capture,
|
||||
capture_layout,
|
||||
arena.alloc(body),
|
||||
);
|
||||
}
|
||||
|
||||
let args: &'a [(InLayout<'a>, Symbol)] = {
|
||||
arena.alloc([
|
||||
(box_capture_layout, ARG_1),
|
||||
(box_argument_layout, ARG_2),
|
||||
(box_return_layout, ARG_3),
|
||||
])
|
||||
};
|
||||
|
||||
let proc = Proc {
|
||||
name: LambdaName::no_niche(proc_symbol),
|
||||
args,
|
||||
body,
|
||||
closure_data_layout: None,
|
||||
ret_layout: Layout::UNIT,
|
||||
is_self_recursive: SelfRecursive::NotSelfRecursive,
|
||||
host_exposed_layouts: HostExposedLayouts::NotHostExposed,
|
||||
};
|
||||
|
||||
if false {
|
||||
let allocator = ven_pretty::BoxAllocator;
|
||||
let doc = proc
|
||||
.to_doc::<_, (), _>(
|
||||
&allocator,
|
||||
layout_interner,
|
||||
true,
|
||||
crate::ir::Parens::NotNeeded,
|
||||
)
|
||||
.1
|
||||
.pretty(80)
|
||||
.to_string();
|
||||
|
||||
println!("{}", doc);
|
||||
}
|
||||
|
||||
Self {
|
||||
proc_symbol,
|
||||
proc_layout,
|
||||
proc,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn let_lowlevel<'a>(
|
||||
arena: &'a Bump,
|
||||
result_layout: InLayout<'a>,
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ use crate::{
|
|||
/**
|
||||
Insert the reference count operations for procedures.
|
||||
*/
|
||||
pub fn insert_inc_dec_operations<'a, 'i>(
|
||||
pub fn insert_inc_dec_operations<'a>(
|
||||
arena: &'a Bump,
|
||||
layout_interner: &'i STLayoutInterner<'a>,
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
procedures: &mut HashMap<(Symbol, ProcLayout), Proc<'a>, BuildHasherDefault<WyHash>>,
|
||||
) {
|
||||
// Create a SymbolRcTypesEnv for the procedures as they get referenced but should be marked as non reference counted.
|
||||
|
|
@ -401,9 +401,9 @@ impl<'v> RefcountEnvironment<'v> {
|
|||
/**
|
||||
Insert the reference counting operations into a statement.
|
||||
*/
|
||||
fn insert_inc_dec_operations_proc<'a, 'i>(
|
||||
fn insert_inc_dec_operations_proc<'a>(
|
||||
arena: &'a Bump,
|
||||
mut symbol_rc_types_env: SymbolRcTypesEnv<'a, 'i>,
|
||||
mut symbol_rc_types_env: SymbolRcTypesEnv<'a, '_>,
|
||||
proc: &mut Proc<'a>,
|
||||
) {
|
||||
// Clone the symbol_rc_types_env and insert the symbols in the current procedure.
|
||||
|
|
|
|||
|
|
@ -282,8 +282,9 @@ impl AbilityAliases {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
|
||||
pub enum CapturedSymbols<'a> {
|
||||
#[default]
|
||||
None,
|
||||
Captured(&'a [(Symbol, Variable)]),
|
||||
}
|
||||
|
|
@ -297,12 +298,6 @@ impl<'a> CapturedSymbols<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Default for CapturedSymbols<'a> {
|
||||
fn default() -> Self {
|
||||
CapturedSymbols::None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Proc<'a> {
|
||||
pub name: LambdaName<'a>,
|
||||
|
|
@ -2725,8 +2720,8 @@ fn patterns_to_when<'a>(
|
|||
/// { x } -> body
|
||||
///
|
||||
/// conversion of one-pattern when expressions will do the most optimal thing
|
||||
fn pattern_to_when<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
fn pattern_to_when(
|
||||
env: &mut Env<'_, '_>,
|
||||
pattern_var: Variable,
|
||||
pattern: Loc<roc_can::pattern::Pattern>,
|
||||
body_var: Variable,
|
||||
|
|
@ -5743,8 +5738,8 @@ fn compile_struct_like<'a, L, UnusedLayout>(
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn late_resolve_ability_specialization<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
fn late_resolve_ability_specialization(
|
||||
env: &mut Env<'_, '_>,
|
||||
member: Symbol,
|
||||
specialization_id: Option<SpecializationId>,
|
||||
specialization_var: Variable,
|
||||
|
|
|
|||
|
|
@ -1193,7 +1193,7 @@ fn extract<'a>(
|
|||
|
||||
/// FIND IRRELEVANT BRANCHES
|
||||
|
||||
fn is_irrelevant_to<'a>(selected_path: &[PathInstruction], branch: &Branch<'a>) -> bool {
|
||||
fn is_irrelevant_to(selected_path: &[PathInstruction], branch: &Branch<'_>) -> bool {
|
||||
match branch
|
||||
.patterns
|
||||
.iter()
|
||||
|
|
@ -1720,7 +1720,7 @@ fn test_to_comparison<'a>(
|
|||
|
||||
Test::IsFloat(test_int, precision) => {
|
||||
// TODO maybe we can actually use i64 comparison here?
|
||||
let test_float = f64::from_bits(test_int as u64);
|
||||
let test_float = f64::from_bits(test_int);
|
||||
let lhs = Expr::Literal(Literal::Float(test_float));
|
||||
let lhs_symbol = env.unique_symbol();
|
||||
stores.push((lhs_symbol, Layout::float_width(precision), lhs));
|
||||
|
|
@ -2240,7 +2240,7 @@ fn decide_to_branching<'a>(
|
|||
|
||||
let tag = match test {
|
||||
Test::IsInt(v, _) => i128::from_ne_bytes(v) as u64,
|
||||
Test::IsFloat(v, _) => v as u64,
|
||||
Test::IsFloat(v, _) => v,
|
||||
Test::IsBit(v) => v as u64,
|
||||
Test::IsByte { tag_id, .. } => tag_id as u64,
|
||||
Test::IsCtor { tag_id, .. } => tag_id as u64,
|
||||
|
|
|
|||
|
|
@ -457,7 +457,7 @@ macro_rules! cached {
|
|||
}
|
||||
|
||||
pub type TagIdIntType = u16;
|
||||
pub const MAX_ENUM_SIZE: usize = (std::mem::size_of::<TagIdIntType>() * 8) as usize;
|
||||
pub const MAX_ENUM_SIZE: usize = std::mem::size_of::<TagIdIntType>() * 8;
|
||||
const GENERATE_NULLABLE: bool = true;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
|
@ -898,7 +898,7 @@ impl<'a> UnionLayout<'a> {
|
|||
} => {
|
||||
debug_assert_ne!(nullable_id, tag_id != 0);
|
||||
|
||||
other_fields[index as usize]
|
||||
other_fields[index]
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ macro_rules! cache_interned_layouts {
|
|||
)*
|
||||
}
|
||||
|
||||
fn fill_reserved_layouts<'a>(interner: &mut STLayoutInterner<'a>) {
|
||||
fn fill_reserved_layouts(interner: &mut STLayoutInterner<'_>) {
|
||||
assert!(interner.is_empty());
|
||||
$(
|
||||
interner.insert($layout);
|
||||
|
|
@ -433,6 +433,22 @@ impl<'a> InLayout<'a> {
|
|||
pub fn index(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn try_int_width(self) -> Option<IntWidth> {
|
||||
match self {
|
||||
Layout::U8 => Some(IntWidth::U8),
|
||||
Layout::U16 => Some(IntWidth::U16),
|
||||
Layout::U32 => Some(IntWidth::U32),
|
||||
Layout::U64 => Some(IntWidth::U64),
|
||||
Layout::U128 => Some(IntWidth::U128),
|
||||
Layout::I8 => Some(IntWidth::I8),
|
||||
Layout::I16 => Some(IntWidth::I16),
|
||||
Layout::I32 => Some(IntWidth::I32),
|
||||
Layout::I64 => Some(IntWidth::I64),
|
||||
Layout::I128 => Some(IntWidth::I128),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A concurrent interner, suitable for usage between threads.
|
||||
|
|
|
|||
|
|
@ -1128,8 +1128,8 @@ impl<'a> ReuseEnvironment<'a> {
|
|||
/**
|
||||
Check if a layout can be reused. by verifying if the layout is a union and if the tag is not nullable.
|
||||
*/
|
||||
fn can_reuse_layout<'a, 'i>(
|
||||
layout_interner: &'i STLayoutInterner<'a>,
|
||||
fn can_reuse_layout<'a>(
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
environment: &ReuseEnvironment<'a>,
|
||||
layout: &InLayout<'a>,
|
||||
) -> Reuse {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ version.workspace = true
|
|||
roc_collections = { path = "../collections" }
|
||||
roc_module = { path = "../module" }
|
||||
roc_region = { path = "../region" }
|
||||
roc_error_macros = { path = "../../error_macros" }
|
||||
|
||||
bumpalo.workspace = true
|
||||
encode_unicode.workspace = true
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ use crate::type_annotation;
|
|||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_collections::soa::Slice;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::called_via::{BinOp, CalledVia, UnaryOp};
|
||||
use roc_region::all::{Loc, Position, Region};
|
||||
|
||||
|
|
@ -2479,10 +2480,10 @@ fn ident_to_expr<'a>(arena: &'a Bump, src: Ident<'a>) -> Expr<'a> {
|
|||
// TODO: make this state impossible to represent in Ident::Access,
|
||||
// by splitting out parts[0] into a separate field with a type of `&'a str`,
|
||||
// rather than a `&'a [Accessor<'a>]`.
|
||||
panic!("Parsed an Ident::Access with a first part of a tuple index");
|
||||
internal_error!("Parsed an Ident::Access with a first part of a tuple index");
|
||||
}
|
||||
None => {
|
||||
panic!("Parsed an Ident::Access with no parts");
|
||||
internal_error!("Parsed an Ident::Access with no parts");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -105,14 +105,14 @@ impl Position {
|
|||
#[must_use]
|
||||
pub const fn bump_column(self, count: u32) -> Self {
|
||||
Self {
|
||||
offset: self.offset + count as u32,
|
||||
offset: self.offset + count,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn bump_invisible(self, count: u32) -> Self {
|
||||
Self {
|
||||
offset: self.offset + count as u32,
|
||||
offset: self.offset + count,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ impl Position {
|
|||
#[must_use]
|
||||
pub const fn sub(self, count: u32) -> Self {
|
||||
Self {
|
||||
offset: self.offset - count as u32,
|
||||
offset: self.offset - count,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -376,7 +376,7 @@ impl LineInfo {
|
|||
let column = offset - self.line_offsets[line];
|
||||
LineColumn {
|
||||
line: line as u32,
|
||||
column: column as u32,
|
||||
column,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2537,14 +2537,14 @@ enum TypeToVar {
|
|||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn type_to_variable<'a>(
|
||||
fn type_to_variable(
|
||||
subs: &mut Subs,
|
||||
rank: Rank,
|
||||
pools: &mut Pools,
|
||||
problems: &mut Vec<TypeError>,
|
||||
abilities_store: &AbilitiesStore,
|
||||
obligation_cache: &mut ObligationCache,
|
||||
arena: &'a bumpalo::Bump,
|
||||
arena: &bumpalo::Bump,
|
||||
aliases: &mut Aliases,
|
||||
types: &mut Types,
|
||||
typ: Index<TypeTag>,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1200,7 +1200,7 @@ fn list_count_if_str() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_on_empty_list_with_int_layout() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
@ -1218,7 +1218,7 @@ fn list_map_on_empty_list_with_int_layout() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_on_non_empty_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
@ -1236,7 +1236,7 @@ fn list_map_on_non_empty_list() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_changes_input() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
@ -1254,7 +1254,7 @@ fn list_map_changes_input() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_on_big_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
@ -1274,7 +1274,7 @@ fn list_map_on_big_list() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_with_type_change() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
@ -1293,7 +1293,7 @@ fn list_map_with_type_change() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_using_defined_function() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
@ -1315,7 +1315,7 @@ fn list_map_using_defined_function() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_all_inline() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
@ -1328,9 +1328,30 @@ fn list_map_all_inline() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_closure_int() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
int : I64
|
||||
int = 123
|
||||
|
||||
single : List I64
|
||||
single =
|
||||
[0]
|
||||
|
||||
List.map single (\x -> x + int)
|
||||
"#
|
||||
),
|
||||
RocList::from_slice(&[123]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn list_map_closure() {
|
||||
fn list_map_closure_float() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
|
|
@ -2926,7 +2947,7 @@ fn list_any_empty_with_unknown_element_type() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_all() {
|
||||
assert_evals_to!("List.all [] (\\e -> e > 3)", true, bool);
|
||||
assert_evals_to!("List.all [1, 2, 3] (\\e -> e > 3)", false, bool);
|
||||
|
|
|
|||
|
|
@ -3113,7 +3113,7 @@ fn when_on_i16() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn num_to_str() {
|
||||
use roc_std::RocStr;
|
||||
|
||||
|
|
@ -3998,3 +3998,84 @@ fn num_count_one_bits() {
|
|||
assert_evals_to!(r#"Num.countOneBits 0u32"#, 0, usize);
|
||||
assert_evals_to!(r#"Num.countOneBits 0b0010_1111u64"#, 5, usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn num_abs_diff_int() {
|
||||
assert_evals_to!(r#"Num.absDiff 0u8 0u8"#, 0, u8);
|
||||
assert_evals_to!(r#"Num.absDiff 1u8 2u8"#, 1, u8);
|
||||
assert_evals_to!(r#"Num.absDiff 2u8 1u8"#, 1, u8);
|
||||
assert_evals_to!(r#"Num.absDiff -1 1"#, 2, i64);
|
||||
assert_evals_to!(r#"Num.absDiff 1 -1"#, 2, i64);
|
||||
assert_evals_to!(r#"Num.absDiff Num.minI64 -1"#, i64::MAX, i64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
fn num_abs_diff_large_bits() {
|
||||
assert_evals_to!(r#"Num.absDiff 0u128 0u128"#, 0, u128);
|
||||
assert_evals_to!(r#"Num.absDiff 1u128 2u128"#, 1, u128);
|
||||
assert_evals_to!(r#"Num.absDiff -1i128 1i128"#, 2, i128);
|
||||
assert_evals_to!(r#"Num.absDiff Num.minI128 -1i128"#, i128::MAX, i128);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn num_abs_diff_float() {
|
||||
assert_evals_to!(r#"Num.absDiff 0.0 0.0"#, 0.0, f64);
|
||||
assert_evals_to!(r#"Num.absDiff 1.0 2.0"#, 1.0, f64);
|
||||
assert_evals_to!(r#"Num.absDiff 2.0 1.0"#, 1.0, f64);
|
||||
assert_evals_to!(r#"Num.absDiff -1.0 1.0"#, 2.0, f64);
|
||||
assert_evals_to!(r#"Num.absDiff 1.0 -1.0"#, 2.0, f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[should_panic(expected = r#"Roc failed with message: "integer subtraction overflowed!"#)]
|
||||
fn num_abs_max_overflow() {
|
||||
assert_evals_to!(r#"Num.absDiff Num.maxI64 -1"#, 0, i64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[should_panic(expected = r#"Roc failed with message: "integer subtraction overflowed!"#)]
|
||||
fn num_abs_int_min_overflow() {
|
||||
assert_evals_to!(r#"Num.absDiff Num.minI64 0"#, 0, i64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[should_panic(expected = r#"Roc failed with message: "integer subtraction overflowed!"#)]
|
||||
fn num_abs_large_bits_min_overflow() {
|
||||
assert_evals_to!(r#"Num.absDiff Num.minI128 0"#, 0, i128);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn num_abs_float_overflow() {
|
||||
assert_evals_to!("Num.absDiff Num.maxF64 Num.minF64", f64::INFINITY, f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
|
||||
fn bool_in_switch() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
app "test" provides [main] to "./platform"
|
||||
|
||||
loop : [ Continue {}, Break {} ]
|
||||
loop = Continue {}
|
||||
|
||||
all = \{} ->
|
||||
when loop is
|
||||
Continue {} -> Bool.true
|
||||
Break {} -> Bool.false
|
||||
|
||||
main = all {}
|
||||
"#
|
||||
),
|
||||
true,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -497,23 +497,23 @@ fn str_concat_empty() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn small_str_is_empty() {
|
||||
assert_evals_to!(r#"Str.isEmpty "abc""#, false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn big_str_is_empty() {
|
||||
assert_evals_to!(
|
||||
r#"Str.isEmpty "this is more than 15 chars long""#,
|
||||
r#"Str.isEmpty "this is more than 23 chars long""#,
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn empty_str_is_empty() {
|
||||
assert_evals_to!(r#"Str.isEmpty """#, true, bool);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -907,7 +907,9 @@ fn alignment_in_multi_tag_pattern_match() {
|
|||
{ bool, int }
|
||||
|
||||
Empty ->
|
||||
{ bool: Bool.false, int: 0 }
|
||||
# dev backend codegen bug means we cannot use this inline
|
||||
false = Bool.false
|
||||
{ bool: false, int: 0 }
|
||||
#"
|
||||
),
|
||||
(32i64, true),
|
||||
|
|
@ -924,7 +926,8 @@ fn alignment_in_multi_tag_pattern_match() {
|
|||
Three bool color int ->
|
||||
{ bool, color, int }
|
||||
Empty ->
|
||||
{ bool: Bool.false, color: Red, int: 0 }
|
||||
false = Bool.false
|
||||
{ bool: false, color: Red, int: 0 }
|
||||
#"
|
||||
),
|
||||
(32i64, true, 2u8),
|
||||
|
|
|
|||
|
|
@ -86,16 +86,16 @@ procedure List.92 (List.430, List.431, List.432):
|
|||
ret List.515;
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.277 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.277;
|
||||
let Num.280 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.280;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.278 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
let Num.281 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.281;
|
||||
|
||||
procedure Num.77 (#Attr.2, #Attr.3):
|
||||
let Num.276 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3;
|
||||
ret Num.276;
|
||||
let Num.279 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3;
|
||||
ret Num.279;
|
||||
|
||||
procedure Test.1 (Test.2):
|
||||
let Test.13 : U64 = 0i64;
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ procedure List.9 (List.287):
|
|||
ret List.496;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Result.5 (Result.12, Result.13):
|
||||
let Result.39 : U8 = 1i64;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.276 : I128 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.276;
|
||||
let Num.279 : I128 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.279;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.6 : I128 = 18446744073709551616i64;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : U128 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : U128 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.2 : U128 = 170141183460469231731687303715884105728u128;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.2 : U64 = 9999999999999999999i64;
|
||||
|
|
|
|||
|
|
@ -40,12 +40,12 @@ procedure List.92 (List.430, List.431, List.432):
|
|||
ret List.497;
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.276 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.276;
|
||||
let Num.279 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.279;
|
||||
|
||||
procedure Str.3 (#Attr.2, #Attr.3):
|
||||
let Str.300 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
|
||||
|
|
|
|||
|
|
@ -79,12 +79,12 @@ procedure List.82 (List.526, List.527, List.528):
|
|||
jump List.508 List.526 List.527 List.528;
|
||||
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.276 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.276;
|
||||
let Num.279 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.279;
|
||||
|
||||
procedure Num.24 (#Attr.2, #Attr.3):
|
||||
let Num.278 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
let Num.281 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.281;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.3 : {} = Struct {};
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ procedure List.66 (#Attr.2, #Attr.3):
|
|||
ret List.499;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.2 (Test.5):
|
||||
dec Test.5;
|
||||
|
|
|
|||
|
|
@ -285,24 +285,24 @@ procedure List.92 (List.430, List.431, List.432):
|
|||
ret List.592;
|
||||
|
||||
procedure Num.127 (#Attr.2):
|
||||
let Num.301 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.301;
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.304 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
let Num.304 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.304;
|
||||
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.302 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.302;
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.307 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.307;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.305 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.305 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.305;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.308 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.308;
|
||||
|
||||
procedure Num.24 (#Attr.2, #Attr.3):
|
||||
let Num.303 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.303;
|
||||
let Num.306 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.306;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.315 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
|
|
|
|||
|
|
@ -169,24 +169,24 @@ procedure List.92 (List.430, List.431, List.432):
|
|||
ret List.525;
|
||||
|
||||
procedure Num.127 (#Attr.2):
|
||||
let Num.282 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.282;
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.285 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
let Num.285 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.285;
|
||||
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.283 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.283;
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.288 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.288;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.286 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.286 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.286;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.289 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.289;
|
||||
|
||||
procedure Num.24 (#Attr.2, #Attr.3):
|
||||
let Num.284 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.284;
|
||||
let Num.287 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.287;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.313 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
|
|
|
|||
|
|
@ -176,24 +176,24 @@ procedure List.92 (List.430, List.431, List.432):
|
|||
ret List.525;
|
||||
|
||||
procedure Num.127 (#Attr.2):
|
||||
let Num.282 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.282;
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.285 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
let Num.285 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.285;
|
||||
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.283 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.283;
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.288 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.288;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.286 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.286 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.286;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.289 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.289;
|
||||
|
||||
procedure Num.24 (#Attr.2, #Attr.3):
|
||||
let Num.284 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.284;
|
||||
let Num.287 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.287;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.313 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ procedure List.8 (#Attr.2, #Attr.3):
|
|||
ret List.504;
|
||||
|
||||
procedure Num.127 (#Attr.2):
|
||||
let Num.276 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.276;
|
||||
let Num.279 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.279;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.312 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
|
|
|
|||
|
|
@ -178,24 +178,24 @@ procedure List.92 (List.430, List.431, List.432):
|
|||
ret List.531;
|
||||
|
||||
procedure Num.127 (#Attr.2):
|
||||
let Num.284 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.284;
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.287 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
let Num.287 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.287;
|
||||
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.285 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.285;
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.290 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.290;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.288 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.288 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.288;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.291 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.291;
|
||||
|
||||
procedure Num.24 (#Attr.2, #Attr.3):
|
||||
let Num.286 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.286;
|
||||
let Num.289 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.289;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.313 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
|
|
|
|||
|
|
@ -181,24 +181,24 @@ procedure List.92 (List.430, List.431, List.432):
|
|||
ret List.531;
|
||||
|
||||
procedure Num.127 (#Attr.2):
|
||||
let Num.284 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.284;
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.287 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
let Num.287 : U8 = lowlevel NumIntCast #Attr.2;
|
||||
ret Num.287;
|
||||
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.285 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.285;
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.290 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.290;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.288 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.288 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.288;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.291 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.291;
|
||||
|
||||
procedure Num.24 (#Attr.2, #Attr.3):
|
||||
let Num.286 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.286;
|
||||
let Num.289 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.289;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.313 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.276 : I64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.276;
|
||||
let Num.279 : I64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.279;
|
||||
|
||||
procedure Num.21 (#Attr.2, #Attr.3):
|
||||
let Num.275 : I64 = lowlevel NumMul #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : I64 = lowlevel NumMul #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.1 (Test.15, Test.16):
|
||||
joinpoint Test.7 Test.2 Test.3:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.1 (Test.8):
|
||||
let Test.3 : I64 = 10i64;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.276 : U8 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.276;
|
||||
let Num.279 : U8 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.279;
|
||||
|
||||
procedure Test.1 (Test.9):
|
||||
let Test.4 : U8 = 10i64;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ procedure Bool.1 ():
|
|||
ret Bool.23;
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.3 (Test.4):
|
||||
ret Test.4;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.277 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.277;
|
||||
let Num.280 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.280;
|
||||
|
||||
procedure Test.2 (Test.3):
|
||||
switch Test.3:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.276 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.276;
|
||||
let Num.279 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.279;
|
||||
|
||||
procedure Test.2 (Test.3, Test.1):
|
||||
let Test.17 : Int1 = false;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ procedure List.6 (#Attr.2):
|
|||
ret List.494;
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.277 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.277;
|
||||
let Num.280 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.280;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.1 : List I64 = Array [1i64, 2i64];
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.2 : I64 = 1i64;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.45 (#Attr.2):
|
||||
let Num.275 : I64 = lowlevel NumRound #Attr.2;
|
||||
ret Num.275;
|
||||
let Num.278 : I64 = lowlevel NumRound #Attr.2;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.2 : Float64 = 3.6f64;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.1 : I64 = 3i64;
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
procedure Num.30 (#Attr.2):
|
||||
let Num.282 : I64 = 0i64;
|
||||
let Num.281 : Int1 = lowlevel Eq #Attr.2 Num.282;
|
||||
ret Num.281;
|
||||
let Num.285 : I64 = 0i64;
|
||||
let Num.284 : Int1 = lowlevel Eq #Attr.2 Num.285;
|
||||
ret Num.284;
|
||||
|
||||
procedure Num.39 (#Attr.2, #Attr.3):
|
||||
let Num.277 : I64 = lowlevel NumDivTruncUnchecked #Attr.2 #Attr.3;
|
||||
ret Num.277;
|
||||
let Num.280 : I64 = lowlevel NumDivTruncUnchecked #Attr.2 #Attr.3;
|
||||
ret Num.280;
|
||||
|
||||
procedure Num.40 (Num.247, Num.248):
|
||||
let Num.278 : Int1 = CallByName Num.30 Num.248;
|
||||
if Num.278 then
|
||||
let Num.280 : {} = Struct {};
|
||||
let Num.279 : [C {}, C I64] = TagId(0) Num.280;
|
||||
ret Num.279;
|
||||
procedure Num.40 (Num.250, Num.251):
|
||||
let Num.281 : Int1 = CallByName Num.30 Num.251;
|
||||
if Num.281 then
|
||||
let Num.283 : {} = Struct {};
|
||||
let Num.282 : [C {}, C I64] = TagId(0) Num.283;
|
||||
ret Num.282;
|
||||
else
|
||||
let Num.276 : I64 = CallByName Num.39 Num.247 Num.248;
|
||||
let Num.275 : [C {}, C I64] = TagId(1) Num.276;
|
||||
ret Num.275;
|
||||
let Num.279 : I64 = CallByName Num.39 Num.250 Num.251;
|
||||
let Num.278 : [C {}, C I64] = TagId(1) Num.279;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.8 : I64 = 1000i64;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.10 : I64 = 41i64;
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ procedure List.9 (List.287):
|
|||
ret List.496;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Str.27 (Str.99):
|
||||
let Str.298 : [C Int1, C I64] = CallByName Str.72 Str.99;
|
||||
|
|
|
|||
|
|
@ -320,16 +320,16 @@ procedure List.72 (#Attr.2, #Attr.3, #Attr.4):
|
|||
ret List.505;
|
||||
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.276 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.276;
|
||||
let Num.279 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.279;
|
||||
|
||||
procedure Num.24 (#Attr.2, #Attr.3):
|
||||
let Num.278 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
let Num.281 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.281;
|
||||
|
||||
procedure Num.77 (#Attr.2, #Attr.3):
|
||||
let Num.280 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3;
|
||||
ret Num.280;
|
||||
let Num.283 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3;
|
||||
ret Num.283;
|
||||
|
||||
procedure Str.48 (#Attr.2, #Attr.3, #Attr.4):
|
||||
let Str.307 : {U64, Str, Int1, U8} = lowlevel StrFromUtf8Range #Attr.2 #Attr.3 #Attr.4;
|
||||
|
|
|
|||
|
|
@ -291,16 +291,16 @@ procedure List.72 (#Attr.2, #Attr.3, #Attr.4):
|
|||
ret List.499;
|
||||
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.276 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.276;
|
||||
let Num.279 : U64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.279;
|
||||
|
||||
procedure Num.24 (#Attr.2, #Attr.3):
|
||||
let Num.278 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
let Num.281 : Int1 = lowlevel NumGt #Attr.2 #Attr.3;
|
||||
ret Num.281;
|
||||
|
||||
procedure Num.77 (#Attr.2, #Attr.3):
|
||||
let Num.280 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3;
|
||||
ret Num.280;
|
||||
let Num.283 : U64 = lowlevel NumSubSaturated #Attr.2 #Attr.3;
|
||||
ret Num.283;
|
||||
|
||||
procedure Str.12 (#Attr.2):
|
||||
let Str.307 : List U8 = lowlevel StrToUtf8 #Attr.2;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
procedure Num.96 (#Attr.2):
|
||||
let Num.275 : Str = lowlevel NumToStr #Attr.2;
|
||||
ret Num.275;
|
||||
let Num.278 : Str = lowlevel NumToStr #Attr.2;
|
||||
ret Num.278;
|
||||
|
||||
procedure Num.96 (#Attr.2):
|
||||
let Num.276 : Str = lowlevel NumToStr #Attr.2;
|
||||
ret Num.276;
|
||||
let Num.279 : Str = lowlevel NumToStr #Attr.2;
|
||||
ret Num.279;
|
||||
|
||||
procedure Test.1 (Test.4):
|
||||
let Test.13 : [C U8, C U64] = TagId(1) Test.4;
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@ procedure Bool.2 ():
|
|||
ret Bool.24;
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Num.21 (#Attr.2, #Attr.3):
|
||||
let Num.276 : U64 = lowlevel NumMul #Attr.2 #Attr.3;
|
||||
ret Num.276;
|
||||
let Num.279 : U64 = lowlevel NumMul #Attr.2 #Attr.3;
|
||||
ret Num.279;
|
||||
|
||||
procedure Test.0 (Test.8):
|
||||
let Test.20 : Int1 = CallByName Bool.2;
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ procedure List.92 (List.430, List.431, List.432):
|
|||
ret List.497;
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.276 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.276;
|
||||
let Num.279 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.279;
|
||||
|
||||
procedure Test.7 (Test.11, Test.12):
|
||||
let Test.17 : {[<rnu>C *self, <null>], [<rnu><null>, C {[<rnu>C *self, <null>], *self}]} = Struct {Test.12, Test.11};
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@ procedure List.67 (#Attr.2, #Attr.3, #Attr.4):
|
|||
ret List.501;
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.276 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.276;
|
||||
let Num.279 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.279;
|
||||
|
||||
procedure Test.1 ():
|
||||
let Test.8 : List I64 = Array [1i64, 2i64, 3i64];
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ procedure List.66 (#Attr.2, #Attr.3):
|
|||
ret List.499;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.1 (Test.2):
|
||||
let Test.6 : List I64 = Array [1i64, 2i64, 3i64];
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ procedure List.6 (#Attr.2):
|
|||
ret List.495;
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : U64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.1 : List I64 = Array [1i64, 2i64, 3i64];
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ procedure List.66 (#Attr.2, #Attr.3):
|
|||
ret List.499;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Str.16 (#Attr.2, #Attr.3):
|
||||
let Str.298 : Str = lowlevel StrRepeat #Attr.2 #Attr.3;
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ procedure List.66 (#Attr.2, #Attr.3):
|
|||
ret List.499;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Str.3 (#Attr.2, #Attr.3):
|
||||
let Str.299 : Str = lowlevel StrConcat #Attr.2 #Attr.3;
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ procedure List.5 (#Attr.2, #Attr.3):
|
|||
|
||||
|
||||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.277 : U8 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.277;
|
||||
let Num.280 : U8 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.280;
|
||||
|
||||
procedure Test.4 (Test.5, #Attr.12):
|
||||
let Test.1 : U8 = UnionAtIndex (Id 0) (Index 0) #Attr.12;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ procedure List.67 (#Attr.2, #Attr.3, #Attr.4):
|
|||
ret List.499;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.275 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.2 (Test.3):
|
||||
let Test.6 : U64 = 0i64;
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ procedure List.59 (List.282):
|
|||
ret List.494;
|
||||
|
||||
procedure Num.46 (#Attr.2, #Attr.3):
|
||||
let Num.275 : U8 = lowlevel NumCompare #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : U8 = lowlevel NumCompare #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.2 : List I64 = Array [4i64, 3i64, 2i64, 1i64];
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.19 : I64 = 41i64;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.37 (#Attr.2, #Attr.3):
|
||||
let Num.275 : Float64 = lowlevel NumDivFrac #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : Float64 = lowlevel NumDivFrac #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.2 : Float64 = 1f64;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
procedure Num.21 (#Attr.2, #Attr.3):
|
||||
let Num.277 : I64 = lowlevel NumMul #Attr.2 #Attr.3;
|
||||
ret Num.277;
|
||||
let Num.280 : I64 = lowlevel NumMul #Attr.2 #Attr.3;
|
||||
ret Num.280;
|
||||
|
||||
procedure Test.1 (Test.6):
|
||||
let Test.21 : Int1 = false;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
procedure Num.19 (#Attr.2, #Attr.3):
|
||||
let Num.275 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.275;
|
||||
let Num.278 : I64 = lowlevel NumAdd #Attr.2 #Attr.3;
|
||||
ret Num.278;
|
||||
|
||||
procedure Num.20 (#Attr.2, #Attr.3):
|
||||
let Num.276 : I64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.276;
|
||||
let Num.279 : I64 = lowlevel NumSub #Attr.2 #Attr.3;
|
||||
ret Num.279;
|
||||
|
||||
procedure Num.22 (#Attr.2, #Attr.3):
|
||||
let Num.277 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.277;
|
||||
let Num.280 : Int1 = lowlevel NumLt #Attr.2 #Attr.3;
|
||||
ret Num.280;
|
||||
|
||||
procedure Test.1 (Test.24, Test.25, Test.26):
|
||||
joinpoint Test.12 Test.2 Test.3 Test.4:
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue