mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-22 08:17:40 +03:00
Merge branch 'trunk' into contrain_expr2_letfunction
This commit is contained in:
commit
2f44383bb3
@ -55,6 +55,7 @@ pub fn build_file<'a>(
|
||||
link_type: LinkType,
|
||||
surgically_link: bool,
|
||||
precompiled: bool,
|
||||
target_valgrind: bool,
|
||||
) -> Result<BuiltFile, LoadingProblem<'a>> {
|
||||
let compilation_start = SystemTime::now();
|
||||
let ptr_bytes = target.pointer_width().unwrap().bytes() as u32;
|
||||
@ -116,6 +117,7 @@ pub fn build_file<'a>(
|
||||
.keys()
|
||||
.map(|x| x.as_str(&loaded.interns).to_string())
|
||||
.collect(),
|
||||
target_valgrind,
|
||||
);
|
||||
|
||||
// TODO try to move as much of this linking as possible to the precompiled
|
||||
@ -280,6 +282,7 @@ pub fn build_file<'a>(
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn spawn_rebuild_thread(
|
||||
opt_level: OptLevel,
|
||||
surgically_link: bool,
|
||||
@ -288,6 +291,7 @@ fn spawn_rebuild_thread(
|
||||
binary_path: PathBuf,
|
||||
target: &Triple,
|
||||
exported_symbols: Vec<String>,
|
||||
target_valgrind: bool,
|
||||
) -> std::thread::JoinHandle<u128> {
|
||||
let thread_local_target = target.clone();
|
||||
std::thread::spawn(move || {
|
||||
@ -299,6 +303,7 @@ fn spawn_rebuild_thread(
|
||||
&thread_local_target,
|
||||
host_input_path.as_path(),
|
||||
exported_symbols,
|
||||
target_valgrind,
|
||||
)
|
||||
.unwrap();
|
||||
} else {
|
||||
@ -307,6 +312,7 @@ fn spawn_rebuild_thread(
|
||||
&thread_local_target,
|
||||
host_input_path.as_path(),
|
||||
None,
|
||||
target_valgrind,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ pub const FLAG_BACKEND: &str = "backend";
|
||||
pub const FLAG_TIME: &str = "time";
|
||||
pub const FLAG_LINK: &str = "roc-linker";
|
||||
pub const FLAG_PRECOMPILED: &str = "precompiled-host";
|
||||
pub const FLAG_VALGRIND: &str = "valgrind";
|
||||
pub const ROC_FILE: &str = "ROC_FILE";
|
||||
pub const BACKEND: &str = "BACKEND";
|
||||
pub const DIRECTORY_OR_FILES: &str = "DIRECTORY_OR_FILES";
|
||||
@ -100,6 +101,12 @@ pub fn build_app<'a>() -> App<'a> {
|
||||
.about("Assumes the host has been precompiled and skips recompiling the host.")
|
||||
.required(false),
|
||||
)
|
||||
.arg(
|
||||
Arg::new(FLAG_VALGRIND)
|
||||
.long(FLAG_VALGRIND)
|
||||
.about("Some assembly instructions are not supported by valgrind, this flag prevents those from being output when building the host.")
|
||||
.required(false),
|
||||
)
|
||||
)
|
||||
.subcommand(App::new(CMD_REPL)
|
||||
.about("Launch the interactive Read Eval Print Loop (REPL)")
|
||||
@ -258,6 +265,7 @@ pub fn build(matches: &ArgMatches, config: BuildConfig) -> io::Result<i32> {
|
||||
};
|
||||
let surgically_link = matches.is_present(FLAG_LINK);
|
||||
let precompiled = matches.is_present(FLAG_PRECOMPILED);
|
||||
|
||||
if surgically_link && !roc_linker::supported(&link_type, &target) {
|
||||
panic!(
|
||||
"Link type, {:?}, with target, {}, not supported by roc linker",
|
||||
@ -287,6 +295,7 @@ pub fn build(matches: &ArgMatches, config: BuildConfig) -> io::Result<i32> {
|
||||
});
|
||||
|
||||
let src_dir = path.parent().unwrap().canonicalize().unwrap();
|
||||
let target_valgrind = matches.is_present(FLAG_VALGRIND);
|
||||
let res_binary_path = build_file(
|
||||
&arena,
|
||||
&target,
|
||||
@ -298,6 +307,7 @@ pub fn build(matches: &ArgMatches, config: BuildConfig) -> io::Result<i32> {
|
||||
link_type,
|
||||
surgically_link,
|
||||
precompiled,
|
||||
target_valgrind,
|
||||
);
|
||||
|
||||
match res_binary_path {
|
||||
|
@ -53,7 +53,14 @@ mod cli_run {
|
||||
expected_ending: &str,
|
||||
use_valgrind: bool,
|
||||
) {
|
||||
let compile_out = run_roc(&[&["build", file.to_str().unwrap()], flags].concat());
|
||||
let mut all_flags = vec![];
|
||||
all_flags.extend_from_slice(flags);
|
||||
|
||||
if use_valgrind {
|
||||
all_flags.extend_from_slice(&["--valgrind"]);
|
||||
}
|
||||
|
||||
let compile_out = run_roc(&[&["build", file.to_str().unwrap()], &all_flags[..]].concat());
|
||||
if !compile_out.stderr.is_empty() {
|
||||
panic!("{}", compile_out.stderr);
|
||||
}
|
||||
|
@ -86,6 +86,7 @@ pub fn build_zig_host_native(
|
||||
target: &str,
|
||||
opt_level: OptLevel,
|
||||
shared_lib_path: Option<&Path>,
|
||||
_target_valgrind: bool,
|
||||
) -> Output {
|
||||
let mut command = Command::new("zig");
|
||||
command
|
||||
@ -118,6 +119,15 @@ pub fn build_zig_host_native(
|
||||
"-target",
|
||||
target,
|
||||
]);
|
||||
|
||||
// use single threaded testing for cli_run and enable this code if valgrind fails with unhandled instruction bytes, see #1963.
|
||||
/*if target_valgrind {
|
||||
command.args(&[
|
||||
"-mcpu",
|
||||
"x86_64"
|
||||
]);
|
||||
}*/
|
||||
|
||||
if matches!(opt_level, OptLevel::Optimize) {
|
||||
command.args(&["-O", "ReleaseSafe"]);
|
||||
}
|
||||
@ -339,6 +349,7 @@ pub fn rebuild_host(
|
||||
target: &Triple,
|
||||
host_input_path: &Path,
|
||||
shared_lib_path: Option<&Path>,
|
||||
target_valgrind: bool,
|
||||
) {
|
||||
let c_host_src = host_input_path.with_file_name("host.c");
|
||||
let c_host_dest = host_input_path.with_file_name("c_host.o");
|
||||
@ -394,6 +405,7 @@ pub fn rebuild_host(
|
||||
"native",
|
||||
opt_level,
|
||||
shared_lib_path,
|
||||
target_valgrind,
|
||||
)
|
||||
}
|
||||
Architecture::X86_32(_) => {
|
||||
@ -407,6 +419,7 @@ pub fn rebuild_host(
|
||||
"i386-linux-musl",
|
||||
opt_level,
|
||||
shared_lib_path,
|
||||
target_valgrind,
|
||||
)
|
||||
}
|
||||
|
||||
@ -421,6 +434,7 @@ pub fn rebuild_host(
|
||||
target_triple_str(target),
|
||||
opt_level,
|
||||
shared_lib_path,
|
||||
target_valgrind,
|
||||
)
|
||||
}
|
||||
_ => panic!("Unsupported architecture {:?}", target.architecture),
|
||||
|
@ -626,8 +626,8 @@ impl<'a> WasmBackend<'a> {
|
||||
self.lookup_string_constant(string, sym, layout);
|
||||
|
||||
self.code_builder.get_local(local_id);
|
||||
self.code_builder.insert_memory_relocation(linker_sym_index);
|
||||
self.code_builder.i32_const(elements_addr as i32);
|
||||
self.code_builder
|
||||
.i32_const_mem_addr(elements_addr, linker_sym_index);
|
||||
self.code_builder.i32_store(Align::Bytes4, offset);
|
||||
|
||||
self.code_builder.get_local(local_id);
|
||||
|
@ -9,7 +9,7 @@ use super::opcodes::{OpCode, OpCode::*};
|
||||
use super::serialize::{SerialBuffer, Serialize};
|
||||
use crate::{round_up_to_alignment, FRAME_ALIGNMENT_BYTES, STACK_POINTER_GLOBAL_ID};
|
||||
|
||||
const ENABLE_DEBUG_LOG: bool = true;
|
||||
const ENABLE_DEBUG_LOG: bool = false;
|
||||
macro_rules! log_instruction {
|
||||
($($x: expr),+) => {
|
||||
if ENABLE_DEBUG_LOG { println!($($x,)*); }
|
||||
@ -572,11 +572,14 @@ impl<'a> CodeBuilder<'a> {
|
||||
);
|
||||
}
|
||||
|
||||
/// Insert a linker relocation for a memory address
|
||||
pub fn insert_memory_relocation(&mut self, symbol_index: u32) {
|
||||
/// Insert a const reference to a memory address
|
||||
pub fn i32_const_mem_addr(&mut self, addr: u32, symbol_index: u32) {
|
||||
self.inst_base(I32CONST, 0, true);
|
||||
let offset = self.code.len() as u32;
|
||||
self.code.encode_padded_u32(addr);
|
||||
self.relocations.push(RelocationEntry::Offset {
|
||||
type_id: OffsetRelocType::MemoryAddrLeb,
|
||||
offset: self.code.len() as u32,
|
||||
offset,
|
||||
symbol_index,
|
||||
addend: 0,
|
||||
});
|
||||
|
@ -29,6 +29,8 @@ pub enum SectionId {
|
||||
Element = 9,
|
||||
Code = 10,
|
||||
Data = 11,
|
||||
/// DataCount section is unused. Only needed for single-pass validation of
|
||||
/// memory.init and data.drop, which we don't use
|
||||
DataCount = 12,
|
||||
}
|
||||
|
||||
@ -525,42 +527,6 @@ impl Serialize for DataSection<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* Data Count section
|
||||
*
|
||||
* Pre-declares the number of segments in the Data section.
|
||||
* This helps the runtime to validate the module in a single pass.
|
||||
* The order of sections is DataCount -> Code -> Data
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DataCountSection {
|
||||
count: u32,
|
||||
}
|
||||
|
||||
impl DataCountSection {
|
||||
fn new(data_section: &DataSection<'_>) -> Self {
|
||||
let count = data_section
|
||||
.segments
|
||||
.iter()
|
||||
.filter(|seg| !seg.init.is_empty())
|
||||
.count() as u32;
|
||||
DataCountSection { count }
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for DataCountSection {
|
||||
fn serialize<T: SerialBuffer>(&self, buffer: &mut T) {
|
||||
if self.count > 0 {
|
||||
let header_indices = write_section_header(buffer, SectionId::DataCount);
|
||||
buffer.encode_u32(self.count);
|
||||
update_section_size(buffer, header_indices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* Module
|
||||
@ -658,11 +624,6 @@ impl<'a> WasmModule<'a> {
|
||||
counter.serialize_and_count(buffer, &self.start);
|
||||
counter.serialize_and_count(buffer, &self.element);
|
||||
|
||||
// Data Count section forward-declares the size of the Data section
|
||||
// so that Code section can be validated in one pass
|
||||
let data_count_section = DataCountSection::new(&self.data);
|
||||
counter.serialize_and_count(buffer, &data_count_section);
|
||||
|
||||
// Code section is the only one with relocations so we can stop counting
|
||||
let code_section_index = counter.section_index;
|
||||
let code_section_body_index = self
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Wasm pointers are only 32bit. This effects RocStr.
|
||||
// These are versions of the str tests assuming 32bit pointers.
|
||||
#![cfg(not(feature = "gen-dev"))]
|
||||
#![cfg(feature = "gen-wasm")]
|
||||
|
||||
// TODO: We need to make these tests work with the llvm wasm backend.
|
||||
|
||||
@ -12,7 +12,7 @@ use crate::helpers::wasm::assert_evals_to;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use indoc::indoc;
|
||||
// use roc_std::RocStr;
|
||||
use roc_std::RocStr;
|
||||
|
||||
// #[test]
|
||||
// fn str_split_bigger_delimiter_small_str() {
|
||||
@ -287,15 +287,14 @@ fn small_str_zeroed_literal() {
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: fix linking errors for undefined symbols roc_alloc, roc_dealloc
|
||||
// #[test]
|
||||
// fn long_str_literal() {
|
||||
// assert_evals_to!(
|
||||
// "\"0123456789 123456789 123456789\"",
|
||||
// RocStr::from_slice(b"0123456789 123456789 123456789"),
|
||||
// RocStr
|
||||
// );
|
||||
// }
|
||||
#[test]
|
||||
fn long_str_literal() {
|
||||
assert_evals_to!(
|
||||
"\"0123456789 123456789 123456789\"",
|
||||
RocStr::from_slice(b"0123456789 123456789 123456789"),
|
||||
RocStr
|
||||
);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn small_str_concat_empty_first_arg() {
|
||||
|
@ -142,10 +142,17 @@ pub fn build_and_preprocess_host(
|
||||
target: &Triple,
|
||||
host_input_path: &Path,
|
||||
exposed_to_host: Vec<String>,
|
||||
target_valgrind: bool,
|
||||
) -> io::Result<()> {
|
||||
let dummy_lib = host_input_path.with_file_name("libapp.so");
|
||||
generate_dynamic_lib(target, exposed_to_host, &dummy_lib)?;
|
||||
rebuild_host(opt_level, target, host_input_path, Some(&dummy_lib));
|
||||
rebuild_host(
|
||||
opt_level,
|
||||
target,
|
||||
host_input_path,
|
||||
Some(&dummy_lib),
|
||||
target_valgrind,
|
||||
);
|
||||
let dynhost = host_input_path.with_file_name("dynhost");
|
||||
let metadata = host_input_path.with_file_name("metadata");
|
||||
let prehost = host_input_path.with_file_name("preprocessedhost");
|
||||
|
Loading…
Reference in New Issue
Block a user