diff options
| author | Amlal El Mahrouss <amlal@nekernel.org> | 2025-05-29 10:48:12 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-05-29 10:48:12 +0200 |
| commit | 433bb5ef102b2bfa0049468be00d63011da8b973 (patch) | |
| tree | e0893a30710477045a5bb085cb7a27aada425c14 /dev/LibCompiler/src | |
| parent | 1ddeab9a4426abd781a5066ba79af2ba64de11d9 (diff) | |
| parent | 756ee7f8dc954e27350fe5bdfbaa83b9f69780c8 (diff) | |
Merge pull request #6 from nekernel-org/dev
0.0.2e3
Diffstat (limited to 'dev/LibCompiler/src')
| -rw-r--r-- | dev/LibCompiler/src/Backend/Assembler32x0.cc (renamed from dev/LibCompiler/src/Assembler32x0.cc) | 24 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Backend/Assembler64x0.cc (renamed from dev/LibCompiler/src/Assembler64x0.cc) | 13 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Backend/AssemblerAMD64.cc (renamed from dev/LibCompiler/src/AssemblerAMD64.cc) | 227 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Backend/AssemblerARM64.cc (renamed from dev/LibCompiler/src/AssemblerARM64.cc) | 15 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Backend/AssemblerPowerPC.cc (renamed from dev/LibCompiler/src/AssemblerPowerPC.cc) | 15 | ||||
| -rw-r--r-- | dev/LibCompiler/src/BasicString.cc (renamed from dev/LibCompiler/src/StringView.cc) | 34 | ||||
| -rw-r--r-- | dev/LibCompiler/src/CCompiler64x0.cc | 1288 | ||||
| -rw-r--r-- | dev/LibCompiler/src/CCompilerARM64.cc | 1286 | ||||
| -rw-r--r-- | dev/LibCompiler/src/CCompilerPower64.cc | 1305 | ||||
| -rw-r--r-- | dev/LibCompiler/src/CodeGen.cc (renamed from dev/LibCompiler/src/AssemblyFactory+AssemblyInterface.cc) | 17 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Frontend.cc | 51 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Frontend/CompilerCPlusPlusAMD64.cc (renamed from dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc) | 433 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Linkers/DynamicLinkerPEF.cc (renamed from dev/LibCompiler/src/DynamicLinkerPEF.cc) | 253 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Macro/CPlusPlusCompilerPreProcessor.cc (renamed from dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc) | 139 |
14 files changed, 633 insertions, 4467 deletions
diff --git a/dev/LibCompiler/src/Assembler32x0.cc b/dev/LibCompiler/src/Backend/Assembler32x0.cc index ac24946..b7ff321 100644 --- a/dev/LibCompiler/src/Assembler32x0.cc +++ b/dev/LibCompiler/src/Backend/Assembler32x0.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + Copyright (C) 2024-2025 Amlal EL Mahrouss, all rights reserved ------------------------------------------- */ @@ -17,26 +17,15 @@ ///////////////////////////////////////////////////////////////////////////////////////// +#ifndef __ASM_NEED_32x0__ #define __ASM_NEED_32x0__ 1 +#endif #include <LibCompiler/AE.h> #include <LibCompiler/Backend/32x0.h> +#include <LibCompiler/Frontend.h> #include <LibCompiler/PEF.h> -#include <LibCompiler/Parser.h> - -///////////////////// - -// ANSI ESCAPE CODES - -///////////////////// - -#define kBlank "\e[0;30m" -#define kRed "\e[0;31m" -#define kWhite "\e[0;97m" -#define kYellow "\e[0;33m" - -#define kStdOut (std::cout << kWhite) -#define kStdErr (std::cout << kRed) +#include <LibCompiler/Util/CompilerUtils.h> ///////////////////////////////////////////////////////////////////////////////////////// @@ -45,5 +34,6 @@ ///////////////////////////////////////////////////////////////////////////////////////// LIBCOMPILER_MODULE(NEAssemblerMain32000) { - return 0; + LibCompiler::install_signal(SIGSEGV, Detail::drvi_crash_handler); + return EXIT_SUCCESS; } diff --git a/dev/LibCompiler/src/Assembler64x0.cc b/dev/LibCompiler/src/Backend/Assembler64x0.cc index 8483e9e..765bea2 100644 --- a/dev/LibCompiler/src/Assembler64x0.cc +++ b/dev/LibCompiler/src/Backend/Assembler64x0.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + Copyright (C) 2024-2025 Amlal EL Mahrouss, all rights reserved ------------------------------------------- */ @@ -17,13 +17,15 @@ ///////////////////////////////////////////////////////////////////////////////////////// +#ifndef __ASM_NEED_64x0__ #define __ASM_NEED_64x0__ 1 +#endif #include <LibCompiler/AE.h> #include <LibCompiler/Backend/64x0.h> -#include <LibCompiler/Detail/ClUtils.h> +#include <LibCompiler/Frontend.h> #include <LibCompiler/PEF.h> -#include <LibCompiler/Parser.h> +#include <LibCompiler/Util/CompilerUtils.h> #include <algorithm> #include <filesystem> #include <fstream> @@ -38,8 +40,7 @@ static char kOutputArch = LibCompiler::kPefArch64000; -/// @note The 64x0 is VLSIW, so we need to jump to 4 bytes. -constexpr auto k64x0IPAlignment = 0x4U; +constexpr auto k64x0IPAlignment = 0x1U; static std::size_t kCounter = 1UL; @@ -67,7 +68,7 @@ static bool asm_read_attributes(std::string line); ///////////////////////////////////////////////////////////////////////////////////////// LIBCOMPILER_MODULE(AssemblerMain64x0) { - ::signal(SIGSEGV, Detail::segfault_handler); + LibCompiler::install_signal(SIGSEGV, Detail::drvi_crash_handler); for (size_t i = 1; i < argc; ++i) { if (argv[i][0] == '-') { diff --git a/dev/LibCompiler/src/AssemblerAMD64.cc b/dev/LibCompiler/src/Backend/AssemblerAMD64.cc index 5e9a7cd..6551743 100644 --- a/dev/LibCompiler/src/AssemblerAMD64.cc +++ b/dev/LibCompiler/src/Backend/AssemblerAMD64.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + Copyright (C) 2024-2025 Amlal EL Mahrouss, all rights reserved ------------------------------------------- */ @@ -21,15 +21,17 @@ ///////////////////////////////////////////////////////////////////////////////////////// +#ifndef __ASM_NEED_AMD64__ #define __ASM_NEED_AMD64__ 1 +#endif #define kAssemblerPragmaSymStr "#" #define kAssemblerPragmaSym '#' #include <LibCompiler/AE.h> -#include <LibCompiler/Backend/Amd64.h> +#include <LibCompiler/Backend/X64.h> +#include <LibCompiler/Frontend.h> #include <LibCompiler/PEF.h> -#include <LibCompiler/Parser.h> #include <algorithm> #include <cstdlib> #include <filesystem> @@ -48,9 +50,6 @@ #define kWhite "\e[0;97m" #define kYellow "\e[0;33m" -#define kStdOut (std::cout << kWhite) -#define kStdErr (std::cout << kRed) - static char kOutputArch = LibCompiler::kPefArchAMD64; constexpr auto kIPAlignement = 0x1U; @@ -77,7 +76,7 @@ static const std::string kUndefinedSymbol = ":UndefinedSymbol:"; // \brief forward decl. static bool asm_read_attributes(std::string line); -#include <LibCompiler/Detail/AsmUtils.h> +#include <LibCompiler/Util/AsmUtils.h> ///////////////////////////////////////////////////////////////////////////////////////// @@ -88,7 +87,7 @@ static bool asm_read_attributes(std::string line); LIBCOMPILER_MODULE(AssemblerMainAMD64) { //////////////// CPU OPCODES BEGIN //////////////// - ::signal(SIGSEGV, Detail::segfault_handler); + LibCompiler::install_signal(SIGSEGV, Detail::drvi_crash_handler); std::string opcodes_jump[kJumpLimit] = {"ja", "jae", "jb", "jbe", "jc", "je", "jg", "jge", "jl", "jle", "jna", "jnae", "jnb", "jnbe", "jnc", "jne", @@ -965,13 +964,9 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string line, std::string file) { {.fName = "dx", .fModRM = 0x2}, {.fName = "bx", .fModRM = 3}, {.fName = "sp", .fModRM = 0x4}, {.fName = "bp", .fModRM = 5}, {.fName = "si", .fModRM = 0x6}, {.fName = "di", .fModRM = 7}, - {.fName = "r8", .fModRM = 8}, {.fName = "r13", .fModRM = 9}, - {.fName = "r9", .fModRM = 10}, {.fName = "r14", .fModRM = 11}, - {.fName = "r10", .fModRM = 12}, {.fName = "r15", .fModRM = 13}, - {.fName = "r11", .fModRM = 14}, }; - bool foundInstruction = false; + BOOL foundInstruction = false; for (auto& opcodeAMD64 : kOpcodesAMD64) { // strict check here @@ -981,140 +976,157 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string line, std::string file) { std::string name(opcodeAMD64.fName); /// Move instruction handler. - if (line.find(name) != std::string::npos && name == "mov") { - std::string substr = line.substr(line.find(name) + name.size()); + if (line.find(name) != std::string::npos) { + if (name == "mov" || name == "xor") { + std::string substr = line.substr(line.find(name) + name.size()); - uint64_t bits = kRegisterBitWidth; + uint64_t bits = kRegisterBitWidth; - if (substr.find(",") == std::string::npos) { - Detail::print_error("Syntax error: missing right operand.", "LibCompiler"); - throw std::runtime_error("syntax_err"); - } + if (substr.find(",") == std::string::npos) { + Detail::print_error("Syntax error: missing right operand.", "LibCompiler"); + throw std::runtime_error("syntax_err"); + } - bool onlyOneReg = true; + bool onlyOneReg = true; - std::vector<RegMapAMD64> currentRegList; + std::vector<RegMapAMD64> currentRegList; - for (auto& reg : kRegisterList) { - std::vector<char> regExt = {'e', 'r'}; + for (auto& reg : kRegisterList) { + std::vector<char> regExt = {'e', 'r'}; - for (auto& ext : regExt) { - std::string registerName; + for (auto& ext : regExt) { + std::string registerName; - if (bits > 16) registerName.push_back(ext); + if (bits > 16) registerName.push_back(ext); - registerName += reg.fName; + registerName += reg.fName; - while (line.find(registerName) != std::string::npos) { - line.erase(line.find(registerName), registerName.size()); + while (line.find(registerName) != std::string::npos) { + line.erase(line.find(registerName), registerName.size()); - if (bits == 16) { - if (registerName[0] == 'r') { - Detail::print_error("invalid size for register, current bit width is: " + - std::to_string(kRegisterBitWidth), - file); - throw std::runtime_error("invalid_reg_size"); + if (bits == 16) { + if (registerName[0] == 'r') { + Detail::print_error("invalid size for register, current bit width is: " + + std::to_string(kRegisterBitWidth), + file); + throw std::runtime_error("invalid_reg_size"); + } } - } - currentRegList.push_back({.fName = registerName, .fModRM = reg.fModRM}); + currentRegList.push_back({.fName = registerName, .fModRM = reg.fModRM}); + } } } - } - - if (currentRegList.size() > 1) onlyOneReg = false; - bool hasRBasedRegs = false; - - if (!onlyOneReg) { - /// very tricky to understand. - /// but this checks for a r8 through r15 register. - if (currentRegList[0].fName[0] == 'r' || currentRegList[1].fName[0] == 'r') { - if (isdigit(currentRegList[0].fName[1]) && isdigit(currentRegList[1].fName[1])) { - kAppBytes.emplace_back(0x4d); - hasRBasedRegs = true; - } else if (isdigit(currentRegList[0].fName[1]) || isdigit(currentRegList[1].fName[1])) { - kAppBytes.emplace_back(0x4c); - hasRBasedRegs = true; + if (currentRegList.size() > 1) onlyOneReg = false; + + bool hasRBasedRegs = false; + + if (!onlyOneReg) { + /// very tricky to understand. + /// but this checks for a r8 through r15 register. + if (currentRegList[0].fName[0] == 'r' || currentRegList[1].fName[0] == 'r') { + if (isdigit(currentRegList[0].fName[1]) && isdigit(currentRegList[1].fName[1])) { + kAppBytes.emplace_back(0x4d); + hasRBasedRegs = true; + } else if (isdigit(currentRegList[0].fName[1]) || + isdigit(currentRegList[1].fName[1])) { + kAppBytes.emplace_back(0x4c); + hasRBasedRegs = true; + } } } - } - if (bits == 64 || bits == 32) { - if (!hasRBasedRegs && bits >= 32) { - kAppBytes.emplace_back(opcodeAMD64.fOpcode); - } + if (name == "mov") { + if (bits == 64 || bits == 32) { + if (!hasRBasedRegs && bits >= 32) { + kAppBytes.emplace_back(opcodeAMD64.fOpcode); + } - if (!onlyOneReg) kAppBytes.emplace_back(0x89); - } else if (bits == 16) { - if (hasRBasedRegs) { - Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); - throw std::runtime_error("comb_op_reg"); + if (!onlyOneReg) kAppBytes.emplace_back(0x89); + } else if (bits == 16) { + if (hasRBasedRegs) { + Detail::print_error("Invalid combination of operands and registers.", + "LibCompiler"); + throw std::runtime_error("comb_op_reg"); + } else { + kAppBytes.emplace_back(0x66); + kAppBytes.emplace_back(0x89); + } + } } else { - kAppBytes.emplace_back(0x66); - kAppBytes.emplace_back(0x89); - } - } - - if (onlyOneReg) { - auto num = GetNumber32(line, ","); + if (!hasRBasedRegs && bits >= 32) { + kAppBytes.emplace_back(opcodeAMD64.fOpcode); + } - for (auto& num_idx : num.number) { - if (num_idx == 0) num_idx = 0xFF; + kAppBytes.emplace_back(0x31); } - auto modrm = (0x3 << 6 | currentRegList[0].fModRM); + if (onlyOneReg) { + auto num = GetNumber32(line, ","); - kAppBytes.emplace_back(0xC7); // prefixed before placing the modrm and then the number. - kAppBytes.emplace_back(modrm); - kAppBytes.emplace_back(num.number[0]); - kAppBytes.emplace_back(num.number[1]); - kAppBytes.emplace_back(num.number[2]); - kAppBytes.emplace_back(num.number[3]); + for (auto& num_idx : num.number) { + if (num_idx == 0) num_idx = 0xFF; + } - break; - } + auto modrm = (0x3 << 6 | currentRegList[0].fModRM); - if (currentRegList[1].fName[0] == 'r' && currentRegList[0].fName[0] == 'e') { - Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); - throw std::runtime_error("comb_op_reg"); - } + kAppBytes.emplace_back(0xC7); // prefixed before placing the modrm and then the number. + kAppBytes.emplace_back(modrm); - if (currentRegList[0].fName[0] == 'r' && currentRegList[1].fName[0] == 'e') { - Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); - throw std::runtime_error("comb_op_reg"); - } + if (name != "xor") { + kAppBytes.emplace_back(num.number[0]); + kAppBytes.emplace_back(num.number[1]); + kAppBytes.emplace_back(num.number[2]); + kAppBytes.emplace_back(num.number[3]); + } - if (bits == 16) { - if (currentRegList[0].fName[0] == 'r' || currentRegList[0].fName[0] == 'e') { - Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); - throw std::runtime_error("comb_op_reg"); + break; } - if (currentRegList[1].fName[0] == 'r' || currentRegList[1].fName[0] == 'e') { + if (currentRegList[1].fName[0] == 'r' && currentRegList[0].fName[0] == 'e') { Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); throw std::runtime_error("comb_op_reg"); } - } else { - if (currentRegList[0].fName[0] != 'r' || currentRegList[0].fName[0] == 'e') { + + if (currentRegList[0].fName[0] == 'r' && currentRegList[1].fName[0] == 'e') { Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); throw std::runtime_error("comb_op_reg"); } - if (currentRegList[1].fName[0] != 'r' || currentRegList[1].fName[0] == 'e') { - Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); - throw std::runtime_error("comb_op_reg"); + if (bits == 16) { + if (currentRegList[0].fName[0] == 'r' || currentRegList[0].fName[0] == 'e') { + Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); + throw std::runtime_error("comb_op_reg"); + } + + if (currentRegList[1].fName[0] == 'r' || currentRegList[1].fName[0] == 'e') { + Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); + throw std::runtime_error("comb_op_reg"); + } + } else { + if (currentRegList[0].fName[0] != 'r' || currentRegList[0].fName[0] == 'e') { + Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); + throw std::runtime_error("comb_op_reg"); + } + + if (currentRegList[1].fName[0] != 'r' || currentRegList[1].fName[0] == 'e') { + Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); + throw std::runtime_error("comb_op_reg"); + } } - } - /// encode register using the modrm encoding. + /// encode register using the modrm encoding. - auto modrm = (0x3 << 6 | currentRegList[1].fModRM << 3 | currentRegList[0].fModRM); + auto modrm = (0x3 << 6 | currentRegList[1].fModRM << 3 | currentRegList[0].fModRM); - kAppBytes.emplace_back(modrm); + kAppBytes.emplace_back(modrm); - break; - } else if (name == "int" || name == "into" || name == "intd") { + break; + } + } + + if (name == "int" || name == "into" || name == "intd") { kAppBytes.emplace_back(opcodeAMD64.fOpcode); this->WriteNumber8(line.find(name) + name.size() + 1, line); @@ -1127,6 +1139,11 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string line, std::string file) { } break; + } else if (name == "syscall") { + kAppBytes.emplace_back(opcodeAMD64.fOpcode); + kAppBytes.emplace_back(0x05); + + break; } else { kAppBytes.emplace_back(opcodeAMD64.fOpcode); diff --git a/dev/LibCompiler/src/AssemblerARM64.cc b/dev/LibCompiler/src/Backend/AssemblerARM64.cc index 8686edb..a1cc6dc 100644 --- a/dev/LibCompiler/src/AssemblerARM64.cc +++ b/dev/LibCompiler/src/Backend/AssemblerARM64.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + Copyright (C) 2024-2025 Amlal EL Mahrouss, all rights reserved ------------------------------------------- */ @@ -15,14 +15,16 @@ ///////////////////////////////////////////////////////////////////////////////////////// +#ifndef __ASM_NEED_ARM64__ #define __ASM_NEED_ARM64__ 1 +#endif #include <LibCompiler/AE.h> #include <LibCompiler/Backend/Aarch64.h> -#include <LibCompiler/Detail/AsmUtils.h> #include <LibCompiler/ErrorID.h> +#include <LibCompiler/Frontend.h> #include <LibCompiler/PEF.h> -#include <LibCompiler/Parser.h> +#include <LibCompiler/Util/AsmUtils.h> #include <LibCompiler/Version.h> #include <algorithm> #include <filesystem> @@ -41,12 +43,9 @@ #define kWhite "\e[0;97m" #define kYellow "\e[0;33m" -#define kStdOut (std::cout << kWhite) -#define kStdErr (std::cout << kRed) - constexpr auto cPowerIPAlignment = 0x1U; -static CharType kOutputArch = LibCompiler::kPefArchARM64; +static Char kOutputArch = LibCompiler::kPefArchARM64; static std::size_t kCounter = 1UL; @@ -74,7 +73,7 @@ static bool asm_read_attributes(std::string line); ///////////////////////////////////////////////////////////////////////////////////////// LIBCOMPILER_MODULE(AssemblerMainARM64) { - ::signal(SIGSEGV, Detail::segfault_handler); + LibCompiler::install_signal(SIGSEGV, Detail::drvi_crash_handler); for (size_t i = 1; i < argc; ++i) { if (argv[i][0] == '-') { diff --git a/dev/LibCompiler/src/AssemblerPowerPC.cc b/dev/LibCompiler/src/Backend/AssemblerPowerPC.cc index f2c3be3..b979f64 100644 --- a/dev/LibCompiler/src/AssemblerPowerPC.cc +++ b/dev/LibCompiler/src/Backend/AssemblerPowerPC.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + Copyright (C) 2024-2025 Amlal EL Mahrouss, all rights reserved ------------------------------------------- */ @@ -15,14 +15,16 @@ ///////////////////////////////////////////////////////////////////////////////////////// +#ifndef __ASM_NEED_PPC__ #define __ASM_NEED_PPC__ 1 +#endif #include <LibCompiler/AE.h> #include <LibCompiler/Backend/PowerPC.h> -#include <LibCompiler/Detail/AsmUtils.h> #include <LibCompiler/ErrorID.h> +#include <LibCompiler/Frontend.h> #include <LibCompiler/PEF.h> -#include <LibCompiler/Parser.h> +#include <LibCompiler/Util/AsmUtils.h> #include <LibCompiler/Version.h> #include <algorithm> #include <filesystem> @@ -41,12 +43,9 @@ #define kWhite "\e[0;97m" #define kYellow "\e[0;33m" -#define kStdOut (std::cout << kWhite) -#define kStdErr (std::cout << kRed) - constexpr auto cPowerIPAlignment = 0x4U; -static CharType kOutputArch = LibCompiler::kPefArchPowerPC; +static Char kOutputArch = LibCompiler::kPefArchPowerPC; static std::size_t kCounter = 1UL; @@ -74,7 +73,7 @@ static bool asm_read_attributes(std::string line); ///////////////////////////////////////////////////////////////////////////////////////// LIBCOMPILER_MODULE(AssemblerMainPower64) { - ::signal(SIGSEGV, Detail::segfault_handler); + LibCompiler::install_signal(SIGSEGV, Detail::drvi_crash_handler); for (size_t i = 1; i < argc; ++i) { if (argv[i][0] == '-') { diff --git a/dev/LibCompiler/src/StringView.cc b/dev/LibCompiler/src/BasicString.cc index 41ee636..41989fe 100644 --- a/dev/LibCompiler/src/StringView.cc +++ b/dev/LibCompiler/src/BasicString.cc @@ -8,7 +8,7 @@ */ /** - * @file String.cxx + * @file BasicString.cxx * @author Amlal (amlal@el-mahrouss-logic.com) * @brief C++ string manipulation API. * @version 0.2 @@ -18,22 +18,22 @@ * */ -#include <LibCompiler/StringView.h> +#include <LibCompiler/BasicString.h> namespace LibCompiler { -CharType* StringView::Data() { +Char* BasicString::Data() { return m_Data; } -const CharType* StringView::CData() const { +const Char* BasicString::CData() const { return m_Data; } -SizeType StringView::Length() const { +SizeType BasicString::Length() const { return strlen(m_Data); } -bool StringView::operator==(const StringView& rhs) const { +bool BasicString::operator==(const BasicString& rhs) const { if (rhs.Length() != Length()) return false; for (SizeType index = 0; index < Length(); ++index) { @@ -43,7 +43,7 @@ bool StringView::operator==(const StringView& rhs) const { return true; } -bool StringView::operator==(const CharType* rhs) const { +bool BasicString::operator==(const Char* rhs) const { if (string_length(rhs) != Length()) return false; for (SizeType index = 0; index < string_length(rhs); ++index) { @@ -53,7 +53,7 @@ bool StringView::operator==(const CharType* rhs) const { return true; } -bool StringView::operator!=(const StringView& rhs) const { +bool BasicString::operator!=(const BasicString& rhs) const { if (rhs.Length() != Length()) return false; for (SizeType index = 0; index < rhs.Length(); ++index) { @@ -63,7 +63,7 @@ bool StringView::operator!=(const StringView& rhs) const { return true; } -bool StringView::operator!=(const CharType* rhs) const { +bool BasicString::operator!=(const Char* rhs) const { if (string_length(rhs) != Length()) return false; for (SizeType index = 0; index < string_length(rhs); ++index) { @@ -73,10 +73,10 @@ bool StringView::operator!=(const CharType* rhs) const { return true; } -StringView StringBuilder::Construct(const CharType* data) { - if (!data || *data == 0) return StringView(0); +BasicString StringBuilder::Construct(const Char* data) { + if (!data || *data == 0) return BasicString(0); - StringView view(strlen(data)); + BasicString view(strlen(data)); view += data; return view; @@ -92,7 +92,7 @@ const char* StringBuilder::FromInt(const char* fmt, int i) { memset(ret, 0, ret_len); - CharType result[sizeof(int64_t)]; + Char result[sizeof(int64_t)]; if (!to_str(result, sizeof(int64_t), i)) { delete[] ret; @@ -183,9 +183,9 @@ const char* StringBuilder::Format(const char* fmt, const char* fmtRight) { return ret; } -StringView& StringView::operator+=(const CharType* rhs) { +BasicString& BasicString::operator+=(const Char* rhs) { if (strlen(rhs) > this->m_Sz) { - throw std::runtime_error("out_of_bounds: StringView"); + throw std::runtime_error("out_of_bounds: BasicString"); } memcpy(this->m_Data + this->m_Cur, rhs, strlen(rhs)); @@ -194,9 +194,9 @@ StringView& StringView::operator+=(const CharType* rhs) { return *this; } -StringView& StringView::operator+=(const StringView& rhs) { +BasicString& BasicString::operator+=(const BasicString& rhs) { if (rhs.m_Cur > this->m_Sz) { - throw std::runtime_error("out_of_bounds: StringView"); + throw std::runtime_error("out_of_bounds: BasicString"); } memcpy(this->m_Data + this->m_Cur, rhs.CData(), strlen(rhs.CData())); diff --git a/dev/LibCompiler/src/CCompiler64x0.cc b/dev/LibCompiler/src/CCompiler64x0.cc deleted file mode 100644 index 79d32ce..0000000 --- a/dev/LibCompiler/src/CCompiler64x0.cc +++ /dev/null @@ -1,1288 +0,0 @@ -/* - * ======================================================== - * - * cc - * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. - * - * ======================================================== - */ - -/// BUGS: 0 -/// TODO: none - -#include <LibCompiler/Backend/64x0.h> -#include <LibCompiler/Detail/ClUtils.h> -#include <LibCompiler/Parser.h> -#include <LibCompiler/UUID.h> -#include <cstdio> -#include <fstream> -#include <iostream> -#include <memory> -#include <random> -#include <string> -#include <utility> -#include <vector> - -/* C driver */ -/* This is part of the LibCompiler. */ -/* (c) Amlal El Mahrouss */ - -/// @author EL Mahrouss Amlal (amlel) -/// @file 64x0-cc.cxx -/// @brief 64x0 C Compiler. - -/// TODO: support structures, else if, else, . and -> - -///////////////////// - -// ANSI ESCAPE CODES - -///////////////////// - -#define kExitOK (0) - -#define kBlank "\e[0;30m" -#define kRed "\e[0;31m" -#define kWhite "\e[0;97m" - -///////////////////////////////////// - -// INTERNAL STUFF OF THE C COMPILER - -///////////////////////////////////// - -namespace Detail { -// \brief Register map structure, used to keep track of each variable's registers. -struct CompilerRegisterMap final { - std::string fName; - std::string fReg; -}; - -// \brief Map for C structs -// \author amlel -struct CompilerStructMap final { - // 'my_foo' - std::string fName; - - // if instance: stores a valid register. - std::string fReg; - - // offset count - std::size_t fOffsetsCnt; - - // offset array. - std::vector<std::pair<Int32, std::string>> fOffsets; -}; - -struct CompilerState final { - std::vector<LibCompiler::SyntaxLeafList> fSyntaxTreeList; - std::vector<CompilerRegisterMap> kStackFrame; - std::vector<CompilerStructMap> kStructMap; - LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr}; - std::unique_ptr<std::ofstream> fOutputAssembly; - std::string fLastFile; - std::string fLastError; - bool fVerbose; -}; -} // namespace Detail - -static Detail::CompilerState kState; -static std::string kIfFunction = ""; - -namespace Detail { -/// @brief prints an error into stdout. -/// @param reason the reason of the error. -/// @param file where does it originate from? -void print_error(std::string reason, std::string file) noexcept; - -struct CompilerType final { - std::string fName; - std::string fValue; -}; -} // namespace Detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// Target architecture. -static int kMachine = 0; - -///////////////////////////////////////// - -// REGISTERS ACCORDING TO USED ASSEMBLER - -///////////////////////////////////////// - -static size_t kRegisterCnt = kAsmRegisterLimit; -static size_t kStartUsable = 2; -static size_t kUsableLimit = 15; -static size_t kRegisterCounter = kStartUsable; -static std::string kRegisterPrefix = kAsmRegisterPrefix; - -///////////////////////////////////////// - -// COMPILER PARSING UTILITIES/STATES. - -///////////////////////////////////////// - -static std::vector<std::string> kFileList; -static LibCompiler::AssemblyFactory kFactory; -static bool kInStruct = false; -static bool kOnWhileLoop = false; -static bool kOnForLoop = false; -static bool kInBraces = false; -static bool kIfFound = false; -static size_t kBracesCount = 0UL; - -/* @brief C compiler backend for C */ -class CompilerFrontend64x0 final : public LibCompiler::ICompilerFrontend { - public: - explicit CompilerFrontend64x0() = default; - ~CompilerFrontend64x0() override = default; - - LIBCOMPILER_COPY_DEFAULT(CompilerFrontend64x0); - - std::string Check(const char* text, const char* file); - bool Compile(std::string text, std::string file) override; - - const char* Language() override { return "64k C"; } -}; - -static CompilerFrontend64x0* kCompilerFrontend = nullptr; -static std::vector<Detail::CompilerType> kCompilerVariables; -static std::vector<std::string> kCompilerFunctions; -static std::vector<Detail::CompilerType> kCompilerTypes; - -namespace Detail { -union number_cast final { - public: - number_cast(UInt64 _Raw) : _Raw(_Raw) {} - - public: - char _Num[8]; - UInt64 _Raw; -}; - -union double_cast final { - public: - double_cast(float _Raw) : _Raw(_Raw) {} - - public: - char _Sign; - char _Lh[8]; - char _Rh[23]; - - float _Raw; -}; -} // namespace Detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// @name Compile -// @brief Generate MASM from a C assignement. - -///////////////////////////////////////////////////////////////////////////////////////// - -bool CompilerFrontend64x0::Compile(std::string text_, std::string file) { - std::string text = text_; - - bool typeFound = false; - bool fnFound = false; - - // setup generator. - std::random_device rd; - - auto seed_data = std::array<int, std::mt19937::state_size>{}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); - std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); - std::mt19937 generator(seq); - - // start parsing - for (size_t text_index = 0; text_index < text.size(); ++text_index) { - auto syntaxLeaf = LibCompiler::SyntaxLeafList::SyntaxLeaf(); - - auto gen = uuids::uuid_random_generator{generator}; - uuids::uuid out = gen(); - - Detail::number_cast time_off = (UInt64) out.as_bytes().data(); - - if (!typeFound) { - auto substr = text.substr(text_index); - std::string match_type; - - for (size_t y = 0; y < substr.size(); ++y) { - if (substr[y] == ' ') { - while (match_type.find(' ') != std::string::npos) { - match_type.erase(match_type.find(' ')); - } - - for (auto& clType : kCompilerTypes) { - if (clType.fName == match_type) { - match_type.clear(); - - std::string buf; - - buf += clType.fValue; - buf += ' '; - - if (substr.find('=') != std::string::npos) { - break; - } - - if (text.find('(') != std::string::npos) { - syntaxLeaf.fUserValue = buf; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - typeFound = true; - break; - } - } - - break; - } - - match_type += substr[y]; - } - } - - if (text[text_index] == '{') { - if (kInStruct) { - continue; - } - - kInBraces = true; - ++kBracesCount; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - // return keyword handler - if (text[text_index] == 'r') { - std::string return_keyword; - return_keyword += "return"; - - std::size_t index = 0UL; - - std::string value; - - for (size_t return_index = text_index; return_index < text.size(); ++return_index) { - if (text[return_index] != return_keyword[index]) { - for (size_t value_index = return_index; value_index < text.size(); ++value_index) { - if (text[value_index] == ';') break; - - value += text[value_index]; - } - - break; - } - - ++index; - } - - if (index == return_keyword.size()) { - if (!value.empty()) { - if (value.find('(') != std::string::npos) { - value.erase(value.find('(')); - } - - if (!isdigit(value[value.find('(') + 2])) { - std::string tmp = value; - bool reg_to_reg = false; - - value.clear(); - - value += " extern_segment"; - value += tmp; - } - - syntaxLeaf.fUserValue = "\tldw r19, "; - - // make it pretty. - if (value.find('\t') != std::string::npos) value.erase(value.find('\t'), 1); - - syntaxLeaf.fUserValue += value + "\n"; - } - - syntaxLeaf.fUserValue += "\tjlr"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - break; - } - } - - if (text[text_index] == 'i' && text[text_index + 1] == 'f') { - auto expr = text.substr(text_index + 2); - text.erase(text_index, 2); - - if (expr.find("{") != std::string::npos) { - expr.erase(expr.find("{")); - } - - if (expr.find("(") != std::string::npos) expr.erase(expr.find("(")); - - if (expr.find(")") != std::string::npos) expr.erase(expr.find(")")); - - kIfFunction = "__LIBCOMPILER_IF_PROC_"; - kIfFunction += std::to_string(time_off._Raw); - - syntaxLeaf.fUserValue = "\tlda r12, extern_segment "; - syntaxLeaf.fUserValue += kIfFunction + - "\n\t#r12 = Code to jump on, r11 right cond, r10 left cond.\n\tbeq " - "r10, r11, r12\ndword public_segment .code64 " + - kIfFunction + "\n"; - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - kIfFound = true; - } - - // Parse expressions and instructions here. - // what does this mean? - // we encounter an assignment, or we reached the end of an expression. - if (text[text_index] == '=' || text[text_index] == ';') { - if (fnFound) continue; - if (kIfFound) continue; - - if (text[text_index] == ';' && kInStruct) continue; - - if (text.find("typedef ") != std::string::npos) continue; - - if (text[text_index] == '=' && kInStruct) { - Detail::print_error("assignement of value in struct " + text, file); - continue; - } - - if (text[text_index] == ';' && kInStruct) { - bool space_found_ = false; - std::string sym; - - for (auto& ch : text) { - if (ch == ' ') { - space_found_ = true; - } - - if (ch == ';') break; - - if (space_found_) sym.push_back(ch); - } - - kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back( - std::make_pair(kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, sym)); - - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt = - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4; - - continue; - } - - if (text[text_index] == '=' && kInStruct) { - continue; - } - - if (text[text_index + 1] == '=' || text[text_index - 1] == '!' || - text[text_index - 1] == '<' || text[text_index - 1] == '>') { - continue; - } - - std::string substr; - - if (text.find('=') != std::string::npos && kInBraces && !kIfFound) { - if (text.find("*") != std::string::npos) { - if (text.find("=") > text.find("*")) - substr += "\tlda "; - else - substr += "\tldw "; - } else { - substr += "\tldw "; - } - } else if (text.find('=') != std::string::npos && !kInBraces) { - substr += "stw public_segment .data64 "; - } - - int first_encountered = 0; - - std::string str_name; - - for (size_t text_index_2 = 0; text_index_2 < text.size(); ++text_index_2) { - if (text[text_index_2] == '\"') { - ++text_index_2; - - // want to add this, so that the parser recognizes that this is a - // string. - substr += '"'; - - for (; text_index_2 < text.size(); ++text_index_2) { - if (text[text_index_2] == '\"') break; - - substr += text[text_index_2]; - } - } - - if (text[text_index_2] == '{' || text[text_index_2] == '}') continue; - - if (text[text_index_2] == ';') { - break; - } - - if (text[text_index_2] == ' ' || text[text_index_2] == '\t') { - if (first_encountered != 2) { - if (text[text_index] != '=' && - substr.find("public_segment .data64") == std::string::npos && !kInStruct) - substr += "public_segment .data64 "; - } - - ++first_encountered; - - continue; - } - - if (text[text_index_2] == '=') { - if (!kInBraces) { - substr.replace(substr.find("public_segment .data64"), strlen("public_segment .data64"), - "public_segment .zero64 "); - } - - substr += ","; - continue; - } - - substr += text[text_index_2]; - } - - for (auto& clType : kCompilerTypes) { - if (substr.find(clType.fName) != std::string::npos) { - if (substr.find(clType.fName) > substr.find('"')) continue; - - substr.erase(substr.find(clType.fName), clType.fName.size()); - } else if (substr.find(clType.fValue) != std::string::npos) { - if (substr.find(clType.fValue) > substr.find('"')) continue; - - if (clType.fName == "const") continue; - - substr.erase(substr.find(clType.fValue), clType.fValue.size()); - } - } - - if (substr.find("extern") != std::string::npos) { - substr.replace(substr.find("extern"), strlen("extern"), "extern_segment "); - - if (substr.find("public_segment .data64") != std::string::npos) - substr.erase(substr.find("public_segment .data64"), strlen("public_segment .data64")); - } - - auto var_to_find = std::find_if( - kCompilerVariables.cbegin(), kCompilerVariables.cend(), - [&](Detail::CompilerType type) { return type.fName.find(substr) != std::string::npos; }); - - if (kRegisterCounter == 5 || kRegisterCounter == 6) ++kRegisterCounter; - - std::string reg = kAsmRegisterPrefix; - reg += std::to_string(kRegisterCounter); - - if (var_to_find == kCompilerVariables.cend()) { - ++kRegisterCounter; - - kState.kStackFrame.push_back({.fName = substr, .fReg = reg}); - kCompilerVariables.push_back({.fName = substr}); - } - - syntaxLeaf.fUserValue += substr; - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - if (text[text_index] == '=') break; - } - - // function handler. - - if (text[text_index] == '(' && !fnFound && !kIfFound) { - std::string substr; - std::string args_buffer; - std::string args; - - bool type_crossed = false; - - for (size_t idx = text.find('(') + 1; idx < text.size(); ++idx) { - if (text[idx] == ',') continue; - - if (text[idx] == ' ') continue; - - if (text[idx] == ')') break; - } - - for (char substr_first_index : text) { - if (substr_first_index != ',') - args_buffer += substr_first_index; - else - args_buffer += '$'; - - if (substr_first_index == ';') { - args_buffer = args_buffer.erase(0, args_buffer.find('(')); - args_buffer = args_buffer.erase(args_buffer.find(';'), 1); - args_buffer = args_buffer.erase(args_buffer.find(')'), 1); - args_buffer = args_buffer.erase(args_buffer.find('('), 1); - - if (!args_buffer.empty()) args += "\tldw r6, "; - - std::string register_type; - std::size_t index = 7UL; - - while (args_buffer.find("$") != std::string::npos) { - register_type = kRegisterPrefix; - register_type += std::to_string(index); - - ++index; - - args_buffer.replace(args_buffer.find('$'), 1, "\n\tldw " + register_type + ","); - } - - args += args_buffer; - args += "\n\tlda r19, "; - } - } - - for (char _text_i : text) { - if (_text_i == '\t' || _text_i == ' ') { - if (!type_crossed) { - substr.clear(); - type_crossed = true; - } - - continue; - } - - if (_text_i == '(') break; - - substr += _text_i; - } - - if (kInBraces) { - syntaxLeaf.fUserValue = args; - syntaxLeaf.fUserValue += substr; - syntaxLeaf.fUserValue += "\n\tjrl\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - fnFound = true; - } else { - syntaxLeaf.fUserValue.clear(); - - syntaxLeaf.fUserValue += "public_segment .code64 "; - - syntaxLeaf.fUserValue += substr; - syntaxLeaf.fUserValue += "\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - fnFound = true; - } - - kCompilerFunctions.push_back(text); - } - - if (text[text_index] == '-' && text[text_index + 1] == '-') { - text = text.replace(text.find("--"), strlen("--"), ""); - - for (int _text_i = 0; _text_i < text.size(); ++_text_i) { - if (text[_text_i] == '\t' || text[_text_i] == ' ') text.erase(_text_i, 1); - } - - syntaxLeaf.fUserValue += "sub "; - syntaxLeaf.fUserValue += text; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - break; - } - - if (text[text_index] == '}') { - kRegisterCounter = kStartUsable; - - --kBracesCount; - - if (kBracesCount < 1) { - kInBraces = false; - kBracesCount = 0; - } - - if (kIfFound) kIfFound = false; - - if (kInStruct) kInStruct = false; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - syntaxLeaf.fUserValue.clear(); - } - - auto syntaxLeaf = LibCompiler::SyntaxLeafList::SyntaxLeaf(); - syntaxLeaf.fUserValue = "\n"; - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - return true; -} - -static bool kShouldHaveBraces = false; -static std::string kFnName; - -std::string CompilerFrontend64x0::Check(const char* text, const char* file) { - std::string err_str; - std::string ln = text; - - if (ln.empty()) { - return err_str; - } - - bool non_ascii_found = false; - - for (int i = 0; i < ln.size(); ++i) { - if (isalnum(ln[i])) { - non_ascii_found = true; - break; - } - } - - if (kShouldHaveBraces && ln.find('{') != std::string::npos) { - kShouldHaveBraces = false; - } - - if (!non_ascii_found) return err_str; - - size_t string_index = 1UL; - - if (ln.find('\'') != std::string::npos) { - string_index = ln.find('\'') + 1; - - for (; string_index < ln.size(); ++string_index) { - if (ln[string_index] == '\'') { - if (ln[string_index + 1] != ';') { - ln.erase(string_index, 1); - } - - return err_str; - } - } - } else if (ln.find('"') != std::string::npos) { - string_index = ln.find('"') + 1; - - for (; string_index < ln.size(); ++string_index) { - if (ln[string_index] == '"') { - if (ln[string_index + 1] != ';') { - ln.erase(string_index, 1); - } else { - break; - } - } - } - } else if (ln.find('"') == std::string::npos && ln.find('\'') == std::string::npos) { - std::vector<std::string> forbidden_words; - - forbidden_words.push_back("\\"); - forbidden_words.push_back("?"); - forbidden_words.push_back("@"); - forbidden_words.push_back("~"); - forbidden_words.push_back("::"); - forbidden_words.push_back("--*"); - forbidden_words.push_back("*/"); - - // add them to avoid stupid mistakes. - forbidden_words.push_back("namespace"); - forbidden_words.push_back("class"); - forbidden_words.push_back("extern \"C\""); - - for (auto& forbidden : forbidden_words) { - if (ln.find(forbidden) != std::string::npos) { - err_str += "\nForbidden character detected: "; - err_str += forbidden; - - return err_str; - } - } - } - - struct CompilerVariableRange final { - std::string fBegin; - std::string fEnd; - }; - - const std::vector<CompilerVariableRange> variables_list = { - {.fBegin = "static ", .fEnd = "="}, {.fBegin = "=", .fEnd = ";"}, - {.fBegin = "if(", .fEnd = "="}, {.fBegin = "if (", .fEnd = "="}, - {.fBegin = "if(", .fEnd = "<"}, {.fBegin = "if (", .fEnd = "<"}, - {.fBegin = "if(", .fEnd = ">"}, {.fBegin = "if (", .fEnd = ">"}, - {.fBegin = "if(", .fEnd = ")"}, {.fBegin = "if (", .fEnd = ")"}, - - {.fBegin = "else(", .fEnd = "="}, {.fBegin = "else (", .fEnd = "="}, - {.fBegin = "else(", .fEnd = "<"}, {.fBegin = "else (", .fEnd = "<"}, - {.fBegin = "else(", .fEnd = ">"}, {.fBegin = "else (", .fEnd = ">"}, - {.fBegin = "else(", .fEnd = ")"}, {.fBegin = "else (", .fEnd = ")"}, - }; - - for (auto& variable : variables_list) { - if (ln.find(variable.fBegin) != std::string::npos) { - string_index = ln.find(variable.fBegin) + variable.fBegin.size(); - - while (ln[string_index] == ' ') ++string_index; - - std::string keyword; - - for (; string_index < ln.size(); ++string_index) { - if (ln[string_index] == variable.fEnd[0]) { - std::string varname = ""; - - for (size_t index_keyword = ln.find(' '); ln[index_keyword] != variable.fBegin[0]; - ++index_keyword) { - if (ln[index_keyword] == ' ') { - continue; - } - - if (isdigit(ln[index_keyword])) { - goto cc_next_loop; - } - - varname += ln[index_keyword]; - } - - if (varname.find(' ') != std::string::npos) { - varname.erase(0, varname.find(' ')); - - if (variable.fBegin == "extern") { - varname.erase(0, varname.find(' ')); - } - } - - if (kRegisterCounter == 5 || kRegisterCounter == 6) ++kRegisterCounter; - - std::string reg = kAsmRegisterPrefix; - reg += std::to_string(kRegisterCounter); - - kCompilerVariables.push_back({.fValue = varname}); - goto cc_check_done; - } - - keyword.push_back(ln[string_index]); - } - - goto cc_next_loop; - - cc_check_done: - - // skip digit value. - if (isdigit(keyword[0]) || keyword[0] == '"') { - goto cc_next_loop; - } - - while (keyword.find(' ') != std::string::npos) keyword.erase(keyword.find(' '), 1); - - for (auto& var : kCompilerVariables) { - if (var.fValue.find(keyword) != std::string::npos) { - err_str.clear(); - goto cc_next; - } - } - - for (auto& fn : kCompilerFunctions) { - if (fn.find(keyword[0]) != std::string::npos) { - auto where_begin = fn.find(keyword[0]); - auto keyword_begin = 0UL; - auto failed = false; - - for (; where_begin < keyword.size(); ++where_begin) { - if (fn[where_begin] == '(' && keyword[keyword_begin] == '(') break; - - if (fn[where_begin] != keyword[keyword_begin]) { - failed = true; - break; - } - - ++keyword_begin; - } - - if (!failed) { - err_str.clear(); - goto cc_next; - } else { - continue; - } - } - } - - cc_error_value: - if (keyword.find("->") != std::string::npos) return err_str; - - if (keyword.find(".") != std::string::npos) return err_str; - - if (isalnum(keyword[0])) err_str += "\nUndefined value: " + keyword; - - return err_str; - } - - cc_next_loop: - continue; - } - -cc_next: - - // extern does not declare anything, it extern_segments a variable. - // so that's why it's not declare upper. - if (LibCompiler::find_word(ln, "extern")) { - auto substr = ln.substr(ln.find("extern") + strlen("extern")); - kCompilerVariables.push_back({.fValue = substr}); - } - - if (kShouldHaveBraces && ln.find('{') == std::string::npos) { - err_str += "Missing '{' for function "; - err_str += kFnName; - err_str += "\n"; - - kShouldHaveBraces = false; - kFnName.clear(); - } else if (kShouldHaveBraces && ln.find('{') != std::string::npos) { - kShouldHaveBraces = false; - kFnName.clear(); - } - - bool type_not_found = true; - - if (ln.find('\'') != std::string::npos) { - ln.replace(ln.find('\''), 3, "0"); - } - - auto first = ln.find('"'); - if (first != std::string::npos) { - auto second = 0UL; - bool found_second_quote = false; - - for (size_t i = first + 1; i < ln.size(); ++i) { - if (ln[i] == '\"') { - found_second_quote = true; - second = i; - - break; - } - } - - if (!found_second_quote) { - err_str += "Missing terminating \"."; - err_str += " here -> " + ln.substr(ln.find('"'), second); - } - } - - if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos) { - if (ln.find('{') == std::string::npos) { - kFnName = ln; - kShouldHaveBraces = true; - - goto skip_braces_check; - } else if (ln.find('{') != std::string::npos) { - kShouldHaveBraces = false; - } - } - -skip_braces_check: - - for (auto& key : kCompilerTypes) { - if (LibCompiler::find_word(ln, key.fName)) { - if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) { - err_str += "\nNumber cannot be set for "; - err_str += key.fName; - err_str += "'s name. here -> "; - err_str += ln; - } - - if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' || - ln[ln.find(key.fName) - 1] == '\t') { - type_not_found = false; - - if (ln[ln.find(key.fName) + key.fName.size()] != ' ') { - type_not_found = true; - - if (ln[ln.find(key.fName) + key.fName.size()] == '\t') type_not_found = false; - - goto next; - } else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') { - type_not_found = true; - - if (ln[ln.find(key.fName) + key.fName.size()] == ' ') type_not_found = false; - } - } - - next: - - if (ln.find(';') == std::string::npos) { - if (ln.find('(') != std::string::npos) { - if (ln.find('=') == std::string::npos) continue; - } - - err_str += "\nMissing ';', here -> "; - err_str += ln; - } else { - continue; - } - - if (ln.find('=') != std::string::npos) { - if (ln.find('(') != std::string::npos) { - if (ln.find(')') == std::string::npos) { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } - } - } - } - } - - if (kInBraces && ln.find("struct") != std::string::npos && - ln.find("union") != std::string::npos && ln.find("enum") != std::string::npos && - ln.find('=') != std::string::npos) { - if (ln.find(';') == std::string::npos) { - err_str += "\nMissing ';' after struct/union/enum declaration, here -> "; - err_str += ln; - } - } - - if (ln.find(';') != std::string::npos && ln.find("for") == std::string::npos) { - if (ln.find(';') + 1 != ln.size()) { - for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) { - if ((ln.substr(ln.find(';') + 1)[i] != ' ') || (ln.substr(ln.find(';') + 1)[i] != '\t')) { - if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); !err.empty()) { - err_str += "\nUnexpected text after ';' -> "; - err_str += ln.substr(ln.find(';')); - err_str += err; - } - } - } - } - } - - if (ln.find('(') != std::string::npos) { - if (ln.find(';') == std::string::npos && !LibCompiler::find_word(ln, "|") && - !LibCompiler::find_word(ln, "||") && !LibCompiler::find_word(ln, "&") && - !LibCompiler::find_word(ln, "&&") && !LibCompiler::find_word(ln, "~")) { - bool found_func = false; - size_t i = ln.find('('); - std::vector<char> opens; - std::vector<char> closes; - - for (; i < ln.size(); ++i) { - if (ln[i] == ')') { - closes.push_back(1); - } - - if (ln[i] == '(') { - opens.push_back(1); - } - } - - if (closes.size() != opens.size()) err_str += "Unterminated (), here -> " + ln; - - bool space_found = false; - - for (int i = 0; i < ln.size(); ++i) { - if (ln[i] == ')' && !space_found) { - space_found = true; - continue; - } - - if (space_found) { - if (ln[i] == ' ' && isalnum(ln[i + 1])) { - err_str += "\nBad function format here -> "; - err_str += ln; - } - } - } - } - - if (ln.find('(') < 1) { - err_str += "\nMissing identifier before '(' here -> "; - err_str += ln; - } else { - if (type_not_found && ln.find(';') == std::string::npos && - ln.find("if") == std::string::npos && ln.find("|") == std::string::npos && - ln.find("&") == std::string::npos && ln.find("(") == std::string::npos && - ln.find(")") == std::string::npos) { - err_str += "\n Missing ';' or type, here -> "; - err_str += ln; - } - } - - if (ln.find(')') == std::string::npos) { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } - } else { - if (ln.find("for") != std::string::npos || ln.find("while") != std::string::npos) { - err_str += "\nMissing '(', after \"for\", here -> "; - err_str += ln; - } - } - - if (ln.find('}') != std::string::npos && !kInBraces) { - if (!kInStruct && ln.find(';') == std::string::npos) { - err_str += "\nMismatched '}', here -> "; - err_str += ln; - } - } - - if (!ln.empty()) { - if (ln.find(';') == std::string::npos && ln.find('{') == std::string::npos && - ln.find('}') == std::string::npos && ln.find(')') == std::string::npos && - ln.find('(') == std::string::npos && ln.find(',') == std::string::npos) { - if (ln.size() <= 2) return err_str; - - err_str += "\nMissing ';', here -> "; - err_str += ln; - } - } - - return err_str; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -/** - * @brief C To Assembly mount-point. - */ - -///////////////////////////////////////////////////////////////////////////////////////// - -class AssemblyCCInterface final ASSEMBLY_INTERFACE { - public: - explicit AssemblyCCInterface() = default; - ~AssemblyCCInterface() override = default; - - LIBCOMPILER_COPY_DEFAULT(AssemblyCCInterface); - - [[maybe_unused]] Int32 Arch() noexcept override { - return LibCompiler::AssemblyFactory::kArch64x0; - } - - Int32 CompileToFormat(std::string src, Int32 arch) override { - if (kCompilerFrontend == nullptr) return 1; - - /* @brief copy contents wihtout extension */ - std::string src_file = src.data(); - std::ifstream src_fp = std::ifstream(src_file, std::ios::in); - std::string dest; - - for (auto& ch : src_file) { - if (ch == '.') { - break; - } - - dest += ch; - } - - /* According to PEF ABI. */ - std::vector<const char*> exts = kAsmFileExts; - dest += exts[4]; - - kState.fOutputAssembly = std::make_unique<std::ofstream>(dest); - - auto fmt = LibCompiler::current_date(); - - (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; - (*kState.fOutputAssembly) << "# Language: 64x0 Assembly (Generated from ANSI C)\n"; - (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n"; - - LibCompiler::SyntaxLeafList syntax; - - kState.fSyntaxTreeList.push_back(syntax); - kState.fSyntaxTree = &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; - - std::string line_src; - - while (std::getline(src_fp, line_src)) { - if (auto err = kCompilerFrontend->Check(line_src.c_str(), src.data()); err.empty()) { - kCompilerFrontend->Compile(line_src, src.data()); - } else { - Detail::print_error(err, src.data()); - } - } - - if (kAcceptableErrors > 0) return 1; - - std::vector<std::string> keywords = {"ldw", "stw", "lda", "sta", "add", "sub", "mv"}; - - /// - /// Replace, optimize, fix assembly output. - /// - - for (auto& leaf : kState.fSyntaxTree->fLeafList) { - std::vector<std::string> access_keywords = {"->", "."}; - - for (auto& access_ident : access_keywords) { - if (LibCompiler::find_word(leaf.fUserValue, access_ident)) { - for (auto& struc : kState.kStructMap) { - /// TODO: - } - } - } - - for (auto& keyword : keywords) { - if (LibCompiler::find_word(leaf.fUserValue, keyword)) { - std::size_t cnt = 0UL; - - for (auto& reg : kState.kStackFrame) { - std::string needle; - - for (size_t i = 0; i < reg.fName.size(); i++) { - if (reg.fName[i] == ' ') { - ++i; - - for (; i < reg.fName.size(); i++) { - if (reg.fName[i] == ',') { - break; - } - - if (reg.fName[i] == ' ') continue; - - needle += reg.fName[i]; - } - - break; - } - } - - if (LibCompiler::find_word(leaf.fUserValue, needle)) { - if (leaf.fUserValue.find("extern_segment " + needle) != std::string::npos) { - std::string range = "extern_segment " + needle; - leaf.fUserValue.replace(leaf.fUserValue.find("extern_segment " + needle), - range.size(), needle); - } - - if (leaf.fUserValue.find("ldw r6") != std::string::npos) { - std::string::difference_type countComma = - std::count(leaf.fUserValue.begin(), leaf.fUserValue.end(), ','); - - if (countComma == 1) { - leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), strlen("ldw"), "mv"); - } - } - - leaf.fUserValue.replace(leaf.fUserValue.find(needle), needle.size(), reg.fReg); - - ++cnt; - } - } - - if (cnt > 1 && keyword != "mv" && keyword != "add" && keyword != "sub") { - leaf.fUserValue.replace(leaf.fUserValue.find(keyword), keyword.size(), "mv"); - } - } - } - } - - for (auto& leaf : kState.fSyntaxTree->fLeafList) { - (*kState.fOutputAssembly) << leaf.fUserValue; - } - - kState.fSyntaxTree = nullptr; - - kState.fOutputAssembly->flush(); - kState.fOutputAssembly.reset(); - - return kExitOK; - } -}; - -///////////////////////////////////////////////////////////////////////////////////////// - -#include <LibCompiler/Version.h> - -#define kPrintF printf -#define kSplashCxx() kPrintF(kWhite "NE C Driver, %s, (c) Amlal El Mahrouss\n", kDistVersion) - -static void cc_print_help() { - kSplashCxx(); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -#define kExt ".c" - -LIBCOMPILER_MODULE(NeOSCompilerCLang64x0) { - ::signal(SIGSEGV, Detail::segfault_handler); - - kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); - kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); - kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); - kCompilerTypes.push_back({.fName = "int", .fValue = "dword"}); - kCompilerTypes.push_back({.fName = "long", .fValue = "qword"}); - kCompilerTypes.push_back({.fName = "*", .fValue = "offset"}); - - bool skip = false; - - kFactory.Mount(new AssemblyCCInterface()); - kMachine = LibCompiler::AssemblyFactory::kArch64x0; - kCompilerFrontend = new CompilerFrontend64x0(); - - for (auto index = 1UL; index < argc; ++index) { - if (skip) { - skip = false; - continue; - } - - if (argv[index][0] == '-') { - if (strcmp(argv[index], "--v") == 0 || strcmp(argv[index], "--version") == 0) { - kSplashCxx(); - return kExitOK; - } - - if (strcmp(argv[index], "--verbose") == 0) { - kState.fVerbose = true; - - continue; - } - - if (strcmp(argv[index], "--h") == 0 || strcmp(argv[index], "--help") == 0) { - cc_print_help(); - - return kExitOK; - } - - if (strcmp(argv[index], "--dialect") == 0) { - if (kCompilerFrontend) std::cout << kCompilerFrontend->Language() << "\n"; - - return kExitOK; - } - - if (strcmp(argv[index], "--fmax-exceptions") == 0) { - try { - kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); - } - // catch anything here - catch (...) { - kErrorLimit = 0; - } - - skip = true; - - continue; - } - - std::string err = "Unknown command: "; - err += argv[index]; - - Detail::print_error(err, "cc"); - - continue; - } - - kFileList.emplace_back(argv[index]); - - std::string srcFile = argv[index]; - - if (strstr(argv[index], kExt) == nullptr) { - if (kState.fVerbose) { - Detail::print_error(srcFile + " is not a valid C source.\n", "cc"); - } - - return 1; - } - - if (kFactory.Compile(srcFile, kMachine) != kExitOK) return 1; - } - - return kExitOK; -} - -// Last rev 8-1-24 diff --git a/dev/LibCompiler/src/CCompilerARM64.cc b/dev/LibCompiler/src/CCompilerARM64.cc deleted file mode 100644 index a5ddf43..0000000 --- a/dev/LibCompiler/src/CCompilerARM64.cc +++ /dev/null @@ -1,1286 +0,0 @@ -/* - * ======================================================== - * - * cc - * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. - * - * ======================================================== - */ - -/// BUGS: 0 -/// TODO: none - -#include <LibCompiler/Backend/Aarch64.h> -#include <LibCompiler/Detail/ClUtils.h> -#include <LibCompiler/Parser.h> -#include <LibCompiler/UUID.h> -#include <cstdio> -#include <fstream> -#include <iostream> -#include <memory> -#include <random> -#include <string> -#include <utility> -#include <vector> - -/* C driver */ -/* This is part of the LibCompiler. */ -/* (c) Amlal El Mahrouss */ - -/// @author EL Mahrouss Amlal (amlel) -/// @file ARM64-cc.cxx -/// @brief ARM64 C Compiler. - -/// TODO: support structures, else if, else, . and -> - -///////////////////// - -// ANSI ESCAPE CODES - -///////////////////// - -#define kExitOK (0) - -#define kBlank "\e[0;30m" -#define kRed "\e[0;31m" -#define kWhite "\e[0;97m" - -///////////////////////////////////// - -// INTERNAL STUFF OF THE C COMPILER - -///////////////////////////////////// - -namespace Detail { -// \brief Register map structure, used to keep track of each variable's registers. -struct CompilerRegisterMap final { - std::string fName; - std::string fReg; -}; - -// \brief Map for C structs -// \author amlel -struct CompilerStructMap final { - // 'my_foo' - std::string fName; - - // if instance: stores a valid register. - std::string fReg; - - // offset count - std::size_t fOffsetsCnt; - - // offset array. - std::vector<std::pair<Int32, std::string>> fOffsets; -}; - -struct CompilerState final { - std::vector<LibCompiler::SyntaxLeafList> fSyntaxTreeList; - std::vector<CompilerRegisterMap> kStackFrame; - std::vector<CompilerStructMap> kStructMap; - LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr}; - std::unique_ptr<std::ofstream> fOutputAssembly; - std::string fLastFile; - std::string fLastError; - bool fVerbose; -}; -} // namespace Detail - -static Detail::CompilerState kState; -static std::string kIfFunction = ""; - -namespace Detail { -/// @brief prints an error into stdout. -/// @param reason the reason of the error. -/// @param file where does it originate from? -void print_error(std::string reason, std::string file) noexcept; - -struct CompilerType final { - std::string fName; - std::string fValue; -}; -} // namespace Detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// Target architecture. -static int kMachine = 0; - -///////////////////////////////////////// - -// REGISTERS ACCORDING TO USED ASSEMBLER - -///////////////////////////////////////// - -static size_t kRegisterCnt = kAsmRegisterLimit; -static size_t kStartUsable = 8; -static size_t kUsableLimit = 15; -static size_t kRegisterCounter = kStartUsable; -static std::string kRegisterPrefix = kAsmRegisterPrefix; - -///////////////////////////////////////// - -// COMPILER PARSING UTILITIES/STATES. - -///////////////////////////////////////// - -static std::vector<std::string> kFileList; -static LibCompiler::AssemblyFactory kFactory; -static bool kInStruct = false; -static bool kOnWhileLoop = false; -static bool kOnForLoop = false; -static bool kInBraces = false; -static bool kIfFound = false; -static size_t kBracesCount = 0UL; - -/* @brief C compiler backend for C */ -class CompilerFrontendARM64 final : public LibCompiler::ICompilerFrontend { - public: - explicit CompilerFrontendARM64() = default; - ~CompilerFrontendARM64() override = default; - - LIBCOMPILER_COPY_DEFAULT(CompilerFrontendARM64); - - std::string Check(const char* text, const char* file); - bool Compile(std::string text, std::string file) override; - - const char* Language() override { return "64k C"; } -}; - -static CompilerFrontendARM64* kCompilerFrontend = nullptr; -static std::vector<Detail::CompilerType> kCompilerVariables; -static std::vector<std::string> kCompilerFunctions; -static std::vector<Detail::CompilerType> kCompilerTypes; - -namespace Detail { -union number_cast final { - public: - number_cast(UInt64 _Raw) : _Raw(_Raw) {} - - public: - char _Num[8]; - UInt64 _Raw; -}; - -union double_cast final { - public: - double_cast(float _Raw) : _Raw(_Raw) {} - - public: - char _Sign; - char _Lh[8]; - char _Rh[23]; - - float _Raw; -}; -} // namespace Detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// @name Compile -// @brief Generate MASM from a C assignement. - -///////////////////////////////////////////////////////////////////////////////////////// - -bool CompilerFrontendARM64::Compile(std::string text, std::string file) { - bool typeFound = false; - bool fnFound = false; - - // setup generator. - std::random_device rd; - - auto seed_data = std::array<int, std::mt19937::state_size>{}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); - std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); - std::mt19937 generator(seq); - - // start parsing - for (size_t text_index = 0; text_index < text.size(); ++text_index) { - auto syntaxLeaf = LibCompiler::SyntaxLeafList::SyntaxLeaf(); - - auto gen = uuids::uuid_random_generator{generator}; - uuids::uuid out = gen(); - - Detail::number_cast time_off = (UInt64) out.as_bytes().data(); - - if (!typeFound) { - auto substr = text.substr(text_index); - std::string match_type; - - for (size_t y = 0; y < substr.size(); ++y) { - if (substr[y] == ' ') { - while (match_type.find(' ') != std::string::npos) { - match_type.erase(match_type.find(' ')); - } - - for (auto& clType : kCompilerTypes) { - if (clType.fName == match_type) { - match_type.clear(); - - std::string buf; - - buf += clType.fValue; - buf += ' '; - - if (substr.find('=') != std::string::npos) { - break; - } - - if (text.find('(') != std::string::npos) { - syntaxLeaf.fUserValue = buf; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - typeFound = true; - break; - } - } - - break; - } - - match_type += substr[y]; - } - } - - if (text[text_index] == '{') { - if (kInStruct) { - continue; - } - - kInBraces = true; - ++kBracesCount; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - // return keyword handler - if (text[text_index] == 'r') { - std::string return_keyword; - return_keyword += "return"; - - std::size_t index = 0UL; - - std::string value; - - for (size_t return_index = text_index; return_index < text.size(); ++return_index) { - if (text[return_index] != return_keyword[index]) { - for (size_t value_index = return_index; value_index < text.size(); ++value_index) { - if (text[value_index] == ';') break; - - value += text[value_index]; - } - - break; - } - - ++index; - } - - if (index == return_keyword.size()) { - if (!value.empty()) { - if (value.find('(') != std::string::npos) { - value.erase(value.find('(')); - } - - if (!isdigit(value[value.find('(') + 2])) { - std::string tmp = value; - bool reg_to_reg = false; - - value.clear(); - - value += " extern_segment"; - value += tmp; - } - - syntaxLeaf.fUserValue = "\tldw r19, "; - - // make it pretty. - if (value.find('\t') != std::string::npos) value.erase(value.find('\t'), 1); - - syntaxLeaf.fUserValue += value + "\n"; - } - - syntaxLeaf.fUserValue += "\tjlr"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - break; - } - } - - if (text[text_index] == 'i' && text[text_index + 1] == 'f') { - auto expr = text.substr(text_index + 2); - text.erase(text_index, 2); - - if (expr.find("{") != std::string::npos) { - expr.erase(expr.find("{")); - } - - if (expr.find("(") != std::string::npos) expr.erase(expr.find("(")); - - if (expr.find(")") != std::string::npos) expr.erase(expr.find(")")); - - kIfFunction = "__LIBCOMPILER_IF_PROC_"; - kIfFunction += std::to_string(time_off._Raw); - - syntaxLeaf.fUserValue = "\tlda r12, extern_segment "; - syntaxLeaf.fUserValue += kIfFunction + - "\n\t#r12 = Code to jump on, r11 right cond, r10 left cond.\n\tbeq " - "r10, r11, r12\ndword public_segment .code64 " + - kIfFunction + "\n"; - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - kIfFound = true; - } - - // Parse expressions and instructions here. - // what does this mean? - // we encounter an assignment, or we reached the end of an expression. - if (text[text_index] == '=' || text[text_index] == ';') { - if (fnFound) continue; - if (kIfFound) continue; - - if (text[text_index] == ';' && kInStruct) continue; - - if (text.find("typedef ") != std::string::npos) continue; - - if (text[text_index] == '=' && kInStruct) { - Detail::print_error("assignement of value in struct " + text, file); - continue; - } - - if (text[text_index] == ';' && kInStruct) { - bool space_found_ = false; - std::string sym; - - for (auto& ch : text) { - if (ch == ' ') { - space_found_ = true; - } - - if (ch == ';') break; - - if (space_found_) sym.push_back(ch); - } - - kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back( - std::make_pair(kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, sym)); - - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt = - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4; - - continue; - } - - if (text[text_index] == '=' && kInStruct) { - continue; - } - - if (text[text_index + 1] == '=' || text[text_index - 1] == '!' || - text[text_index - 1] == '<' || text[text_index - 1] == '>') { - continue; - } - - std::string substr; - - if (text.find('=') != std::string::npos && kInBraces && !kIfFound) { - if (text.find("*") != std::string::npos) { - if (text.find("=") > text.find("*")) - substr += "\tlda "; - else - substr += "\tldw "; - } else { - substr += "\tldw "; - } - } else if (text.find('=') != std::string::npos && !kInBraces) { - substr += "stw public_segment .data64 "; - } - - int first_encountered = 0; - - std::string str_name; - - for (size_t text_index_2 = 0; text_index_2 < text.size(); ++text_index_2) { - if (text[text_index_2] == '\"') { - ++text_index_2; - - // want to add this, so that the parser recognizes that this is a - // string. - substr += '"'; - - for (; text_index_2 < text.size(); ++text_index_2) { - if (text[text_index_2] == '\"') break; - - substr += text[text_index_2]; - } - } - - if (text[text_index_2] == '{' || text[text_index_2] == '}') continue; - - if (text[text_index_2] == ';') { - break; - } - - if (text[text_index_2] == ' ' || text[text_index_2] == '\t') { - if (first_encountered != 2) { - if (text[text_index] != '=' && - substr.find("public_segment .data64") == std::string::npos && !kInStruct) - substr += "public_segment .data64 "; - } - - ++first_encountered; - - continue; - } - - if (text[text_index_2] == '=') { - if (!kInBraces) { - substr.replace(substr.find("public_segment .data64"), strlen("public_segment .data64"), - "public_segment .zero64 "); - } - - substr += ","; - continue; - } - - substr += text[text_index_2]; - } - - for (auto& clType : kCompilerTypes) { - if (substr.find(clType.fName) != std::string::npos) { - if (substr.find(clType.fName) > substr.find('"')) continue; - - substr.erase(substr.find(clType.fName), clType.fName.size()); - } else if (substr.find(clType.fValue) != std::string::npos) { - if (substr.find(clType.fValue) > substr.find('"')) continue; - - if (clType.fName == "const") continue; - - substr.erase(substr.find(clType.fValue), clType.fValue.size()); - } - } - - if (substr.find("extern") != std::string::npos) { - substr.replace(substr.find("extern"), strlen("extern"), "extern_segment "); - - if (substr.find("public_segment .data64") != std::string::npos) - substr.erase(substr.find("public_segment .data64"), strlen("public_segment .data64")); - } - - auto var_to_find = std::find_if( - kCompilerVariables.cbegin(), kCompilerVariables.cend(), - [&](Detail::CompilerType type) { return type.fName.find(substr) != std::string::npos; }); - - if (kRegisterCounter == 5 || kRegisterCounter == 6) ++kRegisterCounter; - - std::string reg = kAsmRegisterPrefix; - reg += std::to_string(kRegisterCounter); - - if (var_to_find == kCompilerVariables.cend()) { - ++kRegisterCounter; - - kState.kStackFrame.push_back({.fName = substr, .fReg = reg}); - kCompilerVariables.push_back({.fName = substr}); - } - - syntaxLeaf.fUserValue += substr; - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - if (text[text_index] == '=') break; - } - - // function handler. - - if (text[text_index] == '(' && !fnFound && !kIfFound) { - std::string substr; - std::string args_buffer; - std::string args; - - bool type_crossed = false; - - for (size_t idx = text.find('(') + 1; idx < text.size(); ++idx) { - if (text[idx] == ',') continue; - - if (text[idx] == ' ') continue; - - if (text[idx] == ')') break; - } - - for (char substr_first_index : text) { - if (substr_first_index != ',') - args_buffer += substr_first_index; - else - args_buffer += '$'; - - if (substr_first_index == ';') { - args_buffer = args_buffer.erase(0, args_buffer.find('(')); - args_buffer = args_buffer.erase(args_buffer.find(';'), 1); - args_buffer = args_buffer.erase(args_buffer.find(')'), 1); - args_buffer = args_buffer.erase(args_buffer.find('('), 1); - - if (!args_buffer.empty()) args += "\tldw r6, "; - - std::string register_type; - std::size_t index = 7UL; - - while (args_buffer.find("$") != std::string::npos) { - register_type = kRegisterPrefix; - register_type += std::to_string(index); - - ++index; - - args_buffer.replace(args_buffer.find('$'), 1, "\n\tldw " + register_type + ","); - } - - args += args_buffer; - args += "\n\tlda r19, "; - } - } - - for (char _text_i : text) { - if (_text_i == '\t' || _text_i == ' ') { - if (!type_crossed) { - substr.clear(); - type_crossed = true; - } - - continue; - } - - if (_text_i == '(') break; - - substr += _text_i; - } - - if (kInBraces) { - syntaxLeaf.fUserValue = args; - syntaxLeaf.fUserValue += substr; - syntaxLeaf.fUserValue += "\n\tjrl\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - fnFound = true; - } else { - syntaxLeaf.fUserValue.clear(); - - syntaxLeaf.fUserValue += "public_segment .code64 "; - - syntaxLeaf.fUserValue += substr; - syntaxLeaf.fUserValue += "\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - fnFound = true; - } - - kCompilerFunctions.push_back(text); - } - - if (text[text_index] == '-' && text[text_index + 1] == '-') { - text = text.replace(text.find("--"), strlen("--"), ""); - - for (int _text_i = 0; _text_i < text.size(); ++_text_i) { - if (text[_text_i] == '\t' || text[_text_i] == ' ') text.erase(_text_i, 1); - } - - syntaxLeaf.fUserValue += "sub "; - syntaxLeaf.fUserValue += text; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - break; - } - - if (text[text_index] == '}') { - kRegisterCounter = kStartUsable; - - --kBracesCount; - - if (kBracesCount < 1) { - kInBraces = false; - kBracesCount = 0; - } - - if (kIfFound) kIfFound = false; - - if (kInStruct) kInStruct = false; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - syntaxLeaf.fUserValue.clear(); - } - - auto syntaxLeaf = LibCompiler::SyntaxLeafList::SyntaxLeaf(); - syntaxLeaf.fUserValue = "\n"; - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - return true; -} - -static bool kShouldHaveBraces = false; -static std::string kFnName; - -std::string CompilerFrontendARM64::Check(const char* text, const char* file) { - std::string err_str; - std::string ln = text; - - if (ln.empty()) { - return err_str; - } - - bool non_ascii_found = false; - - for (int i = 0; i < ln.size(); ++i) { - if (isalnum(ln[i])) { - non_ascii_found = true; - break; - } - } - - if (kShouldHaveBraces && ln.find('{') != std::string::npos) { - kShouldHaveBraces = false; - } - - if (!non_ascii_found) return err_str; - - size_t string_index = 1UL; - - if (ln.find('\'') != std::string::npos) { - string_index = ln.find('\'') + 1; - - for (; string_index < ln.size(); ++string_index) { - if (ln[string_index] == '\'') { - if (ln[string_index + 1] != ';') { - ln.erase(string_index, 1); - } - - return err_str; - } - } - } else if (ln.find('"') != std::string::npos) { - string_index = ln.find('"') + 1; - - for (; string_index < ln.size(); ++string_index) { - if (ln[string_index] == '"') { - if (ln[string_index + 1] != ';') { - ln.erase(string_index, 1); - } else { - break; - } - } - } - } else if (ln.find('"') == std::string::npos && ln.find('\'') == std::string::npos) { - std::vector<std::string> forbidden_words; - - forbidden_words.push_back("\\"); - forbidden_words.push_back("?"); - forbidden_words.push_back("@"); - forbidden_words.push_back("~"); - forbidden_words.push_back("::"); - forbidden_words.push_back("--*"); - forbidden_words.push_back("*/"); - - // add them to avoid stupid mistakes. - forbidden_words.push_back("namespace"); - forbidden_words.push_back("class"); - forbidden_words.push_back("extern \"C\""); - - for (auto& forbidden : forbidden_words) { - if (ln.find(forbidden) != std::string::npos) { - err_str += "\nForbidden character detected: "; - err_str += forbidden; - - return err_str; - } - } - } - - struct CompilerVariableRange final { - std::string fBegin; - std::string fEnd; - }; - - const std::vector<CompilerVariableRange> variables_list = { - {.fBegin = "static ", .fEnd = "="}, {.fBegin = "=", .fEnd = ";"}, - {.fBegin = "if(", .fEnd = "="}, {.fBegin = "if (", .fEnd = "="}, - {.fBegin = "if(", .fEnd = "<"}, {.fBegin = "if (", .fEnd = "<"}, - {.fBegin = "if(", .fEnd = ">"}, {.fBegin = "if (", .fEnd = ">"}, - {.fBegin = "if(", .fEnd = ")"}, {.fBegin = "if (", .fEnd = ")"}, - - {.fBegin = "else(", .fEnd = "="}, {.fBegin = "else (", .fEnd = "="}, - {.fBegin = "else(", .fEnd = "<"}, {.fBegin = "else (", .fEnd = "<"}, - {.fBegin = "else(", .fEnd = ">"}, {.fBegin = "else (", .fEnd = ">"}, - {.fBegin = "else(", .fEnd = ")"}, {.fBegin = "else (", .fEnd = ")"}, - }; - - for (auto& variable : variables_list) { - if (ln.find(variable.fBegin) != std::string::npos) { - string_index = ln.find(variable.fBegin) + variable.fBegin.size(); - - while (ln[string_index] == ' ') ++string_index; - - std::string keyword; - - for (; string_index < ln.size(); ++string_index) { - if (ln[string_index] == variable.fEnd[0]) { - std::string varname = ""; - - for (size_t index_keyword = ln.find(' '); ln[index_keyword] != variable.fBegin[0]; - ++index_keyword) { - if (ln[index_keyword] == ' ') { - continue; - } - - if (isdigit(ln[index_keyword])) { - goto cc_next_loop; - } - - varname += ln[index_keyword]; - } - - if (varname.find(' ') != std::string::npos) { - varname.erase(0, varname.find(' ')); - - if (variable.fBegin == "extern") { - varname.erase(0, varname.find(' ')); - } - } - - if (kRegisterCounter == 5 || kRegisterCounter == 6) ++kRegisterCounter; - - std::string reg = kAsmRegisterPrefix; - reg += std::to_string(kRegisterCounter); - - kCompilerVariables.push_back({.fValue = varname}); - goto cc_check_done; - } - - keyword.push_back(ln[string_index]); - } - - goto cc_next_loop; - - cc_check_done: - - // skip digit value. - if (isdigit(keyword[0]) || keyword[0] == '"') { - goto cc_next_loop; - } - - while (keyword.find(' ') != std::string::npos) keyword.erase(keyword.find(' '), 1); - - for (auto& var : kCompilerVariables) { - if (var.fValue.find(keyword) != std::string::npos) { - err_str.clear(); - goto cc_next; - } - } - - for (auto& fn : kCompilerFunctions) { - if (fn.find(keyword[0]) != std::string::npos) { - auto where_begin = fn.find(keyword[0]); - auto keyword_begin = 0UL; - auto failed = false; - - for (; where_begin < keyword.size(); ++where_begin) { - if (fn[where_begin] == '(' && keyword[keyword_begin] == '(') break; - - if (fn[where_begin] != keyword[keyword_begin]) { - failed = true; - break; - } - - ++keyword_begin; - } - - if (!failed) { - err_str.clear(); - goto cc_next; - } else { - continue; - } - } - } - - cc_error_value: - if (keyword.find("->") != std::string::npos) return err_str; - - if (keyword.find(".") != std::string::npos) return err_str; - - if (isalnum(keyword[0])) err_str += "\nUndefined value: " + keyword; - - return err_str; - } - - cc_next_loop: - continue; - } - -cc_next: - - // extern does not declare anything, it extern_segments a variable. - // so that's why it's not declare upper. - if (LibCompiler::find_word(ln, "extern")) { - auto substr = ln.substr(ln.find("extern") + strlen("extern")); - kCompilerVariables.push_back({.fValue = substr}); - } - - if (kShouldHaveBraces && ln.find('{') == std::string::npos) { - err_str += "Missing '{' for function "; - err_str += kFnName; - err_str += "\n"; - - kShouldHaveBraces = false; - kFnName.clear(); - } else if (kShouldHaveBraces && ln.find('{') != std::string::npos) { - kShouldHaveBraces = false; - kFnName.clear(); - } - - bool type_not_found = true; - - if (ln.find('\'') != std::string::npos) { - ln.replace(ln.find('\''), 3, "0"); - } - - auto first = ln.find('"'); - if (first != std::string::npos) { - auto second = 0UL; - bool found_second_quote = false; - - for (size_t i = first + 1; i < ln.size(); ++i) { - if (ln[i] == '\"') { - found_second_quote = true; - second = i; - - break; - } - } - - if (!found_second_quote) { - err_str += "Missing terminating \"."; - err_str += " here -> " + ln.substr(ln.find('"'), second); - } - } - - if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos) { - if (ln.find('{') == std::string::npos) { - kFnName = ln; - kShouldHaveBraces = true; - - goto skip_braces_check; - } else if (ln.find('{') != std::string::npos) { - kShouldHaveBraces = false; - } - } - -skip_braces_check: - - for (auto& key : kCompilerTypes) { - if (LibCompiler::find_word(ln, key.fName)) { - if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) { - err_str += "\nNumber cannot be set for "; - err_str += key.fName; - err_str += "'s name. here -> "; - err_str += ln; - } - - if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' || - ln[ln.find(key.fName) - 1] == '\t') { - type_not_found = false; - - if (ln[ln.find(key.fName) + key.fName.size()] != ' ') { - type_not_found = true; - - if (ln[ln.find(key.fName) + key.fName.size()] == '\t') type_not_found = false; - - goto next; - } else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') { - type_not_found = true; - - if (ln[ln.find(key.fName) + key.fName.size()] == ' ') type_not_found = false; - } - } - - next: - - if (ln.find(';') == std::string::npos) { - if (ln.find('(') != std::string::npos) { - if (ln.find('=') == std::string::npos) continue; - } - - err_str += "\nMissing ';', here -> "; - err_str += ln; - } else { - continue; - } - - if (ln.find('=') != std::string::npos) { - if (ln.find('(') != std::string::npos) { - if (ln.find(')') == std::string::npos) { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } - } - } - } - } - - if (kInBraces && ln.find("struct") != std::string::npos && - ln.find("union") != std::string::npos && ln.find("enum") != std::string::npos && - ln.find('=') != std::string::npos) { - if (ln.find(';') == std::string::npos) { - err_str += "\nMissing ';' after struct/union/enum declaration, here -> "; - err_str += ln; - } - } - - if (ln.find(';') != std::string::npos && ln.find("for") == std::string::npos) { - if (ln.find(';') + 1 != ln.size()) { - for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) { - if ((ln.substr(ln.find(';') + 1)[i] != ' ') || (ln.substr(ln.find(';') + 1)[i] != '\t')) { - if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); !err.empty()) { - err_str += "\nUnexpected text after ';' -> "; - err_str += ln.substr(ln.find(';')); - err_str += err; - } - } - } - } - } - - if (ln.find('(') != std::string::npos) { - if (ln.find(';') == std::string::npos && !LibCompiler::find_word(ln, "|") && - !LibCompiler::find_word(ln, "||") && !LibCompiler::find_word(ln, "&") && - !LibCompiler::find_word(ln, "&&") && !LibCompiler::find_word(ln, "~")) { - bool found_func = false; - size_t i = ln.find('('); - std::vector<char> opens; - std::vector<char> closes; - - for (; i < ln.size(); ++i) { - if (ln[i] == ')') { - closes.push_back(1); - } - - if (ln[i] == '(') { - opens.push_back(1); - } - } - - if (closes.size() != opens.size()) err_str += "Unterminated (), here -> " + ln; - - bool space_found = false; - - for (int i = 0; i < ln.size(); ++i) { - if (ln[i] == ')' && !space_found) { - space_found = true; - continue; - } - - if (space_found) { - if (ln[i] == ' ' && isalnum(ln[i + 1])) { - err_str += "\nBad function format here -> "; - err_str += ln; - } - } - } - } - - if (ln.find('(') < 1) { - err_str += "\nMissing identifier before '(' here -> "; - err_str += ln; - } else { - if (type_not_found && ln.find(';') == std::string::npos && - ln.find("if") == std::string::npos && ln.find("|") == std::string::npos && - ln.find("&") == std::string::npos && ln.find("(") == std::string::npos && - ln.find(")") == std::string::npos) { - err_str += "\n Missing ';' or type, here -> "; - err_str += ln; - } - } - - if (ln.find(')') == std::string::npos) { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } - } else { - if (ln.find("for") != std::string::npos || ln.find("while") != std::string::npos) { - err_str += "\nMissing '(', after \"for\", here -> "; - err_str += ln; - } - } - - if (ln.find('}') != std::string::npos && !kInBraces) { - if (!kInStruct && ln.find(';') == std::string::npos) { - err_str += "\nMismatched '}', here -> "; - err_str += ln; - } - } - - if (!ln.empty()) { - if (ln.find(';') == std::string::npos && ln.find('{') == std::string::npos && - ln.find('}') == std::string::npos && ln.find(')') == std::string::npos && - ln.find('(') == std::string::npos && ln.find(',') == std::string::npos) { - if (ln.size() <= 2) return err_str; - - err_str += "\nMissing ';', here -> "; - err_str += ln; - } - } - - return err_str; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -/** - * @brief C To Assembly mount-point. - */ - -///////////////////////////////////////////////////////////////////////////////////////// - -class AssemblyCCInterface final ASSEMBLY_INTERFACE { - public: - explicit AssemblyCCInterface() = default; - ~AssemblyCCInterface() override = default; - - LIBCOMPILER_COPY_DEFAULT(AssemblyCCInterface); - - [[maybe_unused]] Int32 Arch() noexcept override { - return LibCompiler::AssemblyFactory::kArchAARCH64; - } - - Int32 CompileToFormat(std::string src, Int32 arch) override { - if (kCompilerFrontend == nullptr) return 1; - - /* @brief copy contents wihtout extension */ - std::string src_file = src.data(); - std::ifstream src_fp = std::ifstream(src_file, std::ios::in); - std::string dest; - - for (auto& ch : src_file) { - if (ch == '.') { - break; - } - - dest += ch; - } - - /* According to PEF ABI. */ - std::vector<const char*> exts = kAsmFileExts; - dest += exts[4]; - - kState.fOutputAssembly = std::make_unique<std::ofstream>(dest); - - auto fmt = LibCompiler::current_date(); - - (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; - (*kState.fOutputAssembly) << "# Language: ARM64 Assembly (Generated from ANSI C)\n"; - (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n"; - - LibCompiler::SyntaxLeafList syntax; - - kState.fSyntaxTreeList.push_back(syntax); - kState.fSyntaxTree = &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; - - std::string line_src; - - while (std::getline(src_fp, line_src)) { - if (auto err = kCompilerFrontend->Check(line_src.c_str(), src.data()); err.empty()) { - kCompilerFrontend->Compile(line_src, src.data()); - } else { - Detail::print_error(err, src.data()); - } - } - - if (kAcceptableErrors > 0) return 1; - - std::vector<std::string> keywords = {"ldw", "stw", "lda", "sta", "add", "sub", "mv"}; - - /// - /// Replace, optimize, fix assembly output. - /// - - for (auto& leaf : kState.fSyntaxTree->fLeafList) { - std::vector<std::string> access_keywords = {"->", "."}; - - for (auto& access_ident : access_keywords) { - if (LibCompiler::find_word(leaf.fUserValue, access_ident)) { - for (auto& struc : kState.kStructMap) { - /// TODO: - } - } - } - - for (auto& keyword : keywords) { - if (LibCompiler::find_word(leaf.fUserValue, keyword)) { - std::size_t cnt = 0UL; - - for (auto& reg : kState.kStackFrame) { - std::string needle; - - for (size_t i = 0; i < reg.fName.size(); i++) { - if (reg.fName[i] == ' ') { - ++i; - - for (; i < reg.fName.size(); i++) { - if (reg.fName[i] == ',') { - break; - } - - if (reg.fName[i] == ' ') continue; - - needle += reg.fName[i]; - } - - break; - } - } - - if (LibCompiler::find_word(leaf.fUserValue, needle)) { - if (leaf.fUserValue.find("extern_segment " + needle) != std::string::npos) { - std::string range = "extern_segment " + needle; - leaf.fUserValue.replace(leaf.fUserValue.find("extern_segment " + needle), - range.size(), needle); - } - - if (leaf.fUserValue.find("ldw r6") != std::string::npos) { - std::string::difference_type countComma = - std::count(leaf.fUserValue.begin(), leaf.fUserValue.end(), ','); - - if (countComma == 1) { - leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), strlen("ldw"), "mv"); - } - } - - leaf.fUserValue.replace(leaf.fUserValue.find(needle), needle.size(), reg.fReg); - - ++cnt; - } - } - - if (cnt > 1 && keyword != "mv" && keyword != "add" && keyword != "sub") { - leaf.fUserValue.replace(leaf.fUserValue.find(keyword), keyword.size(), "mv"); - } - } - } - } - - for (auto& leaf : kState.fSyntaxTree->fLeafList) { - (*kState.fOutputAssembly) << leaf.fUserValue; - } - - kState.fSyntaxTree = nullptr; - - kState.fOutputAssembly->flush(); - kState.fOutputAssembly.reset(); - - return kExitOK; - } -}; - -///////////////////////////////////////////////////////////////////////////////////////// - -#include <LibCompiler/Version.h> - -#define kPrintF printf -#define kSplashCxx() kPrintF(kWhite "NE C Driver, %s, (c) Amlal El Mahrouss\n", kDistVersion) - -static void cc_print_help() { - kSplashCxx(); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -#define kCExtension ".c" - -LIBCOMPILER_MODULE(NeOSCompilerCLangARM64) { - ::signal(SIGSEGV, Detail::segfault_handler); - - kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); - kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); - kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); - kCompilerTypes.push_back({.fName = "int", .fValue = "dword"}); - kCompilerTypes.push_back({.fName = "long", .fValue = "qword"}); - kCompilerTypes.push_back({.fName = "*", .fValue = "offset"}); - - bool skip = false; - - kFactory.Mount(new AssemblyCCInterface()); - kMachine = LibCompiler::AssemblyFactory::kArchAARCH64; - kCompilerFrontend = new CompilerFrontendARM64(); - - for (auto index = 1UL; index < argc; ++index) { - if (skip) { - skip = false; - continue; - } - - if (argv[index][0] == '-') { - if (strcmp(argv[index], "--v") == 0 || strcmp(argv[index], "--version") == 0) { - kSplashCxx(); - return kExitOK; - } - - if (strcmp(argv[index], "--verbose") == 0) { - kState.fVerbose = true; - - continue; - } - - if (strcmp(argv[index], "--h") == 0 || strcmp(argv[index], "--help") == 0) { - cc_print_help(); - - return kExitOK; - } - - if (strcmp(argv[index], "--dialect") == 0) { - if (kCompilerFrontend) std::cout << kCompilerFrontend->Language() << "\n"; - - return kExitOK; - } - - if (strcmp(argv[index], "--fmax-exceptions") == 0) { - try { - kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); - } - // catch anything here - catch (...) { - kErrorLimit = 0; - } - - skip = true; - - continue; - } - - std::string err = "Unknown command: "; - err += argv[index]; - - Detail::print_error(err, "cc"); - - continue; - } - - kFileList.emplace_back(argv[index]); - - std::string srcFile = argv[index]; - - if (strstr(argv[index], kCExtension) == nullptr) { - if (kState.fVerbose) { - Detail::print_error(srcFile + " is not a valid C source.\n", "cc"); - } - - return 1; - } - - if (kFactory.Compile(srcFile, kMachine) != kExitOK) return 1; - } - - return kExitOK; -} - -// Last rev 8-1-24 diff --git a/dev/LibCompiler/src/CCompilerPower64.cc b/dev/LibCompiler/src/CCompilerPower64.cc deleted file mode 100644 index f2eba43..0000000 --- a/dev/LibCompiler/src/CCompilerPower64.cc +++ /dev/null @@ -1,1305 +0,0 @@ -/* - * ======================================================== - * - * CompilerPower64 - * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. - * - * ======================================================== - */ - -#include <LibCompiler/Backend/PowerPC.h> -#include <LibCompiler/Detail/ClUtils.h> -#include <LibCompiler/Parser.h> -#include <LibCompiler/UUID.h> -#include <cstdio> -#include <fstream> -#include <iostream> -#include <memory> -#include <random> -#include <string> -#include <utility> -#include <vector> - -#define kExitOK 0 - -/// @author EL Mahrouss Amlal (amlal@nekernel.org) -/// @file cc.cxx -/// @brief POWER64 C Compiler. - -///////////////////// - -/// ANSI ESCAPE CODES - -///////////////////// - -#define kBlank "\e[0;30m" -#define kRed "\e[0;31m" -#define kWhite "\e[0;97m" - -///////////////////////////////////// - -/// INTERNAL STRUCTURES OF THE C COMPILER - -///////////////////////////////////// - -namespace Detail { -// \brief name to register struct. -struct CompilerRegisterMap final { - std::string fName; - std::string fReg; -}; - -// \brief Map for C structs -// \author amlel -struct CompilerStructMap final { - /// 'struct::my_foo' - std::string fName; - - /// if instance: stores a valid register. - std::string fReg; - - /// offset count - std::size_t fOffsetsCnt; - - /// offset array. - std::vector<std::pair<Int32, std::string>> fOffsets; -}; - -struct CompilerState final { - std::vector<LibCompiler::SyntaxLeafList> fSyntaxTreeList; - std::vector<CompilerRegisterMap> kStackFrame; - std::vector<CompilerStructMap> kStructMap; - LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr}; - std::unique_ptr<std::ofstream> fOutputAssembly; - std::string fLastFile; - std::string fLastError; - bool fVerbose; -}; -} // namespace Detail - -static Detail::CompilerState kState; -static std::string kIfFunction = ""; - -namespace Detail { -/// @brief prints an error into stdout. -/// @param reason the reason of the error. -/// @param file where does it originate from? -void print_error(std::string reason, std::string file) noexcept; - -struct CompilerType final { - std::string fName; - std::string fValue; -}; -} // namespace Detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// Target architecture. -static int kMachine = 0; - -///////////////////////////////////////// - -// REGISTERS ACCORDING TO USED ASSEMBLER - -///////////////////////////////////////// - -static size_t kRegisterCnt = kAsmRegisterLimit; -static size_t kStartUsable = 2; -static size_t kUsableLimit = 15; -static size_t kRegisterCounter = kStartUsable; -static std::string kRegisterPrefix = kAsmRegisterPrefix; - -///////////////////////////////////////// - -// COMPILER PARSING UTILITIES/STATES. - -///////////////////////////////////////// - -static std::vector<std::string> kFileList; -static LibCompiler::AssemblyFactory kFactory; -static bool kInStruct = false; -static bool kOnWhileLoop = false; -static bool kOnForLoop = false; -static bool kInBraces = false; -static bool kIfFound = false; -static size_t kBracesCount = 0UL; - -/* @brief C compiler backend for C */ -class CompilerFrontendPower64 final : public LibCompiler::ICompilerFrontend { - public: - explicit CompilerFrontendPower64() = default; - ~CompilerFrontendPower64() override = default; - - LIBCOMPILER_COPY_DEFAULT(CompilerFrontendPower64); - - std::string Check(const char* text, const char* file); - bool Compile(std::string text, std::string file) override; - - const char* Language() override { return "POWER C"; } -}; - -static CompilerFrontendPower64* kCompilerFrontend = nullptr; -static std::vector<Detail::CompilerType> kCompilerVariables; -static std::vector<std::string> kCompilerFunctions; -static std::vector<Detail::CompilerType> kCompilerTypes; - -namespace Detail { -union number_cast final { - public: - number_cast(UInt64 _Raw) : _Raw(_Raw) {} - - public: - char _Num[8]; - UInt64 _Raw; -}; - -union double_cast final { - public: - double_cast(float _Raw) : _Raw(_Raw) {} - - public: - char _Sign; - char _Lh[8]; - char _Rh[23]; - - float _Raw; -}; -} // namespace Detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// @name Compile -// @brief Generate MASM from a C assignement. - -///////////////////////////////////////////////////////////////////////////////////////// - -bool CompilerFrontendPower64::Compile(std::string text_, std::string file) { - std::string text = text_; - - bool typeFound = false; - bool fnFound = false; - - // setup generator. - std::random_device rd; - - auto seed_data = std::array<int, std::mt19937::state_size>{}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); - std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); - std::mt19937 generator(seq); - - // start parsing - for (size_t text_index = 0; text_index < text.size(); ++text_index) { - auto syntax_leaf = LibCompiler::SyntaxLeafList::SyntaxLeaf(); - - auto gen = uuids::uuid_random_generator{generator}; - uuids::uuid out = gen(); - - Detail::number_cast time_off = (UInt64) out.as_bytes().data(); - - if (!typeFound) { - auto substr = text.substr(text_index); - std::string match_type; - - for (size_t y = 0; y < substr.size(); ++y) { - if (substr[y] == ' ') { - while (match_type.find(' ') != std::string::npos) { - match_type.erase(match_type.find(' ')); - } - - for (auto& clType : kCompilerTypes) { - if (clType.fName == match_type) { - match_type.clear(); - - std::string buf; - - buf += clType.fValue; - buf += ' '; - - if (substr.find('=') != std::string::npos) { - break; - } - - if (text.find('(') != std::string::npos) { - syntax_leaf.fUserValue = buf; - - kState.fSyntaxTree->fLeafList.push_back(syntax_leaf); - } - - typeFound = true; - break; - } - } - - break; - } - - match_type += substr[y]; - } - } - - if (text[text_index] == '{') { - if (kInStruct) { - continue; - } - - kInBraces = true; - ++kBracesCount; - - kState.fSyntaxTree->fLeafList.push_back(syntax_leaf); - } - - // return keyword handler - if (text[text_index] == 'r') { - std::string return_keyword; - return_keyword += "return"; - - std::size_t index = 0UL; - - std::string value; - - for (size_t return_index = text_index; return_index < text.size(); ++return_index) { - if (text[return_index] != return_keyword[index]) { - for (size_t value_index = return_index; value_index < text.size(); ++value_index) { - if (text[value_index] == ';') break; - - value += text[value_index]; - } - - break; - } - - ++index; - } - - if (index == return_keyword.size()) { - if (!value.empty()) { - if (value.find('(') != std::string::npos) { - value.erase(value.find('(')); - } - - if (!isdigit(value[value.find('(') + 2])) { - std::string tmp = value; - bool reg_to_reg = false; - - value.clear(); - - value += " extern_segment"; - value += tmp; - } - - syntax_leaf.fUserValue = "\tmr r31, "; - - // make it pretty. - while (value.find('\t') != std::string::npos) value.erase(value.find('\t'), 1); - - while (value.find(' ') != std::string::npos) value.erase(value.find(' '), 1); - - while (value.find("extern_segment") != std::string::npos) - value.erase(value.find("extern_segment"), strlen("extern_segment")); - - bool found = false; - - for (auto& reg : kState.kStackFrame) { - if (value.find(reg.fName) != std::string::npos) { - found = true; - syntax_leaf.fUserValue += reg.fReg; - break; - } - } - - if (!found) syntax_leaf.fUserValue += "r0"; - } - - syntax_leaf.fUserValue += "\n\tblr"; - - kState.fSyntaxTree->fLeafList.push_back(syntax_leaf); - - break; - } - } - - if (text[text_index] == 'i' && text[text_index + 1] == 'f') { - auto expr = text.substr(text_index + 2); - text.erase(text_index, 2); - - if (expr.find("{") != std::string::npos) { - expr.erase(expr.find("{")); - } - - if (expr.find("(") != std::string::npos) expr.erase(expr.find("(")); - - if (expr.find(")") != std::string::npos) expr.erase(expr.find(")")); - - kIfFunction = "__LIBCOMPILER_IF_PROC_"; - kIfFunction += std::to_string(time_off._Raw); - - syntax_leaf.fUserValue = - "\tcmpw " - "r10, r11"; - - syntax_leaf.fUserValue += "\n\tbeq extern_segment " + kIfFunction + - " \ndword public_segment .code64 " + kIfFunction + "\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntax_leaf); - - kIfFound = true; - } - - // Parse expressions and instructions here. - // what does this mean? - // we encounter an assignment, or we reached the end of an expression. - if (text[text_index] == '=' || text[text_index] == ';') { - if (fnFound) continue; - if (kIfFound) continue; - - if (text[text_index] == ';' && kInStruct) continue; - - if (text.find("typedef ") != std::string::npos) continue; - - if (text[text_index] == '=' && kInStruct) { - Detail::print_error("assignement of value inside a struct " + text, file); - continue; - } - - if (text[text_index] == ';' && kInStruct) { - bool space_found_ = false; - std::string sym; - - for (auto& ch : text) { - if (ch == ' ') { - space_found_ = true; - } - - if (ch == ';') break; - - if (space_found_) sym.push_back(ch); - } - - kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back( - std::make_pair(kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, sym)); - - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt = - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4; - - continue; - } - - if (text[text_index] == '=' && kInStruct) { - continue; - } - - if (text[text_index + 1] == '=' || text[text_index - 1] == '!' || - text[text_index - 1] == '<' || text[text_index - 1] == '>') { - continue; - } - - std::string substr; - - if (text.find('=') != std::string::npos && kInBraces && !kIfFound) { - if (text.find("*") != std::string::npos) { - if (text.find("=") > text.find("*")) - substr += "\tli "; - else - substr += "\tli "; - } else { - substr += "\tli "; - } - } else if (text.find('=') != std::string::npos && !kInBraces) { - substr += "stw public_segment .data64 "; - } - - int first_encountered = 0; - - std::string str_name; - - for (size_t text_index_2 = 0; text_index_2 < text.size(); ++text_index_2) { - if (text[text_index_2] == '\"') { - ++text_index_2; - - // want to add this, so that the parser recognizes that this is a - // string. - substr += '"'; - - for (; text_index_2 < text.size(); ++text_index_2) { - if (text[text_index_2] == '\"') break; - - substr += text[text_index_2]; - } - } - - if (text[text_index_2] == '{' || text[text_index_2] == '}') continue; - - if (text[text_index_2] == ';') { - break; - } - - if (text[text_index_2] == ' ' || text[text_index_2] == '\t') { - if (first_encountered != 2) { - if (text[text_index] != '=' && - substr.find("public_segment .data64") == std::string::npos && !kInStruct) - substr += "public_segment .data64 "; - } - - ++first_encountered; - - continue; - } - - if (text[text_index_2] == '=') { - if (!kInBraces) { - substr.replace(substr.find("public_segment .data64"), strlen("public_segment .data64"), - "public_segment .zero64 "); - } - - substr += ","; - continue; - } - - substr += text[text_index_2]; - } - - for (auto& clType : kCompilerTypes) { - if (substr.find(clType.fName) != std::string::npos) { - if (substr.find(clType.fName) > substr.find('"')) continue; - - substr.erase(substr.find(clType.fName), clType.fName.size()); - } else if (substr.find(clType.fValue) != std::string::npos) { - if (substr.find(clType.fValue) > substr.find('"')) continue; - - if (clType.fName == "const") continue; - - substr.erase(substr.find(clType.fValue), clType.fValue.size()); - } - } - - if (substr.find("extern") != std::string::npos) { - substr.replace(substr.find("extern"), strlen("extern"), "extern_segment "); - - if (substr.find("public_segment .data64") != std::string::npos) - substr.erase(substr.find("public_segment .data64"), strlen("public_segment .data64")); - } - - auto var_to_find = std::find_if( - kCompilerVariables.cbegin(), kCompilerVariables.cend(), - [&](Detail::CompilerType type) { return type.fName.find(substr) != std::string::npos; }); - - kCompilerVariables.push_back({.fName = substr}); - - if (text[text_index] == ';') break; - - std::string reg = kAsmRegisterPrefix; - - ++kRegisterCounter; - reg += std::to_string(kRegisterCounter); - - auto newSubstr = substr.substr(substr.find(" ")); - - std::string symbol; - - for (size_t start = 0; start < newSubstr.size(); ++start) { - if (newSubstr[start] == ',') break; - - if (newSubstr[start] == ' ') continue; - - symbol += (newSubstr[start]); - } - - kState.kStackFrame.push_back({.fName = symbol, .fReg = reg}); - - syntax_leaf.fUserValue += "\n\tli " + reg + substr.substr(substr.find(',')); - kState.fSyntaxTree->fLeafList.push_back(syntax_leaf); - } - - // function handler. - - if (text[text_index] == '(' && !fnFound && !kIfFound) { - std::string substr; - std::string args_buffer; - std::string args; - - bool type_crossed = false; - - for (size_t idx = text.find('(') + 1; idx < text.size(); ++idx) { - if (text[idx] == ',') continue; - - if (text[idx] == ' ') continue; - - if (text[idx] == ')') break; - } - - for (char substr_first_index : text) { - if (substr_first_index != ',') - args_buffer += substr_first_index; - else - args_buffer += '$'; - - if (substr_first_index == ';') { - args_buffer = args_buffer.erase(0, args_buffer.find('(')); - args_buffer = args_buffer.erase(args_buffer.find(';'), 1); - args_buffer = args_buffer.erase(args_buffer.find(')'), 1); - args_buffer = args_buffer.erase(args_buffer.find('('), 1); - - if (!args_buffer.empty()) args += "\tldw r6, "; - - std::string register_type; - std::size_t index = 7UL; - - while (args_buffer.find("$") != std::string::npos) { - register_type = kRegisterPrefix; - register_type += std::to_string(index); - - ++index; - - args_buffer.replace(args_buffer.find('$'), 1, "\n\tldw " + register_type + ","); - } - - args += args_buffer; - args += "\n\tli r31, "; - } - } - - for (char _text_i : text) { - if (_text_i == '\t' || _text_i == ' ') { - if (!type_crossed) { - substr.clear(); - type_crossed = true; - } - - continue; - } - - if (_text_i == '(') break; - - substr += _text_i; - } - - if (kInBraces) { - syntax_leaf.fUserValue = args; - syntax_leaf.fUserValue += substr; - - syntax_leaf.fUserValue += "\n\tblr\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntax_leaf); - - fnFound = true; - } else { - syntax_leaf.fUserValue.clear(); - - syntax_leaf.fUserValue += "public_segment .code64 "; - - syntax_leaf.fUserValue += substr; - syntax_leaf.fUserValue += "\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntax_leaf); - - fnFound = true; - } - - kCompilerFunctions.push_back(text); - } - - if (text[text_index] == '-' && text[text_index + 1] == '-') { - text = text.replace(text.find("--"), strlen("--"), ""); - - for (int _text_i = 0; _text_i < text.size(); ++_text_i) { - if (text[_text_i] == '\t' || text[_text_i] == ' ') text.erase(_text_i, 1); - } - - syntax_leaf.fUserValue += "dec "; - syntax_leaf.fUserValue += text; - - kState.fSyntaxTree->fLeafList.push_back(syntax_leaf); - break; - } - - if (text[text_index] == '}') { - kRegisterCounter = kStartUsable; - - --kBracesCount; - - if (kBracesCount < 1) { - kInBraces = false; - kBracesCount = 0; - } - - if (kIfFound) kIfFound = false; - - if (kInStruct) kInStruct = false; - - kState.fSyntaxTree->fLeafList.push_back(syntax_leaf); - } - - syntax_leaf.fUserValue.clear(); - } - - auto syntax_leaf = LibCompiler::SyntaxLeafList::SyntaxLeaf(); - syntax_leaf.fUserValue = "\n"; - kState.fSyntaxTree->fLeafList.push_back(syntax_leaf); - - return true; -} - -static bool kShouldHaveBraces = false; -static std::string kFnName; - -std::string CompilerFrontendPower64::Check(const char* text, const char* file) { - std::string err_str; - std::string ln = text; - - if (ln.empty()) { - return err_str; - } - - bool non_ascii_found = false; - - for (int i = 0; i < ln.size(); ++i) { - if (isalnum(ln[i])) { - non_ascii_found = true; - break; - } - } - - if (kShouldHaveBraces && ln.find('{') != std::string::npos) { - kShouldHaveBraces = false; - } - - if (!non_ascii_found) return err_str; - - size_t string_index = 1UL; - - if (ln.find('\'') != std::string::npos) { - string_index = ln.find('\'') + 1; - - for (; string_index < ln.size(); ++string_index) { - if (ln[string_index] == '\'') { - if (ln[string_index + 1] != ';') { - ln.erase(string_index, 1); - } - - return err_str; - } - } - } else if (ln.find('"') != std::string::npos) { - string_index = ln.find('"') + 1; - - for (; string_index < ln.size(); ++string_index) { - if (ln[string_index] == '"') { - if (ln[string_index + 1] != ';') { - ln.erase(string_index, 1); - } else { - break; - } - } - } - } else if (ln.find('"') == std::string::npos && ln.find('\'') == std::string::npos) { - std::vector<std::string> forbidden_words; - - forbidden_words.push_back("\\"); - forbidden_words.push_back("?"); - forbidden_words.push_back("@"); - forbidden_words.push_back("~"); - forbidden_words.push_back("::"); - forbidden_words.push_back("--*"); - forbidden_words.push_back("*/"); - - // add them to avoid stupid mistakes. - forbidden_words.push_back("namespace"); - forbidden_words.push_back("class"); - forbidden_words.push_back("extern \"C\""); - - for (auto& forbidden : forbidden_words) { - if (ln.find(forbidden) != std::string::npos) { - err_str += "\nForbidden character detected: "; - err_str += forbidden; - - return err_str; - } - } - } - - struct CompilerVariableRange final { - std::string fBegin; - std::string fEnd; - }; - - const std::vector<CompilerVariableRange> variables_list = { - {.fBegin = "static ", .fEnd = "="}, {.fBegin = "=", .fEnd = ";"}, - {.fBegin = "if(", .fEnd = "="}, {.fBegin = "if (", .fEnd = "="}, - {.fBegin = "if(", .fEnd = "<"}, {.fBegin = "if (", .fEnd = "<"}, - {.fBegin = "if(", .fEnd = ">"}, {.fBegin = "if (", .fEnd = ">"}, - {.fBegin = "if(", .fEnd = ")"}, {.fBegin = "if (", .fEnd = ")"}, - - {.fBegin = "else(", .fEnd = "="}, {.fBegin = "else (", .fEnd = "="}, - {.fBegin = "else(", .fEnd = "<"}, {.fBegin = "else (", .fEnd = "<"}, - {.fBegin = "else(", .fEnd = ">"}, {.fBegin = "else (", .fEnd = ">"}, - {.fBegin = "else(", .fEnd = ")"}, {.fBegin = "else (", .fEnd = ")"}, - }; - - for (auto& variable : variables_list) { - if (ln.find(variable.fBegin) != std::string::npos) { - string_index = ln.find(variable.fBegin) + variable.fBegin.size(); - - while (ln[string_index] == ' ') ++string_index; - - std::string keyword; - - for (; string_index < ln.size(); ++string_index) { - if (ln[string_index] == variable.fEnd[0]) { - std::string varname = ""; - - for (size_t index_keyword = ln.find(' '); ln[index_keyword] != variable.fBegin[0]; - ++index_keyword) { - if (ln[index_keyword] == ' ') { - continue; - } - - if (isdigit(ln[index_keyword])) { - goto cc_next_loop; - } - - varname += ln[index_keyword]; - } - - if (varname.find(' ') != std::string::npos) { - varname.erase(0, varname.find(' ')); - - if (variable.fBegin == "extern") { - varname.erase(0, varname.find(' ')); - } - } - - if (kRegisterCounter == 5 || kRegisterCounter == 6) ++kRegisterCounter; - - std::string reg = kAsmRegisterPrefix; - reg += std::to_string(kRegisterCounter); - - kCompilerVariables.push_back({.fValue = varname}); - goto cc_check_done; - } - - keyword.push_back(ln[string_index]); - } - - goto cc_next_loop; - - cc_check_done: - - // skip digit value. - if (isdigit(keyword[0]) || keyword[0] == '"') { - goto cc_next_loop; - } - - while (keyword.find(' ') != std::string::npos) keyword.erase(keyword.find(' '), 1); - - for (auto& var : kCompilerVariables) { - if (var.fValue.find(keyword) != std::string::npos) { - err_str.clear(); - goto cc_next; - } - } - - for (auto& fn : kCompilerFunctions) { - if (fn.find(keyword[0]) != std::string::npos) { - auto where_begin = fn.find(keyword[0]); - auto keyword_begin = 0UL; - auto failed = false; - - for (; where_begin < keyword.size(); ++where_begin) { - if (fn[where_begin] == '(' && keyword[keyword_begin] == '(') break; - - if (fn[where_begin] != keyword[keyword_begin]) { - failed = true; - break; - } - - ++keyword_begin; - } - - if (!failed) { - err_str.clear(); - goto cc_next; - } else { - continue; - } - } - } - - cc_error_value: - if (keyword.find("->") != std::string::npos) return err_str; - - if (keyword.find(".") != std::string::npos) return err_str; - - if (isalnum(keyword[0])) err_str += "\nUndefined value: " + keyword; - - return err_str; - } - - cc_next_loop: - continue; - } - -cc_next: - - // extern does not declare anything, it extern_segments a variable. - // so that's why it's not declare upper. - if (LibCompiler::find_word(ln, "extern")) { - auto substr = ln.substr(ln.find("extern") + strlen("extern")); - kCompilerVariables.push_back({.fValue = substr}); - } - - if (kShouldHaveBraces && ln.find('{') == std::string::npos) { - err_str += "Missing '{' for function "; - err_str += kFnName; - err_str += "\n"; - - kShouldHaveBraces = false; - kFnName.clear(); - } else if (kShouldHaveBraces && ln.find('{') != std::string::npos) { - kShouldHaveBraces = false; - kFnName.clear(); - } - - bool type_not_found = true; - - if (ln.find('\'') != std::string::npos) { - ln.replace(ln.find('\''), 3, "0"); - } - - auto first = ln.find('"'); - if (first != std::string::npos) { - auto second = 0UL; - bool found_second_quote = false; - - for (size_t i = first + 1; i < ln.size(); ++i) { - if (ln[i] == '\"') { - found_second_quote = true; - second = i; - - break; - } - } - - if (!found_second_quote) { - err_str += "Missing terminating \"."; - err_str += " here -> " + ln.substr(ln.find('"'), second); - } - } - - if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos) { - if (ln.find('{') == std::string::npos) { - kFnName = ln; - kShouldHaveBraces = true; - - goto skip_braces_check; - } else if (ln.find('{') != std::string::npos) { - kShouldHaveBraces = false; - } - } - -skip_braces_check: - - for (auto& key : kCompilerTypes) { - if (LibCompiler::find_word(ln, key.fName)) { - if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) { - err_str += "\nNumber cannot be set for "; - err_str += key.fName; - err_str += "'s name. here -> "; - err_str += ln; - } - - if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' || - ln[ln.find(key.fName) - 1] == '\t') { - type_not_found = false; - - if (ln[ln.find(key.fName) + key.fName.size()] != ' ') { - type_not_found = true; - - if (ln[ln.find(key.fName) + key.fName.size()] == '\t') type_not_found = false; - - goto next; - } else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') { - type_not_found = true; - - if (ln[ln.find(key.fName) + key.fName.size()] == ' ') type_not_found = false; - } - } - - next: - - if (ln.find(';') == std::string::npos) { - if (ln.find('(') != std::string::npos) { - if (ln.find('=') == std::string::npos) continue; - } - - err_str += "\nMissing ';', here -> "; - err_str += ln; - } else { - continue; - } - - if (ln.find('=') != std::string::npos) { - if (ln.find('(') != std::string::npos) { - if (ln.find(')') == std::string::npos) { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } - } - } - } - } - - if (kInBraces && ln.find("struct") != std::string::npos && - ln.find("union") != std::string::npos && ln.find("enum") != std::string::npos && - ln.find('=') != std::string::npos) { - if (ln.find(';') == std::string::npos) { - err_str += "\nMissing ';' after struct/union/enum declaration, here -> "; - err_str += ln; - } - } - - if (ln.find(';') != std::string::npos && ln.find("for") == std::string::npos) { - if (ln.find(';') + 1 != ln.size()) { - for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) { - if ((ln.substr(ln.find(';') + 1)[i] != ' ') || (ln.substr(ln.find(';') + 1)[i] != '\t')) { - if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); !err.empty()) { - err_str += "\nUnexpected text after ';' -> "; - err_str += ln.substr(ln.find(';')); - err_str += err; - } - } - } - } - } - - if (ln.find('(') != std::string::npos) { - if (ln.find(';') == std::string::npos && !LibCompiler::find_word(ln, "|") && - !LibCompiler::find_word(ln, "||") && !LibCompiler::find_word(ln, "&") && - !LibCompiler::find_word(ln, "&&") && !LibCompiler::find_word(ln, "~")) { - bool found_func = false; - size_t i = ln.find('('); - std::vector<char> opens; - std::vector<char> closes; - - for (; i < ln.size(); ++i) { - if (ln[i] == ')') { - closes.push_back(1); - } - - if (ln[i] == '(') { - opens.push_back(1); - } - } - - if (closes.size() != opens.size()) err_str += "Unterminated (), here -> " + ln; - - bool space_found = false; - - for (int i = 0; i < ln.size(); ++i) { - if (ln[i] == ')' && !space_found) { - space_found = true; - continue; - } - - if (space_found) { - if (ln[i] == ' ' && isalnum(ln[i + 1])) { - err_str += "\nBad function format here -> "; - err_str += ln; - } - } - } - } - - if (ln.find('(') < 1) { - err_str += "\nMissing identifier before '(' here -> "; - err_str += ln; - } else { - if (type_not_found && ln.find(';') == std::string::npos && - ln.find("if") == std::string::npos && ln.find("|") == std::string::npos && - ln.find("&") == std::string::npos && ln.find("(") == std::string::npos && - ln.find(")") == std::string::npos) { - err_str += "\n Missing ';' or type, here -> "; - err_str += ln; - } - } - - if (ln.find(')') == std::string::npos) { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } - } else { - if (ln.find("for") != std::string::npos || ln.find("while") != std::string::npos) { - err_str += "\nMissing '(', after \"for\", here -> "; - err_str += ln; - } - } - - if (ln.find('}') != std::string::npos && !kInBraces) { - if (!kInStruct && ln.find(';') == std::string::npos) { - err_str += "\nMismatched '}', here -> "; - err_str += ln; - } - } - - if (!ln.empty()) { - if (ln.find(';') == std::string::npos && ln.find('{') == std::string::npos && - ln.find('}') == std::string::npos && ln.find(')') == std::string::npos && - ln.find('(') == std::string::npos && ln.find(',') == std::string::npos) { - if (ln.size() <= 2) return err_str; - - err_str += "\nMissing ';', here -> "; - err_str += ln; - } - } - - return err_str; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -/** - * @brief C To Assembly mount-point. - */ - -///////////////////////////////////////////////////////////////////////////////////////// - -class AssemblyMountpointCLang final ASSEMBLY_INTERFACE { - public: - explicit AssemblyMountpointCLang() = default; - ~AssemblyMountpointCLang() override = default; - - LIBCOMPILER_COPY_DEFAULT(AssemblyMountpointCLang); - - [[maybe_unused]] Int32 Arch() noexcept override { - return LibCompiler::AssemblyFactory::kArchPowerPC; - } - - Int32 CompileToFormat(std::string src, Int32 arch) override { - if (kCompilerFrontend == nullptr) return 1; - - /* @brief copy contents wihtout extension */ - std::string src_file = src.data(); - std::ifstream src_fp = std::ifstream(src_file, std::ios::in); - std::string dest; - - for (auto& ch : src_file) { - if (ch == '.') { - break; - } - - dest += ch; - } - - /* According to PEF ABI. */ - std::vector<const char*> exts = kAsmFileExts; - dest += exts[4]; - - kState.fOutputAssembly = std::make_unique<std::ofstream>(dest); - - auto fmt = LibCompiler::current_date(); - - (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; - (*kState.fOutputAssembly) << "# Language: POWER Assembly (Generated from C)\n"; - (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n"; - - LibCompiler::SyntaxLeafList syntax; - - kState.fSyntaxTreeList.push_back(syntax); - kState.fSyntaxTree = &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; - - std::string line_src; - - while (std::getline(src_fp, line_src)) { - if (auto err = kCompilerFrontend->Check(line_src.c_str(), src.data()); err.empty()) { - kCompilerFrontend->Compile(line_src, src.data()); - } else { - Detail::print_error(err, src.data()); - } - } - - if (kAcceptableErrors > 0) return 1; - - std::vector<std::string> keywords = {"ld", "stw", "add", "sub", "or"}; - - /// - /// Replace, optimize, fix assembly output. - /// - - for (auto& leaf : kState.fSyntaxTree->fLeafList) { - std::vector<std::string> access_keywords = {"->", "."}; - - for (auto& access_ident : access_keywords) { - if (LibCompiler::find_word(leaf.fUserValue, access_ident)) { - for (auto& struc : kState.kStructMap) { - /// TODO: - } - } - } - - for (auto& keyword : keywords) { - if (LibCompiler::find_word(leaf.fUserValue, keyword)) { - std::size_t cnt = 0UL; - - for (auto& reg : kState.kStackFrame) { - std::string needle; - - for (size_t i = 0; i < reg.fName.size(); i++) { - if (reg.fName[i] == ' ') { - ++i; - - for (; i < reg.fName.size(); i++) { - if (reg.fName[i] == ',') { - break; - } - - if (reg.fName[i] == ' ') continue; - - needle += reg.fName[i]; - } - - break; - } - } - - if (LibCompiler::find_word(leaf.fUserValue, needle)) { - if (leaf.fUserValue.find("extern_segment ") != std::string::npos) { - std::string range = "extern_segment "; - leaf.fUserValue.replace(leaf.fUserValue.find(range), range.size(), ""); - } - - if (leaf.fUserValue.find("ldw r6") != std::string::npos) { - std::string::difference_type countComma = - std::count(leaf.fUserValue.begin(), leaf.fUserValue.end(), ','); - - if (countComma == 1) { - leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), strlen("ldw"), "mr"); - } - } - - leaf.fUserValue.replace(leaf.fUserValue.find(needle), needle.size(), reg.fReg); - - ++cnt; - } - } - - if (cnt > 1 && keyword != "mr" && keyword != "add" && keyword != "dec") { - leaf.fUserValue.replace(leaf.fUserValue.find(keyword), keyword.size(), "mr"); - } - } - } - } - - for (auto& leaf : kState.fSyntaxTree->fLeafList) { - (*kState.fOutputAssembly) << leaf.fUserValue; - } - - kState.fSyntaxTree = nullptr; - - kState.fOutputAssembly->flush(); - kState.fOutputAssembly.reset(); - - return kExitOK; - } -}; - -///////////////////////////////////////////////////////////////////////////////////////// - -#include <LibCompiler/Version.h> - -#define kPrintF printf -#define kSplashCxx() kPrintF(kWhite "cc, %s, (c) Amlal El Mahrouss\n", kDistVersion) - -static void cc_print_help() { - kSplashCxx(); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -#define kExt ".c" - -LIBCOMPILER_MODULE(NeOSCompilerCLangPowerPC) { - ::signal(SIGSEGV, Detail::segfault_handler); - - kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); - kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); - kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); - kCompilerTypes.push_back({.fName = "int", .fValue = "dword"}); - kCompilerTypes.push_back({.fName = "long", .fValue = "qword"}); - kCompilerTypes.push_back({.fName = "*", .fValue = "offset"}); - - bool skip = false; - - kFactory.Mount(new AssemblyMountpointCLang()); - kMachine = LibCompiler::AssemblyFactory::kArchPowerPC; - kCompilerFrontend = new CompilerFrontendPower64(); - - for (auto index = 1UL; index < argc; ++index) { - if (skip) { - skip = false; - continue; - } - - if (argv[index][0] == '-') { - if (strcmp(argv[index], "-v") == 0 || strcmp(argv[index], "-version") == 0) { - kSplashCxx(); - return kExitOK; - } - - if (strcmp(argv[index], "-verbose") == 0) { - kState.fVerbose = true; - - continue; - } - - if (strcmp(argv[index], "-h") == 0 || strcmp(argv[index], "-help") == 0) { - cc_print_help(); - - return kExitOK; - } - - if (strcmp(argv[index], "-dialect") == 0) { - if (kCompilerFrontend) std::cout << kCompilerFrontend->Language() << "\n"; - - return kExitOK; - } - - if (strcmp(argv[index], "-fmax-exceptions") == 0) { - try { - kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); - } - // catch anything here - catch (...) { - kErrorLimit = 0; - } - - skip = true; - - continue; - } - - std::string err = "Unknown command: "; - err += argv[index]; - - Detail::print_error(err, "cc"); - - continue; - } - - kFileList.emplace_back(argv[index]); - - std::string srcFile = argv[index]; - - if (strstr(argv[index], kExt) == nullptr) { - if (kState.fVerbose) { - Detail::print_error(srcFile + " is not a valid C source.\n", "cc"); - } - - return 1; - } - - if (kFactory.Compile(srcFile, kMachine) != kExitOK) return 1; - } - - return kExitOK; -} - -// Last rev 8-1-24 diff --git a/dev/LibCompiler/src/AssemblyFactory+AssemblyInterface.cc b/dev/LibCompiler/src/CodeGen.cc index 11655fb..3f215c5 100644 --- a/dev/LibCompiler/src/AssemblyFactory+AssemblyInterface.cc +++ b/dev/LibCompiler/src/CodeGen.cc @@ -1,10 +1,10 @@ /* ------------------------------------------- - Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + Copyright (C) 2024-2025 Amlal EL Mahrouss, all rights reserved ------------------------------------------- */ -#include <LibCompiler/AssemblyInterface.h> +#include <LibCompiler/CodeGen.h> #include <LibCompiler/ErrorID.h> /** @@ -23,12 +23,17 @@ namespace LibCompiler { ///! @brief Compile for specific format (ELF, PEF, ZBIN) -Int32 AssemblyFactory::Compile(std::string sourceFile, const Int32& arch) noexcept { - if (sourceFile.length() < 1 || !fMounted) return LIBCOMPILER_UNIMPLEMENTED; +Int32 AssemblyFactory::Compile(STLString sourceFile, const Int32& arch) noexcept { + if (sourceFile.length() < 1) return LIBCOMPILER_UNIMPLEMENTED; + if (!fMounted) return LIBCOMPILER_UNIMPLEMENTED; if (arch != fMounted->Arch()) return LIBCOMPILER_INVALID_ARCH; - return fMounted->CompileToFormat(sourceFile, arch); + try { + return this->fMounted->CompileToFormat(sourceFile, arch); + } catch (std::exception& e) { + return LIBCOMPILER_EXEC_ERROR; + } } ///! @brief mount assembly backend. @@ -42,7 +47,7 @@ void AssemblyFactory::Mount(AssemblyInterface* mountPtr) noexcept { AssemblyInterface* AssemblyFactory::Unmount() noexcept { auto mount_prev = fMounted; - if (mount_prev) { + if (fMounted) { fMounted = nullptr; } diff --git a/dev/LibCompiler/src/Frontend.cc b/dev/LibCompiler/src/Frontend.cc new file mode 100644 index 0000000..69ff6fd --- /dev/null +++ b/dev/LibCompiler/src/Frontend.cc @@ -0,0 +1,51 @@ +/* ------------------------------------------- + + Copyright (C) 2025 Amlal EL Mahrouss, all rights reserved + +------------------------------------------- */ + +#include <LibCompiler/Frontend.h> + +namespace LibCompiler { +/// find the perfect matching word in a haystack. +/// \param haystack base string +/// \param needle the string we search for. +/// \return if we found it or not. +bool find_word(std::string haystack, std::string needle) noexcept { + auto index = haystack.find(needle); + + // check for needle validity. + if (index == std::string::npos) return false; + + // declare lambda + auto not_part_of_word = [&](int index) { + if (std::isspace(haystack[index]) || std::ispunct(haystack[index])) return true; + + if (index <= 0 || index >= haystack.size()) return true; + + return false; + }; + + return not_part_of_word(index - 1) && not_part_of_word(index + needle.size()); +} + +/// find a word within strict conditions and returns a range of it. +/// \param haystack +/// \param needle +/// \return position of needle. +std::size_t find_word_range(std::string haystack, std::string needle) noexcept { + auto index = haystack.find(needle); + + // check for needle validity. + if (index == std::string::npos) return false; + + if (!isalnum((haystack[index + needle.size() + 1])) && + !isdigit(haystack[index + needle.size() + 1]) && + !isalnum((haystack[index - needle.size() - 1])) && + !isdigit(haystack[index - needle.size() - 1])) { + return index; + } + + return std::string::npos; +} +} // namespace LibCompiler
\ No newline at end of file diff --git a/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc b/dev/LibCompiler/src/Frontend/CompilerCPlusPlusAMD64.cc index ace6d17..df9035d 100644 --- a/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc +++ b/dev/LibCompiler/src/Frontend/CompilerCPlusPlusAMD64.cc @@ -16,14 +16,12 @@ // extern_segment, @autodelete { ... }, fn foo() -> auto { ... } -#include <LibCompiler/Backend/Amd64.h> -#include <LibCompiler/Detail/ClUtils.h> -#include <LibCompiler/Parser.h> +#include <LibCompiler/Backend/X64.h> +#include <LibCompiler/Frontend.h> #include <LibCompiler/UUID.h> +#include <LibCompiler/Util/CompilerUtils.h> -#include <cstdio> - -/* NE C++ Compiler */ +/* NeKernel C++ Compiler Driver */ /* This is part of the LibCompiler. */ /* (c) Amlal El Mahrouss */ @@ -69,29 +67,23 @@ std::filesystem::path expand_home(const std::filesystem::path& p) { } struct CompilerRegisterMap final { - std::string fName; - std::string fReg; + LibCompiler::STLString fName; + LibCompiler::STLString fReg; }; -// \brief Offset based struct/class +/// \brief Offset based struct/class struct CompilerStructMap final { - std::string fName; - std::string fReg; - - // offset counter - std::size_t fOffsetsCnt; - - // offset array - std::vector<std::pair<Int32, std::string>> fOffsets; + 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; - std::string fOutputValue; - std::string fLastFile; - std::string fLastError; - Boolean fVerbose; + LibCompiler::STLString fLastFile; + LibCompiler::STLString fLastError; }; } // namespace Detail @@ -99,22 +91,10 @@ static Detail::CompilerState kState; static Int32 kOnClassScope = 0; -namespace Detail { -/// @brief prints an error into stdout. -/// @param reason the reason of the error. -/// @param file where does it originate from? -void print_error(std::string reason, std::string file) noexcept; - -struct CompilerType final { - std::string fName; - std::string fValue; -}; -} // namespace Detail - ///////////////////////////////////////////////////////////////////////////////////////// // Target architecture. -static int kMachine = LibCompiler::AssemblyFactory::kArchAMD64; +static Int32 kMachine = LibCompiler::AssemblyFactory::kArchAMD64; ///////////////////////////////////////// @@ -122,10 +102,6 @@ static int kMachine = LibCompiler::AssemblyFactory::kArchAMD64; ///////////////////////////////////////// -static size_t kRegisterCnt = kAsmRegisterLimit; -static size_t kStartUsable = 8; -static size_t kUsableLimit = 15; -static size_t kRegisterCounter = kStartUsable; static std::vector<LibCompiler::CompilerKeyword> kKeywords; ///////////////////////////////////////// @@ -141,15 +117,16 @@ static Boolean kOnForLoop = false; static Boolean kInBraces = false; static size_t kBracesCount = 0UL; -/* @brief C++ compiler backend for the NE C++ driver */ -class CompilerFrontendCPlusPlus final : public LibCompiler::ICompilerFrontend { +/* @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); - Boolean Compile(const std::string text, std::string file) override; + LibCompiler::SyntaxLeafList::SyntaxLeaf Compile(const LibCompiler::STLString text, + LibCompiler::STLString file) override; const char* Language() override; }; @@ -158,15 +135,15 @@ class CompilerFrontendCPlusPlus final : public LibCompiler::ICompilerFrontend { static CompilerFrontendCPlusPlus* kCompilerFrontend = nullptr; -static std::vector<std::string> kRegisterMap; +static std::vector<LibCompiler::STLString> kRegisterMap; -static std::vector<std::string> kRegisterList = { +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<std::string> kRegisterConventionCallList = { +static std::vector<LibCompiler::STLString> kRegisterConventionCallList = { "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", }; @@ -178,8 +155,8 @@ const char* CompilerFrontendCPlusPlus::Language() { return "AMD64 C++"; } -static std::uintptr_t kOrigin = 0x1000000; -static std::vector<std::pair<std::string, std::uintptr_t>> kOriginMap; +static std::uintptr_t kOrigin = 0x1000000; +static std::vector<std::pair<LibCompiler::STLString, std::uintptr_t>> kOriginMap; ///////////////////////////////////////////////////////////////////////////////////////// @@ -188,8 +165,11 @@ static std::vector<std::pair<std::string, std::uintptr_t>> kOriginMap; ///////////////////////////////////////////////////////////////////////////////////////// -Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { - if (text.empty()) return false; +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; @@ -204,16 +184,22 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { break; } - if (text[text.find(keyword.keyword_name) - 1] == '+' && - keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign) + 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 (text[text.find(keyword.keyword_name) - 1] == '-' && - keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign) + if (pos > 0 && text[pos - 1] == '-' && + keyword.keyword_kind == LibCompiler::kKeywordKindVariableAssign) continue; - if (text[text.find(keyword.keyword_name) + 1] == '=' && - keyword.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableAssign) + // 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)); @@ -221,20 +207,29 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { } } - LibCompiler::SyntaxLeafList::SyntaxLeaf syntax_tree; - 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: { - auto expr = text.substr( - text.find(keyword.first.keyword_name) + keyword.first.keyword_name.size() + 1, - text.find(")") - 1); + 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(">=") != std::string::npos) { + 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("<=")); @@ -272,34 +267,36 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { auto& valueOfVar = !isdigit(left[0]) ? left : right; - for (auto pairRight : kRegisterMap) { - ++indexRight; + 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; + } - 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] + "," + + syntax_tree.fUserValue += "cmp " + kRegisterList[kRegisterMap.size() - 1] + ", " + kRegisterList[indexRight + 1] + "\n"; - goto done_iterarting_on_if; + break; } - - 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: - std::string fnName = text; + LibCompiler::STLString fnName = text; fnName.erase(fnName.find(keyword.first.keyword_name)); for (auto& ch : fnName) { @@ -322,11 +319,11 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { goto accept; dont_accept: - return false; + break; accept: - std::string fnName = text; - size_t indexFnName = 0; + LibCompiler::STLString fnName = text; + size_t indexFnName = 0; // this one is for the type. for (auto& ch : text) { @@ -338,12 +335,12 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { fnName = text.substr(indexFnName); - if (text.find("return ") != std::string::npos) { + if (text.find("return ") != LibCompiler::STLString::npos) { text.erase(0, text.find("return ")); break; } - if (text.ends_with(";") && text.find("return") == std::string::npos) + 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); @@ -359,7 +356,7 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { ++indexFnName; } - if (fnName.find("(") != LibCompiler::String::npos) { + if (fnName.find("(") != LibCompiler::STLString::npos) { fnName.erase(fnName.find("(")); } @@ -371,10 +368,11 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { break; lc_write_assembly: - auto it = std::find_if(kOriginMap.begin(), kOriginMap.end(), - [&fnName](std::pair<std::string, std::uintptr_t> pair) -> bool { - return fnName == pair.first; - }); + 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; @@ -403,7 +401,7 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { case LibCompiler::KeywordKind::kKeywordKindVariableInc: case LibCompiler::KeywordKind::kKeywordKindVariableDec: case LibCompiler::KeywordKind::kKeywordKindVariableAssign: { - std::string valueOfVar = ""; + LibCompiler::STLString valueOfVar = ""; if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc) { valueOfVar = text.substr(text.find("+=") + 2); @@ -417,12 +415,12 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { break; } - while (valueOfVar.find(";") != std::string::npos && + while (valueOfVar.find(";") != LibCompiler::STLString::npos && keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindEndInstr) { valueOfVar.erase(valueOfVar.find(";")); } - std::string varName = text; + LibCompiler::STLString varName = text; if (keyword.first.keyword_kind == LibCompiler::KeywordKind::kKeywordKindVariableInc) { varName.erase(varName.find("+=")); @@ -440,7 +438,7 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { for (auto& keyword : kKeywords) { if (keyword.keyword_kind == LibCompiler::kKeywordKindType) { - if (text.find(keyword.keyword_name) != std::string::npos) { + if (text.find(keyword.keyword_name) != LibCompiler::STLString::npos) { if (text[text.find(keyword.keyword_name)] == ' ') { typeFound = false; continue; @@ -451,7 +449,9 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { } } - std::string instr = "mov "; + LibCompiler::STLString instr = "mov "; + + std::vector<LibCompiler::STLString> newVars; if (typeFound && keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindVariableInc && @@ -460,11 +460,11 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { ++kFunctionEmbedLevel; } - while (varName.find(" ") != std::string::npos) { + while (varName.find(" ") != LibCompiler::STLString::npos) { varName.erase(varName.find(" "), 1); } - while (varName.find("\t") != std::string::npos) { + while (varName.find("\t") != LibCompiler::STLString::npos) { varName.erase(varName.find("\t"), 1); } @@ -527,24 +527,27 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { } Detail::print_error("Variable not declared: " + varName, file); - return false; + break; } done: for (auto& keyword : kKeywords) { if (keyword.keyword_kind == LibCompiler::kKeywordKindType && - varName.find(keyword.keyword_name) != std::string::npos) { + varName.find(keyword.keyword_name) != LibCompiler::STLString::npos) { varName.erase(varName.find(keyword.keyword_name), keyword.keyword_name.size()); break; } } - kRegisterMap.push_back(varName); + newVars.push_back(varName); break; } - if (kKeywords[keyword.second - 1].keyword_kind == LibCompiler::kKeywordKindType || + 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; @@ -562,13 +565,13 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { instr = "sub "; } - std::string varErrCpy = varName; + LibCompiler::STLString varErrCpy = varName; - while (varName.find(" ") != std::string::npos) { + while (varName.find(" ") != LibCompiler::STLString::npos) { varName.erase(varName.find(" "), 1); } - while (varName.find("\t") != std::string::npos) { + while (varName.find("\t") != LibCompiler::STLString::npos) { varName.erase(varName.find("\t"), 1); } @@ -580,11 +583,11 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { valueOfVar.erase(i, 1); } - while (valueOfVar.find(" ") != std::string::npos) { + while (valueOfVar.find(" ") != LibCompiler::STLString::npos) { valueOfVar.erase(valueOfVar.find(" "), 1); } - while (valueOfVar.find("\t") != std::string::npos) { + while (valueOfVar.find("\t") != LibCompiler::STLString::npos) { valueOfVar.erase(valueOfVar.find("\t"), 1); } @@ -622,6 +625,7 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { break; } + newVars.push_back(varName); break; } @@ -629,14 +633,16 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { 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; - std::string subText = text.substr(pos); - subText = subText.erase(subText.find(";")); - size_t indxReg = 0UL; + 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])) { @@ -666,14 +672,14 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { } if (syntax_tree.fUserValue.empty()) { - if (subText.find("(") != std::string::npos) { + if (subText.find("(") != LibCompiler::STLString::npos) { subText.erase(subText.find("(")); - auto it = - std::find_if(kOriginMap.begin(), kOriginMap.end(), - [&subText](std::pair<std::string, std::uintptr_t> pair) -> bool { - return pair.first.find(subText) != std::string::npos; - }); + 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); @@ -699,8 +705,7 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { } } - kState.fOutputValue = syntax_tree.fUserValue; - return true; + return syntax_tree; } ///////////////////////////////////////////////////////////////////////////////////////// @@ -711,39 +716,33 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { ///////////////////////////////////////////////////////////////////////////////////////// -class AssemblyCPlusPlusInterface final ASSEMBLY_INTERFACE { +class AssemblyCPlusPlusInterface final LC_ASSEMBLY_INTERFACE { public: explicit AssemblyCPlusPlusInterface() = default; ~AssemblyCPlusPlusInterface() override = default; LIBCOMPILER_COPY_DEFAULT(AssemblyCPlusPlusInterface); - [[maybe_unused]] Int32 Arch() noexcept override { - return LibCompiler::AssemblyFactory::kArchAMD64; - } + UInt32 Arch() noexcept override { return LibCompiler::AssemblyFactory::kArchAMD64; } - Int32 CompileToFormat(std::string src, Int32 arch) override { + Int32 CompileToFormat(LibCompiler::STLString src, Int32 arch) override { if (kCompilerFrontend == nullptr) return kExitNO; - /* @brief copy contents wihtout extension */ - std::ifstream src_fp = std::ifstream(src, std::ios::in); + LibCompiler::STLString dest = src; + dest += ".pp.masm"; - std::string dest = src; - dest += ".masm"; + std::ofstream out_fp(dest); + std::ifstream src_fp = std::ifstream(src + ".pp"); - std::string line_source; + LibCompiler::STLString line_source; - std::ofstream out(dest); + out_fp << "#bits 64\n"; + out_fp << "#org " << kOrigin << "\n\n"; while (std::getline(src_fp, line_source)) { - kCompilerFrontend->Compile(line_source, src); - out << kState.fOutputValue; + out_fp << kCompilerFrontend->Compile(line_source, src).fUserValue; } - out.flush(); - - if (kAcceptableErrors > 0) return kExitNO; - return kExitOK; } }; @@ -758,87 +757,74 @@ class AssemblyCPlusPlusInterface final ASSEMBLY_INTERFACE { LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) { Boolean skip = false; - kKeywords.push_back({.keyword_name = "if", .keyword_kind = LibCompiler::kKeywordKindIf}); - kKeywords.push_back({.keyword_name = "else", .keyword_kind = LibCompiler::kKeywordKindElse}); - kKeywords.push_back({.keyword_name = "else if", .keyword_kind = LibCompiler::kKeywordKindElseIf}); - - kKeywords.push_back({.keyword_name = "class", .keyword_kind = LibCompiler::kKeywordKindClass}); - kKeywords.push_back({.keyword_name = "struct", .keyword_kind = LibCompiler::kKeywordKindClass}); - kKeywords.push_back( - {.keyword_name = "namespace", .keyword_kind = LibCompiler::kKeywordKindNamespace}); - kKeywords.push_back( - {.keyword_name = "typedef", .keyword_kind = LibCompiler::kKeywordKindTypedef}); - kKeywords.push_back({.keyword_name = "using", .keyword_kind = LibCompiler::kKeywordKindTypedef}); - kKeywords.push_back({.keyword_name = "{", .keyword_kind = LibCompiler::kKeywordKindBodyStart}); - kKeywords.push_back({.keyword_name = "}", .keyword_kind = LibCompiler::kKeywordKindBodyEnd}); - kKeywords.push_back({.keyword_name = "auto", .keyword_kind = LibCompiler::kKeywordKindVariable}); - kKeywords.push_back({.keyword_name = "int", .keyword_kind = LibCompiler::kKeywordKindType}); - kKeywords.push_back({.keyword_name = "Boolean", .keyword_kind = LibCompiler::kKeywordKindType}); - kKeywords.push_back({.keyword_name = "unsigned", .keyword_kind = LibCompiler::kKeywordKindType}); - kKeywords.push_back({.keyword_name = "short", .keyword_kind = LibCompiler::kKeywordKindType}); - kKeywords.push_back({.keyword_name = "char", .keyword_kind = LibCompiler::kKeywordKindType}); - kKeywords.push_back({.keyword_name = "long", .keyword_kind = LibCompiler::kKeywordKindType}); - kKeywords.push_back({.keyword_name = "float", .keyword_kind = LibCompiler::kKeywordKindType}); - kKeywords.push_back({.keyword_name = "double", .keyword_kind = LibCompiler::kKeywordKindType}); - kKeywords.push_back({.keyword_name = "void", .keyword_kind = LibCompiler::kKeywordKindType}); - - kKeywords.push_back( - {.keyword_name = "auto*", .keyword_kind = LibCompiler::kKeywordKindVariablePtr}); - kKeywords.push_back({.keyword_name = "int*", .keyword_kind = LibCompiler::kKeywordKindTypePtr}); - kKeywords.push_back( - {.keyword_name = "Boolean*", .keyword_kind = LibCompiler::kKeywordKindTypePtr}); - kKeywords.push_back( - {.keyword_name = "unsigned*", .keyword_kind = LibCompiler::kKeywordKindTypePtr}); - kKeywords.push_back({.keyword_name = "short*", .keyword_kind = LibCompiler::kKeywordKindTypePtr}); - kKeywords.push_back({.keyword_name = "char*", .keyword_kind = LibCompiler::kKeywordKindTypePtr}); - kKeywords.push_back({.keyword_name = "long*", .keyword_kind = LibCompiler::kKeywordKindTypePtr}); - kKeywords.push_back({.keyword_name = "float*", .keyword_kind = LibCompiler::kKeywordKindTypePtr}); - kKeywords.push_back( - {.keyword_name = "double*", .keyword_kind = LibCompiler::kKeywordKindTypePtr}); - kKeywords.push_back({.keyword_name = "void*", .keyword_kind = LibCompiler::kKeywordKindTypePtr}); - - kKeywords.push_back( - {.keyword_name = "(", .keyword_kind = LibCompiler::kKeywordKindFunctionStart}); - kKeywords.push_back({.keyword_name = ")", .keyword_kind = LibCompiler::kKeywordKindFunctionEnd}); - kKeywords.push_back( - {.keyword_name = "=", .keyword_kind = LibCompiler::kKeywordKindVariableAssign}); - kKeywords.push_back({.keyword_name = "+=", .keyword_kind = LibCompiler::kKeywordKindVariableInc}); - kKeywords.push_back({.keyword_name = "-=", .keyword_kind = LibCompiler::kKeywordKindVariableDec}); - kKeywords.push_back({.keyword_name = "const", .keyword_kind = LibCompiler::kKeywordKindConstant}); - kKeywords.push_back({.keyword_name = "*", .keyword_kind = LibCompiler::kKeywordKindPtr}); - kKeywords.push_back({.keyword_name = "->", .keyword_kind = LibCompiler::kKeywordKindPtrAccess}); - kKeywords.push_back({.keyword_name = ".", .keyword_kind = LibCompiler::kKeywordKindAccess}); - kKeywords.push_back({.keyword_name = ",", .keyword_kind = LibCompiler::kKeywordKindArgSeparator}); - kKeywords.push_back({.keyword_name = ";", .keyword_kind = LibCompiler::kKeywordKindEndInstr}); - kKeywords.push_back({.keyword_name = ":", .keyword_kind = LibCompiler::kKeywordKindSpecifier}); - kKeywords.push_back( - {.keyword_name = "public:", .keyword_kind = LibCompiler::kKeywordKindSpecifier}); - kKeywords.push_back( - {.keyword_name = "private:", .keyword_kind = LibCompiler::kKeywordKindSpecifier}); - kKeywords.push_back( - {.keyword_name = "protected:", .keyword_kind = LibCompiler::kKeywordKindSpecifier}); - kKeywords.push_back( - {.keyword_name = "final", .keyword_kind = LibCompiler::kKeywordKindSpecifier}); - kKeywords.push_back({.keyword_name = "return", .keyword_kind = LibCompiler::kKeywordKindReturn}); - kKeywords.push_back( - {.keyword_name = "--*", .keyword_kind = LibCompiler::kKeywordKindCommentMultiLineStart}); - kKeywords.push_back( - {.keyword_name = "*/", .keyword_kind = LibCompiler::kKeywordKindCommentMultiLineStart}); - kKeywords.push_back( - {.keyword_name = "--/", .keyword_kind = LibCompiler::kKeywordKindCommentInline}); - kKeywords.push_back({.keyword_name = "==", .keyword_kind = LibCompiler::kKeywordKindEq}); - kKeywords.push_back({.keyword_name = "!=", .keyword_kind = LibCompiler::kKeywordKindNotEq}); - kKeywords.push_back({.keyword_name = ">=", .keyword_kind = LibCompiler::kKeywordKindGreaterEq}); - kKeywords.push_back({.keyword_name = "<=", .keyword_kind = LibCompiler::kKeywordKindLessEq}); - - kErrorLimit = 100; + 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::segfault_handler); + LibCompiler::install_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; @@ -846,7 +832,7 @@ LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) { } if (strcmp(argv[index], "-cxx-verbose") == 0) { - kState.fVerbose = true; + kVerbose = true; continue; } @@ -854,7 +840,7 @@ LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) { if (strcmp(argv[index], "-cxx-dialect") == 0) { if (kCompilerFrontend) std::cout << kCompilerFrontend->Language() << "\n"; - return kExitOK; + return LIBCOMPILER_SUCCESS; } if (strcmp(argv[index], "-cxx-max-err") == 0) { @@ -871,7 +857,7 @@ LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) { continue; } - std::string err = "Unknown option: "; + LibCompiler::STLString err = "Unknown option: "; err += argv[index]; Detail::print_error(err, "cxxdrv"); @@ -879,31 +865,26 @@ LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) { continue; } - std::string argv_i = argv[index]; + LibCompiler::STLString argv_i = argv[index]; - std::vector exts = kExtListCxx; - Boolean found = false; + std::vector<LibCompiler::STLString> exts = kExtListCxx; - for (std::string ext : exts) { - if (argv_i.find(ext) != std::string::npos) { - found = true; - break; - } - } + for (LibCompiler::STLString ext : exts) { + if (argv_i.ends_with(ext)) { + if (kFactory.Compile(argv_i, kMachine) != kExitOK) { + return LIBCOMPILER_INVALID_DATA; + } - if (!found) { - if (kState.fVerbose) { - Detail::print_error(argv_i + " is not a valid C++ source.\n", "cxxdrv"); + break; } - - return kExitNO; } - - kFactory.Compile(argv_i, kMachine); } - return kExitNO; + kFactory.Unmount(); + + return LIBCOMPILER_SUCCESS; } -// Last rev 8-1-24 +// +// Last rev 23-5-25 // diff --git a/dev/LibCompiler/src/DynamicLinkerPEF.cc b/dev/LibCompiler/src/Linkers/DynamicLinkerPEF.cc index 9e3be82..b58c786 100644 --- a/dev/LibCompiler/src/DynamicLinkerPEF.cc +++ b/dev/LibCompiler/src/Linkers/DynamicLinkerPEF.cc @@ -20,7 +20,7 @@ #include <LibCompiler/ErrorID.h> //! Assembler Kit -#include <LibCompiler/AssemblyInterface.h> +#include <LibCompiler/CodeGen.h> //! Preferred Executable Format #include <LibCompiler/PEF.h> @@ -34,17 +34,14 @@ //! Advanced Executable Object Format. #include <LibCompiler/AE.h> -//! Format header. -#include <format> - //! LibCompiler utils. -#include <LibCompiler/Detail/ClUtils.h> +#include <LibCompiler/Util/CompilerUtils.h> //! I/O stream from std c++ #include <iostream> #define kLinkerVersionStr \ - "NeKernel 64-Bit Linker (Preferred Executable Format) {}, (c) Amlal El Mahrouss " \ + "NeKernel 64-Bit Linker (Preferred Executable Format) %s, (c) Amlal El Mahrouss " \ "2024-2025 " \ "all rights reserved.\n" @@ -59,19 +56,19 @@ #define kLinkerAbiContainer "__PEFContainer:ABI:" #define kPrintF printf -#define kLinkerSplash() kOutCon << std::format(kLinkerVersionStr, kDistVersion) +#define kLinkerSplash() kConsoleOut << std::printf(kLinkerVersionStr, kDistVersion) /// @brief PEF stack size symbol. #define kLinkerStackSizeSymbol "__PEFSizeOfReserveStack" -#define kOutCon \ +#define kConsoleOut \ (std::cout << "\e[0;31m" \ << "ld64: " \ << "\e[0;97m") namespace Detail { struct DynamicLinkerBlob final { - std::vector<CharType> mBlob{}; // PEF code/bss/data blob. + std::vector<Char> mBlob{}; // PEF code/bss/data blob. UIntPtr mOffset{0UL}; // the offset of the PEF container header... }; } // namespace Detail @@ -83,20 +80,20 @@ enum { kABITypeInvalid = 0xFFFF, }; -static LibCompiler::String kOutput = "a" kPefExt; -static Int32 kAbi = kABITypeNE; -static Int32 kSubArch = kPefNoSubCpu; -static Int32 kArch = LibCompiler::kPefArchInvalid; -static Bool kFatBinaryEnable = false; -static Bool kStartFound = false; -static Bool kDuplicateSymbols = false; +static LibCompiler::STLString kOutput = "a" kPefExt; +static Int32 kAbi = kABITypeNE; +static Int32 kSubArch = kPefNoSubCpu; +static Int32 kArch = LibCompiler::kPefArchInvalid; +static Bool kFatBinaryEnable = false; +static Bool kStartFound = false; +static Bool kDuplicateSymbols = false; /* ld64 is to be found, mld is to be found at runtime. */ -static const CharType* kLdDefineSymbol = ":UndefinedSymbol:"; -static const CharType* kLdDynamicSym = ":RuntimeSymbol:"; +static const Char* kLdDefineSymbol = ":UndefinedSymbol:"; +static const Char* kLdDynamicSym = ":RuntimeSymbol:"; /* object code and list. */ -static std::vector<LibCompiler::String> kObjectList; +static std::vector<LibCompiler::STLString> kObjectList; static std::vector<Detail::DynamicLinkerBlob> kObjectBytes; /// @brief NE 64-bit Linker. @@ -104,7 +101,7 @@ static std::vector<Detail::DynamicLinkerBlob> kObjectBytes; LIBCOMPILER_MODULE(DynamicLinker64PEF) { bool is_executable = true; - ::signal(SIGSEGV, Detail::segfault_handler); + ::signal(SIGSEGV, Detail::drvi_crash_handler); /** * @brief parse flags and trigger options. @@ -113,23 +110,24 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { if (StringCompare(argv[linker_arg], "-help") == 0) { kLinkerSplash(); - kOutCon << "-version: Show linker version.\n"; - kOutCon << "-help: Show linker help.\n"; - kOutCon << "-ld-verbose: Enable linker trace.\n"; - kOutCon << "-dylib: Output as a Dynamic PEF.\n"; - kOutCon << "-fat: Output as a FAT PEF.\n"; - kOutCon << "-32k: Output as a 32x0 PEF.\n"; - kOutCon << "-64k: Output as a 64x0 PEF.\n"; - kOutCon << "-amd64: Output as a AMD64 PEF.\n"; - kOutCon << "-rv64: Output as a RISC-V PEF.\n"; - kOutCon << "-power64: Output as a POWER PEF.\n"; - kOutCon << "-arm64: Output as a ARM64 PEF.\n"; - kOutCon << "-output: Select the output file name.\n"; - - return EXIT_SUCCESS; + kConsoleOut << "-version: Show linker version.\n"; + kConsoleOut << "-help: Show linker help.\n"; + kConsoleOut << "-ld-verbose: Enable linker trace.\n"; + kConsoleOut << "-dylib: Output as a Dynamic PEF.\n"; + kConsoleOut << "-fat: Output as a FAT PEF.\n"; + kConsoleOut << "-32k: Output as a 32x0 PEF.\n"; + kConsoleOut << "-64k: Output as a 64x0 PEF.\n"; + kConsoleOut << "-amd64: Output as a AMD64 PEF.\n"; + kConsoleOut << "-rv64: Output as a RISC-V PEF.\n"; + kConsoleOut << "-power64: Output as a POWER PEF.\n"; + kConsoleOut << "-arm64: Output as a ARM64 PEF.\n"; + kConsoleOut << "-output: Select the output file name.\n"; + + return LIBCOMPILER_SUCCESS; } else if (StringCompare(argv[linker_arg], "-version") == 0) { kLinkerSplash(); - return EXIT_SUCCESS; + + return LIBCOMPILER_SUCCESS; } else if (StringCompare(argv[linker_arg], "-fat-binary") == 0) { kFatBinaryEnable = true; @@ -167,7 +165,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { continue; } - if (kOutput.find(kPefExt) != LibCompiler::String::npos) + if (kOutput.find(kPefExt) != LibCompiler::STLString::npos) kOutput.erase(kOutput.find(kPefExt), strlen(kPefExt)); kOutput += kPefDylibExt; @@ -184,7 +182,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { continue; } else { if (argv[linker_arg][0] == '-') { - kOutCon << "unknown flag: " << argv[linker_arg] << "\n"; + kConsoleOut << "unknown flag: " << argv[linker_arg] << "\n"; return EXIT_FAILURE; } @@ -195,10 +193,10 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { } if (kOutput.empty()) { - kOutCon << "no output filename set." << std::endl; + kConsoleOut << "no output filename set." << std::endl; return LIBCOMPILER_EXEC_ERROR; } else if (kObjectList.empty()) { - kOutCon << "no input files." << std::endl; + kConsoleOut << "no input files." << std::endl; return LIBCOMPILER_EXEC_ERROR; } else { namespace FS = std::filesystem; @@ -208,15 +206,15 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { if (!FS::exists(obj)) { // if filesystem doesn't find file // -> throw error. - kOutCon << "no such file: " << obj << std::endl; + kConsoleOut << "no such file: " << obj << std::endl; return LIBCOMPILER_EXEC_ERROR; } } } // PEF expects a valid target architecture when outputing a binary. - if (kArch == 0) { - kOutCon << "no target architecture set, can't continue." << std::endl; + if (kArch == LibCompiler::kPefArchInvalid) { + kConsoleOut << "no target architecture set, can't continue." << std::endl; return LIBCOMPILER_EXEC_ERROR; } @@ -244,7 +242,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { if (output_fc.bad()) { if (kVerbose) { - kOutCon << "error: " << strerror(errno) << "\n"; + kConsoleOut << "error: " << strerror(errno) << "\n"; } return LIBCOMPILER_FILE_NOT_FOUND; @@ -263,41 +261,39 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { reader_protocol.FP = std::ifstream(objectFile, std::ifstream::binary); reader_protocol.FP >> hdr; - auto ae_header = hdr; - - if (ae_header.fMagic[0] == kAEMag0 && ae_header.fMagic[1] == kAEMag1 && - ae_header.fSize == sizeof(LibCompiler::AEHeader)) { - if (ae_header.fArch != kArch) { - if (kVerbose) kOutCon << "Info: is this a FAT binary? : "; + if (hdr.fMagic[0] == kAEMag0 && hdr.fMagic[1] == kAEMag1 && + hdr.fSize == sizeof(LibCompiler::AEHeader)) { + if (hdr.fArch != kArch) { + if (kVerbose) kConsoleOut << "is this a FAT binary? : "; if (!kFatBinaryEnable) { - if (kVerbose) kOutCon << "No.\n"; + if (kVerbose) kConsoleOut << "not a FAT binary.\n"; - kOutCon << "Error: object " << objectFile - << " is a different kind of architecture and output isn't " - "treated as a FAT binary." - << std::endl; + kConsoleOut << "object " << objectFile + << " is a different kind of architecture and output isn't " + "treated as a FAT binary." + << std::endl; return LIBCOMPILER_FAT_ERROR; } else { if (kVerbose) { - kOutCon << "Architecture matches what we expect.\n"; + kConsoleOut << "Architecture matches what we expect.\n"; } } } // append arch type to archs varaible. - archs |= ae_header.fArch; - std::size_t cnt = ae_header.fCount; + archs |= hdr.fArch; + std::size_t cnt = hdr.fCount; - if (kVerbose) kOutCon << "Object header found, record count: " << cnt << "\n"; + if (kVerbose) kConsoleOut << "Object header found, record count: " << cnt << "\n"; pef_container.Count = cnt; char_type* raw_ae_records = new char_type[cnt * sizeof(LibCompiler::AERecordHeader)]; if (!raw_ae_records) { - if (kVerbose) kOutCon << "Allocation failure for records of count: " << cnt << "\n"; + if (kVerbose) kConsoleOut << "Allocation failure for records of count: " << cnt << "\n"; } memset(raw_ae_records, 0, cnt * sizeof(LibCompiler::AERecordHeader)); @@ -312,15 +308,15 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { MemoryCopy(command_header.Name, ae_records[ae_record_index].fName, kPefNameLen); - LibCompiler::String cmd_hdr_name(command_header.Name); + LibCompiler::STLString cmd_hdr_name(command_header.Name); // check this header if it's any valid. - if (cmd_hdr_name.find(kPefCode64) == LibCompiler::String::npos && - cmd_hdr_name.find(kPefData64) == LibCompiler::String::npos && - cmd_hdr_name.find(kPefZero64) == LibCompiler::String::npos) { - if (cmd_hdr_name.find(kPefStart) == LibCompiler::String::npos && + if (cmd_hdr_name.find(kPefCode64) == LibCompiler::STLString::npos && + cmd_hdr_name.find(kPefData64) == LibCompiler::STLString::npos && + cmd_hdr_name.find(kPefZero64) == LibCompiler::STLString::npos) { + if (cmd_hdr_name.find(kPefStart) == LibCompiler::STLString::npos && *command_header.Name == 0) { - if (cmd_hdr_name.find(kLdDefineSymbol) != LibCompiler::String::npos) { + if (cmd_hdr_name.find(kLdDefineSymbol) != LibCompiler::STLString::npos) { goto ld_mark_header; } else { continue; @@ -328,8 +324,8 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { } } - if (cmd_hdr_name.find(kPefStart) != LibCompiler::String::npos && - cmd_hdr_name.find(kPefCode64) != LibCompiler::String::npos) { + if (cmd_hdr_name.find(kPefStart) != LibCompiler::STLString::npos && + cmd_hdr_name.find(kPefCode64) != LibCompiler::STLString::npos) { kStartFound = true; } @@ -337,16 +333,16 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { command_header.Offset = offset_of_obj; command_header.Kind = ae_records[ae_record_index].fKind; command_header.Size = ae_records[ae_record_index].fSize; - command_header.Cpu = ae_header.fArch; + command_header.Cpu = hdr.fArch; command_header.VMAddress = org; /// TODO: - command_header.SubCpu = ae_header.fSubArch; + command_header.SubCpu = hdr.fSubArch; org += command_header.Size; if (kVerbose) { - kOutCon << "Record: " << ae_records[ae_record_index].fName << " is marked.\n"; + kConsoleOut << "Record: " << ae_records[ae_record_index].fName << " is marked.\n"; - kOutCon << "Offset: " << command_header.Offset << "\n"; + kConsoleOut << "Offset: " << command_header.Offset << "\n"; } command_headers.emplace_back(command_header); @@ -356,12 +352,12 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { raw_ae_records = nullptr; std::vector<char> bytes; - bytes.resize(ae_header.fCodeSize); + bytes.resize(hdr.fCodeSize); - reader_protocol.FP.seekg(std::streamsize(ae_header.fStartCode)); - reader_protocol.FP.read(bytes.data(), std::streamsize(ae_header.fCodeSize)); + reader_protocol.FP.seekg(std::streamsize(hdr.fStartCode)); + reader_protocol.FP.read(bytes.data(), std::streamsize(hdr.fCodeSize)); - kObjectBytes.push_back({.mBlob = bytes, .mOffset = ae_header.fStartCode}); + kObjectBytes.push_back({.mBlob = bytes, .mOffset = hdr.fStartCode}); // Blob was written, close fp. @@ -370,7 +366,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { continue; } - kOutCon << "Not an container: " << objectFile << std::endl; + kConsoleOut << "Not an AE container: " << objectFile << std::endl; // don't continue, it is a fatal error. return LIBCOMPILER_EXEC_ERROR; } @@ -380,24 +376,26 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { output_fc << pef_container; if (kVerbose) { - kOutCon << "Wrote container to: " << output_fc.tellp() << ".\n"; + kConsoleOut << "Wrote container to: " << output_fc.tellp() << ".\n"; } output_fc.seekp(std::streamsize(pef_container.HdrSz)); - std::vector<LibCompiler::String> not_found; - std::vector<LibCompiler::String> symbols; + std::vector<LibCompiler::STLString> not_found; + std::vector<LibCompiler::STLString> symbols; // step 2: check for errors (multiple symbols, undefined ones) for (auto& command_hdr : command_headers) { // check if this symbol needs to be resolved. - if (LibCompiler::String(command_hdr.Name).find(kLdDefineSymbol) != LibCompiler::String::npos && - LibCompiler::String(command_hdr.Name).find(kLdDynamicSym) == LibCompiler::String::npos) { - if (kVerbose) kOutCon << "Found undefined symbol: " << command_hdr.Name << "\n"; - - if (auto it = - std::find(not_found.begin(), not_found.end(), LibCompiler::String(command_hdr.Name)); + if (LibCompiler::STLString(command_hdr.Name).find(kLdDefineSymbol) != + LibCompiler::STLString::npos && + LibCompiler::STLString(command_hdr.Name).find(kLdDynamicSym) == + LibCompiler::STLString::npos) { + if (kVerbose) kConsoleOut << "Found undefined symbol: " << command_hdr.Name << "\n"; + + if (auto it = std::find(not_found.begin(), not_found.end(), + LibCompiler::STLString(command_hdr.Name)); it == not_found.end()) { not_found.emplace_back(command_hdr.Name); } @@ -410,26 +408,27 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { for (size_t not_found_idx = 0; not_found_idx < command_headers.size(); ++not_found_idx) { if (const auto it = std::find(not_found.begin(), not_found.end(), - LibCompiler::String(command_headers[not_found_idx].Name)); + LibCompiler::STLString(command_headers[not_found_idx].Name)); it != not_found.end()) { - LibCompiler::String symbol_imp = *it; + LibCompiler::STLString symbol_imp = *it; - if (symbol_imp.find(kLdDefineSymbol) == LibCompiler::String::npos) continue; + if (symbol_imp.find(kLdDefineSymbol) == LibCompiler::STLString::npos) continue; // erase the lookup prefix. symbol_imp.erase(0, symbol_imp.find(kLdDefineSymbol) + strlen(kLdDefineSymbol)); // demangle everything. - while (symbol_imp.find('$') != LibCompiler::String::npos) + while (symbol_imp.find('$') != LibCompiler::STLString::npos) symbol_imp.erase(symbol_imp.find('$'), 1); // the reason we do is because, this may not match the symbol, and we need // to look for other matching symbols. for (auto& command_hdr : command_headers) { - if (LibCompiler::String(command_hdr.Name).find(symbol_imp) != LibCompiler::String::npos && - LibCompiler::String(command_hdr.Name).find(kLdDefineSymbol) == - LibCompiler::String::npos) { - LibCompiler::String undefined_symbol = command_hdr.Name; + if (LibCompiler::STLString(command_hdr.Name).find(symbol_imp) != + LibCompiler::STLString::npos && + LibCompiler::STLString(command_hdr.Name).find(kLdDefineSymbol) == + LibCompiler::STLString::npos) { + LibCompiler::STLString undefined_symbol = command_hdr.Name; auto result_of_sym = undefined_symbol.substr(undefined_symbol.find(symbol_imp)); for (int i = 0; result_of_sym[i] != 0; ++i) { @@ -438,7 +437,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { not_found.erase(it); - if (kVerbose) kOutCon << "Found symbol: " << command_hdr.Name << "\n"; + if (kVerbose) kConsoleOut << "Found symbol: " << command_hdr.Name << "\n"; break; } @@ -453,11 +452,11 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { if (!kStartFound && is_executable) { if (kVerbose) - kOutCon << "Undefined entrypoint: " << kPefStart - << ", you may have forget to link " - "against the C++ runtime library.\n"; + kConsoleOut << "Undefined entrypoint: " << kPefStart + << ", you may have forget to link " + "against the C++ runtime library.\n"; - kOutCon << "Undefined entrypoint " << kPefStart << " for executable: " << kOutput << "\n"; + kConsoleOut << "Undefined entrypoint " << kPefStart << " for executable: " << kOutput << "\n"; } // step 4: write all PEF commands. @@ -466,7 +465,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { time_t timestamp = time(nullptr); - LibCompiler::String timeStampStr = "Container:BuildEpoch:"; + LibCompiler::STLString timeStampStr = "Container:BuildEpoch:"; timeStampStr += std::to_string(timestamp); strncpy(date_cmd_hdr.Name, timeStampStr.c_str(), timeStampStr.size()); @@ -480,7 +479,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { LibCompiler::PEFCommandHeader abi_cmd_hdr{}; - LibCompiler::String abi = kLinkerAbiContainer; + LibCompiler::STLString abi = kLinkerAbiContainer; switch (kArch) { case LibCompiler::kPefArchAMD64: { @@ -546,9 +545,9 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { command_headers.push_back(uuid_cmd_hdr); // prepare a symbol vector. - std::vector<LibCompiler::String> undef_symbols; - std::vector<LibCompiler::String> dupl_symbols; - std::vector<LibCompiler::String> resolve_symbols; + std::vector<LibCompiler::STLString> undef_symbols; + std::vector<LibCompiler::STLString> dupl_symbols; + std::vector<LibCompiler::STLString> resolve_symbols; constexpr Int32 kPaddingOffset = 16; @@ -571,15 +570,15 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { // And check for any duplications for (size_t commandHeaderIndex = 0UL; commandHeaderIndex < command_headers.size(); ++commandHeaderIndex) { - if (LibCompiler::String(command_headers[commandHeaderIndex].Name).find(kLdDefineSymbol) != - LibCompiler::String::npos && - LibCompiler::String(command_headers[commandHeaderIndex].Name).find(kLdDynamicSym) == - LibCompiler::String::npos) { + if (LibCompiler::STLString(command_headers[commandHeaderIndex].Name).find(kLdDefineSymbol) != + LibCompiler::STLString::npos && + LibCompiler::STLString(command_headers[commandHeaderIndex].Name).find(kLdDynamicSym) == + LibCompiler::STLString::npos) { // ignore :UndefinedSymbol: headers, they do not contain code. continue; } - LibCompiler::String symbol_name = command_headers[commandHeaderIndex].Name; + LibCompiler::STLString symbol_name = command_headers[commandHeaderIndex].Name; if (!symbol_name.empty()) { undef_symbols.emplace_back(symbol_name); @@ -588,13 +587,13 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { command_headers[commandHeaderIndex].Offset += previous_offset; previous_offset += command_headers[commandHeaderIndex].Size; - LibCompiler::String name = command_headers[commandHeaderIndex].Name; + LibCompiler::STLString name = command_headers[commandHeaderIndex].Name; /// so this is valid when we get to the entrypoint. /// it is always a code64 container. And should equal to kPefStart as well. /// this chunk of code updates the pef_container.Start with the updated offset. - if (name.find(kPefStart) != LibCompiler::String::npos && - name.find(kPefCode64) != LibCompiler::String::npos) { + if (name.find(kPefStart) != LibCompiler::STLString::npos && + name.find(kPefCode64) != LibCompiler::STLString::npos) { pef_container.Start = command_headers[commandHeaderIndex].Offset; auto tellCurPos = output_fc.tellp(); @@ -605,9 +604,9 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { } if (kVerbose) { - kOutCon << "Command name: " << name << "\n"; - kOutCon << "VMAddress of command content: " << command_headers[commandHeaderIndex].Offset - << "\n"; + kConsoleOut << "Command name: " << name << "\n"; + kConsoleOut << "VMAddress of command content: " << command_headers[commandHeaderIndex].Offset + << "\n"; } output_fc << command_headers[commandHeaderIndex]; @@ -616,12 +615,12 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { ++sub_command_header_index) { if (sub_command_header_index == commandHeaderIndex) continue; - if (LibCompiler::String(command_headers[sub_command_header_index].Name) - .find(kLdDefineSymbol) != LibCompiler::String::npos && - LibCompiler::String(command_headers[sub_command_header_index].Name).find(kLdDynamicSym) == - LibCompiler::String::npos) { + if (LibCompiler::STLString(command_headers[sub_command_header_index].Name) + .find(kLdDefineSymbol) != LibCompiler::STLString::npos && + LibCompiler::STLString(command_headers[sub_command_header_index].Name) + .find(kLdDynamicSym) == LibCompiler::STLString::npos) { if (kVerbose) { - kOutCon << "Ignoring :UndefinedSymbol: headers...\n"; + kConsoleOut << "Ignoring :UndefinedSymbol: headers...\n"; } // ignore :UndefinedSymbol: headers, they do not contain code. @@ -630,13 +629,13 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { auto& command_hdr = command_headers[sub_command_header_index]; - if (command_hdr.Name == LibCompiler::String(command_headers[commandHeaderIndex].Name)) { + if (command_hdr.Name == LibCompiler::STLString(command_headers[commandHeaderIndex].Name)) { if (std::find(dupl_symbols.cbegin(), dupl_symbols.cend(), command_hdr.Name) == dupl_symbols.cend()) { dupl_symbols.emplace_back(command_hdr.Name); } - if (kVerbose) kOutCon << "Found duplicate symbols of: " << command_hdr.Name << "\n"; + if (kVerbose) kConsoleOut << "Found duplicate symbols of: " << command_hdr.Name << "\n"; kDuplicateSymbols = true; } @@ -645,7 +644,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { if (!dupl_symbols.empty()) { for (auto& symbol : dupl_symbols) { - kOutCon << "Multiple symbols of: " << symbol << " detected, cannot continue.\n"; + kConsoleOut << "Multiple symbols of: " << symbol << " detected, cannot continue.\n"; } return LIBCOMPILER_EXEC_ERROR; @@ -658,16 +657,16 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { } if (kVerbose) { - kOutCon << "Wrote contents of: " << kOutput << "\n"; + kConsoleOut << "Wrote contents of: " << kOutput << "\n"; } // step 3: check if we have those symbols - std::vector<LibCompiler::String> unreferenced_symbols; + std::vector<LibCompiler::STLString> unreferenced_symbols; for (auto& command_hdr : command_headers) { if (auto it = - std::find(not_found.begin(), not_found.end(), LibCompiler::String(command_hdr.Name)); + std::find(not_found.begin(), not_found.end(), LibCompiler::STLString(command_hdr.Name)); it != not_found.end()) { unreferenced_symbols.emplace_back(command_hdr.Name); } @@ -675,7 +674,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { if (!unreferenced_symbols.empty()) { for (auto& unreferenced_symbol : unreferenced_symbols) { - kOutCon << "Undefined symbol " << unreferenced_symbol << "\n"; + kConsoleOut << "Undefined symbol " << unreferenced_symbol << "\n"; } return LIBCOMPILER_EXEC_ERROR; @@ -684,7 +683,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { if ((!kStartFound || kDuplicateSymbols) && (std::filesystem::exists(kOutput) || !unreferenced_symbols.empty())) { if (kVerbose) { - kOutCon << "File: " << kOutput << ", is corrupt, removing file...\n"; + kConsoleOut << "File: " << kOutput << ", is corrupt, removing file...\n"; } return LIBCOMPILER_EXEC_ERROR; diff --git a/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc b/dev/LibCompiler/src/Macro/CPlusPlusCompilerPreProcessor.cc index 5d035da..2c7c551 100644 --- a/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc +++ b/dev/LibCompiler/src/Macro/CPlusPlusCompilerPreProcessor.cc @@ -10,7 +10,7 @@ /// BUGS: 0 #include <LibCompiler/ErrorID.h> -#include <LibCompiler/Parser.h> +#include <LibCompiler/Frontend.h> #include <algorithm> #include <filesystem> #include <fstream> @@ -24,7 +24,7 @@ /// @file bpp.cxx /// @brief Preprocessor. -typedef Int32 (*bpp_parser_fn_t)(LibCompiler::String& line, std::ifstream& hdr_file, +typedef Int32 (*bpp_parser_fn_t)(LibCompiler::STLString& line, std::ifstream& hdr_file, std::ofstream& pp_out); ///////////////////////////////////////////////////////////////////////////////////////// @@ -46,8 +46,8 @@ enum { }; struct bpp_macro_condition final { - int32_t fType; - LibCompiler::String fTypeName; + int32_t fType; + LibCompiler::STLString fTypeName; void Print() { std::cout << "type: " << fType << "\n"; @@ -56,9 +56,9 @@ struct bpp_macro_condition final { }; struct bpp_macro final { - std::vector<LibCompiler::String> fArgs; - LibCompiler::String fName; - LibCompiler::String fValue; + std::vector<LibCompiler::STLString> fArgs; + LibCompiler::STLString fName; + LibCompiler::STLString fValue; void Print() { std::cout << "name: " << fName << "\n"; @@ -71,11 +71,11 @@ struct bpp_macro final { }; } // namespace Detail -static std::vector<LibCompiler::String> kFiles; -static std::vector<Detail::bpp_macro> kMacros; -static std::vector<LibCompiler::String> kIncludes; +static std::vector<LibCompiler::STLString> kFiles; +static std::vector<Detail::bpp_macro> kMacros; +static std::vector<LibCompiler::STLString> kIncludes; -static LibCompiler::String kWorkingDir = ""; +static LibCompiler::STLString kWorkingDir = ""; ///////////////////////////////////////////////////////////////////////////////////////// @@ -85,11 +85,12 @@ static LibCompiler::String kWorkingDir = ""; ///////////////////////////////////////////////////////////////////////////////////////// int32_t bpp_parse_if_condition(Detail::bpp_macro_condition& cond, Detail::bpp_macro& macro, - bool& inactive_code, bool& defined, LibCompiler::String& macro_str) { + bool& inactive_code, bool& defined, + LibCompiler::STLString& macro_str) { if (cond.fType == Detail::kEqual) { auto substr_macro = macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); - if (substr_macro.find(macro.fValue) != LibCompiler::String::npos) { + if (substr_macro.find(macro.fValue) != LibCompiler::STLString::npos) { if (macro.fValue == "0") { defined = false; inactive_code = true; @@ -105,8 +106,8 @@ int32_t bpp_parse_if_condition(Detail::bpp_macro_condition& cond, Detail::bpp_ma } else if (cond.fType == Detail::kNotEqual) { auto substr_macro = macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); - if (substr_macro.find(macro.fName) != LibCompiler::String::npos) { - if (substr_macro.find(macro.fValue) != LibCompiler::String::npos) { + if (substr_macro.find(macro.fName) != LibCompiler::STLString::npos) { + if (substr_macro.find(macro.fValue) != LibCompiler::STLString::npos) { defined = false; inactive_code = true; @@ -124,10 +125,10 @@ int32_t bpp_parse_if_condition(Detail::bpp_macro_condition& cond, Detail::bpp_ma auto substr_macro = macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); - LibCompiler::String number; + LibCompiler::STLString number; for (auto& macro_num : kMacros) { - if (substr_macro.find(macro_num.fName) != LibCompiler::String::npos) { + if (substr_macro.find(macro_num.fName) != LibCompiler::STLString::npos) { for (size_t i = 0; i < macro_num.fName.size(); ++i) { if (isdigit(macro_num.fValue[i])) { number += macro_num.fValue[i]; @@ -231,7 +232,7 @@ int32_t bpp_parse_if_condition(Detail::bpp_macro_condition& cond, Detail::bpp_ma ///////////////////////////////////////////////////////////////////////////////////////// -std::vector<LibCompiler::String> kAllIncludes; +std::vector<LibCompiler::STLString> kAllIncludes; ///////////////////////////////////////////////////////////////////////////////////////// @@ -241,8 +242,8 @@ std::vector<LibCompiler::String> kAllIncludes; ///////////////////////////////////////////////////////////////////////////////////////// void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { - LibCompiler::String hdr_line; - LibCompiler::String line_after_include; + LibCompiler::STLString hdr_line; + LibCompiler::STLString line_after_include; bool inactive_code = false; bool defined = false; @@ -250,36 +251,36 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { try { while (std::getline(hdr_file, hdr_line)) { if (inactive_code) { - if (hdr_line.find("#endif") == LibCompiler::String::npos) { + if (hdr_line.find("#endif") == LibCompiler::STLString::npos) { continue; } else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("#endif") != LibCompiler::String::npos) { + hdr_line.find("#endif") != LibCompiler::STLString::npos) { inactive_code = false; } - if (hdr_line.find("*/") != LibCompiler::String::npos) { + if (hdr_line.find("*/") != LibCompiler::STLString::npos) { continue; } } - if (hdr_line.find("--/") != LibCompiler::String::npos) { + if (hdr_line.find("--/") != LibCompiler::STLString::npos) { hdr_line.erase(hdr_line.find("--/")); } - if (hdr_line.find("--*") != LibCompiler::String::npos) { + if (hdr_line.find("--*") != LibCompiler::STLString::npos) { inactive_code = true; // get rid of comment. hdr_line.erase(hdr_line.find("--*")); } /// BPP 'brief' documentation. - if (hdr_line.find("@brief") != LibCompiler::String::npos) { + if (hdr_line.find("@brief") != LibCompiler::STLString::npos) { hdr_line.erase(hdr_line.find("@brief")); // TODO: Write an <file_name>.html or append to it. } - if (hdr_line[0] == kMacroPrefix && hdr_line.find("endif") != LibCompiler::String::npos) { + if (hdr_line[0] == kMacroPrefix && hdr_line.find("endif") != LibCompiler::STLString::npos) { if (!defined && inactive_code) { inactive_code = false; defined = false; @@ -301,17 +302,17 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { for (auto macro : kMacros) { if (LibCompiler::find_word(hdr_line, macro.fName)) { if (hdr_line.substr(hdr_line.find(macro.fName)).find(macro.fName + '(') != - LibCompiler::String::npos) { + LibCompiler::STLString::npos) { if (!macro.fArgs.empty()) { - LibCompiler::String symbol_val = macro.fValue; - std::vector<LibCompiler::String> args; + LibCompiler::STLString symbol_val = macro.fValue; + std::vector<LibCompiler::STLString> args; size_t x_arg_indx = 0; - LibCompiler::String line_after_define = hdr_line; - LibCompiler::String str_arg; + LibCompiler::STLString line_after_define = hdr_line; + LibCompiler::STLString str_arg; - if (line_after_define.find("(") != LibCompiler::String::npos) { + if (line_after_define.find("(") != LibCompiler::STLString::npos) { line_after_define.erase(0, line_after_define.find("(") + 1); for (auto& subc : line_after_define) { @@ -332,7 +333,7 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { } for (auto arg : macro.fArgs) { - if (symbol_val.find(macro.fArgs[x_arg_indx]) != LibCompiler::String::npos) { + if (symbol_val.find(macro.fArgs[x_arg_indx]) != LibCompiler::STLString::npos) { symbol_val.replace(symbol_val.find(macro.fArgs[x_arg_indx]), macro.fArgs[x_arg_indx].size(), args[x_arg_indx]); ++x_arg_indx; @@ -358,16 +359,16 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { } } - if (hdr_line[0] == kMacroPrefix && hdr_line.find("define ") != LibCompiler::String::npos) { + if (hdr_line[0] == kMacroPrefix && hdr_line.find("define ") != LibCompiler::STLString::npos) { auto line_after_define = hdr_line.substr(hdr_line.find("define ") + strlen("define ")); - LibCompiler::String macro_value; - LibCompiler::String macro_key; + LibCompiler::STLString macro_value; + LibCompiler::STLString macro_key; std::size_t pos = 0UL; - std::vector<LibCompiler::String> args; - bool on_args = false; + std::vector<LibCompiler::STLString> args; + bool on_args = false; for (auto& ch : line_after_define) { ++pos; @@ -397,9 +398,9 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { macro_key += ch; } - LibCompiler::String str; + LibCompiler::STLString str; - if (line_after_define.find("(") != LibCompiler::String::npos) { + if (line_after_define.find("(") != LibCompiler::STLString::npos) { line_after_define.erase(0, line_after_define.find("(") + 1); for (auto& subc : line_after_define) { @@ -438,9 +439,9 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { continue; } - if (hdr_line[0] == kMacroPrefix && hdr_line.find("ifndef") != LibCompiler::String::npos) { + if (hdr_line[0] == kMacroPrefix && hdr_line.find("ifndef") != LibCompiler::STLString::npos) { auto line_after_ifndef = hdr_line.substr(hdr_line.find("ifndef") + strlen("ifndef") + 1); - LibCompiler::String macro; + LibCompiler::STLString macro; for (auto& ch : line_after_ifndef) { if (ch == ' ') { @@ -469,7 +470,7 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { inactive_code = false; for (auto& macro_ref : kMacros) { - if (hdr_line.find(macro_ref.fName) != LibCompiler::String::npos) { + if (hdr_line.find(macro_ref.fName) != LibCompiler::STLString::npos) { found = true; break; } @@ -482,7 +483,7 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { continue; } } else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("else") != LibCompiler::String::npos) { + hdr_line.find("else") != LibCompiler::STLString::npos) { if (!defined && inactive_code) { inactive_code = false; defined = true; @@ -495,9 +496,9 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { continue; } } else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("ifdef") != LibCompiler::String::npos) { + hdr_line.find("ifdef") != LibCompiler::STLString::npos) { auto line_after_ifdef = hdr_line.substr(hdr_line.find("ifdef") + strlen("ifdef") + 1); - LibCompiler::String macro; + LibCompiler::STLString macro; for (auto& ch : line_after_ifdef) { if (ch == ' ') { @@ -525,14 +526,15 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { inactive_code = true; for (auto& macro_ref : kMacros) { - if (hdr_line.find(macro_ref.fName) != LibCompiler::String::npos) { + if (hdr_line.find(macro_ref.fName) != LibCompiler::STLString::npos) { defined = true; inactive_code = false; break; } } - } else if (hdr_line[0] == kMacroPrefix && hdr_line.find("if") != LibCompiler::String::npos) { + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("if") != LibCompiler::STLString::npos) { inactive_code = true; std::vector<Detail::bpp_macro_condition> bpp_macro_condition_list = { @@ -565,9 +567,9 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { int32_t good_to_go = 0; for (auto& macro_condition : bpp_macro_condition_list) { - if (hdr_line.find(macro_condition.fTypeName) != LibCompiler::String::npos) { + if (hdr_line.find(macro_condition.fTypeName) != LibCompiler::STLString::npos) { for (auto& found_macro : kMacros) { - if (hdr_line.find(found_macro.fName) != LibCompiler::String::npos) { + if (hdr_line.find(found_macro.fName) != LibCompiler::STLString::npos) { good_to_go = bpp_parse_if_condition(macro_condition, found_macro, inactive_code, defined, hdr_line); @@ -579,8 +581,8 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { if (good_to_go) continue; - auto line_after_if = hdr_line.substr(hdr_line.find("if") + strlen("if") + 1); - LibCompiler::String macro; + auto line_after_if = hdr_line.substr(hdr_line.find("if") + strlen("if") + 1); + LibCompiler::STLString macro; for (auto& ch : line_after_if) { if (ch == ' ') { @@ -605,7 +607,8 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { // last try, is it defined to be one? for (auto& macro_ref : kMacros) { - if (macro_ref.fName.find(macro) != LibCompiler::String::npos && macro_ref.fValue == "1") { + if (macro_ref.fName.find(macro) != LibCompiler::STLString::npos && + macro_ref.fValue == "1") { inactive_code = false; defined = true; @@ -613,9 +616,9 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { } } } else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("warning") != LibCompiler::String::npos) { + hdr_line.find("warning") != LibCompiler::STLString::npos) { auto line_after_warning = hdr_line.substr(hdr_line.find("warning") + strlen("warning") + 1); - LibCompiler::String message; + LibCompiler::STLString message; for (auto& ch : line_after_warning) { if (ch == '\r' || ch == '\n') { @@ -627,9 +630,9 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { std::cout << "warn: " << message << std::endl; } else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("error") != LibCompiler::String::npos) { + hdr_line.find("error") != LibCompiler::STLString::npos) { auto line_after_warning = hdr_line.substr(hdr_line.find("error") + strlen("error") + 1); - LibCompiler::String message; + LibCompiler::STLString message; for (auto& ch : line_after_warning) { if (ch == '\r' || ch == '\n') { @@ -641,7 +644,7 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { throw std::runtime_error("error: " + message); } else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("include ") != LibCompiler::String::npos) { + hdr_line.find("include ") != LibCompiler::STLString::npos) { line_after_include = hdr_line.substr(hdr_line.find("include ") + strlen("include ")); kIncludeFile: @@ -651,7 +654,7 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { continue; } - LibCompiler::String path; + LibCompiler::STLString path; kAllIncludes.push_back(line_after_include); @@ -691,7 +694,7 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { } for (auto& include : kIncludes) { - LibCompiler::String header_path = include; + LibCompiler::STLString header_path = include; header_path.push_back('/'); header_path += path; @@ -830,7 +833,7 @@ LIBCOMPILER_MODULE(CPlusPlusPreprocessorMain) { } if (strcmp(argv[index], "--cppdrv:include-dir") == 0) { - LibCompiler::String inc = argv[index + 1]; + LibCompiler::STLString inc = argv[index + 1]; skip = true; @@ -838,17 +841,17 @@ LIBCOMPILER_MODULE(CPlusPlusPreprocessorMain) { } if (strcmp(argv[index], "--cppdrv:working-dir") == 0) { - LibCompiler::String inc = argv[index + 1]; - skip = true; - kWorkingDir = inc; + LibCompiler::STLString inc = argv[index + 1]; + skip = true; + kWorkingDir = inc; } if (strcmp(argv[index], "--cppdrv:def") == 0 && argv[index + 1] != nullptr && argv[index + 2] != nullptr) { - LibCompiler::String macro_key = argv[index + 1]; + LibCompiler::STLString macro_key = argv[index + 1]; - LibCompiler::String macro_value; - bool is_string = false; + LibCompiler::STLString macro_value; + bool is_string = false; for (int argv_find_len = 0; argv_find_len < strlen(argv[index]); ++argv_find_len) { if (!isdigit(argv[index][argv_find_len])) { |
