forked from M-Labs/nac3
WIP 6
This commit is contained in:
parent
7742fbf9e0
commit
059b130aff
|
@ -2,7 +2,7 @@ use std::marker::PhantomData;
|
||||||
|
|
||||||
use inkwell::{
|
use inkwell::{
|
||||||
types::{BasicType, BasicTypeEnum, IntType},
|
types::{BasicType, BasicTypeEnum, IntType},
|
||||||
values::{BasicValueEnum, IntValue},
|
values::{BasicValueEnum, IntValue, PointerValue},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::codegen::optics::*;
|
use crate::codegen::optics::*;
|
||||||
|
@ -95,7 +95,7 @@ struct Producer<'ctx, G: CodeGenerator + ?Sized, ElementOptic> {
|
||||||
///
|
///
|
||||||
/// See also [`typecheck::type_inferencer::fold_numpy_function_call_shape_argument`] to
|
/// See also [`typecheck::type_inferencer::fold_numpy_function_call_shape_argument`] to
|
||||||
/// learn how `shape` gets from being a Python user expression to here.
|
/// learn how `shape` gets from being a Python user expression to here.
|
||||||
fn parse_input_shape_arg<'ctx, G>(
|
pub fn parse_input_shape_arg<'ctx, G>(
|
||||||
generator: &mut G,
|
generator: &mut G,
|
||||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
shape: BasicValueEnum<'ctx>,
|
shape: BasicValueEnum<'ctx>,
|
||||||
|
@ -258,14 +258,14 @@ where
|
||||||
Ok(ndarray_ptr)
|
Ok(ndarray_ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum NDArrayInitMode<'ctx, G: CodeGenerator + ?Sized> {
|
pub enum NDArrayInitMode<'ctx, G: CodeGenerator + ?Sized> {
|
||||||
NDim { ndim: IntValue<'ctx>, _phantom: PhantomData<&'ctx G> },
|
NDim { ndim: IntValue<'ctx> },
|
||||||
Shape { shape: Producer<'ctx, G, IntLens<'ctx>> },
|
Shape { shape: Producer<'ctx, G, IntLens<'ctx>> },
|
||||||
ShapeAndAllocaData { shape: Producer<'ctx, G, IntLens<'ctx>> },
|
ShapeAndAllocaData { shape: Producer<'ctx, G, IntLens<'ctx>> },
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO: DOCUMENT ME
|
/// TODO: DOCUMENT ME
|
||||||
fn alloca_ndarray_and_init<'ctx, G>(
|
pub fn alloca_ndarray_and_init<'ctx, G>(
|
||||||
generator: &mut G,
|
generator: &mut G,
|
||||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
elem_type: BasicTypeEnum<'ctx>,
|
elem_type: BasicTypeEnum<'ctx>,
|
||||||
|
@ -277,7 +277,7 @@ where
|
||||||
{
|
{
|
||||||
// It is implemented verbosely in order to make the initialization modes super clear in their intent.
|
// It is implemented verbosely in order to make the initialization modes super clear in their intent.
|
||||||
match init_mode {
|
match init_mode {
|
||||||
NDArrayInitMode::NDim { ndim: ndims, _phantom } => {
|
NDArrayInitMode::NDim { ndim } => {
|
||||||
let ndarray = alloca_ndarray(generator, ctx, elem_type, ndims, name)?;
|
let ndarray = alloca_ndarray(generator, ctx, elem_type, ndims, name)?;
|
||||||
Ok(ndarray)
|
Ok(ndarray)
|
||||||
}
|
}
|
||||||
|
@ -397,11 +397,11 @@ fn call_nac3_ndarray_nbytes<'ctx, G: CodeGenerator + ?Sized>(
|
||||||
.returning("nbytes", &IntLens(size_type))
|
.returning("nbytes", &IntLens(size_type))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_nac3_ndarray_fill_generic<'ctx, G: CodeGenerator + ?Sized>(
|
pub fn call_nac3_ndarray_fill_generic<'ctx, G: CodeGenerator + ?Sized>(
|
||||||
generator: &mut G,
|
generator: &mut G,
|
||||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
ndarray_ptr: &Address<'ctx, NpArrayLens<'ctx>>,
|
ndarray_ptr: &Address<'ctx, NpArrayLens<'ctx>>,
|
||||||
fill_value_ptr: &Address<'ctx, IntLens<'ctx>>,
|
fill_value_ptr: PointerValue<'ctx>,
|
||||||
) {
|
) {
|
||||||
let size_type = generator.get_size_type(ctx.ctx);
|
let size_type = generator.get_size_type(ctx.ctx);
|
||||||
|
|
||||||
|
@ -410,6 +410,6 @@ fn call_nac3_ndarray_fill_generic<'ctx, G: CodeGenerator + ?Sized>(
|
||||||
&get_sized_dependent_function_name(size_type, "__nac3_ndarray_fill_generic"),
|
&get_sized_dependent_function_name(size_type, "__nac3_ndarray_fill_generic"),
|
||||||
)
|
)
|
||||||
.arg("ndarray", &AddressLens(NpArrayLens { size_type }), ndarray_ptr)
|
.arg("ndarray", &AddressLens(NpArrayLens { size_type }), ndarray_ptr)
|
||||||
.arg("pvalue", &opaque_address_lens(ctx.ctx), fill_value_ptr)
|
.arg("pvalue", &OpaqueAddressLens, fill_value_ptr)
|
||||||
.returning_void();
|
.returning_void();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,13 +43,13 @@ impl<'ctx, 'a> FunctionBuilder<'ctx, 'a> {
|
||||||
|
|
||||||
// The name is for self-documentation
|
// The name is for self-documentation
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn arg<S: Optic<'ctx>>(mut self, _name: &'static str, optic: &S, arg: &S::Value) -> Self {
|
pub fn arg<S: MemoryOptic<'ctx>>(mut self, _name: &'static str, optic: &S, arg: &S::MemoryValue) -> Self {
|
||||||
self.arguments
|
self.arguments
|
||||||
.push((optic.get_llvm_type(self.ctx.ctx).into(), arg.get_llvm_value().into()));
|
.push((optic.get_llvm_type(self.ctx.ctx).into(), arg.get_llvm_value().into()));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn returning<S: Prism<'ctx>>(self, name: &'static str, return_prism: &S) -> S::Value {
|
pub fn returning<S: Prism<'ctx>>(self, name: &'static str, return_prism: &S) -> S::MemoryValue {
|
||||||
let (param_tys, param_vals): (Vec<_>, Vec<_>) = self.arguments.into_iter().unzip();
|
let (param_tys, param_vals): (Vec<_>, Vec<_>) = self.arguments.into_iter().unzip();
|
||||||
|
|
||||||
let function = self.ctx.module.get_function(self.fn_name).unwrap_or_else(|| {
|
let function = self.ctx.module.get_function(self.fn_name).unwrap_or_else(|| {
|
||||||
|
|
|
@ -26,7 +26,7 @@ use inkwell::{
|
||||||
use irrt::error_context::StrLens;
|
use irrt::error_context::StrLens;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use nac3parser::ast::{Location, Stmt, StrRef};
|
use nac3parser::ast::{Location, Stmt, StrRef};
|
||||||
use optics::Optic as _;
|
use optics::MemoryOptic as _;
|
||||||
use parking_lot::{Condvar, Mutex};
|
use parking_lot::{Condvar, Mutex};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::sync::{
|
use std::sync::{
|
||||||
|
@ -44,6 +44,7 @@ mod generator;
|
||||||
pub mod irrt;
|
pub mod irrt;
|
||||||
pub mod llvm_intrinsics;
|
pub mod llvm_intrinsics;
|
||||||
pub mod numpy;
|
pub mod numpy;
|
||||||
|
pub mod numpy_new;
|
||||||
pub mod optics;
|
pub mod optics;
|
||||||
pub mod stmt;
|
pub mod stmt;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
use inkwell::values::{BasicValueEnum, PointerValue};
|
||||||
|
use nac3parser::ast::StrRef;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
codegen::optics::build_opaque_alloca, symbol_resolver::ValueEnum, toplevel::DefinitionId, typecheck::typedef::{FunSignature, Type}
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
irrt::{
|
||||||
|
self,
|
||||||
|
numpy::{alloca_ndarray_and_init, parse_input_shape_arg, NDArrayInitMode, NpArrayLens},
|
||||||
|
},
|
||||||
|
optics::Address,
|
||||||
|
CodeGenContext, CodeGenerator,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// LLVM-typed implementation for generating the implementation for constructing an empty `NDArray`.
|
||||||
|
fn call_ndarray_empty_impl<'ctx, G>(
|
||||||
|
generator: &mut G,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
elem_ty: Type,
|
||||||
|
shape: BasicValueEnum<'ctx>,
|
||||||
|
shape_ty: Type,
|
||||||
|
name: &str,
|
||||||
|
) -> Result<Address<'ctx, NpArrayLens<'ctx>>, String>
|
||||||
|
where
|
||||||
|
G: CodeGenerator + ?Sized,
|
||||||
|
{
|
||||||
|
let elem_type = ctx.get_llvm_type(generator, elem_ty);
|
||||||
|
let shape = parse_input_shape_arg(generator, ctx, shape, shape_ty);
|
||||||
|
let ndarray_ptr = alloca_ndarray_and_init(
|
||||||
|
generator,
|
||||||
|
ctx,
|
||||||
|
elem_type,
|
||||||
|
NDArrayInitMode::ShapeAndAllocaData { shape },
|
||||||
|
name,
|
||||||
|
)?;
|
||||||
|
Ok(ndarray_ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call_ndarray_fill_impl<'ctx, G>(
|
||||||
|
generator: &mut G,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
elem_ty: Type,
|
||||||
|
shape: BasicValueEnum<'ctx>,
|
||||||
|
shape_ty: Type,
|
||||||
|
fill_value: BasicValueEnum<'ctx>,
|
||||||
|
name: &str,
|
||||||
|
) -> Result<Address<'ctx, NpArrayLens<'ctx>>, String>
|
||||||
|
where
|
||||||
|
G: CodeGenerator + ?Sized,
|
||||||
|
{
|
||||||
|
let ndarray_ptr = call_ndarray_empty_impl(generator, ctx, elem_ty, shape, shape_ty, name)?;
|
||||||
|
|
||||||
|
// NOTE: fill_value's type is not checked!!
|
||||||
|
let fill_value_ptr = build_opaque_alloca(ctx, fill_value.get_type(), name);
|
||||||
|
fill_value_ptr.store(ctx, );
|
||||||
|
// let fill_value_ptr = ctx.builder.build_alloca(, "fill_value_ptr").unwrap();
|
||||||
|
// ctx.builder.build_store(fill_value_ptr, fill_value);
|
||||||
|
|
||||||
|
// let ok = irrt::numpy::call_nac3_ndarray_fill_generic(generator, ctx, ndarray_ptr, Address { fill_value_ptr } );
|
||||||
|
todo!()
|
||||||
|
Ok(ndarray_ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates LLVM IR for `np.empty`.
|
||||||
|
pub fn gen_ndarray_empty<'ctx, G>(
|
||||||
|
context: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
obj: &Option<(Type, ValueEnum<'ctx>)>,
|
||||||
|
fun: (&FunSignature, DefinitionId),
|
||||||
|
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||||
|
generator: &mut dyn CodeGenerator,
|
||||||
|
) -> Result<PointerValue<'ctx>, String> {
|
||||||
|
assert!(obj.is_none());
|
||||||
|
assert_eq!(args.len(), 1);
|
||||||
|
|
||||||
|
// Parse arguments
|
||||||
|
let shape_ty = fun.0.args[0].ty;
|
||||||
|
let shape = args[0].1.clone().to_basic_value_enum(context, generator, shape_ty)?;
|
||||||
|
|
||||||
|
// Implementation
|
||||||
|
let ndarray_ptr = call_ndarray_empty_impl(
|
||||||
|
generator,
|
||||||
|
context,
|
||||||
|
context.primitives.float,
|
||||||
|
shape,
|
||||||
|
shape_ty,
|
||||||
|
"empty_ndarray",
|
||||||
|
)?;
|
||||||
|
Ok(ndarray_ptr.address)
|
||||||
|
}
|
|
@ -7,10 +7,7 @@ use inkwell::{
|
||||||
|
|
||||||
use crate::codegen::CodeGenContext;
|
use crate::codegen::CodeGenContext;
|
||||||
|
|
||||||
use super::{
|
use super::core::{MemoryGetter, MemoryOptic, MemorySetter, OpticValue, Prism};
|
||||||
core::{MemoryGetter, MemorySetter, Optic, OpticValue, Prism},
|
|
||||||
int::IntLens,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Address<'ctx, AddresseeOptic> {
|
pub struct Address<'ctx, AddresseeOptic> {
|
||||||
|
@ -19,7 +16,7 @@ pub struct Address<'ctx, AddresseeOptic> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, AddresseeOptic> Address<'ctx, AddresseeOptic> {
|
impl<'ctx, AddresseeOptic> Address<'ctx, AddresseeOptic> {
|
||||||
pub fn cast_to<S: Optic<'ctx>>(
|
pub fn cast_to<S: MemoryOptic<'ctx>>(
|
||||||
&self,
|
&self,
|
||||||
ctx: &CodeGenContext<'ctx, '_>,
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
new_optic: S,
|
new_optic: S,
|
||||||
|
@ -30,8 +27,8 @@ impl<'ctx, AddresseeOptic> Address<'ctx, AddresseeOptic> {
|
||||||
Address { addressee_optic: new_optic, address: casted_address }
|
Address { addressee_optic: new_optic, address: casted_address }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cast_to_opaque(&self, ctx: &CodeGenContext<'ctx, '_>) -> Address<'ctx, IntLens<'ctx>> {
|
pub fn cast_to_opaque(&self) -> OpaqueAddress<'ctx> {
|
||||||
self.cast_to(ctx, IntLens::int8(ctx.ctx))
|
OpaqueAddress(self.address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,21 +41,16 @@ impl<'ctx, AddresseeOptic> OpticValue<'ctx> for Address<'ctx, AddresseeOptic> {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AddressLens<AddresseeOptic>(pub AddresseeOptic);
|
pub struct AddressLens<AddresseeOptic>(pub AddresseeOptic);
|
||||||
|
|
||||||
#[must_use]
|
impl<'ctx, AddresseeOptic: MemoryOptic<'ctx>> MemoryOptic<'ctx> for AddressLens<AddresseeOptic> {
|
||||||
pub fn opaque_address_lens(ctx: &Context) -> AddressLens<IntLens<'_>> {
|
type MemoryValue = Address<'ctx, AddresseeOptic>;
|
||||||
AddressLens(IntLens::int8(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'ctx, AddresseeOptic: Optic<'ctx>> Optic<'ctx> for AddressLens<AddresseeOptic> {
|
|
||||||
type Value = Address<'ctx, AddresseeOptic>;
|
|
||||||
|
|
||||||
fn get_llvm_type(&self, ctx: &'ctx Context) -> BasicTypeEnum<'ctx> {
|
fn get_llvm_type(&self, ctx: &'ctx Context) -> BasicTypeEnum<'ctx> {
|
||||||
self.0.get_llvm_type(ctx).ptr_type(AddressSpace::default()).as_basic_type_enum()
|
self.0.get_llvm_type(ctx).ptr_type(AddressSpace::default()).as_basic_type_enum()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, AddresseeOptic: Optic<'ctx>> Prism<'ctx> for AddressLens<AddresseeOptic> {
|
impl<'ctx, AddresseeOptic: MemoryOptic<'ctx>> Prism<'ctx> for AddressLens<AddresseeOptic> {
|
||||||
fn review<V: AnyValue<'ctx>>(&self, value: V) -> Self::Value {
|
fn review<V: AnyValue<'ctx>>(&self, value: V) -> Self::MemoryValue {
|
||||||
Address {
|
Address {
|
||||||
addressee_optic: self.0.clone(),
|
addressee_optic: self.0.clone(),
|
||||||
address: value.as_any_value_enum().into_pointer_value(),
|
address: value.as_any_value_enum().into_pointer_value(),
|
||||||
|
@ -66,23 +58,23 @@ impl<'ctx, AddresseeOptic: Optic<'ctx>> Prism<'ctx> for AddressLens<AddresseeOpt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, AddressesOptic: Optic<'ctx>> MemoryGetter<'ctx> for AddressLens<AddressesOptic> {
|
impl<'ctx, AddressesOptic: MemoryOptic<'ctx>> MemoryGetter<'ctx> for AddressLens<AddressesOptic> {
|
||||||
fn get(
|
fn get(
|
||||||
&self,
|
&self,
|
||||||
ctx: &CodeGenContext<'ctx, '_>,
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
pointer: PointerValue<'ctx>,
|
pointer: PointerValue<'ctx>,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Self::Value {
|
) -> Self::MemoryValue {
|
||||||
self.review(ctx.builder.build_load(pointer, name).unwrap())
|
self.review(ctx.builder.build_load(pointer, name).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, AddressesOptic: Optic<'ctx>> MemorySetter<'ctx> for AddressLens<AddressesOptic> {
|
impl<'ctx, AddressesOptic: MemoryOptic<'ctx>> MemorySetter<'ctx> for AddressLens<AddressesOptic> {
|
||||||
fn set(
|
fn set(
|
||||||
&self,
|
&self,
|
||||||
ctx: &CodeGenContext<'ctx, '_>,
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
pointer: PointerValue<'ctx>,
|
pointer: PointerValue<'ctx>,
|
||||||
value: &Self::Value,
|
value: &Self::MemoryValue,
|
||||||
) {
|
) {
|
||||||
ctx.builder.build_store(pointer, value.address).unwrap();
|
ctx.builder.build_store(pointer, value.address).unwrap();
|
||||||
}
|
}
|
||||||
|
@ -90,14 +82,49 @@ impl<'ctx, AddressesOptic: Optic<'ctx>> MemorySetter<'ctx> for AddressLens<Addre
|
||||||
|
|
||||||
// To make [`Address`] convenient to use
|
// To make [`Address`] convenient to use
|
||||||
impl<'ctx, AddresseeOptic: MemoryGetter<'ctx>> Address<'ctx, AddresseeOptic> {
|
impl<'ctx, AddresseeOptic: MemoryGetter<'ctx>> Address<'ctx, AddresseeOptic> {
|
||||||
pub fn load(&self, ctx: &CodeGenContext<'ctx, '_>, name: &str) -> AddresseeOptic::Value {
|
pub fn load(&self, ctx: &CodeGenContext<'ctx, '_>, name: &str) -> AddresseeOptic::MemoryValue {
|
||||||
self.addressee_optic.get(ctx, self.address, name)
|
self.addressee_optic.get(ctx, self.address, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// To make [`Address`] convenient to use
|
// To make [`Address`] convenient to use
|
||||||
impl<'ctx, AddresseeOptic: MemorySetter<'ctx>> Address<'ctx, AddresseeOptic> {
|
impl<'ctx, AddresseeOptic: MemorySetter<'ctx>> Address<'ctx, AddresseeOptic> {
|
||||||
pub fn store(&self, ctx: &CodeGenContext<'ctx, '_>, value: &AddresseeOptic::Value) {
|
pub fn store(&self, ctx: &CodeGenContext<'ctx, '_>, value: &AddresseeOptic::MemoryValue) {
|
||||||
self.addressee_optic.set(ctx, self.address, value);
|
self.addressee_optic.set(ctx, self.address, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct OpaqueAddress<'ctx>(pub PointerValue<'ctx>);
|
||||||
|
|
||||||
|
impl<'ctx> OpaqueAddress<'ctx> {
|
||||||
|
pub fn cast_to<AddresseeOptic: MemoryOptic<'ctx>>(
|
||||||
|
&self,
|
||||||
|
ctx: &'ctx CodeGenContext,
|
||||||
|
addressee_optic: AddresseeOptic,
|
||||||
|
name: &str,
|
||||||
|
) -> Address<'ctx, AddresseeOptic> {
|
||||||
|
let ptr = ctx.builder.build_pointer_cast(
|
||||||
|
self.0,
|
||||||
|
addressee_optic.get_llvm_type(ctx.ctx).ptr_type(AddressSpace::default()),
|
||||||
|
name,
|
||||||
|
);
|
||||||
|
Address { addressee_optic, address: ptr }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct OpaqueAddressLens;
|
||||||
|
|
||||||
|
impl<'ctx> MemoryOptic<'ctx> for OpaqueAddressLens {
|
||||||
|
type MemoryValue = BasicValueEnum<'ctx>;
|
||||||
|
|
||||||
|
fn get_llvm_type(&self, ctx: &'ctx Context) -> BasicTypeEnum<'ctx> {
|
||||||
|
ctx.i8_type().ptr_type(AddressSpace::default()).as_basic_type_enum()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ctx> OpaqueAddress<'ctx> {
|
||||||
|
pub fn store(&self, ctx: &CodeGenContext<'ctx, '_>, value: BasicValueEnum<'ctx>) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,8 +21,8 @@ impl<'ctx, T: BasicValue<'ctx>> OpticValue<'ctx> for T {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: The interface is unintuitive
|
// TODO: The interface is unintuitive
|
||||||
pub trait Optic<'ctx>: Clone {
|
pub trait MemoryOptic<'ctx>: Clone {
|
||||||
type Value: OpticValue<'ctx>;
|
type MemoryValue: OpticValue<'ctx>;
|
||||||
|
|
||||||
fn get_llvm_type(&self, ctx: &'ctx Context) -> BasicTypeEnum<'ctx>;
|
fn get_llvm_type(&self, ctx: &'ctx Context) -> BasicTypeEnum<'ctx>;
|
||||||
|
|
||||||
|
@ -32,20 +32,20 @@ pub trait Optic<'ctx>: Clone {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Prism<'ctx>: Optic<'ctx> {
|
pub trait Prism<'ctx>: MemoryOptic<'ctx> {
|
||||||
// TODO: Return error if `review` fails
|
// TODO: Return error if `review` fails
|
||||||
fn review<V: AnyValue<'ctx>>(&self, value: V) -> Self::Value;
|
fn review<V: AnyValue<'ctx>>(&self, value: V) -> Self::MemoryValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MemoryGetter<'ctx>: Optic<'ctx> {
|
pub trait MemoryGetter<'ctx>: MemoryOptic<'ctx> {
|
||||||
fn get(
|
fn get(
|
||||||
&self,
|
&self,
|
||||||
ctx: &CodeGenContext<'ctx, '_>,
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
pointer: PointerValue<'ctx>,
|
pointer: PointerValue<'ctx>,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Self::Value;
|
) -> Self::MemoryValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MemorySetter<'ctx>: Optic<'ctx> {
|
pub trait MemorySetter<'ctx>: MemoryOptic<'ctx> {
|
||||||
fn set(&self, ctx: &CodeGenContext<'ctx, '_>, pointer: PointerValue<'ctx>, value: &Self::Value);
|
fn set(&self, ctx: &CodeGenContext<'ctx, '_>, pointer: PointerValue<'ctx>, value: &Self::MemoryValue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::codegen::CodeGenContext;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
address::Address,
|
address::Address,
|
||||||
core::{MemoryGetter, Optic},
|
core::{MemoryGetter, MemoryOptic},
|
||||||
};
|
};
|
||||||
|
|
||||||
// ((Memory, Pointer) -> ElementOptic::Value*)
|
// ((Memory, Pointer) -> ElementOptic::Value*)
|
||||||
|
@ -23,21 +23,21 @@ pub struct GepGetter<ElementOptic> {
|
||||||
pub element_optic: ElementOptic,
|
pub element_optic: ElementOptic,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, ElementOptic: Optic<'ctx>> Optic<'ctx> for GepGetter<ElementOptic> {
|
impl<'ctx, ElementOptic: MemoryOptic<'ctx>> MemoryOptic<'ctx> for GepGetter<ElementOptic> {
|
||||||
type Value = Address<'ctx, ElementOptic>;
|
type MemoryValue = Address<'ctx, ElementOptic>;
|
||||||
|
|
||||||
fn get_llvm_type(&self, ctx: &'ctx Context) -> BasicTypeEnum<'ctx> {
|
fn get_llvm_type(&self, ctx: &'ctx Context) -> BasicTypeEnum<'ctx> {
|
||||||
self.element_optic.get_llvm_type(ctx).ptr_type(AddressSpace::default()).as_basic_type_enum()
|
self.element_optic.get_llvm_type(ctx).ptr_type(AddressSpace::default()).as_basic_type_enum()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, ElementOptic: Optic<'ctx>> MemoryGetter<'ctx> for GepGetter<ElementOptic> {
|
impl<'ctx, ElementOptic: MemoryOptic<'ctx>> MemoryGetter<'ctx> for GepGetter<ElementOptic> {
|
||||||
fn get(
|
fn get(
|
||||||
&self,
|
&self,
|
||||||
ctx: &CodeGenContext<'ctx, '_>,
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
pointer: PointerValue<'ctx>,
|
pointer: PointerValue<'ctx>,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Self::Value {
|
) -> Self::MemoryValue {
|
||||||
let llvm_i32 = ctx.ctx.i32_type(); // TODO: I think I'm not supposed to *just* use i32 for GEP like that
|
let llvm_i32 = ctx.ctx.i32_type(); // TODO: I think I'm not supposed to *just* use i32 for GEP like that
|
||||||
let element_ptr = unsafe {
|
let element_ptr = unsafe {
|
||||||
ctx.builder
|
ctx.builder
|
||||||
|
|
|
@ -6,7 +6,7 @@ use inkwell::{
|
||||||
|
|
||||||
use crate::codegen::CodeGenContext;
|
use crate::codegen::CodeGenContext;
|
||||||
|
|
||||||
use super::core::{MemoryGetter, MemorySetter, Optic, Prism};
|
use super::core::{MemoryGetter, MemorySetter, MemoryOptic, Prism};
|
||||||
|
|
||||||
// NOTE: I wanted to make Int8Lens, Int16Lens, Int32Lens, with all
|
// NOTE: I wanted to make Int8Lens, Int16Lens, Int32Lens, with all
|
||||||
// having the trait IsIntLens, and implement `impl <S: IsIntLens> Optic<S> for T`,
|
// having the trait IsIntLens, and implement `impl <S: IsIntLens> Optic<S> for T`,
|
||||||
|
@ -31,8 +31,8 @@ impl<'ctx> IntLens<'ctx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> Optic<'ctx> for IntLens<'ctx> {
|
impl<'ctx> MemoryOptic<'ctx> for IntLens<'ctx> {
|
||||||
type Value = IntValue<'ctx>;
|
type MemoryValue = IntValue<'ctx>;
|
||||||
|
|
||||||
fn get_llvm_type(&self, _ctx: &'ctx Context) -> BasicTypeEnum<'ctx> {
|
fn get_llvm_type(&self, _ctx: &'ctx Context) -> BasicTypeEnum<'ctx> {
|
||||||
self.0.as_basic_type_enum()
|
self.0.as_basic_type_enum()
|
||||||
|
@ -40,7 +40,7 @@ impl<'ctx> Optic<'ctx> for IntLens<'ctx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> Prism<'ctx> for IntLens<'ctx> {
|
impl<'ctx> Prism<'ctx> for IntLens<'ctx> {
|
||||||
fn review<V: AnyValue<'ctx>>(&self, value: V) -> Self::Value {
|
fn review<V: AnyValue<'ctx>>(&self, value: V) -> Self::MemoryValue {
|
||||||
let int = value.as_any_value_enum().into_int_value();
|
let int = value.as_any_value_enum().into_int_value();
|
||||||
debug_assert_eq!(int.get_type().get_bit_width(), self.0.get_bit_width());
|
debug_assert_eq!(int.get_type().get_bit_width(), self.0.get_bit_width());
|
||||||
int
|
int
|
||||||
|
@ -53,13 +53,13 @@ impl<'ctx> MemoryGetter<'ctx> for IntLens<'ctx> {
|
||||||
ctx: &CodeGenContext<'ctx, '_>,
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
pointer: PointerValue<'ctx>,
|
pointer: PointerValue<'ctx>,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Self::Value {
|
) -> Self::MemoryValue {
|
||||||
self.review(ctx.builder.build_load(pointer, name).unwrap())
|
self.review(ctx.builder.build_load(pointer, name).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> MemorySetter<'ctx> for IntLens<'ctx> {
|
impl<'ctx> MemorySetter<'ctx> for IntLens<'ctx> {
|
||||||
fn set(&self, ctx: &CodeGenContext<'ctx, '_>, pointer: PointerValue<'ctx>, int: &Self::Value) {
|
fn set(&self, ctx: &CodeGenContext<'ctx, '_>, pointer: PointerValue<'ctx>, int: &Self::MemoryValue) {
|
||||||
debug_assert_eq!(int.get_type().get_bit_width(), self.0.get_bit_width());
|
debug_assert_eq!(int.get_type().get_bit_width(), self.0.get_bit_width());
|
||||||
ctx.builder.build_store(pointer, int.as_basic_value_enum()).unwrap();
|
ctx.builder.build_store(pointer, int.as_basic_value_enum()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{
|
use super::{
|
||||||
core::Optic,
|
core::MemoryOptic,
|
||||||
ixed::{BoundedIxed, Ixed},
|
ixed::{BoundedIxed, Ixed},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ pub struct ArraySlice<'ctx, ElementOptic> {
|
||||||
pub base: Address<'ctx, ElementOptic>,
|
pub base: Address<'ctx, ElementOptic>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, ElementOptic: Optic<'ctx>> Ixed<'ctx, ElementOptic> for ArraySlice<'ctx, ElementOptic> {
|
impl<'ctx, ElementOptic: MemoryOptic<'ctx>> Ixed<'ctx, ElementOptic> for ArraySlice<'ctx, ElementOptic> {
|
||||||
fn ix(
|
fn ix(
|
||||||
&self,
|
&self,
|
||||||
ctx: &CodeGenContext<'ctx, '_>,
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
|
@ -27,7 +27,7 @@ impl<'ctx, ElementOptic: Optic<'ctx>> Ixed<'ctx, ElementOptic> for ArraySlice<'c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, ElementOptic: Optic<'ctx>> BoundedIxed<'ctx, ElementOptic>
|
impl<'ctx, ElementOptic: MemoryOptic<'ctx>> BoundedIxed<'ctx, ElementOptic>
|
||||||
for ArraySlice<'ctx, ElementOptic>
|
for ArraySlice<'ctx, ElementOptic>
|
||||||
{
|
{
|
||||||
fn num_elements(&self, _ctx: &CodeGenContext<'ctx, '_>) -> IntValue<'ctx> {
|
fn num_elements(&self, _ctx: &CodeGenContext<'ctx, '_>) -> IntValue<'ctx> {
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::codegen::CodeGenContext;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
address::Address,
|
address::Address,
|
||||||
core::{MemoryGetter, MemorySetter, Optic, OpticValue},
|
core::{MemoryGetter, MemorySetter, MemoryOptic, OpticValue},
|
||||||
gep::GepGetter,
|
gep::GepGetter,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ impl<'ctx, StructOptic> OpticValue<'ctx> for OpticalStructValue<'ctx, StructOpti
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check StructType
|
// TODO: check StructType
|
||||||
impl<'ctx, T: StructureOptic<'ctx>> Optic<'ctx> for T {
|
impl<'ctx, T: StructureOptic<'ctx>> MemoryOptic<'ctx> for T {
|
||||||
type Value = OpticalStructValue<'ctx, Self>;
|
type MemoryValue = OpticalStructValue<'ctx, Self>;
|
||||||
|
|
||||||
fn get_llvm_type(&self, ctx: &'ctx Context) -> BasicTypeEnum<'ctx> {
|
fn get_llvm_type(&self, ctx: &'ctx Context) -> BasicTypeEnum<'ctx> {
|
||||||
let mut builder = FieldBuilder::new(ctx, self.struct_name());
|
let mut builder = FieldBuilder::new(ctx, self.struct_name());
|
||||||
|
@ -59,7 +59,7 @@ impl<'ctx, T: StructureOptic<'ctx>> MemoryGetter<'ctx> for T {
|
||||||
ctx: &CodeGenContext<'ctx, '_>,
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
pointer: PointerValue<'ctx>,
|
pointer: PointerValue<'ctx>,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Self::Value {
|
) -> Self::MemoryValue {
|
||||||
OpticalStructValue {
|
OpticalStructValue {
|
||||||
optic: self.clone(),
|
optic: self.clone(),
|
||||||
llvm: ctx.builder.build_load(pointer, name).unwrap().into_struct_value(),
|
llvm: ctx.builder.build_load(pointer, name).unwrap().into_struct_value(),
|
||||||
|
@ -72,14 +72,14 @@ impl<'ctx, T: StructureOptic<'ctx>> MemorySetter<'ctx> for T {
|
||||||
&self,
|
&self,
|
||||||
ctx: &CodeGenContext<'ctx, '_>,
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
pointer: PointerValue<'ctx>,
|
pointer: PointerValue<'ctx>,
|
||||||
value: &Self::Value,
|
value: &Self::MemoryValue,
|
||||||
) {
|
) {
|
||||||
ctx.builder.build_store(pointer, value.llvm).unwrap();
|
ctx.builder.build_store(pointer, value.llvm).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, AddresseeOptic: StructureOptic<'ctx>> Address<'ctx, AddresseeOptic> {
|
impl<'ctx, AddresseeOptic: StructureOptic<'ctx>> Address<'ctx, AddresseeOptic> {
|
||||||
pub fn focus<GetFieldGepFn, FieldElementOptic: Optic<'ctx>>(
|
pub fn focus<GetFieldGepFn, FieldElementOptic: MemoryOptic<'ctx>>(
|
||||||
&self,
|
&self,
|
||||||
ctx: &CodeGenContext<'ctx, '_>,
|
ctx: &CodeGenContext<'ctx, '_>,
|
||||||
get_field_gep_fn: GetFieldGepFn,
|
get_field_gep_fn: GetFieldGepFn,
|
||||||
|
@ -121,7 +121,7 @@ impl<'ctx> FieldBuilder<'ctx> {
|
||||||
index
|
index
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_field<ElementOptic: Optic<'ctx>>(
|
pub fn add_field<ElementOptic: MemoryOptic<'ctx>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
element_optic: ElementOptic,
|
element_optic: ElementOptic,
|
||||||
|
|
Loading…
Reference in New Issue