artiq: Improve IR value naming and add documentation
This commit is contained in:
parent
8373a6cb0f
commit
65d6104d00
@ -28,9 +28,17 @@ use std::{
|
|||||||
|
|
||||||
pub struct ArtiqCodeGenerator<'a> {
|
pub struct ArtiqCodeGenerator<'a> {
|
||||||
name: String,
|
name: String,
|
||||||
|
|
||||||
|
/// The size of a `size_t` variable in bits.
|
||||||
size_t: u32,
|
size_t: u32,
|
||||||
|
|
||||||
|
/// Monotonic counter for naming `start`/`stop` variables used by `with parallel` blocks.
|
||||||
name_counter: u32,
|
name_counter: u32,
|
||||||
|
|
||||||
|
/// Variable for tracking the start of a `with parallel` block.
|
||||||
start: Option<Expr<Option<Type>>>,
|
start: Option<Expr<Option<Type>>>,
|
||||||
|
|
||||||
|
/// Variable for tracking the end of a `with parallel` block.
|
||||||
end: Option<Expr<Option<Type>>>,
|
end: Option<Expr<Option<Type>>>,
|
||||||
timeline: &'a (dyn TimeFns + Sync),
|
timeline: &'a (dyn TimeFns + Sync),
|
||||||
}
|
}
|
||||||
@ -102,6 +110,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
|
|||||||
if let StmtKind::With { items, body, .. } = &stmt.node {
|
if let StmtKind::With { items, body, .. } = &stmt.node {
|
||||||
if items.len() == 1 && items[0].optional_vars.is_none() {
|
if items.len() == 1 && items[0].optional_vars.is_none() {
|
||||||
let item = &items[0];
|
let item = &items[0];
|
||||||
|
|
||||||
// Behavior of parallel and sequential:
|
// Behavior of parallel and sequential:
|
||||||
// Each function call (indirectly, can be inside a sequential block) within a parallel
|
// Each function call (indirectly, can be inside a sequential block) within a parallel
|
||||||
// block will update the end variable to the maximum now_mu in the block.
|
// block will update the end variable to the maximum now_mu in the block.
|
||||||
@ -119,11 +128,15 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
|
|||||||
if id == &"parallel".into() {
|
if id == &"parallel".into() {
|
||||||
let old_start = self.start.take();
|
let old_start = self.start.take();
|
||||||
let old_end = self.end.take();
|
let old_end = self.end.take();
|
||||||
|
|
||||||
let now = if let Some(old_start) = &old_start {
|
let now = if let Some(old_start) = &old_start {
|
||||||
self.gen_expr(ctx, old_start)?.unwrap().to_basic_value_enum(ctx, self, old_start.custom.unwrap())?
|
self.gen_expr(ctx, old_start)?
|
||||||
|
.unwrap()
|
||||||
|
.to_basic_value_enum(ctx, self, old_start.custom.unwrap())?
|
||||||
} else {
|
} else {
|
||||||
self.timeline.emit_now_mu(ctx)
|
self.timeline.emit_now_mu(ctx)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Emulate variable allocation, as we need to use the CodeGenContext
|
// Emulate variable allocation, as we need to use the CodeGenContext
|
||||||
// HashMap to store our variable due to lifetime limitation
|
// HashMap to store our variable due to lifetime limitation
|
||||||
// Note: we should be able to store variables directly if generic
|
// Note: we should be able to store variables directly if generic
|
||||||
@ -157,8 +170,11 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
|
|||||||
ctx.builder.build_store(end, now);
|
ctx.builder.build_store(end, now);
|
||||||
self.end = Some(end_expr);
|
self.end = Some(end_expr);
|
||||||
self.name_counter += 1;
|
self.name_counter += 1;
|
||||||
|
|
||||||
gen_block(self, ctx, body.iter())?;
|
gen_block(self, ctx, body.iter())?;
|
||||||
|
|
||||||
let current = ctx.builder.get_insert_block().unwrap();
|
let current = ctx.builder.get_insert_block().unwrap();
|
||||||
|
|
||||||
// if the current block is terminated, move before the terminator
|
// if the current block is terminated, move before the terminator
|
||||||
// we want to set the timeline before reaching the terminator
|
// we want to set the timeline before reaching the terminator
|
||||||
// TODO: This may be unsound if there are multiple exit paths in the
|
// TODO: This may be unsound if there are multiple exit paths in the
|
||||||
@ -172,6 +188,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
|
|||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
// set duration
|
// set duration
|
||||||
let end_expr = self.end.take().unwrap();
|
let end_expr = self.end.take().unwrap();
|
||||||
let end_val = self
|
let end_val = self
|
||||||
@ -183,6 +200,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
|
|||||||
if old_start.is_none() {
|
if old_start.is_none() {
|
||||||
self.timeline.emit_at_mu(ctx, end_val);
|
self.timeline.emit_at_mu(ctx, end_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// inside a parallel block, should update the outer max now_mu
|
// inside a parallel block, should update the outer max now_mu
|
||||||
if let Some(old_end) = &old_end {
|
if let Some(old_end) = &old_end {
|
||||||
let outer_end_val = self
|
let outer_end_val = self
|
||||||
@ -207,20 +225,25 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
|
|||||||
let outer_end = self.gen_store_target(ctx, old_end, Some("outer_end.addr"))?;
|
let outer_end = self.gen_store_target(ctx, old_end, Some("outer_end.addr"))?;
|
||||||
ctx.builder.build_store(outer_end, max);
|
ctx.builder.build_store(outer_end, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.start = old_start;
|
self.start = old_start;
|
||||||
self.end = old_end;
|
self.end = old_end;
|
||||||
|
|
||||||
if reset_position {
|
if reset_position {
|
||||||
ctx.builder.position_at_end(current);
|
ctx.builder.position_at_end(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else if id == &"sequential".into() {
|
} else if id == &"sequential".into() {
|
||||||
let start = self.start.take();
|
let start = self.start.take();
|
||||||
gen_block(self, ctx, body.iter())?;
|
gen_block(self, ctx, body.iter())?;
|
||||||
self.start = start;
|
self.start = start;
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// not parallel/sequential
|
// not parallel/sequential
|
||||||
gen_with(self, ctx, stmt)
|
gen_with(self, ctx, stmt)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,9 +1,16 @@
|
|||||||
use inkwell::{values::BasicValueEnum, AddressSpace, AtomicOrdering};
|
use inkwell::{values::BasicValueEnum, AddressSpace, AtomicOrdering};
|
||||||
use nac3core::codegen::CodeGenContext;
|
use nac3core::codegen::CodeGenContext;
|
||||||
|
|
||||||
|
/// Functions for manipulating the timeline.
|
||||||
pub trait TimeFns {
|
pub trait TimeFns {
|
||||||
|
|
||||||
|
/// Emits LLVM IR for `now_mu`.
|
||||||
fn emit_now_mu<'ctx, 'a>(&self, ctx: &mut CodeGenContext<'ctx, 'a>) -> BasicValueEnum<'ctx>;
|
fn emit_now_mu<'ctx, 'a>(&self, ctx: &mut CodeGenContext<'ctx, 'a>) -> BasicValueEnum<'ctx>;
|
||||||
|
|
||||||
|
/// Emits LLVM IR for `at_mu`.
|
||||||
fn emit_at_mu<'ctx, 'a>(&self, ctx: &mut CodeGenContext<'ctx, 'a>, t: BasicValueEnum<'ctx>);
|
fn emit_at_mu<'ctx, 'a>(&self, ctx: &mut CodeGenContext<'ctx, 'a>, t: BasicValueEnum<'ctx>);
|
||||||
|
|
||||||
|
/// Emits LLVM IR for `delay_mu`.
|
||||||
fn emit_delay_mu<'ctx, 'a>(&self, ctx: &mut CodeGenContext<'ctx, 'a>, dt: BasicValueEnum<'ctx>);
|
fn emit_delay_mu<'ctx, 'a>(&self, ctx: &mut CodeGenContext<'ctx, 'a>, dt: BasicValueEnum<'ctx>);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,23 +27,25 @@ impl TimeFns for NowPinningTimeFns64 {
|
|||||||
.get_global("now")
|
.get_global("now")
|
||||||
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
|
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
|
||||||
let now_hiptr =
|
let now_hiptr =
|
||||||
ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now_hiptr");
|
ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now.hi.addr");
|
||||||
|
|
||||||
if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr {
|
if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr {
|
||||||
let now_loptr = unsafe {
|
let now_loptr = unsafe {
|
||||||
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now_gep")
|
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now.lo.addr")
|
||||||
};
|
};
|
||||||
|
|
||||||
if let (BasicValueEnum::IntValue(now_hi), BasicValueEnum::IntValue(now_lo)) = (
|
if let (BasicValueEnum::IntValue(now_hi), BasicValueEnum::IntValue(now_lo)) = (
|
||||||
ctx.builder.build_load(now_hiptr, "now_hi"),
|
ctx.builder.build_load(now_hiptr, "now.hi"),
|
||||||
ctx.builder.build_load(now_loptr, "now_lo"),
|
ctx.builder.build_load(now_loptr, "now.lo"),
|
||||||
) {
|
) {
|
||||||
let zext_hi = ctx.builder.build_int_z_extend(now_hi, i64_type, "now_zext_hi");
|
let zext_hi = ctx.builder.build_int_z_extend(now_hi, i64_type, "");
|
||||||
let shifted_hi = ctx.builder.build_left_shift(
|
let shifted_hi = ctx.builder.build_left_shift(
|
||||||
zext_hi,
|
zext_hi,
|
||||||
i64_type.const_int(32, false),
|
i64_type.const_int(32, false),
|
||||||
"now_shifted_zext_hi",
|
"",
|
||||||
);
|
);
|
||||||
let zext_lo = ctx.builder.build_int_z_extend(now_lo, i64_type, "now_zext_lo");
|
let zext_lo = ctx.builder.build_int_z_extend(now_lo, i64_type, "");
|
||||||
ctx.builder.build_or(shifted_hi, zext_lo, "now_or").into()
|
ctx.builder.build_or(shifted_hi, zext_lo, "now_mu").into()
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
@ -48,14 +57,15 @@ impl TimeFns for NowPinningTimeFns64 {
|
|||||||
fn emit_at_mu<'ctx, 'a>(&self, ctx: &mut CodeGenContext<'ctx, 'a>, t: BasicValueEnum<'ctx>) {
|
fn emit_at_mu<'ctx, 'a>(&self, ctx: &mut CodeGenContext<'ctx, 'a>, t: BasicValueEnum<'ctx>) {
|
||||||
let i32_type = ctx.ctx.i32_type();
|
let i32_type = ctx.ctx.i32_type();
|
||||||
let i64_type = ctx.ctx.i64_type();
|
let i64_type = ctx.ctx.i64_type();
|
||||||
|
|
||||||
let i64_32 = i64_type.const_int(32, false);
|
let i64_32 = i64_type.const_int(32, false);
|
||||||
if let BasicValueEnum::IntValue(time) = t {
|
if let BasicValueEnum::IntValue(time) = t {
|
||||||
let time_hi = ctx.builder.build_int_truncate(
|
let time_hi = ctx.builder.build_int_truncate(
|
||||||
ctx.builder.build_right_shift(time, i64_32, false, "now_lshr"),
|
ctx.builder.build_right_shift(time, i64_32, false, "time.hi"),
|
||||||
i32_type,
|
i32_type,
|
||||||
"now_trunc",
|
"",
|
||||||
);
|
);
|
||||||
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc");
|
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "time.lo");
|
||||||
let now = ctx
|
let now = ctx
|
||||||
.module
|
.module
|
||||||
.get_global("now")
|
.get_global("now")
|
||||||
@ -63,11 +73,12 @@ impl TimeFns for NowPinningTimeFns64 {
|
|||||||
let now_hiptr = ctx.builder.build_bitcast(
|
let now_hiptr = ctx.builder.build_bitcast(
|
||||||
now,
|
now,
|
||||||
i32_type.ptr_type(AddressSpace::default()),
|
i32_type.ptr_type(AddressSpace::default()),
|
||||||
"now_bitcast",
|
"now.hi.addr",
|
||||||
);
|
);
|
||||||
|
|
||||||
if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr {
|
if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr {
|
||||||
let now_loptr = unsafe {
|
let now_loptr = unsafe {
|
||||||
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now_gep")
|
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now.lo.addr")
|
||||||
};
|
};
|
||||||
ctx.builder
|
ctx.builder
|
||||||
.build_store(now_hiptr, time_hi)
|
.build_store(now_hiptr, time_hi)
|
||||||
@ -97,41 +108,43 @@ impl TimeFns for NowPinningTimeFns64 {
|
|||||||
.get_global("now")
|
.get_global("now")
|
||||||
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
|
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
|
||||||
let now_hiptr =
|
let now_hiptr =
|
||||||
ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now_hiptr");
|
ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now.hi.addr");
|
||||||
|
|
||||||
if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr {
|
if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr {
|
||||||
let now_loptr = unsafe {
|
let now_loptr = unsafe {
|
||||||
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now_loptr")
|
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now.lo.addr")
|
||||||
};
|
};
|
||||||
|
|
||||||
if let (
|
if let (
|
||||||
BasicValueEnum::IntValue(now_hi),
|
BasicValueEnum::IntValue(now_hi),
|
||||||
BasicValueEnum::IntValue(now_lo),
|
BasicValueEnum::IntValue(now_lo),
|
||||||
BasicValueEnum::IntValue(dt),
|
BasicValueEnum::IntValue(dt),
|
||||||
) = (
|
) = (
|
||||||
ctx.builder.build_load(now_hiptr, "now_hi"),
|
ctx.builder.build_load(now_hiptr, "now.hi"),
|
||||||
ctx.builder.build_load(now_loptr, "now_lo"),
|
ctx.builder.build_load(now_loptr, "now.lo"),
|
||||||
dt,
|
dt,
|
||||||
) {
|
) {
|
||||||
let zext_hi = ctx.builder.build_int_z_extend(now_hi, i64_type, "now_zext_hi");
|
let zext_hi = ctx.builder.build_int_z_extend(now_hi, i64_type, "");
|
||||||
let shifted_hi = ctx.builder.build_left_shift(
|
let shifted_hi = ctx.builder.build_left_shift(
|
||||||
zext_hi,
|
zext_hi,
|
||||||
i64_type.const_int(32, false),
|
i64_type.const_int(32, false),
|
||||||
"now_shifted_zext_hi",
|
"",
|
||||||
);
|
);
|
||||||
let zext_lo = ctx.builder.build_int_z_extend(now_lo, i64_type, "now_zext_lo");
|
let zext_lo = ctx.builder.build_int_z_extend(now_lo, i64_type, "");
|
||||||
let now_val = ctx.builder.build_or(shifted_hi, zext_lo, "now_or");
|
let now_val = ctx.builder.build_or(shifted_hi, zext_lo, "now");
|
||||||
|
|
||||||
let time = ctx.builder.build_int_add(now_val, dt, "now_add");
|
let time = ctx.builder.build_int_add(now_val, dt, "time");
|
||||||
let time_hi = ctx.builder.build_int_truncate(
|
let time_hi = ctx.builder.build_int_truncate(
|
||||||
ctx.builder.build_right_shift(
|
ctx.builder.build_right_shift(
|
||||||
time,
|
time,
|
||||||
i64_type.const_int(32, false),
|
i64_type.const_int(32, false),
|
||||||
false,
|
false,
|
||||||
"now_lshr",
|
"",
|
||||||
),
|
),
|
||||||
i32_type,
|
i32_type,
|
||||||
"now_trunc",
|
"time.hi",
|
||||||
);
|
);
|
||||||
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc");
|
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "time.lo");
|
||||||
|
|
||||||
ctx.builder
|
ctx.builder
|
||||||
.build_store(now_hiptr, time_hi)
|
.build_store(now_hiptr, time_hi)
|
||||||
@ -162,11 +175,12 @@ impl TimeFns for NowPinningTimeFns {
|
|||||||
.get_global("now")
|
.get_global("now")
|
||||||
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
|
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
|
||||||
let now_raw = ctx.builder.build_load(now.as_pointer_value(), "now");
|
let now_raw = ctx.builder.build_load(now.as_pointer_value(), "now");
|
||||||
|
|
||||||
if let BasicValueEnum::IntValue(now_raw) = now_raw {
|
if let BasicValueEnum::IntValue(now_raw) = now_raw {
|
||||||
let i64_32 = i64_type.const_int(32, false);
|
let i64_32 = i64_type.const_int(32, false);
|
||||||
let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now_shl");
|
let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now.lo");
|
||||||
let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now_lshr");
|
let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now.hi");
|
||||||
ctx.builder.build_or(now_lo, now_hi, "now_or").into()
|
ctx.builder.build_or(now_lo, now_hi, "now_mu").into()
|
||||||
} else {
|
} else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
@ -176,11 +190,12 @@ impl TimeFns for NowPinningTimeFns {
|
|||||||
let i32_type = ctx.ctx.i32_type();
|
let i32_type = ctx.ctx.i32_type();
|
||||||
let i64_type = ctx.ctx.i64_type();
|
let i64_type = ctx.ctx.i64_type();
|
||||||
let i64_32 = i64_type.const_int(32, false);
|
let i64_32 = i64_type.const_int(32, false);
|
||||||
|
|
||||||
if let BasicValueEnum::IntValue(time) = t {
|
if let BasicValueEnum::IntValue(time) = t {
|
||||||
let time_hi = ctx.builder.build_int_truncate(
|
let time_hi = ctx.builder.build_int_truncate(
|
||||||
ctx.builder.build_right_shift(time, i64_32, false, "now_lshr"),
|
ctx.builder.build_right_shift(time, i64_32, false, ""),
|
||||||
i32_type,
|
i32_type,
|
||||||
"now_trunc",
|
"time.hi",
|
||||||
);
|
);
|
||||||
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc");
|
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc");
|
||||||
let now = ctx
|
let now = ctx
|
||||||
@ -190,11 +205,12 @@ impl TimeFns for NowPinningTimeFns {
|
|||||||
let now_hiptr = ctx.builder.build_bitcast(
|
let now_hiptr = ctx.builder.build_bitcast(
|
||||||
now,
|
now,
|
||||||
i32_type.ptr_type(AddressSpace::default()),
|
i32_type.ptr_type(AddressSpace::default()),
|
||||||
"now_bitcast",
|
"now.hi.addr",
|
||||||
);
|
);
|
||||||
|
|
||||||
if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr {
|
if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr {
|
||||||
let now_loptr = unsafe {
|
let now_loptr = unsafe {
|
||||||
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false)], "now_gep")
|
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false)], "now.lo.addr")
|
||||||
};
|
};
|
||||||
ctx.builder
|
ctx.builder
|
||||||
.build_store(now_hiptr, time_hi)
|
.build_store(now_hiptr, time_hi)
|
||||||
@ -224,26 +240,28 @@ impl TimeFns for NowPinningTimeFns {
|
|||||||
.module
|
.module
|
||||||
.get_global("now")
|
.get_global("now")
|
||||||
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
|
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
|
||||||
let now_raw = ctx.builder.build_load(now.as_pointer_value(), "now");
|
let now_raw = ctx.builder.build_load(now.as_pointer_value(), "");
|
||||||
|
|
||||||
if let (BasicValueEnum::IntValue(now_raw), BasicValueEnum::IntValue(dt)) = (now_raw, dt) {
|
if let (BasicValueEnum::IntValue(now_raw), BasicValueEnum::IntValue(dt)) = (now_raw, dt) {
|
||||||
let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now_shl");
|
let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now.lo");
|
||||||
let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now_lshr");
|
let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now.hi");
|
||||||
let now_val = ctx.builder.build_or(now_lo, now_hi, "now_or");
|
let now_val = ctx.builder.build_or(now_lo, now_hi, "now_val");
|
||||||
let time = ctx.builder.build_int_add(now_val, dt, "now_add");
|
let time = ctx.builder.build_int_add(now_val, dt, "time");
|
||||||
let time_hi = ctx.builder.build_int_truncate(
|
let time_hi = ctx.builder.build_int_truncate(
|
||||||
ctx.builder.build_right_shift(time, i64_32, false, "now_lshr"),
|
ctx.builder.build_right_shift(time, i64_32, false, "time.hi"),
|
||||||
i32_type,
|
i32_type,
|
||||||
"now_trunc",
|
"now_trunc",
|
||||||
);
|
);
|
||||||
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc");
|
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "time.lo");
|
||||||
let now_hiptr = ctx.builder.build_bitcast(
|
let now_hiptr = ctx.builder.build_bitcast(
|
||||||
now,
|
now,
|
||||||
i32_type.ptr_type(AddressSpace::default()),
|
i32_type.ptr_type(AddressSpace::default()),
|
||||||
"now_bitcast",
|
"now.hi.addr",
|
||||||
);
|
);
|
||||||
|
|
||||||
if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr {
|
if let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr {
|
||||||
let now_loptr = unsafe {
|
let now_loptr = unsafe {
|
||||||
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false)], "now_gep")
|
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false)], "now.lo.addr")
|
||||||
};
|
};
|
||||||
ctx.builder
|
ctx.builder
|
||||||
.build_store(now_hiptr, time_hi)
|
.build_store(now_hiptr, time_hi)
|
||||||
|
Loading…
Reference in New Issue
Block a user