core: Add helper for outputting const values
This commit is contained in:
parent
4d0d4e0eae
commit
35c346881d
|
@ -1,8 +1,9 @@
|
||||||
|
use inkwell::AddressSpace;
|
||||||
use inkwell::attributes::{Attribute, AttributeLoc};
|
use inkwell::attributes::{Attribute, AttributeLoc};
|
||||||
use inkwell::values::{BasicValueEnum, CallSiteValue, FloatValue, IntValue, PointerValue};
|
use inkwell::values::{BasicValueEnum, CallSiteValue, FloatValue, IntValue, PointerValue};
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
|
|
||||||
use crate::codegen::{CodeGenContext, CodeGenerator};
|
use crate::codegen::{CodeGenContext, CodeGenerator, llvm_intrinsics};
|
||||||
|
|
||||||
/// Invokes `dbl_nan` in the demo library.
|
/// Invokes `dbl_nan` in the demo library.
|
||||||
pub fn call_dbl_nan<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>) -> FloatValue<'ctx> {
|
pub fn call_dbl_nan<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>) -> FloatValue<'ctx> {
|
||||||
|
@ -113,6 +114,13 @@ pub fn call_output_bool<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function for invoking `output_bool` with a compile-time constant value.
|
||||||
|
pub fn call_output_bool_const(ctx: &mut CodeGenContext<'_, '_>, value: bool) {
|
||||||
|
let llvm_i1 = ctx.ctx.bool_type();
|
||||||
|
|
||||||
|
call_output_bool(ctx, llvm_i1.const_int(value as u64, false));
|
||||||
|
}
|
||||||
|
|
||||||
/// Invokes `output_int32` in the demo library.
|
/// Invokes `output_int32` in the demo library.
|
||||||
pub fn call_output_int32<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValue<'ctx>) {
|
pub fn call_output_int32<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValue<'ctx>) {
|
||||||
const FN_NAME: &str = "output_int32";
|
const FN_NAME: &str = "output_int32";
|
||||||
|
@ -146,6 +154,13 @@ pub fn call_output_int32<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntVal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function for invoking `output_int32` with a compile-time constant value.
|
||||||
|
pub fn call_output_int32_const(ctx: &mut CodeGenContext<'_, '_>, value: i32) {
|
||||||
|
let llvm_i32 = ctx.ctx.i32_type();
|
||||||
|
|
||||||
|
call_output_int32(ctx, llvm_i32.const_int(value as u64, true));
|
||||||
|
}
|
||||||
|
|
||||||
/// Invokes `output_int64` in the demo library.
|
/// Invokes `output_int64` in the demo library.
|
||||||
pub fn call_output_int64<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValue<'ctx>) {
|
pub fn call_output_int64<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValue<'ctx>) {
|
||||||
const FN_NAME: &str = "output_int64";
|
const FN_NAME: &str = "output_int64";
|
||||||
|
@ -179,6 +194,13 @@ pub fn call_output_int64<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntVal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function for invoking `output_int64` with a compile-time constant value.
|
||||||
|
pub fn call_output_int64_const(ctx: &mut CodeGenContext<'_, '_>, value: i64) {
|
||||||
|
let llvm_i64 = ctx.ctx.i64_type();
|
||||||
|
|
||||||
|
call_output_int64(ctx, llvm_i64.const_int(value as u64, true));
|
||||||
|
}
|
||||||
|
|
||||||
/// Invokes `output_uint32` in the demo library.
|
/// Invokes `output_uint32` in the demo library.
|
||||||
pub fn call_output_uint32<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValue<'ctx>) {
|
pub fn call_output_uint32<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValue<'ctx>) {
|
||||||
const FN_NAME: &str = "output_uint32";
|
const FN_NAME: &str = "output_uint32";
|
||||||
|
@ -212,6 +234,13 @@ pub fn call_output_uint32<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntVa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function for invoking `output_uint32` with a compile-time constant value.
|
||||||
|
pub fn call_output_uint32_const(ctx: &mut CodeGenContext<'_, '_>, value: u32) {
|
||||||
|
let llvm_i32 = ctx.ctx.i32_type();
|
||||||
|
|
||||||
|
call_output_uint32(ctx, llvm_i32.const_int(value as u64, false));
|
||||||
|
}
|
||||||
|
|
||||||
/// Invokes `output_uint64` in the demo library.
|
/// Invokes `output_uint64` in the demo library.
|
||||||
pub fn call_output_uint64<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValue<'ctx>) {
|
pub fn call_output_uint64<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValue<'ctx>) {
|
||||||
const FN_NAME: &str = "output_uint64";
|
const FN_NAME: &str = "output_uint64";
|
||||||
|
@ -245,6 +274,13 @@ pub fn call_output_uint64<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntVa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function for invoking `output_uint64` with a compile-time constant value.
|
||||||
|
pub fn call_output_uint64_const(ctx: &mut CodeGenContext<'_, '_>, value: u64) {
|
||||||
|
let llvm_i64 = ctx.ctx.i64_type();
|
||||||
|
|
||||||
|
call_output_uint64(ctx, llvm_i64.const_int(value, false));
|
||||||
|
}
|
||||||
|
|
||||||
/// Invokes `output_float64` in the demo library.
|
/// Invokes `output_float64` in the demo library.
|
||||||
pub fn call_output_float64<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: FloatValue<'ctx>) {
|
pub fn call_output_float64<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: FloatValue<'ctx>) {
|
||||||
const FN_NAME: &str = "output_float64";
|
const FN_NAME: &str = "output_float64";
|
||||||
|
@ -278,9 +314,16 @@ pub fn call_output_float64<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: Floa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function for invoking `output_float64` with a compile-time constant value.
|
||||||
|
pub fn call_output_float64_const(ctx: &mut CodeGenContext<'_, '_>, value: f64) {
|
||||||
|
let llvm_f64 = ctx.ctx.f64_type();
|
||||||
|
|
||||||
|
call_output_float64(ctx, llvm_f64.const_float(value));
|
||||||
|
}
|
||||||
|
|
||||||
/// Invokes `output_str` in the demo library.
|
/// Invokes `output_str` in the demo library.
|
||||||
pub fn call_output_str<'ctx>(
|
pub fn call_output_str<'ctx, G: CodeGenerator + ?Sized>(
|
||||||
generator: &mut dyn CodeGenerator,
|
generator: &mut G,
|
||||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
value: PointerValue<'ctx>,
|
value: PointerValue<'ctx>,
|
||||||
) {
|
) {
|
||||||
|
@ -288,12 +331,13 @@ pub fn call_output_str<'ctx>(
|
||||||
|
|
||||||
if ctx.registry.codegen_options.use_demo_lib {
|
if ctx.registry.codegen_options.use_demo_lib {
|
||||||
let llvm_void = ctx.ctx.void_type();
|
let llvm_void = ctx.ctx.void_type();
|
||||||
let llvm_str = ctx.get_llvm_type(generator, ctx.primitives.str).into_pointer_type();
|
let llvm_str = ctx.get_llvm_type(generator, ctx.primitives.str).into_struct_type();
|
||||||
|
let llvm_pstr = llvm_str.ptr_type(AddressSpace::default());
|
||||||
|
|
||||||
debug_assert_eq!(value.get_type(), llvm_str);
|
debug_assert_eq!(value.get_type(), llvm_pstr);
|
||||||
|
|
||||||
let extern_fn = ctx.module.get_function(FN_NAME).unwrap_or_else(|| {
|
let extern_fn = ctx.module.get_function(FN_NAME).unwrap_or_else(|| {
|
||||||
let fn_type = llvm_void.fn_type(&[llvm_str.into()], false);
|
let fn_type = llvm_void.fn_type(&[llvm_pstr.into()], false);
|
||||||
let func = ctx.module.add_function(FN_NAME, fn_type, None);
|
let func = ctx.module.add_function(FN_NAME, fn_type, None);
|
||||||
for attr in [
|
for attr in [
|
||||||
"nofree",
|
"nofree",
|
||||||
|
@ -313,4 +357,22 @@ pub fn call_output_str<'ctx>(
|
||||||
.build_call(extern_fn, &[value.into()], "")
|
.build_call(extern_fn, &[value.into()], "")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function for invoking `output_str` with a compile-time constant value.
|
||||||
|
pub fn call_output_str_const<G: CodeGenerator + ?Sized>(
|
||||||
|
generator: &mut G,
|
||||||
|
ctx: &mut CodeGenContext<'_, '_>,
|
||||||
|
value: &str,
|
||||||
|
) {
|
||||||
|
let str = ctx.gen_string(generator, value).into_struct_value();
|
||||||
|
|
||||||
|
// The alloca is necessary to form a pointer to the string struct, but since we only need it for
|
||||||
|
// the call to `call_output_str`, do a stack save-and-restore to ensure that this can be called
|
||||||
|
// anywhere
|
||||||
|
let stack_addr = llvm_intrinsics::call_stacksave(ctx, None);
|
||||||
|
let pstr = ctx.builder.build_alloca(str.get_type(), "").unwrap();
|
||||||
|
ctx.builder.build_store(pstr, str).unwrap();
|
||||||
|
call_output_str(generator, ctx, pstr);
|
||||||
|
llvm_intrinsics::call_stackrestore(ctx, stack_addr);
|
||||||
}
|
}
|
Loading…
Reference in New Issue