diff options
Diffstat (limited to 'dev/LibCompiler/src/Frontend/CPlusPlusCompilerAMD64.cc')
| -rw-r--r-- | dev/LibCompiler/src/Frontend/CPlusPlusCompilerAMD64.cc | 887 |
1 files changed, 887 insertions, 0 deletions
diff --git a/dev/LibCompiler/src/Frontend/CPlusPlusCompilerAMD64.cc b/dev/LibCompiler/src/Frontend/CPlusPlusCompilerAMD64.cc new file mode 100644 index 0000000..217f86b --- /dev/null +++ b/dev/LibCompiler/src/Frontend/CPlusPlusCompilerAMD64.cc @@ -0,0 +1,887 @@ +/* + * ======================================================== + * + * cxxdrv + * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. + * + * ======================================================== + */ + +/// BUGS: 1 + +#include "LibCompiler/Defines.h" +#define kPrintF printf + +#define kExitOK (EXIT_SUCCESS) +#define kExitNO (EXIT_FAILURE) + +// extern_segment, @autodelete { ... }, fn foo() -> auto { ... } + +#include <LibCompiler/Backend/X64.h> +#include <LibCompiler/Frontend.h> +#include <LibCompiler/UUID.h> +#include <LibCompiler/Util/LCClUtils.h> + +/* NeKernel C++ Compiler Driver */ +/* This is part of the LibCompiler. */ +/* (c) Amlal El Mahrouss */ + +/// @author EL Mahrouss Amlal (amlal@nekernel.org) +/// @file CPlusPlusCompilerAMD64.cxx +/// @brief Optimized C++ Compiler Driver. +/// @todo Throw error for scoped inside scoped variables when they get referenced outside. +/// @todo Add class/struct/enum support. + +/////////////////////// + +// ANSI ESCAPE CODES // + +/////////////////////// + +#define kBlank "\e[0;30m" +#define kRed "\e[0;31m" +#define kWhite "\e[0;97m" + +///////////////////////////////////// + +// INTERNALS OF THE C++ COMPILER + +///////////////////////////////////// + +/// @internal +namespace Detail { +std::filesystem::path expand_home(const std::filesystem::path& p) { + if (!p.empty() && p.string()[0] == '~') { + const char* home = std::getenv("HOME"); // For Unix-like systems + + if (!home) { + home = std::getenv("USERPROFILE"); // For Windows + } + + if (home) { + return std::filesystem::path(home) / p.relative_path().string().substr(1); + } else { + throw std::runtime_error("Home directory not found in environment variables"); + } + } + return p; +} + +struct CompilerRegisterMap final { + LibCompiler::STLString fName; + LibCompiler::STLString fReg; +}; + +/// \brief Offset based struct/class +struct CompilerStructMap final { + LibCompiler::STLString fName; + LibCompiler::STLString fReg; + std::vector<std::pair<UInt32, LibCompiler::STLString>> fOffsets; +}; + +/// \brief Compiler state structure. +struct CompilerState final { + std::vector<CompilerRegisterMap> fStackMapVector; + std::vector<CompilerStructMap> fStructMapVector; + LibCompiler::STLString fLastFile; + LibCompiler::STLString fLastError; +}; +} // namespace Detail + +static Detail::CompilerState kState; + +static Int32 kOnClassScope = 0; + +///////////////////////////////////////////////////////////////////////////////////////// + +// Target architecture. +static Int32 kMachine = LibCompiler::AssemblyFactory::kArchAMD64; + +///////////////////////////////////////// + +// ARGUMENTS REGISTERS (R8, R15) + +///////////////////////////////////////// + +static std::vector<LibCompiler::CompilerKeyword> kKeywords; + +///////////////////////////////////////// + +// COMPILER PARSING UTILITIES/STATES. + +///////////////////////////////////////// + +static LibCompiler::AssemblyFactory kFactory; +static Boolean kInStruct = false; +static Boolean kOnWhileLoop = false; +static Boolean kOnForLoop = false; +static Boolean kInBraces = false; +static size_t kBracesCount = 0UL; + +/* @brief C++ compiler backend for the NeKernel C++ driver */ +class CompilerFrontendCPlusPlus final LC_COMPILER_FRONTEND { + public: + explicit CompilerFrontendCPlusPlus() = default; + ~CompilerFrontendCPlusPlus() override = default; + + LIBCOMPILER_COPY_DEFAULT(CompilerFrontendCPlusPlus); + + LibCompiler::SyntaxLeafList::SyntaxLeaf Compile(const LibCompiler::STLString text, LibCompiler::STLString file) override; + + const char* Language() override; +}; + +/// @internal compiler variables + +static CompilerFrontendCPlusPlus* kCompilerFrontend = nullptr; + +static std::vector<LibCompiler::STLString> kRegisterMap; + +static std::vector<LibCompiler::STLString> kRegisterList = { + "rbx", "rsi", "r10", "r11", "r12", "r13", "r14", "r15", "xmm12", "xmm13", "xmm14", "xmm15", +}; + +/// @brief The PEF calling convention (caller must save rax, rbp) +/// @note callee must return via **rax**. +static std::vector<LibCompiler::STLString> kRegisterConventionCallList = { + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", +}; + +static std::size_t kFunctionEmbedLevel = 0UL; + +/// detail namespaces + +const char* CompilerFrontendCPlusPlus::Language() { + return "AMD64 C++"; +} + +static std::uintptr_t kOrigin = 0x1000000; +static std::vector<std::pair<LibCompiler::STLString, std::uintptr_t>> kOriginMap; + +///////////////////////////////////////////////////////////////////////////////////////// + +/// @name Compile +/// @brief Generate assembly from a C++ source. + +///////////////////////////////////////////////////////////////////////////////////////// + +LibCompiler::SyntaxLeafList::SyntaxLeaf CompilerFrontendCPlusPlus::Compile( + LibCompiler::STLString text, LibCompiler::STLString file) { + LibCompiler::SyntaxLeafList::SyntaxLeaf syntax_tree; + + if (text.length() < 1) return syntax_tree; + + std::size_t index = 0UL; + std::vector<std::pair<LibCompiler::CompilerKeyword, std::size_t>> keywords_list; + + for (auto& keyword : kKeywords) { + if (text.find(keyword.keyword_name) != std::string::npos) { + switch (keyword.keyword_kind) { + case LibCompiler::kKeywordKindCommentInline: { + break; + } + default: + break; + } + + std::size_t pos = text.find(keyword.keyword_name); + if (pos == std::string::npos) continue; + + // Safe guard: can't go before start of string + if (pos > 0 && text[pos - 1] == '+' && + keyword.keyword_kind == LibCompiler::kKeywordKindVariableAssign) + continue; + + if (pos > 0 && text[pos - 1] == '-' && + keyword.keyword_kind == LibCompiler::kKeywordKindVariableAssign) + continue; + + // Safe guard: don't go out of range + if ((pos + keyword.keyword_name.size()) < text.size() && + text[pos + keyword.keyword_name.size()] == '=' && + keyword.keyword_kind == LibCompiler::kKeywordKindVariableAssign) + continue; + + keywords_list.emplace_back(std::make_pair(keyword, index)); + ++index; + } + } + + for (auto& keyword : keywords_list) { + if (text.find(keyword.first.keyword_name) == LibCompiler::STLString::npos) continue; + + switch (keyword.first.keyword_kind) { + case LibCompiler::KeywordKind::kKeywordKindClass: { + ++kOnClassScope; + break; + } + case LibCompiler::KeywordKind::kKeywordKindIf: { + std::size_t keywordPos = text.find(keyword.first.keyword_name); + std::size_t openParen = text.find("(", keywordPos); + std::size_t closeParen = text.find(")", openParen); + + if (keywordPos == LibCompiler::STLString::npos || + openParen == LibCompiler::STLString::npos || + closeParen == LibCompiler::STLString::npos || closeParen <= openParen) { + Detail::print_error("Malformed if expression: " + text, file); + break; + } + + auto expr = text.substr(openParen + 1, closeParen - openParen - 1); + + if (expr.find(">=") != LibCompiler::STLString::npos) { + auto left = text.substr( + text.find(keyword.first.keyword_name) + keyword.first.keyword_name.size() + 2, + expr.find("<=") + strlen("<=")); + auto right = text.substr(expr.find(">=") + strlen(">="), text.find(")") - 1); + + size_t i = right.size() - 1; + + if (i < 1) break; + + try { + while (!std::isalnum(right[i])) { + right.erase(i, 1); + --i; + } + + right.erase(0, i); + } catch (...) { + right.erase(0, i); + } + + i = left.size() - 1; + try { + while (!std::isalnum(left[i])) { + left.erase(i, 1); + --i; + } + + left.erase(0, i); + } catch (...) { + left.erase(0, i); + } + + if (!isdigit(left[0]) || !isdigit(right[0])) { + auto indexRight = 0UL; + + auto& valueOfVar = !isdigit(left[0]) ? left : right; + + if (!valueOfVar.empty()) { + for (auto pairRight : kRegisterMap) { + ++indexRight; + + if (pairRight != valueOfVar) { + auto& valueOfVarOpposite = isdigit(left[0]) ? left : right; + + syntax_tree.fUserValue += + "mov " + kRegisterList[indexRight + 1] + ", " + valueOfVarOpposite + "\n"; + syntax_tree.fUserValue += "cmp " + kRegisterList[kRegisterMap.size() - 1] + "," + + kRegisterList[indexRight + 1] + "\n"; + + goto done_iterarting_on_if; + } + + auto& valueOfVarOpposite = isdigit(left[0]) ? left : right; + + syntax_tree.fUserValue += + "mov " + kRegisterList[indexRight + 1] + ", " + valueOfVarOpposite + "\n"; + syntax_tree.fUserValue += "cmp " + kRegisterList[kRegisterMap.size() - 1] + ", " + + kRegisterList[indexRight + 1] + "\n"; + + break; + } + } + } + + done_iterarting_on_if: + + LibCompiler::STLString fnName = text; + fnName.erase(fnName.find(keyword.first.keyword_name)); + + for (auto& ch : fnName) { + if (ch == ' ') ch = '_'; + } + + syntax_tree.fUserValue += + "jge __OFFSET_ON_TRUE_LC\nsegment .code64 __OFFSET_ON_TRUE_LC:\n"; + } + + break; + } + case LibCompiler::KeywordKind::kKeywordKindFunctionStart: { + for (auto& ch : text) { + if (isdigit(ch)) { + goto dont_accept; + } + } + + goto accept; + + dont_accept: + break; + + accept: + LibCompiler::STLString fnName = text; + size_t indexFnName = 0; + + // this one is for the type. + for (auto& ch : text) { + ++indexFnName; + + if (ch == '\t') break; + if (ch == ' ') break; + } + + fnName = text.substr(indexFnName); + + if (text.find("return ") != LibCompiler::STLString::npos) { + text.erase(0, text.find("return ")); + break; + } + + if (text.ends_with(";") && text.find("return") == LibCompiler::STLString::npos) + goto lc_write_assembly; + else if (text.size() <= indexFnName) + Detail::print_error("Invalid function name: " + fnName, file); + + indexFnName = 0; + + for (auto& ch : fnName) { + if (ch == ' ' || ch == '\t') { + if (fnName[indexFnName - 1] != ')') + Detail::print_error("Invalid function name: " + fnName, file); + } + + ++indexFnName; + } + + if (fnName.find("(") != LibCompiler::STLString::npos) { + fnName.erase(fnName.find("(")); + } + + syntax_tree.fUserValue = "public_segment .code64 __LIBCOMPILER_" + fnName + "\n"; + ++kFunctionEmbedLevel; + + kOriginMap.push_back({"__LIBCOMPILER_" + fnName, kOrigin}); + + break; + + lc_write_assembly: + auto it = + std::find_if(kOriginMap.begin(), kOriginMap.end(), + [&fnName](std::pair<LibCompiler::STLString, std::uintptr_t> pair) -> bool { + return fnName == pair.first; + }); + + if (it != kOriginMap.end()) { + std::stringstream ss; + ss << std::hex << it->second; + + syntax_tree.fUserValue = "jmp " + ss.str() + "\n"; + kOrigin += 1UL; + } + } + case LibCompiler::KeywordKind::kKeywordKindFunctionEnd: { + if (kOnClassScope) --kOnClassScope; + + if (text.ends_with(";")) break; + + --kFunctionEmbedLevel; + + if (kRegisterMap.size() > kRegisterList.size()) { + --kFunctionEmbedLevel; + } + + if (kFunctionEmbedLevel < 1) kRegisterMap.clear(); + + break; + } + case LibCompiler::KeywordKind::kKeywordKindEndInstr: + case LibCompiler::KeywordKind::kKeywordKindVariableInc: + case LibCompiler::KeywordKind::kKeywordKindVariableDec: + case LibCompiler::KeywordKind::kKeywordKindVariableAssign: { + LibCompiler::STLString valueOfVar = ""; + + if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc) { + valueOfVar = text.substr(text.find("+=") + 2); + } else if (keyword.first.keyword_kind == + LibCompiler::KeywordKind::kKeywordKindVariableDec) { + valueOfVar = text.substr(text.find("-=") + 2); + } else if (keyword.first.keyword_kind == + LibCompiler::KeywordKind::kKeywordKindVariableAssign) { + valueOfVar = text.substr(text.find("=") + 1); + } else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr) { + break; + } + + while (valueOfVar.find(";") != LibCompiler::STLString::npos && + keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindEndInstr) { + valueOfVar.erase(valueOfVar.find(";")); + } + + LibCompiler::STLString varName = text; + + if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc) { + varName.erase(varName.find("+=")); + } else if (keyword.first.keyword_kind == + LibCompiler::KeywordKind::kKeywordKindVariableDec) { + varName.erase(varName.find("-=")); + } else if (keyword.first.keyword_kind == + LibCompiler::KeywordKind::kKeywordKindVariableAssign) { + varName.erase(varName.find("=")); + } else if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr) { + varName.erase(varName.find(";")); + } + + static Boolean typeFound = false; + + for (auto& keyword : kKeywords) { + if (keyword.keyword_kind == LibCompiler::kKeywordKindType) { + if (text.find(keyword.keyword_name) != LibCompiler::STLString::npos) { + if (text[text.find(keyword.keyword_name)] == ' ') { + typeFound = false; + continue; + } + + typeFound = true; + } + } + } + + LibCompiler::STLString instr = "mov "; + + std::vector<LibCompiler::STLString> newVars; + + if (typeFound && + keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindVariableInc && + keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindVariableDec) { + if (kRegisterMap.size() > kRegisterList.size()) { + ++kFunctionEmbedLevel; + } + + while (varName.find(" ") != LibCompiler::STLString::npos) { + varName.erase(varName.find(" "), 1); + } + + while (varName.find("\t") != LibCompiler::STLString::npos) { + varName.erase(varName.find("\t"), 1); + } + + for (size_t i = 0; !isalnum(valueOfVar[i]); i++) { + if (i > valueOfVar.size()) break; + + valueOfVar.erase(i, 1); + } + + constexpr auto kTrueVal = "true"; + constexpr auto kFalseVal = "false"; + + if (valueOfVar == kTrueVal) { + valueOfVar = "1"; + } else if (valueOfVar == kFalseVal) { + valueOfVar = "0"; + } + + std::size_t indexRight = 0UL; + + for (auto pairRight : kRegisterMap) { + ++indexRight; + + if (pairRight != valueOfVar) { + if (valueOfVar[0] == '\"') { + syntax_tree.fUserValue = "segment .data64 __LIBCOMPILER_LOCAL_VAR_" + varName + + ": db " + valueOfVar + ", 0\n\n"; + syntax_tree.fUserValue += instr + kRegisterList[kRegisterMap.size() - 1] + ", " + + "__LIBCOMPILER_LOCAL_VAR_" + varName + "\n"; + kOrigin += 1UL; + } else { + syntax_tree.fUserValue = + instr + kRegisterList[kRegisterMap.size() - 1] + ", " + valueOfVar + "\n"; + kOrigin += 1UL; + } + + goto done; + } + } + + if (((int) indexRight - 1) < 0) { + if (valueOfVar[0] == '\"') { + syntax_tree.fUserValue = "segment .data64 __LIBCOMPILER_LOCAL_VAR_" + varName + + ": db " + valueOfVar + ", 0\n"; + syntax_tree.fUserValue += instr + kRegisterList[kRegisterMap.size()] + ", " + + "__LIBCOMPILER_LOCAL_VAR_" + varName + "\n"; + kOrigin += 1UL; + } else { + syntax_tree.fUserValue = + instr + kRegisterList[kRegisterMap.size()] + ", " + valueOfVar + "\n"; + kOrigin += 1UL; + } + + goto done; + } + + if (valueOfVar[0] != '\"' && valueOfVar[0] != '\'' && !isdigit(valueOfVar[0])) { + for (auto pair : kRegisterMap) { + if (pair == valueOfVar) goto done; + } + + Detail::print_error("Variable not declared: " + varName, file); + break; + } + + done: + for (auto& keyword : kKeywords) { + if (keyword.keyword_kind == LibCompiler::kKeywordKindType && + varName.find(keyword.keyword_name) != LibCompiler::STLString::npos) { + varName.erase(varName.find(keyword.keyword_name), keyword.keyword_name.size()); + break; + } + } + + newVars.push_back(varName); + + break; + } + + kRegisterMap.insert(kRegisterMap.end(), newVars.begin(), newVars.end()); + + if (keyword.second > 0 && + kKeywords[keyword.second - 1].keyword_kind == LibCompiler::kKeywordKindType || + kKeywords[keyword.second - 1].keyword_kind == LibCompiler::kKeywordKindTypePtr) { + syntax_tree.fUserValue = "\n"; + continue; + } + + if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindEndInstr) { + syntax_tree.fUserValue = "\n"; + continue; + } + + if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc) { + instr = "add "; + } else if (keyword.first.keyword_kind == + LibCompiler::KeywordKind::kKeywordKindVariableDec) { + instr = "sub "; + } + + LibCompiler::STLString varErrCpy = varName; + + while (varName.find(" ") != LibCompiler::STLString::npos) { + varName.erase(varName.find(" "), 1); + } + + while (varName.find("\t") != LibCompiler::STLString::npos) { + varName.erase(varName.find("\t"), 1); + } + + std::size_t indxReg = 0UL; + + for (size_t i = 0; !isalnum(valueOfVar[i]); i++) { + if (i > valueOfVar.size()) break; + + valueOfVar.erase(i, 1); + } + + while (valueOfVar.find(" ") != LibCompiler::STLString::npos) { + valueOfVar.erase(valueOfVar.find(" "), 1); + } + + while (valueOfVar.find("\t") != LibCompiler::STLString::npos) { + valueOfVar.erase(valueOfVar.find("\t"), 1); + } + + constexpr auto kTrueVal = "true"; + constexpr auto kFalseVal = "false"; + + /// interpet boolean values, since we're on C++ + + if (valueOfVar == kTrueVal) { + valueOfVar = "1"; + } else if (valueOfVar == kFalseVal) { + valueOfVar = "0"; + } + + for (auto pair : kRegisterMap) { + ++indxReg; + + if (pair != varName) continue; + + std::size_t indexRight = 0ul; + + for (auto pairRight : kRegisterMap) { + ++indexRight; + + if (pairRight != varName) { + syntax_tree.fUserValue = + instr + kRegisterList[kRegisterMap.size()] + ", " + valueOfVar + "\n"; + kOrigin += 1UL; + continue; + } + + syntax_tree.fUserValue = + instr + kRegisterList[indexRight - 1] + ", " + valueOfVar + "\n"; + kOrigin += 1UL; + break; + } + + newVars.push_back(varName); + break; + } + + if (syntax_tree.fUserValue.empty()) { + Detail::print_error("Variable not declared: " + varName, file); + } + + kRegisterMap.insert(kRegisterMap.end(), newVars.begin(), newVars.end()); + + break; + } + case LibCompiler::KeywordKind::kKeywordKindReturn: { + try { + auto pos = text.find("return") + strlen("return") + 1; + LibCompiler::STLString subText = text.substr(pos); + subText = subText.erase(subText.find(";")); + size_t indxReg = 0UL; + + if (subText[0] != '\"' && subText[0] != '\'') { + if (!isdigit(subText[0])) { + for (auto pair : kRegisterMap) { + ++indxReg; + + if (pair != subText) continue; + + syntax_tree.fUserValue = "mov rax, " + kRegisterList[indxReg - 1] + "\nret\n"; + kOrigin += 1UL; + + break; + } + } else { + syntax_tree.fUserValue = "mov rax, " + subText + "\nret\n"; + kOrigin += 1UL; + + break; + } + } else { + syntax_tree.fUserValue = "__LIBCOMPILER_LOCAL_RETURN_STRING: db " + subText + + ", 0\nmov rcx, __LIBCOMPILER_LOCAL_RETURN_STRING\n"; + syntax_tree.fUserValue += "mov rax, rcx\nret\n"; + kOrigin += 1UL; + + break; + } + + if (syntax_tree.fUserValue.empty()) { + if (subText.find("(") != LibCompiler::STLString::npos) { + subText.erase(subText.find("(")); + + auto it = std::find_if( + kOriginMap.begin(), kOriginMap.end(), + [&subText](std::pair<LibCompiler::STLString, std::uintptr_t> pair) -> bool { + return pair.first.find(subText) != LibCompiler::STLString::npos; + }); + + if (it == kOriginMap.end()) + Detail::print_error("Invalid return value: " + subText, file); + + std::stringstream ss; + ss << it->second; + + syntax_tree.fUserValue = "jmp " + ss.str() + "\nret\n"; + kOrigin += 1UL; + break; + } + } + + break; + } catch (...) { + syntax_tree.fUserValue = "ret\n"; + kOrigin += 1UL; + } + } + default: { + continue; + } + } + } + + return syntax_tree; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +/** + * @brief C++ assembler class. + */ + +///////////////////////////////////////////////////////////////////////////////////////// + +class AssemblyCPlusPlusInterface final LC_ASSEMBLY_INTERFACE { + public: + explicit AssemblyCPlusPlusInterface() = default; + ~AssemblyCPlusPlusInterface() override = default; + + LIBCOMPILER_COPY_DEFAULT(AssemblyCPlusPlusInterface); + + UInt32 Arch() noexcept override { return LibCompiler::AssemblyFactory::kArchAMD64; } + + Int32 CompileToFormat(LibCompiler::STLString src, Int32 arch) override { + if (kCompilerFrontend == nullptr) return kExitNO; + + LibCompiler::STLString dest = src; + dest += ".pp.masm"; + + std::ofstream out_fp(dest); + std::ifstream src_fp = std::ifstream(src + ".pp"); + + LibCompiler::STLString line_source; + + while (std::getline(src_fp, line_source)) { + out_fp << kCompilerFrontend->Compile(line_source, src).fUserValue; + } + + return kExitOK; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////////////////// + +#define kExtListCxx \ + { ".cpp", ".cxx", ".cc", ".c++", ".cp" } + +LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) { + Boolean skip = false; + + kKeywords.emplace_back("if", LibCompiler::kKeywordKindIf); + kKeywords.emplace_back("else", LibCompiler::kKeywordKindElse); + kKeywords.emplace_back("else if", LibCompiler::kKeywordKindElseIf); + + kKeywords.emplace_back("class", LibCompiler::kKeywordKindClass); + kKeywords.emplace_back("struct", LibCompiler::kKeywordKindClass); + kKeywords.emplace_back("namespace", LibCompiler::kKeywordKindNamespace); + kKeywords.emplace_back("typedef", LibCompiler::kKeywordKindTypedef); + kKeywords.emplace_back("using", LibCompiler::kKeywordKindTypedef); + kKeywords.emplace_back("{", LibCompiler::kKeywordKindBodyStart); + kKeywords.emplace_back("}", LibCompiler::kKeywordKindBodyEnd); + kKeywords.emplace_back("auto", LibCompiler::kKeywordKindVariable); + kKeywords.emplace_back("int", LibCompiler::kKeywordKindType); + kKeywords.emplace_back("bool", LibCompiler::kKeywordKindType); + kKeywords.emplace_back("unsigned", LibCompiler::kKeywordKindType); + kKeywords.emplace_back("short", LibCompiler::kKeywordKindType); + kKeywords.emplace_back("char", LibCompiler::kKeywordKindType); + kKeywords.emplace_back("long", LibCompiler::kKeywordKindType); + kKeywords.emplace_back("float", LibCompiler::kKeywordKindType); + kKeywords.emplace_back("double", LibCompiler::kKeywordKindType); + kKeywords.emplace_back("void", LibCompiler::kKeywordKindType); + + kKeywords.emplace_back("auto*", LibCompiler::kKeywordKindVariablePtr); + kKeywords.emplace_back("int*", LibCompiler::kKeywordKindTypePtr); + kKeywords.emplace_back("bool*", LibCompiler::kKeywordKindTypePtr); + kKeywords.emplace_back("unsigned*", LibCompiler::kKeywordKindTypePtr); + kKeywords.emplace_back("short*", LibCompiler::kKeywordKindTypePtr); + kKeywords.emplace_back("char*", LibCompiler::kKeywordKindTypePtr); + kKeywords.emplace_back("long*", LibCompiler::kKeywordKindTypePtr); + kKeywords.emplace_back("float*", LibCompiler::kKeywordKindTypePtr); + kKeywords.emplace_back("double*", LibCompiler::kKeywordKindTypePtr); + kKeywords.emplace_back("void*", LibCompiler::kKeywordKindTypePtr); + + kKeywords.emplace_back("(", LibCompiler::kKeywordKindFunctionStart); + kKeywords.emplace_back(")", LibCompiler::kKeywordKindFunctionEnd); + kKeywords.emplace_back("=", LibCompiler::kKeywordKindVariableAssign); + kKeywords.emplace_back("+=", LibCompiler::kKeywordKindVariableInc); + kKeywords.emplace_back("-=", LibCompiler::kKeywordKindVariableDec); + kKeywords.emplace_back("const", LibCompiler::kKeywordKindConstant); + kKeywords.emplace_back("*", LibCompiler::kKeywordKindPtr); + kKeywords.emplace_back("->", LibCompiler::kKeywordKindPtrAccess); + kKeywords.emplace_back(".", LibCompiler::kKeywordKindAccess); + kKeywords.emplace_back(",", LibCompiler::kKeywordKindArgSeparator); + kKeywords.emplace_back(";", LibCompiler::kKeywordKindEndInstr); + kKeywords.emplace_back(":", LibCompiler::kKeywordKindSpecifier); + kKeywords.emplace_back("public:", LibCompiler::kKeywordKindSpecifier); + kKeywords.emplace_back("private:", LibCompiler::kKeywordKindSpecifier); + kKeywords.emplace_back("protected:", LibCompiler::kKeywordKindSpecifier); + kKeywords.emplace_back("final", LibCompiler::kKeywordKindSpecifier); + kKeywords.emplace_back("return", LibCompiler::kKeywordKindReturn); + kKeywords.emplace_back("/*", LibCompiler::kKeywordKindCommentMultiLineStart); + kKeywords.emplace_back("*/", LibCompiler::kKeywordKindCommentMultiLineEnd); + kKeywords.emplace_back("//", LibCompiler::kKeywordKindCommentInline); + kKeywords.emplace_back("==", LibCompiler::kKeywordKindEq); + kKeywords.emplace_back("!=", LibCompiler::kKeywordKindNotEq); + kKeywords.emplace_back(">=", LibCompiler::kKeywordKindGreaterEq); + kKeywords.emplace_back("<=", LibCompiler::kKeywordKindLessEq); + + kErrorLimit = 0; + + kCompilerFrontend = new CompilerFrontendCPlusPlus(); + kFactory.Mount(new AssemblyCPlusPlusInterface()); + + ::signal(SIGSEGV, Detail::drvi_crash_handler); + + for (auto index = 1UL; index < argc; ++index) { + if (!argv[index]) break; + + if (argv[index][0] == '-') { + if (skip) { + skip = false; + continue; + } + + if (strcmp(argv[index], "-cxx-verbose") == 0) { + kVerbose = true; + + continue; + } + + if (strcmp(argv[index], "-cxx-dialect") == 0) { + if (kCompilerFrontend) std::cout << kCompilerFrontend->Language() << "\n"; + + return LIBCOMPILER_SUCCESS; + } + + if (strcmp(argv[index], "-cxx-max-err") == 0) { + try { + kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); + } + // catch anything here + catch (...) { + kErrorLimit = 0; + } + + skip = true; + + continue; + } + + LibCompiler::STLString err = "Unknown option: "; + err += argv[index]; + + Detail::print_error(err, "cxxdrv"); + + continue; + } + + LibCompiler::STLString argv_i = argv[index]; + + std::vector<LibCompiler::STLString> exts = kExtListCxx; + + for (LibCompiler::STLString ext : exts) { + if (argv_i.ends_with(ext)) { + if (kFactory.Compile(argv_i, kMachine) != kExitOK) { + return LIBCOMPILER_INVALID_DATA; + } + + break; + } + } + } + + kFactory.Unmount(); + + return LIBCOMPILER_SUCCESS; +} + +// +// Last rev 23-5-25 +// |
