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

Update Vector Operations #940

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
126 changes: 123 additions & 3 deletions c2rust-ast-builder/src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! Helpers for building AST nodes. Normally used by calling `mk().some_node(args...)`.

use std::str;
use std::{
iter::{once, repeat},
str,
};

use proc_macro2::{Span, TokenStream, TokenTree};
use std::default::Default;
Expand Down Expand Up @@ -1693,14 +1696,69 @@ impl Builder {
}))
}

// `use <path>;` item
pub fn use_simple_item_rename<Pa, I, Ip, RIt>(self, path: Pa, rename: Option<Ip>) -> Box<Item>
where
Pa: Make<Path>,
I: Make<Ident>,
Ip: Into<(I, RIt)>,
RIt: Iterator<Item = I>,
{
let path = path.make(&self);

fn split_path(mut p: Path) -> (Path, Option<Ident>) {
if let Some(punct) = p.segments.pop() {
(p, Some(punct.into_value().ident))
} else {
(p, None)
}
}
let leading_colon = path.leading_colon;
let (prefix, ident) = split_path(path);
let ident = ident.expect("use_simple_item called with path `::`");

let inner_trees = if let Some(rename) = rename {
let (rename_ident, renames) = rename.into();
let rename_ident = rename_ident.make(&self);

once(UseTree::Name(UseName { ident }))
.chain(repeat(rename_ident).zip(renames).map(|(ident, rename)| {
UseTree::Rename(UseRename {
ident,
as_token: Token![as](self.span),
rename: rename.make(&self),
})
}))
.collect()
} else {
once(UseTree::Name(UseName { ident })).collect()
};

let tree = use_tree_with_prefix(
prefix,
UseTree::Group(UseGroup {
brace_token: token::Brace(self.span),
items: inner_trees,
}),
);

Box::new(Item::Use(ItemUse {
attrs: self.attrs,
vis: self.vis,
use_token: Token![use](self.span),
leading_colon,
semi_token: Token![;](self.span),
tree,
}))
}

// `use <path>;` item
pub fn use_simple_item<Pa, I>(self, path: Pa, rename: Option<I>) -> Box<Item>
where
Pa: Make<Path>,
I: Make<Ident>,
{
let path = path.make(&self);
let rename = rename.map(|n| n.make(&self));

fn split_path(mut p: Path) -> (Path, Option<Ident>) {
if let Some(punct) = p.segments.pop() {
Expand All @@ -1712,18 +1770,20 @@ impl Builder {
let leading_colon = path.leading_colon;
let (prefix, ident) = split_path(path);
let ident = ident.expect("use_simple_item called with path `::`");

let tree = if let Some(rename) = rename {
use_tree_with_prefix(
prefix,
UseTree::Rename(UseRename {
ident,
as_token: Token![as](self.span),
rename,
rename: rename.make(&self),
}),
)
} else {
use_tree_with_prefix(prefix, UseTree::Name(UseName { ident }))
};

Box::new(Item::Use(ItemUse {
attrs: self.attrs,
vis: self.vis,
Expand Down Expand Up @@ -1766,6 +1826,56 @@ impl Builder {
}))
}

pub fn use_multiple_item_rename<Pa, I, Ip, It, RIt>(
self,
path: Pa,
inner: It,
rename: RIt,
) -> Box<Item>
where
Pa: Make<Path>,
I: Make<Ident>,
Ip: Into<(I, It)>,
It: Iterator<Item = I>,
RIt: Iterator<Item = Ip>,
{
let path = path.make(&self);
let inner_trees = inner
.map(|i| {
UseTree::Name(UseName {
ident: i.make(&self),
})
})
.chain(rename.flat_map(|ip| {
let (ident, renames) = ip.into();
let ident = ident.make(&self);
repeat(ident).zip(renames).map(|(ident, rename)| {
UseTree::Rename(UseRename {
ident: ident.make(&self),
as_token: Token![as](self.span),
rename: rename.make(&self),
})
})
}))
.collect();
let leading_colon = path.leading_colon;
let tree = use_tree_with_prefix(
path,
UseTree::Group(UseGroup {
brace_token: token::Brace(self.span),
items: inner_trees,
}),
);
Box::new(Item::Use(ItemUse {
attrs: self.attrs,
vis: self.vis,
use_token: Token![use](self.span),
leading_colon,
semi_token: Token![;](self.span),
tree,
}))
}

pub fn use_glob_item<Pa>(self, path: Pa) -> Box<Item>
where
Pa: Make<Path>,
Expand Down Expand Up @@ -1916,6 +2026,16 @@ impl Builder {
}
}

pub fn struct_field_anon(self, ty: Box<Type>) -> Field {
Field {
ident: None,
vis: self.vis,
attrs: self.attrs,
ty: *ty,
colon_token: None,
}
}

pub fn enum_field(self, ty: Box<Type>) -> Field {
Field {
ident: None,
Expand Down
69 changes: 65 additions & 4 deletions c2rust-transpile/src/rust_ast/item_store.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use c2rust_ast_builder::{mk, Builder};
use indexmap::{IndexMap, IndexSet};
use syn::{ForeignItem, Ident, Item};
use syn::{ForeignItem, Item};

use std::borrow::Cow;
use std::mem::swap;
Expand All @@ -9,13 +9,15 @@ use std::mem::swap;
pub struct MultiImport {
attrs: Option<Builder>,
leaves: IndexSet<String>,
renames: IndexMap<String, IndexSet<String>>,
}

impl MultiImport {
fn new() -> Self {
MultiImport {
attrs: None,
leaves: IndexSet::new(),
renames: IndexMap::new(),
}
}

Expand All @@ -33,6 +35,35 @@ impl MultiImport {
self.insert(leaf);
self.attrs = Some(attrs);
}

pub fn insert_with_rename<'a, S>(&mut self, leaf: S, rename: S)
where
S: Into<Cow<'a, str>>,
{
let leaf: String = leaf.into().into_owned();
let rename: String = rename.into().into_owned();
if let Some(renames) = self.renames.get_mut(&leaf) {
renames.insert(rename);
} else {
let mut set = IndexSet::new();
set.insert(rename);
self.renames.insert(leaf.clone(), set);
};

self.insert(leaf);
}

pub fn insert_with_attr_rename<'a, S>(&mut self, leaf: S, attrs: Builder, rename: S)
where
S: Into<Cow<'a, str>>,
{
self.insert_with_rename(leaf, rename);
self.attrs = Some(attrs);
}

pub fn insert_attrs(&mut self, attrs: Builder) {
self.attrs = Some(attrs);
}
}

#[derive(Debug, Default)]
Expand All @@ -53,11 +84,25 @@ impl PathedMultiImports {
let attrs = imports.attrs.unwrap_or_else(mk);

if leaves.len() == 1 {
path.push(leaves.pop().unwrap());
let leaf = leaves.pop().unwrap();
path.push(leaf.clone());

attrs.use_simple_item(path, None as Option<Ident>)
let renames = imports
.renames
.get(&leaf)
.map(|r| Some((leaf.clone(), r.clone().into_iter())))
.unwrap_or(None);

attrs.use_simple_item_rename(path, renames)
} else {
attrs.use_multiple_item(path, leaves.into_iter())
attrs.use_multiple_item_rename(
path,
leaves.into_iter(),
imports
.renames
.iter()
.map(|(leaf, renames)| (leaf.clone(), renames.clone().into_iter())),
)
}
}

Expand Down Expand Up @@ -95,6 +140,22 @@ impl ItemStore {
self.uses.get_mut(path).insert_with_attr(ident, attrs)
}

pub fn add_use_with_rename(&mut self, path: Vec<String>, ident: &str, rename: &str) {
self.uses.get_mut(path).insert_with_rename(ident, rename)
}

pub fn add_use_with_attr_rename(
&mut self,
path: Vec<String>,
ident: &str,
attrs: Builder,
rename: &str,
) {
self.uses
.get_mut(path)
.insert_with_attr_rename(ident, attrs, rename)
}

pub fn drain(&mut self) -> (Vec<Box<Item>>, Vec<ForeignItem>, PathedMultiImports) {
let mut items = Vec::new();
let mut foreign_items = Vec::new();
Expand Down
13 changes: 13 additions & 0 deletions c2rust-transpile/src/translator/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,19 @@ impl<'c> Translation<'c> {
"__builtin_ia32_pcmpestris128" => self.convert_simd_builtin(ctx, "_mm_cmpestrs", args),
"__builtin_ia32_pcmpestriz128" => self.convert_simd_builtin(ctx, "_mm_cmpestrz", args),

"__builtin_ia32_vcvtph2ps" => self.convert_simd_builtin(ctx, "_mm_cvtph_ps", args),
"__builtin_ia32_vcvtps2ph256" => {
self.convert_simd_builtin(ctx, "_mm256_cvtps_ph", args)
}
"__builtin_ia32_vextractf128_ps256" => {
self.convert_simd_builtin(ctx, "_mm256_extractf128_ps", args)
}
"__builtin_ia32_vextractf128_si256" => {
self.convert_simd_builtin(ctx, "_mm256_extractf128_ps", args)
}
"__builtin_ia32_roundps256" => self.convert_simd_builtin(ctx, "_mm256_round_ps", args),
"__builtin_ia32_vcvtps2ph" => self.convert_simd_builtin(ctx, "_mm_cvtps_ph", args),

"__sync_val_compare_and_swap_1"
| "__sync_val_compare_and_swap_2"
| "__sync_val_compare_and_swap_4"
Expand Down
52 changes: 36 additions & 16 deletions c2rust-transpile/src/translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3595,22 +3595,6 @@ impl<'c> Translation<'c> {
(rhs, lhs, rhs_node)
};

let lhs_node_type = lhs_node
.get_type()
.ok_or_else(|| format_err!("lhs node bad type"))?;
if self
.ast_context
.resolve_type(lhs_node_type)
.kind
.is_vector()
{
return Err(TranslationError::new(
self.ast_context.display_loc(src_loc),
err_msg("Attempting to index a vector type")
.context(TranslationErrorKind::OldLLVMSimd),
));
}

let rhs = self.convert_expr(ctx.used(), *rhs)?;
rhs.and_then(|rhs| {
let simple_index_array = if ctx.needs_address() {
Expand Down Expand Up @@ -3680,6 +3664,40 @@ impl<'c> Translation<'c> {
mk().index_expr(lhs, cast_int(rhs, "usize", false))
}
}))
} else if lhs_node_kind.is_vector() {
// LHS is a vector type, we just need to do a transmute to an array and
// take the type
match lhs_node_kind {
CTypeKind::Vector(vkind, _vsize) => {
let vector_kind_size_of =
self.compute_size_of_type(ctx, vkind.ctype)?;
let vector_ty = self.convert_type(vkind.ctype)?;

let lhs = self.convert_expr(ctx.used(), *lhs)?;
let lhs_type = lhs_node
.get_type()
.ok_or_else(|| format_err!("bad lhs type"))?;
let lhs_type_size_of = self.compute_size_of_type(ctx, lhs_type)?;

Ok(lhs.map(|lhs| {
// Array size is vector_kind_size (e.g. size_of::<__mm256>()) / element size (e.g. size_of::<u16>())
let array_ty = mk().array_ty(
vector_ty,
mk().binary_expr(
BinOp::Div(Default::default()),
// mk().lit_expr(mk().int_lit(*size as u128, "usize")),
lhs_type_size_of.to_expr(),
vector_kind_size_of.to_expr(),
),
);
mk().unsafe_().index_expr(
transmute_expr(mk().infer_ty(), array_ty, lhs),
cast_int(rhs, "usize", false),
)
}))
}
_ => unreachable!(),
}
} else {
// LHS must be ref decayed for the offset method call's self param
let lhs = self.convert_expr(ctx.used().decay_ref(), *lhs)?;
Expand Down Expand Up @@ -3720,6 +3738,7 @@ impl<'c> Translation<'c> {
})?,
)
.map(|ty| &self.ast_context.resolve_type(ty.ctype).kind);

let is_variadic = match fn_ty {
Some(CTypeKind::Function(_, _, is_variadic, _, _)) => *is_variadic,
_ => false,
Expand All @@ -3739,6 +3758,7 @@ impl<'c> Translation<'c> {
return self.convert_builtin(ctx, fexp, args);
}


// Function pointer call
_ => {
let callee = self.convert_expr(ctx.used(), func)?;
Expand Down
Loading