• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env ruby
2
3# Copyright (c) 2021-2024 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_relative 'output'
17
18class CppFunction
19  attr_reader :variants
20
21  def initialize(name)
22    @name = name
23    @variants = []
24    @cpp_params = {}
25  end
26
27  def condition(cond)
28    @current_variant.cond = cond
29  end
30
31  def code(&block)
32    @current_variant.func = Function.new(@current_variant.name, params: @params, mode: [:IrInline], &block)
33    @current_variant.func.compile
34  end
35
36  def params(**kwargs)
37    @params = kwargs
38  end
39
40  def cpp_params(**kwargs)
41    @cpp_params = kwargs
42  end
43
44  def return_type(type)
45    @return_type = type
46  end
47
48  def variant(name, &block)
49    @current_variant = OpenStruct.new({condition: nil, name: name, func: nil})
50    @variants << @current_variant
51    self.instance_eval(&block)
52  end
53
54  def generate_ir(gen)
55    @variants.each { |x| gen.generate_function(x.func) }
56
57    param_list = @params.keys.map { |x| "[[maybe_unused]] AnyBaseType #{x}"} + @cpp_params.map { |name, type| "[[maybe_unused]] #{type} #{name}"}
58    params = (["IntrinsicInst *inst"] + param_list).join(', ')
59    Output.scoped_puts "inline #{@return_type} #{@name}(#{params}) {" do
60      @variants.each do |variant|
61        next if variant.cond == :default
62        Output.scoped_puts "if (#{variant.cond}) {" do
63          Output << "return #{variant.name}(inst);"
64        end
65      end
66      defaults = @variants.select { |x| x.cond == :default }
67      raise "Default condition can be only once" if defaults.size > 1
68      if defaults.empty?
69        Output << "return false;"
70      else
71        Output << "return #{defaults[0].name}(inst);"
72      end
73
74    end
75  end
76end