<commit_before>use std::collections::HashMap;
use std::ffi::CString;
use libc::*;
use llvm::*;
use llvm::core::*;
use llvm::prelude::*;
use bytecode::*;
use ast::{Type, Operator, ptr_type};
use super::valueref::ValueRef;
use super::context::Context;

pub unsafe fn const_int(ctx: &Context, v: isize) -> LLVMValueRef
{
    LLVMConstInt(ctx.native_int_type(), v as c_ulonglong, 1)
}

pub unsafe fn const_uint(ctx: &Context, v: usize) -> LLVMValueRef
{
    LLVMConstInt(ctx.native_int_type(), v as c_ulonglong, 0)
}

pub unsafe fn const_bool(ctx: &Context, v: bool) -> LLVMValueRef
{
    LLVMConstInt(LLVMInt1TypeInContext(ctx.context), if v {1} else {0}, 0)
}

unsafe fn const_float(ctx: &Context, v: f64) -> LLVMValueRef
{
    LLVMConstReal(LLVMDoubleTypeInContext(ctx.context), v)
}

unsafe fn const_char(ctx: &Context, c: char) -> LLVMValueRef
{
    LLVMConstInt(LLVMInt32TypeInContext(ctx.context), c as c_ulonglong, 0)
}

unsafe fn get_variable(ctx: &Context, name: &str) -> ValueRef
{
    ctx.get_variable(name).expect("Unknown variable").value.clone()
}

pub unsafe fn get_operand(ctx: &Context, operand: &Operand) -> ValueRef
{
    match *operand
    {
        Operand::Func(ref func) => {
            let fi = ctx.get_function(func).expect("Unknown function");
            ValueRef::new(
                fi.function,
                fi.sig.typ.clone()
            )
        }

        Operand::Var(ref v) => {
            get_variable(ctx, &v.name)
        }

        Operand::AddressOf(ref v) => {
            ctx.get_variable(&v.name)
                .expect("Unknown variable")
                .value.address_of()
        }

        Operand::Int(v) => ValueRef::new(const_int(ctx, v), Type::Int),
        Operand::UInt(v) => ValueRef::new(const_uint(ctx, v), Type::UInt),
        Operand::Float(v) => ValueRef::new(const_float(ctx, v), Type::Float),
        Operand::Char(v) => ValueRef::new(const_char(ctx, v), Type::Char),
        Operand::String(ref _s) => panic!("NYI"),
        Operand::Bool(v) => ValueRef::new(const_bool(ctx, v), Type::Bool),
    }
}

pub unsafe fn copy(ctx: &Context, dst: LLVMValueRef, src: LLVMValueRef, typ: LLVMTypeRef)
{
    let func = ctx.get_function("memcpy").expect("memcpy not found");
    let void_ptr_type = LLVMPointerType(LLVMVoidTypeInContext(ctx.context), 0);
    let mut args = vec![
        LLVMBuildBitCast(ctx.builder, dst, void_ptr_type, cstr!("dst_cast")),
        LLVMBuildBitCast(ctx.builder, src, void_ptr_type, cstr!("src_cast")),
        const_uint(ctx, ctx.target_machine.size_of_type(typ))
    ];
    LLVMBuildCall(ctx.builder, func.function, args.as_mut_ptr(), args.len() as c_uint, cstr!("ac"));
}

unsafe fn get_function_arg(ctx: &Context, operand: &Operand) -> LLVMValueRef
{
    match *operand
    {
        Operand::Var(ref v) => {
            let src = get_variable(ctx, &v.name);
            let inner_type = src.typ.get_pointer_element_type().expect("Expecting pointer type here");
            if inner_type.pass_by_value() {
                src.load(ctx)
            } else {
                let llvm_type = ctx.resolve_type(inner_type);
                let dst = stack_alloc(ctx, llvm_type, "argcopy");
                copy(ctx, dst, src.value, llvm_type);
                dst
            }
        },

        Operand::AddressOf(ref v) => {
            let src = get_variable(ctx, &v.name);
            src.value
        }

        _ => get_operand(ctx, operand).load(ctx)
    }
}
<commit_msg>Make value arguments work in llvm backend<commit_after>use std::collections::HashMap;
use std::ffi::CString;
use libc::*;
use llvm::*;
use llvm::core::*;
use llvm::prelude::*;
use bytecode::*;
use ast::{Type, Operator, ptr_type};
use super::valueref::ValueRef;
use super::context::Context;

pub unsafe fn const_int(ctx: &Context, v: isize) -> LLVMValueRef
{
    LLVMConstInt(ctx.native_int_type(), v as c_ulonglong, 1)
}

pub unsafe fn const_uint(ctx: &Context, v: usize) -> LLVMValueRef
{
    LLVMConstInt(ctx.native_int_type(), v as c_ulonglong, 0)
}

pub unsafe fn const_bool(ctx: &Context, v: bool) -> LLVMValueRef
{
    LLVMConstInt(LLVMInt1TypeInContext(ctx.context), if v {1} else {0}, 0)
}

unsafe fn const_float(ctx: &Context, v: f64) -> LLVMValueRef
{
    LLVMConstReal(LLVMDoubleTypeInContext(ctx.context), v)
}

unsafe fn const_char(ctx: &Context, c: char) -> LLVMValueRef
{
    LLVMConstInt(LLVMInt32TypeInContext(ctx.context), c as c_ulonglong, 0)
}

unsafe fn get_variable(ctx: &Context, name: &str) -> ValueRef
{
    ctx.get_variable(name).expect("Unknown variable").value.clone()
}

pub unsafe fn get_operand(ctx: &Context, operand: &Operand) -> ValueRef
{
    match *operand
    {
        Operand::Func(ref func) => {
            let fi = ctx.get_function(func).expect("Unknown function");
            ValueRef::new(
                fi.function,
                fi.sig.typ.clone()
            )
        }

        Operand::Var(ref v) => {
            get_variable(ctx, &v.name)
        }

        Operand::AddressOf(ref v) => {
            ctx.get_variable(&v.name)
                .expect("Unknown variable")
                .value.address_of()
        }

        Operand::Int(v) => ValueRef::new(const_int(ctx, v), Type::Int),
        Operand::UInt(v) => ValueRef::new(const_uint(ctx, v), Type::UInt),
        Operand::Float(v) => ValueRef::new(const_float(ctx, v), Type::Float),
        Operand::Char(v) => ValueRef::new(const_char(ctx, v), Type::Char),
        Operand::String(ref _s) => panic!("NYI"),
        Operand::Bool(v) => ValueRef::new(const_bool(ctx, v), Type::Bool),
    }
}

pub unsafe fn copy(ctx: &Context, dst: LLVMValueRef, src: LLVMValueRef, typ: LLVMTypeRef)
{
    let func = ctx.get_function("memcpy").expect("memcpy not found");
    let void_ptr_type = LLVMPointerType(LLVMVoidTypeInContext(ctx.context), 0);
    let mut args = vec![
        LLVMBuildBitCast(ctx.builder, dst, void_ptr_type, cstr!("dst_cast")),
        LLVMBuildBitCast(ctx.builder, src, void_ptr_type, cstr!("src_cast")),
        const_uint(ctx, ctx.target_machine.size_of_type(typ))
    ];
    LLVMBuildCall(ctx.builder, func.function, args.as_mut_ptr(), args.len() as c_uint, cstr!("ac"));
}

unsafe fn get_function_arg(ctx: &Context, operand: &Operand) -> LLVMValueRef
{
    match *operand
    {
        Operand::Var(ref v) => {
            let src = get_variable(ctx, &v.name);
            if !src.typ.is_pointer() {
                return src.value
            }

            let inner_type = src.typ.get_pointer_element_type().expect("Expecting pointer type here");
            if inner_type.pass_by_value() {
                src.load(ctx)
            } else {
                let llvm_type = ctx.resolve_type(inner_type);
                let dst = stack_alloc(ctx, llvm_type, "argcopy");
                copy(ctx, dst, src.value, llvm_type);
                dst
            }
        },

        Operand::AddressOf(ref v) => {
            let src = get_variable(ctx, &v.name);
            src.value
        }

        _ => get_operand(ctx, operand).load(ctx)
    }
}

{'fraction_non_alphanumeric': 0.1494399546292358, 'fraction_numerical': 0.0034028073160357296, 'mean_word_length': 2.873695771554091, 'pattern_counts': {'":': 0, '<': 3, '<?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': '5502638', 'n_tokens_mistral': 2435, 'n_tokens_neox': 2413, 'n_words': 476}