From befde76cfa46c766e81f74eb5ac65d3dae2dde87 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Sat, 19 Apr 2025 17:33:26 +0200 Subject: dev, LibCompiler, tooling: refactor and separate components into modules (cppdrv, cxxdrv) Signed-off-by: Amlal El Mahrouss --- dev/LibCompiler/AAL/AssemblyInterface.h | 242 --- dev/LibCompiler/AAL/CPU/32x0.h | 97 - dev/LibCompiler/AAL/CPU/64x0.h | 106 -- dev/LibCompiler/AAL/CPU/amd64.h | 58 - dev/LibCompiler/AAL/CPU/arm64.h | 44 - dev/LibCompiler/AAL/CPU/power64.h | 1929 -------------------- dev/LibCompiler/AE.h | 142 ++ dev/LibCompiler/AssemblyInterface.h | 242 +++ dev/LibCompiler/Backend/32x0.h | 97 + dev/LibCompiler/Backend/64x0.h | 106 ++ dev/LibCompiler/Backend/amd64.h | 58 + dev/LibCompiler/Backend/arm64.h | 44 + dev/LibCompiler/Backend/power64.h | 1929 ++++++++++++++++++++ dev/LibCompiler/Defines.h | 4 + dev/LibCompiler/ErrorID.h | 23 + dev/LibCompiler/ErrorOr.h | 61 + dev/LibCompiler/NFC/AE.h | 142 -- dev/LibCompiler/NFC/ErrorID.h | 23 - dev/LibCompiler/NFC/ErrorOr.h | 61 - dev/LibCompiler/NFC/PEF.h | 144 -- dev/LibCompiler/NFC/Ref.h | 103 -- dev/LibCompiler/NFC/StringView.h | 90 - dev/LibCompiler/NFC/XCOFF.h | 41 - dev/LibCompiler/PEF.h | 144 ++ dev/LibCompiler/Parser.h | 2 +- dev/LibCompiler/Ref.h | 103 ++ dev/LibCompiler/StringView.h | 90 + dev/LibCompiler/XCOFF.h | 41 + dev/LibCompiler/src/Assembler32x0.cc | 6 +- dev/LibCompiler/src/Assembler64x0.cc | 6 +- dev/LibCompiler/src/AssemblerAMD64.cc | 6 +- dev/LibCompiler/src/AssemblerARM64.cc | 8 +- dev/LibCompiler/src/AssemblerPower.cc | 8 +- dev/LibCompiler/src/AssemblyFactory.cc | 4 +- dev/LibCompiler/src/CCompiler64x0.cc | 2 +- dev/LibCompiler/src/CCompilerARM64.cc | 2 +- dev/LibCompiler/src/CCompilerPower64.cc | 4 +- dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc | 12 +- .../src/CPlusPlusCompilerPreProcessor.cc | 4 +- dev/LibCompiler/src/Detail/AsmUtils.h | 2 +- dev/LibCompiler/src/Detail/ClUtils.h | 2 +- dev/LibCompiler/src/DynamicLinkerPEF.cc | 60 +- dev/LibCompiler/src/StringView.cc | 2 +- dev/LibDebugger/DebuggerContract.h | 14 +- dev/LibDebugger/POSIXMachContract.h | 11 +- dev/LibDebugger/src/POSIXMachContract.cc | 6 +- 46 files changed, 3165 insertions(+), 3160 deletions(-) delete mode 100644 dev/LibCompiler/AAL/AssemblyInterface.h delete mode 100644 dev/LibCompiler/AAL/CPU/32x0.h delete mode 100644 dev/LibCompiler/AAL/CPU/64x0.h delete mode 100644 dev/LibCompiler/AAL/CPU/amd64.h delete mode 100644 dev/LibCompiler/AAL/CPU/arm64.h delete mode 100644 dev/LibCompiler/AAL/CPU/power64.h create mode 100644 dev/LibCompiler/AE.h create mode 100644 dev/LibCompiler/AssemblyInterface.h create mode 100644 dev/LibCompiler/Backend/32x0.h create mode 100644 dev/LibCompiler/Backend/64x0.h create mode 100644 dev/LibCompiler/Backend/amd64.h create mode 100644 dev/LibCompiler/Backend/arm64.h create mode 100644 dev/LibCompiler/Backend/power64.h create mode 100644 dev/LibCompiler/ErrorID.h create mode 100644 dev/LibCompiler/ErrorOr.h delete mode 100644 dev/LibCompiler/NFC/AE.h delete mode 100644 dev/LibCompiler/NFC/ErrorID.h delete mode 100644 dev/LibCompiler/NFC/ErrorOr.h delete mode 100644 dev/LibCompiler/NFC/PEF.h delete mode 100644 dev/LibCompiler/NFC/Ref.h delete mode 100644 dev/LibCompiler/NFC/StringView.h delete mode 100644 dev/LibCompiler/NFC/XCOFF.h create mode 100644 dev/LibCompiler/PEF.h create mode 100644 dev/LibCompiler/Ref.h create mode 100644 dev/LibCompiler/StringView.h create mode 100644 dev/LibCompiler/XCOFF.h (limited to 'dev') diff --git a/dev/LibCompiler/AAL/AssemblyInterface.h b/dev/LibCompiler/AAL/AssemblyInterface.h deleted file mode 100644 index a9ca95b..0000000 --- a/dev/LibCompiler/AAL/AssemblyInterface.h +++ /dev/null @@ -1,242 +0,0 @@ -/* ------------------------------------------- - - Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved - -------------------------------------------- */ - -#pragma once - -#include -#include -#include - -#define ASSEMBLY_INTERFACE : public LibCompiler::AssemblyInterface - -namespace LibCompiler -{ - /// @brief Assembly to binary generator class. - /// @note This interface creates according to the CPU target of the child class. - class AssemblyInterface - { - public: - explicit AssemblyInterface() = default; - virtual ~AssemblyInterface() = default; - - LIBCOMPILER_COPY_DEFAULT(AssemblyInterface); - - /// @brief compile to object file. - /// @note Example C++ -> MASM -> AE object. - virtual Int32 CompileToFormat(std::string& src, Int32 arch) = 0; - }; - - /// @brief Simple assembly factory - class AssemblyFactory final - { - public: - explicit AssemblyFactory() = default; - ~AssemblyFactory() = default; - - LIBCOMPILER_COPY_DEFAULT(AssemblyFactory); - - public: - enum - { - kArchAMD64, - kArch32x0, - kArch64x0, - kArchRISCV, - kArchPowerPC, - kArchAARCH64, - kArchUnknown, - }; - - Int32 Compile(std::string& sourceFile, const Int32& arch) noexcept; - - void Mount(AssemblyInterface* mountPtr) noexcept; - AssemblyInterface* Unmount() noexcept; - - private: - AssemblyInterface* fMounted{nullptr}; - }; - - union NumberCastBase { - NumberCastBase() = default; - ~NumberCastBase() = default; - }; - - union NumberCast64 final { - NumberCast64() = default; - explicit NumberCast64(UInt64 raw) - : raw(raw) - { - } - - ~NumberCast64() - { - raw = 0; - } - - CharType number[8]; - UInt64 raw; - }; - - union NumberCast32 final { - NumberCast32() = default; - explicit NumberCast32(UInt32 raw) - : raw(raw) - { - } - - ~NumberCast32() - { - raw = 0; - } - - CharType number[4]; - UInt32 raw; - }; - - union NumberCast16 final { - NumberCast16() = default; - explicit NumberCast16(UInt16 raw) - : raw(raw) - { - } - - ~NumberCast16() - { - raw = 0; - } - - CharType number[2]; - UInt16 raw; - }; - - union NumberCast8 final { - NumberCast8() = default; - explicit NumberCast8(UInt8 raw) - : raw(raw) - { - } - - ~NumberCast8() - { - raw = 0; - } - - CharType number; - UInt8 raw; - }; - - class EncoderInterface - { - public: - explicit EncoderInterface() = default; - virtual ~EncoderInterface() = default; - - LIBCOMPILER_COPY_DEFAULT(EncoderInterface); - - 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_AMD64__ - - class EncoderAMD64 final : public EncoderInterface - { - public: - explicit EncoderAMD64() = default; - ~EncoderAMD64() override = default; - - LIBCOMPILER_COPY_DEFAULT(EncoderAMD64); - - 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; - - virtual bool WriteNumber16(const std::size_t& pos, std::string& from_what); - virtual bool WriteNumber32(const std::size_t& pos, std::string& from_what); - virtual bool WriteNumber8(const std::size_t& pos, std::string& from_what); - }; - -#endif // __ASM_NEED_AMD64__ - -#ifdef __ASM_NEED_ARM64__ - - class EncoderARM64 final : public EncoderInterface - { - public: - explicit EncoderARM64() = default; - ~EncoderARM64() override = default; - - LIBCOMPILER_COPY_DEFAULT(EncoderARM64); - - 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_ARM64__ - -#ifdef __ASM_NEED_64x0__ - - class Encoder64x0 final : public EncoderInterface - { - public: - explicit Encoder64x0() = default; - ~Encoder64x0() override = default; - - LIBCOMPILER_COPY_DEFAULT(Encoder64x0); - - 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 Encoder32x0 final : public EncoderInterface - { - public: - explicit Encoder32x0() = default; - ~Encoder32x0() override = default; - - LIBCOMPILER_COPY_DEFAULT(Encoder32x0); - - 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__ - -#ifdef __ASM_NEED_PPC__ - - class EncoderPowerPC final : public EncoderInterface - { - public: - explicit EncoderPowerPC() = default; - ~EncoderPowerPC() override = default; - - LIBCOMPILER_COPY_DEFAULT(EncoderPowerPC); - - 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__ -} // namespace LibCompiler diff --git a/dev/LibCompiler/AAL/CPU/32x0.h b/dev/LibCompiler/AAL/CPU/32x0.h deleted file mode 100644 index 007beab..0000000 --- a/dev/LibCompiler/AAL/CPU/32x0.h +++ /dev/null @@ -1,97 +0,0 @@ -/* ------------------------------------------- - - Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved - -------------------------------------------- */ - -#pragma once - -#include - -// @brief 32x0 support. -// @file CPU/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[32]; - uint8_t fOpcode; - uint8_t fSize; - uint8_t fFunct3; - uint8_t fFunct7; -}; - -#define kAsmDWordStr ".dword" /* 64 bit */ -#define kAsmWordStr ".word" /* 32-bit */ -#define kAsmHWordStr ".half" /* 16-bit */ -#define kAsmByteStr ".byte" /* 8-bit */ - -inline std::vector kOpcodes32x0 = { - kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. (1C) - kAsmOpcodeDecl("jmp", 0b1110011, 0b001, kAsmJump) // jump to branch (2C) - kAsmOpcodeDecl("mov", 0b0100011, 0b101, kAsmImmediate) // move registers (3C) - kAsmOpcodeDecl("psh", 0b0111011, 0b000, kAsmImmediate) // push to sp (2C) - kAsmOpcodeDecl("pop", 0b0111011, 0b001, kAsmImmediate) // pop from sp. (1C) - kAsmOpcodeDecl("lea", 0b0111011, 0b010, - kAsmImmediate) // setup stack and call, store address to CR (1C). - kAsmOpcodeDecl("ret", 0b0111011, 0b110, - kAsmImmediate) // return from procedure (2C). - kAsmOpcodeDecl("uc", 0b0111111, 0b000, kAsmSyscall) // user call (1C) - kAsmOpcodeDecl("kc", 0b0111111, 0b001, kAsmSyscall) // kernel call (1C) - kAsmOpcodeDecl("int", 0b0111111, 0b010, kAsmSyscall) // raise interrupt (1C) -}; - -// \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 - -//////////////////////////////// diff --git a/dev/LibCompiler/AAL/CPU/64x0.h b/dev/LibCompiler/AAL/CPU/64x0.h deleted file mode 100644 index 4944e3b..0000000 --- a/dev/LibCompiler/AAL/CPU/64x0.h +++ /dev/null @@ -1,106 +0,0 @@ -/* ------------------------------------------- - - Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved - -------------------------------------------- */ - -#pragma once - -#include -#include - -// @brief 64x0 support. -// @file CPU/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 CpuOpcode64x0 -{ - const e64k_character_t fName[32]; - e64k_num_t fOpcode; - e64k_num_t fFunct3; - e64k_num_t fFunct7; -}; - -inline std::vector 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("sub", 0b0101011, 0b101, kAsmImmediate) - // add/sub with carry flag - kAsmOpcodeDecl("addc", 0b0101011, 0b110, kAsmImmediate) - kAsmOpcodeDecl("subc", 0b0101011, 0b111, kAsmImmediate) - kAsmOpcodeDecl("sc", 0b1110011, 0b00, kAsmSyscall)}; - -// \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 - -//////////////////////////////// diff --git a/dev/LibCompiler/AAL/CPU/amd64.h b/dev/LibCompiler/AAL/CPU/amd64.h deleted file mode 100644 index 0717dc1..0000000 --- a/dev/LibCompiler/AAL/CPU/amd64.h +++ /dev/null @@ -1,58 +0,0 @@ -/* ------------------------------------------- - - Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved - -------------------------------------------- */ - -#pragma once - -#include - -// @brief AMD64 support. -// @file CPU/amd64.hpp - -#define kAsmOpcodeDecl(__NAME, __OPCODE) {.fName = __NAME, .fOpcode = __OPCODE}, - -typedef char i64_character_t; -typedef uint8_t i64_byte_t; -typedef uint16_t i64_hword_t; -typedef uint32_t i64_word_t; - -#define kAsmRegisterPrefix "r" - -struct CpuOpcodeAMD64 -{ - std::string fName; - i64_byte_t fPrefixBytes[4]; - i64_hword_t fOpcode; - i64_hword_t fModReg; - i64_word_t fDisplacment; - i64_word_t fImmediate; -}; - -/// these two are edge cases -#define kAsmIntOpcode 0xCC -#define kasmIntOpcodeAlt 0xCD - -#define kAsmJumpOpcode 0x0F80 -#define kJumpLimit 30 -#define kJumpLimitStandard 0xE3 -#define kJumpLimitStandardLimit 0xEB - -inline std::vector kOpcodesAMD64 = { - kAsmOpcodeDecl("int", 0xCD) - kAsmOpcodeDecl("into", 0xCE) - kAsmOpcodeDecl("intd", 0xF1) - kAsmOpcodeDecl("int3", 0xC3) - kAsmOpcodeDecl("iret", 0xCF) - kAsmOpcodeDecl("retf", 0xCB) - kAsmOpcodeDecl("retn", 0xC3) - kAsmOpcodeDecl("ret", 0xC3) - kAsmOpcodeDecl("sti", 0xfb) - kAsmOpcodeDecl("cli", 0xfa) - kAsmOpcodeDecl("hlt", 0xf4) - kAsmOpcodeDecl("nop", 0x90) - kAsmOpcodeDecl("mov", 0x48) - kAsmOpcodeDecl("call", 0xFF)}; - -#define kAsmRegisterLimit 16 diff --git a/dev/LibCompiler/AAL/CPU/arm64.h b/dev/LibCompiler/AAL/CPU/arm64.h deleted file mode 100644 index 02a2bf2..0000000 --- a/dev/LibCompiler/AAL/CPU/arm64.h +++ /dev/null @@ -1,44 +0,0 @@ -/* ------------------------------------------- - -Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved - -------------------------------------------- */ - -#pragma once - -#include -#include - -/// @brief ARM64 encoding support. -/// @file CPU/arm64.hpp - -struct CpuOpcodeArm64; - -/// @brief ARM64 opcode header. -struct PACKED CpuOpcodeArm64_Data final -{ - uint32_t fOpcode : 10; // Bits 31–22: Opcode for operation - uint32_t fRm : 5; // Bits 21–16: Source register Rm - uint32_t fShamt : 6; // Bits 15–10: Shift amount - uint32_t fRn : 5; // Bits 9–5: Source register Rn - uint32_t fRd : 5; // Bits 4–0: Destination register Rd -}; - -typedef struct -{ - uint32_t opcode : 6; // Bits 31–26: Branch opcode - int32_t offset : 26; // Bits 25–0: Signed offset (branch target) -} PACKED CpuOpcodeArm64_Branch; - -typedef struct -{ - uint32_t size : 2; // Bits 31–30: Size of the data - uint32_t opcode : 7; // Bits 29–23: Opcode for load/store - uint32_t offset : 12; // Bits 22–10: Offset - uint32_t rn : 5; // Bits 9–5: Base address register Rn - uint32_t rt : 5; // Bits 4–0: Target/source register Rt -} PACKED CpuOpcodeArm64_LoadStore; - -#define kAsmRegisterLimit (30) -#define kAsmRegisterPrefix "x" -#define kOpcodeARM64Count (1000) diff --git a/dev/LibCompiler/AAL/CPU/power64.h b/dev/LibCompiler/AAL/CPU/power64.h deleted file mode 100644 index 0f797a5..0000000 --- a/dev/LibCompiler/AAL/CPU/power64.h +++ /dev/null @@ -1,1929 +0,0 @@ -/* ------------------------------------------- - - Some modifications are copyrighted under: - Amlal El Mahrouss - - Original author: - Apple Inc - -------------------------------------------- */ - -#pragma once - -#include - -/// @note Based of: -/// https://opensource.apple.com/source/cctools/cctools-750/as/ppc-opcode.h.auto.html - -#define kOpcodePPCCount (1073U) - -/* - * These defines are use in the cpus field of the instructions. If the field - * is zero it can execute on all cpus. The defines are or'ed together. This - * information is used to set the cpusubtype in the resulting object file. - */ -#define CPU601 0x1 -#define IMPL64 0x2 -#define OPTIONAL 0x4 -#define VMX 0x8 -#define CPU970 0x10 /* added to OPTIONAL insts that the 970 has */ -#define CPUMAHROUSS 0x12 /* optional mahrouss insts. */ - -enum OpcodeType -{ - NONE, /* no operand */ - JBSR, /* jbsr pseudo op */ - PCREL, /* PC relative (branch offset) */ - BADDR, /* Branch address (sign extended absolute address) */ - D, /* 16 bit displacement */ - DS, /* 14 bit displacement (double word) */ - SI, /* signed 16 bit immediate */ - UI, /* unsigned 16 bit immediate */ - HI, /* high 16 bit immediate (with truncation) */ - GREG, /* general register */ - G0REG, /* general register r1-r31 or 0 */ - FREG, /* float register */ - VREG, /* vector register */ - SGREG, /* segment register */ - SPREG, /* special register (or 10 bit number, 5 bit halves reversed) */ - BCND, /* branch condition opcode */ - CRF, /* condition register field */ - CRFONLY, /* condition register field only no expression allowed */ - sh, /* 6 bit number (0 - 63) (sh field, split and reversed) */ - mb, /* 6 bit number (0 - 63) (mb field, mb5 || mb0:4 reversed) */ - NUM, /* number */ - SNUM, /* signed number */ - NUM0, /* number (where 1< + +#define kAEMag0 'A' +#define kAEMag1 'E' + +#define kAESymbolLen (255) +#define kAEPad (8) +#define kAEMagLen (2) +#define kAENullType (0x00) + +// Advanced Executable File Format for ld64. +// Reloctable by offset is the default strategy. +// You can also relocate at runtime but that's up to the operating system loader. + +namespace LibCompiler +{ + // @brief Advanced Executable Header + // One thing to keep in mind. + // This object format, is reloctable. + typedef struct AEHeader final + { + CharType fMagic[kAEMagLen]; + CharType fArch; + CharType fSubArch; + SizeType fCount; + CharType fSize; + SizeType fStartCode; + SizeType fCodeSize; + CharType fPad[kAEPad]; + } 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]; + } PACKED AERecordHeader, *AERecordHeaderPtr; + + enum + { + kKindRelocationByOffset = 0x23f, + kKindRelocationAtRuntime = 0x34f, + }; +} // namespace LibCompiler + +// provide operator<< for AE + +inline std::ofstream& operator<<(std::ofstream& fp, LibCompiler::AEHeader& container) +{ + fp.write((char*)&container, sizeof(LibCompiler::AEHeader)); + + return fp; +} + +inline std::ofstream& operator<<(std::ofstream& fp, + LibCompiler::AERecordHeader& container) +{ + fp.write((char*)&container, sizeof(LibCompiler::AERecordHeader)); + + return fp; +} + +inline std::ifstream& operator>>(std::ifstream& fp, LibCompiler::AEHeader& container) +{ + fp.read((char*)&container, sizeof(LibCompiler::AEHeader)); + return fp; +} + +inline std::ifstream& operator>>(std::ifstream& fp, + LibCompiler::AERecordHeader& container) +{ + fp.read((char*)&container, sizeof(LibCompiler::AERecordHeader)); + return fp; +} + +namespace LibCompiler::Utils +{ + /** + * @brief AE Reader protocol + * + */ + class AEReadableProtocol final + { + public: + std::ifstream FP; + + public: + explicit AEReadableProtocol() = default; + ~AEReadableProtocol() = default; + + LIBCOMPILER_COPY_DELETE(AEReadableProtocol); + + /** + * @brief Read AE Record headers. + * + * @param raw the containing buffer + * @param sz it's size (1 = one AERecordHeader, 2 two AERecordHeader(s)) + * @return AERecordHeaderPtr + */ + AERecordHeaderPtr Read(char* raw, std::size_t sz) + { + if (!raw) + return nullptr; + + return this->_Read(raw, sz * sizeof(AERecordHeader)); + } + + private: + /** + * @brief Implementation of Read for raw classes. + * + * @tparam TypeClass The class to read. + * @param raw the buffer + * @param sz the size + * @return TypeClass* the returning class. + */ + template + TypeClass* _Read(char* raw, std::size_t sz) + { + FP.read(raw, std::streamsize(sz)); + return reinterpret_cast(raw); + } + }; +} // namespace LibCompiler::Utils diff --git a/dev/LibCompiler/AssemblyInterface.h b/dev/LibCompiler/AssemblyInterface.h new file mode 100644 index 0000000..622e2ff --- /dev/null +++ b/dev/LibCompiler/AssemblyInterface.h @@ -0,0 +1,242 @@ +/* ------------------------------------------- + + Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +#define ASSEMBLY_INTERFACE : public LibCompiler::AssemblyInterface + +namespace LibCompiler +{ + /// @brief Assembly to binary generator class. + /// @note This interface creates according to the CPU target of the child class. + class AssemblyInterface + { + public: + explicit AssemblyInterface() = default; + virtual ~AssemblyInterface() = default; + + LIBCOMPILER_COPY_DEFAULT(AssemblyInterface); + + /// @brief compile to object file. + /// @note Example C++ -> MASM -> AE object. + virtual Int32 CompileToFormat(std::string& src, Int32 arch) = 0; + }; + + /// @brief Simple assembly factory + class AssemblyFactory final + { + public: + explicit AssemblyFactory() = default; + ~AssemblyFactory() = default; + + LIBCOMPILER_COPY_DEFAULT(AssemblyFactory); + + public: + enum + { + kArchAMD64, + kArch32x0, + kArch64x0, + kArchRISCV, + kArchPowerPC, + kArchAARCH64, + kArchUnknown, + }; + + Int32 Compile(std::string& sourceFile, const Int32& arch) noexcept; + + void Mount(AssemblyInterface* mountPtr) noexcept; + AssemblyInterface* Unmount() noexcept; + + private: + AssemblyInterface* fMounted{nullptr}; + }; + + union NumberCastBase { + NumberCastBase() = default; + ~NumberCastBase() = default; + }; + + union NumberCast64 final { + NumberCast64() = default; + explicit NumberCast64(UInt64 raw) + : raw(raw) + { + } + + ~NumberCast64() + { + raw = 0; + } + + CharType number[8]; + UInt64 raw; + }; + + union NumberCast32 final { + NumberCast32() = default; + explicit NumberCast32(UInt32 raw) + : raw(raw) + { + } + + ~NumberCast32() + { + raw = 0; + } + + CharType number[4]; + UInt32 raw; + }; + + union NumberCast16 final { + NumberCast16() = default; + explicit NumberCast16(UInt16 raw) + : raw(raw) + { + } + + ~NumberCast16() + { + raw = 0; + } + + CharType number[2]; + UInt16 raw; + }; + + union NumberCast8 final { + NumberCast8() = default; + explicit NumberCast8(UInt8 raw) + : raw(raw) + { + } + + ~NumberCast8() + { + raw = 0; + } + + CharType number; + UInt8 raw; + }; + + class EncoderInterface + { + public: + explicit EncoderInterface() = default; + virtual ~EncoderInterface() = default; + + LIBCOMPILER_COPY_DEFAULT(EncoderInterface); + + 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_AMD64__ + + class EncoderAMD64 final : public EncoderInterface + { + public: + explicit EncoderAMD64() = default; + ~EncoderAMD64() override = default; + + LIBCOMPILER_COPY_DEFAULT(EncoderAMD64); + + 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; + + virtual bool WriteNumber16(const std::size_t& pos, std::string& from_what); + virtual bool WriteNumber32(const std::size_t& pos, std::string& from_what); + virtual bool WriteNumber8(const std::size_t& pos, std::string& from_what); + }; + +#endif // __ASM_NEED_AMD64__ + +#ifdef __ASM_NEED_ARM64__ + + class EncoderARM64 final : public EncoderInterface + { + public: + explicit EncoderARM64() = default; + ~EncoderARM64() override = default; + + LIBCOMPILER_COPY_DEFAULT(EncoderARM64); + + 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_ARM64__ + +#ifdef __ASM_NEED_64x0__ + + class Encoder64x0 final : public EncoderInterface + { + public: + explicit Encoder64x0() = default; + ~Encoder64x0() override = default; + + LIBCOMPILER_COPY_DEFAULT(Encoder64x0); + + 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 Encoder32x0 final : public EncoderInterface + { + public: + explicit Encoder32x0() = default; + ~Encoder32x0() override = default; + + LIBCOMPILER_COPY_DEFAULT(Encoder32x0); + + 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__ + +#ifdef __ASM_NEED_PPC__ + + class EncoderPowerPC final : public EncoderInterface + { + public: + explicit EncoderPowerPC() = default; + ~EncoderPowerPC() override = default; + + LIBCOMPILER_COPY_DEFAULT(EncoderPowerPC); + + 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__ +} // namespace LibCompiler diff --git a/dev/LibCompiler/Backend/32x0.h b/dev/LibCompiler/Backend/32x0.h new file mode 100644 index 0000000..32f31ff --- /dev/null +++ b/dev/LibCompiler/Backend/32x0.h @@ -0,0 +1,97 @@ +/* ------------------------------------------- + + Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + +------------------------------------------- */ + +#pragma once + +#include + +// @brief 32x0 support. +// @file Backend/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[32]; + uint8_t fOpcode; + uint8_t fSize; + uint8_t fFunct3; + uint8_t fFunct7; +}; + +#define kAsmDWordStr ".dword" /* 64 bit */ +#define kAsmWordStr ".word" /* 32-bit */ +#define kAsmHWordStr ".half" /* 16-bit */ +#define kAsmByteStr ".byte" /* 8-bit */ + +inline std::vector kOpcodes32x0 = { + kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. (1C) + kAsmOpcodeDecl("jmp", 0b1110011, 0b001, kAsmJump) // jump to branch (2C) + kAsmOpcodeDecl("mov", 0b0100011, 0b101, kAsmImmediate) // move registers (3C) + kAsmOpcodeDecl("psh", 0b0111011, 0b000, kAsmImmediate) // push to sp (2C) + kAsmOpcodeDecl("pop", 0b0111011, 0b001, kAsmImmediate) // pop from sp. (1C) + kAsmOpcodeDecl("lea", 0b0111011, 0b010, + kAsmImmediate) // setup stack and call, store address to CR (1C). + kAsmOpcodeDecl("ret", 0b0111011, 0b110, + kAsmImmediate) // return from procedure (2C). + kAsmOpcodeDecl("uc", 0b0111111, 0b000, kAsmSyscall) // user call (1C) + kAsmOpcodeDecl("kc", 0b0111111, 0b001, kAsmSyscall) // kernel call (1C) + kAsmOpcodeDecl("int", 0b0111111, 0b010, kAsmSyscall) // raise interrupt (1C) +}; + +// \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 + +//////////////////////////////// diff --git a/dev/LibCompiler/Backend/64x0.h b/dev/LibCompiler/Backend/64x0.h new file mode 100644 index 0000000..a0084b1 --- /dev/null +++ b/dev/LibCompiler/Backend/64x0.h @@ -0,0 +1,106 @@ +/* ------------------------------------------- + + Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + +------------------------------------------- */ + +#pragma once + +#include +#include + +// @brief 64x0 support. +// @file Backend/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 CpuOpcode64x0 +{ + const e64k_character_t fName[32]; + e64k_num_t fOpcode; + e64k_num_t fFunct3; + e64k_num_t fFunct7; +}; + +inline std::vector 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("sub", 0b0101011, 0b101, kAsmImmediate) + // add/sub with carry flag + kAsmOpcodeDecl("addc", 0b0101011, 0b110, kAsmImmediate) + kAsmOpcodeDecl("subc", 0b0101011, 0b111, kAsmImmediate) + kAsmOpcodeDecl("sc", 0b1110011, 0b00, kAsmSyscall)}; + +// \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 + +//////////////////////////////// diff --git a/dev/LibCompiler/Backend/amd64.h b/dev/LibCompiler/Backend/amd64.h new file mode 100644 index 0000000..8486b01 --- /dev/null +++ b/dev/LibCompiler/Backend/amd64.h @@ -0,0 +1,58 @@ +/* ------------------------------------------- + + Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + +------------------------------------------- */ + +#pragma once + +#include + +// @brief AMD64 support. +// @file Backend/amd64.hpp + +#define kAsmOpcodeDecl(__NAME, __OPCODE) {.fName = __NAME, .fOpcode = __OPCODE}, + +typedef char i64_character_t; +typedef uint8_t i64_byte_t; +typedef uint16_t i64_hword_t; +typedef uint32_t i64_word_t; + +#define kAsmRegisterPrefix "r" + +struct CpuOpcodeAMD64 +{ + std::string fName; + i64_byte_t fPrefixBytes[4]; + i64_hword_t fOpcode; + i64_hword_t fModReg; + i64_word_t fDisplacment; + i64_word_t fImmediate; +}; + +/// these two are edge cases +#define kAsmIntOpcode 0xCC +#define kasmIntOpcodeAlt 0xCD + +#define kAsmJumpOpcode 0x0F80 +#define kJumpLimit 30 +#define kJumpLimitStandard 0xE3 +#define kJumpLimitStandardLimit 0xEB + +inline std::vector kOpcodesAMD64 = { + kAsmOpcodeDecl("int", 0xCD) + kAsmOpcodeDecl("into", 0xCE) + kAsmOpcodeDecl("intd", 0xF1) + kAsmOpcodeDecl("int3", 0xC3) + kAsmOpcodeDecl("iret", 0xCF) + kAsmOpcodeDecl("retf", 0xCB) + kAsmOpcodeDecl("retn", 0xC3) + kAsmOpcodeDecl("ret", 0xC3) + kAsmOpcodeDecl("sti", 0xfb) + kAsmOpcodeDecl("cli", 0xfa) + kAsmOpcodeDecl("hlt", 0xf4) + kAsmOpcodeDecl("nop", 0x90) + kAsmOpcodeDecl("mov", 0x48) + kAsmOpcodeDecl("call", 0xFF)}; + +#define kAsmRegisterLimit 16 diff --git a/dev/LibCompiler/Backend/arm64.h b/dev/LibCompiler/Backend/arm64.h new file mode 100644 index 0000000..08096ee --- /dev/null +++ b/dev/LibCompiler/Backend/arm64.h @@ -0,0 +1,44 @@ +/* ------------------------------------------- + +Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + +------------------------------------------- */ + +#pragma once + +#include +#include + +/// @brief ARM64 encoding support. +/// @file Backend/arm64.hpp + +struct CpuOpcodeArm64; + +/// @brief ARM64 opcode header. +struct PACKED CpuOpcodeArm64_Data final +{ + uint32_t fOpcode : 10; // Bits 31–22: Opcode for operation + uint32_t fRm : 5; // Bits 21–16: Source register Rm + uint32_t fShamt : 6; // Bits 15–10: Shift amount + uint32_t fRn : 5; // Bits 9–5: Source register Rn + uint32_t fRd : 5; // Bits 4–0: Destination register Rd +}; + +typedef struct +{ + uint32_t opcode : 6; // Bits 31–26: Branch opcode + int32_t offset : 26; // Bits 25–0: Signed offset (branch target) +} PACKED CpuOpcodeArm64_Branch; + +typedef struct +{ + uint32_t size : 2; // Bits 31–30: Size of the data + uint32_t opcode : 7; // Bits 29–23: Opcode for load/store + uint32_t offset : 12; // Bits 22–10: Offset + uint32_t rn : 5; // Bits 9–5: Base address register Rn + uint32_t rt : 5; // Bits 4–0: Target/source register Rt +} PACKED CpuOpcodeArm64_LoadStore; + +#define kAsmRegisterLimit (30) +#define kAsmRegisterPrefix "x" +#define kOpcodeARM64Count (1000) diff --git a/dev/LibCompiler/Backend/power64.h b/dev/LibCompiler/Backend/power64.h new file mode 100644 index 0000000..0f797a5 --- /dev/null +++ b/dev/LibCompiler/Backend/power64.h @@ -0,0 +1,1929 @@ +/* ------------------------------------------- + + Some modifications are copyrighted under: + Amlal El Mahrouss + + Original author: + Apple Inc + +------------------------------------------- */ + +#pragma once + +#include + +/// @note Based of: +/// https://opensource.apple.com/source/cctools/cctools-750/as/ppc-opcode.h.auto.html + +#define kOpcodePPCCount (1073U) + +/* + * These defines are use in the cpus field of the instructions. If the field + * is zero it can execute on all cpus. The defines are or'ed together. This + * information is used to set the cpusubtype in the resulting object file. + */ +#define CPU601 0x1 +#define IMPL64 0x2 +#define OPTIONAL 0x4 +#define VMX 0x8 +#define CPU970 0x10 /* added to OPTIONAL insts that the 970 has */ +#define CPUMAHROUSS 0x12 /* optional mahrouss insts. */ + +enum OpcodeType +{ + NONE, /* no operand */ + JBSR, /* jbsr pseudo op */ + PCREL, /* PC relative (branch offset) */ + BADDR, /* Branch address (sign extended absolute address) */ + D, /* 16 bit displacement */ + DS, /* 14 bit displacement (double word) */ + SI, /* signed 16 bit immediate */ + UI, /* unsigned 16 bit immediate */ + HI, /* high 16 bit immediate (with truncation) */ + GREG, /* general register */ + G0REG, /* general register r1-r31 or 0 */ + FREG, /* float register */ + VREG, /* vector register */ + SGREG, /* segment register */ + SPREG, /* special register (or 10 bit number, 5 bit halves reversed) */ + BCND, /* branch condition opcode */ + CRF, /* condition register field */ + CRFONLY, /* condition register field only no expression allowed */ + sh, /* 6 bit number (0 - 63) (sh field, split and reversed) */ + mb, /* 6 bit number (0 - 63) (mb field, mb5 || mb0:4 reversed) */ + NUM, /* number */ + SNUM, /* signed number */ + NUM0, /* number (where 1< +#include + +#define LIBCOMPILER_SUCCESSS 0 +#define LIBCOMPILER_EXEC_ERROR -30 +#define LIBCOMPILER_FILE_NOT_FOUND -31 +#define LIBCOMPILER_DIR_NOT_FOUND -32 +#define LIBCOMPILER_FILE_EXISTS -33 +#define LIBCOMPILER_TOO_LONG -34 +#define LIBCOMPILER_INVALID_DATA -35 +#define LIBCOMPILER_UNIMPLEMENTED -36 +#define LIBCOMPILER_FAT_ERROR -37 diff --git a/dev/LibCompiler/ErrorOr.h b/dev/LibCompiler/ErrorOr.h new file mode 100644 index 0000000..2a6d590 --- /dev/null +++ b/dev/LibCompiler/ErrorOr.h @@ -0,0 +1,61 @@ +/* + * ======================================================== + * + * LibCompiler + * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +namespace LibCompiler +{ + using ErrorT = UInt32; + + template + 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 Leak() + { + return mRef; + } + + operator bool() + { + return mRef; + } + + private: + Ref mRef; + Int32 mId{0}; + }; + + using ErrorOrAny = ErrorOr; + +} // namespace LibCompiler diff --git a/dev/LibCompiler/NFC/AE.h b/dev/LibCompiler/NFC/AE.h deleted file mode 100644 index fdf42a5..0000000 --- a/dev/LibCompiler/NFC/AE.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * ======================================================== - * - * LibCompiler - * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include - -#define kAEMag0 'A' -#define kAEMag1 'E' - -#define kAESymbolLen (255) -#define kAEPad (8) -#define kAEMagLen (2) -#define kAENullType (0x00) - -// Advanced Executable File Format for ld64. -// Reloctable by offset is the default strategy. -// You can also relocate at runtime but that's up to the operating system loader. - -namespace LibCompiler -{ - // @brief Advanced Executable Header - // One thing to keep in mind. - // This object format, is reloctable. - typedef struct AEHeader final - { - CharType fMagic[kAEMagLen]; - CharType fArch; - CharType fSubArch; - SizeType fCount; - CharType fSize; - SizeType fStartCode; - SizeType fCodeSize; - CharType fPad[kAEPad]; - } 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]; - } PACKED AERecordHeader, *AERecordHeaderPtr; - - enum - { - kKindRelocationByOffset = 0x23f, - kKindRelocationAtRuntime = 0x34f, - }; -} // namespace LibCompiler - -// provide operator<< for AE - -inline std::ofstream& operator<<(std::ofstream& fp, LibCompiler::AEHeader& container) -{ - fp.write((char*)&container, sizeof(LibCompiler::AEHeader)); - - return fp; -} - -inline std::ofstream& operator<<(std::ofstream& fp, - LibCompiler::AERecordHeader& container) -{ - fp.write((char*)&container, sizeof(LibCompiler::AERecordHeader)); - - return fp; -} - -inline std::ifstream& operator>>(std::ifstream& fp, LibCompiler::AEHeader& container) -{ - fp.read((char*)&container, sizeof(LibCompiler::AEHeader)); - return fp; -} - -inline std::ifstream& operator>>(std::ifstream& fp, - LibCompiler::AERecordHeader& container) -{ - fp.read((char*)&container, sizeof(LibCompiler::AERecordHeader)); - return fp; -} - -namespace LibCompiler::Utils -{ - /** - * @brief AE Reader protocol - * - */ - class AEReadableProtocol final - { - public: - std::ifstream FP; - - public: - explicit AEReadableProtocol() = default; - ~AEReadableProtocol() = default; - - LIBCOMPILER_COPY_DELETE(AEReadableProtocol); - - /** - * @brief Read AE Record headers. - * - * @param raw the containing buffer - * @param sz it's size (1 = one AERecordHeader, 2 two AERecordHeader(s)) - * @return AERecordHeaderPtr - */ - AERecordHeaderPtr Read(char* raw, std::size_t sz) - { - if (!raw) - return nullptr; - - return this->_Read(raw, sz * sizeof(AERecordHeader)); - } - - private: - /** - * @brief Implementation of Read for raw classes. - * - * @tparam TypeClass The class to read. - * @param raw the buffer - * @param sz the size - * @return TypeClass* the returning class. - */ - template - TypeClass* _Read(char* raw, std::size_t sz) - { - FP.read(raw, std::streamsize(sz)); - return reinterpret_cast(raw); - } - }; -} // namespace LibCompiler::Utils diff --git a/dev/LibCompiler/NFC/ErrorID.h b/dev/LibCompiler/NFC/ErrorID.h deleted file mode 100644 index e7f06e1..0000000 --- a/dev/LibCompiler/NFC/ErrorID.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * ======================================================== - * - * LibCompiler - * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -#define LIBCOMPILER_SUCCESSS 0 -#define LIBCOMPILER_EXEC_ERROR -30 -#define LIBCOMPILER_FILE_NOT_FOUND -31 -#define LIBCOMPILER_DIR_NOT_FOUND -32 -#define LIBCOMPILER_FILE_EXISTS -33 -#define LIBCOMPILER_TOO_LONG -34 -#define LIBCOMPILER_INVALID_DATA -35 -#define LIBCOMPILER_UNIMPLEMENTED -36 -#define LIBCOMPILER_FAT_ERROR -37 diff --git a/dev/LibCompiler/NFC/ErrorOr.h b/dev/LibCompiler/NFC/ErrorOr.h deleted file mode 100644 index 9dc607e..0000000 --- a/dev/LibCompiler/NFC/ErrorOr.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * ======================================================== - * - * LibCompiler - * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -namespace LibCompiler -{ - using ErrorT = UInt32; - - template - 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 Leak() - { - return mRef; - } - - operator bool() - { - return mRef; - } - - private: - Ref mRef; - Int32 mId{0}; - }; - - using ErrorOrAny = ErrorOr; - -} // namespace LibCompiler diff --git a/dev/LibCompiler/NFC/PEF.h b/dev/LibCompiler/NFC/PEF.h deleted file mode 100644 index 1148dea..0000000 --- a/dev/LibCompiler/NFC/PEF.h +++ /dev/null @@ -1,144 +0,0 @@ -/* ------------------------------------------- - - Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved - -------------------------------------------- */ - -#pragma once - -#include - -// @file PEF.hpp -// @brief Preferred Executable Format - -#define kPefMagic "Joy!" -#define kPefMagicFat "yoJ!" - -#define kPefExt ".exec" -#define kPefDylibExt ".dylib" -#define kPefLibExt ".lib" -#define kPefObjectExt ".obj" -#define kPefDebugExt ".dbg" -#define kPefDriverExt ".sys" - -#define kPefZero128 ".zero128" -#define kPefCode128 ".code128" -#define kPefData128 ".data128" - -#define kPefZero64 ".zero64" -#define kPefCode64 ".code64" -#define kPefData64 ".data64" - -#define kPefMagicLen (5) - -#define kPefVersion (3) -#define kPefNameLen (255) - -#define kPefBaseOrigin (0x40000000) - -#define kPefStart "__ImageStart" - -namespace LibCompiler -{ - enum - { - kPefArchStart = 99, - kPefArchIntel86S = 100, - kPefArchAMD64, - kPefArchRISCV, - kPefArch64000, /* 64x0 RISC architecture. */ - kPefArch32000, - kPefArchPowerPC, /* 64-bit POWER architecture. */ - kPefArchARM64, - kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1, - kPefArchInvalid = 0xFF, - }; - - enum - { - kPefSubArchAMD, - kPefSubArchIntel, - kPefSubArchARM, - kPefSubArchGeneric, - kPefSubArchIBM, - }; - - enum - { - kPefKindExec = 1, /* .o */ - kPefKindDylib = 2, /* .dylib */ - kPefKindObject = 4, /* .obj */ - kPefKindDebug = 5, /* .dbg */ - kPefKindDriver = 6, - kPefKindCount, - }; - - /* 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 */ - } PACKED PEFContainer, *PEFContainerPtr; - - /* 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 Cpu; /* container cpu */ - UInt32 SubCpu; /* container sub-cpu */ - UInt32 Flags; /* container flags */ - UInt16 Kind; /* container kind */ - UIntPtr Offset; /* file offset */ - SizeType Size; /* file size */ - } PACKED PEFCommandHeader, *PEFCommandHeaderPtr; - - enum - { - kPefCode = 0xC, - kPefData = 0xD, - kPefZero = 0xE, - kPefLinkerID = 0x1, - kPefCount = 4, - kPefInvalid = 0xFF, - }; -} // namespace LibCompiler - -inline std::ofstream& operator<<(std::ofstream& fp, - LibCompiler::PEFContainer& container) -{ - fp.write((char*)&container, sizeof(LibCompiler::PEFContainer)); - return fp; -} - -inline std::ofstream& operator<<(std::ofstream& fp, - LibCompiler::PEFCommandHeader& container) -{ - fp.write((char*)&container, sizeof(LibCompiler::PEFCommandHeader)); - return fp; -} - -inline std::ifstream& operator>>(std::ifstream& fp, - LibCompiler::PEFContainer& container) -{ - fp.read((char*)&container, sizeof(LibCompiler::PEFContainer)); - return fp; -} - -inline std::ifstream& operator>>(std::ifstream& fp, - LibCompiler::PEFCommandHeader& container) -{ - fp.read((char*)&container, sizeof(LibCompiler::PEFCommandHeader)); - return fp; -} diff --git a/dev/LibCompiler/NFC/Ref.h b/dev/LibCompiler/NFC/Ref.h deleted file mode 100644 index 117083c..0000000 --- a/dev/LibCompiler/NFC/Ref.h +++ /dev/null @@ -1,103 +0,0 @@ - -/* - * ======================================================== - * - * LibCompiler - * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include - -namespace LibCompiler -{ - // @author EL Mahrouss Amlal - // @brief Reference holder class, refers to a pointer of data in static memory. - template - class Ref final - { - public: - explicit Ref() = default; - - ~Ref() - { - if (m_Strong) - { - (*m_Class).~T(); - } - } - - LIBCOMPILER_COPY_DEFAULT(Ref); - - 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{nullptr}; - Bool m_Strong{false}; - }; - - // @author EL Mahrouss Amlal - // @brief Non null Reference holder class, refers to a pointer of data in static memory. - template - class NonNullRef final - { - public: - explicit NonNullRef() = delete; - - explicit NonNullRef(T* ref) - : m_Ref(ref, true) - { - } - - Ref& operator->() - { - MUST_PASS(m_Ref); - return m_Ref; - } - - NonNullRef& operator=(const NonNullRef& ref) = delete; - NonNullRef(const NonNullRef& ref) = default; - - private: - Ref m_Ref{nullptr}; - }; -} // namespace LibCompiler diff --git a/dev/LibCompiler/NFC/StringView.h b/dev/LibCompiler/NFC/StringView.h deleted file mode 100644 index 16578e0..0000000 --- a/dev/LibCompiler/NFC/StringView.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * ======================================================== - * - * LibCompiler - * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -namespace LibCompiler -{ - /** - * @brief StringView class, contains a C string and manages it. - * @note No need to manage it it's getting deleted by default. - */ - - class StringView final - { - public: - explicit StringView() = delete; - - explicit StringView(SizeType Sz) noexcept - : m_Sz(Sz) - { - m_Data = new CharType[Sz]; - assert(m_Data); - } - - ~StringView() noexcept - { - if (m_Data) - { - memset(m_Data, 0, m_Sz); - delete[] m_Data; - - m_Data = nullptr; - } - } - - LIBCOMPILER_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 && m_Data[0] != 0; - } - - bool operator!() - { - return !m_Data || m_Data[0] == 0; - } - - private: - CharType* m_Data{nullptr}; - SizeType m_Sz{0}; - SizeType m_Cur{0}; - - friend class StringBuilder; - }; - - /** - * @brief StringBuilder class - * @note These results shall call delete[] after they're used. - */ - 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 LibCompiler diff --git a/dev/LibCompiler/NFC/XCOFF.h b/dev/LibCompiler/NFC/XCOFF.h deleted file mode 100644 index 862c363..0000000 --- a/dev/LibCompiler/NFC/XCOFF.h +++ /dev/null @@ -1,41 +0,0 @@ -/* ------------------------------------------- - - Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved - - File: XCOFF.hpp - Purpose: XCOFF for NeKernel. - - Revision History: - - 04/07/24: Added file (amlel) - -------------------------------------------- */ - -#ifndef __XCOFF__ -#define __XCOFF__ - -#include - -#define kXCOFF64Magic 0x01F7 - -#define kXCOFFRelFlg 0x0001 -#define kXCOFFExecutable 0x0002 -#define kXCOFFLnno 0x0004 -#define kXCOFFLSyms 0x0008 - -namespace LibCompiler -{ - /// @brief XCoff identification header. - typedef struct XCoffFileHeader - { - UInt16 fMagic; - UInt16 fTarget; - UInt16 fNumSecs; - UInt32 fTimeDat; - UIntPtr fSymPtr; - UInt32 fNumSyms; - UInt16 fOptHdr; // ?: Number of bytes in optional header - } XCoffFileHeader; -} // namespace LibCompiler - -#endif // ifndef __XCOFF__ diff --git a/dev/LibCompiler/PEF.h b/dev/LibCompiler/PEF.h new file mode 100644 index 0000000..1148dea --- /dev/null +++ b/dev/LibCompiler/PEF.h @@ -0,0 +1,144 @@ +/* ------------------------------------------- + + Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + +------------------------------------------- */ + +#pragma once + +#include + +// @file PEF.hpp +// @brief Preferred Executable Format + +#define kPefMagic "Joy!" +#define kPefMagicFat "yoJ!" + +#define kPefExt ".exec" +#define kPefDylibExt ".dylib" +#define kPefLibExt ".lib" +#define kPefObjectExt ".obj" +#define kPefDebugExt ".dbg" +#define kPefDriverExt ".sys" + +#define kPefZero128 ".zero128" +#define kPefCode128 ".code128" +#define kPefData128 ".data128" + +#define kPefZero64 ".zero64" +#define kPefCode64 ".code64" +#define kPefData64 ".data64" + +#define kPefMagicLen (5) + +#define kPefVersion (3) +#define kPefNameLen (255) + +#define kPefBaseOrigin (0x40000000) + +#define kPefStart "__ImageStart" + +namespace LibCompiler +{ + enum + { + kPefArchStart = 99, + kPefArchIntel86S = 100, + kPefArchAMD64, + kPefArchRISCV, + kPefArch64000, /* 64x0 RISC architecture. */ + kPefArch32000, + kPefArchPowerPC, /* 64-bit POWER architecture. */ + kPefArchARM64, + kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1, + kPefArchInvalid = 0xFF, + }; + + enum + { + kPefSubArchAMD, + kPefSubArchIntel, + kPefSubArchARM, + kPefSubArchGeneric, + kPefSubArchIBM, + }; + + enum + { + kPefKindExec = 1, /* .o */ + kPefKindDylib = 2, /* .dylib */ + kPefKindObject = 4, /* .obj */ + kPefKindDebug = 5, /* .dbg */ + kPefKindDriver = 6, + kPefKindCount, + }; + + /* 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 */ + } PACKED PEFContainer, *PEFContainerPtr; + + /* 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 Cpu; /* container cpu */ + UInt32 SubCpu; /* container sub-cpu */ + UInt32 Flags; /* container flags */ + UInt16 Kind; /* container kind */ + UIntPtr Offset; /* file offset */ + SizeType Size; /* file size */ + } PACKED PEFCommandHeader, *PEFCommandHeaderPtr; + + enum + { + kPefCode = 0xC, + kPefData = 0xD, + kPefZero = 0xE, + kPefLinkerID = 0x1, + kPefCount = 4, + kPefInvalid = 0xFF, + }; +} // namespace LibCompiler + +inline std::ofstream& operator<<(std::ofstream& fp, + LibCompiler::PEFContainer& container) +{ + fp.write((char*)&container, sizeof(LibCompiler::PEFContainer)); + return fp; +} + +inline std::ofstream& operator<<(std::ofstream& fp, + LibCompiler::PEFCommandHeader& container) +{ + fp.write((char*)&container, sizeof(LibCompiler::PEFCommandHeader)); + return fp; +} + +inline std::ifstream& operator>>(std::ifstream& fp, + LibCompiler::PEFContainer& container) +{ + fp.read((char*)&container, sizeof(LibCompiler::PEFContainer)); + return fp; +} + +inline std::ifstream& operator>>(std::ifstream& fp, + LibCompiler::PEFCommandHeader& container) +{ + fp.read((char*)&container, sizeof(LibCompiler::PEFCommandHeader)); + return fp; +} diff --git a/dev/LibCompiler/Parser.h b/dev/LibCompiler/Parser.h index 74eb204..cb0e470 100644 --- a/dev/LibCompiler/Parser.h +++ b/dev/LibCompiler/Parser.h @@ -6,7 +6,7 @@ #pragma once -#include +#include namespace LibCompiler { diff --git a/dev/LibCompiler/Ref.h b/dev/LibCompiler/Ref.h new file mode 100644 index 0000000..117083c --- /dev/null +++ b/dev/LibCompiler/Ref.h @@ -0,0 +1,103 @@ + +/* + * ======================================================== + * + * LibCompiler + * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include + +namespace LibCompiler +{ + // @author EL Mahrouss Amlal + // @brief Reference holder class, refers to a pointer of data in static memory. + template + class Ref final + { + public: + explicit Ref() = default; + + ~Ref() + { + if (m_Strong) + { + (*m_Class).~T(); + } + } + + LIBCOMPILER_COPY_DEFAULT(Ref); + + 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{nullptr}; + Bool m_Strong{false}; + }; + + // @author EL Mahrouss Amlal + // @brief Non null Reference holder class, refers to a pointer of data in static memory. + template + class NonNullRef final + { + public: + explicit NonNullRef() = delete; + + explicit NonNullRef(T* ref) + : m_Ref(ref, true) + { + } + + Ref& operator->() + { + MUST_PASS(m_Ref); + return m_Ref; + } + + NonNullRef& operator=(const NonNullRef& ref) = delete; + NonNullRef(const NonNullRef& ref) = default; + + private: + Ref m_Ref{nullptr}; + }; +} // namespace LibCompiler diff --git a/dev/LibCompiler/StringView.h b/dev/LibCompiler/StringView.h new file mode 100644 index 0000000..b65121e --- /dev/null +++ b/dev/LibCompiler/StringView.h @@ -0,0 +1,90 @@ +/* + * ======================================================== + * + * LibCompiler + * Copyright (C) 2024-2025 Amlal El Mahrouss, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +namespace LibCompiler +{ + /** + * @brief StringView class, contains a C string and manages it. + * @note No need to manage it it's getting deleted by default. + */ + + class StringView final + { + public: + explicit StringView() = delete; + + explicit StringView(SizeType Sz) noexcept + : m_Sz(Sz) + { + m_Data = new CharType[Sz]; + assert(m_Data); + } + + ~StringView() noexcept + { + if (m_Data) + { + memset(m_Data, 0, m_Sz); + delete[] m_Data; + + m_Data = nullptr; + } + } + + LIBCOMPILER_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 && m_Data[0] != 0; + } + + bool operator!() + { + return !m_Data || m_Data[0] == 0; + } + + private: + CharType* m_Data{nullptr}; + SizeType m_Sz{0}; + SizeType m_Cur{0}; + + friend class StringBuilder; + }; + + /** + * @brief StringBuilder class + * @note These results shall call delete[] after they're used. + */ + 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 LibCompiler diff --git a/dev/LibCompiler/XCOFF.h b/dev/LibCompiler/XCOFF.h new file mode 100644 index 0000000..862c363 --- /dev/null +++ b/dev/LibCompiler/XCOFF.h @@ -0,0 +1,41 @@ +/* ------------------------------------------- + + Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + + File: XCOFF.hpp + Purpose: XCOFF for NeKernel. + + Revision History: + + 04/07/24: Added file (amlel) + +------------------------------------------- */ + +#ifndef __XCOFF__ +#define __XCOFF__ + +#include + +#define kXCOFF64Magic 0x01F7 + +#define kXCOFFRelFlg 0x0001 +#define kXCOFFExecutable 0x0002 +#define kXCOFFLnno 0x0004 +#define kXCOFFLSyms 0x0008 + +namespace LibCompiler +{ + /// @brief XCoff identification header. + typedef struct XCoffFileHeader + { + UInt16 fMagic; + UInt16 fTarget; + UInt16 fNumSecs; + UInt32 fTimeDat; + UIntPtr fSymPtr; + UInt32 fNumSyms; + UInt16 fOptHdr; // ?: Number of bytes in optional header + } XCoffFileHeader; +} // namespace LibCompiler + +#endif // ifndef __XCOFF__ diff --git a/dev/LibCompiler/src/Assembler32x0.cc b/dev/LibCompiler/src/Assembler32x0.cc index 0eaf78a..1790b8b 100644 --- a/dev/LibCompiler/src/Assembler32x0.cc +++ b/dev/LibCompiler/src/Assembler32x0.cc @@ -19,10 +19,10 @@ #define __ASM_NEED_32x0__ 1 -#include +#include #include -#include -#include +#include +#include ///////////////////// diff --git a/dev/LibCompiler/src/Assembler64x0.cc b/dev/LibCompiler/src/Assembler64x0.cc index b074e9f..7630adf 100644 --- a/dev/LibCompiler/src/Assembler64x0.cc +++ b/dev/LibCompiler/src/Assembler64x0.cc @@ -19,10 +19,10 @@ #define __ASM_NEED_64x0__ 1 -#include +#include #include -#include -#include +#include +#include #include #include #include diff --git a/dev/LibCompiler/src/AssemblerAMD64.cc b/dev/LibCompiler/src/AssemblerAMD64.cc index d71caf2..be77ce9 100644 --- a/dev/LibCompiler/src/AssemblerAMD64.cc +++ b/dev/LibCompiler/src/AssemblerAMD64.cc @@ -26,10 +26,10 @@ #define kAssemblerPragmaSymStr "#" #define kAssemblerPragmaSym '#' -#include +#include #include -#include -#include +#include +#include #include #include #include diff --git a/dev/LibCompiler/src/AssemblerARM64.cc b/dev/LibCompiler/src/AssemblerARM64.cc index e402b7f..52b78d6 100644 --- a/dev/LibCompiler/src/AssemblerARM64.cc +++ b/dev/LibCompiler/src/AssemblerARM64.cc @@ -17,11 +17,11 @@ #define __ASM_NEED_ARM64__ 1 -#include -#include -#include +#include +#include +#include #include -#include +#include #include #include #include diff --git a/dev/LibCompiler/src/AssemblerPower.cc b/dev/LibCompiler/src/AssemblerPower.cc index 7cb4ca0..59f7ed6 100644 --- a/dev/LibCompiler/src/AssemblerPower.cc +++ b/dev/LibCompiler/src/AssemblerPower.cc @@ -17,11 +17,11 @@ #define __ASM_NEED_PPC__ 1 -#include -#include -#include +#include +#include +#include #include -#include +#include #include #include #include diff --git a/dev/LibCompiler/src/AssemblyFactory.cc b/dev/LibCompiler/src/AssemblyFactory.cc index 46ebed3..e70f279 100644 --- a/dev/LibCompiler/src/AssemblyFactory.cc +++ b/dev/LibCompiler/src/AssemblyFactory.cc @@ -4,8 +4,8 @@ ------------------------------------------- */ -#include -#include +#include +#include /** * @file AssemblyFactory.cxx diff --git a/dev/LibCompiler/src/CCompiler64x0.cc b/dev/LibCompiler/src/CCompiler64x0.cc index 19446af..89fc682 100644 --- a/dev/LibCompiler/src/CCompiler64x0.cc +++ b/dev/LibCompiler/src/CCompiler64x0.cc @@ -10,7 +10,7 @@ /// BUGS: 0 /// TODO: none -#include +#include #include #include #include diff --git a/dev/LibCompiler/src/CCompilerARM64.cc b/dev/LibCompiler/src/CCompilerARM64.cc index ac09cbd..5d3e892 100644 --- a/dev/LibCompiler/src/CCompilerARM64.cc +++ b/dev/LibCompiler/src/CCompilerARM64.cc @@ -10,7 +10,7 @@ /// BUGS: 0 /// TODO: none -#include +#include #include #include #include diff --git a/dev/LibCompiler/src/CCompilerPower64.cc b/dev/LibCompiler/src/CCompilerPower64.cc index 63b2794..ac35c4a 100644 --- a/dev/LibCompiler/src/CCompilerPower64.cc +++ b/dev/LibCompiler/src/CCompilerPower64.cc @@ -7,7 +7,7 @@ * ======================================================== */ -#include +#include #include #include #include @@ -21,7 +21,7 @@ #define kExitOK 0 -/// @author EL Mahrouss Amlal (amlel) +/// @author EL Mahrouss Amlal (amlal@nekernel.org) /// @file cc.cxx /// @brief POWER64 C Compiler. diff --git a/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc b/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc index 96a2873..c053920 100644 --- a/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc +++ b/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc @@ -19,7 +19,7 @@ // extern_segment, @autodelete { ... }, fn foo() -> auto { ... } -#include +#include #include #include @@ -1078,27 +1078,27 @@ LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) continue; } - if (strcmp(argv[index], "--cl:version") == 0) + if (strcmp(argv[index], "-version") == 0) { kSplashCxx(); return kExitOK; } - if (strcmp(argv[index], "--cl:verbose") == 0) + if (strcmp(argv[index], "-cxx-verbose") == 0) { kState.fVerbose = true; continue; } - if (strcmp(argv[index], "--cl:h") == 0) + if (strcmp(argv[index], "-h") == 0) { cxx_print_help(); return kExitOK; } - if (strcmp(argv[index], "--cl:c++-dialect") == 0) + if (strcmp(argv[index], "-cxx-dialect") == 0) { if (kCompilerFrontend) std::cout << kCompilerFrontend->Language() << "\n"; @@ -1106,7 +1106,7 @@ LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) return kExitOK; } - if (strcmp(argv[index], "--cl:max-err") == 0) + if (strcmp(argv[index], "-max-err") == 0) { try { diff --git a/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc b/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc index 6a4e9cd..336ca5a 100644 --- a/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc +++ b/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc @@ -10,7 +10,7 @@ /// BUGS: 0 #include -#include +#include #include #include #include @@ -419,7 +419,7 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) } else { - throw std::runtime_error("internal: Internal C++ error. (Please report that bug.)"); + throw std::runtime_error("bpp: Internal error."); } } diff --git a/dev/LibCompiler/src/Detail/AsmUtils.h b/dev/LibCompiler/src/Detail/AsmUtils.h index 29dbcbe..997564c 100644 --- a/dev/LibCompiler/src/Detail/AsmUtils.h +++ b/dev/LibCompiler/src/Detail/AsmUtils.h @@ -6,7 +6,7 @@ #pragma once -#include +#include #include using namespace LibCompiler; diff --git a/dev/LibCompiler/src/Detail/ClUtils.h b/dev/LibCompiler/src/Detail/ClUtils.h index aa1e0f6..fe788a2 100644 --- a/dev/LibCompiler/src/Detail/ClUtils.h +++ b/dev/LibCompiler/src/Detail/ClUtils.h @@ -6,7 +6,7 @@ #pragma once -#include +#include #include #define kZero64Section ".zero64" diff --git a/dev/LibCompiler/src/DynamicLinkerPEF.cc b/dev/LibCompiler/src/DynamicLinkerPEF.cc index 22f268c..6410885 100644 --- a/dev/LibCompiler/src/DynamicLinkerPEF.cc +++ b/dev/LibCompiler/src/DynamicLinkerPEF.cc @@ -7,28 +7,28 @@ ------------------------------------------- */ -/// @author EL Mahrouss Amlal (amlel) +/// @author EL Mahrouss Amlal (amlal@nekernel.org) /// @brief NeKernel 64-bit PEF Linker. -/// Last Rev: Sat Feb 24 CET 2024 +/// Last Rev: Sat Apr 19 CET 2025 /// @note Do not look up for anything with .code64/.data64/.zero64! /// It will be loaded when the program loader will start the image. //! Toolchain Kit. #include -#include +#include //! Assembler Kit -#include +#include //! Preferred Executable Format -#include +#include #include //! Release macros. #include //! Advanced Executable Object Format. -#include +#include #include #define kLinkerVersionStr "\e[0;97m NeKernel 64-Bit Linker (Preferred Executable) %s, (c) Amlal El Mahrouss 2024-2025, all rights reserved.\n" @@ -100,79 +100,79 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) */ for (size_t linker_arg = 1; linker_arg < argc; ++linker_arg) { - if (StringCompare(argv[linker_arg], "--ld64:help") == 0) + if (StringCompare(argv[linker_arg], "-help") == 0) { kLinkerSplash(); - kStdOut << "--ld64:version: Show linker version.\n"; - kStdOut << "--ld64:help: Show linker help.\n"; - kStdOut << "--ld64:verbose: Enable linker trace.\n"; - kStdOut << "--ld64:dylib: Output as a Dyanmic PEF.\n"; - kStdOut << "--ld64:fat: Output as a FAT PEF.\n"; - kStdOut << "--ld64:32k: Output as a 32x0 PEF.\n"; - kStdOut << "--ld64:64k: Output as a 64x0 PEF.\n"; - kStdOut << "--ld64:amd64: Output as a AMD64 PEF.\n"; - kStdOut << "--ld64:rv64: Output as a RISC-V PEF.\n"; - kStdOut << "--ld64:power64: Output as a POWER PEF.\n"; - kStdOut << "--ld64:arm64: Output as a ARM64 PEF.\n"; - kStdOut << "--ld64:output: Select the output file name.\n"; + kStdOut << "-version: Show linker version.\n"; + kStdOut << "-help: Show linker help.\n"; + kStdOut << "-ld-verbose: Enable linker trace.\n"; + kStdOut << "-dylib: Output as a Dyanmic PEF.\n"; + kStdOut << "-fat: Output as a FAT PEF.\n"; + kStdOut << "-32k: Output as a 32x0 PEF.\n"; + kStdOut << "-64k: Output as a 64x0 PEF.\n"; + kStdOut << "-amd64: Output as a AMD64 PEF.\n"; + kStdOut << "-rv64: Output as a RISC-V PEF.\n"; + kStdOut << "-power64: Output as a POWER PEF.\n"; + kStdOut << "-arm64: Output as a ARM64 PEF.\n"; + kStdOut << "-output: Select the output file name.\n"; return EXIT_SUCCESS; } - else if (StringCompare(argv[linker_arg], "--ld64:version") == 0) + else if (StringCompare(argv[linker_arg], "-version") == 0) { kLinkerSplash(); return EXIT_SUCCESS; } - else if (StringCompare(argv[linker_arg], "--ld64:fat-binary") == 0) + else if (StringCompare(argv[linker_arg], "-fat-binary") == 0) { kFatBinaryEnable = true; continue; } - else if (StringCompare(argv[linker_arg], "--ld64:64k") == 0) + else if (StringCompare(argv[linker_arg], "-64k") == 0) { kArch = LibCompiler::kPefArch64000; continue; } - else if (StringCompare(argv[linker_arg], "--ld64:amd64") == 0) + else if (StringCompare(argv[linker_arg], "-amd64") == 0) { kArch = LibCompiler::kPefArchAMD64; continue; } - else if (StringCompare(argv[linker_arg], "--ld64:32k") == 0) + else if (StringCompare(argv[linker_arg], "-32k") == 0) { kArch = LibCompiler::kPefArch32000; continue; } - else if (StringCompare(argv[linker_arg], "--ld64:power64") == 0) + else if (StringCompare(argv[linker_arg], "-power64") == 0) { kArch = LibCompiler::kPefArchPowerPC; continue; } - else if (StringCompare(argv[linker_arg], "--ld64:riscv64") == 0) + else if (StringCompare(argv[linker_arg], "-riscv64") == 0) { kArch = LibCompiler::kPefArchRISCV; continue; } - else if (StringCompare(argv[linker_arg], "--ld64:arm64") == 0) + else if (StringCompare(argv[linker_arg], "-arm64") == 0) { kArch = LibCompiler::kPefArchARM64; continue; } - else if (StringCompare(argv[linker_arg], "--ld64:verbose") == 0) + else if (StringCompare(argv[linker_arg], "-ld-verbose") == 0) { kVerbose = true; continue; } - else if (StringCompare(argv[linker_arg], "--ld64:dylib") == 0) + else if (StringCompare(argv[linker_arg], "-dylib") == 0) { if (kOutput.empty()) { @@ -188,7 +188,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) continue; } - else if (StringCompare(argv[linker_arg], "--ld64:output") == 0) + else if (StringCompare(argv[linker_arg], "-output") == 0) { if ((linker_arg + 1) > argc) continue; diff --git a/dev/LibCompiler/src/StringView.cc b/dev/LibCompiler/src/StringView.cc index 30f1b5f..a3bbb4c 100644 --- a/dev/LibCompiler/src/StringView.cc +++ b/dev/LibCompiler/src/StringView.cc @@ -18,7 +18,7 @@ * */ -#include +#include namespace LibCompiler { diff --git a/dev/LibDebugger/DebuggerContract.h b/dev/LibDebugger/DebuggerContract.h index 5d4f728..540ad08 100644 --- a/dev/LibDebugger/DebuggerContract.h +++ b/dev/LibDebugger/DebuggerContract.h @@ -9,8 +9,8 @@ namespace LibDebugger { - typedef uint64_t ProcessID; - typedef char* CAddress; + typedef uint64_t ProcessID; + typedef char* CAddress; /// \brief Debugger contract class in C++, as per the design states. /// \author Amlal El Mahrouss @@ -18,7 +18,7 @@ namespace LibDebugger { public: explicit DebuggerContract() = default; - virtual ~DebuggerContract() = default; + virtual ~DebuggerContract() = default; public: DebuggerContract& operator=(const DebuggerContract&) = default; @@ -26,9 +26,9 @@ namespace LibDebugger public: virtual bool Attach(ProcessID pid) noexcept = 0; - virtual bool Break(CAddress addr) noexcept = 0; - virtual bool Continue() noexcept = 0; - virtual bool Detach() noexcept = 0; + virtual bool Break(CAddress addr) noexcept = 0; + virtual bool Continue() noexcept = 0; + virtual bool Detach() noexcept = 0; virtual std::unordered_map& Get() { @@ -39,4 +39,4 @@ namespace LibDebugger pid_t m_pid; std::unordered_map m_breakpoints; }; -} // namespace LibDebugger::POSIX +} // namespace LibDebugger diff --git a/dev/LibDebugger/POSIXMachContract.h b/dev/LibDebugger/POSIXMachContract.h index 6ff083f..1962202 100644 --- a/dev/LibDebugger/POSIXMachContract.h +++ b/dev/LibDebugger/POSIXMachContract.h @@ -12,6 +12,7 @@ /// @brief POSIX/Mach debugger. #include +#include #include #include @@ -35,7 +36,7 @@ namespace LibDebugger::POSIX { /// \brief POSIXMachContract engine interface class in C++ /// \author Amlal El Mahrouss - class POSIXMachContract final : public DebuggerContract + class POSIXMachContract : public DebuggerContract { public: explicit POSIXMachContract() = default; @@ -46,7 +47,7 @@ namespace LibDebugger::POSIX POSIXMachContract(const POSIXMachContract&) = default; public: - bool Attach(ProcessID pid) noexcept override + BOOL Attach(ProcessID pid) noexcept override { #ifdef __APPLE__ if (pid == 0) @@ -69,7 +70,7 @@ namespace LibDebugger::POSIX #endif } - bool Break(CAddress addr) noexcept override + BOOL Break(CAddress addr) noexcept override { #ifdef __APPLE__ task_read_t task; @@ -100,7 +101,7 @@ namespace LibDebugger::POSIX #endif } - bool Continue() noexcept override + BOOL Continue() noexcept override { #ifdef __APPLE__ task_read_t task; @@ -122,7 +123,7 @@ namespace LibDebugger::POSIX #endif } - bool Detach() noexcept override + BOOL Detach() noexcept override { #ifdef __APPLE__ this->Continue(); diff --git a/dev/LibDebugger/src/POSIXMachContract.cc b/dev/LibDebugger/src/POSIXMachContract.cc index 4e7212c..cfce841 100644 --- a/dev/LibDebugger/src/POSIXMachContract.cc +++ b/dev/LibDebugger/src/POSIXMachContract.cc @@ -10,9 +10,9 @@ #ifndef _WIN32 -static bool kKeepRunning = false; +static BOOL kKeepRunning = false; static LibDebugger::POSIX::POSIXMachContract kDebugger; -static pid_t kPID = 0L; +static LibDebugger::ProcessID kPID = 0L; static LibDebugger::CAddress kActiveAddress = nullptr; /// @internal @@ -33,7 +33,7 @@ static void dbgi_ctrlc_handler(std::int32_t _) kKeepRunning = false; } -LIBCOMPILER_MODULE(DebuggerPOSIX) +LIBCOMPILER_MODULE(DebuggerMachPOSIX) { pfd::notify("Debugger Event", "NeKernel Debugger\n(C) 2025 Amlal El Mahrouss, all rights reserved."); -- cgit v1.2.3