1/* 2 * Copyright 2020 Google LLC 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "src/sksl/SkSLDehydrator.h" 9 10#include <map> 11 12#include "include/private/SkSLProgramElement.h" 13#include "include/private/SkSLStatement.h" 14#include "include/private/SkSLSymbol.h" 15#include "src/sksl/SkSLRehydrator.h" 16#include "src/sksl/ir/SkSLBinaryExpression.h" 17#include "src/sksl/ir/SkSLBreakStatement.h" 18#include "src/sksl/ir/SkSLConstructor.h" 19#include "src/sksl/ir/SkSLConstructorArray.h" 20#include "src/sksl/ir/SkSLConstructorArrayCast.h" 21#include "src/sksl/ir/SkSLConstructorCompound.h" 22#include "src/sksl/ir/SkSLConstructorCompoundCast.h" 23#include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h" 24#include "src/sksl/ir/SkSLConstructorMatrixResize.h" 25#include "src/sksl/ir/SkSLConstructorScalarCast.h" 26#include "src/sksl/ir/SkSLConstructorSplat.h" 27#include "src/sksl/ir/SkSLConstructorStruct.h" 28#include "src/sksl/ir/SkSLContinueStatement.h" 29#include "src/sksl/ir/SkSLDiscardStatement.h" 30#include "src/sksl/ir/SkSLDoStatement.h" 31#include "src/sksl/ir/SkSLExpressionStatement.h" 32#include "src/sksl/ir/SkSLField.h" 33#include "src/sksl/ir/SkSLFieldAccess.h" 34#include "src/sksl/ir/SkSLForStatement.h" 35#include "src/sksl/ir/SkSLFunctionCall.h" 36#include "src/sksl/ir/SkSLFunctionDeclaration.h" 37#include "src/sksl/ir/SkSLFunctionDefinition.h" 38#include "src/sksl/ir/SkSLIfStatement.h" 39#include "src/sksl/ir/SkSLIndexExpression.h" 40#include "src/sksl/ir/SkSLInlineMarker.h" 41#include "src/sksl/ir/SkSLInterfaceBlock.h" 42#include "src/sksl/ir/SkSLLiteral.h" 43#include "src/sksl/ir/SkSLPostfixExpression.h" 44#include "src/sksl/ir/SkSLPrefixExpression.h" 45#include "src/sksl/ir/SkSLReturnStatement.h" 46#include "src/sksl/ir/SkSLSetting.h" 47#include "src/sksl/ir/SkSLStructDefinition.h" 48#include "src/sksl/ir/SkSLSwitchCase.h" 49#include "src/sksl/ir/SkSLSwitchStatement.h" 50#include "src/sksl/ir/SkSLSwizzle.h" 51#include "src/sksl/ir/SkSLSymbolAlias.h" 52#include "src/sksl/ir/SkSLSymbolTable.h" 53#include "src/sksl/ir/SkSLTernaryExpression.h" 54#include "src/sksl/ir/SkSLUnresolvedFunction.h" 55#include "src/sksl/ir/SkSLVarDeclarations.h" 56#include "src/sksl/ir/SkSLVariable.h" 57 58#ifdef SKSL_STANDALONE 59 60namespace SkSL { 61 62static constexpr int HEADER_SIZE = 2; 63 64class AutoDehydratorSymbolTable { 65public: 66 AutoDehydratorSymbolTable(Dehydrator* dehydrator, const std::shared_ptr<SymbolTable>& symbols) 67 : fDehydrator(dehydrator) { 68 dehydrator->fSymbolMap.emplace_back(); 69 if (symbols) { 70 dehydrator->write(*symbols); 71 } else { 72 dehydrator->writeCommand(Rehydrator::kVoid_Command); 73 } 74 } 75 76 ~AutoDehydratorSymbolTable() { 77 fDehydrator->fSymbolMap.pop_back(); 78 } 79 80private: 81 Dehydrator* fDehydrator; 82}; 83 84void Dehydrator::write(Layout l) { 85 if (l == Layout()) { 86 this->writeCommand(Rehydrator::kDefaultLayout_Command); 87 } else if (l == Layout::builtin(l.fBuiltin)) { 88 this->writeCommand(Rehydrator::kBuiltinLayout_Command); 89 this->writeS16(l.fBuiltin); 90 } else { 91 this->writeCommand(Rehydrator::kLayout_Command); 92 fBody.write32(l.fFlags); 93 this->writeS8(l.fLocation); 94 this->writeS8(l.fOffset); 95 this->writeS8(l.fBinding); 96 this->writeS8(l.fIndex); 97 this->writeS8(l.fSet); 98 this->writeS16(l.fBuiltin); 99 this->writeS8(l.fInputAttachmentIndex); 100 } 101} 102 103void Dehydrator::write(Modifiers m) { 104 if (m == Modifiers()) { 105 this->writeCommand(Rehydrator::kDefaultModifiers_Command); 106 } else { 107 if (m.fFlags <= 255) { 108 this->writeCommand(Rehydrator::kModifiers8Bit_Command); 109 this->write(m.fLayout); 110 this->writeU8(m.fFlags); 111 } else { 112 this->writeCommand(Rehydrator::kModifiers_Command); 113 this->write(m.fLayout); 114 this->writeS32(m.fFlags); 115 } 116 } 117} 118 119void Dehydrator::write(skstd::string_view s) { 120 this->write(String(s)); 121} 122 123void Dehydrator::write(String s) { 124 auto found = fStrings.find(s); 125 int offset; 126 if (found == fStrings.end()) { 127 offset = fStringBuffer.str().length() + HEADER_SIZE; 128 fStrings.insert({ s, offset }); 129 SkASSERT(s.length() <= 255); 130 fStringBreaks.add(fStringBuffer.bytesWritten()); 131 fStringBuffer.write8(s.length()); 132 fStringBuffer.writeString(s); 133 } else { 134 offset = found->second; 135 } 136 this->writeU16(offset); 137} 138 139void Dehydrator::write(const Symbol& s) { 140 uint16_t id = this->symbolId(&s, false); 141 if (id) { 142 this->writeCommand(Rehydrator::kSymbolRef_Command); 143 this->writeU16(id); 144 return; 145 } 146 switch (s.kind()) { 147 case Symbol::Kind::kFunctionDeclaration: { 148 const FunctionDeclaration& f = s.as<FunctionDeclaration>(); 149 this->writeCommand(Rehydrator::kFunctionDeclaration_Command); 150 this->writeId(&f); 151 this->write(f.modifiers()); 152 this->write(f.name()); 153 this->writeU8(f.parameters().size()); 154 for (const Variable* p : f.parameters()) { 155 this->writeU16(this->symbolId(p)); 156 } 157 this->write(f.returnType()); 158 break; 159 } 160 case Symbol::Kind::kSymbolAlias: { 161 const SymbolAlias& alias = s.as<SymbolAlias>(); 162 this->writeCommand(Rehydrator::kSymbolAlias_Command); 163 this->writeId(&alias); 164 this->write(alias.name()); 165 this->write(*alias.origSymbol()); 166 break; 167 } 168 case Symbol::Kind::kUnresolvedFunction: { 169 const UnresolvedFunction& f = s.as<UnresolvedFunction>(); 170 this->writeCommand(Rehydrator::kUnresolvedFunction_Command); 171 this->writeId(&f); 172 this->writeU8(f.functions().size()); 173 for (const FunctionDeclaration* funcDecl : f.functions()) { 174 this->write(*funcDecl); 175 } 176 break; 177 } 178 case Symbol::Kind::kType: { 179 const Type& t = s.as<Type>(); 180 switch (t.typeKind()) { 181 case Type::TypeKind::kArray: 182 this->writeCommand(Rehydrator::kArrayType_Command); 183 this->writeId(&t); 184 this->write(t.componentType()); 185 this->writeS8(t.columns()); 186 break; 187 case Type::TypeKind::kStruct: 188 this->writeCommand(Rehydrator::kStructType_Command); 189 this->writeId(&t); 190 this->write(t.name()); 191 this->writeU8(t.fields().size()); 192 for (const Type::Field& f : t.fields()) { 193 this->write(f.fModifiers); 194 this->write(f.fName); 195 this->write(*f.fType); 196 } 197 break; 198 default: 199 this->writeCommand(Rehydrator::kSystemType_Command); 200 this->writeId(&t); 201 this->write(t.name()); 202 break; 203 } 204 break; 205 } 206 case Symbol::Kind::kVariable: { 207 const Variable& v = s.as<Variable>(); 208 this->writeCommand(Rehydrator::kVariable_Command); 209 this->writeId(&v); 210 this->write(v.modifiers()); 211 this->write(v.name()); 212 this->write(v.type()); 213 this->writeU8((int8_t) v.storage()); 214 break; 215 } 216 case Symbol::Kind::kField: { 217 const Field& f = s.as<Field>(); 218 this->writeCommand(Rehydrator::kField_Command); 219 this->writeU16(this->symbolId(&f.owner())); 220 this->writeU8(f.fieldIndex()); 221 break; 222 } 223 case Symbol::Kind::kExternal: 224 SkASSERT(false); 225 break; 226 } 227} 228 229void Dehydrator::write(const SymbolTable& symbols) { 230 this->writeCommand(Rehydrator::kSymbolTable_Command); 231 this->writeU16(symbols.fOwnedSymbols.size()); 232 for (const std::unique_ptr<const Symbol>& s : symbols.fOwnedSymbols) { 233 this->write(*s); 234 } 235 this->writeU16(symbols.fSymbols.count()); 236 std::map<skstd::string_view, const Symbol*> ordered; 237 symbols.foreach([&](skstd::string_view name, const Symbol* symbol) { 238 ordered.insert({name, symbol}); 239 }); 240 for (std::pair<skstd::string_view, const Symbol*> p : ordered) { 241 SkDEBUGCODE(bool found = false;) 242 for (size_t i = 0; i < symbols.fOwnedSymbols.size(); ++i) { 243 if (symbols.fOwnedSymbols[i].get() == p.second) { 244 fCommandBreaks.add(fBody.bytesWritten()); 245 this->writeU16(i); 246 SkDEBUGCODE(found = true;) 247 break; 248 } 249 } 250 SkASSERT(found); 251 } 252} 253 254void Dehydrator::writeExpressionSpan(const SkSpan<const std::unique_ptr<Expression>>& span) { 255 this->writeU8(span.size()); 256 for (const auto& expr : span) { 257 this->write(expr.get()); 258 } 259} 260 261void Dehydrator::write(const Expression* e) { 262 if (e) { 263 switch (e->kind()) { 264 case Expression::Kind::kBinary: { 265 const BinaryExpression& b = e->as<BinaryExpression>(); 266 this->writeCommand(Rehydrator::kBinary_Command); 267 this->write(b.left().get()); 268 this->writeU8((int) b.getOperator().kind()); 269 this->write(b.right().get()); 270 break; 271 } 272 case Expression::Kind::kChildCall: 273 SkDEBUGFAIL("unimplemented--not expected to be used from within an include file"); 274 break; 275 276 case Expression::Kind::kCodeString: 277 SkDEBUGFAIL("shouldn't be able to receive kCodeString here"); 278 break; 279 280 case Expression::Kind::kConstructorArray: 281 this->writeCommand(Rehydrator::kConstructorArray_Command); 282 this->write(e->type()); 283 this->writeExpressionSpan(e->as<ConstructorArray>().argumentSpan()); 284 break; 285 286 case Expression::Kind::kConstructorArrayCast: 287 this->writeCommand(Rehydrator::kConstructorArrayCast_Command); 288 this->write(e->type()); 289 this->writeExpressionSpan(e->as<ConstructorArrayCast>().argumentSpan()); 290 break; 291 292 case Expression::Kind::kConstructorCompound: 293 this->writeCommand(Rehydrator::kConstructorCompound_Command); 294 this->write(e->type()); 295 this->writeExpressionSpan(e->as<ConstructorCompound>().argumentSpan()); 296 break; 297 298 case Expression::Kind::kConstructorCompoundCast: 299 this->writeCommand(Rehydrator::kConstructorCompoundCast_Command); 300 this->write(e->type()); 301 this->writeExpressionSpan(e->as<ConstructorCompoundCast>().argumentSpan()); 302 break; 303 304 case Expression::Kind::kConstructorDiagonalMatrix: 305 this->writeCommand(Rehydrator::kConstructorDiagonalMatrix_Command); 306 this->write(e->type()); 307 this->writeExpressionSpan(e->as<ConstructorDiagonalMatrix>().argumentSpan()); 308 break; 309 310 case Expression::Kind::kConstructorMatrixResize: 311 this->writeCommand(Rehydrator::kConstructorMatrixResize_Command); 312 this->write(e->type()); 313 this->writeExpressionSpan(e->as<ConstructorMatrixResize>().argumentSpan()); 314 break; 315 316 case Expression::Kind::kConstructorScalarCast: 317 this->writeCommand(Rehydrator::kConstructorScalarCast_Command); 318 this->write(e->type()); 319 this->writeExpressionSpan(e->as<ConstructorScalarCast>().argumentSpan()); 320 break; 321 322 case Expression::Kind::kConstructorSplat: 323 this->writeCommand(Rehydrator::kConstructorSplat_Command); 324 this->write(e->type()); 325 this->writeExpressionSpan(e->as<ConstructorSplat>().argumentSpan()); 326 break; 327 328 case Expression::Kind::kConstructorStruct: 329 this->writeCommand(Rehydrator::kConstructorStruct_Command); 330 this->write(e->type()); 331 this->writeExpressionSpan(e->as<ConstructorStruct>().argumentSpan()); 332 break; 333 334 case Expression::Kind::kExternalFunctionCall: 335 case Expression::Kind::kExternalFunctionReference: 336 SkDEBUGFAIL("unimplemented--not expected to be used from within an include file"); 337 break; 338 339 case Expression::Kind::kFieldAccess: { 340 const FieldAccess& f = e->as<FieldAccess>(); 341 this->writeCommand(Rehydrator::kFieldAccess_Command); 342 this->write(f.base().get()); 343 this->writeU8(f.fieldIndex()); 344 this->writeU8((int8_t) f.ownerKind()); 345 break; 346 } 347 case Expression::Kind::kFunctionCall: { 348 const FunctionCall& f = e->as<FunctionCall>(); 349 this->writeCommand(Rehydrator::kFunctionCall_Command); 350 this->write(f.type()); 351 this->writeId(&f.function()); 352 this->writeU8(f.arguments().size()); 353 for (const auto& a : f.arguments()) { 354 this->write(a.get()); 355 } 356 break; 357 } 358 case Expression::Kind::kIndex: { 359 const IndexExpression& i = e->as<IndexExpression>(); 360 this->writeCommand(Rehydrator::kIndex_Command); 361 this->write(i.base().get()); 362 this->write(i.index().get()); 363 break; 364 } 365 case Expression::Kind::kLiteral: { 366 const Literal& l = e->as<Literal>(); 367 if (l.type().isFloat()) { 368 float value = l.floatValue(); 369 int32_t floatBits; 370 memcpy(&floatBits, &value, sizeof(floatBits)); 371 this->writeCommand(Rehydrator::kFloatLiteral_Command); 372 this->write(l.type()); 373 this->writeS32(floatBits); 374 } else if (l.type().isBoolean()) { 375 this->writeCommand(Rehydrator::kBoolLiteral_Command); 376 this->writeU8(l.boolValue()); 377 } else { 378 SkASSERT(l.type().isInteger()); 379 this->writeCommand(Rehydrator::kIntLiteral_Command); 380 this->write(l.type()); 381 this->writeS32(l.intValue()); 382 } 383 break; 384 } 385 case Expression::Kind::kPostfix: { 386 const PostfixExpression& p = e->as<PostfixExpression>(); 387 this->writeCommand(Rehydrator::kPostfix_Command); 388 this->writeU8((int) p.getOperator().kind()); 389 this->write(p.operand().get()); 390 break; 391 } 392 case Expression::Kind::kPrefix: { 393 const PrefixExpression& p = e->as<PrefixExpression>(); 394 this->writeCommand(Rehydrator::kPrefix_Command); 395 this->writeU8((int) p.getOperator().kind()); 396 this->write(p.operand().get()); 397 break; 398 } 399 case Expression::Kind::kSetting: { 400 const Setting& s = e->as<Setting>(); 401 this->writeCommand(Rehydrator::kSetting_Command); 402 this->write(s.name()); 403 break; 404 } 405 case Expression::Kind::kSwizzle: { 406 const Swizzle& s = e->as<Swizzle>(); 407 this->writeCommand(Rehydrator::kSwizzle_Command); 408 this->write(s.base().get()); 409 this->writeU8(s.components().size()); 410 for (int c : s.components()) { 411 this->writeU8(c); 412 } 413 break; 414 } 415 case Expression::Kind::kTernary: { 416 const TernaryExpression& t = e->as<TernaryExpression>(); 417 this->writeCommand(Rehydrator::kTernary_Command); 418 this->write(t.test().get()); 419 this->write(t.ifTrue().get()); 420 this->write(t.ifFalse().get()); 421 break; 422 } 423 case Expression::Kind::kVariableReference: { 424 const VariableReference& v = e->as<VariableReference>(); 425 this->writeCommand(Rehydrator::kVariableReference_Command); 426 this->writeId(v.variable()); 427 this->writeU8((int8_t) v.refKind()); 428 break; 429 } 430 case Expression::Kind::kFunctionReference: 431 case Expression::Kind::kMethodReference: 432 case Expression::Kind::kPoison: 433 case Expression::Kind::kTypeReference: 434 SkDEBUGFAIL("this expression shouldn't appear in finished code"); 435 break; 436 } 437 } else { 438 this->writeCommand(Rehydrator::kVoid_Command); 439 } 440} 441 442void Dehydrator::write(const Statement* s) { 443 if (s) { 444 switch (s->kind()) { 445 case Statement::Kind::kBlock: { 446 const Block& b = s->as<Block>(); 447 this->writeCommand(Rehydrator::kBlock_Command); 448 AutoDehydratorSymbolTable symbols(this, b.symbolTable()); 449 this->writeU8(b.children().size()); 450 for (const std::unique_ptr<Statement>& blockStmt : b.children()) { 451 this->write(blockStmt.get()); 452 } 453 this->writeU8(b.isScope()); 454 break; 455 } 456 case Statement::Kind::kBreak: 457 this->writeCommand(Rehydrator::kBreak_Command); 458 break; 459 case Statement::Kind::kContinue: 460 this->writeCommand(Rehydrator::kContinue_Command); 461 break; 462 case Statement::Kind::kDiscard: 463 this->writeCommand(Rehydrator::kDiscard_Command); 464 break; 465 case Statement::Kind::kDo: { 466 const DoStatement& d = s->as<DoStatement>(); 467 this->writeCommand(Rehydrator::kDo_Command); 468 this->write(d.statement().get()); 469 this->write(d.test().get()); 470 break; 471 } 472 case Statement::Kind::kExpression: { 473 const ExpressionStatement& e = s->as<ExpressionStatement>(); 474 this->writeCommand(Rehydrator::kExpressionStatement_Command); 475 this->write(e.expression().get()); 476 break; 477 } 478 case Statement::Kind::kFor: { 479 const ForStatement& f = s->as<ForStatement>(); 480 this->writeCommand(Rehydrator::kFor_Command); 481 this->write(f.initializer().get()); 482 this->write(f.test().get()); 483 this->write(f.next().get()); 484 this->write(f.statement().get()); 485 this->write(*f.symbols()); 486 break; 487 } 488 case Statement::Kind::kIf: { 489 const IfStatement& i = s->as<IfStatement>(); 490 this->writeCommand(Rehydrator::kIf_Command); 491 this->writeU8(i.isStatic()); 492 this->write(i.test().get()); 493 this->write(i.ifTrue().get()); 494 this->write(i.ifFalse().get()); 495 break; 496 } 497 case Statement::Kind::kInlineMarker: { 498 const InlineMarker& i = s->as<InlineMarker>(); 499 this->writeCommand(Rehydrator::kInlineMarker_Command); 500 this->writeId(&i.function()); 501 break; 502 } 503 case Statement::Kind::kNop: 504 SkDEBUGFAIL("unexpected--nop statement in finished code"); 505 break; 506 case Statement::Kind::kReturn: { 507 const ReturnStatement& r = s->as<ReturnStatement>(); 508 this->writeCommand(Rehydrator::kReturn_Command); 509 this->write(r.expression().get()); 510 break; 511 } 512 case Statement::Kind::kSwitch: { 513 const SwitchStatement& ss = s->as<SwitchStatement>(); 514 this->writeCommand(Rehydrator::kSwitch_Command); 515 this->writeU8(ss.isStatic()); 516 AutoDehydratorSymbolTable symbols(this, ss.symbols()); 517 this->write(ss.value().get()); 518 this->writeU8(ss.cases().size()); 519 for (const std::unique_ptr<Statement>& stmt : ss.cases()) { 520 const SwitchCase& sc = stmt->as<SwitchCase>(); 521 this->write(sc.value().get()); 522 this->write(sc.statement().get()); 523 } 524 break; 525 } 526 case Statement::Kind::kSwitchCase: 527 SkDEBUGFAIL("SwitchCase statements shouldn't appear here"); 528 break; 529 case Statement::Kind::kVarDeclaration: { 530 const VarDeclaration& v = s->as<VarDeclaration>(); 531 this->writeCommand(Rehydrator::kVarDeclaration_Command); 532 this->writeU16(this->symbolId(&v.var())); 533 this->write(v.baseType()); 534 this->writeS8(v.arraySize()); 535 this->write(v.value().get()); 536 break; 537 } 538 } 539 } else { 540 this->writeCommand(Rehydrator::kVoid_Command); 541 } 542} 543 544void Dehydrator::write(const ProgramElement& e) { 545 switch (e.kind()) { 546 case ProgramElement::Kind::kExtension: 547 SkASSERT(false); 548 break; 549 case ProgramElement::Kind::kFunction: { 550 const FunctionDefinition& f = e.as<FunctionDefinition>(); 551 this->writeCommand(Rehydrator::kFunctionDefinition_Command); 552 this->writeU16(this->symbolId(&f.declaration())); 553 this->write(f.body().get()); 554 break; 555 } 556 case ProgramElement::Kind::kFunctionPrototype: { 557 // We don't need to emit function prototypes into the dehydrated data, because we don't 558 // ever need to re-emit the intrinsics files as raw GLSL/Metal. As long as the symbols 559 // exist in the symbol table, we're in good shape. 560 break; 561 } 562 case ProgramElement::Kind::kInterfaceBlock: { 563 const InterfaceBlock& i = e.as<InterfaceBlock>(); 564 this->writeCommand(Rehydrator::kInterfaceBlock_Command); 565 this->write(i.variable()); 566 this->write(i.typeName()); 567 this->write(i.instanceName()); 568 this->writeS8(i.arraySize()); 569 break; 570 } 571 case ProgramElement::Kind::kModifiers: 572 SkASSERT(false); 573 break; 574 case ProgramElement::Kind::kStructDefinition: { 575 const StructDefinition& structDef = e.as<StructDefinition>(); 576 this->writeCommand(Rehydrator::kStructDefinition_Command); 577 this->write(structDef.type()); 578 break; 579 } 580 case ProgramElement::Kind::kGlobalVar: { 581 const GlobalVarDeclaration& v = e.as<GlobalVarDeclaration>(); 582 this->writeCommand(Rehydrator::kVarDeclarations_Command); 583 this->write(v.declaration().get()); 584 break; 585 } 586 } 587} 588 589void Dehydrator::write(const std::vector<std::unique_ptr<ProgramElement>>& elements) { 590 this->writeCommand(Rehydrator::kElements_Command); 591 for (const auto& e : elements) { 592 this->write(*e); 593 } 594 this->writeCommand(Rehydrator::kElementsComplete_Command); 595} 596 597void Dehydrator::finish(OutputStream& out) { 598 String stringBuffer = fStringBuffer.str(); 599 String commandBuffer = fBody.str(); 600 601 out.write16(fStringBuffer.str().size()); 602 fStringBufferStart = 2; 603 out.writeString(stringBuffer); 604 fCommandStart = fStringBufferStart + stringBuffer.size(); 605 out.writeString(commandBuffer); 606} 607 608const char* Dehydrator::prefixAtOffset(size_t byte) { 609 if (byte >= fCommandStart) { 610 return fCommandBreaks.contains(byte - fCommandStart) ? "\n" : ""; 611 } 612 if (byte >= fStringBufferStart) { 613 return fStringBreaks.contains(byte - fStringBufferStart) ? "\n" : ""; 614 } 615 return ""; 616} 617 618} // namespace 619 620#endif 621