Merge branch 'main' into list-walk-with-index-until

This commit is contained in:
Bryce Miller 2023-12-18 17:25:06 +01:00 committed by GitHub
commit a710dd18ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 341 additions and 106 deletions

View file

@ -560,8 +560,6 @@ tau = 2 * pi
# ------- Functions
## Convert a number to a [Str].
##
## This is the same as calling `Num.format {}` - so for more details on
## exact formatting, see `Num.format`.
## ```
## Num.toStr 42
## ```
@ -573,7 +571,6 @@ tau = 2 * pi
## When this function is given a non-[finite](Num.isFinite)
## [F64] or [F32] value, the returned string will be `"NaN"`, `"∞"`, or `"-∞"`.
##
## To get strings in hexadecimal, octal, or binary format, use `Num.format`.
toStr : Num * -> Str
intCast : Int a -> Int b

View file

@ -30,12 +30,25 @@ pub fn call_bitcode_fn<'ctx>(
args: &[BasicValueEnum<'ctx>],
fn_name: &str,
) -> BasicValueEnum<'ctx> {
call_bitcode_fn_help(env, args, fn_name)
let ret = call_bitcode_fn_help(env, args, fn_name)
.try_as_basic_value()
.left()
.unwrap_or_else(|| {
panic!("LLVM error: Did not get return value from bitcode function {fn_name:?}")
})
});
if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
// On windows zig uses a vector type <2xi64> instead of a i128 value
let vec_type = env.context.i64_type().vec_type(2);
if ret.get_type() == vec_type.into() {
return env
.builder
.build_bitcast(ret, env.context.i128_type(), "return_i128")
.unwrap();
}
}
ret
}
pub fn call_void_bitcode_fn<'ctx>(
@ -54,7 +67,35 @@ fn call_bitcode_fn_help<'ctx>(
args: &[BasicValueEnum<'ctx>],
fn_name: &str,
) -> CallSiteValue<'ctx> {
let it = args.iter().map(|x| (*x).into());
let it = args
.iter()
.map(|x| {
if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
if x.get_type() == env.context.i128_type().into() {
let parent = env
.builder
.get_insert_block()
.and_then(|b| b.get_parent())
.unwrap();
let alloca = create_entry_block_alloca(
env,
parent,
x.get_type(),
"pass_u128_by_reference",
);
env.builder.build_store(alloca, *x).unwrap();
alloca.into()
} else {
*x
}
} else {
*x
}
})
.map(|x| (x).into());
let arguments = bumpalo::collections::Vec::from_iter_in(it, env.arena);
let fn_val = env

View file

@ -1067,11 +1067,42 @@ pub fn module_from_builtins<'ctx>(
// Also, must_keep is the functions we depend on that would normally be provide by libc.
// They are magically linked to by llvm builtins, so we must specify that they can't be DCE'd.
let must_keep = ["_fltused", "floorf", "memcpy", "memset"];
let must_keep = [
"_fltused",
"floorf",
"memcpy",
"memset",
// I have no idea why this function is special.
// Without it, some tests hang on M1 mac outside of nix.
"__muloti4",
// fixes `Undefined Symbol in relocation`
"__udivti3",
// Roc special functions
"__roc_force_longjmp",
"__roc_force_setjmp",
"set_shared_buffer",
];
for func in module.get_functions() {
let has_definition = func.count_basic_blocks() > 0;
let name = func.get_name().to_string_lossy();
if has_definition && !must_keep.contains(&name.as_ref()) {
if has_definition
&& !name.starts_with("roc_builtins.")
&& !must_keep.contains(&name.as_ref())
{
func.set_linkage(Linkage::Private);
}
}
// Note, running DCE here is faster then waiting until full app DCE.
let mpm = PassManager::create(());
mpm.add_global_dce_pass();
mpm.run_on(&module);
// Now that the unused compiler-rt functions have been removed,
// mark that the builtin functions are allowed to be DCE'd if they aren't used.
for func in module.get_functions() {
let name = func.get_name().to_string_lossy();
if name.starts_with("roc_builtins.") {
func.set_linkage(Linkage::Private);
}
}

View file

@ -1100,13 +1100,22 @@ pub(crate) fn run_low_level<'a, 'ctx>(
NumBytesToU128 => {
arguments!(list, position);
call_list_bitcode_fn(
let ret = call_list_bitcode_fn(
env,
&[list.into_struct_value()],
&[position],
BitcodeReturns::Basic,
bitcode::NUM_BYTES_TO_U128,
)
);
if env.target_info.operating_system == roc_target::OperatingSystem::Windows {
// On windows the return type is not a i128, likely due to alignment
env.builder
.build_bitcast(ret, env.context.i128_type(), "empty_string")
.unwrap()
} else {
ret
}
}
NumCompare => {
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
@ -2596,7 +2605,16 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
}
}
PtrWidth::Bytes8 => {
if target_int_width.stack_size() as usize > env.target_info.ptr_size() {
let return_by_pointer = {
if env.target_info.operating_system
== roc_target::OperatingSystem::Windows
{
target_int_width.stack_size() as usize >= env.target_info.ptr_size()
} else {
target_int_width.stack_size() as usize > env.target_info.ptr_size()
}
};
if return_by_pointer {
let bitcode_return_type =
zig_to_int_checked_result_type(env, target_int_width.type_name());

View file

@ -684,6 +684,7 @@ impl MakeSpecializationsPass {
struct State<'a> {
pub root_id: ModuleId,
pub root_subs: Option<Subs>,
pub root_path: PathBuf,
pub cache_dir: PathBuf,
/// If the root is an app module, the shorthand specified in its header's `to` field
pub opt_platform_shorthand: Option<&'a str>,
@ -752,6 +753,7 @@ impl<'a> State<'a> {
fn new(
root_id: ModuleId,
root_path: PathBuf,
opt_platform_shorthand: Option<&'a str>,
target_info: TargetInfo,
function_kind: FunctionKind,
@ -770,6 +772,7 @@ impl<'a> State<'a> {
Self {
root_id,
root_path,
root_subs: None,
opt_platform_shorthand,
cache_dir,
@ -1077,8 +1080,9 @@ pub struct LoadStart<'a> {
arc_modules: Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: SharedIdentIdsByModule,
root_id: ModuleId,
opt_platform_shorthand: Option<&'a str>,
root_path: PathBuf,
root_msg: Msg<'a>,
opt_platform_shorthand: Option<&'a str>,
src_dir: PathBuf,
}
@ -1101,7 +1105,7 @@ impl<'a> LoadStart<'a> {
let res_loaded = load_filename(
arena,
filename,
filename.clone(),
true,
None,
None,
@ -1136,6 +1140,7 @@ impl<'a> LoadStart<'a> {
ident_ids_by_module,
src_dir,
root_id: header_output.module_id,
root_path: filename,
root_msg: header_output.msg,
opt_platform_shorthand: header_output.opt_platform_shorthand,
})
@ -1162,7 +1167,7 @@ impl<'a> LoadStart<'a> {
let header_output = load_from_str(
arena,
filename,
filename.clone(),
src,
Arc::clone(&arc_modules),
Arc::clone(&ident_ids_by_module),
@ -1178,6 +1183,7 @@ impl<'a> LoadStart<'a> {
src_dir,
ident_ids_by_module,
root_id,
root_path: filename,
root_msg,
opt_platform_shorthand: opt_platform_id,
})
@ -1352,6 +1358,7 @@ pub fn load_single_threaded<'a>(
arc_modules,
ident_ids_by_module,
root_id,
root_path,
root_msg,
src_dir,
opt_platform_shorthand,
@ -1367,6 +1374,7 @@ pub fn load_single_threaded<'a>(
let number_of_workers = 1;
let mut state = State::new(
root_id,
root_path,
opt_platform_shorthand,
target_info,
function_kind,
@ -1503,7 +1511,7 @@ fn state_thread_step<'a>(
Ok(ControlFlow::Break(LoadResult::Monomorphized(monomorphized)))
}
Msg::FailedToReadFile { filename, error } => {
let buf = to_file_problem_report_string(&filename, error);
let buf = to_file_problem_report_string(filename, error);
Err(LoadingProblem::FormattedReport(buf))
}
@ -1654,7 +1662,7 @@ pub fn report_loading_problem(
}
LoadingProblem::FormattedReport(report) => report,
LoadingProblem::FileProblem { filename, error } => {
to_file_problem_report_string(&filename, error)
to_file_problem_report_string(filename, error)
}
err => todo!("Loading error: {:?}", err),
}
@ -1677,6 +1685,7 @@ fn load_multi_threaded<'a>(
arc_modules,
ident_ids_by_module,
root_id,
root_path,
root_msg,
src_dir,
opt_platform_shorthand,
@ -1707,6 +1716,7 @@ fn load_multi_threaded<'a>(
let mut state = State::new(
root_id,
root_path,
opt_platform_shorthand,
target_info,
function_kind,
@ -2238,6 +2248,7 @@ fn update<'a>(
let buf = to_https_problem_report_string(
url,
Problem::InvalidUrl(url_err),
header.module_path,
);
return Err(LoadingProblem::FormattedReport(buf));
}
@ -3159,7 +3170,7 @@ fn finish_specialization<'a>(
}
Valid(To::NewPackage(p_or_p)) => PathBuf::from(p_or_p.as_str()),
other => {
let buf = to_missing_platform_report(state.root_id, other);
let buf = report_cannot_run(state.root_id, state.root_path, other);
return Err(LoadingProblem::FormattedReport(buf));
}
};
@ -3513,9 +3524,7 @@ fn load_builtin_module_help<'a>(
) -> (HeaderInfo<'a>, roc_parse::state::State<'a>) {
let is_root_module = false;
let opt_shorthand = None;
let filename = PathBuf::from(filename);
let parse_state = roc_parse::state::State::new(src_bytes.as_bytes());
let parsed = roc_parse::module::parse_header(arena, parse_state.clone());
@ -3968,6 +3977,7 @@ fn parse_header<'a>(
module_timing,
)?;
let filename = resolved_header.module_path.clone();
let mut messages = Vec::with_capacity(packages.len() + 1);
// It's important that the app header is first in the list!
@ -3982,6 +3992,7 @@ fn parse_header<'a>(
module_id,
module_ids,
ident_ids_by_module,
filename,
);
// Look at the app module's `to` keyword to determine which package was the platform.
@ -4084,6 +4095,7 @@ fn load_packages<'a>(
module_id: ModuleId,
module_ids: Arc<Mutex<PackageModuleIds<'a>>>,
ident_ids_by_module: SharedIdentIdsByModule,
filename: PathBuf,
) {
// Load all the packages
for Loc { value: entry, .. } in packages.iter() {
@ -4121,7 +4133,7 @@ fn load_packages<'a>(
}
}
Err(problem) => {
let buf = to_https_problem_report_string(src, problem);
let buf = to_https_problem_report_string(src, problem, filename);
load_messages.push(Msg::FailedToLoad(LoadingProblem::FormattedReport(buf)));
return;
@ -6581,7 +6593,11 @@ fn to_parse_problem_report<'a>(
buf
}
fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> String {
fn report_cannot_run(
module_id: ModuleId,
filename: PathBuf,
platform_path: &PlatformPath,
) -> String {
use roc_reporting::report::{Report, RocDocAllocator, DEFAULT_PALETTE};
use ven_pretty::DocAllocator;
use PlatformPath::*;
@ -6591,20 +6607,20 @@ fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> Stri
let alloc = RocDocAllocator::new(&[], module_id, &interns);
let report = {
match other {
match platform_path {
Valid(_) => unreachable!(),
NotSpecified => {
let doc = alloc.stack([
alloc.reflow("I could not find a platform based on your input file."),
alloc.reflow(r"Does the module header contain an entry that looks like this:"),
alloc.reflow(r"Does the module header have an entry that looks like this?"),
alloc
.parser_suggestion(" packages { pf: \"platform\" }")
.parser_suggestion("packages { blah: \"…path or URL to platform…\" }")
.indent(4),
alloc.reflow("See also TODO."),
alloc.reflow("Tip: The following part of the tutorial has an example of specifying a platform:\n\n<https://www.roc-lang.org/tutorial#building-an-application>"),
]);
Report {
filename: "UNKNOWN.roc".into(),
filename,
doc,
title: "NO PLATFORM".to_string(),
severity: Severity::RuntimeError,
@ -6619,7 +6635,7 @@ fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> Stri
]);
Report {
filename: "UNKNOWN.roc".into(),
filename,
doc,
title: "NO PLATFORM".to_string(),
severity: Severity::RuntimeError,
@ -6634,7 +6650,7 @@ fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> Stri
]);
Report {
filename: "UNKNOWN.roc".into(),
filename,
doc,
title: "NO PLATFORM".to_string(),
severity: Severity::RuntimeError,
@ -6649,7 +6665,7 @@ fn to_missing_platform_report(module_id: ModuleId, other: &PlatformPath) -> Stri
]);
Report {
filename: "UNKNOWN.roc".into(),
filename,
doc,
title: "NO PLATFORM".to_string(),
severity: Severity::RuntimeError,

View file

@ -234,7 +234,19 @@ fn verify_procedures<'a>(
if !has_changes.stdout.is_empty() {
println!("{}", std::str::from_utf8(&has_changes.stdout).unwrap());
panic!("Output changed: resolve conflicts and `git add` the file.");
panic!(indoc!(
r#"
Mono output has changed! This is normal when making changes to the builtins.
To fix it; run these commands locally:
cargo test -p test_mono -p uitest --no-fail-fast
git add -u
git commit -S -m "update mono tests"
git push origin YOUR_BRANCH_NAME
"#
));
}
}