getting closer ...

This commit is contained in:
2024-02-22 13:47:06 -08:00
parent 7edaf747aa
commit 26bd7e90fd
9 changed files with 137 additions and 65 deletions

View File

@@ -24,28 +24,6 @@ pub enum ReferenceBuilder {
Argument(ConstantType, entities::Value),
}
impl ReferenceBuilder {
fn refer_to(&self, builder: &mut FunctionBuilder) -> (entities::Value, ConstantType) {
match self {
ReferenceBuilder::Global(ty, gv) => {
let cranelift_type = ir::Type::from(*ty);
let ptr_value = builder.ins().symbol_value(types::I64, *gv);
let value = builder
.ins()
.load(cranelift_type, MemFlags::new(), ptr_value, 0);
(value, *ty)
}
ReferenceBuilder::Local(ty, var) => {
let value = builder.use_var(*var);
(value, *ty)
}
ReferenceBuilder::Argument(ty, val) => (*val, *ty),
}
}
}
impl<M: Module> Backend<M> {
/// Translate the given IR type into an ABI parameter type for cranelift, as
/// best as possible.
@@ -105,6 +83,7 @@ impl<M: Module> Backend<M> {
true,
false,
)?;
println!("defining {} with primitive type {}", top_level_name, pt);
self.module.define_data(data_id, &pt.blank_data())?;
self.defined_symbols
.insert(top_level_name, (data_id, pt.into()));
@@ -146,6 +125,7 @@ impl<M: Module> Backend<M> {
argument_types: Vec<Type>,
return_type: Type,
) -> Result<FuncId, cranelift_module::ModuleError> {
println!("Declaring {:?} function {}", linkage, name);
let basic_signature = Signature {
params: argument_types
.iter()
@@ -176,6 +156,22 @@ impl<M: Module> Backend<M> {
return_type: Type,
body: Expression<Type>,
) -> Result<FuncId, BackendError> {
println!("Compiling function {}", function_name);
{
use pretty::{DocAllocator, Pretty};
let allocator = pretty::BoxAllocator;
allocator
.text("Function body:")
.append(allocator.hardline())
.append(body.pretty(&allocator))
.append(allocator.hardline())
.1
.render_colored(
70,
pretty::termcolor::StandardStream::stdout(pretty::termcolor::ColorChoice::Auto),
)
.expect("rendering works");
}
// reset the next variable counter. this value shouldn't matter; hopefully
// we won't be using close to 2^32 variables!
self.reset_local_variable_tracker();
@@ -423,24 +419,23 @@ impl<M: Module> Backend<M> {
}
},
Expression::Print(ann, var) => {
Expression::Print(_, var) => {
// Get the output buffer (or null) from our general compilation context.
let buffer_ptr = self.output_buffer_ptr();
let buffer_ptr = builder.ins().iconst(types::I64, buffer_ptr as i64);
// Get a reference to the string we want to print.
let string_data_id = self.string_reference(var.as_ref())?;
let var_name = match var {
ValueOrRef::Ref(_, _, ref name) => name.as_ref(),
ValueOrRef::Value(_, _, _) => "<unknown>",
};
let string_data_id = self.string_reference(var_name)?;
let local_name_ref = self
.module
.declare_data_in_func(string_data_id, builder.func);
let name_ptr = builder.ins().symbol_value(types::I64, local_name_ref);
// Look up the value for the variable. Because this might be a
// global variable (and that requires special logic), we just turn
// this into an `Expression` and re-use the logic in that implementation.
let fake_ref =
ValueOrRef::Ref(ann, Type::Primitive(PrimitiveType::U8), var.clone());
let (val, vtype) = self.compile_value_or_ref(fake_ref, variables, builder)?;
let (val, vtype) = self.compile_value_or_ref(var, variables, builder)?;
let vtype_repr = builder.ins().iconst(types::I64, vtype as i64);
@@ -472,10 +467,30 @@ impl<M: Module> Backend<M> {
let ir_type = ir::Type::from(value_type);
let variable = self.generate_local();
builder.declare_var(variable, ir_type);
builder.def_var(variable, value);
variables.insert(name, ReferenceBuilder::Local(value_type, variable));
Ok((builder.ins().iconst(types::I64, 0), ConstantType::Void))
match variables.get(&name) {
Some(ReferenceBuilder::Global(_, global_value)) => {
let pointer = self.module.target_config().pointer_type();
let pointer_to = builder.ins().symbol_value(pointer, *global_value);
println!("STORE {}: cranelift_type {} origin type {:?}", name, value, value_type);
builder.ins().store(MemFlags::new(), value, pointer_to, 0);
Ok((builder.ins().iconst(types::I64, 0), ConstantType::Void))
}
Some(ReferenceBuilder::Argument(_, _)) => {
panic!("Attempt to mutate an argument {}", name)
}
Some(ReferenceBuilder::Local(_, _)) => {
panic!("Attempt to mutate local {}", name);
}
None => {
builder.declare_var(variable, ir_type);
builder.def_var(variable, value);
variables.insert(name, ReferenceBuilder::Local(value_type, variable));
Ok((builder.ins().iconst(types::I64, 0), ConstantType::Void))
}
}
}
Expression::Call(_, _, function, args) => {
@@ -508,9 +523,11 @@ impl<M: Module> Backend<M> {
[result] => match result_type {
Type::Primitive(ct) => Ok((*result, ct.into())),
Type::Function(_, rt) => match *rt {
Type::Function(_, _) => panic!("function returns a function?"),
Type::Function(_, _) => {
panic!("function returns a function?")
}
Type::Primitive(ct) => Ok((*result, ct.into())),
}
},
},
_ => panic!("don't support multi-value returns yet"),
}
@@ -530,6 +547,7 @@ impl<M: Module> Backend<M> {
variables: &HashMap<Variable, ReferenceBuilder>,
builder: &mut FunctionBuilder,
) -> Result<(entities::Value, ConstantType), BackendError> {
println!("compile_value_or_ref {:?}", valref);
match valref {
ValueOrRef::Value(_, _, val) => match val {
Value::I8(_, v) => {
@@ -575,7 +593,25 @@ impl<M: Module> Backend<M> {
},
ValueOrRef::Ref(_, _, name) => match variables.get(&name) {
None => Err(BackendError::VariableLookupFailure(name)),
Some(x) => Ok(x.refer_to(builder)),
Some(ReferenceBuilder::Global(ty, gv)) => {
let pointer_to = self.module.target_config().pointer_type();
let pointer_value = builder.ins().symbol_value(pointer_to, *gv);
let cranelift_type = ir::Type::from(*ty);
println!("READ {}: cranelift_type {} origin type {:?}", name, cranelift_type, ty);
let value =
builder
.ins()
.load(cranelift_type, MemFlags::new(), pointer_value, 0);
Ok((value, *ty))
}
Some(ReferenceBuilder::Argument(ctype, val)) => Ok((*val, *ctype)),
Some(ReferenceBuilder::Local(ctype, var)) => {
let value = builder.use_var(*var);
Ok((value, *ctype))
}
},
}
}
@@ -588,11 +624,11 @@ impl PrimitiveType {
PrimitiveType::U8 => (1, 1),
PrimitiveType::U16 => (2, 2),
PrimitiveType::U32 => (4, 4),
PrimitiveType::U64 => (4, 4),
PrimitiveType::U64 => (8, 8),
PrimitiveType::I8 => (1, 1),
PrimitiveType::I16 => (2, 2),
PrimitiveType::I32 => (4, 4),
PrimitiveType::I64 => (4, 4),
PrimitiveType::I64 => (8, 8),
};
let mut result = DataDescription::new();
result.define_zeroinit(size);