Git Product home page Git Product logo

Comments (2)

0xekez avatar 0xekez commented on August 17, 2024 1

This demo doesn't support that but adding the functionality wouldn't be too bad. In Cranelift you can make foreign calls to libc functions without too much trouble. See here for where I do that in my Cranelift Lisp.

Once you've got foreign calls working you could concatenate two strings the same way you normally would in C with calls to strcat and friends.

from cranelift-jit-demo.

lechatthecat avatar lechatthecat commented on August 17, 2024

You can define anonymous string like this:

fn create_anonymous_string(&mut self, string_content: &str) -> Value {
    self.data_ctx.define(string_content.as_bytes().to_vec().into_boxed_slice());

    let sym = self
        .module
        .declare_anonymous_data(true, false)
        .expect("problem declaring data object");

    let _result = self.module
         .define_data(sym, &self.data_ctx)
         .map_err(|e| e.to_string());
    
    let local_id = self
        .module
        .declare_data_in_func(sym, &mut self.builder.func);
    self.data_ctx.clear();
    
    let pointer = self.module.target_config().pointer_type();
    self.builder.ins().symbol_value(pointer, local_id)
}

Call this like:

let mut string_content_with_terminator = string_content.to_owned();
string_content_with_terminator.push('\0');
let symbol = self.create_anonymous_string(&string_content_with_terminator);

The string data created by the above function can be concatenated by using C functions as @ezekiiel said.

// anonymous string1
let value1 = self.translate_expr(expr1);
// anonymous string2
let value2 = self.translate_expr(expr2);

let len1 = self.get_str_len(value1);
let len2 = self.get_str_len(value2);
let len_both = self.builder.ins().iadd(len1, len2);
let one = self.builder.ins().iconst(self.int, 1);
let len_both = self.builder.ins().iadd(len_both, one);
let location = self.malloc(len_both);

self.strcpy(location, value1);
self.strcat(location, value2);

Each C function is called like this:

fn get_str_len(&mut self, val: Value) -> Value {
    let mut sig = self.module.make_signature();
    let word = self.module.target_config().pointer_type();
    sig.params.push(AbiParam::new(word));
    sig.returns.push(AbiParam::new(word));

    let callee = self.module
        .declare_function("strlen", cranelift_module::Linkage::Import, &sig)
        .map_err(|e| e.to_string()).unwrap();

    let local_callee = self.module
        .declare_func_in_func(callee, &mut self.builder.func);

    let arg = val;
    let args = vec![arg];

    let call = self.builder.ins().call(local_callee, &args);
    self.builder.inst_results(call)[0]
} 

fn malloc(&mut self, size: Value) -> Value {
    let mut sig = self.module.make_signature();
    let word = self.module.target_config().pointer_type();
    sig.params.push(AbiParam::new(word));
    sig.returns.push(AbiParam::new(word));

    let callee = self.module
        .declare_function("malloc", cranelift_module::Linkage::Import, &sig)
        .map_err(|e| e.to_string()).unwrap();

    let local_callee = self.module
        .declare_func_in_func(callee, &mut self.builder.func);

    let args = vec![size];

    let call = self.builder.ins().call(local_callee, &args);
    self.builder.inst_results(call)[0]
} 

fn strcpy(&mut self, message_buf: Value, message: Value) {
    let mut sig = self.module.make_signature();
    let word = self.module.target_config().pointer_type();
    sig.params.push(AbiParam::new(word));
    sig.params.push(AbiParam::new(word));

    let callee = self.module
        .declare_function("strcpy", cranelift_module::Linkage::Import, &sig)
        .map_err(|e| e.to_string()).unwrap();

    let local_callee = self.module
        .declare_func_in_func(callee, &mut self.builder.func);

    let args = vec![message_buf, message];

    let _call = self.builder.ins().call(local_callee, &args);
} 

fn strcat(&mut self, message_buf: Value, message: Value) {
    let mut sig = self.module.make_signature();
    let word = self.module.target_config().pointer_type();
    sig.params.push(AbiParam::new(word));
    sig.params.push(AbiParam::new(word));

    let callee = self.module
        .declare_function("strcat", cranelift_module::Linkage::Import, &sig)
        .map_err(|e| e.to_string()).unwrap();

    let local_callee = self.module
        .declare_func_in_func(callee, &mut self.builder.func);

    let args = vec![message_buf, message];

    let _call = self.builder.ins().call(local_callee, &args);
} 

from cranelift-jit-demo.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.