Skip to content

Commit c0fb333

Browse files
committed
Merge branch 'trying-to-fix-reljumps' into implement-stack-map-table
2 parents 4049f89 + 732396c commit c0fb333

File tree

2 files changed

+49
-52
lines changed

2 files changed

+49
-52
lines changed

Diff for: lib/src/codegen/reljumps.rs

+47-52
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::codegen::Instruction;
2+
use std::cmp::{max, min};
23

34
fn get_instruction_length(istr: &Instruction) -> u16 {
45
match istr {
@@ -21,73 +22,62 @@ fn get_instructions_length(instructions: &[Instruction]) -> u16 {
2122
pub(crate) fn convert_to_absolute_jumps(instructions: Vec<Instruction>) -> Vec<Instruction> {
2223
let mut result = vec![];
2324
for (j, istr) in instructions.iter().enumerate() {
25+
let current_offset = get_instructions_length(&instructions[..j]);
2426
match istr {
27+
Instruction::relgoto(target) => {
28+
let absolute_addr =
29+
calculate_absolute_addr(*target, current_offset, j, &instructions);
30+
result.push(Instruction::goto(absolute_addr, *target));
31+
}
2532
Instruction::reljumpifeq(target) => {
26-
let modifier: i32 = if *target < 0 { -1 } else { 1 };
27-
result.push(Instruction::ifeq(
28-
(get_instructions_length(
29-
&instructions[j..j.saturating_add_signed(*target as isize)],
30-
) as i32
31-
* modifier
32-
+ j as i32
33-
- 1) as u16,
34-
*target,
35-
))
33+
let absolute_addr =
34+
calculate_absolute_addr(*target, current_offset, j, &instructions);
35+
result.push(Instruction::ifeq(absolute_addr, *target));
3636
}
3737
Instruction::reljumpifge(target) => {
38-
let modifier: i32 = if *target < 0 { -1 } else { 1 };
39-
result.push(Instruction::ifge(
40-
(get_instructions_length(
41-
&instructions[j..j.saturating_add_signed(*target as isize)],
42-
) as i32
43-
* modifier
44-
+ j as i32
45-
- 1) as u16,
46-
*target,
47-
))
48-
}
49-
Instruction::relgoto(target) => {
50-
let modifier: i32 = if *target < 0 { -1 } else { 1 };
51-
result.push(Instruction::goto(
52-
(get_instructions_length(
53-
&instructions[j..j.saturating_add_signed(*target as isize)],
54-
) as i32
55-
* modifier
56-
+ j as i32
57-
- 1) as u16,
58-
*target,
59-
))
38+
let absolute_addr =
39+
calculate_absolute_addr(*target, current_offset, j, &instructions);
40+
result.push(Instruction::ifge(absolute_addr, *target));
6041
}
6142
Instruction::reljumpiflt(target) => {
62-
let modifier: i32 = if *target < 0 { -1 } else { 1 };
63-
result.push(Instruction::iflt(
64-
(get_instructions_length(
65-
&instructions[j..j.saturating_add_signed(*target as isize)],
66-
) as i32
67-
* modifier
68-
+ j as i32
69-
- 1) as u16,
70-
*target,
71-
))
43+
let absolute_addr =
44+
calculate_absolute_addr(*target, current_offset, j, &instructions);
45+
result.push(Instruction::iflt(absolute_addr, *target));
7246
}
7347
Instruction::reljumpifne(target) => {
74-
let modifier: i32 = if *target < 0 { -1 } else { 1 };
75-
result.push(Instruction::ifne(
76-
(get_instructions_length(
77-
&instructions[j..j.saturating_add_signed(*target as isize)],
78-
) as i32
79-
* modifier
80-
+ j as i32
81-
- 1) as u16,
82-
*target,
83-
))
48+
let absolute_addr =
49+
calculate_absolute_addr(*target, current_offset, j, &instructions);
50+
result.push(Instruction::ifne(absolute_addr, *target));
8451
}
8552
_ => result.push(*istr),
8653
}
8754
}
8855
result
8956
}
9057

58+
fn calculate_absolute_addr(
59+
target: i16,
60+
current_offset: u16,
61+
j: usize,
62+
instructions: &[Instruction],
63+
) -> u16 {
64+
let modifier: i32 = if target < 0 { -1 } else { 1 };
65+
// Too dumb to figure out the formula for this so here is an ugly if statement
66+
if modifier > 0 {
67+
let min = min(j + 1, j.saturating_add_signed(target as isize));
68+
let max = max(j + 1, j.saturating_add_signed(target as isize));
69+
let instructions_to_jump_over = &instructions[min..max];
70+
let offset = get_instructions_length(instructions_to_jump_over);
71+
(offset as i32 * modifier + current_offset as i32) as u16
72+
} else {
73+
let min = min(j + 1, j.saturating_add_signed(target as isize));
74+
let max = max(j + 1, j.saturating_add_signed(target as isize)) - 1;
75+
let instructions_to_jump_over = &instructions[min..max];
76+
let offset = get_instructions_length(instructions_to_jump_over);
77+
(offset as i32 * modifier + current_offset as i32) as u16
78+
}
79+
}
80+
9181
#[cfg(test)]
9282
mod tests {
9383
use super::*;
@@ -140,4 +130,9 @@ mod tests {
140130
];
141131
assert_eq!(convert_to_absolute_jumps(instructions), expected);
142132
}
133+
#[test]
134+
fn test_calculate_instruction_size() {
135+
let instructions = vec![Instruction::reljumpifge(1), Instruction::relgoto(2)];
136+
assert_eq!(get_instructions_length(&instructions), 6);
137+
}
143138
}

Diff for: lib/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
extern crate core;
2+
13
pub mod codegen;
24
pub mod parser;
35
#[cfg(test)]

0 commit comments

Comments
 (0)