Skip to content

Commit

Permalink
feat(codegen): handle offset label for relocation
Browse files Browse the repository at this point in the history
  • Loading branch information
clearloop committed Nov 20, 2024
1 parent 7ab57c4 commit e378a11
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 47 deletions.
29 changes: 14 additions & 15 deletions codegen/src/jump/pc.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Program counter handlers.
use crate::{
jump::{relocate, Jump, JumpTable},
jump::{Jump, JumpTable},
Error, Result, BUFFER_LIMIT,
};

Expand All @@ -10,8 +10,8 @@ impl JumpTable {
pub fn shift_pc(&mut self, start: u16, offset: u16) -> Result<()> {
tracing::trace!("shift pc from 0x{start:x} with offset={offset}");
self.shift_label_pc(start, offset)?;
self.shift_label_target(start, 0, offset)?;
self.shift_func_target(start, 0, offset)?;
self.shift_label_target(start, offset)?;
self.shift_func_target(start, offset)?;

Ok(())
}
Expand All @@ -35,9 +35,8 @@ impl JumpTable {
total_offset
},
)?;
// let offset = self.target_offset(&target, total_offset)?;

self.shift_target(pc, total_offset, offset)?;
self.shift_target(pc, offset)?;
total_offset += offset;
Ok(())
})
Expand All @@ -48,10 +47,10 @@ impl JumpTable {
/// 1. shift code section.
/// 2. shift label targets.
/// 3. shift function targets.
pub fn shift_target(&mut self, ptr: u16, total_offset: u16, target_offset: u16) -> Result<()> {
self.code.shift(target_offset);
self.shift_label_target(ptr, total_offset, target_offset)?;
self.shift_func_target(ptr, total_offset, target_offset)
pub fn shift_target(&mut self, ptr: u16, offset: u16) -> Result<()> {
self.code.shift(offset);
self.shift_label_target(ptr, offset)?;
self.shift_func_target(ptr, offset)
}

/// Shift program counter for labels.
Expand Down Expand Up @@ -82,7 +81,7 @@ impl JumpTable {
}

/// Shift program counter for functions.
pub fn shift_func_target(&mut self, ptr: u16, total_offset: u16, offset: u16) -> Result<()> {
pub fn shift_func_target(&mut self, ptr: u16, offset: u16) -> Result<()> {
if self.func.is_empty() {
tracing::trace!("No functions to shift.");
return Ok(());
Expand All @@ -93,14 +92,14 @@ impl JumpTable {

if *target > ptr {
tracing::trace!(
"[{total_offset}] shift Func({index}) target with offset={offset}: 0x{target:x}(0x{ptr:x}) -> 0x{:x}",
"shift Func({index}) target with offset={offset}: 0x{target:x}(0x{ptr:x}) -> 0x{:x}",
next_target
);

*target = next_target;
} else {
tracing::trace!(
"[{total_offset}] shift Func({index}) target with offset=0: 0x{target:x}(0x{ptr:x}) -> 0x{target:x}"
"shift Func({index}) target with offset=0: 0x{target:x}(0x{ptr:x}) -> 0x{target:x}"
);
}

Expand All @@ -109,7 +108,7 @@ impl JumpTable {
}

/// Shift target program counter for labels.
pub fn shift_label_target(&mut self, ptr: u16, total_offset: u16, offset: u16) -> Result<()> {
pub fn shift_label_target(&mut self, ptr: u16, offset: u16) -> Result<()> {
if self.jump.is_empty() {
tracing::trace!("No labels to shift.");
return Ok(());
Expand All @@ -121,14 +120,14 @@ impl JumpTable {

if *label > ptr {
tracing::trace!(
"[{total_offset}] shift Label(0x{pc:x}) target with offset={offset}: 0x{label:x}(0x{ptr:x}) -> 0x{:x}",
"shift Label(0x{pc:x}) target with offset={offset}: 0x{label:x}(0x{ptr:x}) -> 0x{:x}",
next_label,
);

*label = next_label;
} else {
tracing::trace!(
"[{total_offset}] shift Label(0x{pc:x}) target with offset=0: 0x{label:x}(0x{ptr:x}) -> 0x{label:x}"
"shift Label(0x{pc:x}) target with offset=0: 0x{label:x}(0x{ptr:x}) -> 0x{label:x}"
);
}
}
Expand Down
58 changes: 29 additions & 29 deletions codegen/src/jump/relocate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,35 +37,35 @@ impl JumpTable {
}
}

/// Get the offset of the program counter for relocation.
pub fn offset(pc: u16) -> Result<u16> {
let mut offset = 0;

// Update the target program counter
{
// The maximum size of the PC is 2 bytes, whatever PUSH1 or PUSH32
// takes 1 more byte.
offset += 1;

// Update the program counter for the edge cases.
//
// Start from 0xff, the lowest significant bytes of the target
// program counter will take 2 bytes instead of 1 byte.
//
// | PC | PC BYTES | TARGET PC |
// |------|----------|-----------|
// | 0xfe | 1 | 0xff |
// | 0xff | 2 | 0x0101 |
offset += if pc > 0xfe { 2 } else { 1 }
}

// Check PC range.
if pc + offset > BUFFER_LIMIT as u16 {
return Err(Error::InvalidPC((pc + offset) as usize));
}

Ok(offset)
}
// /// Get the offset of the program counter for relocation.
// pub fn offset(pc: u16) -> Result<u16> {
// let mut offset = 0;
//
// // Update the target program counter
// {
// // The maximum size of the PC is 2 bytes, whatever PUSH1 or PUSH32
// // takes 1 more byte.
// offset += 1;
//
// // Update the program counter for the edge cases.
// //
// // Start from 0xff, the lowest significant bytes of the target
// // program counter will take 2 bytes instead of 1 byte.
// //
// // | PC | PC BYTES | TARGET PC |
// // |------|----------|-----------|
// // | 0xfe | 1 | 0xff |
// // | 0xff | 2 | 0x0101 |
// offset += if pc > 0xfe { 2 } else { 1 }
// }
//
// // Check PC range.
// if pc + offset > BUFFER_LIMIT as u16 {
// return Err(Error::InvalidPC((pc + offset) as usize));
// }
//
// Ok(offset)
// }

/// Relocate program counter to buffer.
fn pc(buffer: &mut Buffer, original_pc: u16, target_pc: u16) -> Result<usize> {
Expand Down
4 changes: 2 additions & 2 deletions codegen/src/visitor/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl Function {
.into());
}

tracing::trace!("call internal function: index={index}");
tracing::debug!("call internal function: index={index}");
let (params, results) = self.env.funcs.get(&index).unwrap_or(&(0, 0));

// TODO: adapat the case that the params is larger than 0xff (#247)
Expand All @@ -53,7 +53,7 @@ impl Function {
// [ ..,
// <PC>,
// params[SWAP], params[PUSH, SLOT, MSTORE],
// PUSH, PC, JUMP, <JUMPDEST>
// {(PUSH, PC), JUMP, JUMPDEST}
// ]
// <- selfparams[PUSH, OFFSET, CALLDATALOAD]
//
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ impl<'p> Parser<'p> {
let locals = fun.body.get_locals_reader()?.get_count();
let params = sig.params().len();
tracing::trace!(
"computing slots for function {idx}, locals: {locals}, params: {params}, reserved: {slots}"
"computing slots for function {idx}, locals: {locals}, params: {params}, reserved: {slots}, external: {}",
self.env.is_external(fun.index())
);

self.env.slots.insert(fun.index(), slots);
Expand All @@ -56,6 +57,8 @@ impl<'p> Parser<'p> {
.insert(fun.index(), (params as u32, sig.results().len() as u32));

slots += locals;

// process prarams for internal functions only
if !self.env.is_external(fun.index()) && !self.env.is_main(fun.index()) {
slots += params as u32;
}
Expand Down

0 comments on commit e378a11

Please sign in to comment.