compile.rs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. use std::i64;
  2. use super::ir;
  3. use std::io::{Write, Read};
  4. use std::mem;
  5. use super::ir::{MutVisitor, Instruction};
  6. use winapi::um::memoryapi::VirtualAlloc;
  7. use winapi::um::winnt::{MEM_COMMIT, PAGE_EXECUTE_READWRITE};
  8. use dynasmrt::{DynasmApi, DynasmLabelApi};
  9. pub fn compile(mut instrs: Vec<ir::Instruction>) -> Vec<u8> {
  10. /*let mut ops = dynasmrt::x64::Assembler::new().unwrap();
  11. let string = "Hello World!";
  12. dynasm!(ops
  13. ; ->hello:
  14. ; .bytes string.as_bytes()
  15. );
  16. let hello = ops.offset();
  17. dynasm!(ops
  18. ; lea rcx, [->hello]
  19. ; xor edx, edx
  20. ; mov dl, BYTE string.len() as _
  21. ; sub rsp, BYTE 0x28
  22. ; call rax
  23. ; add rsp, BYTE 0x28
  24. ; ret
  25. );
  26. let buf = ops.finalize().unwrap();
  27. buf.to_vec()
  28. */
  29. let mut cg = CodeGenerator::new();
  30. cg.initialize();
  31. let entry = cg.buffer.offset();
  32. cg.visit_instructions(&mut instrs);
  33. cg.buffer.commit();
  34. cg.finalize();
  35. //let buf = cg.buffer.finalize().unwrap();
  36. //let ret = buf.to_vec();
  37. //println!("{:02x?}", ret);
  38. let function: extern "C" fn(memory: *mut u8) -> bool = unsafe {
  39. //mem::transmute(cg.get_callable())
  40. mem::transmute(cg.buffer.finalize().unwrap().ptr(entry))
  41. };
  42. let mut data: Vec<u8> = Vec::with_capacity(100000);
  43. unsafe {
  44. //function(&mut *data.into_boxed_slice().as_mut_ptr() as *mut u8);
  45. function(std::alloc::alloc_zeroed(std::alloc::Layout::new::<[u8; 1000]>()));
  46. }
  47. //cg.into_vec()
  48. //ret
  49. vec![]
  50. }
  51. pub struct CodeGenerator {
  52. pub buffer: dynasmrt::x64::Assembler
  53. }
  54. impl CodeGenerator {
  55. pub fn new() -> Self {
  56. CodeGenerator {
  57. buffer: dynasmrt::x64::Assembler::new().unwrap()
  58. }
  59. }
  60. pub fn initialize(&mut self) {
  61. dynasm!(self.buffer
  62. ; xor rsi, rsi
  63. );
  64. }
  65. pub fn finalize(&mut self) {
  66. dynasm!(self.buffer
  67. ; ret
  68. );
  69. }
  70. #[cfg(target_os = "windows")]
  71. pub fn get_callable(self) -> *const u8 {
  72. let data = self.buffer.finalize().unwrap().to_vec();
  73. println!("asm buffer of size {}", data.len());
  74. let ex = unsafe { VirtualAlloc(0 as _, data.len(), MEM_COMMIT, PAGE_EXECUTE_READWRITE) };
  75. unsafe {
  76. std::ptr::copy_nonoverlapping(data.as_ptr(), ex as _, data.len());
  77. }
  78. ex as _
  79. }
  80. #[cfg(not(target_os = "windows"))]
  81. pub fn get_callable(self) {
  82. }
  83. }
  84. impl ir::MutVisitor for CodeGenerator {
  85. type Ret = ();
  86. fn visit_add(&mut self, add: &'_ mut Instruction) {
  87. if let Instruction::Add{ offset, value } = add {
  88. dynasm!(self.buffer
  89. ; add [rdi + rsi + *offset as i32], BYTE *value as i8
  90. );
  91. }
  92. }
  93. fn visit_linear_loop(&mut self, l: &mut Instruction) {
  94. if let Instruction::LinearLoop(factors) = l {
  95. if factors.len() > 1 ||
  96. factors.len() >= 1 && !factors.contains_key(&0) {
  97. dynasm!(self.buffer
  98. ; mov cl, BYTE [rdi + rsi]
  99. );
  100. }
  101. for (&offset, &mut factor) in factors {
  102. if offset == 0 {
  103. continue;
  104. }
  105. if factor == 0 {
  106. }
  107. else if factor == 1 {
  108. dynasm!(self.buffer
  109. ; add BYTE [rdi + rsi + offset as i32], cl
  110. );
  111. }
  112. else if factor == -1 {
  113. dynasm!(self.buffer
  114. ; sub BYTE [rdi + rsi + offset as i32], cl
  115. );
  116. }
  117. else if factor.count_ones() == 1 {
  118. dynasm!(self.buffer
  119. ; mov bl, cl
  120. ; shl bl, factor.trailing_zeros() as i8
  121. ; add BYTE [rdi + rsi + offset as i32], bl
  122. );
  123. }
  124. else if (-factor).count_ones() == 1 {
  125. dynasm!(self.buffer
  126. ; mov bl, cl
  127. ; shl bl, factor.trailing_zeros() as i8
  128. ; sub BYTE [rdi + rsi + offset as i32], bl
  129. );
  130. }
  131. else {
  132. dynasm!(self.buffer
  133. ; mov al, factor as i8
  134. ; mul cl
  135. ; add BYTE [rdi + rsi + offset as i32], al
  136. );
  137. }
  138. }
  139. dynasm!(self.buffer
  140. ; mov BYTE [rdi + rsi], 0
  141. );
  142. }
  143. }
  144. fn visit_move_ptr(&mut self, mp: &'_ mut Instruction) {
  145. if let Instruction::MovePtr(offset) = mp {
  146. dynasm!(self.buffer
  147. ; add rsi, DWORD *offset as i32
  148. );
  149. }
  150. }
  151. fn visit_loop(&mut self, l: &mut Instruction) {
  152. if let Instruction::Loop(insts) = l {
  153. let begin = self.buffer.new_dynamic_label();
  154. let end = self.buffer.new_dynamic_label();
  155. dynasm!(self.buffer
  156. ; mov al, BYTE [rdi + rsi]
  157. ; test al, al
  158. ; jz => end
  159. ; => begin
  160. );
  161. self.visit_instructions(insts);
  162. dynasm!(self.buffer
  163. ; mov al, BYTE [rdi + rsi]
  164. ; test al, al
  165. ; jnz => begin
  166. ; => end
  167. );
  168. }
  169. }
  170. fn visit_read(&mut self, r: &mut Instruction) {
  171. if let Instruction::Read(offset) = r {
  172. dynasm!(self.buffer
  173. ; push rdi
  174. ; push rsi
  175. ; sub rsp, 24
  176. ; mov rax, QWORD readbyte as _
  177. ; call rax
  178. ; add rsp, 24
  179. ; pop rsi
  180. ; pop rdi
  181. ; mov BYTE [rdi + rsi + *offset as i32], al
  182. );
  183. }
  184. }
  185. fn visit_write(&mut self, w: &mut Instruction) {
  186. if let Instruction::Write(offset) = w {
  187. dynasm!(self.buffer
  188. ; push rdi
  189. ; push rsi
  190. ; sub rsp, 24
  191. ; mov dil, BYTE [rdi + rsi + *offset as i32]
  192. ; mov rax, QWORD putbyte as _
  193. ; call rax
  194. ; add rsp, 24
  195. ; pop rsi
  196. ; pop rdi
  197. );
  198. }
  199. }
  200. }
  201. extern "C" fn putbyte(chr: u8) {
  202. //print!("{:?}", chr as char);
  203. std::io::stdout().write(&[chr]);
  204. }
  205. extern "C" fn readbyte() -> u8 {
  206. let mut byte: u8 = 0;
  207. //std::io::stdin().read(&mut [byte]).unwrap();
  208. std::io::stdin().bytes().next().unwrap_or(Ok(0)).unwrap_or(0)
  209. }