1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4"""
5Copyright (c) 2024 Huawei Device Co., Ltd.
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17
18Description: generate abc with mix compilation
19"""
20
21import os
22import stat
23from utils import *
24
25
26class MixCompiler:
27    def __init__(self, out_file, files_info_list, opt_level, file_threads,
28                 abc_class_threads, function_threads, frontend_tool) -> None:
29        self.out_file = out_file
30        self.files_info_list = files_info_list
31        self.opt_level = opt_level
32        self.file_threads = file_threads
33        self.abc_class_threads = abc_class_threads
34        self.function_threads = function_threads
35        self.frontend_tool = frontend_tool
36        self.abc_outputs = []
37
38    def mix_compile(self, step=1, size=1):
39        flags = os.O_WRONLY | os.O_CREAT
40        modes = stat.S_IWUSR | stat.S_IRUSR
41        files_info_list = self.files_info_list
42        out_file = self.out_file
43        count = 0
44        return_code = 0
45        # For each testcase, we will firstly select some files to generate a merged abc,
46        # and then mix compile it with the remained files to generate the final abc. Will do this for a cycle.
47        for i in range(0, len(files_info_list), step):
48            count = count + 1
49            right_bound = min(i + size, len(files_info_list))
50            selected_file = files_info_list[i : right_bound]
51            remained_file = files_info_list[0 : i]
52            remained_file.extend(files_info_list[right_bound : len(files_info_list)])
53
54            temp_abc = out_file.replace(ABC_EXT, f'_{count}{TEMP_ABC_EXT}')
55            temp_files_info_path = out_file.replace(ABC_EXT, f'_{count}{TEMP_TXT_EXT}')
56            with os.fdopen(os.open(temp_files_info_path, flags, modes), 'w') as f:
57                f.write("".join(selected_file))
58            cmd = [self.frontend_tool, '--opt-level', str(self.opt_level),
59                   '--file-threads', str(self.file_threads),
60                   '--function-threads', str(self.function_threads),
61                   '--output', temp_abc, '--merge-abc', f'@{temp_files_info_path}']
62            return_code = exec_command(cmd)
63            if return_code:
64                print_command(cmd)
65                return return_code
66
67            remained_file.append(f'{temp_abc}\n')
68            abc = out_file.replace(ABC_EXT, f'_{count}{ABC_EXT}')
69            files_info_path = out_file.replace(ABC_EXT, f'_{count}{TXT_EXT}')
70            with os.fdopen(os.open(files_info_path, flags, modes), 'w') as f:
71                f.write("".join(remained_file))
72            cmd = [self.frontend_tool, '--opt-level', str(self.opt_level),
73                   '--file-threads', str(self.file_threads),
74                   '--abc-class-threads', str(self.abc_class_threads),
75                   '--function-threads', str(self.function_threads),
76                   '--output', abc, '--merge-abc', '--enable-abc-input', f'@{files_info_path}']
77            return_code = exec_command(cmd)
78            if return_code:
79                print_command(cmd)
80                return return_code
81
82            self.abc_outputs.append(abc)
83
84        return return_code
85