SkSLByteCodeGenerator.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /*
  2. * Copyright 2019 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. #ifndef SKSL_BYTECODEGENERATOR
  8. #define SKSL_BYTECODEGENERATOR
  9. #include <algorithm>
  10. #include <stack>
  11. #include <unordered_map>
  12. #include "src/sksl/SkSLByteCode.h"
  13. #include "src/sksl/SkSLCodeGenerator.h"
  14. #include "src/sksl/SkSLMemoryLayout.h"
  15. #include "src/sksl/ir/SkSLBinaryExpression.h"
  16. #include "src/sksl/ir/SkSLBlock.h"
  17. #include "src/sksl/ir/SkSLBoolLiteral.h"
  18. #include "src/sksl/ir/SkSLBreakStatement.h"
  19. #include "src/sksl/ir/SkSLConstructor.h"
  20. #include "src/sksl/ir/SkSLContinueStatement.h"
  21. #include "src/sksl/ir/SkSLDoStatement.h"
  22. #include "src/sksl/ir/SkSLExpressionStatement.h"
  23. #include "src/sksl/ir/SkSLExternalFunctionCall.h"
  24. #include "src/sksl/ir/SkSLExternalValueReference.h"
  25. #include "src/sksl/ir/SkSLFieldAccess.h"
  26. #include "src/sksl/ir/SkSLFloatLiteral.h"
  27. #include "src/sksl/ir/SkSLForStatement.h"
  28. #include "src/sksl/ir/SkSLFunctionCall.h"
  29. #include "src/sksl/ir/SkSLFunctionDeclaration.h"
  30. #include "src/sksl/ir/SkSLFunctionDefinition.h"
  31. #include "src/sksl/ir/SkSLIfStatement.h"
  32. #include "src/sksl/ir/SkSLIndexExpression.h"
  33. #include "src/sksl/ir/SkSLIntLiteral.h"
  34. #include "src/sksl/ir/SkSLInterfaceBlock.h"
  35. #include "src/sksl/ir/SkSLNullLiteral.h"
  36. #include "src/sksl/ir/SkSLPostfixExpression.h"
  37. #include "src/sksl/ir/SkSLPrefixExpression.h"
  38. #include "src/sksl/ir/SkSLProgramElement.h"
  39. #include "src/sksl/ir/SkSLReturnStatement.h"
  40. #include "src/sksl/ir/SkSLStatement.h"
  41. #include "src/sksl/ir/SkSLSwitchStatement.h"
  42. #include "src/sksl/ir/SkSLSwizzle.h"
  43. #include "src/sksl/ir/SkSLTernaryExpression.h"
  44. #include "src/sksl/ir/SkSLVarDeclarations.h"
  45. #include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
  46. #include "src/sksl/ir/SkSLVariableReference.h"
  47. #include "src/sksl/ir/SkSLWhileStatement.h"
  48. #include "src/sksl/spirv.h"
  49. namespace SkSL {
  50. class ByteCodeGenerator : public CodeGenerator {
  51. public:
  52. class LValue {
  53. public:
  54. LValue(ByteCodeGenerator& generator)
  55. : fGenerator(generator) {}
  56. virtual ~LValue() {}
  57. /**
  58. * Stack before call: ... lvalue
  59. * Stack after call: ... lvalue load
  60. */
  61. virtual void load() = 0;
  62. /**
  63. * Stack before call: ... lvalue value
  64. * Stack after call: ...
  65. */
  66. virtual void store(bool discard) = 0;
  67. protected:
  68. ByteCodeGenerator& fGenerator;
  69. };
  70. ByteCodeGenerator(const Context* context, const Program* program, ErrorReporter* errors,
  71. ByteCode* output);
  72. bool generateCode() override;
  73. void write8(uint8_t b);
  74. void write16(uint16_t b);
  75. void write32(uint32_t b);
  76. void write(ByteCodeInstruction inst, int count = kUnusedStackCount);
  77. /**
  78. * Based on 'type', writes the s (signed), u (unsigned), or f (float) instruction.
  79. */
  80. void writeTypedInstruction(const Type& type, ByteCodeInstruction s, ByteCodeInstruction u,
  81. ByteCodeInstruction f, int count);
  82. static int SlotCount(const Type& type);
  83. private:
  84. static constexpr int kUnusedStackCount = INT32_MAX;
  85. static int StackUsage(ByteCodeInstruction, int count);
  86. // reserves 16 bits in the output code, to be filled in later with an address once we determine
  87. // it
  88. class DeferredLocation {
  89. public:
  90. DeferredLocation(ByteCodeGenerator* generator)
  91. : fGenerator(*generator)
  92. , fOffset(generator->fCode->size()) {
  93. generator->write16(0);
  94. }
  95. #ifdef SK_DEBUG
  96. ~DeferredLocation() {
  97. SkASSERT(fSet);
  98. }
  99. #endif
  100. void set() {
  101. int target = fGenerator.fCode->size();
  102. SkASSERT(target <= 65535);
  103. (*fGenerator.fCode)[fOffset] = target;
  104. (*fGenerator.fCode)[fOffset + 1] = target >> 8;
  105. #ifdef SK_DEBUG
  106. fSet = true;
  107. #endif
  108. }
  109. private:
  110. ByteCodeGenerator& fGenerator;
  111. size_t fOffset;
  112. #ifdef SK_DEBUG
  113. bool fSet = false;
  114. #endif
  115. };
  116. // Intrinsics which do not simply map to a single opcode
  117. enum class SpecialIntrinsic {
  118. kDot,
  119. };
  120. struct Intrinsic {
  121. Intrinsic(ByteCodeInstruction instruction)
  122. : fIsSpecial(false)
  123. , fValue(instruction) {}
  124. Intrinsic(SpecialIntrinsic special)
  125. : fIsSpecial(true)
  126. , fValue(special) {}
  127. bool fIsSpecial;
  128. union Value {
  129. Value(ByteCodeInstruction instruction)
  130. : fInstruction(instruction) {}
  131. Value(SpecialIntrinsic special)
  132. : fSpecial(special) {}
  133. ByteCodeInstruction fInstruction;
  134. SpecialIntrinsic fSpecial;
  135. } fValue;
  136. };
  137. /**
  138. * Returns the local slot into which var should be stored, allocating a new slot if it has not
  139. * already been assigned one. Compound variables (e.g. vectors) will consume more than one local
  140. * slot, with the getLocation return value indicating where the first element should be stored.
  141. */
  142. int getLocation(const Variable& var);
  143. /**
  144. * As above, but computes the (possibly dynamic) address of an expression involving indexing &
  145. * field access. If the address is known, it's returned. If not, -1 is returned, and the
  146. * location will be left on the top of the stack.
  147. */
  148. int getLocation(const Expression& expr, Variable::Storage* storage);
  149. std::unique_ptr<ByteCodeFunction> writeFunction(const FunctionDefinition& f);
  150. void writeVarDeclarations(const VarDeclarations& decl);
  151. void writeVariableExpression(const Expression& expr);
  152. void writeExpression(const Expression& expr, bool discard = false);
  153. /**
  154. * Pushes whatever values are required by the lvalue onto the stack, and returns an LValue
  155. * permitting loads and stores to it.
  156. */
  157. std::unique_ptr<LValue> getLValue(const Expression& expr);
  158. void writeIntrinsicCall(const FunctionCall& c);
  159. void writeFunctionCall(const FunctionCall& c);
  160. void writeConstructor(const Constructor& c);
  161. void writeExternalFunctionCall(const ExternalFunctionCall& c);
  162. void writeExternalValue(const ExternalValueReference& r);
  163. void writeSwizzle(const Swizzle& swizzle);
  164. bool writeBinaryExpression(const BinaryExpression& b, bool discard);
  165. void writeTernaryExpression(const TernaryExpression& t);
  166. void writeNullLiteral(const NullLiteral& n);
  167. bool writePrefixExpression(const PrefixExpression& p, bool discard);
  168. bool writePostfixExpression(const PostfixExpression& p, bool discard);
  169. void writeBoolLiteral(const BoolLiteral& b);
  170. void writeIntLiteral(const IntLiteral& i);
  171. void writeFloatLiteral(const FloatLiteral& f);
  172. void writeStatement(const Statement& s);
  173. void writeBlock(const Block& b);
  174. void writeBreakStatement(const BreakStatement& b);
  175. void writeContinueStatement(const ContinueStatement& c);
  176. void writeIfStatement(const IfStatement& stmt);
  177. void writeForStatement(const ForStatement& f);
  178. void writeWhileStatement(const WhileStatement& w);
  179. void writeDoStatement(const DoStatement& d);
  180. void writeSwitchStatement(const SwitchStatement& s);
  181. void writeReturnStatement(const ReturnStatement& r);
  182. // updates the current set of breaks to branch to the current location
  183. void setBreakTargets();
  184. // updates the current set of continues to branch to the current location
  185. void setContinueTargets();
  186. void enterLoop() {
  187. fLoopCount++;
  188. fMaxLoopCount = std::max(fMaxLoopCount, fLoopCount);
  189. }
  190. void exitLoop() {
  191. SkASSERT(fLoopCount > 0);
  192. fLoopCount--;
  193. }
  194. void enterCondition() {
  195. fConditionCount++;
  196. fMaxConditionCount = std::max(fMaxConditionCount, fConditionCount);
  197. }
  198. void exitCondition() {
  199. SkASSERT(fConditionCount > 0);
  200. fConditionCount--;
  201. }
  202. const Context& fContext;
  203. ByteCode* fOutput;
  204. const FunctionDefinition* fFunction;
  205. std::vector<uint8_t>* fCode;
  206. std::vector<const Variable*> fLocals;
  207. std::stack<std::vector<DeferredLocation>> fContinueTargets;
  208. std::stack<std::vector<DeferredLocation>> fBreakTargets;
  209. std::vector<const FunctionDefinition*> fFunctions;
  210. int fParameterCount;
  211. int fStackCount;
  212. int fMaxStackCount;
  213. int fLoopCount;
  214. int fMaxLoopCount;
  215. int fConditionCount;
  216. int fMaxConditionCount;
  217. const std::unordered_map<String, Intrinsic> fIntrinsics;
  218. friend class DeferredLocation;
  219. friend class ByteCodeExpressionLValue;
  220. friend class ByteCodeSwizzleLValue;
  221. typedef CodeGenerator INHERITED;
  222. };
  223. }
  224. #endif