-
Hi there. Coming from LLVM and its GEP instruction, i have a hard time understanding how to use How would one access a struct field? Should I use the Also If I have a pointer as a Thanks for feedback PS: is there an IRC chan or Discord server for this project? |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 3 replies
-
There are no struct and arrays types in MIR. It is not so high level as LLVM IR. Basically mem in MIR is for accessing a MIR-type value in memory. MIR type is signed/unsigned integer of different sizes and fp types. The address of the value is calculated as So you need to calculate field address by yourself (to access some external C struct value in MIR I use base reg as struct address and disp got by C offsetof macro).
Zero value of base or index means they are not used in address calculation. So basically in this case you can just put the address into disp and use zero value for base and index reg .
If the pointer value in MIR_op_t (let say prtr_op) is a register, you can address value (let assume 32-bit signed integer) in memory by the pointer as
No, sorry. It is mostly one person project and it is not my major project. So I can not spend much time on it. |
Beta Was this translation helpful? Give feedback.
-
I think I got most of it but const std = @import("std");
const Test = struct {
a: u64,
b: *u64,
c: bool,
};
const Native = fn (t: *Test) u64;
const NativeFn = *const Native;
test "figuring out mir" {
const debug_file = std.c.fopen("/Users/giann/tmp/out.txt", "w").?;
defer _ = std.c.fclose(debug_file);
const ctx = MIR_init();
const module = MIR_new_module(ctx, "test");
// fn (t: Test) u64
const func = MIR_new_func_arr(
ctx,
"test",
1,
&[_]MIR_type_t{MIR_T_U64},
1,
&[_]MIR_var_t{
.{
.type = MIR_T_P,
.name = "arg",
// What is this for?
.size = undefined,
},
},
);
const arg = MIR_reg(ctx, "arg", func.u.func);
const index = MIR_new_func_reg(ctx, func.u.func, MIR_T_I64, "idx");
// put 0 in index
MIR_append_insn(
ctx,
func,
MIR_new_insn_arr(
ctx,
MIR_MOV,
2,
&[_]MIR_op_t{
MIR_new_reg_op(ctx, index),
MIR_new_int_op(ctx, 0),
},
),
);
// Get field a
const a_field = MIR_new_mem_op(
ctx,
MIR_T_U64,
// @offsetOf: Returns the byte offset of a field relative to its containing struct.
@offsetOf(Test, "a"),
arg,
index,
1,
);
// Return it
MIR_append_insn(
ctx,
func,
@call(
.auto,
MIR_new_ret_insn,
.{ ctx, 1, a_field },
),
);
MIR_finish_func(ctx);
MIR_finish_module(ctx);
MIR_load_module(ctx, module);
// MIR_link(ctx, MIR_set_gen_interface, null);
MIR_gen_init(ctx, 1);
MIR_gen_set_debug_file(ctx, 0, debug_file);
const compiled = MIR_gen(ctx, 0, func);
var b: u64 = 43;
var t = Test{
.a = 42,
.b = &b,
.c = true,
};
// Calling compiled function
// compiled(&t)
const a_ptr = @call(
.auto,
@ptrCast(
NativeFn,
@alignCast(
@alignOf(Native),
compiled.?,
),
),
.{&t},
);
std.debug.print("Got {}\n", .{ a_ptr });
MIR_gen_finish(ctx);
MIR_finish(ctx);
} |
Beta Was this translation helpful? Give feedback.
-
@vnmakarov the generated MIR seems ok though:
|
Beta Was this translation helpful? Give feedback.
-
Using the text version of it gives me the same crash so it's not a bad usage of the API. I'm pretty stuck on why this doesn't work: MIR_scan_string(
ctx,
\\
\\ test_m: module
\\ export test
\\ test: func u64, p:arg
\\ local i64:idx
\\ mov idx, 0
\\ ret u64:(arg, idx)
\\ endfunc
\\ endmodule
\\
,
); |
Beta Was this translation helpful? Give feedback.
-
I've tried the following on x86_64-linux:
by I'll will look at this problem. |
Beta Was this translation helpful? Give feedback.
-
It seems you missed call MIR_link that is where MIR simplification is done besides linking loaded modules. You should call MIR_link even for one module. The code on C should look like:
Besides debug info the execution of this program returns :
|
Beta Was this translation helpful? Give feedback.
It seems you missed call MIR_link that is where MIR simplification is done besides linking loaded modules. You should call MIR_link even for one module. The code on C should look like: