| Index: src/sksl/SkSLIRGenerator.cpp
|
| diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
|
| index b93cbfbe9931495765f20b2e8f86e614c59c0980..07fd9e27b0ade573bae73994bcac6c91163a10d6 100644
|
| --- a/src/sksl/SkSLIRGenerator.cpp
|
| +++ b/src/sksl/SkSLIRGenerator.cpp
|
| @@ -204,10 +204,11 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa
|
| }
|
| value = this->coerce(std::move(value), *type);
|
| }
|
| - if ("sk_FragColor" == varDecl.fName && (*fSymbolTable)[varDecl.fName]) {
|
| + if (storage == Variable::kGlobal_Storage && "sk_FragColor" == varDecl.fName &&
|
| + (*fSymbolTable)[varDecl.fName]) {
|
| // already defined, ignore
|
| - } else if ((*fSymbolTable)[varDecl.fName] &&
|
| - (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Kind &&
|
| + } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[varDecl.fName] &&
|
| + (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Kind &&
|
| ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLayout.fBuiltin >= 0) {
|
| // already defined, just update the modifiers
|
| Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName];
|
| @@ -677,6 +678,29 @@ static bool is_matrix_multiply(const Type& left, const Type& right) {
|
| }
|
| return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Kind;
|
| }
|
| +
|
| +static bool is_assignment(Token::Kind op) {
|
| + switch (op) {
|
| + case Token::EQ: // fall through
|
| + case Token::PLUSEQ: // fall through
|
| + case Token::MINUSEQ: // fall through
|
| + case Token::STAREQ: // fall through
|
| + case Token::SLASHEQ: // fall through
|
| + case Token::PERCENTEQ: // fall through
|
| + case Token::SHLEQ: // fall through
|
| + case Token::SHREQ: // fall through
|
| + case Token::BITWISEOREQ: // fall through
|
| + case Token::BITWISEXOREQ: // fall through
|
| + case Token::BITWISEANDEQ: // fall through
|
| + case Token::LOGICALOREQ: // fall through
|
| + case Token::LOGICALXOREQ: // fall through
|
| + case Token::LOGICALANDEQ:
|
| + return true;
|
| + default:
|
| + return false;
|
| + }
|
| +}
|
| +
|
| /**
|
| * Determines the operand and result types of a binary expression. Returns true if the expression is
|
| * legal, false otherwise. If false, the values of the out parameters are undefined.
|
| @@ -690,14 +714,24 @@ static bool determine_binary_type(const Context& context,
|
| const Type** outResultType,
|
| bool tryFlipped) {
|
| bool isLogical;
|
| + bool validMatrixOrVectorOp;
|
| switch (op) {
|
| + case Token::EQ:
|
| + *outLeftType = &left;
|
| + *outRightType = &left;
|
| + *outResultType = &left;
|
| + return right.canCoerceTo(left);
|
| case Token::EQEQ: // fall through
|
| - case Token::NEQ: // fall through
|
| + case Token::NEQ:
|
| + isLogical = true;
|
| + validMatrixOrVectorOp = true;
|
| + break;
|
| case Token::LT: // fall through
|
| case Token::GT: // fall through
|
| case Token::LTEQ: // fall through
|
| case Token::GTEQ:
|
| isLogical = true;
|
| + validMatrixOrVectorOp = false;
|
| break;
|
| case Token::LOGICALOR: // fall through
|
| case Token::LOGICALAND: // fall through
|
| @@ -748,13 +782,26 @@ static bool determine_binary_type(const Context& context,
|
| return false;
|
| }
|
| }
|
| - // fall through
|
| + isLogical = false;
|
| + validMatrixOrVectorOp = true;
|
| + break;
|
| + case Token::PLUS: // fall through
|
| + case Token::PLUSEQ: // fall through
|
| + case Token::MINUS: // fall through
|
| + case Token::MINUSEQ: // fall through
|
| + case Token::SLASH: // fall through
|
| + case Token::SLASHEQ:
|
| + isLogical = false;
|
| + validMatrixOrVectorOp = true;
|
| + break;
|
| default:
|
| isLogical = false;
|
| + validMatrixOrVectorOp = false;
|
| }
|
| - // FIXME: need to disallow illegal operations like vec3 > vec3. Also do not currently have
|
| - // full support for numbers other than float.
|
| - if (left == right) {
|
| + bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
|
| + // FIXME: incorrect for shift
|
| + if (right.canCoerceTo(left) && (left.kind() == Type::kScalar_Kind ||
|
| + (isVectorOrMatrix && validMatrixOrVectorOp))) {
|
| *outLeftType = &left;
|
| *outRightType = &left;
|
| if (isLogical) {
|
| @@ -764,17 +811,6 @@ static bool determine_binary_type(const Context& context,
|
| }
|
| return true;
|
| }
|
| - // FIXME: incorrect for shift operations
|
| - if (left.canCoerceTo(right)) {
|
| - *outLeftType = &right;
|
| - *outRightType = &right;
|
| - if (isLogical) {
|
| - *outResultType = context.fBool_Type.get();
|
| - } else {
|
| - *outResultType = &right;
|
| - }
|
| - return true;
|
| - }
|
| if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
|
| (right.kind() == Type::kScalar_Kind)) {
|
| if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
|
| @@ -809,38 +845,25 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
|
| const Type* rightType;
|
| const Type* resultType;
|
| if (!determine_binary_type(fContext, expression.fOperator, left->fType, right->fType, &leftType,
|
| - &rightType, &resultType, true)) {
|
| + &rightType, &resultType, !is_assignment(expression.fOperator))) {
|
| fErrors.error(expression.fPosition, "type mismatch: '" +
|
| Token::OperatorName(expression.fOperator) +
|
| "' cannot operate on '" + left->fType.fName +
|
| "', '" + right->fType.fName + "'");
|
| return nullptr;
|
| }
|
| - switch (expression.fOperator) {
|
| - case Token::EQ: // fall through
|
| - case Token::PLUSEQ: // fall through
|
| - case Token::MINUSEQ: // fall through
|
| - case Token::STAREQ: // fall through
|
| - case Token::SLASHEQ: // fall through
|
| - case Token::PERCENTEQ: // fall through
|
| - case Token::SHLEQ: // fall through
|
| - case Token::SHREQ: // fall through
|
| - case Token::BITWISEOREQ: // fall through
|
| - case Token::BITWISEXOREQ: // fall through
|
| - case Token::BITWISEANDEQ: // fall through
|
| - case Token::LOGICALOREQ: // fall through
|
| - case Token::LOGICALXOREQ: // fall through
|
| - case Token::LOGICALANDEQ:
|
| - this->markWrittenTo(*left);
|
| - default:
|
| - break;
|
| + if (is_assignment(expression.fOperator)) {
|
| + this->markWrittenTo(*left);
|
| + }
|
| + left = this->coerce(std::move(left), *leftType);
|
| + right = this->coerce(std::move(right), *rightType);
|
| + if (!left || !right) {
|
| + return nullptr;
|
| }
|
| return std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition,
|
| - this->coerce(std::move(left),
|
| - *leftType),
|
| + std::move(left),
|
| expression.fOperator,
|
| - this->coerce(std::move(right),
|
| - *rightType),
|
| + std::move(right),
|
| *resultType));
|
| }
|
|
|
| @@ -894,6 +917,9 @@ std::unique_ptr<Expression> IRGenerator::call(Position position,
|
| }
|
| for (size_t i = 0; i < arguments.size(); i++) {
|
| arguments[i] = this->coerce(std::move(arguments[i]), function.fParameters[i]->fType);
|
| + if (!arguments[i]) {
|
| + return nullptr;
|
| + }
|
| if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifiers::kOut_Flag)) {
|
| this->markWrittenTo(*arguments[i]);
|
| }
|
| @@ -991,6 +1017,7 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor(
|
| fErrors.error(position, "invalid arguments to '" + type.description() +
|
| "' constructor, (expected exactly 1 argument, but found " +
|
| to_string((uint64_t) args.size()) + ")");
|
| + return nullptr;
|
| }
|
| if (args[0]->fType == *fContext.fBool_Type) {
|
| std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0));
|
| @@ -1016,6 +1043,9 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor(
|
| const Type& base = type.componentType();
|
| for (size_t i = 0; i < args.size(); i++) {
|
| args[i] = this->coerce(std::move(args[i]), base);
|
| + if (!args[i]) {
|
| + return nullptr;
|
| + }
|
| }
|
| } else {
|
| ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind);
|
| @@ -1299,8 +1329,9 @@ void IRGenerator::checkValid(const Expression& expr) {
|
| fErrors.error(expr.fPosition, "expected '(' to begin constructor invocation");
|
| break;
|
| default:
|
| - ASSERT(expr.fType != *fContext.fInvalid_Type);
|
| - break;
|
| + if (expr.fType == *fContext.fInvalid_Type) {
|
| + fErrors.error(expr.fPosition, "invalid expression");
|
| + }
|
| }
|
| }
|
|
|
|
|