diff options
| author | Amlal El Mahrouss <amlal.elmahrouss@icloud.com> | 2024-01-27 09:12:14 +0100 |
|---|---|---|
| committer | Amlal El Mahrouss <amlal.elmahrouss@icloud.com> | 2024-01-27 09:12:14 +0100 |
| commit | 59a2e775507d01f3ebc8435bf749ab6d3d5b3eeb (patch) | |
| tree | 2061a6494b2cd14b1109030ba9540685cf60a551 /Private/CompilerKit | |
| parent | f1746ae6c3e305f1be21c68a79e01f57d6ec911a (diff) | |
Breaking changes: Reworked structure of project.
Signed-off-by: Amlal El Mahrouss <amlal.elmahrouss@icloud.com>
Diffstat (limited to 'Private/CompilerKit')
| -rw-r--r-- | Private/CompilerKit/AsmKit/Arch/32x0.hpp | 96 | ||||
| -rw-r--r-- | Private/CompilerKit/AsmKit/Arch/64x0.hpp | 108 | ||||
| -rw-r--r-- | Private/CompilerKit/AsmKit/AsmKit.cc | 62 | ||||
| -rw-r--r-- | Private/CompilerKit/AsmKit/AsmKit.hpp | 123 | ||||
| -rw-r--r-- | Private/CompilerKit/Compiler.hpp | 36 | ||||
| -rw-r--r-- | Private/CompilerKit/Defines.hpp | 146 | ||||
| -rw-r--r-- | Private/CompilerKit/ParserKit.hpp | 111 | ||||
| -rw-r--r-- | Private/CompilerKit/StdKit/AE.hpp | 122 | ||||
| -rw-r--r-- | Private/CompilerKit/StdKit/ErrorID.hpp | 22 | ||||
| -rw-r--r-- | Private/CompilerKit/StdKit/ErrorOr.hpp | 58 | ||||
| -rw-r--r-- | Private/CompilerKit/StdKit/PEF.hpp | 112 | ||||
| -rw-r--r-- | Private/CompilerKit/StdKit/Ref.hpp | 87 | ||||
| -rw-r--r-- | Private/CompilerKit/StdKit/String.cc | 242 | ||||
| -rw-r--r-- | Private/CompilerKit/StdKit/String.hpp | 72 |
14 files changed, 1397 insertions, 0 deletions
diff --git a/Private/CompilerKit/AsmKit/Arch/32x0.hpp b/Private/CompilerKit/AsmKit/Arch/32x0.hpp new file mode 100644 index 0000000..28bf754 --- /dev/null +++ b/Private/CompilerKit/AsmKit/Arch/32x0.hpp @@ -0,0 +1,96 @@ +/* + * ======================================================== + * + * MPCC + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Defines.hpp> + +// @brief 32x0 support. +// @file Arch/32x0.hpp + +#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ + { .fName = __NAME, .fOpcode = __OPCODE, .fFunct3 = __FUNCT3, .fFunct7 = __FUNCT7 }, + + + + +#define kAsmImmediate 0x01 +#define kAsmSyscall 0x02 +#define kAsmJump 0x03 +#define kAsmNoArgs 0x04 + +#define kAsmByte 0 +#define kAsmHWord 1 +#define kAsmWord 2 + +struct CpuCode32x0 +{ + const char fName[16]; + char fOpcode; + char fSize; + char fFunct3; + char fFunct7; +}; + +#define kAsmDWordStr ".dword" /* 64 bit */ +#define kAsmWordStr ".word" /* 32-bit */ +#define kAsmHWordStr ".half" /* 16-bit */ +#define kAsmByteStr ".byte" /* 8-bit */ + +inline std::vector<CpuCode32x0> kOpcodes32x0 = { + kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. + kAsmOpcodeDecl("jmp", 0b1110011, 0b001, kAsmJump) // jump to branch + kAsmOpcodeDecl("move", 0b0100011, 0b101, kAsmImmediate) // move registers + kAsmOpcodeDecl("push", 0b0111011, 0b000, kAsmImmediate) // push to sp + kAsmOpcodeDecl("pop", 0b0111011, 0b001, kAsmImmediate) // pop from sp. + kAsmOpcodeDecl("cls", 0b0111011, 0b010, kAsmImmediate) // setup stack and call, store address to CR. + kAsmOpcodeDecl("rts", 0b0111011, 0b110, kAsmImmediate) // pull stack and return form CR. + kAsmOpcodeDecl("int", 0b0111111, 0b000, kAsmSyscall) // raise interrupt +}; + +// \brief 64x0 register prefix +// example: r32, r0 +// r32 -> sp +// r0 -> hw zero + +#define kAsmRegisterPrefix "r" +#define kAsmRegisterLimit 16 +#define kAsmPcRegister 17 +#define kAsmCrRegister 18 +#define kAsmSpRegister 5 + +/* return address register */ +#define kAsmRetRegister 19 + +///////////////////////////////////////////////////////////////////////////// + +// SYSTEM CALL ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | OFF | + +// IMMEDIATE ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | REG | +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG | OFF | + +// REG TO REG ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG2 | + +//////////////////////////////// + +// LOAD/CALL INTERRUPTS + +// SET A HANDLER IN ADDRESS: TODO: find one +// DISABLE INTERRUPTS +// PROCESS INTERRUPT +// ENABLE INTERRUPTS + +////////////////////////////////
\ No newline at end of file diff --git a/Private/CompilerKit/AsmKit/Arch/64x0.hpp b/Private/CompilerKit/AsmKit/Arch/64x0.hpp new file mode 100644 index 0000000..fde40fa --- /dev/null +++ b/Private/CompilerKit/AsmKit/Arch/64x0.hpp @@ -0,0 +1,108 @@ +/* + * ======================================================== + * + * MPCC + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Defines.hpp> + +// @brief 64x0 support. +// @file Arch/64x0.hpp + +#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ + { .fName = __NAME, .fOpcode = __OPCODE, .fFunct3 = __FUNCT3, .fFunct7 = __FUNCT7 }, + + + +#define kAsmImmediate 0x01 +#define kAsmRegToReg 0x02 +#define kAsmSyscall 0x03 +#define kAsmJump 0x04 +#define kAsmNoArgs 0x00 + +typedef char e64k_character_t; +typedef uint8_t e64k_num_t; + +struct CpuCode64x0 +{ + const e64k_character_t fName[16]; + e64k_num_t fOpcode; + e64k_num_t fFunct3; + e64k_num_t fFunct7; +}; + +inline std::vector<CpuCode64x0> kOpcodes64x0 = { + kAsmOpcodeDecl("nop", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation. + kAsmOpcodeDecl("np", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation. + kAsmOpcodeDecl("jlr", 0b1110011, 0b0000111, kAsmJump) // jump to linked return register + kAsmOpcodeDecl("jrl", 0b1110011, 0b0001111, kAsmJump) // jump from return register. + kAsmOpcodeDecl("mv", 0b0100011, 0b101, kAsmRegToReg) + kAsmOpcodeDecl("bg", 0b1100111, 0b111, kAsmRegToReg) + kAsmOpcodeDecl("bl", 0b1100111, 0b011, kAsmRegToReg) + kAsmOpcodeDecl("beq", 0b1100111, 0b000, kAsmRegToReg) + kAsmOpcodeDecl("bne", 0b1100111, 0b001, kAsmRegToReg) + kAsmOpcodeDecl("bge", 0b1100111, 0b101, kAsmRegToReg) + kAsmOpcodeDecl("ble", 0b1100111, 0b100, kAsmRegToReg) + kAsmOpcodeDecl("stw", 0b0001111, 0b100, kAsmImmediate) + kAsmOpcodeDecl("ldw", 0b0001111, 0b100, kAsmImmediate) + kAsmOpcodeDecl("lda", 0b0001111, 0b101, kAsmImmediate) + kAsmOpcodeDecl("sta", 0b0001111, 0b001, kAsmImmediate) + // add/sub without carry flag + kAsmOpcodeDecl("add", 0b0101011, 0b100, kAsmImmediate) + kAsmOpcodeDecl("dec", 0b0101011, 0b101, kAsmImmediate) + // add/sub with carry flag + kAsmOpcodeDecl("addc", 0b0101011, 0b110, kAsmImmediate) + kAsmOpcodeDecl("decc", 0b0101011, 0b111, kAsmImmediate) + kAsmOpcodeDecl("int", 0b1110011, 0b00, kAsmSyscall) + kAsmOpcodeDecl("pha", 0b1110011, 0b00, kAsmNoArgs) + kAsmOpcodeDecl("pla", 0b1110011, 0b01, kAsmNoArgs) +}; + +// \brief 64x0 register prefix +// example: r32, r0 +// r32 -> sp +// r0 -> hw zero + +#define kAsmFloatZeroRegister 0 +#define kAsmZeroRegister 0 + +#define kAsmRegisterPrefix "r" +#define kAsmRegisterLimit 30 +#define kAsmPcRegister 17 +#define kAsmCrRegister 18 +#define kAsmSpRegister 5 + +/* return address register */ +#define kAsmRetRegister 19 + +///////////////////////////////////////////////////////////////////////////// + +// SYSTEM CALL/JUMP ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | OFF | + +// IMMEDIATE ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | REG | +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG | OFF | + +// REG TO REG ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG2 | + +//////////////////////////////// + +// LOAD/CALL INTERRUPTS + +// SET A HANDLER IN ADDRESS: +// DISABLE INTERRUPTS +// PROCESS INTERRUPT +// ENABLE INTERRUPTS + +////////////////////////////////
\ No newline at end of file diff --git a/Private/CompilerKit/AsmKit/AsmKit.cc b/Private/CompilerKit/AsmKit/AsmKit.cc new file mode 100644 index 0000000..1eea5cc --- /dev/null +++ b/Private/CompilerKit/AsmKit/AsmKit.cc @@ -0,0 +1,62 @@ +/* + * ======================================================== + * + * MPCC + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +#include <AsmKit/AsmKit.hpp> +#include <StdKit/ErrorID.hpp> + +/** + * @file AsmKit.cc + * @author Amlal El Mahrouss (amlal@mahrouss.com) + * @brief Assembler Kit + * @version 0.1 + * @date 2024-01-27 + * + * @copyright Copyright (c) 2024, Mahrouss Logic + * + */ + +#include <iostream> + +//! @file AsmKit.cpp +//! @brief AssemblyKit source implementation. + +namespace CompilerKit +{ + //! @brief Compile for specific format (ELF, PEF, ZBIN) + Int32 AssemblyFactory::Compile(StringView& sourceFile, + const Int32& arch) noexcept + { + if (sourceFile.Length() < 1 || + !fMounted) + return CXXKIT_UNIMPLEMENTED; + + return fMounted->CompileToFormat(sourceFile, arch); + } + + //! @brief mount assembly backend. + void AssemblyFactory::Mount(AssemblyMountpoint* mountPtr) noexcept + { + if (mountPtr) + { + fMounted = mountPtr; + } + } + + AssemblyMountpoint* AssemblyFactory::Unmount() noexcept + { + auto mount_prev = fMounted; + + if (mount_prev) + { + fMounted = nullptr; + } + + return mount_prev; + } +} diff --git a/Private/CompilerKit/AsmKit/AsmKit.hpp b/Private/CompilerKit/AsmKit/AsmKit.hpp new file mode 100644 index 0000000..a159c05 --- /dev/null +++ b/Private/CompilerKit/AsmKit/AsmKit.hpp @@ -0,0 +1,123 @@ +/* + * ======================================================== + * + * MPCC + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Compiler.hpp> +#include <CompilerKit/Defines.hpp> +#include <CompilerKit/StdKit/String.hpp> + +namespace CompilerKit +{ + // + // @brief Frontend to Assembly mountpoint. + // + class AssemblyMountpoint + { + public: + explicit AssemblyMountpoint() = default; + virtual ~AssemblyMountpoint() = default; + + CXXKIT_COPY_DEFAULT(AssemblyMountpoint); + + //@ brief compile to object file. + // Example C++ -> MASM -> AE object. + virtual Int32 CompileToFormat(StringView& src, Int32 arch) = 0; + + }; + + /// @brief Simple assembly factory + class AssemblyFactory final + { + public: + explicit AssemblyFactory() = default; + ~AssemblyFactory() = default; + + CXXKIT_COPY_DEFAULT(AssemblyFactory); + + public: + enum + { + kArchAMD64, + kArch32x0, + kArch64x0, + kArchRISCV, + kArchUnknown, + }; + + Int32 Compile(StringView& sourceFile, const Int32& arch) noexcept; + + void Mount(AssemblyMountpoint* mountPtr) noexcept; + AssemblyMountpoint* Unmount() noexcept; + + private: + AssemblyMountpoint* fMounted{ nullptr }; + + }; + + class PlatformAssembler + { + public: + explicit PlatformAssembler() = default; + ~PlatformAssembler() = default; + + CXXKIT_COPY_DEFAULT(PlatformAssembler); + + virtual std::string CheckLine(std::string &line, const std::string &file) = 0; + virtual bool WriteLine(std::string &line, const std::string &file) = 0; + virtual bool WriteNumber(const std::size_t &pos, std::string &from_what) = 0; + + }; + +#ifdef __ASM_NEED_64x0__ + + class PlatformAssembler64x0 final : public PlatformAssembler + { + public: + explicit PlatformAssembler64x0() = default; + ~PlatformAssembler64x0() = default; + + CXXKIT_COPY_DEFAULT(PlatformAssembler64x0); + + virtual std::string CheckLine(std::string &line, const std::string &file) override; + virtual bool WriteLine(std::string &line, const std::string &file) override; + virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) override; + + }; + +#endif // __ASM_NEED_64x0__ + +#ifdef __ASM_NEED_32x0__ + + class PlatformAssembler32x0 final : public PlatformAssembler + { + public: + explicit PlatformAssembler32x0() = default; + ~PlatformAssembler32x0() = default; + + CXXKIT_COPY_DEFAULT(PlatformAssembler32x0); + + virtual std::string CheckLine(std::string &line, const std::string &file) override; + virtual bool WriteLine(std::string &line, const std::string &file) override; + virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) override; + + }; + +#endif // __ASM_NEED_32x0__ + + union NumberCast final + { + explicit NumberCast(UInt64 raw) : raw(raw) {} + ~NumberCast() { raw = 0; } + + char number[8]; + UInt64 raw; + }; +} + diff --git a/Private/CompilerKit/Compiler.hpp b/Private/CompilerKit/Compiler.hpp new file mode 100644 index 0000000..810652f --- /dev/null +++ b/Private/CompilerKit/Compiler.hpp @@ -0,0 +1,36 @@ +/* + * ======================================================== + * + * MPCC + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +//! provide support for Compiler.hpp header. + +#ifndef _CK_CL_HPP +#define _CK_CL_HPP + +#define CXXKIT_COPY_DELETE(KLASS) \ + KLASS &operator=(const KLASS &) = delete; \ + KLASS(const KLASS &) = delete; + + +#define CXXKIT_COPY_DEFAULT(KLASS) \ + KLASS &operator=(const KLASS &) = default; \ + KLASS(const KLASS &) = default; + + +#define CXXKIT_MOVE_DELETE(KLASS) \ + KLASS &operator=(KLASS &&) = delete; \ + KLASS(KLASS &&) = delete; + + +#define CXXKIT_MOVE_DEFAULT(KLASS) \ + KLASS &operator=(KLASS &&) = default; \ + KLASS(KLASS &&) = default; + + + +#endif /* ifndef _CK_CL_HPP */
\ No newline at end of file diff --git a/Private/CompilerKit/Defines.hpp b/Private/CompilerKit/Defines.hpp new file mode 100644 index 0000000..33fca43 --- /dev/null +++ b/Private/CompilerKit/Defines.hpp @@ -0,0 +1,146 @@ +/* + * ======================================================== + * + * MPCC + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +#ifndef __CXXKIT_DEFINES_HPP__ +#define __CXXKIT_DEFINES_HPP__ + +#ifndef Yes +#define Yes true +#endif // ifndef Yes + +#ifndef No +#define No false +#endif // ifndef No + +#include <stdint.h> + +#define SizeType size_t + +#define VoidPtr void* +#define voidPtr VoidPtr + +#define UIntPtr uintptr_t + +#define Int64 int64_t +#define UInt64 uint64_t + +#define Int32 int32_t +#define UInt32 uint32_t + +#define Bool bool + +#define Int16 int16_t +#define UInt16 uint16_t + +#define Int8 int8_t +#define UInt8 uint8_t + +#define CharType char +#define Boolean bool + +#include <new> +#include <cstring> +#include <cassert> + +#define nullPtr std::nullptr_t + +#define MUST_PASS(E) assert(E) + +#ifndef __FORCE_STRLEN +# define __FORCE_STRLEN 1 + +# define string_length(len) strlen(len) +#endif + +#ifndef __FORCE_MEMCPY +# define __FORCE_MEMCPY 1 + +# define rt_copy_memory(dst, src, len) memcpy(dst, src, len) +#endif + +#define CXXKIT_COPY_DELETE(KLASS) \ + KLASS &operator=(const KLASS &) = delete; \ + KLASS(const KLASS &) = delete; + + +#define CXXKIT_COPY_DEFAULT(KLASS) \ + KLASS &operator=(const KLASS &) = default; \ + KLASS(const KLASS &) = default; + + +#define CXXKIT_MOVE_DELETE(KLASS) \ + KLASS &operator=(KLASS &&) = delete; \ + KLASS(KLASS &&) = delete; + + +#define CXXKIT_MOVE_DEFAULT(KLASS) \ + KLASS &operator=(KLASS &&) = default; \ + KLASS(KLASS &&) = default; + + + +#include <ctime> +#include <string> +#include <fstream> + +namespace CompilerKit +{ + inline constexpr int BASE_YEAR = 1900; + + inline std::string current_date() + { + auto time_data = time(nullptr); + auto time_struct = gmtime(&time_data); + + std::string fmt = std::to_string(BASE_YEAR + time_struct->tm_year); + fmt += "-"; + fmt += std::to_string(time_struct->tm_mon + 1); + fmt += "-"; + fmt += std::to_string(time_struct->tm_mday); + + return fmt; + } + + inline bool to_str(CharType *str, Int32 limit, Int32 base) + { + if (limit == 0) + return false; + + Int32 copy_limit = limit; + Int32 cnt = 0; + Int32 ret = base; + + while (limit != 1) + { + ret = ret % 10; + str[cnt] = ret; + + ++cnt; + --limit; + --ret; + } + + str[copy_limit] = '\0'; + return true; + } +} + +typedef char char_type; + +#define kObjectFileExt ".o" +#define kAsmFileExts { ".64x", ".32x", ".masm", ".s", ".S" } + +#ifdef __MODULE_NEED__ +# define MPCC_MODULE(name) int name(int argc, char** argv) +#else +# define MPCC_MODULE(name) int main(int argc, char** argv) +#endif /* ifdef __MODULE_NEED__ */ + +#endif /* ifndef __CXXKIT_DEFINES_HPP__ */ + diff --git a/Private/CompilerKit/ParserKit.hpp b/Private/CompilerKit/ParserKit.hpp new file mode 100644 index 0000000..49907e5 --- /dev/null +++ b/Private/CompilerKit/ParserKit.hpp @@ -0,0 +1,111 @@ +/* + * ======================================================== + * + * MPCC + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/AsmKit/AsmKit.hpp> + +namespace ParserKit +{ + using namespace CompilerKit; + + class CompilerBackend + { + public: + explicit CompilerBackend() = default; + virtual ~CompilerBackend() = default; + + CXXKIT_COPY_DEFAULT(CompilerBackend); + + // NOTE: cast this to your user defined ast. + typedef void* AstType; + + //! @brief Compile a syntax tree ouf of the text. + //! Also takes the source file name for metadata. + + virtual bool Compile(const std::string& text, const char* file) = 0; + + //! @brief What language are we dealing with? + virtual const char* Language() { return "Generic Language"; } + + }; + + struct SyntaxLeafList; + struct SyntaxLeafList; + + struct SyntaxLeafList final + { + struct SyntaxLeaf final + { + Int32 fUserType; + std::string fUserData; + std::string fUserValue; + struct SyntaxLeaf* fNext; + }; + + std::vector<SyntaxLeaf> fLeafList; + SizeType fNumLeafs; + + size_t SizeOf() { return fNumLeafs; } + std::vector<SyntaxLeaf>& Get() { return fLeafList; } + SyntaxLeaf& At(size_t index) { return fLeafList[index]; } + + }; + + /// find the perfect matching word in a haystack. + /// \param haystack base string + /// \param needle the string we search for. + /// \return if we found it or not. + inline bool find_word(const std::string& haystack,const std::string& needle) noexcept + { + auto index = haystack.find(needle); + + // check for needle validity. + if (index == std::string::npos) + return false; + + // declare lambda + auto not_part_of_word = [&](int index){ + if (std::isspace(haystack[index]) || std::ispunct(haystack[index])) + return true; + + if (index < 0 || index >= haystack.size()) + return true; + + return false; + }; + + return not_part_of_word(index - 1) && + not_part_of_word(index + needle.size()); + } + + /// find a word within strict conditions and returns a range of it. + /// \param haystack + /// \param needle + /// \return position of needle. + inline std::size_t find_word_range(const std::string& haystack, const std::string& needle) noexcept + { + auto index = haystack.find(needle); + + // check for needle validity. + if (index == std::string::npos) + return false; + + if (!isalnum((haystack[index + needle.size() + 1])) && + !isdigit(haystack[index + needle.size() + 1]) && + !isalnum((haystack[index - needle.size() - 1])) && + !isdigit(haystack[index - needle.size() - 1])) + { + return index; + } + + return false; + } +} + diff --git a/Private/CompilerKit/StdKit/AE.hpp b/Private/CompilerKit/StdKit/AE.hpp new file mode 100644 index 0000000..8843404 --- /dev/null +++ b/Private/CompilerKit/StdKit/AE.hpp @@ -0,0 +1,122 @@ +/* + * ======================================================== + * + * MPCC + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Defines.hpp> + +#define kAEMag0 'A' +#define kAEMag1 'E' + +#define kAESymbolLen 64 +#define kAEPad 8 +#define kAEMagLen 2 +#define kAEInvalidOpcode 0x00 + +// Advanced Executable File Format for MetroLink. +// Reloctable by offset is the default strategy. +// You can also relocate at runtime but that's up to the operating system loader. + +namespace CompilerKit +{ + // @brief Advanced Executable Header + // One thing to keep in mind. + // This object format, is reloctable. + typedef struct AEHeader final + { + CharType fMagic[kAEMagLen]; + CharType fArch; + SizeType fCount; + CharType fSize; + SizeType fStartCode; + SizeType fCodeSize; + CharType fPad[kAEPad]; + } __attribute__((packed)) AEHeader, *AEHeaderPtr; + + // @brief Advanced Executable Record. + // Could be data, code or bss. + // fKind must be filled with PEF fields. + + typedef struct AERecordHeader final + { + CharType fName[kAESymbolLen]; + SizeType fKind; + SizeType fSize; + SizeType fFlags; + UIntPtr fOffset; + CharType fPad[kAEPad]; + } __attribute__((packed)) AERecordHeader, *AERecordHeaderPtr; + + enum + { + kKindRelocationByOffset = 0x23f, + kKindRelocationAtRuntime = 0x34f, + }; +} + + +// provide operator<< for AE + +std::ofstream &operator<<(std::ofstream &fp, CompilerKit::AEHeader &container) +{ + fp.write((char *)&container, sizeof(CompilerKit::AEHeader)); + + return fp; +} + +std::ofstream &operator<<(std::ofstream &fp, CompilerKit::AERecordHeader &container) +{ + fp.write((char *)&container, sizeof(CompilerKit::AERecordHeader)); + + return fp; +} + +std::ifstream &operator>>(std::ifstream& fp, CompilerKit::AEHeader& container) +{ + fp.read((char*)&container, sizeof(CompilerKit::AEHeader)); + return fp; +} + +std::ifstream &operator>>(std::ifstream& fp, CompilerKit::AERecordHeader& container) +{ + fp.read((char*)&container, sizeof(CompilerKit::AERecordHeader)); + return fp; +} + +namespace CompilerKit::Utils +{ + class AEReadableProtocol final + { + public: + std::ifstream USED_FP; + + public: + AEReadableProtocol() = default; + ~AEReadableProtocol() = default; + + CXXKIT_COPY_DELETE(AEReadableProtocol); + + AERecordHeaderPtr Read(char* raw, std::size_t sz) + { + if (!raw) + return nullptr; + + return this->_Read<AERecordHeader>(raw, sz * sizeof(AERecordHeader)); + } + + private: + template <typename TypeClass> + TypeClass* _Read(char* raw, std::size_t sz) + { + USED_FP.read(raw, std::streamsize(sz)); + return reinterpret_cast<TypeClass*>(raw); + } + + }; +}
\ No newline at end of file diff --git a/Private/CompilerKit/StdKit/ErrorID.hpp b/Private/CompilerKit/StdKit/ErrorID.hpp new file mode 100644 index 0000000..e7bc7de --- /dev/null +++ b/Private/CompilerKit/StdKit/ErrorID.hpp @@ -0,0 +1,22 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <StdKit/ErrorOr.hpp> +#include <Defines.hpp> + +#define CXXKIT_EXEC_ERROR -30 +#define CXXKIT_FILE_NOT_FOUND -31 +#define CXXKIT_DIR_NOT_FOUND -32 +#define CXXKIT_FILE_EXISTS -33 +#define CXXKIT_TOO_LONG -34 +#define CXXKIT_INVALID_DATA -35 +#define CXXKIT_UNIMPLEMENTED -36 +#define CXXKIT_FAT_ERROR -37 diff --git a/Private/CompilerKit/StdKit/ErrorOr.hpp b/Private/CompilerKit/StdKit/ErrorOr.hpp new file mode 100644 index 0000000..97aeaa2 --- /dev/null +++ b/Private/CompilerKit/StdKit/ErrorOr.hpp @@ -0,0 +1,58 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Defines.hpp> +#include <CompilerKit/StdKit/Ref.hpp> + +namespace CompilerKit +{ +using ErrorT = UInt32; + +template <typename T> +class ErrorOr final +{ + public: + ErrorOr() = default; + ~ErrorOr() = default; + + public: + explicit ErrorOr(Int32 err) + : mId(err) + {} + + explicit ErrorOr(nullPtr Null) + {} + + explicit ErrorOr(T Class) + : mRef(Class) + {} + + ErrorOr &operator=(const ErrorOr &) = default; + ErrorOr(const ErrorOr &) = default; + + Ref<T> Leak() + { + return mRef; + } + + operator bool() + { + return mRef; + } + + private: + Ref<T> mRef; + Int32 mId{0}; +}; + +using ErrorOrAny = ErrorOr<voidPtr>; + +} // namespace CompilerKit diff --git a/Private/CompilerKit/StdKit/PEF.hpp b/Private/CompilerKit/StdKit/PEF.hpp new file mode 100644 index 0000000..163e46f --- /dev/null +++ b/Private/CompilerKit/StdKit/PEF.hpp @@ -0,0 +1,112 @@ +/* + * ======================================================== + * + * MPCC + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Defines.hpp> + +// @file PEF.hpp +// @brief Preferred Executable Format + +#define kPefMagic "PEF" +#define kPefMagicFat "FEP" + +#define kPefExt ".out" +#define kPefDylibExt ".lib" +#define kPefObjectExt ".o" +#define kPefDebugExt ".dbg" + +#define kPefMagicLen 3 + +#define kPefVersion 2 +#define kPefNameLen 64 + +#define kPefBaseOrigin 0x1000 + +namespace CompilerKit +{ + enum + { + kPefArchIntel86S = 100, + kPefArchAMD64, + kPefArchRISCV, + kPefArch64000, /* 64x0 RISC architecture. */ + kPefArch32000, + kPefArchInvalid = 0xFF, + }; + + enum + { + kPefKindExec = 1, /* .o/.pef/<none> */ + kPefKindSharedObject = 2, /* .lib */ + kPefKindObject = 4, /* .obj */ + kPefKindDwarf = 5, /* .dsym */ + }; + + /* PEF container */ + typedef struct PEFContainer final + { + CharType Magic[kPefMagicLen]; + UInt32 Linker; + UInt32 Version; + UInt32 Kind; + UInt32 Abi; + UInt32 Cpu; + UInt32 SubCpu; /* Cpu specific information */ + UIntPtr Start; /* Origin of code */ + SizeType HdrSz; /* Size of header */ + SizeType Count; /* container header count */ + } __attribute__((packed)) PEFContainer; + + /* First PEFCommandHeader starts after PEFContainer */ + /* Last container is __exec_end */ + + /* PEF executable section and commands. */ + + typedef struct PEFCommandHeader final + { + CharType Name[kPefNameLen]; /* container name */ + UInt32 Flags; /* container flags */ + UInt16 Kind; /* container kind */ + UIntPtr Offset; /* file offset */ + SizeType Size; /* file size */ + } __attribute__((packed)) PEFCommandHeader; + + enum + { + kPefCode = 0xC, + kPefData = 0xD, + kPefZero = 0xE, + kPefLinkerID = 0x1, + }; +} + +inline std::ofstream& operator<<(std::ofstream& fp, CompilerKit::PEFContainer& container) +{ + fp.write((char*)&container, sizeof(CompilerKit::PEFContainer)); + return fp; +} + +inline std::ofstream& operator<<(std::ofstream& fp, CompilerKit::PEFCommandHeader& container) +{ + fp.write((char*)&container, sizeof(CompilerKit::PEFCommandHeader)); + return fp; +} + +std::ifstream &operator>>(std::ifstream& fp, CompilerKit::PEFContainer& container) +{ + fp.read((char*)&container, sizeof(CompilerKit::PEFContainer)); + return fp; +} + +std::ifstream &operator>>(std::ifstream& fp, CompilerKit::PEFCommandHeader& container) +{ + fp.read((char*)&container, sizeof(CompilerKit::PEFCommandHeader)); + return fp; +} diff --git a/Private/CompilerKit/StdKit/Ref.hpp b/Private/CompilerKit/StdKit/Ref.hpp new file mode 100644 index 0000000..9b79ca9 --- /dev/null +++ b/Private/CompilerKit/StdKit/Ref.hpp @@ -0,0 +1,87 @@ + +/* + * ======================================================== + * + * CompilerKit + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +namespace CompilerKit +{ + // @author Amlal EL Mahrouss + // @brief Reference class, refers to a pointer of data in static memory. + template <typename T> + class Ref final + { + public: + explicit Ref() = default; + ~Ref() = default; + + public: + explicit Ref(T cls, const bool &strong = false) : m_Class(cls), m_Strong(strong) {} + + Ref& operator=(T ref) + { + m_Class = ref; + return *this; + } + + public: + T operator->() const + { + return m_Class; + } + + T &Leak() + { + return m_Class; + } + + T operator*() + { + return m_Class; + } + + bool IsStrong() const + { + return m_Strong; + } + + operator bool() + { + return m_Class; + } + + private: + T m_Class; + bool m_Strong{ false }; + + }; + + template <typename T> + class NonNullRef final + { + public: + NonNullRef() = delete; + NonNullRef(nullPtr) = delete; + + explicit NonNullRef(T *ref) : m_Ref(ref, true) {} + + Ref<T> &operator->() + { + MUST_PASS(m_Ref); + return m_Ref; + } + + NonNullRef &operator=(const NonNullRef<T> &ref) = delete; + NonNullRef(const NonNullRef<T> &ref) = default; + + private: + Ref<T> m_Ref{ nullptr }; + + }; +} // namespace CompilerKit diff --git a/Private/CompilerKit/StdKit/String.cc b/Private/CompilerKit/StdKit/String.cc new file mode 100644 index 0000000..45662ef --- /dev/null +++ b/Private/CompilerKit/StdKit/String.cc @@ -0,0 +1,242 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +/** + * @file String.cc + * @author Amlal (amlal@mahrouss-logic.com) + * @brief String manipulation API. + * @version 0.1 + * @date 2024-01-23 + * + * @copyright Copyright (c) 2024 Mahrouss Logic + * + */ + +#include "String.hpp" +#include <utility> + +namespace CompilerKit +{ + CharType* StringView::Data() + { + return m_Data.data(); + } + + const CharType* StringView::CData() const + { + return m_Data.c_str(); + } + + SizeType StringView::Length() const + { + return m_Data.size(); + } + + bool StringView::operator==(const StringView &rhs) const + { + if (rhs.Length() != Length()) + return false; + + for (SizeType index = 0; index < Length(); ++index) + { + if (rhs.m_Data[index] != m_Data[index]) + return false; + } + + return true; + } + + bool StringView::operator==(const CharType *rhs) const + { + if (string_length(rhs) != Length()) + return false; + + for (SizeType index = 0; index < string_length(rhs); ++index) + { + if (rhs[index] != m_Data[index]) + return false; + } + + return true; + } + + bool StringView::operator!=(const StringView &rhs) const + { + if (rhs.Length() != Length()) + return false; + + for (SizeType index = 0; index < rhs.Length(); ++index) + { + if (rhs.m_Data[index] == m_Data[index]) + return false; + } + + return true; + } + + bool StringView::operator!=(const CharType *rhs) const + { + if (string_length(rhs) != Length()) + return false; + + for (SizeType index = 0; index < string_length(rhs); ++index) + { + if (rhs[index] == m_Data[index]) + return false; + } + + return true; + } + + StringView StringBuilder::Construct(const CharType *data) + { + if (!data || + *data == 0) + return StringView(0); + + StringView view(strlen(data)); + view += data; + + return view; + } + + const char* StringBuilder::FromInt(const char *fmt, int i) + { + if (!fmt) + return ("-1"); + + char *ret = new char[8 + string_length(fmt)]; + + if (!ret) + return ("-1"); + + CharType result[8]; + if (!to_str(result, sizeof(int), i)) + { + delete[] ret; + return ("-1"); + } + + const auto fmt_len = string_length(fmt); + const auto res_len = string_length(result); + + for (SizeType idx = 0; idx < fmt_len; ++idx) + { + if (fmt[idx] == '%') { + SizeType result_cnt = idx; + + for (auto y_idx = idx; y_idx < res_len; ++y_idx) { + ret[result_cnt] = result[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; /* Copy that ret into a buffer, Alloca allocates to the stack */ + } + + const char* StringBuilder::FromBool(const char *fmt, bool i) + { + if (!fmt) + return ("?"); + + const char *boolean_expr = i ? "true" : "false"; + char *ret = new char[i ? 4 : 5 + string_length(fmt)]; + + if (!ret) + return ("?"); + + const auto fmt_len = string_length(fmt); + const auto res_len = string_length(boolean_expr); + + for (SizeType idx = 0; idx < fmt_len; ++idx) + { + if (fmt[idx] == '%') { + SizeType result_cnt = idx; + + for (auto y_idx = idx; y_idx < res_len; ++y_idx) + { + ret[result_cnt] = boolean_expr[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; + } + + bool StringBuilder::Equals(const char *lhs, const char *rhs) + { + if (string_length(rhs) != string_length(lhs)) + return false; + + for (SizeType index = 0; index < string_length(rhs); ++index) + { + if (rhs[index] != lhs[index]) + return false; + } + + return true; + } + + const char *StringBuilder::Format(const char *fmt, const char *fmt2) + { + if (!fmt || !fmt2) + return ("?"); + + char *ret = new char[string_length(fmt2) + string_length(fmt2)]; + if (!ret) + return ("?"); + + for (SizeType idx = 0; idx < string_length(fmt); ++idx) + { + if (fmt[idx] == '%') { + SizeType result_cnt = idx; + for (SizeType y_idx = 0; y_idx < string_length(fmt2); ++y_idx) + { + ret[result_cnt] = fmt2[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; + } + + StringView &StringView::operator+=(const CharType *rhs) + { + this->m_Data += rhs; + this->m_Cur = this->m_Data.size(); + this->m_Sz = this->m_Data.size(); + + return *this; + } + + StringView &StringView::operator+=(const StringView &rhs) + { + this->m_Data += rhs.CData(); + + this->m_Cur = this->m_Data.size(); + this->m_Sz = this->m_Data.size(); + + return *this; + } +} // namespace CompilerKit diff --git a/Private/CompilerKit/StdKit/String.hpp b/Private/CompilerKit/StdKit/String.hpp new file mode 100644 index 0000000..a3d528f --- /dev/null +++ b/Private/CompilerKit/StdKit/String.hpp @@ -0,0 +1,72 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright 2024, Mahrouss Logic, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <CompilerKit/Defines.hpp> +#include <CompilerKit/StdKit/ErrorOr.hpp> + +namespace CompilerKit +{ + class StringView final + { + public: + StringView() = delete; + + explicit StringView(SizeType Sz) : m_Sz(Sz) + { + + } + + ~StringView() = default; + + CXXKIT_COPY_DEFAULT(StringView); + + CharType *Data(); + const CharType *CData() const; + SizeType Length() const; + + bool operator==(const CharType *rhs) const; + bool operator!=(const CharType *rhs) const; + + bool operator==(const StringView &rhs) const; + bool operator!=(const StringView &rhs) const; + + StringView &operator+=(const CharType *rhs); + StringView &operator+=(const StringView &rhs); + + operator bool() + { + return m_Data.empty() == false; + } + + bool operator!() + { + return m_Data.empty() == true; + } + + private: + std::basic_string<char> m_Data{""}; + SizeType m_Sz{0}; + SizeType m_Cur{0}; + + friend class StringBuilder; + + }; + + struct StringBuilder final + { + static StringView Construct(const CharType *data); + static const char* FromInt(const char *fmt, int n); + static const char* FromBool(const char *fmt, bool n); + static const char* Format(const char *fmt, const char* from); + static bool Equals(const char *lhs, const char *rhs); + + }; +} // namespace CompilerKit |
