Merge branch 'main' into symbol_tags

This commit is contained in:
J.Teeuwissen 2023-04-30 16:35:22 +02:00
commit 297658caba
No known key found for this signature in database
GPG key ID: DB5F7A1ED8D478AD
92 changed files with 2319 additions and 1762 deletions

View file

@ -32,8 +32,8 @@ jobs:
- name: zig version - name: zig version
run: zig version run: zig version
- name: install rust nightly 1.65 - name: install rust nightly 1.66
run: rustup install nightly-2022-09-17 run: rustup install nightly-2022-10-30
- name: set up llvm 13 - name: set up llvm 13
run: | run: |

View file

@ -36,8 +36,8 @@ jobs:
- name: zig version - name: zig version
run: zig version run: zig version
- name: install rust nightly 1.65 - name: install rust nightly 1.66
run: rustup install nightly-2022-09-17 run: rustup install nightly-2022-10-30
- name: set up llvm 13 - name: set up llvm 13
run: | run: |

5
Cargo.lock generated
View file

@ -764,7 +764,7 @@ dependencies = [
[[package]] [[package]]
name = "criterion" name = "criterion"
version = "0.3.5" version = "0.3.5"
source = "git+https://github.com/Anton-4/criterion.rs#3e46ad2b234e36928fb5234d36cf53b5837cbb87" source = "git+https://github.com/Anton-4/criterion.rs?rev=30ea0c5#30ea0c592d7423ed79772234fab13108d1f8de77"
dependencies = [ dependencies = [
"atty", "atty",
"cast", "cast",
@ -789,7 +789,7 @@ dependencies = [
[[package]] [[package]]
name = "criterion-plot" name = "criterion-plot"
version = "0.4.3" version = "0.4.3"
source = "git+https://github.com/Anton-4/criterion.rs#3e46ad2b234e36928fb5234d36cf53b5837cbb87" source = "git+https://github.com/Anton-4/criterion.rs?rev=30ea0c5#30ea0c592d7423ed79772234fab13108d1f8de77"
dependencies = [ dependencies = [
"cast", "cast",
"itertools 0.9.0", "itertools 0.9.0",
@ -3741,6 +3741,7 @@ dependencies = [
"quickcheck", "quickcheck",
"quickcheck_macros", "quickcheck_macros",
"roc_collections", "roc_collections",
"roc_error_macros",
"roc_module", "roc_module",
"roc_region", "roc_region",
] ]

View file

@ -88,8 +88,8 @@ confy = { git = 'https://github.com/rust-cli/confy', features = ["yaml_conf"], d
console_error_panic_hook = "0.1.7" console_error_panic_hook = "0.1.7"
const_format = { version = "0.2.30", features = ["const_generics"] } const_format = { version = "0.2.30", features = ["const_generics"] }
copypasta = "0.8.2" copypasta = "0.8.2"
criterion = { git = "https://github.com/Anton-4/criterion.rs", features = ["html_reports"] } criterion = { git = "https://github.com/Anton-4/criterion.rs", features = ["html_reports"], rev = "30ea0c5" }
criterion-perf-events = { git = "https://github.com/Anton-4/criterion-perf-events" } criterion-perf-events = { git = "https://github.com/Anton-4/criterion-perf-events", rev = "0f38c3e" }
crossbeam = "0.8.2" crossbeam = "0.8.2"
dircpy = "0.3.14" dircpy = "0.3.14"
distance = "0.4.0" distance = "0.4.0"

View file

@ -12,11 +12,11 @@ If you'd like to contribute, check out [good first issues](https://github.com/ro
## Sponsors ## Sponsors
We are very grateful for our corporate sponsors [Vendr](https://www.vendr.com/), [rwx](https://www.rwx.com), and [Tweede golf](https://tweedegolf.nl/en). We are very grateful for our corporate sponsors [Vendr](https://www.vendr.com/), [RWX](https://www.rwx.com), and [Tweede golf](https://tweedegolf.nl/en).
[<img src="https://user-images.githubusercontent.com/1094080/223597445-81755626-a080-4299-a38c-3c92e7548489.png" height="60" alt="Vendr logo"/>](https://www.vendr.com) [<img src="https://user-images.githubusercontent.com/1094080/223597445-81755626-a080-4299-a38c-3c92e7548489.png" height="60" alt="Vendr logo"/>](https://www.vendr.com)
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;
[<img src="https://www.rwx.com/rwx_banner.svg" height="60" alt="rwx logo"/>](https://www.rwx.com) [<img src="https://www.rwx.com/rwx_banner.svg" height="60" alt="RWX logo"/>](https://www.rwx.com)
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;
[<img src="https://user-images.githubusercontent.com/1094080/183123052-856815b1-8cc9-410a-83b0-589f03613188.svg" height="60" alt="tweede golf logo"/>](https://tweedegolf.nl/en) [<img src="https://user-images.githubusercontent.com/1094080/183123052-856815b1-8cc9-410a-83b0-589f03613188.svg" height="60" alt="tweede golf logo"/>](https://tweedegolf.nl/en)

View file

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const str = @import("str"); const str = @import("glue").str;
const RocStr = str.RocStr; const RocStr = str.RocStr;
const testing = std.testing; const testing = std.testing;
const expectEqual = testing.expectEqual; const expectEqual = testing.expectEqual;

View file

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const str = @import("str"); const str = @import("glue").str;
const RocStr = str.RocStr; const RocStr = str.RocStr;
const testing = std.testing; const testing = std.testing;
const expectEqual = testing.expectEqual; const expectEqual = testing.expectEqual;

View file

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const str = @import("str"); const str = @import("glue").str;
const RocStr = str.RocStr; const RocStr = str.RocStr;
const testing = std.testing; const testing = std.testing;
const expectEqual = testing.expectEqual; const expectEqual = testing.expectEqual;

View file

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const str = @import("str"); const str = @import("glue").str;
const RocStr = str.RocStr; const RocStr = str.RocStr;
const testing = std.testing; const testing = std.testing;
const expectEqual = testing.expectEqual; const expectEqual = testing.expectEqual;

View file

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const str = @import("str"); const str = @import("glue").str;
const RocStr = str.RocStr; const RocStr = str.RocStr;
const testing = std.testing; const testing = std.testing;
const expectEqual = testing.expectEqual; const expectEqual = testing.expectEqual;

View file

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const str = @import("str"); const str = @import("glue").str;
const RocStr = str.RocStr; const RocStr = str.RocStr;
const testing = std.testing; const testing = std.testing;
const expectEqual = testing.expectEqual; const expectEqual = testing.expectEqual;

View file

@ -1,6 +1,6 @@
use crate::target::{arch_str, target_zig_str}; use crate::target::{arch_str, target_zig_str};
use libloading::{Error, Library}; 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_error_macros::internal_error;
use roc_mono::ir::OptLevel; use roc_mono::ir::OptLevel;
use std::collections::HashMap; use std::collections::HashMap;
@ -63,31 +63,57 @@ pub fn legacy_host_filename(target: &Triple) -> Option<String> {
) )
} }
fn find_zig_str_path() -> PathBuf { // Attempts to find a file that is stored relative to the roc executable.
// First try using the lib path relative to the executable location. // Since roc is built in target/debug/roc, we may need to drop that path to find the file.
let lib_path_opt = get_lib_path(); // 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 { if let Some(exe_relative_str_path) = exe_relative_str_path_opt {
let zig_str_path = lib_path.join("str.zig"); #[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) { let mut curr_parent_opt = exe_relative_str_path.parent();
return zig_str_path;
// 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) { fn find_zig_glue_path() -> PathBuf {
return zig_str_path; // 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 internal_error!("cannot find `glue.zig`. Check the source code in find_zig_glue_path() to show all the paths I tried.")
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.")
} }
fn find_wasi_libc_path() -> PathBuf { fn find_wasi_libc_path() -> PathBuf {
@ -107,7 +133,6 @@ pub fn build_zig_host_native(
env_home: &str, env_home: &str,
emit_bin: &str, emit_bin: &str,
zig_host_src: &str, zig_host_src: &str,
zig_str_path: &str,
target: &str, target: &str,
opt_level: OptLevel, opt_level: OptLevel,
shared_lib_path: Option<&Path>, shared_lib_path: Option<&Path>,
@ -138,8 +163,8 @@ pub fn build_zig_host_native(
zig_host_src, zig_host_src,
&format!("-femit-bin={}", emit_bin), &format!("-femit-bin={}", emit_bin),
"--pkg-begin", "--pkg-begin",
"str", "glue",
zig_str_path, find_zig_glue_path().to_str().unwrap(),
"--pkg-end", "--pkg-end",
// include libc // include libc
"-lc", "-lc",
@ -180,7 +205,6 @@ pub fn build_zig_host_native(
env_home: &str, env_home: &str,
emit_bin: &str, emit_bin: &str,
zig_host_src: &str, zig_host_src: &str,
zig_str_path: &str,
target: &str, target: &str,
opt_level: OptLevel, opt_level: OptLevel,
shared_lib_path: Option<&Path>, shared_lib_path: Option<&Path>,
@ -211,8 +235,8 @@ pub fn build_zig_host_native(
zig_host_src, zig_host_src,
&format!("-femit-bin={}", emit_bin), &format!("-femit-bin={}", emit_bin),
"--pkg-begin", "--pkg-begin",
"str", "glue",
zig_str_path, find_zig_glue_path().to_str().unwrap(),
"--pkg-end", "--pkg-end",
// include the zig runtime // include the zig runtime
// "-fcompiler-rt", compiler-rt causes segfaults on windows; investigate why // "-fcompiler-rt", compiler-rt causes segfaults on windows; investigate why
@ -240,7 +264,6 @@ pub fn build_zig_host_native(
env_home: &str, env_home: &str,
emit_bin: &str, emit_bin: &str,
zig_host_src: &str, zig_host_src: &str,
zig_str_path: &str,
_target: &str, _target: &str,
opt_level: OptLevel, opt_level: OptLevel,
shared_lib_path: Option<&Path>, shared_lib_path: Option<&Path>,
@ -306,8 +329,8 @@ pub fn build_zig_host_native(
zig_host_src, zig_host_src,
&format!("-femit-bin={}", emit_bin), &format!("-femit-bin={}", emit_bin),
"--pkg-begin", "--pkg-begin",
"str", "glue",
zig_str_path, find_zig_glue_path().to_str().unwrap(),
"--pkg-end", "--pkg-end",
// include the zig runtime // include the zig runtime
"--pkg-begin", "--pkg-begin",
@ -332,7 +355,6 @@ pub fn build_zig_host_wasm32(
env_home: &str, env_home: &str,
emit_bin: &str, emit_bin: &str,
zig_host_src: &str, zig_host_src: &str,
zig_str_path: &str,
opt_level: OptLevel, opt_level: OptLevel,
shared_lib_path: Option<&Path>, shared_lib_path: Option<&Path>,
) -> Command { ) -> Command {
@ -356,31 +378,30 @@ pub fn build_zig_host_wasm32(
// //
// https://github.com/ziglang/zig/issues/9414 // https://github.com/ziglang/zig/issues/9414
let mut zig_cmd = zig(); 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 zig_cmd
.env_clear() .env_clear()
.env("PATH", env_path) .env("PATH", env_path)
.env("HOME", env_home) .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) { if matches!(opt_level, OptLevel::Optimize) {
zig_cmd.args(["-O", "ReleaseSafe"]); zig_cmd.args(["-O", "ReleaseSafe"]);
@ -424,7 +445,6 @@ pub fn build_c_host_native(
env_home, env_home,
dest, dest,
sources[0], sources[0],
find_zig_str_path().to_str().unwrap(),
get_target_str(target), get_target_str(target),
opt_level, opt_level,
Some(shared_lib_path), Some(shared_lib_path),
@ -558,15 +578,6 @@ pub fn rebuild_host(
if zig_host_src.exists() { if zig_host_src.exists() {
// Compile host.zig // 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 { let zig_cmd = match target.architecture {
Architecture::Wasm32 => { Architecture::Wasm32 => {
let emit_bin = if matches!(opt_level, OptLevel::Development) { let emit_bin = if matches!(opt_level, OptLevel::Development) {
@ -579,7 +590,6 @@ pub fn rebuild_host(
&env_home, &env_home,
&emit_bin, &emit_bin,
zig_host_src.to_str().unwrap(), zig_host_src.to_str().unwrap(),
zig_str_path.to_str().unwrap(),
opt_level, opt_level,
shared_lib_path, shared_lib_path,
) )
@ -589,7 +599,6 @@ pub fn rebuild_host(
&env_home, &env_home,
host_dest.to_str().unwrap(), host_dest.to_str().unwrap(),
zig_host_src.to_str().unwrap(), zig_host_src.to_str().unwrap(),
zig_str_path.to_str().unwrap(),
get_target_str(target), get_target_str(target),
opt_level, opt_level,
shared_lib_path, shared_lib_path,
@ -600,7 +609,6 @@ pub fn rebuild_host(
&env_home, &env_home,
host_dest.to_str().unwrap(), host_dest.to_str().unwrap(),
zig_host_src.to_str().unwrap(), zig_host_src.to_str().unwrap(),
zig_str_path.to_str().unwrap(),
"i386-linux-musl", "i386-linux-musl",
opt_level, opt_level,
shared_lib_path, shared_lib_path,
@ -611,7 +619,6 @@ pub fn rebuild_host(
&env_home, &env_home,
host_dest.to_str().unwrap(), host_dest.to_str().unwrap(),
zig_host_src.to_str().unwrap(), zig_host_src.to_str().unwrap(),
zig_str_path.to_str().unwrap(),
target_zig_str(target), target_zig_str(target),
opt_level, opt_level,
shared_lib_path, shared_lib_path,
@ -629,7 +636,7 @@ pub fn rebuild_host(
// on windows, we need the nightly toolchain so we can use `-Z export-executable-symbols` // on windows, we need the nightly toolchain so we can use `-Z export-executable-symbols`
// using `+nightly` only works when running cargo through rustup // using `+nightly` only works when running cargo through rustup
let mut cmd = rustup(); let mut cmd = rustup();
cmd.args(["run", "nightly-2022-09-17", "cargo"]); cmd.args(["run", "nightly-2022-10-30", "cargo"]);
cmd cmd
} else { } else {
@ -1273,7 +1280,6 @@ fn link_wasm32(
input_paths: &[&str], input_paths: &[&str],
_link_type: LinkType, _link_type: LinkType,
) -> io::Result<(Child, PathBuf)> { ) -> io::Result<(Child, PathBuf)> {
let zig_str_path = find_zig_str_path();
let wasi_libc_path = find_wasi_libc_path(); let wasi_libc_path = find_wasi_libc_path();
let child = zig() let child = zig()
@ -1289,8 +1295,8 @@ fn link_wasm32(
"-target", "-target",
"wasm32-wasi-musl", "wasm32-wasi-musl",
"--pkg-begin", "--pkg-begin",
"str", "glue",
zig_str_path.to_str().unwrap(), find_zig_glue_path().to_str().unwrap(),
"--pkg-end", "--pkg-end",
"--strip", "--strip",
"-O", "-O",
@ -1309,8 +1315,6 @@ fn link_windows(
input_paths: &[&str], input_paths: &[&str],
link_type: LinkType, link_type: LinkType,
) -> io::Result<(Child, PathBuf)> { ) -> io::Result<(Child, PathBuf)> {
let zig_str_path = find_zig_str_path();
match link_type { match link_type {
LinkType::Dylib => { LinkType::Dylib => {
let child = zig() let child = zig()
@ -1322,8 +1326,8 @@ fn link_windows(
"-target", "-target",
"native", "native",
"--pkg-begin", "--pkg-begin",
"str", "glue",
zig_str_path.to_str().unwrap(), find_zig_glue_path().to_str().unwrap(),
"--pkg-end", "--pkg-end",
"--strip", "--strip",
"-O", "-O",

View 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");

View file

@ -133,6 +133,7 @@ comptime {
exportStrFn(str.countSegments, "count_segments"); exportStrFn(str.countSegments, "count_segments");
exportStrFn(str.countGraphemeClusters, "count_grapheme_clusters"); exportStrFn(str.countGraphemeClusters, "count_grapheme_clusters");
exportStrFn(str.countUtf8Bytes, "count_utf8_bytes"); exportStrFn(str.countUtf8Bytes, "count_utf8_bytes");
exportStrFn(str.isEmpty, "is_empty");
exportStrFn(str.getCapacity, "capacity"); exportStrFn(str.getCapacity, "capacity");
exportStrFn(str.startsWith, "starts_with"); exportStrFn(str.startsWith, "starts_with");
exportStrFn(str.startsWithScalar, "starts_with_scalar"); exportStrFn(str.startsWithScalar, "starts_with_scalar");

View file

@ -1525,6 +1525,10 @@ pub fn countUtf8Bytes(string: RocStr) callconv(.C) usize {
return string.len(); return string.len();
} }
pub fn isEmpty(string: RocStr) callconv(.C) bool {
return string.isEmpty();
}
pub fn getCapacity(string: RocStr) callconv(.C) usize { pub fn getCapacity(string: RocStr) callconv(.C) usize {
return string.getCapacity(); return string.getCapacity();
} }

View file

@ -1016,7 +1016,7 @@ sublistLowlevel : List elem, Nat, Nat -> List elem
## Intersperses `sep` between the elements of `list` ## Intersperses `sep` between the elements of `list`
## ``` ## ```
## List.intersperse 9 [1, 2, 3] # [1, 9, 2, 9, 3] ## List.intersperse [1, 2, 3] 9 # [1, 9, 2, 9, 3]
## ``` ## ```
intersperse : List elem, elem -> List elem intersperse : List elem, elem -> List elem
intersperse = \list, sep -> intersperse = \list, sep ->

View file

@ -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_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_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_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_CAPACITY: &str = "roc_builtins.str.capacity";
pub const STR_STARTS_WITH: &str = "roc_builtins.str.starts_with"; pub const STR_STARTS_WITH: &str = "roc_builtins.str.starts_with";
pub const STR_STARTS_WITH_SCALAR: &str = "roc_builtins.str.starts_with_scalar"; pub const STR_STARTS_WITH_SCALAR: &str = "roc_builtins.str.starts_with_scalar";

View file

@ -1142,7 +1142,7 @@ fn can_extension_type(
introduced_variables: &mut IntroducedVariables, introduced_variables: &mut IntroducedVariables,
local_aliases: &mut VecMap<Symbol, Alias>, local_aliases: &mut VecMap<Symbol, Alias>,
references: &mut VecSet<Symbol>, references: &mut VecSet<Symbol>,
opt_ext: &Option<&Loc<TypeAnnotation<'_>>>, opt_ext: &Option<&Loc<TypeAnnotation>>,
ext_problem_kind: roc_problem::can::ExtensionTypeKind, ext_problem_kind: roc_problem::can::ExtensionTypeKind,
) -> (Type, ExtImplicitOpenness) { ) -> (Type, ExtImplicitOpenness) {
fn valid_record_ext_type(typ: &Type) -> bool { fn valid_record_ext_type(typ: &Type) -> bool {
@ -1454,7 +1454,7 @@ fn can_assigned_fields<'a>(
fn can_assigned_tuple_elems( fn can_assigned_tuple_elems(
env: &mut Env, env: &mut Env,
pol: CanPolarity, pol: CanPolarity,
elems: &&[Loc<TypeAnnotation<'_>>], elems: &&[Loc<TypeAnnotation>],
scope: &mut Scope, scope: &mut Scope,
var_store: &mut VarStore, var_store: &mut VarStore,
introduced_variables: &mut IntroducedVariables, introduced_variables: &mut IntroducedVariables,

View file

@ -85,6 +85,7 @@ macro_rules! map_symbol_to_lowlevel_and_arity {
// these are used internally and not tied to a symbol // these are used internally and not tied to a symbol
LowLevel::Hash => unimplemented!(), LowLevel::Hash => unimplemented!(),
LowLevel::PtrCast => unimplemented!(), LowLevel::PtrCast => unimplemented!(),
LowLevel::PtrWrite => unimplemented!(),
LowLevel::RefCountInc => unimplemented!(), LowLevel::RefCountInc => unimplemented!(),
LowLevel::RefCountDec => unimplemented!(), LowLevel::RefCountDec => unimplemented!(),

View file

@ -1338,7 +1338,7 @@ fn canonicalize_type_defs<'a>(
/// Resolve all pending abilities, to add them to scope. /// Resolve all pending abilities, to add them to scope.
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn resolve_abilities( fn resolve_abilities(
env: &mut Env<'_>, env: &mut Env,
output: &mut Output, output: &mut Output,
var_store: &mut VarStore, var_store: &mut VarStore,
scope: &mut Scope, scope: &mut Scope,
@ -2812,7 +2812,7 @@ fn to_pending_value_def<'a>(
/// Make aliases recursive /// Make aliases recursive
fn correct_mutual_recursive_type_alias( fn correct_mutual_recursive_type_alias(
env: &mut Env<'_>, env: &mut Env,
original_aliases: VecMap<Symbol, Alias>, original_aliases: VecMap<Symbol, Alias>,
var_store: &mut VarStore, var_store: &mut VarStore,
) -> VecMap<Symbol, Alias> { ) -> VecMap<Symbol, Alias> {
@ -3021,7 +3021,7 @@ fn correct_mutual_recursive_type_alias(
} }
fn make_tag_union_of_alias_recursive( fn make_tag_union_of_alias_recursive(
env: &mut Env<'_>, env: &mut Env,
alias_name: Symbol, alias_name: Symbol,
alias: &mut Alias, alias: &mut Alias,
others: Vec<Symbol>, others: Vec<Symbol>,
@ -3214,7 +3214,7 @@ fn make_tag_union_recursive_help<'a, 'b>(
} }
fn mark_cyclic_alias( fn mark_cyclic_alias(
env: &mut Env<'_>, env: &mut Env,
typ: &mut Type, typ: &mut Type,
symbol: Symbol, symbol: Symbol,
alias_kind: AliasKind, alias_kind: AliasKind,

View file

@ -1378,31 +1378,31 @@ pub fn canonicalize_expr<'a>(
// Below this point, we shouln't see any of these nodes anymore because // Below this point, we shouln't see any of these nodes anymore because
// operator desugaring should have removed them! // operator desugaring should have removed them!
bad_expr @ ast::Expr::ParensAround(_) => { bad_expr @ ast::Expr::ParensAround(_) => {
panic!( internal_error!(
"A ParensAround did not get removed during operator desugaring somehow: {:#?}", "A ParensAround did not get removed during operator desugaring somehow: {:#?}",
bad_expr bad_expr
); );
} }
bad_expr @ ast::Expr::SpaceBefore(_, _) => { bad_expr @ ast::Expr::SpaceBefore(_, _) => {
panic!( internal_error!(
"A SpaceBefore did not get removed during operator desugaring somehow: {:#?}", "A SpaceBefore did not get removed during operator desugaring somehow: {:#?}",
bad_expr bad_expr
); );
} }
bad_expr @ ast::Expr::SpaceAfter(_, _) => { bad_expr @ ast::Expr::SpaceAfter(_, _) => {
panic!( internal_error!(
"A SpaceAfter did not get removed during operator desugaring somehow: {:#?}", "A SpaceAfter did not get removed during operator desugaring somehow: {:#?}",
bad_expr bad_expr
); );
} }
bad_expr @ ast::Expr::BinOps { .. } => { bad_expr @ ast::Expr::BinOps { .. } => {
panic!( internal_error!(
"A binary operator chain did not get desugared somehow: {:#?}", "A binary operator chain did not get desugared somehow: {:#?}",
bad_expr bad_expr
); );
} }
bad_expr @ ast::Expr::UnaryOp(_, _) => { bad_expr @ ast::Expr::UnaryOp(_, _) => {
panic!( internal_error!(
"A unary operator did not get desugared somehow: {:#?}", "A unary operator did not get desugared somehow: {:#?}",
bad_expr bad_expr
); );
@ -1814,7 +1814,7 @@ fn canonicalize_field<'a>(
// A label with no value, e.g. `{ name }` (this is sugar for { name: name }) // A label with no value, e.g. `{ name }` (this is sugar for { name: name })
LabelOnly(_) => { 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, _) => { SpaceBefore(sub_field, _) | SpaceAfter(sub_field, _) => {
@ -1822,7 +1822,7 @@ fn canonicalize_field<'a>(
} }
Malformed(_string) => { Malformed(_string) => {
panic!("TODO canonicalize malformed record field"); internal_error!("TODO canonicalize malformed record field");
} }
} }
} }

View file

@ -199,7 +199,7 @@ impl GeneratedInfo {
env: &mut Env, env: &mut Env,
scope: &mut Scope, scope: &mut Scope,
var_store: &mut VarStore, var_store: &mut VarStore,
header_type: &HeaderType<'_>, header_type: &HeaderType,
) -> Self { ) -> Self {
match header_type { match header_type {
HeaderType::Hosted { HeaderType::Hosted {
@ -338,7 +338,7 @@ pub fn canonicalize_module_defs<'a>(
can_exposed_imports.insert(symbol, region); can_exposed_imports.insert(symbol, region);
} }
Err((_shadowed_symbol, _region)) => { Err((_shadowed_symbol, _region)) => {
panic!("TODO gracefully handle shadowing in imports.") internal_error!("TODO gracefully handle shadowing in imports.")
} }
} }
} else { } else {
@ -359,7 +359,7 @@ pub fn canonicalize_module_defs<'a>(
// here we do nothing special // here we do nothing special
} }
Err((shadowed_symbol, _region)) => { Err((shadowed_symbol, _region)) => {
panic!( internal_error!(
"TODO gracefully handle shadowing in imports, {:?} is shadowed.", "TODO gracefully handle shadowing in imports, {:?} is shadowed.",
shadowed_symbol shadowed_symbol
) )
@ -523,7 +523,7 @@ pub fn canonicalize_module_defs<'a>(
GeneratedInfo::Builtin => { GeneratedInfo::Builtin => {
match crate::builtins::builtin_defs_map(*symbol, var_store) { match crate::builtins::builtin_defs_map(*symbol, var_store) {
None => { 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) => { Some(replacement_def) => {
declarations.update_builtin_def(index, replacement_def); declarations.update_builtin_def(index, replacement_def);
@ -581,7 +581,7 @@ pub fn canonicalize_module_defs<'a>(
GeneratedInfo::Builtin => { GeneratedInfo::Builtin => {
match crate::builtins::builtin_defs_map(*symbol, var_store) { match crate::builtins::builtin_defs_map(*symbol, var_store) {
None => { 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) => { Some(replacement_def) => {
declarations.update_builtin_def(index, replacement_def); declarations.update_builtin_def(index, replacement_def);

View file

@ -2,6 +2,7 @@
use bumpalo::collections::Vec; use bumpalo::collections::Vec;
use bumpalo::Bump; use bumpalo::Bump;
use roc_error_macros::internal_error;
use roc_module::called_via::BinOp::Pizza; use roc_module::called_via::BinOp::Pizza;
use roc_module::called_via::{BinOp, CalledVia}; use roc_module::called_via::{BinOp, CalledVia};
use roc_module::ident::ModuleName; 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 // 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! // 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!");
} }
} }
} }

View file

@ -322,7 +322,7 @@ pub fn canonicalize_def_header_pattern<'a>(
pub struct PermitShadows(pub bool); pub struct PermitShadows(pub bool);
fn canonicalize_pattern_symbol( fn canonicalize_pattern_symbol(
env: &mut Env<'_>, env: &mut Env,
scope: &mut Scope, scope: &mut Scope,
output: &mut Output, output: &mut Output,
region: Region, region: Region,

View file

@ -1,4 +1,5 @@
use roc_collections::{VecMap, VecSet}; use roc_collections::{VecMap, VecSet};
use roc_error_macros::internal_error;
use roc_module::ident::Ident; use roc_module::ident::Ident;
use roc_module::symbol::{IdentId, IdentIds, ModuleId, Symbol}; use roc_module::symbol::{IdentId, IdentIds, ModuleId, Symbol};
use roc_problem::can::RuntimeError; use roc_problem::can::RuntimeError;
@ -470,9 +471,13 @@ pub fn create_alias(
} }
if !hidden.is_empty() { if !hidden.is_empty() {
panic!( internal_error!(
"Found unbound type variables {:?} \n in type alias {:?} {:?} {:?} : {:?}", "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
) )
} }

View file

@ -1,6 +1,7 @@
// use bumpalo::collections::string::String; // use bumpalo::collections::string::String;
// use bumpalo::collections::vec::Vec; // use bumpalo::collections::vec::Vec;
use bumpalo::Bump; use bumpalo::Bump;
use roc_error_macros::internal_error;
use roc_parse::ast::Expr; use roc_parse::ast::Expr;
// use roc_parse::ast::{Attempting, Expr}; // use roc_parse::ast::{Attempting, Expr};
// use roc_parse::ident; // use roc_parse::ident;
@ -12,7 +13,7 @@ use roc_region::all::Region;
// use std::iter::Peekable; // use std::iter::Peekable;
pub fn canonical_string_literal<'a>(_arena: &Bump, _raw: &'a str, _region: Region) -> Expr<'a> { 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(); // let mut problems = std::vec::Vec::new();

View file

@ -65,15 +65,9 @@ impl Newlines {
pub trait Formattable { pub trait Formattable {
fn is_multiline(&self) -> bool; fn is_multiline(&self) -> bool;
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, _parens: Parens, _newlines: Newlines, indent: u16);
&self,
buf: &mut Buf<'_>,
_parens: Parens,
_newlines: Newlines,
indent: u16,
);
fn format(&self, buf: &mut Buf<'_>, indent: u16) { fn format(&self, buf: &mut Buf, indent: u16) {
self.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent); self.format_with_options(buf, Parens::NotNeeded, Newlines::No, indent);
} }
} }
@ -87,17 +81,11 @@ where
(*self).is_multiline() (*self).is_multiline()
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
parens: Parens,
newlines: Newlines,
indent: u16,
) {
(*self).format_with_options(buf, parens, newlines, indent) (*self).format_with_options(buf, parens, newlines, indent)
} }
fn format(&self, buf: &mut Buf<'_>, indent: u16) { fn format(&self, buf: &mut Buf, indent: u16) {
(*self).format(buf, indent) (*self).format(buf, indent)
} }
} }
@ -120,18 +108,12 @@ where
self.value.is_multiline() self.value.is_multiline()
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
parens: Parens,
newlines: Newlines,
indent: u16,
) {
self.value self.value
.format_with_options(buf, parens, newlines, indent) .format_with_options(buf, parens, newlines, indent)
} }
fn format(&self, buf: &mut Buf<'_>, indent: u16) { fn format(&self, buf: &mut Buf, indent: u16) {
self.value.format(buf, indent) self.value.format(buf, indent)
} }
} }
@ -143,7 +125,7 @@ impl<'a> Formattable for UppercaseIdent<'a> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
_parens: Parens, _parens: Parens,
_newlines: Newlines, _newlines: Newlines,
_indent: u16, _indent: u16,
@ -206,13 +188,7 @@ impl<'a> Formattable for TypeAnnotation<'a> {
} }
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
parens: Parens,
newlines: Newlines,
indent: u16,
) {
use roc_parse::ast::TypeAnnotation::*; use roc_parse::ast::TypeAnnotation::*;
let self_is_multiline = self.is_multiline(); let self_is_multiline = self.is_multiline();
@ -424,13 +400,7 @@ impl<'a> Formattable for AssignedField<'a, TypeAnnotation<'a>> {
is_multiline_assigned_field_help(self) is_multiline_assigned_field_help(self)
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, _parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
_parens: Parens,
newlines: Newlines,
indent: u16,
) {
// we abuse the `Newlines` type to decide between multiline or single-line layout // we abuse the `Newlines` type to decide between multiline or single-line layout
format_assigned_field_help(self, buf, indent, 1, newlines == Newlines::Yes); format_assigned_field_help(self, buf, indent, 1, newlines == Newlines::Yes);
} }
@ -441,13 +411,7 @@ impl<'a> Formattable for AssignedField<'a, Expr<'a>> {
is_multiline_assigned_field_help(self) is_multiline_assigned_field_help(self)
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, _parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
_parens: Parens,
newlines: Newlines,
indent: u16,
) {
// we abuse the `Newlines` type to decide between multiline or single-line layout // we abuse the `Newlines` type to decide between multiline or single-line layout
format_assigned_field_help(self, buf, indent, 0, newlines == Newlines::Yes); format_assigned_field_help(self, buf, indent, 0, newlines == Newlines::Yes);
} }
@ -467,8 +431,8 @@ fn is_multiline_assigned_field_help<T: Formattable>(afield: &AssignedField<'_, T
} }
fn format_assigned_field_help<T>( fn format_assigned_field_help<T>(
zelf: &AssignedField<'_, T>, zelf: &AssignedField<T>,
buf: &mut Buf<'_>, buf: &mut Buf,
indent: u16, indent: u16,
separator_spaces: usize, separator_spaces: usize,
is_multiline: bool, is_multiline: bool,
@ -547,7 +511,7 @@ impl<'a> Formattable for Tag<'a> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
_parens: Parens, _parens: Parens,
_newlines: Newlines, _newlines: Newlines,
indent: u16, indent: u16,
@ -592,13 +556,7 @@ impl<'a> Formattable for HasClause<'a> {
false false
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
parens: Parens,
newlines: Newlines,
indent: u16,
) {
buf.push_str(self.var.value.extract_spaces().item); buf.push_str(self.var.value.extract_spaces().item);
buf.spaces(1); buf.spaces(1);
buf.push_str("has"); buf.push_str("has");
@ -623,13 +581,7 @@ impl<'a> Formattable for HasImpls<'a> {
} }
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
parens: Parens,
newlines: Newlines,
indent: u16,
) {
match self { match self {
HasImpls::HasImpls(impls) => { HasImpls::HasImpls(impls) => {
if newlines == Newlines::Yes { if newlines == Newlines::Yes {
@ -662,13 +614,7 @@ impl<'a> Formattable for HasAbility<'a> {
} }
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
parens: Parens,
newlines: Newlines,
indent: u16,
) {
match self { match self {
HasAbility::HasAbility { ability, impls } => { HasAbility::HasAbility { ability, impls } => {
if newlines == Newlines::Yes { if newlines == Newlines::Yes {
@ -703,13 +649,7 @@ impl<'a> Formattable for HasAbilities<'a> {
} }
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
parens: Parens,
newlines: Newlines,
indent: u16,
) {
match self { match self {
HasAbilities::Has(has_abilities) => { HasAbilities::Has(has_abilities) => {
if newlines == Newlines::Yes { if newlines == Newlines::Yes {

View file

@ -17,7 +17,7 @@ impl<'a> Formattable for Defs<'a> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
_parens: Parens, _parens: Parens,
_newlines: Newlines, _newlines: Newlines,
indent: u16, indent: u16,
@ -57,13 +57,7 @@ impl<'a> Formattable for TypeDef<'a> {
} }
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, _parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
_parens: Parens,
newlines: Newlines,
indent: u16,
) {
use roc_parse::ast::TypeDef::*; use roc_parse::ast::TypeDef::*;
match self { match self {
@ -173,7 +167,7 @@ impl<'a> Formattable for TypeHeader<'a> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
_parens: Parens, _parens: Parens,
_newlines: Newlines, _newlines: Newlines,
indent: u16, indent: u16,
@ -205,13 +199,7 @@ impl<'a> Formattable for ValueDef<'a> {
} }
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, _parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
_parens: Parens,
newlines: Newlines,
indent: u16,
) {
use roc_parse::ast::ValueDef::*; use roc_parse::ast::ValueDef::*;
match self { match self {
Annotation(loc_pattern, loc_annotation) => { Annotation(loc_pattern, loc_annotation) => {
@ -315,7 +303,7 @@ fn should_outdent(mut rhs: &TypeAnnotation) -> bool {
} }
fn fmt_dbg_in_def<'a>( fn fmt_dbg_in_def<'a>(
buf: &mut Buf<'_>, buf: &mut Buf,
condition: &'a Loc<Expr<'a>>, condition: &'a Loc<Expr<'a>>,
is_multiline: bool, is_multiline: bool,
indent: u16, indent: u16,
@ -335,12 +323,7 @@ fn fmt_dbg_in_def<'a>(
condition.format(buf, return_indent); condition.format(buf, return_indent);
} }
fn fmt_expect<'a>( fn fmt_expect<'a>(buf: &mut Buf, condition: &'a Loc<Expr<'a>>, is_multiline: bool, indent: u16) {
buf: &mut Buf<'_>,
condition: &'a Loc<Expr<'a>>,
is_multiline: bool,
indent: u16,
) {
buf.ensure_ends_with_newline(); buf.ensure_ends_with_newline();
buf.indent(indent); buf.indent(indent);
buf.push_str("expect"); buf.push_str("expect");
@ -356,12 +339,7 @@ fn fmt_expect<'a>(
condition.format(buf, return_indent); condition.format(buf, return_indent);
} }
fn fmt_expect_fx<'a>( fn fmt_expect_fx<'a>(buf: &mut Buf, condition: &'a Loc<Expr<'a>>, is_multiline: bool, indent: u16) {
buf: &mut Buf<'_>,
condition: &'a Loc<Expr<'a>>,
is_multiline: bool,
indent: u16,
) {
buf.ensure_ends_with_newline(); buf.ensure_ends_with_newline();
buf.indent(indent); buf.indent(indent);
buf.push_str("expect-fx"); buf.push_str("expect-fx");
@ -377,19 +355,19 @@ fn fmt_expect_fx<'a>(
condition.format(buf, return_indent); condition.format(buf, return_indent);
} }
pub fn fmt_value_def(buf: &mut Buf<'_>, def: &roc_parse::ast::ValueDef<'_>, indent: u16) { pub fn fmt_value_def(buf: &mut Buf, def: &roc_parse::ast::ValueDef, indent: u16) {
def.format(buf, indent); def.format(buf, indent);
} }
pub fn fmt_type_def(buf: &mut Buf<'_>, def: &roc_parse::ast::TypeDef<'_>, indent: u16) { pub fn fmt_type_def(buf: &mut Buf, def: &roc_parse::ast::TypeDef, indent: u16) {
def.format(buf, indent); def.format(buf, indent);
} }
pub fn fmt_defs(buf: &mut Buf<'_>, defs: &Defs<'_>, indent: u16) { pub fn fmt_defs(buf: &mut Buf, defs: &Defs, indent: u16) {
defs.format(buf, indent); defs.format(buf, indent);
} }
pub fn fmt_body<'a>(buf: &mut 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); pattern.format_with_options(buf, Parens::InApply, Newlines::No, indent);
buf.indent(indent); buf.indent(indent);
buf.push_str(" ="); buf.push_str(" =");
@ -455,7 +433,7 @@ impl<'a> Formattable for AbilityMember<'a> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
_parens: Parens, _parens: Parens,
_newlines: Newlines, _newlines: Newlines,
indent: u16, indent: u16,

View file

@ -103,13 +103,7 @@ impl<'a> Formattable for Expr<'a> {
} }
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
parens: Parens,
newlines: Newlines,
indent: u16,
) {
use self::Expr::*; use self::Expr::*;
let apply_needs_parens = parens == Parens::InApply; let apply_needs_parens = parens == Parens::InApply;
@ -551,7 +545,7 @@ fn starts_with_newline(expr: &Expr) -> bool {
} }
} }
fn format_str_segment(seg: &StrSegment<'_>, buf: &mut Buf<'_>, indent: u16) { fn format_str_segment(seg: &StrSegment, buf: &mut Buf, indent: u16) {
use StrSegment::*; use StrSegment::*;
match seg { match seg {
@ -614,7 +608,7 @@ fn push_op(buf: &mut Buf, op: BinOp) {
} }
} }
pub fn fmt_str_literal(buf: &mut Buf<'_>, literal: StrLiteral, indent: u16) { pub fn fmt_str_literal(buf: &mut Buf, literal: StrLiteral, indent: u16) {
use roc_parse::ast::StrLiteral::*; use roc_parse::ast::StrLiteral::*;
match literal { match literal {
@ -674,7 +668,7 @@ pub fn fmt_str_literal(buf: &mut Buf<'_>, literal: StrLiteral, indent: u16) {
} }
fn fmt_binops<'a>( fn fmt_binops<'a>(
buf: &mut Buf<'_>, buf: &mut Buf,
lefts: &'a [(Loc<Expr<'a>>, Loc<BinOp>)], lefts: &'a [(Loc<Expr<'a>>, Loc<BinOp>)],
loc_right_side: &'a Loc<Expr<'a>>, loc_right_side: &'a Loc<Expr<'a>>,
part_of_multi_line_binops: bool, part_of_multi_line_binops: bool,
@ -704,12 +698,7 @@ fn fmt_binops<'a>(
loc_right_side.format_with_options(buf, Parens::InOperator, Newlines::Yes, indent); loc_right_side.format_with_options(buf, Parens::InOperator, Newlines::Yes, indent);
} }
fn format_spaces( fn format_spaces(buf: &mut Buf, spaces: &[CommentOrNewline], newlines: Newlines, indent: u16) {
buf: &mut Buf<'_>,
spaces: &[CommentOrNewline<'_>],
newlines: Newlines,
indent: u16,
) {
match newlines { match newlines {
Newlines::Yes => { Newlines::Yes => {
fmt_spaces(buf, spaces.iter(), indent); fmt_spaces(buf, spaces.iter(), indent);
@ -739,7 +728,7 @@ fn is_when_patterns_multiline(when_branch: &WhenBranch) -> bool {
} }
fn fmt_when<'a>( fn fmt_when<'a>(
buf: &mut Buf<'_>, buf: &mut Buf,
loc_condition: &'a Loc<Expr<'a>>, loc_condition: &'a Loc<Expr<'a>>,
branches: &[&'a WhenBranch<'a>], branches: &[&'a WhenBranch<'a>],
indent: u16, indent: u16,
@ -921,7 +910,7 @@ fn fmt_when<'a>(
} }
fn fmt_dbg<'a>( fn fmt_dbg<'a>(
buf: &mut Buf<'_>, buf: &mut Buf,
condition: &'a Loc<Expr<'a>>, condition: &'a Loc<Expr<'a>>,
continuation: &'a Loc<Expr<'a>>, continuation: &'a Loc<Expr<'a>>,
is_multiline: bool, is_multiline: bool,
@ -948,7 +937,7 @@ fn fmt_dbg<'a>(
} }
fn fmt_expect<'a>( fn fmt_expect<'a>(
buf: &mut Buf<'_>, buf: &mut Buf,
condition: &'a Loc<Expr<'a>>, condition: &'a Loc<Expr<'a>>,
continuation: &'a Loc<Expr<'a>>, continuation: &'a Loc<Expr<'a>>,
is_multiline: bool, is_multiline: bool,
@ -975,7 +964,7 @@ fn fmt_expect<'a>(
} }
fn fmt_if<'a>( fn fmt_if<'a>(
buf: &mut Buf<'_>, buf: &mut Buf,
branches: &'a [(Loc<Expr<'a>>, Loc<Expr<'a>>)], branches: &'a [(Loc<Expr<'a>>, Loc<Expr<'a>>)],
final_else: &'a Loc<Expr<'a>>, final_else: &'a Loc<Expr<'a>>,
is_multiline: bool, is_multiline: bool,
@ -1124,7 +1113,7 @@ fn fmt_if<'a>(
} }
fn fmt_closure<'a>( fn fmt_closure<'a>(
buf: &mut Buf<'_>, buf: &mut Buf,
loc_patterns: &'a [Loc<Pattern<'a>>], loc_patterns: &'a [Loc<Pattern<'a>>],
loc_ret: &'a Loc<Expr<'a>>, loc_ret: &'a Loc<Expr<'a>>,
indent: u16, indent: u16,
@ -1225,7 +1214,7 @@ fn fmt_closure<'a>(
} }
fn fmt_backpassing<'a>( fn fmt_backpassing<'a>(
buf: &mut Buf<'_>, buf: &mut Buf,
loc_patterns: &'a [Loc<Pattern<'a>>], loc_patterns: &'a [Loc<Pattern<'a>>],
loc_body: &'a Loc<Expr<'a>>, loc_body: &'a Loc<Expr<'a>>,
loc_ret: &'a Loc<Expr<'a>>, loc_ret: &'a Loc<Expr<'a>>,
@ -1313,7 +1302,7 @@ fn pattern_needs_parens_when_backpassing(pat: &Pattern) -> bool {
} }
fn fmt_record<'a>( fn fmt_record<'a>(
buf: &mut Buf<'_>, buf: &mut Buf,
update: Option<&'a Loc<Expr<'a>>>, update: Option<&'a Loc<Expr<'a>>>,
fields: Collection<'a, Loc<AssignedField<'a, Expr<'a>>>>, fields: Collection<'a, Loc<AssignedField<'a, Expr<'a>>>>,
indent: u16, indent: u16,
@ -1405,8 +1394,8 @@ fn fmt_record<'a>(
} }
fn format_field_multiline<T>( fn format_field_multiline<T>(
buf: &mut Buf<'_>, buf: &mut Buf,
field: &AssignedField<'_, T>, field: &AssignedField<T>,
indent: u16, indent: u16,
separator_prefix: &str, separator_prefix: &str,
) where ) where

View file

@ -88,7 +88,7 @@ impl<V: Formattable> Formattable for Option<V> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
parens: crate::annotation::Parens, parens: crate::annotation::Parens,
newlines: Newlines, newlines: Newlines,
indent: u16, indent: u16,
@ -113,7 +113,7 @@ impl<'a> Formattable for ProvidesTo<'a> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
_parens: crate::annotation::Parens, _parens: crate::annotation::Parens,
_newlines: Newlines, _newlines: Newlines,
indent: u16, indent: u16,
@ -132,7 +132,7 @@ impl<'a> Formattable for PlatformRequires<'a> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
_parens: crate::annotation::Parens, _parens: crate::annotation::Parens,
_newlines: Newlines, _newlines: Newlines,
indent: u16, indent: u16,
@ -148,7 +148,7 @@ impl<'a, V: Formattable> Formattable for Spaces<'a, V> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
parens: crate::annotation::Parens, parens: crate::annotation::Parens,
newlines: Newlines, newlines: Newlines,
indent: u16, indent: u16,
@ -164,20 +164,14 @@ impl<'a, K: Formattable, V: Formattable> Formattable for KeywordItem<'a, K, V> {
self.keyword.is_multiline() || self.item.is_multiline() self.keyword.is_multiline() || self.item.is_multiline()
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
parens: Parens,
newlines: Newlines,
indent: u16,
) {
self.keyword self.keyword
.format_with_options(buf, parens, newlines, indent); .format_with_options(buf, parens, newlines, indent);
self.item.format_with_options(buf, parens, newlines, indent); self.item.format_with_options(buf, parens, newlines, indent);
} }
} }
pub fn fmt_interface_header<'a>(buf: &mut Buf<'_>, header: &'a InterfaceHeader<'a>) { pub fn fmt_interface_header<'a>(buf: &mut Buf, header: &'a InterfaceHeader<'a>) {
buf.indent(0); buf.indent(0);
buf.push_str("interface"); buf.push_str("interface");
let indent = INDENT; let indent = INDENT;
@ -193,7 +187,7 @@ pub fn fmt_interface_header<'a>(buf: &mut Buf<'_>, header: &'a InterfaceHeader<'
fmt_imports(buf, header.imports.item, indent); fmt_imports(buf, header.imports.item, indent);
} }
pub fn fmt_hosted_header<'a>(buf: &mut Buf<'_>, header: &'a HostedHeader<'a>) { pub fn fmt_hosted_header<'a>(buf: &mut Buf, header: &'a HostedHeader<'a>) {
buf.indent(0); buf.indent(0);
buf.push_str("hosted"); buf.push_str("hosted");
let indent = INDENT; let indent = INDENT;
@ -210,7 +204,7 @@ pub fn fmt_hosted_header<'a>(buf: &mut Buf<'_>, header: &'a HostedHeader<'a>) {
fmt_exposes(buf, header.generates_with.item, indent); fmt_exposes(buf, header.generates_with.item, indent);
} }
pub fn fmt_app_header<'a>(buf: &mut Buf<'_>, header: &'a AppHeader<'a>) { pub fn fmt_app_header<'a>(buf: &mut Buf, header: &'a AppHeader<'a>) {
buf.indent(0); buf.indent(0);
buf.push_str("app"); buf.push_str("app");
let indent = INDENT; let indent = INDENT;
@ -229,7 +223,7 @@ pub fn fmt_app_header<'a>(buf: &mut Buf<'_>, header: &'a AppHeader<'a>) {
header.provides.format(buf, indent); header.provides.format(buf, indent);
} }
pub fn fmt_package_header<'a>(buf: &mut Buf<'_>, header: &'a PackageHeader<'a>) { pub fn fmt_package_header<'a>(buf: &mut Buf, header: &'a PackageHeader<'a>) {
buf.indent(0); buf.indent(0);
buf.push_str("package"); buf.push_str("package");
let indent = INDENT; let indent = INDENT;
@ -243,7 +237,7 @@ pub fn fmt_package_header<'a>(buf: &mut Buf<'_>, header: &'a PackageHeader<'a>)
fmt_packages(buf, header.packages.item, indent); fmt_packages(buf, header.packages.item, indent);
} }
pub fn fmt_platform_header<'a>(buf: &mut Buf<'_>, header: &'a PlatformHeader<'a>) { pub fn fmt_platform_header<'a>(buf: &mut Buf, header: &'a PlatformHeader<'a>) {
buf.indent(0); buf.indent(0);
buf.push_str("platform"); buf.push_str("platform");
let indent = INDENT; let indent = INDENT;
@ -262,7 +256,7 @@ pub fn fmt_platform_header<'a>(buf: &mut Buf<'_>, header: &'a PlatformHeader<'a>
fmt_provides(buf, header.provides.item, None, indent); fmt_provides(buf, header.provides.item, None, indent);
} }
fn fmt_requires(buf: &mut Buf<'_>, requires: &PlatformRequires<'_>, indent: u16) { fn fmt_requires(buf: &mut Buf, requires: &PlatformRequires, indent: u16) {
fmt_collection(buf, indent, Braces::Curly, requires.rigids, Newlines::No); fmt_collection(buf, indent, Braces::Curly, requires.rigids, Newlines::No);
buf.push_str(" {"); buf.push_str(" {");
@ -278,7 +272,7 @@ impl<'a> Formattable for TypedIdent<'a> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
_parens: Parens, _parens: Parens,
_newlines: Newlines, _newlines: Newlines,
indent: u16, indent: u16,
@ -293,7 +287,7 @@ impl<'a> Formattable for TypedIdent<'a> {
} }
} }
fn fmt_package_name(buf: &mut Buf<'_>, name: PackageName, indent: u16) { fn fmt_package_name(buf: &mut Buf, name: PackageName, indent: u16) {
buf.indent(indent); buf.indent(indent);
buf.push('"'); buf.push('"');
buf.push_str_allow_spaces(name.to_str()); buf.push_str_allow_spaces(name.to_str());
@ -314,7 +308,7 @@ impl<'a, T: Formattable> Formattable for Spaced<'a, T> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
parens: crate::annotation::Parens, parens: crate::annotation::Parens,
newlines: Newlines, newlines: Newlines,
indent: u16, indent: u16,
@ -336,7 +330,7 @@ impl<'a, T: Formattable> Formattable for Spaced<'a, T> {
} }
fn fmt_imports<'a>( fn fmt_imports<'a>(
buf: &mut Buf<'_>, buf: &mut Buf,
loc_entries: Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>, loc_entries: Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
indent: u16, indent: u16,
) { ) {
@ -344,7 +338,7 @@ fn fmt_imports<'a>(
} }
fn fmt_provides<'a>( fn fmt_provides<'a>(
buf: &mut Buf<'_>, buf: &mut Buf,
loc_exposed_names: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>, loc_exposed_names: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
loc_provided_types: Option<Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>>, loc_provided_types: Option<Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>>,
indent: u16, indent: u16,
@ -356,7 +350,7 @@ fn fmt_provides<'a>(
} }
} }
fn fmt_to(buf: &mut Buf<'_>, to: To, indent: u16) { fn fmt_to(buf: &mut Buf, to: To, indent: u16) {
match to { match to {
To::ExistingPackage(name) => { To::ExistingPackage(name) => {
buf.push_str(name); buf.push_str(name);
@ -366,7 +360,7 @@ fn fmt_to(buf: &mut Buf<'_>, to: To, indent: u16) {
} }
fn fmt_exposes<N: Formattable + Copy + core::fmt::Debug>( fn fmt_exposes<N: Formattable + Copy + core::fmt::Debug>(
buf: &mut Buf<'_>, buf: &mut Buf,
loc_entries: Collection<'_, Loc<Spaced<'_, N>>>, loc_entries: Collection<'_, Loc<Spaced<'_, N>>>,
indent: u16, indent: u16,
) { ) {
@ -374,17 +368,17 @@ fn fmt_exposes<N: Formattable + Copy + core::fmt::Debug>(
} }
pub trait FormatName { pub trait FormatName {
fn format(&self, buf: &mut Buf<'_>); fn format(&self, buf: &mut Buf);
} }
impl<'a> FormatName for &'a str { impl<'a> FormatName for &'a str {
fn format(&self, buf: &mut Buf<'_>) { fn format(&self, buf: &mut Buf) {
buf.push_str(self) buf.push_str(self)
} }
} }
impl<'a> FormatName for ModuleName<'a> { impl<'a> FormatName for ModuleName<'a> {
fn format(&self, buf: &mut Buf<'_>) { fn format(&self, buf: &mut Buf) {
buf.push_str(self.as_str()); buf.push_str(self.as_str());
} }
} }
@ -396,7 +390,7 @@ impl<'a> Formattable for ModuleName<'a> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
_parens: Parens, _parens: Parens,
_newlines: Newlines, _newlines: Newlines,
_indent: u16, _indent: u16,
@ -412,7 +406,7 @@ impl<'a> Formattable for ExposedName<'a> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
_parens: Parens, _parens: Parens,
_newlines: Newlines, _newlines: Newlines,
indent: u16, indent: u16,
@ -423,13 +417,13 @@ impl<'a> Formattable for ExposedName<'a> {
} }
impl<'a> FormatName for ExposedName<'a> { impl<'a> FormatName for ExposedName<'a> {
fn format(&self, buf: &mut Buf<'_>) { fn format(&self, buf: &mut Buf) {
buf.push_str(self.as_str()); buf.push_str(self.as_str());
} }
} }
fn fmt_packages<'a>( fn fmt_packages<'a>(
buf: &mut Buf<'_>, buf: &mut Buf,
loc_entries: Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>, loc_entries: Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>,
indent: u16, indent: u16,
) { ) {
@ -443,7 +437,7 @@ impl<'a> Formattable for PackageEntry<'a> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
_parens: Parens, _parens: Parens,
_newlines: Newlines, _newlines: Newlines,
indent: u16, indent: u16,
@ -459,7 +453,7 @@ impl<'a> Formattable for ImportsEntry<'a> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
_parens: Parens, _parens: Parens,
_newlines: Newlines, _newlines: Newlines,
indent: u16, indent: u16,
@ -467,14 +461,14 @@ impl<'a> Formattable for ImportsEntry<'a> {
fmt_imports_entry(buf, self, indent); fmt_imports_entry(buf, self, indent);
} }
} }
fn fmt_packages_entry(buf: &mut Buf<'_>, entry: &PackageEntry<'_>, indent: u16) { fn fmt_packages_entry(buf: &mut Buf, entry: &PackageEntry, indent: u16) {
buf.push_str(entry.shorthand); buf.push_str(entry.shorthand);
buf.push(':'); buf.push(':');
fmt_default_spaces(buf, entry.spaces_after_shorthand, indent); fmt_default_spaces(buf, entry.spaces_after_shorthand, indent);
fmt_package_name(buf, entry.package_name.value, indent); fmt_package_name(buf, entry.package_name.value, indent);
} }
fn fmt_imports_entry(buf: &mut Buf<'_>, entry: &ImportsEntry<'_>, indent: u16) { fn fmt_imports_entry(buf: &mut Buf, entry: &ImportsEntry, indent: u16) {
use roc_parse::header::ImportsEntry::*; use roc_parse::header::ImportsEntry::*;
buf.indent(indent); buf.indent(indent);

View file

@ -4,7 +4,7 @@ use crate::spaces::{fmt_comments_only, fmt_spaces, NewlineAt, INDENT};
use crate::Buf; use crate::Buf;
use roc_parse::ast::{Base, CommentOrNewline, Pattern, PatternAs}; use roc_parse::ast::{Base, CommentOrNewline, Pattern, PatternAs};
pub fn fmt_pattern<'a>(buf: &mut 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); pattern.format_with_options(buf, parens, Newlines::No, indent);
} }
@ -15,7 +15,7 @@ impl<'a> Formattable for PatternAs<'a> {
fn format_with_options( fn format_with_options(
&self, &self,
buf: &mut Buf<'_>, buf: &mut Buf,
_parens: Parens, _parens: Parens,
_newlines: Newlines, _newlines: Newlines,
indent: u16, indent: u16,
@ -80,13 +80,7 @@ impl<'a> Formattable for Pattern<'a> {
} }
} }
fn format_with_options( fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
&self,
buf: &mut Buf<'_>,
parens: Parens,
newlines: Newlines,
indent: u16,
) {
use self::Pattern::*; use self::Pattern::*;
match self { match self {

View file

@ -21,14 +21,14 @@ use crate::{Ast, Buf};
/// The number of spaces to indent. /// The number of spaces to indent.
pub const INDENT: u16 = 4; pub const INDENT: u16 = 4;
pub fn fmt_default_spaces(buf: &mut Buf<'_>, spaces: &[CommentOrNewline<'_>], indent: u16) { pub fn fmt_default_spaces(buf: &mut Buf, spaces: &[CommentOrNewline], indent: u16) {
if spaces.is_empty() { if spaces.is_empty() {
buf.spaces(1); buf.spaces(1);
} else { } else {
fmt_spaces(buf, spaces.iter(), indent); fmt_spaces(buf, spaces.iter(), indent);
} }
} }
pub fn fmt_default_newline(buf: &mut Buf<'_>, spaces: &[CommentOrNewline<'_>], indent: u16) { pub fn fmt_default_newline(buf: &mut Buf, spaces: &[CommentOrNewline], indent: u16) {
if spaces.is_empty() { if spaces.is_empty() {
buf.newline(); buf.newline();
} else { } else {
@ -145,7 +145,7 @@ pub fn fmt_comments_only<'a, 'buf, I>(
} }
} }
fn fmt_comment(buf: &mut 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, // The '#' in a comment should always be preceded by a newline or a space,
// unless it's the very beginning of the buffer. // unless it's the very beginning of the buffer.
if !buf.is_empty() && !buf.ends_with_space() && !buf.ends_with_newline() { if !buf.is_empty() && !buf.ends_with_space() && !buf.ends_with_newline() {
@ -184,7 +184,7 @@ where
count count
} }
fn fmt_docs(buf: &mut 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, // The "##" in a doc comment should always be preceded by a newline or a space,
// unless it's the very beginning of the buffer. // unless it's the very beginning of the buffer.
if !buf.is_empty() && !buf.ends_with_space() && !buf.ends_with_newline() { if !buf.is_empty() && !buf.ends_with_space() && !buf.ends_with_newline() {

View file

@ -522,6 +522,16 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
todo!("calling functions literal for AArch64"); todo!("calling functions literal for AArch64");
} }
#[inline(always)]
fn function_pointer(
_buf: &mut Vec<'_, u8>,
_relocs: &mut Vec<'_, Relocation>,
_fn_name: String,
_dst: AArch64GeneralReg,
) {
todo!("calling functions literal for AArch64");
}
#[inline(always)] #[inline(always)]
fn imul_reg64_reg64_reg64( fn imul_reg64_reg64_reg64(
buf: &mut Vec<'_, u8>, buf: &mut Vec<'_, u8>,
@ -1038,28 +1048,6 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
fcvt_freg64_freg32(buf, dst, src); fcvt_freg64_freg32(buf, dst, src);
} }
#[inline(always)]
fn lte_reg64_reg64_reg64(
buf: &mut Vec<'_, u8>,
dst: AArch64GeneralReg,
src1: AArch64GeneralReg,
src2: AArch64GeneralReg,
) {
cmp_reg64_reg64(buf, src1, src2);
cset_reg64_cond(buf, dst, ConditionCode::LE);
}
#[inline(always)]
fn gte_reg64_reg64_reg64(
buf: &mut Vec<'_, u8>,
dst: AArch64GeneralReg,
src1: AArch64GeneralReg,
src2: AArch64GeneralReg,
) {
cmp_reg64_reg64(buf, src1, src2);
cset_reg64_cond(buf, dst, ConditionCode::GE);
}
fn set_if_overflow(_buf: &mut Vec<'_, u8>, _dst: AArch64GeneralReg) { fn set_if_overflow(_buf: &mut Vec<'_, u8>, _dst: AArch64GeneralReg) {
todo!("set if overflow for AArch64"); todo!("set if overflow for AArch64");
} }

View file

@ -7,13 +7,15 @@ use roc_builtins::bitcode::{self, FloatWidth, IntWidth};
use roc_collections::all::MutMap; use roc_collections::all::MutMap;
use roc_error_macros::internal_error; use roc_error_macros::internal_error;
use roc_module::symbol::{Interns, ModuleId, Symbol}; 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::{ 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::{ use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout, Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout,
}; };
use roc_mono::low_level::HigherOrder;
use roc_target::TargetInfo; use roc_target::TargetInfo;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -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 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. /// Jumps by an offset of offset bytes unconditionally.
/// It should always generate the same number of bytes to enable replacement if offset changes. /// 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). /// It returns the base offset to calculate the jump from (generally the instruction after the jump).
@ -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 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 set_if_overflow(buf: &mut Vec<'_, u8>, dst: GeneralReg);
fn ret(buf: &mut Vec<'_, u8>); fn ret(buf: &mut Vec<'_, u8>);
@ -489,6 +484,7 @@ pub struct Backend64Bit<
interns: &'r mut Interns, interns: &'r mut Interns,
helper_proc_gen: CodeGenHelp<'a>, helper_proc_gen: CodeGenHelp<'a>,
helper_proc_symbols: Vec<'a, (Symbol, ProcLayout<'a>)>, helper_proc_symbols: Vec<'a, (Symbol, ProcLayout<'a>)>,
caller_procs: Vec<'a, CallerProc<'a>>,
buf: Vec<'a, u8>, buf: Vec<'a, u8>,
relocs: Vec<'a, Relocation>, relocs: Vec<'a, Relocation>,
proc_name: Option<String>, proc_name: Option<String>,
@ -526,6 +522,7 @@ pub fn new_backend_64bit<
layout_interner, layout_interner,
helper_proc_gen: CodeGenHelp::new(env.arena, target_info, env.module_id), helper_proc_gen: CodeGenHelp::new(env.arena, target_info, env.module_id),
helper_proc_symbols: bumpalo::vec![in env.arena], helper_proc_symbols: bumpalo::vec![in env.arena],
caller_procs: bumpalo::vec![in env.arena],
proc_name: None, proc_name: None,
is_self_recursive: None, is_self_recursive: None,
buf: bumpalo::vec![in env.arena], buf: bumpalo::vec![in env.arena],
@ -567,6 +564,9 @@ impl<
fn interns(&self) -> &Interns { fn interns(&self) -> &Interns {
self.interns self.interns
} }
fn interns_mut(&mut self) -> &mut Interns {
self.interns
}
fn interner(&self) -> &STLayoutInterner<'a> { fn interner(&self) -> &STLayoutInterner<'a> {
self.layout_interner self.layout_interner
} }
@ -577,12 +577,14 @@ impl<
&mut STLayoutInterner<'a>, &mut STLayoutInterner<'a>,
&mut Interns, &mut Interns,
&mut CodeGenHelp<'a>, &mut CodeGenHelp<'a>,
&mut Vec<'a, CallerProc<'a>>,
) { ) {
( (
self.env.module_id, self.env.module_id,
self.layout_interner, self.layout_interner,
self.interns, self.interns,
&mut self.helper_proc_gen, &mut self.helper_proc_gen,
&mut self.caller_procs,
) )
} }
fn helper_proc_gen_mut(&mut self) -> &mut CodeGenHelp<'a> { fn helper_proc_gen_mut(&mut self) -> &mut CodeGenHelp<'a> {
@ -738,6 +740,12 @@ impl<
(out.into_bump_slice(), offset) (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( fn build_fn_call(
&mut self, &mut self,
dst: &Symbol, dst: &Symbol,
@ -746,11 +754,6 @@ impl<
arg_layouts: &[InLayout<'a>], arg_layouts: &[InLayout<'a>],
ret_layout: &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. // Save used caller saved regs.
self.storage_manager self.storage_manager
.push_used_caller_saved_regs_to_stack(&mut self.buf); .push_used_caller_saved_regs_to_stack(&mut self.buf);
@ -1221,6 +1224,9 @@ impl<
.load_to_general_reg(&mut self.buf, src2); .load_to_general_reg(&mut self.buf, src2);
ASM::eq_reg64_reg64_reg64(&mut self.buf, width, dst_reg, src1_reg, src2_reg); 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 => { Layout::STR => {
// use a zig call // use a zig call
self.build_fn_call( self.build_fn_call(
@ -1241,7 +1247,33 @@ impl<
let dst_reg = self.storage_manager.load_to_general_reg(&mut self.buf, dst); 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); 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( fn build_num_to_frac(
&mut self, &mut self,
dst: &Symbol, 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( fn build_num_lte(
&mut self, &mut self,
dst: &Symbol, dst: &Symbol,
@ -1489,39 +1421,13 @@ impl<
src2: &Symbol, src2: &Symbol,
arg_layout: &InLayout<'a>, arg_layout: &InLayout<'a>,
) { ) {
match *arg_layout { self.compare(
single_register_int_builtins!() => { CompareOperation::LessThanOrEqual,
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst); dst,
let src1_reg = self src1,
.storage_manager src2,
.load_to_general_reg(&mut self.buf, src1); arg_layout,
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),
}
} }
fn build_num_gte( fn build_num_gte(
@ -1531,38 +1437,178 @@ impl<
src2: &Symbol, src2: &Symbol,
arg_layout: &InLayout<'a>, arg_layout: &InLayout<'a>,
) { ) {
match *arg_layout { self.compare(
single_register_int_builtins!() => { CompareOperation::GreaterThanOrEqual,
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst); dst,
let src1_reg = self src1,
.storage_manager src2,
.load_to_general_reg(&mut self.buf, src1); arg_layout,
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
};
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst); fn build_higher_order_lowlevel(
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1); &mut self,
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2); 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( let (inc_n_data_symbol, inc_n_data_linker_data) = self.helper_proc_gen.gen_refcount_proc(
&mut self.buf, ident_ids,
dst_reg, self.layout_interner,
src1_reg, Layout::UNIT,
src2_reg, HelperOp::Inc,
width, );
CompareOperation::GreaterThanOrEqual,
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 .storage_manager
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout)); .claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
let lowlevel_args = bumpalo::vec![ let lowlevel_args = [
in self.env.arena;
capacity, capacity,
// alignment // alignment
Symbol::DEV_TMP, Symbol::DEV_TMP,
// element_width // element_width
Symbol::DEV_TMP2, Symbol::DEV_TMP2,
]; ];
let lowlevel_arg_layouts = [capacity_layout, Layout::U32, Layout::U64]; let lowlevel_arg_layouts = [capacity_layout, Layout::U32, Layout::U64];
self.build_fn_call( self.build_fn_call(
@ -1727,14 +1772,13 @@ impl<
.storage_manager .storage_manager
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout)); .claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
let lowlevel_args = bumpalo::vec![ let lowlevel_args = [
in self.env.arena;
list, list,
// element // element
Symbol::DEV_TMP, Symbol::DEV_TMP,
// element_width // element_width
Symbol::DEV_TMP2 Symbol::DEV_TMP2,
]; ];
let lowlevel_arg_layouts = [list_layout, Layout::U64, Layout::U64]; let lowlevel_arg_layouts = [list_layout, Layout::U64, Layout::U64];
self.build_fn_call( self.build_fn_call(
@ -2004,8 +2048,7 @@ impl<
.storage_manager .storage_manager
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout)); .claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
let lowlevel_args = bumpalo::vec![ let lowlevel_args = [
in self.env.arena;
list, list,
// alignment // alignment
Symbol::DEV_TMP, Symbol::DEV_TMP,
@ -2013,7 +2056,7 @@ impl<
Symbol::DEV_TMP2, Symbol::DEV_TMP2,
// element_width // element_width
Symbol::DEV_TMP3, Symbol::DEV_TMP3,
]; ];
let lowlevel_arg_layouts = [list_layout, Layout::U32, Layout::U64, Layout::U64]; let lowlevel_arg_layouts = [list_layout, Layout::U32, Layout::U64, Layout::U64];
self.build_fn_call( self.build_fn_call(
@ -2195,27 +2238,16 @@ impl<
} }
} }
fn expr_box(&mut self, sym: Symbol, value: Symbol, element_layout: InLayout<'a>) { fn build_ptr_write(
let element_width_symbol = Symbol::DEV_TMP; &mut self,
self.load_layout_stack_size(element_layout, element_width_symbol); sym: Symbol,
ptr: Symbol,
// Load allocation alignment (u32) value: Symbol,
let element_alignment_symbol = Symbol::DEV_TMP2; element_layout: InLayout<'a>,
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
let ptr_reg = self let ptr_reg = self
.storage_manager .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_width = self.layout_interner.stack_size(element_layout) as u64;
let element_offset = 0; let element_offset = 0;
@ -2237,6 +2269,26 @@ impl<
// box is just a pointer on the stack // box is just a pointer on the stack
let base_offset = self.storage_manager.claim_stack_area(&sym, 8); let base_offset = self.storage_manager.claim_stack_area(&sym, 8);
ASM::mov_base32_reg64(&mut self.buf, base_offset, ptr_reg); 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); self.free_symbol(&Symbol::DEV_TMP3);
} }
@ -2662,6 +2714,28 @@ impl<
FloatWidth::F64 => ASM::sqrt_freg64_freg64(buf, dst_reg, src_reg), 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. /// This impl block is for ir related instructions that need backend specific information.
@ -2675,6 +2749,61 @@ impl<
CC: CallConv<GeneralReg, FloatReg, ASM>, CC: CallConv<GeneralReg, FloatReg, ASM>,
> Backend64Bit<'a, 'r, GeneralReg, FloatReg, ASM, CC> > 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( fn allocate_with_refcount(
&mut self, &mut self,
dst: Symbol, dst: Symbol,
@ -2709,6 +2838,62 @@ impl<
ASM::mov_base32_reg64(buf, base_offset + 16, tmp_reg); 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( fn ptr_read(
buf: &mut Vec<'a, u8>, buf: &mut Vec<'a, u8>,
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>, 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); 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)), _ => todo!("unboxing of {:?}", layout_interner.dbg(element_in_layout)),
} }
} }

View file

@ -654,7 +654,15 @@ impl<
} }
let base_offset = self.claim_stack_area(sym, struct_size); 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; let mut current_offset = base_offset;
for (field, field_layout) in fields.iter().zip(field_layouts.iter()) { for (field, field_layout) in fields.iter().zip(field_layouts.iter()) {
self.copy_symbol_to_stack_offset( self.copy_symbol_to_stack_offset(
@ -670,7 +678,13 @@ impl<
} else { } else {
// This is a single element struct. Just copy the single field to the stack. // This is a single element struct. Just copy the single field to the stack.
debug_assert_eq!(fields.len(), 1); 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,
);
} }
} }

View file

@ -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)] #[inline(always)]
fn imul_reg64_reg64_reg64( fn imul_reg64_reg64_reg64(
buf: &mut Vec<'_, u8>, buf: &mut Vec<'_, u8>,
@ -1607,17 +1622,13 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
src1: X86_64GeneralReg, src1: X86_64GeneralReg,
src2: X86_64GeneralReg, src2: X86_64GeneralReg,
) { ) {
cmp_reg64_reg64(buf, register_width, src1, src2);
match operation { match operation {
CompareOperation::LessThan => { CompareOperation::LessThan => setl_reg64(buf, dst),
cmp_reg64_reg64(buf, register_width, src1, src2); CompareOperation::LessThanOrEqual => setle_reg64(buf, dst),
setl_reg64(buf, dst); CompareOperation::GreaterThan => setg_reg64(buf, dst),
} CompareOperation::GreaterThanOrEqual => setge_reg64(buf, dst),
CompareOperation::LessThanOrEqual => todo!(),
CompareOperation::GreaterThan => {
cmp_reg64_reg64(buf, register_width, src1, src2);
setg_reg64(buf, dst);
}
CompareOperation::GreaterThanOrEqual => todo!(),
} }
} }
@ -1629,18 +1640,13 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
src1: X86_64GeneralReg, src1: X86_64GeneralReg,
src2: X86_64GeneralReg, src2: X86_64GeneralReg,
) { ) {
match operation { cmp_reg64_reg64(buf, register_width, src1, src2);
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);
}
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); 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)] #[inline(always)]
fn ret(buf: &mut Vec<'_, u8>) { fn ret(buf: &mut Vec<'_, u8>) {
ret(buf); ret(buf);
@ -1782,9 +1766,9 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
} }
} }
fn shift_reg64_reg64_reg64<'a, 'r, ASM, CC>( fn shift_reg64_reg64_reg64<'a, ASM, CC>(
buf: &mut Vec<'a, u8>, 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>,
shift_function: fn(buf: &mut Vec<'_, u8>, X86_64GeneralReg), shift_function: fn(buf: &mut Vec<'_, u8>, X86_64GeneralReg),
dst: X86_64GeneralReg, dst: X86_64GeneralReg,
src1: X86_64GeneralReg, src1: 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. /// `MOV r/m64,r64` -> Move r64 to r/m64.
/// This will not generate anything if dst and src are the same. /// This will not generate anything if dst and src are the same.
#[inline(always)] #[inline(always)]
@ -2959,7 +2962,13 @@ fn setae_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
set_reg64_help(0x93, buf, reg); 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)] #[inline(always)]
fn setle_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) { fn setle_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
set_reg64_help(0x9e, buf, reg); 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] #[test]
fn test_mov_reg64_reg64() { fn test_mov_reg64_reg64() {
disassembler_test!( disassembler_test!(
@ -3764,8 +3782,8 @@ mod tests {
cmp_reg64_reg64, cmp_reg64_reg64,
|_, dst: X86_64GeneralReg, src: X86_64GeneralReg| format!( |_, dst: X86_64GeneralReg, src: X86_64GeneralReg| format!(
"cmp {}, {}", "cmp {}, {}",
dbg!(dst.low_16bits_string()), dst.low_16bits_string(),
dbg!(src.low_16bits_string()) src.low_16bits_string()
), ),
[RegisterWidth::W16], [RegisterWidth::W16],
ALL_GENERAL_REGS, ALL_GENERAL_REGS,
@ -3776,8 +3794,8 @@ mod tests {
cmp_reg64_reg64, cmp_reg64_reg64,
|_, dst: X86_64GeneralReg, src: X86_64GeneralReg| format!( |_, dst: X86_64GeneralReg, src: X86_64GeneralReg| format!(
"cmp {}, {}", "cmp {}, {}",
dbg!(dst.low_32bits_string()), dst.low_32bits_string(),
dbg!(src.low_32bits_string()) src.low_32bits_string()
), ),
[RegisterWidth::W32], [RegisterWidth::W32],
ALL_GENERAL_REGS, ALL_GENERAL_REGS,

View file

@ -12,10 +12,10 @@ use roc_error_macros::internal_error;
use roc_module::ident::ModuleName; use roc_module::ident::ModuleName;
use roc_module::low_level::{LowLevel, LowLevelWrapperType}; use roc_module::low_level::{LowLevel, LowLevelWrapperType};
use roc_module::symbol::{Interns, ModuleId, Symbol}; 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::{ use roc_mono::ir::{
BranchInfo, CallType, Expr, JoinPointId, ListLiteralElement, Literal, Param, Proc, ProcLayout, BranchInfo, CallType, Expr, HigherOrderLowLevel, JoinPointId, ListLiteralElement, Literal,
SelfRecursive, Stmt, Param, Proc, ProcLayout, SelfRecursive, Stmt,
}; };
use roc_mono::layout::{ use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, TagIdIntType, Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, TagIdIntType,
@ -65,8 +65,21 @@ pub enum Relocation {
trait Backend<'a> { trait Backend<'a> {
fn env(&self) -> &Env<'a>; fn env(&self) -> &Env<'a>;
fn interns(&self) -> &Interns; fn interns(&self) -> &Interns;
fn interns_mut(&mut self) -> &mut Interns;
fn interner(&self) -> &STLayoutInterner<'a>; 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 // 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, // 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. // rust understands that they are part of a single use of mutable self.
@ -77,6 +90,7 @@ trait Backend<'a> {
&mut STLayoutInterner<'a>, &mut STLayoutInterner<'a>,
&mut Interns, &mut Interns,
&mut CodeGenHelp<'a>, &mut CodeGenHelp<'a>,
&mut Vec<'a, CallerProc<'a>>,
); );
fn function_symbol_to_string<'b, I>( 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 // 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. // for it. Here we don't create linker symbols at this time, but in Wasm backend, we do.
let (rc_stmt, new_specializations) = { 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(); self.module_interns_helpers_mut();
let ident_ids = interns.all_ident_ids.get_mut(&module_id).unwrap(); let ident_ids = interns.all_ident_ids.get_mut(&module_id).unwrap();
@ -329,7 +343,7 @@ trait Backend<'a> {
arg_layouts, arg_layouts,
ret_layout, 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 // These builtins can be built through `build_fn_call` as well, but the
// implementation in `build_builtin` inlines some of the symbols. // implementation in `build_builtin` inlines some of the symbols.
return self.build_builtin( return self.build_builtin(
@ -373,6 +387,9 @@ trait Backend<'a> {
layout, layout,
) )
} }
CallType::HigherOrder(higher_order) => {
self.build_higher_order_lowlevel(sym, higher_order, *layout)
}
x => todo!("the call type, {:?}", x), x => todo!("the call type, {:?}", x),
} }
} }
@ -486,6 +503,22 @@ trait Backend<'a> {
); );
self.build_num_add(sym, &args[0], &args[1], ret_layout) 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 => { LowLevel::NumAddChecked => {
self.build_num_add_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout) 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]) 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( LowLevel::RefCountDec => self.build_fn_call(
sym, sym,
bitcode::UTILS_DECREF.to_string(), bitcode::UTILS_DECREF.to_string(),
@ -1084,6 +1125,34 @@ trait Backend<'a> {
arg_layouts, arg_layouts,
ret_layout, 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), x => todo!("low level, {:?}", x),
} }
} }
@ -1133,16 +1202,24 @@ trait Backend<'a> {
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout) self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
} }
Symbol::BOOL_TRUE => { Symbol::BOOL_TRUE => {
let bool_layout = Layout::BOOL; const LITERAL: &Literal<'static> = &Literal::Bool(true);
self.load_literal(&Symbol::DEV_TMP, &bool_layout, &Literal::Bool(true)); const BOOL_LAYOUT: &InLayout<'static> = &Layout::BOOL;
self.return_symbol(&Symbol::DEV_TMP, &bool_layout);
self.free_symbol(&Symbol::DEV_TMP) if self.env().lazy_literals {
self.literal_map().insert(*sym, (LITERAL, BOOL_LAYOUT));
} else {
self.load_literal(sym, BOOL_LAYOUT, LITERAL);
}
} }
Symbol::BOOL_FALSE => { Symbol::BOOL_FALSE => {
let bool_layout = Layout::BOOL; const LITERAL: &Literal<'static> = &Literal::Bool(false);
self.load_literal(&Symbol::DEV_TMP, &bool_layout, &Literal::Bool(false)); const BOOL_LAYOUT: &InLayout<'static> = &Layout::BOOL;
self.return_symbol(&Symbol::DEV_TMP, &bool_layout);
self.free_symbol(&Symbol::DEV_TMP) 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 => { Symbol::STR_IS_VALID_SCALAR => {
// just call the function // just call the function
@ -1184,9 +1261,20 @@ trait Backend<'a> {
ret_layout: &InLayout<'a>, ret_layout: &InLayout<'a>,
); );
fn build_fn_pointer(&mut self, dst: &Symbol, fn_name: String);
/// Move a returned value into `dst` /// Move a returned value into `dst`
fn move_return_value(&mut self, dst: &Symbol, ret_layout: &InLayout<'a>); 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. /// build_num_abs stores the absolute value of src into dst.
fn build_num_abs(&mut self, dst: &Symbol, src: &Symbol, layout: &InLayout<'a>); 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. /// build_list_len returns the length of a list.
fn build_list_len(&mut self, dst: &Symbol, list: &Symbol); 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. /// build_list_with_capacity creates and returns a list with the given capacity.
fn build_list_with_capacity( fn build_list_with_capacity(
&mut self, &mut self,
@ -1416,6 +1512,14 @@ trait Backend<'a> {
/// build_refcount_getptr loads the pointer to the reference count of src into dst. /// 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_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. /// 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>)>; fn literal_map(&mut self) -> &mut MutMap<Symbol, (*const Literal<'a>, *const InLayout<'a>)>;

View file

@ -246,10 +246,16 @@ fn build_object<'a, B: Backend<'a>>(
// Generate IR for specialized helper procs (refcounting & equality) // Generate IR for specialized helper procs (refcounting & equality)
let helper_procs = { 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 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); module_id.register_debug_idents(ident_ids);
helper_procs helper_procs

View file

@ -24,8 +24,8 @@ use roc_mono::layout::{
use super::build::{create_entry_block_alloca, BuilderExt}; use super::build::{create_entry_block_alloca, BuilderExt};
use super::convert::zig_list_type; use super::convert::zig_list_type;
pub fn call_bitcode_fn<'a, 'ctx, 'env>( pub fn call_bitcode_fn<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
args: &[BasicValueEnum<'ctx>], args: &[BasicValueEnum<'ctx>],
fn_name: &str, fn_name: &str,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
@ -40,8 +40,8 @@ pub fn call_bitcode_fn<'a, 'ctx, 'env>(
}) })
} }
pub fn call_void_bitcode_fn<'a, 'ctx, 'env>( pub fn call_void_bitcode_fn<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
args: &[BasicValueEnum<'ctx>], args: &[BasicValueEnum<'ctx>],
fn_name: &str, fn_name: &str,
) -> InstructionValue<'ctx> { ) -> InstructionValue<'ctx> {
@ -51,8 +51,8 @@ pub fn call_void_bitcode_fn<'a, 'ctx, 'env>(
.unwrap_or_else(|| panic!("LLVM error: Tried to call void bitcode function, but got return value from bitcode function, {:?}", fn_name)) .unwrap_or_else(|| panic!("LLVM error: Tried to call void bitcode function, but got return value from bitcode function, {:?}", fn_name))
} }
fn call_bitcode_fn_help<'a, 'ctx, 'env>( fn call_bitcode_fn_help<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
args: &[BasicValueEnum<'ctx>], args: &[BasicValueEnum<'ctx>],
fn_name: &str, fn_name: &str,
) -> CallSiteValue<'ctx> { ) -> CallSiteValue<'ctx> {
@ -165,8 +165,8 @@ const ARGUMENT_SYMBOLS: [Symbol; 8] = [
Symbol::ARG_8, Symbol::ARG_8,
]; ];
pub(crate) fn build_transform_caller<'a, 'ctx, 'env>( pub(crate) fn build_transform_caller<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
function: FunctionValue<'ctx>, function: FunctionValue<'ctx>,
closure_data_layout: LambdaSet<'a>, closure_data_layout: LambdaSet<'a>,
@ -192,8 +192,8 @@ pub(crate) fn build_transform_caller<'a, 'ctx, 'env>(
} }
} }
fn build_transform_caller_help<'a, 'ctx, 'env>( fn build_transform_caller_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>,
closure_data_layout: LambdaSet<'a>, closure_data_layout: LambdaSet<'a>,
@ -322,8 +322,8 @@ enum Mode {
} }
/// a function that accepts two arguments: the value to increment, and an amount to increment by /// a function that accepts two arguments: the value to increment, and an amount to increment by
pub fn build_inc_n_wrapper<'a, 'ctx, 'env>( pub fn build_inc_n_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
@ -332,8 +332,8 @@ pub fn build_inc_n_wrapper<'a, 'ctx, 'env>(
} }
/// a function that accepts two arguments: the value to increment; increments by 1 /// a function that accepts two arguments: the value to increment; increments by 1
pub fn build_inc_wrapper<'a, 'ctx, 'env>( pub fn build_inc_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
@ -341,8 +341,8 @@ pub fn build_inc_wrapper<'a, 'ctx, 'env>(
build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::Inc) build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::Inc)
} }
pub fn build_dec_wrapper<'a, 'ctx, 'env>( pub fn build_dec_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
@ -350,8 +350,8 @@ pub fn build_dec_wrapper<'a, 'ctx, 'env>(
build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::Dec) build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::Dec)
} }
fn build_rc_wrapper<'a, 'ctx, 'env>( fn build_rc_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
@ -453,8 +453,8 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
function_value function_value
} }
pub fn build_eq_wrapper<'a, 'ctx, 'env>( pub fn build_eq_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
@ -536,8 +536,8 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>(
function_value function_value
} }
pub fn build_compare_wrapper<'a, 'ctx, 'env>( pub fn build_compare_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
roc_function: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>,
@ -705,9 +705,9 @@ impl BitcodeReturns {
} }
} }
fn return_value_64bit<'a, 'ctx, 'env>( fn return_value_64bit<'a, 'ctx>(
&self, &self,
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
arguments: &mut bumpalo::collections::Vec<'a, BasicValueEnum<'ctx>>, arguments: &mut bumpalo::collections::Vec<'a, BasicValueEnum<'ctx>>,
) -> BitcodeReturnValue<'ctx> { ) -> BitcodeReturnValue<'ctx> {
match self { match self {
@ -746,9 +746,9 @@ impl BitcodeReturns {
} }
} }
fn call_and_load_32bit<'a, 'ctx, 'env>( fn call_and_load_32bit<'ctx>(
&self, &self,
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
arguments: &[BasicValueEnum<'ctx>], arguments: &[BasicValueEnum<'ctx>],
fn_name: &str, fn_name: &str,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
@ -764,8 +764,8 @@ impl BitcodeReturns {
} }
} }
fn ptr_len_cap<'a, 'ctx, 'env>( fn ptr_len_cap<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
value: StructValue<'ctx>, value: StructValue<'ctx>,
) -> (PointerValue<'ctx>, IntValue<'ctx>, IntValue<'ctx>) { ) -> (PointerValue<'ctx>, IntValue<'ctx>, IntValue<'ctx>) {
let ptr_and_len = env let ptr_and_len = env
@ -808,8 +808,8 @@ fn ptr_len_cap<'a, 'ctx, 'env>(
} }
/// Converts the { i64, i32 } struct that zig returns into `list.RocList = type { i8*, i32, i32 }` /// Converts the { i64, i32 } struct that zig returns into `list.RocList = type { i8*, i32, i32 }`
fn receive_zig_roc_list_32bit<'a, 'ctx, 'env>( fn receive_zig_roc_list_32bit<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
value: StructValue<'ctx>, value: StructValue<'ctx>,
) -> StructValue<'ctx> { ) -> StructValue<'ctx> {
let list_type = super::convert::zig_list_type(env); let list_type = super::convert::zig_list_type(env);
@ -824,8 +824,8 @@ fn receive_zig_roc_list_32bit<'a, 'ctx, 'env>(
} }
/// Converts the { i64, i32 } struct that zig returns into `list.RocList = type { i8*, i32, i32 }` /// Converts the { i64, i32 } struct that zig returns into `list.RocList = type { i8*, i32, i32 }`
fn receive_zig_roc_str_32bit<'a, 'ctx, 'env>( fn receive_zig_roc_str_32bit<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
value: StructValue<'ctx>, value: StructValue<'ctx>,
) -> StructValue<'ctx> { ) -> StructValue<'ctx> {
let str_type = super::convert::zig_str_type(env); let str_type = super::convert::zig_str_type(env);
@ -839,8 +839,8 @@ fn receive_zig_roc_str_32bit<'a, 'ctx, 'env>(
) )
} }
pub(crate) fn pass_list_to_zig_64bit<'a, 'ctx, 'env>( pub(crate) fn pass_list_to_zig_64bit<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
list: BasicValueEnum<'ctx>, list: BasicValueEnum<'ctx>,
) -> PointerValue<'ctx> { ) -> PointerValue<'ctx> {
let parent = env let parent = env
@ -857,16 +857,16 @@ pub(crate) fn pass_list_to_zig_64bit<'a, 'ctx, 'env>(
list_alloca list_alloca
} }
fn pass_string_to_zig_64bit<'a, 'ctx, 'env>( fn pass_string_to_zig_64bit<'ctx>(
_env: &Env<'a, 'ctx, 'env>, _env: &Env<'_, 'ctx, '_>,
string: BasicValueEnum<'ctx>, string: BasicValueEnum<'ctx>,
) -> PointerValue<'ctx> { ) -> PointerValue<'ctx> {
// we must pass strings by-pointer, and that is already how they are stored // we must pass strings by-pointer, and that is already how they are stored
string.into_pointer_value() string.into_pointer_value()
} }
pub(crate) fn pass_list_or_string_to_zig_32bit<'a, 'ctx, 'env>( pub(crate) fn pass_list_or_string_to_zig_32bit<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
list_or_string: StructValue<'ctx>, list_or_string: StructValue<'ctx>,
) -> (IntValue<'ctx>, IntValue<'ctx>) { ) -> (IntValue<'ctx>, IntValue<'ctx>) {
let ptr = env let ptr = env
@ -907,8 +907,8 @@ pub(crate) fn pass_list_or_string_to_zig_32bit<'a, 'ctx, 'env>(
(ptr_len, cap) (ptr_len, cap)
} }
pub(crate) fn call_str_bitcode_fn<'a, 'ctx, 'env>( pub(crate) fn call_str_bitcode_fn<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
strings: &[BasicValueEnum<'ctx>], strings: &[BasicValueEnum<'ctx>],
other_arguments: &[BasicValueEnum<'ctx>], other_arguments: &[BasicValueEnum<'ctx>],
returns: BitcodeReturns, returns: BitcodeReturns,
@ -948,8 +948,8 @@ pub(crate) fn call_str_bitcode_fn<'a, 'ctx, 'env>(
} }
} }
pub(crate) fn call_list_bitcode_fn<'a, 'ctx, 'env>( pub(crate) fn call_list_bitcode_fn<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
lists: &[StructValue<'ctx>], lists: &[StructValue<'ctx>],
other_arguments: &[BasicValueEnum<'ctx>], other_arguments: &[BasicValueEnum<'ctx>],
returns: BitcodeReturns, returns: BitcodeReturns,

View file

@ -614,8 +614,8 @@ pub fn construct_optimization_passes<'a>(
(mpm, fpm) (mpm, fpm)
} }
fn promote_to_main_function<'a, 'ctx, 'env>( fn promote_to_main_function<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
mod_solutions: &'a ModSolutions, mod_solutions: &'a ModSolutions,
symbol: Symbol, symbol: Symbol,
@ -653,8 +653,8 @@ fn promote_to_main_function<'a, 'ctx, 'env>(
(main_fn_name, main_fn) (main_fn_name, main_fn)
} }
fn promote_to_wasm_test_wrapper<'a, 'ctx, 'env>( fn promote_to_wasm_test_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
mod_solutions: &'a ModSolutions, mod_solutions: &'a ModSolutions,
symbol: Symbol, symbol: Symbol,
@ -746,8 +746,8 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx, 'env>(
(main_fn_name, main_fn) (main_fn_name, main_fn)
} }
fn int_with_precision<'a, 'ctx, 'env>( fn int_with_precision<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
value: i128, value: i128,
int_width: IntWidth, int_width: IntWidth,
) -> IntValue<'ctx> { ) -> IntValue<'ctx> {
@ -762,8 +762,8 @@ fn int_with_precision<'a, 'ctx, 'env>(
} }
} }
fn float_with_precision<'a, 'ctx, 'env>( fn float_with_precision<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
value: f64, value: f64,
float_width: FloatWidth, float_width: FloatWidth,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
@ -773,8 +773,8 @@ fn float_with_precision<'a, 'ctx, 'env>(
} }
} }
pub fn build_exp_literal<'a, 'ctx, 'env>( pub fn build_exp_literal<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &STLayoutInterner<'a>, layout_interner: &STLayoutInterner<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
layout: InLayout<'_>, layout: InLayout<'_>,
@ -817,8 +817,8 @@ pub fn build_exp_literal<'a, 'ctx, 'env>(
} }
} }
fn build_string_literal<'a, 'ctx, 'env>( fn build_string_literal<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
str_literal: &str, str_literal: &str,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
@ -844,8 +844,8 @@ fn build_string_literal<'a, 'ctx, 'env>(
} }
} }
fn const_str_alloca_ptr<'a, 'ctx, 'env>( fn const_str_alloca_ptr<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,
len: IntValue<'ctx>, len: IntValue<'ctx>,
@ -862,8 +862,8 @@ fn const_str_alloca_ptr<'a, 'ctx, 'env>(
alloca alloca
} }
fn small_str_ptr_width_8<'a, 'ctx, 'env>( fn small_str_ptr_width_8<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
str_literal: &str, str_literal: &str,
) -> PointerValue<'ctx> { ) -> PointerValue<'ctx> {
@ -890,10 +890,7 @@ fn small_str_ptr_width_8<'a, 'ctx, 'env>(
const_str_alloca_ptr(env, parent, ptr, len, cap) const_str_alloca_ptr(env, parent, ptr, len, cap)
} }
fn small_str_ptr_width_4<'a, 'ctx, 'env>( fn small_str_ptr_width_4<'ctx>(env: &Env<'_, 'ctx, '_>, str_literal: &str) -> StructValue<'ctx> {
env: &Env<'a, 'ctx, 'env>,
str_literal: &str,
) -> StructValue<'ctx> {
debug_assert_eq!(env.target_info.ptr_width() as u8, 4); debug_assert_eq!(env.target_info.ptr_width() as u8, 4);
let mut array = [0u8; 12]; let mut array = [0u8; 12];
@ -921,8 +918,8 @@ fn small_str_ptr_width_4<'a, 'ctx, 'env>(
) )
} }
pub fn build_exp_call<'a, 'ctx, 'env>( pub fn build_exp_call<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
func_spec_solutions: &FuncSpecSolutions, func_spec_solutions: &FuncSpecSolutions,
@ -1068,8 +1065,8 @@ fn struct_pointer_from_fields<'a, 'ctx, 'env, I>(
} }
} }
pub fn build_exp_expr<'a, 'ctx, 'env>( pub fn build_exp_expr<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
func_spec_solutions: &FuncSpecSolutions, func_spec_solutions: &FuncSpecSolutions,
@ -1489,8 +1486,8 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
} }
} }
fn build_wrapped_tag<'a, 'ctx, 'env>( fn build_wrapped_tag<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
scope: &Scope<'a, 'ctx>, scope: &Scope<'a, 'ctx>,
union_layout: &UnionLayout<'a>, union_layout: &UnionLayout<'a>,
@ -1568,8 +1565,8 @@ fn build_wrapped_tag<'a, 'ctx, 'env>(
} }
} }
pub fn entry_block_alloca_zerofill<'a, 'ctx, 'env>( pub fn entry_block_alloca_zerofill<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
basic_type: BasicTypeEnum<'ctx>, basic_type: BasicTypeEnum<'ctx>,
name: &str, name: &str,
) -> PointerValue<'ctx> { ) -> PointerValue<'ctx> {
@ -1583,8 +1580,8 @@ pub fn entry_block_alloca_zerofill<'a, 'ctx, 'env>(
create_entry_block_alloca(env, parent, basic_type, name) create_entry_block_alloca(env, parent, basic_type, name)
} }
fn build_tag_field_value<'a, 'ctx, 'env>( fn build_tag_field_value<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
value: BasicValueEnum<'ctx>, value: BasicValueEnum<'ctx>,
tag_field_layout: InLayout<'a>, tag_field_layout: InLayout<'a>,
@ -1643,8 +1640,8 @@ fn build_tag_fields<'a, 'r, 'ctx, 'env>(
(field_types, field_values) (field_types, field_values)
} }
fn build_struct<'a, 'ctx, 'env>( fn build_struct<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
scope: &Scope<'a, 'ctx>, scope: &Scope<'a, 'ctx>,
sorted_fields: &[Symbol], sorted_fields: &[Symbol],
@ -1685,8 +1682,8 @@ fn build_struct<'a, 'ctx, 'env>(
struct_from_fields(env, struct_type, field_vals.into_iter().enumerate()) struct_from_fields(env, struct_type, field_vals.into_iter().enumerate())
} }
fn build_tag<'a, 'ctx, 'env>( fn build_tag<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
scope: &Scope<'a, 'ctx>, scope: &Scope<'a, 'ctx>,
union_layout: &UnionLayout<'a>, union_layout: &UnionLayout<'a>,
@ -1844,8 +1841,8 @@ fn build_tag<'a, 'ctx, 'env>(
} }
} }
fn tag_pointer_set_tag_id<'a, 'ctx, 'env>( fn tag_pointer_set_tag_id<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
tag_id: u8, tag_id: u8,
pointer: PointerValue<'ctx>, pointer: PointerValue<'ctx>,
) -> PointerValue<'ctx> { ) -> PointerValue<'ctx> {
@ -1870,8 +1867,8 @@ pub fn tag_pointer_tag_id_bits_and_mask(target_info: TargetInfo) -> (u64, u64) {
} }
} }
pub fn tag_pointer_read_tag_id<'a, 'ctx, 'env>( pub fn tag_pointer_read_tag_id<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>, pointer: PointerValue<'ctx>,
) -> IntValue<'ctx> { ) -> IntValue<'ctx> {
let (_, mask) = tag_pointer_tag_id_bits_and_mask(env.target_info); let (_, mask) = tag_pointer_tag_id_bits_and_mask(env.target_info);
@ -1886,8 +1883,8 @@ pub fn tag_pointer_read_tag_id<'a, 'ctx, 'env>(
.build_int_cast_sign_flag(masked, env.context.i8_type(), false, "to_u8") .build_int_cast_sign_flag(masked, env.context.i8_type(), false, "to_u8")
} }
pub fn tag_pointer_clear_tag_id<'a, 'ctx, 'env>( pub fn tag_pointer_clear_tag_id<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>, pointer: PointerValue<'ctx>,
) -> PointerValue<'ctx> { ) -> PointerValue<'ctx> {
let ptr_int = env.ptr_int(); let ptr_int = env.ptr_int();
@ -1908,8 +1905,8 @@ pub fn tag_pointer_clear_tag_id<'a, 'ctx, 'env>(
.build_int_to_ptr(masked, pointer.get_type(), "to_ptr") .build_int_to_ptr(masked, pointer.get_type(), "to_ptr")
} }
fn allocate_tag<'a, 'ctx, 'env>( fn allocate_tag<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
reuse_allocation: Option<PointerValue<'ctx>>, reuse_allocation: Option<PointerValue<'ctx>>,
@ -1968,8 +1965,8 @@ fn allocate_tag<'a, 'ctx, 'env>(
} }
} }
pub fn get_tag_id<'a, 'ctx, 'env>( pub fn get_tag_id<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
union_layout: &UnionLayout<'a>, union_layout: &UnionLayout<'a>,
@ -2051,8 +2048,8 @@ pub fn get_tag_id<'a, 'ctx, 'env>(
} }
} }
fn lookup_at_index_ptr<'a, 'ctx, 'env>( fn lookup_at_index_ptr<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
field_layouts: &[InLayout<'a>], field_layouts: &[InLayout<'a>],
index: usize, index: usize,
@ -2086,8 +2083,8 @@ fn lookup_at_index_ptr<'a, 'ctx, 'env>(
cast_if_necessary_for_opaque_recursive_pointers(env.builder, result, target_loaded_type) cast_if_necessary_for_opaque_recursive_pointers(env.builder, result, target_loaded_type)
} }
fn lookup_at_index_ptr2<'a, 'ctx, 'env>( fn lookup_at_index_ptr2<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
field_layouts: &'a [InLayout<'a>], field_layouts: &'a [InLayout<'a>],
index: usize, index: usize,
@ -2129,8 +2126,8 @@ fn lookup_at_index_ptr2<'a, 'ctx, 'env>(
cast_if_necessary_for_opaque_recursive_pointers(env.builder, result, target_loaded_type) cast_if_necessary_for_opaque_recursive_pointers(env.builder, result, target_loaded_type)
} }
pub fn reserve_with_refcount<'a, 'ctx, 'env>( pub fn reserve_with_refcount<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
) -> PointerValue<'ctx> { ) -> PointerValue<'ctx> {
@ -2142,8 +2139,8 @@ pub fn reserve_with_refcount<'a, 'ctx, 'env>(
reserve_with_refcount_help(env, basic_type, stack_size, alignment_bytes) reserve_with_refcount_help(env, basic_type, stack_size, alignment_bytes)
} }
fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx, 'env>( fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
union_layout: UnionLayout<'a>, union_layout: UnionLayout<'a>,
fields: &[&[InLayout<'a>]], fields: &[&[InLayout<'a>]],
@ -2177,8 +2174,8 @@ fn reserve_with_refcount_help<'a, 'ctx, 'env>(
allocate_with_refcount_help(env, basic_type, alignment_bytes, value_bytes_intvalue) allocate_with_refcount_help(env, basic_type, alignment_bytes, value_bytes_intvalue)
} }
pub fn allocate_with_refcount<'a, 'ctx, 'env>( pub fn allocate_with_refcount<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
value: BasicValueEnum<'ctx>, value: BasicValueEnum<'ctx>,
@ -2213,8 +2210,8 @@ pub fn allocate_with_refcount_help<'a, 'ctx, 'env>(
.build_pointer_cast(ptr, ptr_type, "alloc_cast_to_desired") .build_pointer_cast(ptr, ptr_type, "alloc_cast_to_desired")
} }
fn list_literal<'a, 'ctx, 'env>( fn list_literal<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
scope: &Scope<'a, 'ctx>, scope: &Scope<'a, 'ctx>,
@ -2382,8 +2379,8 @@ fn list_literal<'a, 'ctx, 'env>(
} }
} }
pub fn load_roc_value<'a, 'ctx, 'env>( pub fn load_roc_value<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
source: PointerValue<'ctx>, source: PointerValue<'ctx>,
@ -2402,8 +2399,8 @@ pub fn load_roc_value<'a, 'ctx, 'env>(
} }
} }
pub fn use_roc_value<'a, 'ctx, 'env>( pub fn use_roc_value<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
source: BasicValueEnum<'ctx>, source: BasicValueEnum<'ctx>,
@ -2424,8 +2421,8 @@ pub fn use_roc_value<'a, 'ctx, 'env>(
} }
} }
pub fn store_roc_value_opaque<'a, 'ctx, 'env>( pub fn store_roc_value_opaque<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
opaque_destination: PointerValue<'ctx>, opaque_destination: PointerValue<'ctx>,
@ -2440,8 +2437,8 @@ pub fn store_roc_value_opaque<'a, 'ctx, 'env>(
store_roc_value(env, layout_interner, layout, destination, value) store_roc_value(env, layout_interner, layout, destination, value)
} }
pub fn store_roc_value<'a, 'ctx, 'env>( pub fn store_roc_value<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
destination: PointerValue<'ctx>, destination: PointerValue<'ctx>,
@ -2481,8 +2478,8 @@ pub fn store_roc_value<'a, 'ctx, 'env>(
} }
} }
pub fn build_exp_stmt<'a, 'ctx, 'env>( pub fn build_exp_stmt<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
func_spec_solutions: &FuncSpecSolutions, func_spec_solutions: &FuncSpecSolutions,
@ -3048,7 +3045,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
} }
} }
pub fn load_symbol<'a, 'ctx>(scope: &Scope<'a, 'ctx>, symbol: &Symbol) -> BasicValueEnum<'ctx> { pub fn load_symbol<'ctx>(scope: &Scope<'_, 'ctx>, symbol: &Symbol) -> BasicValueEnum<'ctx> {
match scope.get(symbol) { match scope.get(symbol) {
Some((_, ptr)) => *ptr, Some((_, ptr)) => *ptr,
@ -3059,8 +3056,8 @@ pub fn load_symbol<'a, 'ctx>(scope: &Scope<'a, 'ctx>, symbol: &Symbol) -> BasicV
} }
} }
pub(crate) fn load_symbol_and_layout<'a, 'ctx, 'b>( pub(crate) fn load_symbol_and_layout<'a, 'ctx>(
scope: &'b Scope<'a, 'ctx>, scope: &Scope<'a, 'ctx>,
symbol: &Symbol, symbol: &Symbol,
) -> (BasicValueEnum<'ctx>, InLayout<'a>) { ) -> (BasicValueEnum<'ctx>, InLayout<'a>) {
match scope.get(symbol) { match scope.get(symbol) {
@ -3172,8 +3169,8 @@ pub fn complex_bitcast<'ctx>(
/// Check the size of the input and output types. Pretending we have more bytes at a pointer than /// Check the size of the input and output types. Pretending we have more bytes at a pointer than
/// we actually do can lead to faulty optimizations and weird segfaults/crashes /// we actually do can lead to faulty optimizations and weird segfaults/crashes
pub fn complex_bitcast_check_size<'a, 'ctx, 'env>( pub fn complex_bitcast_check_size<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
from_value: BasicValueEnum<'ctx>, from_value: BasicValueEnum<'ctx>,
to_type: BasicTypeEnum<'ctx>, to_type: BasicTypeEnum<'ctx>,
name: &str, name: &str,
@ -3284,8 +3281,8 @@ fn complex_bitcast_to_bigger_than_from<'ctx>(
} }
/// get the tag id out of a pointer to a wrapped (i.e. stores the tag id at runtime) layout /// get the tag id out of a pointer to a wrapped (i.e. stores the tag id at runtime) layout
fn get_tag_id_wrapped<'a, 'ctx, 'env>( fn get_tag_id_wrapped<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
union_layout: UnionLayout<'a>, union_layout: UnionLayout<'a>,
from_value: PointerValue<'ctx>, from_value: PointerValue<'ctx>,
@ -3308,8 +3305,8 @@ fn get_tag_id_wrapped<'a, 'ctx, 'env>(
.into_int_value() .into_int_value()
} }
pub fn get_tag_id_non_recursive<'a, 'ctx, 'env>( pub fn get_tag_id_non_recursive<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
tag: StructValue<'ctx>, tag: StructValue<'ctx>,
) -> IntValue<'ctx> { ) -> IntValue<'ctx> {
env.builder env.builder
@ -3326,7 +3323,7 @@ struct SwitchArgsIr<'a, 'ctx> {
pub ret_type: BasicTypeEnum<'ctx>, pub ret_type: BasicTypeEnum<'ctx>,
} }
fn const_i128<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, value: i128) -> IntValue<'ctx> { fn const_i128<'ctx>(env: &Env<'_, 'ctx, '_>, value: i128) -> IntValue<'ctx> {
// truncate the lower 64 bits // truncate the lower 64 bits
let value = value as u128; let value = value as u128;
let a = value as u64; let a = value as u64;
@ -3339,9 +3336,9 @@ fn const_i128<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, value: i128) -> IntValu
.const_int_arbitrary_precision(&[a, b]) .const_int_arbitrary_precision(&[a, b])
} }
fn const_u128<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, value: u128) -> IntValue<'ctx> { fn const_u128<'ctx>(env: &Env<'_, 'ctx, '_>, value: u128) -> IntValue<'ctx> {
// truncate the lower 64 bits // truncate the lower 64 bits
let value = value as u128; let value = value;
let a = value as u64; let a = value as u64;
// get the upper 64 bits // get the upper 64 bits
@ -3352,8 +3349,8 @@ fn const_u128<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, value: u128) -> IntValu
.const_int_arbitrary_precision(&[a, b]) .const_int_arbitrary_precision(&[a, b])
} }
fn build_switch_ir<'a, 'ctx, 'env>( fn build_switch_ir<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
func_spec_solutions: &FuncSpecSolutions, func_spec_solutions: &FuncSpecSolutions,
@ -3488,7 +3485,7 @@ fn build_switch_ir<'a, 'ctx, 'env>(
let int_val = if condition_int_type == context.i128_type() { let int_val = if condition_int_type == context.i128_type() {
const_i128(env, *int as i128) const_i128(env, *int as i128)
} else { } else {
condition_int_type.const_int(*int as u64, false) condition_int_type.const_int(*int, false)
}; };
let block = context.append_basic_block(parent, format!("branch{}", int).as_str()); let block = context.append_basic_block(parent, format!("branch{}", int).as_str());
@ -3557,8 +3554,8 @@ fn build_switch_ir<'a, 'ctx, 'env>(
} }
/// Creates a new stack allocation instruction in the entry block of the function. /// Creates a new stack allocation instruction in the entry block of the function.
pub fn create_entry_block_alloca<'a, 'ctx>( pub fn create_entry_block_alloca<'ctx>(
env: &Env<'a, 'ctx, '_>, env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'_>, parent: FunctionValue<'_>,
basic_type: BasicTypeEnum<'ctx>, basic_type: BasicTypeEnum<'ctx>,
name: &str, name: &str,
@ -3574,8 +3571,8 @@ pub fn create_entry_block_alloca<'a, 'ctx>(
builder.build_alloca(basic_type, name) builder.build_alloca(basic_type, name)
} }
fn expose_function_to_host<'a, 'ctx, 'env>( fn expose_function_to_host<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
symbol: Symbol, symbol: Symbol,
roc_function: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>,
@ -3607,8 +3604,8 @@ fn expose_function_to_host<'a, 'ctx, 'env>(
); );
} }
fn expose_function_to_host_help_c_abi_generic<'a, 'ctx, 'env>( fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>,
arguments: &[InLayout<'a>], arguments: &[InLayout<'a>],
@ -3753,8 +3750,8 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx, 'env>(
c_function c_function
} }
fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx, 'env>( fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
ident_string: &str, ident_string: &str,
roc_function: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>,
@ -3915,8 +3912,8 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx, 'env>(
c_function c_function
} }
fn expose_function_to_host_help_c_abi_v2<'a, 'ctx, 'env>( fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>,
arguments: &[InLayout<'a>], arguments: &[InLayout<'a>],
@ -4151,8 +4148,8 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx, 'env>(
c_function c_function
} }
fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>( fn expose_function_to_host_help_c_abi<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
ident_string: &str, ident_string: &str,
roc_function: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>,
@ -4237,7 +4234,7 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>(
c_function c_function
} }
pub fn get_sjlj_buffer<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> PointerValue<'ctx> { pub fn get_sjlj_buffer<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> {
// The size of jump_buf is target-dependent. // The size of jump_buf is target-dependent.
// - AArch64 needs 3 machine-sized words // - AArch64 needs 3 machine-sized words
// - LLVM says the following about the SJLJ intrinsic: // - LLVM says the following about the SJLJ intrinsic:
@ -4269,7 +4266,7 @@ pub fn get_sjlj_buffer<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> PointerValu
) )
} }
pub fn build_setjmp_call<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> BasicValueEnum<'ctx> { pub fn build_setjmp_call<'ctx>(env: &Env<'_, 'ctx, '_>) -> BasicValueEnum<'ctx> {
let jmp_buf = get_sjlj_buffer(env); let jmp_buf = get_sjlj_buffer(env);
if cfg!(target_arch = "aarch64") { if cfg!(target_arch = "aarch64") {
// Due to https://github.com/roc-lang/roc/issues/2965, we use a setjmp we linked in from Zig // Due to https://github.com/roc-lang/roc/issues/2965, we use a setjmp we linked in from Zig
@ -4336,7 +4333,7 @@ pub fn build_setjmp_call<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> BasicValu
} }
/// Pointer to RocStr which is the panic message. /// Pointer to RocStr which is the panic message.
pub fn get_panic_msg_ptr<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> PointerValue<'ctx> { pub fn get_panic_msg_ptr<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> {
let str_typ = zig_str_type(env); let str_typ = zig_str_type(env);
let global_name = "roc_panic_msg_str"; let global_name = "roc_panic_msg_str";
@ -4351,7 +4348,7 @@ pub fn get_panic_msg_ptr<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> PointerVa
/// Pointer to the panic tag. /// Pointer to the panic tag.
/// Only non-zero values must be written into here. /// Only non-zero values must be written into here.
pub fn get_panic_tag_ptr<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> PointerValue<'ctx> { pub fn get_panic_tag_ptr<'ctx>(env: &Env<'_, 'ctx, '_>) -> PointerValue<'ctx> {
let i64_typ = env.context.i64_type(); let i64_typ = env.context.i64_type();
let global_name = "roc_panic_msg_tag"; let global_name = "roc_panic_msg_tag";
@ -4364,8 +4361,8 @@ pub fn get_panic_tag_ptr<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> PointerVa
global.as_pointer_value() global.as_pointer_value()
} }
fn set_jump_and_catch_long_jump<'a, 'ctx, 'env>( fn set_jump_and_catch_long_jump<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
roc_function: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>,
@ -4446,8 +4443,8 @@ fn set_jump_and_catch_long_jump<'a, 'ctx, 'env>(
) )
} }
fn make_exception_catcher<'a, 'ctx, 'env>( fn make_exception_catcher<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>,
return_layout: InLayout<'a>, return_layout: InLayout<'a>,
@ -4477,8 +4474,8 @@ fn roc_call_result_layout<'a>(
Layout::struct_no_name_order(arena.alloc(elements)) Layout::struct_no_name_order(arena.alloc(elements))
} }
fn roc_call_result_type<'a, 'ctx, 'env>( fn roc_call_result_type<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
return_type: BasicTypeEnum<'ctx>, return_type: BasicTypeEnum<'ctx>,
) -> StructType<'ctx> { ) -> StructType<'ctx> {
env.context.struct_type( env.context.struct_type(
@ -4491,8 +4488,8 @@ fn roc_call_result_type<'a, 'ctx, 'env>(
) )
} }
fn make_good_roc_result<'a, 'ctx, 'env>( fn make_good_roc_result<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
return_layout: InLayout<'a>, return_layout: InLayout<'a>,
return_value: BasicValueEnum<'ctx>, return_value: BasicValueEnum<'ctx>,
@ -4530,8 +4527,8 @@ fn make_good_roc_result<'a, 'ctx, 'env>(
v3.into_struct_value().into() v3.into_struct_value().into()
} }
fn make_exception_catching_wrapper<'a, 'ctx, 'env>( fn make_exception_catching_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>,
return_layout: InLayout<'a>, return_layout: InLayout<'a>,
@ -4607,8 +4604,8 @@ fn make_exception_catching_wrapper<'a, 'ctx, 'env>(
wrapper_function wrapper_function
} }
pub fn build_proc_headers<'a, 'r, 'ctx, 'env>( pub fn build_proc_headers<'a, 'r, 'ctx>(
env: &'r Env<'a, 'ctx, 'env>, env: &'r Env<'a, 'ctx, '_>,
layout_interner: &'r mut STLayoutInterner<'a>, layout_interner: &'r mut STLayoutInterner<'a>,
mod_solutions: &'a ModSolutions, mod_solutions: &'a ModSolutions,
procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>, procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>,
@ -4655,8 +4652,8 @@ pub fn build_proc_headers<'a, 'r, 'ctx, 'env>(
headers headers
} }
pub fn build_procedures<'a, 'ctx, 'env>( pub fn build_procedures<'a>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, '_, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
opt_level: OptLevel, opt_level: OptLevel,
procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>, procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>,
@ -4711,8 +4708,8 @@ pub fn build_procedures<'a, 'ctx, 'env>(
} }
} }
pub fn build_wasm_test_wrapper<'a, 'ctx, 'env>( pub fn build_wasm_test_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
opt_level: OptLevel, opt_level: OptLevel,
procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>, procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>,
@ -4736,8 +4733,8 @@ pub fn build_wasm_test_wrapper<'a, 'ctx, 'env>(
) )
} }
pub fn build_procedures_return_main<'a, 'ctx, 'env>( pub fn build_procedures_return_main<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
opt_level: OptLevel, opt_level: OptLevel,
procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>, procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>,
@ -4761,8 +4758,8 @@ pub fn build_procedures_return_main<'a, 'ctx, 'env>(
) )
} }
pub fn build_procedures_expose_expects<'a, 'ctx, 'env>( pub fn build_procedures_expose_expects<'a>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, '_, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
opt_level: OptLevel, opt_level: OptLevel,
expects: &'a [Symbol], expects: &'a [Symbol],
@ -4832,8 +4829,8 @@ pub fn build_procedures_expose_expects<'a, 'ctx, 'env>(
expect_names expect_names
} }
fn build_procedures_help<'a, 'ctx, 'env>( fn build_procedures_help<'a>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, '_, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
opt_level: OptLevel, opt_level: OptLevel,
procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>, procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>,
@ -4957,8 +4954,8 @@ fn func_spec_name<'a>(
buf buf
} }
fn build_proc_header<'a, 'ctx, 'env>( fn build_proc_header<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
func_spec: FuncSpec, func_spec: FuncSpec,
symbol: Symbol, symbol: Symbol,
@ -5024,8 +5021,8 @@ fn build_proc_header<'a, 'ctx, 'env>(
fn_val fn_val
} }
fn expose_alias_to_host<'a, 'ctx, 'env>( fn expose_alias_to_host<'a>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, '_, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
mod_solutions: &'a ModSolutions, mod_solutions: &'a ModSolutions,
fn_name: &str, fn_name: &str,
@ -5105,8 +5102,8 @@ fn expose_alias_to_host<'a, 'ctx, 'env>(
} }
} }
fn build_closure_caller<'a, 'ctx, 'env>( fn build_closure_caller<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
def_name: &str, def_name: &str,
evaluator: FunctionValue<'ctx>, evaluator: FunctionValue<'ctx>,
@ -5236,8 +5233,8 @@ fn build_closure_caller<'a, 'ctx, 'env>(
); );
} }
fn build_host_exposed_alias_size<'a, 'r, 'ctx, 'env>( fn build_host_exposed_alias_size<'a, 'r>(
env: &'r Env<'a, 'ctx, 'env>, env: &'r Env<'a, '_, '_>,
layout_interner: &'r mut STLayoutInterner<'a>, layout_interner: &'r mut STLayoutInterner<'a>,
def_name: &str, def_name: &str,
alias_symbol: Symbol, alias_symbol: Symbol,
@ -5252,8 +5249,8 @@ fn build_host_exposed_alias_size<'a, 'r, 'ctx, 'env>(
) )
} }
fn build_host_exposed_alias_size_help<'a, 'ctx, 'env>( fn build_host_exposed_alias_size_help<'a, 'ctx>(
env: &'a Env<'a, 'ctx, 'env>, env: &'a Env<'a, 'ctx, '_>,
def_name: &str, def_name: &str,
_alias_symbol: Symbol, _alias_symbol: Symbol,
opt_label: Option<&str>, opt_label: Option<&str>,
@ -5286,8 +5283,8 @@ fn build_host_exposed_alias_size_help<'a, 'ctx, 'env>(
builder.build_return(Some(&size)); builder.build_return(Some(&size));
} }
fn build_proc<'a, 'ctx, 'env>( fn build_proc<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
mod_solutions: &'a ModSolutions, mod_solutions: &'a ModSolutions,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
@ -5371,8 +5368,8 @@ pub fn verify_fn(fn_val: FunctionValue<'_>) {
} }
} }
pub(crate) fn function_value_by_func_spec<'a, 'ctx, 'env>( pub(crate) fn function_value_by_func_spec<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
func_spec: FuncSpec, func_spec: FuncSpec,
symbol: Symbol, symbol: Symbol,
arguments: &[InLayout<'a>], arguments: &[InLayout<'a>],
@ -5385,8 +5382,8 @@ pub(crate) fn function_value_by_func_spec<'a, 'ctx, 'env>(
function_value_by_name_help(env, arguments, niche, result, symbol, fn_name) function_value_by_name_help(env, arguments, niche, result, symbol, fn_name)
} }
fn function_value_by_name_help<'a, 'ctx, 'env>( fn function_value_by_name_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
arguments: &[InLayout<'a>], arguments: &[InLayout<'a>],
_niche: Niche<'a>, _niche: Niche<'a>,
result: InLayout<'a>, result: InLayout<'a>,
@ -5425,8 +5422,8 @@ fn function_value_by_name_help<'a, 'ctx, 'env>(
} }
#[inline(always)] #[inline(always)]
fn roc_call_with_args<'a, 'ctx, 'env>( fn roc_call_with_args<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
argument_layouts: &[InLayout<'a>], argument_layouts: &[InLayout<'a>],
result_layout: InLayout<'a>, result_layout: InLayout<'a>,
@ -5446,8 +5443,8 @@ fn roc_call_with_args<'a, 'ctx, 'env>(
call_roc_function(env, layout_interner, fn_val, result_layout, arguments) call_roc_function(env, layout_interner, fn_val, result_layout, arguments)
} }
pub fn call_roc_function<'a, 'ctx, 'env>( pub fn call_roc_function<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>,
result_layout: InLayout<'a>, result_layout: InLayout<'a>,
@ -5561,8 +5558,8 @@ pub struct RocFunctionCall<'ctx> {
pub data_is_owned: IntValue<'ctx>, pub data_is_owned: IntValue<'ctx>,
} }
pub(crate) fn roc_function_call<'a, 'ctx, 'env>( pub(crate) fn roc_function_call<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
transform: FunctionValue<'ctx>, transform: FunctionValue<'ctx>,
@ -5616,8 +5613,8 @@ pub(crate) fn roc_function_call<'a, 'ctx, 'env>(
/// ///
/// As an example, structs that fit inside an integer type should /// As an example, structs that fit inside an integer type should
/// (this does not currently happen here) be coerced to that integer type. /// (this does not currently happen here) be coerced to that integer type.
fn to_cc_type<'a, 'ctx, 'env>( fn to_cc_type<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
) -> BasicTypeEnum<'ctx> { ) -> BasicTypeEnum<'ctx> {
@ -5630,8 +5627,8 @@ fn to_cc_type<'a, 'ctx, 'env>(
} }
} }
fn to_cc_type_builtin<'a, 'ctx, 'env>( fn to_cc_type_builtin<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
builtin: &Builtin<'a>, builtin: &Builtin<'a>,
) -> BasicTypeEnum<'ctx> { ) -> BasicTypeEnum<'ctx> {
match builtin { match builtin {
@ -5691,8 +5688,8 @@ impl RocReturn {
} }
} }
pub(crate) fn from_layout<'a, 'ctx, 'env>( pub(crate) fn from_layout<'a>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, '_, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
) -> Self { ) -> Self {
@ -5832,8 +5829,8 @@ impl<'ctx> FunctionSpec<'ctx> {
} }
/// According to the C ABI, how should we return a value with the given layout? /// According to the C ABI, how should we return a value with the given layout?
pub fn to_cc_return<'a, 'ctx, 'env>( pub fn to_cc_return<'a>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, '_, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
) -> CCReturn { ) -> CCReturn {
@ -5855,16 +5852,16 @@ pub fn to_cc_return<'a, 'ctx, 'env>(
} }
} }
fn function_arguments<'a, 'ctx, 'env>( fn function_arguments<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
arguments: &[BasicTypeEnum<'ctx>], arguments: &[BasicTypeEnum<'ctx>],
) -> Vec<'a, BasicMetadataTypeEnum<'ctx>> { ) -> Vec<'a, BasicMetadataTypeEnum<'ctx>> {
let it = arguments.iter().map(|x| (*x).into()); let it = arguments.iter().map(|x| (*x).into());
Vec::from_iter_in(it, env.arena) Vec::from_iter_in(it, env.arena)
} }
fn build_foreign_symbol<'a, 'ctx, 'env>( fn build_foreign_symbol<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
scope: &mut Scope<'a, 'ctx>, scope: &mut Scope<'a, 'ctx>,
foreign: &roc_module::ident::ForeignSymbol, foreign: &roc_module::ident::ForeignSymbol,
@ -6038,8 +6035,8 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
) )
} }
fn define_global_str_literal_ptr<'a, 'ctx, 'env>( fn define_global_str_literal_ptr<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
message: &str, message: &str,
) -> PointerValue<'ctx> { ) -> PointerValue<'ctx> {
let global = define_global_str_literal(env, message); let global = define_global_str_literal(env, message);
@ -6065,8 +6062,8 @@ fn define_global_str_literal_ptr<'a, 'ctx, 'env>(
ptr ptr
} }
fn define_global_str_literal<'a, 'ctx, 'env>( fn define_global_str_literal<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
message: &str, message: &str,
) -> inkwell::values::GlobalValue<'ctx> { ) -> inkwell::values::GlobalValue<'ctx> {
let module = env.module; let module = env.module;
@ -6119,8 +6116,8 @@ fn define_global_str_literal<'a, 'ctx, 'env>(
} }
} }
pub(crate) fn throw_internal_exception<'a, 'ctx, 'env>( pub(crate) fn throw_internal_exception<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
message: &str, message: &str,
) { ) {
@ -6133,8 +6130,8 @@ pub(crate) fn throw_internal_exception<'a, 'ctx, 'env>(
builder.build_unreachable(); builder.build_unreachable();
} }
pub(crate) fn throw_exception<'a, 'ctx, 'env>( pub(crate) fn throw_exception<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
scope: &mut Scope<'a, 'ctx>, scope: &mut Scope<'a, 'ctx>,
message: &Symbol, message: &Symbol,
tag: CrashTag, tag: CrashTag,
@ -6146,8 +6143,8 @@ pub(crate) fn throw_exception<'a, 'ctx, 'env>(
env.builder.build_unreachable(); env.builder.build_unreachable();
} }
fn get_foreign_symbol<'a, 'ctx, 'env>( fn get_foreign_symbol<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
foreign_symbol: roc_module::ident::ForeignSymbol, foreign_symbol: roc_module::ident::ForeignSymbol,
function_spec: FunctionSpec<'ctx>, function_spec: FunctionSpec<'ctx>,
) -> FunctionValue<'ctx> { ) -> FunctionValue<'ctx> {

View file

@ -20,8 +20,8 @@ use super::build::{
}; };
use super::convert::zig_list_type; use super::convert::zig_list_type;
fn call_list_bitcode_fn_1<'a, 'ctx, 'env>( fn call_list_bitcode_fn_1<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
list: StructValue<'ctx>, list: StructValue<'ctx>,
other_arguments: &[BasicValueEnum<'ctx>], other_arguments: &[BasicValueEnum<'ctx>],
fn_name: &str, fn_name: &str,
@ -29,8 +29,8 @@ fn call_list_bitcode_fn_1<'a, 'ctx, 'env>(
call_list_bitcode_fn(env, &[list], other_arguments, BitcodeReturns::List, fn_name) call_list_bitcode_fn(env, &[list], other_arguments, BitcodeReturns::List, fn_name)
} }
pub(crate) fn list_symbol_to_c_abi<'a, 'ctx, 'env>( pub(crate) fn list_symbol_to_c_abi<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
scope: &Scope<'a, 'ctx>, scope: &Scope<'a, 'ctx>,
symbol: Symbol, symbol: Symbol,
) -> PointerValue<'ctx> { ) -> PointerValue<'ctx> {
@ -49,8 +49,8 @@ pub(crate) fn list_symbol_to_c_abi<'a, 'ctx, 'env>(
list_alloca list_alloca
} }
pub(crate) fn pass_update_mode<'a, 'ctx, 'env>( pub(crate) fn pass_update_mode<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
update_mode: UpdateMode, update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
match update_mode { match update_mode {
@ -59,8 +59,8 @@ pub(crate) fn pass_update_mode<'a, 'ctx, 'env>(
} }
} }
fn pass_element_as_opaque<'a, 'ctx, 'env>( fn pass_element_as_opaque<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
element: BasicValueEnum<'ctx>, element: BasicValueEnum<'ctx>,
layout: InLayout<'a>, layout: InLayout<'a>,
@ -80,8 +80,8 @@ fn pass_element_as_opaque<'a, 'ctx, 'env>(
.into() .into()
} }
pub(crate) fn layout_width<'a, 'ctx, 'env>( pub(crate) fn layout_width<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
@ -90,8 +90,8 @@ pub(crate) fn layout_width<'a, 'ctx, 'env>(
.into() .into()
} }
pub(crate) fn pass_as_opaque<'a, 'ctx, 'env>( pub(crate) fn pass_as_opaque<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
env.builder env.builder
@ -103,8 +103,8 @@ pub(crate) fn pass_as_opaque<'a, 'ctx, 'env>(
.into() .into()
} }
pub(crate) fn list_with_capacity<'a, 'ctx, 'env>( pub(crate) fn list_with_capacity<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
capacity: IntValue<'ctx>, capacity: IntValue<'ctx>,
element_layout: InLayout<'a>, element_layout: InLayout<'a>,
@ -122,8 +122,8 @@ pub(crate) fn list_with_capacity<'a, 'ctx, 'env>(
) )
} }
pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>( pub(crate) fn list_get_unsafe<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
element_layout: InLayout<'a>, element_layout: InLayout<'a>,
@ -162,8 +162,8 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
} }
/// List.reserve : List elem, Nat -> List elem /// List.reserve : List elem, Nat -> List elem
pub(crate) fn list_reserve<'a, 'ctx, 'env>( pub(crate) fn list_reserve<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
list: BasicValueEnum<'ctx>, list: BasicValueEnum<'ctx>,
spare: BasicValueEnum<'ctx>, spare: BasicValueEnum<'ctx>,
@ -184,8 +184,8 @@ pub(crate) fn list_reserve<'a, 'ctx, 'env>(
} }
/// List.releaseExcessCapacity : List elem -> List elem /// List.releaseExcessCapacity : List elem -> List elem
pub(crate) fn list_release_excess_capacity<'a, 'ctx, 'env>( pub(crate) fn list_release_excess_capacity<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
list: BasicValueEnum<'ctx>, list: BasicValueEnum<'ctx>,
element_layout: InLayout<'a>, element_layout: InLayout<'a>,
@ -204,8 +204,8 @@ pub(crate) fn list_release_excess_capacity<'a, 'ctx, 'env>(
} }
/// List.appendUnsafe : List elem, elem -> List elem /// List.appendUnsafe : List elem, elem -> List elem
pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>( pub(crate) fn list_append_unsafe<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'ctx>, original_wrapper: StructValue<'ctx>,
element: BasicValueEnum<'ctx>, element: BasicValueEnum<'ctx>,
@ -223,8 +223,8 @@ pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
} }
/// List.prepend : List elem, elem -> List elem /// List.prepend : List elem, elem -> List elem
pub(crate) fn list_prepend<'a, 'ctx, 'env>( pub(crate) fn list_prepend<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'ctx>, original_wrapper: StructValue<'ctx>,
element: BasicValueEnum<'ctx>, element: BasicValueEnum<'ctx>,
@ -243,8 +243,8 @@ pub(crate) fn list_prepend<'a, 'ctx, 'env>(
} }
/// List.swap : List elem, Nat, Nat -> List elem /// List.swap : List elem, Nat, Nat -> List elem
pub(crate) fn list_swap<'a, 'ctx, 'env>( pub(crate) fn list_swap<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'ctx>, original_wrapper: StructValue<'ctx>,
index_1: IntValue<'ctx>, index_1: IntValue<'ctx>,
@ -267,8 +267,8 @@ pub(crate) fn list_swap<'a, 'ctx, 'env>(
} }
/// List.sublist : List elem, { start : Nat, len : Nat } -> List elem /// List.sublist : List elem, { start : Nat, len : Nat } -> List elem
pub(crate) fn list_sublist<'a, 'ctx, 'env>( pub(crate) fn list_sublist<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
original_wrapper: StructValue<'ctx>, original_wrapper: StructValue<'ctx>,
@ -292,8 +292,8 @@ pub(crate) fn list_sublist<'a, 'ctx, 'env>(
} }
/// List.dropAt : List elem, Nat -> List elem /// List.dropAt : List elem, Nat -> List elem
pub(crate) fn list_drop_at<'a, 'ctx, 'env>( pub(crate) fn list_drop_at<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
original_wrapper: StructValue<'ctx>, original_wrapper: StructValue<'ctx>,
@ -315,8 +315,8 @@ pub(crate) fn list_drop_at<'a, 'ctx, 'env>(
} }
/// List.replace_unsafe : List elem, Nat, elem -> { list: List elem, value: elem } /// List.replace_unsafe : List elem, Nat, elem -> { list: List elem, value: elem }
pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>( pub(crate) fn list_replace_unsafe<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
_layout_ids: &mut LayoutIds<'a>, _layout_ids: &mut LayoutIds<'a>,
list: BasicValueEnum<'ctx>, list: BasicValueEnum<'ctx>,
@ -429,8 +429,8 @@ pub(crate) fn list_capacity_or_ref_ptr<'ctx>(
// Gets a pointer to just after the refcount for a list or seamless slice. // Gets a pointer to just after the refcount for a list or seamless slice.
// The value is just after the refcount so that normal lists and seamless slices can share code paths easily. // The value is just after the refcount so that normal lists and seamless slices can share code paths easily.
pub(crate) fn list_refcount_ptr<'a, 'ctx, 'env>( pub(crate) fn list_refcount_ptr<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
wrapper_struct: StructValue<'ctx>, wrapper_struct: StructValue<'ctx>,
) -> PointerValue<'ctx> { ) -> PointerValue<'ctx> {
call_list_bitcode_fn( call_list_bitcode_fn(
@ -467,8 +467,8 @@ pub(crate) fn destructure<'ctx>(
} }
/// List.sortWith : List a, (a, a -> Ordering) -> List a /// List.sortWith : List a, (a, a -> Ordering) -> List a
pub(crate) fn list_sort_with<'a, 'ctx, 'env>( pub(crate) fn list_sort_with<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
roc_function_call: RocFunctionCall<'ctx>, roc_function_call: RocFunctionCall<'ctx>,
compare_wrapper: PointerValue<'ctx>, compare_wrapper: PointerValue<'ctx>,
@ -491,8 +491,8 @@ pub(crate) fn list_sort_with<'a, 'ctx, 'env>(
} }
/// List.map : List before, (before -> after) -> List after /// List.map : List before, (before -> after) -> List after
pub(crate) fn list_map<'a, 'ctx, 'env>( pub(crate) fn list_map<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
roc_function_call: RocFunctionCall<'ctx>, roc_function_call: RocFunctionCall<'ctx>,
list: BasicValueEnum<'ctx>, list: BasicValueEnum<'ctx>,
@ -515,8 +515,8 @@ pub(crate) fn list_map<'a, 'ctx, 'env>(
) )
} }
pub(crate) fn list_map2<'a, 'ctx, 'env>( pub(crate) fn list_map2<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
roc_function_call: RocFunctionCall<'ctx>, roc_function_call: RocFunctionCall<'ctx>,
@ -549,8 +549,8 @@ pub(crate) fn list_map2<'a, 'ctx, 'env>(
) )
} }
pub(crate) fn list_map3<'a, 'ctx, 'env>( pub(crate) fn list_map3<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
roc_function_call: RocFunctionCall<'ctx>, roc_function_call: RocFunctionCall<'ctx>,
@ -592,8 +592,8 @@ pub(crate) fn list_map3<'a, 'ctx, 'env>(
) )
} }
pub(crate) fn list_map4<'a, 'ctx, 'env>( pub(crate) fn list_map4<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
roc_function_call: RocFunctionCall<'ctx>, roc_function_call: RocFunctionCall<'ctx>,
@ -642,8 +642,8 @@ pub(crate) fn list_map4<'a, 'ctx, 'env>(
} }
/// List.concat : List elem, List elem -> List elem /// List.concat : List elem, List elem -> List elem
pub(crate) fn list_concat<'a, 'ctx, 'env>( pub(crate) fn list_concat<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
list1: BasicValueEnum<'ctx>, list1: BasicValueEnum<'ctx>,
list2: BasicValueEnum<'ctx>, list2: BasicValueEnum<'ctx>,
@ -756,9 +756,7 @@ where
index_alloca index_alloca
} }
pub(crate) fn empty_polymorphic_list<'a, 'ctx, 'env>( pub(crate) fn empty_polymorphic_list<'ctx>(env: &Env<'_, 'ctx, '_>) -> BasicValueEnum<'ctx> {
env: &Env<'a, 'ctx, 'env>,
) -> BasicValueEnum<'ctx> {
let struct_type = zig_list_type(env); let struct_type = zig_list_type(env);
// The pointer should be null (aka zero) and the length should be zero, // The pointer should be null (aka zero) and the length should be zero,
@ -796,8 +794,8 @@ pub(crate) fn load_list_ptr<'ctx>(
cast_basic_basic(builder, generic_ptr.into(), ptr_type.into()).into_pointer_value() cast_basic_basic(builder, generic_ptr.into(), ptr_type.into()).into_pointer_value()
} }
pub(crate) fn allocate_list<'a, 'ctx, 'env>( pub(crate) fn allocate_list<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
elem_layout: InLayout<'a>, elem_layout: InLayout<'a>,
number_of_elements: IntValue<'ctx>, number_of_elements: IntValue<'ctx>,
@ -815,8 +813,8 @@ pub(crate) fn allocate_list<'a, 'ctx, 'env>(
allocate_with_refcount_help(env, basic_type, alignment_bytes, number_of_data_bytes) allocate_with_refcount_help(env, basic_type, alignment_bytes, number_of_data_bytes)
} }
pub(crate) fn store_list<'a, 'ctx, 'env>( pub(crate) fn store_list<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
pointer_to_first_element: PointerValue<'ctx>, pointer_to_first_element: PointerValue<'ctx>,
len: IntValue<'ctx>, len: IntValue<'ctx>,
) -> StructValue<'ctx> { ) -> StructValue<'ctx> {
@ -835,8 +833,8 @@ pub(crate) fn store_list<'a, 'ctx, 'env>(
) )
} }
pub(crate) fn decref<'a, 'ctx, 'env>( pub(crate) fn decref<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
wrapper_struct: StructValue<'ctx>, wrapper_struct: StructValue<'ctx>,
alignment: u32, alignment: u32,
) { ) {

View file

@ -10,8 +10,8 @@ use super::build::BuilderExt;
pub static CHAR_LAYOUT: InLayout = Layout::U8; pub static CHAR_LAYOUT: InLayout = Layout::U8;
pub(crate) fn decode_from_utf8_result<'a, 'ctx, 'env>( pub(crate) fn decode_from_utf8_result<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>, pointer: PointerValue<'ctx>,
) -> StructValue<'ctx> { ) -> StructValue<'ctx> {
let builder = env.builder; let builder = env.builder;
@ -50,8 +50,8 @@ pub(crate) fn decode_from_utf8_result<'a, 'ctx, 'env>(
/// Dec.toStr : Dec -> Str /// Dec.toStr : Dec -> Str
/// Str.equal : Str, Str -> Bool /// Str.equal : Str, Str -> Bool
pub(crate) fn str_equal<'a, 'ctx, 'env>( pub(crate) fn str_equal<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
value1: BasicValueEnum<'ctx>, value1: BasicValueEnum<'ctx>,
value2: BasicValueEnum<'ctx>, value2: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
@ -66,8 +66,8 @@ pub(crate) fn str_equal<'a, 'ctx, 'env>(
// Gets a pointer to just after the refcount for a list or seamless slice. // Gets a pointer to just after the refcount for a list or seamless slice.
// The value is just after the refcount so that normal lists and seamless slices can share code paths easily. // The value is just after the refcount so that normal lists and seamless slices can share code paths easily.
pub(crate) fn str_refcount_ptr<'a, 'ctx, 'env>( pub(crate) fn str_refcount_ptr<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
value: BasicValueEnum<'ctx>, value: BasicValueEnum<'ctx>,
) -> PointerValue<'ctx> { ) -> PointerValue<'ctx> {
call_str_bitcode_fn( call_str_bitcode_fn(

View file

@ -18,8 +18,8 @@ use super::build::{load_roc_value, use_roc_value, BuilderExt};
use super::convert::argument_type_from_union_layout; use super::convert::argument_type_from_union_layout;
use super::lowlevel::dec_binop_with_unchecked; use super::lowlevel::dec_binop_with_unchecked;
pub fn generic_eq<'a, 'ctx, 'env>( pub fn generic_eq<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>, lhs_val: BasicValueEnum<'ctx>,
@ -38,8 +38,8 @@ pub fn generic_eq<'a, 'ctx, 'env>(
) )
} }
pub fn generic_neq<'a, 'ctx, 'env>( pub fn generic_neq<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>, lhs_val: BasicValueEnum<'ctx>,
@ -58,8 +58,8 @@ pub fn generic_neq<'a, 'ctx, 'env>(
) )
} }
fn build_eq_builtin<'a, 'ctx, 'env>( fn build_eq_builtin<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>, lhs_val: BasicValueEnum<'ctx>,
@ -136,8 +136,8 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
} }
} }
fn build_eq<'a, 'ctx, 'env>( fn build_eq<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>, lhs_val: BasicValueEnum<'ctx>,
@ -236,8 +236,8 @@ fn build_eq<'a, 'ctx, 'env>(
} }
} }
fn build_neq_builtin<'a, 'ctx, 'env>( fn build_neq_builtin<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>, lhs_val: BasicValueEnum<'ctx>,
@ -326,8 +326,8 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
} }
} }
fn build_neq<'a, 'ctx, 'env>( fn build_neq<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>, lhs_val: BasicValueEnum<'ctx>,
@ -411,8 +411,8 @@ fn build_neq<'a, 'ctx, 'env>(
} }
} }
fn build_list_eq<'a, 'ctx, 'env>( fn build_list_eq<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
list_layout: InLayout<'a>, list_layout: InLayout<'a>,
@ -469,8 +469,8 @@ fn build_list_eq<'a, 'ctx, 'env>(
call.try_as_basic_value().left().unwrap() call.try_as_basic_value().left().unwrap()
} }
fn build_list_eq_help<'a, 'ctx, 'env>( fn build_list_eq_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
@ -627,8 +627,8 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
} }
} }
fn build_struct_eq<'a, 'ctx, 'env>( fn build_struct_eq<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
struct_layout: InLayout<'a>, struct_layout: InLayout<'a>,
@ -679,8 +679,8 @@ fn build_struct_eq<'a, 'ctx, 'env>(
call.try_as_basic_value().left().unwrap() call.try_as_basic_value().left().unwrap()
} }
fn build_struct_eq_help<'a, 'ctx, 'env>( fn build_struct_eq_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
@ -812,8 +812,8 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
} }
} }
fn build_tag_eq<'a, 'ctx, 'env>( fn build_tag_eq<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
tag_layout: InLayout<'a>, tag_layout: InLayout<'a>,
@ -864,8 +864,8 @@ fn build_tag_eq<'a, 'ctx, 'env>(
call.try_as_basic_value().left().unwrap() call.try_as_basic_value().left().unwrap()
} }
fn build_tag_eq_help<'a, 'ctx, 'env>( fn build_tag_eq_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
@ -1265,8 +1265,8 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
} }
} }
fn eq_ptr_to_struct<'a, 'ctx, 'env>( fn eq_ptr_to_struct<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
struct_layout: InLayout<'a>, struct_layout: InLayout<'a>,
@ -1314,8 +1314,8 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
/// ---- /// ----
fn build_box_eq<'a, 'ctx, 'env>( fn build_box_eq<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
box_layout: InLayout<'a>, box_layout: InLayout<'a>,
@ -1366,8 +1366,8 @@ fn build_box_eq<'a, 'ctx, 'env>(
call.try_as_basic_value().left().unwrap() call.try_as_basic_value().left().unwrap()
} }
fn build_box_eq_help<'a, 'ctx, 'env>( fn build_box_eq_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,

View file

@ -10,8 +10,8 @@ use roc_mono::layout::{
}; };
use roc_target::TargetInfo; use roc_target::TargetInfo;
fn basic_type_from_record<'a, 'ctx, 'env>( fn basic_type_from_record<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
fields: &[InLayout<'_>], fields: &[InLayout<'_>],
) -> BasicTypeEnum<'ctx> { ) -> BasicTypeEnum<'ctx> {
@ -59,8 +59,8 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
} }
} }
pub fn struct_type_from_union_layout<'a, 'ctx, 'env>( pub fn struct_type_from_union_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
union_layout: &UnionLayout<'_>, union_layout: &UnionLayout<'_>,
) -> StructType<'ctx> { ) -> StructType<'ctx> {
@ -98,8 +98,8 @@ pub fn struct_type_from_union_layout<'a, 'ctx, 'env>(
} }
} }
pub fn basic_type_from_union_layout<'a, 'ctx, 'env>( pub fn basic_type_from_union_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
union_layout: &UnionLayout<'_>, union_layout: &UnionLayout<'_>,
) -> BasicTypeEnum<'ctx> { ) -> BasicTypeEnum<'ctx> {
@ -116,8 +116,8 @@ pub fn basic_type_from_union_layout<'a, 'ctx, 'env>(
} }
} }
pub fn basic_type_from_builtin<'a, 'ctx, 'env>( pub fn basic_type_from_builtin<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
builtin: &Builtin<'_>, builtin: &Builtin<'_>,
) -> BasicTypeEnum<'ctx> { ) -> BasicTypeEnum<'ctx> {
use Builtin::*; use Builtin::*;
@ -145,8 +145,8 @@ pub fn basic_type_from_builtin<'a, 'ctx, 'env>(
/// ///
/// Ideas exist to have (bigger than 2 register) records also be passed by-reference, but this /// Ideas exist to have (bigger than 2 register) records also be passed by-reference, but this
/// is not currently implemented /// is not currently implemented
pub fn argument_type_from_layout<'a, 'ctx, 'env>( pub fn argument_type_from_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
) -> BasicTypeEnum<'ctx> { ) -> BasicTypeEnum<'ctx> {
@ -171,8 +171,8 @@ pub fn argument_type_from_layout<'a, 'ctx, 'env>(
} }
/// Non-recursive tag unions are stored on the stack, but passed by-reference /// Non-recursive tag unions are stored on the stack, but passed by-reference
pub fn argument_type_from_union_layout<'a, 'ctx, 'env>( pub fn argument_type_from_union_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
union_layout: &UnionLayout<'_>, union_layout: &UnionLayout<'_>,
) -> BasicTypeEnum<'ctx> { ) -> BasicTypeEnum<'ctx> {
@ -185,8 +185,8 @@ pub fn argument_type_from_union_layout<'a, 'ctx, 'env>(
} }
} }
pub fn int_type_from_int_width<'a, 'ctx, 'env>( pub fn int_type_from_int_width<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
int_width: IntWidth, int_width: IntWidth,
) -> IntType<'ctx> { ) -> IntType<'ctx> {
use IntWidth::*; use IntWidth::*;
@ -200,8 +200,8 @@ pub fn int_type_from_int_width<'a, 'ctx, 'env>(
} }
} }
pub fn float_type_from_float_width<'a, 'ctx, 'env>( pub fn float_type_from_float_width<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
float_width: FloatWidth, float_width: FloatWidth,
) -> FloatType<'ctx> { ) -> FloatType<'ctx> {
use FloatWidth::*; use FloatWidth::*;
@ -431,27 +431,27 @@ pub fn str_list_int(ctx: &Context, target_info: TargetInfo) -> IntType<'_> {
} }
} }
pub fn zig_list_type<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> StructType<'ctx> { pub fn zig_list_type<'ctx>(env: &Env<'_, 'ctx, '_>) -> StructType<'ctx> {
env.module.get_struct_type("list.RocList").unwrap() env.module.get_struct_type("list.RocList").unwrap()
} }
pub fn zig_str_type<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> StructType<'ctx> { pub fn zig_str_type<'ctx>(env: &Env<'_, 'ctx, '_>) -> StructType<'ctx> {
env.module.get_struct_type("str.RocStr").unwrap() env.module.get_struct_type("str.RocStr").unwrap()
} }
pub fn zig_dec_type<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> StructType<'ctx> { pub fn zig_dec_type<'ctx>(env: &Env<'_, 'ctx, '_>) -> StructType<'ctx> {
env.module.get_struct_type("dec.RocDec").unwrap() env.module.get_struct_type("dec.RocDec").unwrap()
} }
pub fn zig_has_tag_id_type<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> StructType<'ctx> { pub fn zig_has_tag_id_type<'ctx>(env: &Env<'_, 'ctx, '_>) -> StructType<'ctx> {
let u8_ptr_t = env.context.i8_type().ptr_type(AddressSpace::default()); let u8_ptr_t = env.context.i8_type().ptr_type(AddressSpace::default());
env.context env.context
.struct_type(&[env.context.bool_type().into(), u8_ptr_t.into()], false) .struct_type(&[env.context.bool_type().into(), u8_ptr_t.into()], false)
} }
pub fn zig_num_parse_result_type<'a, 'ctx, 'env>( pub fn zig_num_parse_result_type<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
type_name: &str, type_name: &str,
) -> StructType<'ctx> { ) -> StructType<'ctx> {
let name = format!("num.NumParseResult({type_name})"); let name = format!("num.NumParseResult({type_name})");
@ -462,8 +462,8 @@ pub fn zig_num_parse_result_type<'a, 'ctx, 'env>(
} }
} }
pub fn zig_to_int_checked_result_type<'a, 'ctx, 'env>( pub fn zig_to_int_checked_result_type<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
type_name: &str, type_name: &str,
) -> StructType<'ctx> { ) -> StructType<'ctx> {
let name = format!("num.ToIntCheckedResult({type_name})"); let name = format!("num.ToIntCheckedResult({type_name})");
@ -474,7 +474,7 @@ pub fn zig_to_int_checked_result_type<'a, 'ctx, 'env>(
} }
} }
pub fn zig_with_overflow_roc_dec<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> StructType<'ctx> { pub fn zig_with_overflow_roc_dec<'ctx>(env: &Env<'_, 'ctx, '_>) -> StructType<'ctx> {
env.module env.module
.get_struct_type("utils.WithOverflow(dec.RocDec)") .get_struct_type("utils.WithOverflow(dec.RocDec)")
.unwrap() .unwrap()

View file

@ -66,8 +66,8 @@ fn pointer_at_offset<'ctx>(
} }
/// Writes the module and region into the buffer /// Writes the module and region into the buffer
fn write_header<'a, 'ctx, 'env>( fn write_header<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,
mut offset: IntValue<'ctx>, mut offset: IntValue<'ctx>,
condition: Symbol, condition: Symbol,
@ -95,8 +95,8 @@ fn write_header<'a, 'ctx, 'env>(
/// Read the first two 32-bit values from the shared memory, /// Read the first two 32-bit values from the shared memory,
/// representing the total number of expect frames and the next free position /// representing the total number of expect frames and the next free position
fn read_state<'a, 'ctx, 'env>( fn read_state<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,
) -> (IntValue<'ctx>, IntValue<'ctx>) { ) -> (IntValue<'ctx>, IntValue<'ctx>) {
let ptr_type = env.ptr_int().ptr_type(AddressSpace::default()); let ptr_type = env.ptr_int().ptr_type(AddressSpace::default());
@ -113,8 +113,8 @@ fn read_state<'a, 'ctx, 'env>(
(count.into_int_value(), offset.into_int_value()) (count.into_int_value(), offset.into_int_value())
} }
fn write_state<'a, 'ctx, 'env>( fn write_state<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,
count: IntValue<'ctx>, count: IntValue<'ctx>,
offset: IntValue<'ctx>, offset: IntValue<'ctx>,
@ -175,8 +175,8 @@ pub(crate) fn notify_parent_dbg(env: &Env, shared_memory: &SharedMemoryPointer)
// .. // ..
// lookup_val_n (varsize) // lookup_val_n (varsize)
// //
pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>( pub(crate) fn clone_to_shared_memory<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
scope: &Scope<'a, 'ctx>, scope: &Scope<'a, 'ctx>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
@ -287,8 +287,8 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
write_state(env, original_ptr, new_count, offset) write_state(env, original_ptr, new_count, offset)
} }
fn build_clone<'a, 'ctx, 'env>( fn build_clone<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,
@ -417,8 +417,8 @@ fn build_clone<'a, 'ctx, 'env>(
} }
} }
fn build_clone_struct<'a, 'ctx, 'env>( fn build_clone_struct<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,
@ -467,8 +467,8 @@ fn build_clone_struct<'a, 'ctx, 'env>(
} }
} }
fn build_clone_tag<'a, 'ctx, 'env>( fn build_clone_tag<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,
@ -545,8 +545,8 @@ fn build_clone_tag<'a, 'ctx, 'env>(
result.into_int_value() result.into_int_value()
} }
fn load_tag_data<'a, 'ctx, 'env>( fn load_tag_data<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
union_layout: UnionLayout<'a>, union_layout: UnionLayout<'a>,
tag_value: PointerValue<'ctx>, tag_value: PointerValue<'ctx>,
@ -573,8 +573,8 @@ fn load_tag_data<'a, 'ctx, 'env>(
env.builder.new_build_load(tag_type, data_ptr, "load_data") env.builder.new_build_load(tag_type, data_ptr, "load_data")
} }
fn clone_tag_payload_and_id<'a, 'ctx, 'env>( fn clone_tag_payload_and_id<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,
@ -623,8 +623,8 @@ fn clone_tag_payload_and_id<'a, 'ctx, 'env>(
answer answer
} }
fn build_clone_tag_help<'a, 'ctx, 'env>( fn build_clone_tag_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
union_layout: UnionLayout<'a>, union_layout: UnionLayout<'a>,
@ -958,8 +958,8 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
} }
} }
fn write_pointer_with_tag_id<'a, 'ctx, 'env>( fn write_pointer_with_tag_id<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,
offset: IntValue<'ctx>, offset: IntValue<'ctx>,
extra_offset: IntValue<'ctx>, extra_offset: IntValue<'ctx>,
@ -986,8 +986,8 @@ fn write_pointer_with_tag_id<'a, 'ctx, 'env>(
} }
} }
fn build_copy<'a, 'ctx, 'env>( fn build_copy<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,
offset: IntValue<'ctx>, offset: IntValue<'ctx>,
value: BasicValueEnum<'ctx>, value: BasicValueEnum<'ctx>,
@ -1012,8 +1012,8 @@ fn build_copy<'a, 'ctx, 'env>(
env.builder.build_int_add(offset, width, "new_offset") env.builder.build_int_add(offset, width, "new_offset")
} }
fn build_clone_builtin<'a, 'ctx, 'env>( fn build_clone_builtin<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,

View file

@ -50,8 +50,8 @@ use super::{
convert::zig_dec_type, convert::zig_dec_type,
}; };
pub(crate) fn run_low_level<'a, 'ctx, 'env>( pub(crate) fn run_low_level<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
scope: &Scope<'a, 'ctx>, scope: &Scope<'a, 'ctx>,
@ -1247,7 +1247,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
unreachable!("The {:?} operation is turned into mono Expr", op) unreachable!("The {:?} operation is turned into mono Expr", op)
} }
PtrCast | RefCountInc | RefCountDec => { PtrCast | PtrWrite | RefCountInc | RefCountDec => {
unreachable!("Not used in LLVM backend: {:?}", op); unreachable!("Not used in LLVM backend: {:?}", op);
} }
@ -1271,8 +1271,8 @@ fn intwidth_from_layout(layout: InLayout) -> IntWidth {
layout.to_int_width() layout.to_int_width()
} }
fn build_int_binop<'a, 'ctx, 'env>( fn build_int_binop<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
int_width: IntWidth, int_width: IntWidth,
lhs: IntValue<'ctx>, lhs: IntValue<'ctx>,
@ -1492,8 +1492,8 @@ fn build_int_binop<'a, 'ctx, 'env>(
} }
} }
pub fn build_num_binop<'a, 'ctx, 'env>( pub fn build_num_binop<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &STLayoutInterner<'a>, layout_interner: &STLayoutInterner<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
lhs_arg: BasicValueEnum<'ctx>, lhs_arg: BasicValueEnum<'ctx>,
@ -1543,8 +1543,8 @@ pub fn build_num_binop<'a, 'ctx, 'env>(
} }
} }
fn build_float_binop<'a, 'ctx, 'env>( fn build_float_binop<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
float_width: FloatWidth, float_width: FloatWidth,
lhs: FloatValue<'ctx>, lhs: FloatValue<'ctx>,
rhs: FloatValue<'ctx>, rhs: FloatValue<'ctx>,
@ -1656,8 +1656,8 @@ fn build_float_binop<'a, 'ctx, 'env>(
} }
} }
fn throw_on_overflow<'a, 'ctx, 'env>( fn throw_on_overflow<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
result: StructValue<'ctx>, // of the form { value: T, has_overflowed: bool } result: StructValue<'ctx>, // of the form { value: T, has_overflowed: bool }
message: &str, message: &str,
@ -1689,8 +1689,8 @@ fn throw_on_overflow<'a, 'ctx, 'env>(
.unwrap() .unwrap()
} }
fn dec_split_into_words<'a, 'ctx, 'env>( fn dec_split_into_words<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
value: IntValue<'ctx>, value: IntValue<'ctx>,
) -> (IntValue<'ctx>, IntValue<'ctx>) { ) -> (IntValue<'ctx>, IntValue<'ctx>) {
let int_64 = env.context.i128_type().const_int(64, false); let int_64 = env.context.i128_type().const_int(64, false);
@ -1706,10 +1706,7 @@ fn dec_split_into_words<'a, 'ctx, 'env>(
) )
} }
fn dec_alloca<'a, 'ctx, 'env>( fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> PointerValue<'ctx> {
env: &Env<'a, 'ctx, 'env>,
value: IntValue<'ctx>,
) -> PointerValue<'ctx> {
let dec_type = zig_dec_type(env); let dec_type = zig_dec_type(env);
let alloca = env.builder.build_alloca(dec_type, "dec_alloca"); let alloca = env.builder.build_alloca(dec_type, "dec_alloca");
@ -1728,10 +1725,7 @@ fn dec_alloca<'a, 'ctx, 'env>(
alloca alloca
} }
fn dec_to_str<'a, 'ctx, 'env>( fn dec_to_str<'ctx>(env: &Env<'_, 'ctx, '_>, dec: BasicValueEnum<'ctx>) -> BasicValueEnum<'ctx> {
env: &Env<'a, 'ctx, 'env>,
dec: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> {
use roc_target::OperatingSystem::*; use roc_target::OperatingSystem::*;
let dec = dec.into_int_value(); let dec = dec.into_int_value();
@ -1762,8 +1756,8 @@ fn dec_to_str<'a, 'ctx, 'env>(
} }
} }
fn dec_binop_with_overflow<'a, 'ctx, 'env>( fn dec_binop_with_overflow<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
fn_name: &str, fn_name: &str,
lhs: BasicValueEnum<'ctx>, lhs: BasicValueEnum<'ctx>,
rhs: BasicValueEnum<'ctx>, rhs: BasicValueEnum<'ctx>,
@ -1812,8 +1806,8 @@ fn dec_binop_with_overflow<'a, 'ctx, 'env>(
.into_struct_value() .into_struct_value()
} }
pub(crate) fn dec_binop_with_unchecked<'a, 'ctx, 'env>( pub(crate) fn dec_binop_with_unchecked<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
fn_name: &str, fn_name: &str,
lhs: BasicValueEnum<'ctx>, lhs: BasicValueEnum<'ctx>,
rhs: BasicValueEnum<'ctx>, rhs: BasicValueEnum<'ctx>,
@ -1851,8 +1845,8 @@ pub(crate) fn dec_binop_with_unchecked<'a, 'ctx, 'env>(
} }
} }
fn build_dec_binop<'a, 'ctx, 'env>( fn build_dec_binop<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
lhs: BasicValueEnum<'ctx>, lhs: BasicValueEnum<'ctx>,
_lhs_layout: InLayout<'a>, _lhs_layout: InLayout<'a>,
@ -1897,8 +1891,8 @@ fn build_dec_binop<'a, 'ctx, 'env>(
} }
} }
fn build_dec_binop_throw_on_overflow<'a, 'ctx, 'env>( fn build_dec_binop_throw_on_overflow<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
operation: &str, operation: &str,
lhs: BasicValueEnum<'ctx>, lhs: BasicValueEnum<'ctx>,
@ -2128,8 +2122,8 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
} }
} }
fn int_neg_raise_on_overflow<'a, 'ctx, 'env>( fn int_neg_raise_on_overflow<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
arg: IntValue<'ctx>, arg: IntValue<'ctx>,
int_type: IntType<'ctx>, int_type: IntType<'ctx>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
@ -2159,8 +2153,8 @@ fn int_neg_raise_on_overflow<'a, 'ctx, 'env>(
builder.build_int_neg(arg, "negate_int").into() builder.build_int_neg(arg, "negate_int").into()
} }
fn int_abs_raise_on_overflow<'a, 'ctx, 'env>( fn int_abs_raise_on_overflow<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
arg: IntValue<'ctx>, arg: IntValue<'ctx>,
int_type: IntType<'ctx>, int_type: IntType<'ctx>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
@ -2190,8 +2184,8 @@ fn int_abs_raise_on_overflow<'a, 'ctx, 'env>(
int_abs_with_overflow(env, arg, int_type) int_abs_with_overflow(env, arg, int_type)
} }
fn int_abs_with_overflow<'a, 'ctx, 'env>( fn int_abs_with_overflow<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
arg: IntValue<'ctx>, arg: IntValue<'ctx>,
int_type: IntType<'ctx>, int_type: IntType<'ctx>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
@ -2233,8 +2227,8 @@ fn int_abs_with_overflow<'a, 'ctx, 'env>(
) )
} }
fn build_float_unary_op<'a, 'ctx, 'env>( fn build_float_unary_op<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &STLayoutInterner<'a>, layout_interner: &STLayoutInterner<'a>,
layout: InLayout<'a>, layout: InLayout<'a>,
arg: FloatValue<'ctx>, arg: FloatValue<'ctx>,
@ -2349,8 +2343,8 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
} }
} }
pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
scope: &Scope<'a, 'ctx>, scope: &Scope<'a, 'ctx>,
@ -2641,9 +2635,9 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
} }
} }
fn load_symbol_and_lambda_set<'a, 'ctx, 'b>( fn load_symbol_and_lambda_set<'a, 'ctx>(
layout_interner: &STLayoutInterner<'a>, layout_interner: &STLayoutInterner<'a>,
scope: &'b Scope<'a, 'ctx>, scope: &Scope<'a, 'ctx>,
symbol: &Symbol, symbol: &Symbol,
) -> (BasicValueEnum<'ctx>, LambdaSet<'a>) { ) -> (BasicValueEnum<'ctx>, LambdaSet<'a>) {
match scope.get(symbol).map(|(l, v)| (layout_interner.get(*l), v)) { match scope.get(symbol).map(|(l, v)| (layout_interner.get(*l), v)) {

View file

@ -195,8 +195,8 @@ impl<'ctx> PointerToRefcount<'ctx> {
} }
} }
fn incref_pointer<'a, 'ctx, 'env>( fn incref_pointer<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>, pointer: PointerValue<'ctx>,
amount: IntValue<'ctx>, amount: IntValue<'ctx>,
) { ) {
@ -216,11 +216,7 @@ fn incref_pointer<'a, 'ctx, 'env>(
); );
} }
fn decref_pointer<'a, 'ctx, 'env>( fn decref_pointer<'ctx>(env: &Env<'_, 'ctx, '_>, pointer: PointerValue<'ctx>, alignment: u32) {
env: &Env<'a, 'ctx, 'env>,
pointer: PointerValue<'ctx>,
alignment: u32,
) {
let alignment = env.context.i32_type().const_int(alignment as _, false); let alignment = env.context.i32_type().const_int(alignment as _, false);
call_void_bitcode_fn( call_void_bitcode_fn(
env, env,
@ -239,8 +235,8 @@ fn decref_pointer<'a, 'ctx, 'env>(
} }
/// Assumes a pointer to the refcount /// Assumes a pointer to the refcount
pub fn decref_pointer_check_null<'a, 'ctx, 'env>( pub fn decref_pointer_check_null<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>, pointer: PointerValue<'ctx>,
alignment: u32, alignment: u32,
) { ) {
@ -261,8 +257,8 @@ pub fn decref_pointer_check_null<'a, 'ctx, 'env>(
); );
} }
fn modify_refcount_struct<'a, 'ctx, 'env>( fn modify_refcount_struct<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
layouts: &'a [InLayout<'a>], layouts: &'a [InLayout<'a>],
@ -308,8 +304,8 @@ fn modify_refcount_struct<'a, 'ctx, 'env>(
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn modify_refcount_struct_help<'a, 'ctx, 'env>( fn modify_refcount_struct_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
mode: Mode, mode: Mode,
@ -363,8 +359,8 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
builder.build_return(None); builder.build_return(None);
} }
pub fn increment_refcount_layout<'a, 'ctx, 'env>( pub fn increment_refcount_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
inc_amount: u64, inc_amount: u64,
@ -375,8 +371,8 @@ pub fn increment_refcount_layout<'a, 'ctx, 'env>(
increment_n_refcount_layout(env, layout_interner, layout_ids, amount, value, layout); increment_n_refcount_layout(env, layout_interner, layout_ids, amount, value, layout);
} }
pub fn increment_n_refcount_layout<'a, 'ctx, 'env>( pub fn increment_n_refcount_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
amount: IntValue<'ctx>, amount: IntValue<'ctx>,
@ -393,8 +389,8 @@ pub fn increment_n_refcount_layout<'a, 'ctx, 'env>(
); );
} }
pub fn decrement_refcount_layout<'a, 'ctx, 'env>( pub fn decrement_refcount_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
value: BasicValueEnum<'ctx>, value: BasicValueEnum<'ctx>,
@ -410,8 +406,8 @@ pub fn decrement_refcount_layout<'a, 'ctx, 'env>(
); );
} }
fn modify_refcount_builtin<'a, 'ctx, 'env>( fn modify_refcount_builtin<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
mode: Mode, mode: Mode,
@ -443,8 +439,8 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
} }
} }
fn modify_refcount_layout<'a, 'ctx, 'env>( fn modify_refcount_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
call_mode: CallMode<'ctx>, call_mode: CallMode<'ctx>,
@ -454,8 +450,8 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
modify_refcount_layout_help(env, layout_interner, layout_ids, call_mode, value, layout); modify_refcount_layout_help(env, layout_interner, layout_ids, call_mode, value, layout);
} }
fn modify_refcount_layout_help<'a, 'ctx, 'env>( fn modify_refcount_layout_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
call_mode: CallMode<'ctx>, call_mode: CallMode<'ctx>,
@ -495,8 +491,8 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
} }
} }
fn call_help<'a, 'ctx, 'env>( fn call_help<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
function: FunctionValue<'ctx>, function: FunctionValue<'ctx>,
call_mode: CallMode<'ctx>, call_mode: CallMode<'ctx>,
value: BasicValueEnum<'ctx>, value: BasicValueEnum<'ctx>,
@ -522,8 +518,8 @@ fn call_help<'a, 'ctx, 'env>(
call call
} }
fn modify_refcount_layout_build_function<'a, 'ctx, 'env>( fn modify_refcount_layout_build_function<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
mode: Mode, mode: Mode,
@ -596,8 +592,8 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
} }
} }
fn modify_refcount_list<'a, 'ctx, 'env>( fn modify_refcount_list<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
mode: Mode, mode: Mode,
@ -656,8 +652,8 @@ fn mode_to_call_mode(function: FunctionValue<'_>, mode: Mode) -> CallMode<'_> {
} }
} }
fn modify_refcount_list_help<'a, 'ctx, 'env>( fn modify_refcount_list_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
mode: Mode, mode: Mode,
@ -744,8 +740,8 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
builder.build_return(None); builder.build_return(None);
} }
fn modify_refcount_str<'a, 'ctx, 'env>( fn modify_refcount_str<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
mode: Mode, mode: Mode,
@ -781,8 +777,8 @@ fn modify_refcount_str<'a, 'ctx, 'env>(
function function
} }
fn modify_refcount_str_help<'a, 'ctx, 'env>( fn modify_refcount_str_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
mode: Mode, mode: Mode,
layout: InLayout<'a>, layout: InLayout<'a>,
@ -851,8 +847,8 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>(
builder.build_return(None); builder.build_return(None);
} }
fn modify_refcount_boxed<'a, 'ctx, 'env>( fn modify_refcount_boxed<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
mode: Mode, mode: Mode,
@ -890,8 +886,8 @@ fn modify_refcount_boxed<'a, 'ctx, 'env>(
function function
} }
fn modify_refcount_box_help<'a, 'ctx, 'env>( fn modify_refcount_box_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
mode: Mode, mode: Mode,
inner_layout: InLayout<'a>, inner_layout: InLayout<'a>,
@ -923,8 +919,8 @@ fn modify_refcount_box_help<'a, 'ctx, 'env>(
} }
/// Build an increment or decrement function for a specific layout /// Build an increment or decrement function for a specific layout
fn build_header<'a, 'ctx, 'env>( fn build_header<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
arg_type: BasicTypeEnum<'ctx>, arg_type: BasicTypeEnum<'ctx>,
mode: Mode, mode: Mode,
fn_name: &str, fn_name: &str,
@ -941,8 +937,8 @@ fn build_header<'a, 'ctx, 'env>(
} }
/// Build an increment or decrement function for a specific layout /// Build an increment or decrement function for a specific layout
pub fn build_header_help<'a, 'ctx, 'env>( pub fn build_header_help<'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'_, 'ctx, '_>,
fn_name: &str, fn_name: &str,
return_type: AnyTypeEnum<'ctx>, return_type: AnyTypeEnum<'ctx>,
arguments: &[BasicTypeEnum<'ctx>], arguments: &[BasicTypeEnum<'ctx>],
@ -1013,8 +1009,8 @@ enum CallMode<'ctx> {
Dec, Dec,
} }
fn build_rec_union<'a, 'ctx, 'env>( fn build_rec_union<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
mode: Mode, mode: Mode,
@ -1060,8 +1056,8 @@ fn build_rec_union<'a, 'ctx, 'env>(
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn build_rec_union_help<'a, 'ctx, 'env>( fn build_rec_union_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
mode: Mode, mode: Mode,
@ -1184,8 +1180,8 @@ fn fields_need_no_refcounting(interner: &STLayoutInterner, field_layouts: &[InLa
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>( fn build_rec_union_recursive_decrement<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
@ -1414,8 +1410,8 @@ fn union_layout_tags<'a>(
} }
} }
pub fn build_reset<'a, 'ctx, 'env>( pub fn build_reset<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
union_layout: UnionLayout<'a>, union_layout: UnionLayout<'a>,
@ -1458,8 +1454,8 @@ pub fn build_reset<'a, 'ctx, 'env>(
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn build_reuse_rec_union_help<'a, 'ctx, 'env>( fn build_reuse_rec_union_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
union_layout: UnionLayout<'a>, union_layout: UnionLayout<'a>,
@ -1572,8 +1568,8 @@ fn function_name_from_mode<'a>(
} }
} }
fn modify_refcount_nonrecursive<'a, 'ctx, 'env>( fn modify_refcount_nonrecursive<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
mode: Mode, mode: Mode,
@ -1619,8 +1615,8 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
function function
} }
fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>( fn modify_refcount_nonrecursive_help<'a, 'ctx>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>, layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
mode: Mode, mode: Mode,

View file

@ -1955,6 +1955,8 @@ impl<'a> LowLevelCall<'a> {
backend.storage.load_symbols(code_builder, self.arguments); backend.storage.load_symbols(code_builder, self.arguments);
} }
PtrWrite => todo!("{:?}", self.lowlevel),
Hash => todo!("{:?}", self.lowlevel), Hash => todo!("{:?}", self.lowlevel),
Eq | NotEq => self.eq_or_neq(backend), Eq | NotEq => self.eq_or_neq(backend),

View file

@ -115,6 +115,7 @@ pub enum LowLevel {
Not, Not,
Hash, Hash,
PtrCast, PtrCast,
PtrWrite,
RefCountInc, RefCountInc,
RefCountDec, RefCountDec,
BoxExpr, BoxExpr,
@ -219,6 +220,7 @@ macro_rules! map_symbol_to_lowlevel {
// these are used internally and not tied to a symbol // these are used internally and not tied to a symbol
LowLevel::Hash => unimplemented!(), LowLevel::Hash => unimplemented!(),
LowLevel::PtrCast => unimplemented!(), LowLevel::PtrCast => unimplemented!(),
LowLevel::PtrWrite => unimplemented!(),
LowLevel::RefCountInc => unimplemented!(), LowLevel::RefCountInc => unimplemented!(),
LowLevel::RefCountDec => unimplemented!(), LowLevel::RefCountDec => unimplemented!(),

View file

@ -1031,7 +1031,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[Ownership] {
unreachable!("These lowlevel operations are turned into mono Expr's") unreachable!("These lowlevel operations are turned into mono Expr's")
} }
PtrCast | RefCountInc | RefCountDec => { PtrCast | PtrWrite | RefCountInc | RefCountDec => {
unreachable!("Only inserted *after* borrow checking: {:?}", op); unreachable!("Only inserted *after* borrow checking: {:?}", op);
} }
} }

View file

@ -5,8 +5,8 @@ use roc_module::symbol::{IdentIds, ModuleId, Symbol};
use roc_target::TargetInfo; use roc_target::TargetInfo;
use crate::ir::{ use crate::ir::{
Call, CallSpecId, CallType, Expr, HostExposedLayouts, JoinPointId, ModifyRc, Proc, ProcLayout, Call, CallSpecId, CallType, Expr, HostExposedLayouts, JoinPointId, ModifyRc, PassedFunction,
SelfRecursive, Stmt, UpdateModeId, Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId,
}; };
use crate::layout::{ use crate::layout::{
Builtin, InLayout, LambdaName, Layout, LayoutInterner, Niche, STLayoutInterner, UnionLayout, Builtin, InLayout, LambdaName, Layout, LayoutInterner, Niche, STLayoutInterner, UnionLayout,
@ -20,6 +20,7 @@ const LAYOUT_UNIT: InLayout = Layout::UNIT;
const ARG_1: Symbol = Symbol::ARG_1; const ARG_1: Symbol = Symbol::ARG_1;
const ARG_2: Symbol = Symbol::ARG_2; const ARG_2: Symbol = Symbol::ARG_2;
const ARG_3: Symbol = Symbol::ARG_3;
/// "Infinite" reference count, for static values /// "Infinite" reference count, for static values
/// Ref counts are encoded as negative numbers where isize::MIN represents 1 /// Ref counts are encoded as negative numbers where isize::MIN represents 1
@ -580,6 +581,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>( fn let_lowlevel<'a>(
arena: &'a Bump, arena: &'a Bump,
result_layout: InLayout<'a>, result_layout: InLayout<'a>,

View file

@ -63,7 +63,6 @@ pub fn pretty_print_ir_symbols() -> bool {
// if your changes cause this number to go down, great! // if your changes cause this number to go down, great!
// please change it to the lower number. // please change it to the lower number.
// if it went up, maybe check that the change is really required // if it went up, maybe check that the change is really required
roc_error_macros::assert_sizeof_wasm!(Literal, 24); roc_error_macros::assert_sizeof_wasm!(Literal, 24);
roc_error_macros::assert_sizeof_wasm!(Expr, 48); roc_error_macros::assert_sizeof_wasm!(Expr, 48);
roc_error_macros::assert_sizeof_wasm!(Stmt, 64); roc_error_macros::assert_sizeof_wasm!(Stmt, 64);
@ -3027,7 +3026,7 @@ fn specialize_external_help<'a>(
for in_layout in host_exposed_layouts { for in_layout in host_exposed_layouts {
let layout = layout_cache.interner.get(in_layout); let layout = layout_cache.interner.get(in_layout);
let all_glue_procs = generate_glue_procs( let mut all_glue_procs = generate_glue_procs(
env.home, env.home,
env.ident_ids, env.ident_ids,
env.arena, env.arena,
@ -3035,6 +3034,17 @@ fn specialize_external_help<'a>(
env.arena.alloc(layout), env.arena.alloc(layout),
); );
all_glue_procs.extern_names = {
let mut layout_env = layout::Env::from_components(
layout_cache,
env.subs,
env.arena,
env.target_info,
);
find_lambda_sets(&mut layout_env, variable)
};
// for now, getters are not processed here // for now, getters are not processed here
let GlueProcs { let GlueProcs {
getters, getters,
@ -3053,23 +3063,10 @@ fn specialize_external_help<'a>(
let mut aliases = BumpMap::default(); let mut aliases = BumpMap::default();
for (id, mut raw_function_layout) in extern_names { for (id, raw_function_layout) in extern_names {
let symbol = env.unique_symbol(); let symbol = env.unique_symbol();
let lambda_name = LambdaName::no_niche(symbol); let lambda_name = LambdaName::no_niche(symbol);
// fix the recursion in the rocLovesRust example
if false {
raw_function_layout = match raw_function_layout {
RawFunctionLayout::Function(a, mut lambda_set, _) => {
lambda_set.ret = in_layout;
RawFunctionLayout::Function(a, lambda_set, in_layout)
}
RawFunctionLayout::ZeroArgumentThunk(x) => {
RawFunctionLayout::ZeroArgumentThunk(x)
}
};
}
let (key, (top_level, proc)) = generate_host_exposed_function( let (key, (top_level, proc)) = generate_host_exposed_function(
env, env,
procs, procs,
@ -9521,6 +9518,126 @@ impl LambdaSetId {
} }
} }
fn find_lambda_sets<'a>(
env: &mut crate::layout::Env<'a, '_>,
initial: Variable,
) -> Vec<'a, (LambdaSetId, RawFunctionLayout<'a>)> {
let mut stack = bumpalo::collections::Vec::new_in(env.arena);
// ignore the lambda set of top-level functions
match env.subs.get_without_compacting(initial).content {
Content::Structure(FlatType::Func(arguments, _, result)) => {
let arguments = &env.subs.variables[arguments.indices()];
stack.extend(arguments.iter().copied());
stack.push(result);
}
_ => {
stack.push(initial);
}
}
let lambda_set_variables = find_lambda_sets_help(env.subs, stack);
let mut answer =
bumpalo::collections::Vec::with_capacity_in(lambda_set_variables.len(), env.arena);
for (variable, lambda_set_id) in lambda_set_variables {
let lambda_set = env.subs.get_lambda_set(variable);
let raw_function_layout = RawFunctionLayout::from_var(env, lambda_set.ambient_function)
.value()
.unwrap();
let key = (lambda_set_id, raw_function_layout);
answer.push(key);
}
answer
}
pub fn find_lambda_sets_help(
subs: &Subs,
mut stack: Vec<'_, Variable>,
) -> MutMap<Variable, LambdaSetId> {
use roc_types::subs::GetSubsSlice;
let mut lambda_set_id = LambdaSetId::default();
let mut result = MutMap::default();
while let Some(var) = stack.pop() {
match subs.get_content_without_compacting(var) {
Content::RangedNumber(_)
| Content::Error
| Content::FlexVar(_)
| Content::RigidVar(_)
| Content::FlexAbleVar(_, _)
| Content::RigidAbleVar(_, _)
| Content::RecursionVar { .. } => {}
Content::Structure(flat_type) => match flat_type {
FlatType::Apply(_, arguments) => {
stack.extend(subs.get_subs_slice(*arguments).iter().rev());
}
FlatType::Func(arguments, lambda_set_var, ret_var) => {
result.insert(*lambda_set_var, lambda_set_id);
lambda_set_id = lambda_set_id.next();
let arguments = &subs.variables[arguments.indices()];
stack.extend(arguments.iter().copied());
stack.push(*lambda_set_var);
stack.push(*ret_var);
}
FlatType::Record(fields, ext) => {
stack.extend(subs.get_subs_slice(fields.variables()).iter().rev());
stack.push(*ext);
}
FlatType::Tuple(elements, ext) => {
stack.extend(subs.get_subs_slice(elements.variables()).iter().rev());
stack.push(*ext);
}
FlatType::FunctionOrTagUnion(_, _, ext) => {
// just the ext
match ext {
roc_types::subs::TagExt::Openness(var) => stack.push(*var),
roc_types::subs::TagExt::Any(_) => { /* ignore */ }
}
}
FlatType::TagUnion(union_tags, ext)
| FlatType::RecursiveTagUnion(_, union_tags, ext) => {
for tag in union_tags.variables() {
stack.extend(
subs.get_subs_slice(subs.variable_slices[tag.index as usize])
.iter()
.rev(),
);
}
match ext {
roc_types::subs::TagExt::Openness(var) => stack.push(*var),
roc_types::subs::TagExt::Any(_) => { /* ignore */ }
}
}
FlatType::EmptyRecord => {}
FlatType::EmptyTuple => {}
FlatType::EmptyTagUnion => {}
},
Content::Alias(_, _, actual, _) => {
stack.push(*actual);
}
Content::LambdaSet(lambda_set) => {
// the lambda set itself should already be caught by Func above, but the
// capture can itself contain more lambda sets
for index in lambda_set.solved.variables() {
let subs_slice = subs.variable_slices[index.index as usize];
stack.extend(subs.variables[subs_slice.indices()].iter());
}
}
}
}
result
}
pub fn generate_glue_procs<'a, 'i, I>( pub fn generate_glue_procs<'a, 'i, I>(
home: ModuleId, home: ModuleId,
ident_ids: &mut IdentIds, ident_ids: &mut IdentIds,

View file

@ -1193,7 +1193,7 @@ fn extract<'a>(
/// FIND IRRELEVANT BRANCHES /// FIND IRRELEVANT BRANCHES
fn is_irrelevant_to(selected_path: &[PathInstruction], branch: &Branch<'_>) -> bool { fn is_irrelevant_to(selected_path: &[PathInstruction], branch: &Branch) -> bool {
match branch match branch
.patterns .patterns
.iter() .iter()
@ -1358,7 +1358,7 @@ fn small_branching_factor(branches: &[Branch], path: &[PathInstruction]) -> usiz
branches.iter().any(|b| is_irrelevant_to(path, b)) branches.iter().any(|b| is_irrelevant_to(path, b))
}; };
relevant_tests.len() + (if !fallbacks { 0 } else { 1 }) relevant_tests.len() + usize::from(fallbacks)
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]

View file

@ -634,7 +634,10 @@ impl<'a> RawFunctionLayout<'a> {
/// Returns Err(()) if given an error, or Ok(Layout) if given a non-erroneous Structure. /// Returns Err(()) if given an error, or Ok(Layout) if given a non-erroneous Structure.
/// Panics if given a FlexVar or RigidVar, since those should have been /// Panics if given a FlexVar or RigidVar, since those should have been
/// monomorphized away already! /// monomorphized away already!
fn from_var(env: &mut Env<'a, '_>, var: Variable) -> Cacheable<RawFunctionLayoutResult<'a>> { pub(crate) fn from_var(
env: &mut Env<'a, '_>,
var: Variable,
) -> Cacheable<RawFunctionLayoutResult<'a>> {
env.cached_raw_function_or(var, |env| { env.cached_raw_function_or(var, |env| {
if env.is_seen(var) { if env.is_seen(var) {
unreachable!("The initial variable of a signature cannot be seen already") unreachable!("The initial variable of a signature cannot be seen already")
@ -2175,9 +2178,9 @@ macro_rules! list_element_layout {
pub struct Env<'a, 'b> { pub struct Env<'a, 'b> {
target_info: TargetInfo, target_info: TargetInfo,
arena: &'a Bump, pub(crate) arena: &'a Bump,
seen: Vec<'a, Variable>, seen: Vec<'a, Variable>,
subs: &'b Subs, pub(crate) subs: &'b Subs,
cache: &'b mut LayoutCache<'a>, cache: &'b mut LayoutCache<'a>,
} }

View file

@ -433,6 +433,22 @@ impl<'a> InLayout<'a> {
pub fn index(&self) -> usize { pub fn index(&self) -> usize {
self.0 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. /// A concurrent interner, suitable for usage between threads.

View file

@ -14,6 +14,7 @@ version.workspace = true
roc_collections = { path = "../collections" } roc_collections = { path = "../collections" }
roc_module = { path = "../module" } roc_module = { path = "../module" }
roc_region = { path = "../region" } roc_region = { path = "../region" }
roc_error_macros = { path = "../../error_macros" }
bumpalo.workspace = true bumpalo.workspace = true
encode_unicode.workspace = true encode_unicode.workspace = true

View file

@ -21,6 +21,7 @@ use crate::type_annotation;
use bumpalo::collections::Vec; use bumpalo::collections::Vec;
use bumpalo::Bump; use bumpalo::Bump;
use roc_collections::soa::Slice; use roc_collections::soa::Slice;
use roc_error_macros::internal_error;
use roc_module::called_via::{BinOp, CalledVia, UnaryOp}; use roc_module::called_via::{BinOp, CalledVia, UnaryOp};
use roc_region::all::{Loc, Position, Region}; 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, // 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`, // by splitting out parts[0] into a separate field with a type of `&'a str`,
// rather than a `&'a [Accessor<'a>]`. // 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 => { None => {
panic!("Parsed an Ident::Access with no parts"); internal_error!("Parsed an Ident::Access with no parts");
} }
}; };

View file

@ -545,7 +545,7 @@ fn compact_lambda_set<P: Phase>(
Err(()) => { Err(()) => {
// Do nothing other than to remove the concrete lambda to drop from the lambda set, // Do nothing other than to remove the concrete lambda to drop from the lambda set,
// which we already did in 1b above. // which we already did in 1b above.
trace_compact!(3iter_end_skipped. subs, t_f1); trace_compact!(3iter_end_skipped.subs, t_f1);
return OneCompactionResult::Compacted { return OneCompactionResult::Compacted {
new_obligations: Default::default(), new_obligations: Default::default(),
new_lambda_sets_to_specialize: Default::default(), new_lambda_sets_to_specialize: Default::default(),
@ -568,7 +568,7 @@ fn compact_lambda_set<P: Phase>(
Err(()) => { Err(()) => {
// Do nothing other than to remove the concrete lambda to drop from the lambda set, // Do nothing other than to remove the concrete lambda to drop from the lambda set,
// which we already did in 1b above. // which we already did in 1b above.
trace_compact!(3iter_end_skipped. subs, t_f1); trace_compact!(3iter_end_skipped.subs, t_f1);
return OneCompactionResult::Compacted { return OneCompactionResult::Compacted {
new_obligations: Default::default(), new_obligations: Default::default(),
new_lambda_sets_to_specialize: Default::default(), new_lambda_sets_to_specialize: Default::default(),
@ -581,7 +581,7 @@ fn compact_lambda_set<P: Phase>(
let t_f2 = deep_copy_var_in(subs, target_rank, pools, t_f2, arena); let t_f2 = deep_copy_var_in(subs, target_rank, pools, t_f2, arena);
// 3. Unify `t_f1 ~ t_f2`. // 3. Unify `t_f1 ~ t_f2`.
trace_compact!(3iter_start. subs, this_lambda_set, t_f1, t_f2); trace_compact!(3iter_start.subs, this_lambda_set, t_f1, t_f2);
let (vars, new_obligations, new_lambda_sets_to_specialize, _meta) = unify( let (vars, new_obligations, new_lambda_sets_to_specialize, _meta) = unify(
&mut UEnv::new(subs), &mut UEnv::new(subs),
t_f1, t_f1,
@ -590,7 +590,7 @@ fn compact_lambda_set<P: Phase>(
Polarity::Pos, Polarity::Pos,
) )
.expect_success("ambient functions don't unify"); .expect_success("ambient functions don't unify");
trace_compact!(3iter_end. subs, t_f1); trace_compact!(3iter_end.subs, t_f1);
introduce(subs, target_rank, pools, &vars); introduce(subs, target_rank, pools, &vars);

View file

@ -1200,7 +1200,7 @@ fn list_count_if_str() {
} }
#[test] #[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() { fn list_map_on_empty_list_with_int_layout() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -1218,7 +1218,7 @@ fn list_map_on_empty_list_with_int_layout() {
} }
#[test] #[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() { fn list_map_on_non_empty_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -1236,7 +1236,7 @@ fn list_map_on_non_empty_list() {
} }
#[test] #[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() { fn list_map_changes_input() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -1254,7 +1254,7 @@ fn list_map_changes_input() {
} }
#[test] #[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() { fn list_map_on_big_list() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -1274,7 +1274,7 @@ fn list_map_on_big_list() {
} }
#[test] #[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() { fn list_map_with_type_change() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -1293,7 +1293,7 @@ fn list_map_with_type_change() {
} }
#[test] #[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() { fn list_map_using_defined_function() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
@ -1315,7 +1315,7 @@ fn list_map_using_defined_function() {
} }
#[test] #[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() { fn list_map_all_inline() {
assert_evals_to!( assert_evals_to!(
indoc!( 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] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_map_closure() { fn list_map_closure_float() {
assert_evals_to!( assert_evals_to!(
indoc!( indoc!(
r#" r#"
@ -2926,7 +2947,7 @@ fn list_any_empty_with_unknown_element_type() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn list_all() { fn list_all() {
assert_evals_to!("List.all [] (\\e -> e > 3)", true, bool); assert_evals_to!("List.all [] (\\e -> e > 3)", true, bool);
assert_evals_to!("List.all [1, 2, 3] (\\e -> e > 3)", false, bool); assert_evals_to!("List.all [1, 2, 3] (\\e -> e > 3)", false, bool);

View file

@ -3113,7 +3113,7 @@ fn when_on_i16() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn num_to_str() { fn num_to_str() {
use roc_std::RocStr; use roc_std::RocStr;
@ -4055,3 +4055,27 @@ fn num_abs_large_bits_min_overflow() {
fn num_abs_float_overflow() { fn num_abs_float_overflow() {
assert_evals_to!("Num.absDiff Num.maxF64 Num.minF64", f64::INFINITY, f64); 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
);
}

View file

@ -497,23 +497,23 @@ fn str_concat_empty() {
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
fn small_str_is_empty() { fn small_str_is_empty() {
assert_evals_to!(r#"Str.isEmpty "abc""#, false, bool); assert_evals_to!(r#"Str.isEmpty "abc""#, false, bool);
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
fn big_str_is_empty() { fn big_str_is_empty() {
assert_evals_to!( assert_evals_to!(
r#"Str.isEmpty "this is more than 15 chars long""#, r#"Str.isEmpty "this is more than 23 chars long""#,
false, false,
bool bool
); );
} }
#[test] #[test]
#[cfg(any(feature = "gen-llvm"))] #[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
fn empty_str_is_empty() { fn empty_str_is_empty() {
assert_evals_to!(r#"Str.isEmpty """#, true, bool); assert_evals_to!(r#"Str.isEmpty """#, true, bool);
} }

View file

@ -907,7 +907,9 @@ fn alignment_in_multi_tag_pattern_match() {
{ bool, int } { bool, int }
Empty -> 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), (32i64, true),
@ -924,7 +926,8 @@ fn alignment_in_multi_tag_pattern_match() {
Three bool color int -> Three bool color int ->
{ bool, color, int } { bool, color, int }
Empty -> Empty ->
{ bool: Bool.false, color: Red, int: 0 } false = Bool.false
{ bool: false, color: Red, int: 0 }
#" #"
), ),
(32i64, true, 2u8), (32i64, true, 2u8),

View file

@ -1,10 +1,6 @@
procedure Test.1 (Test.4): procedure Test.1 (Test.4):
ret Test.4; ret Test.4;
procedure Test.21 (Test.23, #Attr.12):
let Test.22 : Str = CallByName Test.5 Test.23 #Attr.12;
ret Test.22;
procedure Test.5 (Test.12, Test.4): procedure Test.5 (Test.12, Test.4):
dec Test.4; dec Test.4;
let Test.14 : Str = ""; let Test.14 : Str = "";

View file

@ -3,6 +3,7 @@ procedure Bool.2 ():
ret Bool.23; ret Bool.23;
procedure Test.10 (Test.25): procedure Test.10 (Test.25):
dec Test.25;
let Test.29 : Int1 = CallByName Bool.2; let Test.29 : Int1 = CallByName Bool.2;
if Test.29 then if Test.29 then
let Test.30 : [<rnu><null>, C {}] = CallByName Test.0; let Test.30 : [<rnu><null>, C {}] = CallByName Test.0;
@ -29,7 +30,6 @@ procedure Test.6 (Test.16, #Attr.12):
let Test.19 : {} = Struct {}; let Test.19 : {} = Struct {};
let Test.22 : Str = "foobar"; let Test.22 : Str = "foobar";
let Test.20 : [<rnu><null>, C {}] = CallByName Test.8 Test.22 Test.5; let Test.20 : [<rnu><null>, C {}] = CallByName Test.8 Test.22 Test.5;
dec Test.22;
let Test.21 : U8 = GetTagId Test.20; let Test.21 : U8 = GetTagId Test.20;
switch Test.21: switch Test.21:
case 0: case 0:

View file

@ -18,10 +18,6 @@ procedure Test.34 (Test.35):
let Test.37 : {} = StructAtIndex 1 Test.36; let Test.37 : {} = StructAtIndex 1 Test.36;
ret Test.37; ret Test.37;
procedure Test.38 (Test.40, #Attr.12):
let Test.39 : Str = CallByName Test.4 Test.40 #Attr.12;
ret Test.39;
procedure Test.4 (Test.13, #Attr.12): procedure Test.4 (Test.13, #Attr.12):
let Test.3 : {} = StructAtIndex 1 #Attr.12; let Test.3 : {} = StructAtIndex 1 #Attr.12;
let Test.2 : U16 = StructAtIndex 0 #Attr.12; let Test.2 : U16 = StructAtIndex 0 #Attr.12;
@ -38,10 +34,6 @@ procedure Test.4 (Test.13, #Attr.12):
let Test.15 : Str = CallByName Test.4 Test.16 Test.5; let Test.15 : Str = CallByName Test.4 Test.16 Test.5;
ret Test.15; ret Test.15;
procedure Test.41 (Test.43, #Attr.12):
let Test.42 : {U16, {}} = CallByName Test.6 Test.43;
ret Test.42;
procedure Test.6 (Test.17): procedure Test.6 (Test.17):
let Test.19 : U16 = 1i64; let Test.19 : U16 = 1i64;
let Test.20 : {} = Struct {}; let Test.20 : {} = Struct {};

View file

@ -18,10 +18,6 @@ procedure Test.34 (Test.35):
let Test.37 : {} = StructAtIndex 1 Test.36; let Test.37 : {} = StructAtIndex 1 Test.36;
ret Test.37; ret Test.37;
procedure Test.38 (Test.40, #Attr.12):
let Test.39 : Str = CallByName Test.4 Test.40 #Attr.12;
ret Test.39;
procedure Test.4 (Test.13, #Attr.12): procedure Test.4 (Test.13, #Attr.12):
let Test.3 : {} = StructAtIndex 1 #Attr.12; let Test.3 : {} = StructAtIndex 1 #Attr.12;
let Test.2 : U8 = StructAtIndex 0 #Attr.12; let Test.2 : U8 = StructAtIndex 0 #Attr.12;
@ -38,10 +34,6 @@ procedure Test.4 (Test.13, #Attr.12):
let Test.24 : Str = CallByName Test.8 Test.25; let Test.24 : Str = CallByName Test.8 Test.25;
ret Test.24; ret Test.24;
procedure Test.41 (Test.43, #Attr.12):
let Test.42 : {U8, {}} = CallByName Test.6 Test.43;
ret Test.42;
procedure Test.6 (Test.17): procedure Test.6 (Test.17):
let Test.19 : U8 = 1i64; let Test.19 : U8 = 1i64;
let Test.20 : {} = Struct {}; let Test.20 : {} = Struct {};

View file

@ -2550,7 +2550,6 @@ fn recursively_build_effect() {
} }
#[mono_test] #[mono_test]
#[ignore = "roc glue code generation cannot handle a type that this test generates"]
fn recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026() { fn recursive_lambda_set_has_nested_non_recursive_lambda_sets_issue_5026() {
indoc!( indoc!(
r#" r#"

View file

@ -544,9 +544,9 @@ mod test_snapshots {
let mut parent = std::path::PathBuf::from("tests"); let mut parent = std::path::PathBuf::from("tests");
parent.push("snapshots"); parent.push("snapshots");
parent.push(expect.to_dir_name()); parent.push(expect.to_dir_name());
let input_path = parent.join(&format!("{}.{}.roc", name, ty)); let input_path = parent.join(format!("{}.{}.roc", name, ty));
let result_path = parent.join(&format!("{}.{}.result-ast", name, ty)); let result_path = parent.join(format!("{}.{}.result-ast", name, ty));
let formatted_path = parent.join(&format!("{}.{}.formatted.roc", name, ty)); let formatted_path = parent.join(format!("{}.{}.formatted.roc", name, ty));
let source = std::fs::read_to_string(&input_path).unwrap_or_else(|err| { let source = std::fs::read_to_string(&input_path).unwrap_or_else(|err| {
panic!( panic!(

View file

@ -52,6 +52,7 @@ convertTypesToFile = \types ->
buf buf
TagUnion (NullableWrapped { name, indexOfNullTag, tags, discriminantSize, discriminantOffset }) -> TagUnion (NullableWrapped { name, indexOfNullTag, tags, discriminantSize, discriminantOffset }) ->
# TODO: generate this as `TypeName(*mut u8)` if the payload contains functions / unsized types
generateRecursiveTagUnion buf types id name tags discriminantSize discriminantOffset (Some indexOfNullTag) generateRecursiveTagUnion buf types id name tags discriminantSize discriminantOffset (Some indexOfNullTag)
TagUnion (NullableUnwrapped { name, nullTag, nonNullTag, nonNullPayload, whichTagIsNull }) -> TagUnion (NullableUnwrapped { name, nullTag, nonNullTag, nonNullPayload, whichTagIsNull }) ->
@ -244,14 +245,14 @@ generateStruct = \buf, types, id, name, structFields, visibility ->
pub = pub =
when visibility is when visibility is
Public -> "pub" Public -> "pub "
Private -> "" Private -> ""
structType = Types.shape types id structType = Types.shape types id
buf buf
|> generateDeriveStr types structType IncludeDebug |> generateDeriveStr types structType IncludeDebug
|> Str.concat "#[repr(\(repr))]\n\(pub) struct \(escapedName) {\n" |> Str.concat "#[repr(\(repr))]\n\(pub)struct \(escapedName) {\n"
|> generateStructFields types Public structFields |> generateStructFields types Public structFields
|> Str.concat "}\n\n" |> Str.concat "}\n\n"
@ -836,6 +837,12 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz
Self((ptr as usize | tag_id as usize) as *mut _) Self((ptr as usize | tag_id as usize) as *mut _)
} }
pub fn get_\(tagName)(mut self) -> \(escapedName)_\(tagName) {
debug_assert!(self.is_\(tagName)());
unsafe { core::mem::ManuallyDrop::take(&mut self.ptr_read_union().\(tagName)) }
}
""" """
constructors = constructors =
@ -854,7 +861,7 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz
let tag_id = discriminant_\(escapedName)::\(tagName); let tag_id = discriminant_\(escapedName)::\(tagName);
let payload_union = unsafe { self.ptr_read_union() }; let payload_union = unsafe { self.ptr_read_union() };
let payload = union_\(escapedName) { let payload = union_\(escapedName) {
\(tagName): unsafe { payload_union.\(tagName).clone() }, \(tagName): unsafe { payload_union.\(tagName).clone() },
}; };
@ -880,7 +887,7 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz
let payload_union1 = unsafe { self.ptr_read_union() }; let payload_union1 = unsafe { self.ptr_read_union() };
let payload_union2 = unsafe { other.ptr_read_union() }; let payload_union2 = unsafe { other.ptr_read_union() };
unsafe { unsafe {
payload_union1.\(tagName) == payload_union2.\(tagName) payload_union1.\(tagName) == payload_union2.\(tagName)
} }
}, },
@ -923,7 +930,7 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz
\(tagName) => { \(tagName) => {
let payload_union = unsafe { self.ptr_read_union() }; let payload_union = unsafe { self.ptr_read_union() };
unsafe { unsafe {
f.debug_tuple("\(escapedName)::\(tagName)")\(debugFields).finish() f.debug_tuple("\(escapedName)::\(tagName)")\(debugFields).finish()
} }
}, },
@ -937,7 +944,7 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz
hashCase = \{ name: tagName }, index -> hashCase = \{ name: tagName }, index ->
if Some (Num.intCast index) == nullTagIndex then if Some (Num.intCast index) == nullTagIndex then
""" """
\(tagName) => {} \(tagName) => {}
""" """
else else
""" """
@ -963,7 +970,7 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz
let payload_union1 = unsafe { self.ptr_read_union() }; let payload_union1 = unsafe { self.ptr_read_union() };
let payload_union2 = unsafe { other.ptr_read_union() }; let payload_union2 = unsafe { other.ptr_read_union() };
unsafe { unsafe {
payload_union1.\(tagName).cmp(&payload_union2.\(tagName)) payload_union1.\(tagName).cmp(&payload_union2.\(tagName))
} }
}, },
@ -988,7 +995,7 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz
const _ALIGN_CHECK_\(escapedName): () = assert!(core::mem::align_of::<\(escapedName)>() == \(alignOfSelf)); const _ALIGN_CHECK_\(escapedName): () = assert!(core::mem::align_of::<\(escapedName)>() == \(alignOfSelf));
impl \(escapedName) { impl \(escapedName) {
fn discriminant(&self) -> discriminant_\(escapedName) { pub fn discriminant(&self) -> discriminant_\(escapedName) {
let discriminants = { let discriminants = {
use \(discriminantName)::*; use \(discriminantName)::*;

View file

@ -1226,81 +1226,8 @@ impl<'a> Env<'a> {
} }
fn find_lambda_sets(&self, root: Variable) -> MutMap<Variable, LambdaSetId> { fn find_lambda_sets(&self, root: Variable) -> MutMap<Variable, LambdaSetId> {
let mut lambda_set_id = LambdaSetId::default(); let stack = bumpalo::vec![in self.arena; root];
roc_mono::ir::find_lambda_sets_help(self.subs, stack)
let mut result = MutMap::default();
let mut stack = vec![root];
while let Some(var) = stack.pop() {
match self.subs.get_content_without_compacting(var) {
Content::RangedNumber(_)
| Content::Error
| Content::FlexVar(_)
| Content::RigidVar(_)
| Content::FlexAbleVar(_, _)
| Content::RigidAbleVar(_, _)
| Content::RecursionVar { .. } => {}
Content::Structure(flat_type) => match flat_type {
FlatType::Apply(_, arguments) => {
stack.extend(self.subs.get_subs_slice(*arguments).iter().rev());
}
FlatType::Func(_, lambda_set_var, _) => {
result.insert(*lambda_set_var, lambda_set_id);
lambda_set_id = lambda_set_id.next();
// the lambda set itself can contain more lambda sets
stack.push(*lambda_set_var);
}
FlatType::Record(fields, ext) => {
stack.extend(self.subs.get_subs_slice(fields.variables()).iter().rev());
stack.push(*ext);
}
FlatType::Tuple(elements, ext) => {
stack.extend(self.subs.get_subs_slice(elements.variables()).iter().rev());
stack.push(*ext);
}
FlatType::FunctionOrTagUnion(_, _, ext) => {
// just the ext
match ext {
roc_types::subs::TagExt::Openness(var) => stack.push(*var),
roc_types::subs::TagExt::Any(_) => { /* ignore */ }
}
}
FlatType::TagUnion(union_tags, ext)
| FlatType::RecursiveTagUnion(_, union_tags, ext) => {
for tag in union_tags.variables() {
stack.extend(
self.subs
.get_subs_slice(self.subs.variable_slices[tag.index as usize])
.iter()
.rev(),
);
}
match ext {
roc_types::subs::TagExt::Openness(var) => stack.push(*var),
roc_types::subs::TagExt::Any(_) => { /* ignore */ }
}
}
FlatType::EmptyRecord => {}
FlatType::EmptyTuple => {}
FlatType::EmptyTagUnion => {}
},
Content::Alias(_, _, actual, _) => {
stack.push(*actual);
}
Content::LambdaSet(lambda_set) => {
// the lambda set itself should already be caught by Func above, but the
// capture can itself contain more lambda sets
for index in lambda_set.solved.variables() {
let subs_slice = self.subs.variable_slices[index.index as usize];
stack.extend(self.subs.variables[subs_slice.indices()].iter());
}
}
}
}
result
} }
fn add_toplevel_type(&mut self, var: Variable, types: &mut Types) -> TypeId { fn add_toplevel_type(&mut self, var: Variable, types: &mut Types) -> TypeId {

View file

@ -1,21 +1,22 @@
use bincode::{deserialize_from, serialize_into};
use iced_x86::{Decoder, DecoderOptions, Instruction, OpCodeOperandKind, OpKind}; use iced_x86::{Decoder, DecoderOptions, Instruction, OpCodeOperandKind, OpKind};
use memmap2::MmapMut; use memmap2::MmapMut;
use object::{elf, endian}; use object::{elf, endian};
use object::{ use object::{
CompressedFileRange, CompressionFormat, LittleEndian as LE, NativeEndian, Object, CompressedFileRange, CompressionFormat, LittleEndian as LE, Object, ObjectSection,
ObjectSection, ObjectSymbol, RelocationKind, RelocationTarget, Section, SectionIndex, ObjectSymbol, RelocationKind, RelocationTarget, Section, SectionIndex, SectionKind, Symbol,
SectionKind, Symbol, SymbolIndex, SymbolSection, SymbolIndex, SymbolSection,
}; };
use roc_collections::all::MutMap; use roc_collections::all::MutMap;
use roc_error_macros::{internal_error, user_error}; use roc_error_macros::{internal_error, user_error};
use std::convert::TryFrom; use serde::{Deserialize, Serialize};
use std::ffi::CStr; use std::{
use std::mem; ffi::{c_char, CStr},
use std::os::raw::c_char; io::{BufReader, BufWriter},
use std::path::Path; mem,
use std::time::{Duration, Instant}; path::Path,
time::{Duration, Instant},
use crate::metadata::{self, Metadata, VirtualOffset}; };
use crate::{ use crate::{
align_by_constraint, align_to_offset_by_constraint, load_struct_inplace, align_by_constraint, align_to_offset_by_constraint, load_struct_inplace,
@ -35,6 +36,73 @@ struct ElfDynamicDeps {
shared_lib_index: usize, shared_lib_index: usize,
} }
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
enum VirtualOffset {
Absolute,
Relative(u64),
}
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct SurgeryEntry {
file_offset: u64,
virtual_offset: VirtualOffset,
size: u8,
}
// TODO: Reanalyze each piece of data in this struct.
// I think a number of them can be combined to reduce string duplication.
// Also I think a few of them aren't need.
// For example, I think preprocessing can deal with all shifting and remove the need for added_byte_count.
// TODO: we probably should be storing numbers in an endian neutral way.
#[derive(Default, Serialize, Deserialize, PartialEq, Eq, Debug)]
struct Metadata {
app_functions: Vec<String>,
// offset followed by address.
plt_addresses: MutMap<String, (u64, u64)>,
surgeries: MutMap<String, Vec<SurgeryEntry>>,
dynamic_symbol_indices: MutMap<String, u64>,
static_symbol_indices: MutMap<String, u64>,
roc_symbol_vaddresses: MutMap<String, u64>,
exec_len: u64,
load_align_constraint: u64,
added_byte_count: u64,
last_vaddr: u64,
dynamic_section_offset: u64,
dynamic_symbol_table_section_offset: u64,
symbol_table_section_offset: u64,
symbol_table_size: u64,
_macho_cmd_loc: u64,
}
impl Metadata {
fn write_to_file(&self, metadata_filename: &Path) {
let metadata_file =
std::fs::File::create(metadata_filename).unwrap_or_else(|e| internal_error!("{}", e));
serialize_into(BufWriter::new(metadata_file), self)
.unwrap_or_else(|err| internal_error!("Failed to serialize metadata: {err}"));
}
fn read_from_file(metadata_filename: &Path) -> Self {
let input = std::fs::File::open(metadata_filename).unwrap_or_else(|e| {
internal_error!(
r#"
Error:
{}\n"#,
e
)
});
match deserialize_from(BufReader::new(input)) {
Ok(data) => data,
Err(err) => {
internal_error!("Failed to deserialize metadata: {}", err);
}
}
}
}
fn report_timing(label: &str, duration: Duration) { fn report_timing(label: &str, duration: Duration) {
println!("\t{:9.3} ms {}", duration.as_secs_f64() * 1000.0, label,); println!("\t{:9.3} ms {}", duration.as_secs_f64() * 1000.0, label,);
} }
@ -95,7 +163,7 @@ fn collect_roc_definitions<'a>(object: &object::File<'a, &'a [u8]>) -> MutMap<St
} }
struct Surgeries<'a> { struct Surgeries<'a> {
surgeries: MutMap<String, Vec<metadata::SurgeryEntry>>, surgeries: MutMap<String, Vec<SurgeryEntry>>,
app_func_addresses: MutMap<u64, &'a str>, app_func_addresses: MutMap<u64, &'a str>,
indirect_warning_given: bool, indirect_warning_given: bool,
} }
@ -229,7 +297,7 @@ impl<'a> Surgeries<'a> {
self.surgeries self.surgeries
.get_mut(*func_name) .get_mut(*func_name)
.unwrap() .unwrap()
.push(metadata::SurgeryEntry { .push(SurgeryEntry {
file_offset: offset, file_offset: offset,
virtual_offset: VirtualOffset::Relative(inst.next_ip()), virtual_offset: VirtualOffset::Relative(inst.next_ip()),
size: op_size, size: op_size,
@ -265,7 +333,7 @@ impl<'a> Surgeries<'a> {
} }
} }
/// Constructs a `metadata::Metadata` from a host executable binary, and writes it to disk /// Constructs a `Metadata` from a host executable binary, and writes it to disk
pub(crate) fn preprocess_elf( pub(crate) fn preprocess_elf(
endianness: target_lexicon::Endianness, endianness: target_lexicon::Endianness,
host_exe_path: &Path, host_exe_path: &Path,
@ -285,7 +353,7 @@ pub(crate) fn preprocess_elf(
} }
}; };
let mut md = metadata::Metadata { let mut md = Metadata {
roc_symbol_vaddresses: collect_roc_definitions(&exec_obj), roc_symbol_vaddresses: collect_roc_definitions(&exec_obj),
..Default::default() ..Default::default()
}; };
@ -507,7 +575,7 @@ pub(crate) fn preprocess_elf(
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn gen_elf_le( fn gen_elf_le(
exec_data: &[u8], exec_data: &[u8],
md: &mut metadata::Metadata, md: &mut Metadata,
preprocessed_path: &Path, preprocessed_path: &Path,
got_app_syms: &[(String, usize)], got_app_syms: &[(String, usize)],
got_sections: &[(usize, usize)], got_sections: &[(usize, usize)],
@ -517,12 +585,12 @@ fn gen_elf_le(
verbose: bool, verbose: bool,
) -> MmapMut { ) -> MmapMut {
let exec_header = load_struct_inplace::<elf::FileHeader64<LE>>(exec_data, 0); let exec_header = load_struct_inplace::<elf::FileHeader64<LE>>(exec_data, 0);
let ph_offset = exec_header.e_phoff.get(NativeEndian); let ph_offset = exec_header.e_phoff.get(LE);
let ph_ent_size = exec_header.e_phentsize.get(NativeEndian); let ph_ent_size = exec_header.e_phentsize.get(LE);
let ph_num = exec_header.e_phnum.get(NativeEndian); let ph_num = exec_header.e_phnum.get(LE);
let sh_offset = exec_header.e_shoff.get(NativeEndian); let sh_offset = exec_header.e_shoff.get(LE);
let sh_ent_size = exec_header.e_shentsize.get(NativeEndian); let sh_ent_size = exec_header.e_shentsize.get(LE);
let sh_num = exec_header.e_shnum.get(NativeEndian); let sh_num = exec_header.e_shnum.get(LE);
if verbose { if verbose {
println!(); println!();
@ -555,11 +623,11 @@ fn gen_elf_le(
let mut first_load_found = false; let mut first_load_found = false;
let mut virtual_shift_start = 0; let mut virtual_shift_start = 0;
for ph in program_headers.iter() { for ph in program_headers.iter() {
let p_type = ph.p_type.get(NativeEndian); let p_type = ph.p_type.get(LE);
if p_type == elf::PT_LOAD && ph.p_offset.get(NativeEndian) == 0 { if p_type == elf::PT_LOAD && ph.p_offset.get(LE) == 0 {
first_load_found = true; first_load_found = true;
md.load_align_constraint = ph.p_align.get(NativeEndian); md.load_align_constraint = ph.p_align.get(LE);
virtual_shift_start = physical_shift_start + ph.p_vaddr.get(NativeEndian); virtual_shift_start = physical_shift_start + ph.p_vaddr.get(LE);
} }
} }
if !first_load_found { if !first_load_found {
@ -574,21 +642,22 @@ fn gen_elf_le(
// Shift all of the program headers. // Shift all of the program headers.
for ph in program_headers.iter_mut() { for ph in program_headers.iter_mut() {
let p_type = ph.p_type.get(NativeEndian); let p_type = ph.p_type.get(LE);
let p_offset = ph.p_offset.get(NativeEndian); let p_offset = ph.p_offset.get(LE);
if (p_type == elf::PT_LOAD && p_offset == 0) || p_type == elf::PT_PHDR { if (p_type == elf::PT_LOAD && p_offset == 0) || p_type == elf::PT_PHDR {
// Extend length for the first segment and the program header. // Extend length for the first segment and the program header.
ph.p_filesz = endian::U64::new(LE, ph.p_filesz.get(NativeEndian) + md.added_byte_count); ph.p_filesz
ph.p_memsz = endian::U64::new(LE, ph.p_memsz.get(NativeEndian) + md.added_byte_count); .set(LE, ph.p_filesz.get(LE) + md.added_byte_count);
ph.p_memsz.set(LE, ph.p_memsz.get(LE) + md.added_byte_count);
} else { } else {
// Shift if needed. // Shift if needed.
if physical_shift_start <= p_offset { if physical_shift_start <= p_offset {
ph.p_offset = endian::U64::new(LE, p_offset + md.added_byte_count); ph.p_offset.set(LE, p_offset + md.added_byte_count);
} }
let p_vaddr = ph.p_vaddr.get(NativeEndian); let p_vaddr = ph.p_vaddr.get(LE);
if virtual_shift_start <= p_vaddr { if virtual_shift_start <= p_vaddr {
ph.p_vaddr = endian::U64::new(LE, p_vaddr + md.added_byte_count); ph.p_vaddr.set(LE, p_vaddr + md.added_byte_count);
ph.p_paddr = endian::U64::new(LE, p_vaddr + md.added_byte_count); ph.p_paddr.set(LE, p_vaddr + md.added_byte_count);
} }
} }
} }
@ -597,8 +666,8 @@ fn gen_elf_le(
let last_segment_vaddr = program_headers let last_segment_vaddr = program_headers
.iter() .iter()
.filter_map(|ph| { .filter_map(|ph| {
if ph.p_type.get(NativeEndian) != elf::PT_GNU_STACK { if ph.p_type.get(LE) != elf::PT_GNU_STACK {
Some(ph.p_vaddr.get(NativeEndian) + ph.p_memsz.get(NativeEndian)) Some(ph.p_vaddr.get(LE) + ph.p_memsz.get(LE))
} else { } else {
None None
} }
@ -620,28 +689,28 @@ fn gen_elf_le(
let mut rel_sections: Vec<(u64, u64)> = vec![]; let mut rel_sections: Vec<(u64, u64)> = vec![];
let mut rela_sections: Vec<(usize, u64, u64)> = vec![]; let mut rela_sections: Vec<(usize, u64, u64)> = vec![];
for (i, sh) in section_headers.iter_mut().enumerate() { for (i, sh) in section_headers.iter_mut().enumerate() {
let sh_offset = sh.sh_offset.get(NativeEndian); let sh_offset = sh.sh_offset.get(LE);
let sh_addr = sh.sh_addr.get(NativeEndian); let sh_addr = sh.sh_addr.get(LE);
if physical_shift_start <= sh_offset { if physical_shift_start <= sh_offset {
sh.sh_offset = endian::U64::new(LE, sh_offset + md.added_byte_count); sh.sh_offset.set(LE, sh_offset + md.added_byte_count);
} }
if virtual_shift_start <= sh_addr { if virtual_shift_start <= sh_addr {
sh.sh_addr = endian::U64::new(LE, sh_addr + md.added_byte_count); sh.sh_addr.set(LE, sh_addr + md.added_byte_count);
} }
// Record every relocation section. // Record every relocation section.
let sh_type = sh.sh_type.get(NativeEndian); let sh_type = sh.sh_type.get(LE);
if sh_type == elf::SHT_REL { if sh_type == elf::SHT_REL {
rel_sections.push((sh_offset, sh.sh_size.get(NativeEndian))); rel_sections.push((sh_offset, sh.sh_size.get(LE)));
} else if sh_type == elf::SHT_RELA { } else if sh_type == elf::SHT_RELA {
rela_sections.push((i, sh_offset, sh.sh_size.get(NativeEndian))); rela_sections.push((i, sh_offset, sh.sh_size.get(LE)));
} }
} }
// Get last section virtual address. // Get last section virtual address.
let last_section_vaddr = section_headers let last_section_vaddr = section_headers
.iter() .iter()
.map(|sh| sh.sh_addr.get(NativeEndian) + sh.sh_size.get(NativeEndian)) .map(|sh| sh.sh_addr.get(LE) + sh.sh_size.get(LE))
.max() .max()
.unwrap(); .unwrap();
@ -658,9 +727,9 @@ fn gen_elf_le(
sec_size as usize / mem::size_of::<elf::Rel64<LE>>(), sec_size as usize / mem::size_of::<elf::Rel64<LE>>(),
); );
for rel in relocations.iter_mut() { for rel in relocations.iter_mut() {
let r_offset = rel.r_offset.get(NativeEndian); let r_offset = rel.r_offset.get(LE);
if virtual_shift_start <= r_offset { if virtual_shift_start <= r_offset {
rel.r_offset = endian::U64::new(LE, r_offset + md.added_byte_count); rel.r_offset.set(LE, r_offset + md.added_byte_count);
} }
} }
} }
@ -673,9 +742,9 @@ fn gen_elf_le(
sec_size as usize / mem::size_of::<elf::Rela64<LE>>(), sec_size as usize / mem::size_of::<elf::Rela64<LE>>(),
); );
for (i, rel) in relocations.iter_mut().enumerate() { for (i, rel) in relocations.iter_mut().enumerate() {
let r_offset = rel.r_offset.get(NativeEndian); let r_offset = rel.r_offset.get(LE);
if virtual_shift_start <= r_offset { if virtual_shift_start <= r_offset {
rel.r_offset = endian::U64::new(LE, r_offset + md.added_byte_count); rel.r_offset.set(LE, r_offset + md.added_byte_count);
// Deal with potential adjusts to absolute jumps. // Deal with potential adjusts to absolute jumps.
// TODO: Verify other relocation types. // TODO: Verify other relocation types.
if rel.r_type(LE, false) == elf::R_X86_64_RELATIVE { if rel.r_type(LE, false) == elf::R_X86_64_RELATIVE {
@ -684,9 +753,9 @@ fn gen_elf_le(
} }
} }
// If the relocation goes to a roc function, we need to surgically link it and change it to relative. // If the relocation goes to a roc function, we need to surgically link it and change it to relative.
let r_type = rel.r_type(NativeEndian, false); let r_type = rel.r_type(LE, false);
if r_type == elf::R_X86_64_GLOB_DAT { if r_type == elf::R_X86_64_GLOB_DAT {
let r_sym = rel.r_sym(NativeEndian, false); let r_sym = rel.r_sym(LE, false);
for (name, index) in got_app_syms.iter() { for (name, index) in got_app_syms.iter() {
if *index as u32 == r_sym { if *index as u32 == r_sym {
rel.set_r_info(LE, false, 0, elf::R_X86_64_RELATIVE); rel.set_r_info(LE, false, 0, elf::R_X86_64_RELATIVE);
@ -694,14 +763,11 @@ fn gen_elf_le(
+ i * mem::size_of::<elf::Rela64<LE>>() + i * mem::size_of::<elf::Rela64<LE>>()
// This 16 skips the first 2 fields and gets to the addend field. // This 16 skips the first 2 fields and gets to the addend field.
+ 16; + 16;
md.surgeries md.surgeries.get_mut(name).unwrap().push(SurgeryEntry {
.get_mut(name) file_offset: addend_addr as u64,
.unwrap() virtual_offset: VirtualOffset::Absolute,
.push(metadata::SurgeryEntry { size: 8,
file_offset: addend_addr as u64, });
virtual_offset: VirtualOffset::Absolute,
size: 8,
});
} }
} }
} }
@ -715,8 +781,8 @@ fn gen_elf_le(
.iter() .iter()
.enumerate() .enumerate()
.filter_map(|(i, rel)| { .filter_map(|(i, rel)| {
let r_type = rel.r_type(NativeEndian, false); let r_type = rel.r_type(LE, false);
let r_sym = rel.r_sym(NativeEndian, false); let r_sym = rel.r_sym(LE, false);
if r_type == elf::R_X86_64_JUMP_SLOT && app_sym_indices.contains(&(r_sym as usize)) if r_type == elf::R_X86_64_JUMP_SLOT && app_sym_indices.contains(&(r_sym as usize))
{ {
Some(i) Some(i)
@ -733,7 +799,7 @@ fn gen_elf_le(
let mut j = relocations.len() - 1; let mut j = relocations.len() - 1;
for i in to_remove.iter() { for i in to_remove.iter() {
relocations.swap(*i, j); relocations.swap(*i, j);
let r_sym = relocations[j].r_sym(NativeEndian, false); let r_sym = relocations[j].r_sym(LE, false);
relocations[j].set_r_info(LE, false, r_sym, elf::R_X86_64_NONE); relocations[j].set_r_info(LE, false, r_sym, elf::R_X86_64_NONE);
j -= 1; j -= 1;
} }
@ -744,12 +810,12 @@ fn gen_elf_le(
sh_num as usize, sh_num as usize,
); );
let old_size = section_headers[sec_index].sh_size.get(NativeEndian); let old_size = section_headers[sec_index].sh_size.get(LE);
let removed_count = to_remove.len(); let removed_count = to_remove.len();
let removed_size = removed_count * std::mem::size_of::<elf::Rela64<LE>>(); let removed_size = removed_count * std::mem::size_of::<elf::Rela64<LE>>();
section_headers[sec_index] section_headers[sec_index]
.sh_size .sh_size
.set(NativeEndian, old_size - removed_size as u64); .set(LE, old_size - removed_size as u64);
let dyns = load_structs_inplace_mut::<elf::Dyn64<LE>>( let dyns = load_structs_inplace_mut::<elf::Dyn64<LE>>(
&mut out_mmap, &mut out_mmap,
@ -759,30 +825,30 @@ fn gen_elf_le(
let is_rela_dyn = dyns let is_rela_dyn = dyns
.iter() .iter()
.filter(|d| { .filter(|d| {
let tag = d.d_tag.get(NativeEndian) as u32; let tag = d.d_tag.get(LE) as u32;
tag == elf::DT_RELA tag == elf::DT_RELA
}) })
.any(|d| d.d_val.get(NativeEndian) == sec_offset); .any(|d| d.d_val.get(LE) == sec_offset);
let is_rela_plt = dyns let is_rela_plt = dyns
.iter() .iter()
.filter(|d| { .filter(|d| {
let tag = d.d_tag.get(NativeEndian) as u32; let tag = d.d_tag.get(LE) as u32;
tag == elf::DT_JMPREL tag == elf::DT_JMPREL
}) })
.any(|d| d.d_val.get(NativeEndian) == sec_offset); .any(|d| d.d_val.get(LE) == sec_offset);
for d in dyns.iter_mut() { for d in dyns.iter_mut() {
match d.d_tag.get(NativeEndian) as u32 { match d.d_tag.get(LE) as u32 {
elf::DT_RELACOUNT if is_rela_dyn => { elf::DT_RELACOUNT if is_rela_dyn => {
let old_count = d.d_val.get(NativeEndian); let old_count = d.d_val.get(LE);
d.d_val.set(LE, old_count - removed_count as u64); d.d_val.set(LE, old_count - removed_count as u64);
} }
elf::DT_RELASZ if is_rela_dyn => { elf::DT_RELASZ if is_rela_dyn => {
let old_size = d.d_val.get(NativeEndian); let old_size = d.d_val.get(LE);
d.d_val.set(LE, old_size - removed_size as u64); d.d_val.set(LE, old_size - removed_size as u64);
} }
elf::DT_PLTRELSZ if is_rela_plt => { elf::DT_PLTRELSZ if is_rela_plt => {
let old_size = d.d_val.get(NativeEndian); let old_size = d.d_val.get(LE);
d.d_val.set(LE, old_size - removed_size as u64); d.d_val.set(LE, old_size - removed_size as u64);
} }
_ => {} _ => {}
@ -796,8 +862,8 @@ fn gen_elf_le(
dyn_offset as usize, dyn_offset as usize,
dynamic_lib_count, dynamic_lib_count,
); );
for mut d in dyns { for d in dyns {
match d.d_tag.get(NativeEndian) as u32 { match d.d_tag.get(LE) as u32 {
// I believe this is the list of symbols that need to be update if addresses change. // I believe this is the list of symbols that need to be update if addresses change.
// I am less sure about the symbols from GNU_HASH down. // I am less sure about the symbols from GNU_HASH down.
elf::DT_INIT elf::DT_INIT
@ -828,9 +894,9 @@ fn gen_elf_le(
| elf::DT_VERSYM | elf::DT_VERSYM
| elf::DT_VERDEF | elf::DT_VERDEF
| elf::DT_VERNEED => { | elf::DT_VERNEED => {
let d_addr = d.d_val.get(NativeEndian); let d_addr = d.d_val.get(LE);
if virtual_shift_start <= d_addr { if virtual_shift_start <= d_addr {
d.d_val = endian::U64::new(LE, d_addr + md.added_byte_count); d.d_val.set(LE, d_addr + md.added_byte_count);
} }
} }
_ => {} _ => {}
@ -848,9 +914,9 @@ fn gen_elf_le(
); );
for sym in symbols { for sym in symbols {
let addr = sym.st_value.get(NativeEndian); let addr = sym.st_value.get(LE);
if virtual_shift_start <= addr { if virtual_shift_start <= addr {
sym.st_value = endian::U64::new(LE, addr + md.added_byte_count); sym.st_value.set(LE, addr + md.added_byte_count);
} }
} }
@ -862,7 +928,7 @@ fn gen_elf_le(
size / mem::size_of::<endian::U64<LE>>(), size / mem::size_of::<endian::U64<LE>>(),
); );
for go in global_offsets.iter_mut() { for go in global_offsets.iter_mut() {
let go_addr = go.get(NativeEndian); let go_addr = go.get(LE);
if physical_shift_start <= go_addr { if physical_shift_start <= go_addr {
go.set(LE, go_addr + md.added_byte_count); go.set(LE, go_addr + md.added_byte_count);
} }
@ -882,23 +948,24 @@ fn gen_elf_le(
} }
// Update main elf header for extra data. // Update main elf header for extra data.
let mut file_header = load_struct_inplace_mut::<elf::FileHeader64<LE>>(&mut out_mmap, 0); let file_header = load_struct_inplace_mut::<elf::FileHeader64<LE>>(&mut out_mmap, 0);
file_header.e_shoff = endian::U64::new( file_header
LE, .e_shoff
file_header.e_shoff.get(NativeEndian) + md.added_byte_count, .set(LE, file_header.e_shoff.get(LE) + md.added_byte_count);
); let e_entry = file_header.e_entry.get(LE);
let e_entry = file_header.e_entry.get(NativeEndian);
if virtual_shift_start <= e_entry { if virtual_shift_start <= e_entry {
file_header.e_entry = endian::U64::new(LE, e_entry + md.added_byte_count); file_header.e_entry.set(LE, e_entry + md.added_byte_count);
} }
file_header.e_phnum = endian::U16::new(LE, ph_num + added_header_count as u16); file_header
.e_phnum
.set(LE, ph_num + added_header_count as u16);
out_mmap out_mmap
} }
fn scan_elf_dynamic_deps( fn scan_elf_dynamic_deps(
exec_obj: &object::File, exec_obj: &object::File,
md: &mut metadata::Metadata, md: &mut Metadata,
app_syms: &[Symbol], app_syms: &[Symbol],
shared_lib: &Path, shared_lib: &Path,
exec_data: &[u8], exec_data: &[u8],
@ -1173,7 +1240,7 @@ pub(crate) fn surgery_elf(
fn surgery_elf_help( fn surgery_elf_help(
verbose: bool, verbose: bool,
md: &metadata::Metadata, md: &Metadata,
exec_mmap: &mut MmapMut, exec_mmap: &mut MmapMut,
offset_ref: &mut usize, // TODO return this instead of taking a mutable reference to it offset_ref: &mut usize, // TODO return this instead of taking a mutable reference to it
app_obj: object::File, app_obj: object::File,
@ -1185,12 +1252,12 @@ fn surgery_elf_help(
} }
let exec_header = load_struct_inplace::<elf::FileHeader64<LE>>(exec_mmap, 0); let exec_header = load_struct_inplace::<elf::FileHeader64<LE>>(exec_mmap, 0);
let ph_offset = exec_header.e_phoff.get(NativeEndian); let ph_offset = exec_header.e_phoff.get(LE);
let ph_ent_size = exec_header.e_phentsize.get(NativeEndian); let ph_ent_size = exec_header.e_phentsize.get(LE);
let ph_num = exec_header.e_phnum.get(NativeEndian); let ph_num = exec_header.e_phnum.get(LE);
let sh_offset = exec_header.e_shoff.get(NativeEndian); let sh_offset = exec_header.e_shoff.get(LE);
let sh_ent_size = exec_header.e_shentsize.get(NativeEndian); let sh_ent_size = exec_header.e_shentsize.get(LE);
let sh_num = exec_header.e_shnum.get(NativeEndian); let sh_num = exec_header.e_shnum.get(LE);
if verbose { if verbose {
println!(); println!();
@ -1489,8 +1556,10 @@ fn surgery_elf_help(
// Reload and update file header and size. // Reload and update file header and size.
let file_header = load_struct_inplace_mut::<elf::FileHeader64<LE>>(exec_mmap, 0); let file_header = load_struct_inplace_mut::<elf::FileHeader64<LE>>(exec_mmap, 0);
file_header.e_shoff = endian::U64::new(LE, new_sh_offset as u64); file_header.e_shoff.set(LE, new_sh_offset as u64);
file_header.e_shnum = endian::U16::new(LE, sh_num + new_section_count as u16); file_header
.e_shnum
.set(LE, sh_num + new_section_count as u16);
// Add 2 new segments that match the new sections. // Add 2 new segments that match the new sections.
let program_headers = load_structs_inplace_mut::<elf::ProgramHeader64<LE>>( let program_headers = load_structs_inplace_mut::<elf::ProgramHeader64<LE>>(
@ -1609,9 +1678,9 @@ fn surgery_elf_help(
exec_mmap, exec_mmap,
dynsym_offset as usize + *i as usize * mem::size_of::<elf::Sym64<LE>>(), dynsym_offset as usize + *i as usize * mem::size_of::<elf::Sym64<LE>>(),
); );
sym.st_shndx = endian::U16::new(LE, new_text_section_index as u16); sym.st_shndx.set(LE, new_text_section_index as u16);
sym.st_value = endian::U64::new(LE, func_virt_offset); sym.st_value.set(LE, func_virt_offset);
sym.st_size = endian::U64::new( sym.st_size.set(
LE, LE,
match app_func_size_map.get(func_name) { match app_func_size_map.get(func_name) {
Some(size) => *size, Some(size) => *size,
@ -1626,9 +1695,9 @@ fn surgery_elf_help(
exec_mmap, exec_mmap,
symtab_offset as usize + *i as usize * mem::size_of::<elf::Sym64<LE>>(), symtab_offset as usize + *i as usize * mem::size_of::<elf::Sym64<LE>>(),
); );
sym.st_shndx = endian::U16::new(LE, new_text_section_index as u16); sym.st_shndx.set(LE, new_text_section_index as u16);
sym.st_value = endian::U64::new(LE, func_virt_offset); sym.st_value.set(LE, func_virt_offset);
sym.st_size = endian::U64::new( sym.st_size.set(
LE, LE,
match app_func_size_map.get(func_name) { match app_func_size_map.get(func_name) {
Some(size) => *size, Some(size) => *size,

View file

@ -21,7 +21,6 @@ mod macho;
mod pe; mod pe;
mod generate_dylib; mod generate_dylib;
mod metadata;
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum LinkType { pub enum LinkType {
@ -409,7 +408,7 @@ pub fn preprocess_host(
) )
} }
/// Constructs a `metadata::Metadata` from a host executable binary, and writes it to disk /// Constructs a `Metadata` from a host executable binary, and writes it to disk
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn preprocess( fn preprocess(
target: &Triple, target: &Triple,

View file

@ -1,18 +1,22 @@
use crate::metadata::{self, Metadata, VirtualOffset}; use bincode::{deserialize_from, serialize_into};
use iced_x86::{Decoder, DecoderOptions, Instruction, OpCodeOperandKind, OpKind}; use iced_x86::{Decoder, DecoderOptions, Instruction, OpCodeOperandKind, OpKind};
use memmap2::MmapMut; use memmap2::MmapMut;
use object::macho; use object::macho;
use object::{ use object::{
CompressedFileRange, CompressionFormat, LittleEndian, NativeEndian, Object, ObjectSection, CompressedFileRange, CompressionFormat, LittleEndian as LE, Object, ObjectSection,
ObjectSymbol, RelocationKind, RelocationTarget, Section, SectionIndex, SectionKind, Symbol, ObjectSymbol, RelocationKind, RelocationTarget, Section, SectionIndex, SectionKind, Symbol,
SymbolIndex, SymbolSection, SymbolIndex, SymbolSection,
}; };
use roc_collections::all::MutMap; use roc_collections::all::MutMap;
use roc_error_macros::internal_error; use roc_error_macros::internal_error;
use std::ffi::CStr; use serde::{Deserialize, Serialize};
use std::mem; use std::{
use std::path::Path; ffi::CStr,
use std::time::{Duration, Instant}; io::{BufReader, BufWriter},
mem,
path::Path,
time::{Duration, Instant},
};
use target_lexicon::Triple; use target_lexicon::Triple;
use crate::{ use crate::{
@ -34,6 +38,73 @@ const STUB_ADDRESS_OFFSET: u64 = 0x06;
// shared_lib_index: usize, // shared_lib_index: usize,
// } // }
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
enum VirtualOffset {
Absolute,
Relative(u64),
}
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct SurgeryEntry {
file_offset: u64,
virtual_offset: VirtualOffset,
size: u8,
}
// TODO: Reanalyze each piece of data in this struct.
// I think a number of them can be combined to reduce string duplication.
// Also I think a few of them aren't need.
// For example, I think preprocessing can deal with all shifting and remove the need for added_byte_count.
// TODO: we probably should be storing numbers in an endian neutral way.
#[derive(Default, Serialize, Deserialize, PartialEq, Eq, Debug)]
struct Metadata {
app_functions: Vec<String>,
// offset followed by address.
plt_addresses: MutMap<String, (u64, u64)>,
surgeries: MutMap<String, Vec<SurgeryEntry>>,
dynamic_symbol_indices: MutMap<String, u64>,
_static_symbol_indices: MutMap<String, u64>,
roc_symbol_vaddresses: MutMap<String, u64>,
exec_len: u64,
load_align_constraint: u64,
added_byte_count: u64,
last_vaddr: u64,
_dynamic_section_offset: u64,
_dynamic_symbol_table_section_offset: u64,
_symbol_table_section_offset: u64,
_symbol_table_size: u64,
macho_cmd_loc: u64,
}
impl Metadata {
fn write_to_file(&self, metadata_filename: &Path) {
let metadata_file =
std::fs::File::create(metadata_filename).unwrap_or_else(|e| internal_error!("{}", e));
serialize_into(BufWriter::new(metadata_file), self)
.unwrap_or_else(|err| internal_error!("Failed to serialize metadata: {err}"));
}
fn read_from_file(metadata_filename: &Path) -> Self {
let input = std::fs::File::open(metadata_filename).unwrap_or_else(|e| {
internal_error!(
r#"
Error:
{}\n"#,
e
)
});
match deserialize_from(BufReader::new(input)) {
Ok(data) => data,
Err(err) => {
internal_error!("Failed to deserialize metadata: {}", err);
}
}
}
}
fn report_timing(label: &str, duration: Duration) { fn report_timing(label: &str, duration: Duration) {
println!("\t{:9.3} ms {}", duration.as_secs_f64() * 1000.0, label,); println!("\t{:9.3} ms {}", duration.as_secs_f64() * 1000.0, label,);
} }
@ -83,7 +154,7 @@ fn collect_roc_definitions<'a>(object: &object::File<'a, &'a [u8]>) -> MutMap<St
} }
struct Surgeries<'a> { struct Surgeries<'a> {
surgeries: MutMap<String, Vec<metadata::SurgeryEntry>>, surgeries: MutMap<String, Vec<SurgeryEntry>>,
app_func_addresses: MutMap<u64, &'a str>, app_func_addresses: MutMap<u64, &'a str>,
indirect_warning_given: bool, indirect_warning_given: bool,
} }
@ -217,7 +288,7 @@ impl<'a> Surgeries<'a> {
self.surgeries self.surgeries
.get_mut(*func_name) .get_mut(*func_name)
.unwrap() .unwrap()
.push(metadata::SurgeryEntry { .push(SurgeryEntry {
file_offset: offset, file_offset: offset,
virtual_offset: VirtualOffset::Relative(inst.next_ip()), virtual_offset: VirtualOffset::Relative(inst.next_ip()),
size: op_size, size: op_size,
@ -253,7 +324,7 @@ impl<'a> Surgeries<'a> {
} }
} }
/// Constructs a `metadata::Metadata` from a host executable binary, and writes it to disk /// Constructs a `Metadata` from a host executable binary, and writes it to disk
pub(crate) fn preprocess_macho( pub(crate) fn preprocess_macho(
target: &Triple, target: &Triple,
host_exe_path: &Path, host_exe_path: &Path,
@ -273,7 +344,7 @@ pub(crate) fn preprocess_macho(
} }
}; };
let mut md = metadata::Metadata { let mut md = Metadata {
roc_symbol_vaddresses: collect_roc_definitions(&exec_obj), roc_symbol_vaddresses: collect_roc_definitions(&exec_obj),
..Default::default() ..Default::default()
}; };
@ -325,8 +396,8 @@ pub(crate) fn preprocess_macho(
{ {
use macho::{DyldInfoCommand, DylibCommand, Section64, SegmentCommand64}; use macho::{DyldInfoCommand, DylibCommand, Section64, SegmentCommand64};
let exec_header = load_struct_inplace::<macho::MachHeader64<LittleEndian>>(exec_data, 0); let exec_header = load_struct_inplace::<macho::MachHeader64<LE>>(exec_data, 0);
let num_load_cmds = exec_header.ncmds.get(NativeEndian); let num_load_cmds = exec_header.ncmds.get(LE);
let mut offset = mem::size_of_val(exec_header); let mut offset = mem::size_of_val(exec_header);
@ -334,17 +405,17 @@ pub(crate) fn preprocess_macho(
let mut stubs_symbol_count = None; let mut stubs_symbol_count = None;
'cmds: for _ in 0..num_load_cmds { 'cmds: for _ in 0..num_load_cmds {
let info = load_struct_inplace::<macho::LoadCommand<LittleEndian>>(exec_data, offset); let info = load_struct_inplace::<macho::LoadCommand<LE>>(exec_data, offset);
let cmd = info.cmd.get(NativeEndian); let cmd = info.cmd.get(LE);
let cmdsize = info.cmdsize.get(NativeEndian); let cmdsize = info.cmdsize.get(LE);
if cmd == macho::LC_SEGMENT_64 { if cmd == macho::LC_SEGMENT_64 {
let info = load_struct_inplace::<SegmentCommand64<LittleEndian>>(exec_data, offset); let info = load_struct_inplace::<SegmentCommand64<LE>>(exec_data, offset);
if &info.segname[0..6] == b"__TEXT" { if &info.segname[0..6] == b"__TEXT" {
let sections = info.nsects.get(NativeEndian); let sections = info.nsects.get(LE);
let sections_info = load_structs_inplace::<Section64<LittleEndian>>( let sections_info = load_structs_inplace::<Section64<LE>>(
exec_data, exec_data,
offset + mem::size_of_val(info), offset + mem::size_of_val(info),
sections as usize, sections as usize,
@ -352,9 +423,9 @@ pub(crate) fn preprocess_macho(
for section_info in sections_info { for section_info in sections_info {
if &section_info.sectname[0..7] == b"__stubs" { if &section_info.sectname[0..7] == b"__stubs" {
stubs_symbol_index = Some(section_info.reserved1.get(NativeEndian)); stubs_symbol_index = Some(section_info.reserved1.get(LE));
stubs_symbol_count = stubs_symbol_count =
Some(section_info.size.get(NativeEndian) / STUB_ADDRESS_OFFSET); Some(section_info.size.get(LE) / STUB_ADDRESS_OFFSET);
break 'cmds; break 'cmds;
} }
@ -378,14 +449,14 @@ pub(crate) fn preprocess_macho(
let shared_lib_filename = shared_lib.file_name(); let shared_lib_filename = shared_lib.file_name();
for _ in 0..num_load_cmds { for _ in 0..num_load_cmds {
let info = load_struct_inplace::<macho::LoadCommand<LittleEndian>>(exec_data, offset); let info = load_struct_inplace::<macho::LoadCommand<LE>>(exec_data, offset);
let cmd = info.cmd.get(NativeEndian); let cmd = info.cmd.get(LE);
let cmdsize = info.cmdsize.get(NativeEndian); let cmdsize = info.cmdsize.get(LE);
if cmd == macho::LC_DYLD_INFO_ONLY { if cmd == macho::LC_DYLD_INFO_ONLY {
let info = load_struct_inplace::<DyldInfoCommand<LittleEndian>>(exec_data, offset); let info = load_struct_inplace::<DyldInfoCommand<LE>>(exec_data, offset);
let lazy_bind_offset = info.lazy_bind_off.get(NativeEndian) as usize; let lazy_bind_offset = info.lazy_bind_off.get(LE) as usize;
let lazy_bind_symbols = mach_object::LazyBind::parse( let lazy_bind_symbols = mach_object::LazyBind::parse(
&exec_data[lazy_bind_offset..], &exec_data[lazy_bind_offset..],
@ -412,8 +483,8 @@ pub(crate) fn preprocess_macho(
} }
} }
} else if cmd == macho::LC_LOAD_DYLIB { } else if cmd == macho::LC_LOAD_DYLIB {
let info = load_struct_inplace::<DylibCommand<LittleEndian>>(exec_data, offset); let info = load_struct_inplace::<DylibCommand<LE>>(exec_data, offset);
let name_offset = info.dylib.name.offset.get(NativeEndian) as usize; let name_offset = info.dylib.name.offset.get(LE) as usize;
let str_start_index = offset + name_offset; let str_start_index = offset + name_offset;
let str_end_index = offset + cmdsize as usize; let str_end_index = offset + cmdsize as usize;
let str_bytes = &exec_data[str_start_index..str_end_index]; let str_bytes = &exec_data[str_start_index..str_end_index];
@ -581,7 +652,7 @@ pub(crate) fn preprocess_macho(
fn gen_macho_le( fn gen_macho_le(
exec_data: &[u8], exec_data: &[u8],
md: &mut metadata::Metadata, md: &mut Metadata,
out_filename: &Path, out_filename: &Path,
macho_load_so_offset: usize, macho_load_so_offset: usize,
_target: &Triple, _target: &Triple,
@ -600,19 +671,18 @@ fn gen_macho_le(
use macho::{Section64, SegmentCommand64}; use macho::{Section64, SegmentCommand64};
let exec_header = load_struct_inplace::<macho::MachHeader64<LittleEndian>>(exec_data, 0); let exec_header = load_struct_inplace::<macho::MachHeader64<LE>>(exec_data, 0);
let num_load_cmds = exec_header.ncmds.get(NativeEndian); let num_load_cmds = exec_header.ncmds.get(LE);
let size_of_cmds = exec_header.sizeofcmds.get(NativeEndian) as usize; let size_of_cmds = exec_header.sizeofcmds.get(LE) as usize;
// Add a new text segment and data segment // Add a new text segment and data segment
let segment_cmd_size = mem::size_of::<SegmentCommand64<LittleEndian>>(); let segment_cmd_size = mem::size_of::<SegmentCommand64<LE>>();
let section_size = mem::size_of::<Section64<LittleEndian>>(); let section_size = mem::size_of::<Section64<LE>>();
// We need the full command size, including the dynamic-length string at the end. // We need the full command size, including the dynamic-length string at the end.
// To get that, we need to load the command. // To get that, we need to load the command.
let info = let info = load_struct_inplace::<macho::LoadCommand<LE>>(exec_data, macho_load_so_offset);
load_struct_inplace::<macho::LoadCommand<LittleEndian>>(exec_data, macho_load_so_offset); let total_cmd_size = info.cmdsize.get(LE) as usize;
let total_cmd_size = info.cmdsize.get(NativeEndian) as usize;
// ======================== Important TODO ========================== // ======================== Important TODO ==========================
// TODO: we accidentally instroduced a big change here. // TODO: we accidentally instroduced a big change here.
@ -654,16 +724,16 @@ fn gen_macho_le(
out_mmap[start_index..start_index + rest_of_data.len()].copy_from_slice(rest_of_data); out_mmap[start_index..start_index + rest_of_data.len()].copy_from_slice(rest_of_data);
let out_header = load_struct_inplace_mut::<macho::MachHeader64<LittleEndian>>(&mut out_mmap, 0); let out_header = load_struct_inplace_mut::<macho::MachHeader64<LE>>(&mut out_mmap, 0);
// TODO: this needs to change to adding the 2 new commands when we are ready. // TODO: this needs to change to adding the 2 new commands when we are ready.
// -1 because we're deleting 1 load command and then NOT adding 2 new ones. // -1 because we're deleting 1 load command and then NOT adding 2 new ones.
{ {
let added_bytes = -(total_cmd_size as isize); // TODO: Change when add the new sections. let added_bytes = -(total_cmd_size as isize); // TODO: Change when add the new sections.
out_header.ncmds.set(LittleEndian, num_load_cmds - 1); out_header.ncmds.set(LE, num_load_cmds - 1);
out_header out_header
.sizeofcmds .sizeofcmds
.set(LittleEndian, (size_of_cmds as isize + added_bytes) as u32); .set(LE, (size_of_cmds as isize + added_bytes) as u32);
} }
// Go through every command and shift it by added_bytes if it's absolute, unless it's inside the command header // Go through every command and shift it by added_bytes if it's absolute, unless it's inside the command header
@ -681,50 +751,37 @@ fn gen_macho_le(
// minus one because we "deleted" a load command // minus one because we "deleted" a load command
for _ in 0..(num_load_cmds - 1) { for _ in 0..(num_load_cmds - 1) {
let info = load_struct_inplace::<macho::LoadCommand<LittleEndian>>(&out_mmap, offset); let info = load_struct_inplace::<macho::LoadCommand<LE>>(&out_mmap, offset);
let cmd_size = info.cmdsize.get(NativeEndian) as usize; let cmd_size = info.cmdsize.get(LE) as usize;
match info.cmd.get(NativeEndian) { match info.cmd.get(LE) {
macho::LC_SEGMENT_64 => { macho::LC_SEGMENT_64 => {
let cmd = load_struct_inplace_mut::<macho::SegmentCommand64<LittleEndian>>( let cmd =
&mut out_mmap, load_struct_inplace_mut::<macho::SegmentCommand64<LE>>(&mut out_mmap, offset);
offset,
);
// Ignore page zero, it never moves. // Ignore page zero, it never moves.
if cmd.segname == "__PAGEZERO\0\0\0\0\0\0".as_bytes() if cmd.segname == "__PAGEZERO\0\0\0\0\0\0".as_bytes() || cmd.vmaddr.get(LE) == 0 {
|| cmd.vmaddr.get(NativeEndian) == 0
{
offset += cmd_size; offset += cmd_size;
continue; continue;
} }
let old_file_offest = cmd.fileoff.get(NativeEndian); let old_file_offest = cmd.fileoff.get(LE);
// The segment with file offset zero also includes the header. // The segment with file offset zero also includes the header.
// As such, its file offset does not change. // As such, its file offset does not change.
// Instead, its file size should be increased. // Instead, its file size should be increased.
if old_file_offest > 0 { if old_file_offest > 0 {
cmd.fileoff cmd.fileoff.set(LE, old_file_offest + md.added_byte_count);
.set(LittleEndian, old_file_offest + md.added_byte_count); cmd.vmaddr.set(LE, cmd.vmaddr.get(LE) + md.added_byte_count);
cmd.vmaddr.set(
LittleEndian,
cmd.vmaddr.get(NativeEndian) + md.added_byte_count,
);
} else { } else {
cmd.filesize.set( cmd.filesize
LittleEndian, .set(LE, cmd.filesize.get(LE) + md.added_byte_count);
cmd.filesize.get(NativeEndian) + md.added_byte_count, cmd.vmsize.set(LE, cmd.vmsize.get(LE) + md.added_byte_count);
);
cmd.vmsize.set(
LittleEndian,
cmd.vmsize.get(NativeEndian) + md.added_byte_count,
);
} }
// let num_sections = cmd.nsects.get(NativeEndian); // let num_sections = cmd.nsects.get(LE);
// let sections = load_structs_inplace_mut::<macho::Section64<LittleEndian>>( // let sections = load_structs_inplace_mut::<macho::Section64<LE >>(
// &mut out_mmap, // &mut out_mmap,
// offset + mem::size_of::<macho::SegmentCommand64<LittleEndian>>(), // offset + mem::size_of::<macho::SegmentCommand64<LE >>(),
// num_sections as usize, // num_sections as usize,
// ); // );
// struct Relocation { // struct Relocation {
@ -736,34 +793,34 @@ fn gen_macho_le(
// for section in sections { // for section in sections {
// section.addr.set( // section.addr.set(
// LittleEndian, // LE ,
// section.addr.get(NativeEndian) + md.added_byte_count as u64, // section.addr.get(LE) + md.added_byte_count as u64,
// ); // );
// // If offset is zero, don't update it. // // If offset is zero, don't update it.
// // Zero is used for things like BSS that don't exist in the file. // // Zero is used for things like BSS that don't exist in the file.
// let old_offset = section.offset.get(NativeEndian); // let old_offset = section.offset.get(LE);
// if old_offset > 0 { // if old_offset > 0 {
// section // section
// .offset // .offset
// .set(LittleEndian, old_offset + md.added_byte_count as u32); // .set(LE , old_offset + md.added_byte_count as u32);
// } // }
// // dbg!(&section.reloff.get(NativeEndian)); // // dbg!(&section.reloff.get(LE));
// // dbg!(section.reloff.get(NativeEndian) as i32); // // dbg!(section.reloff.get(LE) as i32);
// // dbg!(&section); // // dbg!(&section);
// // dbg!(&md.added_byte_count); // // dbg!(&md.added_byte_count);
// // dbg!(String::from_utf8_lossy(&section.sectname)); // // dbg!(String::from_utf8_lossy(&section.sectname));
// if section.nreloc.get(NativeEndian) > 0 { // if section.nreloc.get(LE) > 0 {
// section.reloff.set( // section.reloff.set(
// LittleEndian, // LE ,
// section.reloff.get(NativeEndian) + md.added_byte_count as u32, // section.reloff.get(LE) + md.added_byte_count as u32,
// ); // );
// } // }
// relocation_offsets.push(Relocation { // relocation_offsets.push(Relocation {
// offset: section.reloff.get(NativeEndian), // offset: section.reloff.get(LE),
// num_relocations: section.nreloc.get(NativeEndian), // num_relocations: section.nreloc.get(LE),
// }); // });
// } // }
@ -773,7 +830,7 @@ fn gen_macho_le(
// num_relocations, // num_relocations,
// } in relocation_offsets // } in relocation_offsets
// { // {
// let relos = load_structs_inplace_mut::<macho::Relocation<LittleEndian>>( // let relos = load_structs_inplace_mut::<macho::Relocation<LE >>(
// &mut out_mmap, // &mut out_mmap,
// offset as usize, // offset as usize,
// num_relocations as usize, // num_relocations as usize,
@ -781,13 +838,13 @@ fn gen_macho_le(
// // TODO this has never been tested, because scattered relocations only come up on ARM! // // TODO this has never been tested, because scattered relocations only come up on ARM!
// for relo in relos.iter_mut() { // for relo in relos.iter_mut() {
// if relo.r_scattered(LittleEndian, cpu_type) { // if relo.r_scattered(LE , cpu_type) {
// let mut scattered_info = relo.scattered_info(NativeEndian); // let mut scattered_info = relo.scattered_info(LE);
// if !scattered_info.r_pcrel { // if !scattered_info.r_pcrel {
// scattered_info.r_value += md.added_byte_count as u32; // scattered_info.r_value += md.added_byte_count as u32;
// let new_info = scattered_info.relocation(LittleEndian); // let new_info = scattered_info.relocation(LE );
// relo.r_word0 = new_info.r_word0; // relo.r_word0 = new_info.r_word0;
// relo.r_word1 = new_info.r_word1; // relo.r_word1 = new_info.r_word1;
@ -797,30 +854,25 @@ fn gen_macho_le(
// } // }
// TODO this seems to be wrong and unnecessary, and should probably be deleted. // TODO this seems to be wrong and unnecessary, and should probably be deleted.
// offset += num_sections as usize * mem::size_of::<macho::Section64<LittleEndian>>(); // offset += num_sections as usize * mem::size_of::<macho::Section64<LE >>();
} }
macho::LC_SYMTAB => { macho::LC_SYMTAB => {
let cmd = load_struct_inplace_mut::<macho::SymtabCommand<LittleEndian>>( let cmd =
&mut out_mmap, load_struct_inplace_mut::<macho::SymtabCommand<LE>>(&mut out_mmap, offset);
offset,
);
let sym_offset = cmd.symoff.get(NativeEndian); let sym_offset = cmd.symoff.get(LE);
let num_syms = cmd.nsyms.get(NativeEndian); let num_syms = cmd.nsyms.get(LE);
if num_syms > 0 { if num_syms > 0 {
cmd.symoff cmd.symoff.set(LE, sym_offset + md.added_byte_count as u32);
.set(LittleEndian, sym_offset + md.added_byte_count as u32);
} }
if cmd.strsize.get(NativeEndian) > 0 { if cmd.strsize.get(LE) > 0 {
cmd.stroff.set( cmd.stroff
LittleEndian, .set(LE, cmd.stroff.get(LE) + md.added_byte_count as u32);
cmd.stroff.get(NativeEndian) + md.added_byte_count as u32,
);
} }
let table = load_structs_inplace_mut::<macho::Nlist64<LittleEndian>>( let table = load_structs_inplace_mut::<macho::Nlist64<LE>>(
&mut out_mmap, &mut out_mmap,
sym_offset as usize + md.added_byte_count as usize, sym_offset as usize + md.added_byte_count as usize,
num_syms as usize, num_syms as usize,
@ -829,59 +881,44 @@ fn gen_macho_le(
for entry in table { for entry in table {
let entry_type = entry.n_type & macho::N_TYPE; let entry_type = entry.n_type & macho::N_TYPE;
if entry_type == macho::N_ABS || entry_type == macho::N_SECT { if entry_type == macho::N_ABS || entry_type == macho::N_SECT {
entry.n_value.set( entry
LittleEndian, .n_value
entry.n_value.get(NativeEndian) + md.added_byte_count, .set(LE, entry.n_value.get(LE) + md.added_byte_count);
);
} }
} }
} }
macho::LC_DYSYMTAB => { macho::LC_DYSYMTAB => {
let cmd = load_struct_inplace_mut::<macho::DysymtabCommand<LittleEndian>>( let cmd =
&mut out_mmap, load_struct_inplace_mut::<macho::DysymtabCommand<LE>>(&mut out_mmap, offset);
offset,
);
if cmd.ntoc.get(NativeEndian) > 0 { if cmd.ntoc.get(LE) > 0 {
cmd.tocoff.set( cmd.tocoff
LittleEndian, .set(LE, cmd.tocoff.get(LE) + md.added_byte_count as u32);
cmd.tocoff.get(NativeEndian) + md.added_byte_count as u32,
);
} }
if cmd.nmodtab.get(NativeEndian) > 0 { if cmd.nmodtab.get(LE) > 0 {
cmd.modtaboff.set( cmd.modtaboff
LittleEndian, .set(LE, cmd.modtaboff.get(LE) + md.added_byte_count as u32);
cmd.modtaboff.get(NativeEndian) + md.added_byte_count as u32,
);
} }
if cmd.nextrefsyms.get(NativeEndian) > 0 { if cmd.nextrefsyms.get(LE) > 0 {
cmd.extrefsymoff.set( cmd.extrefsymoff
LittleEndian, .set(LE, cmd.extrefsymoff.get(LE) + md.added_byte_count as u32);
cmd.extrefsymoff.get(NativeEndian) + md.added_byte_count as u32,
);
} }
if cmd.nindirectsyms.get(NativeEndian) > 0 { if cmd.nindirectsyms.get(LE) > 0 {
cmd.indirectsymoff.set( cmd.indirectsymoff
LittleEndian, .set(LE, cmd.indirectsymoff.get(LE) + md.added_byte_count as u32);
cmd.indirectsymoff.get(NativeEndian) + md.added_byte_count as u32,
);
} }
if cmd.nextrel.get(NativeEndian) > 0 { if cmd.nextrel.get(LE) > 0 {
cmd.extreloff.set( cmd.extreloff
LittleEndian, .set(LE, cmd.extreloff.get(LE) + md.added_byte_count as u32);
cmd.extreloff.get(NativeEndian) + md.added_byte_count as u32,
);
} }
if cmd.nlocrel.get(NativeEndian) > 0 { if cmd.nlocrel.get(LE) > 0 {
cmd.locreloff.set( cmd.locreloff
LittleEndian, .set(LE, cmd.locreloff.get(LE) + md.added_byte_count as u32);
cmd.locreloff.get(NativeEndian) + md.added_byte_count as u32,
);
} }
// TODO maybe we need to update something else too - relocations maybe? // TODO maybe we need to update something else too - relocations maybe?
@ -889,29 +926,25 @@ fn gen_macho_le(
// Look at otool -I at least for the indirect symbols. // Look at otool -I at least for the indirect symbols.
} }
macho::LC_TWOLEVEL_HINTS => { macho::LC_TWOLEVEL_HINTS => {
let cmd = load_struct_inplace_mut::<macho::TwolevelHintsCommand<LittleEndian>>( let cmd = load_struct_inplace_mut::<macho::TwolevelHintsCommand<LE>>(
&mut out_mmap, &mut out_mmap,
offset, offset,
); );
if cmd.nhints.get(NativeEndian) > 0 { if cmd.nhints.get(LE) > 0 {
cmd.offset.set( cmd.offset
LittleEndian, .set(LE, cmd.offset.get(LE) + md.added_byte_count as u32);
cmd.offset.get(NativeEndian) + md.added_byte_count as u32,
);
} }
} }
macho::LC_FUNCTION_STARTS => { macho::LC_FUNCTION_STARTS => {
let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LittleEndian>>( let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LE>>(
&mut out_mmap, &mut out_mmap,
offset, offset,
); );
if cmd.datasize.get(NativeEndian) > 0 { if cmd.datasize.get(LE) > 0 {
cmd.dataoff.set( cmd.dataoff
LittleEndian, .set(LE, cmd.dataoff.get(LE) + md.added_byte_count as u32);
cmd.dataoff.get(NativeEndian) + md.added_byte_count as u32,
);
// TODO: This lists the start of every function. Which, of course, have moved. // TODO: This lists the start of every function. Which, of course, have moved.
// That being said, to my understanding this section is optional and may just be debug information. // That being said, to my understanding this section is optional and may just be debug information.
// As such, updating it should not be required. // As such, updating it should not be required.
@ -920,36 +953,30 @@ fn gen_macho_le(
} }
macho::LC_DATA_IN_CODE => { macho::LC_DATA_IN_CODE => {
let (offset, size) = { let (offset, size) = {
let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LittleEndian>>( let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LE>>(
&mut out_mmap, &mut out_mmap,
offset, offset,
); );
if cmd.datasize.get(NativeEndian) > 0 { if cmd.datasize.get(LE) > 0 {
cmd.dataoff.set( cmd.dataoff
LittleEndian, .set(LE, cmd.dataoff.get(LE) + md.added_byte_count as u32);
cmd.dataoff.get(NativeEndian) + md.added_byte_count as u32,
);
} }
( (cmd.dataoff.get(LE), cmd.datasize.get(LE))
cmd.dataoff.get(NativeEndian),
cmd.datasize.get(NativeEndian),
)
}; };
// Update every data in code entry. // Update every data in code entry.
if size > 0 { if size > 0 {
let entry_size = mem::size_of::<macho::DataInCodeEntry<LittleEndian>>(); let entry_size = mem::size_of::<macho::DataInCodeEntry<LE>>();
let entries = load_structs_inplace_mut::<macho::DataInCodeEntry<LittleEndian>>( let entries = load_structs_inplace_mut::<macho::DataInCodeEntry<LE>>(
&mut out_mmap, &mut out_mmap,
offset as usize, offset as usize,
size as usize / entry_size, size as usize / entry_size,
); );
for entry in entries.iter_mut() { for entry in entries.iter_mut() {
entry.offset.set( entry
LittleEndian, .offset
entry.offset.get(NativeEndian) + md.added_byte_count as u32, .set(LE, entry.offset.get(LE) + md.added_byte_count as u32)
)
} }
} }
} }
@ -959,63 +986,49 @@ fn gen_macho_le(
| macho::LC_LINKER_OPTIMIZATION_HINT | macho::LC_LINKER_OPTIMIZATION_HINT
| macho::LC_DYLD_EXPORTS_TRIE | macho::LC_DYLD_EXPORTS_TRIE
| macho::LC_DYLD_CHAINED_FIXUPS => { | macho::LC_DYLD_CHAINED_FIXUPS => {
let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LittleEndian>>( let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LE>>(
&mut out_mmap, &mut out_mmap,
offset, offset,
); );
if cmd.datasize.get(NativeEndian) > 0 { if cmd.datasize.get(LE) > 0 {
cmd.dataoff.set( cmd.dataoff
LittleEndian, .set(LE, cmd.dataoff.get(LE) + md.added_byte_count as u32);
cmd.dataoff.get(NativeEndian) + md.added_byte_count as u32,
);
} }
} }
macho::LC_ENCRYPTION_INFO_64 => { macho::LC_ENCRYPTION_INFO_64 => {
let cmd = load_struct_inplace_mut::<macho::EncryptionInfoCommand64<LittleEndian>>( let cmd = load_struct_inplace_mut::<macho::EncryptionInfoCommand64<LE>>(
&mut out_mmap, &mut out_mmap,
offset, offset,
); );
if cmd.cryptsize.get(NativeEndian) > 0 { if cmd.cryptsize.get(LE) > 0 {
cmd.cryptoff.set( cmd.cryptoff
LittleEndian, .set(LE, cmd.cryptoff.get(LE) + md.added_byte_count as u32);
cmd.cryptoff.get(NativeEndian) + md.added_byte_count as u32,
);
} }
} }
macho::LC_DYLD_INFO | macho::LC_DYLD_INFO_ONLY => { macho::LC_DYLD_INFO | macho::LC_DYLD_INFO_ONLY => {
let cmd = load_struct_inplace_mut::<macho::DyldInfoCommand<LittleEndian>>( let cmd =
&mut out_mmap, load_struct_inplace_mut::<macho::DyldInfoCommand<LE>>(&mut out_mmap, offset);
offset,
);
if cmd.rebase_size.get(NativeEndian) > 0 { if cmd.rebase_size.get(LE) > 0 {
cmd.rebase_off.set( cmd.rebase_off
LittleEndian, .set(LE, cmd.rebase_off.get(LE) + md.added_byte_count as u32);
cmd.rebase_off.get(NativeEndian) + md.added_byte_count as u32,
);
} }
if cmd.bind_size.get(NativeEndian) > 0 { if cmd.bind_size.get(LE) > 0 {
cmd.bind_off.set( cmd.bind_off
LittleEndian, .set(LE, cmd.bind_off.get(LE) + md.added_byte_count as u32);
cmd.bind_off.get(NativeEndian) + md.added_byte_count as u32,
);
} }
if cmd.weak_bind_size.get(NativeEndian) > 0 { if cmd.weak_bind_size.get(LE) > 0 {
cmd.weak_bind_off.set( cmd.weak_bind_off
LittleEndian, .set(LE, cmd.weak_bind_off.get(LE) + md.added_byte_count as u32);
cmd.weak_bind_off.get(NativeEndian) + md.added_byte_count as u32,
);
} }
if cmd.lazy_bind_size.get(NativeEndian) > 0 { if cmd.lazy_bind_size.get(LE) > 0 {
cmd.lazy_bind_off.set( cmd.lazy_bind_off
LittleEndian, .set(LE, cmd.lazy_bind_off.get(LE) + md.added_byte_count as u32);
cmd.lazy_bind_off.get(NativeEndian) + md.added_byte_count as u32,
);
} }
// TODO: Parse and update the related tables here. // TODO: Parse and update the related tables here.
@ -1026,40 +1039,26 @@ fn gen_macho_le(
// Also `xcrun dyldinfo` is useful for debugging this. // Also `xcrun dyldinfo` is useful for debugging this.
} }
macho::LC_SYMSEG => { macho::LC_SYMSEG => {
let cmd = load_struct_inplace_mut::<macho::SymsegCommand<LittleEndian>>( let cmd =
&mut out_mmap, load_struct_inplace_mut::<macho::SymsegCommand<LE>>(&mut out_mmap, offset);
offset,
);
if cmd.size.get(NativeEndian) > 0 { if cmd.size.get(LE) > 0 {
cmd.offset.set( cmd.offset
LittleEndian, .set(LE, cmd.offset.get(LE) + md.added_byte_count as u32);
cmd.offset.get(NativeEndian) + md.added_byte_count as u32,
);
} }
} }
macho::LC_MAIN => { macho::LC_MAIN => {
let cmd = load_struct_inplace_mut::<macho::EntryPointCommand<LittleEndian>>( let cmd =
&mut out_mmap, load_struct_inplace_mut::<macho::EntryPointCommand<LE>>(&mut out_mmap, offset);
offset,
);
cmd.entryoff.set( cmd.entryoff
LittleEndian, .set(LE, cmd.entryoff.get(LE) + md.added_byte_count);
cmd.entryoff.get(NativeEndian) + md.added_byte_count,
);
} }
macho::LC_NOTE => { macho::LC_NOTE => {
let cmd = load_struct_inplace_mut::<macho::NoteCommand<LittleEndian>>( let cmd = load_struct_inplace_mut::<macho::NoteCommand<LE>>(&mut out_mmap, offset);
&mut out_mmap,
offset,
);
if cmd.size.get(NativeEndian) > 0 { if cmd.size.get(LE) > 0 {
cmd.offset.set( cmd.offset.set(LE, cmd.offset.get(LE) + md.added_byte_count);
LittleEndian,
cmd.offset.get(NativeEndian) + md.added_byte_count,
);
} }
} }
macho::LC_ID_DYLIB macho::LC_ID_DYLIB
@ -1125,7 +1124,7 @@ fn gen_macho_le(
// fn scan_macho_dynamic_deps( // fn scan_macho_dynamic_deps(
// _exec_obj: &object::File, // _exec_obj: &object::File,
// _md: &mut metadata::Metadata, // _md: &mut Metadata,
// _app_syms: &[Symbol], // _app_syms: &[Symbol],
// _shared_lib: &str, // _shared_lib: &str,
// _exec_data: &[u8], // _exec_data: &[u8],
@ -1223,7 +1222,7 @@ fn surgery_macho_help(
_out_filename: &Path, _out_filename: &Path,
verbose: bool, verbose: bool,
_time: bool, _time: bool,
md: &metadata::Metadata, md: &Metadata,
exec_mmap: &mut MmapMut, exec_mmap: &mut MmapMut,
offset_ref: &mut usize, // TODO return this instead of taking a mutable reference to it offset_ref: &mut usize, // TODO return this instead of taking a mutable reference to it
app_obj: object::File, app_obj: object::File,
@ -1459,89 +1458,89 @@ fn surgery_macho_help(
// // Load this section (we made room for it earlier) and then mutate all its data to make it the desired command // // Load this section (we made room for it earlier) and then mutate all its data to make it the desired command
// { // {
// let cmd = // let cmd =
// load_struct_inplace_mut::<macho::SegmentCommand64<LittleEndian>>(exec_mmap, cmd_offset); // load_struct_inplace_mut::<macho::SegmentCommand64<LE >>(exec_mmap, cmd_offset);
// let size_of_section = mem::size_of::<macho::Section64<LittleEndian>>() as u32; // let size_of_section = mem::size_of::<macho::Section64<LE >>() as u32;
// let size_of_cmd = mem::size_of_val(cmd); // let size_of_cmd = mem::size_of_val(cmd);
// cmd_offset += size_of_cmd; // cmd_offset += size_of_cmd;
// cmd.cmd.set(LittleEndian, macho::LC_SEGMENT_64); // cmd.cmd.set(LE , macho::LC_SEGMENT_64);
// cmd.cmdsize // cmd.cmdsize
// .set(LittleEndian, size_of_section + size_of_cmd as u32); // .set(LE , size_of_section + size_of_cmd as u32);
// cmd.segname = *b"__DATA_CONST\0\0\0\0"; // cmd.segname = *b"__DATA_CONST\0\0\0\0";
// cmd.vmaddr // cmd.vmaddr
// .set(LittleEndian, new_rodata_section_vaddr as u64); // .set(LE , new_rodata_section_vaddr as u64);
// cmd.vmsize.set( // cmd.vmsize.set(
// LittleEndian, // LE ,
// (new_text_section_vaddr - new_rodata_section_vaddr) as u64, // (new_text_section_vaddr - new_rodata_section_vaddr) as u64,
// ); // );
// cmd.fileoff // cmd.fileoff
// .set(LittleEndian, new_rodata_section_offset as u64); // .set(LE , new_rodata_section_offset as u64);
// cmd.filesize.set( // cmd.filesize.set(
// LittleEndian, // LE ,
// (new_text_section_offset - new_rodata_section_offset) as u64, // (new_text_section_offset - new_rodata_section_offset) as u64,
// ); // );
// cmd.nsects.set(LittleEndian, 1); // cmd.nsects.set(LE , 1);
// cmd.maxprot.set(LittleEndian, 0x00000003); // cmd.maxprot.set(LE , 0x00000003);
// cmd.initprot.set(LittleEndian, 0x00000003); // cmd.initprot.set(LE , 0x00000003);
// // TODO set protection // // TODO set protection
// } // }
// { // {
// let cmd = load_struct_inplace_mut::<macho::Section64<LittleEndian>>(exec_mmap, cmd_offset); // let cmd = load_struct_inplace_mut::<macho::Section64<LE >>(exec_mmap, cmd_offset);
// let size_of_cmd = mem::size_of_val(cmd); // let size_of_cmd = mem::size_of_val(cmd);
// cmd_offset += size_of_cmd; // cmd_offset += size_of_cmd;
// cmd.sectname = *b"__const\0\0\0\0\0\0\0\0\0"; // cmd.sectname = *b"__const\0\0\0\0\0\0\0\0\0";
// cmd.segname = *b"__DATA_CONST\0\0\0\0"; // cmd.segname = *b"__DATA_CONST\0\0\0\0";
// cmd.addr.set(LittleEndian, new_rodata_section_vaddr as u64); // cmd.addr.set(LE , new_rodata_section_vaddr as u64);
// cmd.size.set( // cmd.size.set(
// LittleEndian, // LE ,
// (new_text_section_offset - new_rodata_section_offset) as u64, // (new_text_section_offset - new_rodata_section_offset) as u64,
// ); // );
// cmd.offset.set(LittleEndian, 0); // TODO is this offset since the start of the file, or segment offset? // cmd.offset.set(LE , 0); // TODO is this offset since the start of the file, or segment offset?
// cmd.align.set(LittleEndian, 12); // TODO should this be 4096? // cmd.align.set(LE , 12); // TODO should this be 4096?
// cmd.reloff.set(LittleEndian, 264); // TODO this should NOT be hardcoded! Should get it from somewhere. // cmd.reloff.set(LE , 264); // TODO this should NOT be hardcoded! Should get it from somewhere.
// } // }
// { // {
// let cmd = // let cmd =
// load_struct_inplace_mut::<macho::SegmentCommand64<LittleEndian>>(exec_mmap, cmd_offset); // load_struct_inplace_mut::<macho::SegmentCommand64<LE >>(exec_mmap, cmd_offset);
// let size_of_section = mem::size_of::<macho::Section64<LittleEndian>>() as u32; // let size_of_section = mem::size_of::<macho::Section64<LE >>() as u32;
// let size_of_cmd = mem::size_of_val(cmd); // let size_of_cmd = mem::size_of_val(cmd);
// cmd_offset += size_of_cmd; // cmd_offset += size_of_cmd;
// cmd.cmd.set(LittleEndian, macho::LC_SEGMENT_64); // cmd.cmd.set(LE , macho::LC_SEGMENT_64);
// cmd.cmdsize // cmd.cmdsize
// .set(LittleEndian, size_of_section + size_of_cmd as u32); // .set(LE , size_of_section + size_of_cmd as u32);
// cmd.segname = *b"__TEXT\0\0\0\0\0\0\0\0\0\0"; // cmd.segname = *b"__TEXT\0\0\0\0\0\0\0\0\0\0";
// cmd.vmaddr.set(LittleEndian, new_text_section_vaddr as u64); // cmd.vmaddr.set(LE , new_text_section_vaddr as u64);
// cmd.vmsize // cmd.vmsize
// .set(LittleEndian, (offset - new_text_section_offset) as u64); // .set(LE , (offset - new_text_section_offset) as u64);
// cmd.fileoff // cmd.fileoff
// .set(LittleEndian, new_text_section_offset as u64); // .set(LE , new_text_section_offset as u64);
// cmd.filesize // cmd.filesize
// .set(LittleEndian, (offset - new_text_section_offset) as u64); // .set(LE , (offset - new_text_section_offset) as u64);
// cmd.nsects.set(LittleEndian, 1); // cmd.nsects.set(LE , 1);
// cmd.maxprot.set(LittleEndian, 0x00000005); // this is what a zig-generated host had // cmd.maxprot.set(LE , 0x00000005); // this is what a zig-generated host had
// cmd.initprot.set(LittleEndian, 0x00000005); // this is what a zig-generated host had // cmd.initprot.set(LE , 0x00000005); // this is what a zig-generated host had
// } // }
// { // {
// let cmd = load_struct_inplace_mut::<macho::Section64<LittleEndian>>(exec_mmap, cmd_offset); // let cmd = load_struct_inplace_mut::<macho::Section64<LE >>(exec_mmap, cmd_offset);
// cmd.segname = *b"__TEXT\0\0\0\0\0\0\0\0\0\0"; // cmd.segname = *b"__TEXT\0\0\0\0\0\0\0\0\0\0";
// cmd.sectname = *b"__text\0\0\0\0\0\0\0\0\0\0"; // cmd.sectname = *b"__text\0\0\0\0\0\0\0\0\0\0";
// cmd.addr.set(LittleEndian, new_text_section_vaddr as u64); // cmd.addr.set(LE , new_text_section_vaddr as u64);
// cmd.size // cmd.size
// .set(LittleEndian, (offset - new_text_section_offset) as u64); // .set(LE , (offset - new_text_section_offset) as u64);
// cmd.offset.set(LittleEndian, 0); // TODO is this offset since the start of the file, or segment offset? // cmd.offset.set(LE , 0); // TODO is this offset since the start of the file, or segment offset?
// cmd.align.set(LittleEndian, 12); // TODO this is 4096 (2^12) - which load_align_constraint does, above - but should it? // cmd.align.set(LE , 12); // TODO this is 4096 (2^12) - which load_align_constraint does, above - but should it?
// cmd.flags.set(LittleEndian, 0x80000400); // TODO this is what a zig-generated host had // cmd.flags.set(LE , 0x80000400); // TODO this is what a zig-generated host had
// cmd.reloff.set(LittleEndian, 264); // TODO this should NOT be hardcoded! Should get it from somewhere. // cmd.reloff.set(LE , 264); // TODO this should NOT be hardcoded! Should get it from somewhere.
// } // }
// Update calls from platform and dynamic symbols. // Update calls from platform and dynamic symbols.
@ -1618,13 +1617,13 @@ fn surgery_macho_help(
// Commented out because it doesn't apply to mach-o // Commented out because it doesn't apply to mach-o
// if let Some(i) = md.dynamic_symbol_indices.get(func_name) { // if let Some(i) = md.dynamic_symbol_indices.get(func_name) {
// let sym = load_struct_inplace_mut::<elf::Sym64<LittleEndian>>( // let sym = load_struct_inplace_mut::<elf::Sym64<LE >>(
// exec_mmap, // exec_mmap,
// dynsym_offset as usize + *i as usize * mem::size_of::<elf::Sym64<LittleEndian>>(), // dynsym_offset as usize + *i as usize * mem::size_of::<elf::Sym64<LE >>(),
// ); // );
// sym.st_value = endian::U64::new(LittleEndian, func_virt_offset as u64); // sym.st_value.set(LE , func_virt_offset as u64);
// sym.st_size = endian::U64::new( // sym.st_size.set(
// LittleEndian, // LE ,
// match app_func_size_map.get(func_name) { // match app_func_size_map.get(func_name) {
// Some(size) => *size, // Some(size) => *size,
// None => { // None => {

View file

@ -1,75 +0,0 @@
use std::{
io::{BufReader, BufWriter},
path::Path,
};
use bincode::{deserialize_from, serialize_into};
use roc_collections::all::MutMap;
use roc_error_macros::internal_error;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
pub enum VirtualOffset {
Absolute,
Relative(u64),
}
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
pub struct SurgeryEntry {
pub file_offset: u64,
pub virtual_offset: VirtualOffset,
pub size: u8,
}
// TODO: Reanalyze each piece of data in this struct.
// I think a number of them can be combined to reduce string duplication.
// Also I think a few of them aren't need.
// For example, I think preprocessing can deal with all shifting and remove the need for added_byte_count.
#[derive(Default, Serialize, Deserialize, PartialEq, Eq, Debug)]
pub struct Metadata {
pub app_functions: Vec<String>,
// offset followed by address.
pub plt_addresses: MutMap<String, (u64, u64)>,
pub surgeries: MutMap<String, Vec<SurgeryEntry>>,
pub dynamic_symbol_indices: MutMap<String, u64>,
pub static_symbol_indices: MutMap<String, u64>,
pub roc_symbol_vaddresses: MutMap<String, u64>,
pub exec_len: u64,
pub load_align_constraint: u64,
pub added_byte_count: u64,
pub last_vaddr: u64,
pub dynamic_section_offset: u64,
pub dynamic_symbol_table_section_offset: u64,
pub symbol_table_section_offset: u64,
pub symbol_table_size: u64,
pub macho_cmd_loc: u64,
}
impl Metadata {
pub fn write_to_file(&self, metadata_filename: &Path) {
let metadata_file =
std::fs::File::create(metadata_filename).unwrap_or_else(|e| internal_error!("{}", e));
serialize_into(BufWriter::new(metadata_file), self)
.unwrap_or_else(|err| internal_error!("Failed to serialize metadata: {err}"));
}
pub fn read_from_file(metadata_filename: &Path) -> Self {
let input = std::fs::File::open(metadata_filename).unwrap_or_else(|e| {
internal_error!(
r#"
Error:
{}\n"#,
e
)
});
match deserialize_from(BufReader::new(input)) {
Ok(data) => data,
Err(err) => {
internal_error!("Failed to deserialize metadata: {}", err);
}
}
}
}

View file

@ -4,36 +4,6 @@ use std::{
process::Command, process::Command,
}; };
// get the path of the lib folder
// runtime dependencies like zig files, Windows dylib builds, are put in the lib folder
pub fn get_lib_path() -> Option<PathBuf> {
let exe_relative_str_path_opt = std::env::current_exe().ok();
if let Some(exe_relative_str_path) = exe_relative_str_path_opt {
#[cfg(windows)]
let exe_relative_str_path = strip_windows_prefix(&exe_relative_str_path);
let mut curr_parent_opt = exe_relative_str_path.parent();
// this differs for regular build and nix releases, so we check in multiple spots.
for _ in 0..3 {
if let Some(curr_parent) = curr_parent_opt {
let lib_path = curr_parent.join("lib");
if std::path::Path::exists(&lib_path) {
return Some(lib_path);
} else {
curr_parent_opt = curr_parent.parent();
}
} else {
break;
}
}
}
None
}
#[cfg(windows)] #[cfg(windows)]
use std::path::Path; use std::path::Path;

View file

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const str = @import("str"); const str = @import("glue").str;
const RocStr = str.RocStr; const RocStr = str.RocStr;
const testing = std.testing; const testing = std.testing;
const expectEqual = testing.expectEqual; const expectEqual = testing.expectEqual;

View file

@ -6,9 +6,10 @@
, pkgs ? import nixpkgsSource { } , pkgs ? import nixpkgsSource { }
, ,
}: }:
# we only this file to release a nix package, use flake.nix for development # we only use this file to release a nix package, use flake.nix for development
let let
rustPlatform = pkgs.rustPlatform; rustPlatform = pkgs.rustPlatform;
llvmPkgs = pkgs.llvmPackages_13; llvmPkgs = pkgs.llvmPackages_13;
# nix does not store libs in /usr/lib or /lib # nix does not store libs in /usr/lib or /lib
nixGlibcPath = if pkgs.stdenv.isLinux then "${pkgs.glibc.out}/lib" else ""; nixGlibcPath = if pkgs.stdenv.isLinux then "${pkgs.glibc.out}/lib" else "";
@ -23,7 +24,7 @@ rustPlatform.buildRustPackage {
lockFile = ./Cargo.lock; lockFile = ./Cargo.lock;
outputHashes = { outputHashes = {
"confy-0.5.1" = "sha256-3PQdz9W/uJd4CaUZdwAd2u3JJ100SFAoKLCFE6THRZI="; "confy-0.5.1" = "sha256-3PQdz9W/uJd4CaUZdwAd2u3JJ100SFAoKLCFE6THRZI=";
"criterion-0.3.5" = "sha256-7REd3phV6PBzqWwKF8hwttw4FTq2tKGxxAAJDpLC50A="; "criterion-0.3.5" = "sha256-+FibPQGiR45g28xCHcM0pMN+C+Q8gO8206Wb5fiTy+k=";
"inkwell-0.1.0" = "sha256-1kpvY3naS33B99nuu5ZYhb7mdddAyG+DkbUl/RG1Ptg="; "inkwell-0.1.0" = "sha256-1kpvY3naS33B99nuu5ZYhb7mdddAyG+DkbUl/RG1Ptg=";
"plotters-0.3.1" = "sha256-noy/RSjoEPZZbOJTZw1yxGcX5S+2q/7mxnUrzDyxOFw="; "plotters-0.3.1" = "sha256-noy/RSjoEPZZbOJTZw1yxGcX5S+2q/7mxnUrzDyxOFw=";
"rustyline-9.1.1" = "sha256-aqQqz6nSp+Qn44gm3jXmmQUO6/fYTx7iLph2tbA24Bs="; "rustyline-9.1.1" = "sha256-aqQqz6nSp+Qn44gm3jXmmQUO6/fYTx7iLph2tbA24Bs=";

View file

@ -10,7 +10,7 @@ Further steps:
1. Copy the flake.nix and flake.lock file to a new folder outside of the roc repo folder. 1. Copy the flake.nix and flake.lock file to a new folder outside of the roc repo folder.
1. Run `git init` in the new folder. 1. Run `git init` in the new folder.
1. Execute `git add flake.nix`, nix will error if you don't do this. 1. Execute `git add flake.nix`, nix will error if you don't do this.
1. Change `roc.url = "path:/home/username/gitrepos/roc1/roc";` to the location of the roc folder on your machine. 1. Change `roc.url = "path:/home/username/gitrepos/roc9/roc";` to the location of the roc folder on your machine.
1. Follow instructions about vscode extensions [here](#extensions). 1. Follow instructions about vscode extensions [here](#extensions).
1. add other dev tools you like in the `devInputs` list. You can search for those [here](https://search.nixos.org/packages). 1. add other dev tools you like in the `devInputs` list. You can search for those [here](https://search.nixos.org/packages).
1. Run `nix develop`. 1. Run `nix develop`.

100
devtools/flake.lock generated
View file

@ -1,12 +1,15 @@
{ {
"nodes": { "nodes": {
"flake-utils": { "flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": { "locked": {
"lastModified": 1667395993, "lastModified": 1681202837,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -16,12 +19,15 @@
} }
}, },
"flake-utils_2": { "flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": { "locked": {
"lastModified": 1667395993, "lastModified": 1681202837,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -46,12 +52,15 @@
} }
}, },
"flake-utils_4": { "flake-utils_4": {
"inputs": {
"systems": "systems_3"
},
"locked": { "locked": {
"lastModified": 1659877975, "lastModified": 1681202837,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -69,11 +78,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1672992692, "lastModified": 1676383589,
"narHash": "sha256-/eLQLSNIa22ARTZbk+x8i0iE8khe1eiHWkuxgTVXZ7g=", "narHash": "sha256-KCkWZXCjH+C4Kn7fUGSrEl5btk+sERHhZueSsvVbPWc=",
"owner": "guibou", "owner": "guibou",
"repo": "nixGL", "repo": "nixGL",
"rev": "643e730efb981ffaf8478f441ec9b9aeea1c89f5", "rev": "c917918ab9ebeee27b0dd657263d3f57ba6bb8ad",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -84,17 +93,17 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1673134516, "lastModified": 1674860021,
"narHash": "sha256-mAZQKqkNQbBmJnmUU0blOfkKlgMSSVyPHdeWeuKad8U=", "narHash": "sha256-ES4XUf/AlPp8RetKR6WlWgYEZ7bLWI7k6reHp2q9rqY=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "f6f44561884c3470e2b783683d5dbac42dfc833b", "rev": "9f4346eac544cc0db5eb7d889e71eac0f9c8b9eb",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9f4346eac544cc0db5eb7d889e71eac0f9c8b9eb",
"type": "github" "type": "github"
} }
}, },
@ -106,13 +115,13 @@
"rust-overlay": "rust-overlay" "rust-overlay": "rust-overlay"
}, },
"locked": { "locked": {
"lastModified": 1673266343, "lastModified": 1682761608,
"narHash": "sha256-HQGjNhCte1wgvo5/SUL1OjIpfoUCQ8vC/2k0gi7UtmQ=", "narHash": "sha256-+6tHbEK8GYDSCLasgawufSLegyJ0cqHV2nfmJICwzrk=",
"path": "/home/username/gitrepos/roc1/roc", "path": "/home/username/gitrepos/roc9/roc",
"type": "path" "type": "path"
}, },
"original": { "original": {
"path": "/home/username/gitrepos/roc1/roc", "path": "/home/username/gitrepos/roc9/roc",
"type": "path" "type": "path"
} }
}, },
@ -131,11 +140,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1673231106, "lastModified": 1682389182,
"narHash": "sha256-Tbw4N/TL+nHmxF8RBoOJbl/6DRRzado/9/ttPEzkGr8=", "narHash": "sha256-8t2nmFnH+8V48+IJsf8AK51ebXNlVbOSVYOpiqJKvJE=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "3488cec01351c2f1086b02a3a61808be7a25103e", "rev": "74f1a64dd28faeeb85ef081f32cad2989850322c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -143,6 +152,51 @@
"repo": "rust-overlay", "repo": "rust-overlay",
"type": "github" "type": "github"
} }
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -1,9 +1,9 @@
{ {
description = "Allows sharing dependencies between dev tools and roc"; description = "Allows sharing dependencies between dev tools and roc. Prevents version GLIBC_2.36 not found.";
inputs = { inputs = {
# change this path to the path of your roc folder # change this path to the path of your roc folder
roc.url = "path:/home/username/gitrepos/roc1/roc"; roc.url = "path:/home/username/gitrepos/roc9/roc";
# to easily make configs for multiple architectures # to easily make configs for multiple architectures
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
}; };
@ -24,7 +24,7 @@
vscodeWithExtensions = pkgs.vscode-with-extensions.override { vscodeWithExtensions = pkgs.vscode-with-extensions.override {
vscodeExtensions = with pkgs.vscode-extensions; [ vscodeExtensions = with pkgs.vscode-extensions; [
matklad.rust-analyzer matklad.rust-analyzer
eamodio.gitlens # eamodio.gitlens
bbenoist.nix bbenoist.nix
vadimcn.vscode-lldb vadimcn.vscode-lldb
tamasfe.even-better-toml tamasfe.even-better-toml
@ -33,13 +33,12 @@
{ {
name = "roc-lang-support"; name = "roc-lang-support";
publisher = "benjamin-thomas"; publisher = "benjamin-thomas";
version = "0.0.3"; version = "0.0.4";
# keep this sha for the first run, nix will tell you the correct one to change it to # keep this sha for the first run, nix will tell you the correct one to change it to
sha256 = "sha256-mabNegZ+XPQ6EIHFk6jz2mAPLHAU6Pm3w0SiFB7IE+s="; sha256 = "sha256-mabNegZ+XPQ6EIHFk6jz2mAPLHAU6Pm3w0SiFB7IE+s=";
} }
] ]
; ;
}; };
in [ vscodeWithExtensions devInputs ]; in [ vscodeWithExtensions devInputs ];

View file

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const str = @import("str"); const str = @import("glue").str;
const RocStr = str.RocStr; const RocStr = str.RocStr;
const testing = std.testing; const testing = std.testing;
const expectEqual = testing.expectEqual; const expectEqual = testing.expectEqual;

View file

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const str = @import("str"); const str = @import("glue").str;
const RocStr = str.RocStr; const RocStr = str.RocStr;
const testing = std.testing; const testing = std.testing;
const expectEqual = testing.expectEqual; const expectEqual = testing.expectEqual;

View file

@ -1,16 +1,15 @@
#![allow(non_snake_case)] #![allow(non_snake_case)]
mod glue; mod test_glue;
use core::ffi::c_void; use core::ffi::c_void;
use glue::Op;
use roc_std::RocStr; use roc_std::RocStr;
use std::ffi::CStr; use std::ffi::CStr;
use std::io::Write; use std::io::Write;
use std::mem::MaybeUninit;
use std::os::raw::c_char; use std::os::raw::c_char;
use test_glue::Op;
use glue::mainForHost as roc_main; use test_glue::mainForHost as roc_main;
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void { pub unsafe extern "C" fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void {
@ -86,7 +85,7 @@ pub unsafe extern "C" fn roc_shm_open(
#[no_mangle] #[no_mangle]
pub extern "C" fn rust_main() -> i32 { pub extern "C" fn rust_main() -> i32 {
use glue::discriminant_Op::*; use test_glue::discriminant_Op::*;
println!("Let's do things!"); println!("Let's do things!");
@ -95,16 +94,18 @@ pub extern "C" fn rust_main() -> i32 {
loop { loop {
match dbg!(op.discriminant()) { match dbg!(op.discriminant()) {
StdoutWrite => { StdoutWrite => {
let output: RocStr = unsafe { op.get_StdoutWrite_0() }; let stdout_write = unsafe { op.get_StdoutWrite() };
op = unsafe { op.get_StdoutWrite_1().force_thunk(()) }; let output: RocStr = stdout_write.f0;
op = unsafe { stdout_write.f1.force_thunk(()) };
if let Err(e) = std::io::stdout().write_all(output.as_bytes()) { if let Err(e) = std::io::stdout().write_all(output.as_bytes()) {
panic!("Writing to stdout failed! {:?}", e); panic!("Writing to stdout failed! {:?}", e);
} }
} }
StderrWrite => { StderrWrite => {
let output: RocStr = unsafe { op.get_StderrWrite_0() }; let stderr_write = unsafe { op.get_StderrWrite() };
op = unsafe { op.get_StderrWrite_1().force_thunk(()) }; let output: RocStr = stderr_write.f0;
op = unsafe { stderr_write.f1.force_thunk(()) };
if let Err(e) = std::io::stderr().write_all(output.as_bytes()) { if let Err(e) = std::io::stderr().write_all(output.as_bytes()) {
panic!("Writing to stdout failed! {:?}", e); panic!("Writing to stdout failed! {:?}", e);

View file

@ -1,5 +1,5 @@
[toolchain] [toolchain]
channel = "1.65.0" channel = "1.66.1"
profile = "default" profile = "default"

View file

@ -1,4 +1,4 @@
const str = @import("str"); const str = @import("glue").str;
const builtin = @import("builtin"); const builtin = @import("builtin");
const RocStr = str.RocStr; const RocStr = str.RocStr;

View file

@ -1,6 +1,6 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const str = @import("str"); const str = @import("glue").str;
const RocStr = str.RocStr; const RocStr = str.RocStr;
const testing = std.testing; const testing = std.testing;
const expectEqual = testing.expectEqual; const expectEqual = testing.expectEqual;

View file

@ -1,5 +1,5 @@
const std = @import("std"); const std = @import("std");
const str = @import("str"); const str = @import("glue").str;
const builtin = @import("builtin"); const builtin = @import("builtin");
const RocStr = str.RocStr; const RocStr = str.RocStr;

View file

@ -1,5 +1,5 @@
const std = @import("std"); const std = @import("std");
const str = @import("str"); const str = @import("glue").str;
const builtin = @import("builtin"); const builtin = @import("builtin");
const RocStr = str.RocStr; const RocStr = str.RocStr;

68
flake.lock generated
View file

@ -1,12 +1,15 @@
{ {
"nodes": { "nodes": {
"flake-utils": { "flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": { "locked": {
"lastModified": 1667395993, "lastModified": 1681202837,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -31,12 +34,15 @@
} }
}, },
"flake-utils_3": { "flake-utils_3": {
"inputs": {
"systems": "systems_2"
},
"locked": { "locked": {
"lastModified": 1659877975, "lastModified": 1681202837,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -53,11 +59,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1672992692, "lastModified": 1676383589,
"narHash": "sha256-/eLQLSNIa22ARTZbk+x8i0iE8khe1eiHWkuxgTVXZ7g=", "narHash": "sha256-KCkWZXCjH+C4Kn7fUGSrEl5btk+sERHhZueSsvVbPWc=",
"owner": "guibou", "owner": "guibou",
"repo": "nixGL", "repo": "nixGL",
"rev": "643e730efb981ffaf8478f441ec9b9aeea1c89f5", "rev": "c917918ab9ebeee27b0dd657263d3f57ba6bb8ad",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -68,17 +74,17 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1673796341, "lastModified": 1674860021,
"narHash": "sha256-1kZi9OkukpNmOaPY7S5/+SlCDOuYnP3HkXHvNDyLQcc=", "narHash": "sha256-ES4XUf/AlPp8RetKR6WlWgYEZ7bLWI7k6reHp2q9rqY=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "6dccdc458512abce8d19f74195bb20fdb067df50", "rev": "9f4346eac544cc0db5eb7d889e71eac0f9c8b9eb",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nixos", "owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9f4346eac544cc0db5eb7d889e71eac0f9c8b9eb",
"type": "github" "type": "github"
} }
}, },
@ -98,11 +104,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1673922364, "lastModified": 1682389182,
"narHash": "sha256-U0XIY/Y/x4fFtlCZKMtWlqOYUnLiXj4F42GQHxWuPow=", "narHash": "sha256-8t2nmFnH+8V48+IJsf8AK51ebXNlVbOSVYOpiqJKvJE=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "4e0f9b8a5102387f8d19901bced16a256a6ccdc7", "rev": "74f1a64dd28faeeb85ef081f32cad2989850322c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -110,6 +116,36 @@
"repo": "rust-overlay", "repo": "rust-overlay",
"type": "github" "type": "github"
} }
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -2,7 +2,7 @@
description = "Roc flake"; description = "Roc flake";
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs?rev=9f4346eac544cc0db5eb7d889e71eac0f9c8b9eb";
# rust from nixpkgs has some libc problems, this is patched in the rust-overlay # rust from nixpkgs has some libc problems, this is patched in the rust-overlay
rust-overlay = { rust-overlay = {

View file

@ -3,14 +3,15 @@
# - update `channel = "RUST_VERSION"` # - update `channel = "RUST_VERSION"`
# - update `channel = "RUST_VERSION"` in examples/platform-switching/rust-platform/rust-toolchain.toml # - update `channel = "RUST_VERSION"` in examples/platform-switching/rust-platform/rust-toolchain.toml
# - to update the nightly version: # - to update the nightly version:
# - Find the latest nightly release that matches RUST_VERSION here: https://github.com/oxalica/rust-overlay/tree/master/manifests/nightly/2022 # - Find the latest nightly release that matches RUST_VERSION here: https://github.com/oxalica/rust-overlay/tree/master/manifests/nightly/2023
# - update `channel = "nightly-OLD_DATE"` below # - update `channel = "nightly-OLD_DATE"` below
# - update nightly-OLD_DATE in .github/workflows/windows.yml # - update nightly-OLD_DATE in .github/workflows/windows_tests.yml
# - update nightly-OLD_DATE in .github/workflows/windows_release_build.yml
# - update nightly-OLD_DATE in crates/compiler/build/src/link.rs # - update nightly-OLD_DATE in crates/compiler/build/src/link.rs
channel = "1.65.0" # check ^^^ when changing this channel = "1.66.1" # check ^^^ when changing this
# #
# channel = "nightly-2022-09-17" # 1.65 nightly to be able to use unstable features # channel = "nightly-2022-10-30" # 1.66.0 nightly to be able to use unstable features
profile = "default" profile = "default"
components = [ components = [
# for usages of rust-analyzer or similar tools inside `nix develop` # for usages of rust-analyzer or similar tools inside `nix develop`

View file

@ -1982,4 +1982,4 @@ Here are various Roc expressions involving operators, and what they desugar to.
These are all of the language keywords supported by Roc; These are all of the language keywords supported by Roc;
`if`,`then`,`else`,`when`,`as`,`is`,`dbg`,`expect`,`expect-fx`,`crash`,`interface`,`app`,`package`,`platform`,`hosted`,`exposes`,`imports`,`with`,`generates`,`package`,`packages`,`requires`,`provides`,`to` `if`,`then`,`else`,`when`,`as`,`is`,`dbg`,`expect`,`expect-fx`,`crash`,`interface`,`app`,`package`,`platform`,`hosted`,`exposes`,`imports`,`with`,`generates`,`packages`,`requires`,`provides`,`to`