brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.5 KiB · 6781fe7 Raw
245 lines · python
1#!/usr/bin/env python32 3#4# //===----------------------------------------------------------------------===//5# //6# // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.7# // See https://llvm.org/LICENSE.txt for license information.8# // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception9# //10# //===----------------------------------------------------------------------===//11#12 13import argparse14import os15import re16import sys17from libomputils import error, ScriptError, print_error_line18 19 20class DllExports(object):21    def __init__(self):22        self.filename = None23        self.exports = {}24        self.ordinals = set([])25 26    def add_uppercase_entries(self):27        # Ignored entries are C/C++ only functions28        ignores = [29            "omp_alloc",30            "omp_free",31            "omp_calloc",32            "omp_realloc",33            "omp_aligned_alloc",34            "omp_aligned_calloc",35        ]36        keys = list(self.exports.keys())37        for entry in keys:38            info = self.exports[entry]39            if info["obsolete"] or info["is_data"] or entry in ignores:40                continue41            if entry.startswith("omp_") or entry.startswith("kmp_"):42                newentry = entry.upper()43                if info["ordinal"]:44                    newordinal = info["ordinal"] + 100045                else:46                    newordinal = None47                self.exports[newentry] = {48                    "obsolete": False,49                    "is_data": False,50                    "ordinal": newordinal,51                }52 53    @staticmethod54    def create(inputFile, defs=None):55        """Creates DllExports object from inputFile"""56        dllexports = DllExports()57        dllexports.filename = inputFile58        # Create a (possibly empty) list of definitions59        if defs:60            definitions = set(list(defs))61        else:62            definitions = set([])63        # Different kinds of lines to parse64        kw = r"[a-zA-Z_][a-zA-Z0-9_]*"65        ifndef = re.compile(r"%ifndef\s+({})".format(kw))66        ifdef = re.compile(r"%ifdef\s+({})".format(kw))67        endif = re.compile(r"%endif")68        export = re.compile(r"(-)?\s*({0})(=({0}))?(\s+([0-9]+|DATA))?".format(kw))69 70        def err(fil, num, msg):71            error("{}: {}: {}".format(fil, num, msg))72 73        defs_stack = []74        with open(inputFile) as f:75            for lineNumber, line in enumerate(f):76                line = line.strip()77                # Skip empty lines78                if not line:79                    continue80                # Skip comment lines81                if line.startswith("#"):82                    continue83                # Encountered %ifndef DEF84                m = ifndef.search(line)85                if m:86                    defs_stack.append(m.group(1) not in definitions)87                    continue88                # Encountered %ifdef DEF89                m = ifdef.search(line)90                if m:91                    defs_stack.append(m.group(1) in definitions)92                    continue93                # Encountered %endif94                m = endif.search(line)95                if m:96                    if not defs_stack:97                        err(inputFile, lineNumber, "orphan %endif directive")98                    defs_stack.pop()99                    continue100                # Skip lines when not all %ifdef or %ifndef are true101                if defs_stack and not all(defs_stack):102                    continue103                # Encountered an export line104                m = export.search(line)105                if m:106                    obsolete = m.group(1) is not None107                    entry = m.group(2)108                    rename = m.group(4)109                    ordinal = m.group(6)110                    if entry in dllexports.exports:111                        err(112                            inputFile,113                            lineNumber,114                            "already specified entry: {}".format(entry),115                        )116                    if rename:117                        entry += "={}".format(rename)118                    # No ordinal number nor DATA specified119                    if not ordinal:120                        ordinal = None121                        is_data = False122                    # DATA ordinal123                    elif ordinal == "DATA":124                        ordinal = None125                        is_data = True126                    # Regular ordinal number127                    else:128                        is_data = False129                        try:130                            ordinal = int(ordinal)131                        except:132                            err(133                                inputFile,134                                lineNumber,135                                "Bad ordinal value: {}".format(ordinal),136                            )137                        if ordinal >= 1000 and (138                            entry.startswith("omp_") or entry.startswith("kmp_")139                        ):140                            err(141                                inputFile,142                                lineNumber,143                                "Ordinal of user-callable entry must be < 1000",144                            )145                        if ordinal >= 1000 and ordinal < 2000:146                            err(147                                inputFile,148                                lineNumber,149                                "Ordinals between 1000 and 1999 are reserved.",150                            )151                        if ordinal in dllexports.ordinals:152                            err(153                                inputFile,154                                lineNumber,155                                "Ordinal {} has already been used.".format(ordinal),156                            )157                    dllexports.exports[entry] = {158                        "ordinal": ordinal,159                        "obsolete": obsolete,160                        "is_data": is_data,161                    }162                    continue163                err(164                    inputFile,165                    lineNumber,166                    'Cannot parse line:{}"{}"'.format(os.linesep, line),167                )168        if defs_stack:169            error("syntax error: Unterminated %if directive")170        return dllexports171 172 173def generate_def(dllexports, f, no_ordinals=False, name=None):174    """Using dllexports data, write the exports to file, f"""175    if name:176        f.write("LIBRARY {}\n".format(name))177    f.write("EXPORTS\n")178    for entry in sorted(list(dllexports.exports.keys())):179        info = dllexports.exports[entry]180        if info["obsolete"]:181            continue182        f.write("    {:<40} ".format(entry))183        if info["is_data"]:184            f.write("DATA\n")185        elif no_ordinals or not info["ordinal"]:186            f.write("\n")187        else:188            f.write("@{}\n".format(info["ordinal"]))189 190 191def main():192    parser = argparse.ArgumentParser(193        description="Reads input file of dllexports, processes conditional"194        " directives, checks content for consistency, and generates"195        " output file suitable for linker"196    )197    parser.add_argument(198        "-D",199        metavar="DEF",200        action="append",201        dest="defs",202        help="Define a variable. Can specify" " this more than once.",203    )204    parser.add_argument(205        "--no-ordinals",206        action="store_true",207        help="Specify that no ordinal numbers should be generated",208    )209    parser.add_argument(210        "-n",211        "--name",212        dest="name",213        help="Specify library name for def file LIBRARY statement",214    )215    parser.add_argument(216        "-o",217        "--output",218        metavar="FILE",219        dest="output",220        help="Specify output file name. If not specified," " output is sent to stdout",221    )222    parser.add_argument("dllexports", help="The input file describing dllexports")223    commandArgs = parser.parse_args()224    defs = set([])225    if commandArgs.defs:226        defs = set(commandArgs.defs)227    dllexports = DllExports.create(commandArgs.dllexports, defs)228    dllexports.add_uppercase_entries()229    try:230        output = open(commandArgs.output, "w") if commandArgs.output else sys.stdout231        generate_def(dllexports, output, commandArgs.no_ordinals, commandArgs.name)232    finally:233        if commandArgs.output:234            output.close()235 236 237if __name__ == "__main__":238    try:239        main()240    except ScriptError as e:241        print_error_line(str(e))242        sys.exit(1)243 244# end of file245