diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..623cd141 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.clay linguist-language=JavaScript diff --git a/CMakeLists.txt b/CMakeLists.txt index 8388526f..eb6cecba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") find_package(Git) @@ -35,17 +36,20 @@ if(UNIX) if (NOT ${LLVM_CONFIG_VERSION_RESULT} EQUAL 0) message(FATAL_ERROR "${LLVM_CONFIG} failed") endif() + if(LLVM_VERSION VERSION_LESS 18.0) + message(FATAL_ERROR "LLVM 18 or newer is required. Found ${LLVM_VERSION}") + endif() execute_process( COMMAND ${LLVM_CONFIG} --cxxflags OUTPUT_VARIABLE LLVM_CXXFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE ) - set(LLVM_CXXFLAGS "${LLVM_CXXFLAGS}") + set(LLVM_CXXFLAGS ${LLVM_CXXFLAGS}) separate_arguments(LLVM_CXXFLAGS) if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(LLVM_CXXFLAGS "${LLVM_CXXFLAGS} -O0") + list(APPEND LLVM_CXXFLAGS -O0) endif() execute_process( @@ -79,7 +83,7 @@ if(UNIX) OUTPUT_VARIABLE LLVM_INCLUDEDIR OUTPUT_STRIP_TRAILING_WHITESPACE ) - set(LLVM_INCLUDEDIR "${LLVM_INCLUDEDIR}") + set(LLVM_INCLUDEDIR ${LLVM_INCLUDEDIR}) message("-- Using LLVM: ${LLVM_DIR}") message("-- LLVM include dir: ${LLVM_INCLUDEDIR}") diff --git a/compiler/CMakeLists.txt b/compiler/CMakeLists.txt index 2868281a..2b750204 100644 --- a/compiler/CMakeLists.txt +++ b/compiler/CMakeLists.txt @@ -54,41 +54,56 @@ if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") COMPILE_DEFINITIONS "GIT_ID=\"${GIT_WC_ID}\"") endif() -# Compiler flags +# Targets +add_library(compiler STATIC ${COMPILER_SOURCES}) +add_executable(clay ${CLAY_SOURCES}) +add_executable(claydoc ${CLAYDOC_SOURCES}) +add_executable(ut ${UT_SOURCES}) + +# compiler flags +target_compile_options(compiler PRIVATE ${LLVM_CXXFLAGS}) +target_compile_options(clay PRIVATE ${LLVM_CXXFLAGS}) +target_compile_options(claydoc PRIVATE ${LLVM_CXXFLAGS}) +target_compile_options(ut PRIVATE ${LLVM_CXXFLAGS}) + +# include directories +target_include_directories(compiler PRIVATE ${LLVM_INCLUDEDIR}) +target_include_directories(clay PRIVATE ${LLVM_INCLUDEDIR}) +target_include_directories(claydoc PRIVATE ${LLVM_INCLUDEDIR}) +target_include_directories(ut PRIVATE ${LLVM_INCLUDEDIR}) + if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - set(CLAY_CXXFLAGS "${LLVM_CXXFLAGS} -UNDEBUG") + target_compile_definitions(compiler PRIVATE UNDEBUG) + target_compile_definitions(clay PRIVATE UNDEBUG) + target_compile_definitions(claydoc PRIVATE UNDEBUG) + target_compile_definitions(ut PRIVATE UNDEBUG) else() - set(CLAY_CXXFLAGS "${LLVM_CXXFLAGS} -DNDEBUG") + target_compile_definitions(compiler PRIVATE NDEBUG) + target_compile_definitions(clay PRIVATE NDEBUG) + target_compile_definitions(claydoc PRIVATE NDEBUG) + target_compile_definitions(ut PRIVATE NDEBUG) endif() -if (NOT MSVC) - set(CLAY_CXXFLAGS "${CLAY_CXXFLAGS} -fexceptions") + +if(NOT MSVC) + target_compile_options(compiler PRIVATE -fexceptions) + target_compile_options(clay PRIVATE -fexceptions) + target_compile_options(claydoc PRIVATE -fexceptions) + target_compile_options(ut PRIVATE -fexceptions) endif() set(ENABLE_PCH False CACHE BOOL - "Use precompiled headers when building the compiler. (experimental)") + "Use precompiled headers when building the compiler. (experimental)") if(ENABLE_PCH) - precompile_header(clay.hpp SOURCES pch.cpp "${CLAY_CXXFLAGS}") + precompile_header(clay.hpp SOURCES pch.cpp ${LLVM_CXXFLAGS}) endif(ENABLE_PCH) -# Targets -add_library(compiler STATIC ${COMPILER_SOURCES}) -add_executable(clay ${CLAY_SOURCES}) -add_executable(claydoc ${CLAYDOC_SOURCES}) -add_executable(ut ${UT_SOURCES}) - -# compiler flags -target_compile_options(compiler PRIVATE "${CLAY_CXXFLAGS}") -target_compile_options(clay PRIVATE "${CLAY_CXXFLAGS}") -target_compile_options(claydoc PRIVATE "${CLAY_CXXFLAGS}") -target_compile_options(ut PRIVATE "${CLAY_CXXFLAGS}") - if (UNIX) - target_link_options(compiler PRIVATE "${LLVM_LDFLAGS}") - target_link_options(clay PRIVATE "${LLVM_LDFLAGS}") - target_link_options(claydoc PRIVATE "${LLVM_LDFLAGS}") - target_link_options(ut PRIVATE "${LLVM_LDFLAGS}") -endif(UNIX) + target_link_options(compiler PRIVATE ${LLVM_LDFLAGS}) + target_link_options(clay PRIVATE ${LLVM_LDFLAGS}) + target_link_options(claydoc PRIVATE ${LLVM_LDFLAGS}) + target_link_options(ut PRIVATE ${LLVM_LDFLAGS}) +endif() # Libraries target_link_libraries(clay PRIVATE compiler ${LLVM_LIBS}) diff --git a/compiler/analyzer.cpp b/compiler/analyzer.cpp index a64b5d81..631f9bbf 100644 --- a/compiler/analyzer.cpp +++ b/compiler/analyzer.cpp @@ -1,4 +1,3 @@ - #include "clay.hpp" #include "evaluator.hpp" #include "codegen.hpp" @@ -55,8 +54,7 @@ namespace clay { params(params), varParam(varParam), expr(expr) { } - GlobalVariable::~GlobalVariable() { - } + GlobalVariable::~GlobalVariable() = default; static StatementAnalysis analyzeStatement(StatementPtr stmt, EnvPtr env, AnalysisContext *ctx); @@ -219,8 +217,7 @@ namespace clay { static vector analysisErrorCompileContext; struct ClearAnalysisError { - ClearAnalysisError() { - } + ClearAnalysisError() = default; ~ClearAnalysisError() { analysisErrorLocation = Location(); @@ -1442,7 +1439,7 @@ namespace clay { } return; case IITDescriptor::MMX: - if (!Ty->isX86_MMXTy()) { + if (!Ty->isX86_AMXTy()) { errors << "intrinsic argument " << (ai + 1) << " must match LLVM MMX type, but got "; Ty->print(errors); @@ -1479,11 +1476,11 @@ namespace clay { return; case IITDescriptor::Vector: { llvm::VectorType *VT = dyn_cast(Ty); - if (VT == 0) { + if (VT == nullptr) { errors << "intrinsic argument " << (ai + 1) << " must be of an LLVM vector type, but got "; Ty->print(errors); - } else if (VT->getNumElements() != D.Vector_Width) { + } else if (VT->getElementCount() != D.Vector_Width) { errors << "intrinsic argument " << (ai + 1) << " must be of an LLVM vector type with " << D.Vector_Width diff --git a/compiler/analyzer.hpp b/compiler/analyzer.hpp index f2ee6e91..ee73296b 100644 --- a/compiler/analyzer.hpp +++ b/compiler/analyzer.hpp @@ -2,7 +2,6 @@ #include "clay.hpp" -// #include "invoketables.hpp" #include "types.hpp" namespace clay { @@ -24,9 +23,9 @@ namespace clay { bool staticToCallingConv(ObjectPtr x, CallingConv &out); CallingConv staticToCallingConv(MultiStaticPtr x, unsigned index); - static inline PVData staticPValue(ObjectPtr x) { + static PVData staticPValue(const ObjectPtr& x) { const TypePtr t = staticType(x); - return PVData(t, true); + return {t, true}; } enum BoolKind { diff --git a/compiler/analyzer_op.cpp b/compiler/analyzer_op.cpp index 792e28b5..b1ace831 100644 --- a/compiler/analyzer_op.cpp +++ b/compiler/analyzer_op.cpp @@ -4,10 +4,9 @@ #include "constructors.hpp" #include "loader.hpp" #include "env.hpp" - #include "analyzer.hpp" - #include "analyzer_op.hpp" +#include "invoketables.hpp" namespace clay { static size_t staticToSizeTOrIntValue(MultiPValue *args, size_t index) { diff --git a/compiler/clay.cpp b/compiler/clay.cpp index 6a034da0..2b1b76db 100644 --- a/compiler/clay.cpp +++ b/compiler/clay.cpp @@ -1,3 +1,9 @@ +#include +#include +#include +#include +#include + #include "clay.hpp" #include "hirestimer.hpp" #include "error.hpp" @@ -6,6 +12,9 @@ #include "invoketables.hpp" #include "parachute.hpp" +using std::string; +using std::vector; + // for _exit #ifdef _WIN32 # include @@ -26,272 +35,139 @@ namespace clay { #define ENV_SEPARATOR ':' #endif - using namespace std; - - static void addOptimizationPasses(llvm::legacy::PassManager &passes, - llvm::legacy::FunctionPassManager &fpasses, - unsigned optLevel, - bool internalize) { - llvm::Pass *inliningPass = 0; - if (optLevel > 1) { - int threshold = 225; - if (optLevel > 2) - threshold = 275; - inliningPass = llvm::createFunctionInliningPass(threshold); - } else { - inliningPass = llvm::createAlwaysInlinerPass(); + static bool runModule(llvm::Module *module, + const std::vector &argv, + char const *const*envp, + llvm::ArrayRef libSearchPaths, + llvm::ArrayRef libs) { + auto JIT_expected = llvm::orc::LLJITBuilder().create(); + if (!JIT_expected) { + llvm::errs() << "error creating JIT: " << llvm::toString(JIT_expected.takeError()) << "\n"; + return false; } + auto JIT = std::move(JIT_expected.get()); + llvm::orc::LLJIT &jit = *JIT; - llvm::PassManagerBuilder builder; - builder.OptLevel = optLevel; - builder.Inliner = inliningPass; - - builder.populateFunctionPassManager(fpasses); + llvm::orc::JITDylib& mainDylib = jit.getMainJITDylib(); - // If all optimizations are disabled, just run the always-inline pass. - if (optLevel == 0) { - if (builder.Inliner) { - passes.add(builder.Inliner); - builder.Inliner = 0; - } - } else { - passes.add(llvm::createTypeBasedAliasAnalysisPass()); - passes.add(llvm::createBasicAliasAnalysisPass()); + auto Generator_expected = llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess( + jit.getDataLayout().getGlobalPrefix() + ); - passes.add(llvm::createGlobalOptimizerPass()); // Optimize out global vars + if (!Generator_expected) { + llvm::errs() << "error creating generator: " << llvm::toString(Generator_expected.takeError()) << "\n"; + return false; + } - passes.add(llvm::createIPSCCPPass()); // IP SCCP - passes.add(llvm::createDeadArgEliminationPass()); // Dead argument elimination + std::unique_ptr Generator = + std::move(*Generator_expected); - passes.add(llvm::createInstructionCombiningPass()); // Clean up after IPCP & DAE - passes.add(llvm::createCFGSimplificationPass()); // Clean up after IPCP & DAE + mainDylib.addGenerator(std::move(Generator)); - // Start of CallGraph SCC passes. - if (builder.Inliner) { - passes.add(builder.Inliner); - builder.Inliner = 0; - } - if (optLevel > 2) - passes.add(llvm::createArgumentPromotionPass()); // Scalarize uninlined fn args - - // Start of function pass. - // Break up aggregate allocas, using SSAUpdater. - passes.add(llvm::createScalarReplAggregatesPass(-1, false)); - passes.add(llvm::createEarlyCSEPass()); // Catch trivial redundancies - - passes.add(llvm::createJumpThreadingPass()); // Thread jumps. - // Disable Value Propagation pass until fixed LLVM bug #12503 - // passes.add(llvm::createCorrelatedValuePropagationPass()); // Propagate conditionals - passes.add(llvm::createCFGSimplificationPass()); // Merge & remove BBs - passes.add(llvm::createInstructionCombiningPass()); // Combine silly seq's - - passes.add(llvm::createTailCallEliminationPass()); // Eliminate tail calls - passes.add(llvm::createCFGSimplificationPass()); // Merge & remove BBs - passes.add(llvm::createReassociatePass()); // Reassociate expressions - passes.add(llvm::createLoopRotatePass()); // Rotate Loop - passes.add(llvm::createLICMPass()); // Hoist loop invariants - passes.add(llvm::createLoopUnswitchPass(builder.SizeLevel || optLevel < 3)); - passes.add(llvm::createInstructionCombiningPass()); - passes.add(llvm::createIndVarSimplifyPass()); // Canonicalize indvars - passes.add(llvm::createLoopIdiomPass()); // Recognize idioms like memset. - passes.add(llvm::createLoopDeletionPass()); // Delete dead loops - - if (optLevel > 1) - passes.add(llvm::createGVNPass()); // Remove redundancies - passes.add(llvm::createMemCpyOptPass()); // Remove memcpy / form memset - passes.add(llvm::createSCCPPass()); // Constant prop with SCCP - - // Run instcombine after redundancy elimination to exploit opportunities - // opened up by them. - passes.add(llvm::createInstructionCombiningPass()); - passes.add(llvm::createJumpThreadingPass()); // Thread jumps - // Disable Value Propagation pass until fixed LLVM bug #12503 - // passes.add(llvm::createCorrelatedValuePropagationPass()); - passes.add(llvm::createDeadStoreEliminationPass()); // Delete dead stores - - if (builder.Vectorize) { - passes.add(llvm::createBBVectorizePass()); - passes.add(llvm::createInstructionCombiningPass()); - if (optLevel > 1) - passes.add(llvm::createGVNPass()); // Remove redundancies - } + module->setDataLayout(jit.getDataLayout()); - passes.add(llvm::createAggressiveDCEPass()); // Delete dead instructions - passes.add(llvm::createCFGSimplificationPass()); // Merge & remove BBs - passes.add(llvm::createInstructionCombiningPass()); // Clean up after everything. + auto TSM = llvm::orc::ThreadSafeModule(std::unique_ptr(module), + std::make_unique()); - // GlobalOpt already deletes dead functions and globals, at -O3 try a - // late pass of GlobalDCE. It is capable of deleting dead cycles. - if (optLevel > 2) - passes.add(llvm::createGlobalDCEPass()); // Remove dead fns and globals. - - if (optLevel > 1) - passes.add(llvm::createConstantMergePass()); // Merge dup global constants + if (llvm::Error AddIRErr = jit.addIRModule(std::move(TSM))) { + llvm::errs() << "error adding module to JIT: " << llvm::toString(std::move(AddIRErr)) << "\n"; + return false; } - if (optLevel > 2) { - if (internalize) { - vector do_not_internalize; - do_not_internalize.push_back("main"); - passes.add(llvm::createInternalizePass(do_not_internalize)); - } - builder.populateLTOPassManager(passes, false, true); + auto mainAddr_expected = jit.lookup("main"); + if (!mainAddr_expected) { + llvm::errs() << "error resolving main: " << llvm::toString(mainAddr_expected.takeError()) << "\n"; + return false; } - } - static bool linkLibraries(llvm::Module *module, llvm::ArrayRef libSearchPaths, - llvm::ArrayRef libs) { - if (libs.empty()) - return true; - llvm::Linker linker("clay", llvmModule, llvm::Linker::Verbose); - linker.addSystemPaths(); - linker.addPaths(libSearchPaths); - for (size_t i = 0; i < libs.size(); ++i) { - string lib = libs[i]; - llvmModule->addLibrary(lib); - //as in cling/lib/Interpreter/Interpreter.cpp - bool isNative = true; - if (linker.LinkInLibrary(lib, isNative)) { - // that didn't work, try bitcode: - llvm::sys::Path FilePath(lib); - std::string Magic; - if (!FilePath.getMagicNumber(Magic, 64)) { - // filename doesn't exist... - linker.releaseModule(); - return false; - } - if (llvm::sys::IdentifyFileType(Magic.c_str(), 64) - == llvm::sys::Bitcode_FileType) { - // We are promised a bitcode file, complain if it fails - linker.setFlags(0); - if (linker.LinkInFile(llvm::sys::Path(lib), isNative)) { - linker.releaseModule(); - return false; - } - } else { - // Nothing the linker can handle - linker.releaseModule(); - return false; - } - } else if (isNative) { - // native shared library, load it! - llvm::sys::Path SoFile = linker.FindLib(lib); - if (SoFile.isEmpty()) { - llvm::errs() << "Couldn't find shared library " << lib << "\n"; - linker.releaseModule(); - return false; - } - std::string errMsg; - bool hasError = llvm::sys::DynamicLibrary - ::LoadLibraryPermanently(SoFile.str().c_str(), &errMsg); - if (hasError) { - if (hasError) { - llvm::errs() << "Couldn't load shared library " << lib << "\n" << errMsg.c_str(); - linker.releaseModule(); - return false; - } - } - } - } - linker.releaseModule(); - return true; - } + using MainPtr = int (*)(int, char *[], char *[]); - static bool runModule(llvm::Module *module, - vector &argv, - char const *const*envp, - llvm::ArrayRef libSearchPaths, - llvm::ArrayRef libs) { - if (!linkLibraries(module, libSearchPaths, libs)) { - return false; - } - llvm::EngineBuilder eb(llvmModule); - llvm::ExecutionEngine *engine = eb.create(); - llvm::Function *mainFunc = module->getFunction("main"); - if (!mainFunc) { - llvm::errs() << "no main function to -run\n"; - delete engine; - return false; + llvm::orc::ExecutorAddr mainAddr = mainAddr_expected.get(); + auto mainFunc = reinterpret_cast(mainAddr.getValue()); + + std::vector c_argv; + for (const auto& arg : argv) { + c_argv.push_back(arg.c_str()); } - engine->runStaticConstructorsDestructors(false); - engine->runFunctionAsMain(mainFunc, argv, envp); - engine->runStaticConstructorsDestructors(true); + c_argv.push_back(nullptr); + + mainFunc(static_cast(c_argv.size() - 1), const_cast(c_argv.data()), const_cast(envp)); - delete engine; return true; } static void optimizeLLVM(llvm::Module *module, unsigned optLevel, bool internalize) { - llvm::PassManager passes; - - string moduleDataLayout = module->getDataLayout(); - llvm::DataLayout *dl = new llvm::DataLayout(moduleDataLayout); - passes.add(dl); - - llvm::FunctionPassManager fpasses(module); - - fpasses.add(new llvm::DataLayout(*dl)); - - addOptimizationPasses(passes, fpasses, optLevel, internalize); - - fpasses.doInitialization(); - for (llvm::Module::iterator i = module->begin(), e = module->end(); - i != e; ++i) { - fpasses.run(*i); + llvm::LoopAnalysisManager LAM; + llvm::FunctionAnalysisManager FAM; + llvm::CGSCCAnalysisManager CGAM; + llvm::ModuleAnalysisManager MAM; + llvm::PassBuilder PB; + + PB.registerModuleAnalyses(MAM); + PB.registerCGSCCAnalyses(CGAM); + PB.registerFunctionAnalyses(FAM); + PB.registerLoopAnalyses(LAM); + PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); + + llvm::OptimizationLevel O = llvm::OptimizationLevel::O0; + if (optLevel == 1) O = llvm::OptimizationLevel::O1; + else if (optLevel == 2) O = llvm::OptimizationLevel::O2; + else if (optLevel >= 3) O = llvm::OptimizationLevel::O3; + + llvm::ModulePassManager MPM = PB.buildPerModuleDefaultPipeline(O); + + if (optLevel > 2 && internalize) { + MPM.addPass(llvm::InternalizePass([=](const llvm::GlobalValue &GV) { + return GV.getName() == "main"; + })); } - passes.add(llvm::createVerifierPass()); - passes.run(*module); + MPM.addPass(llvm::VerifierPass()); + + MPM.run(*module, MAM); } static void generateLLVM(llvm::Module *module, bool emitAsm, llvm::raw_ostream *out) { - llvm::PassManager passes; + llvm::ModuleAnalysisManager MAM; + llvm::ModulePassManager passes; + if (emitAsm) - passes.add(llvm::createPrintModulePass(out)); + passes.addPass(llvm::PrintModulePass(*out)); else - passes.add(llvm::createBitcodeWriterPass(*out)); - passes.run(*module); + passes.addPass(llvm::BitcodeWriterPass(*out)); + + passes.run(*module, MAM); } static void generateAssembly(llvm::Module *module, llvm::TargetMachine *targetMachine, - llvm::raw_ostream *out, + llvm::raw_pwrite_stream *out, bool emitObject) { - llvm::FunctionPassManager fpasses(module); + llvm::legacy::PassManager passes; - fpasses.add(new llvm::DataLayout(module)); - fpasses.add(llvm::createVerifierPass()); - - targetMachine->setAsmVerbosityDefault(true); - - llvm::formatted_raw_ostream fout(*out); - llvm::TargetMachine::CodeGenFileType fileType = emitObject - ? llvm::TargetMachine::CGFT_ObjectFile - : llvm::TargetMachine::CGFT_AssemblyFile; + passes.add(llvm::createVerifierPass()); - bool result = targetMachine->addPassesToEmitFile(fpasses, fout, fileType); - assert(!result); + llvm::CodeGenFileType fileType = emitObject + ? llvm::CodeGenFileType::ObjectFile + : llvm::CodeGenFileType::AssemblyFile; - fpasses.doInitialization(); - for (llvm::Module::iterator i = module->begin(), e = module->end(); - i != e; ++i) { - fpasses.run(*i); + if (targetMachine->addPassesToEmitFile(passes, *out, nullptr, fileType)) { + llvm::errs() << "error: adding codegen passes failed\n"; + return; } - fpasses.doFinalization(); + + passes.run(*module); } - static string joinCmdArgs(llvm::ArrayRef args) { - string s; + [[maybe_unused]] static std::string joinCmdArgs(llvm::ArrayRef args) + { + std::string s; llvm::raw_string_ostream ss(s); - for (char const *const *arg = args.begin(); - arg != args.end(); ++arg) { - if (arg != args.begin()) { + for (const llvm::StringRef &arg : args) { + if (&arg != args.begin()) { ss << " "; } - if (*arg == 0 && arg + 1 == args.end()) { - continue; - } - ss << *arg; + ss << arg; } return s; } @@ -299,7 +175,7 @@ namespace clay { static bool generateBinary(llvm::Module *module, llvm::TargetMachine *targetMachine, llvm::Twine const &outputFilePath, - llvm::sys::Path const &clangPath, + llvm::StringRef const &clangPath, bool /*exceptions*/, bool sharedLib, bool debug, @@ -307,11 +183,11 @@ namespace clay { bool verbose) { int fd; PathString tempObj; - if (llvm::error_code ec = llvm::sys::fs::unique_file("clayobj-%%%%%%%%.obj", fd, tempObj)) { + if (std::error_code ec = llvm::sys::fs::createUniqueFile("clayobj-%%%%%%%%.obj", fd, tempObj)) { llvm::errs() << "error creating temporary object file: " << ec.message() << '\n'; return false; } - llvm::sys::RemoveFileOnSignal(llvm::sys::Path(tempObj)); + llvm::FileRemover removeTempObj(tempObj); { llvm::raw_fd_ostream objOut(fd, /*shouldClose=*/ true); @@ -321,74 +197,75 @@ namespace clay { string outputFilePathStr = outputFilePath.str(); - vector clangArgs; - clangArgs.push_back(clangPath.c_str()); + std::vector clangArgs; + clangArgs.emplace_back(clangPath.data()); switch (llvmDataLayout->getPointerSizeInBits()) { case 32: - clangArgs.push_back("-m32"); + clangArgs.emplace_back("-m32"); break; case 64: - clangArgs.push_back("-m64"); + clangArgs.emplace_back("-m64"); break; default: assert(false); } llvm::Triple triple(llvmModule->getTargetTriple()); - string linkerFlags; if (sharedLib) { - clangArgs.push_back("-shared"); + clangArgs.emplace_back("-shared"); - if (triple.getOS() == llvm::Triple::MinGW32 - || triple.getOS() == llvm::Triple::Cygwin) { + if (triple.isOSWindows()) { + string linkerFlags; PathString defPath; outputFilePath.toVector(defPath); llvm::sys::path::replace_extension(defPath, "def"); linkerFlags = "-Wl,--output-def," + string(defPath.begin(), defPath.end()); - clangArgs.push_back(linkerFlags.c_str()); + clangArgs.emplace_back(linkerFlags); } } if (debug) { if (triple.getOS() == llvm::Triple::Win32) - clangArgs.push_back("-Wl,/debug"); + clangArgs.emplace_back("-Wl,/debug"); } - clangArgs.push_back("-o"); - clangArgs.push_back(outputFilePathStr.c_str()); - clangArgs.push_back(tempObj.c_str()); - for (unsigned i = 0; i < arguments.size(); ++i) - clangArgs.push_back(arguments[i].c_str()); - clangArgs.push_back(nullptr); + clangArgs.emplace_back("-o"); + clangArgs.emplace_back(outputFilePathStr); + clangArgs.push_back(tempObj); + for (const auto & argument : arguments) + clangArgs.emplace_back(argument); if (verbose) { llvm::errs() << "executing clang to generate binary:\n"; llvm::errs() << " " << joinCmdArgs(clangArgs) << "\n"; } - int result = llvm::sys::Program::ExecuteAndWait(clangPath, &clangArgs[0]); + int result = llvm::sys::ExecuteAndWait(clangPath, clangArgs); + + if (debug && triple.isOSDarwin()) { + llvm::ErrorOr dsymutilPathOrErr = llvm::sys::findProgramByName("dsymutil"); + if (std::error_code ec = dsymutilPathOrErr.getError()) + llvm::errs() << "error creating dsymutil: " << ec.message() << '\n'; - if (debug && triple.getOS() == llvm::Triple::Darwin) { - llvm::sys::Path dsymutilPath = llvm::sys::Program::FindProgramByName("dsymutil"); - if (dsymutilPath.isValid()) { + std::string dsymutilPath = dsymutilPathOrErr ? *dsymutilPathOrErr : ""; + + if (!dsymutilPath.empty()) { string outputDSYMPath = outputFilePathStr; outputDSYMPath.append(".dSYM"); - vector dsymutilArgs; - dsymutilArgs.push_back(dsymutilPath.c_str()); - dsymutilArgs.push_back("-o"); - dsymutilArgs.push_back(outputDSYMPath.c_str()); - dsymutilArgs.push_back(outputFilePathStr.c_str()); - dsymutilArgs.push_back(nullptr); + std::vector dsymutilArgs; + dsymutilArgs.emplace_back(dsymutilPath); + dsymutilArgs.emplace_back("-o"); + dsymutilArgs.emplace_back(outputDSYMPath); + dsymutilArgs.emplace_back(outputFilePathStr); if (verbose) { llvm::errs() << "executing dsymutil:"; llvm::errs() << " " << joinCmdArgs(dsymutilArgs) << "\n"; } - int dsymResult = llvm::sys::Program::ExecuteAndWait(dsymutilPath, - &dsymutilArgs[0]); + int dsymResult = llvm::sys::ExecuteAndWait(dsymutilPath, dsymutilArgs); if (dsymResult != 0) llvm::errs() << "warning: dsymutil exited with error code " << dsymResult << "\n"; @@ -397,13 +274,10 @@ namespace clay { "warning: unable to find dsymutil on the path; debug info for executable will not be generated\n"; } - bool dontcare; - llvm::sys::fs::remove(llvm::StringRef(tempObj), dontcare); - return (result == 0); } - static void usage(char *argv0) { + static void usage(const char *argv0) { llvm::errs() << "usage: " << argv0 << " \n"; llvm::errs() << " " << argv0 << " -e \n"; llvm::errs() << "options:\n"; @@ -466,33 +340,27 @@ namespace clay { } static string sharedExtensionForTarget(llvm::Triple const &triple) { - if (triple.getOS() == llvm::Triple::Win32 - || triple.getOS() == llvm::Triple::MinGW32 - || triple.getOS() == llvm::Triple::Cygwin) { + if (triple.isOSWindows()) { return ".dll"; - } else if (triple.getOS() == llvm::Triple::Darwin) { + } + if (triple.isOSDarwin()) { return ".dylib"; - } else { - return ".so"; } + return ".so"; } static string objExtensionForTarget(llvm::Triple const &triple) { - if (triple.getOS() == llvm::Triple::Win32) { + if (triple.isOSWindows()) { return ".obj"; - } else { - return ".o"; } + return ".o"; } static string exeExtensionForTarget(llvm::Triple const &triple) { - if (triple.getOS() == llvm::Triple::Win32 - || triple.getOS() == llvm::Triple::MinGW32 - || triple.getOS() == llvm::Triple::Cygwin) { + if (triple.isOSWindows()) { return ".exe"; - } else { - return ""; } + return ""; } static void printVersion() { @@ -625,7 +493,7 @@ namespace clay { if (dot == nullptr) { logMatchSymbols.insert(make_pair(string("*"), argv[i])); } else { - logMatchSymbols.insert(make_pair(string((char const *) argv[i], dot), string(dot + 1))); + logMatchSymbols.insert(make_pair(string(static_cast(argv[i]), dot), string(dot + 1))); } } else if (strcmp(argv[i], "-e") == 0) { if (i + 1 == argc) { @@ -684,7 +552,7 @@ namespace clay { llvm::errs() << "error: framework name missing after -framework\n"; return 1; } - frameworks.push_back("-framework"); + frameworks.emplace_back("-framework"); frameworks.push_back(framework); } else if (strcmp(argv[i], "-arch") == 0) { if (i + 1 == argc) { @@ -827,7 +695,7 @@ namespace clay { return 1; } } - searchPath.push_back(PathString(path)); + searchPath.emplace_back(path); } else if (strstr(argv[i], "-version") == argv[i] || strcmp(argv[i], "--version") == 0) { printVersion(); @@ -959,24 +827,23 @@ namespace clay { initExternalTarget(targetTriple); // Try environment variables first - char *libclayPath = getenv("CLAY_PATH"); - if (libclayPath) { + if (char *libclayPath = getenv("CLAY_PATH")) { // Parse the environment variable - // Format expected is standard PATH form, i.e - // CLAY_PATH=path1:path2:path3 (on unix) - // CLAY_PATH=path1;path2;path3 (on windows) + // Format expected is standard PATH form, i.e. + // CLAY_PATH=path1:path2:path3 (on Unix) + // CLAY_PATH=path1;path2;path3 (on Windows) char *begin = libclayPath; char *end; do { end = begin; while (*end && (*end != ENV_SEPARATOR)) ++end; - searchPath.push_back(llvm::StringRef(begin, (size_t) (end - begin))); + searchPath.emplace_back(llvm::StringRef(begin, static_cast(end - begin))); begin = end + 1; } while (*end); } // Add the relative path from the executable - PathString clayExe(llvm::sys::Path::GetMainExecutable(argv[0], (void *) (uintptr_t) &usage).c_str()); + PathString clayExe(llvm::sys::fs::getMainExecutable(argv[0], reinterpret_cast(&usage))); llvm::StringRef clayDir = llvm::sys::path::parent_path(clayExe); PathString libDirDevelopment(clayDir); @@ -990,14 +857,13 @@ namespace clay { searchPath.push_back(libDirDevelopment); searchPath.push_back(libDirProduction1); searchPath.push_back(libDirProduction2); - searchPath.push_back(PathString(".")); + searchPath.emplace_back("."); if (verbose) { llvm::errs() << "using search path:\n"; - for (std::vector::const_iterator it = searchPath.begin(); - it != searchPath.end(); ++it) { - llvm::errs() << " " << *it << "\n"; + for (const auto & it : searchPath) { + llvm::errs() << " " << it << "\n"; } } @@ -1024,7 +890,7 @@ namespace clay { llvm::errs() << "error: output file '" << outputFile << "' is a directory\n"; return 1; } - llvm::sys::RemoveFileOnSignal(llvm::sys::Path(outputFile)); + llvm::sys::RemoveFileOnSignal(outputFile); } if (generateDeps) { @@ -1044,7 +910,7 @@ namespace clay { llvm::errs() << "error: dependencies output file '" << dependenciesOutputFile << "' is a directory\n"; return 1; } - llvm::sys::RemoveFileOnSignal(llvm::sys::Path(dependenciesOutputFile)); + llvm::sys::RemoveFileOnSignal(dependenciesOutputFile); } HiResTimer loadTimer, compileTimer, optTimer, outputTimer; @@ -1056,9 +922,9 @@ namespace clay { initLoader(); ModulePtr m; - string clayScriptSource; vector sourceFiles; if (!clayScript.empty()) { + string clayScriptSource; clayScriptSource = clayScriptImports + "main() {\n" + clayScript + "}"; m = loadProgramSource("-e", clayScriptSource, verbose, repl); } else if (generateDeps) @@ -1072,17 +938,17 @@ namespace clay { compileTimer.stop(); if (generateDeps) { - string errorInfo; + std::error_code ec; if (verbose) { llvm::errs() << "generating dependencies into " << dependenciesOutputFile << "\n"; } - llvm::raw_fd_ostream dependenciesOut(dependenciesOutputFile.c_str(), - errorInfo, - llvm::raw_fd_ostream::F_Binary); - if (!errorInfo.empty()) { - llvm::errs() << "error: " << errorInfo << '\n'; + llvm::raw_fd_ostream dependenciesOut(dependenciesOutputFile, + ec, + llvm::sys::fs::OF_None); + if (ec) { + llvm::errs() << "error creating dependencies file: " << ec.message() << '\n'; return 1; } dependenciesOut << outputFile << ": \\\n"; @@ -1106,19 +972,20 @@ namespace clay { optTimer.stop(); if (run) { - vector argv; - argv.push_back(clayFile); - runModule(llvmModule, argv, envp, libSearchPath, libraries); + vector runArgs; + runArgs.push_back(clayFile); + runModule(llvmModule, runArgs, envp, libSearchPath, libraries); } else if (repl) { - linkLibraries(llvmModule, libSearchPath, libraries); + // TODO: future me task runInteractive(llvmModule, m); } else if (emitLLVM || emitAsm || emitObject) { - string errorInfo; - llvm::raw_fd_ostream out(outputFile.c_str(), - errorInfo, - llvm::raw_fd_ostream::F_Binary); - if (!errorInfo.empty()) { - llvm::errs() << "error: " << errorInfo << '\n'; + std::error_code ec; + + llvm::raw_fd_ostream out(outputFile, + ec, + llvm::sys::fs::OF_None); + if (ec) { + llvm::errs() << "error creating output file: " << ec.message() << '\n'; return 1; } outputTimer.start(); @@ -1129,16 +996,17 @@ namespace clay { outputTimer.stop(); } else { bool result; - llvm::sys::Path clangPath = llvm::sys::Program::FindProgramByName("clang"); - if (!clangPath.isValid()) { - llvm::errs() << "error: unable to find clang on the path\n"; + llvm::ErrorOr clangPathOrErr = llvm::sys::findProgramByName("clang"); + if (std::error_code ec = clangPathOrErr.getError()) { + llvm::errs() << "error: unable to find clang on the path: " << ec.message() << "\n"; return 1; } + const std::string& clangPath = clangPathOrErr.get(); vector arguments; #ifdef __APPLE__ if (!arch.empty()) { - arguments.push_back("-arch"); + arguments.emplace_back("-arch"); arguments.push_back(arch); } #endif @@ -1170,10 +1038,10 @@ namespace clay { return 1; } if (showTiming) { - llvm::errs() << "load time = " << (size_t) loadTimer.elapsedMillis() << " ms\n"; - llvm::errs() << "compile time = " << (size_t) compileTimer.elapsedMillis() << " ms\n"; - llvm::errs() << "optimization time = " << (size_t) optTimer.elapsedMillis() << " ms\n"; - llvm::errs() << "codegen time = " << (size_t) outputTimer.elapsedMillis() << " ms\n"; + llvm::errs() << "load time = " << static_cast(loadTimer.elapsedMillis()) << " ms\n"; + llvm::errs() << "compile time = " << static_cast(compileTimer.elapsedMillis()) << " ms\n"; + llvm::errs() << "optimization time = " << static_cast(optTimer.elapsedMillis()) << " ms\n"; + llvm::errs() << "codegen time = " << static_cast(outputTimer.elapsedMillis()) << " ms\n"; llvm::errs().flush(); } diff --git a/compiler/clay.hpp b/compiler/clay.hpp index cd467c93..bde527a9 100644 --- a/compiler/clay.hpp +++ b/compiler/clay.hpp @@ -17,44 +17,56 @@ #pragma warning(disable: 4146 4244 4267 4355 4146 4800 4996) #endif -#include #include #include #include #include #include -#include #include -#include -#include #include -#include #include #include #include #include -#include #include -#include -#include -#include #include -#include -#include #include +#include +#include +#include +#include #include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include @@ -570,14 +582,16 @@ namespace clay { Source(llvm::StringRef lineOfCode, int dummy); Source(llvm::StringRef fileName, llvm::MemoryBuffer *buffer) - : Object(SOURCE), fileName(fileName), buffer(buffer), debugInfo(nullptr) { + : Object(SOURCE), fileName(fileName), buffer(buffer) { } - const char *data() const { return buffer->getBufferStart(); } - const char *endData() const { return buffer->getBufferEnd(); } - size_t size() const { return buffer->getBufferSize(); } + [[nodiscard]] const char *data() const { return buffer->getBufferStart(); } + [[nodiscard]] const char *endData() const { return buffer->getBufferEnd(); } + [[nodiscard]] size_t size() const { return buffer->getBufferSize(); } - llvm::DIFile getDebugInfo() const { return llvm::DIFile(debugInfo); } + [[nodiscard]] llvm::DIFile *getDebugInfo() const { + // TODO: implement this... + } }; struct Location { @@ -691,7 +705,7 @@ namespace clay { unsigned &column, unsigned &tabColumn); - llvm::DIFile getDebugLineCol(Location const &location, unsigned &line, unsigned &column); + llvm::DIFile *getDebugLineCol(Location const &location, unsigned &line, unsigned &column); void printFileLineCol(llvm::raw_ostream &out, Location const &location); @@ -2711,7 +2725,7 @@ namespace clay { bool fieldsInitialized: 1; bool hasVarField: 1; - RecordType(const RecordDeclPtr &record, llvm::ArrayRef params); + RecordType(RecordDeclPtr record, llvm::ArrayRef params); size_t varFieldSize() const { return fieldTypes.size() - fieldNames.size() + 1; diff --git a/compiler/claydoc.cpp b/compiler/claydoc.cpp index b9603319..f691e46c 100644 --- a/compiler/claydoc.cpp +++ b/compiler/claydoc.cpp @@ -1,37 +1,40 @@ -#include "claydoc.hpp" -#include "parser.hpp" +#include +#include + #include #include +#include "claydoc.hpp" +#include "parser.hpp" + using namespace std; using namespace clay; -static void usage(char *argv0) { +static void usage(const char *argv0) { llvm::errs() << "usage: " << argv0 << " \n"; } -DocModule *docParseModule(string fileName, DocState *state, std::string fqn) { +DocModule *docParseModule(const string &fileName, DocState *state, const std::string& fqn) { SourcePtr src = new Source(fileName); ModulePtr m = parse(fileName, src, ParserKeepDocumentation); - DocModule *docMod = new DocModule; + auto *docMod = new DocModule; docMod->fileName = fileName; docMod->fqn = fqn; - DocSection *section = new DocSection; + auto *section = new DocSection; docMod->sections.push_back(section); DocumentationPtr lastAttachment; - for (vector::iterator i = m->topLevelItems.begin(); i != m->topLevelItems.end(); i++) { - TopLevelItemPtr item = *i; + for (const auto& item : m->topLevelItems) { if (!item) continue; std::string name = identifierString(item->name); switch (item->objKind) { case DOCUMENTATION: { - DocumentationPtr doc = ((Documentation *) item.ptr()); + DocumentationPtr doc = dynamic_cast(item.ptr()); if (doc->annotation.count(ModuleAnnotation)) { docMod->name = doc->annotation.find(ModuleAnnotation)->second; docMod->description = doc->text; @@ -46,16 +49,16 @@ DocModule *docParseModule(string fileName, DocState *state, std::string fqn) { break; } case OVERLOAD: - if (!!((clay::Overload *) item.ptr())->target) - name = ((clay::Overload *) item.ptr())->target->asString(); + if (!!dynamic_cast(item.ptr())->target) + name = dynamic_cast(item.ptr())->target->asString(); case RECORD_DECL: case PROCEDURE: { - DocObject *obj = new DocObject; + auto *obj = new DocObject; obj->item = item; obj->name = name; if (!!lastAttachment) { obj->description = lastAttachment->text; - lastAttachment = 0; + lastAttachment = nullptr; } section->objects.push_back(obj); @@ -109,28 +112,37 @@ int main(int argc, char **argv) { return 1; } - bool whatever; - if (llvm::sys::fs::create_directories(outputDir, whatever) != 0) { + bool whatever = false; + std::error_code ec; + + ec = llvm::sys::fs::create_directories(outputDir, whatever); + if (ec) { llvm::errs() << "cannot create output directory " << outputDir << "\n"; return 4; } - DocState *state = new DocState; + std::error_code ec2; + auto *state = new DocState; state->name = llvm::sys::path::filename(inputDir).str(); - llvm::error_code ec; - for (llvm::sys::fs::recursive_directory_iterator it(inputDir, ec), ite; it != ite; it.increment(ec)) { + for (llvm::sys::fs::recursive_directory_iterator it(inputDir, ec2), ite; it != ite; it.increment(ec)) { llvm::sys::fs::file_status status; - if (!it->status(status) && is_regular_file(status) && endsWith(it->path(), ".clay")) { + if (!it->status() && is_regular_file(status) && endsWith(it->path(), ".clay")) { std::string fqn; llvm::sys::path::const_iterator word = llvm::sys::path::begin(it->path()); - ++word; + llvm::sys::path::const_iterator path_end = llvm::sys::path::end(it->path()); + + if (word != path_end) + ++word; + + for (; word != path_end; ++word) { + llvm::sys::path::const_iterator next_word = word; + ++next_word; - llvm::sys::path::const_iterator worde = llvm::sys::path::end(it->path()); - --worde; + if (next_word == path_end) + break; - for (; word != worde; ++word) { fqn.append(*word); fqn.append("."); } @@ -148,7 +160,7 @@ int main(int argc, char **argv) { emitHtmlIndex(outputDir, state); } -std::string identifierString(clay::IdentifierPtr id) { +std::string identifierString(const IdentifierPtr& id) { if (!id) return {""}; return {id->str.str().begin(), id->str.str().end()}; diff --git a/compiler/claydoc.hpp b/compiler/claydoc.hpp index e0b82d36..48ba7d8a 100644 --- a/compiler/claydoc.hpp +++ b/compiler/claydoc.hpp @@ -32,7 +32,7 @@ struct DocState { std::map modules; }; -std::string identifierString(clay::IdentifierPtr id); +std::string identifierString(const clay::IdentifierPtr& id); void emitHtmlModule(std::string outpath, DocModule *mod, std::string fqn); void emitHtmlIndex(std::string outpath, DocState *); diff --git a/compiler/codegen.cpp b/compiler/codegen.cpp index 9f22d4a1..1cb89164 100644 --- a/compiler/codegen.cpp +++ b/compiler/codegen.cpp @@ -42,7 +42,7 @@ namespace clay { } llvm::Value *noExceptionReturnValue() { - return llvm::ConstantPointernullptr::get(exceptionReturnType()); + return llvm::ConstantPointerNull::get(exceptionReturnType()); } void codegenValueInit(CValuePtr dest, CodegenContext *ctx); @@ -1360,7 +1360,7 @@ namespace clay { assert(mpv->size() == 1); PVData const &y = mpv->values[0]; llvm::Constant *initializer = - llvm::Constant::getnullptrValue(llvmType(y.type)); + llvm::Constant::getNullValue(llvmType(y.type)); llvm::SmallString<128> nameBuf; llvm::raw_svector_ostream nameStr(nameBuf); @@ -1603,7 +1603,7 @@ namespace clay { Location argLocation = arg->location; llvm::DIFile file = getDebugLineCol(argLocation, line, column); llvm::DIVariable debugVar = llvmDIBuilder->createLocalVariable( - llvm::dwarf::DW_TAG_arg_variable, // tag + llvm::dwarf::DW_TAG_variable, // tag x->getDebugInfo(), // scope arg->name->str, // name file, // file @@ -2893,7 +2893,7 @@ namespace clay { llvm::DIFile file = getDebugLineCol(argLocation, line, column); llvm::DebugLoc debugLoc = llvm::DebugLoc::get(line, column, entry->getDebugInfo()); llvm::DIVariable debugVar = llvmDIBuilder->createLocalVariable( - llvm::dwarf::DW_TAG_arg_variable, // tag + llvm::dwarf::DW_TAG_variable, // tag entry->getDebugInfo(), // scope entry->fixedArgNames[i]->str, // name file, // file @@ -2935,7 +2935,7 @@ namespace clay { if (llvmDIBuilder != nullptr) { llvm::DebugLoc debugLoc = llvm::DebugLoc::get(line, column, entry->getDebugInfo()); llvm::DIVariable debugVar = llvmDIBuilder->createLocalVariable( - llvm::dwarf::DW_TAG_arg_variable, // tag + llvm::dwarf::DW_TAG_variable, // tag entry->getDebugInfo(), // scope sout.str(), // name file, // file @@ -2969,7 +2969,7 @@ namespace clay { llvm::DIFile file = getDebugLineCol(argLocation, line, column); llvm::DebugLoc debugLoc = llvm::DebugLoc::get(line, column, entry->getDebugInfo()); llvm::DIVariable debugVar = llvmDIBuilder->createLocalVariable( - llvm::dwarf::DW_TAG_arg_variable, // tag + llvm::dwarf::DW_TAG_variable, // tag entry->getDebugInfo(), // scope entry->fixedArgNames[i]->str, // name file, // file @@ -3995,7 +3995,7 @@ namespace clay { if (llvmDIBuilder != nullptr) { llvm::DILexicalBlock debugBlock = ctx->getDebugScope(); llvm::DIVariable debugVar = llvmDIBuilder->createLocalVariable( - llvm::dwarf::DW_TAG_auto_variable, // tag + llvm::dwarf::DW_TAG_variable, // tag debugBlock, // scope getBindingVariableName(x, i), // name file, // file @@ -4062,7 +4062,7 @@ namespace clay { if (llvmDIBuilder != nullptr) { llvm::DILexicalBlock debugBlock = ctx->getDebugScope(); llvm::DIVariable debugVar = llvmDIBuilder->createLocalVariable( - llvm::dwarf::DW_TAG_auto_variable, // tag + llvm::dwarf::DW_TAG_variable, // tag debugBlock, // scope getBindingVariableName(x, i), // name file, // file @@ -4133,7 +4133,7 @@ namespace clay { llvm::DILexicalBlock debugBlock = ctx->getDebugScope(); llvm::DIType debugType = llvmTypeDebugInfo(pv.type); llvm::DIVariable debugVar = llvmDIBuilder->createLocalVariable( - llvm::dwarf::DW_TAG_auto_variable, // tag + llvm::dwarf::DW_TAG_variable, // tag debugBlock, // scope getBindingVariableName(x, i), // name file, // file diff --git a/compiler/codegen_op.cpp b/compiler/codegen_op.cpp index 990d60dc..dbd5a8c3 100644 --- a/compiler/codegen_op.cpp +++ b/compiler/codegen_op.cpp @@ -9,8 +9,8 @@ #include "constructors.hpp" #include "externals.hpp" #include "env.hpp" - #include "codegen_op.hpp" +#include "invoketables.hpp" namespace clay { static llvm::StringMap stringTableConstants; @@ -155,7 +155,8 @@ namespace clay { } type = cv->type; } - return ctx->builder->CreateLoad(cv->llValue); + llvm::Type *llTy = llvmType(cv->type); + return ctx->builder->CreateLoad(llTy, cv->llValue); } static llvm::Value *floatValue(MultiCValuePtr args, @@ -175,7 +176,8 @@ namespace clay { } type = (FloatType *) cv->type.ptr(); } - return ctx->builder->CreateLoad(cv->llValue); + llvm::Type *llTy = llvmType(cv->type); + return ctx->builder->CreateLoad(llTy, cv->llValue); } static llvm::Value *integerOrPointerLikeValue(MultiCValuePtr args, @@ -198,7 +200,8 @@ namespace clay { } type = cv->type; } - return ctx->builder->CreateLoad(cv->llValue); + llvm::Type *llTy = llvmType(cv->type); + return ctx->builder->CreateLoad(llTy, cv->llValue); } static void checkIntegerValue(MultiCValuePtr args, @@ -222,7 +225,8 @@ namespace clay { CodegenContext *ctx) { checkIntegerValue(args, index, type, ctx); CValuePtr cv = args->values[index]; - return ctx->builder->CreateLoad(cv->llValue); + llvm::Type *llTy = llvmType(cv->type); + return ctx->builder->CreateLoad(llTy, cv->llValue); } static llvm::Value *pointerValue(MultiCValuePtr args, @@ -239,7 +243,8 @@ namespace clay { type = (PointerType *) cv->type.ptr(); llvmType(type->pointeeType); // force the pointee type to be refined } - return ctx->builder->CreateLoad(cv->llValue); + llvm::Type *llTy = llvmType(cv->type); + return ctx->builder->CreateLoad(llTy, cv->llValue); } static llvm::Value *pointerLikeValue(MultiCValuePtr args, @@ -257,7 +262,8 @@ namespace clay { cv->type); type = cv->type; } - return ctx->builder->CreateLoad(cv->llValue); + llvm::Type *llTy = llvmType(cv->type); + return ctx->builder->CreateLoad(llTy, cv->llValue); } static llvm::Value *cCodePointerValue(MultiCValuePtr args, @@ -333,7 +339,8 @@ namespace clay { argumentTypeError(index, "enum type", cv->type); type = (EnumType *) cv->type.ptr(); } - return ctx->builder->CreateLoad(cv->llValue); + llvm::Type *llTy = llvmType(cv->type); + return ctx->builder->CreateLoad(llTy, cv->llValue); } llvm::AtomicOrdering atomicOrderValue(MultiCValuePtr args, unsigned index) { @@ -343,21 +350,21 @@ namespace clay { PrimOp *prim = (PrimOp *) obj.ptr(); switch (prim->primOpCode) { case PRIM_OrderUnordered: - return llvm::Unordered; + return llvm::AtomicOrdering::Unordered; case PRIM_OrderMonotonic: - return llvm::Monotonic; + return llvm::AtomicOrdering::Monotonic; case PRIM_OrderAcquire: - return llvm::Acquire; + return llvm::AtomicOrdering::Acquire; case PRIM_OrderRelease: - return llvm::Release; + return llvm::AtomicOrdering::Release; case PRIM_OrderAcqRel: - return llvm::AcquireRelease; + return llvm::AtomicOrdering::AcquireRelease; case PRIM_OrderSeqCst: - return llvm::SequentiallyConsistent; + return llvm::AtomicOrdering::SequentiallyConsistent; } } argumentTypeError(index, "atomic ordering", cv->type); - return llvm::Unordered; + return llvm::AtomicOrdering::Unordered; } llvm::AtomicRMWInst::BinOp atomicRMWOpValue(MultiCValuePtr args, unsigned index) { @@ -1335,7 +1342,7 @@ namespace clay { break; } - case PRIM_nullptrPointer: { + case PRIM_nullPointer: { ensureArity(args, 1); TypePtr dest = valueToPointerLikeType(args, 0); assert(out->size() == 1); @@ -1343,7 +1350,7 @@ namespace clay { assert(out0->type == dest); llvm::PointerType *llType = llvm::dyn_cast(llvmType(dest)); assert(llType != nullptr); - llvm::Value *result = llvm::ConstantPointernullptr::get(llType); + llvm::Value *result = llvm::ConstantPointerNull::get(llType); ctx->builder->CreateStore(result, out0->llValue); break; } diff --git a/compiler/desugar.cpp b/compiler/desugar.cpp index 15c852f1..1b713e1f 100644 --- a/compiler/desugar.cpp +++ b/compiler/desugar.cpp @@ -1,7 +1,7 @@ #include "clay.hpp" #include "operators.hpp" #include "evaluator.hpp" -// #include "analyzer.hpp" +#include "analyzer.hpp" #include "desugar.hpp" #include "parser.hpp" #include "clone.hpp" @@ -402,7 +402,7 @@ namespace clay { sourceNameOut << ">"; return new Source(sourceNameOut.str(), - llvm::MemoryBuffer::getMemBufferCopy(sourceTextBuf)); + llvm::MemoryBuffer::getMemBufferCopy(sourceTextBuf).get()); } ExprListPtr desugarEvalExpr(EvalExprPtr eval, EnvPtr env) { diff --git a/compiler/error.cpp b/compiler/error.cpp index ddb0ae0f..35e4e592 100644 --- a/compiler/error.cpp +++ b/compiler/error.cpp @@ -4,6 +4,9 @@ #include "matchinvoke.hpp" #include "invoketables.hpp" #include "error.hpp" +#include "printer.hpp" + +#include namespace clay { bool shouldPrintFullMatchErrors; @@ -17,20 +20,20 @@ namespace clay { static constexpr unsigned RECURSION_WARNING_LEVEL = 1000; - void pushCompileContext(ObjectPtr obj) { + void pushCompileContext(const ObjectPtr &obj) { if (contextStack.size() >= RECURSION_WARNING_LEVEL) warning("potential runaway recursion"); if (!contextStack.empty()) contextStack.back().location = topLocation(); - contextStack.push_back(CompileContextEntry(obj)); + contextStack.emplace_back(obj); } - void pushCompileContext(ObjectPtr obj, llvm::ArrayRef params) { + void pushCompileContext(const ObjectPtr &obj, const llvm::ArrayRef params) { if (contextStack.size() >= RECURSION_WARNING_LEVEL) warning("potential runaway recursion"); if (!contextStack.empty()) contextStack.back().location = topLocation(); - contextStack.push_back(CompileContextEntry(obj, params)); + contextStack.emplace_back(obj, params); } void pushCompileContext(ObjectPtr obj, llvm::ArrayRef params, llvm::ArrayRef dispatchIndices) { @@ -38,7 +41,7 @@ namespace clay { warning("potential runaway recursion"); if (!contextStack.empty()) contextStack.back().location = topLocation(); - contextStack.push_back(CompileContextEntry(obj, params, dispatchIndices)); + contextStack.emplace_back(obj, params, dispatchIndices); } void popCompileContext() { @@ -56,8 +59,8 @@ namespace clay { CompileContextPusher::CompileContextPusher(ObjectPtr obj, llvm::ArrayRef params, llvm::ArrayRef dispatchIndices) { vector params2; - for (unsigned i = 0; i < params.size(); ++i) { - params2.push_back(params[i].type.ptr()); + for (const auto & param : params) { + params2.emplace_back(param.type.ptr()); } pushCompileContext(obj, params2, dispatchIndices); } @@ -77,14 +80,13 @@ namespace clay { } Location topLocation() { - vector::iterator i, begin; - i = errorLocations.end(); - begin = errorLocations.begin(); + auto i = errorLocations.end(); + auto begin = errorLocations.begin(); while (i != begin) { --i; if (i->ok()) return *i; } - return Location(); + return {}; } // @@ -133,11 +135,11 @@ namespace clay { } } - llvm::DIFile getDebugLineCol(Location const &location, unsigned &line, unsigned &column) { + llvm::DIFile *getDebugLineCol(Location const &location, unsigned &line, unsigned &column) { if (!location.ok()) { line = 0; column = 0; - return llvm::DIFile(); + return nullptr; } unsigned tabColumn; @@ -158,14 +160,18 @@ namespace clay { computeLineCol(location, line, column, tabColumn); } - static void splitLines(SourcePtr source, vector &lines) { - lines.push_back(string()); - const char *p = source->data(); - const char *end = source->endData(); - for (; p != end; ++p) { - lines.back().push_back(*p); - if (*p == '\n') - lines.push_back(string()); + static void splitLines(const SourcePtr &source, vector &lines) { + lines.clear(); + if (!source || source->data() == source->endData()) { + return; + } + const std::string_view sourceView(source->data(), source->endData() - source->data()); + lines.emplace_back(); + + for (const char c : sourceView) { + lines.back().push_back(c); + if (c == '\n') + lines.emplace_back(); } } @@ -242,7 +248,7 @@ namespace clay { return; llvm::errs() << "\ndebug stack:\n"; for (size_t i = debugStack.size(); i > 0; --i) { - llvm::errs() << " " << debugStack[i - 1] << "\n"; + llvm::errs() << " " << debugStack[i - 1]->toString() << "\n"; } } @@ -321,22 +327,22 @@ namespace clay { error(sout.str()); } - void ensureArity(MultiStaticPtr args, size_t size) { + void ensureArity(const MultiStaticPtr &args, size_t size) { if (args->size() != size) arityError(size, args->size()); } - void ensureArity(MultiEValuePtr args, size_t size) { + void ensureArity(const MultiEValuePtr &args, size_t size) { if (args->size() != size) arityError(size, args->size()); } - void ensureArity(MultiPValuePtr args, size_t size) { + void ensureArity(const MultiPValuePtr &args, size_t size) { if (args->size() != size) arityError(size, args->size()); } - void ensureArity(MultiCValuePtr args, size_t size) { + void ensureArity(const MultiCValuePtr &args, size_t size) { if (args->size() != size) arityError(size, args->size()); } @@ -354,45 +360,45 @@ namespace clay { } static string typeErrorMessage(llvm::StringRef expected, - TypePtr receivedType) { + const TypePtr &receivedType) { string buf; llvm::raw_string_ostream sout(buf); sout << "expected " << expected << ", " - << "but received " << receivedType << " type"; + << "but received " << receivedType->toString() << " type"; return sout.str(); } - static string typeErrorMessage(TypePtr expectedType, - TypePtr receivedType) { + static string typeErrorMessage(const TypePtr &expectedType, + const TypePtr &receivedType) { string buf; llvm::raw_string_ostream sout(buf); - sout << expectedType << " type"; + sout << expectedType->toString() << " type"; return typeErrorMessage(sout.str(), receivedType); } - void typeError(llvm::StringRef expected, TypePtr receivedType) { + void typeError(const llvm::StringRef expected, const TypePtr &receivedType) { error(typeErrorMessage(expected, receivedType)); } - void typeError(TypePtr expectedType, TypePtr receivedType) { + void typeError(const TypePtr &expectedType, const TypePtr &receivedType) { error(typeErrorMessage(expectedType, receivedType)); } - void argumentTypeError(unsigned index, - llvm::StringRef expected, - TypePtr receivedType) { + void argumentTypeError(const unsigned index, + const llvm::StringRef expected, + const TypePtr &receivedType) { argumentError(index, typeErrorMessage(expected, receivedType)); } - void argumentTypeError(unsigned index, - TypePtr expectedType, - TypePtr receivedType) { + void argumentTypeError(const unsigned index, + const TypePtr &expectedType, + const TypePtr &receivedType) { argumentError(index, typeErrorMessage(expectedType, receivedType)); } - void indexRangeError(llvm::StringRef kind, - size_t value, - size_t maxValue) { + void indexRangeError(const llvm::StringRef kind, + const size_t value, + const size_t maxValue) { string buf; llvm::raw_string_ostream sout(buf); sout << kind << " " << value << " is out of range. "; @@ -400,10 +406,10 @@ namespace clay { error(sout.str()); } - void argumentIndexRangeError(unsigned index, - llvm::StringRef kind, - size_t value, - size_t maxValue) { + void argumentIndexRangeError(const unsigned index, + const llvm::StringRef kind, + const size_t value, + const size_t maxValue) { string buf; llvm::raw_string_ostream sout(buf); sout << kind << " " << value << " is out of range. "; @@ -411,17 +417,17 @@ namespace clay { argumentError(index, sout.str()); } - void invalidStaticObjectError(ObjectPtr obj) { + void invalidStaticObjectError(const ObjectPtr &obj) { string buf; llvm::raw_string_ostream sout(buf); - sout << "invalid static object: " << obj; + sout << "invalid static object: " << obj->toString(); error(sout.str()); } - void argumentInvalidStaticObjectError(unsigned index, ObjectPtr obj) { + void argumentInvalidStaticObjectError(const unsigned index, const ObjectPtr &obj) { string buf; llvm::raw_string_ostream sout(buf); - sout << "invalid static object: " << obj; + sout << "invalid static object: " << obj->toString(); argumentError(index, sout.str()); } @@ -436,10 +442,8 @@ namespace clay { llvm::raw_string_ostream sout(outBuf); int hiddenPatternOverloads = 0; - for (MatchFailureVector::const_iterator i = err.failures.begin(); - i != err.failures.end(); - ++i) { - OverloadPtr overload = i->first; + for (const auto & failure : err.failures) { + OverloadPtr overload = failure.first; if (!shouldPrintFullMatchErrors && overload->nameIsPattern) { ++hiddenPatternOverloads; continue; @@ -451,7 +455,7 @@ namespace clay { sout << location.source->fileName.c_str() << "(" << line + 1 << "," << column << ")" << "\n "; - printMatchError(sout, i->second); + printMatchError(sout, failure.second); } if (hiddenPatternOverloads > 0) sout << "\n " << hiddenPatternOverloads << diff --git a/compiler/error.hpp b/compiler/error.hpp index ef3d882e..a08ed56f 100644 --- a/compiler/error.hpp +++ b/compiler/error.hpp @@ -1,7 +1,6 @@ #pragma once #include "clay.hpp" -#include "invoketables.hpp" #include "printer.hpp" #if defined(__GNUC__) || defined(__clang__) @@ -21,20 +20,20 @@ namespace clay { void fmtError(const char *fmt, ...) CLAY_NORETURN; template - inline void error(Pointer context, llvm::Twine const &msg) CLAY_NORETURN; + void error(Pointer context, llvm::Twine const &msg) CLAY_NORETURN; template - inline void error(Pointer context, llvm::Twine const &msg) { + void error(Pointer context, llvm::Twine const &msg) { if (context->location.ok()) pushLocation(context->location); error(msg); } template - inline void error(T const *context, llvm::Twine const &msg) CLAY_NORETURN; + void error(T const *context, llvm::Twine const &msg) CLAY_NORETURN; template - inline void error(T const *context, llvm::Twine const &msg) { + void error(T const *context, llvm::Twine const &msg) { error(context->location, msg); } @@ -44,7 +43,7 @@ namespace clay { void argumentError(size_t index, llvm::StringRef msg, const T &argument) CLAY_NORETURN; template - void argumentError(size_t index, llvm::StringRef msg, const T &argument) { + void argumentError(const size_t index, const llvm::StringRef msg, const T &argument) { string buf; llvm::raw_string_ostream sout(buf); sout << "argument " << (index + 1) << ": " << msg << ", actual " << argument; @@ -55,38 +54,38 @@ namespace clay { void arityError2(size_t minExpected, size_t received) CLAY_NORETURN; template - inline void arityError(Pointer context, size_t expected, size_t received) CLAY_NORETURN; + void arityError(Pointer context, size_t expected, size_t received) CLAY_NORETURN; template - inline void arityError(Pointer context, size_t expected, size_t received) { + void arityError(Pointer context, size_t expected, size_t received) { if (context->location.ok()) pushLocation(context->location); arityError(expected, received); } template - inline void arityError2(Pointer context, size_t minExpected, size_t received) CLAY_NORETURN; + void arityError2(Pointer context, size_t minExpected, size_t received) CLAY_NORETURN; template - inline void arityError2(Pointer context, size_t minExpected, size_t received) { + void arityError2(Pointer context, size_t minExpected, size_t received) { if (context->location.ok()) pushLocation(context->location); arityError2(minExpected, received); } - void ensureArity(MultiStaticPtr args, size_t size); - void ensureArity(MultiEValuePtr args, size_t size); - void ensureArity(MultiPValuePtr args, size_t size); - void ensureArity(MultiCValuePtr args, size_t size); + void ensureArity(const MultiStaticPtr &args, size_t size); + void ensureArity(const MultiEValuePtr &args, size_t size); + void ensureArity(const MultiPValuePtr &args, size_t size); + void ensureArity(const MultiCValuePtr &args, size_t size); template - inline void ensureArity(T const &args, size_t size) { + void ensureArity(T const &args, size_t size) { if (args.size() != size) arityError(size, args.size()); } template - inline void ensureArity2(T const &args, size_t size, bool hasVarArgs) { + void ensureArity2(T const &args, size_t size, bool hasVarArgs) { if (!hasVarArgs) ensureArity(args, size); else if (args.size() < size) @@ -95,16 +94,16 @@ namespace clay { void arityMismatchError(size_t leftArity, size_t rightArity, bool hasVarArg) CLAY_NORETURN; - void typeError(llvm::StringRef expected, TypePtr receivedType) CLAY_NORETURN; - void typeError(TypePtr expectedType, TypePtr receivedType) CLAY_NORETURN; + void typeError(llvm::StringRef expected, const TypePtr &receivedType) CLAY_NORETURN; + void typeError(const TypePtr &expectedType, const TypePtr &receivedType) CLAY_NORETURN; void argumentTypeError(unsigned index, llvm::StringRef expected, - TypePtr receivedType) CLAY_NORETURN; + const TypePtr &receivedType) CLAY_NORETURN; void argumentTypeError(unsigned index, - TypePtr expectedType, - TypePtr receivedType) CLAY_NORETURN; + const TypePtr &expectedType, + const TypePtr &receivedType) CLAY_NORETURN; void indexRangeError(llvm::StringRef kind, size_t value, diff --git a/compiler/externals.hpp b/compiler/externals.hpp index dbdb107f..b5f6f284 100644 --- a/compiler/externals.hpp +++ b/compiler/externals.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "clay.hpp" #include "codegen.hpp" @@ -41,7 +43,7 @@ namespace clay { llvm::CallingConv::ID llConv; ArgInfo retInfo; vector argInfos; - vector> attrs; + llvm::AttributeList attrs; ExternalFunction(CallingConv conv, TypePtr ret, vector &args, size_t numReqArg, diff --git a/compiler/interactive.cpp b/compiler/interactive.cpp index d3f25926..9896819b 100644 --- a/compiler/interactive.cpp +++ b/compiler/interactive.cpp @@ -7,9 +7,9 @@ #include "invoketables.hpp" #include "env.hpp" -#include -#include -#include +#include +#include +#include namespace clay { typedef llvm::SmallString<16U> Str; @@ -17,13 +17,13 @@ namespace clay { const char *replAnonymousFunctionName = "__replAnonymousFunction__"; static ModulePtr module; - static llvm::ExecutionEngine *engine; + static std::unique_ptr jit; jmp_buf recovery; static bool printAST = false; - static void eval(llvm::StringRef code); + static void eval(llvm::StringRef line); string newFunctionName() { static int funNum = 0; @@ -105,7 +105,7 @@ namespace clay { for (size_t k = 0; k < sets.size(); ++k) { llvm::errs() << " "; for (size_t l = 0; l < sets[k]->argsKey.size(); ++l) { - llvm::errs() << sets[k]->argsKey[l] << " : "; + llvm::errs() << sets[k]->argsKey[l]->toString() << " : "; } llvm::errs() << "\n"; } @@ -122,7 +122,7 @@ namespace clay { llvm::errs() << "Can't find identifier " << identifier.c_str(); } else { for (size_t i = 0; i < iter->second.size(); ++i) { - llvm::errs() << iter->second[i] << "\n"; + llvm::errs() << iter->second[i]->toString() << "\n"; } } } @@ -156,15 +156,15 @@ namespace clay { } } - static void loadImports(llvm::ArrayRef imports) { - for (size_t i = 0; i < imports.size(); ++i) { - module->imports.push_back(imports[i]); + static void loadImports(const llvm::ArrayRef imports) { + for (const auto & import : imports) { + module->imports.push_back(import); } - for (size_t i = 0; i < imports.size(); ++i) { - loadDependent(module, nullptr, imports[i], false); + for (const auto & import : imports) { + loadDependent(module, nullptr, import, false); } - for (size_t i = 0; i < imports.size(); ++i) { - initModule(imports[i]->module); + for (const auto & import : imports) { + initModule(import->module); } } @@ -174,7 +174,7 @@ namespace clay { } if (printAST) { for (size_t i = 0; i < toplevels.size(); ++i) { - llvm::errs() << i << ": " << toplevels[i] << "\n"; + llvm::errs() << i << ": " << toplevels[i]->toString() << "\n"; } } addGlobals(module, toplevels); @@ -186,8 +186,8 @@ namespace clay { } if (printAST) { - for (size_t i = 0; i < statements.size(); ++i) { - llvm::errs() << statements[i] << "\n"; + for (const auto & statement : statements) { + llvm::errs() << statement->toString() << "\n"; } } @@ -217,12 +217,34 @@ namespace clay { llvm::Function *dtor; codegenAfterRepl(ctor, dtor); - engine->runFunction(ctor, std::vector()); + // hacky voodoo raw memory address returned by LLJIT symbol lookup + // https://llvm.org/docs/ORCv2.html + using CtorPtr = void (*)(); + using PFN = void (*)(); - void *dtorLlvmFun = engine->getPointerToFunction(dtor); - typedef void (*PFN)(); + auto ctorAddExpected = jit->lookup(ctor->getName()); + if (!ctorAddExpected) { + llvm::errs() << "error: cannot look up constructor: " << llvm::toString(ctorAddExpected.takeError()) << "\n"; + return; + } + CtorPtr ctorFunc = reinterpret_cast(ctorAddExpected->getValue()); + ctorFunc(); + + auto dtorAddExpected = jit->lookup(dtor->getName()); + if (!dtorAddExpected) { + llvm::errs() << "error: cannot look up destructor: " << llvm::toString(dtorAddExpected.takeError()) << "\n"; + return; + } + void *dtorLlvmFun = reinterpret_cast(dtorAddExpected->getValue()); atexit((PFN) (uintptr_t) dtorLlvmFun); - engine->runFunction(entryProc->llvmFunc, std::vector()); + + auto entryAddrExpected = jit->lookup(entryProc->llvmFunc->getName()); + if (!entryAddrExpected) { + llvm::errs() << "error: cannot look up entry function: " << llvm::toString(entryAddrExpected.takeError()) << "\n"; + return; + } + PFN entryFunc = reinterpret_cast(entryAddrExpected->getValue()); + entryFunc(); } static void jitAndPrintExpr(ExprPtr expr) { @@ -249,14 +271,13 @@ namespace clay { } } - static void interactiveLoop() { + [[noreturn]] static void interactiveLoop() { setjmp(recovery); - string line; while (true) { llvm::errs().flush(); llvm::errs() << "clay>"; char buf[255]; - line = fgets(buf, 255, stdin); + string line = fgets(buf, 255, stdin); line = stripSpaces(line); if (line[0] == ':') { replCommand(line.substr(1, line.size() - 1)); @@ -264,7 +285,6 @@ namespace clay { eval(line); } } - engine->runStaticConstructorsDestructors(true); } static void exceptionHandler(int i) { @@ -284,12 +304,37 @@ namespace clay { llvm::errs() << ":globals to list globals\n"; llvm::errs() << "In multi-line mode empty line to exit\n"; - llvm::EngineBuilder eb(llvmModule); - llvm::TargetOptions targetOptions; - targetOptions.JITExceptionHandling = true; - eb.setTargetOptions(targetOptions); - engine = eb.create(); - engine->runStaticConstructorsDestructors(false); + auto expectedJIT = llvm::orc::LLJITBuilder().create(); + if (!expectedJIT) { + llvm::errs() << "error: could not create JIT: " << llvm::toString(expectedJIT.takeError()) << "\n"; + return; + } + jit = std::move(*expectedJIT); + + llvm::orc::JITDylib& mainDylib = jit->getMainJITDylib(); + + auto generatorExpected = llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess( + jit->getDataLayout().getGlobalPrefix() + ); + + if (!generatorExpected) { + llvm::errs() << "error: setting up symbol" << llvm::toString(generatorExpected.takeError()) << "\n"; + } else { + std::unique_ptr generator = + std::move(*generatorExpected); + mainDylib.addGenerator(std::move(generator)); + } + + llvmModule->setDataLayout(jit->getDataLayout()); + + auto tsm = llvm::orc::ThreadSafeModule( + std::unique_ptr(llvmModule), + std::make_unique()); + + if (llvm::Error addIRErr = jit->addIRModule(std::move(tsm))) { + llvm::errs() << "error: " << addIRErr << "\n"; + return; + } setAddTokens(&addTokens); diff --git a/compiler/invoketables.hpp b/compiler/invoketables.hpp index 764885b4..19815b6e 100644 --- a/compiler/invoketables.hpp +++ b/compiler/invoketables.hpp @@ -7,12 +7,14 @@ namespace clay { struct InvokeSet; struct InvokeEntry; - static llvm::SpecificBumpPtrAllocator *invokeEntryAllocator + static auto invokeEntryAllocator = new llvm::SpecificBumpPtrAllocator(); - static llvm::SpecificBumpPtrAllocator *invokeSetAllocator + static auto invokeSetAllocator = new llvm::SpecificBumpPtrAllocator(); struct InvokeEntry { + virtual ~InvokeEntry() = default; + InvokeSet *parent; ObjectPtr callable; vector argsKey; @@ -36,9 +38,9 @@ namespace clay { vector returnTypes; llvm::Function *llvmFunc; - llvm::Function *llvmCWrappers[CC_Count]; + llvm::Function *llvmCWrappers[CC_Count]{}; - llvm::TrackingVH debugInfo; + llvm::TrackingMDNodeRef debugInfo; bool analyzed: 1; bool analyzing: 1; @@ -46,7 +48,7 @@ namespace clay { bool runtimeNop: 1; InvokeEntry(InvokeSet *parent, - ObjectPtr callable, + const ObjectPtr &callable, llvm::ArrayRef argsKey) : parent(parent), callable(callable), argsKey(argsKey), @@ -58,8 +60,8 @@ namespace clay { analyzing(false), callByName(false), runtimeNop(false) { - for (size_t i = 0; i < CC_Count; ++i) - llvmCWrappers[i] = nullptr; + for (auto & llvmCWrapper : llvmCWrappers) + llvmCWrapper = nullptr; } void *operator new(size_t num_bytes) { @@ -67,12 +69,16 @@ namespace clay { } virtual void dealloc() { ANodeAllocator->Deallocate(this); } - llvm::DISubprogram getDebugInfo() { return llvm::DISubprogram(debugInfo); } + llvm::DISubprogram *getDebugInfo() const { + return llvm::dyn_cast_or_null(debugInfo.get()); + } }; extern vector patternOverloads; struct InvokeSet { + virtual ~InvokeSet() = default; + ObjectPtr callable; vector argsKey; OverloadPtr interface; @@ -87,9 +93,9 @@ namespace clay { bool shouldLog: 1; bool evaluatingPredicate: 1; - InvokeSet(ObjectPtr callable, + InvokeSet(const ObjectPtr &callable, llvm::ArrayRef argsKey, - OverloadPtr symbolInterface, + const OverloadPtr &symbolInterface, llvm::ArrayRef symbolOverloads) : callable(callable), argsKey(argsKey), interface(symbolInterface), diff --git a/compiler/lambdas.cpp b/compiler/lambdas.cpp index 95b8ed8b..c96abf15 100644 --- a/compiler/lambdas.cpp +++ b/compiler/lambdas.cpp @@ -16,7 +16,7 @@ namespace clay { vector &freeVars; LambdaContext(LambdaCapture captureBy, - EnvPtr nonLocalEnv, + const EnvPtr& nonLocalEnv, llvm::StringRef closureDataName, vector &freeVars) : captureBy(captureBy), nonLocalEnv(nonLocalEnv), @@ -24,40 +24,39 @@ namespace clay { } }; - void convertFreeVars(LambdaPtr x, EnvPtr env, + void convertFreeVars(const LambdaPtr &x, const EnvPtr &env, llvm::StringRef closureDataName, vector &freeVars); - void convertFreeVars(StatementPtr x, EnvPtr env, LambdaContext &ctx); + void convertFreeVars(const StatementPtr &x, EnvPtr env, LambdaContext &ctx); - void convertFreeVars(ExprPtr &x, EnvPtr env, LambdaContext &ctx); + void convertFreeVars(ExprPtr &x, const EnvPtr &env, LambdaContext &ctx); - void convertFreeVars(ExprList *x, EnvPtr env, LambdaContext &ctx); + void convertFreeVars(ExprList *x, const EnvPtr &env, LambdaContext &ctx); // // initializeLambda // - static TypePtr typeOfValue(ObjectPtr obj) { + static TypePtr typeOfValue(const ObjectPtr& obj) { switch (obj->objKind) { - case PVALUE: return ((PValue *) obj.ptr())->data.type; - case CVALUE: return ((CValue *) obj.ptr())->type; + case PVALUE: return dynamic_cast(obj.ptr())->data.type; + case CVALUE: return dynamic_cast(obj.ptr())->type; default: assert(false); - return nullptr; } } - static vector typesOfValues(ObjectPtr obj) { + static vector typesOfValues(const ObjectPtr &obj) { vector types; switch (obj->objKind) { case MULTI_PVALUE: { - MultiPValue *mpv = (MultiPValue *) obj.ptr(); + auto mpv = dynamic_cast(obj.ptr()); for (unsigned i = 0; i < mpv->size(); ++i) types.push_back(mpv->values[i].type); break; } case MULTI_CVALUE: { - MultiCValue *mcv = (MultiCValue *) obj.ptr(); + auto mcv = dynamic_cast(obj.ptr()); for (unsigned i = 0; i < mcv->size(); ++i) types.push_back(mcv->values[i]->type); break; @@ -68,13 +67,13 @@ namespace clay { return types; } - static void initializeLambdaWithFreeVars(LambdaPtr x, EnvPtr env, + static void initializeLambdaWithFreeVars(const LambdaPtr &x, const EnvPtr &env, llvm::StringRef closureDataName, llvm::StringRef lname); - static void initializeLambdaWithoutFreeVars(LambdaPtr x, EnvPtr env, + static void initializeLambdaWithoutFreeVars(const LambdaPtr &x, const EnvPtr &env, llvm::StringRef lname); - static string lambdaName(LambdaPtr x) { + static string lambdaName(const LambdaPtr &x) { string fullName = shortString(x->asString()); if (fullName.size() <= 80) @@ -86,11 +85,11 @@ namespace clay { printFileLineCol(shortName, x->location); shortName << ">"; - return shortName.str(); + return shortName.str().str(); // what is this abomination } } - void initializeLambda(LambdaPtr x, EnvPtr env) { + void initializeLambda(const LambdaPtr& x, const EnvPtr &env) { assert(!x->initialized); x->initialized = true; @@ -99,7 +98,7 @@ namespace clay { llvm::SmallString<128> buf; llvm::raw_svector_ostream ostr(buf); ostr << "%closureData:" << lname; - string closureDataName = ostr.str(); + string closureDataName = ostr.str().str(); // again convertFreeVars(x, env, closureDataName, x->freeVars); getProcedureMonoTypes(x->mono, env, x->formalArgs, x->hasVarArg); @@ -124,15 +123,15 @@ namespace clay { } } - static void checkForeignExpr(ObjectPtr &obj, EnvPtr env) { + static void checkForeignExpr(ObjectPtr &obj, const EnvPtr &env) { if (obj->objKind == EXPRESSION) { - ExprPtr expr = (Expr *) obj.ptr(); + ExprPtr expr = dynamic_cast(obj.ptr()); if (expr->exprKind == FOREIGN_EXPR) { MultiPValuePtr mpv = safeAnalyzeMulti(new ExprList(expr), env, 0); obj = mpv.ptr(); } } else if (obj->objKind == EXPR_LIST) { - ExprListPtr expr = (ExprList *) obj.ptr(); + ExprListPtr expr = dynamic_cast(obj.ptr()); switch (expr->exprs[0]->exprKind) { case FOREIGN_EXPR: case UNPACK: { @@ -146,7 +145,7 @@ namespace clay { } } - static void initializeLambdaWithFreeVars(LambdaPtr x, EnvPtr env, + static void initializeLambdaWithFreeVars(const LambdaPtr &x, const EnvPtr &env, llvm::StringRef closureDataName, llvm::StringRef lname) { RecordDeclPtr r = new RecordDecl(nullptr, PRIVATE); r->location = x->location; @@ -181,8 +180,7 @@ namespace clay { case MULTI_CVALUE: { vector types = typesOfValues(obj); vector elementTypes; - for (size_t j = 0; j < types.size(); ++j) { - TypePtr t = types[j]; + for (auto t : types) { if (x->captureBy == REF_CAPTURE) t = pointerType(t); elementTypes.push_back(t); @@ -221,9 +219,9 @@ namespace clay { code->location = x->location; IdentifierPtr closureDataIdent = Identifier::get(closureDataName); FormalArgPtr closureDataArg = new FormalArg(closureDataIdent, typeExpr); - code->formalArgs.push_back(closureDataArg.ptr()); - for (size_t i = 0; i < x->formalArgs.size(); ++i) { - code->formalArgs.push_back(x->formalArgs[i]); + code->formalArgs.emplace_back(closureDataArg.ptr()); + for (const auto & formalArg : x->formalArgs) { + code->formalArgs.push_back(formalArg); } code->hasVarArg = x->hasVarArg; code->body = x->body; @@ -236,11 +234,11 @@ namespace clay { ObjectPtr obj = operator_call(); if (obj->objKind != PROCEDURE) error("'call' operator not found!"); - Procedure *callObj = (Procedure *) obj.ptr(); + auto *callObj = dynamic_cast(obj.ptr()); addOverload(callObj->overloads, overload); } - static void initializeLambdaWithoutFreeVars(LambdaPtr x, EnvPtr env, + static void initializeLambdaWithoutFreeVars(const LambdaPtr &x, const EnvPtr &env, llvm::StringRef lname) { IdentifierPtr name = Identifier::get(lname, x->location); x->lambdaProc = new Procedure(nullptr, name, PRIVATE, false); @@ -248,8 +246,8 @@ namespace clay { CodePtr code = new Code(); code->location = x->location; - for (size_t i = 0; i < x->formalArgs.size(); ++i) { - code->formalArgs.push_back(x->formalArgs[i]); + for (const auto & formalArg : x->formalArgs) { + code->formalArgs.push_back(formalArg); } code->hasVarArg = x->hasVarArg; code->body = x->body; @@ -268,11 +266,10 @@ namespace clay { // addFreeVar, typeOfValue, typesOfValues // - static void addFreeVar(LambdaContext &ctx, llvm::StringRef str) { - vector::iterator i; - i = std::find(ctx.freeVars.begin(), ctx.freeVars.end(), str); + static void addFreeVar(const LambdaContext &ctx, llvm::StringRef str) { + auto i = std::find(ctx.freeVars.begin(), ctx.freeVars.end(), str); if (i == ctx.freeVars.end()) { - ctx.freeVars.push_back(str); + ctx.freeVars.push_back(str.str()); } } @@ -280,62 +277,57 @@ namespace clay { // convertFreeVars // - void convertFreeVars(LambdaPtr x, EnvPtr env, + void convertFreeVars(const LambdaPtr &x, const EnvPtr &env, llvm::StringRef closureDataName, vector &freeVars) { EnvPtr env2 = new Env(env); - for (size_t i = 0; i < x->formalArgs.size(); ++i) { - FormalArgPtr arg = x->formalArgs[i]; + for (const auto& arg : x->formalArgs) { addLocal(env2, arg->name, arg->name.ptr()); } LambdaContext ctx(x->captureBy, env, closureDataName, freeVars); convertFreeVars(x->body, env2, ctx); } - static EnvPtr convertFreeVarsFromBinding(BindingPtr binding, EnvPtr env, LambdaContext &ctx) { + static EnvPtr convertFreeVarsFromBinding(const BindingPtr &binding, const EnvPtr &env, LambdaContext &ctx) { convertFreeVars(binding->values.ptr(), env, ctx); EnvPtr env2 = new Env(env); - for (size_t j = 0; j < binding->args.size(); ++j) - addLocal(env2, binding->args[j]->name, binding->args[j]->name.ptr()); + for (const auto & arg : binding->args) + addLocal(env2, arg->name, arg->name.ptr()); return env2; } static EnvPtr convertFreeVarsFromStatementExpressionStatements( llvm::ArrayRef stmts, - EnvPtr env, + const EnvPtr &env, LambdaContext &ctx) { EnvPtr env2 = env; - for (StatementPtr const *i = stmts.begin(), *end = stmts.end(); - i != end; - ++i) { - switch ((*i)->stmtKind) { + for (const auto & stmt : stmts) { + switch (stmt->stmtKind) { case BINDING: - env2 = convertFreeVarsFromBinding((Binding *) i->ptr(), env2, ctx); + env2 = convertFreeVarsFromBinding(dynamic_cast(stmt.ptr()), env2, ctx); break; case ASSIGNMENT: case VARIADIC_ASSIGNMENT: case INIT_ASSIGNMENT: case EXPR_STATEMENT: - convertFreeVars(*i, env2, ctx); + convertFreeVars(stmt, env2, ctx); break; default: assert(false); - return nullptr; } } return env2; } - void convertFreeVars(StatementPtr x, EnvPtr env, LambdaContext &ctx) { + void convertFreeVars(const StatementPtr &x, EnvPtr env, LambdaContext &ctx) { switch (x->stmtKind) { case BLOCK: { - Block *y = (Block *) x.ptr(); - for (size_t i = 0; i < y->statements.size(); ++i) { - StatementPtr z = y->statements[i]; + auto y = dynamic_cast(x.ptr()); + for (const auto& z : y->statements) { if (z->stmtKind == BINDING) - env = convertFreeVarsFromBinding((Binding *) z.ptr(), env, ctx); + env = convertFreeVarsFromBinding(dynamic_cast(z.ptr()), env, ctx); else convertFreeVars(z, env, ctx); } @@ -348,21 +340,21 @@ namespace clay { } case ASSIGNMENT: { - Assignment *y = (Assignment *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->left.ptr(), env, ctx); convertFreeVars(y->right.ptr(), env, ctx); break; } case INIT_ASSIGNMENT: { - InitAssignment *y = (InitAssignment *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->left.ptr(), env, ctx); convertFreeVars(y->right.ptr(), env, ctx); break; } case VARIADIC_ASSIGNMENT: { - VariadicAssignment *y = (VariadicAssignment *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->exprs.ptr(), env, ctx); break; } @@ -372,13 +364,13 @@ namespace clay { } case RETURN: { - Return *y = (Return *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->values.ptr(), env, ctx); break; } case IF: { - If *y = (If *) x.ptr(); + auto y = dynamic_cast(x.ptr()); env = convertFreeVarsFromStatementExpressionStatements(y->conditionStatements, env, ctx); convertFreeVars(y->condition, env, ctx); convertFreeVars(y->thenPart, env, ctx); @@ -388,11 +380,10 @@ namespace clay { } case SWITCH: { - Switch *y = (Switch *) x.ptr(); + auto y = dynamic_cast(x.ptr()); env = convertFreeVarsFromStatementExpressionStatements(y->exprStatements, env, ctx); convertFreeVars(y->expr, env, ctx); - for (size_t i = 0; i < y->caseBlocks.size(); ++i) { - CaseBlockPtr z = y->caseBlocks[i]; + for (const auto& z : y->caseBlocks) { convertFreeVars(z->caseLabels.ptr(), env, ctx); convertFreeVars(z->body, env, ctx); } @@ -402,19 +393,19 @@ namespace clay { } case EVAL_STATEMENT: { - EvalStatement *eval = (EvalStatement *) x.ptr(); + auto eval = dynamic_cast(x.ptr()); convertFreeVars(eval->args.ptr(), env, ctx); break; } case EXPR_STATEMENT: { - ExprStatement *y = (ExprStatement *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->expr, env, ctx); break; } case WHILE: { - While *y = (While *) x.ptr(); + auto y = dynamic_cast(x.ptr()); env = convertFreeVarsFromStatementExpressionStatements(y->conditionStatements, env, ctx); convertFreeVars(y->condition, env, ctx); convertFreeVars(y->body, env, ctx); @@ -427,11 +418,11 @@ namespace clay { } case FOR: { - For *y = (For *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->expr, env, ctx); EnvPtr env2 = new Env(env); - for (size_t j = 0; j < y->variables.size(); ++j) - addLocal(env2, y->variables[j], y->variables[j].ptr()); + for (const auto & variable : y->variables) + addLocal(env2, variable, variable.ptr()); convertFreeVars(y->body, env2, ctx); break; } @@ -441,24 +432,24 @@ namespace clay { } case TRY: { - Try *y = (Try *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->tryBlock, env, ctx); - for (size_t i = 0; i < y->catchBlocks.size(); ++i) { + for (const auto & catchBlock : y->catchBlocks) { EnvPtr env2 = new Env(env); addLocal(env2, - y->catchBlocks[i]->exceptionVar, - y->catchBlocks[i]->exceptionVar.ptr() + catchBlock->exceptionVar, + catchBlock->exceptionVar.ptr() ); - if (y->catchBlocks[i]->exceptionType.ptr()) - convertFreeVars(y->catchBlocks[i]->exceptionType, env, ctx); - convertFreeVars(y->catchBlocks[i]->body, env2, ctx); + if (catchBlock->exceptionType.ptr()) + convertFreeVars(catchBlock->exceptionType, env, ctx); + convertFreeVars(catchBlock->body, env2, ctx); } break; } case THROW: { - Throw *y = (Throw *) x.ptr(); + auto y = dynamic_cast(x.ptr()); desugarThrow(y); convertFreeVars(y->desugaredExpr, env, ctx); if (y->desugaredContext != nullptr) @@ -467,7 +458,7 @@ namespace clay { } case STATIC_FOR: { - StaticFor *y = (StaticFor *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->values.ptr(), env, ctx); EnvPtr env2 = new Env(env); addLocal(env2, y->variable, y->variable.ptr()); @@ -476,20 +467,18 @@ namespace clay { } case FINALLY: { - Finally *y = (Finally *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->body, env, ctx); break; } case ONERROR: { - OnError *y = (OnError *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->body, env, ctx); break; } case UNREACHABLE: - break; - case STATIC_ASSERT_STATEMENT: break; @@ -498,7 +487,7 @@ namespace clay { } } - void convertFreeVars(ExprPtr &x, EnvPtr env, LambdaContext &ctx) { + void convertFreeVars(ExprPtr &x, const EnvPtr &env, LambdaContext &ctx) { switch (x->exprKind) { case BOOL_LITERAL: case INT_LITERAL: @@ -508,7 +497,7 @@ namespace clay { break; case NAME_REF: { - NameRef *y = (NameRef *) x.ptr(); + auto y = dynamic_cast(x.ptr()); bool isNonLocal = false; bool isGlobal = false; ObjectPtr z = lookupEnvEx(env, y->name, ctx.nonLocalEnv, @@ -551,16 +540,16 @@ namespace clay { } else if ((z->objKind == MULTI_PVALUE) || (z->objKind == MULTI_CVALUE)) { vector types = typesOfValues(z); bool allStatic = true; - for (size_t i = 0; i < types.size(); ++i) { - if (!isStaticOrTupleOfStatics(types[i])) { + for (const auto & type : types) { + if (!isStaticOrTupleOfStatics(type)) { allStatic = false; break; } } if (allStatic) { ExprListPtr args = new ExprList(); - for (size_t i = 0; i < types.size(); ++i) - args->add(new ObjectExpr(types[i].ptr())); + for (const auto & type : types) + args->add(new ObjectExpr(type.ptr())); CallPtr call = new Call(operator_expr_typesToRValues(), args); call->location = y->location; x = call.ptr(); @@ -600,33 +589,33 @@ namespace clay { } case TUPLE: { - Tuple *y = (Tuple *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->args.ptr(), env, ctx); break; } case PAREN: { - Paren *y = (Paren *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->args.ptr(), env, ctx); break; } case INDEXING: { - Indexing *y = (Indexing *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->expr, env, ctx); convertFreeVars(y->args.ptr(), env, ctx); break; } case CALL: { - Call *y = (Call *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->expr, env, ctx); convertFreeVars(y->parenArgs.ptr(), env, ctx); break; } case FIELD_REF: { - FieldRef *y = (FieldRef *) x.ptr(); + auto y = dynamic_cast(x.ptr()); if (y->desugared == nullptr) desugarFieldRef(y, safeLookupModule(env)); if (!y->isDottedModuleName) @@ -635,60 +624,60 @@ namespace clay { } case STATIC_INDEXING: { - StaticIndexing *y = (StaticIndexing *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->expr, env, ctx); break; } case VARIADIC_OP: { - VariadicOp *y = (VariadicOp *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->exprs.ptr(), env, ctx); break; } case AND: { - And *y = (And *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->expr1, env, ctx); convertFreeVars(y->expr2, env, ctx); break; } case OR: { - Or *y = (Or *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->expr1, env, ctx); convertFreeVars(y->expr2, env, ctx); break; } case LAMBDA: { - Lambda *y = (Lambda *) x.ptr(); + auto y = dynamic_cast(x.ptr()); EnvPtr env2 = new Env(env); - for (size_t i = 0; i < y->formalArgs.size(); ++i) - addLocal(env2, y->formalArgs[i]->name, y->formalArgs[i]->name.ptr()); + for (const auto & formalArg : y->formalArgs) + addLocal(env2, formalArg->name, formalArg->name.ptr()); convertFreeVars(y->body, env2, ctx); break; } case UNPACK: { - Unpack *y = (Unpack *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->expr, env, ctx); break; } case STATIC_EXPR: { - StaticExpr *y = (StaticExpr *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->expr, env, ctx); break; } case DISPATCH_EXPR: { - DispatchExpr *y = (DispatchExpr *) x.ptr(); + auto y = dynamic_cast(x.ptr()); convertFreeVars(y->expr, env, ctx); break; } case EVAL_EXPR: { - EvalExpr *eval = (EvalExpr *) x.ptr(); + auto eval = dynamic_cast(x.ptr()); convertFreeVars(eval->args, env, ctx); break; } @@ -703,7 +692,7 @@ namespace clay { } } - void convertFreeVars(ExprList *x, EnvPtr env, LambdaContext &ctx) { + void convertFreeVars(ExprList *x, const EnvPtr &env, LambdaContext &ctx) { for (unsigned i = 0; i < x->size(); ++i) convertFreeVars(x->exprs[i], env, ctx); } diff --git a/compiler/lambdas.hpp b/compiler/lambdas.hpp index f2386831..a9310232 100644 --- a/compiler/lambdas.hpp +++ b/compiler/lambdas.hpp @@ -3,7 +3,5 @@ #include "clay.hpp" namespace clay { - -void initializeLambda(LambdaPtr x, EnvPtr env); - + void initializeLambda(const LambdaPtr& x, EnvPtr env); } diff --git a/compiler/loader.cpp b/compiler/loader.cpp index 071d8338..d2bbc060 100644 --- a/compiler/loader.cpp +++ b/compiler/loader.cpp @@ -1,3 +1,5 @@ +#include + #include "clay.hpp" #include "loader.hpp" #include "patterns.hpp" diff --git a/compiler/loader.hpp b/compiler/loader.hpp index 20a860df..0f0cada9 100644 --- a/compiler/loader.hpp +++ b/compiler/loader.hpp @@ -1,6 +1,5 @@ #pragma once - #include "clay.hpp" namespace clay { @@ -14,7 +13,7 @@ namespace clay { llvm::ArrayRef formalArgs, bool hasVarArg); void initLoader(); - void setSearchPath(const llvm::ArrayRef path); + void setSearchPath(llvm::ArrayRef path); ModulePtr loadProgram(llvm::StringRef fileName, vector *sourceFiles, bool verbose, bool repl); ModulePtr loadProgramSource(llvm::StringRef name, llvm::StringRef source, bool verbose, bool repl); ModulePtr loadedModule(llvm::StringRef module); diff --git a/compiler/parachute.cpp b/compiler/parachute.cpp index 308312cb..6bb047c2 100644 --- a/compiler/parachute.cpp +++ b/compiler/parachute.cpp @@ -55,13 +55,13 @@ namespace clay { // Signal parachute -#include +#include namespace clay { static volatile int threatLevel = 0; - static void emergencyCompileContext(int sig) { - int oldThreatLevel = __sync_fetch_and_add(&threatLevel, 1); + static void emergencyCompileContext(const int sig) { + const int oldThreatLevel = __sync_fetch_and_add(&threatLevel, 1); if (oldThreatLevel == 0) { fprintf(stderr, "signal %d!\n", sig); displayCompileContext(); diff --git a/compiler/parser.cpp b/compiler/parser.cpp index 13698281..2d79761b 100644 --- a/compiler/parser.cpp +++ b/compiler/parser.cpp @@ -24,7 +24,7 @@ namespace clay { if (inRepl) { assert(addTokens != nullptr); vector toks = addTokens(); - if (toks.size() == 0) { + if (toks.empty()) { inRepl = false; return false; } @@ -50,7 +50,7 @@ namespace clay { static Location currentLocation() { if (position == tokens->size()) - return Location(); + return {}; return (*tokens)[position].location; } @@ -278,10 +278,9 @@ namespace clay { } static bool expressionList(ExprListPtr &x, bool = false) { - ExprListPtr a; ExprPtr b; if (!expression(b)) return false; - a = new ExprList(b); + ExprListPtr a = new ExprList(b); while (true) { unsigned p = save(); if (!symbol(",")) { @@ -481,30 +480,30 @@ namespace clay { return false; } - static void setSuffixBase(Expr *a, ExprPtr base) { + static void setSuffixBase(Expr *a, const ExprPtr &base) { switch (a->exprKind) { case INDEXING: { - Indexing *b = (Indexing *) a; + auto b = dynamic_cast(a); b->expr = base; break; } case CALL: { - Call *b = (Call *) a; + Call *b = dynamic_cast(a); b->expr = base; break; } case FIELD_REF: { - FieldRef *b = (FieldRef *) a; + auto b = dynamic_cast(a); b->expr = base; break; } case STATIC_INDEXING: { - StaticIndexing *b = (StaticIndexing *) a; + auto b = dynamic_cast(a); b->expr = base; break; } case VARIADIC_OP: { - VariadicOp *b = (VariadicOp *) a; + auto *b = dynamic_cast(a); assert(b->op == DEREFERENCE); b->exprs->add(base); break; @@ -1033,7 +1032,7 @@ namespace clay { static bool optPatternVarsWithCond(vector &x, ExprPtr &y); - static bool bindingsBody(vector &args, bool &hasVarArg); + static bool bindingsBody(vector &x, bool &hasVarArg); static bool localBinding(StatementPtr &x) { Location location = currentLocation(); @@ -1146,7 +1145,7 @@ namespace clay { if (!symbol(";")) return false; ExprListPtr exprs = new ExprList(new NameRef(Identifier::get(op, true))); if (z->exprKind == VARIADIC_OP) { - VariadicOp *y = (VariadicOp *) z.ptr(); + auto y = dynamic_cast(z.ptr()); exprs->add(y->exprs); } else { exprs->add(z); @@ -1167,8 +1166,8 @@ namespace clay { ExprListPtr exprs = new ExprList(new NameRef(Identifier::get(op, true))); exprs->add(y); if (z->exprKind == VARIADIC_OP) { - VariadicOp *y = (VariadicOp *) z.ptr(); - exprs->add(y->exprs); + auto variadic_op = dynamic_cast(z.ptr()); + exprs->add(variadic_op->exprs); } else { exprs->add(z); } @@ -1694,7 +1693,7 @@ namespace clay { return true; } - static FormalArgPtr makeStaticFormalArg(size_t index, ExprPtr expr, Location const &location) { + static FormalArgPtr makeStaticFormalArg(size_t index, const ExprPtr &expr, Location const &location) { // desugar static args llvm::SmallString<128> buf; llvm::raw_svector_ostream sout(buf); @@ -1889,12 +1888,12 @@ namespace clay { } else { int bracket = 1; while (bracket) { - unsigned p = save(); + unsigned i = save(); if (symbol("[")) { ++bracket; continue; } - restore(p); + restore(i); if (symbol("]")) --bracket; } @@ -2285,7 +2284,7 @@ namespace clay { if (symbol(":")) { if (!optReturnTypeList(returnSpecs)) return false; if (!optVarReturnType(varReturnSpec)) return false; - if (returnSpecs.size() > 0 || varReturnSpec != nullptr) + if (!returnSpecs.empty() || varReturnSpec != nullptr) exprRetSpecs = true; return true; } else { @@ -2312,7 +2311,7 @@ namespace clay { // static bool isOverload(bool &isDefault) { - int p = save(); + int p = static_cast(save()); if (keyword("overload")) isDefault = false; else if (restore(p), keyword("default")) @@ -2394,7 +2393,7 @@ namespace clay { ProcedurePtr u = new Procedure(module, z, vis, true); u->location = location; - x.push_back(u.ptr()); + x.emplace_back(u.ptr()); ExprPtr target = new NameRef(z); target->location = location; @@ -2402,7 +2401,7 @@ namespace clay { target->endLocation = targetEndLocation; OverloadPtr v = new Overload(module, target, y, false, isInline, hasAsConversion); v->location = location; - x.push_back(v.ptr()); + x.emplace_back(v.ptr()); u->singleOverload = v; @@ -2444,7 +2443,7 @@ namespace clay { ProcedurePtr proc = new Procedure(module, name, vis, privateOverload, interface); proc->location = location; - x.push_back(proc.ptr()); + x.emplace_back(proc.ptr()); return true; } @@ -2475,14 +2474,14 @@ namespace clay { if (!body(code->body)) return false; code->location = location; if (exprRetSpecs && code->body->stmtKind == RETURN) { - Return *x = (Return *) code->body.ptr(); - if (x->isExprReturn) - x->isReturnSpecs = true; + auto return_ = dynamic_cast(code->body.ptr()); + if (return_->isExprReturn) + return_->isReturnSpecs = true; } ProcedurePtr proc = new Procedure(module, name, vis, true); proc->location = location; - x.push_back(proc.ptr()); + x.emplace_back(proc.ptr()); ExprPtr target = new NameRef(name); target->location = location; @@ -2490,7 +2489,7 @@ namespace clay { target->endLocation = targetEndLocation; OverloadPtr oload = new Overload(module, target, code, callByName, isInline, hasAsConversion); oload->location = location; - x.push_back(oload.ptr()); + x.emplace_back(oload.ptr()); proc->singleOverload = oload; @@ -2542,9 +2541,9 @@ namespace clay { if (!llvmCode(code->llvmBody)) return false; } if (exprRetSpecs && code->body->stmtKind == RETURN) { - Return *x = (Return *) code->body.ptr(); - if (x->isExprReturn) - x->isReturnSpecs = true; + auto return_ = dynamic_cast(code->body.ptr()); + if (return_->isExprReturn) + return_->isReturnSpecs = true; } target->location = location; target->startLocation = targetStartLocation; @@ -2975,7 +2974,7 @@ namespace clay { Location location = currentLocation(); Token *t; if (!next(t) || t->tokenKind != T_DOC_PROPERTY) return false; - llvm::StringRef key = llvm::StringRef(t->str); + auto key = llvm::StringRef(t->str); DocumentationAnnotation ano; if (key == "section") { @@ -2993,7 +2992,7 @@ namespace clay { } if (!next(t) || t->tokenKind != T_DOC_TEXT) return false; - llvm::StringRef value = llvm::StringRef(t->str); + auto value = llvm::StringRef(t->str); an.insert(std::pair(ano, value.str())); return true; @@ -3173,22 +3172,22 @@ namespace clay { break; } - unsigned p = save(); + unsigned i = save(); if (!topLevelItem(x.toplevels, nullptr)) { - restore(p); + restore(i); } else { continue; } if (!import(x.imports)) { - restore(p); + restore(i); } else { continue; } if (!blockItem(stmtItem)) { - restore(p); + restore(i); break; } else { x.stmts.push_back(stmtItem); @@ -3205,7 +3204,7 @@ namespace clay { // template - void applyParser(SourcePtr source, unsigned offset, size_t length, Parser parser, ParserParam parserParam, + void applyParser(const SourcePtr& source, unsigned offset, size_t length, Parser parser, ParserParam parserParam, Node &node) { vector t; tokenize(source, offset, length, t); @@ -3216,7 +3215,7 @@ namespace clay { if (!parser(node, parserParam) || (position < t.size())) { Location location; if (maxPosition == t.size()) - location = Location(source.ptr(), unsigned(source->size())); + location = Location(source.ptr(), static_cast(source->size())); else location = t[maxPosition].location; pushLocation(location); @@ -3229,11 +3228,11 @@ namespace clay { struct ModuleParser { llvm::StringRef moduleName; - bool operator()(ModulePtr &m, Module *) { return module(moduleName, m); } + bool operator()(ModulePtr &m, Module *) const { return module(moduleName, m); } }; - ModulePtr parse(llvm::StringRef moduleName, SourcePtr source, ParserFlags flags) { - if (flags && ParserKeepDocumentation) + ModulePtr parse(llvm::StringRef moduleName, const SourcePtr &source, ParserFlags flags) { + if (flags) parserOptionKeepDocumentation = true; ModulePtr m; ModuleParser p = {moduleName}; @@ -3246,7 +3245,7 @@ namespace clay { // parseExpr // - ExprPtr parseExpr(SourcePtr source, unsigned offset, size_t length) { + ExprPtr parseExpr(const SourcePtr &source, unsigned offset, size_t length) { ExprPtr expr; applyParser(source, offset, length, expression, false, expr); return expr; @@ -3256,7 +3255,7 @@ namespace clay { // parseExprList // - ExprListPtr parseExprList(SourcePtr source, unsigned offset, size_t length) { + ExprListPtr parseExprList(const SourcePtr &source, unsigned offset, size_t length) { ExprListPtr exprList; applyParser(source, offset, length, expressionList, false, exprList); return exprList; @@ -3266,7 +3265,7 @@ namespace clay { // parseStatements // - void parseStatements(SourcePtr source, unsigned offset, size_t length, + void parseStatements(const SourcePtr &source, unsigned offset, size_t length, vector &stmts) { applyParser(source, offset, length, blockItems, false, stmts); } @@ -3275,7 +3274,7 @@ namespace clay { // parseTopLevelItems // - void parseTopLevelItems(SourcePtr source, unsigned offset, size_t length, + void parseTopLevelItems(const SourcePtr &source, unsigned offset, size_t length, vector &topLevels, Module *module) { applyParser(source, offset, length, topLevelItems, module, topLevels); } @@ -3284,7 +3283,7 @@ namespace clay { // parseInteractive // - ReplItem parseInteractive(SourcePtr source, unsigned offset, size_t length) { + ReplItem parseInteractive(const SourcePtr &source, unsigned offset, size_t length) { ReplItem x; applyParser(source, offset, length, replItems, false, x); return x; diff --git a/compiler/parser.hpp b/compiler/parser.hpp index 3af1a3a9..a8243843 100644 --- a/compiler/parser.hpp +++ b/compiler/parser.hpp @@ -17,19 +17,19 @@ namespace clay { vector stmts; }; - ModulePtr parse(llvm::StringRef moduleName, SourcePtr source, ParserFlags flags = NoParserFlags); + ModulePtr parse(llvm::StringRef moduleName, const SourcePtr &source, ParserFlags flags = NoParserFlags); - ExprPtr parseExpr(SourcePtr source, unsigned offset, size_t length); + ExprPtr parseExpr(const SourcePtr &source, unsigned offset, size_t length); - ExprListPtr parseExprList(SourcePtr source, unsigned offset, size_t length); + ExprListPtr parseExprList(const SourcePtr &source, unsigned offset, size_t length); - void parseStatements(SourcePtr source, unsigned offset, size_t length, + void parseStatements(const SourcePtr &source, unsigned offset, size_t length, vector &statements); - void parseTopLevelItems(SourcePtr source, unsigned offset, size_t length, + void parseTopLevelItems(const SourcePtr &source, unsigned offset, size_t length, vector &topLevels, Module *); - ReplItem parseInteractive(SourcePtr source, unsigned offset, size_t length); + ReplItem parseInteractive(const SourcePtr &source, unsigned offset, size_t length); typedef vector (*AddTokensCallback)(); diff --git a/compiler/profiler.cpp b/compiler/profiler.cpp index d473fdb5..56940757 100644 --- a/compiler/profiler.cpp +++ b/compiler/profiler.cpp @@ -1,6 +1,5 @@ #include "clay.hpp" #include "profiler.hpp" -#include "printer.hpp" namespace clay { static llvm::StringMap countsMap; @@ -8,7 +7,7 @@ namespace clay { void incrementCount(const ObjectPtr &obj) { string buf; llvm::raw_string_ostream sout(buf); - sout << obj; + sout << obj->toString(); string s = sout.str(); llvm::StringMap::iterator i = countsMap.find(s); if (i == countsMap.end()) { @@ -22,7 +21,7 @@ namespace clay { vector > counts; llvm::StringMap::iterator cmi = countsMap.begin(); while (cmi != countsMap.end()) { - counts.push_back(vector>::value_type(make_pair(cmi->getValue(), cmi->getKey()))); + counts.emplace_back(cmi->getValue(), cmi->getKey()); ++cmi; } sort(counts.begin(), counts.end()); diff --git a/compiler/refcounted.hpp b/compiler/refcounted.hpp index 3ec490b4..286310a2 100644 --- a/compiler/refcounted.hpp +++ b/compiler/refcounted.hpp @@ -73,7 +73,7 @@ namespace clay { } } - int getRefCount() const { return refCount; } + [[nodiscard]] int getRefCount() const { return refCount; } virtual ~RefCounted() = default; }; diff --git a/compiler/refcounted_ut.cpp b/compiler/refcounted_ut.cpp index 05582979..0d61a641 100644 --- a/compiler/refcounted_ut.cpp +++ b/compiler/refcounted_ut.cpp @@ -1,13 +1,14 @@ -#include "refcounted.hpp" +#include +#include "refcounted.hpp" #include "ut.hpp" namespace clay { CLAY_UNITTEST(RefCounted_copy_constructor) { - Pointer p(new RefCounted); + Pointer p(new RefCounted); UT_ASSERT(p->getRefCount() == 1); - Pointer p2(new RefCounted(*p)); + Pointer p2(new RefCounted(*p)); UT_ASSERT(p->getRefCount() == 1); UT_ASSERT(p2->getRefCount() == 1); } diff --git a/compiler/types.cpp b/compiler/types.cpp index 055c45e9..ba7e4f06 100644 --- a/compiler/types.cpp +++ b/compiler/types.cpp @@ -250,7 +250,7 @@ namespace clay { TypePtr cCodePointerType(CallingConv callingConv, llvm::ArrayRef argTypes, bool hasVarArgs, - TypePtr returnType) { + const TypePtr& returnType) { unsigned h = unsigned(callingConv) * 100; for (unsigned i = 0; i < argTypes.size(); ++i) { h += pointerHash(argTypes[i].ptr()); @@ -277,7 +277,7 @@ namespace clay { return t.ptr(); } - TypePtr arrayType(TypePtr elementType, unsigned size) { + TypePtr arrayType(const TypePtr& elementType, const unsigned size) { unsigned h = pointerHash(elementType.ptr()) + size; h &= unsigned(arrayTypes.size() - 1); vector::iterator i, end; @@ -292,7 +292,7 @@ namespace clay { return t.ptr(); } - TypePtr vecType(TypePtr elementType, unsigned size) { + TypePtr vecType(const TypePtr& elementType, const unsigned size) { if (elementType->typeKind != INTEGER_TYPE && elementType->typeKind != FLOAT_TYPE) error("Vec element type must be an integer or float type"); unsigned h = pointerHash(elementType.ptr()) + size; @@ -329,7 +329,7 @@ namespace clay { return t.ptr(); } - TypePtr unionType(llvm::ArrayRef memberTypes) { + TypePtr unionType(const llvm::ArrayRef memberTypes) { unsigned h = 0; TypePtr const *mi, *mend; for (mi = memberTypes.begin(), mend = memberTypes.end(); @@ -370,7 +370,7 @@ namespace clay { return t.ptr(); } - TypePtr variantType(VariantDeclPtr variant, llvm::ArrayRef params) { + TypePtr variantType(const VariantDeclPtr& variant, llvm::ArrayRef params) { unsigned h = pointerHash(variant.ptr()); for (unsigned i = 0; i < params.size(); ++i) h += objectHash(params[i]); @@ -388,7 +388,7 @@ namespace clay { return t.ptr(); } - TypePtr staticType(ObjectPtr obj) { + TypePtr staticType(const ObjectPtr& obj) { unsigned h = objectHash(obj); h &= unsigned(staticTypes.size() - 1); vector &bucket = staticTypes[h]; @@ -412,13 +412,13 @@ namespace clay { t->initialized = true; } - TypePtr enumType(EnumDeclPtr enumeration) { + TypePtr enumType(const EnumDeclPtr& enumeration) { if (!enumeration->type) enumeration->type = new EnumType(enumeration); return enumeration->type; } - void initializeNewType(NewTypePtr t) { + void initializeNewType(const NewTypePtr& t) { if (t->newtype->initialized) return; CompileContextPusher pusher(t.ptr()); @@ -426,13 +426,13 @@ namespace clay { t->newtype->initialized = true; } - TypePtr newType(NewTypeDeclPtr newtype) { + TypePtr newType(const NewTypeDeclPtr& newtype) { if (!newtype->type) newtype->type = new NewType(newtype); return newtype->type.ptr(); } - TypePtr newtypeReprType(NewTypePtr t) { + TypePtr newtypeReprType(const NewTypePtr& t) { if (!t->newtype->initialized) initializeNewType(t); return t->newtype->baseType; @@ -640,7 +640,7 @@ namespace clay { setProperty(type, props[i]); } - void initializeRecordFields(RecordTypePtr t) { + void initializeRecordFields(const RecordTypePtr& t) { CompileContextPusher pusher(t.ptr()); assert(!t->fieldsInitialized); @@ -727,7 +727,7 @@ namespace clay { return t->fieldNames; } - llvm::ArrayRef recordFieldTypes(RecordTypePtr t) { + llvm::ArrayRef recordFieldTypes(const RecordTypePtr& t) { if (!t->fieldsInitialized) initializeRecordFields(t); return t->fieldTypes; @@ -743,14 +743,14 @@ namespace clay { // variantMemberTypes, variantReprType, dispatchTagCount // - static TypePtr getVariantReprType(VariantTypePtr t) { + static TypePtr getVariantReprType(const VariantTypePtr& t) { ExprPtr variantReprType = operator_expr_variantReprType(); ExprPtr reprExpr = new Call(variantReprType, new ExprList(new ObjectExpr(t.ptr()))); return evaluateType(reprExpr, new Env()); } - static void initializeVariantType(VariantTypePtr t) { + static void initializeVariantType(const VariantTypePtr& t) { assert(!t->initialized); CompileContextPusher pusher(t.ptr()); @@ -987,7 +987,7 @@ namespace clay { static void defineLLVMType(TypePtr t); - static void makeLLVMType(TypePtr t); + static void makeLLVMType(const TypePtr& t); llvm::PointerType *llvmPointerType(TypePtr t) { if (!t->llType) @@ -1024,7 +1024,7 @@ namespace clay { // llvmType // - static void makeLLVMType(TypePtr t) { + static void makeLLVMType(const TypePtr& t) { if (t->llType == nullptr) { verifyRecursionCorrectness(t); declareLLVMType(t); @@ -1034,7 +1034,7 @@ namespace clay { } } - llvm::Type *llvmType(TypePtr t) { + llvm::Type *llvmType(const TypePtr& t) { makeLLVMType(t); return t->llType; @@ -1050,7 +1050,7 @@ namespace clay { return theType; } - llvm::DIType llvmTypeDebugInfo(TypePtr t) { + llvm::DIType llvmTypeDebugInfo(const TypePtr& t) { if (t->llType == nullptr) declareLLVMType(t); diff --git a/compiler/ut.hpp b/compiler/ut.hpp index 51e01da7..bbb6cb11 100644 --- a/compiler/ut.hpp +++ b/compiler/ut.hpp @@ -1,5 +1,7 @@ #pragma once +#include + namespace clay { typedef void (*TestFunc)(); @@ -15,7 +17,8 @@ namespace clay { static TestRegistrator_ ## NAME testRegistrator_ ## NAME; \ void NAME ## _testImpl() - struct AssertionError { + struct AssertionError : std::runtime_error { + AssertionError() : std::runtime_error("AssertionError") {} }; #define UT_FAIL() do { \ diff --git a/compiler/ut_main.cpp b/compiler/ut_main.cpp index 6ba1cfb8..f91ae7aa 100644 --- a/compiler/ut_main.cpp +++ b/compiler/ut_main.cpp @@ -1,36 +1,35 @@ +#include #include #include "ut.hpp" #include "parachute.hpp" -using namespace std; - namespace clay { struct Test { const char *name; TestFunc func; }; - static vector *tests; + static std::vector *tests; void register_test(const char *name, const TestFunc func) { if (tests == nullptr) { - tests = new vector; + tests = new std::vector; } - tests->push_back(Test()); + tests->emplace_back(); tests->back().name = name; tests->back().func = func; } int real_main(int argc, char **argv, char const *const *envp) { for (const auto test : *tests) { - printf("%s...\n", test.name); + std::cout << test.name << "...\n"; try { test.func(); - printf("%s OK\n", test.name); + std::cout << test.name << " OK\n"; } catch (const AssertionError &) { - printf("%s FAILED\n", test.name); + std::cout << test.name << " FAILED\n"; } } return 0;