diff options
| author | 2013-08-05 18:33:30 -0700 | |
|---|---|---|
| committer | 2013-08-07 10:27:52 -0700 | |
| commit | 6547fa9749d0e32cc367d64f8cc6b3d65bf43a5d (patch) | |
| tree | e9a9d88c1c938dcbf03a6fc61b11159672e73229 | |
| parent | 9642c96bd5a1ccc4e221de9c0af4a545af8182d2 (diff) | |
SEA IR type handling complete for fibonacci.
types.h: Encapsulated types map into separate class.
code_gen.*, visitor.h: Added visitor function for
unnamed constants to enable correct
.dot display and type handling.
type_inference_visitor.cc: Propagated types through
phi functions, invoke, add-int instructions. Added
SEA IR type merging functions.
Change-Id: I0fb1c4d40e3af43dc295133a826ce125a787cc33
| -rw-r--r-- | compiler/sea_ir/code_gen.cc | 8 | ||||
| -rw-r--r-- | compiler/sea_ir/code_gen.h | 5 | ||||
| -rw-r--r-- | compiler/sea_ir/debug/dot_gen.cc | 5 | ||||
| -rw-r--r-- | compiler/sea_ir/debug/dot_gen.h | 8 | ||||
| -rw-r--r-- | compiler/sea_ir/frontend.cc | 6 | ||||
| -rw-r--r-- | compiler/sea_ir/types/type_inference.cc | 41 | ||||
| -rw-r--r-- | compiler/sea_ir/types/type_inference.h | 21 | ||||
| -rw-r--r-- | compiler/sea_ir/types/type_inference_visitor.cc | 73 | ||||
| -rw-r--r-- | compiler/sea_ir/types/type_inference_visitor.h | 21 | ||||
| -rw-r--r-- | compiler/sea_ir/types/types.h | 29 | ||||
| -rw-r--r-- | compiler/sea_ir/visitor.h | 3 |
11 files changed, 187 insertions, 33 deletions
diff --git a/compiler/sea_ir/code_gen.cc b/compiler/sea_ir/code_gen.cc index 0ef21b4800..7fd6c86c8c 100644 --- a/compiler/sea_ir/code_gen.cc +++ b/compiler/sea_ir/code_gen.cc @@ -114,6 +114,14 @@ void CodeGenVisitor::Visit(InstructionNode* instruction) { std::string instr = instruction->GetInstruction()->DumpString(NULL); DCHECK(0); // This whole function is useful only during development. } + +void CodeGenVisitor::Visit(UnnamedConstInstructionNode* instruction) { + std::string instr = instruction->GetInstruction()->DumpString(NULL); + std::cout << "1.Instruction: " << instr << std::endl; + llvm_data_->AddValue(instruction, + llvm::ConstantInt::get(*llvm_data_->context_, llvm::APInt(32, instruction->GetConstValue()))); +} + void CodeGenVisitor::Visit(ConstInstructionNode* instruction) { std::string instr = instruction->GetInstruction()->DumpString(NULL); std::cout << "1.Instruction: " << instr << std::endl; diff --git a/compiler/sea_ir/code_gen.h b/compiler/sea_ir/code_gen.h index 5fea79a0a2..edef19d000 100644 --- a/compiler/sea_ir/code_gen.h +++ b/compiler/sea_ir/code_gen.h @@ -101,6 +101,8 @@ class CodeGenPrepassVisitor: public CodeGenPassVisitor { void Visit(SignatureNode* region); void Visit(Region* region); void Visit(InstructionNode* instruction) { } + + void Visit(UnnamedConstInstructionNode* instruction) { } void Visit(ConstInstructionNode* instruction) { } void Visit(ReturnInstructionNode* instruction) { } void Visit(IfNeInstructionNode* instruction) { } @@ -120,6 +122,7 @@ class CodeGenPostpassVisitor: public CodeGenPassVisitor { void Visit(SignatureNode* region); void Visit(Region* region); void Visit(InstructionNode* region) { } + void Visit(UnnamedConstInstructionNode* instruction) { } void Visit(ConstInstructionNode* instruction) { } void Visit(ReturnInstructionNode* instruction) { } void Visit(IfNeInstructionNode* instruction) { } @@ -139,10 +142,10 @@ class CodeGenVisitor: public CodeGenPassVisitor { void Visit(SignatureNode* region); void Visit(Region* region); void Visit(InstructionNode* region); + void Visit(UnnamedConstInstructionNode* instruction); void Visit(ConstInstructionNode* instruction); void Visit(ReturnInstructionNode* instruction); void Visit(IfNeInstructionNode* instruction); - // void Visit(AddIntLitInstructionNode* instruction); void Visit(MoveResultInstructionNode* instruction); void Visit(InvokeStaticInstructionNode* instruction); void Visit(AddIntInstructionNode* instruction); diff --git a/compiler/sea_ir/debug/dot_gen.cc b/compiler/sea_ir/debug/dot_gen.cc index ecb641e661..9442684a52 100644 --- a/compiler/sea_ir/debug/dot_gen.cc +++ b/compiler/sea_ir/debug/dot_gen.cc @@ -14,6 +14,7 @@ * limitations under the License. */ + #include "scoped_thread_state_change.h" #include "sea_ir/debug/dot_gen.h" @@ -50,7 +51,7 @@ void DotGenerationVisitor::ToDotSSAEdges(InstructionNode* instruction) { dot_text_ += def_it->second->StringId() + " -> "; dot_text_ += instruction->StringId() + "[color=gray,label=\""; dot_text_ += art::StringPrintf("vR = %d", def_it->first); - std::map<int, const Type*>::const_iterator type_it = types_->find(def_it->second->Id()); + art::SafeMap<int, const Type*>::const_iterator type_it = types_->find(def_it->second->Id()); if (type_it != types_->end()) { art::ScopedObjectAccess soa(art::Thread::Current()); dot_text_ += "(" + type_it->second->Dump() + ")"; @@ -82,7 +83,7 @@ void DotGenerationVisitor::ToDotSSAEdges(PhiInstructionNode* instruction) { dot_text_ += (*def_it)->StringId() + " -> "; dot_text_ += instruction->StringId() + "[color=gray,label=\""; dot_text_ += art::StringPrintf("vR = %d", instruction->GetRegisterNumber()); - std::map<int, const Type*>::const_iterator type_it = types_->find((*def_it)->Id()); + art::SafeMap<int, const Type*>::const_iterator type_it = types_->find((*def_it)->Id()); if (type_it != types_->end()) { art::ScopedObjectAccess soa(art::Thread::Current()); dot_text_ += "(" + type_it->second->Dump() + ")"; diff --git a/compiler/sea_ir/debug/dot_gen.h b/compiler/sea_ir/debug/dot_gen.h index df74901c7b..301c70fb4d 100644 --- a/compiler/sea_ir/debug/dot_gen.h +++ b/compiler/sea_ir/debug/dot_gen.h @@ -17,6 +17,7 @@ #ifndef ART_COMPILER_SEA_IR_DEBUG_DOT_GEN_H_ #define ART_COMPILER_SEA_IR_DEBUG_DOT_GEN_H_ +#include "safe_map.h" #include "base/stringprintf.h" #include "file_output_stream.h" #include "sea_ir/sea.h" @@ -37,7 +38,7 @@ class DotConversionOptions { class DotGenerationVisitor: public IRVisitor { public: explicit DotGenerationVisitor(const DotConversionOptions* const options, - std::map<int, const Type*>* types): graph_(), types_(types), options_(options) { } + art::SafeMap<int, const Type*>* types): graph_(), types_(types), options_(options) { } virtual void Initialize(SeaGraph* graph); // Saves the ssa def->use edges corresponding to @instruction. @@ -88,7 +89,7 @@ class DotGenerationVisitor: public IRVisitor { private: std::string dot_text_; SeaGraph* graph_; - std::map<int, const Type*>* types_; + art::SafeMap<int, const Type*>* types_; const DotConversionOptions* const options_; }; @@ -97,7 +98,8 @@ class DotConversion { public: DotConversion(): options_() { } // Saves to @filename the .dot representation of @graph with the options @options. - void DumpSea(SeaGraph* graph, std::string filename, std::map<int, const Type*>* types) const { + void DumpSea(SeaGraph* graph, std::string filename, + art::SafeMap<int, const Type*>* types) const { LOG(INFO) << "Starting to write SEA string to file."; DotGenerationVisitor dgv = DotGenerationVisitor(&options_, types); graph->Accept(&dgv); diff --git a/compiler/sea_ir/frontend.cc b/compiler/sea_ir/frontend.cc index 951273c304..b6f84eee8f 100644 --- a/compiler/sea_ir/frontend.cc +++ b/compiler/sea_ir/frontend.cc @@ -23,7 +23,7 @@ #include "llvm/llvm_compilation_unit.h" #include "mirror/object.h" #include "runtime.h" - +#include "safe_map.h" #include "sea_ir/sea.h" #include "sea_ir/debug/dot_gen.h" @@ -46,8 +46,8 @@ static CompiledMethod* CompileMethodWithSeaIr(CompilerDriver& compiler, sea_ir::SeaGraph* ir_graph = sea_ir::SeaGraph::GetCurrentGraph(dex_file); ir_graph->CompileMethod(code_item, class_def_idx, method_idx, method_access_flags, dex_file); sea_ir::DotConversion dc; - std::map<int, const sea_ir::Type*> types = ir_graph->ti_->GetTypeMap(); - dc.DumpSea(ir_graph, "/tmp/temp.dot", &types); + SafeMap<int, const sea_ir::Type*>* types = ir_graph->ti_->GetTypeMap(); + dc.DumpSea(ir_graph, "/tmp/temp.dot", types); CHECK(0 && "No SEA compiled function exists yet."); return NULL; } diff --git a/compiler/sea_ir/types/type_inference.cc b/compiler/sea_ir/types/type_inference.cc index 78888f3d43..77470c273d 100644 --- a/compiler/sea_ir/types/type_inference.cc +++ b/compiler/sea_ir/types/type_inference.cc @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#include "scoped_thread_state_change.h" #include "sea_ir/types/type_inference.h" #include "sea_ir/types/type_inference_visitor.h" #include "sea_ir/sea.h" @@ -44,8 +44,29 @@ FunctionTypeInfo::FunctionTypeInfo(const SeaGraph* graph, art::verifier::RegType declaring_class_ = &(type_cache_->FromDescriptor(NULL, descriptor, false)); } -std::vector<const Type*> FunctionTypeInfo::GetDeclaredArgumentTypes() - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { +FunctionTypeInfo::FunctionTypeInfo(const SeaGraph* graph, InstructionNode* inst, + art::verifier::RegTypeCache* types): dex_file_(graph->GetDexFile()), + dex_method_idx_(inst->GetInstruction()->VRegB_35c()), type_cache_(types), + method_access_flags_(0) { + // TODO: Test that GetDeclaredArgumentTypes() works correctly when using this constructor. + const art::DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_); + const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(method_id.class_idx_)); + declaring_class_ = &(type_cache_->FromDescriptor(NULL, descriptor, false)); +} + +const Type* FunctionTypeInfo::GetReturnValueType() { + const art::DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx_); + uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_; + const char* descriptor = dex_file_->StringByTypeIdx(return_type_idx); + art::ScopedObjectAccess soa(art::Thread::Current()); + const Type& return_type = type_cache_->FromDescriptor(NULL, descriptor, false); + return &return_type; +} + + + +std::vector<const Type*> FunctionTypeInfo::GetDeclaredArgumentTypes() { + art::ScopedObjectAccess soa(art::Thread::Current()); std::vector<const Type*> argument_types; // Include the "this" pointer. size_t cur_arg = 0; @@ -127,7 +148,7 @@ void TypeInference::ComputeTypes(SeaGraph* graph) SHARED_LOCKS_REQUIRED(Locks::m std::vector<InstructionNode*>* instructions = (*region_it)->GetInstructions(); std::copy(instructions->begin(), instructions->end(), std::back_inserter(worklist)); } - TypeInferenceVisitor tiv(graph, type_cache_); + TypeInferenceVisitor tiv(graph, &type_data_, type_cache_); // Sparse (SSA) fixed-point algorithm that processes each instruction in the work-list, // adding consumers of instructions whose result changed type back into the work-list. // Note: According to [1] list iterators should not be invalidated on insertion, @@ -140,15 +161,13 @@ void TypeInference::ComputeTypes(SeaGraph* graph) SHARED_LOCKS_REQUIRED(Locks::m instruction_it != worklist.end(); instruction_it++) { std::cout << "[TI] Instruction: " << (*instruction_it)->Id() << std::endl; (*instruction_it)->Accept(&tiv); - std::map<int, const Type*>::const_iterator old_result_it = - type_map_.find((*instruction_it)->Id()); + const Type* old_type = type_data_.FindTypeOf((*instruction_it)->Id()); const Type* new_type = tiv.GetType(); - bool first_time_set = (old_result_it == type_map_.end()) && (new_type != NULL); - bool type_changed = (old_result_it != type_map_.end()) && ((*old_result_it).second != new_type); - if (first_time_set || type_changed) { + bool type_changed = (old_type != new_type); + if (type_changed) { std::cout << " New type:" << new_type->IsIntegralTypes() << std::endl; - std::cout << " Descrip:" << new_type->Dump()<< "on " << (*instruction_it)->Id() << std::endl; - type_map_[(*instruction_it)->Id()] = new_type; + std::cout << " Descrip:" << new_type->Dump()<< " on " << (*instruction_it)->Id() << std::endl; + type_data_.SetTypeOf((*instruction_it)->Id(), new_type); // Add SSA consumers of the current instruction to the work-list. std::vector<InstructionNode*>* consumers = (*instruction_it)->GetSSAConsumers(); for (std::vector<InstructionNode*>::iterator consumer = consumers->begin(); diff --git a/compiler/sea_ir/types/type_inference.h b/compiler/sea_ir/types/type_inference.h index 9014c96e91..d951d82071 100644 --- a/compiler/sea_ir/types/type_inference.h +++ b/compiler/sea_ir/types/type_inference.h @@ -17,16 +17,18 @@ #ifndef ART_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_H_ #define ART_COMPILER_SEA_IR_TYPES_TYPE_INFERENCE_H_ +#include "safe_map.h" #include "dex_file-inl.h" #include "sea_ir/types/types.h" namespace sea_ir { class SeaGraph; +class InstructionNode; // The type inference in SEA IR is different from the verifier in that it is concerned // with a rich type hierarchy (TODO) usable in optimization and does not perform -// precise verification which is the job of the verifier. +// precise verification (which is the job of the verifier). class TypeInference { public: TypeInference() { @@ -36,26 +38,37 @@ class TypeInference { // Computes the types for the method with SEA IR representation provided by @graph. void ComputeTypes(SeaGraph* graph); - std::map<int, const Type*> GetTypeMap() const { - return type_map_; + art::SafeMap<int, const Type*>* GetTypeMap() { + return type_data_.GetTypeMap(); } // Returns true if @descriptor corresponds to a primitive type. static bool IsPrimitiveDescriptor(char descriptor); protected: art::verifier::RegTypeCache* type_cache_; - std::map<int, const Type*> type_map_; + TypeData type_data_; }; // Stores information about the exact type of a function. class FunctionTypeInfo { public: + // Finds method information about the method encoded by a SEA IR graph. // @graph provides the input method SEA IR representation. // @types provides the input cache of types from which the // parameter types of the function are found. FunctionTypeInfo(const SeaGraph* graph, art::verifier::RegTypeCache* types); + // Finds method information about the method encoded by + // an invocation instruction in a SEA IR graph. + // @graph provides the input method SEA IR representation. + // @inst is an invocation instruction for the desired method. + // @types provides the input cache of types from which the + // parameter types of the function are found. + FunctionTypeInfo(const SeaGraph* graph, InstructionNode* inst, + art::verifier::RegTypeCache* types); // Returns the ordered vector of types corresponding to the function arguments. std::vector<const Type*> GetDeclaredArgumentTypes(); + // Returns the declared return value type. + const Type* GetReturnValueType(); // Returns the type corresponding to the class that declared the method. const Type& GetDeclaringClass() { return *declaring_class_; diff --git a/compiler/sea_ir/types/type_inference_visitor.cc b/compiler/sea_ir/types/type_inference_visitor.cc index 8faa4d5f83..bafe5c50ba 100644 --- a/compiler/sea_ir/types/type_inference_visitor.cc +++ b/compiler/sea_ir/types/type_inference_visitor.cc @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "scoped_thread_state_change.h" #include "sea_ir/types/type_inference_visitor.h" #include "sea_ir/types/type_inference.h" #include "sea_ir/sea.h" @@ -21,13 +22,81 @@ namespace sea_ir { void TypeInferenceVisitor::Visit(SignatureNode* parameter) { - std::cout << "[TI] Visiting signature node:" << parameter->GetResultRegister() << std::endl; FunctionTypeInfo fti(graph_, type_cache_); std::vector<const Type*> arguments = fti.GetDeclaredArgumentTypes(); - crt_type_.clear(); DCHECK_LT(parameter->GetPositionInSignature(), arguments.size()) << "Signature node position not present in signature."; crt_type_.push_back(arguments.at(parameter->GetPositionInSignature())); } +void TypeInferenceVisitor::Visit(UnnamedConstInstructionNode* instruction) { + crt_type_.push_back(&type_cache_->Integer()); +} + +void TypeInferenceVisitor::Visit(PhiInstructionNode* instruction) { + std::vector<const Type*> types_to_merge = GetOperandTypes(instruction); + const Type* result_type = MergeTypes(types_to_merge); + crt_type_.push_back(result_type); +} + +void TypeInferenceVisitor::Visit(AddIntInstructionNode* instruction) { + std::vector<const Type*> operand_types = GetOperandTypes(instruction); + for (std::vector<const Type*>::const_iterator cit = operand_types.begin(); + cit != operand_types.end(); cit++) { + if (*cit != NULL) { + DCHECK((*cit)->IsInteger()); + } + } + crt_type_.push_back(&type_cache_->Integer()); +} + +void TypeInferenceVisitor::Visit(MoveResultInstructionNode* instruction) { + std::vector<const Type*> operand_types = GetOperandTypes(instruction); + const Type* operand_type = operand_types.at(0); + crt_type_.push_back(operand_type); +} + +void TypeInferenceVisitor::Visit(InvokeStaticInstructionNode* instruction) { + FunctionTypeInfo fti(graph_, instruction, type_cache_); + const Type* result_type = fti.GetReturnValueType(); + crt_type_.push_back(result_type); +} + +std::vector<const Type*> TypeInferenceVisitor::GetOperandTypes(InstructionNode* instruction) { + std::vector<InstructionNode*> sources = instruction->GetSSAProducers(); + std::vector<const Type*> types_to_merge; + for (std::vector<InstructionNode*>::const_iterator cit = sources.begin(); cit != sources.end(); + cit++) { + const Type* source_type = type_data_->FindTypeOf((*cit)->Id()); + if (source_type != NULL) { + types_to_merge.push_back(source_type); + } + } + return types_to_merge; +} + +const Type* TypeInferenceVisitor::MergeTypes(std::vector<const Type*>& types) const { + const Type* type = NULL; + if (types.size()>0) { + type = *(types.begin()); + if (types.size()>1) { + for (std::vector<const Type*>::const_iterator cit = types.begin(); + cit != types.end(); cit++) { + if (!type->Equals(**cit)) { + type = MergeTypes(type, *cit); + } + } + } + } + return type; +} + +const Type* TypeInferenceVisitor::MergeTypes(const Type* t1, const Type* t2) const { + DCHECK(t2 != NULL); + DCHECK(t1 != NULL); + art::ScopedObjectAccess soa(art::Thread::Current()); + const Type* result = &(t1->Merge(*t2, type_cache_)); + return result; +} + } // namespace sea_ir diff --git a/compiler/sea_ir/types/type_inference_visitor.h b/compiler/sea_ir/types/type_inference_visitor.h index bf7f4c0d12..889557d210 100644 --- a/compiler/sea_ir/types/type_inference_visitor.h +++ b/compiler/sea_ir/types/type_inference_visitor.h @@ -34,26 +34,31 @@ namespace sea_ir { // version 2: with template return value). class TypeInferenceVisitor: public IRVisitor { public: - TypeInferenceVisitor(SeaGraph* graph, art::verifier::RegTypeCache* types): - graph_(graph), type_cache_(types), crt_type_() { + TypeInferenceVisitor(SeaGraph* graph, TypeData* type_data, + art::verifier::RegTypeCache* types): + graph_(graph), type_data_(type_data), type_cache_(types), crt_type_() { } // There are no type related actions to be performed on these classes. void Initialize(SeaGraph* graph) { } void Visit(SeaGraph* graph) { } void Visit(Region* region) { } - void Visit(PhiInstructionNode* instruction) { } + void Visit(PhiInstructionNode* instruction); void Visit(SignatureNode* parameter); void Visit(InstructionNode* instruction) { } + void Visit(UnnamedConstInstructionNode* instruction); void Visit(ConstInstructionNode* instruction) { } void Visit(ReturnInstructionNode* instruction) { } void Visit(IfNeInstructionNode* instruction) { } - void Visit(MoveResultInstructionNode* instruction) { } - void Visit(InvokeStaticInstructionNode* instruction) { } - void Visit(AddIntInstructionNode* instruction) { } + void Visit(MoveResultInstructionNode* instruction); + void Visit(InvokeStaticInstructionNode* instruction); + void Visit(AddIntInstructionNode* instruction); void Visit(GotoInstructionNode* instruction) { } void Visit(IfEqzInstructionNode* instruction) { } + const Type* MergeTypes(std::vector<const Type*>& types) const; + const Type* MergeTypes(const Type* t1, const Type* t2) const; + const Type* GetType() { // TODO: Currently multiple defined types are not supported. if (crt_type_.size()>0) { @@ -66,8 +71,12 @@ class TypeInferenceVisitor: public IRVisitor { protected: const SeaGraph* const graph_; + TypeData* type_data_; art::verifier::RegTypeCache* type_cache_; std::vector<const Type*> crt_type_; // Stored temporarily between two calls to Visit. + + private: + std::vector<const Type*> GetOperandTypes(InstructionNode* instruction); }; } // namespace sea_ir diff --git a/compiler/sea_ir/types/types.h b/compiler/sea_ir/types/types.h index 8aa5d161ef..64f25243d0 100644 --- a/compiler/sea_ir/types/types.h +++ b/compiler/sea_ir/types/types.h @@ -17,6 +17,7 @@ #ifndef ART_COMPILER_SEA_IR_TYPES_TYPES_H_ #define ART_COMPILER_SEA_IR_TYPES_TYPES_H_ +#include "safe_map.h" #include "verifier/reg_type.h" #include "verifier/reg_type_cache.h" @@ -25,5 +26,33 @@ namespace sea_ir { // TODO: Replace typedef with an actual class implementation when we have more types. typedef art::verifier::RegType Type; +// Stores information about the result type of each instruction. +// Note: Main purpose is to encapsulate the map<instruction id, type*>, +// so that we can replace the underlying storage at any time. +class TypeData { + public: + art::SafeMap<int, const Type*>* GetTypeMap() { + return &type_map_; + } + // Returns the type associated with instruction with @instruction_id. + const Type* FindTypeOf(int instruction_id) { + art::SafeMap<int, const Type*>::const_iterator result_it = type_map_.find(instruction_id); + if (type_map_.end() != result_it) { + return result_it->second; + } + return NULL; + } + + // Saves the fact that instruction @instruction_id produces a value of type @type. + void SetTypeOf(int instruction_id, const Type* type) { + type_map_.Overwrite(instruction_id, type); + } + + private: + art::SafeMap<int, const Type*> type_map_; +}; + + + } // namespace sea_ir #endif // ART_COMPILER_SEA_IR_TYPES_TYPES_H_ diff --git a/compiler/sea_ir/visitor.h b/compiler/sea_ir/visitor.h index ffb073ece9..4f207dab94 100644 --- a/compiler/sea_ir/visitor.h +++ b/compiler/sea_ir/visitor.h @@ -24,6 +24,7 @@ class Region; class InstructionNode; class PhiInstructionNode; class SignatureNode; +class UnnamedConstInstructionNode; class ConstInstructionNode; class ReturnInstructionNode; class IfNeInstructionNode; @@ -49,9 +50,9 @@ class IRVisitor { virtual void Visit(InstructionNode* region) = 0; virtual void Visit(ConstInstructionNode* instruction) = 0; + virtual void Visit(UnnamedConstInstructionNode* instruction) = 0; virtual void Visit(ReturnInstructionNode* instruction) = 0; virtual void Visit(IfNeInstructionNode* instruction) = 0; - // virtual void Visit(AddIntLitInstructionNode* instruction) = 0; virtual void Visit(MoveResultInstructionNode* instruction) = 0; virtual void Visit(InvokeStaticInstructionNode* instruction) = 0; virtual void Visit(AddIntInstructionNode* instruction) = 0; |