• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env ruby
2
3# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16require 'optparse'
17require 'ostruct'
18require 'yaml'
19
20Options = OpenStruct.new
21class << Options
22
23  attr_accessor :compiling
24
25  def parse
26    OptionParser.new do |opts|
27      opts.banner = "Usage: irtoc.rb [options] INPUT_FILE"
28
29      opts.on("--ark_source_dir=PATH", "Path to panda source code") { |v| self.ark_source_dir = v }
30      opts.on("--output=PATH", "Output file") { |v| self.output_file = v }
31      opts.on("--input=PATH", "Input files, separated by ':' symbol") { |v| self.input_files = v.split(':') }
32      opts.on("--definitions=LIST", "C++ definitions that will be used for compiling output file") { |v| self.definitions = v }
33      opts.on("--arch=ARCH", "Target architecture") { |v| self.arch = v }
34      opts.on('--ir-api=API', 'API to emit during C++ code generation') { |v| self.ir_api = v }
35      opts.on('--isa=PATH', 'ISA YAML file') { |v| self.isa = v }
36      opts.on('--plugins=PATH', 'Plugins file') { |v| self.plugins = v }
37      opts.on('--keep-artifacts', 'Do not remove intermediate files') { |v| self.keep_artifacts = true }
38    end.parse!
39
40    self.instructions_yaml = "#{self.ark_source_dir}/compiler/optimizer/ir/instructions.yaml"
41    self.isapi = "#{self.ark_source_dir}/isa/isapi.rb"
42    self.commonapi = "#{self.ark_source_dir}/templates/common.rb"
43
44    # Collect compiler definitions
45    if self.definitions
46      defines = self.definitions.split(':')
47      new_definitions = OpenStruct.new
48      defines.each do |define|
49        vals = define.split('=')
50        new_definitions[vals[0]] = vals.size > 1 ? vals[1] : true
51      end
52      self.definitions = new_definitions
53    else
54      self.definitions = OpenStruct.new
55    end
56    self.definitions.DEBUG = !self.definitions.NDEBUG
57
58    # Collect plugins files
59    if self.plugins
60      new_plugins = Hash.new { |h, k| h[k] = [] }
61      File.open(self.plugins).readlines.each do |plugin|
62        next if plugin.strip.empty?
63        full_plugin_path = "#{self.ark_source_dir}/#{plugin}".chop
64        line_matches = File.open(full_plugin_path).to_a.first.match(/# +plugin +(.*)/)
65        raise "Irtoc plugin doesn't specifiy its name: #{full_plugin_path}" unless line_matches
66        plugin_name = line_matches[1]
67        new_plugins[plugin_name] << full_plugin_path
68      end
69      self.plugins = new_plugins
70    else
71      self.plugins = Hash.new { |h, k| h[k] = [] }
72    end
73
74    # Determine target architecture
75    if self.arch.nil?
76      arch_str = self.definitions.marshal_dump.keys.grep(/PANDA_TARGET_(AMD64|ARM64|ARM32)/)[0]
77      self.arch = arch_str.to_s.sub('PANDA_TARGET_','').downcase
78    end
79    self.arch = self.arch.to_sym
80    if self.arch == :amd64 || self.arch == :x64
81      self.arch = :x86_64
82    end
83    if self.arch == :arm
84      self.arch = :arm32
85    end
86    possible_arch = %w[arm64 arm32 x86_64 x86]
87    raise "Wrong arch: #{arch_str}" unless possible_arch.include?(self.arch.to_s)
88
89    # Read compiler arch info
90    arch_info = YAML.load_file("#{self.ark_source_dir}/compiler/optimizer/ir/instructions.yaml")['arch_info']
91    raise "Compiler config doesn't contain `arch_info`" unless arch_info
92    arch_info = arch_info[arch_info.index { |x| x['name'].to_sym == self.arch }]
93    raise "Arch info not found for #{self.arch}" unless arch_info
94    self.arch_info = OpenStruct.new(arch_info)
95
96    raise 'Supported IR APIs: ir-constructor, ir-builder, ir-inline' unless self.ir_api =~ /^ir-(constructor|builder|inline)$/
97  end
98
99  def arch_64_bits?
100    self.arch == :x86_64 || self.arch == :arm64
101  end
102
103  def arm64?
104    self.arch == :arm64
105  end
106
107  def cpp_arch
108    @cpp_arch_map ||= {
109      arm32: "Arch::AARCH32",
110      arm64: "Arch::AARCH64",
111      x86_64: "Arch::X86_64"
112    }
113    @cpp_arch_map[self.arch]
114  end
115
116end
117