diff options
| author | Amlal El Mahrouss <amlal@nekernel.org> | 2025-05-23 03:48:06 +0200 |
|---|---|---|
| committer | Amlal El Mahrouss <amlal@nekernel.org> | 2025-05-23 03:48:06 +0200 |
| commit | 2eed4954c762bb8050e40798c3d9f1d3998324d1 (patch) | |
| tree | 8848d4345fca4d62c23d1e7136eeff2978c9e6c5 /dev/LibCompiler/src/CCompilerPower64.cc | |
| parent | 8ad58a91a11380203c4a81fe4dc93e7734631b32 (diff) | |
feat!(LibCompiler): Codebase and diagram has been improved.
Signed-off-by: Amlal El Mahrouss <amlal@nekernel.org>
Diffstat (limited to 'dev/LibCompiler/src/CCompilerPower64.cc')
| -rw-r--r-- | dev/LibCompiler/src/CCompilerPower64.cc | 1303 |
1 files changed, 0 insertions, 1303 deletions
diff --git a/dev/LibCompiler/src/CCompilerPower64.cc b/dev/LibCompiler/src/CCompilerPower64.cc deleted file mode 100644 index 91cd32f..0000000 --- a/dev/LibCompiler/src/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/CompilerFrontend.h> -#include <LibCompiler/Detail/ClUtils.h> -#include <LibCompiler/UUID.h> -#include <cstdio> -#include <fstream> -#include <iostream> -#include <memory> -#include <random> -#include <string> -#include <utility> -#include <vector> - -#define kExitOK 0 - -/// @author EL Mahrouss Amlal (amlal@nekernel.org) -/// @file cc.cxx -/// @brief POWER64 C Compiler. - -///////////////////// - -/// ANSI ESCAPE CODES - -///////////////////// - -#define kBlank "\e[0;30m" -#define kRed "\e[0;31m" -#define kWhite "\e[0;97m" - -///////////////////////////////////// - -/// INTERNAL STRUCTURES OF THE C COMPILER - -///////////////////////////////////// - -namespace Detail { -// \brief name to register struct. -struct CompilerRegisterMap final { - std::string fName; - std::string fReg; -}; - -// \brief Map for C structs -// \author amlel -struct CompilerStructMap final { - /// 'struct::my_foo' - std::string fName; - - /// if instance: stores a valid register. - std::string fReg; - - /// offset count - std::size_t fOffsetsCnt; - - /// offset array. - std::vector<std::pair<Int32, std::string>> fOffsets; -}; - -struct CompilerState final { - std::vector<LibCompiler::SyntaxLeafList> fSyntaxTreeList; - std::vector<CompilerRegisterMap> kStackFrame; - std::vector<CompilerStructMap> kStructMap; - LibCompiler::SyntaxLeafList* fSyntaxTree{nullptr}; - std::unique_ptr<std::ofstream> fOutputAssembly; - std::string fLastFile; - std::string fLastError; - bool fVerbose; -}; -} // namespace Detail - -static Detail::CompilerState kState; -static std::string kIfFunction = ""; - -namespace Detail { -/// @brief prints an error into stdout. -/// @param reason the reason of the error. -/// @param file where does it originate from? -void print_error(std::string reason, std::string file) noexcept; - -struct CompilerType final { - std::string fName; - std::string fValue; -}; -} // namespace Detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// Target architecture. -static int kMachine = 0; - -///////////////////////////////////////// - -// REGISTERS ACCORDING TO USED ASSEMBLER - -///////////////////////////////////////// - -static size_t kRegisterCnt = kAsmRegisterLimit; -static size_t kStartUsable = 2; -static size_t kUsableLimit = 15; -static size_t kRegisterCounter = kStartUsable; -static std::string kRegisterPrefix = kAsmRegisterPrefix; - -///////////////////////////////////////// - -// COMPILER PARSING UTILITIES/STATES. - -///////////////////////////////////////// - -static std::vector<std::string> kFileList; -static LibCompiler::AssemblyFactory kFactory; -static bool kInStruct = false; -static bool kOnWhileLoop = false; -static bool kOnForLoop = false; -static bool kInBraces = false; -static bool kIfFound = false; -static size_t kBracesCount = 0UL; - -/* @brief C compiler backend for C */ -class CompilerFrontendPower64 final : public LibCompiler::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::drv_segfault_handler); - - kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); - kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); - kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); - kCompilerTypes.push_back({.fName = "int", .fValue = "dword"}); - kCompilerTypes.push_back({.fName = "long", .fValue = "qword"}); - kCompilerTypes.push_back({.fName = "*", .fValue = "offset"}); - - bool skip = false; - - kFactory.Mount(new AssemblyMountpointCLang()); - kMachine = LibCompiler::AssemblyFactory::kArchPowerPC; - kCompilerFrontend = new CompilerFrontendPower64(); - - for (auto index = 1UL; index < argc; ++index) { - if (skip) { - skip = false; - continue; - } - - if (argv[index][0] == '-') { - if (strcmp(argv[index], "-v") == 0 || strcmp(argv[index], "-version") == 0) { - kSplashCxx(); - return kExitOK; - } - - if (strcmp(argv[index], "-verbose") == 0) { - kState.fVerbose = true; - - continue; - } - - if (strcmp(argv[index], "-h") == 0 || strcmp(argv[index], "-help") == 0) { - cc_print_help(); - - return kExitOK; - } - - if (strcmp(argv[index], "-dialect") == 0) { - if (kCompilerFrontend) std::cout << kCompilerFrontend->Language() << "\n"; - - return kExitOK; - } - - if (strcmp(argv[index], "-fmax-exceptions") == 0) { - try { - kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); - } - // catch anything here - catch (...) { - kErrorLimit = 0; - } - - skip = true; - - continue; - } - - std::string err = "Unknown command: "; - err += argv[index]; - - Detail::print_error(err, "cc"); - - continue; - } - - kFileList.emplace_back(argv[index]); - - std::string srcFile = argv[index]; - - if (strstr(argv[index], kExt) == nullptr) { - if (kState.fVerbose) { - Detail::print_error(srcFile + " is not a valid C source.\n", "cc"); - } - - return 1; - } - - if (kFactory.Compile(srcFile, kMachine) != kExitOK) return 1; - } - - return kExitOK; -} - -// Last rev 8-1-24 |
