Skip to content

Commit

Permalink
feat: add lang-repr as a combinatoric and rust as a convention
Browse files Browse the repository at this point in the history
fixes #27
fixes #36
  • Loading branch information
Gankra committed Jul 1, 2024
1 parent 6ba6865 commit 842036b
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 96 deletions.
21 changes: 20 additions & 1 deletion kdl-script/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,30 @@ pub enum Repr {
Transparent,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, serde::Serialize)]
pub enum LangRepr {
Rust,
C,
}
impl std::fmt::Display for LangRepr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
LangRepr::Rust => "rust",
LangRepr::C => "c",
};
s.fmt(f)
}
}
impl std::str::FromStr for LangRepr {
type Err = String;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
"rust" => Ok(Self::Rust),
"c" => Ok(Self::C),
_ => Err(format!("unknown lang repr {s}")),
}
}
}

/// An attribute to passthrough to the target language.
///
Expand Down
101 changes: 53 additions & 48 deletions src/abis/c/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ impl CcAbiImpl {
// Nominal types we need to emit a decl for
Ty::Struct(struct_ty) => {
// Emit an actual struct decl
self.generate_repr_attr(f, &struct_ty.attrs, "struct")?;
self.generate_repr_attr(f, state, &struct_ty.attrs, "struct")?;
writeln!(f, "typedef struct {} {{", struct_ty.name)?;
f.add_indent(1);
for field in &struct_ty.fields {
Expand All @@ -233,7 +233,7 @@ impl CcAbiImpl {
}
Ty::Union(union_ty) => {
// Emit an actual union decl
self.generate_repr_attr(f, &union_ty.attrs, "union")?;
self.generate_repr_attr(f, state, &union_ty.attrs, "union")?;
writeln!(f, "typedef union {} {{", union_ty.name)?;
f.add_indent(1);
for field in &union_ty.fields {
Expand All @@ -246,7 +246,7 @@ impl CcAbiImpl {
}
Ty::Enum(enum_ty) => {
// Emit an actual enum decl
self.generate_repr_attr(f, &enum_ty.attrs, "enum")?;
self.generate_repr_attr(f, state, &enum_ty.attrs, "enum")?;
writeln!(f, "typedef enum {} {{", enum_ty.name)?;
f.add_indent(1);
for variant in &enum_ty.variants {
Expand Down Expand Up @@ -336,88 +336,80 @@ impl CcAbiImpl {

pub fn generate_repr_attr(
&self,
_f: &mut Fivemat,
f: &mut Fivemat,
state: &TestState,
attrs: &[Attr],
_ty_style: &str,
) -> Result<(), GenerateError> {
use kdl_script::parse::{AttrAligned, AttrPacked, AttrPassthrough, AttrRepr, Repr};
if !attrs.is_empty() {
return Err(UnsupportedError::Other(
"c doesn't support attrs yet".to_owned(),
))?;
}

/*
let mut default_c_repr = true;
let mut default_lang_repr = true;
let mut lang_repr = None;
let mut repr_attrs = vec![];
let mut other_attrs = vec![];
for attr in attrs {
match attr {
Attr::Align(AttrAligned { align }) => {
repr_attrs.push(format!("align({})", align.val));
Attr::Align(AttrAligned { align: _ }) => {
return Err(UnsupportedError::Other("@align not implemented".to_owned()))?;
}
Attr::Packed(AttrPacked {}) => {
repr_attrs.push("packed".to_owned());
return Err(UnsupportedError::Other(
"@packed not implemented".to_owned(),
))?;
}
Attr::Passthrough(AttrPassthrough(attr)) => {
other_attrs.push(attr.to_string());
other_attrs.push(attr);
}
Attr::Repr(AttrRepr { reprs }) => {
default_lang_repr = false;
// Any explicit repr attributes disables default C
default_c_repr = false;
for repr in reprs {
let val = match repr {
Repr::Primitive(prim) => match prim {
PrimitiveTy::I8 => "i8",
PrimitiveTy::I16 => "i16",
PrimitiveTy::I32 => "i32",
PrimitiveTy::I64 => "i64",
PrimitiveTy::I128 => "i128",
PrimitiveTy::U8 => "u8",
PrimitiveTy::U16 => "u16",
PrimitiveTy::U32 => "u32",
PrimitiveTy::U64 => "u64",
PrimitiveTy::U128 => "u128",
PrimitiveTy::I256
| PrimitiveTy::U256
| PrimitiveTy::F16
| PrimitiveTy::F32
| PrimitiveTy::F64
| PrimitiveTy::F128
| PrimitiveTy::Bool
| PrimitiveTy::Ptr => {
match repr {
Repr::Transparent => {
return Err(UnsupportedError::Other(
"unsupport repr transparent".to_owned(),
))?;
}
Repr::Primitive(prim) => {
return Err(UnsupportedError::Other(format!(
"unsupport repr {prim:?}"
)))?;
}
Repr::Lang(repr) => {
if let Some(old_repr) = lang_repr {
return Err(UnsupportedError::Other(format!(
"unsupport repr({prim:?})"
"multiple lang reprs on one type ({old_repr}, {repr})"
)))?;
}
},
Repr::Lang(LangRepr::C) => "C",
Repr::Lang(LangRepr::Rust) => {
lang_repr = Some(*repr);
continue;
}
Repr::Transparent => "transparent",
};
repr_attrs.push(val.to_owned());
}
}
}
}
if default_c_repr {
repr_attrs.push("C".to_owned());
if default_lang_repr && lang_repr.is_none() {
lang_repr = Some(state.options.repr);
}
write!(f, "#[repr(")?;
let mut multi = false;
for repr in repr_attrs {
if multi {
write!(f, ", ")?;
if let Some(lang_repr) = lang_repr {
if let Some(attr) = self.lang_repr_decl(lang_repr)? {
repr_attrs.push(attr.to_owned());
}
multi = true;
write!(f, "{repr}")?;
}
writeln!(f, ")]")?;
if !repr_attrs.is_empty() {
return Err(UnsupportedError::Other(
"c doesn't implement non-trivial reprs attributes yet".to_owned(),
))?;
}
for attr in other_attrs {
writeln!(f, "{}", attr)?;
}
*/
Ok(())
}

Expand Down Expand Up @@ -478,6 +470,10 @@ impl CcAbiImpl {
// all properly convered by other ABIs
return Err(self.unsupported_convention(&convention))?;
}
// C knows no Rust
Rust => {
return Err(self.unsupported_convention(&convention))?;
}
C => "",
Cdecl => {
if self.platform == Windows {
Expand Down Expand Up @@ -524,6 +520,15 @@ impl CcAbiImpl {
Ok(val)
}

fn lang_repr_decl(&self, repr: LangRepr) -> Result<Option<&'static str>, GenerateError> {
match repr {
LangRepr::Rust => Err(UnsupportedError::Other(
"c doesn't support repr rust".to_owned(),
))?,
LangRepr::C => Ok(None),
}
}

fn unsupported_convention(&self, convention: &CallingConvention) -> UnsupportedError {
UnsupportedError::Other(format!("unsupported convention {convention}"))
}
Expand Down
10 changes: 10 additions & 0 deletions src/abis/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::{collections::HashMap, fmt::Write, sync::Arc};

use camino::Utf8Path;
use kdl_script::{
parse::LangRepr,
types::{FuncIdx, TyIdx},
DefinitionGraph, PunEnv, TypedProgram,
};
Expand All @@ -30,17 +31,21 @@ pub static ABI_IMPL_CLANG: &str = "clang";
pub static ABI_IMPL_MSVC: &str = "msvc";

pub static ALL_CONVENTIONS: &[CallingConvention] = &[
// C!
CallingConvention::C,
CallingConvention::Cdecl,
CallingConvention::Stdcall,
CallingConvention::Fastcall,
CallingConvention::Vectorcall,
// Rust!
CallingConvention::Rust,
// Note sure if these have a purpose, so omitting them for now
// CallingConvention::System,
// CallingConvention::Win64,
// CallingConvention::Sysv64,
// CallingConvention::Aapcs,
];
pub static ALL_REPRS: &[LangRepr] = &[LangRepr::Rust, LangRepr::C];

/// A test case, fully abstract.
///
Expand Down Expand Up @@ -95,6 +100,7 @@ pub struct TestOptions {
pub functions: FunctionSelector,
pub val_writer: WriteImpl,
pub val_generator: ValueGeneratorKind,
pub repr: LangRepr,
}
impl FunctionSelector {
pub fn should_write_arg(&self, func_idx: usize, arg_idx: usize) -> bool {
Expand Down Expand Up @@ -333,6 +339,8 @@ impl TestWithAbi {
pub enum CallingConvention {
/// The platform's default C convention (cdecl?)
C,
/// Rust's default calling convention
Rust,
/// ???
Cdecl,
/// The platorm's default OS convention (usually C, but Windows is Weird).
Expand Down Expand Up @@ -361,6 +369,7 @@ impl CallingConvention {
pub fn name(&self) -> &'static str {
match self {
CallingConvention::C => "c",
CallingConvention::Rust => "rust",
CallingConvention::Cdecl => "cdecl",
CallingConvention::System => "system",
CallingConvention::Win64 => "win64",
Expand All @@ -385,6 +394,7 @@ impl std::str::FromStr for CallingConvention {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let val = match s {
"c" => CallingConvention::C,
"rust" => CallingConvention::Rust,
"cdecl" => CallingConvention::Cdecl,
"system" => CallingConvention::System,
"win64" => CallingConvention::Win64,
Expand Down
Loading

0 comments on commit 842036b

Please sign in to comment.