diff options
Diffstat (limited to 'dev/LibCompiler/src')
| -rw-r--r-- | dev/LibCompiler/src/Backend/Assembler32x0.cc (renamed from dev/LibCompiler/src/Asm/Assembler32x0.cc) | 0 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Backend/Assembler64x0.cc (renamed from dev/LibCompiler/src/Asm/Assembler64x0.cc) | 0 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Backend/AssemblerAMD64.cc (renamed from dev/LibCompiler/src/Asm/AssemblerAMD64.cc) | 0 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Backend/AssemblerARM64.cc (renamed from dev/LibCompiler/src/Asm/AssemblerARM64.cc) | 0 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Backend/AssemblerPowerPC.cc (renamed from dev/LibCompiler/src/Asm/AssemblerPowerPC.cc) | 0 | ||||
| -rw-r--r-- | dev/LibCompiler/src/BasicString.cc (renamed from dev/LibCompiler/src/PString.cc) | 32 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Cl/CCompiler64x0.cc | 1286 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Cl/CCompilerARM64.cc | 1284 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Cl/CCompilerPower64.cc | 1303 | ||||
| -rw-r--r-- | dev/LibCompiler/src/CodeGen.cc | 5 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Frontend/CPlusPlusCompilerAMD64.cc (renamed from dev/LibCompiler/src/Cl/CPlusPlusCompilerAMD64.cc) | 159 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Linkers/DynamicLinkerPEF.cc (renamed from dev/LibCompiler/src/Linker/DynamicLinkerPEF.cc) | 0 | ||||
| -rw-r--r-- | dev/LibCompiler/src/Macro/CPlusPlusCompilerPreProcessor.cc (renamed from dev/LibCompiler/src/PP/CPlusPlusCompilerPreProcessor.cc) | 0 |
13 files changed, 91 insertions, 3978 deletions
diff --git a/dev/LibCompiler/src/Asm/Assembler32x0.cc b/dev/LibCompiler/src/Backend/Assembler32x0.cc index 683b866..683b866 100644 --- a/dev/LibCompiler/src/Asm/Assembler32x0.cc +++ b/dev/LibCompiler/src/Backend/Assembler32x0.cc diff --git a/dev/LibCompiler/src/Asm/Assembler64x0.cc b/dev/LibCompiler/src/Backend/Assembler64x0.cc index fb96708..fb96708 100644 --- a/dev/LibCompiler/src/Asm/Assembler64x0.cc +++ b/dev/LibCompiler/src/Backend/Assembler64x0.cc diff --git a/dev/LibCompiler/src/Asm/AssemblerAMD64.cc b/dev/LibCompiler/src/Backend/AssemblerAMD64.cc index e9f3ad5..e9f3ad5 100644 --- a/dev/LibCompiler/src/Asm/AssemblerAMD64.cc +++ b/dev/LibCompiler/src/Backend/AssemblerAMD64.cc diff --git a/dev/LibCompiler/src/Asm/AssemblerARM64.cc b/dev/LibCompiler/src/Backend/AssemblerARM64.cc index 8fad6b5..8fad6b5 100644 --- a/dev/LibCompiler/src/Asm/AssemblerARM64.cc +++ b/dev/LibCompiler/src/Backend/AssemblerARM64.cc diff --git a/dev/LibCompiler/src/Asm/AssemblerPowerPC.cc b/dev/LibCompiler/src/Backend/AssemblerPowerPC.cc index 86a70b9..86a70b9 100644 --- a/dev/LibCompiler/src/Asm/AssemblerPowerPC.cc +++ b/dev/LibCompiler/src/Backend/AssemblerPowerPC.cc diff --git a/dev/LibCompiler/src/PString.cc b/dev/LibCompiler/src/BasicString.cc index c8c060b..78bfcaa 100644 --- a/dev/LibCompiler/src/PString.cc +++ b/dev/LibCompiler/src/BasicString.cc @@ -8,7 +8,7 @@ */ /** - * @file PString.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/PString.h> +#include <LibCompiler/BasicString.h> namespace LibCompiler { -CharType* PString::Data() { +CharType* BasicString::Data() { return m_Data; } -const CharType* PString::CData() const { +const CharType* BasicString::CData() const { return m_Data; } -SizeType PString::Length() const { +SizeType BasicString::Length() const { return strlen(m_Data); } -bool PString::operator==(const PString& 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 PString::operator==(const PString& rhs) const { return true; } -bool PString::operator==(const CharType* rhs) const { +bool BasicString::operator==(const CharType* rhs) const { if (string_length(rhs) != Length()) return false; for (SizeType index = 0; index < string_length(rhs); ++index) { @@ -53,7 +53,7 @@ bool PString::operator==(const CharType* rhs) const { return true; } -bool PString::operator!=(const PString& 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 PString::operator!=(const PString& rhs) const { return true; } -bool PString::operator!=(const CharType* rhs) const { +bool BasicString::operator!=(const CharType* rhs) const { if (string_length(rhs) != Length()) return false; for (SizeType index = 0; index < string_length(rhs); ++index) { @@ -73,10 +73,10 @@ bool PString::operator!=(const CharType* rhs) const { return true; } -PString StringBuilder::Construct(const CharType* data) { - if (!data || *data == 0) return PString(0); +BasicString StringBuilder::Construct(const CharType* data) { + if (!data || *data == 0) return BasicString(0); - PString view(strlen(data)); + BasicString view(strlen(data)); view += data; return view; @@ -183,9 +183,9 @@ const char* StringBuilder::Format(const char* fmt, const char* fmtRight) { return ret; } -PString& PString::operator+=(const CharType* rhs) { +BasicString& BasicString::operator+=(const CharType* rhs) { if (strlen(rhs) > this->m_Sz) { - throw std::runtime_error("out_of_bounds: PString"); + throw std::runtime_error("out_of_bounds: BasicString"); } memcpy(this->m_Data + this->m_Cur, rhs, strlen(rhs)); @@ -194,9 +194,9 @@ PString& PString::operator+=(const CharType* rhs) { return *this; } -PString& PString::operator+=(const PString& rhs) { +BasicString& BasicString::operator+=(const BasicString& rhs) { if (rhs.m_Cur > this->m_Sz) { - throw std::runtime_error("out_of_bounds: PString"); + 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/Cl/CCompiler64x0.cc b/dev/LibCompiler/src/Cl/CCompiler64x0.cc deleted file mode 100644 index fc31ef9..0000000 --- a/dev/LibCompiler/src/Cl/CCompiler64x0.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/64x0.h> -#include <LibCompiler/Frontend.h> -#include <LibCompiler/UUID.h> -#include <LibCompiler/Util/LCClUtils.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::CompilerFrontendInterface { - 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 LC_ASSEMBLY_INTERFACE { - public: - explicit AssemblyCCInterface() = default; - ~AssemblyCCInterface() override = default; - - LIBCOMPILER_COPY_DEFAULT(AssemblyCCInterface); - - UInt32 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::drvi_crash_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/Cl/CCompilerARM64.cc b/dev/LibCompiler/src/Cl/CCompilerARM64.cc deleted file mode 100644 index 02e39f9..0000000 --- a/dev/LibCompiler/src/Cl/CCompilerARM64.cc +++ /dev/null @@ -1,1284 +0,0 @@ -/* - * ======================================================== - * - * cc - * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. - * - * ======================================================== - */ - -/// BUGS: 0 -/// TODO: none - -#include <LibCompiler/Backend/Aarch64.h> -#include <LibCompiler/Frontend.h> -#include <LibCompiler/UUID.h> -#include <LibCompiler/Util/LCClUtils.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::CompilerFrontendInterface { - 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 LC_ASSEMBLY_INTERFACE { - public: - explicit AssemblyCCInterface() = default; - ~AssemblyCCInterface() override = default; - - LIBCOMPILER_COPY_DEFAULT(AssemblyCCInterface); - - UInt32 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::drvi_crash_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/Cl/CCompilerPower64.cc b/dev/LibCompiler/src/Cl/CCompilerPower64.cc deleted file mode 100644 index 216891a..0000000 --- a/dev/LibCompiler/src/Cl/CCompilerPower64.cc +++ /dev/null @@ -1,1303 +0,0 @@ -/* - * ======================================================== - * - * CompilerPower64 - * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. - * - * ======================================================== - */ - -#include <LibCompiler/Backend/PowerPC.h> -#include <LibCompiler/Frontend.h> -#include <LibCompiler/UUID.h> -#include <LibCompiler/Util/LCClUtils.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::CompilerFrontendInterface { - 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 LC_ASSEMBLY_INTERFACE { - public: - explicit AssemblyMountpointCLang() = default; - ~AssemblyMountpointCLang() override = default; - - LIBCOMPILER_COPY_DEFAULT(AssemblyMountpointCLang); - - UInt32 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::drvi_crash_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/CodeGen.cc b/dev/LibCompiler/src/CodeGen.cc index 31a809b..3f215c5 100644 --- a/dev/LibCompiler/src/CodeGen.cc +++ b/dev/LibCompiler/src/CodeGen.cc @@ -24,10 +24,9 @@ namespace LibCompiler { ///! @brief Compile for specific format (ELF, PEF, ZBIN) Int32 AssemblyFactory::Compile(STLString sourceFile, const Int32& arch) noexcept { - if (sourceFile.length() < 1 || !fMounted) return LIBCOMPILER_UNIMPLEMENTED; + if (sourceFile.length() < 1) return LIBCOMPILER_UNIMPLEMENTED; if (!fMounted) return LIBCOMPILER_UNIMPLEMENTED; - if (arch != fMounted->Arch()) return LIBCOMPILER_INVALID_ARCH; try { @@ -48,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/Cl/CPlusPlusCompilerAMD64.cc b/dev/LibCompiler/src/Frontend/CPlusPlusCompilerAMD64.cc index bfa1896..217f86b 100644 --- a/dev/LibCompiler/src/Cl/CPlusPlusCompilerAMD64.cc +++ b/dev/LibCompiler/src/Frontend/CPlusPlusCompilerAMD64.cc @@ -68,24 +68,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 struct CompilerStructMap final { - std::string fName; - std::string fReg; - std::vector<std::pair<UInt32, 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; + LibCompiler::STLString fLastFile; + LibCompiler::STLString fLastError; }; } // namespace Detail @@ -120,14 +119,14 @@ static Boolean kInBraces = false; static size_t kBracesCount = 0UL; /* @brief C++ compiler backend for the NeKernel C++ driver */ -class CompilerFrontendCPlusPlus final : public LibCompiler::CompilerFrontendInterface { +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; }; @@ -136,15 +135,15 @@ class CompilerFrontendCPlusPlus final : public LibCompiler::CompilerFrontendInte 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", }; @@ -156,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; ///////////////////////////////////////////////////////////////////////////////////////// @@ -166,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.length() < 1) 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; @@ -205,10 +207,8 @@ 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) == std::string::npos) continue; + if (text.find(keyword.first.keyword_name) == LibCompiler::STLString::npos) continue; switch (keyword.first.keyword_kind) { case LibCompiler::KeywordKind::kKeywordKindClass: { @@ -220,15 +220,16 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { std::size_t openParen = text.find("(", keywordPos); std::size_t closeParen = text.find(")", openParen); - if (keywordPos == std::string::npos || openParen == std::string::npos || - closeParen == std::string::npos || closeParen <= openParen) { + if (keywordPos == LibCompiler::STLString::npos || + openParen == LibCompiler::STLString::npos || + closeParen == LibCompiler::STLString::npos || closeParen <= openParen) { Detail::print_error("Malformed if expression: " + text, file); - return false; + 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("<=")); @@ -295,7 +296,7 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { done_iterarting_on_if: - std::string fnName = text; + LibCompiler::STLString fnName = text; fnName.erase(fnName.find(keyword.first.keyword_name)); for (auto& ch : fnName) { @@ -318,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) { @@ -334,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); @@ -367,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; @@ -399,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); @@ -413,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("+=")); @@ -436,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; @@ -447,9 +449,9 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { } } - std::string instr = "mov "; + LibCompiler::STLString instr = "mov "; - std::vector<std::string> newVars; + std::vector<LibCompiler::STLString> newVars; if (typeFound && keyword.first.keyword_kind != LibCompiler::KeywordKind::kKeywordKindVariableInc && @@ -458,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); } @@ -525,13 +527,13 @@ 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; } @@ -563,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); } @@ -581,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); } @@ -637,10 +639,10 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { } 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])) { @@ -670,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); @@ -703,8 +705,7 @@ Boolean CompilerFrontendCPlusPlus::Compile(std::string text, std::string file) { } } - kState.fOutputValue = syntax_tree.fUserValue; - return true; + return syntax_tree; } ///////////////////////////////////////////////////////////////////////////////////////// @@ -724,23 +725,19 @@ class AssemblyCPlusPlusInterface final LC_ASSEMBLY_INTERFACE { 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; - std::string dest = src; + LibCompiler::STLString dest = src; dest += ".pp.masm"; std::ofstream out_fp(dest); - std::ifstream src_fp = std::ifstream(src + ".pp"); - std::string line_source; + LibCompiler::STLString line_source; while (std::getline(src_fp, line_source)) { - kCompilerFrontend->Compile(line_source, src); - - out_fp << kState.fOutputValue; - kState.fOutputValue.clear(); + out_fp << kCompilerFrontend->Compile(line_source, src).fUserValue; } return kExitOK; @@ -823,6 +820,8 @@ LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) { ::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; @@ -855,7 +854,7 @@ LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) { continue; } - std::string err = "Unknown option: "; + LibCompiler::STLString err = "Unknown option: "; err += argv[index]; Detail::print_error(err, "cxxdrv"); @@ -863,35 +862,23 @@ LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) { continue; } - std::string argv_i = argv[index]; + LibCompiler::STLString argv_i = argv[index]; - std::vector<std::string> exts = kExtListCxx; - BOOL found = false; + std::vector<LibCompiler::STLString> exts = kExtListCxx; - for (std::string ext : exts) { + for (LibCompiler::STLString ext : exts) { if (argv_i.ends_with(ext)) { - found = true; - if (kFactory.Compile(argv_i, kMachine) != kExitOK) { return LIBCOMPILER_INVALID_DATA; } - } - } - if (!found) { - if (kVerbose) { - Detail::print_error(argv_i + " is not a valid C++ source.", "cxxdrv"); + break; } - - return LIBCOMPILER_INVALID_DATA; } } kFactory.Unmount(); - delete kCompilerFrontend; - kCompilerFrontend = nullptr; - return LIBCOMPILER_SUCCESS; } diff --git a/dev/LibCompiler/src/Linker/DynamicLinkerPEF.cc b/dev/LibCompiler/src/Linkers/DynamicLinkerPEF.cc index edfd47a..edfd47a 100644 --- a/dev/LibCompiler/src/Linker/DynamicLinkerPEF.cc +++ b/dev/LibCompiler/src/Linkers/DynamicLinkerPEF.cc diff --git a/dev/LibCompiler/src/PP/CPlusPlusCompilerPreProcessor.cc b/dev/LibCompiler/src/Macro/CPlusPlusCompilerPreProcessor.cc index 2c7c551..2c7c551 100644 --- a/dev/LibCompiler/src/PP/CPlusPlusCompilerPreProcessor.cc +++ b/dev/LibCompiler/src/Macro/CPlusPlusCompilerPreProcessor.cc |
