Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IR traits #21

Merged
merged 5 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ use combine::{parser, Parser};
use downcast_rs::{impl_downcast, Downcast};
use dyn_clone::DynClone;
use intertrait::{cast::CastRef, CastFrom};
use rustc_hash::FxHashMap;

use crate::{
common_traits::Verify,
common_traits::{Qualified, Verify},
context::Context,
dialect::{Dialect, DialectName},
error::Result,
Expand All @@ -48,6 +49,8 @@ use crate::{
printable::{self, Printable},
};

pub type AttributeDict = FxHashMap<&'static str, AttrObj>;

/// Basic functionality that every attribute in the IR must implement.
///
/// See [module](crate::attribute) documentation for more information.
Expand Down Expand Up @@ -80,6 +83,14 @@ pub trait Attribute: Printable + Verify + Downcast + CastFrom + Sync + DynClone
impl_downcast!(Attribute);
dyn_clone::clone_trait_object!(Attribute);

impl Qualified for dyn Attribute {
type Qualifier = AttrId;

fn get_qualifier(&self, _ctx: &Context) -> Self::Qualifier {
self.get_attr_id()
}
}

/// [Attribute] objects are boxed and stored in the IR.
pub type AttrObj = Box<dyn Attribute>;

Expand Down Expand Up @@ -327,6 +338,14 @@ macro_rules! impl_attr {
Ok(())
}
}

impl $crate::common_traits::Qualified for $structname {
type Qualifier = $crate::attribute::AttrId;

fn get_qualifier(&self, _ctx: &Context) -> Self::Qualifier {
self.get_attr_id()
}
}
}
}

Expand Down
8 changes: 7 additions & 1 deletion src/basic_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::{
operation::Operation,
parsable::{self, spaced, IntoParseResult, Parsable, ParseResult},
printable::{self, indented_nl, ListSeparator, Printable, PrintableIter},
r#type::{type_parser, TypeObj},
r#type::{type_parser, TypeObj, Typed},
region::Region,
use_def_lists::{DefNode, Value},
};
Expand Down Expand Up @@ -54,6 +54,12 @@ impl BlockArgument {
}
}

impl Typed for BlockArgument {
fn get_type(&self, _cfg: &Context) -> Ptr<TypeObj> {
self.ty
}
}

impl Named for BlockArgument {
fn given_name(&self, ctx: &Context) -> Option<String> {
get_block_arg_name(ctx, self.get_def_block(), self.arg_idx)
Expand Down
38 changes: 37 additions & 1 deletion src/common_traits.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,42 @@
//! Utility traits such as [Named], [Verify] etc.

use crate::{context::Context, error::Result};
use crate::{
context::{private::ArenaObj, Context, Ptr},
error::Result,
};

// Objects that have a qualified name within a dialect.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Objects IR entities

// All Attribute and Type instances are qualified objects with their <kind>ID type as the
// qualifier.
pub trait Qualified {
type Qualifier;

fn get_qualifier(&self, ctx: &Context) -> Self::Qualifier;
}

impl<T: Qualified> Qualified for &T {
type Qualifier = T::Qualifier;

fn get_qualifier(&self, ctx: &Context) -> Self::Qualifier {
(*self).get_qualifier(ctx)
}
}

impl<T: Qualified + ?Sized> Qualified for Box<T> {
type Qualifier = T::Qualifier;

fn get_qualifier(&self, ctx: &Context) -> Self::Qualifier {
(**self).get_qualifier(ctx)
}
}

impl<T: Qualified + ArenaObj> Qualified for Ptr<T> {
type Qualifier = T::Qualifier;

fn get_qualifier(&self, ctx: &Context) -> Self::Qualifier {
self.deref(ctx).get_qualifier(ctx)
}
}

/// Check and ensure correctness.
pub trait Verify {
Expand Down
1 change: 0 additions & 1 deletion src/dialects/builtin/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use crate::{
parsable::{spaced, IntoParseResult, Parsable, ParseResult, StateStream},
printable::{self, ListSeparator, Printable, PrintableIter},
r#type::{type_parser, Type, TypeObj},
storage_uniquer::TypeValueHash,
};

#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug)]
Expand Down
1 change: 0 additions & 1 deletion src/dialects/llvm/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::{
parsable::{spaced, IntoParseResult, Parsable, ParseResult, StateStream},
printable::{self, Printable, PrintableIter},
r#type::{type_parser, Type, TypeObj},
storage_uniquer::TypeValueHash,
verify_err_noloc,
};
use combine::{between, optional, parser::char::spaces, sep_by, token, Parser};
Expand Down
21 changes: 16 additions & 5 deletions src/operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
use std::marker::PhantomData;

use combine::{attempt, parser::char::spaces, position, token, Parser};
use rustc_hash::FxHashMap;
use thiserror::Error;

use crate::{
attribute::AttrObj,
attribute::AttributeDict,
basic_block::BasicBlock,
common_traits::{Named, Verify},
context::{private::ArenaObj, ArenaCell, Context, Ptr},
Expand All @@ -22,7 +21,7 @@ use crate::{
op::{self, OpId, OpObj},
parsable::{self, spaced, Parsable, ParseResult, StateStream},
printable::{self, Printable},
r#type::TypeObj,
r#type::{TypeObj, Typed},
region::Region,
use_def_lists::{DefNode, DefTrait, DefUseParticipant, Use, UseNode, Value},
vec_exns::VecExtns,
Expand All @@ -48,6 +47,12 @@ impl OpResult {
}
}

impl Typed for OpResult {
fn get_type(&self, _ctx: &Context) -> Ptr<TypeObj> {
self.ty
}
}

impl From<&OpResult> for Value {
fn from(value: &OpResult) -> Self {
Value::OpResult {
Expand Down Expand Up @@ -103,7 +108,7 @@ pub struct Operation {
/// previous and next [Operation]s in the block.
pub(crate) block_links: BlockLinks,
/// A dictionary of attributes.
pub attributes: FxHashMap<&'static str, AttrObj>,
pub attributes: AttributeDict,
/// Regions contained inside this operation.
pub(crate) regions: Vec<Ptr<Region>>,
/// Source location of this operation.
Expand Down Expand Up @@ -157,7 +162,7 @@ impl Operation {
operands: vec![],
successors: vec![],
block_links: BlockLinks::new_unlinked(),
attributes: FxHashMap::default(),
attributes: AttributeDict::default(),
regions: vec![],
loc: Location::Unknown,
};
Expand Down Expand Up @@ -437,6 +442,12 @@ impl<T: DefUseParticipant + Named> Printable for Operand<T> {
}
}

impl<T: DefUseParticipant + Typed> Typed for Operand<T> {
fn get_type(&self, ctx: &Context) -> Ptr<TypeObj> {
self.r#use.get_def().get_type(ctx)
}
}

#[derive(Error, Debug)]
#[error("operand is not a use of its def")]
pub struct DefUseVerifyErr;
Expand Down
2 changes: 1 addition & 1 deletion src/parsable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ impl NameTracker {
// Check if there are any unresolved forward label references.
for (id, op) in label_scope {
if matches!(op, LabelRef::ForwardRef(_)) {
input_err!(loc.clone(), UnresolvedReference(id.clone()))?
return input_err!(loc.clone(), UnresolvedReference(id.clone()))?;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooops, I wanted to clean that up. I had a conflict with the commit introducing locations when rebasing

}
}

Expand Down
58 changes: 55 additions & 3 deletions src/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
//!
//! The [impl_type](crate::impl_type) macro can be used to implement [Type] for a rust type.

use crate::common_traits::Verify;
use crate::common_traits::{Qualified, Verify};
use crate::context::{private::ArenaObj, ArenaCell, Context, Ptr};
use crate::dialect::{Dialect, DialectName};
use crate::error::Result;
Expand Down Expand Up @@ -122,6 +122,50 @@ pub trait Type: Printable + Verify + Downcast + Sync + Debug {
}
impl_downcast!(Type);

impl Qualified for dyn Type {
type Qualifier = TypeId;

fn get_qualifier(&self, _ctx: &Context) -> Self::Qualifier {
self.get_type_id()
}
}

/// Trait for objects that have a direct type.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

object IR entity. Here and the next line.

pub trait Typed {
/// Get the [Type] of the current object.
fn get_type(&self, ctx: &Context) -> Ptr<TypeObj>;
}

impl Typed for Ptr<TypeObj> {
fn get_type(&self, _ctx: &Context) -> Ptr<TypeObj> {
*self
}
}

impl Typed for dyn Type {
fn get_type(&self, ctx: &Context) -> Ptr<TypeObj> {
self.get_self_ptr(ctx)
}
}

impl<T: Typed + ?Sized> Typed for &T {
fn get_type(&self, ctx: &Context) -> Ptr<TypeObj> {
(*self).get_type(ctx)
}
}

impl<T: Typed + ?Sized> Typed for &mut T {
fn get_type(&self, ctx: &Context) -> Ptr<TypeObj> {
(**self).get_type(ctx)
}
}

impl<T: Typed + ?Sized> Typed for Box<T> {
fn get_type(&self, ctx: &Context) -> Ptr<TypeObj> {
(**self).get_type(ctx)
}
}

#[derive(Clone, Hash, PartialEq, Eq)]
/// A Type's name (not including it's dialect).
pub struct TypeName(Identifier);
Expand Down Expand Up @@ -303,8 +347,8 @@ macro_rules! impl_type {
$structname: ident, $type_name: literal, $dialect_name: literal) => {
$(#[$outer])*
impl $crate::r#type::Type for $structname {
fn hash_type(&self) -> TypeValueHash {
TypeValueHash::new(self)
fn hash_type(&self) -> $crate::storage_uniquer::TypeValueHash {
$crate::storage_uniquer::TypeValueHash::new(self)
}

fn eq_type(&self, other: &dyn Type) -> bool {
Expand All @@ -324,6 +368,14 @@ macro_rules! impl_type {
}
}
}

impl $crate::common_traits::Qualified for $structname {
type Qualifier = $crate::r#type::TypeId;

fn get_qualifier(&self, _ctx: &$crate::context::Context) -> Self::Qualifier {
Self::get_type_id_static()
}
}
}
}

Expand Down
8 changes: 7 additions & 1 deletion src/use_def_lists.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{
context::{Context, Ptr},
linked_list::{ContainsLinkedList, LinkedList},
operation::Operation,
r#type::TypeObj,
r#type::{TypeObj, Typed},
};

/// def-use chains are implemented for [Value]s and `Ptr<BasicBlock`.
Expand Down Expand Up @@ -170,6 +170,12 @@ impl Value {
}
}

impl Typed for Value {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you see any problem if I just replace this function with the contents of Value::get_type(..) and remove that impl method?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i.e., get_type(..) won't be a method on Value anymore, but will provide that functionality by implementing the Typed trait.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem with that. I was thinking to propose this as a follow up :)

fn get_type(&self, ctx: &Context) -> Ptr<TypeObj> {
self.get_type(ctx)
}
}

impl Named for Value {
fn given_name(&self, ctx: &Context) -> Option<String> {
match self {
Expand Down