From 765733e00646148740bf06ef09ca95077746a1da Mon Sep 17 00:00:00 2001 From: jakeallen Date: Thu, 11 Jan 2024 18:18:09 -0800 Subject: [PATCH] compiler_cmake --- compiler/CMakeLists.txt | 22 +++++++ compiler/cmake/LLVMIRTest.cmake | 111 ++++++++++++++++++++++++++++++++ compiler/cmake/RISCVTest.cmake | 110 +++++++++++++++++++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 compiler/CMakeLists.txt create mode 100644 compiler/cmake/LLVMIRTest.cmake create mode 100644 compiler/cmake/RISCVTest.cmake diff --git a/compiler/CMakeLists.txt b/compiler/CMakeLists.txt new file mode 100644 index 0000000..bb9f580 --- /dev/null +++ b/compiler/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.16) +option(BUILD_IR_TESTING "Build IR testing" OFF) + +# Common build options +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0") +# set(BUILD_IR_TESTING true) + +# Generic includes +set(INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/include") +include_directories(${INCLUDE_DIRECTORIES}) + +# Compiler sources +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) +add_subdirectory(src) +add_subdirectory(runtime) + +# Unit tests +include(CTest) +if(BUILD_TESTING) + add_subdirectory(test) +endif(BUILD_TESTING) diff --git a/compiler/cmake/LLVMIRTest.cmake b/compiler/cmake/LLVMIRTest.cmake new file mode 100644 index 0000000..f90523a --- /dev/null +++ b/compiler/cmake/LLVMIRTest.cmake @@ -0,0 +1,111 @@ +# arguments checking +if(NOT COMPILER) + message(FATAL_ERROR "Require COMPILER to be defined") +endif(NOT COMPILER) + +if(NOT RUNTIME) + message(FATAL_ERROR "Require RUNTIME to be defined") +endif(NOT RUNTIME) + +if(NOT TEST_DIR) + message(FATAL_ERROR "Require TEST_DIR to be defined") +endif(NOT TEST_DIR) + +if(NOT TEST_NAME) + message(FATAL_ERROR "Require TEST_NAME to be defined") +endif(NOT TEST_NAME) + +# Sources +set(TEST_SRC "${TEST_DIR}/${TEST_NAME}.sy") + +if(EXISTS "${TEST_DIR}/${TEST_NAME}.in") + set(TEST_INS "${TEST_DIR}/${TEST_NAME}.in") +else(EXISTS "${TEST_DIR}/${TEST_NAME}.in") + set(TEST_INS "/dev/null") +endif(EXISTS "${TEST_DIR}/${TEST_NAME}.in") + +set(RUNTIME_ASM "${RUNTIME}/sysy.ll") + +# Generated +set(TEST_ASM "${TEST_NAME}.ll") +set(TEST_BTC "${TEST_NAME}.bc") +set(TEST_OUT "${TEST_NAME}_ir.out") +configure_file("${TEST_DIR}/${TEST_NAME}.out" "${TEST_NAME}.ref" NEWLINE_STYLE LF) +set(TEST_REF "${TEST_NAME}.ref") + +# SysY to LLVM IR +execute_process( + COMMAND + ${COMPILER} -c ${TEST_SRC} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + OUTPUT_FILE ${TEST_ASM} + ERROR_VARIABLE TEST_ERR + RESULT_VARIABLE TEST_RET +) + +if(TEST_RET) + message(SEND_ERROR "Failed: SysY Compiler Error in ${TEST_SRC}: ${TEST_ERR}") + file(READ "${TEST_SRC}" TEST_SRC_CONTENT) + message(NOTICE "Source File:\n ${TEST_SRC_CONTENT}") + return() +endif(TEST_RET) + +# LLVM IR & Runtime link to BitCode +execute_process( + COMMAND + llvm-link "${RUNTIME_ASM}" "${CMAKE_CURRENT_BINARY_DIR}/${TEST_ASM}" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + OUTPUT_FILE ${TEST_BTC} + ERROR_VARIABLE TEST_ERR + RESULT_VARIABLE TEST_RET +) + +if(TEST_RET) + message(SEND_ERROR "Failed: LLVM Link Error in ${TEST_SRC}: ${TEST_ERR}") + file(READ "${TEST_ERR}" TEST_ERR_CONTENT) + message(NOTICE "Generated Assmebly:\n ${TEST_ERR_CONTENT}") + return() +endif(TEST_RET) + +# Run BitCode with lli +execute_process( + COMMAND + lli ${TEST_BTC} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + INPUT_FILE ${TEST_INS} + OUTPUT_VARIABLE TEST_OUT_CONTENT + ERROR_VARIABLE TEST_ERR + RESULT_VARIABLE TEST_RET + TIMEOUT 10 +) + +# Append EOF LR, if not presented +if(TEST_OUT_CONTENT) + string(LENGTH "${TEST_OUT_CONTENT}" TEST_OUT_LEN) + math(EXPR TEST_OUT_LAST "${TEST_OUT_LEN} - 1") + string(SUBSTRING "${TEST_OUT_CONTENT}" ${TEST_OUT_LAST} 1 LAST_CHAR) + + if(NOT "${LAST_CHAR}" STREQUAL "\n") + # If it's not, append a newline to var + set(TEST_OUT_CONTENT "${TEST_OUT_CONTENT}\n") + endif() +endif(TEST_OUT_CONTENT) + +set(TEST_OUT_CONTENT "${TEST_OUT_CONTENT}${TEST_RET}\n") +file(WRITE "${TEST_OUT}" "${TEST_OUT_CONTENT}") + +execute_process( + COMMAND "${CMAKE_COMMAND}" -E compare_files "${TEST_OUT}" "${TEST_REF}" + RESULT_VARIABLE TEST_RESULT +) + +if(TEST_RESULT) + # get_filename_component(TESTNAME "${TEST_ARGS}" NAME) + # file(RENAME "${TEST_OUTPUT}" "${CMAKE_BINARY_DIR}/${TESTNAME}.out") + # file(WRITE "${CMAKE_BINARY_DIR}/${TESTNAME}.err" ${TEST_ERROR}) + message(SEND_ERROR "Failed: The output of ${TEST_NAME} did not match ${TEST_REF}") + file(READ ${TEST_REF} TEST_REF_CONTENT) + message(NOTICE "Expected Output: ${TEST_REF_CONTENT}") + message(NOTICE "Auctual Output: ${TEST_OUT_CONTENT}") + return() +endif(TEST_RESULT) \ No newline at end of file diff --git a/compiler/cmake/RISCVTest.cmake b/compiler/cmake/RISCVTest.cmake new file mode 100644 index 0000000..6f41ef7 --- /dev/null +++ b/compiler/cmake/RISCVTest.cmake @@ -0,0 +1,110 @@ +# arguments checking +if(NOT COMPILER) + message(FATAL_ERROR "Require COMPILER to be defined") +endif(NOT COMPILER) + +if(NOT RUNTIME) + message(FATAL_ERROR "Require RUNTIME to be defined") +endif(NOT RUNTIME) + +if(NOT TEST_DIR) + message(FATAL_ERROR "Require TEST_DIR to be defined") +endif(NOT TEST_DIR) + +if(NOT TEST_NAME) + message(FATAL_ERROR "Require TEST_NAME to be defined") +endif(NOT TEST_NAME) + +# Sources +set(TEST_SRC "${TEST_DIR}/${TEST_NAME}.sy") + +if(EXISTS "${TEST_DIR}/${TEST_NAME}.in") + set(TEST_INS "${TEST_DIR}/${TEST_NAME}.in") +else(EXISTS "${TEST_DIR}/${TEST_NAME}.in") + set(TEST_INS "/dev/null") +endif(EXISTS "${TEST_DIR}/${TEST_NAME}.in") + +set(RUNTIME_LIB "${RUNTIME}/libsysy.a") + +# Generated +set(TEST_ASM "${TEST_NAME}.s") +set(TEST_EXE "${TEST_NAME}") +set(TEST_OUT "${TEST_NAME}_rv.out") +configure_file("${TEST_DIR}/${TEST_NAME}.out" "${TEST_NAME}.ref" NEWLINE_STYLE LF) +set(TEST_REF "${TEST_NAME}.ref") + +# SysY to RISC-V Assembly +execute_process( + COMMAND + ${COMPILER} -S ${TEST_SRC} -O1 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + OUTPUT_FILE ${TEST_ASM} + ERROR_VARIABLE TEST_ERR + RESULT_VARIABLE TEST_RET +) + +if(TEST_RET) + message(SEND_ERROR "Failed: SysY Compiler Error in ${TEST_SRC}: ${TEST_ERR}") + file(READ "${TEST_SRC}" TEST_SRC_CONTENT) + message(NOTICE "Source File:\n ${TEST_SRC_CONTENT}") + return() +endif(TEST_RET) + +# GCC Assemble and Link +execute_process( + COMMAND + riscv64-linux-gnu-gcc "${CMAKE_CURRENT_BINARY_DIR}/${TEST_ASM}" "${RUNTIME_LIB}" -march=rv64gc -static -o "${CMAKE_CURRENT_BINARY_DIR}/${TEST_EXE}" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ERROR_VARIABLE TEST_ERR + RESULT_VARIABLE TEST_RET +) + +if(TEST_RET) + message(SEND_ERROR "Failed: GCC Assemble and Link Error in ${TEST_SRC}: ${TEST_ERR}") + # file(READ "${TEST_ASM}" TEST_ASM_CONTENT) + message(NOTICE "Generated Assmebly:\n ${TEST_ASM_CONTENT}") + return() +endif(TEST_RET) + +# Run the executable with qemu +execute_process( + COMMAND + qemu-riscv64 ${TEST_EXE} -M sifive_u -smp 5 -m 2G + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + INPUT_FILE ${TEST_INS} + OUTPUT_VARIABLE TEST_OUT_CONTENT + ERROR_VARIABLE TEST_ERR + RESULT_VARIABLE TEST_RET + TIMEOUT 60 +) + +# Append EOF LR, if not presented +if(TEST_OUT_CONTENT) + string(LENGTH "${TEST_OUT_CONTENT}" TEST_OUT_LEN) + math(EXPR TEST_OUT_LAST "${TEST_OUT_LEN} - 1") + string(SUBSTRING "${TEST_OUT_CONTENT}" ${TEST_OUT_LAST} 1 LAST_CHAR) + + if(NOT "${LAST_CHAR}" STREQUAL "\n") + # If it's not, append a newline to var + set(TEST_OUT_CONTENT "${TEST_OUT_CONTENT}\n") + endif() +endif(TEST_OUT_CONTENT) + +set(TEST_OUT_CONTENT "${TEST_OUT_CONTENT}${TEST_RET}\n") +file(WRITE "${TEST_OUT}" "${TEST_OUT_CONTENT}") + +execute_process( + COMMAND "${CMAKE_COMMAND}" -E compare_files "${TEST_OUT}" "${TEST_REF}" + RESULT_VARIABLE TEST_RESULT +) + +if(TEST_RESULT) + # get_filename_component(TESTNAME "${TEST_ARGS}" NAME) + # file(RENAME "${TEST_OUTPUT}" "${CMAKE_BINARY_DIR}/${TESTNAME}.out") + # file(WRITE "${CMAKE_BINARY_DIR}/${TESTNAME}.err" ${TEST_ERROR}) + message(SEND_ERROR "Failed: The output of ${TEST_NAME} did not match ${TEST_REF}") + file(READ ${TEST_REF} TEST_REF_CONTENT) + message(NOTICE "Expected Output: ${TEST_REF_CONTENT}") + message(NOTICE "Auctual Output: ${TEST_OUT_CONTENT}") + return() +endif(TEST_RESULT) \ No newline at end of file