inkwell icon indicating copy to clipboard operation
inkwell copied to clipboard

How to interact with stdin / stdout/ stderr

Open mrLSD opened this issue 5 years ago • 9 comments

Is there the best way to interact from LLVM with stdin / stdout /stderr?

How to implement it with inkwell?

For example, I build a standalone executable and want a print to stdout.

mrLSD avatar Sep 30 '20 22:09 mrLSD

I don't really understand what you're trying to do. If you want to use stdin/out rust provides methods to use them in std::io. Inkwell provides some methods to print llvm data to a string, and you can write that to stdout for example.

TheDan64 avatar Sep 30 '20 23:09 TheDan64

@TheDan64 For example, I have main function in LLVM:

use inkwell::context::Context;
use inkwell::execution_engine::JitFunction;
use inkwell::OptimizationLevel;
use std::path::Path;

type AppFunc = unsafe extern "C" fn(u64, u64, u64) -> u64;
type PutChar = unsafe extern "C" fn(u64) -> u64;

fn main() {
    let context = Context::create();
    let module = context.create_module("app");
    let builder = context.create_builder();

    let i64_type = context.i64_type();
    let fn_type = i64_type.fn_type(&[i64_type.into(), i64_type.into(), i64_type.into()], false);
    let function = module.add_function("main", fn_type, None);
    let basic_block = context.append_basic_block(function, "entry");

    builder.position_at_end(basic_block);

    let x = function.get_nth_param(0).unwrap().into_int_value();
    let y = function.get_nth_param(1).unwrap().into_int_value();
    let z = function.get_nth_param(2).unwrap().into_int_value();

    let sum = builder.build_int_add(x, y, "sum");
    let sum = builder.build_int_add(sum, z, "sum");

    builder.build_return(Some(&sum));
    module.verify().unwrap();

    let path = Path::new("module.bc");
    module.write_bitcode_to_path(&path);
}

So I declared main func: let function = module.add_function("main", fn_type, None);. And I want to print some result to strout. After execution I have got module.bc and run:

$ llc module.bs --filetype=asm
$ clang module.s -o app
$ ./app # run main function in app

mrLSD avatar Oct 01 '20 04:10 mrLSD

If you're trying to print the module to stdout you can do println!("{}", module.print_to_string()); or if you're trying to write to stdout in your generated program you'll have to call putchar or some similar external c/llvm function

TheDan64 avatar Oct 01 '20 04:10 TheDan64

I'm sorry porbabely for simple question, but how I can invoke external functions using ikwell?

Also do you know some more easy way build/compile from Rust standalong LLVM app?

mrLSD avatar Oct 01 '20 04:10 mrLSD

I believe if you create a FunctionValue with no body attached to it, it'll assume it's extern. As long as it has a matching signature to the LLVM builtin function you're trying to call, it should work. You might have to set the Linkage when you call add_function but the default might suffice.

TheDan64 avatar Oct 02 '20 02:10 TheDan64