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
run: zig version
- name: install rust nightly 1.65
run: rustup install nightly-2022-09-17
- name: install rust nightly 1.66
run: rustup install nightly-2022-10-30
- name: set up llvm 13
run: |

View file

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

5
Cargo.lock generated
View file

@ -764,7 +764,7 @@ dependencies = [
[[package]]
name = "criterion"
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 = [
"atty",
"cast",
@ -789,7 +789,7 @@ dependencies = [
[[package]]
name = "criterion-plot"
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 = [
"cast",
"itertools 0.9.0",
@ -3741,6 +3741,7 @@ dependencies = [
"quickcheck",
"quickcheck_macros",
"roc_collections",
"roc_error_macros",
"roc_module",
"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"
const_format = { version = "0.2.30", features = ["const_generics"] }
copypasta = "0.8.2"
criterion = { git = "https://github.com/Anton-4/criterion.rs", features = ["html_reports"] }
criterion-perf-events = { git = "https://github.com/Anton-4/criterion-perf-events" }
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", rev = "0f38c3e" }
crossbeam = "0.8.2"
dircpy = "0.3.14"
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
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)
&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;
[<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 builtin = @import("builtin");
const str = @import("str");
const str = @import("glue").str;
const RocStr = str.RocStr;
const testing = std.testing;
const expectEqual = testing.expectEqual;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
use crate::target::{arch_str, target_zig_str};
use libloading::{Error, Library};
use roc_command_utils::{cargo, clang, get_lib_path, rustup, zig};
use roc_command_utils::{cargo, clang, rustup, zig};
use roc_error_macros::internal_error;
use roc_mono::ir::OptLevel;
use std::collections::HashMap;
@ -63,31 +63,57 @@ pub fn legacy_host_filename(target: &Triple) -> Option<String> {
)
}
fn find_zig_str_path() -> PathBuf {
// First try using the lib path relative to the executable location.
let lib_path_opt = get_lib_path();
// Attempts to find a file that is stored relative to the roc executable.
// Since roc is built in target/debug/roc, we may need to drop that path to find the file.
// This is used to avoid depending on the current working directory.
pub fn get_relative_path(sub_path: &Path) -> Option<PathBuf> {
if sub_path.is_absolute() {
internal_error!(
"get_relative_path requires sub_path to be relative, instead got {:?}",
sub_path
);
}
let exe_relative_str_path_opt = std::env::current_exe().ok();
if let Some(lib_path) = lib_path_opt {
let zig_str_path = lib_path.join("str.zig");
if let Some(exe_relative_str_path) = exe_relative_str_path_opt {
#[cfg(windows)]
let exe_relative_str_path = roc_command_utils::strip_windows_prefix(&exe_relative_str_path);
if std::path::Path::exists(&zig_str_path) {
return zig_str_path;
let mut curr_parent_opt = exe_relative_str_path.parent();
// We need to support paths like ./roc, ./bin/roc, ./target/debug/roc and tests like ./target/debug/deps/valgrind-63c787aa176d1277
// This requires dropping up to 3 directories.
for _ in 0..=3 {
if let Some(curr_parent) = curr_parent_opt {
let potential_path = curr_parent.join(sub_path);
if std::path::Path::exists(&potential_path) {
return Some(potential_path);
} else {
curr_parent_opt = curr_parent.parent();
}
} else {
break;
}
}
}
let zig_str_path = PathBuf::from("crates/compiler/builtins/bitcode/src/str.zig");
None
}
if std::path::Path::exists(&zig_str_path) {
return zig_str_path;
fn find_zig_glue_path() -> PathBuf {
// First try using the repo path relative to the executable location.
let path = get_relative_path(Path::new("crates/compiler/builtins/bitcode/src/glue.zig"));
if let Some(path) = path {
return path;
}
// Fallback on a lib path relative to the executable location.
let path = get_relative_path(Path::new("lib/glue.zig"));
if let Some(path) = path {
return path;
}
// when running the tests, we start in the /cli directory
let zig_str_path = PathBuf::from("../compiler/builtins/bitcode/src/str.zig");
if std::path::Path::exists(&zig_str_path) {
return zig_str_path;
}
internal_error!("cannot find `str.zig`. Check the source code in find_zig_str_path() to show all the paths I tried.")
internal_error!("cannot find `glue.zig`. Check the source code in find_zig_glue_path() to show all the paths I tried.")
}
fn find_wasi_libc_path() -> PathBuf {
@ -107,7 +133,6 @@ pub fn build_zig_host_native(
env_home: &str,
emit_bin: &str,
zig_host_src: &str,
zig_str_path: &str,
target: &str,
opt_level: OptLevel,
shared_lib_path: Option<&Path>,
@ -138,8 +163,8 @@ pub fn build_zig_host_native(
zig_host_src,
&format!("-femit-bin={}", emit_bin),
"--pkg-begin",
"str",
zig_str_path,
"glue",
find_zig_glue_path().to_str().unwrap(),
"--pkg-end",
// include libc
"-lc",
@ -180,7 +205,6 @@ pub fn build_zig_host_native(
env_home: &str,
emit_bin: &str,
zig_host_src: &str,
zig_str_path: &str,
target: &str,
opt_level: OptLevel,
shared_lib_path: Option<&Path>,
@ -211,8 +235,8 @@ pub fn build_zig_host_native(
zig_host_src,
&format!("-femit-bin={}", emit_bin),
"--pkg-begin",
"str",
zig_str_path,
"glue",
find_zig_glue_path().to_str().unwrap(),
"--pkg-end",
// include the zig runtime
// "-fcompiler-rt", compiler-rt causes segfaults on windows; investigate why
@ -240,7 +264,6 @@ pub fn build_zig_host_native(
env_home: &str,
emit_bin: &str,
zig_host_src: &str,
zig_str_path: &str,
_target: &str,
opt_level: OptLevel,
shared_lib_path: Option<&Path>,
@ -306,8 +329,8 @@ pub fn build_zig_host_native(
zig_host_src,
&format!("-femit-bin={}", emit_bin),
"--pkg-begin",
"str",
zig_str_path,
"glue",
find_zig_glue_path().to_str().unwrap(),
"--pkg-end",
// include the zig runtime
"--pkg-begin",
@ -332,7 +355,6 @@ pub fn build_zig_host_wasm32(
env_home: &str,
emit_bin: &str,
zig_host_src: &str,
zig_str_path: &str,
opt_level: OptLevel,
shared_lib_path: Option<&Path>,
) -> Command {
@ -356,13 +378,18 @@ pub fn build_zig_host_wasm32(
//
// https://github.com/ziglang/zig/issues/9414
let mut zig_cmd = zig();
let args = &[
zig_cmd
.env_clear()
.env("PATH", env_path)
.env("HOME", env_home)
.args([
"build-obj",
zig_host_src,
emit_bin,
"--pkg-begin",
"str",
zig_str_path,
"glue",
find_zig_glue_path().to_str().unwrap(),
"--pkg-end",
// include the zig runtime
// "-fcompiler-rt",
@ -374,13 +401,7 @@ pub fn build_zig_host_wasm32(
// "-femit-llvm-ir=/home/folkertdev/roc/roc/crates/cli_testing_examples/benchmarks/platform/host.ll",
"-fPIC",
"--strip",
];
zig_cmd
.env_clear()
.env("PATH", env_path)
.env("HOME", env_home)
.args(args);
]);
if matches!(opt_level, OptLevel::Optimize) {
zig_cmd.args(["-O", "ReleaseSafe"]);
@ -424,7 +445,6 @@ pub fn build_c_host_native(
env_home,
dest,
sources[0],
find_zig_str_path().to_str().unwrap(),
get_target_str(target),
opt_level,
Some(shared_lib_path),
@ -558,15 +578,6 @@ pub fn rebuild_host(
if zig_host_src.exists() {
// Compile host.zig
let zig_str_path = find_zig_str_path();
debug_assert!(
std::path::Path::exists(&zig_str_path),
"Cannot find str.zig, looking at {:?}",
&zig_str_path
);
let zig_cmd = match target.architecture {
Architecture::Wasm32 => {
let emit_bin = if matches!(opt_level, OptLevel::Development) {
@ -579,7 +590,6 @@ pub fn rebuild_host(
&env_home,
&emit_bin,
zig_host_src.to_str().unwrap(),
zig_str_path.to_str().unwrap(),
opt_level,
shared_lib_path,
)
@ -589,7 +599,6 @@ pub fn rebuild_host(
&env_home,
host_dest.to_str().unwrap(),
zig_host_src.to_str().unwrap(),
zig_str_path.to_str().unwrap(),
get_target_str(target),
opt_level,
shared_lib_path,
@ -600,7 +609,6 @@ pub fn rebuild_host(
&env_home,
host_dest.to_str().unwrap(),
zig_host_src.to_str().unwrap(),
zig_str_path.to_str().unwrap(),
"i386-linux-musl",
opt_level,
shared_lib_path,
@ -611,7 +619,6 @@ pub fn rebuild_host(
&env_home,
host_dest.to_str().unwrap(),
zig_host_src.to_str().unwrap(),
zig_str_path.to_str().unwrap(),
target_zig_str(target),
opt_level,
shared_lib_path,
@ -629,7 +636,7 @@ pub fn rebuild_host(
// on windows, we need the nightly toolchain so we can use `-Z export-executable-symbols`
// using `+nightly` only works when running cargo through rustup
let mut cmd = rustup();
cmd.args(["run", "nightly-2022-09-17", "cargo"]);
cmd.args(["run", "nightly-2022-10-30", "cargo"]);
cmd
} else {
@ -1273,7 +1280,6 @@ fn link_wasm32(
input_paths: &[&str],
_link_type: LinkType,
) -> io::Result<(Child, PathBuf)> {
let zig_str_path = find_zig_str_path();
let wasi_libc_path = find_wasi_libc_path();
let child = zig()
@ -1289,8 +1295,8 @@ fn link_wasm32(
"-target",
"wasm32-wasi-musl",
"--pkg-begin",
"str",
zig_str_path.to_str().unwrap(),
"glue",
find_zig_glue_path().to_str().unwrap(),
"--pkg-end",
"--strip",
"-O",
@ -1309,8 +1315,6 @@ fn link_windows(
input_paths: &[&str],
link_type: LinkType,
) -> io::Result<(Child, PathBuf)> {
let zig_str_path = find_zig_str_path();
match link_type {
LinkType::Dylib => {
let child = zig()
@ -1322,8 +1326,8 @@ fn link_windows(
"-target",
"native",
"--pkg-begin",
"str",
zig_str_path.to_str().unwrap(),
"glue",
find_zig_glue_path().to_str().unwrap(),
"--pkg-end",
"--strip",
"-O",

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.countGraphemeClusters, "count_grapheme_clusters");
exportStrFn(str.countUtf8Bytes, "count_utf8_bytes");
exportStrFn(str.isEmpty, "is_empty");
exportStrFn(str.getCapacity, "capacity");
exportStrFn(str.startsWith, "starts_with");
exportStrFn(str.startsWithScalar, "starts_with_scalar");

View file

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

View file

@ -1016,7 +1016,7 @@ sublistLowlevel : List elem, Nat, Nat -> List elem
## 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, 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_COUNT_GRAPEHEME_CLUSTERS: &str = "roc_builtins.str.count_grapheme_clusters";
pub const STR_COUNT_UTF8_BYTES: &str = "roc_builtins.str.count_utf8_bytes";
pub const STR_IS_EMPTY: &str = "roc_builtins.str.is_empty";
pub const STR_CAPACITY: &str = "roc_builtins.str.capacity";
pub const STR_STARTS_WITH: &str = "roc_builtins.str.starts_with";
pub const STR_STARTS_WITH_SCALAR: &str = "roc_builtins.str.starts_with_scalar";

View file

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

View file

@ -1338,7 +1338,7 @@ fn canonicalize_type_defs<'a>(
/// Resolve all pending abilities, to add them to scope.
#[allow(clippy::too_many_arguments)]
fn resolve_abilities(
env: &mut Env<'_>,
env: &mut Env,
output: &mut Output,
var_store: &mut VarStore,
scope: &mut Scope,
@ -2812,7 +2812,7 @@ fn to_pending_value_def<'a>(
/// Make aliases recursive
fn correct_mutual_recursive_type_alias(
env: &mut Env<'_>,
env: &mut Env,
original_aliases: VecMap<Symbol, Alias>,
var_store: &mut VarStore,
) -> VecMap<Symbol, Alias> {
@ -3021,7 +3021,7 @@ fn correct_mutual_recursive_type_alias(
}
fn make_tag_union_of_alias_recursive(
env: &mut Env<'_>,
env: &mut Env,
alias_name: Symbol,
alias: &mut Alias,
others: Vec<Symbol>,
@ -3214,7 +3214,7 @@ fn make_tag_union_recursive_help<'a, 'b>(
}
fn mark_cyclic_alias(
env: &mut Env<'_>,
env: &mut Env,
typ: &mut Type,
symbol: Symbol,
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
// operator desugaring should have removed them!
bad_expr @ ast::Expr::ParensAround(_) => {
panic!(
internal_error!(
"A ParensAround did not get removed during operator desugaring somehow: {:#?}",
bad_expr
);
}
bad_expr @ ast::Expr::SpaceBefore(_, _) => {
panic!(
internal_error!(
"A SpaceBefore did not get removed during operator desugaring somehow: {:#?}",
bad_expr
);
}
bad_expr @ ast::Expr::SpaceAfter(_, _) => {
panic!(
internal_error!(
"A SpaceAfter did not get removed during operator desugaring somehow: {:#?}",
bad_expr
);
}
bad_expr @ ast::Expr::BinOps { .. } => {
panic!(
internal_error!(
"A binary operator chain did not get desugared somehow: {:#?}",
bad_expr
);
}
bad_expr @ ast::Expr::UnaryOp(_, _) => {
panic!(
internal_error!(
"A unary operator did not get desugared somehow: {:#?}",
bad_expr
);
@ -1814,7 +1814,7 @@ fn canonicalize_field<'a>(
// A label with no value, e.g. `{ name }` (this is sugar for { name: name })
LabelOnly(_) => {
panic!("Somehow a LabelOnly record field was not desugared!");
internal_error!("Somehow a LabelOnly record field was not desugared!");
}
SpaceBefore(sub_field, _) | SpaceAfter(sub_field, _) => {
@ -1822,7 +1822,7 @@ fn canonicalize_field<'a>(
}
Malformed(_string) => {
panic!("TODO canonicalize malformed record field");
internal_error!("TODO canonicalize malformed record field");
}
}
}

View file

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

View file

@ -2,6 +2,7 @@
use bumpalo::collections::Vec;
use bumpalo::Bump;
use roc_error_macros::internal_error;
use roc_module::called_via::BinOp::Pizza;
use roc_module::called_via::{BinOp, CalledVia};
use roc_module::ident::ModuleName;
@ -592,7 +593,7 @@ fn binop_step<'a>(
//
// By design, Roc neither allows custom operators nor has any built-in operators with
// the same precedence and different associativity, so this should never happen!
panic!("BinOps had the same associativity, but different precedence. This should never happen!");
internal_error!("BinOps had the same associativity, but different precedence. This should never happen!");
}
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -103,13 +103,7 @@ impl<'a> Formattable for Expr<'a> {
}
}
fn format_with_options(
&self,
buf: &mut Buf<'_>,
parens: Parens,
newlines: Newlines,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
use self::Expr::*;
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::*;
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::*;
match literal {
@ -674,7 +668,7 @@ pub fn fmt_str_literal(buf: &mut Buf<'_>, literal: StrLiteral, indent: u16) {
}
fn fmt_binops<'a>(
buf: &mut Buf<'_>,
buf: &mut Buf,
lefts: &'a [(Loc<Expr<'a>>, Loc<BinOp>)],
loc_right_side: &'a Loc<Expr<'a>>,
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);
}
fn format_spaces(
buf: &mut Buf<'_>,
spaces: &[CommentOrNewline<'_>],
newlines: Newlines,
indent: u16,
) {
fn format_spaces(buf: &mut Buf, spaces: &[CommentOrNewline], newlines: Newlines, indent: u16) {
match newlines {
Newlines::Yes => {
fmt_spaces(buf, spaces.iter(), indent);
@ -739,7 +728,7 @@ fn is_when_patterns_multiline(when_branch: &WhenBranch) -> bool {
}
fn fmt_when<'a>(
buf: &mut Buf<'_>,
buf: &mut Buf,
loc_condition: &'a Loc<Expr<'a>>,
branches: &[&'a WhenBranch<'a>],
indent: u16,
@ -921,7 +910,7 @@ fn fmt_when<'a>(
}
fn fmt_dbg<'a>(
buf: &mut Buf<'_>,
buf: &mut Buf,
condition: &'a Loc<Expr<'a>>,
continuation: &'a Loc<Expr<'a>>,
is_multiline: bool,
@ -948,7 +937,7 @@ fn fmt_dbg<'a>(
}
fn fmt_expect<'a>(
buf: &mut Buf<'_>,
buf: &mut Buf,
condition: &'a Loc<Expr<'a>>,
continuation: &'a Loc<Expr<'a>>,
is_multiline: bool,
@ -975,7 +964,7 @@ fn fmt_expect<'a>(
}
fn fmt_if<'a>(
buf: &mut Buf<'_>,
buf: &mut Buf,
branches: &'a [(Loc<Expr<'a>>, Loc<Expr<'a>>)],
final_else: &'a Loc<Expr<'a>>,
is_multiline: bool,
@ -1124,7 +1113,7 @@ fn fmt_if<'a>(
}
fn fmt_closure<'a>(
buf: &mut Buf<'_>,
buf: &mut Buf,
loc_patterns: &'a [Loc<Pattern<'a>>],
loc_ret: &'a Loc<Expr<'a>>,
indent: u16,
@ -1225,7 +1214,7 @@ fn fmt_closure<'a>(
}
fn fmt_backpassing<'a>(
buf: &mut Buf<'_>,
buf: &mut Buf,
loc_patterns: &'a [Loc<Pattern<'a>>],
loc_body: &'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>(
buf: &mut Buf<'_>,
buf: &mut Buf,
update: Option<&'a Loc<Expr<'a>>>,
fields: Collection<'a, Loc<AssignedField<'a, Expr<'a>>>>,
indent: u16,
@ -1405,8 +1394,8 @@ fn fmt_record<'a>(
}
fn format_field_multiline<T>(
buf: &mut Buf<'_>,
field: &AssignedField<'_, T>,
buf: &mut Buf,
field: &AssignedField<T>,
indent: u16,
separator_prefix: &str,
) where

View file

@ -88,7 +88,7 @@ impl<V: Formattable> Formattable for Option<V> {
fn format_with_options(
&self,
buf: &mut Buf<'_>,
buf: &mut Buf,
parens: crate::annotation::Parens,
newlines: Newlines,
indent: u16,
@ -113,7 +113,7 @@ impl<'a> Formattable for ProvidesTo<'a> {
fn format_with_options(
&self,
buf: &mut Buf<'_>,
buf: &mut Buf,
_parens: crate::annotation::Parens,
_newlines: Newlines,
indent: u16,
@ -132,7 +132,7 @@ impl<'a> Formattable for PlatformRequires<'a> {
fn format_with_options(
&self,
buf: &mut Buf<'_>,
buf: &mut Buf,
_parens: crate::annotation::Parens,
_newlines: Newlines,
indent: u16,
@ -148,7 +148,7 @@ impl<'a, V: Formattable> Formattable for Spaces<'a, V> {
fn format_with_options(
&self,
buf: &mut Buf<'_>,
buf: &mut Buf,
parens: crate::annotation::Parens,
newlines: Newlines,
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()
}
fn format_with_options(
&self,
buf: &mut Buf<'_>,
parens: Parens,
newlines: Newlines,
indent: u16,
) {
fn format_with_options(&self, buf: &mut Buf, parens: Parens, newlines: Newlines, indent: u16) {
self.keyword
.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.push_str("interface");
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);
}
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.push_str("hosted");
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);
}
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.push_str("app");
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);
}
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.push_str("package");
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);
}
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.push_str("platform");
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);
}
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);
buf.push_str(" {");
@ -278,7 +272,7 @@ impl<'a> Formattable for TypedIdent<'a> {
fn format_with_options(
&self,
buf: &mut Buf<'_>,
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
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.push('"');
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(
&self,
buf: &mut Buf<'_>,
buf: &mut Buf,
parens: crate::annotation::Parens,
newlines: Newlines,
indent: u16,
@ -336,7 +330,7 @@ impl<'a, T: Formattable> Formattable for Spaced<'a, T> {
}
fn fmt_imports<'a>(
buf: &mut Buf<'_>,
buf: &mut Buf,
loc_entries: Collection<'a, Loc<Spaced<'a, ImportsEntry<'a>>>>,
indent: u16,
) {
@ -344,7 +338,7 @@ fn fmt_imports<'a>(
}
fn fmt_provides<'a>(
buf: &mut Buf<'_>,
buf: &mut Buf,
loc_exposed_names: Collection<'a, Loc<Spaced<'a, ExposedName<'a>>>>,
loc_provided_types: Option<Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>>,
indent: u16,
@ -356,7 +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 {
To::ExistingPackage(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>(
buf: &mut Buf<'_>,
buf: &mut Buf,
loc_entries: Collection<'_, Loc<Spaced<'_, N>>>,
indent: u16,
) {
@ -374,17 +368,17 @@ fn fmt_exposes<N: Formattable + Copy + core::fmt::Debug>(
}
pub trait FormatName {
fn format(&self, buf: &mut Buf<'_>);
fn format(&self, buf: &mut Buf);
}
impl<'a> FormatName for &'a str {
fn format(&self, buf: &mut Buf<'_>) {
fn format(&self, buf: &mut Buf) {
buf.push_str(self)
}
}
impl<'a> FormatName for ModuleName<'a> {
fn format(&self, buf: &mut Buf<'_>) {
fn format(&self, buf: &mut Buf) {
buf.push_str(self.as_str());
}
}
@ -396,7 +390,7 @@ impl<'a> Formattable for ModuleName<'a> {
fn format_with_options(
&self,
buf: &mut Buf<'_>,
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
_indent: u16,
@ -412,7 +406,7 @@ impl<'a> Formattable for ExposedName<'a> {
fn format_with_options(
&self,
buf: &mut Buf<'_>,
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
indent: u16,
@ -423,13 +417,13 @@ impl<'a> Formattable 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());
}
}
fn fmt_packages<'a>(
buf: &mut Buf<'_>,
buf: &mut Buf,
loc_entries: Collection<'a, Loc<Spaced<'a, PackageEntry<'a>>>>,
indent: u16,
) {
@ -443,7 +437,7 @@ impl<'a> Formattable for PackageEntry<'a> {
fn format_with_options(
&self,
buf: &mut Buf<'_>,
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
indent: u16,
@ -459,7 +453,7 @@ impl<'a> Formattable for ImportsEntry<'a> {
fn format_with_options(
&self,
buf: &mut Buf<'_>,
buf: &mut Buf,
_parens: Parens,
_newlines: Newlines,
indent: u16,
@ -467,14 +461,14 @@ impl<'a> Formattable for ImportsEntry<'a> {
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(':');
fmt_default_spaces(buf, entry.spaces_after_shorthand, 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::*;
buf.indent(indent);

View file

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

View file

@ -21,14 +21,14 @@ use crate::{Ast, Buf};
/// The number of spaces to indent.
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() {
buf.spaces(1);
} else {
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() {
buf.newline();
} 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,
// unless it's the very beginning of the buffer.
if !buf.is_empty() && !buf.ends_with_space() && !buf.ends_with_newline() {
@ -184,7 +184,7 @@ where
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,
// unless it's the very beginning of the buffer.
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");
}
#[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)]
fn imul_reg64_reg64_reg64(
buf: &mut Vec<'_, u8>,
@ -1038,28 +1048,6 @@ impl Assembler<AArch64GeneralReg, AArch64FloatReg> for AArch64Assembler {
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) {
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_error_macros::internal_error;
use roc_module::symbol::{Interns, ModuleId, Symbol};
use roc_mono::code_gen_help::CodeGenHelp;
use roc_mono::code_gen_help::{CallerProc, CodeGenHelp, HelperOp};
use roc_mono::ir::{
BranchInfo, JoinPointId, ListLiteralElement, Literal, Param, ProcLayout, SelfRecursive, Stmt,
BranchInfo, HigherOrderLowLevel, JoinPointId, ListLiteralElement, Literal, Param, ProcLayout,
SelfRecursive, Stmt,
};
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout,
};
use roc_mono::low_level::HigherOrder;
use roc_target::TargetInfo;
use std::marker::PhantomData;
@ -216,6 +218,13 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
fn call(buf: &mut Vec<'_, u8>, relocs: &mut Vec<'_, Relocation>, fn_name: String);
fn function_pointer(
buf: &mut Vec<'_, u8>,
relocs: &mut Vec<'_, Relocation>,
fn_name: String,
dst: GeneralReg,
);
/// Jumps by an offset of offset bytes unconditionally.
/// It should always generate the same number of bytes to enable replacement if offset changes.
/// It returns the base offset to calculate the jump from (generally the instruction after the jump).
@ -447,20 +456,6 @@ pub trait Assembler<GeneralReg: RegTrait, FloatReg: RegTrait>: Sized + Copy {
fn to_float_freg64_freg32(buf: &mut Vec<'_, u8>, dst: FloatReg, src: FloatReg);
fn lte_reg64_reg64_reg64(
buf: &mut Vec<'_, u8>,
dst: GeneralReg,
src1: GeneralReg,
src2: GeneralReg,
);
fn gte_reg64_reg64_reg64(
buf: &mut Vec<'_, u8>,
dst: GeneralReg,
src1: GeneralReg,
src2: GeneralReg,
);
fn set_if_overflow(buf: &mut Vec<'_, u8>, dst: GeneralReg);
fn ret(buf: &mut Vec<'_, u8>);
@ -489,6 +484,7 @@ pub struct Backend64Bit<
interns: &'r mut Interns,
helper_proc_gen: CodeGenHelp<'a>,
helper_proc_symbols: Vec<'a, (Symbol, ProcLayout<'a>)>,
caller_procs: Vec<'a, CallerProc<'a>>,
buf: Vec<'a, u8>,
relocs: Vec<'a, Relocation>,
proc_name: Option<String>,
@ -526,6 +522,7 @@ pub fn new_backend_64bit<
layout_interner,
helper_proc_gen: CodeGenHelp::new(env.arena, target_info, env.module_id),
helper_proc_symbols: bumpalo::vec![in env.arena],
caller_procs: bumpalo::vec![in env.arena],
proc_name: None,
is_self_recursive: None,
buf: bumpalo::vec![in env.arena],
@ -567,6 +564,9 @@ impl<
fn interns(&self) -> &Interns {
self.interns
}
fn interns_mut(&mut self) -> &mut Interns {
self.interns
}
fn interner(&self) -> &STLayoutInterner<'a> {
self.layout_interner
}
@ -577,12 +577,14 @@ impl<
&mut STLayoutInterner<'a>,
&mut Interns,
&mut CodeGenHelp<'a>,
&mut Vec<'a, CallerProc<'a>>,
) {
(
self.env.module_id,
self.layout_interner,
self.interns,
&mut self.helper_proc_gen,
&mut self.caller_procs,
)
}
fn helper_proc_gen_mut(&mut self) -> &mut CodeGenHelp<'a> {
@ -738,6 +740,12 @@ impl<
(out.into_bump_slice(), offset)
}
fn build_fn_pointer(&mut self, dst: &Symbol, fn_name: String) {
let reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
ASM::function_pointer(&mut self.buf, &mut self.relocs, fn_name, reg)
}
fn build_fn_call(
&mut self,
dst: &Symbol,
@ -746,11 +754,6 @@ impl<
arg_layouts: &[InLayout<'a>],
ret_layout: &InLayout<'a>,
) {
if let Some(SelfRecursive::SelfRecursive(id)) = self.is_self_recursive {
if &fn_name == self.proc_name.as_ref().unwrap() && self.join_map.contains_key(&id) {
return self.build_jump(&id, args, arg_layouts, ret_layout);
}
}
// Save used caller saved regs.
self.storage_manager
.push_used_caller_saved_regs_to_stack(&mut self.buf);
@ -1221,6 +1224,9 @@ impl<
.load_to_general_reg(&mut self.buf, src2);
ASM::eq_reg64_reg64_reg64(&mut self.buf, width, dst_reg, src1_reg, src2_reg);
}
Layout::F32 => todo!("NumEq: layout, {:?}", self.layout_interner.dbg(Layout::F32)),
Layout::F64 => todo!("NumEq: layout, {:?}", self.layout_interner.dbg(Layout::F64)),
Layout::DEC => todo!("NumEq: layout, {:?}", self.layout_interner.dbg(Layout::DEC)),
Layout::STR => {
// use a zig call
self.build_fn_call(
@ -1241,7 +1247,33 @@ impl<
let dst_reg = self.storage_manager.load_to_general_reg(&mut self.buf, dst);
ASM::eq_reg64_reg64_reg64(&mut self.buf, width, dst_reg, dst_reg, tmp_reg);
}
x => todo!("NumEq: layout, {:?}", x),
other => {
let ident_ids = self
.interns
.all_ident_ids
.get_mut(&self.env.module_id)
.unwrap();
// generate a proc
let (eq_symbol, eq_linker_data) = self.helper_proc_gen.gen_refcount_proc(
ident_ids,
self.layout_interner,
other,
HelperOp::Eq,
);
let fn_name = self.function_symbol_to_string(
eq_symbol,
[other, other].into_iter(),
None,
Layout::U8,
);
self.helper_proc_symbols.extend(eq_linker_data);
self.build_fn_call(dst, fn_name, &[*src1, *src2], &[other, other], &Layout::U8)
}
}
}
@ -1304,126 +1336,6 @@ impl<
}
}
fn build_num_lt(
&mut self,
dst: &Symbol,
src1: &Symbol,
src2: &Symbol,
arg_layout: &InLayout<'a>,
) {
match self.layout_interner.get(*arg_layout) {
Layout::Builtin(Builtin::Int(IntWidth::I64)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, src1);
let src2_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, src2);
ASM::signed_compare_reg64(
&mut self.buf,
RegisterWidth::W64,
CompareOperation::LessThan,
dst_reg,
src1_reg,
src2_reg,
);
}
Layout::Builtin(Builtin::Int(IntWidth::U64)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, src1);
let src2_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, src2);
ASM::unsigned_compare_reg64(
&mut self.buf,
RegisterWidth::W64,
CompareOperation::LessThan,
dst_reg,
src1_reg,
src2_reg,
);
}
Layout::Builtin(Builtin::Float(width)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
ASM::cmp_freg_freg_reg64(
&mut self.buf,
dst_reg,
src1_reg,
src2_reg,
width,
CompareOperation::LessThan,
);
}
x => todo!("NumLt: layout, {:?}", x),
}
}
fn build_num_gt(
&mut self,
dst: &Symbol,
src1: &Symbol,
src2: &Symbol,
arg_layout: &InLayout<'a>,
) {
match self.layout_interner.get(*arg_layout) {
Layout::Builtin(Builtin::Int(IntWidth::I64)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, src1);
let src2_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, src2);
ASM::signed_compare_reg64(
&mut self.buf,
RegisterWidth::W64,
CompareOperation::GreaterThan,
dst_reg,
src1_reg,
src2_reg,
);
}
Layout::Builtin(Builtin::Int(IntWidth::U64)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, src1);
let src2_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, src2);
ASM::unsigned_compare_reg64(
&mut self.buf,
RegisterWidth::W64,
CompareOperation::GreaterThan,
dst_reg,
src1_reg,
src2_reg,
);
}
Layout::Builtin(Builtin::Float(width)) => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
ASM::cmp_freg_freg_reg64(
&mut self.buf,
dst_reg,
src1_reg,
src2_reg,
width,
CompareOperation::GreaterThan,
);
}
x => todo!("NumGt: layout, {:?}", x),
}
}
fn build_num_to_frac(
&mut self,
dst: &Symbol,
@ -1482,6 +1394,26 @@ impl<
}
}
fn build_num_lt(
&mut self,
dst: &Symbol,
src1: &Symbol,
src2: &Symbol,
arg_layout: &InLayout<'a>,
) {
self.compare(CompareOperation::LessThan, dst, src1, src2, arg_layout)
}
fn build_num_gt(
&mut self,
dst: &Symbol,
src1: &Symbol,
src2: &Symbol,
arg_layout: &InLayout<'a>,
) {
self.compare(CompareOperation::GreaterThan, dst, src1, src2, arg_layout)
}
fn build_num_lte(
&mut self,
dst: &Symbol,
@ -1489,39 +1421,13 @@ impl<
src2: &Symbol,
arg_layout: &InLayout<'a>,
) {
match *arg_layout {
single_register_int_builtins!() => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, src1);
let src2_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, src2);
ASM::lte_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
}
Layout::F64 | Layout::F32 => {
let width = if *arg_layout == Layout::F64 {
FloatWidth::F64
} else {
FloatWidth::F32
};
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
ASM::cmp_freg_freg_reg64(
&mut self.buf,
dst_reg,
src1_reg,
src2_reg,
width,
self.compare(
CompareOperation::LessThanOrEqual,
);
}
x => todo!("NumLte: layout, {:?}", x),
}
dst,
src1,
src2,
arg_layout,
)
}
fn build_num_gte(
@ -1531,38 +1437,178 @@ impl<
src2: &Symbol,
arg_layout: &InLayout<'a>,
) {
match *arg_layout {
single_register_int_builtins!() => {
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, src1);
let src2_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, src2);
ASM::gte_reg64_reg64_reg64(&mut self.buf, dst_reg, src1_reg, src2_reg);
}
Layout::F64 | Layout::F32 => {
let width = if *arg_layout == Layout::F64 {
FloatWidth::F64
} else {
FloatWidth::F32
};
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,
self.compare(
CompareOperation::GreaterThanOrEqual,
);
dst,
src1,
src2,
arg_layout,
)
}
x => todo!("NumGte: layout, {:?}", x),
fn build_higher_order_lowlevel(
&mut self,
dst: &Symbol,
higher_order: &HigherOrderLowLevel<'a>,
ret_layout: InLayout<'a>,
) {
let ident_ids = self
.interns
.all_ident_ids
.get_mut(&self.env.module_id)
.unwrap();
let (inc_n_data_symbol, inc_n_data_linker_data) = self.helper_proc_gen.gen_refcount_proc(
ident_ids,
self.layout_interner,
Layout::UNIT,
HelperOp::Inc,
);
let caller_proc = CallerProc::new(
self.env.arena,
self.env.module_id,
ident_ids,
self.layout_interner,
&higher_order.passed_function,
higher_order.closure_env_layout,
);
match higher_order.op {
HigherOrder::ListMap { xs } => {
let old_element_layout = higher_order.passed_function.argument_layouts[0];
let new_element_layout = higher_order.passed_function.return_layout;
let input_list_layout = Layout::Builtin(Builtin::List(old_element_layout));
let input_list_in_layout = self.layout_interner.insert(input_list_layout);
let caller = self.debug_symbol("caller");
let data = self.debug_symbol("data");
let alignment = self.debug_symbol("alignment");
let old_element_width = self.debug_symbol("old_element_width");
let new_element_width = self.debug_symbol("new_element_width");
self.load_layout_alignment(new_element_layout, alignment);
self.load_layout_stack_size(old_element_layout, old_element_width);
self.load_layout_stack_size(new_element_layout, new_element_width);
self.helper_proc_symbols.extend(inc_n_data_linker_data);
self.helper_proc_symbols
.extend([(caller_proc.proc_symbol, caller_proc.proc_layout)]);
let inc_n_data_string = self.function_symbol_to_string(
inc_n_data_symbol,
std::iter::empty(),
None,
Layout::UNIT,
);
let caller_string = self.function_symbol_to_string(
caller_proc.proc_symbol,
std::iter::empty(),
None,
Layout::UNIT,
);
self.caller_procs.push(caller_proc);
let inc_n_data = Symbol::DEV_TMP5;
self.build_fn_pointer(&inc_n_data, inc_n_data_string);
self.build_fn_pointer(&caller, caller_string);
if let Some(_closure_data_layout) = higher_order.closure_env_layout {
let data_symbol = higher_order.passed_function.captured_environment;
self.storage_manager
.ensure_symbol_on_stack(&mut self.buf, &data_symbol);
let (new_elem_offset, _) =
self.storage_manager.stack_offset_and_size(&data_symbol);
// Load address of output element into register.
let reg = self.storage_manager.claim_general_reg(&mut self.buf, &data);
ASM::add_reg64_reg64_imm32(
&mut self.buf,
reg,
CC::BASE_PTR_REG,
new_elem_offset,
);
} else {
// use a null pointer
self.load_literal(&data, &Layout::U64, &Literal::Int(0u128.to_be_bytes()));
}
self.load_literal(
&Symbol::DEV_TMP3,
&Layout::BOOL,
&Literal::Bool(higher_order.passed_function.owns_captured_environment),
);
// list: RocList,
// caller: Caller1,
// data: Opaque,
// inc_n_data: IncN,
// data_is_owned: bool,
// alignment: u32,
// old_element_width: usize,
// new_element_width: usize,
let arguments = [
xs,
caller,
data,
inc_n_data,
Symbol::DEV_TMP3,
alignment,
old_element_width,
new_element_width,
];
let ptr = Layout::U64;
let usize_ = Layout::U64;
let layouts = [
input_list_in_layout,
ptr,
ptr,
ptr,
Layout::BOOL,
Layout::U32,
usize_,
usize_,
];
// Setup the return location.
let base_offset = self
.storage_manager
.claim_stack_area(dst, self.layout_interner.stack_size(ret_layout));
self.build_fn_call(
&Symbol::DEV_TMP4,
bitcode::LIST_MAP.to_string(),
&arguments,
&layouts,
&ret_layout,
);
self.free_symbol(&Symbol::DEV_TMP3);
self.free_symbol(&Symbol::DEV_TMP5);
// Return list value from fn call
self.storage_manager.copy_symbol_to_stack_offset(
self.layout_interner,
&mut self.buf,
base_offset,
&Symbol::DEV_TMP4,
&ret_layout,
);
self.free_symbol(&Symbol::DEV_TMP4);
}
HigherOrder::ListMap2 { .. } => todo!(),
HigherOrder::ListMap3 { .. } => todo!(),
HigherOrder::ListMap4 { .. } => todo!(),
HigherOrder::ListSortWith { .. } => todo!(),
}
}
@ -1589,8 +1635,7 @@ impl<
.storage_manager
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
let lowlevel_args = bumpalo::vec![
in self.env.arena;
let lowlevel_args = [
capacity,
// alignment
Symbol::DEV_TMP,
@ -1727,13 +1772,12 @@ impl<
.storage_manager
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
let lowlevel_args = bumpalo::vec![
in self.env.arena;
let lowlevel_args = [
list,
// element
Symbol::DEV_TMP,
// element_width
Symbol::DEV_TMP2
Symbol::DEV_TMP2,
];
let lowlevel_arg_layouts = [list_layout, Layout::U64, Layout::U64];
@ -2004,8 +2048,7 @@ impl<
.storage_manager
.claim_stack_area(dst, self.layout_interner.stack_size(*ret_layout));
let lowlevel_args = bumpalo::vec![
in self.env.arena;
let lowlevel_args = [
list,
// alignment
Symbol::DEV_TMP,
@ -2195,27 +2238,16 @@ impl<
}
}
fn expr_box(&mut self, sym: Symbol, value: Symbol, element_layout: InLayout<'a>) {
let element_width_symbol = Symbol::DEV_TMP;
self.load_layout_stack_size(element_layout, element_width_symbol);
// Load allocation alignment (u32)
let element_alignment_symbol = Symbol::DEV_TMP2;
self.load_layout_alignment(Layout::U32, element_alignment_symbol);
self.allocate_with_refcount(
Symbol::DEV_TMP3,
element_width_symbol,
element_alignment_symbol,
);
self.free_symbol(&element_width_symbol);
self.free_symbol(&element_alignment_symbol);
// Fill pointer with the value
fn build_ptr_write(
&mut self,
sym: Symbol,
ptr: Symbol,
value: Symbol,
element_layout: InLayout<'a>,
) {
let ptr_reg = self
.storage_manager
.load_to_general_reg(&mut self.buf, &Symbol::DEV_TMP3);
.load_to_general_reg(&mut self.buf, &ptr);
let element_width = self.layout_interner.stack_size(element_layout) as u64;
let element_offset = 0;
@ -2237,6 +2269,26 @@ impl<
// box is just a pointer on the stack
let base_offset = self.storage_manager.claim_stack_area(&sym, 8);
ASM::mov_base32_reg64(&mut self.buf, base_offset, ptr_reg);
}
fn expr_box(&mut self, sym: Symbol, value: Symbol, element_layout: InLayout<'a>) {
let element_width_symbol = Symbol::DEV_TMP;
self.load_layout_stack_size(element_layout, element_width_symbol);
// Load allocation alignment (u32)
let element_alignment_symbol = Symbol::DEV_TMP2;
self.load_layout_alignment(Layout::U32, element_alignment_symbol);
self.allocate_with_refcount(
Symbol::DEV_TMP3,
element_width_symbol,
element_alignment_symbol,
);
self.free_symbol(&element_width_symbol);
self.free_symbol(&element_alignment_symbol);
self.build_ptr_write(sym, Symbol::DEV_TMP3, value, element_layout);
self.free_symbol(&Symbol::DEV_TMP3);
}
@ -2662,6 +2714,28 @@ impl<
FloatWidth::F64 => ASM::sqrt_freg64_freg64(buf, dst_reg, src_reg),
}
}
fn build_num_int_cast(
&mut self,
dst: &Symbol,
src: &Symbol,
source: IntWidth,
target: IntWidth,
) {
let buf = &mut self.buf;
let dst_reg = self.storage_manager.claim_general_reg(buf, dst);
let src_reg = self.storage_manager.load_to_general_reg(buf, src);
if source.stack_size() == target.stack_size() {
match source.stack_size() {
8 => ASM::mov_reg64_reg64(buf, dst_reg, src_reg),
_ => todo!("int cast from {source:?} to {target:?}"),
}
} else {
todo!("int cast from {source:?} to {target:?}");
}
}
}
/// This impl block is for ir related instructions that need backend specific information.
@ -2675,6 +2749,61 @@ impl<
CC: CallConv<GeneralReg, FloatReg, ASM>,
> Backend64Bit<'a, 'r, GeneralReg, FloatReg, ASM, CC>
{
fn compare(
&mut self,
op: CompareOperation,
dst: &Symbol,
src1: &Symbol,
src2: &Symbol,
arg_layout: &InLayout<'a>,
) {
match *arg_layout {
single_register_integers!() => {
let buf = &mut self.buf;
let dst = self.storage_manager.claim_general_reg(buf, dst);
let src1 = self.storage_manager.load_to_general_reg(buf, src1);
let src2 = self.storage_manager.load_to_general_reg(buf, src2);
let int_width = arg_layout.try_int_width().unwrap();
let register_width = match int_width.stack_size() {
8 => RegisterWidth::W64,
4 => RegisterWidth::W32,
2 => RegisterWidth::W16,
1 => RegisterWidth::W8,
_ => unreachable!(),
};
if int_width.is_signed() {
ASM::signed_compare_reg64(buf, register_width, op, dst, src1, src2)
} else {
ASM::unsigned_compare_reg64(buf, register_width, op, dst, src1, src2)
}
}
Layout::F32 | Layout::F64 => {
let float_width = match *arg_layout {
Layout::F32 => FloatWidth::F32,
Layout::F64 => FloatWidth::F64,
_ => unreachable!(),
};
let dst_reg = self.storage_manager.claim_general_reg(&mut self.buf, dst);
let src1_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src1);
let src2_reg = self.storage_manager.load_to_float_reg(&mut self.buf, src2);
ASM::cmp_freg_freg_reg64(
&mut self.buf,
dst_reg,
src1_reg,
src2_reg,
float_width,
op,
);
}
x => todo!("NumLt: layout, {:?}", x),
}
}
fn allocate_with_refcount(
&mut self,
dst: Symbol,
@ -2709,6 +2838,62 @@ impl<
ASM::mov_base32_reg64(buf, base_offset + 16, tmp_reg);
}
fn unbox_to_stack(
buf: &mut Vec<'a, u8>,
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
dst: Symbol,
stack_size: u32,
ptr_reg: GeneralReg,
tmp_reg: GeneralReg,
) {
let mut copied = 0;
let size = stack_size as i32;
let base_offset = storage_manager.claim_stack_area(&dst, stack_size);
if size - copied >= 8 {
for _ in (0..(size - copied)).step_by(8) {
ASM::mov_reg64_mem64_offset32(buf, tmp_reg, ptr_reg, copied);
ASM::mov_base32_reg64(buf, base_offset, tmp_reg);
copied += 8;
}
}
if size - copied > 0 {
panic!("value only partially copied");
}
/*
if size - copied >= 4 {
for _ in (0..(size - copied)).step_by(4) {
ASM::mov_reg32_base32(buf, reg, from_offset + copied);
ASM::mov_base32_reg32(buf, to_offset + copied, reg);
copied += 4;
}
}
if size - copied >= 2 {
for _ in (0..(size - copied)).step_by(2) {
ASM::mov_reg16_base32(buf, reg, from_offset + copied);
ASM::mov_base32_reg16(buf, to_offset + copied, reg);
copied += 2;
}
}
if size - copied >= 1 {
for _ in (0..(size - copied)).step_by(1) {
ASM::mov_reg8_base32(buf, reg, from_offset + copied);
ASM::mov_base32_reg8(buf, to_offset + copied, reg);
copied += 1;
}
}
*/
}
fn ptr_read(
buf: &mut Vec<'a, u8>,
storage_manager: &mut StorageManager<'a, 'r, GeneralReg, FloatReg, ASM, CC>,
@ -2766,6 +2951,15 @@ impl<
ASM::mov_reg64_mem64_offset32(buf, dst_reg, ptr_reg, 0);
}
Layout::Struct { .. } => {
// put it on the stack
let stack_size = layout_interner.stack_size(element_in_layout);
storage_manager.with_tmp_general_reg(buf, |storage_manager, buf, tmp_reg| {
Self::unbox_to_stack(buf, storage_manager, dst, stack_size, ptr_reg, tmp_reg);
});
}
_ => todo!("unboxing of {:?}", layout_interner.dbg(element_in_layout)),
}
}

View file

@ -654,7 +654,15 @@ impl<
}
let base_offset = self.claim_stack_area(sym, struct_size);
if let Layout::Struct { field_layouts, .. } = layout_interner.get(*layout) {
let mut in_layout = *layout;
let layout = loop {
match layout_interner.get(in_layout) {
Layout::LambdaSet(inner) => in_layout = inner.runtime_representation(),
other => break other,
}
};
if let Layout::Struct { field_layouts, .. } = layout {
let mut current_offset = base_offset;
for (field, field_layout) in fields.iter().zip(field_layouts.iter()) {
self.copy_symbol_to_stack_offset(
@ -670,7 +678,13 @@ impl<
} else {
// This is a single element struct. Just copy the single field to the stack.
debug_assert_eq!(fields.len(), 1);
self.copy_symbol_to_stack_offset(layout_interner, buf, base_offset, &fields[0], layout);
self.copy_symbol_to_stack_offset(
layout_interner,
buf,
base_offset,
&fields[0],
&in_layout,
);
}
}

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)]
fn imul_reg64_reg64_reg64(
buf: &mut Vec<'_, u8>,
@ -1607,17 +1622,13 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
src1: X86_64GeneralReg,
src2: X86_64GeneralReg,
) {
cmp_reg64_reg64(buf, register_width, src1, src2);
match operation {
CompareOperation::LessThan => {
cmp_reg64_reg64(buf, register_width, src1, src2);
setl_reg64(buf, dst);
}
CompareOperation::LessThanOrEqual => todo!(),
CompareOperation::GreaterThan => {
cmp_reg64_reg64(buf, register_width, src1, src2);
setg_reg64(buf, dst);
}
CompareOperation::GreaterThanOrEqual => todo!(),
CompareOperation::LessThan => setl_reg64(buf, dst),
CompareOperation::LessThanOrEqual => setle_reg64(buf, dst),
CompareOperation::GreaterThan => setg_reg64(buf, dst),
CompareOperation::GreaterThanOrEqual => setge_reg64(buf, dst),
}
}
@ -1629,18 +1640,13 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
src1: X86_64GeneralReg,
src2: X86_64GeneralReg,
) {
match operation {
CompareOperation::LessThan => {
cmp_reg64_reg64(buf, register_width, src1, src2);
setb_reg64(buf, dst);
}
CompareOperation::LessThanOrEqual => todo!(),
CompareOperation::GreaterThan => {
cmp_reg64_reg64(buf, register_width, src1, src2);
seta_reg64(buf, dst);
}
CompareOperation::GreaterThanOrEqual => todo!(),
match operation {
CompareOperation::LessThan => setb_reg64(buf, dst),
CompareOperation::LessThanOrEqual => setbe_reg64(buf, dst),
CompareOperation::GreaterThan => seta_reg64(buf, dst),
CompareOperation::GreaterThanOrEqual => setae_reg64(buf, dst),
}
}
@ -1691,28 +1697,6 @@ impl Assembler<X86_64GeneralReg, X86_64FloatReg> for X86_64Assembler {
cvtsi2sd_freg64_reg64(buf, dst, src);
}
#[inline(always)]
fn lte_reg64_reg64_reg64(
buf: &mut Vec<'_, u8>,
dst: X86_64GeneralReg,
src1: X86_64GeneralReg,
src2: X86_64GeneralReg,
) {
cmp_reg64_reg64(buf, RegisterWidth::W64, src1, src2);
setle_reg64(buf, dst);
}
#[inline(always)]
fn gte_reg64_reg64_reg64(
buf: &mut Vec<'_, u8>,
dst: X86_64GeneralReg,
src1: X86_64GeneralReg,
src2: X86_64GeneralReg,
) {
cmp_reg64_reg64(buf, RegisterWidth::W64, src1, src2);
setge_reg64(buf, dst);
}
#[inline(always)]
fn ret(buf: &mut Vec<'_, u8>) {
ret(buf);
@ -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>,
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),
dst: 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.
/// This will not generate anything if dst and src are the same.
#[inline(always)]
@ -2959,7 +2962,13 @@ fn setae_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
set_reg64_help(0x93, buf, reg);
}
/// `SETLE r/m64` -> Set byte if less or equal (ZF=1 or SF≠ OF).
/// `SETBE r/m64` -> Set byte if below or equal (CF=1 or ZF=1).
#[inline(always)]
fn setbe_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
set_reg64_help(0x96, buf, reg);
}
/// `SETLE r/m64` -> Set byte if less or equal (ZF=1 or SF ≠ OF).
#[inline(always)]
fn setle_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
set_reg64_help(0x9e, buf, reg);
@ -3413,6 +3422,15 @@ mod tests {
);
}
#[test]
fn test_lea_reg64() {
disassembler_test!(
lea_reg64,
|reg| format!("lea {}, [rip]", reg),
ALL_GENERAL_REGS
);
}
#[test]
fn test_mov_reg64_reg64() {
disassembler_test!(
@ -3764,8 +3782,8 @@ mod tests {
cmp_reg64_reg64,
|_, dst: X86_64GeneralReg, src: X86_64GeneralReg| format!(
"cmp {}, {}",
dbg!(dst.low_16bits_string()),
dbg!(src.low_16bits_string())
dst.low_16bits_string(),
src.low_16bits_string()
),
[RegisterWidth::W16],
ALL_GENERAL_REGS,
@ -3776,8 +3794,8 @@ mod tests {
cmp_reg64_reg64,
|_, dst: X86_64GeneralReg, src: X86_64GeneralReg| format!(
"cmp {}, {}",
dbg!(dst.low_32bits_string()),
dbg!(src.low_32bits_string())
dst.low_32bits_string(),
src.low_32bits_string()
),
[RegisterWidth::W32],
ALL_GENERAL_REGS,

View file

@ -12,10 +12,10 @@ use roc_error_macros::internal_error;
use roc_module::ident::ModuleName;
use roc_module::low_level::{LowLevel, LowLevelWrapperType};
use roc_module::symbol::{Interns, ModuleId, Symbol};
use roc_mono::code_gen_help::CodeGenHelp;
use roc_mono::code_gen_help::{CallerProc, CodeGenHelp};
use roc_mono::ir::{
BranchInfo, CallType, Expr, JoinPointId, ListLiteralElement, Literal, Param, Proc, ProcLayout,
SelfRecursive, Stmt,
BranchInfo, CallType, Expr, HigherOrderLowLevel, JoinPointId, ListLiteralElement, Literal,
Param, Proc, ProcLayout, SelfRecursive, Stmt,
};
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, TagIdIntType,
@ -65,8 +65,21 @@ pub enum Relocation {
trait Backend<'a> {
fn env(&self) -> &Env<'a>;
fn interns(&self) -> &Interns;
fn interns_mut(&mut self) -> &mut Interns;
fn interner(&self) -> &STLayoutInterner<'a>;
fn debug_symbol(&mut self, name: &str) -> Symbol {
let module_id = self.env().module_id;
let ident_ids = self
.interns_mut()
.all_ident_ids
.get_mut(&module_id)
.unwrap();
let ident_id = ident_ids.add_str(name);
Symbol::new(self.env().module_id, ident_id)
}
// This method is suboptimal, but it seems to be the only way to make rust understand
// that all of these values can be mutable at the same time. By returning them together,
// rust understands that they are part of a single use of mutable self.
@ -77,6 +90,7 @@ trait Backend<'a> {
&mut STLayoutInterner<'a>,
&mut Interns,
&mut CodeGenHelp<'a>,
&mut Vec<'a, CallerProc<'a>>,
);
fn function_symbol_to_string<'b, I>(
@ -201,7 +215,7 @@ trait Backend<'a> {
// If this layout requires a new RC proc, we get enough info to create a linker symbol
// for it. Here we don't create linker symbols at this time, but in Wasm backend, we do.
let (rc_stmt, new_specializations) = {
let (module_id, layout_interner, interns, rc_proc_gen) =
let (module_id, layout_interner, interns, rc_proc_gen, _) =
self.module_interns_helpers_mut();
let ident_ids = interns.all_ident_ids.get_mut(&module_id).unwrap();
@ -329,7 +343,7 @@ trait Backend<'a> {
arg_layouts,
ret_layout,
);
} else if sym.is_builtin() {
} else if func_sym.name().is_builtin() {
// These builtins can be built through `build_fn_call` as well, but the
// implementation in `build_builtin` inlines some of the symbols.
return self.build_builtin(
@ -373,6 +387,9 @@ trait Backend<'a> {
layout,
)
}
CallType::HigherOrder(higher_order) => {
self.build_higher_order_lowlevel(sym, higher_order, *layout)
}
x => todo!("the call type, {:?}", x),
}
}
@ -486,6 +503,22 @@ trait Backend<'a> {
);
self.build_num_add(sym, &args[0], &args[1], ret_layout)
}
LowLevel::NumAddWrap => {
debug_assert_eq!(
2,
args.len(),
"NumAdd: expected to have exactly two argument"
);
debug_assert_eq!(
arg_layouts[0], arg_layouts[1],
"NumAdd: expected all arguments of to have the same layout"
);
debug_assert_eq!(
arg_layouts[0], *ret_layout,
"NumAdd: expected to have the same argument and return layout"
);
self.build_num_add(sym, &args[0], &args[1], ret_layout)
}
LowLevel::NumAddChecked => {
self.build_num_add_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout)
}
@ -1070,6 +1103,14 @@ trait Backend<'a> {
);
self.build_ptr_cast(sym, &args[0])
}
LowLevel::PtrWrite => {
let element_layout = match self.interner().get(*ret_layout) {
Layout::Boxed(boxed) => boxed,
_ => unreachable!(),
};
self.build_ptr_write(*sym, args[0], args[1], element_layout);
}
LowLevel::RefCountDec => self.build_fn_call(
sym,
bitcode::UTILS_DECREF.to_string(),
@ -1084,6 +1125,34 @@ trait Backend<'a> {
arg_layouts,
ret_layout,
),
LowLevel::NumToStr => {
let arg_layout = arg_layouts[0];
let intrinsic = match self.interner().get(arg_layout) {
Layout::Builtin(Builtin::Int(width)) => &bitcode::STR_FROM_INT[width],
Layout::Builtin(Builtin::Float(width)) => &bitcode::STR_FROM_FLOAT[width],
Layout::Builtin(Builtin::Decimal) => bitcode::DEC_TO_STR,
x => internal_error!("NumToStr is not defined for {:?}", x),
};
self.build_fn_call(sym, intrinsic.to_string(), args, arg_layouts, ret_layout)
}
LowLevel::StrIsEmpty => {
let intrinsic = bitcode::STR_IS_EMPTY.to_string();
self.build_fn_call(sym, intrinsic, args, arg_layouts, ret_layout);
}
LowLevel::NumIntCast => {
let source_width = match self.interner().get(arg_layouts[0]) {
Layout::Builtin(Builtin::Int(width)) => width,
_ => unreachable!(),
};
let target_width = match self.interner().get(*ret_layout) {
Layout::Builtin(Builtin::Int(width)) => width,
_ => unreachable!(),
};
self.build_num_int_cast(sym, &args[0], source_width, target_width)
}
x => todo!("low level, {:?}", x),
}
}
@ -1133,16 +1202,24 @@ trait Backend<'a> {
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
}
Symbol::BOOL_TRUE => {
let bool_layout = Layout::BOOL;
self.load_literal(&Symbol::DEV_TMP, &bool_layout, &Literal::Bool(true));
self.return_symbol(&Symbol::DEV_TMP, &bool_layout);
self.free_symbol(&Symbol::DEV_TMP)
const LITERAL: &Literal<'static> = &Literal::Bool(true);
const BOOL_LAYOUT: &InLayout<'static> = &Layout::BOOL;
if self.env().lazy_literals {
self.literal_map().insert(*sym, (LITERAL, BOOL_LAYOUT));
} else {
self.load_literal(sym, BOOL_LAYOUT, LITERAL);
}
}
Symbol::BOOL_FALSE => {
let bool_layout = Layout::BOOL;
self.load_literal(&Symbol::DEV_TMP, &bool_layout, &Literal::Bool(false));
self.return_symbol(&Symbol::DEV_TMP, &bool_layout);
self.free_symbol(&Symbol::DEV_TMP)
const LITERAL: &Literal<'static> = &Literal::Bool(false);
const BOOL_LAYOUT: &InLayout<'static> = &Layout::BOOL;
if self.env().lazy_literals {
self.literal_map().insert(*sym, (LITERAL, BOOL_LAYOUT));
} else {
self.load_literal(sym, BOOL_LAYOUT, LITERAL);
}
}
Symbol::STR_IS_VALID_SCALAR => {
// just call the function
@ -1184,9 +1261,20 @@ trait Backend<'a> {
ret_layout: &InLayout<'a>,
);
fn build_fn_pointer(&mut self, dst: &Symbol, fn_name: String);
/// Move a returned value into `dst`
fn move_return_value(&mut self, dst: &Symbol, ret_layout: &InLayout<'a>);
/// build_num_abs stores the absolute value of src into dst.
fn build_num_int_cast(
&mut self,
dst: &Symbol,
src: &Symbol,
source: IntWidth,
target: IntWidth,
);
/// build_num_abs stores the absolute value of src into dst.
fn build_num_abs(&mut self, dst: &Symbol, src: &Symbol, layout: &InLayout<'a>);
@ -1348,6 +1436,14 @@ trait Backend<'a> {
/// build_list_len returns the length of a list.
fn build_list_len(&mut self, dst: &Symbol, list: &Symbol);
/// generate a call to a higher-order lowlevel
fn build_higher_order_lowlevel(
&mut self,
dst: &Symbol,
holl: &HigherOrderLowLevel<'a>,
ret_layout: InLayout<'a>,
);
/// build_list_with_capacity creates and returns a list with the given capacity.
fn build_list_with_capacity(
&mut self,
@ -1416,6 +1512,14 @@ trait Backend<'a> {
/// build_refcount_getptr loads the pointer to the reference count of src into dst.
fn build_ptr_cast(&mut self, dst: &Symbol, src: &Symbol);
fn build_ptr_write(
&mut self,
sym: Symbol,
ptr: Symbol,
value: Symbol,
element_layout: InLayout<'a>,
);
/// literal_map gets the map from symbol to literal and layout, used for lazy loading and literal folding.
fn literal_map(&mut self) -> &mut MutMap<Symbol, (*const Literal<'a>, *const InLayout<'a>)>;

View file

@ -246,10 +246,16 @@ fn build_object<'a, B: Backend<'a>>(
// Generate IR for specialized helper procs (refcounting & equality)
let helper_procs = {
let (module_id, _interner, interns, helper_proc_gen) = backend.module_interns_helpers_mut();
let (module_id, _interner, interns, helper_proc_gen, caller_procs) =
backend.module_interns_helpers_mut();
let mut owned_caller_procs = bumpalo::collections::Vec::new_in(arena);
std::mem::swap(caller_procs, &mut owned_caller_procs);
let ident_ids = interns.all_ident_ids.get_mut(&module_id).unwrap();
let helper_procs = helper_proc_gen.take_procs();
let mut helper_procs = helper_proc_gen.take_procs();
helper_procs.extend(owned_caller_procs.into_iter().map(|cp| cp.proc));
module_id.register_debug_idents(ident_ids);
helper_procs

View file

@ -24,8 +24,8 @@ use roc_mono::layout::{
use super::build::{create_entry_block_alloca, BuilderExt};
use super::convert::zig_list_type;
pub fn call_bitcode_fn<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn call_bitcode_fn<'ctx>(
env: &Env<'_, 'ctx, '_>,
args: &[BasicValueEnum<'ctx>],
fn_name: &str,
) -> BasicValueEnum<'ctx> {
@ -40,8 +40,8 @@ pub fn call_bitcode_fn<'a, 'ctx, 'env>(
})
}
pub fn call_void_bitcode_fn<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn call_void_bitcode_fn<'ctx>(
env: &Env<'_, 'ctx, '_>,
args: &[BasicValueEnum<'ctx>],
fn_name: &str,
) -> 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))
}
fn call_bitcode_fn_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn call_bitcode_fn_help<'ctx>(
env: &Env<'_, 'ctx, '_>,
args: &[BasicValueEnum<'ctx>],
fn_name: &str,
) -> CallSiteValue<'ctx> {
@ -165,8 +165,8 @@ const ARGUMENT_SYMBOLS: [Symbol; 8] = [
Symbol::ARG_8,
];
pub(crate) fn build_transform_caller<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn build_transform_caller<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
function: FunctionValue<'ctx>,
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>(
env: &Env<'a, 'ctx, 'env>,
fn build_transform_caller_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>,
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
pub fn build_inc_n_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_inc_n_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'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
pub fn build_inc_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_inc_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'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)
}
pub fn build_dec_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_dec_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'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)
}
fn build_rc_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_rc_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
layout: InLayout<'a>,
@ -453,8 +453,8 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
function_value
}
pub fn build_eq_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_eq_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
layout: InLayout<'a>,
@ -536,8 +536,8 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>(
function_value
}
pub fn build_compare_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_compare_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
roc_function: FunctionValue<'ctx>,
@ -705,9 +705,9 @@ impl BitcodeReturns {
}
}
fn return_value_64bit<'a, 'ctx, 'env>(
fn return_value_64bit<'a, 'ctx>(
&self,
env: &Env<'a, 'ctx, 'env>,
env: &Env<'a, 'ctx, '_>,
arguments: &mut bumpalo::collections::Vec<'a, BasicValueEnum<'ctx>>,
) -> BitcodeReturnValue<'ctx> {
match self {
@ -746,9 +746,9 @@ impl BitcodeReturns {
}
}
fn call_and_load_32bit<'a, 'ctx, 'env>(
fn call_and_load_32bit<'ctx>(
&self,
env: &Env<'a, 'ctx, 'env>,
env: &Env<'_, 'ctx, '_>,
arguments: &[BasicValueEnum<'ctx>],
fn_name: &str,
) -> BasicValueEnum<'ctx> {
@ -764,8 +764,8 @@ impl BitcodeReturns {
}
}
fn ptr_len_cap<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn ptr_len_cap<'ctx>(
env: &Env<'_, 'ctx, '_>,
value: StructValue<'ctx>,
) -> (PointerValue<'ctx>, IntValue<'ctx>, IntValue<'ctx>) {
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 }`
fn receive_zig_roc_list_32bit<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn receive_zig_roc_list_32bit<'ctx>(
env: &Env<'_, 'ctx, '_>,
value: StructValue<'ctx>,
) -> StructValue<'ctx> {
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 }`
fn receive_zig_roc_str_32bit<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn receive_zig_roc_str_32bit<'ctx>(
env: &Env<'_, 'ctx, '_>,
value: StructValue<'ctx>,
) -> StructValue<'ctx> {
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>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn pass_list_to_zig_64bit<'ctx>(
env: &Env<'_, 'ctx, '_>,
list: BasicValueEnum<'ctx>,
) -> PointerValue<'ctx> {
let parent = env
@ -857,16 +857,16 @@ pub(crate) fn pass_list_to_zig_64bit<'a, 'ctx, 'env>(
list_alloca
}
fn pass_string_to_zig_64bit<'a, 'ctx, 'env>(
_env: &Env<'a, 'ctx, 'env>,
fn pass_string_to_zig_64bit<'ctx>(
_env: &Env<'_, 'ctx, '_>,
string: BasicValueEnum<'ctx>,
) -> PointerValue<'ctx> {
// we must pass strings by-pointer, and that is already how they are stored
string.into_pointer_value()
}
pub(crate) fn pass_list_or_string_to_zig_32bit<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn pass_list_or_string_to_zig_32bit<'ctx>(
env: &Env<'_, 'ctx, '_>,
list_or_string: StructValue<'ctx>,
) -> (IntValue<'ctx>, IntValue<'ctx>) {
let ptr = env
@ -907,8 +907,8 @@ pub(crate) fn pass_list_or_string_to_zig_32bit<'a, 'ctx, 'env>(
(ptr_len, cap)
}
pub(crate) fn call_str_bitcode_fn<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn call_str_bitcode_fn<'ctx>(
env: &Env<'_, 'ctx, '_>,
strings: &[BasicValueEnum<'ctx>],
other_arguments: &[BasicValueEnum<'ctx>],
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>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn call_list_bitcode_fn<'ctx>(
env: &Env<'_, 'ctx, '_>,
lists: &[StructValue<'ctx>],
other_arguments: &[BasicValueEnum<'ctx>],
returns: BitcodeReturns,

View file

@ -614,8 +614,8 @@ pub fn construct_optimization_passes<'a>(
(mpm, fpm)
}
fn promote_to_main_function<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn promote_to_main_function<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
mod_solutions: &'a ModSolutions,
symbol: Symbol,
@ -653,8 +653,8 @@ fn promote_to_main_function<'a, 'ctx, 'env>(
(main_fn_name, main_fn)
}
fn promote_to_wasm_test_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn promote_to_wasm_test_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
mod_solutions: &'a ModSolutions,
symbol: Symbol,
@ -746,8 +746,8 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx, 'env>(
(main_fn_name, main_fn)
}
fn int_with_precision<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn int_with_precision<'ctx>(
env: &Env<'_, 'ctx, '_>,
value: i128,
int_width: IntWidth,
) -> IntValue<'ctx> {
@ -762,8 +762,8 @@ fn int_with_precision<'a, 'ctx, 'env>(
}
}
fn float_with_precision<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn float_with_precision<'ctx>(
env: &Env<'_, 'ctx, '_>,
value: f64,
float_width: FloatWidth,
) -> BasicValueEnum<'ctx> {
@ -773,8 +773,8 @@ fn float_with_precision<'a, 'ctx, 'env>(
}
}
pub fn build_exp_literal<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_exp_literal<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &STLayoutInterner<'a>,
parent: FunctionValue<'ctx>,
layout: InLayout<'_>,
@ -817,8 +817,8 @@ pub fn build_exp_literal<'a, 'ctx, 'env>(
}
}
fn build_string_literal<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_string_literal<'ctx>(
env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>,
str_literal: &str,
) -> BasicValueEnum<'ctx> {
@ -844,8 +844,8 @@ fn build_string_literal<'a, 'ctx, 'env>(
}
}
fn const_str_alloca_ptr<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn const_str_alloca_ptr<'ctx>(
env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>,
ptr: PointerValue<'ctx>,
len: IntValue<'ctx>,
@ -862,8 +862,8 @@ fn const_str_alloca_ptr<'a, 'ctx, 'env>(
alloca
}
fn small_str_ptr_width_8<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn small_str_ptr_width_8<'ctx>(
env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>,
str_literal: &str,
) -> PointerValue<'ctx> {
@ -890,10 +890,7 @@ fn small_str_ptr_width_8<'a, 'ctx, 'env>(
const_str_alloca_ptr(env, parent, ptr, len, cap)
}
fn small_str_ptr_width_4<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
str_literal: &str,
) -> StructValue<'ctx> {
fn small_str_ptr_width_4<'ctx>(env: &Env<'_, 'ctx, '_>, str_literal: &str) -> StructValue<'ctx> {
debug_assert_eq!(env.target_info.ptr_width() as u8, 4);
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>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_exp_call<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
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>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_exp_expr<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
func_spec_solutions: &FuncSpecSolutions,
@ -1489,8 +1486,8 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
}
}
fn build_wrapped_tag<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_wrapped_tag<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
scope: &Scope<'a, 'ctx>,
union_layout: &UnionLayout<'a>,
@ -1568,8 +1565,8 @@ fn build_wrapped_tag<'a, 'ctx, 'env>(
}
}
pub fn entry_block_alloca_zerofill<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn entry_block_alloca_zerofill<'ctx>(
env: &Env<'_, 'ctx, '_>,
basic_type: BasicTypeEnum<'ctx>,
name: &str,
) -> PointerValue<'ctx> {
@ -1583,8 +1580,8 @@ pub fn entry_block_alloca_zerofill<'a, 'ctx, 'env>(
create_entry_block_alloca(env, parent, basic_type, name)
}
fn build_tag_field_value<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_tag_field_value<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
value: BasicValueEnum<'ctx>,
tag_field_layout: InLayout<'a>,
@ -1643,8 +1640,8 @@ fn build_tag_fields<'a, 'r, 'ctx, 'env>(
(field_types, field_values)
}
fn build_struct<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_struct<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
scope: &Scope<'a, 'ctx>,
sorted_fields: &[Symbol],
@ -1685,8 +1682,8 @@ fn build_struct<'a, 'ctx, 'env>(
struct_from_fields(env, struct_type, field_vals.into_iter().enumerate())
}
fn build_tag<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_tag<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
scope: &Scope<'a, 'ctx>,
union_layout: &UnionLayout<'a>,
@ -1844,8 +1841,8 @@ fn build_tag<'a, 'ctx, 'env>(
}
}
fn tag_pointer_set_tag_id<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn tag_pointer_set_tag_id<'ctx>(
env: &Env<'_, 'ctx, '_>,
tag_id: u8,
pointer: 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>(
env: &Env<'a, 'ctx, 'env>,
pub fn tag_pointer_read_tag_id<'ctx>(
env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>,
) -> IntValue<'ctx> {
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")
}
pub fn tag_pointer_clear_tag_id<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn tag_pointer_clear_tag_id<'ctx>(
env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>,
) -> PointerValue<'ctx> {
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")
}
fn allocate_tag<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn allocate_tag<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>,
reuse_allocation: Option<PointerValue<'ctx>>,
@ -1968,8 +1965,8 @@ fn allocate_tag<'a, 'ctx, 'env>(
}
}
pub fn get_tag_id<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn get_tag_id<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>,
union_layout: &UnionLayout<'a>,
@ -2051,8 +2048,8 @@ pub fn get_tag_id<'a, 'ctx, 'env>(
}
}
fn lookup_at_index_ptr<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn lookup_at_index_ptr<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
field_layouts: &[InLayout<'a>],
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)
}
fn lookup_at_index_ptr2<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn lookup_at_index_ptr2<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
field_layouts: &'a [InLayout<'a>],
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)
}
pub fn reserve_with_refcount<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn reserve_with_refcount<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
) -> 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)
}
fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: UnionLayout<'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)
}
pub fn allocate_with_refcount<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn allocate_with_refcount<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
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")
}
fn list_literal<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn list_literal<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>,
scope: &Scope<'a, 'ctx>,
@ -2382,8 +2379,8 @@ fn list_literal<'a, 'ctx, 'env>(
}
}
pub fn load_roc_value<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn load_roc_value<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
source: PointerValue<'ctx>,
@ -2402,8 +2399,8 @@ pub fn load_roc_value<'a, 'ctx, 'env>(
}
}
pub fn use_roc_value<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn use_roc_value<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
source: BasicValueEnum<'ctx>,
@ -2424,8 +2421,8 @@ pub fn use_roc_value<'a, 'ctx, 'env>(
}
}
pub fn store_roc_value_opaque<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn store_roc_value_opaque<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
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)
}
pub fn store_roc_value<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn store_roc_value<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
destination: PointerValue<'ctx>,
@ -2481,8 +2478,8 @@ pub fn store_roc_value<'a, 'ctx, 'env>(
}
}
pub fn build_exp_stmt<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_exp_stmt<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
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) {
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>(
scope: &'b Scope<'a, 'ctx>,
pub(crate) fn load_symbol_and_layout<'a, 'ctx>(
scope: &Scope<'a, 'ctx>,
symbol: &Symbol,
) -> (BasicValueEnum<'ctx>, InLayout<'a>) {
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
/// we actually do can lead to faulty optimizations and weird segfaults/crashes
pub fn complex_bitcast_check_size<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn complex_bitcast_check_size<'ctx>(
env: &Env<'_, 'ctx, '_>,
from_value: BasicValueEnum<'ctx>,
to_type: BasicTypeEnum<'ctx>,
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
fn get_tag_id_wrapped<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn get_tag_id_wrapped<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: UnionLayout<'a>,
from_value: PointerValue<'ctx>,
@ -3308,8 +3305,8 @@ fn get_tag_id_wrapped<'a, 'ctx, 'env>(
.into_int_value()
}
pub fn get_tag_id_non_recursive<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn get_tag_id_non_recursive<'ctx>(
env: &Env<'_, 'ctx, '_>,
tag: StructValue<'ctx>,
) -> IntValue<'ctx> {
env.builder
@ -3326,7 +3323,7 @@ struct SwitchArgsIr<'a, '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
let value = value as u128;
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])
}
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
let value = value as u128;
let value = value;
let a = value as u64;
// 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])
}
fn build_switch_ir<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_switch_ir<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
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() {
const_i128(env, *int as i128)
} 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());
@ -3557,8 +3554,8 @@ fn build_switch_ir<'a, 'ctx, 'env>(
}
/// Creates a new stack allocation instruction in the entry block of the function.
pub fn create_entry_block_alloca<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
pub fn create_entry_block_alloca<'ctx>(
env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'_>,
basic_type: BasicTypeEnum<'ctx>,
name: &str,
@ -3574,8 +3571,8 @@ pub fn create_entry_block_alloca<'a, 'ctx>(
builder.build_alloca(basic_type, name)
}
fn expose_function_to_host<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn expose_function_to_host<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
symbol: Symbol,
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>(
env: &Env<'a, 'ctx, 'env>,
fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>,
arguments: &[InLayout<'a>],
@ -3753,8 +3750,8 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx, 'env>(
c_function
}
fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
ident_string: &str,
roc_function: FunctionValue<'ctx>,
@ -3915,8 +3912,8 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx, 'env>(
c_function
}
fn expose_function_to_host_help_c_abi_v2<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>,
arguments: &[InLayout<'a>],
@ -4151,8 +4148,8 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx, 'env>(
c_function
}
fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn expose_function_to_host_help_c_abi<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
ident_string: &str,
roc_function: FunctionValue<'ctx>,
@ -4237,7 +4234,7 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>(
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.
// - AArch64 needs 3 machine-sized words
// - 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);
if cfg!(target_arch = "aarch64") {
// 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.
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 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.
/// 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 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()
}
fn set_jump_and_catch_long_jump<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn set_jump_and_catch_long_jump<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
parent: 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>(
env: &Env<'a, 'ctx, 'env>,
fn make_exception_catcher<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>,
return_layout: InLayout<'a>,
@ -4477,8 +4474,8 @@ fn roc_call_result_layout<'a>(
Layout::struct_no_name_order(arena.alloc(elements))
}
fn roc_call_result_type<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn roc_call_result_type<'ctx>(
env: &Env<'_, 'ctx, '_>,
return_type: BasicTypeEnum<'ctx>,
) -> StructType<'ctx> {
env.context.struct_type(
@ -4491,8 +4488,8 @@ fn roc_call_result_type<'a, 'ctx, 'env>(
)
}
fn make_good_roc_result<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn make_good_roc_result<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
return_layout: InLayout<'a>,
return_value: BasicValueEnum<'ctx>,
@ -4530,8 +4527,8 @@ fn make_good_roc_result<'a, 'ctx, 'env>(
v3.into_struct_value().into()
}
fn make_exception_catching_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn make_exception_catching_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>,
return_layout: InLayout<'a>,
@ -4607,8 +4604,8 @@ fn make_exception_catching_wrapper<'a, 'ctx, 'env>(
wrapper_function
}
pub fn build_proc_headers<'a, 'r, 'ctx, 'env>(
env: &'r Env<'a, 'ctx, 'env>,
pub fn build_proc_headers<'a, 'r, 'ctx>(
env: &'r Env<'a, 'ctx, '_>,
layout_interner: &'r mut STLayoutInterner<'a>,
mod_solutions: &'a ModSolutions,
procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>,
@ -4655,8 +4652,8 @@ pub fn build_proc_headers<'a, 'r, 'ctx, 'env>(
headers
}
pub fn build_procedures<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_procedures<'a>(
env: &Env<'a, '_, '_>,
layout_interner: &mut STLayoutInterner<'a>,
opt_level: OptLevel,
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>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_wasm_test_wrapper<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
opt_level: OptLevel,
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>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_procedures_return_main<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
opt_level: OptLevel,
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>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_procedures_expose_expects<'a>(
env: &Env<'a, '_, '_>,
layout_interner: &mut STLayoutInterner<'a>,
opt_level: OptLevel,
expects: &'a [Symbol],
@ -4832,8 +4829,8 @@ pub fn build_procedures_expose_expects<'a, 'ctx, 'env>(
expect_names
}
fn build_procedures_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_procedures_help<'a>(
env: &Env<'a, '_, '_>,
layout_interner: &mut STLayoutInterner<'a>,
opt_level: OptLevel,
procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>,
@ -4957,8 +4954,8 @@ fn func_spec_name<'a>(
buf
}
fn build_proc_header<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_proc_header<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
func_spec: FuncSpec,
symbol: Symbol,
@ -5024,8 +5021,8 @@ fn build_proc_header<'a, 'ctx, 'env>(
fn_val
}
fn expose_alias_to_host<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn expose_alias_to_host<'a>(
env: &Env<'a, '_, '_>,
layout_interner: &mut STLayoutInterner<'a>,
mod_solutions: &'a ModSolutions,
fn_name: &str,
@ -5105,8 +5102,8 @@ fn expose_alias_to_host<'a, 'ctx, 'env>(
}
}
fn build_closure_caller<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_closure_caller<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
def_name: &str,
evaluator: FunctionValue<'ctx>,
@ -5236,8 +5233,8 @@ fn build_closure_caller<'a, 'ctx, 'env>(
);
}
fn build_host_exposed_alias_size<'a, 'r, 'ctx, 'env>(
env: &'r Env<'a, 'ctx, 'env>,
fn build_host_exposed_alias_size<'a, 'r>(
env: &'r Env<'a, '_, '_>,
layout_interner: &'r mut STLayoutInterner<'a>,
def_name: &str,
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>(
env: &'a Env<'a, 'ctx, 'env>,
fn build_host_exposed_alias_size_help<'a, 'ctx>(
env: &'a Env<'a, 'ctx, '_>,
def_name: &str,
_alias_symbol: Symbol,
opt_label: Option<&str>,
@ -5286,8 +5283,8 @@ fn build_host_exposed_alias_size_help<'a, 'ctx, 'env>(
builder.build_return(Some(&size));
}
fn build_proc<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_proc<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
mod_solutions: &'a ModSolutions,
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>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn function_value_by_func_spec<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
func_spec: FuncSpec,
symbol: Symbol,
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)
}
fn function_value_by_name_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn function_value_by_name_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
arguments: &[InLayout<'a>],
_niche: Niche<'a>,
result: InLayout<'a>,
@ -5425,8 +5422,8 @@ fn function_value_by_name_help<'a, 'ctx, 'env>(
}
#[inline(always)]
fn roc_call_with_args<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn roc_call_with_args<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
argument_layouts: &[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)
}
pub fn call_roc_function<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn call_roc_function<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>,
result_layout: InLayout<'a>,
@ -5561,8 +5558,8 @@ pub struct RocFunctionCall<'ctx> {
pub data_is_owned: IntValue<'ctx>,
}
pub(crate) fn roc_function_call<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn roc_function_call<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
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
/// (this does not currently happen here) be coerced to that integer type.
fn to_cc_type<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn to_cc_type<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
) -> BasicTypeEnum<'ctx> {
@ -5630,8 +5627,8 @@ fn to_cc_type<'a, 'ctx, 'env>(
}
}
fn to_cc_type_builtin<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn to_cc_type_builtin<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
builtin: &Builtin<'a>,
) -> BasicTypeEnum<'ctx> {
match builtin {
@ -5691,8 +5688,8 @@ impl RocReturn {
}
}
pub(crate) fn from_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn from_layout<'a>(
env: &Env<'a, '_, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
) -> Self {
@ -5832,8 +5829,8 @@ impl<'ctx> FunctionSpec<'ctx> {
}
/// According to the C ABI, how should we return a value with the given layout?
pub fn to_cc_return<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn to_cc_return<'a>(
env: &Env<'a, '_, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
) -> CCReturn {
@ -5855,16 +5852,16 @@ pub fn to_cc_return<'a, 'ctx, 'env>(
}
}
fn function_arguments<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn function_arguments<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
arguments: &[BasicTypeEnum<'ctx>],
) -> Vec<'a, BasicMetadataTypeEnum<'ctx>> {
let it = arguments.iter().map(|x| (*x).into());
Vec::from_iter_in(it, env.arena)
}
fn build_foreign_symbol<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_foreign_symbol<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
scope: &mut Scope<'a, 'ctx>,
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>(
env: &Env<'a, 'ctx, 'env>,
fn define_global_str_literal_ptr<'ctx>(
env: &Env<'_, 'ctx, '_>,
message: &str,
) -> PointerValue<'ctx> {
let global = define_global_str_literal(env, message);
@ -6065,8 +6062,8 @@ fn define_global_str_literal_ptr<'a, 'ctx, 'env>(
ptr
}
fn define_global_str_literal<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn define_global_str_literal<'ctx>(
env: &Env<'_, 'ctx, '_>,
message: &str,
) -> inkwell::values::GlobalValue<'ctx> {
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>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn throw_internal_exception<'ctx>(
env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>,
message: &str,
) {
@ -6133,8 +6130,8 @@ pub(crate) fn throw_internal_exception<'a, 'ctx, 'env>(
builder.build_unreachable();
}
pub(crate) fn throw_exception<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn throw_exception<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
scope: &mut Scope<'a, 'ctx>,
message: &Symbol,
tag: CrashTag,
@ -6146,8 +6143,8 @@ pub(crate) fn throw_exception<'a, 'ctx, 'env>(
env.builder.build_unreachable();
}
fn get_foreign_symbol<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn get_foreign_symbol<'ctx>(
env: &Env<'_, 'ctx, '_>,
foreign_symbol: roc_module::ident::ForeignSymbol,
function_spec: FunctionSpec<'ctx>,
) -> FunctionValue<'ctx> {

View file

@ -20,8 +20,8 @@ use super::build::{
};
use super::convert::zig_list_type;
fn call_list_bitcode_fn_1<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn call_list_bitcode_fn_1<'ctx>(
env: &Env<'_, 'ctx, '_>,
list: StructValue<'ctx>,
other_arguments: &[BasicValueEnum<'ctx>],
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)
}
pub(crate) fn list_symbol_to_c_abi<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_symbol_to_c_abi<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
scope: &Scope<'a, 'ctx>,
symbol: Symbol,
) -> PointerValue<'ctx> {
@ -49,8 +49,8 @@ pub(crate) fn list_symbol_to_c_abi<'a, 'ctx, 'env>(
list_alloca
}
pub(crate) fn pass_update_mode<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn pass_update_mode<'ctx>(
env: &Env<'_, 'ctx, '_>,
update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> {
match update_mode {
@ -59,8 +59,8 @@ pub(crate) fn pass_update_mode<'a, 'ctx, 'env>(
}
}
fn pass_element_as_opaque<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn pass_element_as_opaque<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
element: BasicValueEnum<'ctx>,
layout: InLayout<'a>,
@ -80,8 +80,8 @@ fn pass_element_as_opaque<'a, 'ctx, 'env>(
.into()
}
pub(crate) fn layout_width<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn layout_width<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
@ -90,8 +90,8 @@ pub(crate) fn layout_width<'a, 'ctx, 'env>(
.into()
}
pub(crate) fn pass_as_opaque<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn pass_as_opaque<'ctx>(
env: &Env<'_, 'ctx, '_>,
ptr: PointerValue<'ctx>,
) -> BasicValueEnum<'ctx> {
env.builder
@ -103,8 +103,8 @@ pub(crate) fn pass_as_opaque<'a, 'ctx, 'env>(
.into()
}
pub(crate) fn list_with_capacity<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_with_capacity<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
capacity: IntValue<'ctx>,
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>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_get_unsafe<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
element_layout: InLayout<'a>,
@ -162,8 +162,8 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
}
/// List.reserve : List elem, Nat -> List elem
pub(crate) fn list_reserve<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_reserve<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
list: BasicValueEnum<'ctx>,
spare: BasicValueEnum<'ctx>,
@ -184,8 +184,8 @@ pub(crate) fn list_reserve<'a, 'ctx, 'env>(
}
/// List.releaseExcessCapacity : List elem -> List elem
pub(crate) fn list_release_excess_capacity<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_release_excess_capacity<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
list: BasicValueEnum<'ctx>,
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
pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_append_unsafe<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'ctx>,
element: BasicValueEnum<'ctx>,
@ -223,8 +223,8 @@ pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
}
/// List.prepend : List elem, elem -> List elem
pub(crate) fn list_prepend<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_prepend<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'ctx>,
element: BasicValueEnum<'ctx>,
@ -243,8 +243,8 @@ pub(crate) fn list_prepend<'a, 'ctx, 'env>(
}
/// List.swap : List elem, Nat, Nat -> List elem
pub(crate) fn list_swap<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_swap<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'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
pub(crate) fn list_sublist<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_sublist<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
original_wrapper: StructValue<'ctx>,
@ -292,8 +292,8 @@ pub(crate) fn list_sublist<'a, 'ctx, 'env>(
}
/// List.dropAt : List elem, Nat -> List elem
pub(crate) fn list_drop_at<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_drop_at<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
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 }
pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_replace_unsafe<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
_layout_ids: &mut LayoutIds<'a>,
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.
// 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>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_refcount_ptr<'ctx>(
env: &Env<'_, 'ctx, '_>,
wrapper_struct: StructValue<'ctx>,
) -> PointerValue<'ctx> {
call_list_bitcode_fn(
@ -467,8 +467,8 @@ pub(crate) fn destructure<'ctx>(
}
/// List.sortWith : List a, (a, a -> Ordering) -> List a
pub(crate) fn list_sort_with<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_sort_with<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function_call: RocFunctionCall<'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
pub(crate) fn list_map<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_map<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function_call: RocFunctionCall<'ctx>,
list: BasicValueEnum<'ctx>,
@ -515,8 +515,8 @@ pub(crate) fn list_map<'a, 'ctx, 'env>(
)
}
pub(crate) fn list_map2<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_map2<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
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>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_map3<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
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>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_map4<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
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
pub(crate) fn list_concat<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn list_concat<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
list1: BasicValueEnum<'ctx>,
list2: BasicValueEnum<'ctx>,
@ -756,9 +756,7 @@ where
index_alloca
}
pub(crate) fn empty_polymorphic_list<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
) -> BasicValueEnum<'ctx> {
pub(crate) fn empty_polymorphic_list<'ctx>(env: &Env<'_, 'ctx, '_>) -> BasicValueEnum<'ctx> {
let struct_type = zig_list_type(env);
// 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()
}
pub(crate) fn allocate_list<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn allocate_list<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
elem_layout: InLayout<'a>,
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)
}
pub(crate) fn store_list<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn store_list<'ctx>(
env: &Env<'_, 'ctx, '_>,
pointer_to_first_element: PointerValue<'ctx>,
len: IntValue<'ctx>,
) -> StructValue<'ctx> {
@ -835,8 +833,8 @@ pub(crate) fn store_list<'a, 'ctx, 'env>(
)
}
pub(crate) fn decref<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn decref<'ctx>(
env: &Env<'_, 'ctx, '_>,
wrapper_struct: StructValue<'ctx>,
alignment: u32,
) {

View file

@ -10,8 +10,8 @@ use super::build::BuilderExt;
pub static CHAR_LAYOUT: InLayout = Layout::U8;
pub(crate) fn decode_from_utf8_result<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn decode_from_utf8_result<'ctx>(
env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>,
) -> StructValue<'ctx> {
let builder = env.builder;
@ -50,8 +50,8 @@ pub(crate) fn decode_from_utf8_result<'a, 'ctx, 'env>(
/// Dec.toStr : Dec -> Str
/// Str.equal : Str, Str -> Bool
pub(crate) fn str_equal<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn str_equal<'ctx>(
env: &Env<'_, 'ctx, '_>,
value1: BasicValueEnum<'ctx>,
value2: 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.
// 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>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn str_refcount_ptr<'ctx>(
env: &Env<'_, 'ctx, '_>,
value: BasicValueEnum<'ctx>,
) -> PointerValue<'ctx> {
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::lowlevel::dec_binop_with_unchecked;
pub fn generic_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn generic_eq<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
@ -38,8 +38,8 @@ pub fn generic_eq<'a, 'ctx, 'env>(
)
}
pub fn generic_neq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn generic_neq<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
@ -58,8 +58,8 @@ pub fn generic_neq<'a, 'ctx, 'env>(
)
}
fn build_eq_builtin<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_eq_builtin<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
@ -136,8 +136,8 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
}
}
fn build_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_eq<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
@ -236,8 +236,8 @@ fn build_eq<'a, 'ctx, 'env>(
}
}
fn build_neq_builtin<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_neq_builtin<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
@ -326,8 +326,8 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
}
}
fn build_neq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_neq<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
@ -411,8 +411,8 @@ fn build_neq<'a, 'ctx, 'env>(
}
}
fn build_list_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_list_eq<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
list_layout: InLayout<'a>,
@ -469,8 +469,8 @@ fn build_list_eq<'a, 'ctx, 'env>(
call.try_as_basic_value().left().unwrap()
}
fn build_list_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_list_eq_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>,
@ -627,8 +627,8 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
}
}
fn build_struct_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_struct_eq<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
struct_layout: InLayout<'a>,
@ -679,8 +679,8 @@ fn build_struct_eq<'a, 'ctx, 'env>(
call.try_as_basic_value().left().unwrap()
}
fn build_struct_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_struct_eq_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>,
@ -812,8 +812,8 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
}
}
fn build_tag_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_tag_eq<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
tag_layout: InLayout<'a>,
@ -864,8 +864,8 @@ fn build_tag_eq<'a, 'ctx, 'env>(
call.try_as_basic_value().left().unwrap()
}
fn build_tag_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_tag_eq_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>,
@ -1265,8 +1265,8 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
}
}
fn eq_ptr_to_struct<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn eq_ptr_to_struct<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
struct_layout: InLayout<'a>,
@ -1314,8 +1314,8 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
/// ----
fn build_box_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_box_eq<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
box_layout: InLayout<'a>,
@ -1366,8 +1366,8 @@ fn build_box_eq<'a, 'ctx, 'env>(
call.try_as_basic_value().left().unwrap()
}
fn build_box_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_box_eq_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>,

View file

@ -10,8 +10,8 @@ use roc_mono::layout::{
};
use roc_target::TargetInfo;
fn basic_type_from_record<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn basic_type_from_record<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
fields: &[InLayout<'_>],
) -> 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>(
env: &Env<'a, 'ctx, 'env>,
pub fn struct_type_from_union_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: &UnionLayout<'_>,
) -> 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>(
env: &Env<'a, 'ctx, 'env>,
pub fn basic_type_from_union_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: &UnionLayout<'_>,
) -> 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>(
env: &Env<'a, 'ctx, 'env>,
pub fn basic_type_from_builtin<'ctx>(
env: &Env<'_, 'ctx, '_>,
builtin: &Builtin<'_>,
) -> BasicTypeEnum<'ctx> {
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
/// is not currently implemented
pub fn argument_type_from_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn argument_type_from_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout: InLayout<'a>,
) -> 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
pub fn argument_type_from_union_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn argument_type_from_union_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: &UnionLayout<'_>,
) -> 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>(
env: &Env<'a, 'ctx, 'env>,
pub fn int_type_from_int_width<'ctx>(
env: &Env<'_, 'ctx, '_>,
int_width: IntWidth,
) -> IntType<'ctx> {
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>(
env: &Env<'a, 'ctx, 'env>,
pub fn float_type_from_float_width<'ctx>(
env: &Env<'_, 'ctx, '_>,
float_width: FloatWidth,
) -> FloatType<'ctx> {
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()
}
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()
}
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()
}
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());
env.context
.struct_type(&[env.context.bool_type().into(), u8_ptr_t.into()], false)
}
pub fn zig_num_parse_result_type<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn zig_num_parse_result_type<'ctx>(
env: &Env<'_, 'ctx, '_>,
type_name: &str,
) -> StructType<'ctx> {
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>(
env: &Env<'a, 'ctx, 'env>,
pub fn zig_to_int_checked_result_type<'ctx>(
env: &Env<'_, 'ctx, '_>,
type_name: &str,
) -> StructType<'ctx> {
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
.get_struct_type("utils.WithOverflow(dec.RocDec)")
.unwrap()

View file

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

View file

@ -50,8 +50,8 @@ use super::{
convert::zig_dec_type,
};
pub(crate) fn run_low_level<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn run_low_level<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
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)
}
PtrCast | RefCountInc | RefCountDec => {
PtrCast | PtrWrite | RefCountInc | RefCountDec => {
unreachable!("Not used in LLVM backend: {:?}", op);
}
@ -1271,8 +1271,8 @@ fn intwidth_from_layout(layout: InLayout) -> IntWidth {
layout.to_int_width()
}
fn build_int_binop<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_int_binop<'ctx>(
env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>,
int_width: IntWidth,
lhs: IntValue<'ctx>,
@ -1492,8 +1492,8 @@ fn build_int_binop<'a, 'ctx, 'env>(
}
}
pub fn build_num_binop<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_num_binop<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &STLayoutInterner<'a>,
parent: FunctionValue<'ctx>,
lhs_arg: BasicValueEnum<'ctx>,
@ -1543,8 +1543,8 @@ pub fn build_num_binop<'a, 'ctx, 'env>(
}
}
fn build_float_binop<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_float_binop<'ctx>(
env: &Env<'_, 'ctx, '_>,
float_width: FloatWidth,
lhs: FloatValue<'ctx>,
rhs: FloatValue<'ctx>,
@ -1656,8 +1656,8 @@ fn build_float_binop<'a, 'ctx, 'env>(
}
}
fn throw_on_overflow<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn throw_on_overflow<'ctx>(
env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>,
result: StructValue<'ctx>, // of the form { value: T, has_overflowed: bool }
message: &str,
@ -1689,8 +1689,8 @@ fn throw_on_overflow<'a, 'ctx, 'env>(
.unwrap()
}
fn dec_split_into_words<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn dec_split_into_words<'ctx>(
env: &Env<'_, 'ctx, '_>,
value: IntValue<'ctx>,
) -> (IntValue<'ctx>, IntValue<'ctx>) {
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>(
env: &Env<'a, 'ctx, 'env>,
value: IntValue<'ctx>,
) -> PointerValue<'ctx> {
fn dec_alloca<'ctx>(env: &Env<'_, 'ctx, '_>, value: IntValue<'ctx>) -> PointerValue<'ctx> {
let dec_type = zig_dec_type(env);
let alloca = env.builder.build_alloca(dec_type, "dec_alloca");
@ -1728,10 +1725,7 @@ fn dec_alloca<'a, 'ctx, 'env>(
alloca
}
fn dec_to_str<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
dec: BasicValueEnum<'ctx>,
) -> BasicValueEnum<'ctx> {
fn dec_to_str<'ctx>(env: &Env<'_, 'ctx, '_>, dec: BasicValueEnum<'ctx>) -> BasicValueEnum<'ctx> {
use roc_target::OperatingSystem::*;
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>(
env: &Env<'a, 'ctx, 'env>,
fn dec_binop_with_overflow<'ctx>(
env: &Env<'_, 'ctx, '_>,
fn_name: &str,
lhs: BasicValueEnum<'ctx>,
rhs: BasicValueEnum<'ctx>,
@ -1812,8 +1806,8 @@ fn dec_binop_with_overflow<'a, 'ctx, 'env>(
.into_struct_value()
}
pub(crate) fn dec_binop_with_unchecked<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn dec_binop_with_unchecked<'ctx>(
env: &Env<'_, 'ctx, '_>,
fn_name: &str,
lhs: 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>(
env: &Env<'a, 'ctx, 'env>,
fn build_dec_binop<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
parent: FunctionValue<'ctx>,
lhs: BasicValueEnum<'ctx>,
_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>(
env: &Env<'a, 'ctx, 'env>,
fn build_dec_binop_throw_on_overflow<'ctx>(
env: &Env<'_, 'ctx, '_>,
parent: FunctionValue<'ctx>,
operation: &str,
lhs: BasicValueEnum<'ctx>,
@ -2128,8 +2122,8 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
}
}
fn int_neg_raise_on_overflow<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn int_neg_raise_on_overflow<'ctx>(
env: &Env<'_, 'ctx, '_>,
arg: IntValue<'ctx>,
int_type: IntType<'ctx>,
) -> BasicValueEnum<'ctx> {
@ -2159,8 +2153,8 @@ fn int_neg_raise_on_overflow<'a, 'ctx, 'env>(
builder.build_int_neg(arg, "negate_int").into()
}
fn int_abs_raise_on_overflow<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn int_abs_raise_on_overflow<'ctx>(
env: &Env<'_, 'ctx, '_>,
arg: IntValue<'ctx>,
int_type: IntType<'ctx>,
) -> BasicValueEnum<'ctx> {
@ -2190,8 +2184,8 @@ fn int_abs_raise_on_overflow<'a, 'ctx, 'env>(
int_abs_with_overflow(env, arg, int_type)
}
fn int_abs_with_overflow<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn int_abs_with_overflow<'ctx>(
env: &Env<'_, 'ctx, '_>,
arg: IntValue<'ctx>,
int_type: IntType<'ctx>,
) -> BasicValueEnum<'ctx> {
@ -2233,8 +2227,8 @@ fn int_abs_with_overflow<'a, 'ctx, 'env>(
)
}
fn build_float_unary_op<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_float_unary_op<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &STLayoutInterner<'a>,
layout: InLayout<'a>,
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>(
env: &Env<'a, 'ctx, 'env>,
pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
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>,
scope: &'b Scope<'a, 'ctx>,
scope: &Scope<'a, 'ctx>,
symbol: &Symbol,
) -> (BasicValueEnum<'ctx>, LambdaSet<'a>) {
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>(
env: &Env<'a, 'ctx, 'env>,
fn incref_pointer<'ctx>(
env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>,
amount: IntValue<'ctx>,
) {
@ -216,11 +216,7 @@ fn incref_pointer<'a, 'ctx, 'env>(
);
}
fn decref_pointer<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pointer: PointerValue<'ctx>,
alignment: u32,
) {
fn decref_pointer<'ctx>(env: &Env<'_, 'ctx, '_>, pointer: PointerValue<'ctx>, alignment: u32) {
let alignment = env.context.i32_type().const_int(alignment as _, false);
call_void_bitcode_fn(
env,
@ -239,8 +235,8 @@ fn decref_pointer<'a, 'ctx, 'env>(
}
/// Assumes a pointer to the refcount
pub fn decref_pointer_check_null<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn decref_pointer_check_null<'ctx>(
env: &Env<'_, 'ctx, '_>,
pointer: PointerValue<'ctx>,
alignment: u32,
) {
@ -261,8 +257,8 @@ pub fn decref_pointer_check_null<'a, 'ctx, 'env>(
);
}
fn modify_refcount_struct<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_struct<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
layouts: &'a [InLayout<'a>],
@ -308,8 +304,8 @@ fn modify_refcount_struct<'a, 'ctx, 'env>(
}
#[allow(clippy::too_many_arguments)]
fn modify_refcount_struct_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_struct_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
@ -363,8 +359,8 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
builder.build_return(None);
}
pub fn increment_refcount_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn increment_refcount_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
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);
}
pub fn increment_n_refcount_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn increment_n_refcount_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
amount: IntValue<'ctx>,
@ -393,8 +389,8 @@ pub fn increment_n_refcount_layout<'a, 'ctx, 'env>(
);
}
pub fn decrement_refcount_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn decrement_refcount_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
value: BasicValueEnum<'ctx>,
@ -410,8 +406,8 @@ pub fn decrement_refcount_layout<'a, 'ctx, 'env>(
);
}
fn modify_refcount_builtin<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_builtin<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
@ -443,8 +439,8 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
}
}
fn modify_refcount_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_layout<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
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);
}
fn modify_refcount_layout_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_layout_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
call_mode: CallMode<'ctx>,
@ -495,8 +491,8 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
}
}
fn call_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn call_help<'ctx>(
env: &Env<'_, 'ctx, '_>,
function: FunctionValue<'ctx>,
call_mode: CallMode<'ctx>,
value: BasicValueEnum<'ctx>,
@ -522,8 +518,8 @@ fn call_help<'a, 'ctx, 'env>(
call
}
fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_layout_build_function<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
@ -596,8 +592,8 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
}
}
fn modify_refcount_list<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_list<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
@ -656,8 +652,8 @@ fn mode_to_call_mode(function: FunctionValue<'_>, mode: Mode) -> CallMode<'_> {
}
}
fn modify_refcount_list_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_list_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
@ -744,8 +740,8 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
builder.build_return(None);
}
fn modify_refcount_str<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_str<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
@ -781,8 +777,8 @@ fn modify_refcount_str<'a, 'ctx, 'env>(
function
}
fn modify_refcount_str_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_str_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
mode: Mode,
layout: InLayout<'a>,
@ -851,8 +847,8 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>(
builder.build_return(None);
}
fn modify_refcount_boxed<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_boxed<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
@ -890,8 +886,8 @@ fn modify_refcount_boxed<'a, 'ctx, 'env>(
function
}
fn modify_refcount_box_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_box_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
mode: Mode,
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
fn build_header<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_header<'ctx>(
env: &Env<'_, 'ctx, '_>,
arg_type: BasicTypeEnum<'ctx>,
mode: Mode,
fn_name: &str,
@ -941,8 +937,8 @@ fn build_header<'a, 'ctx, 'env>(
}
/// Build an increment or decrement function for a specific layout
pub fn build_header_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_header_help<'ctx>(
env: &Env<'_, 'ctx, '_>,
fn_name: &str,
return_type: AnyTypeEnum<'ctx>,
arguments: &[BasicTypeEnum<'ctx>],
@ -1013,8 +1009,8 @@ enum CallMode<'ctx> {
Dec,
}
fn build_rec_union<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_rec_union<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
@ -1060,8 +1056,8 @@ fn build_rec_union<'a, 'ctx, 'env>(
}
#[allow(clippy::too_many_arguments)]
fn build_rec_union_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_rec_union_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
@ -1184,8 +1180,8 @@ fn fields_need_no_refcounting(interner: &STLayoutInterner, field_layouts: &[InLa
}
#[allow(clippy::too_many_arguments)]
fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_rec_union_recursive_decrement<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>,
@ -1414,8 +1410,8 @@ fn union_layout_tags<'a>(
}
}
pub fn build_reset<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
pub fn build_reset<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
union_layout: UnionLayout<'a>,
@ -1458,8 +1454,8 @@ pub fn build_reset<'a, 'ctx, 'env>(
}
#[allow(clippy::too_many_arguments)]
fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn build_reuse_rec_union_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
union_layout: UnionLayout<'a>,
@ -1572,8 +1568,8 @@ fn function_name_from_mode<'a>(
}
}
fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_nonrecursive<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
@ -1619,8 +1615,8 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
function
}
fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
fn modify_refcount_nonrecursive_help<'a, 'ctx>(
env: &Env<'a, 'ctx, '_>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,

View file

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

View file

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

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")
}
PtrCast | RefCountInc | RefCountDec => {
PtrCast | PtrWrite | RefCountInc | RefCountDec => {
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 crate::ir::{
Call, CallSpecId, CallType, Expr, HostExposedLayouts, JoinPointId, ModifyRc, Proc, ProcLayout,
SelfRecursive, Stmt, UpdateModeId,
Call, CallSpecId, CallType, Expr, HostExposedLayouts, JoinPointId, ModifyRc, PassedFunction,
Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId,
};
use crate::layout::{
Builtin, InLayout, LambdaName, Layout, LayoutInterner, Niche, STLayoutInterner, UnionLayout,
@ -20,6 +20,7 @@ const LAYOUT_UNIT: InLayout = Layout::UNIT;
const ARG_1: Symbol = Symbol::ARG_1;
const ARG_2: Symbol = Symbol::ARG_2;
const ARG_3: Symbol = Symbol::ARG_3;
/// "Infinite" reference count, for static values
/// Ref counts are encoded as negative numbers where isize::MIN represents 1
@ -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>(
arena: &'a Bump,
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!
// please change it to the lower number.
// 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!(Expr, 48);
roc_error_macros::assert_sizeof_wasm!(Stmt, 64);
@ -3027,7 +3026,7 @@ fn specialize_external_help<'a>(
for in_layout in host_exposed_layouts {
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.ident_ids,
env.arena,
@ -3035,6 +3034,17 @@ fn specialize_external_help<'a>(
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
let GlueProcs {
getters,
@ -3053,23 +3063,10 @@ fn specialize_external_help<'a>(
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 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(
env,
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>(
home: ModuleId,
ident_ids: &mut IdentIds,

View file

@ -1193,7 +1193,7 @@ fn extract<'a>(
/// 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
.patterns
.iter()
@ -1358,7 +1358,7 @@ fn small_branching_factor(branches: &[Branch], path: &[PathInstruction]) -> usiz
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)]

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.
/// Panics if given a FlexVar or RigidVar, since those should have been
/// 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| {
if env.is_seen(var) {
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> {
target_info: TargetInfo,
arena: &'a Bump,
pub(crate) arena: &'a Bump,
seen: Vec<'a, Variable>,
subs: &'b Subs,
pub(crate) subs: &'b Subs,
cache: &'b mut LayoutCache<'a>,
}

View file

@ -433,6 +433,22 @@ impl<'a> InLayout<'a> {
pub fn index(&self) -> usize {
self.0
}
pub fn try_int_width(self) -> Option<IntWidth> {
match self {
Layout::U8 => Some(IntWidth::U8),
Layout::U16 => Some(IntWidth::U16),
Layout::U32 => Some(IntWidth::U32),
Layout::U64 => Some(IntWidth::U64),
Layout::U128 => Some(IntWidth::U128),
Layout::I8 => Some(IntWidth::I8),
Layout::I16 => Some(IntWidth::I16),
Layout::I32 => Some(IntWidth::I32),
Layout::I64 => Some(IntWidth::I64),
Layout::I128 => Some(IntWidth::I128),
_ => None,
}
}
}
/// A concurrent interner, suitable for usage between threads.

View file

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

View file

@ -21,6 +21,7 @@ use crate::type_annotation;
use bumpalo::collections::Vec;
use bumpalo::Bump;
use roc_collections::soa::Slice;
use roc_error_macros::internal_error;
use roc_module::called_via::{BinOp, CalledVia, UnaryOp};
use roc_region::all::{Loc, Position, Region};
@ -2479,10 +2480,10 @@ fn ident_to_expr<'a>(arena: &'a Bump, src: Ident<'a>) -> Expr<'a> {
// TODO: make this state impossible to represent in Ident::Access,
// by splitting out parts[0] into a separate field with a type of `&'a str`,
// rather than a `&'a [Accessor<'a>]`.
panic!("Parsed an Ident::Access with a first part of a tuple index");
internal_error!("Parsed an Ident::Access with a first part of a tuple index");
}
None => {
panic!("Parsed an Ident::Access with no parts");
internal_error!("Parsed an Ident::Access with no parts");
}
};

View file

@ -545,7 +545,7 @@ fn compact_lambda_set<P: Phase>(
Err(()) => {
// Do nothing other than to remove the concrete lambda to drop from the lambda set,
// 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 {
new_obligations: Default::default(),
new_lambda_sets_to_specialize: Default::default(),
@ -568,7 +568,7 @@ fn compact_lambda_set<P: Phase>(
Err(()) => {
// Do nothing other than to remove the concrete lambda to drop from the lambda set,
// 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 {
new_obligations: 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);
// 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(
&mut UEnv::new(subs),
t_f1,
@ -590,7 +590,7 @@ fn compact_lambda_set<P: Phase>(
Polarity::Pos,
)
.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);

View file

@ -1200,7 +1200,7 @@ fn list_count_if_str() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn list_map_on_empty_list_with_int_layout() {
assert_evals_to!(
indoc!(
@ -1218,7 +1218,7 @@ fn list_map_on_empty_list_with_int_layout() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn list_map_on_non_empty_list() {
assert_evals_to!(
indoc!(
@ -1236,7 +1236,7 @@ fn list_map_on_non_empty_list() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn list_map_changes_input() {
assert_evals_to!(
indoc!(
@ -1254,7 +1254,7 @@ fn list_map_changes_input() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn list_map_on_big_list() {
assert_evals_to!(
indoc!(
@ -1274,7 +1274,7 @@ fn list_map_on_big_list() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn list_map_with_type_change() {
assert_evals_to!(
indoc!(
@ -1293,7 +1293,7 @@ fn list_map_with_type_change() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn list_map_using_defined_function() {
assert_evals_to!(
indoc!(
@ -1315,7 +1315,7 @@ fn list_map_using_defined_function() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn list_map_all_inline() {
assert_evals_to!(
indoc!(
@ -1328,9 +1328,30 @@ fn list_map_all_inline() {
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn list_map_closure_int() {
assert_evals_to!(
indoc!(
r#"
int : I64
int = 123
single : List I64
single =
[0]
List.map single (\x -> x + int)
"#
),
RocList::from_slice(&[123]),
RocList<i64>
);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
fn list_map_closure() {
fn list_map_closure_float() {
assert_evals_to!(
indoc!(
r#"
@ -2926,7 +2947,7 @@ fn list_any_empty_with_unknown_element_type() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn list_all() {
assert_evals_to!("List.all [] (\\e -> e > 3)", true, bool);
assert_evals_to!("List.all [1, 2, 3] (\\e -> e > 3)", false, bool);

View file

@ -3113,7 +3113,7 @@ fn when_on_i16() {
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
fn num_to_str() {
use roc_std::RocStr;
@ -4055,3 +4055,27 @@ fn num_abs_large_bits_min_overflow() {
fn num_abs_float_overflow() {
assert_evals_to!("Num.absDiff Num.maxF64 Num.minF64", f64::INFINITY, f64);
}
#[test]
#[cfg(any(feature = "gen-llvm", feature = "gen-dev", feature = "gen-wasm"))]
fn bool_in_switch() {
assert_evals_to!(
indoc!(
r#"
app "test" provides [main] to "./platform"
loop : [ Continue {}, Break {} ]
loop = Continue {}
all = \{} ->
when loop is
Continue {} -> Bool.true
Break {} -> Bool.false
main = all {}
"#
),
true,
bool
);
}

View file

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

View file

@ -907,7 +907,9 @@ fn alignment_in_multi_tag_pattern_match() {
{ bool, int }
Empty ->
{ bool: Bool.false, int: 0 }
# dev backend codegen bug means we cannot use this inline
false = Bool.false
{ bool: false, int: 0 }
#"
),
(32i64, true),
@ -924,7 +926,8 @@ fn alignment_in_multi_tag_pattern_match() {
Three bool color int ->
{ bool, color, int }
Empty ->
{ bool: Bool.false, color: Red, int: 0 }
false = Bool.false
{ bool: false, color: Red, int: 0 }
#"
),
(32i64, true, 2u8),

View file

@ -1,10 +1,6 @@
procedure Test.1 (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):
dec Test.4;
let Test.14 : Str = "";

View file

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

View file

@ -18,10 +18,6 @@ procedure Test.34 (Test.35):
let Test.37 : {} = StructAtIndex 1 Test.36;
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):
let Test.3 : {} = StructAtIndex 1 #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;
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):
let Test.19 : U16 = 1i64;
let Test.20 : {} = Struct {};

View file

@ -18,10 +18,6 @@ procedure Test.34 (Test.35):
let Test.37 : {} = StructAtIndex 1 Test.36;
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):
let Test.3 : {} = StructAtIndex 1 #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;
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):
let Test.19 : U8 = 1i64;
let Test.20 : {} = Struct {};

View file

@ -2550,7 +2550,6 @@ fn recursively_build_effect() {
}
#[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() {
indoc!(
r#"

View file

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

View file

@ -52,6 +52,7 @@ convertTypesToFile = \types ->
buf
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)
TagUnion (NullableUnwrapped { name, nullTag, nonNullTag, nonNullPayload, whichTagIsNull }) ->
@ -244,14 +245,14 @@ generateStruct = \buf, types, id, name, structFields, visibility ->
pub =
when visibility is
Public -> "pub"
Public -> "pub "
Private -> ""
structType = Types.shape types id
buf
|> 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
|> 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 _)
}
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 =
@ -988,7 +995,7 @@ generateRecursiveTagUnion = \buf, types, id, tagUnionName, tags, discriminantSiz
const _ALIGN_CHECK_\(escapedName): () = assert!(core::mem::align_of::<\(escapedName)>() == \(alignOfSelf));
impl \(escapedName) {
fn discriminant(&self) -> discriminant_\(escapedName) {
pub fn discriminant(&self) -> discriminant_\(escapedName) {
let discriminants = {
use \(discriminantName)::*;

View file

@ -1226,81 +1226,8 @@ impl<'a> Env<'a> {
}
fn find_lambda_sets(&self, root: Variable) -> MutMap<Variable, LambdaSetId> {
let mut lambda_set_id = LambdaSetId::default();
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
let stack = bumpalo::vec![in self.arena; root];
roc_mono::ir::find_lambda_sets_help(self.subs, stack)
}
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 memmap2::MmapMut;
use object::{elf, endian};
use object::{
CompressedFileRange, CompressionFormat, LittleEndian as LE, NativeEndian, Object,
ObjectSection, ObjectSymbol, RelocationKind, RelocationTarget, Section, SectionIndex,
SectionKind, Symbol, SymbolIndex, SymbolSection,
CompressedFileRange, CompressionFormat, LittleEndian as LE, Object, ObjectSection,
ObjectSymbol, RelocationKind, RelocationTarget, Section, SectionIndex, SectionKind, Symbol,
SymbolIndex, SymbolSection,
};
use roc_collections::all::MutMap;
use roc_error_macros::{internal_error, user_error};
use std::convert::TryFrom;
use std::ffi::CStr;
use std::mem;
use std::os::raw::c_char;
use std::path::Path;
use std::time::{Duration, Instant};
use crate::metadata::{self, Metadata, VirtualOffset};
use serde::{Deserialize, Serialize};
use std::{
ffi::{c_char, CStr},
io::{BufReader, BufWriter},
mem,
path::Path,
time::{Duration, Instant},
};
use crate::{
align_by_constraint, align_to_offset_by_constraint, load_struct_inplace,
@ -35,6 +36,73 @@ struct ElfDynamicDeps {
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) {
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> {
surgeries: MutMap<String, Vec<metadata::SurgeryEntry>>,
surgeries: MutMap<String, Vec<SurgeryEntry>>,
app_func_addresses: MutMap<u64, &'a str>,
indirect_warning_given: bool,
}
@ -229,7 +297,7 @@ impl<'a> Surgeries<'a> {
self.surgeries
.get_mut(*func_name)
.unwrap()
.push(metadata::SurgeryEntry {
.push(SurgeryEntry {
file_offset: offset,
virtual_offset: VirtualOffset::Relative(inst.next_ip()),
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(
endianness: target_lexicon::Endianness,
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),
..Default::default()
};
@ -507,7 +575,7 @@ pub(crate) fn preprocess_elf(
#[allow(clippy::too_many_arguments)]
fn gen_elf_le(
exec_data: &[u8],
md: &mut metadata::Metadata,
md: &mut Metadata,
preprocessed_path: &Path,
got_app_syms: &[(String, usize)],
got_sections: &[(usize, usize)],
@ -517,12 +585,12 @@ fn gen_elf_le(
verbose: bool,
) -> MmapMut {
let exec_header = load_struct_inplace::<elf::FileHeader64<LE>>(exec_data, 0);
let ph_offset = exec_header.e_phoff.get(NativeEndian);
let ph_ent_size = exec_header.e_phentsize.get(NativeEndian);
let ph_num = exec_header.e_phnum.get(NativeEndian);
let sh_offset = exec_header.e_shoff.get(NativeEndian);
let sh_ent_size = exec_header.e_shentsize.get(NativeEndian);
let sh_num = exec_header.e_shnum.get(NativeEndian);
let ph_offset = exec_header.e_phoff.get(LE);
let ph_ent_size = exec_header.e_phentsize.get(LE);
let ph_num = exec_header.e_phnum.get(LE);
let sh_offset = exec_header.e_shoff.get(LE);
let sh_ent_size = exec_header.e_shentsize.get(LE);
let sh_num = exec_header.e_shnum.get(LE);
if verbose {
println!();
@ -555,11 +623,11 @@ fn gen_elf_le(
let mut first_load_found = false;
let mut virtual_shift_start = 0;
for ph in program_headers.iter() {
let p_type = ph.p_type.get(NativeEndian);
if p_type == elf::PT_LOAD && ph.p_offset.get(NativeEndian) == 0 {
let p_type = ph.p_type.get(LE);
if p_type == elf::PT_LOAD && ph.p_offset.get(LE) == 0 {
first_load_found = true;
md.load_align_constraint = ph.p_align.get(NativeEndian);
virtual_shift_start = physical_shift_start + ph.p_vaddr.get(NativeEndian);
md.load_align_constraint = ph.p_align.get(LE);
virtual_shift_start = physical_shift_start + ph.p_vaddr.get(LE);
}
}
if !first_load_found {
@ -574,21 +642,22 @@ fn gen_elf_le(
// Shift all of the program headers.
for ph in program_headers.iter_mut() {
let p_type = ph.p_type.get(NativeEndian);
let p_offset = ph.p_offset.get(NativeEndian);
let p_type = ph.p_type.get(LE);
let p_offset = ph.p_offset.get(LE);
if (p_type == elf::PT_LOAD && p_offset == 0) || p_type == elf::PT_PHDR {
// 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_memsz = endian::U64::new(LE, ph.p_memsz.get(NativeEndian) + md.added_byte_count);
ph.p_filesz
.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 {
// Shift if needed.
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 {
ph.p_vaddr = endian::U64::new(LE, p_vaddr + md.added_byte_count);
ph.p_paddr = endian::U64::new(LE, p_vaddr + md.added_byte_count);
ph.p_vaddr.set(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
.iter()
.filter_map(|ph| {
if ph.p_type.get(NativeEndian) != elf::PT_GNU_STACK {
Some(ph.p_vaddr.get(NativeEndian) + ph.p_memsz.get(NativeEndian))
if ph.p_type.get(LE) != elf::PT_GNU_STACK {
Some(ph.p_vaddr.get(LE) + ph.p_memsz.get(LE))
} else {
None
}
@ -620,28 +689,28 @@ fn gen_elf_le(
let mut rel_sections: Vec<(u64, u64)> = vec![];
let mut rela_sections: Vec<(usize, u64, u64)> = vec![];
for (i, sh) in section_headers.iter_mut().enumerate() {
let sh_offset = sh.sh_offset.get(NativeEndian);
let sh_addr = sh.sh_addr.get(NativeEndian);
let sh_offset = sh.sh_offset.get(LE);
let sh_addr = sh.sh_addr.get(LE);
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 {
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.
let sh_type = sh.sh_type.get(NativeEndian);
let sh_type = sh.sh_type.get(LE);
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 {
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.
let last_section_vaddr = section_headers
.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()
.unwrap();
@ -658,9 +727,9 @@ fn gen_elf_le(
sec_size as usize / mem::size_of::<elf::Rel64<LE>>(),
);
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 {
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>>(),
);
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 {
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.
// TODO: Verify other relocation types.
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.
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 {
let r_sym = rel.r_sym(NativeEndian, false);
let r_sym = rel.r_sym(LE, false);
for (name, index) in got_app_syms.iter() {
if *index as u32 == r_sym {
rel.set_r_info(LE, false, 0, elf::R_X86_64_RELATIVE);
@ -694,10 +763,7 @@ fn gen_elf_le(
+ i * mem::size_of::<elf::Rela64<LE>>()
// This 16 skips the first 2 fields and gets to the addend field.
+ 16;
md.surgeries
.get_mut(name)
.unwrap()
.push(metadata::SurgeryEntry {
md.surgeries.get_mut(name).unwrap().push(SurgeryEntry {
file_offset: addend_addr as u64,
virtual_offset: VirtualOffset::Absolute,
size: 8,
@ -715,8 +781,8 @@ fn gen_elf_le(
.iter()
.enumerate()
.filter_map(|(i, rel)| {
let r_type = rel.r_type(NativeEndian, false);
let r_sym = rel.r_sym(NativeEndian, false);
let r_type = rel.r_type(LE, 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))
{
Some(i)
@ -733,7 +799,7 @@ fn gen_elf_le(
let mut j = relocations.len() - 1;
for i in to_remove.iter() {
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);
j -= 1;
}
@ -744,12 +810,12 @@ fn gen_elf_le(
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_size = removed_count * std::mem::size_of::<elf::Rela64<LE>>();
section_headers[sec_index]
.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>>(
&mut out_mmap,
@ -759,30 +825,30 @@ fn gen_elf_le(
let is_rela_dyn = dyns
.iter()
.filter(|d| {
let tag = d.d_tag.get(NativeEndian) as u32;
let tag = d.d_tag.get(LE) as u32;
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
.iter()
.filter(|d| {
let tag = d.d_tag.get(NativeEndian) as u32;
let tag = d.d_tag.get(LE) as u32;
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() {
match d.d_tag.get(NativeEndian) as u32 {
match d.d_tag.get(LE) as u32 {
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);
}
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);
}
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);
}
_ => {}
@ -796,8 +862,8 @@ fn gen_elf_le(
dyn_offset as usize,
dynamic_lib_count,
);
for mut d in dyns {
match d.d_tag.get(NativeEndian) as u32 {
for d in dyns {
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 am less sure about the symbols from GNU_HASH down.
elf::DT_INIT
@ -828,9 +894,9 @@ fn gen_elf_le(
| elf::DT_VERSYM
| elf::DT_VERDEF
| 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 {
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 {
let addr = sym.st_value.get(NativeEndian);
let addr = sym.st_value.get(LE);
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>>(),
);
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 {
go.set(LE, go_addr + md.added_byte_count);
}
@ -882,23 +948,24 @@ fn gen_elf_le(
}
// Update main elf header for extra data.
let mut file_header = load_struct_inplace_mut::<elf::FileHeader64<LE>>(&mut out_mmap, 0);
file_header.e_shoff = endian::U64::new(
LE,
file_header.e_shoff.get(NativeEndian) + md.added_byte_count,
);
let e_entry = file_header.e_entry.get(NativeEndian);
let file_header = load_struct_inplace_mut::<elf::FileHeader64<LE>>(&mut out_mmap, 0);
file_header
.e_shoff
.set(LE, file_header.e_shoff.get(LE) + md.added_byte_count);
let e_entry = file_header.e_entry.get(LE);
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
}
fn scan_elf_dynamic_deps(
exec_obj: &object::File,
md: &mut metadata::Metadata,
md: &mut Metadata,
app_syms: &[Symbol],
shared_lib: &Path,
exec_data: &[u8],
@ -1173,7 +1240,7 @@ pub(crate) fn surgery_elf(
fn surgery_elf_help(
verbose: bool,
md: &metadata::Metadata,
md: &Metadata,
exec_mmap: &mut MmapMut,
offset_ref: &mut usize, // TODO return this instead of taking a mutable reference to it
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 ph_offset = exec_header.e_phoff.get(NativeEndian);
let ph_ent_size = exec_header.e_phentsize.get(NativeEndian);
let ph_num = exec_header.e_phnum.get(NativeEndian);
let sh_offset = exec_header.e_shoff.get(NativeEndian);
let sh_ent_size = exec_header.e_shentsize.get(NativeEndian);
let sh_num = exec_header.e_shnum.get(NativeEndian);
let ph_offset = exec_header.e_phoff.get(LE);
let ph_ent_size = exec_header.e_phentsize.get(LE);
let ph_num = exec_header.e_phnum.get(LE);
let sh_offset = exec_header.e_shoff.get(LE);
let sh_ent_size = exec_header.e_shentsize.get(LE);
let sh_num = exec_header.e_shnum.get(LE);
if verbose {
println!();
@ -1489,8 +1556,10 @@ fn surgery_elf_help(
// Reload and update file header and size.
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_shnum = endian::U16::new(LE, sh_num + new_section_count as u16);
file_header.e_shoff.set(LE, new_sh_offset as u64);
file_header
.e_shnum
.set(LE, sh_num + new_section_count as u16);
// Add 2 new segments that match the new sections.
let program_headers = load_structs_inplace_mut::<elf::ProgramHeader64<LE>>(
@ -1609,9 +1678,9 @@ fn surgery_elf_help(
exec_mmap,
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_value = endian::U64::new(LE, func_virt_offset);
sym.st_size = endian::U64::new(
sym.st_shndx.set(LE, new_text_section_index as u16);
sym.st_value.set(LE, func_virt_offset);
sym.st_size.set(
LE,
match app_func_size_map.get(func_name) {
Some(size) => *size,
@ -1626,9 +1695,9 @@ fn surgery_elf_help(
exec_mmap,
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_value = endian::U64::new(LE, func_virt_offset);
sym.st_size = endian::U64::new(
sym.st_shndx.set(LE, new_text_section_index as u16);
sym.st_value.set(LE, func_virt_offset);
sym.st_size.set(
LE,
match app_func_size_map.get(func_name) {
Some(size) => *size,

View file

@ -21,7 +21,6 @@ mod macho;
mod pe;
mod generate_dylib;
mod metadata;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
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)]
fn preprocess(
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 memmap2::MmapMut;
use object::macho;
use object::{
CompressedFileRange, CompressionFormat, LittleEndian, NativeEndian, Object, ObjectSection,
CompressedFileRange, CompressionFormat, LittleEndian as LE, Object, ObjectSection,
ObjectSymbol, RelocationKind, RelocationTarget, Section, SectionIndex, SectionKind, Symbol,
SymbolIndex, SymbolSection,
};
use roc_collections::all::MutMap;
use roc_error_macros::internal_error;
use std::ffi::CStr;
use std::mem;
use std::path::Path;
use std::time::{Duration, Instant};
use serde::{Deserialize, Serialize};
use std::{
ffi::CStr,
io::{BufReader, BufWriter},
mem,
path::Path,
time::{Duration, Instant},
};
use target_lexicon::Triple;
use crate::{
@ -34,6 +38,73 @@ const STUB_ADDRESS_OFFSET: u64 = 0x06;
// 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) {
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> {
surgeries: MutMap<String, Vec<metadata::SurgeryEntry>>,
surgeries: MutMap<String, Vec<SurgeryEntry>>,
app_func_addresses: MutMap<u64, &'a str>,
indirect_warning_given: bool,
}
@ -217,7 +288,7 @@ impl<'a> Surgeries<'a> {
self.surgeries
.get_mut(*func_name)
.unwrap()
.push(metadata::SurgeryEntry {
.push(SurgeryEntry {
file_offset: offset,
virtual_offset: VirtualOffset::Relative(inst.next_ip()),
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(
target: &Triple,
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),
..Default::default()
};
@ -325,8 +396,8 @@ pub(crate) fn preprocess_macho(
{
use macho::{DyldInfoCommand, DylibCommand, Section64, SegmentCommand64};
let exec_header = load_struct_inplace::<macho::MachHeader64<LittleEndian>>(exec_data, 0);
let num_load_cmds = exec_header.ncmds.get(NativeEndian);
let exec_header = load_struct_inplace::<macho::MachHeader64<LE>>(exec_data, 0);
let num_load_cmds = exec_header.ncmds.get(LE);
let mut offset = mem::size_of_val(exec_header);
@ -334,17 +405,17 @@ pub(crate) fn preprocess_macho(
let mut stubs_symbol_count = None;
'cmds: for _ in 0..num_load_cmds {
let info = load_struct_inplace::<macho::LoadCommand<LittleEndian>>(exec_data, offset);
let cmd = info.cmd.get(NativeEndian);
let cmdsize = info.cmdsize.get(NativeEndian);
let info = load_struct_inplace::<macho::LoadCommand<LE>>(exec_data, offset);
let cmd = info.cmd.get(LE);
let cmdsize = info.cmdsize.get(LE);
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" {
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,
offset + mem::size_of_val(info),
sections as usize,
@ -352,9 +423,9 @@ pub(crate) fn preprocess_macho(
for section_info in sections_info {
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 =
Some(section_info.size.get(NativeEndian) / STUB_ADDRESS_OFFSET);
Some(section_info.size.get(LE) / STUB_ADDRESS_OFFSET);
break 'cmds;
}
@ -378,14 +449,14 @@ pub(crate) fn preprocess_macho(
let shared_lib_filename = shared_lib.file_name();
for _ in 0..num_load_cmds {
let info = load_struct_inplace::<macho::LoadCommand<LittleEndian>>(exec_data, offset);
let cmd = info.cmd.get(NativeEndian);
let cmdsize = info.cmdsize.get(NativeEndian);
let info = load_struct_inplace::<macho::LoadCommand<LE>>(exec_data, offset);
let cmd = info.cmd.get(LE);
let cmdsize = info.cmdsize.get(LE);
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(
&exec_data[lazy_bind_offset..],
@ -412,8 +483,8 @@ pub(crate) fn preprocess_macho(
}
}
} else if cmd == macho::LC_LOAD_DYLIB {
let info = load_struct_inplace::<DylibCommand<LittleEndian>>(exec_data, offset);
let name_offset = info.dylib.name.offset.get(NativeEndian) as usize;
let info = load_struct_inplace::<DylibCommand<LE>>(exec_data, offset);
let name_offset = info.dylib.name.offset.get(LE) as usize;
let str_start_index = offset + name_offset;
let str_end_index = offset + cmdsize as usize;
let str_bytes = &exec_data[str_start_index..str_end_index];
@ -581,7 +652,7 @@ pub(crate) fn preprocess_macho(
fn gen_macho_le(
exec_data: &[u8],
md: &mut metadata::Metadata,
md: &mut Metadata,
out_filename: &Path,
macho_load_so_offset: usize,
_target: &Triple,
@ -600,19 +671,18 @@ fn gen_macho_le(
use macho::{Section64, SegmentCommand64};
let exec_header = load_struct_inplace::<macho::MachHeader64<LittleEndian>>(exec_data, 0);
let num_load_cmds = exec_header.ncmds.get(NativeEndian);
let size_of_cmds = exec_header.sizeofcmds.get(NativeEndian) as usize;
let exec_header = load_struct_inplace::<macho::MachHeader64<LE>>(exec_data, 0);
let num_load_cmds = exec_header.ncmds.get(LE);
let size_of_cmds = exec_header.sizeofcmds.get(LE) as usize;
// Add a new text segment and data segment
let segment_cmd_size = mem::size_of::<SegmentCommand64<LittleEndian>>();
let section_size = mem::size_of::<Section64<LittleEndian>>();
let segment_cmd_size = mem::size_of::<SegmentCommand64<LE>>();
let section_size = mem::size_of::<Section64<LE>>();
// We need the full command size, including the dynamic-length string at the end.
// To get that, we need to load the command.
let info =
load_struct_inplace::<macho::LoadCommand<LittleEndian>>(exec_data, macho_load_so_offset);
let total_cmd_size = info.cmdsize.get(NativeEndian) as usize;
let info = load_struct_inplace::<macho::LoadCommand<LE>>(exec_data, macho_load_so_offset);
let total_cmd_size = info.cmdsize.get(LE) as usize;
// ======================== Important TODO ==========================
// 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);
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.
// -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.
out_header.ncmds.set(LittleEndian, num_load_cmds - 1);
out_header.ncmds.set(LE, num_load_cmds - 1);
out_header
.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
@ -681,50 +751,37 @@ fn gen_macho_le(
// minus one because we "deleted" a load command
for _ in 0..(num_load_cmds - 1) {
let info = load_struct_inplace::<macho::LoadCommand<LittleEndian>>(&out_mmap, offset);
let cmd_size = info.cmdsize.get(NativeEndian) as usize;
let info = load_struct_inplace::<macho::LoadCommand<LE>>(&out_mmap, offset);
let cmd_size = info.cmdsize.get(LE) as usize;
match info.cmd.get(NativeEndian) {
match info.cmd.get(LE) {
macho::LC_SEGMENT_64 => {
let cmd = load_struct_inplace_mut::<macho::SegmentCommand64<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd =
load_struct_inplace_mut::<macho::SegmentCommand64<LE>>(&mut out_mmap, offset);
// Ignore page zero, it never moves.
if cmd.segname == "__PAGEZERO\0\0\0\0\0\0".as_bytes()
|| cmd.vmaddr.get(NativeEndian) == 0
{
if cmd.segname == "__PAGEZERO\0\0\0\0\0\0".as_bytes() || cmd.vmaddr.get(LE) == 0 {
offset += cmd_size;
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.
// As such, its file offset does not change.
// Instead, its file size should be increased.
if old_file_offest > 0 {
cmd.fileoff
.set(LittleEndian, old_file_offest + md.added_byte_count);
cmd.vmaddr.set(
LittleEndian,
cmd.vmaddr.get(NativeEndian) + md.added_byte_count,
);
cmd.fileoff.set(LE, old_file_offest + md.added_byte_count);
cmd.vmaddr.set(LE, cmd.vmaddr.get(LE) + md.added_byte_count);
} else {
cmd.filesize.set(
LittleEndian,
cmd.filesize.get(NativeEndian) + md.added_byte_count,
);
cmd.vmsize.set(
LittleEndian,
cmd.vmsize.get(NativeEndian) + md.added_byte_count,
);
cmd.filesize
.set(LE, cmd.filesize.get(LE) + md.added_byte_count);
cmd.vmsize.set(LE, cmd.vmsize.get(LE) + md.added_byte_count);
}
// let num_sections = cmd.nsects.get(NativeEndian);
// let sections = load_structs_inplace_mut::<macho::Section64<LittleEndian>>(
// let num_sections = cmd.nsects.get(LE);
// let sections = load_structs_inplace_mut::<macho::Section64<LE >>(
// &mut out_mmap,
// offset + mem::size_of::<macho::SegmentCommand64<LittleEndian>>(),
// offset + mem::size_of::<macho::SegmentCommand64<LE >>(),
// num_sections as usize,
// );
// struct Relocation {
@ -736,34 +793,34 @@ fn gen_macho_le(
// for section in sections {
// section.addr.set(
// LittleEndian,
// section.addr.get(NativeEndian) + md.added_byte_count as u64,
// LE ,
// section.addr.get(LE) + md.added_byte_count as u64,
// );
// // If offset is zero, don't update it.
// // 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 {
// section
// .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(NativeEndian) as i32);
// // dbg!(&section.reloff.get(LE));
// // dbg!(section.reloff.get(LE) as i32);
// // dbg!(&section);
// // dbg!(&md.added_byte_count);
// // dbg!(String::from_utf8_lossy(&section.sectname));
// if section.nreloc.get(NativeEndian) > 0 {
// if section.nreloc.get(LE) > 0 {
// section.reloff.set(
// LittleEndian,
// section.reloff.get(NativeEndian) + md.added_byte_count as u32,
// LE ,
// section.reloff.get(LE) + md.added_byte_count as u32,
// );
// }
// relocation_offsets.push(Relocation {
// offset: section.reloff.get(NativeEndian),
// num_relocations: section.nreloc.get(NativeEndian),
// offset: section.reloff.get(LE),
// num_relocations: section.nreloc.get(LE),
// });
// }
@ -773,7 +830,7 @@ fn gen_macho_le(
// num_relocations,
// } in relocation_offsets
// {
// let relos = load_structs_inplace_mut::<macho::Relocation<LittleEndian>>(
// let relos = load_structs_inplace_mut::<macho::Relocation<LE >>(
// &mut out_mmap,
// offset 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!
// for relo in relos.iter_mut() {
// if relo.r_scattered(LittleEndian, cpu_type) {
// let mut scattered_info = relo.scattered_info(NativeEndian);
// if relo.r_scattered(LE , cpu_type) {
// let mut scattered_info = relo.scattered_info(LE);
// if !scattered_info.r_pcrel {
// 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_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.
// 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 => {
let cmd = load_struct_inplace_mut::<macho::SymtabCommand<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd =
load_struct_inplace_mut::<macho::SymtabCommand<LE>>(&mut out_mmap, offset);
let sym_offset = cmd.symoff.get(NativeEndian);
let num_syms = cmd.nsyms.get(NativeEndian);
let sym_offset = cmd.symoff.get(LE);
let num_syms = cmd.nsyms.get(LE);
if num_syms > 0 {
cmd.symoff
.set(LittleEndian, sym_offset + md.added_byte_count as u32);
cmd.symoff.set(LE, sym_offset + md.added_byte_count as u32);
}
if cmd.strsize.get(NativeEndian) > 0 {
cmd.stroff.set(
LittleEndian,
cmd.stroff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.strsize.get(LE) > 0 {
cmd.stroff
.set(LE, cmd.stroff.get(LE) + 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,
sym_offset as usize + md.added_byte_count as usize,
num_syms as usize,
@ -829,59 +881,44 @@ fn gen_macho_le(
for entry in table {
let entry_type = entry.n_type & macho::N_TYPE;
if entry_type == macho::N_ABS || entry_type == macho::N_SECT {
entry.n_value.set(
LittleEndian,
entry.n_value.get(NativeEndian) + md.added_byte_count,
);
entry
.n_value
.set(LE, entry.n_value.get(LE) + md.added_byte_count);
}
}
}
macho::LC_DYSYMTAB => {
let cmd = load_struct_inplace_mut::<macho::DysymtabCommand<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd =
load_struct_inplace_mut::<macho::DysymtabCommand<LE>>(&mut out_mmap, offset);
if cmd.ntoc.get(NativeEndian) > 0 {
cmd.tocoff.set(
LittleEndian,
cmd.tocoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.ntoc.get(LE) > 0 {
cmd.tocoff
.set(LE, cmd.tocoff.get(LE) + md.added_byte_count as u32);
}
if cmd.nmodtab.get(NativeEndian) > 0 {
cmd.modtaboff.set(
LittleEndian,
cmd.modtaboff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.nmodtab.get(LE) > 0 {
cmd.modtaboff
.set(LE, cmd.modtaboff.get(LE) + md.added_byte_count as u32);
}
if cmd.nextrefsyms.get(NativeEndian) > 0 {
cmd.extrefsymoff.set(
LittleEndian,
cmd.extrefsymoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.nextrefsyms.get(LE) > 0 {
cmd.extrefsymoff
.set(LE, cmd.extrefsymoff.get(LE) + md.added_byte_count as u32);
}
if cmd.nindirectsyms.get(NativeEndian) > 0 {
cmd.indirectsymoff.set(
LittleEndian,
cmd.indirectsymoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.nindirectsyms.get(LE) > 0 {
cmd.indirectsymoff
.set(LE, cmd.indirectsymoff.get(LE) + md.added_byte_count as u32);
}
if cmd.nextrel.get(NativeEndian) > 0 {
cmd.extreloff.set(
LittleEndian,
cmd.extreloff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.nextrel.get(LE) > 0 {
cmd.extreloff
.set(LE, cmd.extreloff.get(LE) + md.added_byte_count as u32);
}
if cmd.nlocrel.get(NativeEndian) > 0 {
cmd.locreloff.set(
LittleEndian,
cmd.locreloff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.nlocrel.get(LE) > 0 {
cmd.locreloff
.set(LE, cmd.locreloff.get(LE) + md.added_byte_count as u32);
}
// 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.
}
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,
offset,
);
if cmd.nhints.get(NativeEndian) > 0 {
cmd.offset.set(
LittleEndian,
cmd.offset.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.nhints.get(LE) > 0 {
cmd.offset
.set(LE, cmd.offset.get(LE) + md.added_byte_count as u32);
}
}
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,
offset,
);
if cmd.datasize.get(NativeEndian) > 0 {
cmd.dataoff.set(
LittleEndian,
cmd.dataoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.datasize.get(LE) > 0 {
cmd.dataoff
.set(LE, cmd.dataoff.get(LE) + md.added_byte_count as u32);
// 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.
// As such, updating it should not be required.
@ -920,36 +953,30 @@ fn gen_macho_le(
}
macho::LC_DATA_IN_CODE => {
let (offset, size) = {
let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LittleEndian>>(
let cmd = load_struct_inplace_mut::<macho::LinkeditDataCommand<LE>>(
&mut out_mmap,
offset,
);
if cmd.datasize.get(NativeEndian) > 0 {
cmd.dataoff.set(
LittleEndian,
cmd.dataoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.datasize.get(LE) > 0 {
cmd.dataoff
.set(LE, cmd.dataoff.get(LE) + md.added_byte_count as u32);
}
(
cmd.dataoff.get(NativeEndian),
cmd.datasize.get(NativeEndian),
)
(cmd.dataoff.get(LE), cmd.datasize.get(LE))
};
// Update every data in code entry.
if size > 0 {
let entry_size = mem::size_of::<macho::DataInCodeEntry<LittleEndian>>();
let entries = load_structs_inplace_mut::<macho::DataInCodeEntry<LittleEndian>>(
let entry_size = mem::size_of::<macho::DataInCodeEntry<LE>>();
let entries = load_structs_inplace_mut::<macho::DataInCodeEntry<LE>>(
&mut out_mmap,
offset as usize,
size as usize / entry_size,
);
for entry in entries.iter_mut() {
entry.offset.set(
LittleEndian,
entry.offset.get(NativeEndian) + md.added_byte_count as u32,
)
entry
.offset
.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_DYLD_EXPORTS_TRIE
| 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,
offset,
);
if cmd.datasize.get(NativeEndian) > 0 {
cmd.dataoff.set(
LittleEndian,
cmd.dataoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.datasize.get(LE) > 0 {
cmd.dataoff
.set(LE, cmd.dataoff.get(LE) + md.added_byte_count as u32);
}
}
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,
offset,
);
if cmd.cryptsize.get(NativeEndian) > 0 {
cmd.cryptoff.set(
LittleEndian,
cmd.cryptoff.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.cryptsize.get(LE) > 0 {
cmd.cryptoff
.set(LE, cmd.cryptoff.get(LE) + md.added_byte_count as u32);
}
}
macho::LC_DYLD_INFO | macho::LC_DYLD_INFO_ONLY => {
let cmd = load_struct_inplace_mut::<macho::DyldInfoCommand<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd =
load_struct_inplace_mut::<macho::DyldInfoCommand<LE>>(&mut out_mmap, offset);
if cmd.rebase_size.get(NativeEndian) > 0 {
cmd.rebase_off.set(
LittleEndian,
cmd.rebase_off.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.rebase_size.get(LE) > 0 {
cmd.rebase_off
.set(LE, cmd.rebase_off.get(LE) + md.added_byte_count as u32);
}
if cmd.bind_size.get(NativeEndian) > 0 {
cmd.bind_off.set(
LittleEndian,
cmd.bind_off.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.bind_size.get(LE) > 0 {
cmd.bind_off
.set(LE, cmd.bind_off.get(LE) + md.added_byte_count as u32);
}
if cmd.weak_bind_size.get(NativeEndian) > 0 {
cmd.weak_bind_off.set(
LittleEndian,
cmd.weak_bind_off.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.weak_bind_size.get(LE) > 0 {
cmd.weak_bind_off
.set(LE, cmd.weak_bind_off.get(LE) + md.added_byte_count as u32);
}
if cmd.lazy_bind_size.get(NativeEndian) > 0 {
cmd.lazy_bind_off.set(
LittleEndian,
cmd.lazy_bind_off.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.lazy_bind_size.get(LE) > 0 {
cmd.lazy_bind_off
.set(LE, cmd.lazy_bind_off.get(LE) + md.added_byte_count as u32);
}
// TODO: Parse and update the related tables here.
@ -1026,40 +1039,26 @@ fn gen_macho_le(
// Also `xcrun dyldinfo` is useful for debugging this.
}
macho::LC_SYMSEG => {
let cmd = load_struct_inplace_mut::<macho::SymsegCommand<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd =
load_struct_inplace_mut::<macho::SymsegCommand<LE>>(&mut out_mmap, offset);
if cmd.size.get(NativeEndian) > 0 {
cmd.offset.set(
LittleEndian,
cmd.offset.get(NativeEndian) + md.added_byte_count as u32,
);
if cmd.size.get(LE) > 0 {
cmd.offset
.set(LE, cmd.offset.get(LE) + md.added_byte_count as u32);
}
}
macho::LC_MAIN => {
let cmd = load_struct_inplace_mut::<macho::EntryPointCommand<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd =
load_struct_inplace_mut::<macho::EntryPointCommand<LE>>(&mut out_mmap, offset);
cmd.entryoff.set(
LittleEndian,
cmd.entryoff.get(NativeEndian) + md.added_byte_count,
);
cmd.entryoff
.set(LE, cmd.entryoff.get(LE) + md.added_byte_count);
}
macho::LC_NOTE => {
let cmd = load_struct_inplace_mut::<macho::NoteCommand<LittleEndian>>(
&mut out_mmap,
offset,
);
let cmd = load_struct_inplace_mut::<macho::NoteCommand<LE>>(&mut out_mmap, offset);
if cmd.size.get(NativeEndian) > 0 {
cmd.offset.set(
LittleEndian,
cmd.offset.get(NativeEndian) + md.added_byte_count,
);
if cmd.size.get(LE) > 0 {
cmd.offset.set(LE, cmd.offset.get(LE) + md.added_byte_count);
}
}
macho::LC_ID_DYLIB
@ -1125,7 +1124,7 @@ fn gen_macho_le(
// fn scan_macho_dynamic_deps(
// _exec_obj: &object::File,
// _md: &mut metadata::Metadata,
// _md: &mut Metadata,
// _app_syms: &[Symbol],
// _shared_lib: &str,
// _exec_data: &[u8],
@ -1223,7 +1222,7 @@ fn surgery_macho_help(
_out_filename: &Path,
verbose: bool,
_time: bool,
md: &metadata::Metadata,
md: &Metadata,
exec_mmap: &mut MmapMut,
offset_ref: &mut usize, // TODO return this instead of taking a mutable reference to it
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
// {
// let cmd =
// load_struct_inplace_mut::<macho::SegmentCommand64<LittleEndian>>(exec_mmap, cmd_offset);
// let size_of_section = mem::size_of::<macho::Section64<LittleEndian>>() as u32;
// load_struct_inplace_mut::<macho::SegmentCommand64<LE >>(exec_mmap, cmd_offset);
// let size_of_section = mem::size_of::<macho::Section64<LE >>() as u32;
// let size_of_cmd = mem::size_of_val(cmd);
// cmd_offset += size_of_cmd;
// cmd.cmd.set(LittleEndian, macho::LC_SEGMENT_64);
// cmd.cmd.set(LE , macho::LC_SEGMENT_64);
// 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.vmaddr
// .set(LittleEndian, new_rodata_section_vaddr as u64);
// .set(LE , new_rodata_section_vaddr as u64);
// cmd.vmsize.set(
// LittleEndian,
// LE ,
// (new_text_section_vaddr - new_rodata_section_vaddr) as u64,
// );
// cmd.fileoff
// .set(LittleEndian, new_rodata_section_offset as u64);
// .set(LE , new_rodata_section_offset as u64);
// cmd.filesize.set(
// LittleEndian,
// LE ,
// (new_text_section_offset - new_rodata_section_offset) as u64,
// );
// cmd.nsects.set(LittleEndian, 1);
// cmd.maxprot.set(LittleEndian, 0x00000003);
// cmd.initprot.set(LittleEndian, 0x00000003);
// cmd.nsects.set(LE , 1);
// cmd.maxprot.set(LE , 0x00000003);
// cmd.initprot.set(LE , 0x00000003);
// // 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);
// cmd_offset += size_of_cmd;
// cmd.sectname = *b"__const\0\0\0\0\0\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(
// LittleEndian,
// LE ,
// (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.align.set(LittleEndian, 12); // TODO should this be 4096?
// cmd.reloff.set(LittleEndian, 264); // TODO this should NOT be hardcoded! Should get it from somewhere.
// cmd.offset.set(LE , 0); // TODO is this offset since the start of the file, or segment offset?
// cmd.align.set(LE , 12); // TODO should this be 4096?
// cmd.reloff.set(LE , 264); // TODO this should NOT be hardcoded! Should get it from somewhere.
// }
// {
// let cmd =
// load_struct_inplace_mut::<macho::SegmentCommand64<LittleEndian>>(exec_mmap, cmd_offset);
// let size_of_section = mem::size_of::<macho::Section64<LittleEndian>>() as u32;
// load_struct_inplace_mut::<macho::SegmentCommand64<LE >>(exec_mmap, cmd_offset);
// let size_of_section = mem::size_of::<macho::Section64<LE >>() as u32;
// let size_of_cmd = mem::size_of_val(cmd);
// cmd_offset += size_of_cmd;
// cmd.cmd.set(LittleEndian, macho::LC_SEGMENT_64);
// cmd.cmd.set(LE , macho::LC_SEGMENT_64);
// 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.vmaddr.set(LittleEndian, new_text_section_vaddr as u64);
// cmd.vmaddr.set(LE , new_text_section_vaddr as u64);
// cmd.vmsize
// .set(LittleEndian, (offset - new_text_section_offset) as u64);
// .set(LE , (offset - new_text_section_offset) as u64);
// cmd.fileoff
// .set(LittleEndian, new_text_section_offset as u64);
// .set(LE , new_text_section_offset as u64);
// cmd.filesize
// .set(LittleEndian, (offset - new_text_section_offset) as u64);
// cmd.nsects.set(LittleEndian, 1);
// cmd.maxprot.set(LittleEndian, 0x00000005); // this is what a zig-generated host had
// cmd.initprot.set(LittleEndian, 0x00000005); // this is what a zig-generated host had
// .set(LE , (offset - new_text_section_offset) as u64);
// cmd.nsects.set(LE , 1);
// cmd.maxprot.set(LE , 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.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
// .set(LittleEndian, (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.align.set(LittleEndian, 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.reloff.set(LittleEndian, 264); // TODO this should NOT be hardcoded! Should get it from somewhere.
// .set(LE , (offset - new_text_section_offset) as u64);
// cmd.offset.set(LE , 0); // TODO is this offset since the start of the file, or segment offset?
// cmd.align.set(LE , 12); // TODO this is 4096 (2^12) - which load_align_constraint does, above - but should it?
// cmd.flags.set(LE , 0x80000400); // TODO this is what a zig-generated host had
// cmd.reloff.set(LE , 264); // TODO this should NOT be hardcoded! Should get it from somewhere.
// }
// 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
// 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,
// 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_size = endian::U64::new(
// LittleEndian,
// sym.st_value.set(LE , func_virt_offset as u64);
// sym.st_size.set(
// LE ,
// match app_func_size_map.get(func_name) {
// Some(size) => *size,
// 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,
};
// 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)]
use std::path::Path;

View file

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

View file

@ -6,9 +6,10 @@
, 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
rustPlatform = pkgs.rustPlatform;
llvmPkgs = pkgs.llvmPackages_13;
# nix does not store libs in /usr/lib or /lib
nixGlibcPath = if pkgs.stdenv.isLinux then "${pkgs.glibc.out}/lib" else "";
@ -23,7 +24,7 @@ rustPlatform.buildRustPackage {
lockFile = ./Cargo.lock;
outputHashes = {
"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=";
"plotters-0.3.1" = "sha256-noy/RSjoEPZZbOJTZw1yxGcX5S+2q/7mxnUrzDyxOFw=";
"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. Run `git init` in the new folder.
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. 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`.

100
devtools/flake.lock generated
View file

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

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 = {
# 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
flake-utils.url = "github:numtide/flake-utils";
};
@ -24,7 +24,7 @@
vscodeWithExtensions = pkgs.vscode-with-extensions.override {
vscodeExtensions = with pkgs.vscode-extensions; [
matklad.rust-analyzer
eamodio.gitlens
# eamodio.gitlens
bbenoist.nix
vadimcn.vscode-lldb
tamasfe.even-better-toml
@ -33,13 +33,12 @@
{
name = "roc-lang-support";
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
sha256 = "sha256-mabNegZ+XPQ6EIHFk6jz2mAPLHAU6Pm3w0SiFB7IE+s=";
}
]
;
};
in [ vscodeWithExtensions devInputs ];

View file

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

View file

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

View file

@ -1,16 +1,15 @@
#![allow(non_snake_case)]
mod glue;
mod test_glue;
use core::ffi::c_void;
use glue::Op;
use roc_std::RocStr;
use std::ffi::CStr;
use std::io::Write;
use std::mem::MaybeUninit;
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]
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]
pub extern "C" fn rust_main() -> i32 {
use glue::discriminant_Op::*;
use test_glue::discriminant_Op::*;
println!("Let's do things!");
@ -95,16 +94,18 @@ pub extern "C" fn rust_main() -> i32 {
loop {
match dbg!(op.discriminant()) {
StdoutWrite => {
let output: RocStr = unsafe { op.get_StdoutWrite_0() };
op = unsafe { op.get_StdoutWrite_1().force_thunk(()) };
let stdout_write = unsafe { op.get_StdoutWrite() };
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()) {
panic!("Writing to stdout failed! {:?}", e);
}
}
StderrWrite => {
let output: RocStr = unsafe { op.get_StderrWrite_0() };
op = unsafe { op.get_StderrWrite_1().force_thunk(()) };
let stderr_write = unsafe { op.get_StderrWrite() };
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()) {
panic!("Writing to stdout failed! {:?}", e);

View file

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

View file

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

View file

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

View file

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

View file

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

68
flake.lock generated
View file

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

View file

@ -2,7 +2,7 @@
description = "Roc flake";
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-overlay = {

View file

@ -3,14 +3,15 @@
# - update `channel = "RUST_VERSION"`
# - update `channel = "RUST_VERSION"` in examples/platform-switching/rust-platform/rust-toolchain.toml
# - 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 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
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"
components = [
# 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;
`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`