diff --git a/ptx/src/ast.rs b/ptx/src/ast.rs index 6304aac..a7bbe1f 100644 --- a/ptx/src/ast.rs +++ b/ptx/src/ast.rs @@ -55,7 +55,7 @@ pub struct Function<'a> { pub kernel: bool, pub name: &'a str, pub args: Vec>, - pub body: Vec>, + pub body: Vec>, } #[derive(Default)] @@ -102,16 +102,16 @@ impl Default for ScalarType { } } -pub enum Statement<'a> { - Label(&'a str), - Variable(Variable<'a>), - Instruction(Option>, Instruction<'a>), +pub enum Statement { + Label(ID), + Variable(Variable), + Instruction(Option>, Instruction), } -pub struct Variable<'a> { +pub struct Variable { pub space: StateSpace, pub v_type: Type, - pub name: &'a str, + pub name: ID, pub count: Option, } @@ -124,71 +124,71 @@ pub enum StateSpace { Shared, } -pub struct PredAt<'a> { +pub struct PredAt { pub not: bool, - pub label: &'a str, + pub label: ID, } -pub enum Instruction<'a> { - Ld(LdData, Arg2<'a>), - Mov(MovData, Arg2Mov<'a>), - Mul(MulData, Arg3<'a>), - Add(AddData, Arg3<'a>), - Setp(SetpData, Arg4<'a>), - SetpBool(SetpBoolData, Arg5<'a>), - Not(NotData, Arg2<'a>), - Bra(BraData, Arg1<'a>), - Cvt(CvtData, Arg2<'a>), - Shl(ShlData, Arg3<'a>), - St(StData, Arg2<'a>), - At(AtData, Arg1<'a>), +pub enum Instruction { + Ld(LdData, Arg2), + Mov(MovData, Arg2Mov), + Mul(MulData, Arg3), + Add(AddData, Arg3), + Setp(SetpData, Arg4), + SetpBool(SetpBoolData, Arg5), + Not(NotData, Arg2), + Bra(BraData, Arg1), + Cvt(CvtData, Arg2), + Shl(ShlData, Arg3), + St(StData, Arg2), + At(AtData, Arg1), Ret(RetData), } -pub struct Arg1<'a> { - pub dst: &'a str, +pub struct Arg1 { + pub dst: ID, } -pub struct Arg2<'a> { - pub dst: &'a str, - pub src: Operand<'a>, +pub struct Arg2 { + pub dst: ID, + pub src: Operand, } -pub struct Arg2Mov<'a> { - pub dst: &'a str, - pub src: MovOperand<'a>, +pub struct Arg2Mov { + pub dst: ID, + pub src: MovOperand, } -pub struct Arg3<'a> { - pub dst: &'a str, - pub src1: Operand<'a>, - pub src2: Operand<'a>, +pub struct Arg3 { + pub dst: ID, + pub src1: Operand, + pub src2: Operand, } -pub struct Arg4<'a> { - pub dst1: &'a str, - pub dst2: Option<&'a str>, - pub src1: Operand<'a>, - pub src2: Operand<'a>, +pub struct Arg4 { + pub dst1: ID, + pub dst2: Option, + pub src1: Operand, + pub src2: Operand, } -pub struct Arg5<'a> { - pub dst1: &'a str, - pub dst2: Option<&'a str>, - pub src1: Operand<'a>, - pub src2: Operand<'a>, - pub src3: Operand<'a>, +pub struct Arg5 { + pub dst1: ID, + pub dst2: Option, + pub src1: Operand, + pub src2: Operand, + pub src3: Operand, } -pub enum Operand<'a> { - Reg(&'a str), - RegOffset(&'a str, i32), +pub enum Operand { + Reg(ID), + RegOffset(ID, i32), Imm(i128), } -pub enum MovOperand<'a> { - Op(Operand<'a>), - Vec(&'a str, &'a str), +pub enum MovOperand { + Op(Operand), + Vec(String, String), } pub struct LdData {} diff --git a/ptx/src/ptx.lalrpop b/ptx/src/ptx.lalrpop index 52c4c2c..2168ba7 100644 --- a/ptx/src/ptx.lalrpop +++ b/ptx/src/ptx.lalrpop @@ -86,7 +86,7 @@ FunctionInput: ast::Argument<'input> = { } }; -FunctionBody: Vec> = { +FunctionBody: Vec> = { "{" "}" => { without_none(s) } }; @@ -135,7 +135,7 @@ BaseType = { ".f32", ".f64" }; -Statement: Option> = { +Statement: Option> = { => Some(ast::Statement::Label(l)), DebugDirective => None, ";" => Some(ast::Statement::Variable(v)), @@ -155,7 +155,7 @@ Label: &'input str = { ":" => id }; -Variable: ast::Variable<'input> = { +Variable: ast::Variable<&'input str> = { => { let (name, count) = v; ast::Variable { space: s, v_type: t, name: name, count: count } @@ -175,7 +175,7 @@ VariableName: (&'input str, Option) = { } }; -Instruction: ast::Instruction<'input> = { +Instruction: ast::Instruction<&'input str> = { InstLd, InstMov, InstMul, @@ -190,7 +190,7 @@ Instruction: ast::Instruction<'input> = { }; // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-ld -InstLd: ast::Instruction<'input> = { +InstLd: ast::Instruction<&'input str> = { "ld" LdQualifier? LdStateSpace? LdCacheOperator? Vector? BaseType "," "[" "]" => { ast::Instruction::Ld(ast::LdData{}, ast::Arg2{dst:dst, src:src}) } @@ -224,7 +224,7 @@ LdCacheOperator = { }; // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-mov -InstMov: ast::Instruction<'input> = { +InstMov: ast::Instruction<&'input str> = { "mov" MovType => { ast::Instruction::Mov(ast::MovData{}, a) } @@ -241,7 +241,7 @@ MovType = { // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#integer-arithmetic-instructions-mul // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#floating-point-instructions-mul // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#half-precision-floating-point-instructions-mul -InstMul: ast::Instruction<'input> = { +InstMul: ast::Instruction<&'input str> = { "mul" => ast::Instruction::Mul(d, a) }; @@ -270,7 +270,7 @@ IntType = { // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#integer-arithmetic-instructions-add // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#floating-point-instructions-add // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#half-precision-floating-point-instructions-add -InstAdd: ast::Instruction<'input> = { +InstAdd: ast::Instruction<&'input str> = { "add" => ast::Instruction::Add(d, a) }; @@ -286,7 +286,7 @@ InstAddMode: ast::AddData = { // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#comparison-and-selection-instructions-setp // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#half-precision-comparison-instructions-setp // TODO: support f16 setp -InstSetp: ast::Instruction<'input> = { +InstSetp: ast::Instruction<&'input str> = { "setp" => ast::Instruction::Setp(d, a), "setp" => ast::Instruction::SetpBool(d, a), }; @@ -316,7 +316,7 @@ SetpType = { }; // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#logic-and-shift-instructions-not -InstNot: ast::Instruction<'input> = { +InstNot: ast::Instruction<&'input str> = { "not" NotType => ast::Instruction::Not(ast::NotData{}, a) }; @@ -325,18 +325,18 @@ NotType = { }; // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#control-flow-instructions-at -PredAt: ast::PredAt<'input> = { +PredAt: ast::PredAt<&'input str> = { "@" => ast::PredAt { not: false, label:label }, "@" "!" => ast::PredAt { not: true, label:label } }; // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#control-flow-instructions-bra -InstBra: ast::Instruction<'input> = { +InstBra: ast::Instruction<&'input str> = { "bra" ".uni"? => ast::Instruction::Bra(ast::BraData{}, a) }; // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-cvt -InstCvt: ast::Instruction<'input> = { +InstCvt: ast::Instruction<&'input str> = { "cvt" CvtRnd? ".ftz"? ".sat"? CvtType CvtType => { ast::Instruction::Cvt(ast::CvtData{}, a) } @@ -362,7 +362,7 @@ CvtType = { }; // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#logic-and-shift-instructions-shl -InstShl: ast::Instruction<'input> = { +InstShl: ast::Instruction<&'input str> = { "shl" ShlType => ast::Instruction::Shl(ast::ShlData{}, a) }; @@ -371,7 +371,7 @@ ShlType = { }; // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-st -InstSt: ast::Instruction<'input> = { +InstSt: ast::Instruction<&'input str> = { "st" LdQualifier? StStateSpace? StCacheOperator? Vector? BaseType "[" "]" "," => { ast::Instruction::St(ast::StData{}, ast::Arg2{dst:dst, src:src}) } @@ -392,11 +392,11 @@ StCacheOperator = { }; // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#control-flow-instructions-ret -InstRet: ast::Instruction<'input> = { +InstRet: ast::Instruction<&'input str> = { "ret" ".uni"? => ast::Instruction::Ret(ast::RetData{}) }; -Operand: ast::Operand<'input> = { +Operand: ast::Operand<&'input str> = { => ast::Operand::Reg(r), "+" => { let offset = o.parse::(); @@ -412,11 +412,11 @@ Operand: ast::Operand<'input> = { } }; -MovOperand: ast::MovOperand<'input> = { +MovOperand: ast::MovOperand<&'input str> = { => ast::MovOperand::Op(o), => { let (pref, suf) = o; - ast::MovOperand::Vec(pref, suf) + ast::MovOperand::Vec(pref.to_string(), suf.to_string()) } }; @@ -425,28 +425,28 @@ VectorOperand: (&'input str, &'input str) = { => (pref, &suf[1..]), }; -Arg1: ast::Arg1<'input> = { +Arg1: ast::Arg1<&'input str> = { => ast::Arg1{<>} }; -Arg2: ast::Arg2<'input> = { +Arg2: ast::Arg2<&'input str> = { "," => ast::Arg2{<>} }; -Arg2Mov: ast::Arg2Mov<'input> = { +Arg2Mov: ast::Arg2Mov<&'input str> = { "," => ast::Arg2Mov{<>} }; -Arg3: ast::Arg3<'input> = { +Arg3: ast::Arg3<&'input str> = { "," "," => ast::Arg3{<>} }; -Arg4: ast::Arg4<'input> = { +Arg4: ast::Arg4<&'input str> = { "," "," => ast::Arg4{<>} }; // TODO: pass src3 negation somewhere -Arg5: ast::Arg5<'input> = { +Arg5: ast::Arg5<&'input str> = { "," "," "," "!"? => ast::Arg5{<>} }; diff --git a/ptx/src/translate.rs b/ptx/src/translate.rs index 15782bf..2382180 100644 --- a/ptx/src/translate.rs +++ b/ptx/src/translate.rs @@ -138,7 +138,7 @@ fn emit_function<'a>( } // TODO: support scopes -fn normalize_identifiers<'a>(func: Vec>) -> Vec { +fn normalize_identifiers<'a>(func: Vec>) -> Vec { let mut result = Vec::with_capacity(func.len()); let mut id: u32 = 0; let mut known_ids = HashMap::new(); @@ -162,193 +162,124 @@ fn ssa_legalize(func: Vec) -> Vec { enum Statement { Label(u32), - Instruction(Option, Instruction), + Instruction(Option>, ast::Instruction), Phi(Vec), } impl Statement { - fn from_ast<'a, F: FnMut(&'a str) -> u32>(s: ast::Statement<'a>, f: &mut F) -> Option { + fn from_ast<'a, F: FnMut(&'a str) -> u32>(s: ast::Statement<&'a str>, f: &mut F) -> Option { match s { ast::Statement::Label(name) => Some(Statement::Label(f(name))), ast::Statement::Instruction(p, i) => Some(Statement::Instruction( - p.map(|p| PredAt::from_ast(p, f)), - Instruction::from_ast(i, f), + p.map(|p| p.map_id(f)), + i.map_id(f), )), ast::Statement::Variable(_) => None, } } } -struct PredAt { - pub not: bool, - pub label: u32, -} - -impl PredAt { - fn from_ast<'a, F: FnMut(&'a str) -> u32>(p: ast::PredAt<'a>, f: &mut F) -> Self { - PredAt { - not: p.not, - label: f(p.label), +impl ast::PredAt { + fn map_id U>(self, f: &mut F) -> ast::PredAt { + ast::PredAt { + not: self.not, + label: f(self.label), } } } -enum Instruction { - Ld(ast::LdData, Arg2), - Mov(ast::MovData, Arg2Mov), - Mul(ast::MulData, Arg3), - Add(ast::AddData, Arg3), - Setp(ast::SetpData, Arg4), - SetpBool(ast::SetpBoolData, Arg5), - Not(ast::NotData, Arg2), - Bra(ast::BraData, Arg1), - Cvt(ast::CvtData, Arg2), - Shl(ast::ShlData, Arg3), - St(ast::StData, Arg2), - At(ast::AtData, Arg1), - Ret(ast::RetData), -} - -impl Instruction { - fn from_ast<'a, F: FnMut(&'a str) -> u32>(i: ast::Instruction<'a>, f: &mut F) -> Self { - match i { - ast::Instruction::Ld(d, a) => Instruction::Ld(d, Arg2::from_ast(a, f)), - ast::Instruction::Mov(d, a) => Instruction::Mov(d, Arg2Mov::from_ast(a, f)), - ast::Instruction::Mul(d, a) => Instruction::Mul(d, Arg3::from_ast(a, f)), - ast::Instruction::Add(d, a) => Instruction::Add(d, Arg3::from_ast(a, f)), - ast::Instruction::Setp(d, a) => Instruction::Setp(d, Arg4::from_ast(a, f)), - ast::Instruction::SetpBool(d, a) => Instruction::SetpBool(d, Arg5::from_ast(a, f)), - ast::Instruction::Not(d, a) => Instruction::Not(d, Arg2::from_ast(a, f)), - ast::Instruction::Bra(d, a) => Instruction::Bra(d, Arg1::from_ast(a, f)), - ast::Instruction::Cvt(d, a) => Instruction::Cvt(d, Arg2::from_ast(a, f)), - ast::Instruction::Shl(d, a) => Instruction::Shl(d, Arg3::from_ast(a, f)), - ast::Instruction::St(d, a) => Instruction::St(d, Arg2::from_ast(a, f)), - ast::Instruction::At(d, a) => Instruction::At(d, Arg1::from_ast(a, f)), - ast::Instruction::Ret(d) => Instruction::Ret(d), +impl ast::Instruction { + fn map_id U>(self, f: &mut F) -> ast::Instruction { + match self { + ast::Instruction::Ld(d, a) => ast::Instruction::Ld(d, a.map_id(f)), + ast::Instruction::Mov(d, a) => ast::Instruction::Mov(d, a.map_id(f)), + ast::Instruction::Mul(d, a) => ast::Instruction::Mul(d, a.map_id(f)), + ast::Instruction::Add(d, a) => ast::Instruction::Add(d, a.map_id(f)), + ast::Instruction::Setp(d, a) => ast::Instruction::Setp(d, a.map_id(f)), + ast::Instruction::SetpBool(d, a) => ast::Instruction::SetpBool(d, a.map_id(f)), + ast::Instruction::Not(d, a) => ast::Instruction::Not(d, a.map_id(f)), + ast::Instruction::Bra(d, a) => ast::Instruction::Bra(d, a.map_id(f)), + ast::Instruction::Cvt(d, a) => ast::Instruction::Cvt(d, a.map_id(f)), + ast::Instruction::Shl(d, a) => ast::Instruction::Shl(d, a.map_id(f)), + ast::Instruction::St(d, a) => ast::Instruction::St(d, a.map_id(f)), + ast::Instruction::At(d, a) => ast::Instruction::At(d, a.map_id(f)), + ast::Instruction::Ret(d) => ast::Instruction::Ret(d), } } } -pub struct Arg1 { - pub dst: u32, -} - -impl Arg1 { - fn from_ast<'a, F: FnMut(&'a str) -> u32>(a: ast::Arg1<'a>, f: &mut F) -> Self { - Arg1 { dst: f(a.dst) } +impl ast::Arg1 { + fn map_id U>(self, f: &mut F) -> ast::Arg1 { + ast::Arg1 { dst: f(self.dst) } } } -pub struct Arg2 { - pub dst: u32, - pub src: Operand, -} - -impl Arg2 { - fn from_ast<'a, F: FnMut(&'a str) -> u32>(a: ast::Arg2<'a>, f: &mut F) -> Self { - Arg2 { - dst: f(a.dst), - src: Operand::from_ast(a.src, f), +impl ast::Arg2 { + fn map_id U>(self, f: &mut F) -> ast::Arg2 { + ast::Arg2 { + dst: f(self.dst), + src: self.src.map_id(f), } } } -pub struct Arg2Mov { - pub dst: u32, - pub src: MovOperand, -} - -impl Arg2Mov { - fn from_ast<'a, F: FnMut(&'a str) -> u32>(a: ast::Arg2Mov<'a>, f: &mut F) -> Self { - Arg2Mov { - dst: f(a.dst), - src: MovOperand::from_ast(a.src, f), +impl ast::Arg2Mov { + fn map_id U>(self, f: &mut F) -> ast::Arg2Mov { + ast::Arg2Mov { + dst: f(self.dst), + src: self.src.map_id(f), } } } -pub struct Arg3 { - pub dst: u32, - pub src1: Operand, - pub src2: Operand, -} - -impl Arg3 { - fn from_ast<'a, F: FnMut(&'a str) -> u32>(a: ast::Arg3<'a>, f: &mut F) -> Self { - Arg3 { - dst: f(a.dst), - src1: Operand::from_ast(a.src1, f), - src2: Operand::from_ast(a.src2, f), +impl ast::Arg3 { + fn map_id U>(self, f: &mut F) -> ast::Arg3 { + ast::Arg3 { + dst: f(self.dst), + src1: self.src1.map_id(f), + src2: self.src2.map_id(f), } } } -pub struct Arg4 { - pub dst1: u32, - pub dst2: Option, - pub src1: Operand, - pub src2: Operand, -} - -impl Arg4 { - fn from_ast<'a, F: FnMut(&'a str) -> u32>(a: ast::Arg4<'a>, f: &mut F) -> Self { - Arg4 { - dst1: f(a.dst1), - dst2: a.dst2.map(|i| f(i)), - src1: Operand::from_ast(a.src1, f), - src2: Operand::from_ast(a.src2, f), +impl ast::Arg4 { + fn map_id U>(self, f: &mut F) -> ast::Arg4 { + ast::Arg4 { + dst1: f(self.dst1), + dst2: self.dst2.map(|i| f(i)), + src1: self.src1.map_id(f), + src2: self.src2.map_id(f), } } } -pub struct Arg5 { - pub dst1: u32, - pub dst2: Option, - pub src1: Operand, - pub src2: Operand, - pub src3: Operand, -} - -impl Arg5 { - fn from_ast<'a, F: FnMut(&'a str) -> u32>(a: ast::Arg5<'a>, f: &mut F) -> Self { - Arg5 { - dst1: f(a.dst1), - dst2: a.dst2.map(|i| f(i)), - src1: Operand::from_ast(a.src1, f), - src2: Operand::from_ast(a.src2, f), - src3: Operand::from_ast(a.src3, f), +impl ast::Arg5 { + fn map_id U>(self, f: &mut F) -> ast::Arg5 { + ast::Arg5 { + dst1: f(self.dst1), + dst2: self.dst2.map(|i| f(i)), + src1: self.src1.map_id(f), + src2: self.src2.map_id(f), + src3: self.src3.map_id(f), } } } -pub enum Operand { - Reg(u32), - RegOffset(u32, i32), - Imm(i128), -} - -impl Operand { - fn from_ast<'a, F: FnMut(&'a str) -> u32>(a: ast::Operand<'a>, f: &mut F) -> Self { - match a { - ast::Operand::Reg(i) => Operand::Reg(f(i)), - ast::Operand::RegOffset(i, o) => Operand::RegOffset(f(i), o), - ast::Operand::Imm(v) => Operand::Imm(v), +impl ast::Operand { + fn map_id U>(self, f: &mut F) -> ast::Operand { + match self { + ast::Operand::Reg(i) => ast::Operand::Reg(f(i)), + ast::Operand::RegOffset(i, o) => ast::Operand::RegOffset(f(i), o), + ast::Operand::Imm(v) => ast::Operand::Imm(v), } } } -pub enum MovOperand { - Op(Operand), - Vec(String, String), -} - -impl MovOperand { - fn from_ast<'a, F: FnMut(&'a str) -> u32>(a: ast::MovOperand<'a>, f: &mut F) -> Self { - match a { - ast::MovOperand::Op(o) => MovOperand::Op(Operand::from_ast(o, f)), - ast::MovOperand::Vec(var, idx) => { - MovOperand::Vec(var.to_owned(), idx.to_string()) - } +impl ast::MovOperand { + fn map_id U>(self, f: &mut F) -> ast::MovOperand { + match self { + ast::MovOperand::Op(o) => ast::MovOperand::Op(o.map_id(f)), + ast::MovOperand::Vec(s1, s2) => ast::MovOperand::Vec(s1, s2) } } -} +} \ No newline at end of file