1 // Copyright (c) 2016 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef SOURCE_OPT_IR_LOADER_H_
16 #define SOURCE_OPT_IR_LOADER_H_
17 
18 #include <memory>
19 #include <string>
20 #include <vector>
21 
22 #include "source/opt/basic_block.h"
23 #include "source/opt/instruction.h"
24 #include "source/opt/module.h"
25 #include "spirv-tools/libspirv.hpp"
26 
27 namespace spvtools {
28 namespace opt {
29 
30 // Loader class for constructing SPIR-V in-memory IR representation. Methods in
31 // this class are designed to work with the interface for spvBinaryParse() in
32 // libspirv.h so that we can leverage the syntax checks implemented behind it.
33 //
34 // The user is expected to call SetModuleHeader() to fill in the module's
35 // header, and then AddInstruction() for each decoded instruction, and finally
36 // EndModule() to finalize the module. The instructions processed in sequence
37 // by AddInstruction() should comprise a valid SPIR-V module.
38 class IrLoader {
39  public:
40   // Instantiates a builder to construct the given |module| gradually.
41   // All internal messages will be communicated to the outside via the given
42   // message |consumer|. This instance only keeps a reference to the |consumer|,
43   // so the |consumer| should outlive this instance.
44   IrLoader(const MessageConsumer& consumer, Module* m);
45 
46   // Sets the source name of the module.
SetSource(const std::string & src)47   void SetSource(const std::string& src) { source_ = src; }
48 
module()49   Module* module() const { return module_; }
50 
51   // Sets the fields in the module's header to the given parameters.
SetModuleHeader(uint32_t magic,uint32_t version,uint32_t generator,uint32_t bound,uint32_t reserved)52   void SetModuleHeader(uint32_t magic, uint32_t version, uint32_t generator,
53                        uint32_t bound, uint32_t reserved) {
54     module_->SetHeader({magic, version, generator, bound, reserved});
55   }
56   // Adds an instruction to the module. Returns true if no error occurs. This
57   // method will properly capture and store the data provided in |inst| so that
58   // |inst| is no longer needed after returning.
59   bool AddInstruction(const spv_parsed_instruction_t* inst);
60   // Finalizes the module construction. This must be called after the module
61   // header has been set and all instructions have been added.  This is
62   // forgiving in the case of a missing terminator instruction on a basic block,
63   // or a missing OpFunctionEnd.  Resolves internal bookkeeping.
64   void EndModule();
65 
66   // Sets whether extra OpLine instructions should be injected to better
67   // track line information.
SetExtraLineTracking(bool flag)68   void SetExtraLineTracking(bool flag) { extra_line_tracking_ = flag; }
69 
70  private:
71   // Consumer for communicating messages to outside.
72   const MessageConsumer& consumer_;
73   // The module to be built.
74   Module* module_;
75   // The source name of the module.
76   std::string source_;
77   // The last used instruction index.
78   uint32_t inst_index_;
79   // The current Function under construction.
80   std::unique_ptr<Function> function_;
81   // The current BasicBlock under construction.
82   std::unique_ptr<BasicBlock> block_;
83   // Line related debug instructions accumulated thus far.
84   std::vector<Instruction> dbg_line_info_;
85   // If doing extra line tracking, this is the line instruction that should be
86   // applied to the next instruction.  Otherwise it always contains null.
87   std::unique_ptr<Instruction> last_line_inst_;
88 
89   // The last DebugScope information that IrLoader::AddInstruction() handled.
90   DebugScope last_dbg_scope_;
91 
92   // When true, do extra line information tracking: Additional OpLine
93   // instructions will be injected to help track line info more robustly during
94   // transformations.
95   bool extra_line_tracking_ = true;
96 };
97 
98 }  // namespace opt
99 }  // namespace spvtools
100 
101 #endif  // SOURCE_OPT_IR_LOADER_H_
102