Skip to content

Commit 3a8a3b2

Browse files
committed
Make 𝐧𝐚𝐭𝐢𝐯𝐞_𝐦𝐚𝐜𝐡𝐢𝐧𝐞_𝐜𝐨𝐝𝐞 generic (supports i16/i32/i64/isize).
While isize displacement is enough for native compilation we may also want to generate code for a foreign architecture and this is realitively simple change. The only complication is rust-lang/rust#20671 Because of that limitation we have a lot of code duplication in that module. Also add smoke tests to verify that all supported operations work.
1 parent 266084f commit 3a8a3b2

File tree

11 files changed

+1871
-1079
lines changed

11 files changed

+1871
-1079
lines changed

lib/src/assembler/mc/mod.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,18 @@ pub trait 𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆_𝒆𝒎𝒊𝒕𝒕𝒆
126126

127127
fn new_label(&mut self) -> <Self::𝐜𝐨𝐝𝐞 as 𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆>::𝐥𝐚𝐛𝐞𝐥;
128128
fn set_label(&mut self, lbl: <Self::𝐜𝐨𝐝𝐞 as 𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆>::𝐥𝐚𝐛𝐞𝐥) -> Result<(), <Self::𝐜𝐨𝐝𝐞 as 𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆>::𝐞𝐫𝐫𝐨𝐫_𝐭𝐲𝐩𝐞>;
129+
fn emit_byte(&mut self, expr: <Self::𝐜𝐨𝐝𝐞 as 𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆>::𝐥𝐚𝐛𝐞𝐥_𝐞𝐱𝐩𝐫𝐞𝐬𝐬𝐢𝐨𝐧)
130+
-> Result<(), <Self::𝐜𝐨𝐝𝐞 as 𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆>::𝐞𝐫𝐫𝐨𝐫_𝐭𝐲𝐩𝐞>;
131+
fn emit_2byte(&mut self, expr: <Self::𝐜𝐨𝐝𝐞 as 𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆>::𝐥𝐚𝐛𝐞𝐥_𝐞𝐱𝐩𝐫𝐞𝐬𝐬𝐢𝐨𝐧)
132+
-> Result<(), <Self::𝐜𝐨𝐝𝐞 as 𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆>::𝐞𝐫𝐫𝐨𝐫_𝐭𝐲𝐩𝐞>;
133+
fn emit_4byte(&mut self, expr: <Self::𝐜𝐨𝐝𝐞 as 𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆>::𝐥𝐚𝐛𝐞𝐥_𝐞𝐱𝐩𝐫𝐞𝐬𝐬𝐢𝐨𝐧)
134+
-> Result<(), <Self::𝐜𝐨𝐝𝐞 as 𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆>::𝐞𝐫𝐫𝐨𝐫_𝐭𝐲𝐩𝐞>;
135+
fn emit_8byte(&mut self, expr: <Self::𝐜𝐨𝐝𝐞 as 𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆>::𝐥𝐚𝐛𝐞𝐥_𝐞𝐱𝐩𝐫𝐞𝐬𝐬𝐢𝐨𝐧)
136+
-> Result<(), <Self::𝐜𝐨𝐝𝐞 as 𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆>::𝐞𝐫𝐫𝐨𝐫_𝐭𝐲𝐩𝐞>;
129137
}
130138

131-
#[path = "native_code.rs"]
139+
#[path = "native-code.rs"]
132140
pub mod 𝗻𝗮𝘁𝗶𝘃𝗲_𝗰𝗼𝗱𝗲;
133141

134-
#[path = "numbered_labels.rs"]
142+
#[path = "numbered-labels.rs"]
135143
pub mod 𝗻𝘂𝗺𝗯𝗲𝗿𝗲𝗱_𝗹𝗮𝗯𝗲𝗹𝘀;
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/*
2+
* Permission is hereby granted, free of charge, to any human obtaining a copy of this software and associated documentation files
3+
* (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,
4+
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit humans to whom the Software is
5+
* furnished to do so, subject to the following conditions:
6+
*
7+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8+
*
9+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
10+
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
11+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
12+
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13+
*/
14+
15+
use super::{super::super::𝒅𝒚𝒏_𝒃𝒚𝒕𝒆_𝒆𝒎𝒊𝒕𝒕𝒆𝒓,𝐧𝐚𝐭𝐢𝐯𝐞_𝐦𝐚𝐜𝐡𝐢𝐧𝐞_𝐜𝐨𝐝𝐞};
16+
17+
struct 𝐭𝐞𝐬𝐭_𝐞𝐦𝐢𝐭𝐭𝐞𝐫 {
18+
𝖼𝗈𝗇𝗍𝖾𝗇𝗍: Vec<u8>,
19+
}
20+
21+
impl 𝐭𝐞𝐬𝐭_𝐞𝐦𝐢𝐭𝐭𝐞𝐫 {
22+
pub const fn new() -> Self {
23+
𝐭𝐞𝐬𝐭_𝐞𝐦𝐢𝐭𝐭𝐞𝐫 {
24+
𝖼𝗈𝗇𝗍𝖾𝗇𝗍: Vec::<u8>::new(),
25+
}
26+
}
27+
}
28+
29+
impl 𝒅𝒚𝒏_𝒃𝒚𝒕𝒆_𝒆𝒎𝒊𝒕𝒕𝒆𝒓 for 𝐭𝐞𝐬𝐭_𝐞𝐦𝐢𝐭𝐭𝐞𝐫 {
30+
#[inline(always)]
31+
fn emit_u8(&mut self, value: u8) -> Result<(), Box<dyn std::error::Error>> {
32+
self.𝖼𝗈𝗇𝗍𝖾𝗇𝗍.push(value);
33+
Ok(())
34+
}
35+
}
36+
37+
#[test]
38+
fn test_emit_labels_as_bytes_i16() {
39+
use super::super::𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆_𝒆𝒎𝒊𝒕𝒕𝒆𝒓;
40+
let mut machine_code = 𝐧𝐚𝐭𝐢𝐯𝐞_𝐦𝐚𝐜𝐡𝐢𝐧𝐞_𝐜𝐨𝐝𝐞::new();
41+
let label = machine_code.new_label();
42+
assert!(machine_code.set_label(label).is_ok());
43+
assert!(machine_code.emit_byte(label.into()).is_ok());
44+
assert!(machine_code.emit_2byte(label.into()).is_ok());
45+
assert!(machine_code.emit_4byte(label.into()).is_ok());
46+
assert!(machine_code.emit_8byte(label.into()).is_ok());
47+
assert_eq!(machine_code.finalize(0x1234i16, 10).unwrap(), 15);
48+
let mut raw_emitter = 𝐭𝐞𝐬𝐭_𝐞𝐦𝐢𝐭𝐭𝐞𝐫::new();
49+
assert!(machine_code.emit_code(&mut raw_emitter).is_ok());
50+
assert_eq!(
51+
&[0x34, 0x34, 0x12, 0x34, 0x12, 0x00, 0x00, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
52+
&raw_emitter.𝖼𝗈𝗇𝗍𝖾𝗇𝗍[0..raw_emitter.𝖼𝗈𝗇𝗍𝖾𝗇𝗍.len()]);
53+
}
54+
55+
#[test]
56+
fn test_emit_labels_as_bytes_i32() {
57+
use super::super::𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆_𝒆𝒎𝒊𝒕𝒕𝒆𝒓;
58+
let mut machine_code = 𝐧𝐚𝐭𝐢𝐯𝐞_𝐦𝐚𝐜𝐡𝐢𝐧𝐞_𝐜𝐨𝐝𝐞::new();
59+
let label = machine_code.new_label();
60+
assert!(machine_code.set_label(label).is_ok());
61+
assert!(machine_code.emit_byte(label.into()).is_ok());
62+
assert!(machine_code.emit_2byte(label.into()).is_ok());
63+
assert!(machine_code.emit_4byte(label.into()).is_ok());
64+
assert!(machine_code.emit_8byte(label.into()).is_ok());
65+
assert_eq!(machine_code.finalize(0x12345678i32, 10).unwrap(), 15);
66+
let mut raw_emitter = 𝐭𝐞𝐬𝐭_𝐞𝐦𝐢𝐭𝐭𝐞𝐫::new();
67+
assert!(machine_code.emit_code(&mut raw_emitter).is_ok());
68+
assert_eq!(
69+
&[0x78, 0x78, 0x56, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00],
70+
&raw_emitter.𝖼𝗈𝗇𝗍𝖾𝗇𝗍[0..raw_emitter.𝖼𝗈𝗇𝗍𝖾𝗇𝗍.len()]);
71+
}
72+
73+
#[test]
74+
fn test_emit_labels_as_bytes_i64() {
75+
use super::super::𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆_𝒆𝒎𝒊𝒕𝒕𝒆𝒓;
76+
let mut machine_code = 𝐧𝐚𝐭𝐢𝐯𝐞_𝐦𝐚𝐜𝐡𝐢𝐧𝐞_𝐜𝐨𝐝𝐞::new();
77+
let label = machine_code.new_label();
78+
assert!(machine_code.set_label(label).is_ok());
79+
assert!(machine_code.emit_byte(label.into()).is_ok());
80+
assert!(machine_code.emit_2byte(label.into()).is_ok());
81+
assert!(machine_code.emit_4byte(label.into()).is_ok());
82+
assert!(machine_code.emit_8byte(label.into()).is_ok());
83+
assert_eq!(machine_code.finalize(0x123456789abcdefi64, 10).unwrap(), 15);
84+
let mut raw_emitter = 𝐭𝐞𝐬𝐭_𝐞𝐦𝐢𝐭𝐭𝐞𝐫::new();
85+
assert!(machine_code.emit_code(&mut raw_emitter).is_ok());
86+
assert_eq!(
87+
&[0xef, 0xef, 0xcd, 0xef, 0xcd, 0xab, 0x89, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01],
88+
&raw_emitter.𝖼𝗈𝗇𝗍𝖾𝗇𝗍[0..raw_emitter.𝖼𝗈𝗇𝗍𝖾𝗇𝗍.len()]);
89+
}
90+
91+
#[test]
92+
fn test_emit_labels_as_bytes_isize() {
93+
use super::super::𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆_𝒆𝒎𝒊𝒕𝒕𝒆𝒓;
94+
let mut machine_code = 𝐧𝐚𝐭𝐢𝐯𝐞_𝐦𝐚𝐜𝐡𝐢𝐧𝐞_𝐜𝐨𝐝𝐞::new();
95+
let label = machine_code.new_label();
96+
assert!(machine_code.set_label(label).is_ok());
97+
assert!(machine_code.emit_byte(label.into()).is_ok());
98+
assert!(machine_code.emit_2byte(label.into()).is_ok());
99+
assert!(machine_code.emit_4byte(label.into()).is_ok());
100+
assert!(machine_code.emit_8byte(label.into()).is_ok());
101+
#[cfg(target_pointer_width = "32")]
102+
assert_eq!(machine_code.finalize(0x12345678isize, 10).unwrap(), 15);
103+
#[cfg(target_pointer_width = "64")]
104+
assert_eq!(machine_code.finalize(0x123456789abcdefisize, 10).unwrap(), 15);
105+
let mut raw_emitter = 𝐭𝐞𝐬𝐭_𝐞𝐦𝐢𝐭𝐭𝐞𝐫::new();
106+
assert!(machine_code.emit_code(&mut raw_emitter).is_ok());
107+
#[cfg(target_pointer_width = "32")]
108+
assert_eq!(
109+
&[0x78, 0x78, 0x56, 0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00],
110+
&raw_emitter.𝖼𝗈𝗇𝗍𝖾𝗇𝗍[0..raw_emitter.𝖼𝗈𝗇𝗍𝖾𝗇𝗍.len()]);
111+
#[cfg(target_pointer_width = "64")]
112+
assert_eq!(
113+
&[0xef, 0xef, 0xcd, 0xef, 0xcd, 0xab, 0x89, 0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01],
114+
&raw_emitter.𝖼𝗈𝗇𝗍𝖾𝗇𝗍[0..raw_emitter.𝖼𝗈𝗇𝗍𝖾𝗇𝗍.len()]);
115+
}
116+
117+
#[test]
118+
fn test_emit_label_operations_i64() {
119+
use super::super::𝒎𝒂𝒄𝒉𝒊𝒏𝒆_𝒄𝒐𝒅𝒆_𝒆𝒎𝒊𝒕𝒕𝒆𝒓;
120+
let mut machine_code = 𝐧𝐚𝐭𝐢𝐯𝐞_𝐦𝐚𝐜𝐡𝐢𝐧𝐞_𝐜𝐨𝐝𝐞::new();
121+
let label0 = machine_code.new_label();
122+
let label1 = machine_code.new_label();
123+
assert!(machine_code.set_label(label0).is_ok());
124+
assert!(machine_code.emit_8byte(label0+1).is_ok());
125+
assert!(machine_code.emit_8byte(label0-1).is_ok());
126+
assert!(machine_code.emit_8byte(label0*3).is_ok());
127+
assert!(machine_code.emit_8byte(label0/7).is_ok());
128+
assert!(machine_code.emit_8byte(label0%7).is_ok());
129+
assert!(machine_code.emit_8byte((label0<<7)>>7).is_ok());
130+
assert!(machine_code.emit_8byte((label0<<7)>>7u8).is_ok());
131+
assert!(machine_code.emit_8byte(-label0).is_ok());
132+
assert!(machine_code.emit_8byte(!label0).is_ok());
133+
assert!(machine_code.emit_8byte(label1-label0).is_ok());
134+
assert!(machine_code.set_label(label1).is_ok());
135+
assert_eq!(machine_code.finalize(0x123456789abcdefi64, 10).unwrap(), 80);
136+
let mut raw_emitter = 𝐭𝐞𝐬𝐭_𝐞𝐦𝐢𝐭𝐭𝐞𝐫::new();
137+
assert!(machine_code.emit_code(&mut raw_emitter).is_ok());
138+
assert_eq!(
139+
&[0xf0, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01,
140+
0xee, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01,
141+
0xcd, 0x69, 0x03, 0x9d, 0x36, 0xd0, 0x69, 0x03,
142+
0x8f, 0x66, 0xcf, 0x5c, 0x33, 0x9c, 0x29, 0x00,
143+
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144+
0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0xff,
145+
0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01,
146+
0x11, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe,
147+
0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe,
148+
0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
149+
&raw_emitter.𝖼𝗈𝗇𝗍𝖾𝗇𝗍[0..raw_emitter.𝖼𝗈𝗇𝗍𝖾𝗇𝗍.len()]);
150+
}

0 commit comments

Comments
 (0)