Skip to content

Commit

Permalink
Some optimizations when cloning constants with pointers in them
Browse files Browse the repository at this point in the history
  • Loading branch information
TrolledWoods committed Sep 17, 2020
1 parent 2a55b12 commit 40e3b78
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 24 deletions.
64 changes: 49 additions & 15 deletions src/code_gen.rs
Expand Up @@ -31,6 +31,7 @@ pub enum Instruction {
LessThan(LocalHandle, Value, Value),

SetAddressOf(LocalHandle, LocalHandle),
GetAddressOfResource(LocalHandle, ResourceId),

IndirectMove(IndirectLocalHandle, Value),
Move(LocalHandle, Value),
Expand All @@ -56,6 +57,8 @@ impl fmt::Debug for Instruction {
write!(f, "{:?} = {:?} * {:?}", result, a, b),
Instruction::WrappingDiv(result, a, b) =>
write!(f, "{:?} = {:?} / {:?}", result, a, b),
Instruction::GetAddressOfResource(to, id) =>
write!(f, "{:?} = resource({:?})", to, id),
Instruction::SetAddressOf(to, from) =>
write!(f, "{:?} = &{:?}", to, from),
Instruction::LessThan(result, a, b) =>
Expand Down Expand Up @@ -506,6 +509,50 @@ pub fn compile_expression(
Ok((locals.layout(), instructions, node_values.last().unwrap().clone()))
}

/// Returns a pointer to a resource, either by copying the resource onto the stack and taking a
/// pointer to that, or by taking a pointer to the resource itself. The pointer is always
/// in a local, because it cannot possibly be a constant(because pointers to resources change
/// when compiling etc).
fn get_resource_pointer(
types: &Types,
instructions: &mut Vec<Instruction>,
locals: &mut Locals,
loc: &CodeLoc,
resources: &Resources,
id: ResourceId,
local: LocalHandle,
sub_type_handle: TypeHandle,
) -> Result<(), Dependency> {
// TODO: Also optimize direct pointers to constants.
let resource = resources.resource(id);
match resource.kind {
ResourceKind::Value(ResourceValue::Value(_, _, _, ref pointer_members))
if pointer_members.len() == 0 && false =>
{
// There is an instruction for this!
push_instr!(instructions, Instruction::GetAddressOfResource(local, id));
Ok(())
}
_ => {
// This is just a random pointer
let (n_values, value) =
get_resource_constant(types, instructions, locals, loc, resources, id)?;

let value_local = match value {
Value::Local(local) => local,
_ => {
let value_local = locals.allocate_several(sub_type_handle, n_values);
push_instr!(instructions, Instruction::Move(value_local, value));
value_local
}
};

push_instr!(instructions, Instruction::SetAddressOf(local, value_local));
Ok(())
}
}
}

fn get_resource_constant(
types: &Types,
instructions: &mut Vec<Instruction>,
Expand All @@ -529,21 +576,8 @@ fn get_resource_constant(
push_instr!(instructions, Instruction::Move(local, Value::Constant(value.clone())));

for &(offset, sub_resource_id, sub_type_handle) in pointer_members {
let (n_values, value) =
get_resource_constant(types, instructions, locals, loc, resources, sub_resource_id)?;

let value_local = match value {
Value::Local(local) => local,
_ => {
let value_local = locals.allocate_several(sub_type_handle, n_values);
push_instr!(instructions, Instruction::Move(value_local, value));
value_local
}
};

push_instr!(instructions, Instruction::SetAddressOf(
local.sub_local(offset, 8, 8), value_local
));
// Put the resource pointer into the right local.
get_resource_pointer(types, instructions, locals, loc, resources, sub_resource_id, local.sub_local(offset, 8, 8), sub_type_handle)?;
}

Ok((n_values, Value::Local(local)))
Expand Down
2 changes: 0 additions & 2 deletions src/resource.rs
Expand Up @@ -535,8 +535,6 @@ pub enum ResourceValue {
/// It is a little unfortunate that we may have to do an almost full deep copy whenever loading
/// a constant as a pointer, but that might be necessary. Not sure how to reliably make it work
/// in any other way.
// TODO: Don't create a local variable if the value does not contain any pointers
// on its own.
Value(TypeHandle, usize, crate::stack_frame::ConstBuffer, Vec<(usize, ResourceId, TypeHandle)>),
}

Expand Down
10 changes: 10 additions & 0 deletions src/run.rs
Expand Up @@ -117,6 +117,16 @@ pub fn run_instructions(
_ => panic!("Unknown thing"),
}
}
Instruction::GetAddressOfResource(to, resource_id) => {
if let ResourceKind::Value(ResourceValue::Value(_, _, ref val, _)) =
resources.resource(resource_id).kind
{
let bytes = (val.as_ptr() as u64).to_le_bytes();
stack_frame_instance.insert_into_local(to, &bytes);
} else {
panic!();
}
}
Instruction::SetAddressOf(to, from) => {
let bytes = (stack_frame_instance.address_of_local(from) as u64).to_le_bytes();
stack_frame_instance.insert_into_local(to, &bytes);
Expand Down
13 changes: 6 additions & 7 deletions test.im
@@ -1,11 +1,10 @@
std :: import "std";

{
my_string := "x\n";
buffer := bit_cast { pointer: &U8, _: U64 } (my_string);

a := *(buffer.pointer + bit_cast &U8 (0));
put_char(a);
b := *(buffer.pointer + bit_cast &U8 (1));
put_char(b);
std\print("Hello, World!\n");
};





0 comments on commit 40e3b78

Please sign in to comment.