mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-05-13 19:01:24 +00:00
Implement bitwise complement operator
This translates to/from OpNot for SPIR-V, and ~ for all three textual language backends. Fixed: tint:866 Change-Id: Id934fb309221e3fca0e7efa33edaaae137fd8085 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/54980 Auto-Submit: James Price <jrprice@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
52b6a004b8
commit
c932b5535f
@ -23,6 +23,10 @@ std::ostream& operator<<(std::ostream& out, UnaryOp mod) {
|
|||||||
out << "address-of";
|
out << "address-of";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case UnaryOp::kComplement: {
|
||||||
|
out << "complement";
|
||||||
|
break;
|
||||||
|
}
|
||||||
case UnaryOp::kIndirection: {
|
case UnaryOp::kIndirection: {
|
||||||
out << "indirection";
|
out << "indirection";
|
||||||
break;
|
break;
|
||||||
|
@ -23,6 +23,7 @@ namespace ast {
|
|||||||
/// The unary op
|
/// The unary op
|
||||||
enum class UnaryOp {
|
enum class UnaryOp {
|
||||||
kAddressOf, // &EXPR
|
kAddressOf, // &EXPR
|
||||||
|
kComplement, // ~EXPR
|
||||||
kIndirection, // *EXPR
|
kIndirection, // *EXPR
|
||||||
kNegation, // -EXPR
|
kNegation, // -EXPR
|
||||||
kNot, // !EXPR
|
kNot, // !EXPR
|
||||||
|
@ -155,9 +155,11 @@ bool GetUnaryOp(SpvOp opcode, ast::UnaryOp* ast_unary_op) {
|
|||||||
*ast_unary_op = ast::UnaryOp::kNegation;
|
*ast_unary_op = ast::UnaryOp::kNegation;
|
||||||
return true;
|
return true;
|
||||||
case SpvOpLogicalNot:
|
case SpvOpLogicalNot:
|
||||||
case SpvOpNot:
|
|
||||||
*ast_unary_op = ast::UnaryOp::kNot;
|
*ast_unary_op = ast::UnaryOp::kNot;
|
||||||
return true;
|
return true;
|
||||||
|
case SpvOpNot:
|
||||||
|
*ast_unary_op = ast::UnaryOp::kComplement;
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1136,7 +1136,7 @@ TEST_F(SpvUnaryBitTest, Not_Int_Int) {
|
|||||||
__i32
|
__i32
|
||||||
{
|
{
|
||||||
UnaryOp[not set]{
|
UnaryOp[not set]{
|
||||||
not
|
complement
|
||||||
ScalarConstructor[not set]{30}
|
ScalarConstructor[not set]{30}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1164,7 +1164,7 @@ TEST_F(SpvUnaryBitTest, Not_Int_Uint) {
|
|||||||
{
|
{
|
||||||
Bitcast[not set]<__i32>{
|
Bitcast[not set]<__i32>{
|
||||||
UnaryOp[not set]{
|
UnaryOp[not set]{
|
||||||
not
|
complement
|
||||||
ScalarConstructor[not set]{10u}
|
ScalarConstructor[not set]{10u}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1193,7 +1193,7 @@ TEST_F(SpvUnaryBitTest, Not_Uint_Int) {
|
|||||||
{
|
{
|
||||||
Bitcast[not set]<__u32>{
|
Bitcast[not set]<__u32>{
|
||||||
UnaryOp[not set]{
|
UnaryOp[not set]{
|
||||||
not
|
complement
|
||||||
ScalarConstructor[not set]{30}
|
ScalarConstructor[not set]{30}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1221,7 +1221,7 @@ TEST_F(SpvUnaryBitTest, Not_Uint_Uint) {
|
|||||||
__u32
|
__u32
|
||||||
{
|
{
|
||||||
UnaryOp[not set]{
|
UnaryOp[not set]{
|
||||||
not
|
complement
|
||||||
ScalarConstructor[not set]{10u}
|
ScalarConstructor[not set]{10u}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1248,7 +1248,7 @@ TEST_F(SpvUnaryBitTest, Not_SignedVec_SignedVec) {
|
|||||||
__vec_2__i32
|
__vec_2__i32
|
||||||
{
|
{
|
||||||
UnaryOp[not set]{
|
UnaryOp[not set]{
|
||||||
not
|
complement
|
||||||
TypeConstructor[not set]{
|
TypeConstructor[not set]{
|
||||||
__vec_2__i32
|
__vec_2__i32
|
||||||
ScalarConstructor[not set]{30}
|
ScalarConstructor[not set]{30}
|
||||||
@ -1280,7 +1280,7 @@ TEST_F(SpvUnaryBitTest, Not_SignedVec_UnsignedVec) {
|
|||||||
{
|
{
|
||||||
Bitcast[not set]<__vec_2__i32>{
|
Bitcast[not set]<__vec_2__i32>{
|
||||||
UnaryOp[not set]{
|
UnaryOp[not set]{
|
||||||
not
|
complement
|
||||||
TypeConstructor[not set]{
|
TypeConstructor[not set]{
|
||||||
__vec_2__u32
|
__vec_2__u32
|
||||||
ScalarConstructor[not set]{10u}
|
ScalarConstructor[not set]{10u}
|
||||||
@ -1313,7 +1313,7 @@ TEST_F(SpvUnaryBitTest, Not_UnsignedVec_SignedVec) {
|
|||||||
{
|
{
|
||||||
Bitcast[not set]<__vec_2__u32>{
|
Bitcast[not set]<__vec_2__u32>{
|
||||||
UnaryOp[not set]{
|
UnaryOp[not set]{
|
||||||
not
|
complement
|
||||||
TypeConstructor[not set]{
|
TypeConstructor[not set]{
|
||||||
__vec_2__i32
|
__vec_2__i32
|
||||||
ScalarConstructor[not set]{30}
|
ScalarConstructor[not set]{30}
|
||||||
@ -1344,7 +1344,7 @@ TEST_F(SpvUnaryBitTest, Not_UnsignedVec_UnsignedVec) {
|
|||||||
__vec_2__u32
|
__vec_2__u32
|
||||||
{
|
{
|
||||||
UnaryOp[not set]{
|
UnaryOp[not set]{
|
||||||
not
|
complement
|
||||||
TypeConstructor[not set]{
|
TypeConstructor[not set]{
|
||||||
__vec_2__u32
|
__vec_2__u32
|
||||||
ScalarConstructor[not set]{10u}
|
ScalarConstructor[not set]{10u}
|
||||||
|
@ -456,6 +456,10 @@ Token Lexer::try_punctuation() {
|
|||||||
type = Token::Type::kStar;
|
type = Token::Type::kStar;
|
||||||
pos_ += 1;
|
pos_ += 1;
|
||||||
location_.column += 1;
|
location_.column += 1;
|
||||||
|
} else if (matches(pos_, "~")) {
|
||||||
|
type = Token::Type::kTilde;
|
||||||
|
pos_ += 1;
|
||||||
|
location_.column += 1;
|
||||||
} else if (matches(pos_, "^")) {
|
} else if (matches(pos_, "^")) {
|
||||||
type = Token::Type::kXor;
|
type = Token::Type::kXor;
|
||||||
pos_ += 1;
|
pos_ += 1;
|
||||||
|
@ -395,6 +395,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||||||
TokenData{")", Token::Type::kParenRight},
|
TokenData{")", Token::Type::kParenRight},
|
||||||
TokenData{";", Token::Type::kSemicolon},
|
TokenData{";", Token::Type::kSemicolon},
|
||||||
TokenData{"*", Token::Type::kStar},
|
TokenData{"*", Token::Type::kStar},
|
||||||
|
TokenData{"~", Token::Type::kTilde},
|
||||||
TokenData{"^", Token::Type::kXor}));
|
TokenData{"^", Token::Type::kXor}));
|
||||||
|
|
||||||
using KeywordTest = testing::TestWithParam<TokenData>;
|
using KeywordTest = testing::TestWithParam<TokenData>;
|
||||||
|
@ -2308,6 +2308,7 @@ Expect<ast::ExpressionList> ParserImpl::expect_argument_expression_list(
|
|||||||
// : singular_expression
|
// : singular_expression
|
||||||
// | MINUS unary_expression
|
// | MINUS unary_expression
|
||||||
// | BANG unary_expression
|
// | BANG unary_expression
|
||||||
|
// | TILDE unary_expression
|
||||||
// | STAR unary_expression
|
// | STAR unary_expression
|
||||||
// | AND unary_expression
|
// | AND unary_expression
|
||||||
Maybe<ast::Expression*> ParserImpl::unary_expression() {
|
Maybe<ast::Expression*> ParserImpl::unary_expression() {
|
||||||
@ -2318,6 +2319,8 @@ Maybe<ast::Expression*> ParserImpl::unary_expression() {
|
|||||||
op = ast::UnaryOp::kNegation;
|
op = ast::UnaryOp::kNegation;
|
||||||
} else if (match(Token::Type::kBang)) {
|
} else if (match(Token::Type::kBang)) {
|
||||||
op = ast::UnaryOp::kNot;
|
op = ast::UnaryOp::kNot;
|
||||||
|
} else if (match(Token::Type::kTilde)) {
|
||||||
|
op = ast::UnaryOp::kComplement;
|
||||||
} else if (match(Token::Type::kStar)) {
|
} else if (match(Token::Type::kStar)) {
|
||||||
op = ast::UnaryOp::kIndirection;
|
op = ast::UnaryOp::kIndirection;
|
||||||
} else if (match(Token::Type::kAnd)) {
|
} else if (match(Token::Type::kAnd)) {
|
||||||
|
@ -157,6 +157,26 @@ TEST_F(ParserImplTest, UnaryExpression_Bang_InvalidRHS) {
|
|||||||
EXPECT_EQ(p->error(), "1:2: unable to parse right side of ! expression");
|
EXPECT_EQ(p->error(), "1:2: unable to parse right side of ! expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ParserImplTest, UnaryExpression_Tilde) {
|
||||||
|
auto p = parser("~1");
|
||||||
|
auto e = p->unary_expression();
|
||||||
|
EXPECT_TRUE(e.matched);
|
||||||
|
EXPECT_FALSE(e.errored);
|
||||||
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
|
||||||
|
|
||||||
|
auto* u = e->As<ast::UnaryOpExpression>();
|
||||||
|
ASSERT_EQ(u->op(), ast::UnaryOp::kComplement);
|
||||||
|
|
||||||
|
ASSERT_TRUE(u->expr()->Is<ast::ConstructorExpression>());
|
||||||
|
ASSERT_TRUE(u->expr()->Is<ast::ScalarConstructorExpression>());
|
||||||
|
|
||||||
|
auto* init = u->expr()->As<ast::ScalarConstructorExpression>();
|
||||||
|
ASSERT_TRUE(init->literal()->Is<ast::SintLiteral>());
|
||||||
|
EXPECT_EQ(init->literal()->As<ast::SintLiteral>()->value(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace wgsl
|
} // namespace wgsl
|
||||||
} // namespace reader
|
} // namespace reader
|
||||||
|
@ -102,6 +102,8 @@ std::string Token::TypeToName(Type type) {
|
|||||||
return ";";
|
return ";";
|
||||||
case Token::Type::kStar:
|
case Token::Type::kStar:
|
||||||
return "*";
|
return "*";
|
||||||
|
case Token::Type::kTilde:
|
||||||
|
return "~";
|
||||||
case Token::Type::kXor:
|
case Token::Type::kXor:
|
||||||
return "^";
|
return "^";
|
||||||
|
|
||||||
|
@ -110,6 +110,8 @@ class Token {
|
|||||||
kSemicolon,
|
kSemicolon,
|
||||||
/// A '*'
|
/// A '*'
|
||||||
kStar,
|
kStar,
|
||||||
|
/// A '~'
|
||||||
|
kTilde,
|
||||||
/// A '^'
|
/// A '^'
|
||||||
kXor,
|
kXor,
|
||||||
|
|
||||||
@ -445,6 +447,8 @@ class Token {
|
|||||||
bool IsSemicolon() const { return type_ == Type::kSemicolon; }
|
bool IsSemicolon() const { return type_ == Type::kSemicolon; }
|
||||||
/// @returns true if token is a '*'
|
/// @returns true if token is a '*'
|
||||||
bool IsStar() const { return type_ == Type::kStar; }
|
bool IsStar() const { return type_ == Type::kStar; }
|
||||||
|
/// @returns true if token is a '~'
|
||||||
|
bool IsTilde() const { return type_ == Type::kTilde; }
|
||||||
/// @returns true if token is a '^'
|
/// @returns true if token is a '^'
|
||||||
bool IsXor() const { return type_ == Type::kXor; }
|
bool IsXor() const { return type_ == Type::kXor; }
|
||||||
|
|
||||||
|
@ -2500,6 +2500,7 @@ bool Resolver::UnaryOp(ast::UnaryOpExpression* unary) {
|
|||||||
const sem::Type* type = nullptr;
|
const sem::Type* type = nullptr;
|
||||||
|
|
||||||
switch (unary->op()) {
|
switch (unary->op()) {
|
||||||
|
case ast::UnaryOp::kComplement:
|
||||||
case ast::UnaryOp::kNegation:
|
case ast::UnaryOp::kNegation:
|
||||||
case ast::UnaryOp::kNot:
|
case ast::UnaryOp::kNot:
|
||||||
// Result type matches the deref'd inner type.
|
// Result type matches the deref'd inner type.
|
||||||
|
@ -1946,7 +1946,8 @@ TEST_P(UnaryOpExpressionTest, Expr_UnaryOp) {
|
|||||||
}
|
}
|
||||||
INSTANTIATE_TEST_SUITE_P(ResolverTest,
|
INSTANTIATE_TEST_SUITE_P(ResolverTest,
|
||||||
UnaryOpExpressionTest,
|
UnaryOpExpressionTest,
|
||||||
testing::Values(ast::UnaryOp::kNegation,
|
testing::Values(ast::UnaryOp::kComplement,
|
||||||
|
ast::UnaryOp::kNegation,
|
||||||
ast::UnaryOp::kNot));
|
ast::UnaryOp::kNot));
|
||||||
|
|
||||||
TEST_F(ResolverTest, StorageClass_SetsIfMissing) {
|
TEST_F(ResolverTest, StorageClass_SetsIfMissing) {
|
||||||
|
@ -2448,6 +2448,9 @@ bool GeneratorImpl::EmitUnaryOp(std::ostream& pre,
|
|||||||
case ast::UnaryOp::kIndirection:
|
case ast::UnaryOp::kIndirection:
|
||||||
case ast::UnaryOp::kAddressOf:
|
case ast::UnaryOp::kAddressOf:
|
||||||
return EmitExpression(pre, out, expr->expr());
|
return EmitExpression(pre, out, expr->expr());
|
||||||
|
case ast::UnaryOp::kComplement:
|
||||||
|
out << "~";
|
||||||
|
break;
|
||||||
case ast::UnaryOp::kNot:
|
case ast::UnaryOp::kNot:
|
||||||
out << "!";
|
out << "!";
|
||||||
break;
|
break;
|
||||||
|
@ -33,6 +33,18 @@ TEST_F(HlslUnaryOpTest, AddressOf) {
|
|||||||
EXPECT_EQ(result(), "expr");
|
EXPECT_EQ(result(), "expr");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(HlslUnaryOpTest, Complement) {
|
||||||
|
Global("expr", ty.f32(), ast::StorageClass::kPrivate);
|
||||||
|
auto* op =
|
||||||
|
create<ast::UnaryOpExpression>(ast::UnaryOp::kComplement, Expr("expr"));
|
||||||
|
WrapInFunction(op);
|
||||||
|
|
||||||
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
|
ASSERT_TRUE(gen.EmitExpression(pre, out, op)) << gen.error();
|
||||||
|
EXPECT_EQ(result(), "~(expr)");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(HlslUnaryOpTest, Indirection) {
|
TEST_F(HlslUnaryOpTest, Indirection) {
|
||||||
Global("G", ty.f32(), ast::StorageClass::kPrivate);
|
Global("G", ty.f32(), ast::StorageClass::kPrivate);
|
||||||
auto* p = Const(
|
auto* p = Const(
|
||||||
|
@ -2288,6 +2288,9 @@ bool GeneratorImpl::EmitUnaryOp(ast::UnaryOpExpression* expr) {
|
|||||||
case ast::UnaryOp::kAddressOf:
|
case ast::UnaryOp::kAddressOf:
|
||||||
out_ << "&";
|
out_ << "&";
|
||||||
break;
|
break;
|
||||||
|
case ast::UnaryOp::kComplement:
|
||||||
|
out_ << "~";
|
||||||
|
break;
|
||||||
case ast::UnaryOp::kIndirection:
|
case ast::UnaryOp::kIndirection:
|
||||||
out_ << "*";
|
out_ << "*";
|
||||||
break;
|
break;
|
||||||
|
@ -33,6 +33,18 @@ TEST_F(MslUnaryOpTest, AddressOf) {
|
|||||||
EXPECT_EQ(gen.result(), "&(expr)");
|
EXPECT_EQ(gen.result(), "&(expr)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(MslUnaryOpTest, Complement) {
|
||||||
|
Global("expr", ty.f32(), ast::StorageClass::kPrivate);
|
||||||
|
auto* op =
|
||||||
|
create<ast::UnaryOpExpression>(ast::UnaryOp::kComplement, Expr("expr"));
|
||||||
|
WrapInFunction(op);
|
||||||
|
|
||||||
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
|
ASSERT_TRUE(gen.EmitExpression(op)) << gen.error();
|
||||||
|
EXPECT_EQ(gen.result(), "~(expr)");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(MslUnaryOpTest, Indirection) {
|
TEST_F(MslUnaryOpTest, Indirection) {
|
||||||
Global("G", ty.f32(), ast::StorageClass::kPrivate);
|
Global("G", ty.f32(), ast::StorageClass::kPrivate);
|
||||||
auto* p = Const(
|
auto* p = Const(
|
||||||
|
@ -1158,6 +1158,9 @@ uint32_t Builder::GenerateUnaryOpExpression(ast::UnaryOpExpression* expr) {
|
|||||||
|
|
||||||
spv::Op op = spv::Op::OpNop;
|
spv::Op op = spv::Op::OpNop;
|
||||||
switch (expr->op()) {
|
switch (expr->op()) {
|
||||||
|
case ast::UnaryOp::kComplement:
|
||||||
|
op = spv::Op::OpNot;
|
||||||
|
break;
|
||||||
case ast::UnaryOp::kNegation:
|
case ast::UnaryOp::kNegation:
|
||||||
if (TypeOf(expr)->is_float_scalar_or_vector()) {
|
if (TypeOf(expr)->is_float_scalar_or_vector()) {
|
||||||
op = spv::Op::OpFNegate;
|
op = spv::Op::OpFNegate;
|
||||||
|
@ -55,6 +55,23 @@ TEST_F(BuilderTest, UnaryOp_Negation_Float) {
|
|||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest, UnaryOp_Complement) {
|
||||||
|
auto* expr =
|
||||||
|
create<ast::UnaryOpExpression>(ast::UnaryOp::kComplement, Expr(1));
|
||||||
|
WrapInFunction(expr);
|
||||||
|
|
||||||
|
spirv::Builder& b = Build();
|
||||||
|
|
||||||
|
b.push_function(Function{});
|
||||||
|
EXPECT_EQ(b.GenerateUnaryOpExpression(expr), 1u) << b.error();
|
||||||
|
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 1
|
||||||
|
%3 = OpConstant %2 1
|
||||||
|
)");
|
||||||
|
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
||||||
|
R"(%1 = OpNot %2 %3
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(BuilderTest, UnaryOp_Not) {
|
TEST_F(BuilderTest, UnaryOp_Not) {
|
||||||
auto* expr = create<ast::UnaryOpExpression>(ast::UnaryOp::kNot, Expr(false));
|
auto* expr = create<ast::UnaryOpExpression>(ast::UnaryOp::kNot, Expr(false));
|
||||||
WrapInFunction(expr);
|
WrapInFunction(expr);
|
||||||
|
@ -761,6 +761,9 @@ bool GeneratorImpl::EmitUnaryOp(ast::UnaryOpExpression* expr) {
|
|||||||
case ast::UnaryOp::kAddressOf:
|
case ast::UnaryOp::kAddressOf:
|
||||||
out_ << "&";
|
out_ << "&";
|
||||||
break;
|
break;
|
||||||
|
case ast::UnaryOp::kComplement:
|
||||||
|
out_ << "~";
|
||||||
|
break;
|
||||||
case ast::UnaryOp::kIndirection:
|
case ast::UnaryOp::kIndirection:
|
||||||
out_ << "*";
|
out_ << "*";
|
||||||
break;
|
break;
|
||||||
|
@ -33,6 +33,18 @@ TEST_F(WgslUnaryOpTest, AddressOf) {
|
|||||||
EXPECT_EQ(gen.result(), "&(expr)");
|
EXPECT_EQ(gen.result(), "&(expr)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(WgslUnaryOpTest, Complement) {
|
||||||
|
Global("expr", ty.f32(), ast::StorageClass::kPrivate);
|
||||||
|
auto* op =
|
||||||
|
create<ast::UnaryOpExpression>(ast::UnaryOp::kComplement, Expr("expr"));
|
||||||
|
WrapInFunction(op);
|
||||||
|
|
||||||
|
GeneratorImpl& gen = Build();
|
||||||
|
|
||||||
|
ASSERT_TRUE(gen.EmitExpression(op)) << gen.error();
|
||||||
|
EXPECT_EQ(gen.result(), "~(expr)");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(WgslUnaryOpTest, Indirection) {
|
TEST_F(WgslUnaryOpTest, Indirection) {
|
||||||
Global("G", ty.f32(), ast::StorageClass::kPrivate);
|
Global("G", ty.f32(), ast::StorageClass::kPrivate);
|
||||||
auto* p = Const(
|
auto* p = Const(
|
||||||
|
15
test/expressions/unary/complement.wgsl
Normal file
15
test/expressions/unary/complement.wgsl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
fn i(x : i32) -> i32 {
|
||||||
|
return ~x;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u(x : u32) -> u32 {
|
||||||
|
return ~x;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vi(x : vec4<i32>) -> vec4<i32> {
|
||||||
|
return ~x;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vu(x : vec4<u32>) -> vec4<u32> {
|
||||||
|
return ~x;
|
||||||
|
}
|
20
test/expressions/unary/complement.wgsl.expected.hlsl
Normal file
20
test/expressions/unary/complement.wgsl.expected.hlsl
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
[numthreads(1, 1, 1)]
|
||||||
|
void unused_entry_point() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i(int x) {
|
||||||
|
return ~(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint u(uint x) {
|
||||||
|
return ~(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
int4 vi(int4 x) {
|
||||||
|
return ~(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint4 vu(uint4 x) {
|
||||||
|
return ~(x);
|
||||||
|
}
|
19
test/expressions/unary/complement.wgsl.expected.msl
Normal file
19
test/expressions/unary/complement.wgsl.expected.msl
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
int i(int x) {
|
||||||
|
return ~(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint u(uint x) {
|
||||||
|
return ~(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
int4 vi(int4 x) {
|
||||||
|
return ~(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint4 vu(uint4 x) {
|
||||||
|
return ~(x);
|
||||||
|
}
|
||||||
|
|
56
test/expressions/unary/complement.wgsl.expected.spvasm
Normal file
56
test/expressions/unary/complement.wgsl.expected.spvasm
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
; SPIR-V
|
||||||
|
; Version: 1.3
|
||||||
|
; Generator: Google Tint Compiler; 0
|
||||||
|
; Bound: 29
|
||||||
|
; Schema: 0
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
|
||||||
|
OpExecutionMode %unused_entry_point LocalSize 1 1 1
|
||||||
|
OpName %unused_entry_point "unused_entry_point"
|
||||||
|
OpName %i "i"
|
||||||
|
OpName %x "x"
|
||||||
|
OpName %u "u"
|
||||||
|
OpName %x_0 "x"
|
||||||
|
OpName %vi "vi"
|
||||||
|
OpName %x_1 "x"
|
||||||
|
OpName %vu "vu"
|
||||||
|
OpName %x_2 "x"
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%1 = OpTypeFunction %void
|
||||||
|
%int = OpTypeInt 32 1
|
||||||
|
%5 = OpTypeFunction %int %int
|
||||||
|
%uint = OpTypeInt 32 0
|
||||||
|
%11 = OpTypeFunction %uint %uint
|
||||||
|
%v4int = OpTypeVector %int 4
|
||||||
|
%17 = OpTypeFunction %v4int %v4int
|
||||||
|
%v4uint = OpTypeVector %uint 4
|
||||||
|
%23 = OpTypeFunction %v4uint %v4uint
|
||||||
|
%unused_entry_point = OpFunction %void None %1
|
||||||
|
%4 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
%i = OpFunction %int None %5
|
||||||
|
%x = OpFunctionParameter %int
|
||||||
|
%9 = OpLabel
|
||||||
|
%10 = OpNot %int %x
|
||||||
|
OpReturnValue %10
|
||||||
|
OpFunctionEnd
|
||||||
|
%u = OpFunction %uint None %11
|
||||||
|
%x_0 = OpFunctionParameter %uint
|
||||||
|
%15 = OpLabel
|
||||||
|
%16 = OpNot %uint %x_0
|
||||||
|
OpReturnValue %16
|
||||||
|
OpFunctionEnd
|
||||||
|
%vi = OpFunction %v4int None %17
|
||||||
|
%x_1 = OpFunctionParameter %v4int
|
||||||
|
%21 = OpLabel
|
||||||
|
%22 = OpNot %v4int %x_1
|
||||||
|
OpReturnValue %22
|
||||||
|
OpFunctionEnd
|
||||||
|
%vu = OpFunction %v4uint None %23
|
||||||
|
%x_2 = OpFunctionParameter %v4uint
|
||||||
|
%27 = OpLabel
|
||||||
|
%28 = OpNot %v4uint %x_2
|
||||||
|
OpReturnValue %28
|
||||||
|
OpFunctionEnd
|
15
test/expressions/unary/complement.wgsl.expected.wgsl
Normal file
15
test/expressions/unary/complement.wgsl.expected.wgsl
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
fn i(x : i32) -> i32 {
|
||||||
|
return ~(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u(x : u32) -> u32 {
|
||||||
|
return ~(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vi(x : vec4<i32>) -> vec4<i32> {
|
||||||
|
return ~(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vu(x : vec4<u32>) -> vec4<u32> {
|
||||||
|
return ~(x);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user