diff --git a/configure.ac b/configure.ac
index d87d30f..0d234d7 100755
--- a/configure.ac
+++ b/configure.ac
@@ -23,7 +23,7 @@ AC_PROG_CC([gcc])
AC_DEFINE_UNQUOTED([GCC_PATH], ["$CC"], [GCC path for dragonegg])
AC_SUBST(GCC_PATH, $CC)
-AX_LLVM([7.0],[16.0],[all])
+AX_LLVM([7.0],[16.0.6],[all])
AC_SUBST(LLVM_CPPFLAGS, $LLVM_CPPFLAGS)
# Check if Fortran/flang has been enabled (disabled by default)
@@ -37,6 +37,9 @@ fi
AC_DEFINE_UNQUOTED([FORTRAN_SUPPORT], ["$with_flang"], [enables or disables Fortran/flang support])
AC_SUBST(FORTRAN_SUPPORT, $with_flang)
+# Define Automake var to optionally distribute ceref
+AM_CONDITIONAL([WITH_FLANG], [test "x$with_flang" = "xyes"])
+
# The profiler and gfortran libraries added to LIBS by AC_CHECK_LIB are needed only at
# cere run time, not when building cere. Therefore we have to reset LIBS.
LIBS=""
@@ -113,6 +116,7 @@ AC_C_BIGENDIAN(
[AC_MSG_ERROR([universal endianess not supported])]
)
+
# Check for Python >= 3
AM_PATH_PYTHON([3])
diff --git a/src/Makefile.am b/src/Makefile.am
index 77a09cc..629f578 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,23 +1,29 @@
SUBDIRS=ccan rdtsc memory_dump RegionOutliner RegionInstrumentation RegionReplay RegionDump GlobalRename
-dist_bin_SCRIPTS=cerec
+dist_bin_SCRIPTS = cerec cerec++
+if WITH_FLANG
+ dist_bin_SCRIPTS += ceref
+endif
+
pkgpython_PYTHON= \
+ cere/compiler_frontend.py \
cere/lel.py \
+ cere/lec.py \
+ cere/vars.py \
+ cere/utils.py \
+ cere/__main__.py \
cere/cere_sanity_check.py \
cere/ilp_update_graph.py \
cere/cere_trace.py \
cere/granularity.py \
cere/cere_regions.py \
- cere/__main__.py \
cere/cere_select_max_cov.py \
cere/cere_selectinv.py \
cere/graph_utils.py \
- cere/vars.py \
cere/compress.py \
cere/__init__.py \
cere/cere_select_ilp.py \
cere/cere_profile.py \
- cere/utils.py \
cere/cere_hybrid.py \
cere/errors.py \
cere/max_cov_update_graph.py \
@@ -25,7 +31,6 @@ pkgpython_PYTHON= \
cere/graph_error.py \
cere/cere_check_matching.py \
cere/regions_selector.py \
- cere/lec.py \
cere/cere_instrument.py \
cere/cere_replay.py \
cere/cere_capture.py \
diff --git a/src/cere/compiler_frontend.py b/src/cere/compiler_frontend.py
new file mode 100755
index 0000000..090e90d
--- /dev/null
+++ b/src/cere/compiler_frontend.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python
+# This file is part of CERE.
+#
+# Copyright (c) 2013-2016, Universite de Versailles St-Quentin-en-Yvelines
+#
+# CERE is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License,
+# or (at your option) any later version.
+#
+# CERE is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with CERE. If not, see .
+
+import argparse
+import os
+import sys
+from cere.vars import *
+import cere.lec as lec
+import cere.lel as lel
+
+# By default, compile for C
+COMPILER = CLANG
+
+option_forbidden = set([("dump", "--instrument"),
+ ("dump", "--nested-regions"),
+ ("dump", "--no-nested-regions"),
+ ("dump", "--instrument-app"),
+ ("dump", "--hybrid"),
+ ("dump", "--static"),
+ ("replay", "--regions-file"),
+ ("replay", "--nested-regions"),
+ ("replay", "--no-nested-regions"),
+ ("replay", "--instrument-app"),
+ ("replay", "--hybrid")])
+
+#to ignore prefix matching
+class MyParser(argparse.ArgumentParser):
+ def _get_option_tuples(self, option_string):
+ return []
+
+#Allowed option verification
+class OptAction(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ if (parser.description, option_string) in option_forbidden:
+ exit("Error:can't {option} in {mode} mode".format(
+ option=option_string, mode=parser.description))
+ else:
+ if (self.const):
+ setattr(namespace, self.dest, self.const)
+ else:
+ setattr(namespace, self.dest, values)
+
+#Initialize Includes parser
+class IncludeAction(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ namespace.Inc = (namespace.Inc + [option_string + values])
+
+def init_parser_incl(parser, liste):
+ parser.set_defaults(Inc=[])
+ for j in liste:
+ parser.add_argument(j, action=IncludeAction)
+
+# initialize subparsers
+def init_subpars(parser, region_required):
+ parser.add_argument('--region', action=OptAction, required=region_required)
+ parser.add_argument('--regions-file', action=OptAction)
+ parser.add_argument('--invocation', action=OptAction)
+ parser.add_argument('--instrument', action=OptAction, nargs=0,
+ const=True, default=False)
+ parser.add_argument('--instrument-app', action=OptAction, nargs=0,
+ const=True, default=False)
+ parser.add_argument('--regions-infos', action=OptAction, default="")
+ parser.add_argument('--hybrid-regions', action=OptAction, default="")
+ parser.add_argument('--extraction-lvl', action=OptAction, default="")
+ parser.add_argument('--cere-objects', action=OptAction, default="")
+ parser.add_argument('--hybrid', action=OptAction, nargs=0,
+ const=True, default=False)
+ parser.add_argument('--static', action=OptAction, nargs=0,
+ const=True, default=False)
+ parser.add_argument('--wrapper', action=OptAction, default="")
+ parser.add_argument('-o')
+ parser.add_argument('-c', action=OptAction, nargs=0,
+ const=True, default=False)
+
+def init_parser_core(parser):
+ '''
+ initialize main parser
+ Create Subparsers for dump replay and original mode and
+ manage version
+ '''
+ parser.add_argument('--version', '-v', action='version',
+ version='%(prog)s '+VERSION)
+ subparsers = parser.add_subparsers(help='sub-command help')
+ parser_dump = subparsers.add_parser('dump', description='dump')
+ init_subpars(parser_dump, True)
+ parser_dump.set_defaults(func="dump_fun")
+ parser_replay = subparsers.add_parser('replay', description='replay')
+ init_subpars(parser_replay, True)
+ parser_replay.set_defaults(func="replay_fun")
+ parser_instrument = subparsers.add_parser('original',
+ description='original')
+ init_subpars(parser_instrument, False)
+ parser_instrument.set_defaults(func="original_fun")
+
+
+def fail_frontend(error_message):
+ exit("Error {prog} : {cmd}".format(prog='compiler_frontend', cmd=error_message))
+
+def safe_system(command):
+ '''
+ Try-catch system call
+ Verify system call and exit with appropriate error message
+ '''
+ ret = os.system(command)
+ if(ret):
+ fail_frontend("safe_system -> " + command)
+
+
+def run(lang, argv):
+ '''
+ Main function
+ '''
+
+ # Select compiler depending on lang
+ if lang == "c":
+ COMPILER = CLANG
+ elif lang == "cpp":
+ COMPILER = CLANGPP
+ elif lang == "fortran":
+ if FORTRAN_SUPPORT:
+ compiler = "flang"
+ else:
+ fail_lec("Fortran support disabled in this build (reconfigure & reinstall using --with-flang).")
+
+ # Get CERE_MODE from environment variable
+ # If CERE_MODE is not defined, we "short-circuit" the normal build process by
+ # performing a simple compiler call by passing the flags directly to the LLVM frontend.
+ # This avoids unnecessary compiltion steps that dump the .ll files and can cause issues,
+ # for instance where build systems such as CMake and autotools build a bunch of test
+ # programs to validate the compiler.
+ try:
+ cere_args = os.environ["CERE_MODE"].split()
+ except KeyError:
+ print("Compiling in normal mode (CERE_MODE undefined)")
+ argv = " ".join(argv[1:])
+ safe_system("{0} {1}".format(COMPILER, argv))
+ exit(0)
+
+
+ # Create parsers
+ parser = MyParser()
+ # This second parser does not remove prefix matching
+ incl_parser = argparse.ArgumentParser()
+ init_parser_core(parser)
+ init_parser_incl(incl_parser, ["-I", "-D"])
+
+ #Parse args
+ args = parser.parse_known_args(cere_args + sys.argv[1:])
+ args2 = incl_parser.parse_known_args(args[1])
+ if args[0].c:
+ lec.compile(args, args2, COMPILER)
+ else:
+ lel.link(args, COMPILER)
diff --git a/src/cere/lec.py b/src/cere/lec.py
index ab79abe..4f4c7d4 100755
--- a/src/cere/lec.py
+++ b/src/cere/lec.py
@@ -20,6 +20,9 @@
from cere.vars import *
+# By default, compile for C
+COMPILER = CLANG
+
OMP_FLAGS=""
if "CERE_OMP" in os.environ:
OMP_FLAGS="-omp"
@@ -217,24 +220,11 @@ def original_fun(mode_opt, BASE, regions):
def first_compil(INCLUDES, SOURCE, BASE, ext, COMPIL_OPT):
'''
- First Compilation
- Detect source language (fortran or C/C++ for the moment)
- and compile SOURCE code
+ On first compilation, generate .ll files for later custom passes
'''
- if ext in FORTRAN_EXTENSIONS:
- if FORTRAN_SUPPORT:
- compiler = "flang"
-
- else:
- fail_lec("Fortran support disabled in this build (recompile using --with-flang).")
- elif ext in CXX_EXTENSIONS:
- compiler = "clang++"
- else:
- compiler = "clang"
-
- safe_system(("{llvm_bindir}/{compiler} {opts} -O0 -g {includes} {source} -S -emit-llvm -o " +
- "{base}.ll").format(compiler=compiler, llvm_bindir=LLVM_BINDIR, opts=" ".join(COMPIL_OPT), includes=" ".join(INCLUDES),
+ safe_system(("{compiler} {opts} -O0 -g {includes} {source} -S -emit-llvm -o " +
+ "{base}.ll").format(compiler=COMPILER, llvm_bindir=LLVM_BINDIR, opts=" ".join(COMPIL_OPT), includes=" ".join(INCLUDES),
source=SOURCE, base=BASE))
def last_compil(INCLUDES, SOURCE, BASE, OBJECT, COMPIL_OPT):
@@ -279,12 +269,14 @@ def last_compil(INCLUDES, SOURCE, BASE, OBJECT, COMPIL_OPT):
llvm_bindir=LLVM_BINDIR, opts=" ".join(COMPIL_OPT), includes=" ".join(INCLUDES),
backend_flags=BACKEND_FLAGS, source=SOURCE, base=BASE, object=OBJECT))
-def compile(args, args2):
+def compile(args, args2, new_compiler):
function={}
function["replay_fun"] = replay_fun
function["dump_fun"] = dump_fun
function["original_fun"] = original_fun
+ COMPILER = new_compiler
+
SOURCES = []
if (len(args2[1]) == 0):
exit("Error:Need source file")
diff --git a/src/cere/lel.py b/src/cere/lel.py
index 8b34f08..1e624f1 100755
--- a/src/cere/lel.py
+++ b/src/cere/lel.py
@@ -23,6 +23,9 @@
from cere.vars import *
from cere.compress import compress
+# By default, compile for C
+COMPILER = CLANG
+
def grep(path, regex):
regex=".*"+regex+".*"
regObj = re.compile(regex)
@@ -92,7 +95,7 @@ def dump_fun(mode_opt, BINARY, COMPIL_OPT):
'''
safe_system(("{link} {opts} -o {binary} {libdir} " +
"-Wl,-z,now -lcere_dump -ldl"
- ).format(link=CLANGPP, binary=BINARY,
+ ).format(link=COMPILER, binary=BINARY,
opts=COMPIL_OPT, Root=PROJECT_ROOT,libdir=LIBDIR_FLAGS))
def sysout(cmd):
@@ -244,25 +247,26 @@ def original_fun(mode_opt, BINARY, COMPIL_OPT):
if(mode_opt.instrument_app):
safe_system(("{link} -o {binary} {opts} {libs} {libdir}").format(
- link=CLANGPP, binary=BINARY, opts=COMPIL_OPT, libs=PROFILE_LIB,
+ link=COMPILER, binary=BINARY, opts=COMPIL_OPT, libs=PROFILE_LIB,
libdir=LIBDIR_FLAGS))
elif(mode_opt.instrument):
safe_system(("{link} -o {binary} {opts} {wrapper} {libdir}").format(
- link=CLANGPP, binary=BINARY, opts=COMPIL_OPT,
+ link=COMPILER, binary=BINARY, opts=COMPIL_OPT,
wrapper=mode_opt.wrapper, libdir=LIBDIR_FLAGS))
else:
- # NOTE In all linker modes, we now use CLANGPP by default in case we link
- # some objects containing C++ symbols.
- safe_system(("{link} -o {binary} {opts}").format(link=CLANGPP,
+ safe_system(("{link} -o {binary} {opts}").format(link=COMPILER,
binary=BINARY, opts=COMPIL_OPT))
-def link(args):
+def link(args, new_compiler):
function={}
function["replay_fun"] = replay_fun
function["dump_fun"] = dump_fun
function["original_fun"] = original_fun
+
+ COMPILER = new_compiler
+
if (len(args[1]) == 0):
exit("Error:Need source file")
objs = ""
diff --git a/src/cere/vars.py.in.in b/src/cere/vars.py.in.in
index 7d056cc..325242e 100755
--- a/src/cere/vars.py.in.in
+++ b/src/cere/vars.py.in.in
@@ -21,11 +21,17 @@ VERSION = "@PACKAGE_VERSION@"
FORTRAN_SUPPORT="@FORTRAN_SUPPORT@"
CLANG = os.path.join("@LLVM_BINDIR@","clang")
CLANGPP = os.path.join("@LLVM_BINDIR@","clang++")
+FLANG = os.path.join("@LLVM_BINDIR@","flang")
PPROF = "@PPROF@"
LLVM_BINDIR = "@LLVM_BINDIR@"
GCC="@GCC_PATH@"
LIBDIR = "%LIBDIR%"
+C_EXTENSIONS=[".c", ".C"]
+CXX_EXTENSIONS=[".cpp", ".cc", ".cxx", ".CPP", ".CC", ".CXX"]
+FORTRAN_EXTENSIONS=[".f", ".f90", ".f77", ".F", ".F90", ".F77"]
+SOURCE_EXTENSIONS= C_EXTENSIONS + CXX_EXTENSIONS + FORTRAN_EXTENSIONS
+
ROOT = os.path.dirname(os.path.realpath(__file__))
PROJECT_ROOT = os.path.dirname(os.path.realpath(__file__+"/.."))
PROFILE_LIB = "-lprofiler"
@@ -39,12 +45,8 @@ GLOB_RENAME = LIBDIR + "/libcere_globalrename.so"
LIBDIR_FLAGS = "-L {libdir} -Wl,--rpath={libdir}".format(libdir=LIBDIR)
RDTSC_WRAPPER = "-lcere_rdtsc"
LIKWID = "-llikwid"
-FORTRAN_EXTENSIONS=[".f", ".f90", ".f77", ".F90"]
-CXX_EXTENSIONS=[".cpp", ".cc", ".cxx"]
DUMPS_DIR = ".cere/dumps/"
-SOURCE_EXTENSIONS=[".C", ".c"] + CXX_EXTENSIONS + FORTRAN_EXTENSIONS
-
INVALID_REGION_FILE = "invalid_regions"
CERE_DIRECTORIES = []
diff --git a/src/cerec b/src/cerec
index 69d0ae0..13223ba 100755
--- a/src/cerec
+++ b/src/cerec
@@ -1,132 +1,7 @@
#!/usr/bin/env python
-# This file is part of CERE.
-#
-# Copyright (c) 2013-2016, Universite de Versailles St-Quentin-en-Yvelines
-#
-# CERE is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License,
-# or (at your option) any later version.
-#
-# CERE is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with CERE. If not, see .
-import argparse
-import os
+from cere import compiler_frontend
import sys
-from cere.vars import *
-import cere.lec as lec
-import cere.lel as lel
-
-option_forbidden = set([("dump", "--instrument"),
- ("dump", "--nested-regions"),
- ("dump", "--no-nested-regions"),
- ("dump", "--instrument-app"),
- ("dump", "--hybrid"),
- ("dump", "--static"),
- ("replay", "--regions-file"),
- ("replay", "--nested-regions"),
- ("replay", "--no-nested-regions"),
- ("replay", "--instrument-app"),
- ("replay", "--hybrid")])
-
-#to ignore prefix matching
-class MyParser(argparse.ArgumentParser):
- def _get_option_tuples(self, option_string):
- return []
-
-#Allowed option verification
-class OptAction(argparse.Action):
- def __call__(self, parser, namespace, values, option_string=None):
- if (parser.description, option_string) in option_forbidden:
- exit("Error:can't {option} in {mode} mode".format(
- option=option_string, mode=parser.description))
- else:
- if (self.const):
- setattr(namespace, self.dest, self.const)
- else:
- setattr(namespace, self.dest, values)
-
-#Initialize Includes parser
-class IncludeAction(argparse.Action):
- def __call__(self, parser, namespace, values, option_string=None):
- namespace.Inc = (namespace.Inc + [option_string + values])
-
-def init_parser_incl(parser, liste):
- parser.set_defaults(Inc=[])
- for j in liste:
- parser.add_argument(j, action=IncludeAction)
-
-# initialize subparsers
-def init_subpars(parser, region_required):
- parser.add_argument('--region', action=OptAction, required=region_required)
- parser.add_argument('--regions-file', action=OptAction)
- parser.add_argument('--invocation', action=OptAction)
- parser.add_argument('--instrument', action=OptAction, nargs=0,
- const=True, default=False)
- parser.add_argument('--instrument-app', action=OptAction, nargs=0,
- const=True, default=False)
- parser.add_argument('--regions-infos', action=OptAction, default="")
- parser.add_argument('--hybrid-regions', action=OptAction, default="")
- parser.add_argument('--extraction-lvl', action=OptAction, default="")
- parser.add_argument('--cere-objects', action=OptAction, default="")
- parser.add_argument('--hybrid', action=OptAction, nargs=0,
- const=True, default=False)
- parser.add_argument('--static', action=OptAction, nargs=0,
- const=True, default=False)
- parser.add_argument('--wrapper', action=OptAction, default="")
- parser.add_argument('-o')
- parser.add_argument('-c', action=OptAction, nargs=0,
- const=True, default=False)
-
-def init_parser_core(parser):
- '''
- initialize main parser
- Create Subparsers for dump replay and original mode and
- manage version
- '''
- parser.add_argument('--version', '-v', action='version',
- version='%(prog)s '+VERSION)
- subparsers = parser.add_subparsers(help='sub-command help')
- parser_dump = subparsers.add_parser('dump', description='dump')
- init_subpars(parser_dump, True)
- parser_dump.set_defaults(func="dump_fun")
- parser_replay = subparsers.add_parser('replay', description='replay')
- init_subpars(parser_replay, True)
- parser_replay.set_defaults(func="replay_fun")
- parser_instrument = subparsers.add_parser('original',
- description='original')
- init_subpars(parser_instrument, False)
- parser_instrument.set_defaults(func="original_fun")
if __name__ == "__main__":
- '''
- Main function
- '''
- # Get CERE_MODE from environment variable
- # If CERE_MODE is not defined we build the original binary
- try:
- cere_args = os.environ["CERE_MODE"].split()
- except KeyError:
- print("cerec: CERE_MODE not defined. Building original binary.")
- cere_args = ["original"]
-
- # Create parsers
- parser = MyParser()
- # This second parser does not remove prefix matching
- incl_parser = argparse.ArgumentParser()
- init_parser_core(parser)
- init_parser_incl(incl_parser, ["-I", "-D"])
-
- #Parse args
- args = parser.parse_known_args(cere_args + sys.argv[1:])
- args2 = incl_parser.parse_known_args(args[1])
- if args[0].c:
- lec.compile(args, args2)
- else:
- lel.link(args)
+ compiler_frontend.run("c", sys.argv)
diff --git a/src/cerec++ b/src/cerec++
new file mode 100755
index 0000000..281778b
--- /dev/null
+++ b/src/cerec++
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+from cere import compiler_frontend
+import sys
+
+if __name__ == "__main__":
+ compiler_frontend.run("cpp", sys.argv)
diff --git a/src/ceref b/src/ceref
new file mode 100755
index 0000000..1281551
--- /dev/null
+++ b/src/ceref
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+from cere import compiler_frontend
+import sys
+
+if __name__ == "__main__":
+ compiler_frontend.run("fortran", sys.argv)