<commit_before>use std::collections::HashMap;
use std::collections::HashSet;
use std::slice;

use capstone::{Engine, Error};

use ast::*;
use ast::Stmt::*;
use ast::visit::*;

use baseline::expr::*;
use baseline::fct::{CatchType, Comment, CommentFormat, GcPoint, JitFct};
use baseline::info;
use baseline::map::CodeData;
use cpu::{Mem, Reg, REG_PARAMS, REG_RESULT};
use ctxt::{Context, Fct, FctId, FctSrc, VarId};
use driver::cmd::AsmSyntax;
use masm::*;

use os;
use os::signal::Trap;
use semck::always_returns;
use ty::MachineMode;

pub fn generate<'ast>(ctxt: &Context<'ast>, id: FctId) -> *const u8 {
    let fct = ctxt.fcts[id].borrow();
    let src = fct.src();
    let mut src = src.lock().unwrap();

    generate_fct(ctxt, &fct, &mut src)
}

pub fn generate_fct<'ast>(ctxt: &Context<'ast>,
                          fct: &Fct<'ast>,
                          src: &mut FctSrc<'ast>)
                          -> *const u8 {
    if let Some(ref jit) = src.jit_fct {
        return jit.fct_ptr();
    }

    let ast = fct.ast;

    let jit_fct = CodeGen {
            ctxt: ctxt,
            fct: &fct,
            ast: ast,
            masm: MacroAssembler::new(),
            scopes: Scopes::new(),
            src: src,

            lbl_break: None,
            lbl_continue: None,
            lbl_finally: None,
        }
        .generate();

    if should_emit_asm(ctxt, &*fct) {
        dump_asm(ctxt,
                 &*fct,
                 &jit_fct,
                 Some(&src),
                 ctxt.args.flag_asm_syntax.unwrap_or(AsmSyntax::Att));
    }

    let fct_ptr = jit_fct.fct_ptr();
    src.jit_fct = Some(jit_fct);

    fct_ptr
}

#[cfg(target_arch = "x86_64")]
fn get_engine() -> Result<Engine, Error> {
    use capstone::{Arch, MODE_64};

    Engine::new(Arch::X86, MODE_64)
}

#[cfg(target_arch = "aarch64")]
fn get_engine() -> Result<Engine, Error> {
    use capstone::{Arch, MODE_ARM};

    Engine::new(Arch::Arm64, MODE_ARM)
}

pub fn dump_asm<'ast>(ctxt: &Context<'ast>,
                      fct: &Fct<'ast>,
                      jit_fct: &JitFct,
                      fct_src: Option<&FctSrc<'ast>>,
                      asm_syntax: AsmSyntax) {
    use capstone::*;

    let buf: &[u8] = unsafe { slice::from_raw_parts(jit_fct.fct_ptr(), jit_fct.fct_len()) };

    let asm_syntax = match asm_syntax {
        AsmSyntax::Intel => 1,
        AsmSyntax::Att => 2,
    };

    let engine = get_engine().expect("cannot create capstone engine");
    if let Err(_) = engine.set_option(Opt::Syntax, asm_syntax) {
        panic!("capstone: syntax couldn't be set");
    }

    let start_addr = jit_fct.fct_ptr() as u64;
    let instrs = engine.disasm(buf, start_addr, jit_fct.fct_len())
        .expect("could not disassemble code");

    let name = fct.full_name(ctxt);

    println!("fn {} {:#x}", &name, start_addr);

    if let Some(fct_src) = fct_src {
        for var in &fct_src.vars {
            let name = ctxt.interner.str(var.name);
            let op = if var.offset < 0 { "-" } else { "" };
            println!("  var `{}`: offset {} ({}0x{:02x}) type {}",
                     name,
                     var.offset,
                     op,
                     var.offset.abs(),
                     var.ty.name(ctxt));
        }

        if fct_src.vars.len() > 0 {
            println!();
        }
    }

    for instr in instrs {
        let addr = (instr.addr - start_addr) as i32;

        if let Some(comments) = jit_fct.get_comment(addr) {
            for comment in comments {
                if comment.is_newline() {
                    println!();
                    continue;
                }

                let cfmt = CommentFormat {
                    comment: comment,
                    ctxt: ctxt,
                    fct_src: fct_src,
                };

                println!("\t\t  ; {}", cfmt);
            }
        }

        println!("  {:#06x}: {}\t\t{}",
                 instr.addr,
                 instr.mnemonic,
                 instr.op_str);
    }

    println!("");<commit_msg>emit gc points in assembly code<commit_after>use std::collections::HashMap;
use std::collections::HashSet;
use std::slice;

use capstone::{Engine, Error};

use ast::*;
use ast::Stmt::*;
use ast::visit::*;

use baseline::expr::*;
use baseline::fct::{CatchType, Comment, CommentFormat, GcPoint, JitFct};
use baseline::info;
use baseline::map::CodeData;
use cpu::{Mem, Reg, REG_PARAMS, REG_RESULT};
use ctxt::{Context, Fct, FctId, FctSrc, VarId};
use driver::cmd::AsmSyntax;
use masm::*;

use os;
use os::signal::Trap;
use semck::always_returns;
use ty::MachineMode;

pub fn generate<'ast>(ctxt: &Context<'ast>, id: FctId) -> *const u8 {
    let fct = ctxt.fcts[id].borrow();
    let src = fct.src();
    let mut src = src.lock().unwrap();

    generate_fct(ctxt, &fct, &mut src)
}

pub fn generate_fct<'ast>(ctxt: &Context<'ast>,
                          fct: &Fct<'ast>,
                          src: &mut FctSrc<'ast>)
                          -> *const u8 {
    if let Some(ref jit) = src.jit_fct {
        return jit.fct_ptr();
    }

    let ast = fct.ast;

    let jit_fct = CodeGen {
            ctxt: ctxt,
            fct: &fct,
            ast: ast,
            masm: MacroAssembler::new(),
            scopes: Scopes::new(),
            src: src,

            lbl_break: None,
            lbl_continue: None,
            lbl_finally: None,
        }
        .generate();

    if should_emit_asm(ctxt, &*fct) {
        dump_asm(ctxt,
                 &*fct,
                 &jit_fct,
                 Some(&src),
                 ctxt.args.flag_asm_syntax.unwrap_or(AsmSyntax::Att));
    }

    let fct_ptr = jit_fct.fct_ptr();
    src.jit_fct = Some(jit_fct);

    fct_ptr
}

#[cfg(target_arch = "x86_64")]
fn get_engine() -> Result<Engine, Error> {
    use capstone::{Arch, MODE_64};

    Engine::new(Arch::X86, MODE_64)
}

#[cfg(target_arch = "aarch64")]
fn get_engine() -> Result<Engine, Error> {
    use capstone::{Arch, MODE_ARM};

    Engine::new(Arch::Arm64, MODE_ARM)
}

pub fn dump_asm<'ast>(ctxt: &Context<'ast>,
                      fct: &Fct<'ast>,
                      jit_fct: &JitFct,
                      fct_src: Option<&FctSrc<'ast>>,
                      asm_syntax: AsmSyntax) {
    use capstone::*;

    let buf: &[u8] = unsafe { slice::from_raw_parts(jit_fct.fct_ptr(), jit_fct.fct_len()) };

    let asm_syntax = match asm_syntax {
        AsmSyntax::Intel => 1,
        AsmSyntax::Att => 2,
    };

    let engine = get_engine().expect("cannot create capstone engine");
    if let Err(_) = engine.set_option(Opt::Syntax, asm_syntax) {
        panic!("capstone: syntax couldn't be set");
    }

    let start_addr = jit_fct.fct_ptr() as u64;
    let instrs = engine.disasm(buf, start_addr, jit_fct.fct_len())
        .expect("could not disassemble code");

    let name = fct.full_name(ctxt);

    println!("fn {} {:#x}", &name, start_addr);

    if let Some(fct_src) = fct_src {
        for var in &fct_src.vars {
            let name = ctxt.interner.str(var.name);
            let op = if var.offset < 0 { "-" } else { "" };
            println!("  var `{}`: offset {} ({}0x{:02x}) type {}",
                     name,
                     var.offset,
                     op,
                     var.offset.abs(),
                     var.ty.name(ctxt));
        }

        if fct_src.vars.len() > 0 {
            println!();
        }
    }

    for instr in instrs {
        let addr = (instr.addr - start_addr) as i32;

        if let Some(gc_point) = jit_fct.gcpoint_for_offset(addr) {
            print!("\t\t  ; gc points = (");
            let mut first = true;

            for &offset in &gc_point.offsets {
                if !first {
                    print!(", ");
                }

                print!("{}", offset);
                first = false;
            }

            println!(")");
        }

        if let Some(comments) = jit_fct.get_comment(addr) {
            for comment in comments {
                if comment.is_newline() {
                    println!();
                    continue;
                }

                let cfmt = CommentFormat {
                    comment: comment,
                    ctxt: ctxt,
                    fct_src: fct_src,
                };

                println!("\t\t  ; {}", cfmt);
            }
        }

        println!("  {:#06x}: {}\t\t{}",
                 instr.addr,
                 instr.mnemonic,
                 instr.op_str);
    }

    println!("");
{'fraction_non_alphanumeric': 0.14798363530099357, 'fraction_numerical': 0.0070134424313267095, 'mean_word_length': 1.7274466050366593, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1646061', 'n_tokens_mistral': 2978, 'n_tokens_neox': 2894, 'n_words': 601}