From 91130da483f062300b87409d8ffb549557eb0877 Mon Sep 17 00:00:00 2001 From: David Mak Date: Thu, 23 Jan 2025 14:46:30 +0800 Subject: [PATCH] [core] codegen: Add StructProxy{Type,Value} --- nac3core/src/codegen/types/structure.rs | 40 +++++++++++++++++++++++- nac3core/src/codegen/values/mod.rs | 1 + nac3core/src/codegen/values/structure.rs | 21 +++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 nac3core/src/codegen/values/structure.rs diff --git a/nac3core/src/codegen/types/structure.rs b/nac3core/src/codegen/types/structure.rs index 87781d11..958d0dcb 100644 --- a/nac3core/src/codegen/types/structure.rs +++ b/nac3core/src/codegen/types/structure.rs @@ -2,13 +2,51 @@ use std::marker::PhantomData; use inkwell::{ context::AsContextRef, - types::{BasicTypeEnum, IntType, StructType}, + types::{BasicTypeEnum, IntType, PointerType, StructType}, values::{BasicValue, BasicValueEnum, IntValue, PointerValue, StructValue}, + AddressSpace, }; use itertools::Itertools; +use super::ProxyType; use crate::codegen::CodeGenContext; +/// A LLVM type that is used to represent a corresponding structure-like type in NAC3. +pub trait StructProxyType<'ctx>: ProxyType<'ctx, Base = PointerType<'ctx>> { + /// The concrete type of [`StructFields`]. + type StructFields: StructFields<'ctx>; + + fn has_same_struct_repr( + llvm_ty: StructType<'ctx>, + llvm_usize: IntType<'ctx>, + ) -> Result<(), String> { + Self::has_same_pointer_repr(llvm_ty.ptr_type(AddressSpace::default()), llvm_usize) + } + + fn has_same_pointer_repr( + llvm_ty: PointerType<'ctx>, + llvm_usize: IntType<'ctx>, + ) -> Result<(), String> { + Self::has_same_repr(llvm_ty, llvm_usize) + } + + /// Returns the fields present in this [`StructProxyType`]. + #[must_use] + fn get_fields(&self) -> Self::StructFields; + + /// Returns the [`StructType`]. + #[must_use] + fn get_struct_type(&self) -> StructType<'ctx> { + self.as_base_type().get_element_type().into_struct_type() + } + + /// Returns the [`PointerType`] representing this type. + #[must_use] + fn get_pointer_type(&self) -> PointerType<'ctx> { + self.as_base_type() + } +} + /// Trait indicating that the structure is a field-wise representation of an LLVM structure. /// /// # Usage diff --git a/nac3core/src/codegen/values/mod.rs b/nac3core/src/codegen/values/mod.rs index dae10f31..9a246356 100644 --- a/nac3core/src/codegen/values/mod.rs +++ b/nac3core/src/codegen/values/mod.rs @@ -10,6 +10,7 @@ mod array; mod list; pub mod ndarray; mod range; +pub mod structure; mod tuple; pub mod utils; diff --git a/nac3core/src/codegen/values/structure.rs b/nac3core/src/codegen/values/structure.rs new file mode 100644 index 00000000..d93d490a --- /dev/null +++ b/nac3core/src/codegen/values/structure.rs @@ -0,0 +1,21 @@ +use inkwell::values::{BasicValueEnum, PointerValue, StructValue}; + +use super::ProxyValue; +use crate::codegen::{types::structure::StructProxyType, CodeGenContext}; + +pub trait StructProxyValue<'ctx>: + ProxyValue<'ctx, Base = PointerValue<'ctx>, Type: StructProxyType<'ctx, Value = Self>> +{ + #[must_use] + fn get_struct_value(&self, ctx: &CodeGenContext<'ctx, '_>) -> StructValue<'ctx> { + ctx.builder + .build_load(self.get_pointer_value(ctx), "") + .map(BasicValueEnum::into_struct_value) + .unwrap() + } + + #[must_use] + fn get_pointer_value(&self, _: &CodeGenContext<'ctx, '_>) -> PointerValue<'ctx> { + self.as_base_value() + } +}