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