From ed7f735592fb871f4688e0b72432feff31f29006 Mon Sep 17 00:00:00 2001 From: Connor Horman Date: Tue, 12 Nov 2024 19:39:42 -0500 Subject: [PATCH] feat(xlang-ir): Add `RequiredMetadata` metadata --- xlang/xlang_struct/Cargo.toml | 6 +- xlang/xlang_struct/src/lib.rs | 15 +++-- xlang/xlang_struct/src/meta.rs | 14 ++++- xlang/xlang_struct/src/meta/block.rs | 10 +++- xlang/xlang_struct/src/meta/body.rs | 1 + xlang/xlang_struct/src/meta/file.rs | 85 ++++++++++++++++++++++++++++ 6 files changed, 120 insertions(+), 11 deletions(-) create mode 100644 xlang/xlang_struct/src/meta/body.rs create mode 100644 xlang/xlang_struct/src/meta/file.rs diff --git a/xlang/xlang_struct/Cargo.toml b/xlang/xlang_struct/Cargo.toml index eebf146c..55c0453c 100644 --- a/xlang/xlang_struct/Cargo.toml +++ b/xlang/xlang_struct/Cargo.toml @@ -11,7 +11,7 @@ ABI Safe structures for representing xlang's intermediate representation # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -xlang_abi = {path="../xlang_abi",version="0.2.0"} -xlang_targets = {path="../xlang_targets",version="0.2.0"} -bitflags = "1.3" +xlang_abi = { path = "../xlang_abi", version = "0.2.0" } +xlang_targets = { path = "../xlang_targets", version = "0.2.0" } +bitflags.workspace = true fake-enum = "0.1.4" diff --git a/xlang/xlang_struct/src/lib.rs b/xlang/xlang_struct/src/lib.rs index a7ab4424..66b9e5d8 100644 --- a/xlang/xlang_struct/src/lib.rs +++ b/xlang/xlang_struct/src/lib.rs @@ -414,6 +414,7 @@ bitflags::bitflags! { /// static-specifier := "immut" /// ``` #[repr(transparent)] + #[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct StaticSpecifier : u16{ const IMMUTABLE = 0x001; } @@ -478,7 +479,7 @@ bitflags::bitflags! { /// `uninit` is considered invalid for any scalar type that has any validity constraint - loading/storing such a value yields `invalid`. /// #[repr(transparent)] - #[derive(Default)] + #[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct ScalarValidity : u8{ /// The `scalar-validity` specifier `"nonzero"`. /// Indicates that a zero value is not permitted. @@ -522,6 +523,7 @@ bitflags::bitflags! { /// char-specifier := ["unicode"] /// ``` #[repr(transparent)] + #[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct CharFlags: u8{ /// Whether or not the type is considered to be signed or unsigned /// @@ -1027,6 +1029,7 @@ bitflags::bitflags! { /// field-specifier := "mutable" /// ``` #[repr(transparent)] + #[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct AggregateFieldSpecifier : u32{ /// Indicates that the field is writable, regardless of `readonly`, `readshallow`, or top level `immutable binding` const MUTABLE = 0x0001; @@ -1160,7 +1163,7 @@ bitflags::bitflags! { /// pointer-aliasing = "unique" / "readonly" / "nonnull" /// ``` #[repr(transparent)] - #[derive(Default)] + #[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct PointerAliasingRule : u32{ /// Indicates that no other pointers access any of the same bytes while this pointer is active. /// @@ -1215,7 +1218,7 @@ bitflags::bitflags! { /// ``` /// #[repr(transparent)] - #[derive(Default)] + #[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct ValidRangeType : u16{ /// Indicates that the valid range of the pointer const INBOUNDS = 1; @@ -1225,7 +1228,7 @@ bitflags::bitflags! { } bitflags::bitflags! { #[repr(transparent)] - #[derive(Default)] + #[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct PointerDeclarationType : u16{ const REF = 1; const CONST = 2; @@ -2267,7 +2270,7 @@ bitflags::bitflags! { /// jump-target-flag := "fallthrough" / "cold" / "continue" /// ``` #[repr(transparent)] - #[derive(Default)] + #[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct JumpTargetFlags : u32{ /// The "fallthrough" flag. /// Indicates that the jump does not perform a branch but instead continues on to the next basic block @@ -2319,6 +2322,7 @@ impl core::fmt::Display for JumpTarget { bitflags::bitflags! { /// Flags for the call instruction #[repr(transparent)] + #[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct CallFlags: u32{ /// Indicates the the call or tailcall will definitely return in finite time const WILLRETURN = 1; @@ -2384,6 +2388,7 @@ impl core::fmt::Display for AsmConstraint { bitflags::bitflags! { #[repr(transparent)] + #[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] // more like clippy::readable_literal pub struct AsmOptions : u32{ #[allow(clippy::unreadable_literal)] diff --git a/xlang/xlang_struct/src/meta.rs b/xlang/xlang_struct/src/meta.rs index feb013c4..0294369e 100644 --- a/xlang/xlang_struct/src/meta.rs +++ b/xlang/xlang_struct/src/meta.rs @@ -9,6 +9,8 @@ use xlang_abi::prelude::v1::*; use xlang_abi::result::Result::{self, Ok}; pub mod block; +pub mod body; +pub mod file; #[repr(C)] #[cfg_attr(target_pointer_width = "32", repr(align(32)))] @@ -169,7 +171,7 @@ impl Metadata { } } - pub fn get>(&self) -> Option<&T> { + pub fn get>(&self) -> Option<&M> { if self.ty == M::TAG { Some(unsafe { transmute_unchecked(&self.data) }) } else { @@ -177,7 +179,7 @@ impl Metadata { } } - pub fn get_mut>(&mut self) -> Option<&mut T> { + pub fn get_mut>(&mut self) -> Option<&mut M> { if self.ty == M::TAG { Some(unsafe { transmute_unchecked(&mut self.data) }) } else { @@ -276,6 +278,14 @@ impl MetadataList { pub fn push>>(&mut self, m: M) { self.0.push(m.into()) } + + pub fn get>(&self) -> Option<&M> { + self.0.iter().find_map(Metadata::get) + } + + pub fn get_mut>(&mut self) -> Option<&mut M> { + self.0.iter_mut().find_map(Metadata::get_mut) + } } impl>> core::iter::FromIterator for MetadataList { diff --git a/xlang/xlang_struct/src/meta/block.rs b/xlang/xlang_struct/src/meta/block.rs index c771af92..f80a7b16 100644 --- a/xlang/xlang_struct/src/meta/block.rs +++ b/xlang/xlang_struct/src/meta/block.rs @@ -3,11 +3,19 @@ use crate::Block; use xlang_abi::prelude::v1::*; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] pub struct ReachableFrom { pub reachable: Vec, } +impl ReachableFrom { + pub const fn new() -> Self { + Self { + reachable: Vec::new(), + } + } +} + impl core::fmt::Display for ReachableFrom { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut sep = ""; diff --git a/xlang/xlang_struct/src/meta/body.rs b/xlang/xlang_struct/src/meta/body.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/xlang/xlang_struct/src/meta/body.rs @@ -0,0 +1 @@ + diff --git a/xlang/xlang_struct/src/meta/file.rs b/xlang/xlang_struct/src/meta/file.rs new file mode 100644 index 00000000..c742ee8e --- /dev/null +++ b/xlang/xlang_struct/src/meta/file.rs @@ -0,0 +1,85 @@ +use xlang_abi::string::{CowStr, StringView}; + +use crate::File; + +use crate::meta::MetadataFor; + +#[repr(C)] +#[derive(Clone, Debug)] +pub struct RequiredMetadata { + pub meta: Vec, +} + +impl super::sealed::Sealed for RequiredMetadata {} + +impl MetadataFor for RequiredMetadata { + const TAG: StringView<'static> = StringView::new("requires"); +} + +impl core::fmt::Display for RequiredMetadata { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut sep = ""; + + for m in &self.meta { + f.write_str(sep)?; + sep = ", "; + m.fmt(f)?; + } + Ok(()) + } +} + +bitflags::bitflags! { + #[repr(transparent)] + #[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] + pub struct RequiredMetadataContext : u32{ + /// Any plugin that views the incoming IR *must* not process a file that sets the metadata type it doesn't recognize + /// (Metadata is mandatory for interpreting the file at all) + const PROCESSOR = 0x00000001; + /// An output plugin (code generator) must not process a file that sets the metadata type it doesn't recognize + /// (Metadata is mandatory for emitting code from the metadata) + const OUTPUT = 0x00000002; + /// Any plugin that mutates the incoming IR in place must not process a file that sets the metadata type it doesn't recognize + const TRANSFORMER = 0x00000004; + /// Any transformer plugin that is an optimizer must not process a file that sets the metadata type it doesn't recognize + const OPTIMIZER = 0x00000008; + } +} + +bitflags::bitflags! { + #[repr(transparent)] + #[derive(Default, Copy, Clone, Debug, Hash, PartialEq, Eq)] + pub struct RequiredMetadataPosition : u128{ + const FILE = 0x0001; + } +} + +#[repr(C)] +#[derive(Clone, Debug)] +pub struct RequiresEntry { + pub key: CowStr<'static>, + pub ctx: RequiredMetadataContext, + pub positions: RequiredMetadataPosition, +} + +impl core::fmt::Display for RequiresEntry { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(self.key.as_str())?; + f.write_str(" ")?; + + for (name, _) in self.ctx.iter_names() { + f.write_str(&name.to_ascii_lowercase())?; + f.write_str(" ")?; + } + + let mut sep = ""; + f.write_str("{")?; + for (pos, _) in self.positions.iter_names() { + f.write_str(sep)?; + sep = ", "; + f.write_str(&pos.to_ascii_lowercase())?; + } + + f.write_str("}") + } +}