asm_backend.rs 20.9 KB
Newer Older
1 2
#![allow(unused_variables)]

3
use compiler::backend::x86_64;
4
use compiler::backend::x86_64::CodeGenerator;
5
use vm::machine_code::MachineCode;
6 7 8

use ast::ptr::P;
use ast::ir::*;
qinsoon's avatar
qinsoon committed
9
use ast::inst::*;
10

11 12
use std::collections::HashMap;
use std::str;
13
use std::usize;
14 15 16

struct ASMCode {
    name: MuTag, 
17 18
    code: Vec<ASM>,
    reg_defines: HashMap<MuID, Vec<ASMLocation>>,
19 20 21 22 23 24 25 26 27
    reg_uses: HashMap<MuID, Vec<ASMLocation>>,
    
    preds: Vec<Vec<usize>>,
    succs: Vec<Vec<usize>>,
    
    idx_to_blk: HashMap<usize, MuTag>,
    blk_to_idx: HashMap<MuTag, usize>,
    cond_branches: HashMap<usize, MuTag>,
    branches: HashMap<usize, MuTag>
28 29
}

30 31 32 33
impl MachineCode for ASMCode {
    fn number_of_insts(&self) -> usize {
        self.code.len()
    }
34
    
35 36 37 38 39 40 41 42
    fn is_move(&self, index: usize) -> bool {
        let inst = self.code.get(index);
        match inst {
            Some(inst) => inst.code.starts_with("mov"),
            None => false
        }
    }
    
qinsoon's avatar
qinsoon committed
43 44 45 46 47 48 49 50
    fn get_succs(&self, index: usize) -> &Vec<usize> {
        &self.succs[index]
    }
    
    fn get_preds(&self, index: usize) -> &Vec<usize> {
        &self.preds[index]
    }
    
51
    fn get_inst_reg_uses(&self, index: usize) -> &Vec<MuID> {
qinsoon's avatar
qinsoon committed
52
        &self.code[index].uses
53 54
    }
    
55
    fn get_inst_reg_defines(&self, index: usize) -> &Vec<MuID> {
qinsoon's avatar
qinsoon committed
56
        &self.code[index].defines
57
    }
58 59 60 61 62 63 64 65
    
    fn print(&self) {
        println!("");

        println!("code for {}: ", self.name);
        let n_insts = self.code.len();
        for i in 0..n_insts {
            let ref line = self.code[i];
66 67 68
            println!("#{}\t{:30}\t\tdefine: {:?}\tuses: {:?}\tpred: {:?}\tsucc: {:?}", 
                i, line.code, self.get_inst_reg_defines(i), self.get_inst_reg_uses(i),
                self.preds[i], self.succs[i]);
69 70 71
        }
        
        println!("");        
72 73 74 75 76 77 78
    }
}

struct ASM {
    code: String,
    defines: Vec<MuID>,
    uses: Vec<MuID>
79 80
}

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
impl ASM {
    fn symbolic(line: String) -> ASM {
        ASM {
            code: line,
            defines: vec![],
            uses: vec![]
        }
    }
    
    fn inst(inst: String, defines: Vec<MuID>, uses: Vec<MuID>) -> ASM {
        ASM {
            code: inst,
            defines: defines,
            uses: uses
        }
    }
    
    fn branch(line: String) -> ASM {
        ASM {
            code: line,
            defines: vec![],
            uses: vec![]
        }
    }
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    
    fn call(line: String) -> ASM {
        ASM {
            code: line,
            defines: vec![],
            uses: vec![]
        }
    }
    
    fn ret(line: String) -> ASM {
        ASM {
            code: line,
            defines: vec![],
            uses: vec![]
        }
    }
121 122
}

123
#[derive(Clone, Debug)]
124 125 126 127 128 129 130
struct ASMLocation {
    line: usize,
    index: usize,
    len: usize
}

impl ASMLocation {
131 132
    /// the 'line' field will be updated later
    fn new(index: usize, len: usize) -> ASMLocation {
133
        ASMLocation{
134
            line: usize::MAX,
135 136 137 138 139 140
            index: index,
            len: len
        }
    }
}

141
pub struct ASMCodeGen {
142
    cur: Option<Box<ASMCode>>
143 144
}

145 146 147 148 149 150 151
const REG_PLACEHOLDER_LEN : usize = 3;
lazy_static! {
    pub static ref REG_PLACEHOLDER : String = {
        let blank_spaces = [' ' as u8; REG_PLACEHOLDER_LEN];
        
        format!("%{}", str::from_utf8(&blank_spaces).unwrap())
    };
152 153 154 155
}

impl ASMCodeGen {
    pub fn new() -> ASMCodeGen {
156
        ASMCodeGen {
157
            cur: None
158 159 160 161 162 163 164 165 166 167 168
        }
    }
    
    fn cur(&self) -> &ASMCode {
        self.cur.as_ref().unwrap()
    }
    
    fn cur_mut(&mut self) -> &mut ASMCode {
        self.cur.as_mut().unwrap()
    }
    
169 170 171 172
    fn line(&self) -> usize {
        self.cur().code.len()
    }
    
173 174 175 176 177 178 179 180 181 182 183 184
    fn replace(s: &mut String, index: usize, replace: &str, replace_len: usize) {
        let vec = unsafe {s.as_mut_vec()};
        
        for i in 0..replace_len {
            if i < replace.len() {
                vec[index + i] = replace.as_bytes()[i] as u8;
            } else {
                vec[index + i] = ' ' as u8;
            }
        }
    }
    
185 186 187 188 189 190 191 192
    fn add_asm_block_label(&mut self, code: String, block_name: &'static str) {
        let l = self.line();
        self.cur_mut().code.push(ASM::symbolic(code));
        
        self.cur_mut().idx_to_blk.insert(l, block_name);
        self.cur_mut().blk_to_idx.insert(block_name, l);
    }
    
193 194 195 196
    fn add_asm_symbolic(&mut self, code: String){
        self.cur_mut().code.push(ASM::symbolic(code));
    }
    
197 198 199 200 201 202 203 204 205 206
    fn add_asm_call(&mut self, code: String) {
        self.cur_mut().code.push(ASM::call(code));
    }
    
    fn add_asm_ret(&mut self, code: String) {
        self.cur_mut().code.push(ASM::ret(code));
    }
    
    fn add_asm_branch(&mut self, code: String, target: &'static str) {
        let l = self.line();
207
        self.cur_mut().code.push(ASM::branch(code));
208 209 210 211 212 213 214 215 216
        
        self.cur_mut().branches.insert(l, target);
    }
    
    fn add_asm_branch2(&mut self, code: String, target: &'static str) {
        let l = self.line();
        self.cur_mut().code.push(ASM::branch(code));
        
        self.cur_mut().cond_branches.insert(l, target);
217 218 219 220 221 222
    }
    
    fn add_asm_inst(
        &mut self, 
        code: String, 
        defines: Vec<MuID>,
223
        mut define_locs: Vec<ASMLocation>, 
224
        uses: Vec<MuID>,
225
        mut use_locs: Vec<ASMLocation>) 
226
    {
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
        let line = self.line();
        
        trace!("asm: {}", code);
        trace!("     defines: {:?}, def_locs: {:?}", defines, define_locs);
        trace!("     uses: {:?}, use_locs: {:?}", uses, use_locs);
        let mc = self.cur_mut();
       
        // add locations of defined registers
        for i in 0..define_locs.len() {
            let id = defines[i];
            
            // update line in location
            let ref mut loc = define_locs[i];
            loc.line = line;
            
            if mc.reg_defines.contains_key(&id) {
                mc.reg_defines.get_mut(&id).unwrap().push(loc.clone());
            } else {
                mc.reg_defines.insert(id, vec![loc.clone()]);
            }
        }
       
        for i in 0..use_locs.len() {
            let id = uses[i];
            
            // update line in location
            let ref mut loc = use_locs[i];
            loc.line = line;
            
            if mc.reg_uses.contains_key(&id) {
257
                mc.reg_uses.get_mut(&id).unwrap().push(loc.clone());
258
            } else {
259
                mc.reg_uses.insert(id, vec![loc.clone()]);
260 261
            }
        }
262
       
263 264
        // put the instruction
        mc.code.push(ASM::inst(code, defines, uses));
265 266 267 268
    }
    
    fn define_reg(&mut self, reg: &P<Value>, loc: ASMLocation) {
        let id = reg.extract_ssa_id().unwrap();
269
        
270 271 272 273 274 275 276
        let code = self.cur_mut();
        if code.reg_defines.contains_key(&id) {
            let regs = code.reg_defines.get_mut(&id).unwrap();
            regs.push(loc);
        } else {
            code.reg_defines.insert(id, vec![loc]);
        } 
277 278 279 280 281 282
    }
    
    fn use_reg(&mut self, reg: &P<Value>, loc: ASMLocation) {
        let id = reg.extract_ssa_id().unwrap();
        
        let code = self.cur_mut();
283 284 285
        if code.reg_uses.contains_key(&id) {
            let reg_uses = code.reg_uses.get_mut(&id).unwrap();
            reg_uses.push(loc);
286
        } else {
287
            code.reg_uses.insert(id, vec![loc]);
288 289 290
        } 
    }
    
291 292 293 294 295 296 297 298
    fn prepare_op(&self, op: &P<Value>, loc: usize) -> (String, MuID, ASMLocation) {
        let str = self.asm_reg_op(op);
        let len = str.len();
        (str, op.extract_ssa_id().unwrap(), ASMLocation::new(loc, len)) 
    }
    
    fn prepare_machine_reg(&self, op: &P<Value>) -> MuID {
        op.extract_ssa_id().unwrap()
299
    }
300
    
301 302 303 304 305 306 307 308 309 310 311 312 313
    fn asm_reg_op(&self, op: &P<Value>) -> String {
        let id = op.extract_ssa_id().unwrap();
        if id < RESERVED_NODE_IDS_FOR_MACHINE {
            // machine reg
            format!("%{}", op.tag)
        } else {
            // virtual register, use place holder
            REG_PLACEHOLDER.clone()
        }
    }
    
    fn asm_block_label(&self, label: MuTag) -> String {
        format!("{}_{}", self.cur().name, label)
314
    }
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
    
    fn control_flow_analysis(&mut self) {
        // control flow analysis
        let n_insts = self.line();
        
        let code = self.cur_mut();
        code.preds = vec![vec![]; n_insts];
        code.succs = vec![vec![]; n_insts];
        
        for i in 0..n_insts {
            // determine predecessor - if cur is not block start, its predecessor is previous insts
            let is_block_start = code.idx_to_blk.get(&i);
            if is_block_start.is_none() {
                if i > 0 {
                    code.preds[i].push(i - 1);
                }
            } else {
                // if cur is a branch target, we already set its predecessor
                // if cur is a fall-through block, we set it in a sanity check pass
            }
            
            // determine successor
            let is_branch = code.branches.get(&i);
            if is_branch.is_some() {
                // branch to target
                let target = is_branch.unwrap();
                let target_n = code.blk_to_idx.get(target).unwrap();
                
                // cur inst's succ is target
                code.succs[i].push(*target_n);
                
                // target's pred is cur
                code.preds[*target_n].push(i);
            } else {
                let is_cond_branch = code.cond_branches.get(&i);
                if is_cond_branch.is_some() {
                    // branch to target
                    let target = is_cond_branch.unwrap();
                    let target_n = code.blk_to_idx.get(target).unwrap();
                    
                    // cur insts' succ is target and next inst
                    code.succs[i].push(*target_n);
                    if i < n_insts - 1 {
                        code.succs[i].push(i + 1);
                    }
                    
                    // target's pred is cur
                    code.preds[*target_n].push(i);
                } else {
                    // not branch nor cond branch, succ is next inst
                    if i < n_insts - 1 {
                        code.succs[i].push(i + 1);
                    }
                }
            } 
        }
        
        // a sanity check for fallthrough blocks
        for i in 0..n_insts {
            if i != 0 && code.preds[i].len() == 0 {
                code.preds[i].push(i - 1);
            }
        }        
    }
379 380 381
}

impl CodeGenerator for ASMCodeGen {
382
    fn start_code(&mut self, func_name: MuTag) {
383
        self.cur = Some(Box::new(ASMCode {
384 385
                name: func_name,
                code: vec![],
386
                reg_defines: HashMap::new(),
387 388 389 390 391 392 393 394 395 396
                reg_uses: HashMap::new(),
                
                preds: vec![],
                succs: vec![],
                
                idx_to_blk: HashMap::new(),
                blk_to_idx: HashMap::new(),
                cond_branches: HashMap::new(),
                branches: HashMap::new()
            }));
397
        
398
        self.add_asm_symbolic(format!(".globl {}", func_name));
399 400
    }
    
401 402 403
    fn finish_code(&mut self) -> Box<MachineCode> {
        self.control_flow_analysis();
        self.cur.take().unwrap()
404 405 406 407 408 409 410 411 412
    }
    
    fn print_cur_code(&self) {
        println!("");
        
        if self.cur.is_some() {
            let code = self.cur.as_ref().unwrap();
            
            println!("code for {}: ", code.name);
413 414 415 416
            let n_insts = code.code.len();
            for i in 0..n_insts {
                let ref line = code.code[i];
                println!("#{}\t{}", i, line.code);
417 418 419 420 421 422 423 424 425
            }
        } else {
            println!("no current code");
        }
        
        println!("");
    }
    
    fn start_block(&mut self, block_name: MuTag) {
426 427
        let label = format!("{}:", self.asm_block_label(block_name));        
        self.add_asm_block_label(label, block_name);
428 429
    }
    
430
    fn emit_cmp_r64_r64(&mut self, op1: &P<Value>, op2: &P<Value>) {
qinsoon's avatar
qinsoon committed
431
        trace!("emit: cmp {} {}", op1, op2);
432
        
433 434
        let (reg1, id1, loc1) = self.prepare_op(op1, 4 + 1);
        let (reg2, id2, loc2) = self.prepare_op(op2, 4 + 1 + reg1.len() + 1);
435 436 437
        
        let asm = format!("cmpq {} {}", reg1, reg2);
        
438 439 440 441 442 443 444
        self.add_asm_inst(
            asm,
            vec![],
            vec![],
            vec![id1, id2],
            vec![loc1, loc2]
        );
445 446
    }
    
qinsoon's avatar
qinsoon committed
447 448
    fn emit_cmp_r64_imm32(&mut self, op1: &P<Value>, op2: u32) {
        trace!("emit: cmp {} {}", op1, op2);
449
        
450
        let (reg1, id1, loc1) = self.prepare_op(op1, 4 + 1);
451 452 453
        
        let asm = format!("cmpq {} ${}", reg1, op2);
        
454 455 456 457 458 459 460
        self.add_asm_inst(
            asm,
            vec![],
            vec![],
            vec![id1],
            vec![loc1]
        )
461 462 463
    }
    
    fn emit_cmp_r64_mem64(&mut self, op1: &P<Value>, op2: &P<Value>) {
qinsoon's avatar
qinsoon committed
464
        trace!("emit: cmp {} {}", op1, op2);
465
        unimplemented!()
466 467
    }
    
qinsoon's avatar
qinsoon committed
468 469
    fn emit_mov_r64_imm32(&mut self, dest: &P<Value>, src: u32) {
        trace!("emit: mov {} -> {}", src, dest);
470
        
471
        let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1 + 1 + src.to_string().len() + 1);
472
        
473
        let asm = format!("movq ${} {}", src, reg1);
474
        
475 476 477
        self.add_asm_inst(
            asm,
            vec![id1],
478 479 480
            vec![loc1],
            vec![],
            vec![]
481
        )
482 483 484
    }
    
    fn emit_mov_r64_mem64(&mut self, dest: &P<Value>, src: &P<Value>) {
qinsoon's avatar
qinsoon committed
485
        trace!("emit: mov {} -> {}", src, dest);
486
        unimplemented!()
qinsoon's avatar
qinsoon committed
487 488 489 490
    }
    
    fn emit_mov_r64_r64(&mut self, dest: &P<Value>, src: &P<Value>) {
        trace!("emit: mov {} -> {}", src, dest);
491
        
492 493
        let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1);
        let (reg2, id2, loc2) = self.prepare_op(src, 4 + 1 + reg1.len() + 1);
494 495 496
        
        let asm = format!("movq {} {}", reg2, reg1);
        
497 498 499 500 501 502 503
        self.add_asm_inst(
            asm,
            vec![id1],
            vec![loc1],
            vec![id2],
            vec![loc2]
        )
qinsoon's avatar
qinsoon committed
504 505 506 507
    }
    
    fn emit_add_r64_r64(&mut self, dest: &P<Value>, src: &P<Value>) {
        trace!("emit: add {}, {} -> {}", dest, src, dest);
508
        
509 510
        let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1);
        let (reg2, id2, loc2) = self.prepare_op(src, 4 + 1 + reg1.len() + 1);
511 512 513
        
        let asm = format!("addq {} {}", reg2, reg1);
        
514 515 516 517 518 519 520
        self.add_asm_inst(
            asm,
            vec![id1],
            vec![loc1.clone()],
            vec![id1, id2],
            vec![loc1, loc2]
        )
qinsoon's avatar
qinsoon committed
521 522 523 524
    }
    
    fn emit_add_r64_mem64(&mut self, dest: &P<Value>, src: &P<Value>) {
        trace!("emit: add {}, {} -> {}", dest, src, dest);
525
        unimplemented!()
qinsoon's avatar
qinsoon committed
526 527 528 529
    }
    
    fn emit_add_r64_imm32(&mut self, dest: &P<Value>, src: u32) {
        trace!("emit: add {}, {} -> {}", dest, src, dest);
530
        
531
        let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1);
532 533 534
        
        let asm = format!("addq {} ${}", src, reg1);
        
535 536 537 538 539 540 541
        self.add_asm_inst(
            asm,
            vec![id1],
            vec![loc1.clone()],
            vec![id1],
            vec![loc1]
        )
qinsoon's avatar
qinsoon committed
542 543 544 545
    }
    
    fn emit_sub_r64_r64(&mut self, dest: &P<Value>, src: &P<Value>) {
        trace!("emit: sub {}, {} -> {}", dest, src, dest);
546
        
547 548
        let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1);
        let (reg2, id2, loc2) = self.prepare_op(src, 4 + 1 + reg1.len() + 1);
549 550 551
        
        let asm = format!("subq {} {}", reg2, reg1);
        
552 553 554 555 556 557 558
        self.add_asm_inst(
            asm,
            vec![id1],
            vec![loc1.clone()],
            vec![id1, id2],
            vec![loc1, loc2]
        )        
qinsoon's avatar
qinsoon committed
559 560 561 562
    }
    
    fn emit_sub_r64_mem64(&mut self, dest: &P<Value>, src: &P<Value>) {
        trace!("emit: sub {}, {} -> {}", dest, src, dest);
563
        unimplemented!()
qinsoon's avatar
qinsoon committed
564 565 566 567
    }
    
    fn emit_sub_r64_imm32(&mut self, dest: &P<Value>, src: u32) {
        trace!("emit: sub {}, {} -> {}", dest, src, dest);
568
        
569
        let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1);
570 571 572
        
        let asm = format!("subq {} ${}", src, reg1);
        
573 574 575 576 577 578 579
        self.add_asm_inst(
            asm,
            vec![id1],
            vec![loc1.clone()],
            vec![id1],
            vec![loc1]
        )        
qinsoon's avatar
qinsoon committed
580 581
    }
    
582
    fn emit_mul_r64(&mut self, src: &P<Value>) {
583
        trace!("emit: mul rax, {} -> (rdx, rax)", src);
584
        
585 586 587
        let (reg, id, loc) = self.prepare_op(src, 3 + 1);
        let rax = self.prepare_machine_reg(&x86_64::RAX);
        let rdx = self.prepare_machine_reg(&x86_64::RDX);
588 589 590
        
        let asm = format!("mul {}", reg);
        
591 592 593 594 595 596 597
        self.add_asm_inst(
            asm,
            vec![rax, rdx],
            vec![],
            vec![id, rax],
            vec![loc]
        )
598 599 600 601
    }
    
    fn emit_mul_mem64(&mut self, src: &P<Value>) {
        trace!("emit: mul rax, {} -> rax", src);
602
        unimplemented!()
603 604
    }
    
qinsoon's avatar
qinsoon committed
605 606
    fn emit_jmp(&mut self, dest: &Destination) {
        trace!("emit: jmp {}", dest.target);
607 608 609
        
        // symbolic label, we dont need to patch it
        let asm = format!("jmp {}", self.asm_block_label(dest.target));
610
        self.add_asm_branch(asm, dest.target)
qinsoon's avatar
qinsoon committed
611 612 613 614
    }
    
    fn emit_je(&mut self, dest: &Destination) {
        trace!("emit: je {}", dest.target);
615 616
        
        let asm = format!("je {}", self.asm_block_label(dest.target));
617
        self.add_asm_branch2(asm, dest.target);        
qinsoon's avatar
qinsoon committed
618 619 620 621
    }
    
    fn emit_jne(&mut self, dest: &Destination) {
        trace!("emit: jne {}", dest.target);
622 623
        
        let asm = format!("jne {}", self.asm_block_label(dest.target));
624
        self.add_asm_branch2(asm, dest.target);
qinsoon's avatar
qinsoon committed
625 626 627 628
    }
    
    fn emit_ja(&mut self, dest: &Destination) {
        trace!("emit: ja {}", dest.target);
629 630
        
        let asm = format!("ja {}", self.asm_block_label(dest.target));
631
        self.add_asm_branch2(asm, dest.target);
qinsoon's avatar
qinsoon committed
632 633 634 635
    }
    
    fn emit_jae(&mut self, dest: &Destination) {
        trace!("emit: jae {}", dest.target);
636 637
        
        let asm = format!("jae {}", self.asm_block_label(dest.target));
638
        self.add_asm_branch2(asm, dest.target);        
qinsoon's avatar
qinsoon committed
639 640 641 642
    }
    
    fn emit_jb(&mut self, dest: &Destination) {
        trace!("emit: jb {}", dest.target);
643 644
        
        let asm = format!("jb {}", self.asm_block_label(dest.target));
645
        self.add_asm_branch2(asm, dest.target);
qinsoon's avatar
qinsoon committed
646 647 648 649
    }
    
    fn emit_jbe(&mut self, dest: &Destination) {
        trace!("emit: jbe {}", dest.target);
650 651
        
        let asm = format!("jbe {}", self.asm_block_label(dest.target));
652
        self.add_asm_branch2(asm, dest.target);        
qinsoon's avatar
qinsoon committed
653 654
    }
    
655 656
    fn emit_jg(&mut self, dest: &Destination) {
        trace!("emit: jg {}", dest.target);
657 658
        
        let asm = format!("jg {}", self.asm_block_label(dest.target));
659
        self.add_asm_branch2(asm, dest.target);        
660 661 662 663
    }
    
    fn emit_jge(&mut self, dest: &Destination) {
        trace!("emit: jge {}", dest.target);
664 665
        
        let asm = format!("jge {}", self.asm_block_label(dest.target));
666
        self.add_asm_branch2(asm, dest.target);        
667 668 669 670
    }
    
    fn emit_jl(&mut self, dest: &Destination) {
        trace!("emit: jl {}", dest.target);
671 672
        
        let asm = format!("jl {}", self.asm_block_label(dest.target));
673
        self.add_asm_branch2(asm, dest.target);        
674 675 676 677
    }
    
    fn emit_jle(&mut self, dest: &Destination) {
        trace!("emit: jle {}", dest.target);
678 679
        
        let asm = format!("jle {}", self.asm_block_label(dest.target));
680
        self.add_asm_branch2(asm, dest.target);        
681 682
    }    
    
683 684
    fn emit_call_near_rel32(&mut self, func: MuTag) {
        trace!("emit: call {}", func);
685 686
        
        let asm = format!("call {}", func);
687
        self.add_asm_call(asm);
688 689
        
        // FIXME: call interferes with machine registers
690 691 692 693
    }
    
    fn emit_call_near_r64(&mut self, func: &P<Value>) {
        trace!("emit: call {}", func);
694
        unimplemented!()
695 696 697
    }
    
    fn emit_call_near_mem64(&mut self, func: &P<Value>) {
qinsoon's avatar
qinsoon committed
698
        trace!("emit: call {}", func);
699
        unimplemented!()
qinsoon's avatar
qinsoon committed
700 701 702 703
    }
    
    fn emit_ret(&mut self) {
        trace!("emit: ret");
704 705
        
        let asm = format!("ret");
706
        self.add_asm_ret(asm);
707
    }
708
    
709
    fn emit_push_r64(&mut self, src: &P<Value>) {
710
        trace!("emit: push {}", src);
711
        
712
        let (reg, id, loc) = self.prepare_op(src, 5 + 1);
713
        let rsp = self.prepare_machine_reg(&x86_64::RSP);
714 715 716
        
        let asm = format!("pushq {}", reg);
        
717 718
        self.add_asm_inst(
            asm,
719
            vec![rsp],
720
            vec![],
721 722
            vec![rsp],
            vec![]
723
        )
724 725
    }
    
726
    fn emit_pop_r64(&mut self, dest: &P<Value>) {
727
        trace!("emit: pop {}", dest);
728
        
729
        let (reg, id, loc) = self.prepare_op(dest, 4 + 1);
730
        let rsp = self.prepare_machine_reg(&x86_64::RSP);
731 732 733
        
        let asm = format!("popq {}", reg);
        
734 735
        self.add_asm_inst(
            asm,
736
            vec![id, rsp],
737
            vec![loc.clone()],
738
            vec![id, rsp],
739 740
            vec![loc]
        )        
741
    }    
742
}