import subprocess
from pathlib import Path
[docs]class Clang:
"""
Class to define functions for calling the Clang compiler
"""
def __init__(self):
"""
"""
pass
[docs] @staticmethod
def compile_cfile(file_in, newlocation, output_type, args):
"""
Compiles the specified C file with Clang, using the specified args.
Stores this file in the specified location and returns the location as a string.
If this is being used to filter the input file and
if the C file successfully compiles it will be entered in the filter file.
:param file_in: File to compile
:param newlocation: location to save LLVM files to
:param output_type: the type that the file must be compiled to, such as
"elf"
:param args: Arguments for the compiler to use while compiling
"""
file_name = Path(file_in).stem
location_path = Path(newlocation)
file_out = str(location_path.joinpath(file_name + output_type).resolve())
command = "clang -shared -undefined dynamic_lookup -Wno-everything -fPIC " + file_in + " " + args + " -o " + file_out
result = subprocess.run(command, shell=True).returncode # , check=True)
if result == 0:
return newlocation + "/" + file_name + output_type
[docs] @staticmethod
def compile_all(file_path, newlocation, out_type, args=""):
"""
Compiles the C file given as a path with Clang, using the specified args.
Writes to a file by calling compile_cfile then returns the
specified location of the file path. If this is being used
to filter the input files, the C files that successfully
compile will be entered in.
:param file_path: File with list of C file names to compile
:param newlocation: location to save LLVM files to
:param out_type: the type that the file must be compiled to, such as "elf"
:param args: Arguments for the compiler to use while compiling
"""
# check if file path exists
input_file_path = Path(file_path)
# check if my file exists
if input_file_path.exists():
# creates new directory if one does not exist.
location_path = Path(newlocation)
if not location_path.is_dir():
location_path.mkdir()
# then compile it and return the data
return Clang.compile_cfile(file_path, newlocation, out_type, args=args)
else:
print("File not Found", file_path)
[docs] @staticmethod
def to_assembly(file_path, newlocation):
"""
Compiles the C file given as a path to x86 assembly.
Writes to a file by calling compile_cfile through compile_all
then returns the specified location of the file path.
:param file_path: file path to compile
:param newlocation: location to save assembly files to
:return: the file location which llvm_unopt was saved to.
:rtype: str or None
"""
args = "-S -masm=intel"
out_type = "-assembly.asm"
return Clang.compile_all(file_path, newlocation, out_type, args=args)
[docs] @staticmethod
def to_elf(file_path, newlocation):
"""
Compiles the C file given as a path to elf executables.
Writes to a file by calling compile_cfile through compile_all
then returns the specified location of the file path.
:param file_path: file path to compile
:param newlocation: location to save LLVM files to
"""
out_type = "-elf.elf"
return Clang.compile_all(file_path, newlocation, out_type)
[docs] @staticmethod
def to_llvm_opt(file_path, newlocation, optlevel=""):
"""
Compiles the C file given as a path to optimized LLVM IR, at
the specified opt level. Writes to a file by calling compile_cfile
through compile_all then returns the specified location of the file path.
:param file_path: File with list of C file names to compile
:param newlocation: location to save LLVM files to
:return: the file location which llvm_unopt was saved to.
:rtype: str or None
"""
args = "-S -emit-llvm " + optlevel
out_type = "-opt.ll"
return Clang.compile_all(file_path, newlocation, out_type, args=args)
[docs] @staticmethod
def to_llvm_unopt(file_path, newlocation):
"""
Compiles the C file given as a path to unoptimized LLVM IR.
Writes to a file by calling compile_cfile through compile_all
then returns the specified location of the file path.
:param file_path: File with list of C file names to compile
:param newlocation: location to save LLVM files to
:return: the file location which llvm_unopt was saved to.
:rtype: str or None
"""
args = "-O1 -Xclang -disable-llvm-passes -S -emit-llvm"
out_type = "-unopt.ll"
return Clang.compile_all(file_path, newlocation, out_type, args=args)
[docs] @staticmethod
def to_object_file(file_path, newlocation):
"""
Compiles the C file given as a path to an object file.
Writes to a file by calling compile_cfile
through compile_all then returns the specified location of the file path.
:param file_path: File with list of C file names to compile
:param newlocation: location to save Object files to
:return: the file location which llvm_unopt was saved to.
:rtype: str or None
"""
args = "-c "
out_type = ".o"
return Clang.compile_all(file_path, newlocation, out_type, args=args)