mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-07-31 13:28:38 +00:00
Implement not, or, and, bra
This commit is contained in:
parent
c08e6a6772
commit
22492ec7f1
5 changed files with 316 additions and 119 deletions
|
@ -231,7 +231,8 @@ impl SingleOpcodeDefinition {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_and_insert(
|
fn extract_and_insert(
|
||||||
output: &mut FxHashMap<Ident, Vec<SingleOpcodeDefinition>>,
|
definitions: &mut FxHashMap<Ident, Vec<SingleOpcodeDefinition>>,
|
||||||
|
special_definitions: &mut FxHashMap<Ident, proc_macro2::Group>,
|
||||||
parser::OpcodeDefinition(pattern_seq, rules): parser::OpcodeDefinition,
|
parser::OpcodeDefinition(pattern_seq, rules): parser::OpcodeDefinition,
|
||||||
) {
|
) {
|
||||||
let (mut named_rules, mut unnamed_rules) = gather_rules(rules);
|
let (mut named_rules, mut unnamed_rules) = gather_rules(rules);
|
||||||
|
@ -242,8 +243,18 @@ impl SingleOpcodeDefinition {
|
||||||
named_rules = FxHashMap::default();
|
named_rules = FxHashMap::default();
|
||||||
unnamed_rules = FxHashMap::default();
|
unnamed_rules = FxHashMap::default();
|
||||||
}
|
}
|
||||||
let mut possible_modifiers = FxHashSet::default();
|
|
||||||
let parser::OpcodeDecl(instruction, arguments) = opcode_decl;
|
let parser::OpcodeDecl(instruction, arguments) = opcode_decl;
|
||||||
|
if code_block.special {
|
||||||
|
if !instruction.modifiers.is_empty() || !arguments.0.is_empty() {
|
||||||
|
panic!(
|
||||||
|
"`{}`: no modifiers or arguments are allowed in parser definition.",
|
||||||
|
instruction.name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
special_definitions.insert(instruction.name, code_block.code);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut possible_modifiers = FxHashSet::default();
|
||||||
let mut unordered_modifiers = instruction
|
let mut unordered_modifiers = instruction
|
||||||
.modifiers
|
.modifiers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -287,7 +298,7 @@ impl SingleOpcodeDefinition {
|
||||||
arguments,
|
arguments,
|
||||||
code_block,
|
code_block,
|
||||||
};
|
};
|
||||||
multihash_extend(output, current_opcode.clone(), entry);
|
multihash_extend(definitions, current_opcode.clone(), entry);
|
||||||
last_opcode = current_opcode;
|
last_opcode = current_opcode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -350,10 +361,15 @@ fn gather_rules(
|
||||||
pub fn derive_parser(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn derive_parser(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
let parse_definitions = parse_macro_input!(tokens as gen_impl::parser::ParseDefinitions);
|
let parse_definitions = parse_macro_input!(tokens as gen_impl::parser::ParseDefinitions);
|
||||||
let mut definitions = FxHashMap::default();
|
let mut definitions = FxHashMap::default();
|
||||||
|
let mut special_definitions = FxHashMap::default();
|
||||||
let types = OpcodeDefinitions::get_enum_types(&parse_definitions.definitions);
|
let types = OpcodeDefinitions::get_enum_types(&parse_definitions.definitions);
|
||||||
let enum_types_tokens = emit_enum_types(types, parse_definitions.additional_enums);
|
let enum_types_tokens = emit_enum_types(types, parse_definitions.additional_enums);
|
||||||
for definition in parse_definitions.definitions.into_iter() {
|
for definition in parse_definitions.definitions.into_iter() {
|
||||||
SingleOpcodeDefinition::extract_and_insert(&mut definitions, definition);
|
SingleOpcodeDefinition::extract_and_insert(
|
||||||
|
&mut definitions,
|
||||||
|
&mut special_definitions,
|
||||||
|
definition,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let definitions = definitions
|
let definitions = definitions
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -363,9 +379,12 @@ pub fn derive_parser(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream
|
||||||
})
|
})
|
||||||
.collect::<FxHashMap<_, _>>();
|
.collect::<FxHashMap<_, _>>();
|
||||||
let mut token_enum = parse_definitions.token_type;
|
let mut token_enum = parse_definitions.token_type;
|
||||||
let (all_opcode, all_modifier) =
|
let (all_opcode, all_modifier) = write_definitions_into_tokens(
|
||||||
write_definitions_into_tokens(&definitions, &mut token_enum.variants);
|
&definitions,
|
||||||
let token_impl = emit_parse_function(&token_enum.ident, &definitions, all_opcode, all_modifier);
|
special_definitions.keys(),
|
||||||
|
&mut token_enum.variants,
|
||||||
|
);
|
||||||
|
let token_impl = emit_parse_function(&token_enum.ident, &definitions, &special_definitions, all_opcode, all_modifier);
|
||||||
let tokens = quote! {
|
let tokens = quote! {
|
||||||
#enum_types_tokens
|
#enum_types_tokens
|
||||||
|
|
||||||
|
@ -422,6 +441,7 @@ fn emit_enum_types(
|
||||||
fn emit_parse_function(
|
fn emit_parse_function(
|
||||||
type_name: &Ident,
|
type_name: &Ident,
|
||||||
defs: &FxHashMap<Ident, OpcodeDefinitions>,
|
defs: &FxHashMap<Ident, OpcodeDefinitions>,
|
||||||
|
special_defs: &FxHashMap<Ident, proc_macro2::Group>,
|
||||||
all_opcode: Vec<&Ident>,
|
all_opcode: Vec<&Ident>,
|
||||||
all_modifier: FxHashSet<&parser::DotModifier>,
|
all_modifier: FxHashSet<&parser::DotModifier>,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
|
@ -433,7 +453,7 @@ fn emit_parse_function(
|
||||||
let mut fn_name = opcode.to_string();
|
let mut fn_name = opcode.to_string();
|
||||||
write!(&mut fn_name, "_{}", idx).ok();
|
write!(&mut fn_name, "_{}", idx).ok();
|
||||||
let fn_name = Ident::new(&fn_name, Span::call_site());
|
let fn_name = Ident::new(&fn_name, Span::call_site());
|
||||||
let code_block = &def.code_block.0;
|
let code_block = &def.code_block.code;
|
||||||
let args = def.function_arguments_declarations();
|
let args = def.function_arguments_declarations();
|
||||||
quote! {
|
quote! {
|
||||||
fn #fn_name<'input>(state: &mut PtxParserState, #(#args),* ) -> Instruction<ParsedOperandStr<'input>> #code_block
|
fn #fn_name<'input>(state: &mut PtxParserState, #(#args),* ) -> Instruction<ParsedOperandStr<'input>> #code_block
|
||||||
|
@ -494,7 +514,12 @@ fn emit_parse_function(
|
||||||
}
|
}
|
||||||
.to_tokens(&mut result);
|
.to_tokens(&mut result);
|
||||||
result
|
result
|
||||||
});
|
}).chain(special_defs.iter().map(|(opcode, code)| {
|
||||||
|
let opcode_variant = Ident::new(&capitalize(&opcode.to_string()), opcode.span());
|
||||||
|
quote! {
|
||||||
|
#opcode_variant => { #code? }
|
||||||
|
}
|
||||||
|
}));
|
||||||
let opcodes = all_opcode.into_iter().map(|op_ident| {
|
let opcodes = all_opcode.into_iter().map(|op_ident| {
|
||||||
let op = op_ident.to_string();
|
let op = op_ident.to_string();
|
||||||
let variant = Ident::new(&capitalize(&op), op_ident.span());
|
let variant = Ident::new(&capitalize(&op), op_ident.span());
|
||||||
|
@ -749,7 +774,7 @@ fn emit_definition_parser(
|
||||||
};
|
};
|
||||||
let pre_pipe = if arg.pre_pipe {
|
let pre_pipe = if arg.pre_pipe {
|
||||||
quote! {
|
quote! {
|
||||||
any.verify(|t| *t == #token_type::Or).void()
|
any.verify(|t| *t == #token_type::Pipe).void()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quote! {
|
quote! {
|
||||||
|
@ -845,6 +870,7 @@ fn emit_definition_parser(
|
||||||
|
|
||||||
fn write_definitions_into_tokens<'a>(
|
fn write_definitions_into_tokens<'a>(
|
||||||
defs: &'a FxHashMap<Ident, OpcodeDefinitions>,
|
defs: &'a FxHashMap<Ident, OpcodeDefinitions>,
|
||||||
|
special_definitions: impl Iterator<Item = &'a Ident>,
|
||||||
variants: &mut Punctuated<Variant, Token![,]>,
|
variants: &mut Punctuated<Variant, Token![,]>,
|
||||||
) -> (Vec<&'a Ident>, FxHashSet<&'a parser::DotModifier>) {
|
) -> (Vec<&'a Ident>, FxHashSet<&'a parser::DotModifier>) {
|
||||||
let mut all_opcodes = Vec::new();
|
let mut all_opcodes = Vec::new();
|
||||||
|
@ -864,6 +890,16 @@ fn write_definitions_into_tokens<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for opcode in special_definitions {
|
||||||
|
all_opcodes.push(opcode);
|
||||||
|
let opcode_as_string = opcode.to_string();
|
||||||
|
let variant_name = Ident::new(&capitalize(&opcode_as_string), opcode.span());
|
||||||
|
let arg: Variant = syn::parse_quote! {
|
||||||
|
#[token(#opcode_as_string)]
|
||||||
|
#variant_name
|
||||||
|
};
|
||||||
|
variants.push(arg);
|
||||||
|
}
|
||||||
for modifier in all_modifiers.iter() {
|
for modifier in all_modifiers.iter() {
|
||||||
let modifier_as_string = modifier.to_string();
|
let modifier_as_string = modifier.to_string();
|
||||||
let variant_name = modifier.dot_capitalized();
|
let variant_name = modifier.dot_capitalized();
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{format_ident, quote, ToTokens};
|
use quote::{format_ident, quote, ToTokens};
|
||||||
use syn::{
|
use syn::{
|
||||||
braced, parse::Parse, punctuated::Punctuated, token, Expr, Ident, Token, Type, TypeParam,
|
braced, parse::Parse, punctuated::Punctuated, token, Expr, Ident, PathSegment, Token, Type,
|
||||||
Visibility,
|
TypeParam, Visibility,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
@ -18,7 +18,7 @@ pub struct GenerateInstructionType {
|
||||||
impl GenerateInstructionType {
|
impl GenerateInstructionType {
|
||||||
pub fn emit_arg_types(&self, tokens: &mut TokenStream) {
|
pub fn emit_arg_types(&self, tokens: &mut TokenStream) {
|
||||||
for v in self.variants.iter() {
|
for v in self.variants.iter() {
|
||||||
v.emit_type(&self.visibility, &self.type_parameters, tokens);
|
v.emit_type(&self.visibility, tokens);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ impl Parse for GenerateInstructionType {
|
||||||
|
|
||||||
pub struct InstructionVariant {
|
pub struct InstructionVariant {
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
pub type_: Option<Expr>,
|
pub type_: Option<Option<Expr>>,
|
||||||
pub space: Option<Expr>,
|
pub space: Option<Expr>,
|
||||||
pub data: Option<Type>,
|
pub data: Option<Type>,
|
||||||
pub arguments: Option<InstructionArguments>,
|
pub arguments: Option<InstructionArguments>,
|
||||||
|
@ -225,7 +225,7 @@ impl InstructionVariant {
|
||||||
&self,
|
&self,
|
||||||
enum_: &Ident,
|
enum_: &Ident,
|
||||||
tokens: &mut TokenStream,
|
tokens: &mut TokenStream,
|
||||||
mut fn_: impl FnMut(&InstructionArguments, &Option<Expr>, &Option<Expr>) -> TokenStream,
|
mut fn_: impl FnMut(&InstructionArguments, &Option<Option<Expr>>, &Option<Expr>) -> TokenStream,
|
||||||
) {
|
) {
|
||||||
let name = &self.name;
|
let name = &self.name;
|
||||||
let arguments = match &self.arguments {
|
let arguments = match &self.arguments {
|
||||||
|
@ -238,9 +238,10 @@ impl InstructionVariant {
|
||||||
}
|
}
|
||||||
Some(args) => args,
|
Some(args) => args,
|
||||||
};
|
};
|
||||||
|
let data = &self.data.as_ref().map(|_| quote! { data,});
|
||||||
let arg_calls = fn_(arguments, &self.type_, &self.space);
|
let arg_calls = fn_(arguments, &self.type_, &self.space);
|
||||||
quote! {
|
quote! {
|
||||||
#enum_ :: #name { arguments, data } => {
|
#enum_ :: #name { #data arguments } => {
|
||||||
#arg_calls
|
#arg_calls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -269,19 +270,14 @@ impl InstructionVariant {
|
||||||
.to_tokens(tokens);
|
.to_tokens(tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_type(
|
fn emit_type(&self, vis: &Option<Visibility>, tokens: &mut TokenStream) {
|
||||||
&self,
|
|
||||||
vis: &Option<Visibility>,
|
|
||||||
type_parameters: &Punctuated<TypeParam, Token![,]>,
|
|
||||||
tokens: &mut TokenStream,
|
|
||||||
) {
|
|
||||||
let arguments = match self.arguments {
|
let arguments = match self.arguments {
|
||||||
Some(ref a) => a,
|
Some(ref a) => a,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
let name = self.args_name();
|
let name = self.args_name();
|
||||||
let type_parameters = if arguments.generic.is_some() {
|
let type_parameters = if arguments.generic.is_some() {
|
||||||
Some(quote! { <#type_parameters> })
|
Some(quote! { <T> })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -324,7 +320,7 @@ impl Parse for InstructionVariant {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum VariantProperty {
|
enum VariantProperty {
|
||||||
Type(Expr),
|
Type(Option<Expr>),
|
||||||
Space(Expr),
|
Space(Expr),
|
||||||
Data(Type),
|
Data(Type),
|
||||||
Arguments(InstructionArguments),
|
Arguments(InstructionArguments),
|
||||||
|
@ -336,7 +332,12 @@ impl VariantProperty {
|
||||||
Ok(if lookahead.peek(Token![type]) {
|
Ok(if lookahead.peek(Token![type]) {
|
||||||
input.parse::<Token![type]>()?;
|
input.parse::<Token![type]>()?;
|
||||||
input.parse::<Token![:]>()?;
|
input.parse::<Token![:]>()?;
|
||||||
VariantProperty::Type(input.parse::<Expr>()?)
|
VariantProperty::Type(if input.peek(Token![!]) {
|
||||||
|
input.parse::<Token![!]>()?;
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(input.parse::<Expr>()?)
|
||||||
|
})
|
||||||
} else if lookahead.peek(Ident) {
|
} else if lookahead.peek(Ident) {
|
||||||
let key = input.parse::<Ident>()?;
|
let key = input.parse::<Ident>()?;
|
||||||
match &*key.to_string() {
|
match &*key.to_string() {
|
||||||
|
@ -352,7 +353,7 @@ impl VariantProperty {
|
||||||
let generics = if input.peek(Token![<]) {
|
let generics = if input.peek(Token![<]) {
|
||||||
input.parse::<Token![<]>()?;
|
input.parse::<Token![<]>()?;
|
||||||
let gen_params =
|
let gen_params =
|
||||||
Punctuated::<TypeParam, Token![,]>::parse_separated_nonempty(input)?;
|
Punctuated::<PathSegment, syn::token::PathSep>::parse_separated_nonempty(input)?;
|
||||||
input.parse::<Token![>]>()?;
|
input.parse::<Token![>]>()?;
|
||||||
Some(gen_params)
|
Some(gen_params)
|
||||||
} else {
|
} else {
|
||||||
|
@ -380,13 +381,13 @@ impl VariantProperty {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InstructionArguments {
|
pub struct InstructionArguments {
|
||||||
pub generic: Option<Punctuated<TypeParam, Token![,]>>,
|
pub generic: Option<Punctuated<PathSegment, syn::token::PathSep>>,
|
||||||
pub fields: Punctuated<ArgumentField, Token![,]>,
|
pub fields: Punctuated<ArgumentField, Token![,]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstructionArguments {
|
impl InstructionArguments {
|
||||||
pub fn parse(
|
pub fn parse(
|
||||||
generic: Option<Punctuated<TypeParam, Token![,]>>,
|
generic: Option<Punctuated<PathSegment, syn::token::PathSep>>,
|
||||||
input: syn::parse::ParseStream,
|
input: syn::parse::ParseStream,
|
||||||
) -> syn::Result<Self> {
|
) -> syn::Result<Self> {
|
||||||
let fields = Punctuated::<ArgumentField, Token![,]>::parse_terminated_with(
|
let fields = Punctuated::<ArgumentField, Token![,]>::parse_terminated_with(
|
||||||
|
@ -396,13 +397,17 @@ impl InstructionArguments {
|
||||||
Ok(Self { generic, fields })
|
Ok(Self { generic, fields })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_visit(&self, parent_type: &Option<Expr>, parent_space: &Option<Expr>) -> TokenStream {
|
fn emit_visit(
|
||||||
|
&self,
|
||||||
|
parent_type: &Option<Option<Expr>>,
|
||||||
|
parent_space: &Option<Expr>,
|
||||||
|
) -> TokenStream {
|
||||||
self.emit_visit_impl(parent_type, parent_space, ArgumentField::emit_visit)
|
self.emit_visit_impl(parent_type, parent_space, ArgumentField::emit_visit)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_visit_mut(
|
fn emit_visit_mut(
|
||||||
&self,
|
&self,
|
||||||
parent_type: &Option<Expr>,
|
parent_type: &Option<Option<Expr>>,
|
||||||
parent_space: &Option<Expr>,
|
parent_space: &Option<Expr>,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
self.emit_visit_impl(parent_type, parent_space, ArgumentField::emit_visit_mut)
|
self.emit_visit_impl(parent_type, parent_space, ArgumentField::emit_visit_mut)
|
||||||
|
@ -410,7 +415,7 @@ impl InstructionArguments {
|
||||||
|
|
||||||
fn emit_visit_map(
|
fn emit_visit_map(
|
||||||
&self,
|
&self,
|
||||||
parent_type: &Option<Expr>,
|
parent_type: &Option<Option<Expr>>,
|
||||||
parent_space: &Option<Expr>,
|
parent_space: &Option<Expr>,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
self.emit_visit_impl(parent_type, parent_space, ArgumentField::emit_visit_map)
|
self.emit_visit_impl(parent_type, parent_space, ArgumentField::emit_visit_map)
|
||||||
|
@ -418,14 +423,19 @@ impl InstructionArguments {
|
||||||
|
|
||||||
fn emit_visit_impl(
|
fn emit_visit_impl(
|
||||||
&self,
|
&self,
|
||||||
parent_type: &Option<Expr>,
|
parent_type: &Option<Option<Expr>>,
|
||||||
parent_space: &Option<Expr>,
|
parent_space: &Option<Expr>,
|
||||||
mut fn_: impl FnMut(&ArgumentField, &Option<Expr>, &Option<Expr>) -> TokenStream,
|
mut fn_: impl FnMut(&ArgumentField, &Option<Option<Expr>>, &Option<Expr>, bool) -> TokenStream,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
|
let is_ident = if let Some(ref generic) = self.generic {
|
||||||
|
generic.len() > 1
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
let field_calls = self
|
let field_calls = self
|
||||||
.fields
|
.fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|f| fn_(f, parent_type, parent_space));
|
.map(|f| fn_(f, parent_type, parent_space, is_ident));
|
||||||
quote! {
|
quote! {
|
||||||
#(#field_calls)*
|
#(#field_calls)*
|
||||||
}
|
}
|
||||||
|
@ -487,25 +497,37 @@ impl ArgumentField {
|
||||||
input.parse::<Type>()
|
input.parse::<Type>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_visit(&self, parent_type: &Option<Expr>, parent_space: &Option<Expr>) -> TokenStream {
|
fn emit_visit(
|
||||||
self.emit_visit_impl(parent_type, parent_space, false)
|
&self,
|
||||||
|
parent_type: &Option<Option<Expr>>,
|
||||||
|
parent_space: &Option<Expr>,
|
||||||
|
is_ident: bool,
|
||||||
|
) -> TokenStream {
|
||||||
|
self.emit_visit_impl(parent_type, parent_space, is_ident, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_visit_mut(
|
fn emit_visit_mut(
|
||||||
&self,
|
&self,
|
||||||
parent_type: &Option<Expr>,
|
parent_type: &Option<Option<Expr>>,
|
||||||
parent_space: &Option<Expr>,
|
parent_space: &Option<Expr>,
|
||||||
|
is_ident: bool,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
self.emit_visit_impl(parent_type, parent_space, true)
|
self.emit_visit_impl(parent_type, parent_space, is_ident, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_visit_impl(
|
fn emit_visit_impl(
|
||||||
&self,
|
&self,
|
||||||
parent_type: &Option<Expr>,
|
parent_type: &Option<Option<Expr>>,
|
||||||
parent_space: &Option<Expr>,
|
parent_space: &Option<Expr>,
|
||||||
|
is_ident: bool,
|
||||||
is_mut: bool,
|
is_mut: bool,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let type_ = self.type_.as_ref().or(parent_type.as_ref()).unwrap();
|
let (is_typeless, type_) = match (self.type_.as_ref(), parent_type) {
|
||||||
|
(Some(type_), _) => (false, Some(type_)),
|
||||||
|
(None, None) => panic!("No type set"),
|
||||||
|
(None, Some(None)) => (true, None),
|
||||||
|
(None, Some(Some(type_))) => (false, Some(type_)),
|
||||||
|
};
|
||||||
let space = self
|
let space = self
|
||||||
.space
|
.space
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -514,38 +536,72 @@ impl ArgumentField {
|
||||||
.unwrap_or_else(|| quote! { StateSpace::Reg });
|
.unwrap_or_else(|| quote! { StateSpace::Reg });
|
||||||
let is_dst = self.is_dst;
|
let is_dst = self.is_dst;
|
||||||
let name = &self.name;
|
let name = &self.name;
|
||||||
let (operand_fn, arguments_name) = if is_mut {
|
let type_space = if is_typeless {
|
||||||
(
|
quote! {
|
||||||
quote! {
|
let type_space = None;
|
||||||
VisitOperand::visit_mut
|
}
|
||||||
},
|
|
||||||
quote! {
|
|
||||||
&mut arguments.#name
|
|
||||||
},
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
(
|
quote! {
|
||||||
quote! {
|
let type_ = #type_;
|
||||||
VisitOperand::visit
|
let space = #space;
|
||||||
},
|
let type_space = Some((std::borrow::Borrow::<Type>::borrow(&type_), space));
|
||||||
quote! {
|
}
|
||||||
& arguments.#name
|
|
||||||
},
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
quote! {{
|
if is_ident {
|
||||||
let type_ = #type_;
|
if is_mut {
|
||||||
let space = #space;
|
quote! {
|
||||||
#operand_fn(#arguments_name, |x| visitor.visit(x, &type_, space, #is_dst));
|
{
|
||||||
}}
|
#type_space
|
||||||
|
visitor.visit_ident(&mut arguments.#name, type_space, #is_dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
{
|
||||||
|
#type_space
|
||||||
|
visitor.visit_ident(& arguments.#name, type_space, #is_dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let (operand_fn, arguments_name) = if is_mut {
|
||||||
|
(
|
||||||
|
quote! {
|
||||||
|
VisitOperand::visit_mut
|
||||||
|
},
|
||||||
|
quote! {
|
||||||
|
&mut arguments.#name
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
quote! {
|
||||||
|
VisitOperand::visit
|
||||||
|
},
|
||||||
|
quote! {
|
||||||
|
& arguments.#name
|
||||||
|
},
|
||||||
|
)
|
||||||
|
};
|
||||||
|
quote! {{
|
||||||
|
#type_space
|
||||||
|
#operand_fn(#arguments_name, |x| visitor.visit(x, type_space, #is_dst));
|
||||||
|
}}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_visit_map(
|
fn emit_visit_map(
|
||||||
&self,
|
&self,
|
||||||
parent_type: &Option<Expr>,
|
parent_type: &Option<Option<Expr>>,
|
||||||
parent_space: &Option<Expr>,
|
parent_space: &Option<Expr>,
|
||||||
|
is_ident: bool,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
let type_ = self.type_.as_ref().or(parent_type.as_ref()).unwrap();
|
let (is_typeless, type_) = match (self.type_.as_ref(), parent_type) {
|
||||||
|
(Some(type_), _) => (false, Some(type_)),
|
||||||
|
(None, None) => panic!("No type set"),
|
||||||
|
(None, Some(None)) => (true, None),
|
||||||
|
(None, Some(Some(type_))) => (false, Some(type_)),
|
||||||
|
};
|
||||||
let space = self
|
let space = self
|
||||||
.space
|
.space
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -554,11 +610,30 @@ impl ArgumentField {
|
||||||
.unwrap_or_else(|| quote! { StateSpace::Reg });
|
.unwrap_or_else(|| quote! { StateSpace::Reg });
|
||||||
let is_dst = self.is_dst;
|
let is_dst = self.is_dst;
|
||||||
let name = &self.name;
|
let name = &self.name;
|
||||||
quote! {
|
let type_space = if is_typeless {
|
||||||
let #name = {
|
quote! {
|
||||||
|
let type_space = None;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
let type_ = #type_;
|
let type_ = #type_;
|
||||||
let space = #space;
|
let space = #space;
|
||||||
MapOperand::map(arguments.#name, |x| visitor.visit(x, &type_, space, #is_dst))
|
let type_space = Some((std::borrow::Borrow::<Type>::borrow(&type_), space));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let map_call = if is_ident {
|
||||||
|
quote! {
|
||||||
|
visitor.visit_ident(arguments.#name, type_space, #is_dst)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {
|
||||||
|
MapOperand::map(arguments.#name, |x| visitor.visit(x, type_space, #is_dst))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
let #name = {
|
||||||
|
#type_space
|
||||||
|
#map_call
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -702,27 +777,6 @@ mod tests {
|
||||||
assert!(matches!(src.space, None));
|
assert!(matches!(src.space, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn visit_variant() {
|
|
||||||
let input = quote! {
|
|
||||||
Ld {
|
|
||||||
type: ScalarType::U32,
|
|
||||||
data: LdDetails,
|
|
||||||
arguments<P>: {
|
|
||||||
dst: {
|
|
||||||
repr: P::Operand,
|
|
||||||
type: ScalarType::U32
|
|
||||||
},
|
|
||||||
src: P::Operand,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let variant = syn::parse2::<InstructionVariant>(input).unwrap();
|
|
||||||
let mut output = TokenStream::new();
|
|
||||||
variant.emit_visit(&Ident::new("Instruction", Span::call_site()), &mut output);
|
|
||||||
assert_eq!(output.to_string(), "Instruction :: Ld { arguments , data } => { { let type_ = ScalarType :: U32 ; let space = StateSpace :: Reg ; visitor . visit (& arguments . dst , & type_ , space , true) ; } { let type_ = ScalarType :: U32 ; let space = StateSpace :: Reg ; visitor . visit (& arguments . src , & type_ , space , false) ; } }");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn visit_variant_empty() {
|
fn visit_variant_empty() {
|
||||||
let input = quote! {
|
let input = quote! {
|
||||||
|
|
|
@ -86,13 +86,27 @@ impl Parse for OpcodeDecl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CodeBlock(pub proc_macro2::Group);
|
pub struct CodeBlock {
|
||||||
|
pub special: bool,
|
||||||
|
pub code: proc_macro2::Group,
|
||||||
|
}
|
||||||
|
|
||||||
impl Parse for CodeBlock {
|
impl Parse for CodeBlock {
|
||||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||||
input.parse::<Token![=>]>()?;
|
let lookahead = input.lookahead1();
|
||||||
let group = input.parse::<proc_macro2::Group>()?;
|
let (special, code) = if lookahead.peek(Token![<]) {
|
||||||
Ok(Self(group))
|
input.parse::<Token![<]>()?;
|
||||||
|
input.parse::<Token![=]>()?;
|
||||||
|
//input.parse::<Token![>]>()?;
|
||||||
|
(true, input.parse::<proc_macro2::Group>()?)
|
||||||
|
} else if lookahead.peek(Token![=]) {
|
||||||
|
input.parse::<Token![=]>()?;
|
||||||
|
input.parse::<Token![>]>()?;
|
||||||
|
(false, input.parse::<proc_macro2::Group>()?)
|
||||||
|
} else {
|
||||||
|
return Err(lookahead.error());
|
||||||
|
};
|
||||||
|
Ok(Self{special, code})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,7 +775,7 @@ mod tests {
|
||||||
.ss: StateSpace = { .global, .local, .param{::func}, .shared{::cta, ::cluster} }
|
.ss: StateSpace = { .global, .local, .param{::func}, .shared{::cta, ::cluster} }
|
||||||
};
|
};
|
||||||
let rule = syn::parse2::<super::Rule>(input).unwrap();
|
let rule = syn::parse2::<super::Rule>(input).unwrap();
|
||||||
assert_eq!(". ss", rule.modifier.tokens().to_string());
|
assert_eq!(". ss", rule.modifier.unwrap().tokens().to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"StateSpace",
|
"StateSpace",
|
||||||
rule.type_.unwrap().to_token_stream().to_string()
|
rule.type_.unwrap().to_token_stream().to_string()
|
||||||
|
@ -791,7 +805,7 @@ mod tests {
|
||||||
.cop: StCacheOperator = { .wb, .cg, .cs, .wt }
|
.cop: StCacheOperator = { .wb, .cg, .cs, .wt }
|
||||||
};
|
};
|
||||||
let rule = syn::parse2::<super::Rule>(input).unwrap();
|
let rule = syn::parse2::<super::Rule>(input).unwrap();
|
||||||
assert_eq!(". cop", rule.modifier.tokens().to_string());
|
assert_eq!(". cop", rule.modifier.unwrap().tokens().to_string());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
"StCacheOperator",
|
"StCacheOperator",
|
||||||
rule.type_.unwrap().to_token_stream().to_string()
|
rule.type_.unwrap().to_token_stream().to_string()
|
||||||
|
@ -819,4 +833,12 @@ mod tests {
|
||||||
assert!(!a.can_be_negated);
|
assert!(!a.can_be_negated);
|
||||||
assert!(a.unified);
|
assert!(a.unified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn special_block() {
|
||||||
|
let input = quote! {
|
||||||
|
bra <= { bra(stream) }
|
||||||
|
};
|
||||||
|
syn::parse2::<super::OpcodeDefinition>(input).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ gen::generate_instruction_type!(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Add {
|
Add {
|
||||||
type: { data.type_().into() },
|
type: { Type::from(data.type_()) },
|
||||||
data: ArithDetails,
|
data: ArithDetails,
|
||||||
arguments<T>: {
|
arguments<T>: {
|
||||||
dst: T,
|
dst: T,
|
||||||
|
@ -51,12 +51,12 @@ gen::generate_instruction_type!(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Mul {
|
Mul {
|
||||||
type: { data.type_().into() },
|
type: { Type::from(data.type_()) },
|
||||||
data: MulDetails,
|
data: MulDetails,
|
||||||
arguments<T>: {
|
arguments<T>: {
|
||||||
dst: {
|
dst: {
|
||||||
repr: T,
|
repr: T,
|
||||||
type: { data.dst_type().into() },
|
type: { Type::from(data.dst_type()) },
|
||||||
},
|
},
|
||||||
src1: T,
|
src1: T,
|
||||||
src2: T,
|
src2: T,
|
||||||
|
@ -67,19 +67,19 @@ gen::generate_instruction_type!(
|
||||||
arguments<T>: {
|
arguments<T>: {
|
||||||
dst1: {
|
dst1: {
|
||||||
repr: T,
|
repr: T,
|
||||||
type: ScalarType::Pred.into()
|
type: Type::from(ScalarType::Pred)
|
||||||
},
|
},
|
||||||
dst2: {
|
dst2: {
|
||||||
repr: Option<T>,
|
repr: Option<T>,
|
||||||
type: ScalarType::Pred.into()
|
type: Type::from(ScalarType::Pred)
|
||||||
},
|
},
|
||||||
src1: {
|
src1: {
|
||||||
repr: T,
|
repr: T,
|
||||||
type: data.type_.into(),
|
type: Type::from(data.type_),
|
||||||
},
|
},
|
||||||
src2: {
|
src2: {
|
||||||
repr: T,
|
repr: T,
|
||||||
type: data.type_.into(),
|
type: Type::from(data.type_),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -88,26 +88,58 @@ gen::generate_instruction_type!(
|
||||||
arguments<T>: {
|
arguments<T>: {
|
||||||
dst1: {
|
dst1: {
|
||||||
repr: T,
|
repr: T,
|
||||||
type: ScalarType::Pred.into()
|
type: Type::from(ScalarType::Pred)
|
||||||
},
|
},
|
||||||
dst2: {
|
dst2: {
|
||||||
repr: Option<T>,
|
repr: Option<T>,
|
||||||
type: ScalarType::Pred.into()
|
type: Type::from(ScalarType::Pred)
|
||||||
},
|
},
|
||||||
src1: {
|
src1: {
|
||||||
repr: T,
|
repr: T,
|
||||||
type: data.base.type_.into(),
|
type: Type::from(data.base.type_),
|
||||||
},
|
},
|
||||||
src2: {
|
src2: {
|
||||||
repr: T,
|
repr: T,
|
||||||
type: data.base.type_.into(),
|
type: Type::from(data.base.type_),
|
||||||
},
|
},
|
||||||
src3: {
|
src3: {
|
||||||
repr: T,
|
repr: T,
|
||||||
type: ScalarType::Pred.into()
|
type: Type::from(ScalarType::Pred)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Not {
|
||||||
|
data: ScalarType,
|
||||||
|
type: { Type::Scalar(data.clone()) },
|
||||||
|
arguments<T>: {
|
||||||
|
dst: T,
|
||||||
|
src: T,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Or {
|
||||||
|
data: ScalarType,
|
||||||
|
type: { Type::Scalar(data.clone()) },
|
||||||
|
arguments<T>: {
|
||||||
|
dst: T,
|
||||||
|
src1: T,
|
||||||
|
src2: T,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
And {
|
||||||
|
data: ScalarType,
|
||||||
|
type: { Type::Scalar(data.clone()) },
|
||||||
|
arguments<T>: {
|
||||||
|
dst: T,
|
||||||
|
src1: T,
|
||||||
|
src2: T,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Bra {
|
||||||
|
type: !,
|
||||||
|
arguments<T::Ident>: {
|
||||||
|
src: T
|
||||||
|
}
|
||||||
|
},
|
||||||
Ret {
|
Ret {
|
||||||
data: RetData
|
data: RetData
|
||||||
},
|
},
|
||||||
|
@ -115,21 +147,26 @@ gen::generate_instruction_type!(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
pub trait Visitor<T> {
|
pub trait Visitor<T: Operand> {
|
||||||
fn visit(&mut self, args: &T, type_: &Type, space: StateSpace, is_dst: bool);
|
fn visit(&mut self, args: &T, type_space: Option<(&Type, StateSpace)>, is_dst: bool);
|
||||||
|
fn visit_ident(&self, args: &T::Ident, type_space: Option<(&Type, StateSpace)>, is_dst: bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait VisitorMut<T> {
|
pub trait VisitorMut<T: Operand> {
|
||||||
fn visit(&mut self, args: &mut T, type_: &Type, space: StateSpace, is_dst: bool);
|
fn visit(&mut self, args: &mut T, type_space: Option<(&Type, StateSpace)>, is_dst: bool);
|
||||||
|
fn visit_ident(&mut self, args: &mut T::Ident, type_space: Option<(&Type, StateSpace)>, is_dst: bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait VisitorMap<From, To> {
|
pub trait VisitorMap<From: Operand, To: Operand> {
|
||||||
fn visit(&mut self, args: From, type_: &Type, space: StateSpace, is_dst: bool) -> To;
|
fn visit(&mut self, args: From, type_space: Option<(&Type, StateSpace)>, is_dst: bool) -> To;
|
||||||
|
fn visit_ident(&mut self, args: From::Ident, type_space: Option<(&Type, StateSpace)>, is_dst: bool) -> To::Ident;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait VisitOperand {
|
trait VisitOperand {
|
||||||
type Operand;
|
type Operand: Operand;
|
||||||
|
#[allow(unused)] // Used by generated code
|
||||||
fn visit(&self, fn_: impl FnOnce(&Self::Operand));
|
fn visit(&self, fn_: impl FnOnce(&Self::Operand));
|
||||||
|
#[allow(unused)] // Used by generated code
|
||||||
fn visit_mut(&mut self, fn_: impl FnOnce(&mut Self::Operand));
|
fn visit_mut(&mut self, fn_: impl FnOnce(&mut Self::Operand));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,6 +193,7 @@ impl<T: Operand> VisitOperand for Option<T> {
|
||||||
trait MapOperand: Sized {
|
trait MapOperand: Sized {
|
||||||
type Input;
|
type Input;
|
||||||
type Output<U>;
|
type Output<U>;
|
||||||
|
#[allow(unused)] // Used by generated code
|
||||||
fn map<U>(self, fn_: impl FnOnce(Self::Input) -> U) -> Self::Output<U>;
|
fn map<U>(self, fn_: impl FnOnce(Self::Input) -> U) -> Self::Output<U>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,12 +327,12 @@ pub enum ParsedOperand<Ident> {
|
||||||
VecPack(Vec<Ident>),
|
VecPack(Vec<Ident>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Ident> Operand for ParsedOperand<Ident> {
|
impl<Ident: Copy> Operand for ParsedOperand<Ident> {
|
||||||
type Ident = Ident;
|
type Ident = Ident;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Operand {
|
pub trait Operand {
|
||||||
type Ident;
|
type Ident: Copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -447,6 +485,7 @@ pub enum MulDetails {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MulDetails {
|
impl MulDetails {
|
||||||
|
#[allow(unused)] // Used by generated code
|
||||||
fn type_(&self) -> ScalarType {
|
fn type_(&self) -> ScalarType {
|
||||||
match self {
|
match self {
|
||||||
MulDetails::Integer { type_, .. } => *type_,
|
MulDetails::Integer { type_, .. } => *type_,
|
||||||
|
@ -454,6 +493,7 @@ impl MulDetails {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)] // Used by generated code
|
||||||
fn dst_type(&self) -> ScalarType {
|
fn dst_type(&self) -> ScalarType {
|
||||||
match self {
|
match self {
|
||||||
MulDetails::Integer {
|
MulDetails::Integer {
|
||||||
|
@ -521,7 +561,7 @@ impl SetpData {
|
||||||
pub struct SetpBoolData {
|
pub struct SetpBoolData {
|
||||||
pub base: SetpData,
|
pub base: SetpData,
|
||||||
pub bool_op: SetpBoolPostOp,
|
pub bool_op: SetpBoolPostOp,
|
||||||
pub negate_src3: bool
|
pub negate_src3: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
#[derive(PartialEq, Eq, Copy, Clone)]
|
||||||
|
|
|
@ -623,7 +623,7 @@ fn predicated_instruction<'a, 'input>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pred_at<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<ast::PredAt<&'input str>> {
|
fn pred_at<'a, 'input>(stream: &mut PtxParser<'a, 'input>) -> PResult<ast::PredAt<&'input str>> {
|
||||||
(Token::At, opt(Token::Not), ident)
|
(Token::At, opt(Token::Exclamation), ident)
|
||||||
.map(|(_, not, label)| ast::PredAt {
|
.map(|(_, not, label)| ast::PredAt {
|
||||||
not: not.is_some(),
|
not: not.is_some(),
|
||||||
label,
|
label,
|
||||||
|
@ -888,6 +888,21 @@ impl<'input, I: Stream<Token = Self> + StreamIsPartial, E: ParserError<I>> Parse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bra<'a, 'input>(
|
||||||
|
stream: &mut PtxParser<'a, 'input>,
|
||||||
|
) -> PResult<ast::Instruction<ParsedOperandStr<'input>>> {
|
||||||
|
preceded(
|
||||||
|
opt(Token::DotUni),
|
||||||
|
any.verify_map(|t| match t {
|
||||||
|
Token::Ident(ident) => Some(ast::Instruction::Bra {
|
||||||
|
arguments: BraArgs { src: ident },
|
||||||
|
}),
|
||||||
|
_ => None,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.parse_next(stream)
|
||||||
|
}
|
||||||
|
|
||||||
// Modifiers are turned into arguments to the blocks, with type:
|
// Modifiers are turned into arguments to the blocks, with type:
|
||||||
// * If it is an alternative:
|
// * If it is an alternative:
|
||||||
// * If it is mandatory then its type is Foo (as defined by the relevant rule)
|
// * If it is mandatory then its type is Foo (as defined by the relevant rule)
|
||||||
|
@ -919,9 +934,9 @@ derive_parser!(
|
||||||
#[regex(r#""[^"]*""#)]
|
#[regex(r#""[^"]*""#)]
|
||||||
String,
|
String,
|
||||||
#[token("|")]
|
#[token("|")]
|
||||||
Or,
|
Pipe,
|
||||||
#[token("!")]
|
#[token("!")]
|
||||||
Not,
|
Exclamation,
|
||||||
#[token("(")]
|
#[token("(")]
|
||||||
LParen,
|
LParen,
|
||||||
#[token(")")]
|
#[token(")")]
|
||||||
|
@ -1461,6 +1476,36 @@ derive_parser!(
|
||||||
.f32, .f64,
|
.f32, .f64,
|
||||||
.f16, .f16x2, .bf16, .bf16x2 };
|
.f16, .f16x2, .bf16, .bf16x2 };
|
||||||
|
|
||||||
|
// https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#logic-and-shift-instructions-not
|
||||||
|
not.type d, a => {
|
||||||
|
ast::Instruction::Not {
|
||||||
|
data: type_,
|
||||||
|
arguments: NotArgs { dst: d, src: a }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.type: ScalarType = { .pred, .b16, .b32, .b64 };
|
||||||
|
|
||||||
|
// https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#logic-and-shift-instructions-or
|
||||||
|
or.type d, a, b => {
|
||||||
|
ast::Instruction::Or {
|
||||||
|
data: type_,
|
||||||
|
arguments: OrArgs { dst: d, src1: a, src2: b }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.type: ScalarType = { .pred, .b16, .b32, .b64 };
|
||||||
|
|
||||||
|
// https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#logic-and-shift-instructions-and
|
||||||
|
and.type d, a, b => {
|
||||||
|
ast::Instruction::And {
|
||||||
|
data: type_,
|
||||||
|
arguments: AndArgs { dst: d, src1: a, src2: b }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.type: ScalarType = { .pred, .b16, .b32, .b64 };
|
||||||
|
|
||||||
|
// https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#control-flow-instructions-bra
|
||||||
|
bra <= { bra(stream) }
|
||||||
|
|
||||||
// https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#control-flow-instructions-ret
|
// https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#control-flow-instructions-ret
|
||||||
ret{.uni} => {
|
ret{.uni} => {
|
||||||
Instruction::Ret { data: RetData { uniform: uni } }
|
Instruction::Ret { data: RetData { uniform: uni } }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue