1b1994897Sopenharmony_ci# Copyright (c) 2021-2022 Huawei Device Co., Ltd. 2b1994897Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License"); 3b1994897Sopenharmony_ci# you may not use this file except in compliance with the License. 4b1994897Sopenharmony_ci# You may obtain a copy of the License at 5b1994897Sopenharmony_ci# 6b1994897Sopenharmony_ci# http://www.apache.org/licenses/LICENSE-2.0 7b1994897Sopenharmony_ci# 8b1994897Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software 9b1994897Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS, 10b1994897Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11b1994897Sopenharmony_ci# See the License for the specific language governing permissions and 12b1994897Sopenharmony_ci# limitations under the License. 13b1994897Sopenharmony_ci 14b1994897Sopenharmony_cirequire 'ostruct' 15b1994897Sopenharmony_cirequire_relative 'codegen_arm64' 16b1994897Sopenharmony_cirequire 'delegate' 17b1994897Sopenharmony_ci 18b1994897Sopenharmony_cimodule Tokens 19b1994897Sopenharmony_ci module_function 20b1994897Sopenharmony_ci 21b1994897Sopenharmony_ci module Types 22b1994897Sopenharmony_ci INT8 = 'i8' 23b1994897Sopenharmony_ci INT16 = 'i16' 24b1994897Sopenharmony_ci INT32 = 'i32' 25b1994897Sopenharmony_ci INT64 = 'i64' 26b1994897Sopenharmony_ci UINT8 = 'u8' 27b1994897Sopenharmony_ci UINT16 = 'u16' 28b1994897Sopenharmony_ci UINT32 = 'u32' 29b1994897Sopenharmony_ci UINT64 = 'u64' 30b1994897Sopenharmony_ci FLOAT32 = 'f32' 31b1994897Sopenharmony_ci FLOAT64 = 'f64' 32b1994897Sopenharmony_ci BOOL = 'bool' 33b1994897Sopenharmony_ci REF = 'ref' 34b1994897Sopenharmony_ci PTR = 'ptr' 35b1994897Sopenharmony_ci VOID = 'void' 36b1994897Sopenharmony_ci IMM = 'imm' 37b1994897Sopenharmony_ci INTEGER = 'int' 38b1994897Sopenharmony_ci FLOAT = 'float' 39b1994897Sopenharmony_ci NUMBER = 'number' 40b1994897Sopenharmony_ci REAL = 'real' 41b1994897Sopenharmony_ci ANY = 'any' 42b1994897Sopenharmony_ci ACC = 'acc' 43b1994897Sopenharmony_ci STRING = 'string_id' 44b1994897Sopenharmony_ci METHOD = 'method_id' 45b1994897Sopenharmony_ci SAVE_STATE = 'save_state' 46b1994897Sopenharmony_ci end 47b1994897Sopenharmony_ci 48b1994897Sopenharmony_ci module Other 49b1994897Sopenharmony_ci DST = 'd' 50b1994897Sopenharmony_ci DYNAMIC = 'dyn' 51b1994897Sopenharmony_ci PSEUDO = 'pseudo' 52b1994897Sopenharmony_ci NULL_CHECK = 'nc' 53b1994897Sopenharmony_ci ZERO_CHECK = 'zc' 54b1994897Sopenharmony_ci NEGATIVE_CHECK = 'ngc' 55b1994897Sopenharmony_ci BOUNDS_CHECK = 'bc' 56b1994897Sopenharmony_ci end 57b1994897Sopenharmony_ci 58b1994897Sopenharmony_ciend 59b1994897Sopenharmony_ci 60b1994897Sopenharmony_ciclass Operand 61b1994897Sopenharmony_ci attr_accessor :tokens, :types 62b1994897Sopenharmony_ci 63b1994897Sopenharmony_ci TYPE_ALIASES = { 64b1994897Sopenharmony_ci # We add `bool` type into the `int`, because IR uses same constant instructions for bool and integer types, i.e. 65b1994897Sopenharmony_ci # same constant instruction can be definition for bool and integer instructions simultaneously. 66b1994897Sopenharmony_ci "int" => %w[bool i8 i16 i32 i64 u8 u16 u32 u64], 67b1994897Sopenharmony_ci "float" => %w[f32 f64], 68b1994897Sopenharmony_ci "number" => %w[bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64], 69b1994897Sopenharmony_ci "real" => %w[bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 ref ptr] 70b1994897Sopenharmony_ci } 71b1994897Sopenharmony_ci 72b1994897Sopenharmony_ci CPP_IR_TYPES = { 73b1994897Sopenharmony_ci Tokens::Types::INT8 => "DataType::INT8", 74b1994897Sopenharmony_ci Tokens::Types::INT16 => "DataType::INT16", 75b1994897Sopenharmony_ci Tokens::Types::INT32 => "DataType::INT32", 76b1994897Sopenharmony_ci Tokens::Types::INT64 => "DataType::INT64", 77b1994897Sopenharmony_ci Tokens::Types::UINT8 => "DataType::UINT8", 78b1994897Sopenharmony_ci Tokens::Types::UINT16 => "DataType::UINT16", 79b1994897Sopenharmony_ci Tokens::Types::UINT32 => "DataType::UINT32", 80b1994897Sopenharmony_ci Tokens::Types::UINT64 => "DataType::UINT64", 81b1994897Sopenharmony_ci Tokens::Types::BOOL => "DataType::BOOL", 82b1994897Sopenharmony_ci Tokens::Types::FLOAT32 => "DataType::FLOAT32", 83b1994897Sopenharmony_ci Tokens::Types::FLOAT64 => "DataType::FLOAT64", 84b1994897Sopenharmony_ci Tokens::Types::REF => "DataType::REFERENCE", 85b1994897Sopenharmony_ci Tokens::Types::PTR => "DataType::POINTER", 86b1994897Sopenharmony_ci Tokens::Types::VOID => "DataType::VOID", 87b1994897Sopenharmony_ci Tokens::Types::ANY => "DataType::ANY" 88b1994897Sopenharmony_ci } 89b1994897Sopenharmony_ci 90b1994897Sopenharmony_ci def initialize(descr) 91b1994897Sopenharmony_ci @tokens = descr.split('-') 92b1994897Sopenharmony_ci @types = [] 93b1994897Sopenharmony_ci @aux_types = [] 94b1994897Sopenharmony_ci @tokens.each do |token| 95b1994897Sopenharmony_ci if IR::types.include?(token) 96b1994897Sopenharmony_ci @types << token 97b1994897Sopenharmony_ci next 98b1994897Sopenharmony_ci end 99b1994897Sopenharmony_ci resolved = TYPE_ALIASES[token] 100b1994897Sopenharmony_ci if resolved 101b1994897Sopenharmony_ci @types += resolved 102b1994897Sopenharmony_ci next 103b1994897Sopenharmony_ci end 104b1994897Sopenharmony_ci @aux_types << token 105b1994897Sopenharmony_ci end 106b1994897Sopenharmony_ci end 107b1994897Sopenharmony_ci 108b1994897Sopenharmony_ci def has(type) 109b1994897Sopenharmony_ci @tokens.include? type 110b1994897Sopenharmony_ci end 111b1994897Sopenharmony_ci 112b1994897Sopenharmony_ci def types_string 113b1994897Sopenharmony_ci @tokens.join(', ') + (@tokens.include?(Tokens::Other::DYNAMIC) ? ", ..." : "") 114b1994897Sopenharmony_ci end 115b1994897Sopenharmony_ci 116b1994897Sopenharmony_ci def is_dst? 117b1994897Sopenharmony_ci has(Tokens::Other::DST) 118b1994897Sopenharmony_ci end 119b1994897Sopenharmony_ci 120b1994897Sopenharmony_ci def is_dyn? 121b1994897Sopenharmony_ci has(Tokens::Other::DYNAMIC) 122b1994897Sopenharmony_ci end 123b1994897Sopenharmony_ci 124b1994897Sopenharmony_ci def pseudo? 125b1994897Sopenharmony_ci has(Tokens::Other::PSEUDO) 126b1994897Sopenharmony_ci end 127b1994897Sopenharmony_ci 128b1994897Sopenharmony_ci def self.cpp_type(t) 129b1994897Sopenharmony_ci raise "No cpp token for type #{t}" unless CPP_IR_TYPES.include?(t.to_s) 130b1994897Sopenharmony_ci CPP_IR_TYPES[t] 131b1994897Sopenharmony_ci end 132b1994897Sopenharmony_ciend 133b1994897Sopenharmony_ci 134b1994897Sopenharmony_ciclass Instruction < SimpleDelegator 135b1994897Sopenharmony_ci attr_reader :operands, :inputs 136b1994897Sopenharmony_ci 137b1994897Sopenharmony_ci def initialize(data) 138b1994897Sopenharmony_ci data.modes ||= IR::modes.each_pair.map { |key, value| key.to_s } 139b1994897Sopenharmony_ci super(data) 140b1994897Sopenharmony_ci @operands = signature.map { |sgn| Operand.new(sgn) } 141b1994897Sopenharmony_ci if @operands.empty? 142b1994897Sopenharmony_ci @inputs = [] 143b1994897Sopenharmony_ci else 144b1994897Sopenharmony_ci @inputs = @operands.drop(@operands.first.is_dst? ? 1 : 0) 145b1994897Sopenharmony_ci end 146b1994897Sopenharmony_ci raise "Destination can be only first operand" if inputs.any? { |x| x.is_dst? } 147b1994897Sopenharmony_ci end 148b1994897Sopenharmony_ci 149b1994897Sopenharmony_ci def has_dst? 150b1994897Sopenharmony_ci !operands.empty? && operands.first.is_dst? 151b1994897Sopenharmony_ci end 152b1994897Sopenharmony_ci 153b1994897Sopenharmony_ci def dst 154b1994897Sopenharmony_ci @operands.first 155b1994897Sopenharmony_ci end 156b1994897Sopenharmony_ci 157b1994897Sopenharmony_ci def has_inputs? 158b1994897Sopenharmony_ci !inputs.empty? 159b1994897Sopenharmony_ci end 160b1994897Sopenharmony_ci 161b1994897Sopenharmony_ci def is_call? 162b1994897Sopenharmony_ci flags.include?("call") 163b1994897Sopenharmony_ci end 164b1994897Sopenharmony_ci 165b1994897Sopenharmony_ci def resolve_item(item) 166b1994897Sopenharmony_ci if item.is_a? Array 167b1994897Sopenharmony_ci return item.map { |v| (v.start_with? '$') ? IR::templates[v[1..-1]] : v } 168b1994897Sopenharmony_ci elsif item.is_a? Hash 169b1994897Sopenharmony_ci return item.map { |k, v| (v.start_with? '$') ? [k, IR::templates[v[1..-1]]] : [k, v] } 170b1994897Sopenharmony_ci else 171b1994897Sopenharmony_ci return item 172b1994897Sopenharmony_ci end 173b1994897Sopenharmony_ci end 174b1994897Sopenharmony_ci 175b1994897Sopenharmony_ci def resolve 176b1994897Sopenharmony_ci self['verification'] = resolve_item(verification) if respond_to? 'verification' 177b1994897Sopenharmony_ci self 178b1994897Sopenharmony_ci end 179b1994897Sopenharmony_ciend 180b1994897Sopenharmony_ci 181b1994897Sopenharmony_cimodule IR 182b1994897Sopenharmony_ci module_function 183b1994897Sopenharmony_ci 184b1994897Sopenharmony_ci def instructions 185b1994897Sopenharmony_ci @instructions ||= @data['instructions'].map do |inst_dscr| 186b1994897Sopenharmony_ci Instruction.new(OpenStruct.new(inst_dscr)).resolve 187b1994897Sopenharmony_ci end 188b1994897Sopenharmony_ci end 189b1994897Sopenharmony_ci 190b1994897Sopenharmony_ci def flags 191b1994897Sopenharmony_ci @data['flags'] 192b1994897Sopenharmony_ci end 193b1994897Sopenharmony_ci 194b1994897Sopenharmony_ci def modes 195b1994897Sopenharmony_ci @data['modes'] 196b1994897Sopenharmony_ci end 197b1994897Sopenharmony_ci 198b1994897Sopenharmony_ci def templates 199b1994897Sopenharmony_ci @data['templates'] 200b1994897Sopenharmony_ci end 201b1994897Sopenharmony_ci 202b1994897Sopenharmony_ci def arch_info 203b1994897Sopenharmony_ci @data['arch_info'] 204b1994897Sopenharmony_ci end 205b1994897Sopenharmony_ci 206b1994897Sopenharmony_ci def legend 207b1994897Sopenharmony_ci @data['legend'] 208b1994897Sopenharmony_ci end 209b1994897Sopenharmony_ci 210b1994897Sopenharmony_ci def wrap_data(data) 211b1994897Sopenharmony_ci @data = data 212b1994897Sopenharmony_ci end 213b1994897Sopenharmony_ci 214b1994897Sopenharmony_ci def types 215b1994897Sopenharmony_ci @types ||= @data['types'].map { |x| x.name } 216b1994897Sopenharmony_ci end 217b1994897Sopenharmony_ci 218b1994897Sopenharmony_ci def codegen 219b1994897Sopenharmony_ci @@cg ||= Codegen.new 220b1994897Sopenharmony_ci end 221b1994897Sopenharmony_ci 222b1994897Sopenharmony_ci def get_ir_type(type) 223b1994897Sopenharmony_ci @type_map ||= { 224b1994897Sopenharmony_ci 'i8' => 'DataType::INT8', 225b1994897Sopenharmony_ci 'i16' => 'DataType::INT16', 226b1994897Sopenharmony_ci 'i32' => 'DataType::INT32', 227b1994897Sopenharmony_ci 'i64' => 'DataType::INT64', 228b1994897Sopenharmony_ci 'u8' => 'DataType::UINT8', 229b1994897Sopenharmony_ci 'u16' => 'DataType::UINT16', 230b1994897Sopenharmony_ci 'u32' => 'DataType::UINT32', 231b1994897Sopenharmony_ci 'u64' => 'DataType::UINT64', 232b1994897Sopenharmony_ci 'f32' => 'DataType::FLOAT32', 233b1994897Sopenharmony_ci 'f64' => 'DataType::FLOAT64', 234b1994897Sopenharmony_ci 'obj' => 'DataType::REFERENCE', 235b1994897Sopenharmony_ci 'any' => 'DataType::ANY', 236b1994897Sopenharmony_ci 'acc' => 'DataType::ACC', 237b1994897Sopenharmony_ci 'string_id' => 'DataType::UINT32', 238b1994897Sopenharmony_ci 'method_id' => 'DataType::UINT32', 239b1994897Sopenharmony_ci 'none' => 'DataType::NO_TYPE'} 240b1994897Sopenharmony_ci @type_map[type] 241b1994897Sopenharmony_ci end 242b1994897Sopenharmony_ci 243b1994897Sopenharmony_ciend 244b1994897Sopenharmony_ci 245b1994897Sopenharmony_cidef Gen.on_require(data) 246b1994897Sopenharmony_ci IR.wrap_data(data) 247b1994897Sopenharmony_ciend 248