getting closer ...
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user