-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Generate actual bytecode using
fuel_asm
(#52)
* begin register allocator * begin reg alloc * mutable virtual registers; basic allocation algorithm skeleton * mutable registers in allocation * pull in fuel-asm official ops * switching laptops * begin work on virtual registers and ops * daily checkpoint * add AllocatedOp abstraction * template for parsing ops * allocation algorithm progress * change op parsing logic * WIP parsing inline asm to new ops * more op parsing * finish parsing virtual ops from asm * start registers method * register allocation method * convert virtual registers to allocated ones * switch back to organizational labels for jumps * realized ops * fully allocate registers and resolve labels * print allocated registers * fill in todo!() errors in asm parsing * resolve all todosudo apt-get install vlc in core_lang * switch to ssh for fuel-asm * resolve warnings * fix git url * rustfmt * small self-code-review * resolve module * map the virtual opcodes to fuel_asm ops * code review feedback * factor finalized asm out into its own file * realize data section and instructions to bits * data section offset label * initial bytecode generation * add forc --asm command * print out the loading of the data section op * resolve warnings * fix register allocater bug * cleanup * fix bad error message * code review feedback * fix doctest * fix typo * reference fuel_core for register constants * new ssh key * git change rust version * wrong rust version Co-authored-by: Alexander Hansen <alexanderhansen@Alexanders-MacBook-Pro.local>
- Loading branch information
Showing
20 changed files
with
799 additions
and
187 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,15 @@ | ||
pub(crate) const NUM_FREE_REGISTERS: u8 = 48; | ||
/// The number of registers available for the compiler to use. Registers reserved by the | ||
/// compiler are contained within these. | ||
const NUM_FREE_REGISTERS: u8 = 48; | ||
pub(crate) const TWENTY_FOUR_BITS: u64 = 0b111_111_111_111_111_111_111_111; | ||
pub(crate) const EIGHTEEN_BITS: u64 = 0b111_111_111_111_111_111; | ||
pub(crate) const TWELVE_BITS: u64 = 0b111_111_111_111; | ||
|
||
/// This is the number of registers reserved by the compiler. Adjust this number if a new | ||
/// reservation must be made. | ||
/// So far, the compiler-reserved registers are: | ||
/// 1. DATA_SECTION_BEGIN | ||
const NUM_COMPILER_RESERVED_REGISTERS: u8 = 1; | ||
pub(crate) const DATA_SECTION_REGISTER: u8 = NUM_FREE_REGISTERS - 2; | ||
pub(crate) const NUM_ALLOCATABLE_REGISTERS: u8 = | ||
NUM_FREE_REGISTERS - NUM_COMPILER_RESERVED_REGISTERS; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
use super::{DataSection, InstructionSet}; | ||
use crate::error::*; | ||
use either::Either; | ||
use std::io::Write; | ||
/// Represents an ASM set which has had register allocation, jump elimination, and optimization | ||
/// applied to it | ||
pub enum FinalizedAsm<'sc> { | ||
ContractAbi, | ||
ScriptMain { | ||
data_section: DataSection<'sc>, | ||
program_section: InstructionSet<'sc>, | ||
}, | ||
PredicateMain { | ||
data_section: DataSection<'sc>, | ||
program_section: InstructionSet<'sc>, | ||
}, | ||
// Libraries do not generate any asm. | ||
Library, | ||
} | ||
|
||
impl<'sc> FinalizedAsm<'sc> { | ||
pub(crate) fn to_bytecode(&self) -> CompileResult<'sc, Vec<u8>> { | ||
use FinalizedAsm::*; | ||
match self { | ||
ContractAbi | Library => ok(vec![], vec![], vec![]), | ||
ScriptMain { | ||
program_section, | ||
data_section, | ||
} => to_bytecode(program_section, data_section), | ||
PredicateMain { | ||
program_section, | ||
data_section, | ||
} => to_bytecode(program_section, data_section), | ||
} | ||
} | ||
} | ||
|
||
fn to_bytecode<'sc>( | ||
program_section: &InstructionSet<'sc>, | ||
data_section: &DataSection<'sc>, | ||
) -> CompileResult<'sc, Vec<u8>> { | ||
let mut errors = vec![]; | ||
if program_section.ops.len() & 1 != 0 { | ||
println!("ops len: {}", program_section.ops.len()); | ||
errors.push(CompileError::Internal( | ||
"Non-word-aligned (odd-number) ops generated. This is an invariant violation.", | ||
pest::Span::new(" ", 0, 0).unwrap(), | ||
)); | ||
return err(vec![], errors); | ||
} | ||
// The below invariant is introduced to word-align the data section. | ||
// A noop is inserted in ASM generation if there is an odd number of ops. | ||
assert_eq!(program_section.ops.len() & 1, 0); | ||
let offset_to_data_section = (program_section.ops.len() * 4) as u64; | ||
|
||
// each op is four bytes, so the length of the buf is then number of ops times four. | ||
let mut buf = vec![0; program_section.ops.len() * 4]; | ||
|
||
for (ix, op) in program_section.ops.iter().enumerate() { | ||
let op = op.to_fuel_asm(offset_to_data_section, data_section); | ||
match op { | ||
Either::Right(data) => { | ||
for i in 0..data.len() { | ||
buf[ix + i] = data[i]; | ||
} | ||
} | ||
Either::Left(mut op) => { | ||
op.write(&buf[ix * 4..]) | ||
.expect("Failed to write to in-memory buffer."); | ||
} | ||
} | ||
} | ||
|
||
let mut data_section = data_section.serialize_to_bytes(); | ||
|
||
buf.append(&mut data_section); | ||
|
||
ok(buf, vec![], errors) | ||
} |
Oops, something went wrong.