1 /* 2 * Copyright 2016 Google Inc. 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 #ifndef SKSL_FUNCTIONDEFINITION 9 #define SKSL_FUNCTIONDEFINITION 10 11 #include "include/private/SkSLProgramElement.h" 12 #include "src/sksl/ir/SkSLBlock.h" 13 #include "src/sksl/ir/SkSLFunctionDeclaration.h" 14 15 namespace SkSL { 16 17 struct ASTNode; 18 19 /** 20 * A function definition (a declaration plus an associated block of code). 21 */ 22 class FunctionDefinition final : public ProgramElement { 23 public: 24 inline static constexpr Kind kProgramElementKind = Kind::kFunction; 25 26 using IntrinsicSet = std::unordered_set<const FunctionDeclaration*>; 27 FunctionDefinition(int line,const FunctionDeclaration * declaration,bool builtin,std::unique_ptr<Statement> body,IntrinsicSet referencedIntrinsics)28 FunctionDefinition(int line, const FunctionDeclaration* declaration, bool builtin, 29 std::unique_ptr<Statement> body, IntrinsicSet referencedIntrinsics) 30 : INHERITED(line, kProgramElementKind) 31 , fDeclaration(declaration) 32 , fBuiltin(builtin) 33 , fBody(std::move(body)) 34 , fReferencedIntrinsics(std::move(referencedIntrinsics)) 35 , fSource(nullptr) {} 36 37 /** 38 * Coerces `return` statements to the return type of the function, and reports errors in the 39 * function that can't be detected at the individual statement level: 40 * - `break` and `continue` statements must be in reasonable places. 41 * - non-void functions are required to return a value on all paths. 42 * - vertex main() functions don't allow early returns. 43 * 44 * This will return a FunctionDefinition even if an error is detected; this leads to better 45 * diagnostics overall. (Returning null here leads to spurious "function 'f()' was not defined" 46 * errors when trying to call a function with an error in it.) 47 */ 48 static std::unique_ptr<FunctionDefinition> Convert(const Context& context, 49 int line, 50 const FunctionDeclaration& function, 51 std::unique_ptr<Statement> body, 52 bool builtin); 53 declaration()54 const FunctionDeclaration& declaration() const { 55 return *fDeclaration; 56 } 57 isBuiltin()58 bool isBuiltin() const { 59 return fBuiltin; 60 } 61 body()62 std::unique_ptr<Statement>& body() { 63 return fBody; 64 } 65 body()66 const std::unique_ptr<Statement>& body() const { 67 return fBody; 68 } 69 referencedIntrinsics()70 const std::unordered_set<const FunctionDeclaration*>& referencedIntrinsics() const { 71 return fReferencedIntrinsics; 72 } 73 source()74 const ASTNode* source() const { 75 return fSource; 76 } 77 setSource(const ASTNode * source)78 void setSource(const ASTNode* source) { 79 fSource = source; 80 } 81 clone()82 std::unique_ptr<ProgramElement> clone() const override { 83 return std::make_unique<FunctionDefinition>(fLine, &this->declaration(), 84 /*builtin=*/false, this->body()->clone(), 85 this->referencedIntrinsics()); 86 } 87 description()88 String description() const override { 89 return this->declaration().description() + " " + this->body()->description(); 90 } 91 92 private: 93 const FunctionDeclaration* fDeclaration; 94 bool fBuiltin; 95 std::unique_ptr<Statement> fBody; 96 // We track intrinsic functions we reference so that we can ensure that all of them end up 97 // copied into the final output. 98 IntrinsicSet fReferencedIntrinsics; 99 // This pointer may be null, and even when non-null is not guaranteed to remain valid for 100 // the entire lifespan of this object. The parse tree's lifespan is normally controlled by 101 // IRGenerator, so the IRGenerator being destroyed or being used to compile another file 102 // will invalidate this pointer. 103 const ASTNode* fSource; 104 105 using INHERITED = ProgramElement; 106 }; 107 108 } // namespace SkSL 109 110 #endif 111