Merge remote-tracking branch 'remote/main' into rebuild-platform

This commit is contained in:
Luke Boswell 2024-10-09 09:57:27 +11:00
commit de9491eb7f
No known key found for this signature in database
GPG key ID: F6DB3C9DB47377B0
24 changed files with 361 additions and 140 deletions

View file

@ -28,7 +28,7 @@ pub const MOD_APP: ModName = ModName(b"UserApp");
pub const STATIC_STR_NAME: ConstName = ConstName(&Symbol::STR_ALIAS_ANALYSIS_STATIC.to_ne_bytes());
pub const STATIC_LIST_NAME: ConstName = ConstName(b"THIS IS A STATIC LIST");
const ENTRY_POINT_NAME: &[u8] = b"mainForHost";
const DEFAULT_ENTRY_POINT_NAME: &[u8] = b"mainForHost";
pub fn func_name_bytes(proc: &Proc) -> [u8; SIZE] {
let bytes = func_name_bytes_help(
@ -149,6 +149,7 @@ where
I1: Iterator<Item = &'r Proc<'a>>,
I2: Iterator<Item = &'r HostExposedLambdaSet<'a>>,
{
let mut entry_point_names = bumpalo::vec![in arena;];
let main_module = {
let mut m = ModDefBuilder::new();
@ -237,34 +238,38 @@ where
}
match entry_point {
EntryPoint::Single(SingleEntryPoint {
symbol: entry_point_symbol,
layout: entry_point_layout,
}) => {
// the entry point wrapper
let roc_main_bytes = func_name_bytes_help(
entry_point_symbol,
entry_point_layout.arguments.iter().copied(),
Niche::NONE,
entry_point_layout.result,
);
let roc_main = FuncName(&roc_main_bytes);
EntryPoint::Program(entry_points) => {
for SingleEntryPoint {
name: entry_point_name,
symbol: entry_point_symbol,
layout: entry_point_layout,
} in entry_points
{
let roc_main_bytes = func_name_bytes_help(
*entry_point_symbol,
entry_point_layout.arguments.iter().copied(),
Niche::NONE,
entry_point_layout.result,
);
let roc_main = FuncName(&roc_main_bytes);
let mut env = Env::new();
let mut env = Env::new();
let entry_point_function = build_entry_point(
&mut env,
interner,
entry_point_layout,
Some(roc_main),
&host_exposed_functions,
&erased_functions,
)?;
let entry_point_function = build_entry_point(
&mut env,
interner,
*entry_point_layout,
Some(roc_main),
&host_exposed_functions,
&erased_functions,
)?;
type_definitions.extend(env.type_names);
type_definitions.extend(env.type_names);
let entry_point_name = FuncName(ENTRY_POINT_NAME);
m.add_func(entry_point_name, entry_point_function)?;
entry_point_names.push(entry_point_name.as_bytes());
let entry_point_name = FuncName(entry_point_name.as_bytes());
m.add_func(entry_point_name, entry_point_function)?;
}
}
EntryPoint::Expects { symbols } => {
// construct a big pattern match picking one of the expects at random
@ -296,7 +301,8 @@ where
type_definitions.extend(env.type_names);
let entry_point_name = FuncName(ENTRY_POINT_NAME);
entry_point_names.push(DEFAULT_ENTRY_POINT_NAME);
let entry_point_name = FuncName(DEFAULT_ENTRY_POINT_NAME);
m.add_func(entry_point_name, entry_point_function)?;
}
}
@ -335,11 +341,13 @@ where
let mut p = ProgramBuilder::new();
p.add_mod(MOD_APP, main_module)?;
p.add_entry_point(
EntryPointName(ENTRY_POINT_NAME),
MOD_APP,
FuncName(ENTRY_POINT_NAME),
)?;
for entry_point_name in entry_point_names {
p.add_entry_point(
EntryPointName(entry_point_name),
MOD_APP,
FuncName(entry_point_name),
)?;
}
p.build()?
};

View file

@ -1,4 +1,5 @@
use crate::link::{link, preprocess_host_wasm32, rebuild_host, LinkType, LinkingStrategy};
use bumpalo::collections::CollectIn;
use bumpalo::Bump;
use inkwell::memory_buffer::MemoryBuffer;
use roc_error_macros::internal_error;
@ -226,11 +227,16 @@ fn gen_from_mono_module_llvm<'a>(
exposed_to_host,
platform_path: _,
} => {
// TODO support multiple of these!
debug_assert_eq!(exposed_to_host.len(), 1);
let (symbol, layout) = exposed_to_host[0];
let entry_points: bumpalo::collections::Vec<_> = exposed_to_host
.iter()
.map(|(fn_name, symbol, layout)| SingleEntryPoint {
name: fn_name,
symbol: *symbol,
layout: *layout,
})
.collect_in(arena);
roc_mono::ir::EntryPoint::Single(SingleEntryPoint { symbol, layout })
roc_mono::ir::EntryPoint::Program(entry_points.into_bump_slice())
}
EntryPoint::Test => roc_mono::ir::EntryPoint::Expects { symbols: &[] },
};

View file

@ -120,7 +120,7 @@ impl<'a> Formattable for ProvidesTo<'a> {
impl<'a> Formattable for PlatformRequires<'a> {
fn is_multiline(&self) -> bool {
is_collection_multiline(&self.rigids) || self.signature.is_multiline()
is_collection_multiline(&self.rigids) || is_collection_multiline(&self.signatures)
}
fn format_with_options(
@ -260,10 +260,14 @@ pub fn fmt_platform_header<'a>(buf: &mut Buf, header: &'a PlatformHeader<'a>) {
fn fmt_requires(buf: &mut Buf, requires: &PlatformRequires, indent: u16) {
fmt_collection(buf, indent, Braces::Curly, requires.rigids, Newlines::No);
buf.push_str(" {");
buf.spaces(1);
requires.signature.value.format(buf, indent);
buf.push_str(" }");
fmt_collection(
buf,
indent,
Braces::Curly,
requires.signatures,
Newlines::No,
);
}
impl<'a> Formattable for TypedIdent<'a> {

View file

@ -5592,7 +5592,7 @@ pub fn build_wasm_test_wrapper<'a, 'ctx>(
opt_level,
procedures,
vec![],
EntryPoint::Single(entry_point),
EntryPoint::Program(env.arena.alloc([entry_point])),
Some(&std::env::temp_dir().join("test.ll")),
);
@ -5619,7 +5619,7 @@ pub fn build_procedures_return_main<'a, 'ctx>(
opt_level,
procedures,
host_exposed_lambda_sets,
EntryPoint::Single(entry_point),
EntryPoint::Program(env.arena.alloc([entry_point])),
Some(&std::env::temp_dir().join("test.ll")),
);

View file

@ -51,7 +51,7 @@ use roc_parse::ast::{self, CommentOrNewline, ExtractSpaces, Spaced, ValueDef};
use roc_parse::header::parse_module_defs;
use roc_parse::header::{
self, AppHeader, ExposedName, HeaderType, ImportsKeywordItem, PackageEntry, PackageHeader,
PlatformHeader, To, TypedIdent,
PlatformHeader, To,
};
use roc_parse::parser::{FileError, SourceError, SyntaxError};
use roc_problem::Severity;
@ -667,7 +667,7 @@ enum PlatformPath<'a> {
#[derive(Debug)]
struct PlatformData<'a> {
module_id: ModuleId,
provides: &'a [(Loc<ExposedName<'a>>, Loc<TypedIdent<'a>>)],
provides: &'a [Loc<ExposedName<'a>>],
is_prebuilt: bool,
}
@ -3171,7 +3171,7 @@ fn finish_specialization<'a>(
let proc_layout =
proc_layout_for(state.procedures.keys().copied(), symbol);
buf.push((symbol, proc_layout));
buf.push(("", symbol, proc_layout));
}
buf.into_bump_slice()
@ -3185,13 +3185,14 @@ fn finish_specialization<'a>(
let mut buf =
bumpalo::collections::Vec::with_capacity_in(provides.len(), arena);
for (loc_name, _loc_typed_ident) in provides {
let ident_id = ident_ids.get_or_insert(loc_name.value.as_str());
for loc_name in provides {
let fn_name = loc_name.value.as_str();
let ident_id = ident_ids.get_or_insert(fn_name);
let symbol = Symbol::new(module_id, ident_id);
let proc_layout =
proc_layout_for(state.procedures.keys().copied(), symbol);
buf.push((symbol, proc_layout));
buf.push((fn_name, symbol, proc_layout));
}
buf.into_bump_slice()
@ -4987,15 +4988,16 @@ fn build_platform_header<'a>(
comments: &'a [CommentOrNewline<'a>],
module_timing: ModuleTiming,
) -> Result<(ModuleId, PQModuleName<'a>, ModuleHeader<'a>), LoadingProblem<'a>> {
let requires = arena.alloc([Loc::at(
header.requires.item.signature.region,
header.requires.item.signature.extract_spaces().item,
)]);
let requires = header
.requires
.item
.signatures
.map_items(arena, |item| {
Loc::at(item.region, item.extract_spaces().item)
})
.items;
let provides = bumpalo::collections::Vec::from_iter_in(
unspace(arena, header.provides.item.items)
.iter()
.copied()
.zip(requires.iter().copied()),
unspace(arena, header.provides.item.items).iter().copied(),
arena,
);
let packages = unspace(arena, header.packages.item.items);
@ -5447,7 +5449,7 @@ fn parse<'a>(
if let HeaderType::Platform { provides, .. } = header.header_type {
exposed.reserve(provides.len());
for (loc_name, _loc_typed_ident) in provides.iter() {
for loc_name in provides.iter() {
// Use get_or_insert here because the ident_ids may already
// created an IdentId for this, when it was imported exposed
// in a dependent module.

View file

@ -213,7 +213,7 @@ pub struct ParsedModule<'a> {
#[derive(Debug)]
pub enum EntryPoint<'a> {
Executable {
exposed_to_host: &'a [(Symbol, ProcLayout<'a>)],
exposed_to_host: &'a [(&'a str, Symbol, ProcLayout<'a>)],
platform_path: PathBuf,
},
Test,

View file

@ -132,13 +132,14 @@ pub enum OptLevel {
#[derive(Debug, Clone, Copy)]
pub struct SingleEntryPoint<'a> {
pub name: &'a str,
pub symbol: Symbol,
pub layout: ProcLayout<'a>,
}
#[derive(Debug, Clone, Copy)]
pub enum EntryPoint<'a> {
Single(SingleEntryPoint<'a>),
Program(&'a [SingleEntryPoint<'a>]),
Expects { symbols: &'a [Symbol] },
}

View file

@ -4,7 +4,7 @@ use crate::ast::{
Collection, CommentOrNewline, Defs, Header, Malformed, Pattern, Spaced, Spaces, SpacesBefore,
StrLiteral, TypeAnnotation,
};
use crate::blankspace::{space0_around_ee, space0_before_e, space0_e};
use crate::blankspace::{space0_before_e, space0_e};
use crate::expr::merge_spaces;
use crate::ident::{self, lowercase_ident, unqualified_ident, UppercaseIdent};
use crate::parser::Progress::{self, *};
@ -587,7 +587,7 @@ fn requires<'a>(
fn platform_requires<'a>() -> impl Parser<'a, PlatformRequires<'a>, ERequires<'a>> {
record!(PlatformRequires {
rigids: skip_second(requires_rigids(), space0_e(ERequires::ListStart)),
signature: requires_typed_ident()
signatures: requires_typed_ident()
})
}
@ -607,18 +607,15 @@ fn requires_rigids<'a>(
}
#[inline(always)]
fn requires_typed_ident<'a>() -> impl Parser<'a, Loc<Spaced<'a, TypedIdent<'a>>>, ERequires<'a>> {
skip_first(
fn requires_typed_ident<'a>(
) -> impl Parser<'a, Collection<'a, Loc<Spaced<'a, TypedIdent<'a>>>>, ERequires<'a>> {
reset_min_indent(collection_trailing_sep_e(
byte(b'{', ERequires::ListStart),
skip_second(
reset_min_indent(space0_around_ee(
specialize_err(ERequires::TypedIdent, loc(typed_ident())),
ERequires::ListStart,
ERequires::ListEnd,
)),
byte(b'}', ERequires::ListStart),
),
)
specialize_err(ERequires::TypedIdent, loc(typed_ident())),
byte(b',', ERequires::ListEnd),
byte(b'}', ERequires::ListEnd),
Spaced::SpaceBefore,
))
}
#[inline(always)]
@ -955,7 +952,7 @@ pub enum HeaderType<'a> {
opt_app_module_id: Option<ModuleId>,
/// the name and type scheme of the main function (required by the platform)
/// (type scheme is currently unused)
provides: &'a [(Loc<ExposedName<'a>>, Loc<TypedIdent<'a>>)],
provides: &'a [Loc<ExposedName<'a>>],
requires: &'a [Loc<TypedIdent<'a>>],
requires_types: &'a [Loc<UppercaseIdent<'a>>],
exposes: &'a [Loc<ModuleName<'a>>],
@ -1239,7 +1236,7 @@ pub struct PackageHeader<'a> {
#[derive(Clone, Debug, PartialEq)]
pub struct PlatformRequires<'a> {
pub rigids: Collection<'a, Loc<Spaced<'a, UppercaseIdent<'a>>>>,
pub signature: Loc<Spaced<'a, TypedIdent<'a>>>,
pub signatures: Collection<'a, Loc<Spaced<'a, TypedIdent<'a>>>>,
}
#[derive(Clone, Debug, PartialEq)]
@ -1393,7 +1390,7 @@ impl<'a> Malformed for PackageHeader<'a> {
impl<'a> Malformed for PlatformRequires<'a> {
fn is_malformed(&self) -> bool {
self.signature.is_malformed()
self.signatures.items.iter().any(|x| x.is_malformed())
}
}

View file

@ -254,7 +254,7 @@ impl<'a> Normalize<'a> for PlatformRequires<'a> {
fn normalize(&self, arena: &'a Bump) -> Self {
PlatformRequires {
rigids: self.rigids.normalize(arena),
signature: self.signature.normalize(arena),
signatures: self.signatures.map_items(arena, |x| x.normalize(arena)),
}
}
}

View file

@ -113,9 +113,13 @@ pub fn helper(
} => {
// TODO support multiple of these!
debug_assert_eq!(exposed_to_host.len(), 1);
let (symbol, layout) = exposed_to_host[0];
let (name, symbol, layout) = exposed_to_host[0];
SingleEntryPoint { symbol, layout }
SingleEntryPoint {
name,
symbol,
layout,
}
}
EntryPoint::Test => {
unreachable!()

View file

@ -243,9 +243,13 @@ fn create_llvm_module<'a>(
} => {
// TODO support multiple of these!
debug_assert_eq!(exposed_to_host.len(), 1);
let (symbol, layout) = exposed_to_host[0];
let (name, symbol, layout) = exposed_to_host[0];
SingleEntryPoint { symbol, layout }
SingleEntryPoint {
name,
symbol,
layout,
}
}
EntryPoint::Test => {
unreachable!()

View file

@ -14,14 +14,24 @@ SpacesBefore {
},
item: PlatformRequires {
rigids: [],
signature: @40-49 TypedIdent {
ident: @40-44 "main",
spaces_before_colon: [],
ann: @47-49 Record {
fields: [],
ext: None,
signatures: [
@40-49 TypedIdent {
ident: @40-44 "init",
spaces_before_colon: [],
ann: @47-49 Record {
fields: [],
ext: None,
},
},
},
@51-62 TypedIdent {
ident: @51-57 "update",
spaces_before_colon: [],
ann: @60-62 Record {
fields: [],
ext: None,
},
},
],
},
},
exposes: KeywordItem {

View file

@ -1 +1 @@
platform "rtfeldman/blah" requires {} { main : {} } exposes [] packages {} imports [] provides []
platform "rtfeldman/blah" requires {} { init : {}, update : {} } exposes [] packages {} imports [] provides []

View file

@ -16,24 +16,26 @@ SpacesBefore {
},
item: PlatformRequires {
rigids: [],
signature: @32-49 TypedIdent {
ident: @32-36 "main",
spaces_before_colon: [],
ann: @39-49 Apply(
"",
"Task",
[
@44-46 Record {
fields: [],
ext: None,
},
@47-49 TagUnion {
ext: None,
tags: [],
},
],
),
},
signatures: [
@32-49 TypedIdent {
ident: @32-36 "main",
spaces_before_colon: [],
ann: @39-49 Apply(
"",
"Task",
[
@44-46 Record {
fields: [],
ext: None,
},
@47-49 TagUnion {
ext: None,
tags: [],
},
],
),
},
],
},
},
exposes: KeywordItem {

View file

@ -20,14 +20,16 @@ SpacesBefore {
"Model",
),
],
signature: @45-54 TypedIdent {
ident: @45-49 "main",
spaces_before_colon: [],
ann: @52-54 Record {
fields: [],
ext: None,
signatures: [
@45-54 TypedIdent {
ident: @45-49 "main",
spaces_before_colon: [],
ann: @52-54 Record {
fields: [],
ext: None,
},
},
},
],
},
},
exposes: KeywordItem {

View file

@ -23,26 +23,28 @@ SpacesBefore {
"Model",
),
],
signature: @55-77 TypedIdent {
ident: @55-59 "main",
spaces_before_colon: [],
ann: @62-77 Apply(
"",
"App",
[
@66-71 Apply(
"",
"Flags",
[],
),
@72-77 Apply(
"",
"Model",
[],
),
],
),
},
signatures: [
@55-77 TypedIdent {
ident: @55-59 "main",
spaces_before_colon: [],
ann: @62-77 Apply(
"",
"App",
[
@66-71 Apply(
"",
"Flags",
[],
),
@72-77 Apply(
"",
"Model",
[],
),
],
),
},
],
},
},
exposes: KeywordItem {