mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 22:09:09 +00:00
Merge branch 'main' into symbol_tags
This commit is contained in:
commit
297658caba
92 changed files with 2319 additions and 1762 deletions
4
.github/workflows/windows_release_build.yml
vendored
4
.github/workflows/windows_release_build.yml
vendored
|
@ -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: |
|
||||
|
|
4
.github/workflows/windows_tests.yml
vendored
4
.github/workflows/windows_tests.yml
vendored
|
@ -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
5
Cargo.lock
generated
|
@ -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",
|
||||
]
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
||||
[<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)
|
||||
|
||||
[<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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
||||
if std::path::Path::exists(&zig_str_path) {
|
||||
return zig_str_path;
|
||||
None
|
||||
}
|
||||
|
||||
// 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;
|
||||
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;
|
||||
}
|
||||
|
||||
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",
|
||||
|
|
7
crates/compiler/builtins/bitcode/src/glue.zig
Normal file
7
crates/compiler/builtins/bitcode/src/glue.zig
Normal file
|
@ -0,0 +1,7 @@
|
|||
// This is a glue package that just re-exports other libs useful for zig hosts.
|
||||
// Long term, a slimmed down version of these libraries without all of the roc builtins should be create via `roc glue`.
|
||||
// We also should make RocList use comptime types in order to make it nice to use in zig.
|
||||
|
||||
pub const dec = @import("dec.zig");
|
||||
pub const list = @import("list.zig");
|
||||
pub const str = @import("str.zig");
|
|
@ -133,6 +133,7 @@ comptime {
|
|||
exportStrFn(str.countSegments, "count_segments");
|
||||
exportStrFn(str.countGraphemeClusters, "count_grapheme_clusters");
|
||||
exportStrFn(str.countUtf8Bytes, "count_utf8_bytes");
|
||||
exportStrFn(str.isEmpty, "is_empty");
|
||||
exportStrFn(str.getCapacity, "capacity");
|
||||
exportStrFn(str.startsWith, "starts_with");
|
||||
exportStrFn(str.startsWithScalar, "starts_with_scalar");
|
||||
|
|
|
@ -1525,6 +1525,10 @@ pub fn countUtf8Bytes(string: RocStr) callconv(.C) usize {
|
|||
return string.len();
|
||||
}
|
||||
|
||||
pub fn isEmpty(string: RocStr) callconv(.C) bool {
|
||||
return string.isEmpty();
|
||||
}
|
||||
|
||||
pub fn getCapacity(string: RocStr) callconv(.C) usize {
|
||||
return string.getCapacity();
|
||||
}
|
||||
|
|
|
@ -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 ->
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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!(),
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use roc_collections::{VecMap, VecSet};
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::ident::Ident;
|
||||
use roc_module::symbol::{IdentId, IdentIds, ModuleId, Symbol};
|
||||
use roc_problem::can::RuntimeError;
|
||||
|
@ -470,9 +471,13 @@ pub fn create_alias(
|
|||
}
|
||||
|
||||
if !hidden.is_empty() {
|
||||
panic!(
|
||||
internal_error!(
|
||||
"Found unbound type variables {:?} \n in type alias {:?} {:?} {:?} : {:?}",
|
||||
hidden, name, &vars, &infer_ext_in_output_variables, &typ
|
||||
hidden,
|
||||
name,
|
||||
&vars,
|
||||
&infer_ext_in_output_variables,
|
||||
&typ
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// use bumpalo::collections::string::String;
|
||||
// use bumpalo::collections::vec::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_parse::ast::Expr;
|
||||
// use roc_parse::ast::{Attempting, Expr};
|
||||
// use roc_parse::ident;
|
||||
|
@ -12,7 +13,7 @@ use roc_region::all::Region;
|
|||
// use std::iter::Peekable;
|
||||
|
||||
pub fn canonical_string_literal<'a>(_arena: &Bump, _raw: &'a str, _region: Region) -> Expr<'a> {
|
||||
panic!("TODO restore canonicalization");
|
||||
internal_error!("TODO restore canonicalization");
|
||||
}
|
||||
// let mut problems = std::vec::Vec::new();
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,6 +2962,12 @@ fn setae_reg64(buf: &mut Vec<'_, u8>, reg: X86_64GeneralReg) {
|
|||
set_reg64_help(0x93, buf, reg);
|
||||
}
|
||||
|
||||
/// `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) {
|
||||
|
@ -3413,6 +3422,15 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lea_reg64() {
|
||||
disassembler_test!(
|
||||
lea_reg64,
|
||||
|reg| format!("lea {}, [rip]", reg),
|
||||
ALL_GENERAL_REGS
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mov_reg64_reg64() {
|
||||
disassembler_test!(
|
||||
|
@ -3764,8 +3782,8 @@ mod tests {
|
|||
cmp_reg64_reg64,
|
||||
|_, dst: X86_64GeneralReg, src: X86_64GeneralReg| format!(
|
||||
"cmp {}, {}",
|
||||
dbg!(dst.low_16bits_string()),
|
||||
dbg!(src.low_16bits_string())
|
||||
dst.low_16bits_string(),
|
||||
src.low_16bits_string()
|
||||
),
|
||||
[RegisterWidth::W16],
|
||||
ALL_GENERAL_REGS,
|
||||
|
@ -3776,8 +3794,8 @@ mod tests {
|
|||
cmp_reg64_reg64,
|
||||
|_, dst: X86_64GeneralReg, src: X86_64GeneralReg| format!(
|
||||
"cmp {}, {}",
|
||||
dbg!(dst.low_32bits_string()),
|
||||
dbg!(src.low_32bits_string())
|
||||
dst.low_32bits_string(),
|
||||
src.low_32bits_string()
|
||||
),
|
||||
[RegisterWidth::W32],
|
||||
ALL_GENERAL_REGS,
|
||||
|
|
|
@ -12,10 +12,10 @@ use roc_error_macros::internal_error;
|
|||
use roc_module::ident::ModuleName;
|
||||
use roc_module::low_level::{LowLevel, LowLevelWrapperType};
|
||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||
use roc_mono::code_gen_help::CodeGenHelp;
|
||||
use roc_mono::code_gen_help::{CallerProc, CodeGenHelp};
|
||||
use roc_mono::ir::{
|
||||
BranchInfo, CallType, Expr, JoinPointId, ListLiteralElement, Literal, Param, Proc, ProcLayout,
|
||||
SelfRecursive, Stmt,
|
||||
BranchInfo, CallType, Expr, HigherOrderLowLevel, JoinPointId, ListLiteralElement, Literal,
|
||||
Param, Proc, ProcLayout, SelfRecursive, Stmt,
|
||||
};
|
||||
use roc_mono::layout::{
|
||||
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, TagIdIntType,
|
||||
|
@ -65,8 +65,21 @@ pub enum Relocation {
|
|||
trait Backend<'a> {
|
||||
fn env(&self) -> &Env<'a>;
|
||||
fn interns(&self) -> &Interns;
|
||||
fn interns_mut(&mut self) -> &mut Interns;
|
||||
fn interner(&self) -> &STLayoutInterner<'a>;
|
||||
|
||||
fn debug_symbol(&mut self, name: &str) -> Symbol {
|
||||
let module_id = self.env().module_id;
|
||||
let ident_ids = self
|
||||
.interns_mut()
|
||||
.all_ident_ids
|
||||
.get_mut(&module_id)
|
||||
.unwrap();
|
||||
|
||||
let ident_id = ident_ids.add_str(name);
|
||||
Symbol::new(self.env().module_id, ident_id)
|
||||
}
|
||||
|
||||
// This method is suboptimal, but it seems to be the only way to make rust understand
|
||||
// that all of these values can be mutable at the same time. By returning them together,
|
||||
// rust understands that they are part of a single use of mutable self.
|
||||
|
@ -77,6 +90,7 @@ trait Backend<'a> {
|
|||
&mut STLayoutInterner<'a>,
|
||||
&mut Interns,
|
||||
&mut CodeGenHelp<'a>,
|
||||
&mut Vec<'a, CallerProc<'a>>,
|
||||
);
|
||||
|
||||
fn function_symbol_to_string<'b, I>(
|
||||
|
@ -201,7 +215,7 @@ trait Backend<'a> {
|
|||
// If this layout requires a new RC proc, we get enough info to create a linker symbol
|
||||
// for it. Here we don't create linker symbols at this time, but in Wasm backend, we do.
|
||||
let (rc_stmt, new_specializations) = {
|
||||
let (module_id, layout_interner, interns, rc_proc_gen) =
|
||||
let (module_id, layout_interner, interns, rc_proc_gen, _) =
|
||||
self.module_interns_helpers_mut();
|
||||
let ident_ids = interns.all_ident_ids.get_mut(&module_id).unwrap();
|
||||
|
||||
|
@ -329,7 +343,7 @@ trait Backend<'a> {
|
|||
arg_layouts,
|
||||
ret_layout,
|
||||
);
|
||||
} else if sym.is_builtin() {
|
||||
} else if func_sym.name().is_builtin() {
|
||||
// These builtins can be built through `build_fn_call` as well, but the
|
||||
// implementation in `build_builtin` inlines some of the symbols.
|
||||
return self.build_builtin(
|
||||
|
@ -373,6 +387,9 @@ trait Backend<'a> {
|
|||
layout,
|
||||
)
|
||||
}
|
||||
CallType::HigherOrder(higher_order) => {
|
||||
self.build_higher_order_lowlevel(sym, higher_order, *layout)
|
||||
}
|
||||
x => todo!("the call type, {:?}", x),
|
||||
}
|
||||
}
|
||||
|
@ -486,6 +503,22 @@ trait Backend<'a> {
|
|||
);
|
||||
self.build_num_add(sym, &args[0], &args[1], ret_layout)
|
||||
}
|
||||
LowLevel::NumAddWrap => {
|
||||
debug_assert_eq!(
|
||||
2,
|
||||
args.len(),
|
||||
"NumAdd: expected to have exactly two argument"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
arg_layouts[0], arg_layouts[1],
|
||||
"NumAdd: expected all arguments of to have the same layout"
|
||||
);
|
||||
debug_assert_eq!(
|
||||
arg_layouts[0], *ret_layout,
|
||||
"NumAdd: expected to have the same argument and return layout"
|
||||
);
|
||||
self.build_num_add(sym, &args[0], &args[1], ret_layout)
|
||||
}
|
||||
LowLevel::NumAddChecked => {
|
||||
self.build_num_add_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout)
|
||||
}
|
||||
|
@ -1070,6 +1103,14 @@ trait Backend<'a> {
|
|||
);
|
||||
self.build_ptr_cast(sym, &args[0])
|
||||
}
|
||||
LowLevel::PtrWrite => {
|
||||
let element_layout = match self.interner().get(*ret_layout) {
|
||||
Layout::Boxed(boxed) => boxed,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
self.build_ptr_write(*sym, args[0], args[1], element_layout);
|
||||
}
|
||||
LowLevel::RefCountDec => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::UTILS_DECREF.to_string(),
|
||||
|
@ -1084,6 +1125,34 @@ trait Backend<'a> {
|
|||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::NumToStr => {
|
||||
let arg_layout = arg_layouts[0];
|
||||
let intrinsic = match self.interner().get(arg_layout) {
|
||||
Layout::Builtin(Builtin::Int(width)) => &bitcode::STR_FROM_INT[width],
|
||||
Layout::Builtin(Builtin::Float(width)) => &bitcode::STR_FROM_FLOAT[width],
|
||||
Layout::Builtin(Builtin::Decimal) => bitcode::DEC_TO_STR,
|
||||
x => internal_error!("NumToStr is not defined for {:?}", x),
|
||||
};
|
||||
|
||||
self.build_fn_call(sym, intrinsic.to_string(), args, arg_layouts, ret_layout)
|
||||
}
|
||||
LowLevel::StrIsEmpty => {
|
||||
let intrinsic = bitcode::STR_IS_EMPTY.to_string();
|
||||
self.build_fn_call(sym, intrinsic, args, arg_layouts, ret_layout);
|
||||
}
|
||||
LowLevel::NumIntCast => {
|
||||
let source_width = match self.interner().get(arg_layouts[0]) {
|
||||
Layout::Builtin(Builtin::Int(width)) => width,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let target_width = match self.interner().get(*ret_layout) {
|
||||
Layout::Builtin(Builtin::Int(width)) => width,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
self.build_num_int_cast(sym, &args[0], source_width, target_width)
|
||||
}
|
||||
x => todo!("low level, {:?}", x),
|
||||
}
|
||||
}
|
||||
|
@ -1133,16 +1202,24 @@ trait Backend<'a> {
|
|||
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
|
||||
}
|
||||
Symbol::BOOL_TRUE => {
|
||||
let bool_layout = Layout::BOOL;
|
||||
self.load_literal(&Symbol::DEV_TMP, &bool_layout, &Literal::Bool(true));
|
||||
self.return_symbol(&Symbol::DEV_TMP, &bool_layout);
|
||||
self.free_symbol(&Symbol::DEV_TMP)
|
||||
const LITERAL: &Literal<'static> = &Literal::Bool(true);
|
||||
const BOOL_LAYOUT: &InLayout<'static> = &Layout::BOOL;
|
||||
|
||||
if self.env().lazy_literals {
|
||||
self.literal_map().insert(*sym, (LITERAL, BOOL_LAYOUT));
|
||||
} else {
|
||||
self.load_literal(sym, BOOL_LAYOUT, LITERAL);
|
||||
}
|
||||
}
|
||||
Symbol::BOOL_FALSE => {
|
||||
let bool_layout = Layout::BOOL;
|
||||
self.load_literal(&Symbol::DEV_TMP, &bool_layout, &Literal::Bool(false));
|
||||
self.return_symbol(&Symbol::DEV_TMP, &bool_layout);
|
||||
self.free_symbol(&Symbol::DEV_TMP)
|
||||
const LITERAL: &Literal<'static> = &Literal::Bool(false);
|
||||
const BOOL_LAYOUT: &InLayout<'static> = &Layout::BOOL;
|
||||
|
||||
if self.env().lazy_literals {
|
||||
self.literal_map().insert(*sym, (LITERAL, BOOL_LAYOUT));
|
||||
} else {
|
||||
self.load_literal(sym, BOOL_LAYOUT, LITERAL);
|
||||
}
|
||||
}
|
||||
Symbol::STR_IS_VALID_SCALAR => {
|
||||
// just call the function
|
||||
|
@ -1184,9 +1261,20 @@ trait Backend<'a> {
|
|||
ret_layout: &InLayout<'a>,
|
||||
);
|
||||
|
||||
fn build_fn_pointer(&mut self, dst: &Symbol, fn_name: String);
|
||||
|
||||
/// Move a returned value into `dst`
|
||||
fn move_return_value(&mut self, dst: &Symbol, ret_layout: &InLayout<'a>);
|
||||
|
||||
/// build_num_abs stores the absolute value of src into dst.
|
||||
fn build_num_int_cast(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src: &Symbol,
|
||||
source: IntWidth,
|
||||
target: IntWidth,
|
||||
);
|
||||
|
||||
/// build_num_abs stores the absolute value of src into dst.
|
||||
fn build_num_abs(&mut self, dst: &Symbol, src: &Symbol, layout: &InLayout<'a>);
|
||||
|
||||
|
@ -1348,6 +1436,14 @@ trait Backend<'a> {
|
|||
/// build_list_len returns the length of a list.
|
||||
fn build_list_len(&mut self, dst: &Symbol, list: &Symbol);
|
||||
|
||||
/// generate a call to a higher-order lowlevel
|
||||
fn build_higher_order_lowlevel(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
holl: &HigherOrderLowLevel<'a>,
|
||||
ret_layout: InLayout<'a>,
|
||||
);
|
||||
|
||||
/// build_list_with_capacity creates and returns a list with the given capacity.
|
||||
fn build_list_with_capacity(
|
||||
&mut self,
|
||||
|
@ -1416,6 +1512,14 @@ trait Backend<'a> {
|
|||
/// build_refcount_getptr loads the pointer to the reference count of src into dst.
|
||||
fn build_ptr_cast(&mut self, dst: &Symbol, src: &Symbol);
|
||||
|
||||
fn build_ptr_write(
|
||||
&mut self,
|
||||
sym: Symbol,
|
||||
ptr: Symbol,
|
||||
value: Symbol,
|
||||
element_layout: InLayout<'a>,
|
||||
);
|
||||
|
||||
/// literal_map gets the map from symbol to literal and layout, used for lazy loading and literal folding.
|
||||
fn literal_map(&mut self) -> &mut MutMap<Symbol, (*const Literal<'a>, *const InLayout<'a>)>;
|
||||
|
||||
|
|
|
@ -246,10 +246,16 @@ fn build_object<'a, B: Backend<'a>>(
|
|||
|
||||
// Generate IR for specialized helper procs (refcounting & equality)
|
||||
let helper_procs = {
|
||||
let (module_id, _interner, interns, helper_proc_gen) = backend.module_interns_helpers_mut();
|
||||
let (module_id, _interner, interns, helper_proc_gen, caller_procs) =
|
||||
backend.module_interns_helpers_mut();
|
||||
|
||||
let mut owned_caller_procs = bumpalo::collections::Vec::new_in(arena);
|
||||
std::mem::swap(caller_procs, &mut owned_caller_procs);
|
||||
|
||||
let ident_ids = interns.all_ident_ids.get_mut(&module_id).unwrap();
|
||||
let helper_procs = helper_proc_gen.take_procs();
|
||||
let mut helper_procs = helper_proc_gen.take_procs();
|
||||
|
||||
helper_procs.extend(owned_caller_procs.into_iter().map(|cp| cp.proc));
|
||||
module_id.register_debug_idents(ident_ids);
|
||||
|
||||
helper_procs
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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,
|
||||
) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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!(),
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -14,6 +14,7 @@ version.workspace = true
|
|||
roc_collections = { path = "../collections" }
|
||||
roc_module = { path = "../module" }
|
||||
roc_region = { path = "../region" }
|
||||
roc_error_macros = { path = "../../error_macros" }
|
||||
|
||||
bumpalo.workspace = true
|
||||
encode_unicode.workspace = true
|
||||
|
|
|
@ -21,6 +21,7 @@ use crate::type_annotation;
|
|||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_collections::soa::Slice;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::called_via::{BinOp, CalledVia, UnaryOp};
|
||||
use roc_region::all::{Loc, Position, Region};
|
||||
|
||||
|
@ -2479,10 +2480,10 @@ fn ident_to_expr<'a>(arena: &'a Bump, src: Ident<'a>) -> Expr<'a> {
|
|||
// TODO: make this state impossible to represent in Ident::Access,
|
||||
// by splitting out parts[0] into a separate field with a type of `&'a str`,
|
||||
// rather than a `&'a [Accessor<'a>]`.
|
||||
panic!("Parsed an Ident::Access with a first part of a tuple index");
|
||||
internal_error!("Parsed an Ident::Access with a first part of a tuple index");
|
||||
}
|
||||
None => {
|
||||
panic!("Parsed an Ident::Access with no parts");
|
||||
internal_error!("Parsed an Ident::Access with no parts");
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1200,7 +1200,7 @@ fn list_count_if_str() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_on_empty_list_with_int_layout() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1218,7 +1218,7 @@ fn list_map_on_empty_list_with_int_layout() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_on_non_empty_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1236,7 +1236,7 @@ fn list_map_on_non_empty_list() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_changes_input() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1254,7 +1254,7 @@ fn list_map_changes_input() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_on_big_list() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1274,7 +1274,7 @@ fn list_map_on_big_list() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_with_type_change() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1293,7 +1293,7 @@ fn list_map_with_type_change() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_using_defined_function() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1315,7 +1315,7 @@ fn list_map_using_defined_function() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_all_inline() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
@ -1328,9 +1328,30 @@ fn list_map_all_inline() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_map_closure_int() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
int : I64
|
||||
int = 123
|
||||
|
||||
single : List I64
|
||||
single =
|
||||
[0]
|
||||
|
||||
List.map single (\x -> x + int)
|
||||
"#
|
||||
),
|
||||
RocList::from_slice(&[123]),
|
||||
RocList<i64>
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
fn list_map_closure() {
|
||||
fn list_map_closure_float() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
r#"
|
||||
|
@ -2926,7 +2947,7 @@ fn list_any_empty_with_unknown_element_type() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn list_all() {
|
||||
assert_evals_to!("List.all [] (\\e -> e > 3)", true, bool);
|
||||
assert_evals_to!("List.all [1, 2, 3] (\\e -> e > 3)", false, bool);
|
||||
|
|
|
@ -3113,7 +3113,7 @@ fn when_on_i16() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
fn num_to_str() {
|
||||
use roc_std::RocStr;
|
||||
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -497,23 +497,23 @@ fn str_concat_empty() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn small_str_is_empty() {
|
||||
assert_evals_to!(r#"Str.isEmpty "abc""#, false, bool);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn big_str_is_empty() {
|
||||
assert_evals_to!(
|
||||
r#"Str.isEmpty "this is more than 15 chars long""#,
|
||||
r#"Str.isEmpty "this is more than 23 chars long""#,
|
||||
false,
|
||||
bool
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm"))]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-dev"))]
|
||||
fn empty_str_is_empty() {
|
||||
assert_evals_to!(r#"Str.isEmpty """#, true, bool);
|
||||
}
|
||||
|
|
|
@ -907,7 +907,9 @@ fn alignment_in_multi_tag_pattern_match() {
|
|||
{ bool, int }
|
||||
|
||||
Empty ->
|
||||
{ bool: Bool.false, int: 0 }
|
||||
# dev backend codegen bug means we cannot use this inline
|
||||
false = Bool.false
|
||||
{ bool: false, int: 0 }
|
||||
#"
|
||||
),
|
||||
(32i64, true),
|
||||
|
@ -924,7 +926,8 @@ fn alignment_in_multi_tag_pattern_match() {
|
|||
Three bool color int ->
|
||||
{ bool, color, int }
|
||||
Empty ->
|
||||
{ bool: Bool.false, color: Red, int: 0 }
|
||||
false = Bool.false
|
||||
{ bool: false, color: Red, int: 0 }
|
||||
#"
|
||||
),
|
||||
(32i64, true, 2u8),
|
||||
|
|
|
@ -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 = "";
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 {};
|
||||
|
|
|
@ -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 {};
|
||||
|
|
|
@ -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#"
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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 }) ->
|
||||
|
@ -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)::*;
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 §ion_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!(§ion.reloff.get(NativeEndian));
|
||||
// // dbg!(section.reloff.get(NativeEndian) as i32);
|
||||
// // dbg!(§ion.reloff.get(LE));
|
||||
// // dbg!(section.reloff.get(LE) as i32);
|
||||
// // dbg!(§ion);
|
||||
// // dbg!(&md.added_byte_count);
|
||||
// // dbg!(String::from_utf8_lossy(§ion.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 => {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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=";
|
||||
|
|
|
@ -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
100
devtools/flake.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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 ];
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[toolchain]
|
||||
channel = "1.65.0"
|
||||
channel = "1.66.1"
|
||||
|
||||
profile = "default"
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const str = @import("str");
|
||||
const str = @import("glue").str;
|
||||
const builtin = @import("builtin");
|
||||
const RocStr = str.RocStr;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
68
flake.lock
generated
|
@ -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",
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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`
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue