generate signature for the entry points

This commit is contained in:
Folkert 2023-04-02 20:21:25 +02:00
parent d42e831e47
commit 3ff17aa0ea
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
11 changed files with 150 additions and 92 deletions

View file

@ -1,5 +1,5 @@
interface Types
exposes [Types, shape, size, alignment, target, walkShapes]
exposes [Types, shape, size, alignment, target, walkShapes, entryPoints]
imports [Shape.{ Shape }, TypeId.{ TypeId }, Target.{ Target }, InternalTypeId]
# TODO: switch AssocList uses to Dict once roc_std is updated.
@ -19,12 +19,19 @@ Types := {
## This is important for declaration order in C; we need to output a
## type declaration earlier in the file than where it gets referenced by another type.
deps : List Tuple2,
## Names and types of the entry points of the program (e.g. mainForHost)
entrypoints : List Tuple1,
target : Target,
}
target : Types -> Target
target = \@Types types -> types.target
entryPoints : Types -> List Tuple1
entryPoints = \@Types { entrypoints} -> entrypoints
walkShapes : Types, state, (state, Shape, TypeId -> state) -> state
walkShapes = \@Types { types: shapes }, originalState, update ->
List.walk shapes { index: 0, state: originalState } \{ index, state }, elem ->

View file

@ -8,7 +8,7 @@ makeGlue = \typesByArch ->
modFileContent =
List.walk typesByArch "" \content, types ->
arch = (Types.target types).architecture
archStr = archName arch
archStr = archName arch
Str.concat
content
@ -17,7 +17,7 @@ makeGlue = \typesByArch ->
mod \(archStr);
#[cfg(target_arch = "\(archStr)")]
pub use \(archStr)::*;
"""
typesByArch
@ -88,13 +88,90 @@ convertTypesToFile = \types ->
buf
arch = (Types.target types).architecture
archStr = archName arch
archStr = archName arch
{
name: "\(archStr).rs",
content,
content: content |> generateEntryPoints types,
}
generateEntryPoints: Str, Types -> Str
generateEntryPoints = \buf, types ->
List.walk (Types.entryPoints types) buf \accum, T name id -> generateEntryPoint accum types name id
generateEntryPoint: Str, Types, Str, TypeId -> Str
generateEntryPoint = \buf, types, name, id ->
# functionName: Str,
# externName: Str,
# args: List TypeId,
# lambdaSet: TypeId,
# ret: TypeId,
publicSignature =
when Types.shape types id is
Function rocFn ->
arguments =
rocFn.args
|> List.mapWithIndex \i, argId ->
type = typeName types argId
c = Num.toStr i
"arg\(c): \(type)"
|> Str.joinWith ", "
ret = typeName types rocFn.ret
"(\(arguments)) -> \(ret)"
_ ->
ret = typeName types id
"() -> \(ret)"
externSignature =
when Types.shape types id is
Function rocFn ->
arguments =
rocFn.args
|> List.map \argId ->
type = typeName types argId
"_: \(type)"
|> Str.joinWith ", "
ret = typeName types rocFn.ret
"(_: *mut \(ret), \(arguments))"
_ ->
ret = typeName types id
"(_: *mut \(ret))"
externArguments =
when Types.shape types id is
Function rocFn ->
rocFn.args
|> List.mapWithIndex \i, _ ->
c = Num.toStr i
"arg\(c)"
|> Str.joinWith ", "
_ ->
""
"""
\(buf)
pub fn \(name)\(publicSignature) {
extern "C" {
fn roc__\(name)_1_exposed_generic\(externSignature);
}
let mut ret = std::mem::MaybeUninit::uninit();
unsafe { roc__\(name)_1_exposed_generic(ret.as_mut_ptr(), \(externArguments)) };
unsafe { ret.assume_init() }
}
"""
generateStruct : Str, Types, TypeId, _, _, _ -> Str
generateStruct = \buf, types, id, name, structFields, visibility ->
escapedName = escapeKW name
@ -169,7 +246,7 @@ generateEnumeration = \buf, types, enumType, name, tags, tagBytes ->
impl core::fmt::Debug for \(escapedName) {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
"""
|> \b -> List.walk tags b (generateEnumTagsDebug name)
|> Str.concat "\(indent)\(indent)}\n\(indent)}\n}\n\n"
@ -222,7 +299,7 @@ generateNonRecursiveTagUnion = \buf, types, id, name, tags, discriminantSize, di
}
}
"""
|> Str.concat "// TODO: NonRecursive TagUnion constructor impls\n\n"
|> \b ->
@ -235,7 +312,7 @@ generateNonRecursiveTagUnion = \buf, types, id, name, tags, discriminantSize, di
impl Drop for \(escapedName) {
fn drop(&mut self) {
// Drop the payloads
"""
|> generateTagUnionDropPayload types selfMut tags discriminantName discriminantSize 2
|> Str.concat
@ -243,7 +320,7 @@ generateNonRecursiveTagUnion = \buf, types, id, name, tags, discriminantSize, di
}
}
"""
else
b
@ -428,7 +505,7 @@ generateMultiElementSingleTagStruct = \buf, types, name, tagName, payloadFields,
|> Str.concat
"""
impl \(name) {
"""
|> \b ->
fieldTypes =
@ -475,7 +552,7 @@ generateMultiElementSingleTagStruct = \buf, types, name, tagName, payloadFields,
\(indent) }
\(indent)}
""",
fieldTypes,
fieldAccesses,
@ -494,7 +571,7 @@ generateMultiElementSingleTagStruct = \buf, types, name, tagName, payloadFields,
\(indent) \(retExpr)
\(indent)}
""",
fieldTypes,
fieldAccesses,
@ -517,7 +594,7 @@ generateMultiElementSingleTagStruct = \buf, types, name, tagName, payloadFields,
\(indent)pub fn as_\(tagName)(&self) -> \(retType) {
\(indent) \(retExpr)
\(indent)}
"""
|> Str.concat
"""
@ -527,7 +604,7 @@ generateMultiElementSingleTagStruct = \buf, types, name, tagName, payloadFields,
impl core::fmt::Debug for \(name) {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("\(name)::\(tagName)")
"""
|> \b ->
payloadFields
@ -542,7 +619,7 @@ generateMultiElementSingleTagStruct = \buf, types, name, tagName, payloadFields,
}
}
"""
asRustTuple = \list ->
@ -585,7 +662,7 @@ generateZeroElementSingleTagStruct = \buf, name, tagName ->
}
}
"""
generateDeriveStr = \buf, types, type, includeDebug ->
@ -854,7 +931,7 @@ fileHeader =
#![allow(clippy::clone_on_copy)]
"""
indent = " "

View file

@ -453,7 +453,7 @@ pub fn load_types(
}
}
let types = Types::new(
let types = Types::new_with_entry_points(
arena,
subs,
variables.clone(),
@ -461,6 +461,7 @@ pub fn load_types(
glue_procs_by_layout,
layout_cache,
target_info,
exposed_to_host.clone(),
);
arch_types.push(types);

View file

@ -42,6 +42,7 @@ pub struct File {
pub struct Types {
pub aligns: roc_std::RocList<u32>,
pub deps: roc_std::RocList<Tuple2>,
pub entrypoints: roc_std::RocList<Tuple1>,
pub sizes: roc_std::RocList<u32>,
pub types: roc_std::RocList<RocType>,
pub typesByName: roc_std::RocList<Tuple1>,

View file

@ -81,7 +81,7 @@ impl Types {
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn new<'a, I: Iterator<Item = Variable>>(
pub(crate) fn new_with_entry_points<'a, I: Iterator<Item = Variable>>(
arena: &'a Bump,
subs: &'a Subs,
variables: I,
@ -89,6 +89,7 @@ impl Types {
glue_procs_by_layout: MutMap<Layout<'a>, &'a [String]>,
layout_cache: LayoutCache<'a>,
target: TargetInfo,
mut entry_points: MutMap<Symbol, Variable>,
) -> Self {
let mut types = Self::with_capacity(variables.size_hint().0, target);
let mut env = Env::new(
@ -102,9 +103,37 @@ impl Types {
for var in variables {
env.lambda_set_ids = env.find_lambda_sets(var);
env.add_type(var, &mut types);
let id = env.add_type(var, &mut types);
let key = entry_points
.iter()
.find_map(|(k, v)| (*v == var).then_some((*k, id)));
if let Some((k, id)) = key {
let name = k.as_str(env.interns).to_string();
types.entry_points.push((name, id));
entry_points.remove(&k);
}
}
let variables: Vec<_> = entry_points.values().copied().collect();
for var in variables {
env.lambda_set_ids = env.find_lambda_sets(var);
let id = env.add_type(var, &mut types);
let key = entry_points
.iter()
.find_map(|(k, v)| (*v == var).then_some((*k, id)));
if let Some((k, id)) = key {
let name = k.as_str(env.interns).to_string();
types.entry_points.push((name, id));
entry_points.remove(&k);
}
}
debug_assert!(entry_points.is_empty());
env.resolve_pending_recursive_types(&mut types);
types
@ -626,9 +655,17 @@ impl From<&Types> for roc_type::Types {
.iter()
.map(|(k, v)| roc_type::Tuple1::T(k.as_str().into(), v.0 as _))
.collect();
let entrypoints = types
.entry_points()
.iter()
.map(|(k, v)| roc_type::Tuple1::T(k.as_str().into(), v.0 as _))
.collect();
roc_type::Types {
aligns: types.aligns.as_slice().into(),
deps,
entrypoints,
sizes: types.sizes.as_slice().into(),
types: types.types.iter().map(|t| t.into()).collect(),
typesByName: types_by_name,

View file

@ -1,22 +1,11 @@
mod test_glue;
extern "C" {
#[link_name = "roc__mainForHost_1_exposed_generic"]
fn roc_main(_: *mut test_glue::MyRcd);
}
#[no_mangle]
pub extern "C" fn rust_main() -> i32 {
use std::cmp::Ordering;
use std::collections::hash_set::HashSet;
let record = unsafe {
let mut ret: core::mem::MaybeUninit<test_glue::MyRcd> = core::mem::MaybeUninit::uninit();
roc_main(ret.as_mut_ptr());
ret.assume_init()
};
let record = test_glue::mainForHost();
// Verify that the record has all the expected traits.

View file

@ -1,22 +1,11 @@
mod test_glue;
extern "C" {
#[link_name = "roc__mainForHost_1_exposed_generic"]
fn roc_main(_: *mut test_glue::MyEnum);
}
#[no_mangle]
pub extern "C" fn rust_main() -> i32 {
use std::cmp::Ordering;
use std::collections::hash_set::HashSet;
let tag_union = unsafe {
let mut ret: core::mem::MaybeUninit<test_glue::MyEnum> = core::mem::MaybeUninit::uninit();
roc_main(ret.as_mut_ptr());
ret.assume_init()
};
let tag_union = test_glue::mainForHost();
// Verify that it has all the expected traits.

View file

@ -1,25 +1,13 @@
mod test_glue;
use indoc::indoc;
use test_glue::Combined;
extern "C" {
#[link_name = "roc__mainForHost_1_exposed_generic"]
fn roc_main(_: *mut Combined);
}
#[no_mangle]
pub extern "C" fn rust_main() -> i32 {
use std::cmp::Ordering;
use std::collections::hash_set::HashSet;
let tag_union = unsafe {
let mut ret: core::mem::MaybeUninit<Combined> = core::mem::MaybeUninit::uninit();
roc_main(ret.as_mut_ptr());
ret.assume_init()
};
let tag_union = test_glue::mainForHost();
// Verify that it has all the expected traits.

View file

@ -1,21 +1,10 @@
mod test_glue;
extern "C" {
#[link_name = "roc__mainForHost_1_exposed_generic"]
fn roc_main(_: *mut test_glue::Outer);
}
#[no_mangle]
pub extern "C" fn rust_main() -> i32 {
use std::cmp::Ordering;
let outer = unsafe {
let mut ret: core::mem::MaybeUninit<test_glue::Outer> = core::mem::MaybeUninit::uninit();
roc_main(ret.as_mut_ptr());
ret.assume_init()
};
let outer = test_glue::mainForHost();
// Verify that `inner` has all the expected traits.
{

View file

@ -3,23 +3,12 @@ mod test_glue;
use indoc::indoc;
use test_glue::SingleTagUnion;
extern "C" {
#[link_name = "roc__mainForHost_1_exposed_generic"]
fn roc_main(_: *mut SingleTagUnion);
}
#[no_mangle]
pub extern "C" fn rust_main() -> i32 {
use std::cmp::Ordering;
use std::collections::hash_set::HashSet;
let tag_union = unsafe {
let mut ret: core::mem::MaybeUninit<SingleTagUnion> = core::mem::MaybeUninit::uninit();
roc_main(ret.as_mut_ptr());
ret.assume_init()
};
let tag_union = test_glue::mainForHost();
// Verify that it has all the expected traits.

View file

@ -10,10 +10,7 @@ use std::io::Write;
use std::mem::MaybeUninit;
use std::os::raw::c_char;
extern "C" {
#[link_name = "roc__mainForHost_1_exposed_generic"]
fn roc_main(_: *mut Op);
}
use glue::mainForHost as roc_main;
#[no_mangle]
pub unsafe extern "C" fn roc_alloc(size: usize, _alignment: u32) -> *mut c_void {
@ -93,13 +90,7 @@ pub extern "C" fn rust_main() -> i32 {
println!("Let's do things!");
let mut op: Op = unsafe {
let mut mem = MaybeUninit::uninit();
roc_main(mem.as_mut_ptr());
mem.assume_init()
};
let mut op: Op = roc_main();
loop {
match dbg!(op.discriminant()) {