Skip to content

Commit

Permalink
Basic metadata generation (#1820)
Browse files Browse the repository at this point in the history
  • Loading branch information
kennykerr authored Jun 15, 2022
1 parent 22fc69d commit d3eee4a
Show file tree
Hide file tree
Showing 17 changed files with 379 additions and 130 deletions.
10 changes: 5 additions & 5 deletions crates/libs/bindgen/src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ fn gen_struct_with_name(gen: &Gen, def: TypeDef, struct_name: &str, cfg: &Cfg) -

if gen.reader.field_flags(f).literal() {
quote! {}
} else if !gen.sys && flags.union() && !gen.reader.field_is_blittable(f, def) {
} else if !gen.sys && flags.explicit_layout() && !gen.reader.field_is_blittable(f, def) {
quote! { pub #name: ::core::mem::ManuallyDrop<#ty>, }
} else {
quote! { pub #name: #ty, }
}
});

let struct_or_union = if flags.union() {
let struct_or_union = if flags.explicit_layout() {
quote! { union }
} else {
quote! { struct }
Expand Down Expand Up @@ -153,7 +153,7 @@ fn gen_compare_traits(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) ->

if gen.sys {
quote! {}
} else if gen.reader.type_def_is_blittable(def) || gen.reader.type_def_flags(def).union() || gen.reader.type_def_class_layout(def).is_some() {
} else if gen.reader.type_def_is_blittable(def) || gen.reader.type_def_flags(def).explicit_layout() || gen.reader.type_def_class_layout(def).is_some() {
quote! {
#features
impl ::core::cmp::PartialEq for #name {
Expand Down Expand Up @@ -197,7 +197,7 @@ fn gen_compare_traits(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) ->
}

fn gen_debug(gen: &Gen, def: TypeDef, ident: &TokenStream, cfg: &Cfg) -> TokenStream {
if gen.sys || gen.reader.type_def_has_union(def) || gen.reader.type_def_has_packing(def) {
if gen.sys || gen.reader.type_def_has_explicit_layout(def) || gen.reader.type_def_has_packing(def) {
quote! {}
} else {
let name = ident.as_str();
Expand Down Expand Up @@ -245,7 +245,7 @@ fn gen_copy_clone(gen: &Gen, def: TypeDef, name: &TokenStream, cfg: &Cfg) -> Tok
}
}
}
} else if gen.reader.type_def_flags(def).union() {
} else if gen.reader.type_def_flags(def).explicit_layout() {
quote! {
#features
impl ::core::clone::Clone for #name {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
#[derive(Default)]
pub struct FieldAttributes(pub usize);

#[derive(Default)]
pub struct MethodAttributes(pub usize);

#[derive(Default)]
pub struct MethodImplAttributes(pub usize);

#[derive(Default)]
pub struct ParamAttributes(pub usize);

#[derive(Default)]
pub struct PInvokeAttributes(pub usize);

#[derive(Default)]
pub struct TypeAttributes(pub usize);

impl FieldAttributes {
Expand All @@ -27,9 +38,11 @@ impl ParamAttributes {
pub fn input(&self) -> bool {
self.0 & 0x1 != 0
}

pub fn output(&self) -> bool {
self.0 & 0x2 != 0
}

pub fn optional(&self) -> bool {
self.0 & 0x10 != 0
}
Expand All @@ -42,13 +55,38 @@ impl PInvokeAttributes {
}

impl TypeAttributes {
pub fn union(&self) -> bool {
pub fn public(&self) -> bool {
self.0 & 0x1 != 0
}
pub fn set_public(&mut self) {
self.0 |= 0x1;
}

pub fn explicit_layout(&self) -> bool {
self.0 & 0x10 != 0
}
pub fn set_explicit_layout(&mut self) {
self.0 |= 0x10;
}

pub fn get_abstract(&self) -> bool {
self.0 & 0x80 != 0
}
pub fn set_abstract(&mut self) {
self.0 |= 0x80;
}

pub fn winrt(&self) -> bool {
self.0 & 0x4000 != 0
}
pub fn set_winrt(&mut self) {
self.0 |= 0x4000;
}

pub fn interface(&self) -> bool {
self.0 & 0x20 != 0
}
pub fn set_interface(&mut self) {
self.0 |= 0x20
}
}
45 changes: 45 additions & 0 deletions crates/libs/metadata/src/imp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#[repr(C)]
#[derive(Default)]
pub struct METADATA_HEADER {
pub signature: u32,
pub major_version: u16,
pub minor_version: u16,
pub reserved: u32,
pub length: u32,
pub version: [u8; 20],
pub flags: u16,
pub streams: u16,
}

pub const METADATA_SIGNATURE: u32 = 0x424A_5342;

extern "C" {
pub fn strlen(cs: *const u8) -> usize;
}

pub fn composite_index_size(tables: &[usize]) -> usize {
fn small(row_count: usize, bits: u8) -> bool {
(row_count as u64) < (1u64 << (16 - bits))
}

fn bits_needed(value: usize) -> u8 {
let mut value = value - 1;
let mut bits: u8 = 1;
loop {
value >>= 1;
if value == 0 {
break;
}
bits += 1;
}
bits
}

let bits_needed = bits_needed(tables.len());

if tables.iter().all(|table| small(*table, bits_needed)) {
2
} else {
4
}
}
50 changes: 4 additions & 46 deletions crates/libs/metadata/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,55 +1,13 @@
#![allow(dead_code)]

use std::collections::*;
mod flags;
mod imp;
pub mod reader;
pub mod writer;

pub use flags::*;
use imp::*;
use std::io::*;
use std::mem::*;
use std::ptr::*;

#[repr(C)]
#[derive(Default)]
struct METADATA_HEADER {
signature: u32,
major_version: u16,
minor_version: u16,
reserved: u32,
length: u32,
version: [u8; 20],
flags: u16,
streams: u16,
}

const METADATA_SIGNATURE: u32 = 0x424A_5342;

extern "C" {
fn strlen(cs: *const u8) -> usize;
}

fn composite_index_size(tables: &[usize]) -> usize {
fn small(row_count: usize, bits: u8) -> bool {
(row_count as u64) < (1u64 << (16 - bits))
}

fn bits_needed(value: usize) -> u8 {
let mut value = value - 1;
let mut bits: u8 = 1;
loop {
value >>= 1;
if value == 0 {
break;
}
bits += 1;
}
bits
}

let bits_needed = bits_needed(tables.len());

if tables.iter().all(|table| small(*table, bits_needed)) {
2
} else {
4
}
}
20 changes: 9 additions & 11 deletions crates/libs/metadata/src/reader/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
mod blob;
mod codes;
mod file;
mod flags;
mod guid;
mod row;
mod tree;
Expand All @@ -12,7 +11,6 @@ use super::*;
pub use blob::*;
pub use codes::*;
pub use file::*;
pub use flags::*;
pub use guid::*;
pub use r#type::*;
pub use row::*;
Expand Down Expand Up @@ -94,7 +92,7 @@ pub enum AsyncKind {
OperationWithProgress,
}

#[derive(PartialEq, Eq)]
#[derive(PartialEq, Eq, Debug)]
pub enum TypeKind {
Interface,
Class,
Expand Down Expand Up @@ -589,7 +587,7 @@ impl<'a> Reader<'a> {
}
fn type_def_size(reader: &Reader, def: TypeDef) -> usize {
if reader.type_def_kind(def) == TypeKind::Struct {
if reader.type_def_flags(def).union() {
if reader.type_def_flags(def).explicit_layout() {
reader.type_def_fields(def).map(|field| type_size(reader, &reader.field_type(field, Some(def)))).max().unwrap_or(1)
} else {
reader.type_def_fields(def).fold(0, |sum, field| sum + type_size(reader, &reader.field_type(field, Some(def))))
Expand Down Expand Up @@ -721,7 +719,7 @@ impl<'a> Reader<'a> {
}
pub fn type_def_stdcall(&self, row: TypeDef) -> usize {
if self.type_def_kind(row) == TypeKind::Struct {
if self.type_def_flags(row).union() {
if self.type_def_flags(row).explicit_layout() {
self.type_def_fields(row).map(|field| self.type_stdcall(&self.field_type(field, Some(row)))).max().unwrap_or(1)
} else {
self.type_def_fields(row).fold(0, |sum, field| sum + self.type_stdcall(&self.field_type(field, Some(row))))
Expand Down Expand Up @@ -806,15 +804,15 @@ impl<'a> Reader<'a> {
_ => false,
}
}
pub fn type_def_has_union(&self, row: TypeDef) -> bool {
pub fn type_def_has_explicit_layout(&self, row: TypeDef) -> bool {
if self.type_def_kind(row) != TypeKind::Struct {
return false;
}
fn check(reader: &Reader, row: TypeDef) -> bool {
if reader.type_def_flags(row).union() {
if reader.type_def_flags(row).explicit_layout() {
return true;
}
if reader.type_def_fields(row).any(|field| reader.type_has_union(&reader.field_type(field, Some(row)))) {
if reader.type_def_fields(row).any(|field| reader.type_has_explicit_layout(&reader.field_type(field, Some(row)))) {
return true;
}
false
Expand Down Expand Up @@ -1357,10 +1355,10 @@ impl<'a> Reader<'a> {
_ => true,
}
}
pub fn type_has_union(&self, ty: &Type) -> bool {
pub fn type_has_explicit_layout(&self, ty: &Type) -> bool {
match ty {
Type::TypeDef((row, _)) => self.type_def_has_union(*row),
Type::Win32Array((ty, _)) => self.type_has_union(ty),
Type::TypeDef((row, _)) => self.type_def_has_explicit_layout(*row),
Type::Win32Array((ty, _)) => self.type_has_explicit_layout(ty),
_ => false,
}
}
Expand Down
51 changes: 51 additions & 0 deletions crates/libs/metadata/src/writer/codes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#[derive(Clone, Copy)]
pub enum ResolutionScope {
None,
Module(usize),
ModuleRef(usize),
AssemblyRef(usize),
TypeRef(usize),
}

impl ResolutionScope {
pub fn encode(&self) -> usize {
match self {
Self::Module(row) => ((row + 1) << 2),
Self::ModuleRef(row) => ((row + 1) << 2) + 1,
Self::AssemblyRef(row) => ((row + 1) << 2) + 2,
Self::TypeRef(row) => ((row + 1) << 2) + 3,
_ => unimplemented!(),
}
}
}

impl Default for ResolutionScope {
fn default() -> Self {
Self::None
}
}

#[derive(Clone, Copy)]
pub enum TypeDefOrRef {
None,
TypeDef(usize),
TypeRef(usize),
TypeSpec(usize),
}

impl TypeDefOrRef {
pub fn encode(&self) -> usize {
match self {
Self::TypeDef(row) => ((row + 1) << 2),
Self::TypeRef(row) => ((row + 1) << 2) + 1,
Self::TypeSpec(row) => ((row + 1) << 2) + 2,
_ => 0,
}
}
}

impl Default for TypeDefOrRef {
fn default() -> Self {
Self::None
}
}
28 changes: 8 additions & 20 deletions crates/libs/metadata/src/writer/mod.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
mod blobs;
mod codes;
mod gen;
mod helpers;
mod pe;
pub mod pe;
mod strings;
mod tables;
use blobs::*;
mod type_name;

use super::*;
use blobs::*;
use codes::*;
pub use gen::*;
use helpers::*;
pub use helpers::*;
use strings::*;
use tables::*;

pub fn test() {
let mut tables = Tables::new();
tables.module.push(Module::new("test.winmd"));
tables.type_def.push(TypeDef::module());

let mut stringable = TypeDef::winrt_interface("IStringable", "Windows.Foundation");
stringable.method_list.push(MethodDef::new("ToString"));
tables.type_def.push(stringable);

let mut closable = TypeDef::winrt_interface("IClosable", "Windows.Foundation");
closable.method_list.push(MethodDef::new("Close"));
tables.type_def.push(closable);

pe::write("/git/test.winmd", tables);
}
pub use tables::*;
pub use type_name::*;
Loading

0 comments on commit d3eee4a

Please sign in to comment.