mirror of
https://github.com/llvm/llvm-project.git
synced 2025-05-03 23:16:06 +00:00

* Removes all Perl scripts and modules * Adds Python3 scripts which mimic the behavior of the Perl scripts * Removes Perl from CMake; Adds Python3 requirement to CMake * The check-instruction-set.pl script is Knights Corner specific. The script is removed and not replicated with a corresponding Python3 script. Relevant Discourse: https://discourse.llvm.org/t/error-compiling-clang-with-offloading-support/79223/4 Fixes: https://github.com/llvm/llvm-project/issues/62289
245 lines
8.5 KiB
Python
245 lines
8.5 KiB
Python
#!/usr/bin/env python3
|
|
|
|
#
|
|
# //===----------------------------------------------------------------------===//
|
|
# //
|
|
# // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
# // See https://llvm.org/LICENSE.txt for license information.
|
|
# // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
# //
|
|
# //===----------------------------------------------------------------------===//
|
|
#
|
|
|
|
import argparse
|
|
import os
|
|
import re
|
|
import sys
|
|
from libomputils import error, ScriptError, print_error_line
|
|
|
|
|
|
class DllExports(object):
|
|
def __init__(self):
|
|
self.filename = None
|
|
self.exports = {}
|
|
self.ordinals = set([])
|
|
|
|
def add_uppercase_entries(self):
|
|
# Ignored entries are C/C++ only functions
|
|
ignores = [
|
|
"omp_alloc",
|
|
"omp_free",
|
|
"omp_calloc",
|
|
"omp_realloc",
|
|
"omp_aligned_alloc",
|
|
"omp_aligned_calloc",
|
|
]
|
|
keys = list(self.exports.keys())
|
|
for entry in keys:
|
|
info = self.exports[entry]
|
|
if info["obsolete"] or info["is_data"] or entry in ignores:
|
|
continue
|
|
if entry.startswith("omp_") or entry.startswith("kmp_"):
|
|
newentry = entry.upper()
|
|
if info["ordinal"]:
|
|
newordinal = info["ordinal"] + 1000
|
|
else:
|
|
newordinal = None
|
|
self.exports[newentry] = {
|
|
"obsolete": False,
|
|
"is_data": False,
|
|
"ordinal": newordinal,
|
|
}
|
|
|
|
@staticmethod
|
|
def create(inputFile, defs=None):
|
|
"""Creates DllExports object from inputFile"""
|
|
dllexports = DllExports()
|
|
dllexports.filename = inputFile
|
|
# Create a (possibly empty) list of definitions
|
|
if defs:
|
|
definitions = set(list(defs))
|
|
else:
|
|
definitions = set([])
|
|
# Different kinds of lines to parse
|
|
kw = r"[a-zA-Z_][a-zA-Z0-9_]*"
|
|
ifndef = re.compile(r"%ifndef\s+({})".format(kw))
|
|
ifdef = re.compile(r"%ifdef\s+({})".format(kw))
|
|
endif = re.compile(r"%endif")
|
|
export = re.compile(r"(-)?\s*({0})(=({0}))?(\s+([0-9]+|DATA))?".format(kw))
|
|
|
|
def err(fil, num, msg):
|
|
error("{}: {}: {}".format(fil, num, msg))
|
|
|
|
defs_stack = []
|
|
with open(inputFile) as f:
|
|
for lineNumber, line in enumerate(f):
|
|
line = line.strip()
|
|
# Skip empty lines
|
|
if not line:
|
|
continue
|
|
# Skip comment lines
|
|
if line.startswith("#"):
|
|
continue
|
|
# Encountered %ifndef DEF
|
|
m = ifndef.search(line)
|
|
if m:
|
|
defs_stack.append(m.group(1) not in definitions)
|
|
continue
|
|
# Encountered %ifdef DEF
|
|
m = ifdef.search(line)
|
|
if m:
|
|
defs_stack.append(m.group(1) in definitions)
|
|
continue
|
|
# Encountered %endif
|
|
m = endif.search(line)
|
|
if m:
|
|
if not defs_stack:
|
|
err(inputFile, lineNumber, "orphan %endif directive")
|
|
defs_stack.pop()
|
|
continue
|
|
# Skip lines when not all %ifdef or %ifndef are true
|
|
if defs_stack and not all(defs_stack):
|
|
continue
|
|
# Encountered an export line
|
|
m = export.search(line)
|
|
if m:
|
|
obsolete = m.group(1) is not None
|
|
entry = m.group(2)
|
|
rename = m.group(4)
|
|
ordinal = m.group(6)
|
|
if entry in dllexports.exports:
|
|
err(
|
|
inputFile,
|
|
lineNumber,
|
|
"already specified entry: {}".format(entry),
|
|
)
|
|
if rename:
|
|
entry += "={}".format(rename)
|
|
# No ordinal number nor DATA specified
|
|
if not ordinal:
|
|
ordinal = None
|
|
is_data = False
|
|
# DATA ordinal
|
|
elif ordinal == "DATA":
|
|
ordinal = None
|
|
is_data = True
|
|
# Regular ordinal number
|
|
else:
|
|
is_data = False
|
|
try:
|
|
ordinal = int(ordinal)
|
|
except:
|
|
err(
|
|
inputFile,
|
|
lineNumber,
|
|
"Bad ordinal value: {}".format(ordinal),
|
|
)
|
|
if ordinal >= 1000 and (
|
|
entry.startswith("omp_") or entry.startswith("kmp_")
|
|
):
|
|
err(
|
|
inputFile,
|
|
lineNumber,
|
|
"Ordinal of user-callable entry must be < 1000",
|
|
)
|
|
if ordinal >= 1000 and ordinal < 2000:
|
|
err(
|
|
inputFile,
|
|
lineNumber,
|
|
"Ordinals between 1000 and 1999 are reserved.",
|
|
)
|
|
if ordinal in dllexports.ordinals:
|
|
err(
|
|
inputFile,
|
|
lineNumber,
|
|
"Ordinal {} has already been used.".format(ordinal),
|
|
)
|
|
dllexports.exports[entry] = {
|
|
"ordinal": ordinal,
|
|
"obsolete": obsolete,
|
|
"is_data": is_data,
|
|
}
|
|
continue
|
|
err(
|
|
inputFile,
|
|
lineNumber,
|
|
'Cannot parse line:{}"{}"'.format(os.linesep, line),
|
|
)
|
|
if defs_stack:
|
|
error("syntax error: Unterminated %if directive")
|
|
return dllexports
|
|
|
|
|
|
def generate_def(dllexports, f, no_ordinals=False, name=None):
|
|
"""Using dllexports data, write the exports to file, f"""
|
|
if name:
|
|
f.write("LIBRARY {}\n".format(name))
|
|
f.write("EXPORTS\n")
|
|
for entry in sorted(list(dllexports.exports.keys())):
|
|
info = dllexports.exports[entry]
|
|
if info["obsolete"]:
|
|
continue
|
|
f.write(" {:<40} ".format(entry))
|
|
if info["is_data"]:
|
|
f.write("DATA\n")
|
|
elif no_ordinals or not info["ordinal"]:
|
|
f.write("\n")
|
|
else:
|
|
f.write("@{}\n".format(info["ordinal"]))
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Reads input file of dllexports, processes conditional"
|
|
" directives, checks content for consistency, and generates"
|
|
" output file suitable for linker"
|
|
)
|
|
parser.add_argument(
|
|
"-D",
|
|
metavar="DEF",
|
|
action="append",
|
|
dest="defs",
|
|
help="Define a variable. Can specify" " this more than once.",
|
|
)
|
|
parser.add_argument(
|
|
"--no-ordinals",
|
|
action="store_true",
|
|
help="Specify that no ordinal numbers should be generated",
|
|
)
|
|
parser.add_argument(
|
|
"-n",
|
|
"--name",
|
|
dest="name",
|
|
help="Specify library name for def file LIBRARY statement",
|
|
)
|
|
parser.add_argument(
|
|
"-o",
|
|
"--output",
|
|
metavar="FILE",
|
|
dest="output",
|
|
help="Specify output file name. If not specified," " output is sent to stdout",
|
|
)
|
|
parser.add_argument("dllexports", help="The input file describing dllexports")
|
|
commandArgs = parser.parse_args()
|
|
defs = set([])
|
|
if commandArgs.defs:
|
|
defs = set(commandArgs.defs)
|
|
dllexports = DllExports.create(commandArgs.dllexports, defs)
|
|
dllexports.add_uppercase_entries()
|
|
try:
|
|
output = open(commandArgs.output, "w") if commandArgs.output else sys.stdout
|
|
generate_def(dllexports, output, commandArgs.no_ordinals, commandArgs.name)
|
|
finally:
|
|
if commandArgs.output:
|
|
output.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
main()
|
|
except ScriptError as e:
|
|
print_error_line(str(e))
|
|
sys.exit(1)
|
|
|
|
# end of file
|