Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ endif()
# set the project name
project(cpfe)

# Setup CMake module path to find our custom modules (like FindLibGCCJIT.cmake)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

# GCC Backend Option
option(EDG_ENABLE_GCC_BACKEND "Enable the libgccjit backend" OFF)
if(EDG_ENABLE_GCC_BACKEND)
find_package(LibGCCJIT REQUIRED)
endif()

# Check for attempts to use an in-source build.
if("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}")
message(FATAL_ERROR
Expand Down Expand Up @@ -82,6 +91,10 @@ if(NOT WIN32)
set(EDG_BUILD_LIB TRUE CACHE BOOL "Enable the EDG library build")
endif()

# Enable Testing
enable_testing()
include(CTest)

# For GCC and Clang provide an (off by default) option for colored output.
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR
CMAKE_CXX_COMPILER_ID MATCHES "Clang")
Expand Down Expand Up @@ -145,3 +158,29 @@ include(${CMAKE_SOURCE_DIR}/cmake/wrapper.cmake)
# Handle wrapping eccp, needed for building the C library, and general
# development
add_edg_wrapper_script(eccp "." ${CMAKE_SOURCE_DIR}/util/eccp.sh)

if(EDG_ENABLE_GCC_BACKEND)
add_subdirectory(tests/gcc_be)
endif()

# --- CPack Integration ---
set(CPACK_PACKAGE_NAME "edg-cpfe")
set(CPACK_PACKAGE_VERSION "1.0.0")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "EDG C++ Front End (with GCC backend)")
set(CPACK_PACKAGE_VENDOR "Edison Design Group")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt")

if(APPLE)
set(CPACK_GENERATOR "DragNDrop;TGZ")
elseif(WIN32)
set(CPACK_GENERATOR "ZIP;WIX")
elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
set(CPACK_GENERATOR "TXZ")
else()
set(CPACK_GENERATOR "DEB;RPM")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "EDG")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libgccjit0 (>= 10.0.0) | libgccjit-10-dev | libgccjit-11-dev | libgccjit-12-dev | libgccjit-13-dev | libgccjit-14-dev")
set(CPACK_RPM_PACKAGE_REQUIRES "libgccjit")
endif()

include(CPack)
68 changes: 68 additions & 0 deletions cmake/FindLibGCCJIT.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# FindLibGCCJIT
# -------------

find_path(LibGCCJIT_INCLUDE_DIR
NAMES libgccjit.h
PATHS
/usr/include
/usr/local/include
/opt/homebrew/include
/opt/local/include
"C:/msys64/mingw64/include"
"C:/Program Files/GCC/include"
)

find_library(LibGCCJIT_LIBRARY
NAMES gccjit
PATHS
/usr/lib
/usr/local/lib
/usr/lib64
/usr/lib/x86_64-linux-gnu
/usr/lib/aarch64-linux-gnu
/opt/homebrew/lib
/opt/homebrew/lib/gcc/current
/opt/local/lib
"C:/msys64/mingw64/lib"
"C:/Program Files/GCC/lib"
)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LibGCCJIT
REQUIRED_VARS LibGCCJIT_LIBRARY LibGCCJIT_INCLUDE_DIR
)

if(LibGCCJIT_FOUND)
set(LibGCCJIT_INCLUDE_DIRS ${LibGCCJIT_INCLUDE_DIR})
set(LibGCCJIT_LIBRARIES ${LibGCCJIT_LIBRARY})

if(NOT TARGET LibGCCJIT::LibGCCJIT)
add_library(LibGCCJIT::LibGCCJIT UNKNOWN IMPORTED)
set_target_properties(LibGCCJIT::LibGCCJIT PROPERTIES
IMPORTED_LOCATION "${LibGCCJIT_LIBRARY}"
INTERFACE_INCLUDE_DIRECTORIES "${LibGCCJIT_INCLUDE_DIR}"
)
endif()

include(CheckCSourceCompiles)
set(CMAKE_REQUIRED_INCLUDES ${LibGCCJIT_INCLUDE_DIR})

# Inspect header libgccjit.h for feature availability macros
macro(check_libgccjit_feature FEATURE)
check_c_source_compiles("
#include <libgccjit.h>
#ifndef ${FEATURE}
#error \"Feature ${FEATURE} not available\"
#endif
int main() { return 0; }
" ${FEATURE})
endmacro()

check_libgccjit_feature(LIBGCCJIT_HAVE_gcc_jit_context_add_command_line_option)
check_libgccjit_feature(LIBGCCJIT_HAVE_gcc_jit_context_add_driver_option)
check_libgccjit_feature(LIBGCCJIT_HAVE_gcc_jit_context_new_bitcast)
check_libgccjit_feature(LIBGCCJIT_HAVE_gcc_jit_context_new_rvalue_from_vector)
check_libgccjit_feature(LIBGCCJIT_HAVE_gcc_jit_version)
endif()

mark_as_advanced(LibGCCJIT_INCLUDE_DIR LibGCCJIT_LIBRARY)
49 changes: 49 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,42 @@ if(MSVC)
link_libraries(mscoree)
endif()

if(EDG_ENABLE_GCC_BACKEND)
add_compile_definitions(BACK_END_IS_GCC_GEN_BE=1)
list(APPEND CORE_FRONT_END_SOURCE_FILES
"${PROJECT_SOURCE_DIR}/gcc_gen_be_error.c"
"${PROJECT_SOURCE_DIR}/gcc_gen_be_context.c"
"${PROJECT_SOURCE_DIR}/gcc_gen_be_cache.c"
"${PROJECT_SOURCE_DIR}/gcc_gen_be_lib_loader.c"
"${PROJECT_SOURCE_DIR}/gcc_gen_be_location.c"
"${PROJECT_SOURCE_DIR}/gcc_gen_be_type.c"
"${PROJECT_SOURCE_DIR}/gcc_gen_be_decl.c"
"${PROJECT_SOURCE_DIR}/gcc_gen_be_expr.c"
"${PROJECT_SOURCE_DIR}/gcc_gen_be_stmt.c"
"${PROJECT_SOURCE_DIR}/gcc_gen_be_main.c"
)
link_libraries(LibGCCJIT::LibGCCJIT)
if(APPLE)
set(CMAKE_INSTALL_RPATH "@executable_path/../lib;@rpath")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
endif()
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)

if(MSVC)
add_link_options(/DELAYLOAD:libgccjit.dll)
endif()

if(BUILD_TESTING OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set_source_files_properties("${PROJECT_SOURCE_DIR}/gcc_gen_be_error.c" "${PROJECT_SOURCE_DIR}/gcc_gen_be_context.c" "${PROJECT_SOURCE_DIR}/gcc_gen_be_cache.c" "${PROJECT_SOURCE_DIR}/gcc_gen_be_lib_loader.c" "${PROJECT_SOURCE_DIR}/gcc_gen_be_location.c" "${PROJECT_SOURCE_DIR}/gcc_gen_be_type.c" "${PROJECT_SOURCE_DIR}/gcc_gen_be_decl.c" "${PROJECT_SOURCE_DIR}/gcc_gen_be_expr.c" "${PROJECT_SOURCE_DIR}/gcc_gen_be_stmt.c" "${PROJECT_SOURCE_DIR}/gcc_gen_be_main.c" PROPERTIES COMPILE_OPTIONS "-fprofile-arcs;-ftest-coverage")
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_link_options(-lgcov)
else()
add_link_options(--coverage)
endif()
endif()
endif()

add_custom_target(cpfe-all)

# A quirk of CMake is that scoping is really done in CMakeLists.txt files via
Expand All @@ -254,3 +290,16 @@ add_custom_target(cpfe-all)
add_subdirectory(cmake/cpfe)
add_subdirectory(cmake/cpfe-cp)
add_subdirectory(cmake/cdisp)


if(EDG_ENABLE_GCC_BACKEND)
# Apply coverage instrumentation specifically to gcc_gen_be_*.c
set_source_files_properties(gcc_gen_be_*.c PROPERTIES COMPILE_FLAGS "--coverage")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set_source_files_properties(gcc_gen_be_*.c PROPERTIES COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
target_link_libraries(cpfe PRIVATE gcov)
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set_source_files_properties(gcc_gen_be_*.c PROPERTIES COMPILE_FLAGS "--coverage")
target_link_options(cpfe PRIVATE "--coverage")
endif()
endif()
11 changes: 10 additions & 1 deletion src/cfe.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,13 @@ Open-sourced in September of 2026.
#if BACK_END_IS_CP_GEN_BE
#include "cp_gen_be.h"
#endif /* BACK_END_IS_CP_GEN_BE */
#if BACK_END_IS_GCC_GEN_BE
#include "gcc_gen_be_main.h"
#include "gcc_gen_be_context.h"
#include "gcc_gen_be_context.h"
#endif /* BACK_END_IS_GCC_GEN_BE */
#if BACK_END_SHOULD_BE_CALLED && \
!BACK_END_IS_C_GEN_BE && !BACK_END_IS_CP_GEN_BE
!BACK_END_IS_C_GEN_BE && !BACK_END_IS_CP_GEN_BE && !BACK_END_IS_GCC_GEN_BE
/*
Provide a declaration for a non-EDG-supplied back end (not in the "edg"
namespace).
Expand Down Expand Up @@ -104,6 +109,10 @@ MAKE_FRONT_END_CALLABLE is TRUE.
if it wasn't invoked during this compilation). */
cp_gen_be_early_init();
#endif /* BACK_END_SHOULD_BE_CALLED && BACK_END_IS_CP_GEN_BE && ... */
#if BACK_END_SHOULD_BE_CALLED && BACK_END_IS_GCC_GEN_BE && \
MAKE_FRONT_END_CALLABLE
gcc_gen_be_early_init();
#endif /* BACK_END_SHOULD_BE_CALLED && BACK_END_IS_GCC_GEN_BE && ... */
/* Get the execution starting time. Do this unconditionally because the
timing command line option will not have been processed yet. This must
be done after the early initialization done above. */
Expand Down
35 changes: 35 additions & 0 deletions src/cmd_line.c
Original file line number Diff line number Diff line change
Expand Up @@ -1806,6 +1806,21 @@ Initialize the option information table.
/*arg_required=*/FALSE, pchek_command_line);
add_option_description(optk_incognito, "no_incognito", '\0', /*value=*/FALSE,
/*arg_required=*/FALSE, pchek_command_line);

#if BACK_END_IS_GCC_GEN_BE
add_option_description(optk_gcc_be_O0, "O0", '\0', TRUE, FALSE, pchek_command_line);
add_option_description(optk_gcc_be_O1, "O1", '\0', TRUE, FALSE, pchek_command_line);
add_option_description(optk_gcc_be_O2, "O2", '\0', TRUE, FALSE, pchek_command_line);
add_option_description(optk_gcc_be_O3, "O3", '\0', TRUE, FALSE, pchek_command_line);
add_option_description(optk_gcc_be_Os, "Os", '\0', TRUE, FALSE, pchek_command_line);
add_option_description(optk_gcc_be_Ofast, "Ofast", '\0', TRUE, FALSE, pchek_command_line);
add_option_description(optk_gcc_be_g, "g", '\0', TRUE, FALSE, pchek_command_line);
add_option_description(optk_gcc_be_fPIC, "fPIC", '\0', TRUE, FALSE, pchek_command_line);
add_option_description(optk_gcc_be_fPIE, "fPIE", '\0', TRUE, FALSE, pchek_command_line);
add_option_description(optk_gcc_be_dump_initial_tree, "fdump-tree-all", '\0', TRUE, FALSE, pchek_command_line);
add_option_description(optk_gcc_be_dump_gimple, "fdump-tree-gimple", '\0', TRUE, FALSE, pchek_command_line);
#endif /* BACK_END_IS_GCC_GEN_BE */

} /* initialize_option_descriptions */


Expand Down Expand Up @@ -12250,6 +12265,21 @@ Process the arguments on the command line that invoked the compiler.
case optk_incognito:
incognito = opt_value;
break;

#if BACK_END_IS_GCC_GEN_BE
case optk_gcc_be_O0: gcc_be_opt_level = 0; break;
case optk_gcc_be_O1: gcc_be_opt_level = 1; break;
case optk_gcc_be_O2: gcc_be_opt_level = 2; break;
case optk_gcc_be_O3: gcc_be_opt_level = 3; break;
case optk_gcc_be_Os: gcc_be_opt_level = 2; /* libgccjit doesn't have Os natively, map to 2 */ break;
case optk_gcc_be_Ofast: gcc_be_opt_level = 3; break;
case optk_gcc_be_g: gcc_be_debug_info = TRUE; break;
case optk_gcc_be_fPIC: gcc_be_fPIC = TRUE; break;
case optk_gcc_be_fPIE: gcc_be_fPIE = TRUE; break;
case optk_gcc_be_dump_initial_tree: gcc_be_dump_initial_tree = TRUE; break;
case optk_gcc_be_dump_gimple: gcc_be_dump_gimple = TRUE; break;
#endif /* BACK_END_IS_GCC_GEN_BE */

default:
/* It should not be possible to get here. */
unexpected_condition();
Expand Down Expand Up @@ -13041,6 +13071,11 @@ Process the arguments on the command line that invoked the compiler.
create_template_deduction_name_references = NEED_NAME_MANGLING;
/* If the -o option appeared, its file should have been taken for
something. */
#if BACK_END_IS_GCC_GEN_BE
gcc_be_output_file_name = ofile_name;
ofile_name = NULL;
#endif

if (ofile_name != NULL) {
command_line_error(ec_cl_no_output_file_needed);
} /* if */
Expand Down
32 changes: 29 additions & 3 deletions src/cmd_line.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,21 @@ enum an_option_kind {
optk_dump_command_options,
optk_output_mode,
optk_incognito,
optk_last /* Must be last. */
};
#if BACK_END_IS_GCC_GEN_BE
optk_gcc_be_O0,
optk_gcc_be_O1,
optk_gcc_be_O2,
optk_gcc_be_O3,
optk_gcc_be_Os,
optk_gcc_be_Ofast,
optk_gcc_be_g,
optk_gcc_be_fPIC,
optk_gcc_be_fPIE,
optk_gcc_be_dump_initial_tree,
optk_gcc_be_dump_gimple,
#endif /* BACK_END_IS_GCC_GEN_BE */
optk_last /* Must be last. */
};

/* C_dialect is in basics.h. */

Expand Down Expand Up @@ -480,7 +493,20 @@ EXTERN_THREAD FILE
TRUE. */
EXTERN_THREAD a_const_char
*pp_file_name;
/* Name of the preprocessing output file to be

EXTERN_THREAD a_const_char
*gcc_be_output_file_name;

#if BACK_END_IS_GCC_GEN_BE
EXTERN_THREAD int gcc_be_opt_level;
EXTERN_THREAD a_boolean gcc_be_debug_info;
EXTERN_THREAD a_boolean gcc_be_fPIC;
EXTERN_THREAD a_boolean gcc_be_fPIE;
EXTERN_THREAD a_boolean gcc_be_dump_initial_tree;
EXTERN_THREAD a_boolean gcc_be_dump_gimple;
#endif /* BACK_END_IS_GCC_GEN_BE */

/* Name of the preprocessing output file to be
opened, or NULL if no such file is needed or if
a default file should be used. */
EXTERN_THREAD a_boolean
Expand Down
Loading