cranelift-jit-demo icon indicating copy to clipboard operation
cranelift-jit-demo copied to clipboard

how to concatenate strings? Send or get string args

Open zhuxiujia opened this issue 3 years ago • 2 comments

Hello, I am a beginner wasm how do I concatenate strings? Send string?in this jit-demo

zhuxiujia avatar Feb 26 '21 02:02 zhuxiujia

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.

0xekez avatar May 30 '21 18:05 0xekez

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);
} 

lechatthecat avatar Feb 11 '22 15:02 lechatthecat