got some basics working!

This commit is contained in:
2023-12-27 14:32:00 -08:00
parent 7101b62efb
commit 53a9d081bb
9 changed files with 125 additions and 31 deletions

View File

@@ -21,6 +21,7 @@ use crate::backend::Backend;
enum ReferenceBuilder {
Global(ConstantType, GlobalValue),
Local(ConstantType, cranelift_frontend::Variable),
Argument(ConstantType, entities::Value),
}
impl ReferenceBuilder {
@@ -36,6 +37,8 @@ impl ReferenceBuilder {
let value = builder.use_var(*var);
(value, *ty)
}
ReferenceBuilder::Argument(ty, val) => (*val, *ty),
}
}
}
@@ -172,6 +175,21 @@ impl<M: Module> Backend<M> {
// flow, we might add more blocks after this one. But, for now, we only have
// the one block.
let main_block = builder.create_block();
// add the block parameters, which should be the function parameters
for (name, ty) in arguments.iter() {
let constant_type = ty
.try_into()
.map_err(|_| BackendError::NoFunctionArguments {
function_name: function_name.to_string(),
argument_name: name.to_string(),
})?;
let value = builder.append_block_param(main_block, ir::Type::from(constant_type));
variables.insert(
name.clone(),
ReferenceBuilder::Argument(constant_type, value),
);
}
builder.switch_to_block(main_block);
let (value, _) = self.compile_expression(body, &mut variables, &mut builder)?;
@@ -388,14 +406,23 @@ impl<M: Module> Backend<M> {
match valref {
ValueOrRef::Value(_, _, val) => match val {
Value::I8(_, v) => {
Ok((builder.ins().iconst(types::I8, v as i64), ConstantType::I8))
// Cranelift does a funny thing where it checks you aren't using bits in the I64
// we provide above the size of the type we provide. So, in this case, we can only
// set the low 8 bits of the i64. This restriction creates a bit of a problem when
// casting direction from i8 to i64, because Rust will (helpfully) sign-extend the
// negative number for us. Which sets the high bits, which makes Cranelift unhappy.
// So first we cast the i8 as u8, to get rid of the whole concept of sign extension,
// and *then* we cast to i64.
Ok((builder.ins().iconst(types::I8, v as u8 as i64), ConstantType::I8))
}
Value::I16(_, v) => Ok((
builder.ins().iconst(types::I16, v as i64),
// see above note for the "... as ... as"
builder.ins().iconst(types::I16, v as u16 as i64),
ConstantType::I16,
)),
Value::I32(_, v) => Ok((
builder.ins().iconst(types::I32, v as i64),
// see above note for the "... as ... as"
builder.ins().iconst(types::I32, v as u32 as i64),
ConstantType::I32,
)),
Value::I64(_, v) => Ok((builder.ins().iconst(types::I64, v), ConstantType::I64)),