• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/writer/msl/test_helper.h"
16 
17 namespace tint {
18 namespace writer {
19 namespace msl {
20 namespace {
21 
22 struct BinaryData {
23   const char* result;
24   ast::BinaryOp op;
25 };
operator <<(std::ostream & out,BinaryData data)26 inline std::ostream& operator<<(std::ostream& out, BinaryData data) {
27   out << data.op;
28   return out;
29 }
30 using MslBinaryTest = TestParamHelper<BinaryData>;
TEST_P(MslBinaryTest,Emit)31 TEST_P(MslBinaryTest, Emit) {
32   auto params = GetParam();
33 
34   auto type = [&] {
35     return ((params.op == ast::BinaryOp::kLogicalAnd) ||
36             (params.op == ast::BinaryOp::kLogicalOr))
37                ? static_cast<const ast::Type*>(ty.bool_())
38                : static_cast<const ast::Type*>(ty.u32());
39   };
40 
41   auto* left = Var("left", type());
42   auto* right = Var("right", type());
43 
44   auto* expr =
45       create<ast::BinaryExpression>(params.op, Expr(left), Expr(right));
46   WrapInFunction(left, right, expr);
47 
48   GeneratorImpl& gen = Build();
49 
50   std::stringstream out;
51   ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
52   EXPECT_EQ(out.str(), params.result);
53 }
54 INSTANTIATE_TEST_SUITE_P(
55     MslGeneratorImplTest,
56     MslBinaryTest,
57     testing::Values(
58         BinaryData{"(left & right)", ast::BinaryOp::kAnd},
59         BinaryData{"(left | right)", ast::BinaryOp::kOr},
60         BinaryData{"(left ^ right)", ast::BinaryOp::kXor},
61         BinaryData{"(left && right)", ast::BinaryOp::kLogicalAnd},
62         BinaryData{"(left || right)", ast::BinaryOp::kLogicalOr},
63         BinaryData{"(left == right)", ast::BinaryOp::kEqual},
64         BinaryData{"(left != right)", ast::BinaryOp::kNotEqual},
65         BinaryData{"(left < right)", ast::BinaryOp::kLessThan},
66         BinaryData{"(left > right)", ast::BinaryOp::kGreaterThan},
67         BinaryData{"(left <= right)", ast::BinaryOp::kLessThanEqual},
68         BinaryData{"(left >= right)", ast::BinaryOp::kGreaterThanEqual},
69         BinaryData{"(left << right)", ast::BinaryOp::kShiftLeft},
70         BinaryData{"(left >> right)", ast::BinaryOp::kShiftRight},
71         BinaryData{"(left + right)", ast::BinaryOp::kAdd},
72         BinaryData{"(left - right)", ast::BinaryOp::kSubtract},
73         BinaryData{"(left * right)", ast::BinaryOp::kMultiply},
74         BinaryData{"(left / right)", ast::BinaryOp::kDivide},
75         BinaryData{"(left % right)", ast::BinaryOp::kModulo}));
76 
77 using MslBinaryTest_SignedOverflowDefinedBehaviour =
78     TestParamHelper<BinaryData>;
TEST_P(MslBinaryTest_SignedOverflowDefinedBehaviour,Emit)79 TEST_P(MslBinaryTest_SignedOverflowDefinedBehaviour, Emit) {
80   auto params = GetParam();
81 
82   auto* a_type = ty.i32();
83   auto* b_type = (params.op == ast::BinaryOp::kShiftLeft ||
84                   params.op == ast::BinaryOp::kShiftRight)
85                      ? static_cast<const ast::Type*>(ty.u32())
86                      : ty.i32();
87 
88   auto* a = Var("a", a_type);
89   auto* b = Var("b", b_type);
90 
91   auto* expr = create<ast::BinaryExpression>(params.op, Expr(a), Expr(b));
92   WrapInFunction(a, b, expr);
93 
94   GeneratorImpl& gen = Build();
95 
96   std::stringstream out;
97   ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
98   EXPECT_EQ(out.str(), params.result);
99 }
100 using Op = ast::BinaryOp;
101 constexpr BinaryData signed_overflow_defined_behaviour_cases[] = {
102     {"as_type<int>((as_type<uint>(a) << b))", Op::kShiftLeft},
103     {"(a >> b)", Op::kShiftRight},
104     {"as_type<int>((as_type<uint>(a) + as_type<uint>(b)))", Op::kAdd},
105     {"as_type<int>((as_type<uint>(a) - as_type<uint>(b)))", Op::kSubtract},
106     {"as_type<int>((as_type<uint>(a) * as_type<uint>(b)))", Op::kMultiply}};
107 INSTANTIATE_TEST_SUITE_P(
108     MslGeneratorImplTest,
109     MslBinaryTest_SignedOverflowDefinedBehaviour,
110     testing::ValuesIn(signed_overflow_defined_behaviour_cases));
111 
112 using MslBinaryTest_SignedOverflowDefinedBehaviour_Chained =
113     TestParamHelper<BinaryData>;
TEST_P(MslBinaryTest_SignedOverflowDefinedBehaviour_Chained,Emit)114 TEST_P(MslBinaryTest_SignedOverflowDefinedBehaviour_Chained, Emit) {
115   auto params = GetParam();
116 
117   auto* a_type = ty.i32();
118   auto* b_type = (params.op == ast::BinaryOp::kShiftLeft ||
119                   params.op == ast::BinaryOp::kShiftRight)
120                      ? static_cast<const ast::Type*>(ty.u32())
121                      : ty.i32();
122 
123   auto* a = Var("a", a_type);
124   auto* b = Var("b", b_type);
125 
126   auto* expr1 = create<ast::BinaryExpression>(params.op, Expr(a), Expr(b));
127   auto* expr2 = create<ast::BinaryExpression>(params.op, expr1, Expr(b));
128   WrapInFunction(a, b, expr2);
129 
130   GeneratorImpl& gen = Build();
131 
132   std::stringstream out;
133   ASSERT_TRUE(gen.EmitExpression(out, expr2)) << gen.error();
134   EXPECT_EQ(out.str(), params.result);
135 }
136 using Op = ast::BinaryOp;
137 constexpr BinaryData signed_overflow_defined_behaviour_chained_cases[] = {
138     {"as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) << b))) << "
139      "b))",
140      Op::kShiftLeft},
141     {"((a >> b) >> b)", Op::kShiftRight},
142     {"as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) + "
143      "as_type<uint>(b)))) + as_type<uint>(b)))",
144      Op::kAdd},
145     {"as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) - "
146      "as_type<uint>(b)))) - as_type<uint>(b)))",
147      Op::kSubtract},
148     {"as_type<int>((as_type<uint>(as_type<int>((as_type<uint>(a) * "
149      "as_type<uint>(b)))) * as_type<uint>(b)))",
150      Op::kMultiply}};
151 INSTANTIATE_TEST_SUITE_P(
152     MslGeneratorImplTest,
153     MslBinaryTest_SignedOverflowDefinedBehaviour_Chained,
154     testing::ValuesIn(signed_overflow_defined_behaviour_chained_cases));
155 
TEST_F(MslBinaryTest,ModF32)156 TEST_F(MslBinaryTest, ModF32) {
157   auto* left = Var("left", ty.f32());
158   auto* right = Var("right", ty.f32());
159   auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kModulo, Expr(left),
160                                              Expr(right));
161   WrapInFunction(left, right, expr);
162 
163   GeneratorImpl& gen = Build();
164 
165   std::stringstream out;
166   ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
167   EXPECT_EQ(out.str(), "fmod(left, right)");
168 }
169 
TEST_F(MslBinaryTest,ModVec3F32)170 TEST_F(MslBinaryTest, ModVec3F32) {
171   auto* left = Var("left", ty.vec3<f32>());
172   auto* right = Var("right", ty.vec3<f32>());
173   auto* expr = create<ast::BinaryExpression>(ast::BinaryOp::kModulo, Expr(left),
174                                              Expr(right));
175   WrapInFunction(left, right, expr);
176 
177   GeneratorImpl& gen = Build();
178 
179   std::stringstream out;
180   ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
181   EXPECT_EQ(out.str(), "fmod(left, right)");
182 }
183 
184 }  // namespace
185 }  // namespace msl
186 }  // namespace writer
187 }  // namespace tint
188