use inkwell::values::BasicValueEnum;
use crate::{checker::types::TypeId, ir, report::throw_llvm_error};
use super::Llvm;
impl<'ll> Llvm<'ll> {
pub fn llvm_compile_value(&mut self, ir_basic_value: &ir::IrBasicValue) -> BasicValueEnum<'ll> {
match &ir_basic_value.value {
ir::BasicValue::Int(value) => self.llvm_compile_int(ir_basic_value.get_type(), *value),
ir::BasicValue::Float(value) => self.llvm_compile_float(ir_basic_value.get_type(), *value),
ir::BasicValue::Bool(value) => self.ctx.bool_type().const_int(*value as u64, false).into(),
ir::BasicValue::String(value) => self.llvm_compile_string(value),
ir::BasicValue::Char(_) => throw_llvm_error("unsupported char value"),
ir::BasicValue::None => throw_llvm_error("unsupported none value"),
ir::BasicValue::Register(name) => self.llvm_compile_register(name),
}
}
fn llvm_compile_int(&mut self, type_id: TypeId, value: u64) -> BasicValueEnum<'ll> {
match type_id {
TypeId::I8 => self.ctx.i8_type().const_int(value, false).into(),
TypeId::U8 => self.ctx.i8_type().const_int(value, true).into(),
TypeId::I16 => self.ctx.i16_type().const_int(value, false).into(),
TypeId::U16 => self.ctx.i16_type().const_int(value, true).into(),
TypeId::I32 => self.ctx.i32_type().const_int(value, false).into(),
TypeId::U32 => self.ctx.i32_type().const_int(value, true).into(),
TypeId::I64 => self.ctx.i64_type().const_int(value, false).into(),
TypeId::U64 => self.ctx.i64_type().const_int(value, true).into(),
_ => throw_llvm_error("unsupported int type"),
}
}
fn llvm_compile_float(&mut self, type_id: TypeId, value: f64) -> BasicValueEnum<'ll> {
match type_id {
TypeId::F32 => self.ctx.f32_type().const_float(value).into(),
TypeId::F64 => self.ctx.f64_type().const_float(value).into(),
_ => throw_llvm_error("unsupported float type"),
}
}
pub fn llvm_compile_value_and_load(&mut self, value: &ir::IrBasicValue) -> BasicValueEnum<'ll> {
let basic_value = self.llvm_compile_value(value);
if !basic_value.is_pointer_value() {
return basic_value;
};
let ptr = basic_value.into_pointer_value();
let basic_type = self.compile_type_to_basic_type(value.type_id);
let dest = self.env.get_temp();
self.load(basic_type, ptr, dest.as_str())
}
fn llvm_compile_register(&mut self, name: &str) -> BasicValueEnum<'ll> {
if let Some(ptr) = self.env.get_ptr_value(name) {
return ptr.into();
}
if let Some(value) = self.env.get_value(name) {
return *value;
}
throw_llvm_error(format!("register not found '{}'", name));
}
}