Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(304)

Side by Side Diff: src/sksl/SkSLIRGenerator.cpp

Issue 2288033003: Turned on SkSL->GLSL compiler (Closed)
Patch Set: changed <iostream> to <ostream> Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/sksl/SkSLIRGenerator.h ('k') | src/sksl/SkSLMain.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkSLIRGenerator.h" 8 #include "SkSLIRGenerator.h"
9 9
10 #include "limits.h" 10 #include "limits.h"
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, modifi ers, varDecl.fName, 182 auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, modifi ers, varDecl.fName,
183 *type, storage)); 183 *type, storage));
184 std::unique_ptr<Expression> value; 184 std::unique_ptr<Expression> value;
185 if (varDecl.fValue) { 185 if (varDecl.fValue) {
186 value = this->convertExpression(*varDecl.fValue); 186 value = this->convertExpression(*varDecl.fValue);
187 if (!value) { 187 if (!value) {
188 return nullptr; 188 return nullptr;
189 } 189 }
190 value = this->coerce(std::move(value), *type); 190 value = this->coerce(std::move(value), *type);
191 } 191 }
192 if ("gl_FragCoord" == varDecl.fName && (*fSymbolTable)[varDecl.fName]) { 192 if ("sk_FragColor" == varDecl.fName && (*fSymbolTable)[varDecl.fName]) {
193 // already defined, ignore
194 } else if ((*fSymbolTable)[varDecl.fName] &&
195 (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Ki nd &&
196 ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLay out.fBuiltin >= 0) {
193 // already defined, just update the modifiers 197 // already defined, just update the modifiers
194 Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName]; 198 Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName];
195 old->fModifiers = var->fModifiers; 199 old->fModifiers = var->fModifiers;
196 } else { 200 } else {
197 variables.emplace_back(var.get(), std::move(sizes), std::move(value) ); 201 variables.emplace_back(var.get(), std::move(sizes), std::move(value) );
198 fSymbolTable->add(varDecl.fName, std::move(var)); 202 fSymbolTable->add(varDecl.fName, std::move(var));
199 } 203 }
200 } 204 }
201 return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition, 205 return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition,
202 baseType, 206 baseType,
203 std::move(variab les))); 207 std::move(variab les)));
204 } 208 }
205 209
210 std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(
211 const ASTModifi ersDeclaration& m) {
212 Modifiers modifiers = this->convertModifiers(m.fModifiers);
213 return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifi ers));
214 }
215
206 std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) { 216 std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
207 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.f Test), 217 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.f Test),
208 *fContext.fBool_Type); 218 *fContext.fBool_Type);
209 if (!test) { 219 if (!test) {
210 return nullptr; 220 return nullptr;
211 } 221 }
212 std::unique_ptr<Statement> ifTrue = this->convertStatement(*s.fIfTrue); 222 std::unique_ptr<Statement> ifTrue = this->convertStatement(*s.fIfTrue);
213 if (!ifTrue) { 223 if (!ifTrue) {
214 return nullptr; 224 return nullptr;
215 } 225 }
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 FunctionDeclaration newDecl(f.fPosition, f.fName, parame ters, *returnType); 422 FunctionDeclaration newDecl(f.fPosition, f.fName, parame ters, *returnType);
413 fErrors.error(f.fPosition, "functions '" + newDecl.descr iption() + 423 fErrors.error(f.fPosition, "functions '" + newDecl.descr iption() +
414 "' and '" + other->descriptio n() + 424 "' and '" + other->descriptio n() +
415 "' differ only in return type "); 425 "' differ only in return type ");
416 return nullptr; 426 return nullptr;
417 } 427 }
418 decl = other; 428 decl = other;
419 for (size_t i = 0; i < parameters.size(); i++) { 429 for (size_t i = 0; i < parameters.size(); i++) {
420 if (parameters[i]->fModifiers != other->fParameters[i]-> fModifiers) { 430 if (parameters[i]->fModifiers != other->fParameters[i]-> fModifiers) {
421 fErrors.error(f.fPosition, "modifiers on parameter " + 431 fErrors.error(f.fPosition, "modifiers on parameter " +
422 to_string(i + 1) + " diff er between " + 432 to_string((uint64_t) i + 1) +
423 "declaration and definiti on"); 433 " differ between declarat ion and "
434 "definition");
424 return nullptr; 435 return nullptr;
425 } 436 }
426 } 437 }
427 if (other->fDefined) { 438 if (other->fDefined) {
428 fErrors.error(f.fPosition, "duplicate definition of " + 439 fErrors.error(f.fPosition, "duplicate definition of " +
429 other->description()); 440 other->description());
430 } 441 }
431 break; 442 break;
432 } 443 }
433 } 444 }
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 return nullptr; 620 return nullptr;
610 } 621 }
611 if (type.kind() == Type::kScalar_Kind) { 622 if (type.kind() == Type::kScalar_Kind) {
612 std::vector<std::unique_ptr<Expression>> args; 623 std::vector<std::unique_ptr<Expression>> args;
613 args.push_back(std::move(expr)); 624 args.push_back(std::move(expr));
614 ASTIdentifier id(Position(), type.description()); 625 ASTIdentifier id(Position(), type.description());
615 std::unique_ptr<Expression> ctor = this->convertIdentifier(id); 626 std::unique_ptr<Expression> ctor = this->convertIdentifier(id);
616 ASSERT(ctor); 627 ASSERT(ctor);
617 return this->call(Position(), std::move(ctor), std::move(args)); 628 return this->call(Position(), std::move(ctor), std::move(args));
618 } 629 }
619 ABORT("cannot coerce %s to %s", expr->fType.description().c_str(), 630 std::vector<std::unique_ptr<Expression>> args;
620 type.description().c_str()); 631 args.push_back(std::move(expr));
632 return std::unique_ptr<Expression>(new Constructor(Position(), type, std::mo ve(args)));
621 } 633 }
622 634
623 static bool is_matrix_multiply(const Type& left, const Type& right) { 635 static bool is_matrix_multiply(const Type& left, const Type& right) {
624 if (left.kind() == Type::kMatrix_Kind) { 636 if (left.kind() == Type::kMatrix_Kind) {
625 return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVect or_Kind; 637 return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVect or_Kind;
626 } 638 }
627 return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Ki nd; 639 return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Ki nd;
628 } 640 }
629 /** 641 /**
630 * Determines the operand and result types of a binary expression. Returns true if the expression is 642 * Determines the operand and result types of a binary expression. Returns true if the expression is
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
825 std::move(test), 837 std::move(test),
826 std::move(ifTrue), 838 std::move(ifTrue),
827 std::move(ifFalse)) ); 839 std::move(ifFalse)) );
828 } 840 }
829 841
830 std::unique_ptr<Expression> IRGenerator::call(Position position, 842 std::unique_ptr<Expression> IRGenerator::call(Position position,
831 const FunctionDeclaration& functio n, 843 const FunctionDeclaration& functio n,
832 std::vector<std::unique_ptr<Expres sion>> arguments) { 844 std::vector<std::unique_ptr<Expres sion>> arguments) {
833 if (function.fParameters.size() != arguments.size()) { 845 if (function.fParameters.size() != arguments.size()) {
834 std::string msg = "call to '" + function.fName + "' expected " + 846 std::string msg = "call to '" + function.fName + "' expected " +
835 to_string(function.fParameters.size()) + 847 to_string((uint64_t) function.fParameters.size( )) +
836 " argument"; 848 " argument";
837 if (function.fParameters.size() != 1) { 849 if (function.fParameters.size() != 1) {
838 msg += "s"; 850 msg += "s";
839 } 851 }
840 msg += ", but found " + to_string(arguments.size()); 852 msg += ", but found " + to_string((uint64_t) arguments.size());
841 fErrors.error(position, msg); 853 fErrors.error(position, msg);
842 return nullptr; 854 return nullptr;
843 } 855 }
844 for (size_t i = 0; i < arguments.size(); i++) { 856 for (size_t i = 0; i < arguments.size(); i++) {
845 arguments[i] = this->coerce(std::move(arguments[i]), function.fParameter s[i]->fType); 857 arguments[i] = this->coerce(std::move(arguments[i]), function.fParameter s[i]->fType);
846 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifi ers::kOut_Flag)) { 858 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifi ers::kOut_Flag)) {
847 this->markWrittenTo(*arguments[i]); 859 this->markWrittenTo(*arguments[i]);
848 } 860 }
849 } 861 }
850 return std::unique_ptr<FunctionCall>(new FunctionCall(position, function, 862 return std::unique_ptr<FunctionCall>(new FunctionCall(position, function,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
914 } 926 }
915 return this->call(position, *ref->fFunctions[0], std::move(arguments)); 927 return this->call(position, *ref->fFunctions[0], std::move(arguments));
916 } 928 }
917 929
918 std::unique_ptr<Expression> IRGenerator::convertConstructor( 930 std::unique_ptr<Expression> IRGenerator::convertConstructor(
919 Position position, 931 Position position,
920 const Type& type, 932 const Type& type,
921 std::vector<std::unique_ptr< Expression>> args) { 933 std::vector<std::unique_ptr< Expression>> args) {
922 // FIXME: add support for structs and arrays 934 // FIXME: add support for structs and arrays
923 Type::Kind kind = type.kind(); 935 Type::Kind kind = type.kind();
924 if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_ Kind) { 936 if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_ Kind &&
937 kind != Type::kArray_Kind) {
925 fErrors.error(position, "cannot construct '" + type.description() + "'") ; 938 fErrors.error(position, "cannot construct '" + type.description() + "'") ;
926 return nullptr; 939 return nullptr;
927 } 940 }
928 if (type == *fContext.fFloat_Type && args.size() == 1 && 941 if (type == *fContext.fFloat_Type && args.size() == 1 &&
929 args[0]->fKind == Expression::kIntLiteral_Kind) { 942 args[0]->fKind == Expression::kIntLiteral_Kind) {
930 int64_t value = ((IntLiteral&) *args[0]).fValue; 943 int64_t value = ((IntLiteral&) *args[0]).fValue;
931 return std::unique_ptr<Expression>(new FloatLiteral(fContext, position, (double) value)); 944 return std::unique_ptr<Expression>(new FloatLiteral(fContext, position, (double) value));
932 } 945 }
933 if (args.size() == 1 && args[0]->fType == type) { 946 if (args.size() == 1 && args[0]->fType == type) {
934 // argument is already the right type, just return it 947 // argument is already the right type, just return it
935 return std::move(args[0]); 948 return std::move(args[0]);
936 } 949 }
937 if (type.isNumber()) { 950 if (type.isNumber()) {
938 if (args.size() != 1) { 951 if (args.size() != 1) {
939 fErrors.error(position, "invalid arguments to '" + type.description( ) + 952 fErrors.error(position, "invalid arguments to '" + type.description( ) +
940 "' constructor, (expected exactly 1 argument , but found " + 953 "' constructor, (expected exactly 1 argument , but found " +
941 to_string(args.size()) + ")"); 954 to_string((uint64_t) args.size()) + ")");
942 } 955 }
943 if (args[0]->fType == *fContext.fBool_Type) { 956 if (args[0]->fType == *fContext.fBool_Type) {
944 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0)); 957 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0));
945 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, position, 1 )); 958 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, position, 1 ));
946 return std::unique_ptr<Expression>( 959 return std::unique_ptr<Expression>(
947 new TernaryExpression(position, std::mo ve(args[0]), 960 new TernaryExpression(position, std::mo ve(args[0]),
948 this->coerce(std: :move(one), type), 961 this->coerce(std: :move(one), type),
949 this->coerce(std: :move(zero), 962 this->coerce(std: :move(zero),
950 type ))); 963 type )));
951 } else if (!args[0]->fType.isNumber()) { 964 } else if (!args[0]->fType.isNumber()) {
952 fErrors.error(position, "invalid argument to '" + type.description() + 965 fErrors.error(position, "invalid argument to '" + type.description() +
953 "' constructor (expected a number or bool, b ut found '" + 966 "' constructor (expected a number or bool, b ut found '" +
954 args[0]->fType.description() + "')"); 967 args[0]->fType.description() + "')");
955 } 968 }
969 if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext .fInt_Type ||
970 type == *fContext.fUInt_Type)) {
971 return std::unique_ptr<Expression>(new IntLiteral(fContext,
972 position,
973 ((IntLiteral&) *ar gs[0]).fValue,
974 &type));
975 }
976 } else if (kind == Type::kArray_Kind) {
977 const Type& base = type.componentType();
978 for (size_t i = 0; i < args.size(); i++) {
979 args[i] = this->coerce(std::move(args[i]), base);
980 }
956 } else { 981 } else {
957 ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind); 982 ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind);
958 int actual = 0; 983 int actual = 0;
959 for (size_t i = 0; i < args.size(); i++) { 984 for (size_t i = 0; i < args.size(); i++) {
960 if (args[i]->fType.kind() == Type::kVector_Kind || 985 if (args[i]->fType.kind() == Type::kVector_Kind ||
961 args[i]->fType.kind() == Type::kMatrix_Kind) { 986 args[i]->fType.kind() == Type::kMatrix_Kind) {
962 int columns = args[i]->fType.columns(); 987 int columns = args[i]->fType.columns();
963 int rows = args[i]->fType.rows(); 988 int rows = args[i]->fType.rows();
964 args[i] = this->coerce(std::move(args[i]), 989 args[i] = this->coerce(std::move(args[i]),
965 type.componentType().toCompound(fContext, columns, rows)); 990 type.componentType().toCompound(fContext, columns, rows));
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 break; 1055 break;
1031 case Token::MINUSMINUS: 1056 case Token::MINUSMINUS:
1032 if (!base->fType.isNumber()) { 1057 if (!base->fType.isNumber()) {
1033 fErrors.error(expression.fPosition, 1058 fErrors.error(expression.fPosition,
1034 "'" + Token::OperatorName(expression.fOperator) + 1059 "'" + Token::OperatorName(expression.fOperator) +
1035 "' cannot operate on '" + base->fType.description( ) + "'"); 1060 "' cannot operate on '" + base->fType.description( ) + "'");
1036 return nullptr; 1061 return nullptr;
1037 } 1062 }
1038 this->markWrittenTo(*base); 1063 this->markWrittenTo(*base);
1039 break; 1064 break;
1040 case Token::NOT: 1065 case Token::LOGICALNOT:
1041 if (base->fType != *fContext.fBool_Type) { 1066 if (base->fType != *fContext.fBool_Type) {
1042 fErrors.error(expression.fPosition, 1067 fErrors.error(expression.fPosition,
1043 "'" + Token::OperatorName(expression.fOperator) + 1068 "'" + Token::OperatorName(expression.fOperator) +
1044 "' cannot operate on '" + base->fType.description( ) + "'"); 1069 "' cannot operate on '" + base->fType.description( ) + "'");
1045 return nullptr; 1070 return nullptr;
1046 } 1071 }
1047 break; 1072 break;
1073 case Token::BITWISENOT:
1074 if (base->fType != *fContext.fInt_Type) {
1075 fErrors.error(expression.fPosition,
1076 "'" + Token::OperatorName(expression.fOperator) +
1077 "' cannot operate on '" + base->fType.description( ) + "'");
1078 return nullptr;
1079 }
1080 break;
1048 default: 1081 default:
1049 ABORT("unsupported prefix operator\n"); 1082 ABORT("unsupported prefix operator\n");
1050 } 1083 }
1051 return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator , 1084 return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator ,
1052 std::move(base))); 1085 std::move(base)));
1053 } 1086 }
1054 1087
1055 std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression > base, 1088 std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression > base,
1056 const ASTExpression& index ) { 1089 const ASTExpression& index ) {
1057 if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::k Matrix_Kind) { 1090 if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::k Matrix_Kind &&
1091 base->fType.kind() != Type::kVector_Kind) {
1058 fErrors.error(base->fPosition, "expected array, but found '" + base->fTy pe.description() + 1092 fErrors.error(base->fPosition, "expected array, but found '" + base->fTy pe.description() +
1059 "'"); 1093 "'");
1060 return nullptr; 1094 return nullptr;
1061 } 1095 }
1062 std::unique_ptr<Expression> converted = this->convertExpression(index); 1096 std::unique_ptr<Expression> converted = this->convertExpression(index);
1063 if (!converted) { 1097 if (!converted) {
1064 return nullptr; 1098 return nullptr;
1065 } 1099 }
1066 converted = this->coerce(std::move(converted), *fContext.fInt_Type); 1100 if (converted->fType != *fContext.fUInt_Type) {
1067 if (!converted) { 1101 converted = this->coerce(std::move(converted), *fContext.fInt_Type);
1068 return nullptr; 1102 if (!converted) {
1103 return nullptr;
1104 }
1069 } 1105 }
1070 return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(b ase), 1106 return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(b ase),
1071 std::move(converted)) ); 1107 std::move(converted)) );
1072 } 1108 }
1073 1109
1074 std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression > base, 1110 std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression > base,
1075 const std::string& field) { 1111 const std::string& field) {
1076 auto fields = base->fType.fields(); 1112 auto fields = base->fType.fields();
1077 for (size_t i = 0; i < fields.size(); i++) { 1113 for (size_t i = 0; i < fields.size(); i++) {
1078 if (fields[i].fName == field) { 1114 if (fields[i].fName == field) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1136 return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), sw izzleComponents)); 1172 return std::unique_ptr<Expression>(new Swizzle(fContext, std::move(base), sw izzleComponents));
1137 } 1173 }
1138 1174
1139 std::unique_ptr<Expression> IRGenerator::convertSuffixExpression( 1175 std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
1140 const ASTSuffixExpre ssion& expression) { 1176 const ASTSuffixExpre ssion& expression) {
1141 std::unique_ptr<Expression> base = this->convertExpression(*expression.fBase ); 1177 std::unique_ptr<Expression> base = this->convertExpression(*expression.fBase );
1142 if (!base) { 1178 if (!base) {
1143 return nullptr; 1179 return nullptr;
1144 } 1180 }
1145 switch (expression.fSuffix->fKind) { 1181 switch (expression.fSuffix->fKind) {
1146 case ASTSuffix::kIndex_Kind: 1182 case ASTSuffix::kIndex_Kind: {
1147 return this->convertIndex(std::move(base), 1183 const ASTExpression* expr = ((ASTIndexSuffix&) *expression.fSuffix). fExpression.get();
1148 *((ASTIndexSuffix&) *expression.fSuffix).f Expression); 1184 if (expr) {
1185 return this->convertIndex(std::move(base), *expr);
1186 } else if (base->fKind == Expression::kTypeReference_Kind) {
1187 const Type& oldType = ((TypeReference&) *base).fValue;
1188 Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kin d, oldType,
1189 -1);
1190 fSymbolTable->takeOwnership(newType);
1191 return std::unique_ptr<Expression>(new TypeReference(fContext, b ase->fPosition,
1192 *newType));
1193 } else {
1194 fErrors.error(expression.fPosition, "'[]' must follow a type nam e");
1195 }
1196 }
1149 case ASTSuffix::kCall_Kind: { 1197 case ASTSuffix::kCall_Kind: {
1150 auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArgumen ts; 1198 auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArgumen ts;
1151 std::vector<std::unique_ptr<Expression>> arguments; 1199 std::vector<std::unique_ptr<Expression>> arguments;
1152 for (size_t i = 0; i < rawArguments->size(); i++) { 1200 for (size_t i = 0; i < rawArguments->size(); i++) {
1153 std::unique_ptr<Expression> converted = 1201 std::unique_ptr<Expression> converted =
1154 this->convertExpression(*(*rawArguments)[i]); 1202 this->convertExpression(*(*rawArguments)[i]);
1155 if (!converted) { 1203 if (!converted) {
1156 return nullptr; 1204 return nullptr;
1157 } 1205 }
1158 arguments.push_back(std::move(converted)); 1206 arguments.push_back(std::move(converted));
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1251 case Expression::kIndex_Kind: 1299 case Expression::kIndex_Kind:
1252 this->markWrittenTo(*((IndexExpression&) expr).fBase); 1300 this->markWrittenTo(*((IndexExpression&) expr).fBase);
1253 break; 1301 break;
1254 default: 1302 default:
1255 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio n() + "'"); 1303 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio n() + "'");
1256 break; 1304 break;
1257 } 1305 }
1258 } 1306 }
1259 1307
1260 } 1308 }
OLDNEW
« no previous file with comments | « src/sksl/SkSLIRGenerator.h ('k') | src/sksl/SkSLMain.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698