λ Support functions! #5

Open
acw wants to merge 59 commits from awick/functions into develop
8 changed files with 119 additions and 9 deletions
Showing only changes of commit 5f2fc7cb34 - Show all commits

View File

@@ -3,6 +3,8 @@ struct Point {
y: u64;
}
v = 1u64;
function getX(p: Point) -> u64
p.x;

View File

@@ -0,0 +1,13 @@
struct Point {
x: u64;
y: u64;
}
test = Point {
x: 1;
y: 2;
};
foo = test.x;
print foo;

View File

@@ -1,7 +1,13 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#define HEAP_SIZE (1024 * 1024)
void *__global_allocation_pointer__ = NULL;
void print(char *_ignore, char *variable_name, int64_t vtype, int64_t value) {
switch(vtype) {
case /* U8 = */ 10:
@@ -39,6 +45,18 @@ void print(char *_ignore, char *variable_name, int64_t vtype, int64_t value) {
extern void gogogo();
int main(int argc, char **argv) {
__global_allocation_pointer__ = malloc(HEAP_SIZE);
if(__global_allocation_pointer__ == NULL) {
printf("ERROR: Couldn't allocation heap space.");
return 1;
}
if(memset(__global_allocation_pointer__, 0, HEAP_SIZE) != __global_allocation_pointer__) {
printf("ERROR: Weird return trying to zero out heap.");
return 2;
}
gogogo();
return 0;
}

View File

@@ -89,7 +89,7 @@ impl Backend<JITModule> {
let mut module = JITModule::new(builder);
let runtime_functions = RuntimeFunctions::new(&platform, &mut module)?;
Ok(Backend {
let mut retval = Backend {
module,
data_ctx: DataDescription::new(),
runtime_functions,
@@ -99,7 +99,18 @@ impl Backend<JITModule> {
output_buffer,
platform: Triple::host(),
next_variable: 23,
})
};
let alloc = "__global_allocation_pointer__".to_string();
let id = retval
.module
.declare_data(&alloc, Linkage::Import, true, false)?;
retval.defined_symbols.insert(
ArcIntern::new(alloc),
(id, retval.module.target_config().pointer_type()),
);
Ok(retval)
}
/// Given a compiled function ID, get a pointer to where that function was written
@@ -130,7 +141,7 @@ impl Backend<ObjectModule> {
let mut module = ObjectModule::new(object_builder);
let runtime_functions = RuntimeFunctions::new(&platform, &mut module)?;
Ok(Backend {
let mut retval = Backend {
module,
data_ctx: DataDescription::new(),
runtime_functions,
@@ -140,7 +151,18 @@ impl Backend<ObjectModule> {
output_buffer: None,
platform,
next_variable: 23,
})
};
let alloc = "__global_allocation_pointer__".to_string();
let id = retval
.module
.declare_data(&alloc, Linkage::Import, true, false)?;
retval.defined_symbols.insert(
ArcIntern::new(alloc),
(id, retval.module.target_config().pointer_type()),
);
Ok(retval)
}
/// Given all the functions defined, return the bytes the object file should contain.

View File

@@ -406,12 +406,53 @@ impl<M: Module> Backend<M> {
}
}
Expression::Construct(_, ty, name, fields) => {
let Type::Structure(fields) = ty else {
Expression::Construct(_, ty, _, fields) => {
let Type::Structure(type_fields) = ty else {
panic!("Got to backend with non-structure type in structure construction?!");
};
unimplemented!()
let global_allocator = ArcIntern::new("__global_allocation_pointer__".to_string());
let Some(ReferenceBuilder::Global(_, allocator_variable)) =
variables.get(&global_allocator)
else {
panic!("Couldn't find global allocation pointer");
};
let pointer_to = self.module.target_config().pointer_type();
let allocator_pointer = builder.ins().symbol_value(pointer_to, *allocator_variable);
let structure =
builder
.ins()
.load(pointer_to, MemFlags::new(), allocator_pointer, 0);
let structure_size = builder
.ins()
.iconst(pointer_to, type_fields.object_size() as i64);
let updated_allocator_value = builder.ins().iadd(structure, structure_size);
builder.ins().store(
MemFlags::new(),
updated_allocator_value,
allocator_pointer,
0,
);
for (field_name, field_value) in fields.into_iter() {
let (field_value, field_cranelift_type) =
self.compile_value_or_ref(field_value, variables, builder)?;
let Some((field_internal_type, offset)) =
type_fields.field_type_and_offset(&field_name)
else {
panic!("Got to backend with mismatched construction and type definition");
};
assert_eq!(
field_cranelift_type,
self.translate_type(field_internal_type).value_type
);
builder
.ins()
.store(MemFlags::new(), field_value, structure, offset);
}
Ok((structure, self.module.target_config().pointer_type()))
}
Expression::FieldRef(_, _, struct_type, val, field) => {
@@ -427,7 +468,10 @@ impl<M: Module> Backend<M> {
let field_cranelift_type = self.translate_type(field_type).value_type;
let value = builder.ins().load(field_cranelift_type, MemFlags::new(), structure, offset);
let value =
builder
.ins()
.load(field_cranelift_type, MemFlags::new(), structure, offset);
Ok((value, field_cranelift_type))
}

View File

@@ -91,7 +91,14 @@ impl RuntimeFunctions {
/// one; both to reduce the chance that they deviate, and to reduce overall
/// maintenance burden.
pub fn register_jit_implementations(builder: &mut JITBuilder) {
let allocation_pointer = unsafe {
std::alloc::alloc_zeroed(
std::alloc::Layout::from_size_align(1024 * 1024, 1024 * 1024)
.expect("reasonable layout is reasonable"),
)
};
builder.symbol("print", runtime_print as *const u8);
builder.symbol("__global_allocation_pointer__", allocation_pointer);
}
}

View File

@@ -133,6 +133,10 @@ impl<T> Fields<T> {
None
}
pub fn object_size(&self) -> usize {
self.total_size
}
}
impl<T> IntoIterator for Fields<T> {

View File

@@ -183,7 +183,7 @@ fn convert_statement(
let iname = ArcIntern::new(name.to_string());
let final_name = renames
.get(&iname)
.map(Clone::clone)
.cloned()
.unwrap_or_else(|| iname.clone());
let varty = bindings
.get(&final_name)