Skip to content

Commit

Permalink
IR explicit pointer refactor. (FuelLabs#4336)
Browse files Browse the repository at this point in the history
  • Loading branch information
otrho authored Apr 2, 2023
1 parent 5731920 commit d6238ae
Show file tree
Hide file tree
Showing 126 changed files with 5,303 additions and 4,114 deletions.
107 changes: 40 additions & 67 deletions sway-core/src/asm_generation/evm/evm_asm_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,6 @@ impl<'ir> EvmAsmBuilder<'ir> {
let mut errors = Vec::new();
if let Some(instruction) = instr_val.get_instruction(self.context) {
match instruction {
Instruction::AddrOf(arg) => self.compile_addr_of(instr_val, arg),
Instruction::AsmBlock(asm, args) => {
check!(
self.compile_asm_block(instr_val, asm, args),
Expand All @@ -308,9 +307,7 @@ impl<'ir> EvmAsmBuilder<'ir> {
}
Instruction::Branch(to_block) => self.compile_branch(to_block),
Instruction::Call(func, args) => self.compile_call(instr_val, func, args),
Instruction::CastPtr(val, ty, offs) => {
self.compile_cast_ptr(instr_val, val, ty, *offs)
}
Instruction::CastPtr(val, ty) => self.compile_cast_ptr(instr_val, val, ty),
Instruction::Cmp(pred, lhs_value, rhs_value) => {
self.compile_cmp(instr_val, pred, lhs_value, rhs_value)
}
Expand All @@ -331,14 +328,6 @@ impl<'ir> EvmAsmBuilder<'ir> {
gas,
..
} => self.compile_contract_call(instr_val, params, coins, asset_id, gas),
Instruction::ExtractElement {
array,
ty,
index_val,
} => self.compile_extract_element(instr_val, array, ty, index_val),
Instruction::ExtractValue {
aggregate, indices, ..
} => self.compile_extract_value(instr_val, aggregate, indices),
Instruction::FuelVm(fuel_vm_instr) => {
errors.push(CompileError::Internal(
"Invalid FuelVM IR instruction provided to the EVM code gen.",
Expand All @@ -347,32 +336,32 @@ impl<'ir> EvmAsmBuilder<'ir> {
.unwrap_or_else(Self::empty_span),
));
}
Instruction::GetLocal(local_var) => self.compile_get_local(instr_val, local_var),
Instruction::InsertElement {
array,
ty,
value,
index_val,
} => self.compile_insert_element(instr_val, array, ty, value, index_val),
Instruction::InsertValue {
aggregate,
value,
Instruction::GetElemPtr {
base,
elem_ptr_ty,
indices,
..
} => self.compile_insert_value(instr_val, aggregate, value, indices),
} => self.compile_get_elem_ptr(instr_val, base, elem_ptr_ty, indices),
Instruction::GetLocal(local_var) => self.compile_get_local(instr_val, local_var),
Instruction::IntToPtr(val, _) => self.compile_int_to_ptr(instr_val, val),
Instruction::Load(src_val) => check!(
self.compile_load(instr_val, src_val),
return err(warnings, errors),
warnings,
errors
),
Instruction::MemCopy {
dst_val,
src_val,
Instruction::MemCopyBytes {
dst_val_ptr,
src_val_ptr,
byte_len,
} => self.compile_mem_copy(instr_val, dst_val, src_val, *byte_len),
} => self.compile_mem_copy_bytes(instr_val, dst_val_ptr, src_val_ptr, *byte_len),
Instruction::MemCopyVal {
dst_val_ptr,
src_val_ptr,
} => self.compile_mem_copy_val(instr_val, dst_val_ptr, src_val_ptr),
Instruction::Nop => (),
Instruction::PtrToInt(ptr_val, int_ty) => {
self.compile_ptr_to_int(instr_val, ptr_val, int_ty)
}
Instruction::Ret(ret_val, ty) => {
if func_is_entry {
self.compile_ret_from_entry(instr_val, ret_val, ty)
Expand All @@ -381,7 +370,7 @@ impl<'ir> EvmAsmBuilder<'ir> {
}
}
Instruction::Store {
dst_val,
dst_val_ptr: dst_val,
stored_val,
} => check!(
self.compile_store(instr_val, dst_val, stored_val),
Expand Down Expand Up @@ -410,10 +399,6 @@ impl<'ir> EvmAsmBuilder<'ir> {
todo!();
}

fn compile_addr_of(&mut self, instr_val: &Value, arg: &Value) {
todo!();
}

fn compile_bitcast(&mut self, instr_val: &Value, bitcast_val: &Value, to_type: &Type) {
todo!();
}
Expand All @@ -432,7 +417,7 @@ impl<'ir> EvmAsmBuilder<'ir> {
todo!();
}

fn compile_cast_ptr(&mut self, instr_val: &Value, val: &Value, ty: &Type, offs: u64) {
fn compile_cast_ptr(&mut self, instr_val: &Value, val: &Value, ty: &Type) {
todo!();
}

Expand Down Expand Up @@ -471,72 +456,60 @@ impl<'ir> EvmAsmBuilder<'ir> {
todo!();
}

fn compile_extract_element(
fn compile_get_storage_key(&mut self, instr_val: &Value) -> CompileResult<()> {
todo!();
}

fn compile_get_elem_ptr(
&mut self,
instr_val: &Value,
array: &Value,
ty: &Type,
index_val: &Value,
base: &Value,
elem_ptr_ty: &Type,
indices: &[Value],
) {
todo!();
}

fn compile_extract_value(&mut self, instr_val: &Value, aggregate_val: &Value, indices: &[u64]) {
fn compile_get_local(&mut self, instr_val: &Value, local_var: &LocalVar) {
todo!();
}

fn compile_get_storage_key(&mut self, instr_val: &Value) -> CompileResult<()> {
fn compile_gtf(&mut self, instr_val: &Value, index: &Value, tx_field_id: u64) {
todo!();
}

fn compile_get_local(&mut self, instr_val: &Value, local_var: &LocalVar) {
fn compile_int_to_ptr(&mut self, instr_val: &Value, int_to_ptr_val: &Value) {
todo!();
}

fn compile_gtf(&mut self, instr_val: &Value, index: &Value, tx_field_id: u64) {
fn compile_load(&mut self, instr_val: &Value, src_val: &Value) -> CompileResult<()> {
todo!();
}

fn compile_insert_element(
&mut self,
instr_val: &Value,
array: &Value,
ty: &Type,
value: &Value,
index_val: &Value,
) {
fn compile_log(&mut self, instr_val: &Value, log_val: &Value, log_ty: &Type, log_id: &Value) {
todo!();
}

fn compile_insert_value(
fn compile_mem_copy_bytes(
&mut self,
instr_val: &Value,
aggregate_val: &Value,
value: &Value,
indices: &[u64],
dst_val_ptr: &Value,
src_val_ptr: &Value,
byte_len: u64,
) {
todo!();
}

fn compile_int_to_ptr(&mut self, instr_val: &Value, int_to_ptr_val: &Value) {
todo!();
}

fn compile_load(&mut self, instr_val: &Value, src_val: &Value) -> CompileResult<()> {
todo!();
}

fn compile_mem_copy(
fn compile_mem_copy_val(
&mut self,
instr_val: &Value,
dst_val: &Value,
src_val: &Value,
byte_len: u64,
dst_val_ptr: &Value,
src_val_ptr: &Value,
) {
todo!();
}

fn compile_log(&mut self, instr_val: &Value, log_val: &Value, log_ty: &Type, log_id: &Value) {
fn compile_ptr_to_int(&mut self, instr_val: &Value, ptr_val: &Value, int_ty: &Type) {
todo!();
}

Expand Down
46 changes: 1 addition & 45 deletions sway-core/src/asm_generation/from_ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ pub enum StateAccessType {

pub(crate) fn ir_type_size_in_bytes(context: &Context, ty: &Type) -> u64 {
match ty.get_content(context) {
TypeContent::Unit | TypeContent::Bool | TypeContent::Uint(_) => 8,
TypeContent::Unit | TypeContent::Bool | TypeContent::Uint(_) | TypeContent::Pointer(_) => 8,
TypeContent::Slice => 16,
TypeContent::B256 => 32,
TypeContent::String(n) => size_bytes_round_up_to_word_alignment!(*n),
Expand All @@ -223,47 +223,3 @@ pub(crate) fn ir_type_size_in_bytes(context: &Context, ty: &Type) -> u64 {
}
}
}

// Aggregate (nested) field offset in words and size in bytes.
pub(crate) fn aggregate_idcs_to_field_layout(
context: &Context,
ty: &Type,
idcs: &[u64],
) -> ((u64, u64), Type) {
idcs.iter().fold(((0, 0), *ty), |((offs, _), ty), idx| {
if ty.is_struct(context) {
let idx = *idx as usize;
let field_types = ty.get_field_types(context);
let field_type = field_types[idx];
let field_offs_in_bytes = field_types
.iter()
.take(idx)
.map(|field_ty| ir_type_size_in_bytes(context, field_ty))
.sum::<u64>();
let field_size_in_bytes = ir_type_size_in_bytes(context, &field_type);

(
(
offs + size_bytes_in_words!(field_offs_in_bytes),
field_size_in_bytes,
),
field_type,
)
} else if ty.is_union(context) {
let idx = *idx as usize;
let field_type = ty.get_field_types(context)[idx];
let union_size_in_bytes = ir_type_size_in_bytes(context, &ty);
let field_size_in_bytes = ir_type_size_in_bytes(context, &field_type);
// The union fields are at offset (union_size - variant_size) due to left padding.
(
(
offs + size_bytes_in_words!(union_size_in_bytes - field_size_in_bytes),
field_size_in_bytes,
),
field_type,
)
} else {
panic!("Attempt to access field in non-aggregate.")
}
})
}
21 changes: 18 additions & 3 deletions sway-core/src/asm_generation/fuel/abstract_instruction_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,9 @@ impl AbstractInstructionSet {
/// algorithm (https://en.wikipedia.org/wiki/Chaitin%27s_algorithm). The individual steps of
/// the algorithm are thoroughly explained in register_allocator.rs.
///
pub(crate) fn allocate_registers(self) -> AllocatedAbstractInstructionSet {
pub(crate) fn allocate_registers(
self,
) -> Result<AllocatedAbstractInstructionSet, CompileError> {
// Step 1: Liveness Analysis.
let live_out = register_allocator::liveness_analysis(&self.ops);

Expand All @@ -183,8 +185,21 @@ impl AbstractInstructionSet {
// each colorable node and its neighbors.
let mut stack = register_allocator::color_interference_graph(&mut interference_graph);

// Uncomment the following to get some idea of which function is failing to complete
// register allocation. The last comment printed will indicate the current function name.
// This will be unnecessary once we have the new register allocator, coming very soon!
//
//let comment = self.ops.iter().find_map(|op| {
// if let Either::Right(crate::asm_lang::ControlFlowOp::Label(_)) = op.opcode {
// Some(op.comment.clone())
// } else {
// None
// }
//});
//dbg!(comment);

// Step 5: Use the stack to assign a register for each virtual register.
let pool = register_allocator::assign_registers(&mut stack);
let pool = register_allocator::assign_registers(&mut stack)?;

// Step 6: Update all instructions to use the resulting register pool.
let mut buf = vec![];
Expand All @@ -196,7 +211,7 @@ impl AbstractInstructionSet {
})
}

AllocatedAbstractInstructionSet { ops: buf }
Ok(AllocatedAbstractInstructionSet { ops: buf })
}
}

Expand Down
Loading

0 comments on commit d6238ae

Please sign in to comment.