From aed39642ea46602e16096f93ee163e8dbd53d1b7 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Wed, 8 May 2024 23:49:39 +0200 Subject: MHR-21: :boom: refactor. Signed-off-by: Amlal El Mahrouss --- Sources/String.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Sources/String.cc') diff --git a/Sources/String.cc b/Sources/String.cc index 449c933..6f7603f 100644 --- a/Sources/String.cc +++ b/Sources/String.cc @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright Mahrouss Logic, all rights reserved. + * Copyright SoftwareLabs, all rights reserved. * * ======================================================== */ @@ -14,7 +14,7 @@ * @version 0.2 * @date 2024-01-23 * - * @copyright Copyright (c) 2024 Mahrouss Logic + * @copyright Copyright (c) 2024 SoftwareLabs * */ -- cgit v1.2.3 From ebab1465b4d42910da1b36d8c65487c2f077b481 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Tue, 28 May 2024 21:32:21 +0200 Subject: MHR-21: refactors. Signed-off-by: Amlal El Mahrouss --- .gitignore | 4 +- .vscode/c_cpp_properties.json | 4 +- 64asm.rsrc | 8 +- 64x0-cc.rsrc | 8 +- Common/AsmKit/AsmKit.hpp | 217 ++++ Common/AsmKit/CPU/32x0.hpp | 95 ++ Common/AsmKit/CPU/64x0.hpp | 108 ++ Common/AsmKit/CPU/amd64.hpp | 56 + Common/AsmKit/CPU/ppc.hpp | 1919 ++++++++++++++++++++++++++++ Common/CompilerKit.hpp | 33 + Common/Defines.hpp | 147 +++ Common/ParserKit.hpp | 171 +++ Common/Public/SDK/CRT/__mpcc_alloca.hxx | 15 + Common/Public/SDK/CRT/__mpcc_defines.hxx | 89 ++ Common/Public/SDK/CRT/__mpcc_exception.hxx | 27 + Common/Public/SDK/CRT/__mpcc_hint.hxx | 20 + Common/Public/SDK/CRT/__mpcc_malloc.hxx | 30 + Common/Public/SDK/CRT/__mpcc_power.inc | 35 + Common/StdKit/AE.hpp | 143 +++ Common/StdKit/ELF.hpp | 389 ++++++ Common/StdKit/ErrorID.hpp | 22 + Common/StdKit/ErrorOr.hpp | 61 + Common/StdKit/PEF.hpp | 132 ++ Common/StdKit/Ref.hpp | 91 ++ Common/StdKit/String.hpp | 90 ++ Common/StdKit/XCOFF.hxx | 41 + Common/UUID.hpp | 983 ++++++++++++++ Common/Version.hxx | 3 + Documentation/ASM_SPECS.TXT | 11 - Documentation/HAVP.TXT | 13 - Documentation/Inside 64x0.pdf | Bin 64675 -> 0 bytes Documentation/NOTICE.TXT | 4 - Documentation/VNRP.TXT | 17 - Headers/AsmKit/AsmKit.hpp | 217 ---- Headers/AsmKit/CPU/32x0.hpp | 95 -- Headers/AsmKit/CPU/64x0.hpp | 108 -- Headers/AsmKit/CPU/amd64.hpp | 56 - Headers/AsmKit/CPU/ppc.hpp | 1919 ---------------------------- Headers/CompilerKit.hpp | 33 - Headers/Defines.hpp | 147 --- Headers/ParserKit.hpp | 171 --- Headers/StdKit/AE.hpp | 143 --- Headers/StdKit/ELF.hpp | 389 ------ Headers/StdKit/ErrorID.hpp | 22 - Headers/StdKit/ErrorOr.hpp | 61 - Headers/StdKit/PEF.hpp | 132 -- Headers/StdKit/Ref.hpp | 91 -- Headers/StdKit/String.hpp | 90 -- Headers/StdKit/XCOFF.hxx | 41 - Headers/UUID.hpp | 983 -------------- Headers/Version.hxx | 3 - SDK/__mpcc_alloca.hxx | 15 - SDK/__mpcc_defines.hxx | 89 -- SDK/__mpcc_exception.hxx | 27 - SDK/__mpcc_hint.hxx | 20 - SDK/__mpcc_malloc.hxx | 30 - SDK/__mpcc_power.inc | 35 - Sources/32asm.cc | 8 +- Sources/64asm.cc | 8 +- Sources/64x0-cc.cc | 6 +- Sources/AssemblyFactory.cc | 4 +- Sources/Detail/asmutils.hxx | 4 +- Sources/Detail/compilerutils.hxx | 4 +- Sources/String.cc | 2 +- Sources/bpp.cc | 4 +- Sources/coff2ae.cc | 6 +- Sources/cplusplus.cc | 4 +- Sources/elf2ae.cc | 6 +- Sources/i64asm.cc | 8 +- Sources/link.cc | 12 +- Sources/power-cc.cc | 1645 ++++++++++++++++++++++++ Sources/ppc-cc.cc | 1645 ------------------------ Sources/ppcasm.cc | 12 +- bpp.rsrc | 4 +- docs/Inside 64x0.pdf | Bin 0 -> 64675 bytes docs/asm-specs.txt | 11 + docs/havp.txt | 13 + docs/notice.txt | 4 + docs/vnrp.txt | 17 + i64asm.rsrc | 8 +- link.rsrc | 6 +- posix.make | 6 +- power-cc.rsrc | 27 + ppc-cc.rsrc | 27 - ppcasm.rsrc | 8 +- win64.make | 10 +- 86 files changed, 6711 insertions(+), 6711 deletions(-) create mode 100644 Common/AsmKit/AsmKit.hpp create mode 100644 Common/AsmKit/CPU/32x0.hpp create mode 100644 Common/AsmKit/CPU/64x0.hpp create mode 100644 Common/AsmKit/CPU/amd64.hpp create mode 100644 Common/AsmKit/CPU/ppc.hpp create mode 100644 Common/CompilerKit.hpp create mode 100644 Common/Defines.hpp create mode 100644 Common/ParserKit.hpp create mode 100644 Common/Public/SDK/CRT/__mpcc_alloca.hxx create mode 100644 Common/Public/SDK/CRT/__mpcc_defines.hxx create mode 100644 Common/Public/SDK/CRT/__mpcc_exception.hxx create mode 100644 Common/Public/SDK/CRT/__mpcc_hint.hxx create mode 100644 Common/Public/SDK/CRT/__mpcc_malloc.hxx create mode 100644 Common/Public/SDK/CRT/__mpcc_power.inc create mode 100644 Common/StdKit/AE.hpp create mode 100644 Common/StdKit/ELF.hpp create mode 100644 Common/StdKit/ErrorID.hpp create mode 100644 Common/StdKit/ErrorOr.hpp create mode 100644 Common/StdKit/PEF.hpp create mode 100644 Common/StdKit/Ref.hpp create mode 100644 Common/StdKit/String.hpp create mode 100644 Common/StdKit/XCOFF.hxx create mode 100644 Common/UUID.hpp create mode 100644 Common/Version.hxx delete mode 100644 Documentation/ASM_SPECS.TXT delete mode 100644 Documentation/HAVP.TXT delete mode 100644 Documentation/Inside 64x0.pdf delete mode 100644 Documentation/NOTICE.TXT delete mode 100644 Documentation/VNRP.TXT delete mode 100644 Headers/AsmKit/AsmKit.hpp delete mode 100644 Headers/AsmKit/CPU/32x0.hpp delete mode 100644 Headers/AsmKit/CPU/64x0.hpp delete mode 100644 Headers/AsmKit/CPU/amd64.hpp delete mode 100644 Headers/AsmKit/CPU/ppc.hpp delete mode 100644 Headers/CompilerKit.hpp delete mode 100644 Headers/Defines.hpp delete mode 100644 Headers/ParserKit.hpp delete mode 100644 Headers/StdKit/AE.hpp delete mode 100644 Headers/StdKit/ELF.hpp delete mode 100644 Headers/StdKit/ErrorID.hpp delete mode 100644 Headers/StdKit/ErrorOr.hpp delete mode 100644 Headers/StdKit/PEF.hpp delete mode 100644 Headers/StdKit/Ref.hpp delete mode 100644 Headers/StdKit/String.hpp delete mode 100644 Headers/StdKit/XCOFF.hxx delete mode 100644 Headers/UUID.hpp delete mode 100644 Headers/Version.hxx delete mode 100644 SDK/__mpcc_alloca.hxx delete mode 100644 SDK/__mpcc_defines.hxx delete mode 100644 SDK/__mpcc_exception.hxx delete mode 100644 SDK/__mpcc_hint.hxx delete mode 100644 SDK/__mpcc_malloc.hxx delete mode 100644 SDK/__mpcc_power.inc create mode 100644 Sources/power-cc.cc delete mode 100644 Sources/ppc-cc.cc create mode 100644 docs/Inside 64x0.pdf create mode 100644 docs/asm-specs.txt create mode 100644 docs/havp.txt create mode 100644 docs/notice.txt create mode 100644 docs/vnrp.txt create mode 100644 power-cc.rsrc delete mode 100644 ppc-cc.rsrc (limited to 'Sources/String.cc') diff --git a/.gitignore b/.gitignore index ee93641..c8ab9fa 100644 --- a/.gitignore +++ b/.gitignore @@ -12,8 +12,6 @@ local.properties *.exec *.bin -docs/ - # Compiled class file *.class @@ -66,6 +64,8 @@ Drivers/Output/Tests/*.masm .vs +docs/html +docs/latex docs/doxygen *.pc diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 8059633..0aad778 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -3,7 +3,7 @@ { "name": "Macintosh (CLang)", "includePath": [ - "${workspaceFolder}/Headers/**", + "${workspaceFolder}/Common/**", "${workspaceFolder}/Sources/Detail/**", "${workspaceFolder}/**" ], @@ -16,7 +16,7 @@ { "name": "Windows (Cygwin)", "includePath": [ - "${workspaceFolder}/Headers/**", + "${workspaceFolder}/Common/**", "${workspaceFolder}/Sources/Detail/**", "${workspaceFolder}/**" ], diff --git a/64asm.rsrc b/64asm.rsrc index 7c84d45..9f473f1 100644 --- a/64asm.rsrc +++ b/64asm.rsrc @@ -1,4 +1,4 @@ -#include "Headers/Version.hxx" +#include "Common/Version.hxx" 1 ICON "Icons/app-logo.ico" @@ -11,12 +11,12 @@ BEGIN BLOCK "080904E4" BEGIN VALUE "CompanyName", "SoftwareLabs" - VALUE "FileDescription", "NewOS 64x0 assembler." + VALUE "FileDescription", "SoftwareLabs assembler for 64x000." VALUE "FileVersion", kDistVersion - VALUE "InternalName", "NewAssembler" + VALUE "InternalName", "Assembler" VALUE "LegalCopyright", "SoftwareLabs" VALUE "OriginalFilename", "64asm.exe" - VALUE "ProductName", "NewAssembler" + VALUE "ProductName", "Assembler" VALUE "ProductVersion", kDistVersion END END diff --git a/64x0-cc.rsrc b/64x0-cc.rsrc index dcec172..300c684 100644 --- a/64x0-cc.rsrc +++ b/64x0-cc.rsrc @@ -1,4 +1,4 @@ -#include "Headers/Version.hxx" +#include "Common/Version.hxx" 1 ICON "Icons/app-logo.ico" @@ -11,12 +11,12 @@ BEGIN BLOCK "080904E4" BEGIN VALUE "CompanyName", "SoftwareLabs" - VALUE "FileDescription", "NewOS 64x0 C compiler." + VALUE "FileDescription", "SoftwareLabs C Compiler for 64x000." VALUE "FileVersion", kDistVersion - VALUE "InternalName", "NewC" + VALUE "InternalName", "Compiler" VALUE "LegalCopyright", "SoftwareLabs" VALUE "OriginalFilename", "64x0-cc.exe" - VALUE "ProductName", "NewC" + VALUE "ProductName", "Compiler" VALUE "ProductVersion", kDistVersion END END diff --git a/Common/AsmKit/AsmKit.hpp b/Common/AsmKit/AsmKit.hpp new file mode 100644 index 0000000..020ca5c --- /dev/null +++ b/Common/AsmKit/AsmKit.hpp @@ -0,0 +1,217 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace CompilerKit +{ + // + // @brief Frontend to Assembly mountpoint. + // + class AssemblyInterface + { + public: + explicit AssemblyInterface() = default; + virtual ~AssemblyInterface() = default; + + MPCC_COPY_DEFAULT(AssemblyInterface); + + //@ brief compile to object file. + // 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; + + MPCC_COPY_DEFAULT(AssemblyFactory); + + public: + enum + { + kArchAMD64, + kArch32x0, + kArch64x0, + kArchRISCV, + kArchPowerPC, + 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; + + MPCC_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; + + MPCC_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_64x0__ + + class Encoder64x0 final : public EncoderInterface + { + public: + explicit Encoder64x0() = default; + ~Encoder64x0() override = default; + + MPCC_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; + + MPCC_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; + + MPCC_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 CompilerKit diff --git a/Common/AsmKit/CPU/32x0.hpp b/Common/AsmKit/CPU/32x0.hpp new file mode 100644 index 0000000..fe03336 --- /dev/null +++ b/Common/AsmKit/CPU/32x0.hpp @@ -0,0 +1,95 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#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]; + 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 kOpcodes32x0 = { + kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. + kAsmOpcodeDecl("br", 0b1110011, 0b001, kAsmJump) // jump to branch + kAsmOpcodeDecl("mr", 0b0100011, 0b101, kAsmImmediate) // move registers + kAsmOpcodeDecl("psh", 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 + +//////////////////////////////// diff --git a/Common/AsmKit/CPU/64x0.hpp b/Common/AsmKit/CPU/64x0.hpp new file mode 100644 index 0000000..b28866f --- /dev/null +++ b/Common/AsmKit/CPU/64x0.hpp @@ -0,0 +1,108 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#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("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 + +//////////////////////////////// diff --git a/Common/AsmKit/CPU/amd64.hpp b/Common/AsmKit/CPU/amd64.hpp new file mode 100644 index 0000000..507602c --- /dev/null +++ b/Common/AsmKit/CPU/amd64.hpp @@ -0,0 +1,56 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#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; + +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 15 diff --git a/Common/AsmKit/CPU/ppc.hpp b/Common/AsmKit/CPU/ppc.hpp new file mode 100644 index 0000000..c4265da --- /dev/null +++ b/Common/AsmKit/CPU/ppc.hpp @@ -0,0 +1,1919 @@ +#pragma once + +#include + +/// @note Based of: +/// https://opensource.apple.com/source/cctools/cctools-750/as/ppc-opcode.h.auto.html + +/* + * 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 optype +{ + 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 SizeType size_t + +#define VoidPtr void* +#define voidPtr VoidPtr + +#define UIntPtr uintptr_t + +#define Int64 int64_t +#define UInt64 uint64_t + +#define Int32 int +#define UInt32 unsigned + +#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 +#include +#include + +#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 MPCC_COPY_DELETE(KLASS) \ + KLASS& operator=(const KLASS&) = delete; \ + KLASS(const KLASS&) = delete; + +#define MPCC_COPY_DEFAULT(KLASS) \ + KLASS& operator=(const KLASS&) = default; \ + KLASS(const KLASS&) = default; + +#define MPCC_MOVE_DELETE(KLASS) \ + KLASS& operator=(KLASS&&) = delete; \ + KLASS(KLASS&&) = delete; + +#define MPCC_MOVE_DEFAULT(KLASS) \ + KLASS& operator=(KLASS&&) = default; \ + KLASS(KLASS&&) = default; + +#include +#include +#include +#include + +namespace CompilerKit +{ + inline constexpr int BASE_YEAR = 1900; + + inline std::string current_date() noexcept + { + 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) noexcept + { + 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; + } +} // namespace CompilerKit + +#define PACKED __attribute__((packed)) + +typedef char char_type; + +#define kObjectFileExt ".obj" +#define kBinaryFileExt ".bin" + +#define kAsmFileExts \ + { \ + ".64x", ".32x", ".masm", ".s", ".S", ".asm" \ + } + +#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__ */ + +#pragma scalar_storage_order big - endian + +#endif /* ifndef __MPCC_DEFINES_HPP__ */ diff --git a/Common/ParserKit.hpp b/Common/ParserKit.hpp new file mode 100644 index 0000000..6e15c75 --- /dev/null +++ b/Common/ParserKit.hpp @@ -0,0 +1,171 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include + +namespace ParserKit +{ + using namespace CompilerKit; + + /// @brief Compiler backend, implements a frontend, such as C, C++... + /// See Toolchain, for some examples. + class CompilerBackend + { + public: + explicit CompilerBackend() = default; + virtual ~CompilerBackend() = default; + + MPCC_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 "Invalid Language"; + } + }; + + struct SyntaxLeafList; + struct SyntaxLeafList; + struct CompilerKeyword; + + /// we want to do that because to separate keywords. + enum KeywordKind + { + eKeywordKindNamespace, + eKeywordKindFunctionStart, + eKeywordKindFunctionEnd, + eKeywordKindVariable, + eKeywordKindType, + eKeywordKindExpressionBegin, + eKeywordKindExpressionEnd, + eKeywordKindArgSeparator, + eKeywordKindBodyStart, + eKeywordKindBodyEnd, + eKeywordKindClass, + eKeywordKindPtrAccess, + eKeywordKindAccess, + eKeywordKindIf, + eKeywordKindElse, + eKeywordKindElseIf, + eKeywordKindVariableAssign, + eKeywordKindVariableDec, + eKeywordKindVariableInc, + eKeywordKindConstant, + eKeywordKindTypedef, + eKeywordKindEndInstr, + eKeywordKindSpecifier, + eKeywordKindInvalid, + eKeywordKindReturn, + eKeywordKindCommentInline, + eKeywordKindCommentMultiLineStart, + eKeywordKindCommentMultiLineEnd, + eKeywordKindEq, + eKeywordKindNotEq, + eKeywordKindGreaterEq, + eKeywordKindLessEq, + eKeywordKindPtr, + }; + + /// \brief Compiler keyword information struct. + struct CompilerKeyword + { + std::string keyword_name; + KeywordKind keyword_kind = eKeywordKindInvalid; + }; + struct SyntaxLeafList final + { + struct SyntaxLeaf final + { + Int32 fUserType; +#ifdef __PK_USE_STRUCT_INSTEAD__ + CompilerKeyword fUserData; +#else + std::string fUserData; +#endif + + std::string fUserValue; + struct SyntaxLeaf* fNext; + }; + + std::vector fLeafList; + SizeType fNumLeafs; + + size_t SizeOf() + { + return fNumLeafs; + } + std::vector& 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; + } +} // namespace ParserKit diff --git a/Common/Public/SDK/CRT/__mpcc_alloca.hxx b/Common/Public/SDK/CRT/__mpcc_alloca.hxx new file mode 100644 index 0000000..a1c638e --- /dev/null +++ b/Common/Public/SDK/CRT/__mpcc_alloca.hxx @@ -0,0 +1,15 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +typedef void* ptr_type; +typedef __SIZE_TYPE__ size_type; + +inline void* __mpcc_alloca_gcc(size_type sz) +{ + return __builtin_alloca(sz); +} diff --git a/Common/Public/SDK/CRT/__mpcc_defines.hxx b/Common/Public/SDK/CRT/__mpcc_defines.hxx new file mode 100644 index 0000000..5560410 --- /dev/null +++ b/Common/Public/SDK/CRT/__mpcc_defines.hxx @@ -0,0 +1,89 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef __MPCC_DEF__ +#define __MPCC_DEF__ + +#ifndef __GNUC__ + +typedef __SIZE_TYPE__ size_t; + +#ifdef __LP64__ +typedef long int ssize_t; +#else +typedef int ssize_t; +#endif // __LP64__ + +typedef size_t ptrdiff_t; +typedef size_t uintptr_t; +typedef void* voidptr_t; +typedef void* any_t; +typedef char* caddr_t; + +#ifndef NULL +#define NULL ((voidptr_t)0) +#endif // !null + +#ifdef __GNUC__ +#include +#define __mpcc_alloca(sz) __mpcc_alloca_gcc(sz) +#elif defined(__MPCC__) + +#define __alloca(sz) __mpcc_alloca(sz) +#endif + +#define __deref(ptr) (*(ptr)) + +#ifdef __cplusplus +#define __init_decl() \ + extern "C" \ + { +#define __fini_decl() \ + } \ + ; +#else +#define __init_decl() +#define __fini_decl() +#endif + +#if __has_builtin(__builtin_alloca) +#define alloca(sz) __builtin_alloca(sz) +#ifdef __alloca +#undef __alloca +#endif +#define __alloca alloca +#else +#warning alloca not detected (MPCC) +#endif + +typedef long long off_t; +typedef unsigned long long uoff_t; + +typedef union float_cast { + struct + { + unsigned int mantissa : 23; + unsigned int exponent : 8; + unsigned int sign : 1; + }; + + float f; +} __attribute__((packed)) float_cast_t; + +typedef union double_cast { + struct + { + unsigned long long int mantissa : 52; + unsigned int exponent : 11; + unsigned int sign : 1; + }; + + double f; +} __attribute__((packed)) double_cast_t; + +#endif // ifndef __GNUC__ + +#endif /* __MPCC_DEF__ */ diff --git a/Common/Public/SDK/CRT/__mpcc_exception.hxx b/Common/Public/SDK/CRT/__mpcc_exception.hxx new file mode 100644 index 0000000..9366102 --- /dev/null +++ b/Common/Public/SDK/CRT/__mpcc_exception.hxx @@ -0,0 +1,27 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +/// This file is an implementation of __throw* family of functions. + +#include +#include +#include + +namespace std +{ + inline void __throw_general(void) + { + throw std::runtime_error("MPCC C++ Runtime error."); + } + + inline void __throw_domain_error(const char* error) + { + std::cout << "MPCC C++: Domain error: " << error << "\r"; + __throw_general(); + } +} // namespace std diff --git a/Common/Public/SDK/CRT/__mpcc_hint.hxx b/Common/Public/SDK/CRT/__mpcc_hint.hxx new file mode 100644 index 0000000..ee14711 --- /dev/null +++ b/Common/Public/SDK/CRT/__mpcc_hint.hxx @@ -0,0 +1,20 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#pragma compiler(hint_manifest) + +#define _Input +#define _Output + +#define _Optional + +#define _StrictCheckInput +#define _StrictCheckOutput + +#define _InOut +#define _StrictInOut diff --git a/Common/Public/SDK/CRT/__mpcc_malloc.hxx b/Common/Public/SDK/CRT/__mpcc_malloc.hxx new file mode 100644 index 0000000..2731868 --- /dev/null +++ b/Common/Public/SDK/CRT/__mpcc_malloc.hxx @@ -0,0 +1,30 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +namespace stdx +{ + /// @brief allocate a new class. + /// @tparam KindClass the class type to allocate. + template + inline void* allocate(Args&&... args) + { + return new KindClass(std::forward(args)...); + } + + /// @brief free a class. + /// @tparam KindClass the class type to allocate. + template + inline void release(KindClass ptr) + { + if (!ptr) + return; + delete ptr; + } +} // namespace stdx diff --git a/Common/Public/SDK/CRT/__mpcc_power.inc b/Common/Public/SDK/CRT/__mpcc_power.inc new file mode 100644 index 0000000..9e4928c --- /dev/null +++ b/Common/Public/SDK/CRT/__mpcc_power.inc @@ -0,0 +1,35 @@ +# Path: SDK/__mpcc_power.inc +# Language: MPCC POWER Assembly support for GNU. +# Build Date: 2024-6-4 + +%ifdef __CODETOOLS__ + +%def lda li +%def sta stw +%def ldw li + +%def r0 0 +%def r1 1 +%def r2 2 +%def r3 3 +%def r4 4 +%def r5 5 +%def r6 6 +%def r7 7 +%def r8 8 +%def r9 9 +%def r10 10 +%def r11 11 +%def r12 12 +%def r13 13 +%def r14 14 +%def r15 15 +%def r16 16 +%def r17 17 +%def r18 18 +%def r19 19 +%def r20 20 + +%endif + +%def nop mr 0, 0 diff --git a/Common/StdKit/AE.hpp b/Common/StdKit/AE.hpp new file mode 100644 index 0000000..9c4ac1a --- /dev/null +++ b/Common/StdKit/AE.hpp @@ -0,0 +1,143 @@ +/* + * ======================================================== + * + * MPCC + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include + +#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; + 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 CompilerKit + +// 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 +{ + /** + * @brief AE Reader protocol + * + */ + class AEReadableProtocol final + { + public: + std::ifstream FP; + + public: + explicit AEReadableProtocol() = default; + ~AEReadableProtocol() = default; + + MPCC_COPY_DELETE(AEReadableProtocol); + + /** + * @brief Read AE record + * + * @param raw the containing buffer + * @param sz it's size (without sizeof(AERecordHeader) added to it.) + * @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 CompilerKit::Utils diff --git a/Common/StdKit/ELF.hpp b/Common/StdKit/ELF.hpp new file mode 100644 index 0000000..4f0d0ae --- /dev/null +++ b/Common/StdKit/ELF.hpp @@ -0,0 +1,389 @@ +#pragma once + +#include +#include + +struct file; + +#ifndef elf_read_implies_exec +/* Executables for which elf_read_implies_exec() returns TRUE will + have the READ_IMPLIES_EXEC personality flag set automatically. + Override in asm/elf.h as needed. */ +#define elf_read_implies_exec(ex, have_pt_gnu_stack) 0 +#endif + +/* 32-bit ELF base types. */ +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +/* 64-bit ELF base types. */ +typedef uintptr_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* These constants are for the segment types stored in the image headers */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* OS-specific */ +#define PT_HIOS 0x6fffffff /* OS-specific */ +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff +#define PT_GNU_EH_FRAME 0x6474e550 + +#define PT_GNU_STACK (PT_LOOS + 0x474e551) + +/* These constants define the different elf file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* This is the info that is needed to parse the dynamic section of the file */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_ENCODING 32 +#define OLD_DT_LOOS 0x60000000 +#define DT_LOOS 0x6000000d +#define DT_HIOS 0x6ffff000 +#define DT_VALRNGLO 0x6ffffd00 +#define DT_VALRNGHI 0x6ffffdff +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_VERSYM 0x6ffffff0 +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa +#define DT_FLAGS_1 0x6ffffffb +#define DT_VERDEF 0x6ffffffc +#define DT_VERDEFNUM 0x6ffffffd +#define DT_VERNEED 0x6ffffffe +#define DT_VERNEEDNUM 0x6fffffff +#define OLD_DT_HIOS 0x6fffffff +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* This info is needed when parsing the symbol table */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_COMMON 5 +#define STT_TLS 6 + +#define ELF_ST_BIND(x) ((x) >> 4) +#define ELF_ST_TYPE(x) (((unsigned int)x) & 0xf) +#define ELF32_ST_BIND(x) ELF_ST_BIND(x) +#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) +#define ELF64_ST_BIND(x) ELF_ST_BIND(x) +#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x) + +typedef struct dynamic +{ + Elf32_Sword d_tag; + union { + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; /* entry tag value */ + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +/* The following are used with relocations */ +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x)&0xff) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i)&0xffffffff) + +typedef struct elf32_rel +{ + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf64_rel +{ + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ +} Elf64_Rel; + +typedef struct elf32_rela +{ + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct elf64_rela +{ + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ + Elf64_Sxword r_addend; /* Constant addend used to compute value */ +} Elf64_Rela; + +typedef struct elf32_sym +{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +typedef struct elf64_sym +{ + Elf64_Word st_name; /* Symbol name, index in string tbl */ + unsigned char st_info; /* Type and binding attributes */ + unsigned char st_other; /* No defined meaning, 0 */ + Elf64_Half st_shndx; /* Associated section index */ + Elf64_Addr st_value; /* Value of the symbol */ + Elf64_Xword st_size; /* Associated symbol size */ +} Elf64_Sym; + +#define EI_NIDENT 16 + +typedef struct elf32_hdr +{ + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; /* Entry point */ + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +typedef struct elf64_hdr +{ + unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* These constants define the permissions on sections in the program + header, p_flags. */ +#define PF_R 0x4 +#define PF_W 0x2 +#define PF_X 0x1 + +typedef struct elf32_phdr +{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +typedef struct elf64_phdr +{ + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment, file & memory */ +} Elf64_Phdr; + +/* sh_type */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* sh_flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +/* special section indexes */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +typedef struct +{ + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct elf64_shdr +{ + Elf64_Word sh_name; /* Section name, index in string tbl */ + Elf64_Word sh_type; /* Type of section */ + Elf64_Xword sh_flags; /* Miscellaneous section attributes */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Size of section in bytes */ + Elf64_Word sh_link; /* Index of another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +#define ELFOSABI_NONE 0 +#define ELFOSABI_LINUX 3 + +#ifndef ELF_OSABI +#define ELF_OSABI ELFOSABI_NONE +#endif + +/* Notes used in ET_CORE */ +#define NT_PRSTATUS 1 +#define NT_PRFPREG 2 +#define NT_PRPSINFO 3 +#define NT_TASKSTRUCT 4 +#define NT_AUXV 6 +#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ +#define NT_PPC_VMX 0x100 /* POWER Altivec/VMX registers */ +#define NT_PPC_SPE 0x101 /* POWER SPE/EVR registers */ +#define NT_PPC_VSX 0x102 /* POWER VSX registers */ +#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ +#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ +#define NT_PRXSTATUS 0x300 /* s390 upper register halves */ + +/* Note header in a PT_NOTE section */ +typedef struct elf32_note +{ + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +} Elf32_Nhdr; + +/* Note header in a PT_NOTE section */ +typedef struct elf64_note +{ + Elf64_Word n_namesz; /* Name size */ + Elf64_Word n_descsz; /* Content size */ + Elf64_Word n_type; /* Content type */ +} Elf64_Nhdr; diff --git a/Common/StdKit/ErrorID.hpp b/Common/StdKit/ErrorID.hpp new file mode 100644 index 0000000..9f12ab2 --- /dev/null +++ b/Common/StdKit/ErrorID.hpp @@ -0,0 +1,22 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +#define MPCC_EXEC_ERROR -30 +#define MPCC_FILE_NOT_FOUND -31 +#define MPCC_DIR_NOT_FOUND -32 +#define MPCC_FILE_EXISTS -33 +#define MPCC_TOO_LONG -34 +#define MPCC_INVALID_DATA -35 +#define MPCC_UNIMPLEMENTED -36 +#define MPCC_FAT_ERROR -37 diff --git a/Common/StdKit/ErrorOr.hpp b/Common/StdKit/ErrorOr.hpp new file mode 100644 index 0000000..cf35b26 --- /dev/null +++ b/Common/StdKit/ErrorOr.hpp @@ -0,0 +1,61 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +namespace CompilerKit +{ + 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 CompilerKit diff --git a/Common/StdKit/PEF.hpp b/Common/StdKit/PEF.hpp new file mode 100644 index 0000000..b084f32 --- /dev/null +++ b/Common/StdKit/PEF.hpp @@ -0,0 +1,132 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +// @file PEF.hpp +// @brief Preferred Executable Format + +#define kPefMagic "Joy!" +#define kPefMagicFat "yoJ!" + +#define kPefExt ".exec" +#define kPefDylibExt ".lib" +#define kPefLibExt ".slib" +#define kPefObjectExt ".obj" +#define kPefDebugExt ".dbg" + +#define kPefMagicLen 5 + +#define kPefVersion 2 +#define kPefNameLen 255 + +#define kPefBaseOrigin (0x1000000) + +#define kPefStart "__ImageStart" + +namespace CompilerKit +{ + enum + { + kPefArchIntel86S = 100, + kPefArchAMD64, + kPefArchRISCV, + kPefArch64000, /* 64x0 RISC architecture. */ + kPefArch32000, + kPefArchPowerPC, /* 64-bit POWER architecture. */ + kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1, + kPefArchInvalid = 0xFF, + }; + + enum + { + kPefSubArchAMD, + kPefSubArchIntel, + kPefSubArchARM, + kPefSubArchIBM, + }; + + enum + { + kPefKindExec = 1, /* .exe */ + kPefKindSharedObject = 2, /* .lib */ + 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; + + /* 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; + + enum + { + kPefCode = 0xC, + kPefData = 0xD, + kPefZero = 0xE, + kPefLinkerID = 0x1, + kPefCount = 4, + kPefInvalid = 0xFF, + }; +} // namespace CompilerKit + +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/Common/StdKit/Ref.hpp b/Common/StdKit/Ref.hpp new file mode 100644 index 0000000..d13f97c --- /dev/null +++ b/Common/StdKit/Ref.hpp @@ -0,0 +1,91 @@ + +/* + * ======================================================== + * + * CompilerKit + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +namespace CompilerKit +{ + // @author Amlal EL Mahrouss + // @brief Reference class, refers to a pointer of data in static memory. + template + 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 + class NonNullRef final + { + public: + NonNullRef() = delete; + NonNullRef(nullPtr) = 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 CompilerKit diff --git a/Common/StdKit/String.hpp b/Common/StdKit/String.hpp new file mode 100644 index 0000000..a05a31c --- /dev/null +++ b/Common/StdKit/String.hpp @@ -0,0 +1,90 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +namespace CompilerKit +{ + /** + * @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 char[Sz]; + assert(m_Data); + } + + ~StringView() noexcept + { + if (m_Data) + { + memset(m_Data, 0, m_Sz); + delete[] m_Data; + + m_Data = nullptr; + } + } + + MPCC_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: + char* 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 CompilerKit diff --git a/Common/StdKit/XCOFF.hxx b/Common/StdKit/XCOFF.hxx new file mode 100644 index 0000000..a26b591 --- /dev/null +++ b/Common/StdKit/XCOFF.hxx @@ -0,0 +1,41 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: XCOFF.hpp + Purpose: XCOFF for NewOS. + + 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 CompilerKit +{ + /// @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 CompilerKit + +#endif // ifndef __XCOFF__ \ No newline at end of file diff --git a/Common/UUID.hpp b/Common/UUID.hpp new file mode 100644 index 0000000..00b153b --- /dev/null +++ b/Common/UUID.hpp @@ -0,0 +1,983 @@ +#ifndef STDUUID_H +#define STDUUID_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus + +#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) +#define LIBUUID_CPP20_OR_GREATER +#endif + +#endif + +#ifdef LIBUUID_CPP20_OR_GREATER +#include +#else +#include +#endif + +#ifdef _WIN32 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef UUID_SYSTEM_GENERATOR +#include +#endif + +#ifdef UUID_TIME_GENERATOR +#include +#pragma comment(lib, "IPHLPAPI.lib") +#endif + +#elif defined(__linux__) || defined(__unix__) + +#ifdef UUID_SYSTEM_GENERATOR +#include +#endif + +#elif defined(__APPLE__) + +#ifdef UUID_SYSTEM_GENERATOR +#include +#endif + +#endif + +namespace uuids +{ +#ifdef __cpp_lib_span + template + using span = std::span; +#else + template + using span = gsl::span; +#endif + + namespace detail + { + template + [[nodiscard]] constexpr inline unsigned char hex2char(TChar const ch) noexcept + { + if (ch >= static_cast('0') && ch <= static_cast('9')) + return static_cast(ch - static_cast('0')); + if (ch >= static_cast('a') && ch <= static_cast('f')) + return static_cast(10 + ch - static_cast('a')); + if (ch >= static_cast('A') && ch <= static_cast('F')) + return static_cast(10 + ch - static_cast('A')); + return 0; + } + + template + [[nodiscard]] constexpr inline bool is_hex(TChar const ch) noexcept + { + return (ch >= static_cast('0') && ch <= static_cast('9')) || + (ch >= static_cast('a') && ch <= static_cast('f')) || + (ch >= static_cast('A') && ch <= static_cast('F')); + } + + template + [[nodiscard]] constexpr std::basic_string_view to_string_view( + TChar const* str) noexcept + { + if (str) + return str; + return {}; + } + + template + [[nodiscard]] constexpr std::basic_string_view + to_string_view(StringType const& str) noexcept + { + return str; + } + + class sha1 + { + public: + using digest32_t = uint32_t[5]; + using digest8_t = uint8_t[20]; + + static constexpr unsigned int block_bytes = 64; + + [[nodiscard]] inline static uint32_t left_rotate( + uint32_t value, size_t const count) noexcept + { + return (value << count) ^ (value >> (32 - count)); + } + + sha1() + { + reset(); + } + + void reset() noexcept + { + m_digest[0] = 0x67452301; + m_digest[1] = 0xEFCDAB89; + m_digest[2] = 0x98BADCFE; + m_digest[3] = 0x10325476; + m_digest[4] = 0xC3D2E1F0; + m_blockByteIndex = 0; + m_byteCount = 0; + } + + void process_byte(uint8_t octet) + { + this->m_block[this->m_blockByteIndex++] = octet; + ++this->m_byteCount; + if (m_blockByteIndex == block_bytes) + { + this->m_blockByteIndex = 0; + process_block(); + } + } + + void process_block(void const* const start, void const* const end) + { + const uint8_t* begin = static_cast(start); + const uint8_t* finish = static_cast(end); + while (begin != finish) + { + process_byte(*begin); + begin++; + } + } + + void process_bytes(void const* const data, size_t const len) + { + const uint8_t* block = static_cast(data); + process_block(block, block + len); + } + + uint32_t const* get_digest(digest32_t digest) + { + size_t const bitCount = this->m_byteCount * 8; + process_byte(0x80); + if (this->m_blockByteIndex > 56) + { + while (m_blockByteIndex != 0) + { + process_byte(0); + } + while (m_blockByteIndex < 56) + { + process_byte(0); + } + } + else + { + while (m_blockByteIndex < 56) + { + process_byte(0); + } + } + process_byte(0); + process_byte(0); + process_byte(0); + process_byte(0); + process_byte(static_cast((bitCount >> 24) & 0xFF)); + process_byte(static_cast((bitCount >> 16) & 0xFF)); + process_byte(static_cast((bitCount >> 8) & 0xFF)); + process_byte(static_cast((bitCount)&0xFF)); + + memcpy(digest, m_digest, 5 * sizeof(uint32_t)); + return digest; + } + + uint8_t const* get_digest_bytes(digest8_t digest) + { + digest32_t d32; + get_digest(d32); + size_t di = 0; + digest[di++] = static_cast(d32[0] >> 24); + digest[di++] = static_cast(d32[0] >> 16); + digest[di++] = static_cast(d32[0] >> 8); + digest[di++] = static_cast(d32[0] >> 0); + + digest[di++] = static_cast(d32[1] >> 24); + digest[di++] = static_cast(d32[1] >> 16); + digest[di++] = static_cast(d32[1] >> 8); + digest[di++] = static_cast(d32[1] >> 0); + + digest[di++] = static_cast(d32[2] >> 24); + digest[di++] = static_cast(d32[2] >> 16); + digest[di++] = static_cast(d32[2] >> 8); + digest[di++] = static_cast(d32[2] >> 0); + + digest[di++] = static_cast(d32[3] >> 24); + digest[di++] = static_cast(d32[3] >> 16); + digest[di++] = static_cast(d32[3] >> 8); + digest[di++] = static_cast(d32[3] >> 0); + + digest[di++] = static_cast(d32[4] >> 24); + digest[di++] = static_cast(d32[4] >> 16); + digest[di++] = static_cast(d32[4] >> 8); + digest[di++] = static_cast(d32[4] >> 0); + + return digest; + } + + private: + void process_block() + { + uint32_t w[80]; + for (size_t i = 0; i < 16; i++) + { + w[i] = static_cast(m_block[i * 4 + 0] << 24); + w[i] |= static_cast(m_block[i * 4 + 1] << 16); + w[i] |= static_cast(m_block[i * 4 + 2] << 8); + w[i] |= static_cast(m_block[i * 4 + 3]); + } + for (size_t i = 16; i < 80; i++) + { + w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1); + } + + uint32_t a = m_digest[0]; + uint32_t b = m_digest[1]; + uint32_t c = m_digest[2]; + uint32_t d = m_digest[3]; + uint32_t e = m_digest[4]; + + for (std::size_t i = 0; i < 80; ++i) + { + uint32_t f = 0; + uint32_t k = 0; + + if (i < 20) + { + f = (b & c) | (~b & d); + k = 0x5A827999; + } + else if (i < 40) + { + f = b ^ c ^ d; + k = 0x6ED9EBA1; + } + else if (i < 60) + { + f = (b & c) | (b & d) | (c & d); + k = 0x8F1BBCDC; + } + else + { + f = b ^ c ^ d; + k = 0xCA62C1D6; + } + uint32_t temp = left_rotate(a, 5) + f + e + k + w[i]; + e = d; + d = c; + c = left_rotate(b, 30); + b = a; + a = temp; + } + + m_digest[0] += a; + m_digest[1] += b; + m_digest[2] += c; + m_digest[3] += d; + m_digest[4] += e; + } + + private: + digest32_t m_digest; + uint8_t m_block[64]; + size_t m_blockByteIndex; + size_t m_byteCount; + }; + + template + inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000"; + + template <> + inline constexpr wchar_t empty_guid[37] = + L"00000000-0000-0000-0000-000000000000"; + + template + inline constexpr CharT guid_encoder[17] = "0123456789abcdef"; + + template <> + inline constexpr wchar_t guid_encoder[17] = L"0123456789abcdef"; + } // namespace detail + + // -------------------------------------------------------------------------------------------------------------------------- + // UUID format https://tools.ietf.org/html/rfc4122 + // -------------------------------------------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------------------------------------------- + // Field NDR Data Type Octet # Note + // -------------------------------------------------------------------------------------------------------------------------- + // time_low unsigned long 0 - 3 The low field + // of the timestamp. time_mid unsigned short 4 - 5 + // The middle field of the timestamp. time_hi_and_version unsigned + // short 6 - 7 The high field of the timestamp multiplexed + // with the version number. clock_seq_hi_and_reserved unsigned small 8 + // The high field of the clock sequence multiplexed with the variant. + // clock_seq_low unsigned small 9 The low + // field of the clock sequence. node character 10 + // - 15 The spatially unique node identifier. + // -------------------------------------------------------------------------------------------------------------------------- + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | time_low | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | time_mid | time_hi_and_version | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // |clk_seq_hi_res | clk_seq_low | node (0-1) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | node (2-5) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + // -------------------------------------------------------------------------------------------------------------------------- + // enumerations + // -------------------------------------------------------------------------------------------------------------------------- + + // indicated by a bit pattern in octet 8, marked with N in + // xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx + enum class uuid_variant + { + // NCS backward compatibility (with the obsolete Apollo Network Computing + // System 1.5 UUID format) N bit pattern: 0xxx > the first 6 octets of the + // UUID are a 48-bit timestamp (the number of 4 microsecond units of time + // since 1 Jan 1980 UTC); > the next 2 octets are reserved; > the next octet + // is the "address family"; > the final 7 octets are a 56-bit host ID in the + // form specified by the address family + ncs, + + // RFC 4122/DCE 1.1 + // N bit pattern: 10xx + // > big-endian byte order + rfc, + + // Microsoft Corporation backward compatibility + // N bit pattern: 110x + // > little endian byte order + // > formely used in the Component Object Model (COM) library + microsoft, + + // reserved for possible future definition + // N bit pattern: 111x + reserved + }; + + // indicated by a bit pattern in octet 6, marked with M in + // xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx + enum class uuid_version + { + none = 0, // only possible for nil or invalid uuids + time_based = 1, // The time-based version specified in RFC 4122 + dce_security = 2, // DCE Security version, with embedded POSIX UIDs. + name_based_md5 = + 3, // The name-based version specified in RFS 4122 with MD5 hashing + random_number_based = 4, // The randomly or pseudo-randomly generated version + // specified in RFS 4122 + name_based_sha1 = + 5 // The name-based version specified in RFS 4122 with SHA1 hashing + }; + + // Forward declare uuid & to_string so that we can declare to_string as a friend + // later. + class uuid; + template , class Allocator = std::allocator> + std::basic_string to_string(uuid const& id); + + // -------------------------------------------------------------------------------------------------------------------------- + // uuid class + // -------------------------------------------------------------------------------------------------------------------------- + class uuid + { + public: + using value_type = uint8_t; + + constexpr uuid() noexcept = default; + + uuid(value_type (&arr)[16]) noexcept + { + std::copy(std::cbegin(arr), std::cend(arr), std::begin(data)); + } + + constexpr uuid(std::array const& arr) noexcept + : data{arr} + { + } + + explicit uuid(span bytes) + { + std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data)); + } + + template + explicit uuid(ForwardIterator first, ForwardIterator last) + { + if (std::distance(first, last) == 16) + std::copy(first, last, std::begin(data)); + } + + [[nodiscard]] constexpr uuid_variant variant() const noexcept + { + if ((data[8] & 0x80) == 0x00) + return uuid_variant::ncs; + else if ((data[8] & 0xC0) == 0x80) + return uuid_variant::rfc; + else if ((data[8] & 0xE0) == 0xC0) + return uuid_variant::microsoft; + else + return uuid_variant::reserved; + } + + [[nodiscard]] constexpr uuid_version version() const noexcept + { + if ((data[6] & 0xF0) == 0x10) + return uuid_version::time_based; + else if ((data[6] & 0xF0) == 0x20) + return uuid_version::dce_security; + else if ((data[6] & 0xF0) == 0x30) + return uuid_version::name_based_md5; + else if ((data[6] & 0xF0) == 0x40) + return uuid_version::random_number_based; + else if ((data[6] & 0xF0) == 0x50) + return uuid_version::name_based_sha1; + else + return uuid_version::none; + } + + [[nodiscard]] constexpr bool is_nil() const noexcept + { + for (size_t i = 0; i < data.size(); ++i) + if (data[i] != 0) + return false; + return true; + } + + void swap(uuid& other) noexcept + { + data.swap(other.data); + } + + [[nodiscard]] inline span as_bytes() const + { + return span( + reinterpret_cast(data.data()), 16); + } + + template + [[nodiscard]] constexpr static bool is_valid_uuid( + StringType const& in_str) noexcept + { + auto str = detail::to_string_view(in_str); + bool firstDigit = true; + size_t hasBraces = 0; + size_t index = 0; + + if (str.empty()) + return false; + + if (str.front() == '{') + hasBraces = 1; + if (hasBraces && str.back() != '}') + return false; + + for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) + { + if (str[i] == '-') + continue; + + if (index >= 16 || !detail::is_hex(str[i])) + { + return false; + } + + if (firstDigit) + { + firstDigit = false; + } + else + { + index++; + firstDigit = true; + } + } + + if (index < 16) + { + return false; + } + + return true; + } + + template + [[nodiscard]] constexpr static std::optional from_string( + StringType const& in_str) noexcept + { + auto str = detail::to_string_view(in_str); + bool firstDigit = true; + size_t hasBraces = 0; + size_t index = 0; + + std::array data{{0}}; + + if (str.empty()) + return {}; + + if (str.front() == '{') + hasBraces = 1; + if (hasBraces && str.back() != '}') + return {}; + + for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) + { + if (str[i] == '-') + continue; + + if (index >= 16 || !detail::is_hex(str[i])) + { + return {}; + } + + if (firstDigit) + { + data[index] = static_cast(detail::hex2char(str[i]) << 4); + firstDigit = false; + } + else + { + data[index] = + static_cast(data[index] | detail::hex2char(str[i])); + index++; + firstDigit = true; + } + } + + if (index < 16) + { + return {}; + } + + return uuid{data}; + } + + private: + std::array data{{0}}; + + friend bool operator==(uuid const& lhs, uuid const& rhs) noexcept; + friend bool operator<(uuid const& lhs, uuid const& rhs) noexcept; + + template + friend std::basic_ostream& operator<<( + std::basic_ostream& s, uuid const& id); + + template + friend std::basic_string to_string(uuid const& id); + + friend std::hash; + }; + + // -------------------------------------------------------------------------------------------------------------------------- + // operators and non-member functions + // -------------------------------------------------------------------------------------------------------------------------- + + [[nodiscard]] inline bool operator==(uuid const& lhs, + uuid const& rhs) noexcept + { + return lhs.data == rhs.data; + } + + [[nodiscard]] inline bool operator!=(uuid const& lhs, + uuid const& rhs) noexcept + { + return !(lhs == rhs); + } + + [[nodiscard]] inline bool operator<(uuid const& lhs, uuid const& rhs) noexcept + { + return lhs.data < rhs.data; + } + + template + [[nodiscard]] inline std::basic_string to_string( + uuid const& id) + { + std::basic_string uustr{detail::empty_guid}; + + for (size_t i = 0, index = 0; i < 36; ++i) + { + if (i == 8 || i == 13 || i == 18 || i == 23) + { + continue; + } + uustr[i] = detail::guid_encoder[id.data[index] >> 4 & 0x0f]; + uustr[++i] = detail::guid_encoder[id.data[index] & 0x0f]; + index++; + } + + return uustr; + } + + template + std::basic_ostream& operator<<( + std::basic_ostream& s, uuid const& id) + { + s << to_string(id); + return s; + } + + inline void swap(uuids::uuid& lhs, uuids::uuid& rhs) noexcept + { + lhs.swap(rhs); + } + + // -------------------------------------------------------------------------------------------------------------------------- + // namespace IDs that could be used for generating name-based uuids + // -------------------------------------------------------------------------------------------------------------------------- + + // Name string is a fully-qualified domain name + static uuid uuid_namespace_dns{{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // Name string is a URL + static uuid uuid_namespace_url{{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // Name string is an ISO OID (See https://oidref.com/, + // https://en.wikipedia.org/wiki/Object_identifier) + static uuid uuid_namespace_oid{{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // Name string is an X.500 DN, in DER or a text output format (See + // https://en.wikipedia.org/wiki/X.500, + // https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One) + static uuid uuid_namespace_x500{{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // -------------------------------------------------------------------------------------------------------------------------- + // uuid generators + // -------------------------------------------------------------------------------------------------------------------------- + +#ifdef UUID_SYSTEM_GENERATOR + class uuid_system_generator + { + public: + using result_type = uuid; + + uuid operator()() + { +#ifdef _WIN32 + + GUID newId; + HRESULT hr = ::CoCreateGuid(&newId); + + if (FAILED(hr)) + { + throw std::system_error(hr, std::system_category(), + "CoCreateGuid failed"); + } + + std::array bytes = { + {static_cast((newId.Data1 >> 24) & 0xFF), + static_cast((newId.Data1 >> 16) & 0xFF), + static_cast((newId.Data1 >> 8) & 0xFF), + static_cast((newId.Data1) & 0xFF), + + (unsigned char)((newId.Data2 >> 8) & 0xFF), + (unsigned char)((newId.Data2) & 0xFF), + + (unsigned char)((newId.Data3 >> 8) & 0xFF), + (unsigned char)((newId.Data3) & 0xFF), + + newId.Data4[0], newId.Data4[1], newId.Data4[2], newId.Data4[3], + newId.Data4[4], newId.Data4[5], newId.Data4[6], newId.Data4[7]}}; + + return uuid{std::begin(bytes), std::end(bytes)}; + +#elif defined(__linux__) || defined(__unix__) + + uuid_t id; + uuid_generate(id); + + std::array bytes = {{id[0], id[1], id[2], id[3], id[4], id[5], + id[6], id[7], id[8], id[9], id[10], + id[11], id[12], id[13], id[14], id[15]}}; + + return uuid{std::begin(bytes), std::end(bytes)}; + +#elif defined(__APPLE__) + auto newId = CFUUIDCreate(NULL); + auto bytes = CFUUIDGetUUIDBytes(newId); + CFRelease(newId); + + std::array arrbytes = { + {bytes.byte0, bytes.byte1, bytes.byte2, bytes.byte3, bytes.byte4, + bytes.byte5, bytes.byte6, bytes.byte7, bytes.byte8, bytes.byte9, + bytes.byte10, bytes.byte11, bytes.byte12, bytes.byte13, bytes.byte14, + bytes.byte15}}; + return uuid{std::begin(arrbytes), std::end(arrbytes)}; +#else + return uuid{}; +#endif + } + }; +#endif + + template + class basic_uuid_random_generator + { + public: + using engine_type = UniformRandomNumberGenerator; + + explicit basic_uuid_random_generator(engine_type& gen) + : generator(&gen, [](auto) {}) + { + } + explicit basic_uuid_random_generator(engine_type* gen) + : generator(gen, [](auto) {}) + { + } + + [[nodiscard]] uuid operator()() + { + alignas(uint32_t) uint8_t bytes[16]; + for (int i = 0; i < 16; i += 4) + *reinterpret_cast(bytes + i) = distribution(*generator); + + // variant must be 10xxxxxx + bytes[8] &= 0xBF; + bytes[8] |= 0x80; + + // version must be 0100xxxx + bytes[6] &= 0x4F; + bytes[6] |= 0x40; + + return uuid{std::begin(bytes), std::end(bytes)}; + } + + private: + std::uniform_int_distribution distribution; + std::shared_ptr generator; + }; + + using uuid_random_generator = basic_uuid_random_generator; + + class uuid_name_generator + { + public: + explicit uuid_name_generator(uuid const& namespace_uuid) noexcept + : nsuuid(namespace_uuid) + { + } + + template + [[nodiscard]] uuid operator()(StringType const& name) + { + reset(); + process_characters(detail::to_string_view(name)); + return make_uuid(); + } + + private: + void reset() + { + hasher.reset(); + std::byte bytes[16]; + auto nsbytes = nsuuid.as_bytes(); + std::copy(std::cbegin(nsbytes), std::cend(nsbytes), bytes); + hasher.process_bytes(bytes, 16); + } + + template + void process_characters(std::basic_string_view const str) + { + for (uint32_t c : str) + { + hasher.process_byte(static_cast(c & 0xFF)); + if constexpr (!std::is_same_v) + { + hasher.process_byte(static_cast((c >> 8) & 0xFF)); + hasher.process_byte(static_cast((c >> 16) & 0xFF)); + hasher.process_byte(static_cast((c >> 24) & 0xFF)); + } + } + } + + [[nodiscard]] uuid make_uuid() + { + detail::sha1::digest8_t digest; + hasher.get_digest_bytes(digest); + + // variant must be 0b10xxxxxx + digest[8] &= 0xBF; + digest[8] |= 0x80; + + // version must be 0b0101xxxx + digest[6] &= 0x5F; + digest[6] |= 0x50; + + return uuid{digest, digest + 16}; + } + + private: + uuid nsuuid; + detail::sha1 hasher; + }; + +#ifdef UUID_TIME_GENERATOR + // !!! DO NOT USE THIS IN PRODUCTION + // this implementation is unreliable for good uuids + class uuid_time_generator + { + using mac_address = std::array; + + std::optional device_address; + + [[nodiscard]] bool get_mac_address() + { + if (device_address.has_value()) + { + return true; + } + +#ifdef _WIN32 + DWORD len = 0; + auto ret = GetAdaptersInfo(nullptr, &len); + if (ret != ERROR_BUFFER_OVERFLOW) + return false; + std::vector buf(len); + auto pips = reinterpret_cast(&buf.front()); + ret = GetAdaptersInfo(pips, &len); + if (ret != ERROR_SUCCESS) + return false; + mac_address addr; + std::copy(pips->Address, pips->Address + 6, std::begin(addr)); + device_address = addr; +#endif + + return device_address.has_value(); + } + + [[nodiscard]] long long get_time_intervals() + { + auto start = std::chrono::system_clock::from_time_t(time_t(-12219292800)); + auto diff = std::chrono::system_clock::now() - start; + auto ns = + std::chrono::duration_cast(diff).count(); + return ns / 100; + } + + [[nodiscard]] static unsigned short get_clock_sequence() + { + static std::mt19937 clock_gen(std::random_device{}()); + static std::uniform_int_distribution clock_dis; + static std::atomic_ushort clock_sequence = clock_dis(clock_gen); + return clock_sequence++; + } + + public: + [[nodiscard]] uuid operator()() + { + if (get_mac_address()) + { + std::array data; + + auto tm = get_time_intervals(); + + auto clock_seq = get_clock_sequence(); + + auto ptm = reinterpret_cast(&tm); + + memcpy(&data[0], ptm + 4, 4); + memcpy(&data[4], ptm + 2, 2); + memcpy(&data[6], ptm, 2); + + memcpy(&data[8], &clock_seq, 2); + + // variant must be 0b10xxxxxx + data[8] &= 0xBF; + data[8] |= 0x80; + + // version must be 0b0001xxxx + data[6] &= 0x1F; + data[6] |= 0x10; + + memcpy(&data[10], &device_address.value()[0], 6); + + return uuids::uuid{std::cbegin(data), std::cend(data)}; + } + + return {}; + } + }; +#endif +} // namespace uuids + +namespace std +{ + template <> + struct hash + { + using argument_type = uuids::uuid; + using result_type = std::size_t; + + [[nodiscard]] result_type operator()(argument_type const& uuid) const + { +#ifdef UUID_HASH_STRING_BASED + std::hash hasher; + return static_cast(hasher(uuids::to_string(uuid))); +#else + uint64_t l = static_cast(uuid.data[0]) << 56 | + static_cast(uuid.data[1]) << 48 | + static_cast(uuid.data[2]) << 40 | + static_cast(uuid.data[3]) << 32 | + static_cast(uuid.data[4]) << 24 | + static_cast(uuid.data[5]) << 16 | + static_cast(uuid.data[6]) << 8 | + static_cast(uuid.data[7]); + uint64_t h = static_cast(uuid.data[8]) << 56 | + static_cast(uuid.data[9]) << 48 | + static_cast(uuid.data[10]) << 40 | + static_cast(uuid.data[11]) << 32 | + static_cast(uuid.data[12]) << 24 | + static_cast(uuid.data[13]) << 16 | + static_cast(uuid.data[14]) << 8 | + static_cast(uuid.data[15]); + + if constexpr (sizeof(result_type) > 4) + { + return result_type(l ^ h); + } + else + { + uint64_t hash64 = l ^ h; + return result_type(uint32_t(hash64 >> 32) ^ uint32_t(hash64)); + } +#endif + } + }; +} // namespace std + +#endif /* STDUUID_H */ \ No newline at end of file diff --git a/Common/Version.hxx b/Common/Version.hxx new file mode 100644 index 0000000..377a688 --- /dev/null +++ b/Common/Version.hxx @@ -0,0 +1,3 @@ +#pragma once + +#define kDistVersion "v1.20" diff --git a/Documentation/ASM_SPECS.TXT b/Documentation/ASM_SPECS.TXT deleted file mode 100644 index a0c42bf..0000000 --- a/Documentation/ASM_SPECS.TXT +++ /dev/null @@ -1,11 +0,0 @@ -==================== -X86 ASSEMBLER SPECS -==================== - -WHAT TO DO: - Provide a complete support of x86-64 with: - - - org directive. - - 64-bit and 32-bit registers. - - basic instructions (load, store, jump to) - - flushable into object-code and flat binary. \ No newline at end of file diff --git a/Documentation/HAVP.TXT b/Documentation/HAVP.TXT deleted file mode 100644 index 12fcec5..0000000 --- a/Documentation/HAVP.TXT +++ /dev/null @@ -1,13 +0,0 @@ -HAVP - Harvard Audio/Video Processor - -- Encoding: IBAD - -- Data path = 24 - - 16: sound data - - 8: information data - -- Register size: 32 -- Store strategy: shift registers. -- Standard registers: [ r0, r9 ] -- Floating point registers: [ f0, f2 ] -- Builtin SRAM: 512kb diff --git a/Documentation/Inside 64x0.pdf b/Documentation/Inside 64x0.pdf deleted file mode 100644 index bcd6782..0000000 Binary files a/Documentation/Inside 64x0.pdf and /dev/null differ diff --git a/Documentation/NOTICE.TXT b/Documentation/NOTICE.TXT deleted file mode 100644 index 23691da..0000000 --- a/Documentation/NOTICE.TXT +++ /dev/null @@ -1,4 +0,0 @@ -The X64000 draft papers -They contain thing that might appear through the next iteration of 64k. - -Please look at the document shared for the latest revisions. \ No newline at end of file diff --git a/Documentation/VNRP.TXT b/Documentation/VNRP.TXT deleted file mode 100644 index e17b494..0000000 --- a/Documentation/VNRP.TXT +++ /dev/null @@ -1,17 +0,0 @@ -VNRP - Von Neumann, RISC Processor - -- Encoding = RegToReg, Imm, Syscall, Jump, NoArgs - -- Data path = 128-bit (register data) -- Addressing = 58-bit physical address size. - -- Registers (128-bit) = r0, r19 -- Float/Vector registers (128-bit) = f0, f9 - -- Out of order (superscalar also added to the equation) = Yes -- Superscalar = Yes - -- L1 cache: 16kb (8 instr, 8 data) -- L2 cache: 1024kb (512 instr, 512 data) - -- Clock speed: 1 Ghz diff --git a/Headers/AsmKit/AsmKit.hpp b/Headers/AsmKit/AsmKit.hpp deleted file mode 100644 index d22ec21..0000000 --- a/Headers/AsmKit/AsmKit.hpp +++ /dev/null @@ -1,217 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -#include -#include -#include - -namespace CompilerKit -{ - // - // @brief Frontend to Assembly mountpoint. - // - class AssemblyInterface - { - public: - explicit AssemblyInterface() = default; - virtual ~AssemblyInterface() = default; - - MPCC_COPY_DEFAULT(AssemblyInterface); - - //@ brief compile to object file. - // 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; - - MPCC_COPY_DEFAULT(AssemblyFactory); - - public: - enum - { - kArchAMD64, - kArch32x0, - kArch64x0, - kArchRISCV, - kArchPowerPC, - 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; - - MPCC_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; - - MPCC_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_64x0__ - - class Encoder64x0 final : public EncoderInterface - { - public: - explicit Encoder64x0() = default; - ~Encoder64x0() override = default; - - MPCC_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; - - MPCC_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; - - MPCC_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 CompilerKit diff --git a/Headers/AsmKit/CPU/32x0.hpp b/Headers/AsmKit/CPU/32x0.hpp deleted file mode 100644 index 4d66da5..0000000 --- a/Headers/AsmKit/CPU/32x0.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#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]; - 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 kOpcodes32x0 = { - kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. - kAsmOpcodeDecl("br", 0b1110011, 0b001, kAsmJump) // jump to branch - kAsmOpcodeDecl("mr", 0b0100011, 0b101, kAsmImmediate) // move registers - kAsmOpcodeDecl("psh", 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 - -//////////////////////////////// diff --git a/Headers/AsmKit/CPU/64x0.hpp b/Headers/AsmKit/CPU/64x0.hpp deleted file mode 100644 index 974f346..0000000 --- a/Headers/AsmKit/CPU/64x0.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#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("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 - -//////////////////////////////// diff --git a/Headers/AsmKit/CPU/amd64.hpp b/Headers/AsmKit/CPU/amd64.hpp deleted file mode 100644 index 8f7e05c..0000000 --- a/Headers/AsmKit/CPU/amd64.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#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; - -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 15 diff --git a/Headers/AsmKit/CPU/ppc.hpp b/Headers/AsmKit/CPU/ppc.hpp deleted file mode 100644 index c4265da..0000000 --- a/Headers/AsmKit/CPU/ppc.hpp +++ /dev/null @@ -1,1919 +0,0 @@ -#pragma once - -#include - -/// @note Based of: -/// https://opensource.apple.com/source/cctools/cctools-750/as/ppc-opcode.h.auto.html - -/* - * 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 optype -{ - 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 SizeType size_t - -#define VoidPtr void* -#define voidPtr VoidPtr - -#define UIntPtr uintptr_t - -#define Int64 int64_t -#define UInt64 uint64_t - -#define Int32 int -#define UInt32 unsigned - -#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 -#include -#include - -#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 MPCC_COPY_DELETE(KLASS) \ - KLASS& operator=(const KLASS&) = delete; \ - KLASS(const KLASS&) = delete; - -#define MPCC_COPY_DEFAULT(KLASS) \ - KLASS& operator=(const KLASS&) = default; \ - KLASS(const KLASS&) = default; - -#define MPCC_MOVE_DELETE(KLASS) \ - KLASS& operator=(KLASS&&) = delete; \ - KLASS(KLASS&&) = delete; - -#define MPCC_MOVE_DEFAULT(KLASS) \ - KLASS& operator=(KLASS&&) = default; \ - KLASS(KLASS&&) = default; - -#include -#include -#include -#include - -namespace CompilerKit -{ - inline constexpr int BASE_YEAR = 1900; - - inline std::string current_date() noexcept - { - 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) noexcept - { - 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; - } -} // namespace CompilerKit - -#define PACKED __attribute__((packed)) - -typedef char char_type; - -#define kObjectFileExt ".obj" -#define kBinaryFileExt ".bin" - -#define kAsmFileExts \ - { \ - ".64x", ".32x", ".masm", ".s", ".S", ".asm" \ - } - -#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__ */ - -#pragma scalar_storage_order big - endian - -#endif /* ifndef __MPCC_DEFINES_HPP__ */ diff --git a/Headers/ParserKit.hpp b/Headers/ParserKit.hpp deleted file mode 100644 index f77dba9..0000000 --- a/Headers/ParserKit.hpp +++ /dev/null @@ -1,171 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -#include -#include - -namespace ParserKit -{ - using namespace CompilerKit; - - /// @brief Compiler backend, implements a frontend, such as C, C++... - /// See Toolchain, for some examples. - class CompilerBackend - { - public: - explicit CompilerBackend() = default; - virtual ~CompilerBackend() = default; - - MPCC_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 "Invalid Language"; - } - }; - - struct SyntaxLeafList; - struct SyntaxLeafList; - struct CompilerKeyword; - - /// we want to do that because to separate keywords. - enum KeywordKind - { - eKeywordKindNamespace, - eKeywordKindFunctionStart, - eKeywordKindFunctionEnd, - eKeywordKindVariable, - eKeywordKindType, - eKeywordKindExpressionBegin, - eKeywordKindExpressionEnd, - eKeywordKindArgSeparator, - eKeywordKindBodyStart, - eKeywordKindBodyEnd, - eKeywordKindClass, - eKeywordKindPtrAccess, - eKeywordKindAccess, - eKeywordKindIf, - eKeywordKindElse, - eKeywordKindElseIf, - eKeywordKindVariableAssign, - eKeywordKindVariableDec, - eKeywordKindVariableInc, - eKeywordKindConstant, - eKeywordKindTypedef, - eKeywordKindEndInstr, - eKeywordKindSpecifier, - eKeywordKindInvalid, - eKeywordKindReturn, - eKeywordKindCommentInline, - eKeywordKindCommentMultiLineStart, - eKeywordKindCommentMultiLineEnd, - eKeywordKindEq, - eKeywordKindNotEq, - eKeywordKindGreaterEq, - eKeywordKindLessEq, - eKeywordKindPtr, - }; - - /// \brief Compiler keyword information struct. - struct CompilerKeyword - { - std::string keyword_name; - KeywordKind keyword_kind = eKeywordKindInvalid; - }; - struct SyntaxLeafList final - { - struct SyntaxLeaf final - { - Int32 fUserType; -#ifdef __PK_USE_STRUCT_INSTEAD__ - CompilerKeyword fUserData; -#else - std::string fUserData; -#endif - - std::string fUserValue; - struct SyntaxLeaf* fNext; - }; - - std::vector fLeafList; - SizeType fNumLeafs; - - size_t SizeOf() - { - return fNumLeafs; - } - std::vector& 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; - } -} // namespace ParserKit diff --git a/Headers/StdKit/AE.hpp b/Headers/StdKit/AE.hpp deleted file mode 100644 index ebae770..0000000 --- a/Headers/StdKit/AE.hpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * ======================================================== - * - * MPCC - * Copyright SoftwareLabs, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include - -#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; - 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 CompilerKit - -// 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 -{ - /** - * @brief AE Reader protocol - * - */ - class AEReadableProtocol final - { - public: - std::ifstream FP; - - public: - explicit AEReadableProtocol() = default; - ~AEReadableProtocol() = default; - - MPCC_COPY_DELETE(AEReadableProtocol); - - /** - * @brief Read AE record - * - * @param raw the containing buffer - * @param sz it's size (without sizeof(AERecordHeader) added to it.) - * @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 CompilerKit::Utils diff --git a/Headers/StdKit/ELF.hpp b/Headers/StdKit/ELF.hpp deleted file mode 100644 index 4f0d0ae..0000000 --- a/Headers/StdKit/ELF.hpp +++ /dev/null @@ -1,389 +0,0 @@ -#pragma once - -#include -#include - -struct file; - -#ifndef elf_read_implies_exec -/* Executables for which elf_read_implies_exec() returns TRUE will - have the READ_IMPLIES_EXEC personality flag set automatically. - Override in asm/elf.h as needed. */ -#define elf_read_implies_exec(ex, have_pt_gnu_stack) 0 -#endif - -/* 32-bit ELF base types. */ -typedef uint32_t Elf32_Addr; -typedef uint16_t Elf32_Half; -typedef uint32_t Elf32_Off; -typedef int32_t Elf32_Sword; -typedef uint32_t Elf32_Word; - -/* 64-bit ELF base types. */ -typedef uintptr_t Elf64_Addr; -typedef uint16_t Elf64_Half; -typedef int16_t Elf64_SHalf; -typedef uint64_t Elf64_Off; -typedef int32_t Elf64_Sword; -typedef uint32_t Elf64_Word; -typedef uint64_t Elf64_Xword; -typedef int64_t Elf64_Sxword; - -/* These constants are for the segment types stored in the image headers */ -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_TLS 7 /* Thread local storage segment */ -#define PT_LOOS 0x60000000 /* OS-specific */ -#define PT_HIOS 0x6fffffff /* OS-specific */ -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff -#define PT_GNU_EH_FRAME 0x6474e550 - -#define PT_GNU_STACK (PT_LOOS + 0x474e551) - -/* These constants define the different elf file types */ -#define ET_NONE 0 -#define ET_REL 1 -#define ET_EXEC 2 -#define ET_DYN 3 -#define ET_CORE 4 -#define ET_LOPROC 0xff00 -#define ET_HIPROC 0xffff - -/* This is the info that is needed to parse the dynamic section of the file */ -#define DT_NULL 0 -#define DT_NEEDED 1 -#define DT_PLTRELSZ 2 -#define DT_PLTGOT 3 -#define DT_HASH 4 -#define DT_STRTAB 5 -#define DT_SYMTAB 6 -#define DT_RELA 7 -#define DT_RELASZ 8 -#define DT_RELAENT 9 -#define DT_STRSZ 10 -#define DT_SYMENT 11 -#define DT_INIT 12 -#define DT_FINI 13 -#define DT_SONAME 14 -#define DT_RPATH 15 -#define DT_SYMBOLIC 16 -#define DT_REL 17 -#define DT_RELSZ 18 -#define DT_RELENT 19 -#define DT_PLTREL 20 -#define DT_DEBUG 21 -#define DT_TEXTREL 22 -#define DT_JMPREL 23 -#define DT_ENCODING 32 -#define OLD_DT_LOOS 0x60000000 -#define DT_LOOS 0x6000000d -#define DT_HIOS 0x6ffff000 -#define DT_VALRNGLO 0x6ffffd00 -#define DT_VALRNGHI 0x6ffffdff -#define DT_ADDRRNGLO 0x6ffffe00 -#define DT_ADDRRNGHI 0x6ffffeff -#define DT_VERSYM 0x6ffffff0 -#define DT_RELACOUNT 0x6ffffff9 -#define DT_RELCOUNT 0x6ffffffa -#define DT_FLAGS_1 0x6ffffffb -#define DT_VERDEF 0x6ffffffc -#define DT_VERDEFNUM 0x6ffffffd -#define DT_VERNEED 0x6ffffffe -#define DT_VERNEEDNUM 0x6fffffff -#define OLD_DT_HIOS 0x6fffffff -#define DT_LOPROC 0x70000000 -#define DT_HIPROC 0x7fffffff - -/* This info is needed when parsing the symbol table */ -#define STB_LOCAL 0 -#define STB_GLOBAL 1 -#define STB_WEAK 2 - -#define STT_NOTYPE 0 -#define STT_OBJECT 1 -#define STT_FUNC 2 -#define STT_SECTION 3 -#define STT_FILE 4 -#define STT_COMMON 5 -#define STT_TLS 6 - -#define ELF_ST_BIND(x) ((x) >> 4) -#define ELF_ST_TYPE(x) (((unsigned int)x) & 0xf) -#define ELF32_ST_BIND(x) ELF_ST_BIND(x) -#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) -#define ELF64_ST_BIND(x) ELF_ST_BIND(x) -#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x) - -typedef struct dynamic -{ - Elf32_Sword d_tag; - union { - Elf32_Sword d_val; - Elf32_Addr d_ptr; - } d_un; -} Elf32_Dyn; - -typedef struct -{ - Elf64_Sxword d_tag; /* entry tag value */ - union { - Elf64_Xword d_val; - Elf64_Addr d_ptr; - } d_un; -} Elf64_Dyn; - -/* The following are used with relocations */ -#define ELF32_R_SYM(x) ((x) >> 8) -#define ELF32_R_TYPE(x) ((x)&0xff) - -#define ELF64_R_SYM(i) ((i) >> 32) -#define ELF64_R_TYPE(i) ((i)&0xffffffff) - -typedef struct elf32_rel -{ - Elf32_Addr r_offset; - Elf32_Word r_info; -} Elf32_Rel; - -typedef struct elf64_rel -{ - Elf64_Addr r_offset; /* Location at which to apply the action */ - Elf64_Xword r_info; /* index and type of relocation */ -} Elf64_Rel; - -typedef struct elf32_rela -{ - Elf32_Addr r_offset; - Elf32_Word r_info; - Elf32_Sword r_addend; -} Elf32_Rela; - -typedef struct elf64_rela -{ - Elf64_Addr r_offset; /* Location at which to apply the action */ - Elf64_Xword r_info; /* index and type of relocation */ - Elf64_Sxword r_addend; /* Constant addend used to compute value */ -} Elf64_Rela; - -typedef struct elf32_sym -{ - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; - unsigned char st_info; - unsigned char st_other; - Elf32_Half st_shndx; -} Elf32_Sym; - -typedef struct elf64_sym -{ - Elf64_Word st_name; /* Symbol name, index in string tbl */ - unsigned char st_info; /* Type and binding attributes */ - unsigned char st_other; /* No defined meaning, 0 */ - Elf64_Half st_shndx; /* Associated section index */ - Elf64_Addr st_value; /* Value of the symbol */ - Elf64_Xword st_size; /* Associated symbol size */ -} Elf64_Sym; - -#define EI_NIDENT 16 - -typedef struct elf32_hdr -{ - unsigned char e_ident[EI_NIDENT]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; /* Entry point */ - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -} Elf32_Ehdr; - -typedef struct elf64_hdr -{ - unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ - Elf64_Half e_type; - Elf64_Half e_machine; - Elf64_Word e_version; - Elf64_Addr e_entry; /* Entry point virtual address */ - Elf64_Off e_phoff; /* Program header table file offset */ - Elf64_Off e_shoff; /* Section header table file offset */ - Elf64_Word e_flags; - Elf64_Half e_ehsize; - Elf64_Half e_phentsize; - Elf64_Half e_phnum; - Elf64_Half e_shentsize; - Elf64_Half e_shnum; - Elf64_Half e_shstrndx; -} Elf64_Ehdr; - -/* These constants define the permissions on sections in the program - header, p_flags. */ -#define PF_R 0x4 -#define PF_W 0x2 -#define PF_X 0x1 - -typedef struct elf32_phdr -{ - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; -} Elf32_Phdr; - -typedef struct elf64_phdr -{ - Elf64_Word p_type; - Elf64_Word p_flags; - Elf64_Off p_offset; /* Segment file offset */ - Elf64_Addr p_vaddr; /* Segment virtual address */ - Elf64_Addr p_paddr; /* Segment physical address */ - Elf64_Xword p_filesz; /* Segment size in file */ - Elf64_Xword p_memsz; /* Segment size in memory */ - Elf64_Xword p_align; /* Segment alignment, file & memory */ -} Elf64_Phdr; - -/* sh_type */ -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 -#define SHT_NUM 12 -#define SHT_LOPROC 0x70000000 -#define SHT_HIPROC 0x7fffffff -#define SHT_LOUSER 0x80000000 -#define SHT_HIUSER 0xffffffff - -/* sh_flags */ -#define SHF_WRITE 0x1 -#define SHF_ALLOC 0x2 -#define SHF_EXECINSTR 0x4 -#define SHF_MASKPROC 0xf0000000 - -/* special section indexes */ -#define SHN_UNDEF 0 -#define SHN_LORESERVE 0xff00 -#define SHN_LOPROC 0xff00 -#define SHN_HIPROC 0xff1f -#define SHN_ABS 0xfff1 -#define SHN_COMMON 0xfff2 -#define SHN_HIRESERVE 0xffff - -typedef struct -{ - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -} Elf32_Shdr; - -typedef struct elf64_shdr -{ - Elf64_Word sh_name; /* Section name, index in string tbl */ - Elf64_Word sh_type; /* Type of section */ - Elf64_Xword sh_flags; /* Miscellaneous section attributes */ - Elf64_Addr sh_addr; /* Section virtual addr at execution */ - Elf64_Off sh_offset; /* Section file offset */ - Elf64_Xword sh_size; /* Size of section in bytes */ - Elf64_Word sh_link; /* Index of another section */ - Elf64_Word sh_info; /* Additional section information */ - Elf64_Xword sh_addralign; /* Section alignment */ - Elf64_Xword sh_entsize; /* Entry size if section holds table */ -} Elf64_Shdr; - -#define EI_MAG0 0 /* e_ident[] indexes */ -#define EI_MAG1 1 -#define EI_MAG2 2 -#define EI_MAG3 3 -#define EI_CLASS 4 -#define EI_DATA 5 -#define EI_VERSION 6 -#define EI_OSABI 7 -#define EI_PAD 8 - -#define ELFMAG0 0x7f /* EI_MAG */ -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -#define ELFCLASSNONE 0 /* EI_CLASS */ -#define ELFCLASS32 1 -#define ELFCLASS64 2 -#define ELFCLASSNUM 3 - -#define ELFDATANONE 0 /* e_ident[EI_DATA] */ -#define ELFDATA2LSB 1 -#define ELFDATA2MSB 2 - -#define EV_NONE 0 /* e_version, EI_VERSION */ -#define EV_CURRENT 1 -#define EV_NUM 2 - -#define ELFOSABI_NONE 0 -#define ELFOSABI_LINUX 3 - -#ifndef ELF_OSABI -#define ELF_OSABI ELFOSABI_NONE -#endif - -/* Notes used in ET_CORE */ -#define NT_PRSTATUS 1 -#define NT_PRFPREG 2 -#define NT_PRPSINFO 3 -#define NT_TASKSTRUCT 4 -#define NT_AUXV 6 -#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ -#define NT_PPC_VMX 0x100 /* POWER Altivec/VMX registers */ -#define NT_PPC_SPE 0x101 /* POWER SPE/EVR registers */ -#define NT_PPC_VSX 0x102 /* POWER VSX registers */ -#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ -#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ -#define NT_PRXSTATUS 0x300 /* s390 upper register halves */ - -/* Note header in a PT_NOTE section */ -typedef struct elf32_note -{ - Elf32_Word n_namesz; /* Name size */ - Elf32_Word n_descsz; /* Content size */ - Elf32_Word n_type; /* Content type */ -} Elf32_Nhdr; - -/* Note header in a PT_NOTE section */ -typedef struct elf64_note -{ - Elf64_Word n_namesz; /* Name size */ - Elf64_Word n_descsz; /* Content size */ - Elf64_Word n_type; /* Content type */ -} Elf64_Nhdr; diff --git a/Headers/StdKit/ErrorID.hpp b/Headers/StdKit/ErrorID.hpp deleted file mode 100644 index ef1f778..0000000 --- a/Headers/StdKit/ErrorID.hpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * ======================================================== - * - * CompilerKit - * Copyright SoftwareLabs, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -#define MPCC_EXEC_ERROR -30 -#define MPCC_FILE_NOT_FOUND -31 -#define MPCC_DIR_NOT_FOUND -32 -#define MPCC_FILE_EXISTS -33 -#define MPCC_TOO_LONG -34 -#define MPCC_INVALID_DATA -35 -#define MPCC_UNIMPLEMENTED -36 -#define MPCC_FAT_ERROR -37 diff --git a/Headers/StdKit/ErrorOr.hpp b/Headers/StdKit/ErrorOr.hpp deleted file mode 100644 index d61f3e9..0000000 --- a/Headers/StdKit/ErrorOr.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * ======================================================== - * - * CompilerKit - * Copyright SoftwareLabs, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -namespace CompilerKit -{ - 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 CompilerKit diff --git a/Headers/StdKit/PEF.hpp b/Headers/StdKit/PEF.hpp deleted file mode 100644 index 88c20ea..0000000 --- a/Headers/StdKit/PEF.hpp +++ /dev/null @@ -1,132 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -#include - -// @file PEF.hpp -// @brief Preferred Executable Format - -#define kPefMagic "Joy!" -#define kPefMagicFat "yoJ!" - -#define kPefExt ".exec" -#define kPefDylibExt ".lib" -#define kPefLibExt ".slib" -#define kPefObjectExt ".obj" -#define kPefDebugExt ".dbg" - -#define kPefMagicLen 5 - -#define kPefVersion 2 -#define kPefNameLen 255 - -#define kPefBaseOrigin (0x1000000) - -#define kPefStart "__ImageStart" - -namespace CompilerKit -{ - enum - { - kPefArchIntel86S = 100, - kPefArchAMD64, - kPefArchRISCV, - kPefArch64000, /* 64x0 RISC architecture. */ - kPefArch32000, - kPefArchPowerPC, /* 64-bit POWER architecture. */ - kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1, - kPefArchInvalid = 0xFF, - }; - - enum - { - kPefSubArchAMD, - kPefSubArchIntel, - kPefSubArchARM, - kPefSubArchIBM, - }; - - enum - { - kPefKindExec = 1, /* .exe */ - kPefKindSharedObject = 2, /* .lib */ - 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; - - /* 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; - - enum - { - kPefCode = 0xC, - kPefData = 0xD, - kPefZero = 0xE, - kPefLinkerID = 0x1, - kPefCount = 4, - kPefInvalid = 0xFF, - }; -} // namespace CompilerKit - -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/Headers/StdKit/Ref.hpp b/Headers/StdKit/Ref.hpp deleted file mode 100644 index d13f97c..0000000 --- a/Headers/StdKit/Ref.hpp +++ /dev/null @@ -1,91 +0,0 @@ - -/* - * ======================================================== - * - * CompilerKit - * Copyright SoftwareLabs, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -namespace CompilerKit -{ - // @author Amlal EL Mahrouss - // @brief Reference class, refers to a pointer of data in static memory. - template - 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 - class NonNullRef final - { - public: - NonNullRef() = delete; - NonNullRef(nullPtr) = 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 CompilerKit diff --git a/Headers/StdKit/String.hpp b/Headers/StdKit/String.hpp deleted file mode 100644 index d4048ee..0000000 --- a/Headers/StdKit/String.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * ======================================================== - * - * CompilerKit - * Copyright SoftwareLabs, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -namespace CompilerKit -{ - /** - * @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 char[Sz]; - assert(m_Data); - } - - ~StringView() noexcept - { - if (m_Data) - { - memset(m_Data, 0, m_Sz); - delete[] m_Data; - - m_Data = nullptr; - } - } - - MPCC_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: - char* 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 CompilerKit diff --git a/Headers/StdKit/XCOFF.hxx b/Headers/StdKit/XCOFF.hxx deleted file mode 100644 index d339daa..0000000 --- a/Headers/StdKit/XCOFF.hxx +++ /dev/null @@ -1,41 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - - File: XCOFF.hpp - Purpose: XCOFF for NewOS. - - 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 CompilerKit -{ - /// @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 CompilerKit - -#endif // ifndef __XCOFF__ \ No newline at end of file diff --git a/Headers/UUID.hpp b/Headers/UUID.hpp deleted file mode 100644 index 00b153b..0000000 --- a/Headers/UUID.hpp +++ /dev/null @@ -1,983 +0,0 @@ -#ifndef STDUUID_H -#define STDUUID_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus - -#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) -#define LIBUUID_CPP20_OR_GREATER -#endif - -#endif - -#ifdef LIBUUID_CPP20_OR_GREATER -#include -#else -#include -#endif - -#ifdef _WIN32 - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#ifdef UUID_SYSTEM_GENERATOR -#include -#endif - -#ifdef UUID_TIME_GENERATOR -#include -#pragma comment(lib, "IPHLPAPI.lib") -#endif - -#elif defined(__linux__) || defined(__unix__) - -#ifdef UUID_SYSTEM_GENERATOR -#include -#endif - -#elif defined(__APPLE__) - -#ifdef UUID_SYSTEM_GENERATOR -#include -#endif - -#endif - -namespace uuids -{ -#ifdef __cpp_lib_span - template - using span = std::span; -#else - template - using span = gsl::span; -#endif - - namespace detail - { - template - [[nodiscard]] constexpr inline unsigned char hex2char(TChar const ch) noexcept - { - if (ch >= static_cast('0') && ch <= static_cast('9')) - return static_cast(ch - static_cast('0')); - if (ch >= static_cast('a') && ch <= static_cast('f')) - return static_cast(10 + ch - static_cast('a')); - if (ch >= static_cast('A') && ch <= static_cast('F')) - return static_cast(10 + ch - static_cast('A')); - return 0; - } - - template - [[nodiscard]] constexpr inline bool is_hex(TChar const ch) noexcept - { - return (ch >= static_cast('0') && ch <= static_cast('9')) || - (ch >= static_cast('a') && ch <= static_cast('f')) || - (ch >= static_cast('A') && ch <= static_cast('F')); - } - - template - [[nodiscard]] constexpr std::basic_string_view to_string_view( - TChar const* str) noexcept - { - if (str) - return str; - return {}; - } - - template - [[nodiscard]] constexpr std::basic_string_view - to_string_view(StringType const& str) noexcept - { - return str; - } - - class sha1 - { - public: - using digest32_t = uint32_t[5]; - using digest8_t = uint8_t[20]; - - static constexpr unsigned int block_bytes = 64; - - [[nodiscard]] inline static uint32_t left_rotate( - uint32_t value, size_t const count) noexcept - { - return (value << count) ^ (value >> (32 - count)); - } - - sha1() - { - reset(); - } - - void reset() noexcept - { - m_digest[0] = 0x67452301; - m_digest[1] = 0xEFCDAB89; - m_digest[2] = 0x98BADCFE; - m_digest[3] = 0x10325476; - m_digest[4] = 0xC3D2E1F0; - m_blockByteIndex = 0; - m_byteCount = 0; - } - - void process_byte(uint8_t octet) - { - this->m_block[this->m_blockByteIndex++] = octet; - ++this->m_byteCount; - if (m_blockByteIndex == block_bytes) - { - this->m_blockByteIndex = 0; - process_block(); - } - } - - void process_block(void const* const start, void const* const end) - { - const uint8_t* begin = static_cast(start); - const uint8_t* finish = static_cast(end); - while (begin != finish) - { - process_byte(*begin); - begin++; - } - } - - void process_bytes(void const* const data, size_t const len) - { - const uint8_t* block = static_cast(data); - process_block(block, block + len); - } - - uint32_t const* get_digest(digest32_t digest) - { - size_t const bitCount = this->m_byteCount * 8; - process_byte(0x80); - if (this->m_blockByteIndex > 56) - { - while (m_blockByteIndex != 0) - { - process_byte(0); - } - while (m_blockByteIndex < 56) - { - process_byte(0); - } - } - else - { - while (m_blockByteIndex < 56) - { - process_byte(0); - } - } - process_byte(0); - process_byte(0); - process_byte(0); - process_byte(0); - process_byte(static_cast((bitCount >> 24) & 0xFF)); - process_byte(static_cast((bitCount >> 16) & 0xFF)); - process_byte(static_cast((bitCount >> 8) & 0xFF)); - process_byte(static_cast((bitCount)&0xFF)); - - memcpy(digest, m_digest, 5 * sizeof(uint32_t)); - return digest; - } - - uint8_t const* get_digest_bytes(digest8_t digest) - { - digest32_t d32; - get_digest(d32); - size_t di = 0; - digest[di++] = static_cast(d32[0] >> 24); - digest[di++] = static_cast(d32[0] >> 16); - digest[di++] = static_cast(d32[0] >> 8); - digest[di++] = static_cast(d32[0] >> 0); - - digest[di++] = static_cast(d32[1] >> 24); - digest[di++] = static_cast(d32[1] >> 16); - digest[di++] = static_cast(d32[1] >> 8); - digest[di++] = static_cast(d32[1] >> 0); - - digest[di++] = static_cast(d32[2] >> 24); - digest[di++] = static_cast(d32[2] >> 16); - digest[di++] = static_cast(d32[2] >> 8); - digest[di++] = static_cast(d32[2] >> 0); - - digest[di++] = static_cast(d32[3] >> 24); - digest[di++] = static_cast(d32[3] >> 16); - digest[di++] = static_cast(d32[3] >> 8); - digest[di++] = static_cast(d32[3] >> 0); - - digest[di++] = static_cast(d32[4] >> 24); - digest[di++] = static_cast(d32[4] >> 16); - digest[di++] = static_cast(d32[4] >> 8); - digest[di++] = static_cast(d32[4] >> 0); - - return digest; - } - - private: - void process_block() - { - uint32_t w[80]; - for (size_t i = 0; i < 16; i++) - { - w[i] = static_cast(m_block[i * 4 + 0] << 24); - w[i] |= static_cast(m_block[i * 4 + 1] << 16); - w[i] |= static_cast(m_block[i * 4 + 2] << 8); - w[i] |= static_cast(m_block[i * 4 + 3]); - } - for (size_t i = 16; i < 80; i++) - { - w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1); - } - - uint32_t a = m_digest[0]; - uint32_t b = m_digest[1]; - uint32_t c = m_digest[2]; - uint32_t d = m_digest[3]; - uint32_t e = m_digest[4]; - - for (std::size_t i = 0; i < 80; ++i) - { - uint32_t f = 0; - uint32_t k = 0; - - if (i < 20) - { - f = (b & c) | (~b & d); - k = 0x5A827999; - } - else if (i < 40) - { - f = b ^ c ^ d; - k = 0x6ED9EBA1; - } - else if (i < 60) - { - f = (b & c) | (b & d) | (c & d); - k = 0x8F1BBCDC; - } - else - { - f = b ^ c ^ d; - k = 0xCA62C1D6; - } - uint32_t temp = left_rotate(a, 5) + f + e + k + w[i]; - e = d; - d = c; - c = left_rotate(b, 30); - b = a; - a = temp; - } - - m_digest[0] += a; - m_digest[1] += b; - m_digest[2] += c; - m_digest[3] += d; - m_digest[4] += e; - } - - private: - digest32_t m_digest; - uint8_t m_block[64]; - size_t m_blockByteIndex; - size_t m_byteCount; - }; - - template - inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000"; - - template <> - inline constexpr wchar_t empty_guid[37] = - L"00000000-0000-0000-0000-000000000000"; - - template - inline constexpr CharT guid_encoder[17] = "0123456789abcdef"; - - template <> - inline constexpr wchar_t guid_encoder[17] = L"0123456789abcdef"; - } // namespace detail - - // -------------------------------------------------------------------------------------------------------------------------- - // UUID format https://tools.ietf.org/html/rfc4122 - // -------------------------------------------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------------------------------------------- - // Field NDR Data Type Octet # Note - // -------------------------------------------------------------------------------------------------------------------------- - // time_low unsigned long 0 - 3 The low field - // of the timestamp. time_mid unsigned short 4 - 5 - // The middle field of the timestamp. time_hi_and_version unsigned - // short 6 - 7 The high field of the timestamp multiplexed - // with the version number. clock_seq_hi_and_reserved unsigned small 8 - // The high field of the clock sequence multiplexed with the variant. - // clock_seq_low unsigned small 9 The low - // field of the clock sequence. node character 10 - // - 15 The spatially unique node identifier. - // -------------------------------------------------------------------------------------------------------------------------- - // 0 1 2 3 - // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | time_low | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | time_mid | time_hi_and_version | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // |clk_seq_hi_res | clk_seq_low | node (0-1) | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | node (2-5) | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - // -------------------------------------------------------------------------------------------------------------------------- - // enumerations - // -------------------------------------------------------------------------------------------------------------------------- - - // indicated by a bit pattern in octet 8, marked with N in - // xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx - enum class uuid_variant - { - // NCS backward compatibility (with the obsolete Apollo Network Computing - // System 1.5 UUID format) N bit pattern: 0xxx > the first 6 octets of the - // UUID are a 48-bit timestamp (the number of 4 microsecond units of time - // since 1 Jan 1980 UTC); > the next 2 octets are reserved; > the next octet - // is the "address family"; > the final 7 octets are a 56-bit host ID in the - // form specified by the address family - ncs, - - // RFC 4122/DCE 1.1 - // N bit pattern: 10xx - // > big-endian byte order - rfc, - - // Microsoft Corporation backward compatibility - // N bit pattern: 110x - // > little endian byte order - // > formely used in the Component Object Model (COM) library - microsoft, - - // reserved for possible future definition - // N bit pattern: 111x - reserved - }; - - // indicated by a bit pattern in octet 6, marked with M in - // xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx - enum class uuid_version - { - none = 0, // only possible for nil or invalid uuids - time_based = 1, // The time-based version specified in RFC 4122 - dce_security = 2, // DCE Security version, with embedded POSIX UIDs. - name_based_md5 = - 3, // The name-based version specified in RFS 4122 with MD5 hashing - random_number_based = 4, // The randomly or pseudo-randomly generated version - // specified in RFS 4122 - name_based_sha1 = - 5 // The name-based version specified in RFS 4122 with SHA1 hashing - }; - - // Forward declare uuid & to_string so that we can declare to_string as a friend - // later. - class uuid; - template , class Allocator = std::allocator> - std::basic_string to_string(uuid const& id); - - // -------------------------------------------------------------------------------------------------------------------------- - // uuid class - // -------------------------------------------------------------------------------------------------------------------------- - class uuid - { - public: - using value_type = uint8_t; - - constexpr uuid() noexcept = default; - - uuid(value_type (&arr)[16]) noexcept - { - std::copy(std::cbegin(arr), std::cend(arr), std::begin(data)); - } - - constexpr uuid(std::array const& arr) noexcept - : data{arr} - { - } - - explicit uuid(span bytes) - { - std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data)); - } - - template - explicit uuid(ForwardIterator first, ForwardIterator last) - { - if (std::distance(first, last) == 16) - std::copy(first, last, std::begin(data)); - } - - [[nodiscard]] constexpr uuid_variant variant() const noexcept - { - if ((data[8] & 0x80) == 0x00) - return uuid_variant::ncs; - else if ((data[8] & 0xC0) == 0x80) - return uuid_variant::rfc; - else if ((data[8] & 0xE0) == 0xC0) - return uuid_variant::microsoft; - else - return uuid_variant::reserved; - } - - [[nodiscard]] constexpr uuid_version version() const noexcept - { - if ((data[6] & 0xF0) == 0x10) - return uuid_version::time_based; - else if ((data[6] & 0xF0) == 0x20) - return uuid_version::dce_security; - else if ((data[6] & 0xF0) == 0x30) - return uuid_version::name_based_md5; - else if ((data[6] & 0xF0) == 0x40) - return uuid_version::random_number_based; - else if ((data[6] & 0xF0) == 0x50) - return uuid_version::name_based_sha1; - else - return uuid_version::none; - } - - [[nodiscard]] constexpr bool is_nil() const noexcept - { - for (size_t i = 0; i < data.size(); ++i) - if (data[i] != 0) - return false; - return true; - } - - void swap(uuid& other) noexcept - { - data.swap(other.data); - } - - [[nodiscard]] inline span as_bytes() const - { - return span( - reinterpret_cast(data.data()), 16); - } - - template - [[nodiscard]] constexpr static bool is_valid_uuid( - StringType const& in_str) noexcept - { - auto str = detail::to_string_view(in_str); - bool firstDigit = true; - size_t hasBraces = 0; - size_t index = 0; - - if (str.empty()) - return false; - - if (str.front() == '{') - hasBraces = 1; - if (hasBraces && str.back() != '}') - return false; - - for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) - { - if (str[i] == '-') - continue; - - if (index >= 16 || !detail::is_hex(str[i])) - { - return false; - } - - if (firstDigit) - { - firstDigit = false; - } - else - { - index++; - firstDigit = true; - } - } - - if (index < 16) - { - return false; - } - - return true; - } - - template - [[nodiscard]] constexpr static std::optional from_string( - StringType const& in_str) noexcept - { - auto str = detail::to_string_view(in_str); - bool firstDigit = true; - size_t hasBraces = 0; - size_t index = 0; - - std::array data{{0}}; - - if (str.empty()) - return {}; - - if (str.front() == '{') - hasBraces = 1; - if (hasBraces && str.back() != '}') - return {}; - - for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) - { - if (str[i] == '-') - continue; - - if (index >= 16 || !detail::is_hex(str[i])) - { - return {}; - } - - if (firstDigit) - { - data[index] = static_cast(detail::hex2char(str[i]) << 4); - firstDigit = false; - } - else - { - data[index] = - static_cast(data[index] | detail::hex2char(str[i])); - index++; - firstDigit = true; - } - } - - if (index < 16) - { - return {}; - } - - return uuid{data}; - } - - private: - std::array data{{0}}; - - friend bool operator==(uuid const& lhs, uuid const& rhs) noexcept; - friend bool operator<(uuid const& lhs, uuid const& rhs) noexcept; - - template - friend std::basic_ostream& operator<<( - std::basic_ostream& s, uuid const& id); - - template - friend std::basic_string to_string(uuid const& id); - - friend std::hash; - }; - - // -------------------------------------------------------------------------------------------------------------------------- - // operators and non-member functions - // -------------------------------------------------------------------------------------------------------------------------- - - [[nodiscard]] inline bool operator==(uuid const& lhs, - uuid const& rhs) noexcept - { - return lhs.data == rhs.data; - } - - [[nodiscard]] inline bool operator!=(uuid const& lhs, - uuid const& rhs) noexcept - { - return !(lhs == rhs); - } - - [[nodiscard]] inline bool operator<(uuid const& lhs, uuid const& rhs) noexcept - { - return lhs.data < rhs.data; - } - - template - [[nodiscard]] inline std::basic_string to_string( - uuid const& id) - { - std::basic_string uustr{detail::empty_guid}; - - for (size_t i = 0, index = 0; i < 36; ++i) - { - if (i == 8 || i == 13 || i == 18 || i == 23) - { - continue; - } - uustr[i] = detail::guid_encoder[id.data[index] >> 4 & 0x0f]; - uustr[++i] = detail::guid_encoder[id.data[index] & 0x0f]; - index++; - } - - return uustr; - } - - template - std::basic_ostream& operator<<( - std::basic_ostream& s, uuid const& id) - { - s << to_string(id); - return s; - } - - inline void swap(uuids::uuid& lhs, uuids::uuid& rhs) noexcept - { - lhs.swap(rhs); - } - - // -------------------------------------------------------------------------------------------------------------------------- - // namespace IDs that could be used for generating name-based uuids - // -------------------------------------------------------------------------------------------------------------------------- - - // Name string is a fully-qualified domain name - static uuid uuid_namespace_dns{{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // Name string is a URL - static uuid uuid_namespace_url{{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // Name string is an ISO OID (See https://oidref.com/, - // https://en.wikipedia.org/wiki/Object_identifier) - static uuid uuid_namespace_oid{{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // Name string is an X.500 DN, in DER or a text output format (See - // https://en.wikipedia.org/wiki/X.500, - // https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One) - static uuid uuid_namespace_x500{{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // -------------------------------------------------------------------------------------------------------------------------- - // uuid generators - // -------------------------------------------------------------------------------------------------------------------------- - -#ifdef UUID_SYSTEM_GENERATOR - class uuid_system_generator - { - public: - using result_type = uuid; - - uuid operator()() - { -#ifdef _WIN32 - - GUID newId; - HRESULT hr = ::CoCreateGuid(&newId); - - if (FAILED(hr)) - { - throw std::system_error(hr, std::system_category(), - "CoCreateGuid failed"); - } - - std::array bytes = { - {static_cast((newId.Data1 >> 24) & 0xFF), - static_cast((newId.Data1 >> 16) & 0xFF), - static_cast((newId.Data1 >> 8) & 0xFF), - static_cast((newId.Data1) & 0xFF), - - (unsigned char)((newId.Data2 >> 8) & 0xFF), - (unsigned char)((newId.Data2) & 0xFF), - - (unsigned char)((newId.Data3 >> 8) & 0xFF), - (unsigned char)((newId.Data3) & 0xFF), - - newId.Data4[0], newId.Data4[1], newId.Data4[2], newId.Data4[3], - newId.Data4[4], newId.Data4[5], newId.Data4[6], newId.Data4[7]}}; - - return uuid{std::begin(bytes), std::end(bytes)}; - -#elif defined(__linux__) || defined(__unix__) - - uuid_t id; - uuid_generate(id); - - std::array bytes = {{id[0], id[1], id[2], id[3], id[4], id[5], - id[6], id[7], id[8], id[9], id[10], - id[11], id[12], id[13], id[14], id[15]}}; - - return uuid{std::begin(bytes), std::end(bytes)}; - -#elif defined(__APPLE__) - auto newId = CFUUIDCreate(NULL); - auto bytes = CFUUIDGetUUIDBytes(newId); - CFRelease(newId); - - std::array arrbytes = { - {bytes.byte0, bytes.byte1, bytes.byte2, bytes.byte3, bytes.byte4, - bytes.byte5, bytes.byte6, bytes.byte7, bytes.byte8, bytes.byte9, - bytes.byte10, bytes.byte11, bytes.byte12, bytes.byte13, bytes.byte14, - bytes.byte15}}; - return uuid{std::begin(arrbytes), std::end(arrbytes)}; -#else - return uuid{}; -#endif - } - }; -#endif - - template - class basic_uuid_random_generator - { - public: - using engine_type = UniformRandomNumberGenerator; - - explicit basic_uuid_random_generator(engine_type& gen) - : generator(&gen, [](auto) {}) - { - } - explicit basic_uuid_random_generator(engine_type* gen) - : generator(gen, [](auto) {}) - { - } - - [[nodiscard]] uuid operator()() - { - alignas(uint32_t) uint8_t bytes[16]; - for (int i = 0; i < 16; i += 4) - *reinterpret_cast(bytes + i) = distribution(*generator); - - // variant must be 10xxxxxx - bytes[8] &= 0xBF; - bytes[8] |= 0x80; - - // version must be 0100xxxx - bytes[6] &= 0x4F; - bytes[6] |= 0x40; - - return uuid{std::begin(bytes), std::end(bytes)}; - } - - private: - std::uniform_int_distribution distribution; - std::shared_ptr generator; - }; - - using uuid_random_generator = basic_uuid_random_generator; - - class uuid_name_generator - { - public: - explicit uuid_name_generator(uuid const& namespace_uuid) noexcept - : nsuuid(namespace_uuid) - { - } - - template - [[nodiscard]] uuid operator()(StringType const& name) - { - reset(); - process_characters(detail::to_string_view(name)); - return make_uuid(); - } - - private: - void reset() - { - hasher.reset(); - std::byte bytes[16]; - auto nsbytes = nsuuid.as_bytes(); - std::copy(std::cbegin(nsbytes), std::cend(nsbytes), bytes); - hasher.process_bytes(bytes, 16); - } - - template - void process_characters(std::basic_string_view const str) - { - for (uint32_t c : str) - { - hasher.process_byte(static_cast(c & 0xFF)); - if constexpr (!std::is_same_v) - { - hasher.process_byte(static_cast((c >> 8) & 0xFF)); - hasher.process_byte(static_cast((c >> 16) & 0xFF)); - hasher.process_byte(static_cast((c >> 24) & 0xFF)); - } - } - } - - [[nodiscard]] uuid make_uuid() - { - detail::sha1::digest8_t digest; - hasher.get_digest_bytes(digest); - - // variant must be 0b10xxxxxx - digest[8] &= 0xBF; - digest[8] |= 0x80; - - // version must be 0b0101xxxx - digest[6] &= 0x5F; - digest[6] |= 0x50; - - return uuid{digest, digest + 16}; - } - - private: - uuid nsuuid; - detail::sha1 hasher; - }; - -#ifdef UUID_TIME_GENERATOR - // !!! DO NOT USE THIS IN PRODUCTION - // this implementation is unreliable for good uuids - class uuid_time_generator - { - using mac_address = std::array; - - std::optional device_address; - - [[nodiscard]] bool get_mac_address() - { - if (device_address.has_value()) - { - return true; - } - -#ifdef _WIN32 - DWORD len = 0; - auto ret = GetAdaptersInfo(nullptr, &len); - if (ret != ERROR_BUFFER_OVERFLOW) - return false; - std::vector buf(len); - auto pips = reinterpret_cast(&buf.front()); - ret = GetAdaptersInfo(pips, &len); - if (ret != ERROR_SUCCESS) - return false; - mac_address addr; - std::copy(pips->Address, pips->Address + 6, std::begin(addr)); - device_address = addr; -#endif - - return device_address.has_value(); - } - - [[nodiscard]] long long get_time_intervals() - { - auto start = std::chrono::system_clock::from_time_t(time_t(-12219292800)); - auto diff = std::chrono::system_clock::now() - start; - auto ns = - std::chrono::duration_cast(diff).count(); - return ns / 100; - } - - [[nodiscard]] static unsigned short get_clock_sequence() - { - static std::mt19937 clock_gen(std::random_device{}()); - static std::uniform_int_distribution clock_dis; - static std::atomic_ushort clock_sequence = clock_dis(clock_gen); - return clock_sequence++; - } - - public: - [[nodiscard]] uuid operator()() - { - if (get_mac_address()) - { - std::array data; - - auto tm = get_time_intervals(); - - auto clock_seq = get_clock_sequence(); - - auto ptm = reinterpret_cast(&tm); - - memcpy(&data[0], ptm + 4, 4); - memcpy(&data[4], ptm + 2, 2); - memcpy(&data[6], ptm, 2); - - memcpy(&data[8], &clock_seq, 2); - - // variant must be 0b10xxxxxx - data[8] &= 0xBF; - data[8] |= 0x80; - - // version must be 0b0001xxxx - data[6] &= 0x1F; - data[6] |= 0x10; - - memcpy(&data[10], &device_address.value()[0], 6); - - return uuids::uuid{std::cbegin(data), std::cend(data)}; - } - - return {}; - } - }; -#endif -} // namespace uuids - -namespace std -{ - template <> - struct hash - { - using argument_type = uuids::uuid; - using result_type = std::size_t; - - [[nodiscard]] result_type operator()(argument_type const& uuid) const - { -#ifdef UUID_HASH_STRING_BASED - std::hash hasher; - return static_cast(hasher(uuids::to_string(uuid))); -#else - uint64_t l = static_cast(uuid.data[0]) << 56 | - static_cast(uuid.data[1]) << 48 | - static_cast(uuid.data[2]) << 40 | - static_cast(uuid.data[3]) << 32 | - static_cast(uuid.data[4]) << 24 | - static_cast(uuid.data[5]) << 16 | - static_cast(uuid.data[6]) << 8 | - static_cast(uuid.data[7]); - uint64_t h = static_cast(uuid.data[8]) << 56 | - static_cast(uuid.data[9]) << 48 | - static_cast(uuid.data[10]) << 40 | - static_cast(uuid.data[11]) << 32 | - static_cast(uuid.data[12]) << 24 | - static_cast(uuid.data[13]) << 16 | - static_cast(uuid.data[14]) << 8 | - static_cast(uuid.data[15]); - - if constexpr (sizeof(result_type) > 4) - { - return result_type(l ^ h); - } - else - { - uint64_t hash64 = l ^ h; - return result_type(uint32_t(hash64 >> 32) ^ uint32_t(hash64)); - } -#endif - } - }; -} // namespace std - -#endif /* STDUUID_H */ \ No newline at end of file diff --git a/Headers/Version.hxx b/Headers/Version.hxx deleted file mode 100644 index 377a688..0000000 --- a/Headers/Version.hxx +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#define kDistVersion "v1.20" diff --git a/SDK/__mpcc_alloca.hxx b/SDK/__mpcc_alloca.hxx deleted file mode 100644 index a1c638e..0000000 --- a/SDK/__mpcc_alloca.hxx +++ /dev/null @@ -1,15 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -typedef void* ptr_type; -typedef __SIZE_TYPE__ size_type; - -inline void* __mpcc_alloca_gcc(size_type sz) -{ - return __builtin_alloca(sz); -} diff --git a/SDK/__mpcc_defines.hxx b/SDK/__mpcc_defines.hxx deleted file mode 100644 index 5560410..0000000 --- a/SDK/__mpcc_defines.hxx +++ /dev/null @@ -1,89 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#ifndef __MPCC_DEF__ -#define __MPCC_DEF__ - -#ifndef __GNUC__ - -typedef __SIZE_TYPE__ size_t; - -#ifdef __LP64__ -typedef long int ssize_t; -#else -typedef int ssize_t; -#endif // __LP64__ - -typedef size_t ptrdiff_t; -typedef size_t uintptr_t; -typedef void* voidptr_t; -typedef void* any_t; -typedef char* caddr_t; - -#ifndef NULL -#define NULL ((voidptr_t)0) -#endif // !null - -#ifdef __GNUC__ -#include -#define __mpcc_alloca(sz) __mpcc_alloca_gcc(sz) -#elif defined(__MPCC__) - -#define __alloca(sz) __mpcc_alloca(sz) -#endif - -#define __deref(ptr) (*(ptr)) - -#ifdef __cplusplus -#define __init_decl() \ - extern "C" \ - { -#define __fini_decl() \ - } \ - ; -#else -#define __init_decl() -#define __fini_decl() -#endif - -#if __has_builtin(__builtin_alloca) -#define alloca(sz) __builtin_alloca(sz) -#ifdef __alloca -#undef __alloca -#endif -#define __alloca alloca -#else -#warning alloca not detected (MPCC) -#endif - -typedef long long off_t; -typedef unsigned long long uoff_t; - -typedef union float_cast { - struct - { - unsigned int mantissa : 23; - unsigned int exponent : 8; - unsigned int sign : 1; - }; - - float f; -} __attribute__((packed)) float_cast_t; - -typedef union double_cast { - struct - { - unsigned long long int mantissa : 52; - unsigned int exponent : 11; - unsigned int sign : 1; - }; - - double f; -} __attribute__((packed)) double_cast_t; - -#endif // ifndef __GNUC__ - -#endif /* __MPCC_DEF__ */ diff --git a/SDK/__mpcc_exception.hxx b/SDK/__mpcc_exception.hxx deleted file mode 100644 index 9366102..0000000 --- a/SDK/__mpcc_exception.hxx +++ /dev/null @@ -1,27 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -/// This file is an implementation of __throw* family of functions. - -#include -#include -#include - -namespace std -{ - inline void __throw_general(void) - { - throw std::runtime_error("MPCC C++ Runtime error."); - } - - inline void __throw_domain_error(const char* error) - { - std::cout << "MPCC C++: Domain error: " << error << "\r"; - __throw_general(); - } -} // namespace std diff --git a/SDK/__mpcc_hint.hxx b/SDK/__mpcc_hint.hxx deleted file mode 100644 index ee14711..0000000 --- a/SDK/__mpcc_hint.hxx +++ /dev/null @@ -1,20 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -#pragma compiler(hint_manifest) - -#define _Input -#define _Output - -#define _Optional - -#define _StrictCheckInput -#define _StrictCheckOutput - -#define _InOut -#define _StrictInOut diff --git a/SDK/__mpcc_malloc.hxx b/SDK/__mpcc_malloc.hxx deleted file mode 100644 index 2731868..0000000 --- a/SDK/__mpcc_malloc.hxx +++ /dev/null @@ -1,30 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -#include - -namespace stdx -{ - /// @brief allocate a new class. - /// @tparam KindClass the class type to allocate. - template - inline void* allocate(Args&&... args) - { - return new KindClass(std::forward(args)...); - } - - /// @brief free a class. - /// @tparam KindClass the class type to allocate. - template - inline void release(KindClass ptr) - { - if (!ptr) - return; - delete ptr; - } -} // namespace stdx diff --git a/SDK/__mpcc_power.inc b/SDK/__mpcc_power.inc deleted file mode 100644 index 9e4928c..0000000 --- a/SDK/__mpcc_power.inc +++ /dev/null @@ -1,35 +0,0 @@ -# Path: SDK/__mpcc_power.inc -# Language: MPCC POWER Assembly support for GNU. -# Build Date: 2024-6-4 - -%ifdef __CODETOOLS__ - -%def lda li -%def sta stw -%def ldw li - -%def r0 0 -%def r1 1 -%def r2 2 -%def r3 3 -%def r4 4 -%def r5 5 -%def r6 6 -%def r7 7 -%def r8 8 -%def r9 9 -%def r10 10 -%def r11 11 -%def r12 12 -%def r13 13 -%def r14 14 -%def r15 15 -%def r16 16 -%def r17 17 -%def r18 18 -%def r19 19 -%def r20 20 - -%endif - -%def nop mr 0, 0 diff --git a/Sources/32asm.cc b/Sources/32asm.cc index 4c98645..f877553 100644 --- a/Sources/32asm.cc +++ b/Sources/32asm.cc @@ -19,10 +19,10 @@ #define __ASM_NEED_32x0__ 1 -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include diff --git a/Sources/64asm.cc b/Sources/64asm.cc index 96bdc90..6e8cc6d 100644 --- a/Sources/64asm.cc +++ b/Sources/64asm.cc @@ -19,10 +19,10 @@ #define __ASM_NEED_64x0__ 1 -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include diff --git a/Sources/64x0-cc.cc b/Sources/64x0-cc.cc index d7b7491..3a0e569 100644 --- a/Sources/64x0-cc.cc +++ b/Sources/64x0-cc.cc @@ -10,9 +10,9 @@ /// BUGS: ? /// TODO: -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/Sources/AssemblyFactory.cc b/Sources/AssemblyFactory.cc index d5c0da7..0000ab7 100644 --- a/Sources/AssemblyFactory.cc +++ b/Sources/AssemblyFactory.cc @@ -4,8 +4,8 @@ ------------------------------------------- */ -#include -#include +#include +#include /** * @file AssemblyFactory.cxx diff --git a/Sources/Detail/asmutils.hxx b/Sources/Detail/asmutils.hxx index 36c5901..f6fdb41 100644 --- a/Sources/Detail/asmutils.hxx +++ b/Sources/Detail/asmutils.hxx @@ -6,8 +6,8 @@ #pragma once -#include -#include +#include +#include using namespace CompilerKit; diff --git a/Sources/Detail/compilerutils.hxx b/Sources/Detail/compilerutils.hxx index bebdd7f..9ddd3a2 100644 --- a/Sources/Detail/compilerutils.hxx +++ b/Sources/Detail/compilerutils.hxx @@ -6,8 +6,8 @@ #pragma once -#include -#include +#include +#include #define kZero64Section ".zero64" #define kCode64Section ".code64" diff --git a/Sources/String.cc b/Sources/String.cc index 6f7603f..38bd444 100644 --- a/Sources/String.cc +++ b/Sources/String.cc @@ -18,7 +18,7 @@ * */ -#include +#include #include namespace CompilerKit { diff --git a/Sources/bpp.cc b/Sources/bpp.cc index a988693..accbef5 100644 --- a/Sources/bpp.cc +++ b/Sources/bpp.cc @@ -9,8 +9,8 @@ /// BUGS: 0 -#include -#include +#include +#include #include #include #include diff --git a/Sources/coff2ae.cc b/Sources/coff2ae.cc index 59a99d4..349d543 100644 --- a/Sources/coff2ae.cc +++ b/Sources/coff2ae.cc @@ -4,9 +4,9 @@ ------------------------------------------- */ -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/Sources/cplusplus.cc b/Sources/cplusplus.cc index 3622606..db33688 100644 --- a/Sources/cplusplus.cc +++ b/Sources/cplusplus.cc @@ -16,8 +16,8 @@ #define kSplashCxx() \ kPrintF(kWhite "%s\n", "LightSpeed C++ Compiler, Copyright SoftwareLabs.") -#include -#include +#include +#include #include #include #include diff --git a/Sources/elf2ae.cc b/Sources/elf2ae.cc index 5f838be..a451a0a 100644 --- a/Sources/elf2ae.cc +++ b/Sources/elf2ae.cc @@ -4,9 +4,9 @@ ------------------------------------------- */ -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/Sources/i64asm.cc b/Sources/i64asm.cc index 5f0812c..5510252 100644 --- a/Sources/i64asm.cc +++ b/Sources/i64asm.cc @@ -27,10 +27,10 @@ #define kAssemblerPragmaSymStr "#" #define kAssemblerPragmaSym '#' -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include diff --git a/Sources/link.cc b/Sources/link.cc index d0d330e..47406c4 100644 --- a/Sources/link.cc +++ b/Sources/link.cc @@ -13,23 +13,23 @@ /// note: Do not look up for anything with .code64/.data64/.zero64! /// It will be loaded when program will start up! -#include +#include //! Assembler Kit -#include +#include //! Preferred Executable Format -#include -#include +#include +#include #include #include #include //! Dist version -#include +#include //! Advanced Executable Object Format -#include +#include //! C++ I/O headers. #include diff --git a/Sources/power-cc.cc b/Sources/power-cc.cc new file mode 100644 index 0000000..b26dbf2 --- /dev/null +++ b/Sources/power-cc.cc @@ -0,0 +1,1645 @@ +/* + * ======================================================== + * + * cc + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define kOk 0 + +/// @author Amlal El Mahrouss (amlel) +/// @file cc.cc +/// @brief POWER C Compiler. + +///////////////////// + +/// ANSI ESCAPE CODES + +///////////////////// + +#define kBlank "\e[0;30m" +#define kRed "\e[0;31m" +#define kWhite "\e[0;97m" + +///////////////////////////////////// + +/// INTERNAL STRUCT OF THE C COMPILER + +///////////////////////////////////// + +namespace detail +{ + // \brief name to register struct. + struct CompilerRegisterMap final + { + std::string fName; + std::string fReg; + }; + + // \brief Map for C structs + // \author amlel + struct CompilerStructMap final + { + /// 'struct::my_foo' + std::string fName; + + /// if instance: stores a valid register. + std::string fReg; + + /// offset count + std::size_t fOffsetsCnt; + + /// offset array. + std::vector> fOffsets; + }; + + struct CompilerState final + { + std::vector fSyntaxTreeList; + std::vector kStackFrame; + std::vector kStructMap; + ParserKit::SyntaxLeafList* fSyntaxTree{nullptr}; + std::unique_ptr fOutputAssembly; + std::string fLastFile; + std::string fLastError; + bool fVerbose; + }; +} // namespace detail + +static detail::CompilerState kState; +static SizeType kErrorLimit = 100; +static std::string kIfFunction = ""; +static Int32 kAcceptableErrors = 0; + +namespace detail +{ + /// @brief prints an error into stdout. + /// @param reason the reason of the error. + /// @param file where does it originate from? + void print_error(std::string reason, std::string file) noexcept + { + if (reason[0] == '\n') + reason.erase(0, 1); + + if (file.find(".pp") != std::string::npos) + file.erase(file.find(".pp"), 3); + + if (kState.fLastFile != file) + { + std::cout << kRed << "[ cc ] " << kWhite + << ((file == "cc") ? "internal compiler error " + : ("in file, " + file)) + << kBlank << std::endl; + std::cout << kRed << "[ cc ] " << kWhite << reason << kBlank << std::endl; + + kState.fLastFile = file; + } + else + { + std::cout << kRed << "[ cc ] [ " << kState.fLastFile << " ] " << kWhite + << reason << kBlank << std::endl; + } + + if (kAcceptableErrors > kErrorLimit) + std::exit(3); + + ++kAcceptableErrors; + } + + struct CompilerType final + { + std::string fName; + std::string fValue; + }; +} // namespace detail + +///////////////////////////////////////////////////////////////////////////////////////// + +// Target architecture. +static int kMachine = 0; + +///////////////////////////////////////// + +// REGISTERS ACCORDING TO USED ASSEMBLER + +///////////////////////////////////////// + +static size_t kRegisterCnt = kAsmRegisterLimit; +static size_t kStartUsable = 2; +static size_t kUsableLimit = 15; +static size_t kRegisterCounter = kStartUsable; +static std::string kRegisterPrefix = kAsmRegisterPrefix; + +///////////////////////////////////////// + +// COMPILER PARSING UTILITIES/STATES. + +///////////////////////////////////////// + +static std::vector kFileList; +static CompilerKit::AssemblyFactory kFactory; +static bool kInStruct = false; +static bool kOnWhileLoop = false; +static bool kOnForLoop = false; +static bool kInBraces = false; +static bool kIfFound = false; +static size_t kBracesCount = 0UL; + +/* @brief C compiler backend for C */ +class CompilerBackendCLang final : public ParserKit::CompilerBackend +{ +public: + explicit CompilerBackendCLang() = default; + ~CompilerBackendCLang() override = default; + + MPCC_COPY_DEFAULT(CompilerBackendCLang); + + std::string Check(const char* text, const char* file); + bool Compile(const std::string& text, const char* file) override; + + const char* Language() override + { + return "POWER C"; + } +}; + +static CompilerBackendCLang* kCompilerBackend = nullptr; +static std::vector kCompilerVariables; +static std::vector kCompilerFunctions; +static std::vector kCompilerTypes; + +namespace detail +{ + union number_cast final { + public: + number_cast(UInt64 _Raw) + : _Raw(_Raw) + { + } + + public: + char _Num[8]; + UInt64 _Raw; + }; + + union double_cast final { + public: + double_cast(float _Raw) + : _Raw(_Raw) + { + } + + public: + char _Sign; + char _Lh[8]; + char _Rh[23]; + + float _Raw; + }; +} // namespace detail + +///////////////////////////////////////////////////////////////////////////////////////// + +// @name Compile +// @brief Generate MASM from a C assignement. + +///////////////////////////////////////////////////////////////////////////////////////// + +bool CompilerBackendCLang::Compile(const std::string& text, const char* file) +{ + std::string textBuffer = text; + + bool typeFound = false; + bool fnFound = false; + + // setup generator. + std::random_device rd; + + auto seed_data = std::array{}; + std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); + std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); + std::mt19937 generator(seq); + + // start parsing + for (size_t text_index = 0; text_index < textBuffer.size(); ++text_index) + { + auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf(); + + auto gen = uuids::uuid_random_generator{generator}; + uuids::uuid out = gen(); + + detail::number_cast time_off = (UInt64)out.as_bytes().data(); + + if (!typeFound) + { + auto substr = textBuffer.substr(text_index); + std::string match_type; + + for (size_t y = 0; y < substr.size(); ++y) + { + if (substr[y] == ' ') + { + while (match_type.find(' ') != std::string::npos) + { + match_type.erase(match_type.find(' ')); + } + + for (auto& clType : kCompilerTypes) + { + if (clType.fName == match_type) + { + match_type.clear(); + + std::string buf; + + buf += clType.fValue; + buf += ' '; + + if (substr.find('=') != std::string::npos) + { + break; + } + + if (textBuffer.find('(') != std::string::npos) + { + syntaxLeaf.fUserValue = buf; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + } + + typeFound = true; + break; + } + } + + break; + } + + match_type += substr[y]; + } + } + + if (textBuffer[text_index] == '{') + { + if (kInStruct) + { + continue; + } + + kInBraces = true; + ++kBracesCount; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + } + + // return keyword handler + if (textBuffer[text_index] == 'r') + { + std::string return_keyword; + return_keyword += "return"; + + std::size_t index = 0UL; + + std::string value; + + for (size_t return_index = text_index; return_index < textBuffer.size(); + ++return_index) + { + if (textBuffer[return_index] != return_keyword[index]) + { + for (size_t value_index = return_index; + value_index < textBuffer.size(); ++value_index) + { + if (textBuffer[value_index] == ';') + break; + + value += textBuffer[value_index]; + } + + break; + } + + ++index; + } + + if (index == return_keyword.size()) + { + if (!value.empty()) + { + if (value.find('(') != std::string::npos) + { + value.erase(value.find('(')); + } + + if (!isdigit(value[value.find('(') + 2])) + { + std::string tmp = value; + bool reg_to_reg = false; + + value.clear(); + + value += " import"; + value += tmp; + } + + syntaxLeaf.fUserValue = "\tmr r31, "; + + // make it pretty. + while (value.find('\t') != std::string::npos) + value.erase(value.find('\t'), 1); + + while (value.find(' ') != std::string::npos) + value.erase(value.find(' '), 1); + + while (value.find("import") != std::string::npos) + value.erase(value.find("import"), strlen("import")); + + bool found = false; + + for (auto& reg : kState.kStackFrame) + { + if (value.find(reg.fName) != std::string::npos) + { + found = true; + syntaxLeaf.fUserValue += reg.fReg; + break; + } + } + + if (!found) + syntaxLeaf.fUserValue += "r0"; + } + + syntaxLeaf.fUserValue += "\n\tblr"; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + break; + } + } + + if (textBuffer[text_index] == 'i' && textBuffer[text_index + 1] == 'f') + { + auto expr = textBuffer.substr(text_index + 2); + textBuffer.erase(text_index, 2); + + if (expr.find("{") != std::string::npos) + { + expr.erase(expr.find("{")); + } + + if (expr.find("(") != std::string::npos) + expr.erase(expr.find("(")); + + if (expr.find(")") != std::string::npos) + expr.erase(expr.find(")")); + + kIfFunction = "__MPCC_IF_PROC_"; + kIfFunction += std::to_string(time_off._Raw); + + syntaxLeaf.fUserValue = + "\tcmpw " + "r10, r11"; + + syntaxLeaf.fUserValue += "\n\tbeq import " + kIfFunction + + " \ndword export .code64 " + kIfFunction + "\n"; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + kIfFound = true; + } + + // Parse expressions and instructions here. + // what does this mean? + // we encounter an assignment, or we reached the end of an expression. + if (textBuffer[text_index] == '=' || textBuffer[text_index] == ';') + { + if (fnFound) + continue; + if (kIfFound) + continue; + + if (textBuffer[text_index] == ';' && kInStruct) + continue; + + if (textBuffer.find("typedef ") != std::string::npos) + continue; + + if (textBuffer[text_index] == '=' && kInStruct) + { + detail::print_error( + "assignement of value inside a struct " + textBuffer, file); + continue; + } + + if (textBuffer[text_index] == ';' && kInStruct) + { + bool space_found_ = false; + std::string sym; + + for (auto& ch : textBuffer) + { + if (ch == ' ') + { + space_found_ = true; + } + + if (ch == ';') + break; + + if (space_found_) + sym.push_back(ch); + } + + kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back( + std::make_pair( + kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, + sym)); + + kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt = + kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4; + + continue; + } + + if (textBuffer[text_index] == '=' && kInStruct) + { + continue; + } + + if (textBuffer[text_index + 1] == '=' || + textBuffer[text_index - 1] == '!' || + textBuffer[text_index - 1] == '<' || + textBuffer[text_index - 1] == '>') + { + continue; + } + + std::string substr; + + if (textBuffer.find('=') != std::string::npos && kInBraces && !kIfFound) + { + if (textBuffer.find("*") != std::string::npos) + { + if (textBuffer.find("=") > textBuffer.find("*")) + substr += "\tli "; + else + substr += "\tli "; + } + else + { + substr += "\tli "; + } + } + else if (textBuffer.find('=') != std::string::npos && !kInBraces) + { + substr += "stw export .data64 "; + } + + int first_encountered = 0; + + std::string str_name; + + for (size_t text_index_2 = 0; text_index_2 < textBuffer.size(); + ++text_index_2) + { + if (textBuffer[text_index_2] == '\"') + { + ++text_index_2; + + // want to add this, so that the parser recognizes that this is a + // string. + substr += '"'; + + for (; text_index_2 < textBuffer.size(); ++text_index_2) + { + if (textBuffer[text_index_2] == '\"') + break; + + substr += textBuffer[text_index_2]; + } + } + + if (textBuffer[text_index_2] == '{' || textBuffer[text_index_2] == '}') + continue; + + if (textBuffer[text_index_2] == ';') + { + break; + } + + if (textBuffer[text_index_2] == ' ' || + textBuffer[text_index_2] == '\t') + { + if (first_encountered != 2) + { + if (textBuffer[text_index] != '=' && + substr.find("export .data64") == std::string::npos && + !kInStruct) + substr += "export .data64 "; + } + + ++first_encountered; + + continue; + } + + if (textBuffer[text_index_2] == '=') + { + if (!kInBraces) + { + substr.replace(substr.find("export .data64"), + strlen("export .data64"), "export .zero64 "); + } + + substr += ","; + continue; + } + + substr += textBuffer[text_index_2]; + } + + for (auto& clType : kCompilerTypes) + { + if (substr.find(clType.fName) != std::string::npos) + { + if (substr.find(clType.fName) > substr.find('"')) + continue; + + substr.erase(substr.find(clType.fName), clType.fName.size()); + } + else if (substr.find(clType.fValue) != std::string::npos) + { + if (substr.find(clType.fValue) > substr.find('"')) + continue; + + if (clType.fName == "const") + continue; + + substr.erase(substr.find(clType.fValue), clType.fValue.size()); + } + } + + if (substr.find("extern") != std::string::npos) + { + substr.replace(substr.find("extern"), strlen("extern"), "import "); + + if (substr.find("export .data64") != std::string::npos) + substr.erase(substr.find("export .data64"), strlen("export .data64")); + } + + auto var_to_find = + std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(), + [&](detail::CompilerType type) { + return type.fName.find(substr) != std::string::npos; + }); + + kCompilerVariables.push_back({.fName = substr}); + + if (textBuffer[text_index] == ';') + break; + + std::string reg = kAsmRegisterPrefix; + + ++kRegisterCounter; + reg += std::to_string(kRegisterCounter); + + auto newSubstr = substr.substr(substr.find(" ")); + + std::string symbol; + + for (size_t start = 0; start < newSubstr.size(); ++start) + { + if (newSubstr[start] == ',') + break; + + if (newSubstr[start] == ' ') + continue; + + symbol += (newSubstr[start]); + } + + kState.kStackFrame.push_back({.fName = symbol, .fReg = reg}); + + syntaxLeaf.fUserValue += + "\n\tli " + reg + substr.substr(substr.find(',')); + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + } + + // function handler. + + if (textBuffer[text_index] == '(' && !fnFound && !kIfFound) + { + std::string substr; + std::string args_buffer; + std::string args; + + bool type_crossed = false; + + for (size_t idx = textBuffer.find('(') + 1; idx < textBuffer.size(); + ++idx) + { + if (textBuffer[idx] == ',') + continue; + + if (textBuffer[idx] == ' ') + continue; + + if (textBuffer[idx] == ')') + break; + } + + for (char substr_first_index : textBuffer) + { + if (substr_first_index != ',') + args_buffer += substr_first_index; + else + args_buffer += '$'; + + if (substr_first_index == ';') + { + args_buffer = args_buffer.erase(0, args_buffer.find('(')); + args_buffer = args_buffer.erase(args_buffer.find(';'), 1); + args_buffer = args_buffer.erase(args_buffer.find(')'), 1); + args_buffer = args_buffer.erase(args_buffer.find('('), 1); + + if (!args_buffer.empty()) + args += "\tldw r6, "; + + std::string register_type; + std::size_t index = 7UL; + + while (args_buffer.find("$") != std::string::npos) + { + register_type = kRegisterPrefix; + register_type += std::to_string(index); + + ++index; + + args_buffer.replace(args_buffer.find('$'), 1, + "\n\tldw " + register_type + ","); + } + + args += args_buffer; + args += "\n\tli r31, "; + } + } + + for (char _text_i : textBuffer) + { + if (_text_i == '\t' || _text_i == ' ') + { + if (!type_crossed) + { + substr.clear(); + type_crossed = true; + } + + continue; + } + + if (_text_i == '(') + break; + + substr += _text_i; + } + + if (kInBraces) + { + syntaxLeaf.fUserValue = args; + syntaxLeaf.fUserValue += substr; + + syntaxLeaf.fUserValue += "\n\tblr\n"; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + fnFound = true; + } + else + { + syntaxLeaf.fUserValue.clear(); + + syntaxLeaf.fUserValue += "export .code64 "; + + syntaxLeaf.fUserValue += substr; + syntaxLeaf.fUserValue += "\n"; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + fnFound = true; + } + + kCompilerFunctions.push_back(textBuffer); + } + + if (textBuffer[text_index] == '-' && textBuffer[text_index + 1] == '-') + { + textBuffer = textBuffer.replace(textBuffer.find("--"), strlen("--"), ""); + + for (int _text_i = 0; _text_i < textBuffer.size(); ++_text_i) + { + if (textBuffer[_text_i] == '\t' || textBuffer[_text_i] == ' ') + textBuffer.erase(_text_i, 1); + } + + syntaxLeaf.fUserValue += "dec "; + syntaxLeaf.fUserValue += textBuffer; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + break; + } + + if (textBuffer[text_index] == '}') + { + kRegisterCounter = kStartUsable; + + --kBracesCount; + + if (kBracesCount < 1) + { + kInBraces = false; + kBracesCount = 0; + } + + if (kIfFound) + kIfFound = false; + + if (kInStruct) + kInStruct = false; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + } + + syntaxLeaf.fUserValue.clear(); + } + + auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf(); + syntaxLeaf.fUserValue = "\n"; + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + return true; +} + +static bool kShouldHaveBraces = false; +static std::string kFnName; + +std::string CompilerBackendCLang::Check(const char* text, const char* file) +{ + std::string err_str; + std::string ln = text; + + if (ln.empty()) + { + return err_str; + } + + bool non_ascii_found = false; + + for (int i = 0; i < ln.size(); ++i) + { + if (isalnum(ln[i])) + { + non_ascii_found = true; + break; + } + } + + if (kShouldHaveBraces && ln.find('{') != std::string::npos) + { + kShouldHaveBraces = false; + } + + if (!non_ascii_found) + return err_str; + + size_t string_index = 1UL; + + if (ln.find('\'') != std::string::npos) + { + string_index = ln.find('\'') + 1; + + for (; string_index < ln.size(); ++string_index) + { + if (ln[string_index] == '\'') + { + if (ln[string_index + 1] != ';') + { + ln.erase(string_index, 1); + } + + return err_str; + } + } + } + else if (ln.find('"') != std::string::npos) + { + string_index = ln.find('"') + 1; + + for (; string_index < ln.size(); ++string_index) + { + if (ln[string_index] == '"') + { + if (ln[string_index + 1] != ';') + { + ln.erase(string_index, 1); + } + else + { + break; + } + } + } + } + else if (ln.find('"') == std::string::npos && + ln.find('\'') == std::string::npos) + { + std::vector forbidden_words; + + forbidden_words.push_back("\\"); + forbidden_words.push_back("?"); + forbidden_words.push_back("@"); + forbidden_words.push_back("~"); + forbidden_words.push_back("::"); + forbidden_words.push_back("/*"); + forbidden_words.push_back("*/"); + + // add them to avoid stupid mistakes. + forbidden_words.push_back("namespace"); + forbidden_words.push_back("class"); + forbidden_words.push_back("extern \"C\""); + + for (auto& forbidden : forbidden_words) + { + if (ln.find(forbidden) != std::string::npos) + { + err_str += "\nForbidden character detected: "; + err_str += forbidden; + + return err_str; + } + } + } + + struct CompilerVariableRange final + { + std::string fBegin; + std::string fEnd; + }; + + const std::vector variables_list = { + {.fBegin = "static ", .fEnd = "="}, + {.fBegin = "=", .fEnd = ";"}, + {.fBegin = "if(", .fEnd = "="}, + {.fBegin = "if (", .fEnd = "="}, + {.fBegin = "if(", .fEnd = "<"}, + {.fBegin = "if (", .fEnd = "<"}, + {.fBegin = "if(", .fEnd = ">"}, + {.fBegin = "if (", .fEnd = ">"}, + {.fBegin = "if(", .fEnd = ")"}, + {.fBegin = "if (", .fEnd = ")"}, + + {.fBegin = "else(", .fEnd = "="}, + {.fBegin = "else (", .fEnd = "="}, + {.fBegin = "else(", .fEnd = "<"}, + {.fBegin = "else (", .fEnd = "<"}, + {.fBegin = "else(", .fEnd = ">"}, + {.fBegin = "else (", .fEnd = ">"}, + {.fBegin = "else(", .fEnd = ")"}, + {.fBegin = "else (", .fEnd = ")"}, + }; + + for (auto& variable : variables_list) + { + if (ln.find(variable.fBegin) != std::string::npos) + { + string_index = ln.find(variable.fBegin) + variable.fBegin.size(); + + while (ln[string_index] == ' ') + ++string_index; + + std::string keyword; + + for (; string_index < ln.size(); ++string_index) + { + if (ln[string_index] == variable.fEnd[0]) + { + std::string varname = ""; + + for (size_t index_keyword = ln.find(' '); + ln[index_keyword] != variable.fBegin[0]; ++index_keyword) + { + if (ln[index_keyword] == ' ') + { + continue; + } + + if (isdigit(ln[index_keyword])) + { + goto cc_next_loop; + } + + varname += ln[index_keyword]; + } + + if (varname.find(' ') != std::string::npos) + { + varname.erase(0, varname.find(' ')); + + if (variable.fBegin == "extern") + { + varname.erase(0, varname.find(' ')); + } + } + + if (kRegisterCounter == 5 || kRegisterCounter == 6) + ++kRegisterCounter; + + std::string reg = kAsmRegisterPrefix; + reg += std::to_string(kRegisterCounter); + + kCompilerVariables.push_back({.fValue = varname}); + goto cc_check_done; + } + + keyword.push_back(ln[string_index]); + } + + goto cc_next_loop; + + cc_check_done: + + // skip digit value. + if (isdigit(keyword[0]) || keyword[0] == '"') + { + goto cc_next_loop; + } + + while (keyword.find(' ') != std::string::npos) + keyword.erase(keyword.find(' '), 1); + + for (auto& var : kCompilerVariables) + { + if (var.fValue.find(keyword) != std::string::npos) + { + err_str.clear(); + goto cc_next; + } + } + + for (auto& fn : kCompilerFunctions) + { + if (fn.find(keyword[0]) != std::string::npos) + { + auto where_begin = fn.find(keyword[0]); + auto keyword_begin = 0UL; + auto failed = false; + + for (; where_begin < keyword.size(); ++where_begin) + { + if (fn[where_begin] == '(' && keyword[keyword_begin] == '(') + break; + + if (fn[where_begin] != keyword[keyword_begin]) + { + failed = true; + break; + } + + ++keyword_begin; + } + + if (!failed) + { + err_str.clear(); + goto cc_next; + } + else + { + continue; + } + } + } + + cc_error_value: + if (keyword.find("->") != std::string::npos) + return err_str; + + if (keyword.find(".") != std::string::npos) + return err_str; + + if (isalnum(keyword[0])) + err_str += "\nUndefined value: " + keyword; + + return err_str; + } + + cc_next_loop: + continue; + } + +cc_next: + + // extern does not declare anything, it imports a variable. + // so that's why it's not declare upper. + if (ParserKit::find_word(ln, "extern")) + { + auto substr = ln.substr(ln.find("extern") + strlen("extern")); + kCompilerVariables.push_back({.fValue = substr}); + } + + if (kShouldHaveBraces && ln.find('{') == std::string::npos) + { + err_str += "Missing '{' for function "; + err_str += kFnName; + err_str += "\n"; + + kShouldHaveBraces = false; + kFnName.clear(); + } + else if (kShouldHaveBraces && ln.find('{') != std::string::npos) + { + kShouldHaveBraces = false; + kFnName.clear(); + } + + bool type_not_found = true; + + if (ln.find('\'') != std::string::npos) + { + ln.replace(ln.find('\''), 3, "0"); + } + + auto first = ln.find('"'); + if (first != std::string::npos) + { + auto second = 0UL; + bool found_second_quote = false; + + for (size_t i = first + 1; i < ln.size(); ++i) + { + if (ln[i] == '\"') + { + found_second_quote = true; + second = i; + + break; + } + } + + if (!found_second_quote) + { + err_str += "Missing terminating \"."; + err_str += " here -> " + ln.substr(ln.find('"'), second); + } + } + + if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos) + { + if (ln.find('{') == std::string::npos) + { + kFnName = ln; + kShouldHaveBraces = true; + + goto skip_braces_check; + } + else if (ln.find('{') != std::string::npos) + { + kShouldHaveBraces = false; + } + } + +skip_braces_check: + + for (auto& key : kCompilerTypes) + { + if (ParserKit::find_word(ln, key.fName)) + { + if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) + { + err_str += "\nNumber cannot be set for "; + err_str += key.fName; + err_str += "'s name. here -> "; + err_str += ln; + } + + if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' || + ln[ln.find(key.fName) - 1] == '\t') + { + type_not_found = false; + + if (ln[ln.find(key.fName) + key.fName.size()] != ' ') + { + type_not_found = true; + + if (ln[ln.find(key.fName) + key.fName.size()] == '\t') + type_not_found = false; + + goto next; + } + else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') + { + type_not_found = true; + + if (ln[ln.find(key.fName) + key.fName.size()] == ' ') + type_not_found = false; + } + } + + next: + + if (ln.find(';') == std::string::npos) + { + if (ln.find('(') != std::string::npos) + { + if (ln.find('=') == std::string::npos) + continue; + } + + err_str += "\nMissing ';', here -> "; + err_str += ln; + } + else + { + continue; + } + + if (ln.find('=') != std::string::npos) + { + if (ln.find('(') != std::string::npos) + { + if (ln.find(')') == std::string::npos) + { + err_str += "\nMissing ')', after '(' here -> "; + err_str += ln.substr(ln.find('(')); + } + } + } + } + } + + if (kInBraces && ln.find("struct") != std::string::npos && + ln.find("union") != std::string::npos && + ln.find("enum") != std::string::npos && + ln.find('=') != std::string::npos) + { + if (ln.find(';') == std::string::npos) + { + err_str += "\nMissing ';' after struct/union/enum declaration, here -> "; + err_str += ln; + } + } + + if (ln.find(';') != std::string::npos && + ln.find("for") == std::string::npos) + { + if (ln.find(';') + 1 != ln.size()) + { + for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) + { + if ((ln.substr(ln.find(';') + 1)[i] != ' ') || + (ln.substr(ln.find(';') + 1)[i] != '\t')) + { + if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); + !err.empty()) + { + err_str += "\nUnexpected text after ';' -> "; + err_str += ln.substr(ln.find(';')); + err_str += err; + } + } + } + } + } + + if (ln.find('(') != std::string::npos) + { + if (ln.find(';') == std::string::npos && !ParserKit::find_word(ln, "|") && + !ParserKit::find_word(ln, "||") && !ParserKit::find_word(ln, "&") && + !ParserKit::find_word(ln, "&&") && !ParserKit::find_word(ln, "~")) + { + bool found_func = false; + size_t i = ln.find('('); + std::vector opens; + std::vector closes; + + for (; i < ln.size(); ++i) + { + if (ln[i] == ')') + { + closes.push_back(1); + } + + if (ln[i] == '(') + { + opens.push_back(1); + } + } + + if (closes.size() != opens.size()) + err_str += "Unterminated (), here -> " + ln; + + bool space_found = false; + + for (int i = 0; i < ln.size(); ++i) + { + if (ln[i] == ')' && !space_found) + { + space_found = true; + continue; + } + + if (space_found) + { + if (ln[i] == ' ' && isalnum(ln[i + 1])) + { + err_str += "\nBad function format here -> "; + err_str += ln; + } + } + } + } + + if (ln.find('(') < 1) + { + err_str += "\nMissing identifier before '(' here -> "; + err_str += ln; + } + else + { + if (type_not_found && ln.find(';') == std::string::npos && + ln.find("if") == std::string::npos && + ln.find("|") == std::string::npos && + ln.find("&") == std::string::npos && + ln.find("(") == std::string::npos && + ln.find(")") == std::string::npos) + { + err_str += "\n Missing ';' or type, here -> "; + err_str += ln; + } + } + + if (ln.find(')') == std::string::npos) + { + err_str += "\nMissing ')', after '(' here -> "; + err_str += ln.substr(ln.find('(')); + } + } + else + { + if (ln.find("for") != std::string::npos || + ln.find("while") != std::string::npos) + { + err_str += "\nMissing '(', after \"for\", here -> "; + err_str += ln; + } + } + + if (ln.find('}') != std::string::npos && !kInBraces) + { + if (!kInStruct && ln.find(';') == std::string::npos) + { + err_str += "\nMismatched '}', here -> "; + err_str += ln; + } + } + + if (!ln.empty()) + { + if (ln.find(';') == std::string::npos && + ln.find('{') == std::string::npos && + ln.find('}') == std::string::npos && + ln.find(')') == std::string::npos && + ln.find('(') == std::string::npos && + ln.find(',') == std::string::npos) + { + if (ln.size() <= 2) + return err_str; + + err_str += "\nMissing ';', here -> "; + err_str += ln; + } + } + + return err_str; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +/** + * @brief C To Assembly mount-point. + */ + +///////////////////////////////////////////////////////////////////////////////////////// + +class AssemblyMountpointCLang final : public CompilerKit::AssemblyInterface +{ +public: + explicit AssemblyMountpointCLang() = default; + ~AssemblyMountpointCLang() override = default; + + MPCC_COPY_DEFAULT(AssemblyMountpointCLang); + + [[maybe_unused]] static Int32 Arch() noexcept + { + return CompilerKit::AssemblyFactory::kArchPowerPC; + } + + Int32 CompileToFormat(std::string& src, Int32 arch) override + { + if (arch != AssemblyMountpointCLang::Arch()) + return -1; + + if (kCompilerBackend == nullptr) + return -1; + + /* @brief copy contents wihtout extension */ + std::string src_file = src.data(); + std::ifstream src_fp = std::ifstream(src_file, std::ios::in); + std::string dest; + + for (auto& ch : src_file) + { + if (ch == '.') + { + break; + } + + dest += ch; + } + + /* According to PEF ABI. */ + std::vector exts = kAsmFileExts; + dest += exts[4]; + + kState.fOutputAssembly = std::make_unique(dest); + + auto fmt = CompilerKit::current_date(); + + (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; + (*kState.fOutputAssembly) + << "# Language: POWER Assembly (Generated from C)\n"; + (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n"; + + ParserKit::SyntaxLeafList syntax; + + kState.fSyntaxTreeList.push_back(syntax); + kState.fSyntaxTree = + &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; + + std::string line_src; + + while (std::getline(src_fp, line_src)) + { + if (auto err = kCompilerBackend->Check(line_src.c_str(), src.data()); + err.empty()) + { + kCompilerBackend->Compile(line_src, src.data()); + } + else + { + detail::print_error(err, src.data()); + } + } + + if (kAcceptableErrors > 0) + return -1; + + std::vector keywords = {"ld", "stw", "add", "sub", "or"}; + + /// + /// Replace, optimize, fix assembly output. + /// + + for (auto& leaf : kState.fSyntaxTree->fLeafList) + { + std::vector access_keywords = {"->", "."}; + + for (auto& access_ident : access_keywords) + { + if (ParserKit::find_word(leaf.fUserValue, access_ident)) + { + for (auto& struc : kState.kStructMap) + { + /// TODO: + } + } + } + + for (auto& keyword : keywords) + { + if (ParserKit::find_word(leaf.fUserValue, keyword)) + { + std::size_t cnt = 0UL; + + for (auto& reg : kState.kStackFrame) + { + std::string needle; + + for (size_t i = 0; i < reg.fName.size(); i++) + { + if (reg.fName[i] == ' ') + { + ++i; + + for (; i < reg.fName.size(); i++) + { + if (reg.fName[i] == ',') + { + break; + } + + if (reg.fName[i] == ' ') + continue; + + needle += reg.fName[i]; + } + + break; + } + } + + if (ParserKit::find_word(leaf.fUserValue, needle)) + { + if (leaf.fUserValue.find("import ") != std::string::npos) + { + std::string range = "import "; + leaf.fUserValue.replace(leaf.fUserValue.find(range), + range.size(), ""); + } + + if (leaf.fUserValue.find("ldw r6") != std::string::npos) + { + std::string::difference_type countComma = std::count( + leaf.fUserValue.begin(), leaf.fUserValue.end(), ','); + + if (countComma == 1) + { + leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), + strlen("ldw"), "mr"); + } + } + + leaf.fUserValue.replace(leaf.fUserValue.find(needle), + needle.size(), reg.fReg); + + ++cnt; + } + } + + if (cnt > 1 && keyword != "mr" && keyword != "add" && + keyword != "dec") + { + leaf.fUserValue.replace(leaf.fUserValue.find(keyword), + keyword.size(), "mr"); + } + } + } + } + + for (auto& leaf : kState.fSyntaxTree->fLeafList) + { + (*kState.fOutputAssembly) << leaf.fUserValue; + } + + kState.fSyntaxTree = nullptr; + + kState.fOutputAssembly->flush(); + kState.fOutputAssembly.reset(); + + return kOk; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +#include + +#define kPrintF printf +#define kSplashCxx() \ + kPrintF(kWhite "cc, %s, (c) SoftwareLabs\n", kDistVersion) + +static void cc_print_help() +{ + kSplashCxx(); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +#define kExt ".c" + +MPCC_MODULE(NewOSCompilerCLangPowerPC) +{ + kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); + kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); + kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); + kCompilerTypes.push_back({.fName = "int", .fValue = "dword"}); + kCompilerTypes.push_back({.fName = "long", .fValue = "qword"}); + kCompilerTypes.push_back({.fName = "*", .fValue = "offset"}); + + bool skip = false; + + kFactory.Mount(new AssemblyMountpointCLang()); + kMachine = CompilerKit::AssemblyFactory::kArchPowerPC; + kCompilerBackend = new CompilerBackendCLang(); + + for (auto index = 1UL; index < argc; ++index) + { + if (skip) + { + skip = false; + continue; + } + + if (argv[index][0] == '-') + { + if (strcmp(argv[index], "-v") == 0 || + strcmp(argv[index], "-version") == 0) + { + kSplashCxx(); + return kOk; + } + + if (strcmp(argv[index], "-verbose") == 0) + { + kState.fVerbose = true; + + continue; + } + + if (strcmp(argv[index], "-h") == 0 || strcmp(argv[index], "-help") == 0) + { + cc_print_help(); + + return kOk; + } + + if (strcmp(argv[index], "-dialect") == 0) + { + if (kCompilerBackend) + std::cout << kCompilerBackend->Language() << "\n"; + + return kOk; + } + + if (strcmp(argv[index], "-fmax-exceptions") == 0) + { + try + { + kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); + } + // catch anything here + catch (...) + { + kErrorLimit = 0; + } + + skip = true; + + continue; + } + + std::string err = "Unknown command: "; + err += argv[index]; + + detail::print_error(err, "cc"); + + continue; + } + + kFileList.emplace_back(argv[index]); + + std::string srcFile = argv[index]; + + if (strstr(argv[index], kExt) == nullptr) + { + if (kState.fVerbose) + { + detail::print_error(srcFile + " is not a valid C source.\n", "cc"); + } + + return 1; + } + + if (kFactory.Compile(srcFile, kMachine) != kOk) + return -1; + } + + return kOk; +} + +// Last rev 8-1-24 diff --git a/Sources/ppc-cc.cc b/Sources/ppc-cc.cc deleted file mode 100644 index 31dc359..0000000 --- a/Sources/ppc-cc.cc +++ /dev/null @@ -1,1645 +0,0 @@ -/* - * ======================================================== - * - * cc - * Copyright SoftwareLabs, all rights reserved. - * - * ======================================================== - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define kOk 0 - -/// @author Amlal El Mahrouss (amlel) -/// @file cc.cc -/// @brief POWER C Compiler. - -///////////////////// - -/// ANSI ESCAPE CODES - -///////////////////// - -#define kBlank "\e[0;30m" -#define kRed "\e[0;31m" -#define kWhite "\e[0;97m" - -///////////////////////////////////// - -/// INTERNAL STRUCT OF THE C COMPILER - -///////////////////////////////////// - -namespace detail -{ - // \brief name to register struct. - struct CompilerRegisterMap final - { - std::string fName; - std::string fReg; - }; - - // \brief Map for C structs - // \author amlel - struct CompilerStructMap final - { - /// 'struct::my_foo' - std::string fName; - - /// if instance: stores a valid register. - std::string fReg; - - /// offset count - std::size_t fOffsetsCnt; - - /// offset array. - std::vector> fOffsets; - }; - - struct CompilerState final - { - std::vector fSyntaxTreeList; - std::vector kStackFrame; - std::vector kStructMap; - ParserKit::SyntaxLeafList* fSyntaxTree{nullptr}; - std::unique_ptr fOutputAssembly; - std::string fLastFile; - std::string fLastError; - bool fVerbose; - }; -} // namespace detail - -static detail::CompilerState kState; -static SizeType kErrorLimit = 100; -static std::string kIfFunction = ""; -static Int32 kAcceptableErrors = 0; - -namespace detail -{ - /// @brief prints an error into stdout. - /// @param reason the reason of the error. - /// @param file where does it originate from? - void print_error(std::string reason, std::string file) noexcept - { - if (reason[0] == '\n') - reason.erase(0, 1); - - if (file.find(".pp") != std::string::npos) - file.erase(file.find(".pp"), 3); - - if (kState.fLastFile != file) - { - std::cout << kRed << "[ cc ] " << kWhite - << ((file == "cc") ? "internal compiler error " - : ("in file, " + file)) - << kBlank << std::endl; - std::cout << kRed << "[ cc ] " << kWhite << reason << kBlank << std::endl; - - kState.fLastFile = file; - } - else - { - std::cout << kRed << "[ cc ] [ " << kState.fLastFile << " ] " << kWhite - << reason << kBlank << std::endl; - } - - if (kAcceptableErrors > kErrorLimit) - std::exit(3); - - ++kAcceptableErrors; - } - - struct CompilerType final - { - std::string fName; - std::string fValue; - }; -} // namespace detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// Target architecture. -static int kMachine = 0; - -///////////////////////////////////////// - -// REGISTERS ACCORDING TO USED ASSEMBLER - -///////////////////////////////////////// - -static size_t kRegisterCnt = kAsmRegisterLimit; -static size_t kStartUsable = 2; -static size_t kUsableLimit = 15; -static size_t kRegisterCounter = kStartUsable; -static std::string kRegisterPrefix = kAsmRegisterPrefix; - -///////////////////////////////////////// - -// COMPILER PARSING UTILITIES/STATES. - -///////////////////////////////////////// - -static std::vector kFileList; -static CompilerKit::AssemblyFactory kFactory; -static bool kInStruct = false; -static bool kOnWhileLoop = false; -static bool kOnForLoop = false; -static bool kInBraces = false; -static bool kIfFound = false; -static size_t kBracesCount = 0UL; - -/* @brief C compiler backend for C */ -class CompilerBackendCLang final : public ParserKit::CompilerBackend -{ -public: - explicit CompilerBackendCLang() = default; - ~CompilerBackendCLang() override = default; - - MPCC_COPY_DEFAULT(CompilerBackendCLang); - - std::string Check(const char* text, const char* file); - bool Compile(const std::string& text, const char* file) override; - - const char* Language() override - { - return "POWER C"; - } -}; - -static CompilerBackendCLang* kCompilerBackend = nullptr; -static std::vector kCompilerVariables; -static std::vector kCompilerFunctions; -static std::vector kCompilerTypes; - -namespace detail -{ - union number_cast final { - public: - number_cast(UInt64 _Raw) - : _Raw(_Raw) - { - } - - public: - char _Num[8]; - UInt64 _Raw; - }; - - union double_cast final { - public: - double_cast(float _Raw) - : _Raw(_Raw) - { - } - - public: - char _Sign; - char _Lh[8]; - char _Rh[23]; - - float _Raw; - }; -} // namespace detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// @name Compile -// @brief Generate MASM from a C assignement. - -///////////////////////////////////////////////////////////////////////////////////////// - -bool CompilerBackendCLang::Compile(const std::string& text, const char* file) -{ - std::string textBuffer = text; - - bool typeFound = false; - bool fnFound = false; - - // setup generator. - std::random_device rd; - - auto seed_data = std::array{}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); - std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); - std::mt19937 generator(seq); - - // start parsing - for (size_t text_index = 0; text_index < textBuffer.size(); ++text_index) - { - auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf(); - - auto gen = uuids::uuid_random_generator{generator}; - uuids::uuid out = gen(); - - detail::number_cast time_off = (UInt64)out.as_bytes().data(); - - if (!typeFound) - { - auto substr = textBuffer.substr(text_index); - std::string match_type; - - for (size_t y = 0; y < substr.size(); ++y) - { - if (substr[y] == ' ') - { - while (match_type.find(' ') != std::string::npos) - { - match_type.erase(match_type.find(' ')); - } - - for (auto& clType : kCompilerTypes) - { - if (clType.fName == match_type) - { - match_type.clear(); - - std::string buf; - - buf += clType.fValue; - buf += ' '; - - if (substr.find('=') != std::string::npos) - { - break; - } - - if (textBuffer.find('(') != std::string::npos) - { - syntaxLeaf.fUserValue = buf; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - typeFound = true; - break; - } - } - - break; - } - - match_type += substr[y]; - } - } - - if (textBuffer[text_index] == '{') - { - if (kInStruct) - { - continue; - } - - kInBraces = true; - ++kBracesCount; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - // return keyword handler - if (textBuffer[text_index] == 'r') - { - std::string return_keyword; - return_keyword += "return"; - - std::size_t index = 0UL; - - std::string value; - - for (size_t return_index = text_index; return_index < textBuffer.size(); - ++return_index) - { - if (textBuffer[return_index] != return_keyword[index]) - { - for (size_t value_index = return_index; - value_index < textBuffer.size(); ++value_index) - { - if (textBuffer[value_index] == ';') - break; - - value += textBuffer[value_index]; - } - - break; - } - - ++index; - } - - if (index == return_keyword.size()) - { - if (!value.empty()) - { - if (value.find('(') != std::string::npos) - { - value.erase(value.find('(')); - } - - if (!isdigit(value[value.find('(') + 2])) - { - std::string tmp = value; - bool reg_to_reg = false; - - value.clear(); - - value += " import"; - value += tmp; - } - - syntaxLeaf.fUserValue = "\tmr r31, "; - - // make it pretty. - while (value.find('\t') != std::string::npos) - value.erase(value.find('\t'), 1); - - while (value.find(' ') != std::string::npos) - value.erase(value.find(' '), 1); - - while (value.find("import") != std::string::npos) - value.erase(value.find("import"), strlen("import")); - - bool found = false; - - for (auto& reg : kState.kStackFrame) - { - if (value.find(reg.fName) != std::string::npos) - { - found = true; - syntaxLeaf.fUserValue += reg.fReg; - break; - } - } - - if (!found) - syntaxLeaf.fUserValue += "r0"; - } - - syntaxLeaf.fUserValue += "\n\tblr"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - break; - } - } - - if (textBuffer[text_index] == 'i' && textBuffer[text_index + 1] == 'f') - { - auto expr = textBuffer.substr(text_index + 2); - textBuffer.erase(text_index, 2); - - if (expr.find("{") != std::string::npos) - { - expr.erase(expr.find("{")); - } - - if (expr.find("(") != std::string::npos) - expr.erase(expr.find("(")); - - if (expr.find(")") != std::string::npos) - expr.erase(expr.find(")")); - - kIfFunction = "__MPCC_IF_PROC_"; - kIfFunction += std::to_string(time_off._Raw); - - syntaxLeaf.fUserValue = - "\tcmpw " - "r10, r11"; - - syntaxLeaf.fUserValue += "\n\tbeq import " + kIfFunction + - " \ndword export .code64 " + kIfFunction + "\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - kIfFound = true; - } - - // Parse expressions and instructions here. - // what does this mean? - // we encounter an assignment, or we reached the end of an expression. - if (textBuffer[text_index] == '=' || textBuffer[text_index] == ';') - { - if (fnFound) - continue; - if (kIfFound) - continue; - - if (textBuffer[text_index] == ';' && kInStruct) - continue; - - if (textBuffer.find("typedef ") != std::string::npos) - continue; - - if (textBuffer[text_index] == '=' && kInStruct) - { - detail::print_error( - "assignement of value inside a struct " + textBuffer, file); - continue; - } - - if (textBuffer[text_index] == ';' && kInStruct) - { - bool space_found_ = false; - std::string sym; - - for (auto& ch : textBuffer) - { - if (ch == ' ') - { - space_found_ = true; - } - - if (ch == ';') - break; - - if (space_found_) - sym.push_back(ch); - } - - kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back( - std::make_pair( - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, - sym)); - - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt = - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4; - - continue; - } - - if (textBuffer[text_index] == '=' && kInStruct) - { - continue; - } - - if (textBuffer[text_index + 1] == '=' || - textBuffer[text_index - 1] == '!' || - textBuffer[text_index - 1] == '<' || - textBuffer[text_index - 1] == '>') - { - continue; - } - - std::string substr; - - if (textBuffer.find('=') != std::string::npos && kInBraces && !kIfFound) - { - if (textBuffer.find("*") != std::string::npos) - { - if (textBuffer.find("=") > textBuffer.find("*")) - substr += "\tli "; - else - substr += "\tli "; - } - else - { - substr += "\tli "; - } - } - else if (textBuffer.find('=') != std::string::npos && !kInBraces) - { - substr += "stw export .data64 "; - } - - int first_encountered = 0; - - std::string str_name; - - for (size_t text_index_2 = 0; text_index_2 < textBuffer.size(); - ++text_index_2) - { - if (textBuffer[text_index_2] == '\"') - { - ++text_index_2; - - // want to add this, so that the parser recognizes that this is a - // string. - substr += '"'; - - for (; text_index_2 < textBuffer.size(); ++text_index_2) - { - if (textBuffer[text_index_2] == '\"') - break; - - substr += textBuffer[text_index_2]; - } - } - - if (textBuffer[text_index_2] == '{' || textBuffer[text_index_2] == '}') - continue; - - if (textBuffer[text_index_2] == ';') - { - break; - } - - if (textBuffer[text_index_2] == ' ' || - textBuffer[text_index_2] == '\t') - { - if (first_encountered != 2) - { - if (textBuffer[text_index] != '=' && - substr.find("export .data64") == std::string::npos && - !kInStruct) - substr += "export .data64 "; - } - - ++first_encountered; - - continue; - } - - if (textBuffer[text_index_2] == '=') - { - if (!kInBraces) - { - substr.replace(substr.find("export .data64"), - strlen("export .data64"), "export .zero64 "); - } - - substr += ","; - continue; - } - - substr += textBuffer[text_index_2]; - } - - for (auto& clType : kCompilerTypes) - { - if (substr.find(clType.fName) != std::string::npos) - { - if (substr.find(clType.fName) > substr.find('"')) - continue; - - substr.erase(substr.find(clType.fName), clType.fName.size()); - } - else if (substr.find(clType.fValue) != std::string::npos) - { - if (substr.find(clType.fValue) > substr.find('"')) - continue; - - if (clType.fName == "const") - continue; - - substr.erase(substr.find(clType.fValue), clType.fValue.size()); - } - } - - if (substr.find("extern") != std::string::npos) - { - substr.replace(substr.find("extern"), strlen("extern"), "import "); - - if (substr.find("export .data64") != std::string::npos) - substr.erase(substr.find("export .data64"), strlen("export .data64")); - } - - auto var_to_find = - std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(), - [&](detail::CompilerType type) { - return type.fName.find(substr) != std::string::npos; - }); - - kCompilerVariables.push_back({.fName = substr}); - - if (textBuffer[text_index] == ';') - break; - - std::string reg = kAsmRegisterPrefix; - - ++kRegisterCounter; - reg += std::to_string(kRegisterCounter); - - auto newSubstr = substr.substr(substr.find(" ")); - - std::string symbol; - - for (size_t start = 0; start < newSubstr.size(); ++start) - { - if (newSubstr[start] == ',') - break; - - if (newSubstr[start] == ' ') - continue; - - symbol += (newSubstr[start]); - } - - kState.kStackFrame.push_back({.fName = symbol, .fReg = reg}); - - syntaxLeaf.fUserValue += - "\n\tli " + reg + substr.substr(substr.find(',')); - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - // function handler. - - if (textBuffer[text_index] == '(' && !fnFound && !kIfFound) - { - std::string substr; - std::string args_buffer; - std::string args; - - bool type_crossed = false; - - for (size_t idx = textBuffer.find('(') + 1; idx < textBuffer.size(); - ++idx) - { - if (textBuffer[idx] == ',') - continue; - - if (textBuffer[idx] == ' ') - continue; - - if (textBuffer[idx] == ')') - break; - } - - for (char substr_first_index : textBuffer) - { - if (substr_first_index != ',') - args_buffer += substr_first_index; - else - args_buffer += '$'; - - if (substr_first_index == ';') - { - args_buffer = args_buffer.erase(0, args_buffer.find('(')); - args_buffer = args_buffer.erase(args_buffer.find(';'), 1); - args_buffer = args_buffer.erase(args_buffer.find(')'), 1); - args_buffer = args_buffer.erase(args_buffer.find('('), 1); - - if (!args_buffer.empty()) - args += "\tldw r6, "; - - std::string register_type; - std::size_t index = 7UL; - - while (args_buffer.find("$") != std::string::npos) - { - register_type = kRegisterPrefix; - register_type += std::to_string(index); - - ++index; - - args_buffer.replace(args_buffer.find('$'), 1, - "\n\tldw " + register_type + ","); - } - - args += args_buffer; - args += "\n\tli r31, "; - } - } - - for (char _text_i : textBuffer) - { - if (_text_i == '\t' || _text_i == ' ') - { - if (!type_crossed) - { - substr.clear(); - type_crossed = true; - } - - continue; - } - - if (_text_i == '(') - break; - - substr += _text_i; - } - - if (kInBraces) - { - syntaxLeaf.fUserValue = args; - syntaxLeaf.fUserValue += substr; - - syntaxLeaf.fUserValue += "\n\tblr\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - fnFound = true; - } - else - { - syntaxLeaf.fUserValue.clear(); - - syntaxLeaf.fUserValue += "export .code64 "; - - syntaxLeaf.fUserValue += substr; - syntaxLeaf.fUserValue += "\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - fnFound = true; - } - - kCompilerFunctions.push_back(textBuffer); - } - - if (textBuffer[text_index] == '-' && textBuffer[text_index + 1] == '-') - { - textBuffer = textBuffer.replace(textBuffer.find("--"), strlen("--"), ""); - - for (int _text_i = 0; _text_i < textBuffer.size(); ++_text_i) - { - if (textBuffer[_text_i] == '\t' || textBuffer[_text_i] == ' ') - textBuffer.erase(_text_i, 1); - } - - syntaxLeaf.fUserValue += "dec "; - syntaxLeaf.fUserValue += textBuffer; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - break; - } - - if (textBuffer[text_index] == '}') - { - kRegisterCounter = kStartUsable; - - --kBracesCount; - - if (kBracesCount < 1) - { - kInBraces = false; - kBracesCount = 0; - } - - if (kIfFound) - kIfFound = false; - - if (kInStruct) - kInStruct = false; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - syntaxLeaf.fUserValue.clear(); - } - - auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf(); - syntaxLeaf.fUserValue = "\n"; - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - return true; -} - -static bool kShouldHaveBraces = false; -static std::string kFnName; - -std::string CompilerBackendCLang::Check(const char* text, const char* file) -{ - std::string err_str; - std::string ln = text; - - if (ln.empty()) - { - return err_str; - } - - bool non_ascii_found = false; - - for (int i = 0; i < ln.size(); ++i) - { - if (isalnum(ln[i])) - { - non_ascii_found = true; - break; - } - } - - if (kShouldHaveBraces && ln.find('{') != std::string::npos) - { - kShouldHaveBraces = false; - } - - if (!non_ascii_found) - return err_str; - - size_t string_index = 1UL; - - if (ln.find('\'') != std::string::npos) - { - string_index = ln.find('\'') + 1; - - for (; string_index < ln.size(); ++string_index) - { - if (ln[string_index] == '\'') - { - if (ln[string_index + 1] != ';') - { - ln.erase(string_index, 1); - } - - return err_str; - } - } - } - else if (ln.find('"') != std::string::npos) - { - string_index = ln.find('"') + 1; - - for (; string_index < ln.size(); ++string_index) - { - if (ln[string_index] == '"') - { - if (ln[string_index + 1] != ';') - { - ln.erase(string_index, 1); - } - else - { - break; - } - } - } - } - else if (ln.find('"') == std::string::npos && - ln.find('\'') == std::string::npos) - { - std::vector forbidden_words; - - forbidden_words.push_back("\\"); - forbidden_words.push_back("?"); - forbidden_words.push_back("@"); - forbidden_words.push_back("~"); - forbidden_words.push_back("::"); - forbidden_words.push_back("/*"); - forbidden_words.push_back("*/"); - - // add them to avoid stupid mistakes. - forbidden_words.push_back("namespace"); - forbidden_words.push_back("class"); - forbidden_words.push_back("extern \"C\""); - - for (auto& forbidden : forbidden_words) - { - if (ln.find(forbidden) != std::string::npos) - { - err_str += "\nForbidden character detected: "; - err_str += forbidden; - - return err_str; - } - } - } - - struct CompilerVariableRange final - { - std::string fBegin; - std::string fEnd; - }; - - const std::vector variables_list = { - {.fBegin = "static ", .fEnd = "="}, - {.fBegin = "=", .fEnd = ";"}, - {.fBegin = "if(", .fEnd = "="}, - {.fBegin = "if (", .fEnd = "="}, - {.fBegin = "if(", .fEnd = "<"}, - {.fBegin = "if (", .fEnd = "<"}, - {.fBegin = "if(", .fEnd = ">"}, - {.fBegin = "if (", .fEnd = ">"}, - {.fBegin = "if(", .fEnd = ")"}, - {.fBegin = "if (", .fEnd = ")"}, - - {.fBegin = "else(", .fEnd = "="}, - {.fBegin = "else (", .fEnd = "="}, - {.fBegin = "else(", .fEnd = "<"}, - {.fBegin = "else (", .fEnd = "<"}, - {.fBegin = "else(", .fEnd = ">"}, - {.fBegin = "else (", .fEnd = ">"}, - {.fBegin = "else(", .fEnd = ")"}, - {.fBegin = "else (", .fEnd = ")"}, - }; - - for (auto& variable : variables_list) - { - if (ln.find(variable.fBegin) != std::string::npos) - { - string_index = ln.find(variable.fBegin) + variable.fBegin.size(); - - while (ln[string_index] == ' ') - ++string_index; - - std::string keyword; - - for (; string_index < ln.size(); ++string_index) - { - if (ln[string_index] == variable.fEnd[0]) - { - std::string varname = ""; - - for (size_t index_keyword = ln.find(' '); - ln[index_keyword] != variable.fBegin[0]; ++index_keyword) - { - if (ln[index_keyword] == ' ') - { - continue; - } - - if (isdigit(ln[index_keyword])) - { - goto cc_next_loop; - } - - varname += ln[index_keyword]; - } - - if (varname.find(' ') != std::string::npos) - { - varname.erase(0, varname.find(' ')); - - if (variable.fBegin == "extern") - { - varname.erase(0, varname.find(' ')); - } - } - - if (kRegisterCounter == 5 || kRegisterCounter == 6) - ++kRegisterCounter; - - std::string reg = kAsmRegisterPrefix; - reg += std::to_string(kRegisterCounter); - - kCompilerVariables.push_back({.fValue = varname}); - goto cc_check_done; - } - - keyword.push_back(ln[string_index]); - } - - goto cc_next_loop; - - cc_check_done: - - // skip digit value. - if (isdigit(keyword[0]) || keyword[0] == '"') - { - goto cc_next_loop; - } - - while (keyword.find(' ') != std::string::npos) - keyword.erase(keyword.find(' '), 1); - - for (auto& var : kCompilerVariables) - { - if (var.fValue.find(keyword) != std::string::npos) - { - err_str.clear(); - goto cc_next; - } - } - - for (auto& fn : kCompilerFunctions) - { - if (fn.find(keyword[0]) != std::string::npos) - { - auto where_begin = fn.find(keyword[0]); - auto keyword_begin = 0UL; - auto failed = false; - - for (; where_begin < keyword.size(); ++where_begin) - { - if (fn[where_begin] == '(' && keyword[keyword_begin] == '(') - break; - - if (fn[where_begin] != keyword[keyword_begin]) - { - failed = true; - break; - } - - ++keyword_begin; - } - - if (!failed) - { - err_str.clear(); - goto cc_next; - } - else - { - continue; - } - } - } - - cc_error_value: - if (keyword.find("->") != std::string::npos) - return err_str; - - if (keyword.find(".") != std::string::npos) - return err_str; - - if (isalnum(keyword[0])) - err_str += "\nUndefined value: " + keyword; - - return err_str; - } - - cc_next_loop: - continue; - } - -cc_next: - - // extern does not declare anything, it imports a variable. - // so that's why it's not declare upper. - if (ParserKit::find_word(ln, "extern")) - { - auto substr = ln.substr(ln.find("extern") + strlen("extern")); - kCompilerVariables.push_back({.fValue = substr}); - } - - if (kShouldHaveBraces && ln.find('{') == std::string::npos) - { - err_str += "Missing '{' for function "; - err_str += kFnName; - err_str += "\n"; - - kShouldHaveBraces = false; - kFnName.clear(); - } - else if (kShouldHaveBraces && ln.find('{') != std::string::npos) - { - kShouldHaveBraces = false; - kFnName.clear(); - } - - bool type_not_found = true; - - if (ln.find('\'') != std::string::npos) - { - ln.replace(ln.find('\''), 3, "0"); - } - - auto first = ln.find('"'); - if (first != std::string::npos) - { - auto second = 0UL; - bool found_second_quote = false; - - for (size_t i = first + 1; i < ln.size(); ++i) - { - if (ln[i] == '\"') - { - found_second_quote = true; - second = i; - - break; - } - } - - if (!found_second_quote) - { - err_str += "Missing terminating \"."; - err_str += " here -> " + ln.substr(ln.find('"'), second); - } - } - - if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos) - { - if (ln.find('{') == std::string::npos) - { - kFnName = ln; - kShouldHaveBraces = true; - - goto skip_braces_check; - } - else if (ln.find('{') != std::string::npos) - { - kShouldHaveBraces = false; - } - } - -skip_braces_check: - - for (auto& key : kCompilerTypes) - { - if (ParserKit::find_word(ln, key.fName)) - { - if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) - { - err_str += "\nNumber cannot be set for "; - err_str += key.fName; - err_str += "'s name. here -> "; - err_str += ln; - } - - if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' || - ln[ln.find(key.fName) - 1] == '\t') - { - type_not_found = false; - - if (ln[ln.find(key.fName) + key.fName.size()] != ' ') - { - type_not_found = true; - - if (ln[ln.find(key.fName) + key.fName.size()] == '\t') - type_not_found = false; - - goto next; - } - else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') - { - type_not_found = true; - - if (ln[ln.find(key.fName) + key.fName.size()] == ' ') - type_not_found = false; - } - } - - next: - - if (ln.find(';') == std::string::npos) - { - if (ln.find('(') != std::string::npos) - { - if (ln.find('=') == std::string::npos) - continue; - } - - err_str += "\nMissing ';', here -> "; - err_str += ln; - } - else - { - continue; - } - - if (ln.find('=') != std::string::npos) - { - if (ln.find('(') != std::string::npos) - { - if (ln.find(')') == std::string::npos) - { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } - } - } - } - } - - if (kInBraces && ln.find("struct") != std::string::npos && - ln.find("union") != std::string::npos && - ln.find("enum") != std::string::npos && - ln.find('=') != std::string::npos) - { - if (ln.find(';') == std::string::npos) - { - err_str += "\nMissing ';' after struct/union/enum declaration, here -> "; - err_str += ln; - } - } - - if (ln.find(';') != std::string::npos && - ln.find("for") == std::string::npos) - { - if (ln.find(';') + 1 != ln.size()) - { - for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) - { - if ((ln.substr(ln.find(';') + 1)[i] != ' ') || - (ln.substr(ln.find(';') + 1)[i] != '\t')) - { - if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); - !err.empty()) - { - err_str += "\nUnexpected text after ';' -> "; - err_str += ln.substr(ln.find(';')); - err_str += err; - } - } - } - } - } - - if (ln.find('(') != std::string::npos) - { - if (ln.find(';') == std::string::npos && !ParserKit::find_word(ln, "|") && - !ParserKit::find_word(ln, "||") && !ParserKit::find_word(ln, "&") && - !ParserKit::find_word(ln, "&&") && !ParserKit::find_word(ln, "~")) - { - bool found_func = false; - size_t i = ln.find('('); - std::vector opens; - std::vector closes; - - for (; i < ln.size(); ++i) - { - if (ln[i] == ')') - { - closes.push_back(1); - } - - if (ln[i] == '(') - { - opens.push_back(1); - } - } - - if (closes.size() != opens.size()) - err_str += "Unterminated (), here -> " + ln; - - bool space_found = false; - - for (int i = 0; i < ln.size(); ++i) - { - if (ln[i] == ')' && !space_found) - { - space_found = true; - continue; - } - - if (space_found) - { - if (ln[i] == ' ' && isalnum(ln[i + 1])) - { - err_str += "\nBad function format here -> "; - err_str += ln; - } - } - } - } - - if (ln.find('(') < 1) - { - err_str += "\nMissing identifier before '(' here -> "; - err_str += ln; - } - else - { - if (type_not_found && ln.find(';') == std::string::npos && - ln.find("if") == std::string::npos && - ln.find("|") == std::string::npos && - ln.find("&") == std::string::npos && - ln.find("(") == std::string::npos && - ln.find(")") == std::string::npos) - { - err_str += "\n Missing ';' or type, here -> "; - err_str += ln; - } - } - - if (ln.find(')') == std::string::npos) - { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } - } - else - { - if (ln.find("for") != std::string::npos || - ln.find("while") != std::string::npos) - { - err_str += "\nMissing '(', after \"for\", here -> "; - err_str += ln; - } - } - - if (ln.find('}') != std::string::npos && !kInBraces) - { - if (!kInStruct && ln.find(';') == std::string::npos) - { - err_str += "\nMismatched '}', here -> "; - err_str += ln; - } - } - - if (!ln.empty()) - { - if (ln.find(';') == std::string::npos && - ln.find('{') == std::string::npos && - ln.find('}') == std::string::npos && - ln.find(')') == std::string::npos && - ln.find('(') == std::string::npos && - ln.find(',') == std::string::npos) - { - if (ln.size() <= 2) - return err_str; - - err_str += "\nMissing ';', here -> "; - err_str += ln; - } - } - - return err_str; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -/** - * @brief C To Assembly mount-point. - */ - -///////////////////////////////////////////////////////////////////////////////////////// - -class AssemblyMountpointCLang final : public CompilerKit::AssemblyInterface -{ -public: - explicit AssemblyMountpointCLang() = default; - ~AssemblyMountpointCLang() override = default; - - MPCC_COPY_DEFAULT(AssemblyMountpointCLang); - - [[maybe_unused]] static Int32 Arch() noexcept - { - return CompilerKit::AssemblyFactory::kArchPowerPC; - } - - Int32 CompileToFormat(std::string& src, Int32 arch) override - { - if (arch != AssemblyMountpointCLang::Arch()) - return -1; - - if (kCompilerBackend == nullptr) - return -1; - - /* @brief copy contents wihtout extension */ - std::string src_file = src.data(); - std::ifstream src_fp = std::ifstream(src_file, std::ios::in); - std::string dest; - - for (auto& ch : src_file) - { - if (ch == '.') - { - break; - } - - dest += ch; - } - - /* According to PEF ABI. */ - std::vector exts = kAsmFileExts; - dest += exts[4]; - - kState.fOutputAssembly = std::make_unique(dest); - - auto fmt = CompilerKit::current_date(); - - (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; - (*kState.fOutputAssembly) - << "# Language: POWER Assembly (Generated from C)\n"; - (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n"; - - ParserKit::SyntaxLeafList syntax; - - kState.fSyntaxTreeList.push_back(syntax); - kState.fSyntaxTree = - &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; - - std::string line_src; - - while (std::getline(src_fp, line_src)) - { - if (auto err = kCompilerBackend->Check(line_src.c_str(), src.data()); - err.empty()) - { - kCompilerBackend->Compile(line_src, src.data()); - } - else - { - detail::print_error(err, src.data()); - } - } - - if (kAcceptableErrors > 0) - return -1; - - std::vector keywords = {"ld", "stw", "add", "sub", "or"}; - - /// - /// Replace, optimize, fix assembly output. - /// - - for (auto& leaf : kState.fSyntaxTree->fLeafList) - { - std::vector access_keywords = {"->", "."}; - - for (auto& access_ident : access_keywords) - { - if (ParserKit::find_word(leaf.fUserValue, access_ident)) - { - for (auto& struc : kState.kStructMap) - { - /// TODO: - } - } - } - - for (auto& keyword : keywords) - { - if (ParserKit::find_word(leaf.fUserValue, keyword)) - { - std::size_t cnt = 0UL; - - for (auto& reg : kState.kStackFrame) - { - std::string needle; - - for (size_t i = 0; i < reg.fName.size(); i++) - { - if (reg.fName[i] == ' ') - { - ++i; - - for (; i < reg.fName.size(); i++) - { - if (reg.fName[i] == ',') - { - break; - } - - if (reg.fName[i] == ' ') - continue; - - needle += reg.fName[i]; - } - - break; - } - } - - if (ParserKit::find_word(leaf.fUserValue, needle)) - { - if (leaf.fUserValue.find("import ") != std::string::npos) - { - std::string range = "import "; - leaf.fUserValue.replace(leaf.fUserValue.find(range), - range.size(), ""); - } - - if (leaf.fUserValue.find("ldw r6") != std::string::npos) - { - std::string::difference_type countComma = std::count( - leaf.fUserValue.begin(), leaf.fUserValue.end(), ','); - - if (countComma == 1) - { - leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), - strlen("ldw"), "mr"); - } - } - - leaf.fUserValue.replace(leaf.fUserValue.find(needle), - needle.size(), reg.fReg); - - ++cnt; - } - } - - if (cnt > 1 && keyword != "mr" && keyword != "add" && - keyword != "dec") - { - leaf.fUserValue.replace(leaf.fUserValue.find(keyword), - keyword.size(), "mr"); - } - } - } - } - - for (auto& leaf : kState.fSyntaxTree->fLeafList) - { - (*kState.fOutputAssembly) << leaf.fUserValue; - } - - kState.fSyntaxTree = nullptr; - - kState.fOutputAssembly->flush(); - kState.fOutputAssembly.reset(); - - return kOk; - } -}; - -///////////////////////////////////////////////////////////////////////////////////////// - -#include - -#define kPrintF printf -#define kSplashCxx() \ - kPrintF(kWhite "cc, %s, (c) SoftwareLabs\n", kDistVersion) - -static void cc_print_help() -{ - kSplashCxx(); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -#define kExt ".c" - -MPCC_MODULE(NewOSCompilerCLangPowerPC) -{ - kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); - kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); - kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); - kCompilerTypes.push_back({.fName = "int", .fValue = "dword"}); - kCompilerTypes.push_back({.fName = "long", .fValue = "qword"}); - kCompilerTypes.push_back({.fName = "*", .fValue = "offset"}); - - bool skip = false; - - kFactory.Mount(new AssemblyMountpointCLang()); - kMachine = CompilerKit::AssemblyFactory::kArchPowerPC; - kCompilerBackend = new CompilerBackendCLang(); - - for (auto index = 1UL; index < argc; ++index) - { - if (skip) - { - skip = false; - continue; - } - - if (argv[index][0] == '-') - { - if (strcmp(argv[index], "-v") == 0 || - strcmp(argv[index], "-version") == 0) - { - kSplashCxx(); - return kOk; - } - - if (strcmp(argv[index], "-verbose") == 0) - { - kState.fVerbose = true; - - continue; - } - - if (strcmp(argv[index], "-h") == 0 || strcmp(argv[index], "-help") == 0) - { - cc_print_help(); - - return kOk; - } - - if (strcmp(argv[index], "-dialect") == 0) - { - if (kCompilerBackend) - std::cout << kCompilerBackend->Language() << "\n"; - - return kOk; - } - - if (strcmp(argv[index], "-fmax-exceptions") == 0) - { - try - { - kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); - } - // catch anything here - catch (...) - { - kErrorLimit = 0; - } - - skip = true; - - continue; - } - - std::string err = "Unknown command: "; - err += argv[index]; - - detail::print_error(err, "cc"); - - continue; - } - - kFileList.emplace_back(argv[index]); - - std::string srcFile = argv[index]; - - if (strstr(argv[index], kExt) == nullptr) - { - if (kState.fVerbose) - { - detail::print_error(srcFile + " is not a valid C source.\n", "cc"); - } - - return 1; - } - - if (kFactory.Compile(srcFile, kMachine) != kOk) - return -1; - } - - return kOk; -} - -// Last rev 8-1-24 diff --git a/Sources/ppcasm.cc b/Sources/ppcasm.cc index 5c444dd..0236491 100644 --- a/Sources/ppcasm.cc +++ b/Sources/ppcasm.cc @@ -17,12 +17,12 @@ #define __ASM_NEED_PPC__ 1 -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/bpp.rsrc b/bpp.rsrc index 6ed8ac5..3a8d4d9 100644 --- a/bpp.rsrc +++ b/bpp.rsrc @@ -1,4 +1,4 @@ -#include "Headers/Version.hxx" +#include "Common/Version.hxx" 1 ICON "Icons/app-logo.ico" @@ -11,7 +11,7 @@ BEGIN BLOCK "080904E4" BEGIN VALUE "CompanyName", "SoftwareLabs" - VALUE "FileDescription", "NewOS Assembler Preprocessor." + VALUE "FileDescription", "SoftwareLabs Preprocessor." VALUE "FileVersion", kDistVersion VALUE "InternalName", "NewPreprocessor" VALUE "LegalCopyright", "SoftwareLabs" diff --git a/docs/Inside 64x0.pdf b/docs/Inside 64x0.pdf new file mode 100644 index 0000000..bcd6782 Binary files /dev/null and b/docs/Inside 64x0.pdf differ diff --git a/docs/asm-specs.txt b/docs/asm-specs.txt new file mode 100644 index 0000000..a0c42bf --- /dev/null +++ b/docs/asm-specs.txt @@ -0,0 +1,11 @@ +==================== +X86 ASSEMBLER SPECS +==================== + +WHAT TO DO: + Provide a complete support of x86-64 with: + + - org directive. + - 64-bit and 32-bit registers. + - basic instructions (load, store, jump to) + - flushable into object-code and flat binary. \ No newline at end of file diff --git a/docs/havp.txt b/docs/havp.txt new file mode 100644 index 0000000..12fcec5 --- /dev/null +++ b/docs/havp.txt @@ -0,0 +1,13 @@ +HAVP - Harvard Audio/Video Processor + +- Encoding: IBAD + +- Data path = 24 + - 16: sound data + - 8: information data + +- Register size: 32 +- Store strategy: shift registers. +- Standard registers: [ r0, r9 ] +- Floating point registers: [ f0, f2 ] +- Builtin SRAM: 512kb diff --git a/docs/notice.txt b/docs/notice.txt new file mode 100644 index 0000000..23691da --- /dev/null +++ b/docs/notice.txt @@ -0,0 +1,4 @@ +The X64000 draft papers +They contain thing that might appear through the next iteration of 64k. + +Please look at the document shared for the latest revisions. \ No newline at end of file diff --git a/docs/vnrp.txt b/docs/vnrp.txt new file mode 100644 index 0000000..e17b494 --- /dev/null +++ b/docs/vnrp.txt @@ -0,0 +1,17 @@ +VNRP - Von Neumann, RISC Processor + +- Encoding = RegToReg, Imm, Syscall, Jump, NoArgs + +- Data path = 128-bit (register data) +- Addressing = 58-bit physical address size. + +- Registers (128-bit) = r0, r19 +- Float/Vector registers (128-bit) = f0, f9 + +- Out of order (superscalar also added to the equation) = Yes +- Superscalar = Yes + +- L1 cache: 16kb (8 instr, 8 data) +- L2 cache: 1024kb (512 instr, 512 data) + +- Clock speed: 1 Ghz diff --git a/i64asm.rsrc b/i64asm.rsrc index 2f981a6..4472b3f 100644 --- a/i64asm.rsrc +++ b/i64asm.rsrc @@ -1,4 +1,4 @@ -#include "Headers/Version.hxx" +#include "Common/Version.hxx" 1 ICON "Icons/app-logo.ico" @@ -11,12 +11,12 @@ BEGIN BLOCK "080904E4" BEGIN VALUE "CompanyName", "SoftwareLabs" - VALUE "FileDescription", "NewOS AMD64 assembler." + VALUE "FileDescription", "SoftwareLabs assembler for AMD64." VALUE "FileVersion", kDistVersion - VALUE "InternalName", "NewAssembler" + VALUE "InternalName", "Assembler" VALUE "LegalCopyright", "SoftwareLabs" VALUE "OriginalFilename", "i64asm.exe" - VALUE "ProductName", "NewAssembler" + VALUE "ProductName", "Assembler" VALUE "ProductVersion", kDistVersion END END diff --git a/link.rsrc b/link.rsrc index 9661b04..550d87a 100644 --- a/link.rsrc +++ b/link.rsrc @@ -1,4 +1,4 @@ -#include "Headers/Version.hxx" +#include "Common/Version.hxx" 1 ICON "Icons/app-logo.ico" @@ -13,10 +13,10 @@ BEGIN VALUE "CompanyName", "SoftwareLabs" VALUE "FileDescription", "NewOS linker." VALUE "FileVersion", kDistVersion - VALUE "InternalName", "NewLinker" + VALUE "InternalName", "Linker" VALUE "LegalCopyright", "SoftwareLabs" VALUE "OriginalFilename", "link.exe" - VALUE "ProductName", "NewLinker" + VALUE "ProductName", "Linker" VALUE "ProductVersion", kDistVersion END END diff --git a/posix.make b/posix.make index 4e47c53..0a6ef8e 100644 --- a/posix.make +++ b/posix.make @@ -7,7 +7,7 @@ # ======================================================== # -COMMON_INC=-I./Headers -I./ -I./Sources/Detail +COMMON_INC=-I./Common -I./ -I./Sources/Detail LINK_CC=g++ -std=c++20 LINK_SRC=Sources/link.cc LINK_OUTPUT=Output/link.exec @@ -30,8 +30,8 @@ AMD64_CXX_OUTPUT=Output/cplusplus.exec 64X0_CC_OUTPUT=Output/64x0-cc.exec # C Compiler (Our own RISC) -PPC_CC_SRC=Sources/ppc-cc.cc $(SRC_COMMON) -PPC_CC_OUTPUT=Output/ppc-cc.exec +PPC_CC_SRC=Sources/power-cc.cc $(SRC_COMMON) +PPC_CC_OUTPUT=Output/power-cc.exec # 64x0 Assembler (Our Own RISC) ASM_SRC=Sources/64asm.cc $(SRC_COMMON) diff --git a/power-cc.rsrc b/power-cc.rsrc new file mode 100644 index 0000000..4a10e6b --- /dev/null +++ b/power-cc.rsrc @@ -0,0 +1,27 @@ +#include "Common/Version.hxx" + +1 ICON "Icons/app-logo.ico" + +1 VERSIONINFO +FILEVERSION 1,0,0,0 +PRODUCTVERSION 1,0,0,0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080904E4" + BEGIN + VALUE "CompanyName", "SoftwareLabs" + VALUE "FileDescription", "SoftwareLabs C Compiler for POWER." + VALUE "FileVersion", kDistVersion + VALUE "InternalName", "Compiler" + VALUE "LegalCopyright", "SoftwareLabs" + VALUE "OriginalFilename", "power-cc.exe" + VALUE "ProductName", "Compiler" + VALUE "ProductVersion", kDistVersion + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x809, 1252 + END +END diff --git a/ppc-cc.rsrc b/ppc-cc.rsrc deleted file mode 100644 index 031dd4e..0000000 --- a/ppc-cc.rsrc +++ /dev/null @@ -1,27 +0,0 @@ -#include "Headers/Version.hxx" - -1 ICON "Icons/app-logo.ico" - -1 VERSIONINFO -FILEVERSION 1,0,0,0 -PRODUCTVERSION 1,0,0,0 -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "080904E4" - BEGIN - VALUE "CompanyName", "SoftwareLabs" - VALUE "FileDescription", "NewOS POWER C compiler." - VALUE "FileVersion", kDistVersion - VALUE "InternalName", "NewC" - VALUE "LegalCopyright", "SoftwareLabs" - VALUE "OriginalFilename", "ppc-cc.exe" - VALUE "ProductName", "NewC" - VALUE "ProductVersion", kDistVersion - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x809, 1252 - END -END diff --git a/ppcasm.rsrc b/ppcasm.rsrc index 4d3affe..cf3fbb9 100644 --- a/ppcasm.rsrc +++ b/ppcasm.rsrc @@ -1,4 +1,4 @@ -#include "Headers/Version.hxx" +#include "Common/Version.hxx" 1 ICON "Icons/app-logo.ico" @@ -11,12 +11,12 @@ BEGIN BLOCK "080904E4" BEGIN VALUE "CompanyName", "SoftwareLabs" - VALUE "FileDescription", "NewOS POWER assembler." + VALUE "FileDescription", "SoftwareLabs assembler for POWER." VALUE "FileVersion", kDistVersion - VALUE "InternalName", "NewAssembler" + VALUE "InternalName", "Assembler" VALUE "LegalCopyright", "SoftwareLabs" VALUE "OriginalFilename", "ppcasm.exe" - VALUE "ProductName", "NewAssembler" + VALUE "ProductName", "Assembler" VALUE "ProductVersion", kDistVersion END END diff --git a/win64.make b/win64.make index 0d8482d..1e70bfd 100644 --- a/win64.make +++ b/win64.make @@ -7,7 +7,7 @@ # ======================================================== # -COMMON_INC=-I./Headers -I./ -I./Sources/Detail +COMMON_INC=-I./Common -I./ -I./Sources/Detail LINK_CC=x86_64-w64-mingw32-g++.exe -std=c++20 -Xlinker -s WINRES=x86_64-w64-mingw32-windres LINK_SRC=Sources/link.cc @@ -30,8 +30,8 @@ AMD64_CXX_OUTPUT=Output/cplusplus.exe 64X0_CC_OUTPUT=Output/64x0-cc.exe # C Compiler -PPC_CC_SRC=Sources/ppc-cc.cc $(SRC_COMMON) -PPC_CC_OUTPUT=Output/ppc-cc.exe +PPC_CC_SRC=Sources/power-cc.cc $(SRC_COMMON) +PPC_CC_OUTPUT=Output/power-cc.exe # 64x0 Assembler ASM_SRC=Sources/64asm.cc $(SRC_COMMON) @@ -60,10 +60,10 @@ compiler: $(WINRES) 64asm.rsrc -O coff -o 64asm.obj $(WINRES) ppcasm.rsrc -O coff -o ppcasm.obj $(WINRES) 64x0-cc.rsrc -O coff -o 64x0-cc.obj - $(WINRES) ppc-cc.rsrc -O coff -o ppc-cc.obj + $(WINRES) power-cc.rsrc -O coff -o power-cc.obj $(LINK_CC) $(COMMON_INC) 64x0-cc.obj $(64X0_CC_SRC) -o $(64X0_CC_OUTPUT) $(LINK_CC) $(COMMON_INC) $(AMD64_CXX_SRC) -o $(AMD64_CXX_OUTPUT) - $(LINK_CC) $(COMMON_INC) ppc-cc.obj $(PPC_CC_SRC) -o $(PPC_CC_OUTPUT) + $(LINK_CC) $(COMMON_INC) power-cc.obj $(PPC_CC_SRC) -o $(PPC_CC_OUTPUT) $(LINK_CC) $(COMMON_INC) i64asm.obj $(IASM_SRC) -o $(IASM_OUTPUT) $(LINK_CC) $(COMMON_INC) 64asm.obj $(ASM_SRC) -o $(ASM_OUTPUT) $(LINK_CC) $(COMMON_INC) ppcasm.obj $(PPCASM_SRC) -o $(PPCASM_OUTPUT) -- cgit v1.2.3 From d0b25baeca4f807b43cff3bda2efd03fdff96728 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Sat, 1 Jun 2024 12:22:17 +0200 Subject: publishing my work. Signed-off-by: Amlal El Mahrouss --- 64asm.rsrc | 6 +++--- 64x0-cc.rsrc | 6 +++--- Common/AsmKit/AsmKit.hpp | 2 +- Common/AsmKit/CPU/32x0.hpp | 2 +- Common/AsmKit/CPU/64x0.hpp | 2 +- Common/AsmKit/CPU/amd64.hpp | 2 +- Common/CompilerKit.hpp | 2 +- Common/Defines.hpp | 2 +- Common/ParserKit.hpp | 2 +- Common/Public/SDK/CRT/__mpcc_alloca.hxx | 2 +- Common/Public/SDK/CRT/__mpcc_defines.hxx | 2 +- Common/Public/SDK/CRT/__mpcc_exception.hxx | 2 +- Common/Public/SDK/CRT/__mpcc_hint.hxx | 2 +- Common/Public/SDK/CRT/__mpcc_malloc.hxx | 2 +- Common/StdKit/AE.hpp | 2 +- Common/StdKit/ErrorID.hpp | 2 +- Common/StdKit/ErrorOr.hpp | 2 +- Common/StdKit/PEF.hpp | 2 +- Common/StdKit/Ref.hpp | 2 +- Common/StdKit/String.hpp | 2 +- Common/StdKit/XCOFF.hxx | 2 +- ReadMe.md | 2 +- Sources/32asm.cc | 2 +- Sources/64asm.cc | 4 ++-- Sources/64x0-cc.cc | 6 +++--- Sources/AssemblyFactory.cc | 4 ++-- Sources/Detail/asmutils.hxx | 2 +- Sources/Detail/compilerutils.hxx | 2 +- Sources/String.cc | 4 ++-- Sources/bpp.cc | 6 +++--- Sources/coff2ae.cc | 2 +- Sources/cplusplus.cc | 10 +++++----- Sources/elf2ae.cc | 2 +- Sources/i64asm.cc | 6 +++--- Sources/link.cc | 8 ++++---- Sources/power-cc.cc | 4 ++-- Sources/ppcasm.cc | 6 +++--- bpp.rsrc | 6 +++--- i64asm.rsrc | 6 +++--- link.rsrc | 4 ++-- posix.make | 4 ++-- power-cc.rsrc | 6 +++--- ppcasm.rsrc | 6 +++--- win64.make | 4 ++-- 44 files changed, 78 insertions(+), 78 deletions(-) (limited to 'Sources/String.cc') diff --git a/64asm.rsrc b/64asm.rsrc index 9f473f1..c01fa7a 100644 --- a/64asm.rsrc +++ b/64asm.rsrc @@ -10,11 +10,11 @@ BEGIN BEGIN BLOCK "080904E4" BEGIN - VALUE "CompanyName", "SoftwareLabs" - VALUE "FileDescription", "SoftwareLabs assembler for 64x000." + VALUE "CompanyName", "Amlal El Mahrouss" + VALUE "FileDescription", "Amlal El Mahrouss assembler for 64x000." VALUE "FileVersion", kDistVersion VALUE "InternalName", "Assembler" - VALUE "LegalCopyright", "SoftwareLabs" + VALUE "LegalCopyright", "Amlal El Mahrouss" VALUE "OriginalFilename", "64asm.exe" VALUE "ProductName", "Assembler" VALUE "ProductVersion", kDistVersion diff --git a/64x0-cc.rsrc b/64x0-cc.rsrc index 300c684..78d23b4 100644 --- a/64x0-cc.rsrc +++ b/64x0-cc.rsrc @@ -10,11 +10,11 @@ BEGIN BEGIN BLOCK "080904E4" BEGIN - VALUE "CompanyName", "SoftwareLabs" - VALUE "FileDescription", "SoftwareLabs C Compiler for 64x000." + VALUE "CompanyName", "Amlal El Mahrouss" + VALUE "FileDescription", "Amlal El Mahrouss C Compiler for 64x000." VALUE "FileVersion", kDistVersion VALUE "InternalName", "Compiler" - VALUE "LegalCopyright", "SoftwareLabs" + VALUE "LegalCopyright", "Amlal El Mahrouss" VALUE "OriginalFilename", "64x0-cc.exe" VALUE "ProductName", "Compiler" VALUE "ProductVersion", kDistVersion diff --git a/Common/AsmKit/AsmKit.hpp b/Common/AsmKit/AsmKit.hpp index 020ca5c..f4aecaf 100644 --- a/Common/AsmKit/AsmKit.hpp +++ b/Common/AsmKit/AsmKit.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Common/AsmKit/CPU/32x0.hpp b/Common/AsmKit/CPU/32x0.hpp index fe03336..94ec43a 100644 --- a/Common/AsmKit/CPU/32x0.hpp +++ b/Common/AsmKit/CPU/32x0.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Common/AsmKit/CPU/64x0.hpp b/Common/AsmKit/CPU/64x0.hpp index b28866f..48ebf95 100644 --- a/Common/AsmKit/CPU/64x0.hpp +++ b/Common/AsmKit/CPU/64x0.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Common/AsmKit/CPU/amd64.hpp b/Common/AsmKit/CPU/amd64.hpp index 507602c..92e649a 100644 --- a/Common/AsmKit/CPU/amd64.hpp +++ b/Common/AsmKit/CPU/amd64.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Common/CompilerKit.hpp b/Common/CompilerKit.hpp index b9de089..9abe154 100644 --- a/Common/CompilerKit.hpp +++ b/Common/CompilerKit.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Common/Defines.hpp b/Common/Defines.hpp index d76620c..3bf1ea8 100644 --- a/Common/Defines.hpp +++ b/Common/Defines.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Common/ParserKit.hpp b/Common/ParserKit.hpp index 6e15c75..98d078d 100644 --- a/Common/ParserKit.hpp +++ b/Common/ParserKit.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Common/Public/SDK/CRT/__mpcc_alloca.hxx b/Common/Public/SDK/CRT/__mpcc_alloca.hxx index a1c638e..b653682 100644 --- a/Common/Public/SDK/CRT/__mpcc_alloca.hxx +++ b/Common/Public/SDK/CRT/__mpcc_alloca.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Common/Public/SDK/CRT/__mpcc_defines.hxx b/Common/Public/SDK/CRT/__mpcc_defines.hxx index 5560410..1230662 100644 --- a/Common/Public/SDK/CRT/__mpcc_defines.hxx +++ b/Common/Public/SDK/CRT/__mpcc_defines.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Common/Public/SDK/CRT/__mpcc_exception.hxx b/Common/Public/SDK/CRT/__mpcc_exception.hxx index 9366102..663a5d2 100644 --- a/Common/Public/SDK/CRT/__mpcc_exception.hxx +++ b/Common/Public/SDK/CRT/__mpcc_exception.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Common/Public/SDK/CRT/__mpcc_hint.hxx b/Common/Public/SDK/CRT/__mpcc_hint.hxx index ee14711..3168e8e 100644 --- a/Common/Public/SDK/CRT/__mpcc_hint.hxx +++ b/Common/Public/SDK/CRT/__mpcc_hint.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Common/Public/SDK/CRT/__mpcc_malloc.hxx b/Common/Public/SDK/CRT/__mpcc_malloc.hxx index 2731868..3fd7fcc 100644 --- a/Common/Public/SDK/CRT/__mpcc_malloc.hxx +++ b/Common/Public/SDK/CRT/__mpcc_malloc.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Common/StdKit/AE.hpp b/Common/StdKit/AE.hpp index 9c4ac1a..4755b06 100644 --- a/Common/StdKit/AE.hpp +++ b/Common/StdKit/AE.hpp @@ -2,7 +2,7 @@ * ======================================================== * * MPCC - * Copyright SoftwareLabs, all rights reserved. + * Copyright Amlal El Mahrouss, all rights reserved. * * ======================================================== */ diff --git a/Common/StdKit/ErrorID.hpp b/Common/StdKit/ErrorID.hpp index 9f12ab2..92d2172 100644 --- a/Common/StdKit/ErrorID.hpp +++ b/Common/StdKit/ErrorID.hpp @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright SoftwareLabs, all rights reserved. + * Copyright Amlal El Mahrouss, all rights reserved. * * ======================================================== */ diff --git a/Common/StdKit/ErrorOr.hpp b/Common/StdKit/ErrorOr.hpp index cf35b26..7ad6e8d 100644 --- a/Common/StdKit/ErrorOr.hpp +++ b/Common/StdKit/ErrorOr.hpp @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright SoftwareLabs, all rights reserved. + * Copyright Amlal El Mahrouss, all rights reserved. * * ======================================================== */ diff --git a/Common/StdKit/PEF.hpp b/Common/StdKit/PEF.hpp index b084f32..e82e5ef 100644 --- a/Common/StdKit/PEF.hpp +++ b/Common/StdKit/PEF.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Common/StdKit/Ref.hpp b/Common/StdKit/Ref.hpp index d13f97c..7ba4d95 100644 --- a/Common/StdKit/Ref.hpp +++ b/Common/StdKit/Ref.hpp @@ -3,7 +3,7 @@ * ======================================================== * * CompilerKit - * Copyright SoftwareLabs, all rights reserved. + * Copyright Amlal El Mahrouss, all rights reserved. * * ======================================================== */ diff --git a/Common/StdKit/String.hpp b/Common/StdKit/String.hpp index a05a31c..3da302c 100644 --- a/Common/StdKit/String.hpp +++ b/Common/StdKit/String.hpp @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright SoftwareLabs, all rights reserved. + * Copyright Amlal El Mahrouss, all rights reserved. * * ======================================================== */ diff --git a/Common/StdKit/XCOFF.hxx b/Common/StdKit/XCOFF.hxx index a26b591..6e9fd6d 100644 --- a/Common/StdKit/XCOFF.hxx +++ b/Common/StdKit/XCOFF.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss File: XCOFF.hpp Purpose: XCOFF for NewOS. diff --git a/ReadMe.md b/ReadMe.md index 82b3217..47e0e89 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -14,4 +14,4 @@ make all Author: Amlal El Mahrouss -##### Copyright SoftwareLabs, all rights reserved. +##### Copyright Amlal El Mahrouss, all rights reserved. diff --git a/Sources/32asm.cc b/Sources/32asm.cc index f877553..3f98cb7 100644 --- a/Sources/32asm.cc +++ b/Sources/32asm.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Sources/64asm.cc b/Sources/64asm.cc index 6e8cc6d..587d5c3 100644 --- a/Sources/64asm.cc +++ b/Sources/64asm.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ @@ -110,7 +110,7 @@ MPCC_MODULE(NewOSAssembler64000) { if (argv[i][0] == '-') { if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { kStdOut << "64asm: 64x0 Assembler.\n64asm: v1.10\n64asm: Copyright (c) " - "2024 SoftwareLabs.\n"; + "2024 Amlal El Mahrouss.\n"; return 0; } else if (strcmp(argv[i], "-h") == 0) { kStdOut << "64asm: 64x0 Assembler.\n64asm: Copyright (c) 2024 Mahrouss " diff --git a/Sources/64x0-cc.cc b/Sources/64x0-cc.cc index 3a0e569..e3a0771 100644 --- a/Sources/64x0-cc.cc +++ b/Sources/64x0-cc.cc @@ -2,7 +2,7 @@ * ======================================================== * * cc - * Copyright SoftwareLabs, all rights reserved. + * Copyright Amlal El Mahrouss, all rights reserved. * * ======================================================== */ @@ -27,7 +27,7 @@ /* C driver */ /* This is part of MPCC C SDK. */ -/* (c) SoftwareLabs */ +/* (c) Amlal El Mahrouss */ /// @author Amlal El Mahrouss (amlel) /// @file 64x0-cc.cc @@ -1513,7 +1513,7 @@ public: #define kPrintF printf #define kSplashCxx() \ - kPrintF(kWhite "cc, %s, (c) SoftwareLabs\n", kDistVersion) + kPrintF(kWhite "cc, %s, (c) Amlal El Mahrouss\n", kDistVersion) static void cc_print_help() { diff --git a/Sources/AssemblyFactory.cc b/Sources/AssemblyFactory.cc index 0000ab7..3b2fb7c 100644 --- a/Sources/AssemblyFactory.cc +++ b/Sources/AssemblyFactory.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ @@ -14,7 +14,7 @@ * @version 0.1 * @date 2024-01-27 * - * @copyright Copyright (c) 2024, SoftwareLabs + * @copyright Copyright (c) 2024, Amlal El Mahrouss * */ diff --git a/Sources/Detail/asmutils.hxx b/Sources/Detail/asmutils.hxx index f6fdb41..d0eb2c7 100644 --- a/Sources/Detail/asmutils.hxx +++ b/Sources/Detail/asmutils.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Sources/Detail/compilerutils.hxx b/Sources/Detail/compilerutils.hxx index 9ddd3a2..a9332f4 100644 --- a/Sources/Detail/compilerutils.hxx +++ b/Sources/Detail/compilerutils.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Sources/String.cc b/Sources/String.cc index 38bd444..7926441 100644 --- a/Sources/String.cc +++ b/Sources/String.cc @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright SoftwareLabs, all rights reserved. + * Copyright Amlal El Mahrouss, all rights reserved. * * ======================================================== */ @@ -14,7 +14,7 @@ * @version 0.2 * @date 2024-01-23 * - * @copyright Copyright (c) 2024 SoftwareLabs + * @copyright Copyright (c) 2024 Amlal El Mahrouss * */ diff --git a/Sources/bpp.cc b/Sources/bpp.cc index accbef5..27dba78 100644 --- a/Sources/bpp.cc +++ b/Sources/bpp.cc @@ -2,7 +2,7 @@ * ======================================================== * * bpp - * Copyright SoftwareLabs, all rights reserved. + * Copyright Amlal El Mahrouss, all rights reserved. * * ======================================================== */ @@ -812,12 +812,12 @@ MPCC_MODULE(NewOSPreprocessor) { if (argv[index][0] == '-') { if (strcmp(argv[index], "-v") == 0) { - printf("%s\n", "bpp v1.11, (c) SoftwareLabs"); + printf("%s\n", "bpp v1.11, (c) Amlal El Mahrouss"); return 0; } if (strcmp(argv[index], "-h") == 0) { - printf("%s\n", "bpp v1.11, (c) SoftwareLabs"); + printf("%s\n", "bpp v1.11, (c) Amlal El Mahrouss"); printf("%s\n", "-working-dir : set directory to working path."); printf("%s\n", "-include-dir : add directory to include path."); printf("%s\n", "-def : def macro."); diff --git a/Sources/coff2ae.cc b/Sources/coff2ae.cc index 349d543..6baa964 100644 --- a/Sources/coff2ae.cc +++ b/Sources/coff2ae.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Sources/cplusplus.cc b/Sources/cplusplus.cc index db33688..d03987c 100644 --- a/Sources/cplusplus.cc +++ b/Sources/cplusplus.cc @@ -2,7 +2,7 @@ * ======================================================== * * cplusplus - * Copyright SoftwareLabs, all rights reserved. + * Copyright Amlal El Mahrouss, all rights reserved. * * ======================================================== */ @@ -14,7 +14,7 @@ #define kPrintF printf #define kSplashCxx() \ - kPrintF(kWhite "%s\n", "LightSpeed C++ Compiler, Copyright SoftwareLabs.") + kPrintF(kWhite "%s\n", "LightSpeed C++ Compiler, Copyright Amlal El Mahrouss.") #include #include @@ -29,9 +29,9 @@ #define kOk 0 -/* SoftwareLabs C++ driver */ +/* Amlal El Mahrouss C++ driver */ /* This is part of MPCC C++ compiler. */ -/* (c) SoftwareLabs */ +/* (c) Amlal El Mahrouss */ /// @author Amlal El Mahrouss (amlel) /// @file cc.cc @@ -170,7 +170,7 @@ static bool kOnForLoop = false; static bool kInBraces = false; static size_t kBracesCount = 0UL; -/* @brief C++ compiler backend for SoftwareLabs C++ */ +/* @brief C++ compiler backend for Amlal El Mahrouss C++ */ class CompilerBackendCPlusPlus final : public ParserKit::CompilerBackend { public: diff --git a/Sources/elf2ae.cc b/Sources/elf2ae.cc index a451a0a..f559c21 100644 --- a/Sources/elf2ae.cc +++ b/Sources/elf2ae.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ diff --git a/Sources/i64asm.cc b/Sources/i64asm.cc index 5510252..31f19b8 100644 --- a/Sources/i64asm.cc +++ b/Sources/i64asm.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ @@ -175,13 +175,13 @@ MPCC_MODULE(NewOSAssemblerAMD64) if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { kStdOut << "i64asm: AMD64 Assembler.\ni64asm: v1.10\ni64asm: Copyright " - "(c) 2024 SoftwareLabs.\n"; + "(c) 2024 Amlal El Mahrouss.\n"; return 0; } else if (strcmp(argv[i], "-h") == 0) { kStdOut << "i64asm: AMD64 Assembler.\ni64asm: Copyright (c) 2024 " - "SoftwareLabs.\n"; + "Amlal El Mahrouss.\n"; kStdOut << "-version: Print program version.\n"; kStdOut << "-verbose: Print verbose output.\n"; kStdOut << "-binary: Output as flat binary.\n"; diff --git a/Sources/link.cc b/Sources/link.cc index 47406c4..e245f4c 100644 --- a/Sources/link.cc +++ b/Sources/link.cc @@ -1,12 +1,12 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ /// @file link.cc /// @author Amlal El Mahrouss (amlel) -/// @brief SoftwareLabs Linker. +/// @brief Amlal El Mahrouss Linker. /// Last Rev: Sat Feb 24 CET 2024 @@ -35,7 +35,7 @@ #include #include -#define kLinkerVersion "SoftwareLabs Linker %s, (c) SoftwareLabs 2024\n" +#define kLinkerVersion "Amlal El Mahrouss Linker %s, (c) Amlal El Mahrouss 2024\n" #define StringCompare(DST, SRC) strcmp(DST, SRC) @@ -184,7 +184,7 @@ MPCC_MODULE(NewOSLinker) { pef_container.Count = 0UL; pef_container.Kind = CompilerKit::kPefKindExec; pef_container.SubCpu = kSubArch; - pef_container.Linker = kLinkerId; // SoftwareLabs Linker + pef_container.Linker = kLinkerId; // Amlal El Mahrouss Linker pef_container.Abi = kAbi; // Multi-Processor UX ABI pef_container.Magic[0] = kPefMagic[kFatBinaryEnable ? 2 : 0]; pef_container.Magic[1] = kPefMagic[1]; diff --git a/Sources/power-cc.cc b/Sources/power-cc.cc index b26dbf2..80573b9 100644 --- a/Sources/power-cc.cc +++ b/Sources/power-cc.cc @@ -2,7 +2,7 @@ * ======================================================== * * cc - * Copyright SoftwareLabs, all rights reserved. + * Copyright Amlal El Mahrouss, all rights reserved. * * ======================================================== */ @@ -1531,7 +1531,7 @@ public: #define kPrintF printf #define kSplashCxx() \ - kPrintF(kWhite "cc, %s, (c) SoftwareLabs\n", kDistVersion) + kPrintF(kWhite "cc, %s, (c) Amlal El Mahrouss\n", kDistVersion) static void cc_print_help() { diff --git a/Sources/ppcasm.cc b/Sources/ppcasm.cc index 0236491..2192ccd 100644 --- a/Sources/ppcasm.cc +++ b/Sources/ppcasm.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Amlal El Mahrouss ------------------------------------------- */ @@ -115,11 +115,11 @@ MPCC_MODULE(NewOSAssemblerPowerPC) { if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { kStdOut << "ppcasm: POWER Assembler.\nppcasm: " << kDistVersion << "\nppcasm: " "Copyright (c) " - "2024 SoftwareLabs.\n"; + "2024 Amlal El Mahrouss.\n"; return 0; } else if (strcmp(argv[i], "-h") == 0) { kStdOut << "ppcasm: POWER Assembler.\nppcasm: Copyright (c) 2024 " - "SoftwareLabs.\n"; + "Amlal El Mahrouss.\n"; kStdOut << "-version: Print program version.\n"; kStdOut << "-verbose: Print verbose output.\n"; kStdOut << "-binary: Output as flat binary.\n"; diff --git a/bpp.rsrc b/bpp.rsrc index 3a8d4d9..5cc550c 100644 --- a/bpp.rsrc +++ b/bpp.rsrc @@ -10,11 +10,11 @@ BEGIN BEGIN BLOCK "080904E4" BEGIN - VALUE "CompanyName", "SoftwareLabs" - VALUE "FileDescription", "SoftwareLabs Preprocessor." + VALUE "CompanyName", "Amlal El Mahrouss" + VALUE "FileDescription", "Amlal El Mahrouss Preprocessor." VALUE "FileVersion", kDistVersion VALUE "InternalName", "NewPreprocessor" - VALUE "LegalCopyright", "SoftwareLabs" + VALUE "LegalCopyright", "Amlal El Mahrouss" VALUE "OriginalFilename", "bpp.exe" VALUE "ProductName", "NewPreprocessor" VALUE "ProductVersion", kDistVersion diff --git a/i64asm.rsrc b/i64asm.rsrc index 4472b3f..1c12923 100644 --- a/i64asm.rsrc +++ b/i64asm.rsrc @@ -10,11 +10,11 @@ BEGIN BEGIN BLOCK "080904E4" BEGIN - VALUE "CompanyName", "SoftwareLabs" - VALUE "FileDescription", "SoftwareLabs assembler for AMD64." + VALUE "CompanyName", "Amlal El Mahrouss" + VALUE "FileDescription", "Amlal El Mahrouss assembler for AMD64." VALUE "FileVersion", kDistVersion VALUE "InternalName", "Assembler" - VALUE "LegalCopyright", "SoftwareLabs" + VALUE "LegalCopyright", "Amlal El Mahrouss" VALUE "OriginalFilename", "i64asm.exe" VALUE "ProductName", "Assembler" VALUE "ProductVersion", kDistVersion diff --git a/link.rsrc b/link.rsrc index 550d87a..88ca4d6 100644 --- a/link.rsrc +++ b/link.rsrc @@ -10,11 +10,11 @@ BEGIN BEGIN BLOCK "080904E4" BEGIN - VALUE "CompanyName", "SoftwareLabs" + VALUE "CompanyName", "Amlal El Mahrouss" VALUE "FileDescription", "NewOS linker." VALUE "FileVersion", kDistVersion VALUE "InternalName", "Linker" - VALUE "LegalCopyright", "SoftwareLabs" + VALUE "LegalCopyright", "Amlal El Mahrouss" VALUE "OriginalFilename", "link.exe" VALUE "ProductName", "Linker" VALUE "ProductVersion", kDistVersion diff --git a/posix.make b/posix.make index 0a6ef8e..b543b34 100644 --- a/posix.make +++ b/posix.make @@ -2,7 +2,7 @@ # ======================================================== # # MPCC - # Copyright SoftwareLabs, all rights reserved. + # Copyright Amlal El Mahrouss, all rights reserved. # # ======================================================== # @@ -74,7 +74,7 @@ linker: help: @echo "Compiler - MPCC Compiler Suite." @echo "Preprocessor - MPCC Preprocessor Suite." - @echo "linker - SoftwareLabs Linkers." + @echo "linker - Amlal El Mahrouss Linkers." @echo "clean - Clean objects and executables." .PHONY: clean diff --git a/power-cc.rsrc b/power-cc.rsrc index 4a10e6b..7831667 100644 --- a/power-cc.rsrc +++ b/power-cc.rsrc @@ -10,11 +10,11 @@ BEGIN BEGIN BLOCK "080904E4" BEGIN - VALUE "CompanyName", "SoftwareLabs" - VALUE "FileDescription", "SoftwareLabs C Compiler for POWER." + VALUE "CompanyName", "Amlal El Mahrouss" + VALUE "FileDescription", "Amlal El Mahrouss C Compiler for POWER." VALUE "FileVersion", kDistVersion VALUE "InternalName", "Compiler" - VALUE "LegalCopyright", "SoftwareLabs" + VALUE "LegalCopyright", "Amlal El Mahrouss" VALUE "OriginalFilename", "power-cc.exe" VALUE "ProductName", "Compiler" VALUE "ProductVersion", kDistVersion diff --git a/ppcasm.rsrc b/ppcasm.rsrc index cf3fbb9..174bc5c 100644 --- a/ppcasm.rsrc +++ b/ppcasm.rsrc @@ -10,11 +10,11 @@ BEGIN BEGIN BLOCK "080904E4" BEGIN - VALUE "CompanyName", "SoftwareLabs" - VALUE "FileDescription", "SoftwareLabs assembler for POWER." + VALUE "CompanyName", "Amlal El Mahrouss" + VALUE "FileDescription", "Amlal El Mahrouss assembler for POWER." VALUE "FileVersion", kDistVersion VALUE "InternalName", "Assembler" - VALUE "LegalCopyright", "SoftwareLabs" + VALUE "LegalCopyright", "Amlal El Mahrouss" VALUE "OriginalFilename", "ppcasm.exe" VALUE "ProductName", "Assembler" VALUE "ProductVersion", kDistVersion diff --git a/win64.make b/win64.make index 1e70bfd..ca10243 100644 --- a/win64.make +++ b/win64.make @@ -2,7 +2,7 @@ # ======================================================== # # MPCC - # Copyright SoftwareLabs, all rights reserved. + # Copyright Amlal El Mahrouss, all rights reserved. # # ======================================================== # @@ -80,7 +80,7 @@ linker: help: @echo "Compiler - MPCC Compiler Suite." @echo "Preprocessor - MPCC Preprocessor Suite." - @echo "linker - SoftwareLabs Linkers." + @echo "linker - Amlal El Mahrouss Linkers." @echo "clean - Clean objects and executables." .PHONY: clean -- cgit v1.2.3 From 68b1c532bad643ca983b37e29d6621bd8b957d69 Mon Sep 17 00:00:00 2001 From: Amlal EL Mahrouss Date: Sat, 1 Jun 2024 18:22:01 +0200 Subject: MHR-21: Amend commit, did some cleaning. Signed-off-by: Amlal EL Mahrouss --- 64asm.rsrc | 27 --------------------------- 64x0-cc.rsrc | 27 --------------------------- Common/AsmKit/AsmKit.hpp | 2 +- Common/AsmKit/CPU/32x0.hpp | 2 +- Common/AsmKit/CPU/64x0.hpp | 2 +- Common/AsmKit/CPU/amd64.hpp | 2 +- Common/CompilerKit.hpp | 2 +- Common/Defines.hpp | 2 +- Common/ParserKit.hpp | 2 +- Common/Public/SDK/CRT/__mpcc_alloca.hxx | 2 +- Common/Public/SDK/CRT/__mpcc_defines.hxx | 2 +- Common/Public/SDK/CRT/__mpcc_exception.hxx | 2 +- Common/Public/SDK/CRT/__mpcc_hint.hxx | 2 +- Common/Public/SDK/CRT/__mpcc_malloc.hxx | 2 +- Common/StdKit/AE.hpp | 2 +- Common/StdKit/ErrorID.hpp | 2 +- Common/StdKit/ErrorOr.hpp | 2 +- Common/StdKit/PEF.hpp | 2 +- Common/StdKit/Ref.hpp | 4 ++-- Common/StdKit/String.hpp | 2 +- Common/StdKit/XCOFF.hxx | 2 +- ReadMe.md | 5 ++--- Sources/32asm.cc | 4 ++-- Sources/64asm.cc | 6 +++--- Sources/64x0-cc.cc | 8 ++++---- Sources/AssemblyFactory.cc | 6 +++--- Sources/Detail/asmutils.hxx | 2 +- Sources/Detail/compilerutils.hxx | 2 +- Sources/String.cc | 4 ++-- Sources/bpp.cc | 8 ++++---- Sources/coff2ae.cc | 2 +- Sources/cplusplus.cc | 12 ++++++------ Sources/elf2ae.cc | 2 +- Sources/i64asm.cc | 8 ++++---- Sources/link.cc | 10 +++++----- Sources/power-cc.cc | 6 +++--- Sources/ppcasm.cc | 8 ++++---- bpp.rsrc | 27 --------------------------- i64asm.rsrc | 27 --------------------------- link.rsrc | 27 --------------------------- posix.make | 6 +++--- power-cc.rsrc | 27 --------------------------- ppcasm.rsrc | 27 --------------------------- win64.make | 14 +++----------- 44 files changed, 72 insertions(+), 270 deletions(-) delete mode 100644 64asm.rsrc delete mode 100644 64x0-cc.rsrc delete mode 100644 bpp.rsrc delete mode 100644 i64asm.rsrc delete mode 100644 link.rsrc delete mode 100644 power-cc.rsrc delete mode 100644 ppcasm.rsrc (limited to 'Sources/String.cc') diff --git a/64asm.rsrc b/64asm.rsrc deleted file mode 100644 index c01fa7a..0000000 --- a/64asm.rsrc +++ /dev/null @@ -1,27 +0,0 @@ -#include "Common/Version.hxx" - -1 ICON "Icons/app-logo.ico" - -1 VERSIONINFO -FILEVERSION 1,0,0,0 -PRODUCTVERSION 1,0,0,0 -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "080904E4" - BEGIN - VALUE "CompanyName", "Amlal El Mahrouss" - VALUE "FileDescription", "Amlal El Mahrouss assembler for 64x000." - VALUE "FileVersion", kDistVersion - VALUE "InternalName", "Assembler" - VALUE "LegalCopyright", "Amlal El Mahrouss" - VALUE "OriginalFilename", "64asm.exe" - VALUE "ProductName", "Assembler" - VALUE "ProductVersion", kDistVersion - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x809, 1252 - END -END diff --git a/64x0-cc.rsrc b/64x0-cc.rsrc deleted file mode 100644 index 78d23b4..0000000 --- a/64x0-cc.rsrc +++ /dev/null @@ -1,27 +0,0 @@ -#include "Common/Version.hxx" - -1 ICON "Icons/app-logo.ico" - -1 VERSIONINFO -FILEVERSION 1,0,0,0 -PRODUCTVERSION 1,0,0,0 -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "080904E4" - BEGIN - VALUE "CompanyName", "Amlal El Mahrouss" - VALUE "FileDescription", "Amlal El Mahrouss C Compiler for 64x000." - VALUE "FileVersion", kDistVersion - VALUE "InternalName", "Compiler" - VALUE "LegalCopyright", "Amlal El Mahrouss" - VALUE "OriginalFilename", "64x0-cc.exe" - VALUE "ProductName", "Compiler" - VALUE "ProductVersion", kDistVersion - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x809, 1252 - END -END diff --git a/Common/AsmKit/AsmKit.hpp b/Common/AsmKit/AsmKit.hpp index f4aecaf..020ca5c 100644 --- a/Common/AsmKit/AsmKit.hpp +++ b/Common/AsmKit/AsmKit.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Common/AsmKit/CPU/32x0.hpp b/Common/AsmKit/CPU/32x0.hpp index 94ec43a..fe03336 100644 --- a/Common/AsmKit/CPU/32x0.hpp +++ b/Common/AsmKit/CPU/32x0.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Common/AsmKit/CPU/64x0.hpp b/Common/AsmKit/CPU/64x0.hpp index 48ebf95..b28866f 100644 --- a/Common/AsmKit/CPU/64x0.hpp +++ b/Common/AsmKit/CPU/64x0.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Common/AsmKit/CPU/amd64.hpp b/Common/AsmKit/CPU/amd64.hpp index 92e649a..507602c 100644 --- a/Common/AsmKit/CPU/amd64.hpp +++ b/Common/AsmKit/CPU/amd64.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Common/CompilerKit.hpp b/Common/CompilerKit.hpp index 9abe154..b9de089 100644 --- a/Common/CompilerKit.hpp +++ b/Common/CompilerKit.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Common/Defines.hpp b/Common/Defines.hpp index 3bf1ea8..d76620c 100644 --- a/Common/Defines.hpp +++ b/Common/Defines.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Common/ParserKit.hpp b/Common/ParserKit.hpp index 98d078d..6e15c75 100644 --- a/Common/ParserKit.hpp +++ b/Common/ParserKit.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Common/Public/SDK/CRT/__mpcc_alloca.hxx b/Common/Public/SDK/CRT/__mpcc_alloca.hxx index b653682..a1c638e 100644 --- a/Common/Public/SDK/CRT/__mpcc_alloca.hxx +++ b/Common/Public/SDK/CRT/__mpcc_alloca.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Common/Public/SDK/CRT/__mpcc_defines.hxx b/Common/Public/SDK/CRT/__mpcc_defines.hxx index 1230662..5560410 100644 --- a/Common/Public/SDK/CRT/__mpcc_defines.hxx +++ b/Common/Public/SDK/CRT/__mpcc_defines.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Common/Public/SDK/CRT/__mpcc_exception.hxx b/Common/Public/SDK/CRT/__mpcc_exception.hxx index 663a5d2..9366102 100644 --- a/Common/Public/SDK/CRT/__mpcc_exception.hxx +++ b/Common/Public/SDK/CRT/__mpcc_exception.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Common/Public/SDK/CRT/__mpcc_hint.hxx b/Common/Public/SDK/CRT/__mpcc_hint.hxx index 3168e8e..ee14711 100644 --- a/Common/Public/SDK/CRT/__mpcc_hint.hxx +++ b/Common/Public/SDK/CRT/__mpcc_hint.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Common/Public/SDK/CRT/__mpcc_malloc.hxx b/Common/Public/SDK/CRT/__mpcc_malloc.hxx index 3fd7fcc..2731868 100644 --- a/Common/Public/SDK/CRT/__mpcc_malloc.hxx +++ b/Common/Public/SDK/CRT/__mpcc_malloc.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Common/StdKit/AE.hpp b/Common/StdKit/AE.hpp index 4755b06..9c4ac1a 100644 --- a/Common/StdKit/AE.hpp +++ b/Common/StdKit/AE.hpp @@ -2,7 +2,7 @@ * ======================================================== * * MPCC - * Copyright Amlal El Mahrouss, all rights reserved. + * Copyright SoftwareLabs, all rights reserved. * * ======================================================== */ diff --git a/Common/StdKit/ErrorID.hpp b/Common/StdKit/ErrorID.hpp index 92d2172..9f12ab2 100644 --- a/Common/StdKit/ErrorID.hpp +++ b/Common/StdKit/ErrorID.hpp @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright Amlal El Mahrouss, all rights reserved. + * Copyright SoftwareLabs, all rights reserved. * * ======================================================== */ diff --git a/Common/StdKit/ErrorOr.hpp b/Common/StdKit/ErrorOr.hpp index 7ad6e8d..cf35b26 100644 --- a/Common/StdKit/ErrorOr.hpp +++ b/Common/StdKit/ErrorOr.hpp @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright Amlal El Mahrouss, all rights reserved. + * Copyright SoftwareLabs, all rights reserved. * * ======================================================== */ diff --git a/Common/StdKit/PEF.hpp b/Common/StdKit/PEF.hpp index e82e5ef..b084f32 100644 --- a/Common/StdKit/PEF.hpp +++ b/Common/StdKit/PEF.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Common/StdKit/Ref.hpp b/Common/StdKit/Ref.hpp index 7ba4d95..f4a11c0 100644 --- a/Common/StdKit/Ref.hpp +++ b/Common/StdKit/Ref.hpp @@ -3,7 +3,7 @@ * ======================================================== * * CompilerKit - * Copyright Amlal El Mahrouss, all rights reserved. + * Copyright SoftwareLabs, all rights reserved. * * ======================================================== */ @@ -12,7 +12,7 @@ namespace CompilerKit { - // @author Amlal EL Mahrouss + // @author SoftwareLabs // @brief Reference class, refers to a pointer of data in static memory. template class Ref final diff --git a/Common/StdKit/String.hpp b/Common/StdKit/String.hpp index 3da302c..a05a31c 100644 --- a/Common/StdKit/String.hpp +++ b/Common/StdKit/String.hpp @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright Amlal El Mahrouss, all rights reserved. + * Copyright SoftwareLabs, all rights reserved. * * ======================================================== */ diff --git a/Common/StdKit/XCOFF.hxx b/Common/StdKit/XCOFF.hxx index 6e9fd6d..a26b591 100644 --- a/Common/StdKit/XCOFF.hxx +++ b/Common/StdKit/XCOFF.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs File: XCOFF.hpp Purpose: XCOFF for NewOS. diff --git a/ReadMe.md b/ReadMe.md index 47e0e89..ba91d98 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -9,9 +9,8 @@ git clone git@bitbucket.org:mahrouss/codetools.git and ``` -make all +make -f .make all ``` -Author: Amlal El Mahrouss -##### Copyright Amlal El Mahrouss, all rights reserved. +##### Copyright SoftwareLabs, all rights reserved. diff --git a/Sources/32asm.cc b/Sources/32asm.cc index 3f98cb7..82d23e6 100644 --- a/Sources/32asm.cc +++ b/Sources/32asm.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ @@ -9,7 +9,7 @@ ///////////////////////////////////////////////////////////////////////////////////////// // @file 32asm.cxx -// @author Amlal El Mahrouss +// @author SoftwareLabs // @brief 32x0 Assembler. // REMINDER: when dealing with an undefined symbol use (string diff --git a/Sources/64asm.cc b/Sources/64asm.cc index 587d5c3..6287b3e 100644 --- a/Sources/64asm.cc +++ b/Sources/64asm.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ @@ -9,7 +9,7 @@ ///////////////////////////////////////////////////////////////////////////////////////// // @file 64asm.cxx -// @author Amlal El Mahrouss +// @author SoftwareLabs // @brief 64x0 Assembler. // REMINDER: when dealing with an undefined symbol use (string @@ -110,7 +110,7 @@ MPCC_MODULE(NewOSAssembler64000) { if (argv[i][0] == '-') { if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { kStdOut << "64asm: 64x0 Assembler.\n64asm: v1.10\n64asm: Copyright (c) " - "2024 Amlal El Mahrouss.\n"; + "2024 SoftwareLabs.\n"; return 0; } else if (strcmp(argv[i], "-h") == 0) { kStdOut << "64asm: 64x0 Assembler.\n64asm: Copyright (c) 2024 Mahrouss " diff --git a/Sources/64x0-cc.cc b/Sources/64x0-cc.cc index e3a0771..36f56a8 100644 --- a/Sources/64x0-cc.cc +++ b/Sources/64x0-cc.cc @@ -2,7 +2,7 @@ * ======================================================== * * cc - * Copyright Amlal El Mahrouss, all rights reserved. + * Copyright SoftwareLabs, all rights reserved. * * ======================================================== */ @@ -27,9 +27,9 @@ /* C driver */ /* This is part of MPCC C SDK. */ -/* (c) Amlal El Mahrouss */ +/* (c) SoftwareLabs */ -/// @author Amlal El Mahrouss (amlel) +/// @author SoftwareLabs (amlel) /// @file 64x0-cc.cc /// @brief 64x0 C Compiler. @@ -1513,7 +1513,7 @@ public: #define kPrintF printf #define kSplashCxx() \ - kPrintF(kWhite "cc, %s, (c) Amlal El Mahrouss\n", kDistVersion) + kPrintF(kWhite "cc, %s, (c) SoftwareLabs\n", kDistVersion) static void cc_print_help() { diff --git a/Sources/AssemblyFactory.cc b/Sources/AssemblyFactory.cc index 3b2fb7c..1952f54 100644 --- a/Sources/AssemblyFactory.cc +++ b/Sources/AssemblyFactory.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ @@ -9,12 +9,12 @@ /** * @file AssemblyFactory.cxx - * @author Amlal El Mahrouss (amlal@mahrouss.com) + * @author SoftwareLabs (amlal@mahrouss.com) * @brief Assembler Kit * @version 0.1 * @date 2024-01-27 * - * @copyright Copyright (c) 2024, Amlal El Mahrouss + * @copyright Copyright (c) 2024, SoftwareLabs * */ diff --git a/Sources/Detail/asmutils.hxx b/Sources/Detail/asmutils.hxx index d0eb2c7..f6fdb41 100644 --- a/Sources/Detail/asmutils.hxx +++ b/Sources/Detail/asmutils.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Sources/Detail/compilerutils.hxx b/Sources/Detail/compilerutils.hxx index a9332f4..9ddd3a2 100644 --- a/Sources/Detail/compilerutils.hxx +++ b/Sources/Detail/compilerutils.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Sources/String.cc b/Sources/String.cc index 7926441..38bd444 100644 --- a/Sources/String.cc +++ b/Sources/String.cc @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright Amlal El Mahrouss, all rights reserved. + * Copyright SoftwareLabs, all rights reserved. * * ======================================================== */ @@ -14,7 +14,7 @@ * @version 0.2 * @date 2024-01-23 * - * @copyright Copyright (c) 2024 Amlal El Mahrouss + * @copyright Copyright (c) 2024 SoftwareLabs * */ diff --git a/Sources/bpp.cc b/Sources/bpp.cc index 27dba78..aa0b72a 100644 --- a/Sources/bpp.cc +++ b/Sources/bpp.cc @@ -2,7 +2,7 @@ * ======================================================== * * bpp - * Copyright Amlal El Mahrouss, all rights reserved. + * Copyright SoftwareLabs, all rights reserved. * * ======================================================== */ @@ -19,7 +19,7 @@ #define kMacroPrefix '%' -// @author Amlal El Mahrouss (amlel) +// @author SoftwareLabs (amlel) // @file bpp.cc // @brief C preprocessor. @@ -812,12 +812,12 @@ MPCC_MODULE(NewOSPreprocessor) { if (argv[index][0] == '-') { if (strcmp(argv[index], "-v") == 0) { - printf("%s\n", "bpp v1.11, (c) Amlal El Mahrouss"); + printf("%s\n", "bpp v1.11, (c) SoftwareLabs"); return 0; } if (strcmp(argv[index], "-h") == 0) { - printf("%s\n", "bpp v1.11, (c) Amlal El Mahrouss"); + printf("%s\n", "bpp v1.11, (c) SoftwareLabs"); printf("%s\n", "-working-dir : set directory to working path."); printf("%s\n", "-include-dir : add directory to include path."); printf("%s\n", "-def : def macro."); diff --git a/Sources/coff2ae.cc b/Sources/coff2ae.cc index 6baa964..349d543 100644 --- a/Sources/coff2ae.cc +++ b/Sources/coff2ae.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Sources/cplusplus.cc b/Sources/cplusplus.cc index d03987c..72b654a 100644 --- a/Sources/cplusplus.cc +++ b/Sources/cplusplus.cc @@ -2,7 +2,7 @@ * ======================================================== * * cplusplus - * Copyright Amlal El Mahrouss, all rights reserved. + * Copyright SoftwareLabs, all rights reserved. * * ======================================================== */ @@ -14,7 +14,7 @@ #define kPrintF printf #define kSplashCxx() \ - kPrintF(kWhite "%s\n", "LightSpeed C++ Compiler, Copyright Amlal El Mahrouss.") + kPrintF(kWhite "%s\n", "LightSpeed C++ Compiler, Copyright SoftwareLabs.") #include #include @@ -29,11 +29,11 @@ #define kOk 0 -/* Amlal El Mahrouss C++ driver */ +/* SoftwareLabs C++ driver */ /* This is part of MPCC C++ compiler. */ -/* (c) Amlal El Mahrouss */ +/* (c) SoftwareLabs */ -/// @author Amlal El Mahrouss (amlel) +/// @author SoftwareLabs (amlel) /// @file cc.cc /// @brief Optimized C++ Compiler. /// @todo Throw error for scoped inside scoped variables when they get referenced outside. @@ -170,7 +170,7 @@ static bool kOnForLoop = false; static bool kInBraces = false; static size_t kBracesCount = 0UL; -/* @brief C++ compiler backend for Amlal El Mahrouss C++ */ +/* @brief C++ compiler backend for SoftwareLabs C++ */ class CompilerBackendCPlusPlus final : public ParserKit::CompilerBackend { public: diff --git a/Sources/elf2ae.cc b/Sources/elf2ae.cc index f559c21..a451a0a 100644 --- a/Sources/elf2ae.cc +++ b/Sources/elf2ae.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ diff --git a/Sources/i64asm.cc b/Sources/i64asm.cc index 31f19b8..391c63f 100644 --- a/Sources/i64asm.cc +++ b/Sources/i64asm.cc @@ -1,13 +1,13 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ ///////////////////////////////////////////////////////////////////////////////////////// /// @file i64asm.cxx -/// @author Amlal El Mahrouss +/// @author SoftwareLabs /// @brief AMD64 Assembler. /// REMINDER: when dealing with an undefined symbol use (string @@ -175,13 +175,13 @@ MPCC_MODULE(NewOSAssemblerAMD64) if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { kStdOut << "i64asm: AMD64 Assembler.\ni64asm: v1.10\ni64asm: Copyright " - "(c) 2024 Amlal El Mahrouss.\n"; + "(c) 2024 SoftwareLabs.\n"; return 0; } else if (strcmp(argv[i], "-h") == 0) { kStdOut << "i64asm: AMD64 Assembler.\ni64asm: Copyright (c) 2024 " - "Amlal El Mahrouss.\n"; + "SoftwareLabs.\n"; kStdOut << "-version: Print program version.\n"; kStdOut << "-verbose: Print verbose output.\n"; kStdOut << "-binary: Output as flat binary.\n"; diff --git a/Sources/link.cc b/Sources/link.cc index e245f4c..e0a49cf 100644 --- a/Sources/link.cc +++ b/Sources/link.cc @@ -1,12 +1,12 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ /// @file link.cc -/// @author Amlal El Mahrouss (amlel) -/// @brief Amlal El Mahrouss Linker. +/// @author SoftwareLabs (amlel) +/// @brief SoftwareLabs Linker. /// Last Rev: Sat Feb 24 CET 2024 @@ -35,7 +35,7 @@ #include #include -#define kLinkerVersion "Amlal El Mahrouss Linker %s, (c) Amlal El Mahrouss 2024\n" +#define kLinkerVersion "SoftwareLabs Linker %s, (c) SoftwareLabs 2024\n" #define StringCompare(DST, SRC) strcmp(DST, SRC) @@ -184,7 +184,7 @@ MPCC_MODULE(NewOSLinker) { pef_container.Count = 0UL; pef_container.Kind = CompilerKit::kPefKindExec; pef_container.SubCpu = kSubArch; - pef_container.Linker = kLinkerId; // Amlal El Mahrouss Linker + pef_container.Linker = kLinkerId; // SoftwareLabs Linker pef_container.Abi = kAbi; // Multi-Processor UX ABI pef_container.Magic[0] = kPefMagic[kFatBinaryEnable ? 2 : 0]; pef_container.Magic[1] = kPefMagic[1]; diff --git a/Sources/power-cc.cc b/Sources/power-cc.cc index 80573b9..ad99611 100644 --- a/Sources/power-cc.cc +++ b/Sources/power-cc.cc @@ -2,7 +2,7 @@ * ======================================================== * * cc - * Copyright Amlal El Mahrouss, all rights reserved. + * Copyright SoftwareLabs, all rights reserved. * * ======================================================== */ @@ -22,7 +22,7 @@ #define kOk 0 -/// @author Amlal El Mahrouss (amlel) +/// @author SoftwareLabs (amlel) /// @file cc.cc /// @brief POWER C Compiler. @@ -1531,7 +1531,7 @@ public: #define kPrintF printf #define kSplashCxx() \ - kPrintF(kWhite "cc, %s, (c) Amlal El Mahrouss\n", kDistVersion) + kPrintF(kWhite "cc, %s, (c) SoftwareLabs\n", kDistVersion) static void cc_print_help() { diff --git a/Sources/ppcasm.cc b/Sources/ppcasm.cc index 2192ccd..89de014 100644 --- a/Sources/ppcasm.cc +++ b/Sources/ppcasm.cc @@ -1,13 +1,13 @@ /* ------------------------------------------- - Copyright Amlal El Mahrouss + Copyright SoftwareLabs ------------------------------------------- */ ///////////////////////////////////////////////////////////////////////////////////////// /// @file ppcasm.cxx -/// @author Amlal El Mahrouss +/// @author SoftwareLabs /// @brief POWER Assembler. /// REMINDER: when dealing with an undefined symbol use (string @@ -115,11 +115,11 @@ MPCC_MODULE(NewOSAssemblerPowerPC) { if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { kStdOut << "ppcasm: POWER Assembler.\nppcasm: " << kDistVersion << "\nppcasm: " "Copyright (c) " - "2024 Amlal El Mahrouss.\n"; + "2024 SoftwareLabs.\n"; return 0; } else if (strcmp(argv[i], "-h") == 0) { kStdOut << "ppcasm: POWER Assembler.\nppcasm: Copyright (c) 2024 " - "Amlal El Mahrouss.\n"; + "SoftwareLabs.\n"; kStdOut << "-version: Print program version.\n"; kStdOut << "-verbose: Print verbose output.\n"; kStdOut << "-binary: Output as flat binary.\n"; diff --git a/bpp.rsrc b/bpp.rsrc deleted file mode 100644 index 5cc550c..0000000 --- a/bpp.rsrc +++ /dev/null @@ -1,27 +0,0 @@ -#include "Common/Version.hxx" - -1 ICON "Icons/app-logo.ico" - -1 VERSIONINFO -FILEVERSION 1,0,0,0 -PRODUCTVERSION 1,0,0,0 -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "080904E4" - BEGIN - VALUE "CompanyName", "Amlal El Mahrouss" - VALUE "FileDescription", "Amlal El Mahrouss Preprocessor." - VALUE "FileVersion", kDistVersion - VALUE "InternalName", "NewPreprocessor" - VALUE "LegalCopyright", "Amlal El Mahrouss" - VALUE "OriginalFilename", "bpp.exe" - VALUE "ProductName", "NewPreprocessor" - VALUE "ProductVersion", kDistVersion - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x809, 1252 - END -END diff --git a/i64asm.rsrc b/i64asm.rsrc deleted file mode 100644 index 1c12923..0000000 --- a/i64asm.rsrc +++ /dev/null @@ -1,27 +0,0 @@ -#include "Common/Version.hxx" - -1 ICON "Icons/app-logo.ico" - -1 VERSIONINFO -FILEVERSION 1,0,0,0 -PRODUCTVERSION 1,0,0,0 -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "080904E4" - BEGIN - VALUE "CompanyName", "Amlal El Mahrouss" - VALUE "FileDescription", "Amlal El Mahrouss assembler for AMD64." - VALUE "FileVersion", kDistVersion - VALUE "InternalName", "Assembler" - VALUE "LegalCopyright", "Amlal El Mahrouss" - VALUE "OriginalFilename", "i64asm.exe" - VALUE "ProductName", "Assembler" - VALUE "ProductVersion", kDistVersion - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x809, 1252 - END -END diff --git a/link.rsrc b/link.rsrc deleted file mode 100644 index 88ca4d6..0000000 --- a/link.rsrc +++ /dev/null @@ -1,27 +0,0 @@ -#include "Common/Version.hxx" - -1 ICON "Icons/app-logo.ico" - -1 VERSIONINFO -FILEVERSION 1,0,0,0 -PRODUCTVERSION 1,0,0,0 -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "080904E4" - BEGIN - VALUE "CompanyName", "Amlal El Mahrouss" - VALUE "FileDescription", "NewOS linker." - VALUE "FileVersion", kDistVersion - VALUE "InternalName", "Linker" - VALUE "LegalCopyright", "Amlal El Mahrouss" - VALUE "OriginalFilename", "link.exe" - VALUE "ProductName", "Linker" - VALUE "ProductVersion", kDistVersion - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x809, 1252 - END -END diff --git a/posix.make b/posix.make index b543b34..119457d 100644 --- a/posix.make +++ b/posix.make @@ -2,13 +2,13 @@ # ======================================================== # # MPCC - # Copyright Amlal El Mahrouss, all rights reserved. + # Copyright SoftwareLabs, all rights reserved. # # ======================================================== # COMMON_INC=-I./Common -I./ -I./Sources/Detail -LINK_CC=g++ -std=c++20 +LINK_CC=clang++ -std=c++20 LINK_SRC=Sources/link.cc LINK_OUTPUT=Output/link.exec LINK_ALT_OUTPUT=Output/64link.exec @@ -74,7 +74,7 @@ linker: help: @echo "Compiler - MPCC Compiler Suite." @echo "Preprocessor - MPCC Preprocessor Suite." - @echo "linker - Amlal El Mahrouss Linkers." + @echo "linker - SoftwareLabs Linkers." @echo "clean - Clean objects and executables." .PHONY: clean diff --git a/power-cc.rsrc b/power-cc.rsrc deleted file mode 100644 index 7831667..0000000 --- a/power-cc.rsrc +++ /dev/null @@ -1,27 +0,0 @@ -#include "Common/Version.hxx" - -1 ICON "Icons/app-logo.ico" - -1 VERSIONINFO -FILEVERSION 1,0,0,0 -PRODUCTVERSION 1,0,0,0 -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "080904E4" - BEGIN - VALUE "CompanyName", "Amlal El Mahrouss" - VALUE "FileDescription", "Amlal El Mahrouss C Compiler for POWER." - VALUE "FileVersion", kDistVersion - VALUE "InternalName", "Compiler" - VALUE "LegalCopyright", "Amlal El Mahrouss" - VALUE "OriginalFilename", "power-cc.exe" - VALUE "ProductName", "Compiler" - VALUE "ProductVersion", kDistVersion - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x809, 1252 - END -END diff --git a/ppcasm.rsrc b/ppcasm.rsrc deleted file mode 100644 index 174bc5c..0000000 --- a/ppcasm.rsrc +++ /dev/null @@ -1,27 +0,0 @@ -#include "Common/Version.hxx" - -1 ICON "Icons/app-logo.ico" - -1 VERSIONINFO -FILEVERSION 1,0,0,0 -PRODUCTVERSION 1,0,0,0 -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "080904E4" - BEGIN - VALUE "CompanyName", "Amlal El Mahrouss" - VALUE "FileDescription", "Amlal El Mahrouss assembler for POWER." - VALUE "FileVersion", kDistVersion - VALUE "InternalName", "Assembler" - VALUE "LegalCopyright", "Amlal El Mahrouss" - VALUE "OriginalFilename", "ppcasm.exe" - VALUE "ProductName", "Assembler" - VALUE "ProductVersion", kDistVersion - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x809, 1252 - END -END diff --git a/win64.make b/win64.make index ca10243..0315371 100644 --- a/win64.make +++ b/win64.make @@ -2,14 +2,13 @@ # ======================================================== # # MPCC - # Copyright Amlal El Mahrouss, all rights reserved. + # Copyright SoftwareLabs, all rights reserved. # # ======================================================== # COMMON_INC=-I./Common -I./ -I./Sources/Detail -LINK_CC=x86_64-w64-mingw32-g++.exe -std=c++20 -Xlinker -s -WINRES=x86_64-w64-mingw32-windres +LINK_CC=clang++ -std=c++20 -Xlinker -s LINK_SRC=Sources/link.cc LINK_OUTPUT=Output/link.exe LINK_ALT_OUTPUT=Output/64link.exe @@ -51,16 +50,10 @@ all: pre-processor compiler linker .PHONY: pre-processor pre-processor: - $(WINRES) bpp.rsrc -O coff -o bpp.obj $(LINK_CC) $(COMMON_INC) $(PP_SRC) bpp.obj -o $(PP_OUTPUT) .PHONY: compiler compiler: - $(WINRES) i64asm.rsrc -O coff -o i64asm.obj - $(WINRES) 64asm.rsrc -O coff -o 64asm.obj - $(WINRES) ppcasm.rsrc -O coff -o ppcasm.obj - $(WINRES) 64x0-cc.rsrc -O coff -o 64x0-cc.obj - $(WINRES) power-cc.rsrc -O coff -o power-cc.obj $(LINK_CC) $(COMMON_INC) 64x0-cc.obj $(64X0_CC_SRC) -o $(64X0_CC_OUTPUT) $(LINK_CC) $(COMMON_INC) $(AMD64_CXX_SRC) -o $(AMD64_CXX_OUTPUT) $(LINK_CC) $(COMMON_INC) power-cc.obj $(PPC_CC_SRC) -o $(PPC_CC_OUTPUT) @@ -70,7 +63,6 @@ compiler: .PHONY: linker linker: - $(WINRES) link.rsrc -O coff -o link.obj $(LINK_CC) $(COMMON_INC) link.obj $(LINK_SRC) -o $(LINK_OUTPUT) cp $(LINK_OUTPUT) $(LINK_ALT_OUTPUT) cp $(LINK_OUTPUT) $(LINK_ALT_2_OUTPUT) @@ -80,7 +72,7 @@ linker: help: @echo "Compiler - MPCC Compiler Suite." @echo "Preprocessor - MPCC Preprocessor Suite." - @echo "linker - Amlal El Mahrouss Linkers." + @echo "linker - SoftwareLabs Linkers." @echo "clean - Clean objects and executables." .PHONY: clean -- cgit v1.2.3 From 0aebad569eef2989e32d9825ce52708371685ff9 Mon Sep 17 00:00:00 2001 From: Amlal EL Mahrouss Date: Sun, 9 Jun 2024 19:57:20 +0200 Subject: MHR-21: Finish C++ compiler. Signed-off-by: Amlal EL Mahrouss --- .vscode/c_cpp_properties.json | 4 +- Comm/AsmKit/AsmKit.hpp | 217 ++++ Comm/AsmKit/CPU/32x0.hpp | 95 ++ Comm/AsmKit/CPU/64x0.hpp | 108 ++ Comm/AsmKit/CPU/amd64.hpp | 56 + Comm/AsmKit/CPU/ppc.hpp | 1919 ++++++++++++++++++++++++++++ Comm/CompilerKit.hpp | 33 + Comm/Defines.hpp | 147 +++ Comm/ParserKit.hpp | 171 +++ Comm/Public/SDK/CRT/__mpcc_alloca.hxx | 15 + Comm/Public/SDK/CRT/__mpcc_defines.hxx | 89 ++ Comm/Public/SDK/CRT/__mpcc_exception.hxx | 27 + Comm/Public/SDK/CRT/__mpcc_hint.hxx | 20 + Comm/Public/SDK/CRT/__mpcc_malloc.hxx | 30 + Comm/Public/SDK/CRT/__mpcc_power.inc | 35 + Comm/StdKit/AE.hpp | 143 +++ Comm/StdKit/ELF.hpp | 389 ++++++ Comm/StdKit/ErrorID.hpp | 22 + Comm/StdKit/ErrorOr.hpp | 61 + Comm/StdKit/PEF.hpp | 132 ++ Comm/StdKit/Ref.hpp | 91 ++ Comm/StdKit/String.hpp | 90 ++ Comm/StdKit/XCOFF.hxx | 41 + Comm/UUID.hpp | 983 ++++++++++++++ Comm/Version.hxx | 3 + Common/AsmKit/AsmKit.hpp | 217 ---- Common/AsmKit/CPU/32x0.hpp | 95 -- Common/AsmKit/CPU/64x0.hpp | 108 -- Common/AsmKit/CPU/amd64.hpp | 56 - Common/AsmKit/CPU/ppc.hpp | 1919 ---------------------------- Common/CompilerKit.hpp | 33 - Common/Defines.hpp | 147 --- Common/ParserKit.hpp | 171 --- Common/Public/SDK/CRT/__mpcc_alloca.hxx | 15 - Common/Public/SDK/CRT/__mpcc_defines.hxx | 89 -- Common/Public/SDK/CRT/__mpcc_exception.hxx | 27 - Common/Public/SDK/CRT/__mpcc_hint.hxx | 20 - Common/Public/SDK/CRT/__mpcc_malloc.hxx | 30 - Common/Public/SDK/CRT/__mpcc_power.inc | 35 - Common/StdKit/AE.hpp | 143 --- Common/StdKit/ELF.hpp | 389 ------ Common/StdKit/ErrorID.hpp | 22 - Common/StdKit/ErrorOr.hpp | 61 - Common/StdKit/PEF.hpp | 132 -- Common/StdKit/Ref.hpp | 91 -- Common/StdKit/String.hpp | 90 -- Common/StdKit/XCOFF.hxx | 41 - Common/UUID.hpp | 983 -------------- Common/Version.hxx | 3 - Doc/Inside 64x0.pdf | Bin 0 -> 64675 bytes Doc/asm-specs.txt | 11 + Doc/havp.txt | 13 + Doc/notice.txt | 4 + Doc/vnrp.txt | 17 + Sources/32asm.cc | 8 +- Sources/64asm.cc | 8 +- Sources/64x0-cc.cc | 6 +- Sources/AssemblyFactory.cc | 4 +- Sources/Detail/asmutils.hxx | 4 +- Sources/Detail/compilerutils.hxx | 4 +- Sources/String.cc | 2 +- Sources/bpp.cc | 4 +- Sources/coff2ae.cc | 6 +- Sources/cplusplus.cc | 4 +- Sources/elf2ae.cc | 6 +- Sources/i64asm.cc | 8 +- Sources/link.cc | 12 +- Sources/power-cc.cc | 6 +- Sources/ppcasm.cc | 12 +- docs/Inside 64x0.pdf | Bin 64675 -> 0 bytes docs/asm-specs.txt | 11 - docs/havp.txt | 13 - docs/notice.txt | 4 - docs/vnrp.txt | 17 - posix.make | 2 +- win64.make | 2 +- 76 files changed, 5013 insertions(+), 5013 deletions(-) create mode 100644 Comm/AsmKit/AsmKit.hpp create mode 100644 Comm/AsmKit/CPU/32x0.hpp create mode 100644 Comm/AsmKit/CPU/64x0.hpp create mode 100644 Comm/AsmKit/CPU/amd64.hpp create mode 100644 Comm/AsmKit/CPU/ppc.hpp create mode 100644 Comm/CompilerKit.hpp create mode 100644 Comm/Defines.hpp create mode 100644 Comm/ParserKit.hpp create mode 100644 Comm/Public/SDK/CRT/__mpcc_alloca.hxx create mode 100644 Comm/Public/SDK/CRT/__mpcc_defines.hxx create mode 100644 Comm/Public/SDK/CRT/__mpcc_exception.hxx create mode 100644 Comm/Public/SDK/CRT/__mpcc_hint.hxx create mode 100644 Comm/Public/SDK/CRT/__mpcc_malloc.hxx create mode 100644 Comm/Public/SDK/CRT/__mpcc_power.inc create mode 100644 Comm/StdKit/AE.hpp create mode 100644 Comm/StdKit/ELF.hpp create mode 100644 Comm/StdKit/ErrorID.hpp create mode 100644 Comm/StdKit/ErrorOr.hpp create mode 100644 Comm/StdKit/PEF.hpp create mode 100644 Comm/StdKit/Ref.hpp create mode 100644 Comm/StdKit/String.hpp create mode 100644 Comm/StdKit/XCOFF.hxx create mode 100644 Comm/UUID.hpp create mode 100644 Comm/Version.hxx delete mode 100644 Common/AsmKit/AsmKit.hpp delete mode 100644 Common/AsmKit/CPU/32x0.hpp delete mode 100644 Common/AsmKit/CPU/64x0.hpp delete mode 100644 Common/AsmKit/CPU/amd64.hpp delete mode 100644 Common/AsmKit/CPU/ppc.hpp delete mode 100644 Common/CompilerKit.hpp delete mode 100644 Common/Defines.hpp delete mode 100644 Common/ParserKit.hpp delete mode 100644 Common/Public/SDK/CRT/__mpcc_alloca.hxx delete mode 100644 Common/Public/SDK/CRT/__mpcc_defines.hxx delete mode 100644 Common/Public/SDK/CRT/__mpcc_exception.hxx delete mode 100644 Common/Public/SDK/CRT/__mpcc_hint.hxx delete mode 100644 Common/Public/SDK/CRT/__mpcc_malloc.hxx delete mode 100644 Common/Public/SDK/CRT/__mpcc_power.inc delete mode 100644 Common/StdKit/AE.hpp delete mode 100644 Common/StdKit/ELF.hpp delete mode 100644 Common/StdKit/ErrorID.hpp delete mode 100644 Common/StdKit/ErrorOr.hpp delete mode 100644 Common/StdKit/PEF.hpp delete mode 100644 Common/StdKit/Ref.hpp delete mode 100644 Common/StdKit/String.hpp delete mode 100644 Common/StdKit/XCOFF.hxx delete mode 100644 Common/UUID.hpp delete mode 100644 Common/Version.hxx create mode 100644 Doc/Inside 64x0.pdf create mode 100644 Doc/asm-specs.txt create mode 100644 Doc/havp.txt create mode 100644 Doc/notice.txt create mode 100644 Doc/vnrp.txt delete mode 100644 docs/Inside 64x0.pdf delete mode 100644 docs/asm-specs.txt delete mode 100644 docs/havp.txt delete mode 100644 docs/notice.txt delete mode 100644 docs/vnrp.txt (limited to 'Sources/String.cc') diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 0aad778..696e195 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -3,7 +3,7 @@ { "name": "Macintosh (CLang)", "includePath": [ - "${workspaceFolder}/Common/**", + "${workspaceFolder}/Comm/**", "${workspaceFolder}/Sources/Detail/**", "${workspaceFolder}/**" ], @@ -16,7 +16,7 @@ { "name": "Windows (Cygwin)", "includePath": [ - "${workspaceFolder}/Common/**", + "${workspaceFolder}/Comm/**", "${workspaceFolder}/Sources/Detail/**", "${workspaceFolder}/**" ], diff --git a/Comm/AsmKit/AsmKit.hpp b/Comm/AsmKit/AsmKit.hpp new file mode 100644 index 0000000..1801130 --- /dev/null +++ b/Comm/AsmKit/AsmKit.hpp @@ -0,0 +1,217 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace CompilerKit +{ + // + // @brief Frontend to Assembly mountpoint. + // + class AssemblyInterface + { + public: + explicit AssemblyInterface() = default; + virtual ~AssemblyInterface() = default; + + MPCC_COPY_DEFAULT(AssemblyInterface); + + //@ brief compile to object file. + // 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; + + MPCC_COPY_DEFAULT(AssemblyFactory); + + public: + enum + { + kArchAMD64, + kArch32x0, + kArch64x0, + kArchRISCV, + kArchPowerPC, + 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; + + MPCC_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; + + MPCC_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_64x0__ + + class Encoder64x0 final : public EncoderInterface + { + public: + explicit Encoder64x0() = default; + ~Encoder64x0() override = default; + + MPCC_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; + + MPCC_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; + + MPCC_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 CompilerKit diff --git a/Comm/AsmKit/CPU/32x0.hpp b/Comm/AsmKit/CPU/32x0.hpp new file mode 100644 index 0000000..0013752 --- /dev/null +++ b/Comm/AsmKit/CPU/32x0.hpp @@ -0,0 +1,95 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#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]; + 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 kOpcodes32x0 = { + kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. + kAsmOpcodeDecl("br", 0b1110011, 0b001, kAsmJump) // jump to branch + kAsmOpcodeDecl("mr", 0b0100011, 0b101, kAsmImmediate) // move registers + kAsmOpcodeDecl("psh", 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 + +//////////////////////////////// diff --git a/Comm/AsmKit/CPU/64x0.hpp b/Comm/AsmKit/CPU/64x0.hpp new file mode 100644 index 0000000..e2e03c8 --- /dev/null +++ b/Comm/AsmKit/CPU/64x0.hpp @@ -0,0 +1,108 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#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("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 + +//////////////////////////////// diff --git a/Comm/AsmKit/CPU/amd64.hpp b/Comm/AsmKit/CPU/amd64.hpp new file mode 100644 index 0000000..d461574 --- /dev/null +++ b/Comm/AsmKit/CPU/amd64.hpp @@ -0,0 +1,56 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#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; + +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 15 diff --git a/Comm/AsmKit/CPU/ppc.hpp b/Comm/AsmKit/CPU/ppc.hpp new file mode 100644 index 0000000..c4265da --- /dev/null +++ b/Comm/AsmKit/CPU/ppc.hpp @@ -0,0 +1,1919 @@ +#pragma once + +#include + +/// @note Based of: +/// https://opensource.apple.com/source/cctools/cctools-750/as/ppc-opcode.h.auto.html + +/* + * 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 optype +{ + 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 SizeType size_t + +#define VoidPtr void* +#define voidPtr VoidPtr + +#define UIntPtr uintptr_t + +#define Int64 int64_t +#define UInt64 uint64_t + +#define Int32 int +#define UInt32 unsigned + +#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 +#include +#include + +#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 MPCC_COPY_DELETE(KLASS) \ + KLASS& operator=(const KLASS&) = delete; \ + KLASS(const KLASS&) = delete; + +#define MPCC_COPY_DEFAULT(KLASS) \ + KLASS& operator=(const KLASS&) = default; \ + KLASS(const KLASS&) = default; + +#define MPCC_MOVE_DELETE(KLASS) \ + KLASS& operator=(KLASS&&) = delete; \ + KLASS(KLASS&&) = delete; + +#define MPCC_MOVE_DEFAULT(KLASS) \ + KLASS& operator=(KLASS&&) = default; \ + KLASS(KLASS&&) = default; + +#include +#include +#include +#include + +namespace CompilerKit +{ + inline constexpr int BASE_YEAR = 1900; + + inline std::string current_date() noexcept + { + 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) noexcept + { + 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; + } +} // namespace CompilerKit + +#define PACKED __attribute__((packed)) + +typedef char char_type; + +#define kObjectFileExt ".obj" +#define kBinaryFileExt ".bin" + +#define kAsmFileExts \ + { \ + ".64x", ".32x", ".masm", ".s", ".S", ".asm" \ + } + +#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__ */ + +#pragma scalar_storage_order big - endian + +#endif /* ifndef __MPCC_DEFINES_HPP__ */ diff --git a/Comm/ParserKit.hpp b/Comm/ParserKit.hpp new file mode 100644 index 0000000..9109d32 --- /dev/null +++ b/Comm/ParserKit.hpp @@ -0,0 +1,171 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include +#include + +namespace ParserKit +{ + using namespace CompilerKit; + + /// @brief Compiler backend, implements a frontend, such as C, C++... + /// See Toolchain, for some examples. + class CompilerBackend + { + public: + explicit CompilerBackend() = default; + virtual ~CompilerBackend() = default; + + MPCC_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 "Invalid Language"; + } + }; + + struct SyntaxLeafList; + struct SyntaxLeafList; + struct CompilerKeyword; + + /// we want to do that because to separate keywords. + enum KeywordKind + { + eKeywordKindNamespace, + eKeywordKindFunctionStart, + eKeywordKindFunctionEnd, + eKeywordKindVariable, + eKeywordKindType, + eKeywordKindExpressionBegin, + eKeywordKindExpressionEnd, + eKeywordKindArgSeparator, + eKeywordKindBodyStart, + eKeywordKindBodyEnd, + eKeywordKindClass, + eKeywordKindPtrAccess, + eKeywordKindAccess, + eKeywordKindIf, + eKeywordKindElse, + eKeywordKindElseIf, + eKeywordKindVariableAssign, + eKeywordKindVariableDec, + eKeywordKindVariableInc, + eKeywordKindConstant, + eKeywordKindTypedef, + eKeywordKindEndInstr, + eKeywordKindSpecifier, + eKeywordKindInvalid, + eKeywordKindReturn, + eKeywordKindCommentInline, + eKeywordKindCommentMultiLineStart, + eKeywordKindCommentMultiLineEnd, + eKeywordKindEq, + eKeywordKindNotEq, + eKeywordKindGreaterEq, + eKeywordKindLessEq, + eKeywordKindPtr, + }; + + /// \brief Compiler keyword information struct. + struct CompilerKeyword + { + std::string keyword_name; + KeywordKind keyword_kind = eKeywordKindInvalid; + }; + struct SyntaxLeafList final + { + struct SyntaxLeaf final + { + Int32 fUserType; +#ifdef __PK_USE_STRUCT_INSTEAD__ + CompilerKeyword fUserData; +#else + std::string fUserData; +#endif + + std::string fUserValue; + struct SyntaxLeaf* fNext; + }; + + std::vector fLeafList; + SizeType fNumLeafs; + + size_t SizeOf() + { + return fNumLeafs; + } + std::vector& 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; + } +} // namespace ParserKit diff --git a/Comm/Public/SDK/CRT/__mpcc_alloca.hxx b/Comm/Public/SDK/CRT/__mpcc_alloca.hxx new file mode 100644 index 0000000..a1c638e --- /dev/null +++ b/Comm/Public/SDK/CRT/__mpcc_alloca.hxx @@ -0,0 +1,15 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +typedef void* ptr_type; +typedef __SIZE_TYPE__ size_type; + +inline void* __mpcc_alloca_gcc(size_type sz) +{ + return __builtin_alloca(sz); +} diff --git a/Comm/Public/SDK/CRT/__mpcc_defines.hxx b/Comm/Public/SDK/CRT/__mpcc_defines.hxx new file mode 100644 index 0000000..5560410 --- /dev/null +++ b/Comm/Public/SDK/CRT/__mpcc_defines.hxx @@ -0,0 +1,89 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifndef __MPCC_DEF__ +#define __MPCC_DEF__ + +#ifndef __GNUC__ + +typedef __SIZE_TYPE__ size_t; + +#ifdef __LP64__ +typedef long int ssize_t; +#else +typedef int ssize_t; +#endif // __LP64__ + +typedef size_t ptrdiff_t; +typedef size_t uintptr_t; +typedef void* voidptr_t; +typedef void* any_t; +typedef char* caddr_t; + +#ifndef NULL +#define NULL ((voidptr_t)0) +#endif // !null + +#ifdef __GNUC__ +#include +#define __mpcc_alloca(sz) __mpcc_alloca_gcc(sz) +#elif defined(__MPCC__) + +#define __alloca(sz) __mpcc_alloca(sz) +#endif + +#define __deref(ptr) (*(ptr)) + +#ifdef __cplusplus +#define __init_decl() \ + extern "C" \ + { +#define __fini_decl() \ + } \ + ; +#else +#define __init_decl() +#define __fini_decl() +#endif + +#if __has_builtin(__builtin_alloca) +#define alloca(sz) __builtin_alloca(sz) +#ifdef __alloca +#undef __alloca +#endif +#define __alloca alloca +#else +#warning alloca not detected (MPCC) +#endif + +typedef long long off_t; +typedef unsigned long long uoff_t; + +typedef union float_cast { + struct + { + unsigned int mantissa : 23; + unsigned int exponent : 8; + unsigned int sign : 1; + }; + + float f; +} __attribute__((packed)) float_cast_t; + +typedef union double_cast { + struct + { + unsigned long long int mantissa : 52; + unsigned int exponent : 11; + unsigned int sign : 1; + }; + + double f; +} __attribute__((packed)) double_cast_t; + +#endif // ifndef __GNUC__ + +#endif /* __MPCC_DEF__ */ diff --git a/Comm/Public/SDK/CRT/__mpcc_exception.hxx b/Comm/Public/SDK/CRT/__mpcc_exception.hxx new file mode 100644 index 0000000..9366102 --- /dev/null +++ b/Comm/Public/SDK/CRT/__mpcc_exception.hxx @@ -0,0 +1,27 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +/// This file is an implementation of __throw* family of functions. + +#include +#include +#include + +namespace std +{ + inline void __throw_general(void) + { + throw std::runtime_error("MPCC C++ Runtime error."); + } + + inline void __throw_domain_error(const char* error) + { + std::cout << "MPCC C++: Domain error: " << error << "\r"; + __throw_general(); + } +} // namespace std diff --git a/Comm/Public/SDK/CRT/__mpcc_hint.hxx b/Comm/Public/SDK/CRT/__mpcc_hint.hxx new file mode 100644 index 0000000..ee14711 --- /dev/null +++ b/Comm/Public/SDK/CRT/__mpcc_hint.hxx @@ -0,0 +1,20 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#pragma compiler(hint_manifest) + +#define _Input +#define _Output + +#define _Optional + +#define _StrictCheckInput +#define _StrictCheckOutput + +#define _InOut +#define _StrictInOut diff --git a/Comm/Public/SDK/CRT/__mpcc_malloc.hxx b/Comm/Public/SDK/CRT/__mpcc_malloc.hxx new file mode 100644 index 0000000..2731868 --- /dev/null +++ b/Comm/Public/SDK/CRT/__mpcc_malloc.hxx @@ -0,0 +1,30 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +namespace stdx +{ + /// @brief allocate a new class. + /// @tparam KindClass the class type to allocate. + template + inline void* allocate(Args&&... args) + { + return new KindClass(std::forward(args)...); + } + + /// @brief free a class. + /// @tparam KindClass the class type to allocate. + template + inline void release(KindClass ptr) + { + if (!ptr) + return; + delete ptr; + } +} // namespace stdx diff --git a/Comm/Public/SDK/CRT/__mpcc_power.inc b/Comm/Public/SDK/CRT/__mpcc_power.inc new file mode 100644 index 0000000..9e4928c --- /dev/null +++ b/Comm/Public/SDK/CRT/__mpcc_power.inc @@ -0,0 +1,35 @@ +# Path: SDK/__mpcc_power.inc +# Language: MPCC POWER Assembly support for GNU. +# Build Date: 2024-6-4 + +%ifdef __CODETOOLS__ + +%def lda li +%def sta stw +%def ldw li + +%def r0 0 +%def r1 1 +%def r2 2 +%def r3 3 +%def r4 4 +%def r5 5 +%def r6 6 +%def r7 7 +%def r8 8 +%def r9 9 +%def r10 10 +%def r11 11 +%def r12 12 +%def r13 13 +%def r14 14 +%def r15 15 +%def r16 16 +%def r17 17 +%def r18 18 +%def r19 19 +%def r20 20 + +%endif + +%def nop mr 0, 0 diff --git a/Comm/StdKit/AE.hpp b/Comm/StdKit/AE.hpp new file mode 100644 index 0000000..505ed77 --- /dev/null +++ b/Comm/StdKit/AE.hpp @@ -0,0 +1,143 @@ +/* + * ======================================================== + * + * MPCC + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include + +#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; + 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 CompilerKit + +// 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 +{ + /** + * @brief AE Reader protocol + * + */ + class AEReadableProtocol final + { + public: + std::ifstream FP; + + public: + explicit AEReadableProtocol() = default; + ~AEReadableProtocol() = default; + + MPCC_COPY_DELETE(AEReadableProtocol); + + /** + * @brief Read AE record + * + * @param raw the containing buffer + * @param sz it's size (without sizeof(AERecordHeader) added to it.) + * @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 CompilerKit::Utils diff --git a/Comm/StdKit/ELF.hpp b/Comm/StdKit/ELF.hpp new file mode 100644 index 0000000..4f0d0ae --- /dev/null +++ b/Comm/StdKit/ELF.hpp @@ -0,0 +1,389 @@ +#pragma once + +#include +#include + +struct file; + +#ifndef elf_read_implies_exec +/* Executables for which elf_read_implies_exec() returns TRUE will + have the READ_IMPLIES_EXEC personality flag set automatically. + Override in asm/elf.h as needed. */ +#define elf_read_implies_exec(ex, have_pt_gnu_stack) 0 +#endif + +/* 32-bit ELF base types. */ +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +/* 64-bit ELF base types. */ +typedef uintptr_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* These constants are for the segment types stored in the image headers */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* OS-specific */ +#define PT_HIOS 0x6fffffff /* OS-specific */ +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff +#define PT_GNU_EH_FRAME 0x6474e550 + +#define PT_GNU_STACK (PT_LOOS + 0x474e551) + +/* These constants define the different elf file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* This is the info that is needed to parse the dynamic section of the file */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_ENCODING 32 +#define OLD_DT_LOOS 0x60000000 +#define DT_LOOS 0x6000000d +#define DT_HIOS 0x6ffff000 +#define DT_VALRNGLO 0x6ffffd00 +#define DT_VALRNGHI 0x6ffffdff +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_VERSYM 0x6ffffff0 +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa +#define DT_FLAGS_1 0x6ffffffb +#define DT_VERDEF 0x6ffffffc +#define DT_VERDEFNUM 0x6ffffffd +#define DT_VERNEED 0x6ffffffe +#define DT_VERNEEDNUM 0x6fffffff +#define OLD_DT_HIOS 0x6fffffff +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* This info is needed when parsing the symbol table */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_COMMON 5 +#define STT_TLS 6 + +#define ELF_ST_BIND(x) ((x) >> 4) +#define ELF_ST_TYPE(x) (((unsigned int)x) & 0xf) +#define ELF32_ST_BIND(x) ELF_ST_BIND(x) +#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) +#define ELF64_ST_BIND(x) ELF_ST_BIND(x) +#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x) + +typedef struct dynamic +{ + Elf32_Sword d_tag; + union { + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; /* entry tag value */ + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +/* The following are used with relocations */ +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x)&0xff) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i)&0xffffffff) + +typedef struct elf32_rel +{ + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf64_rel +{ + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ +} Elf64_Rel; + +typedef struct elf32_rela +{ + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct elf64_rela +{ + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ + Elf64_Sxword r_addend; /* Constant addend used to compute value */ +} Elf64_Rela; + +typedef struct elf32_sym +{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +typedef struct elf64_sym +{ + Elf64_Word st_name; /* Symbol name, index in string tbl */ + unsigned char st_info; /* Type and binding attributes */ + unsigned char st_other; /* No defined meaning, 0 */ + Elf64_Half st_shndx; /* Associated section index */ + Elf64_Addr st_value; /* Value of the symbol */ + Elf64_Xword st_size; /* Associated symbol size */ +} Elf64_Sym; + +#define EI_NIDENT 16 + +typedef struct elf32_hdr +{ + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; /* Entry point */ + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +typedef struct elf64_hdr +{ + unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* These constants define the permissions on sections in the program + header, p_flags. */ +#define PF_R 0x4 +#define PF_W 0x2 +#define PF_X 0x1 + +typedef struct elf32_phdr +{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +typedef struct elf64_phdr +{ + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment, file & memory */ +} Elf64_Phdr; + +/* sh_type */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* sh_flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +/* special section indexes */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +typedef struct +{ + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct elf64_shdr +{ + Elf64_Word sh_name; /* Section name, index in string tbl */ + Elf64_Word sh_type; /* Type of section */ + Elf64_Xword sh_flags; /* Miscellaneous section attributes */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Size of section in bytes */ + Elf64_Word sh_link; /* Index of another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +#define ELFOSABI_NONE 0 +#define ELFOSABI_LINUX 3 + +#ifndef ELF_OSABI +#define ELF_OSABI ELFOSABI_NONE +#endif + +/* Notes used in ET_CORE */ +#define NT_PRSTATUS 1 +#define NT_PRFPREG 2 +#define NT_PRPSINFO 3 +#define NT_TASKSTRUCT 4 +#define NT_AUXV 6 +#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ +#define NT_PPC_VMX 0x100 /* POWER Altivec/VMX registers */ +#define NT_PPC_SPE 0x101 /* POWER SPE/EVR registers */ +#define NT_PPC_VSX 0x102 /* POWER VSX registers */ +#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ +#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ +#define NT_PRXSTATUS 0x300 /* s390 upper register halves */ + +/* Note header in a PT_NOTE section */ +typedef struct elf32_note +{ + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +} Elf32_Nhdr; + +/* Note header in a PT_NOTE section */ +typedef struct elf64_note +{ + Elf64_Word n_namesz; /* Name size */ + Elf64_Word n_descsz; /* Content size */ + Elf64_Word n_type; /* Content type */ +} Elf64_Nhdr; diff --git a/Comm/StdKit/ErrorID.hpp b/Comm/StdKit/ErrorID.hpp new file mode 100644 index 0000000..bea70ae --- /dev/null +++ b/Comm/StdKit/ErrorID.hpp @@ -0,0 +1,22 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +#define MPCC_EXEC_ERROR -30 +#define MPCC_FILE_NOT_FOUND -31 +#define MPCC_DIR_NOT_FOUND -32 +#define MPCC_FILE_EXISTS -33 +#define MPCC_TOO_LONG -34 +#define MPCC_INVALID_DATA -35 +#define MPCC_UNIMPLEMENTED -36 +#define MPCC_FAT_ERROR -37 diff --git a/Comm/StdKit/ErrorOr.hpp b/Comm/StdKit/ErrorOr.hpp new file mode 100644 index 0000000..0125f82 --- /dev/null +++ b/Comm/StdKit/ErrorOr.hpp @@ -0,0 +1,61 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +namespace CompilerKit +{ + 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 CompilerKit diff --git a/Comm/StdKit/PEF.hpp b/Comm/StdKit/PEF.hpp new file mode 100644 index 0000000..e790d6a --- /dev/null +++ b/Comm/StdKit/PEF.hpp @@ -0,0 +1,132 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +#include + +// @file PEF.hpp +// @brief Preferred Executable Format + +#define kPefMagic "Joy!" +#define kPefMagicFat "yoJ!" + +#define kPefExt ".exec" +#define kPefDylibExt ".lib" +#define kPefLibExt ".slib" +#define kPefObjectExt ".obj" +#define kPefDebugExt ".dbg" + +#define kPefMagicLen 5 + +#define kPefVersion 2 +#define kPefNameLen 255 + +#define kPefBaseOrigin (0x1000000) + +#define kPefStart "__ImageStart" + +namespace CompilerKit +{ + enum + { + kPefArchIntel86S = 100, + kPefArchAMD64, + kPefArchRISCV, + kPefArch64000, /* 64x0 RISC architecture. */ + kPefArch32000, + kPefArchPowerPC, /* 64-bit POWER architecture. */ + kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1, + kPefArchInvalid = 0xFF, + }; + + enum + { + kPefSubArchAMD, + kPefSubArchIntel, + kPefSubArchGeneric, + kPefSubArchIBM, + }; + + enum + { + kPefKindExec = 1, /* .exe */ + kPefKindSharedObject = 2, /* .lib */ + 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; + + /* 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; + + enum + { + kPefCode = 0xC, + kPefData = 0xD, + kPefZero = 0xE, + kPefLinkerID = 0x1, + kPefCount = 4, + kPefInvalid = 0xFF, + }; +} // namespace CompilerKit + +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/Comm/StdKit/Ref.hpp b/Comm/StdKit/Ref.hpp new file mode 100644 index 0000000..f4a11c0 --- /dev/null +++ b/Comm/StdKit/Ref.hpp @@ -0,0 +1,91 @@ + +/* + * ======================================================== + * + * CompilerKit + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +namespace CompilerKit +{ + // @author SoftwareLabs + // @brief Reference class, refers to a pointer of data in static memory. + template + 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 + class NonNullRef final + { + public: + NonNullRef() = delete; + NonNullRef(nullPtr) = 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 CompilerKit diff --git a/Comm/StdKit/String.hpp b/Comm/StdKit/String.hpp new file mode 100644 index 0000000..c6589cc --- /dev/null +++ b/Comm/StdKit/String.hpp @@ -0,0 +1,90 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +namespace CompilerKit +{ + /** + * @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 char[Sz]; + assert(m_Data); + } + + ~StringView() noexcept + { + if (m_Data) + { + memset(m_Data, 0, m_Sz); + delete[] m_Data; + + m_Data = nullptr; + } + } + + MPCC_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: + char* 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 CompilerKit diff --git a/Comm/StdKit/XCOFF.hxx b/Comm/StdKit/XCOFF.hxx new file mode 100644 index 0000000..fee1888 --- /dev/null +++ b/Comm/StdKit/XCOFF.hxx @@ -0,0 +1,41 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: XCOFF.hpp + Purpose: XCOFF for NewOS. + + 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 CompilerKit +{ + /// @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 CompilerKit + +#endif // ifndef __XCOFF__ \ No newline at end of file diff --git a/Comm/UUID.hpp b/Comm/UUID.hpp new file mode 100644 index 0000000..00b153b --- /dev/null +++ b/Comm/UUID.hpp @@ -0,0 +1,983 @@ +#ifndef STDUUID_H +#define STDUUID_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus + +#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) +#define LIBUUID_CPP20_OR_GREATER +#endif + +#endif + +#ifdef LIBUUID_CPP20_OR_GREATER +#include +#else +#include +#endif + +#ifdef _WIN32 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef UUID_SYSTEM_GENERATOR +#include +#endif + +#ifdef UUID_TIME_GENERATOR +#include +#pragma comment(lib, "IPHLPAPI.lib") +#endif + +#elif defined(__linux__) || defined(__unix__) + +#ifdef UUID_SYSTEM_GENERATOR +#include +#endif + +#elif defined(__APPLE__) + +#ifdef UUID_SYSTEM_GENERATOR +#include +#endif + +#endif + +namespace uuids +{ +#ifdef __cpp_lib_span + template + using span = std::span; +#else + template + using span = gsl::span; +#endif + + namespace detail + { + template + [[nodiscard]] constexpr inline unsigned char hex2char(TChar const ch) noexcept + { + if (ch >= static_cast('0') && ch <= static_cast('9')) + return static_cast(ch - static_cast('0')); + if (ch >= static_cast('a') && ch <= static_cast('f')) + return static_cast(10 + ch - static_cast('a')); + if (ch >= static_cast('A') && ch <= static_cast('F')) + return static_cast(10 + ch - static_cast('A')); + return 0; + } + + template + [[nodiscard]] constexpr inline bool is_hex(TChar const ch) noexcept + { + return (ch >= static_cast('0') && ch <= static_cast('9')) || + (ch >= static_cast('a') && ch <= static_cast('f')) || + (ch >= static_cast('A') && ch <= static_cast('F')); + } + + template + [[nodiscard]] constexpr std::basic_string_view to_string_view( + TChar const* str) noexcept + { + if (str) + return str; + return {}; + } + + template + [[nodiscard]] constexpr std::basic_string_view + to_string_view(StringType const& str) noexcept + { + return str; + } + + class sha1 + { + public: + using digest32_t = uint32_t[5]; + using digest8_t = uint8_t[20]; + + static constexpr unsigned int block_bytes = 64; + + [[nodiscard]] inline static uint32_t left_rotate( + uint32_t value, size_t const count) noexcept + { + return (value << count) ^ (value >> (32 - count)); + } + + sha1() + { + reset(); + } + + void reset() noexcept + { + m_digest[0] = 0x67452301; + m_digest[1] = 0xEFCDAB89; + m_digest[2] = 0x98BADCFE; + m_digest[3] = 0x10325476; + m_digest[4] = 0xC3D2E1F0; + m_blockByteIndex = 0; + m_byteCount = 0; + } + + void process_byte(uint8_t octet) + { + this->m_block[this->m_blockByteIndex++] = octet; + ++this->m_byteCount; + if (m_blockByteIndex == block_bytes) + { + this->m_blockByteIndex = 0; + process_block(); + } + } + + void process_block(void const* const start, void const* const end) + { + const uint8_t* begin = static_cast(start); + const uint8_t* finish = static_cast(end); + while (begin != finish) + { + process_byte(*begin); + begin++; + } + } + + void process_bytes(void const* const data, size_t const len) + { + const uint8_t* block = static_cast(data); + process_block(block, block + len); + } + + uint32_t const* get_digest(digest32_t digest) + { + size_t const bitCount = this->m_byteCount * 8; + process_byte(0x80); + if (this->m_blockByteIndex > 56) + { + while (m_blockByteIndex != 0) + { + process_byte(0); + } + while (m_blockByteIndex < 56) + { + process_byte(0); + } + } + else + { + while (m_blockByteIndex < 56) + { + process_byte(0); + } + } + process_byte(0); + process_byte(0); + process_byte(0); + process_byte(0); + process_byte(static_cast((bitCount >> 24) & 0xFF)); + process_byte(static_cast((bitCount >> 16) & 0xFF)); + process_byte(static_cast((bitCount >> 8) & 0xFF)); + process_byte(static_cast((bitCount)&0xFF)); + + memcpy(digest, m_digest, 5 * sizeof(uint32_t)); + return digest; + } + + uint8_t const* get_digest_bytes(digest8_t digest) + { + digest32_t d32; + get_digest(d32); + size_t di = 0; + digest[di++] = static_cast(d32[0] >> 24); + digest[di++] = static_cast(d32[0] >> 16); + digest[di++] = static_cast(d32[0] >> 8); + digest[di++] = static_cast(d32[0] >> 0); + + digest[di++] = static_cast(d32[1] >> 24); + digest[di++] = static_cast(d32[1] >> 16); + digest[di++] = static_cast(d32[1] >> 8); + digest[di++] = static_cast(d32[1] >> 0); + + digest[di++] = static_cast(d32[2] >> 24); + digest[di++] = static_cast(d32[2] >> 16); + digest[di++] = static_cast(d32[2] >> 8); + digest[di++] = static_cast(d32[2] >> 0); + + digest[di++] = static_cast(d32[3] >> 24); + digest[di++] = static_cast(d32[3] >> 16); + digest[di++] = static_cast(d32[3] >> 8); + digest[di++] = static_cast(d32[3] >> 0); + + digest[di++] = static_cast(d32[4] >> 24); + digest[di++] = static_cast(d32[4] >> 16); + digest[di++] = static_cast(d32[4] >> 8); + digest[di++] = static_cast(d32[4] >> 0); + + return digest; + } + + private: + void process_block() + { + uint32_t w[80]; + for (size_t i = 0; i < 16; i++) + { + w[i] = static_cast(m_block[i * 4 + 0] << 24); + w[i] |= static_cast(m_block[i * 4 + 1] << 16); + w[i] |= static_cast(m_block[i * 4 + 2] << 8); + w[i] |= static_cast(m_block[i * 4 + 3]); + } + for (size_t i = 16; i < 80; i++) + { + w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1); + } + + uint32_t a = m_digest[0]; + uint32_t b = m_digest[1]; + uint32_t c = m_digest[2]; + uint32_t d = m_digest[3]; + uint32_t e = m_digest[4]; + + for (std::size_t i = 0; i < 80; ++i) + { + uint32_t f = 0; + uint32_t k = 0; + + if (i < 20) + { + f = (b & c) | (~b & d); + k = 0x5A827999; + } + else if (i < 40) + { + f = b ^ c ^ d; + k = 0x6ED9EBA1; + } + else if (i < 60) + { + f = (b & c) | (b & d) | (c & d); + k = 0x8F1BBCDC; + } + else + { + f = b ^ c ^ d; + k = 0xCA62C1D6; + } + uint32_t temp = left_rotate(a, 5) + f + e + k + w[i]; + e = d; + d = c; + c = left_rotate(b, 30); + b = a; + a = temp; + } + + m_digest[0] += a; + m_digest[1] += b; + m_digest[2] += c; + m_digest[3] += d; + m_digest[4] += e; + } + + private: + digest32_t m_digest; + uint8_t m_block[64]; + size_t m_blockByteIndex; + size_t m_byteCount; + }; + + template + inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000"; + + template <> + inline constexpr wchar_t empty_guid[37] = + L"00000000-0000-0000-0000-000000000000"; + + template + inline constexpr CharT guid_encoder[17] = "0123456789abcdef"; + + template <> + inline constexpr wchar_t guid_encoder[17] = L"0123456789abcdef"; + } // namespace detail + + // -------------------------------------------------------------------------------------------------------------------------- + // UUID format https://tools.ietf.org/html/rfc4122 + // -------------------------------------------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------------------------------------------- + // Field NDR Data Type Octet # Note + // -------------------------------------------------------------------------------------------------------------------------- + // time_low unsigned long 0 - 3 The low field + // of the timestamp. time_mid unsigned short 4 - 5 + // The middle field of the timestamp. time_hi_and_version unsigned + // short 6 - 7 The high field of the timestamp multiplexed + // with the version number. clock_seq_hi_and_reserved unsigned small 8 + // The high field of the clock sequence multiplexed with the variant. + // clock_seq_low unsigned small 9 The low + // field of the clock sequence. node character 10 + // - 15 The spatially unique node identifier. + // -------------------------------------------------------------------------------------------------------------------------- + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | time_low | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | time_mid | time_hi_and_version | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // |clk_seq_hi_res | clk_seq_low | node (0-1) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | node (2-5) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + // -------------------------------------------------------------------------------------------------------------------------- + // enumerations + // -------------------------------------------------------------------------------------------------------------------------- + + // indicated by a bit pattern in octet 8, marked with N in + // xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx + enum class uuid_variant + { + // NCS backward compatibility (with the obsolete Apollo Network Computing + // System 1.5 UUID format) N bit pattern: 0xxx > the first 6 octets of the + // UUID are a 48-bit timestamp (the number of 4 microsecond units of time + // since 1 Jan 1980 UTC); > the next 2 octets are reserved; > the next octet + // is the "address family"; > the final 7 octets are a 56-bit host ID in the + // form specified by the address family + ncs, + + // RFC 4122/DCE 1.1 + // N bit pattern: 10xx + // > big-endian byte order + rfc, + + // Microsoft Corporation backward compatibility + // N bit pattern: 110x + // > little endian byte order + // > formely used in the Component Object Model (COM) library + microsoft, + + // reserved for possible future definition + // N bit pattern: 111x + reserved + }; + + // indicated by a bit pattern in octet 6, marked with M in + // xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx + enum class uuid_version + { + none = 0, // only possible for nil or invalid uuids + time_based = 1, // The time-based version specified in RFC 4122 + dce_security = 2, // DCE Security version, with embedded POSIX UIDs. + name_based_md5 = + 3, // The name-based version specified in RFS 4122 with MD5 hashing + random_number_based = 4, // The randomly or pseudo-randomly generated version + // specified in RFS 4122 + name_based_sha1 = + 5 // The name-based version specified in RFS 4122 with SHA1 hashing + }; + + // Forward declare uuid & to_string so that we can declare to_string as a friend + // later. + class uuid; + template , class Allocator = std::allocator> + std::basic_string to_string(uuid const& id); + + // -------------------------------------------------------------------------------------------------------------------------- + // uuid class + // -------------------------------------------------------------------------------------------------------------------------- + class uuid + { + public: + using value_type = uint8_t; + + constexpr uuid() noexcept = default; + + uuid(value_type (&arr)[16]) noexcept + { + std::copy(std::cbegin(arr), std::cend(arr), std::begin(data)); + } + + constexpr uuid(std::array const& arr) noexcept + : data{arr} + { + } + + explicit uuid(span bytes) + { + std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data)); + } + + template + explicit uuid(ForwardIterator first, ForwardIterator last) + { + if (std::distance(first, last) == 16) + std::copy(first, last, std::begin(data)); + } + + [[nodiscard]] constexpr uuid_variant variant() const noexcept + { + if ((data[8] & 0x80) == 0x00) + return uuid_variant::ncs; + else if ((data[8] & 0xC0) == 0x80) + return uuid_variant::rfc; + else if ((data[8] & 0xE0) == 0xC0) + return uuid_variant::microsoft; + else + return uuid_variant::reserved; + } + + [[nodiscard]] constexpr uuid_version version() const noexcept + { + if ((data[6] & 0xF0) == 0x10) + return uuid_version::time_based; + else if ((data[6] & 0xF0) == 0x20) + return uuid_version::dce_security; + else if ((data[6] & 0xF0) == 0x30) + return uuid_version::name_based_md5; + else if ((data[6] & 0xF0) == 0x40) + return uuid_version::random_number_based; + else if ((data[6] & 0xF0) == 0x50) + return uuid_version::name_based_sha1; + else + return uuid_version::none; + } + + [[nodiscard]] constexpr bool is_nil() const noexcept + { + for (size_t i = 0; i < data.size(); ++i) + if (data[i] != 0) + return false; + return true; + } + + void swap(uuid& other) noexcept + { + data.swap(other.data); + } + + [[nodiscard]] inline span as_bytes() const + { + return span( + reinterpret_cast(data.data()), 16); + } + + template + [[nodiscard]] constexpr static bool is_valid_uuid( + StringType const& in_str) noexcept + { + auto str = detail::to_string_view(in_str); + bool firstDigit = true; + size_t hasBraces = 0; + size_t index = 0; + + if (str.empty()) + return false; + + if (str.front() == '{') + hasBraces = 1; + if (hasBraces && str.back() != '}') + return false; + + for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) + { + if (str[i] == '-') + continue; + + if (index >= 16 || !detail::is_hex(str[i])) + { + return false; + } + + if (firstDigit) + { + firstDigit = false; + } + else + { + index++; + firstDigit = true; + } + } + + if (index < 16) + { + return false; + } + + return true; + } + + template + [[nodiscard]] constexpr static std::optional from_string( + StringType const& in_str) noexcept + { + auto str = detail::to_string_view(in_str); + bool firstDigit = true; + size_t hasBraces = 0; + size_t index = 0; + + std::array data{{0}}; + + if (str.empty()) + return {}; + + if (str.front() == '{') + hasBraces = 1; + if (hasBraces && str.back() != '}') + return {}; + + for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) + { + if (str[i] == '-') + continue; + + if (index >= 16 || !detail::is_hex(str[i])) + { + return {}; + } + + if (firstDigit) + { + data[index] = static_cast(detail::hex2char(str[i]) << 4); + firstDigit = false; + } + else + { + data[index] = + static_cast(data[index] | detail::hex2char(str[i])); + index++; + firstDigit = true; + } + } + + if (index < 16) + { + return {}; + } + + return uuid{data}; + } + + private: + std::array data{{0}}; + + friend bool operator==(uuid const& lhs, uuid const& rhs) noexcept; + friend bool operator<(uuid const& lhs, uuid const& rhs) noexcept; + + template + friend std::basic_ostream& operator<<( + std::basic_ostream& s, uuid const& id); + + template + friend std::basic_string to_string(uuid const& id); + + friend std::hash; + }; + + // -------------------------------------------------------------------------------------------------------------------------- + // operators and non-member functions + // -------------------------------------------------------------------------------------------------------------------------- + + [[nodiscard]] inline bool operator==(uuid const& lhs, + uuid const& rhs) noexcept + { + return lhs.data == rhs.data; + } + + [[nodiscard]] inline bool operator!=(uuid const& lhs, + uuid const& rhs) noexcept + { + return !(lhs == rhs); + } + + [[nodiscard]] inline bool operator<(uuid const& lhs, uuid const& rhs) noexcept + { + return lhs.data < rhs.data; + } + + template + [[nodiscard]] inline std::basic_string to_string( + uuid const& id) + { + std::basic_string uustr{detail::empty_guid}; + + for (size_t i = 0, index = 0; i < 36; ++i) + { + if (i == 8 || i == 13 || i == 18 || i == 23) + { + continue; + } + uustr[i] = detail::guid_encoder[id.data[index] >> 4 & 0x0f]; + uustr[++i] = detail::guid_encoder[id.data[index] & 0x0f]; + index++; + } + + return uustr; + } + + template + std::basic_ostream& operator<<( + std::basic_ostream& s, uuid const& id) + { + s << to_string(id); + return s; + } + + inline void swap(uuids::uuid& lhs, uuids::uuid& rhs) noexcept + { + lhs.swap(rhs); + } + + // -------------------------------------------------------------------------------------------------------------------------- + // namespace IDs that could be used for generating name-based uuids + // -------------------------------------------------------------------------------------------------------------------------- + + // Name string is a fully-qualified domain name + static uuid uuid_namespace_dns{{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // Name string is a URL + static uuid uuid_namespace_url{{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // Name string is an ISO OID (See https://oidref.com/, + // https://en.wikipedia.org/wiki/Object_identifier) + static uuid uuid_namespace_oid{{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // Name string is an X.500 DN, in DER or a text output format (See + // https://en.wikipedia.org/wiki/X.500, + // https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One) + static uuid uuid_namespace_x500{{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // -------------------------------------------------------------------------------------------------------------------------- + // uuid generators + // -------------------------------------------------------------------------------------------------------------------------- + +#ifdef UUID_SYSTEM_GENERATOR + class uuid_system_generator + { + public: + using result_type = uuid; + + uuid operator()() + { +#ifdef _WIN32 + + GUID newId; + HRESULT hr = ::CoCreateGuid(&newId); + + if (FAILED(hr)) + { + throw std::system_error(hr, std::system_category(), + "CoCreateGuid failed"); + } + + std::array bytes = { + {static_cast((newId.Data1 >> 24) & 0xFF), + static_cast((newId.Data1 >> 16) & 0xFF), + static_cast((newId.Data1 >> 8) & 0xFF), + static_cast((newId.Data1) & 0xFF), + + (unsigned char)((newId.Data2 >> 8) & 0xFF), + (unsigned char)((newId.Data2) & 0xFF), + + (unsigned char)((newId.Data3 >> 8) & 0xFF), + (unsigned char)((newId.Data3) & 0xFF), + + newId.Data4[0], newId.Data4[1], newId.Data4[2], newId.Data4[3], + newId.Data4[4], newId.Data4[5], newId.Data4[6], newId.Data4[7]}}; + + return uuid{std::begin(bytes), std::end(bytes)}; + +#elif defined(__linux__) || defined(__unix__) + + uuid_t id; + uuid_generate(id); + + std::array bytes = {{id[0], id[1], id[2], id[3], id[4], id[5], + id[6], id[7], id[8], id[9], id[10], + id[11], id[12], id[13], id[14], id[15]}}; + + return uuid{std::begin(bytes), std::end(bytes)}; + +#elif defined(__APPLE__) + auto newId = CFUUIDCreate(NULL); + auto bytes = CFUUIDGetUUIDBytes(newId); + CFRelease(newId); + + std::array arrbytes = { + {bytes.byte0, bytes.byte1, bytes.byte2, bytes.byte3, bytes.byte4, + bytes.byte5, bytes.byte6, bytes.byte7, bytes.byte8, bytes.byte9, + bytes.byte10, bytes.byte11, bytes.byte12, bytes.byte13, bytes.byte14, + bytes.byte15}}; + return uuid{std::begin(arrbytes), std::end(arrbytes)}; +#else + return uuid{}; +#endif + } + }; +#endif + + template + class basic_uuid_random_generator + { + public: + using engine_type = UniformRandomNumberGenerator; + + explicit basic_uuid_random_generator(engine_type& gen) + : generator(&gen, [](auto) {}) + { + } + explicit basic_uuid_random_generator(engine_type* gen) + : generator(gen, [](auto) {}) + { + } + + [[nodiscard]] uuid operator()() + { + alignas(uint32_t) uint8_t bytes[16]; + for (int i = 0; i < 16; i += 4) + *reinterpret_cast(bytes + i) = distribution(*generator); + + // variant must be 10xxxxxx + bytes[8] &= 0xBF; + bytes[8] |= 0x80; + + // version must be 0100xxxx + bytes[6] &= 0x4F; + bytes[6] |= 0x40; + + return uuid{std::begin(bytes), std::end(bytes)}; + } + + private: + std::uniform_int_distribution distribution; + std::shared_ptr generator; + }; + + using uuid_random_generator = basic_uuid_random_generator; + + class uuid_name_generator + { + public: + explicit uuid_name_generator(uuid const& namespace_uuid) noexcept + : nsuuid(namespace_uuid) + { + } + + template + [[nodiscard]] uuid operator()(StringType const& name) + { + reset(); + process_characters(detail::to_string_view(name)); + return make_uuid(); + } + + private: + void reset() + { + hasher.reset(); + std::byte bytes[16]; + auto nsbytes = nsuuid.as_bytes(); + std::copy(std::cbegin(nsbytes), std::cend(nsbytes), bytes); + hasher.process_bytes(bytes, 16); + } + + template + void process_characters(std::basic_string_view const str) + { + for (uint32_t c : str) + { + hasher.process_byte(static_cast(c & 0xFF)); + if constexpr (!std::is_same_v) + { + hasher.process_byte(static_cast((c >> 8) & 0xFF)); + hasher.process_byte(static_cast((c >> 16) & 0xFF)); + hasher.process_byte(static_cast((c >> 24) & 0xFF)); + } + } + } + + [[nodiscard]] uuid make_uuid() + { + detail::sha1::digest8_t digest; + hasher.get_digest_bytes(digest); + + // variant must be 0b10xxxxxx + digest[8] &= 0xBF; + digest[8] |= 0x80; + + // version must be 0b0101xxxx + digest[6] &= 0x5F; + digest[6] |= 0x50; + + return uuid{digest, digest + 16}; + } + + private: + uuid nsuuid; + detail::sha1 hasher; + }; + +#ifdef UUID_TIME_GENERATOR + // !!! DO NOT USE THIS IN PRODUCTION + // this implementation is unreliable for good uuids + class uuid_time_generator + { + using mac_address = std::array; + + std::optional device_address; + + [[nodiscard]] bool get_mac_address() + { + if (device_address.has_value()) + { + return true; + } + +#ifdef _WIN32 + DWORD len = 0; + auto ret = GetAdaptersInfo(nullptr, &len); + if (ret != ERROR_BUFFER_OVERFLOW) + return false; + std::vector buf(len); + auto pips = reinterpret_cast(&buf.front()); + ret = GetAdaptersInfo(pips, &len); + if (ret != ERROR_SUCCESS) + return false; + mac_address addr; + std::copy(pips->Address, pips->Address + 6, std::begin(addr)); + device_address = addr; +#endif + + return device_address.has_value(); + } + + [[nodiscard]] long long get_time_intervals() + { + auto start = std::chrono::system_clock::from_time_t(time_t(-12219292800)); + auto diff = std::chrono::system_clock::now() - start; + auto ns = + std::chrono::duration_cast(diff).count(); + return ns / 100; + } + + [[nodiscard]] static unsigned short get_clock_sequence() + { + static std::mt19937 clock_gen(std::random_device{}()); + static std::uniform_int_distribution clock_dis; + static std::atomic_ushort clock_sequence = clock_dis(clock_gen); + return clock_sequence++; + } + + public: + [[nodiscard]] uuid operator()() + { + if (get_mac_address()) + { + std::array data; + + auto tm = get_time_intervals(); + + auto clock_seq = get_clock_sequence(); + + auto ptm = reinterpret_cast(&tm); + + memcpy(&data[0], ptm + 4, 4); + memcpy(&data[4], ptm + 2, 2); + memcpy(&data[6], ptm, 2); + + memcpy(&data[8], &clock_seq, 2); + + // variant must be 0b10xxxxxx + data[8] &= 0xBF; + data[8] |= 0x80; + + // version must be 0b0001xxxx + data[6] &= 0x1F; + data[6] |= 0x10; + + memcpy(&data[10], &device_address.value()[0], 6); + + return uuids::uuid{std::cbegin(data), std::cend(data)}; + } + + return {}; + } + }; +#endif +} // namespace uuids + +namespace std +{ + template <> + struct hash + { + using argument_type = uuids::uuid; + using result_type = std::size_t; + + [[nodiscard]] result_type operator()(argument_type const& uuid) const + { +#ifdef UUID_HASH_STRING_BASED + std::hash hasher; + return static_cast(hasher(uuids::to_string(uuid))); +#else + uint64_t l = static_cast(uuid.data[0]) << 56 | + static_cast(uuid.data[1]) << 48 | + static_cast(uuid.data[2]) << 40 | + static_cast(uuid.data[3]) << 32 | + static_cast(uuid.data[4]) << 24 | + static_cast(uuid.data[5]) << 16 | + static_cast(uuid.data[6]) << 8 | + static_cast(uuid.data[7]); + uint64_t h = static_cast(uuid.data[8]) << 56 | + static_cast(uuid.data[9]) << 48 | + static_cast(uuid.data[10]) << 40 | + static_cast(uuid.data[11]) << 32 | + static_cast(uuid.data[12]) << 24 | + static_cast(uuid.data[13]) << 16 | + static_cast(uuid.data[14]) << 8 | + static_cast(uuid.data[15]); + + if constexpr (sizeof(result_type) > 4) + { + return result_type(l ^ h); + } + else + { + uint64_t hash64 = l ^ h; + return result_type(uint32_t(hash64 >> 32) ^ uint32_t(hash64)); + } +#endif + } + }; +} // namespace std + +#endif /* STDUUID_H */ \ No newline at end of file diff --git a/Comm/Version.hxx b/Comm/Version.hxx new file mode 100644 index 0000000..377a688 --- /dev/null +++ b/Comm/Version.hxx @@ -0,0 +1,3 @@ +#pragma once + +#define kDistVersion "v1.20" diff --git a/Common/AsmKit/AsmKit.hpp b/Common/AsmKit/AsmKit.hpp deleted file mode 100644 index 020ca5c..0000000 --- a/Common/AsmKit/AsmKit.hpp +++ /dev/null @@ -1,217 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -#include -#include -#include - -namespace CompilerKit -{ - // - // @brief Frontend to Assembly mountpoint. - // - class AssemblyInterface - { - public: - explicit AssemblyInterface() = default; - virtual ~AssemblyInterface() = default; - - MPCC_COPY_DEFAULT(AssemblyInterface); - - //@ brief compile to object file. - // 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; - - MPCC_COPY_DEFAULT(AssemblyFactory); - - public: - enum - { - kArchAMD64, - kArch32x0, - kArch64x0, - kArchRISCV, - kArchPowerPC, - 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; - - MPCC_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; - - MPCC_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_64x0__ - - class Encoder64x0 final : public EncoderInterface - { - public: - explicit Encoder64x0() = default; - ~Encoder64x0() override = default; - - MPCC_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; - - MPCC_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; - - MPCC_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 CompilerKit diff --git a/Common/AsmKit/CPU/32x0.hpp b/Common/AsmKit/CPU/32x0.hpp deleted file mode 100644 index fe03336..0000000 --- a/Common/AsmKit/CPU/32x0.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#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]; - 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 kOpcodes32x0 = { - kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. - kAsmOpcodeDecl("br", 0b1110011, 0b001, kAsmJump) // jump to branch - kAsmOpcodeDecl("mr", 0b0100011, 0b101, kAsmImmediate) // move registers - kAsmOpcodeDecl("psh", 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 - -//////////////////////////////// diff --git a/Common/AsmKit/CPU/64x0.hpp b/Common/AsmKit/CPU/64x0.hpp deleted file mode 100644 index b28866f..0000000 --- a/Common/AsmKit/CPU/64x0.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#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("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 - -//////////////////////////////// diff --git a/Common/AsmKit/CPU/amd64.hpp b/Common/AsmKit/CPU/amd64.hpp deleted file mode 100644 index 507602c..0000000 --- a/Common/AsmKit/CPU/amd64.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#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; - -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 15 diff --git a/Common/AsmKit/CPU/ppc.hpp b/Common/AsmKit/CPU/ppc.hpp deleted file mode 100644 index c4265da..0000000 --- a/Common/AsmKit/CPU/ppc.hpp +++ /dev/null @@ -1,1919 +0,0 @@ -#pragma once - -#include - -/// @note Based of: -/// https://opensource.apple.com/source/cctools/cctools-750/as/ppc-opcode.h.auto.html - -/* - * 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 optype -{ - 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 SizeType size_t - -#define VoidPtr void* -#define voidPtr VoidPtr - -#define UIntPtr uintptr_t - -#define Int64 int64_t -#define UInt64 uint64_t - -#define Int32 int -#define UInt32 unsigned - -#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 -#include -#include - -#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 MPCC_COPY_DELETE(KLASS) \ - KLASS& operator=(const KLASS&) = delete; \ - KLASS(const KLASS&) = delete; - -#define MPCC_COPY_DEFAULT(KLASS) \ - KLASS& operator=(const KLASS&) = default; \ - KLASS(const KLASS&) = default; - -#define MPCC_MOVE_DELETE(KLASS) \ - KLASS& operator=(KLASS&&) = delete; \ - KLASS(KLASS&&) = delete; - -#define MPCC_MOVE_DEFAULT(KLASS) \ - KLASS& operator=(KLASS&&) = default; \ - KLASS(KLASS&&) = default; - -#include -#include -#include -#include - -namespace CompilerKit -{ - inline constexpr int BASE_YEAR = 1900; - - inline std::string current_date() noexcept - { - 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) noexcept - { - 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; - } -} // namespace CompilerKit - -#define PACKED __attribute__((packed)) - -typedef char char_type; - -#define kObjectFileExt ".obj" -#define kBinaryFileExt ".bin" - -#define kAsmFileExts \ - { \ - ".64x", ".32x", ".masm", ".s", ".S", ".asm" \ - } - -#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__ */ - -#pragma scalar_storage_order big - endian - -#endif /* ifndef __MPCC_DEFINES_HPP__ */ diff --git a/Common/ParserKit.hpp b/Common/ParserKit.hpp deleted file mode 100644 index 6e15c75..0000000 --- a/Common/ParserKit.hpp +++ /dev/null @@ -1,171 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -#include -#include - -namespace ParserKit -{ - using namespace CompilerKit; - - /// @brief Compiler backend, implements a frontend, such as C, C++... - /// See Toolchain, for some examples. - class CompilerBackend - { - public: - explicit CompilerBackend() = default; - virtual ~CompilerBackend() = default; - - MPCC_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 "Invalid Language"; - } - }; - - struct SyntaxLeafList; - struct SyntaxLeafList; - struct CompilerKeyword; - - /// we want to do that because to separate keywords. - enum KeywordKind - { - eKeywordKindNamespace, - eKeywordKindFunctionStart, - eKeywordKindFunctionEnd, - eKeywordKindVariable, - eKeywordKindType, - eKeywordKindExpressionBegin, - eKeywordKindExpressionEnd, - eKeywordKindArgSeparator, - eKeywordKindBodyStart, - eKeywordKindBodyEnd, - eKeywordKindClass, - eKeywordKindPtrAccess, - eKeywordKindAccess, - eKeywordKindIf, - eKeywordKindElse, - eKeywordKindElseIf, - eKeywordKindVariableAssign, - eKeywordKindVariableDec, - eKeywordKindVariableInc, - eKeywordKindConstant, - eKeywordKindTypedef, - eKeywordKindEndInstr, - eKeywordKindSpecifier, - eKeywordKindInvalid, - eKeywordKindReturn, - eKeywordKindCommentInline, - eKeywordKindCommentMultiLineStart, - eKeywordKindCommentMultiLineEnd, - eKeywordKindEq, - eKeywordKindNotEq, - eKeywordKindGreaterEq, - eKeywordKindLessEq, - eKeywordKindPtr, - }; - - /// \brief Compiler keyword information struct. - struct CompilerKeyword - { - std::string keyword_name; - KeywordKind keyword_kind = eKeywordKindInvalid; - }; - struct SyntaxLeafList final - { - struct SyntaxLeaf final - { - Int32 fUserType; -#ifdef __PK_USE_STRUCT_INSTEAD__ - CompilerKeyword fUserData; -#else - std::string fUserData; -#endif - - std::string fUserValue; - struct SyntaxLeaf* fNext; - }; - - std::vector fLeafList; - SizeType fNumLeafs; - - size_t SizeOf() - { - return fNumLeafs; - } - std::vector& 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; - } -} // namespace ParserKit diff --git a/Common/Public/SDK/CRT/__mpcc_alloca.hxx b/Common/Public/SDK/CRT/__mpcc_alloca.hxx deleted file mode 100644 index a1c638e..0000000 --- a/Common/Public/SDK/CRT/__mpcc_alloca.hxx +++ /dev/null @@ -1,15 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -typedef void* ptr_type; -typedef __SIZE_TYPE__ size_type; - -inline void* __mpcc_alloca_gcc(size_type sz) -{ - return __builtin_alloca(sz); -} diff --git a/Common/Public/SDK/CRT/__mpcc_defines.hxx b/Common/Public/SDK/CRT/__mpcc_defines.hxx deleted file mode 100644 index 5560410..0000000 --- a/Common/Public/SDK/CRT/__mpcc_defines.hxx +++ /dev/null @@ -1,89 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#ifndef __MPCC_DEF__ -#define __MPCC_DEF__ - -#ifndef __GNUC__ - -typedef __SIZE_TYPE__ size_t; - -#ifdef __LP64__ -typedef long int ssize_t; -#else -typedef int ssize_t; -#endif // __LP64__ - -typedef size_t ptrdiff_t; -typedef size_t uintptr_t; -typedef void* voidptr_t; -typedef void* any_t; -typedef char* caddr_t; - -#ifndef NULL -#define NULL ((voidptr_t)0) -#endif // !null - -#ifdef __GNUC__ -#include -#define __mpcc_alloca(sz) __mpcc_alloca_gcc(sz) -#elif defined(__MPCC__) - -#define __alloca(sz) __mpcc_alloca(sz) -#endif - -#define __deref(ptr) (*(ptr)) - -#ifdef __cplusplus -#define __init_decl() \ - extern "C" \ - { -#define __fini_decl() \ - } \ - ; -#else -#define __init_decl() -#define __fini_decl() -#endif - -#if __has_builtin(__builtin_alloca) -#define alloca(sz) __builtin_alloca(sz) -#ifdef __alloca -#undef __alloca -#endif -#define __alloca alloca -#else -#warning alloca not detected (MPCC) -#endif - -typedef long long off_t; -typedef unsigned long long uoff_t; - -typedef union float_cast { - struct - { - unsigned int mantissa : 23; - unsigned int exponent : 8; - unsigned int sign : 1; - }; - - float f; -} __attribute__((packed)) float_cast_t; - -typedef union double_cast { - struct - { - unsigned long long int mantissa : 52; - unsigned int exponent : 11; - unsigned int sign : 1; - }; - - double f; -} __attribute__((packed)) double_cast_t; - -#endif // ifndef __GNUC__ - -#endif /* __MPCC_DEF__ */ diff --git a/Common/Public/SDK/CRT/__mpcc_exception.hxx b/Common/Public/SDK/CRT/__mpcc_exception.hxx deleted file mode 100644 index 9366102..0000000 --- a/Common/Public/SDK/CRT/__mpcc_exception.hxx +++ /dev/null @@ -1,27 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -/// This file is an implementation of __throw* family of functions. - -#include -#include -#include - -namespace std -{ - inline void __throw_general(void) - { - throw std::runtime_error("MPCC C++ Runtime error."); - } - - inline void __throw_domain_error(const char* error) - { - std::cout << "MPCC C++: Domain error: " << error << "\r"; - __throw_general(); - } -} // namespace std diff --git a/Common/Public/SDK/CRT/__mpcc_hint.hxx b/Common/Public/SDK/CRT/__mpcc_hint.hxx deleted file mode 100644 index ee14711..0000000 --- a/Common/Public/SDK/CRT/__mpcc_hint.hxx +++ /dev/null @@ -1,20 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -#pragma compiler(hint_manifest) - -#define _Input -#define _Output - -#define _Optional - -#define _StrictCheckInput -#define _StrictCheckOutput - -#define _InOut -#define _StrictInOut diff --git a/Common/Public/SDK/CRT/__mpcc_malloc.hxx b/Common/Public/SDK/CRT/__mpcc_malloc.hxx deleted file mode 100644 index 2731868..0000000 --- a/Common/Public/SDK/CRT/__mpcc_malloc.hxx +++ /dev/null @@ -1,30 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -#include - -namespace stdx -{ - /// @brief allocate a new class. - /// @tparam KindClass the class type to allocate. - template - inline void* allocate(Args&&... args) - { - return new KindClass(std::forward(args)...); - } - - /// @brief free a class. - /// @tparam KindClass the class type to allocate. - template - inline void release(KindClass ptr) - { - if (!ptr) - return; - delete ptr; - } -} // namespace stdx diff --git a/Common/Public/SDK/CRT/__mpcc_power.inc b/Common/Public/SDK/CRT/__mpcc_power.inc deleted file mode 100644 index 9e4928c..0000000 --- a/Common/Public/SDK/CRT/__mpcc_power.inc +++ /dev/null @@ -1,35 +0,0 @@ -# Path: SDK/__mpcc_power.inc -# Language: MPCC POWER Assembly support for GNU. -# Build Date: 2024-6-4 - -%ifdef __CODETOOLS__ - -%def lda li -%def sta stw -%def ldw li - -%def r0 0 -%def r1 1 -%def r2 2 -%def r3 3 -%def r4 4 -%def r5 5 -%def r6 6 -%def r7 7 -%def r8 8 -%def r9 9 -%def r10 10 -%def r11 11 -%def r12 12 -%def r13 13 -%def r14 14 -%def r15 15 -%def r16 16 -%def r17 17 -%def r18 18 -%def r19 19 -%def r20 20 - -%endif - -%def nop mr 0, 0 diff --git a/Common/StdKit/AE.hpp b/Common/StdKit/AE.hpp deleted file mode 100644 index 9c4ac1a..0000000 --- a/Common/StdKit/AE.hpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * ======================================================== - * - * MPCC - * Copyright SoftwareLabs, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include - -#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; - 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 CompilerKit - -// 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 -{ - /** - * @brief AE Reader protocol - * - */ - class AEReadableProtocol final - { - public: - std::ifstream FP; - - public: - explicit AEReadableProtocol() = default; - ~AEReadableProtocol() = default; - - MPCC_COPY_DELETE(AEReadableProtocol); - - /** - * @brief Read AE record - * - * @param raw the containing buffer - * @param sz it's size (without sizeof(AERecordHeader) added to it.) - * @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 CompilerKit::Utils diff --git a/Common/StdKit/ELF.hpp b/Common/StdKit/ELF.hpp deleted file mode 100644 index 4f0d0ae..0000000 --- a/Common/StdKit/ELF.hpp +++ /dev/null @@ -1,389 +0,0 @@ -#pragma once - -#include -#include - -struct file; - -#ifndef elf_read_implies_exec -/* Executables for which elf_read_implies_exec() returns TRUE will - have the READ_IMPLIES_EXEC personality flag set automatically. - Override in asm/elf.h as needed. */ -#define elf_read_implies_exec(ex, have_pt_gnu_stack) 0 -#endif - -/* 32-bit ELF base types. */ -typedef uint32_t Elf32_Addr; -typedef uint16_t Elf32_Half; -typedef uint32_t Elf32_Off; -typedef int32_t Elf32_Sword; -typedef uint32_t Elf32_Word; - -/* 64-bit ELF base types. */ -typedef uintptr_t Elf64_Addr; -typedef uint16_t Elf64_Half; -typedef int16_t Elf64_SHalf; -typedef uint64_t Elf64_Off; -typedef int32_t Elf64_Sword; -typedef uint32_t Elf64_Word; -typedef uint64_t Elf64_Xword; -typedef int64_t Elf64_Sxword; - -/* These constants are for the segment types stored in the image headers */ -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_TLS 7 /* Thread local storage segment */ -#define PT_LOOS 0x60000000 /* OS-specific */ -#define PT_HIOS 0x6fffffff /* OS-specific */ -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff -#define PT_GNU_EH_FRAME 0x6474e550 - -#define PT_GNU_STACK (PT_LOOS + 0x474e551) - -/* These constants define the different elf file types */ -#define ET_NONE 0 -#define ET_REL 1 -#define ET_EXEC 2 -#define ET_DYN 3 -#define ET_CORE 4 -#define ET_LOPROC 0xff00 -#define ET_HIPROC 0xffff - -/* This is the info that is needed to parse the dynamic section of the file */ -#define DT_NULL 0 -#define DT_NEEDED 1 -#define DT_PLTRELSZ 2 -#define DT_PLTGOT 3 -#define DT_HASH 4 -#define DT_STRTAB 5 -#define DT_SYMTAB 6 -#define DT_RELA 7 -#define DT_RELASZ 8 -#define DT_RELAENT 9 -#define DT_STRSZ 10 -#define DT_SYMENT 11 -#define DT_INIT 12 -#define DT_FINI 13 -#define DT_SONAME 14 -#define DT_RPATH 15 -#define DT_SYMBOLIC 16 -#define DT_REL 17 -#define DT_RELSZ 18 -#define DT_RELENT 19 -#define DT_PLTREL 20 -#define DT_DEBUG 21 -#define DT_TEXTREL 22 -#define DT_JMPREL 23 -#define DT_ENCODING 32 -#define OLD_DT_LOOS 0x60000000 -#define DT_LOOS 0x6000000d -#define DT_HIOS 0x6ffff000 -#define DT_VALRNGLO 0x6ffffd00 -#define DT_VALRNGHI 0x6ffffdff -#define DT_ADDRRNGLO 0x6ffffe00 -#define DT_ADDRRNGHI 0x6ffffeff -#define DT_VERSYM 0x6ffffff0 -#define DT_RELACOUNT 0x6ffffff9 -#define DT_RELCOUNT 0x6ffffffa -#define DT_FLAGS_1 0x6ffffffb -#define DT_VERDEF 0x6ffffffc -#define DT_VERDEFNUM 0x6ffffffd -#define DT_VERNEED 0x6ffffffe -#define DT_VERNEEDNUM 0x6fffffff -#define OLD_DT_HIOS 0x6fffffff -#define DT_LOPROC 0x70000000 -#define DT_HIPROC 0x7fffffff - -/* This info is needed when parsing the symbol table */ -#define STB_LOCAL 0 -#define STB_GLOBAL 1 -#define STB_WEAK 2 - -#define STT_NOTYPE 0 -#define STT_OBJECT 1 -#define STT_FUNC 2 -#define STT_SECTION 3 -#define STT_FILE 4 -#define STT_COMMON 5 -#define STT_TLS 6 - -#define ELF_ST_BIND(x) ((x) >> 4) -#define ELF_ST_TYPE(x) (((unsigned int)x) & 0xf) -#define ELF32_ST_BIND(x) ELF_ST_BIND(x) -#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) -#define ELF64_ST_BIND(x) ELF_ST_BIND(x) -#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x) - -typedef struct dynamic -{ - Elf32_Sword d_tag; - union { - Elf32_Sword d_val; - Elf32_Addr d_ptr; - } d_un; -} Elf32_Dyn; - -typedef struct -{ - Elf64_Sxword d_tag; /* entry tag value */ - union { - Elf64_Xword d_val; - Elf64_Addr d_ptr; - } d_un; -} Elf64_Dyn; - -/* The following are used with relocations */ -#define ELF32_R_SYM(x) ((x) >> 8) -#define ELF32_R_TYPE(x) ((x)&0xff) - -#define ELF64_R_SYM(i) ((i) >> 32) -#define ELF64_R_TYPE(i) ((i)&0xffffffff) - -typedef struct elf32_rel -{ - Elf32_Addr r_offset; - Elf32_Word r_info; -} Elf32_Rel; - -typedef struct elf64_rel -{ - Elf64_Addr r_offset; /* Location at which to apply the action */ - Elf64_Xword r_info; /* index and type of relocation */ -} Elf64_Rel; - -typedef struct elf32_rela -{ - Elf32_Addr r_offset; - Elf32_Word r_info; - Elf32_Sword r_addend; -} Elf32_Rela; - -typedef struct elf64_rela -{ - Elf64_Addr r_offset; /* Location at which to apply the action */ - Elf64_Xword r_info; /* index and type of relocation */ - Elf64_Sxword r_addend; /* Constant addend used to compute value */ -} Elf64_Rela; - -typedef struct elf32_sym -{ - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; - unsigned char st_info; - unsigned char st_other; - Elf32_Half st_shndx; -} Elf32_Sym; - -typedef struct elf64_sym -{ - Elf64_Word st_name; /* Symbol name, index in string tbl */ - unsigned char st_info; /* Type and binding attributes */ - unsigned char st_other; /* No defined meaning, 0 */ - Elf64_Half st_shndx; /* Associated section index */ - Elf64_Addr st_value; /* Value of the symbol */ - Elf64_Xword st_size; /* Associated symbol size */ -} Elf64_Sym; - -#define EI_NIDENT 16 - -typedef struct elf32_hdr -{ - unsigned char e_ident[EI_NIDENT]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; /* Entry point */ - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -} Elf32_Ehdr; - -typedef struct elf64_hdr -{ - unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ - Elf64_Half e_type; - Elf64_Half e_machine; - Elf64_Word e_version; - Elf64_Addr e_entry; /* Entry point virtual address */ - Elf64_Off e_phoff; /* Program header table file offset */ - Elf64_Off e_shoff; /* Section header table file offset */ - Elf64_Word e_flags; - Elf64_Half e_ehsize; - Elf64_Half e_phentsize; - Elf64_Half e_phnum; - Elf64_Half e_shentsize; - Elf64_Half e_shnum; - Elf64_Half e_shstrndx; -} Elf64_Ehdr; - -/* These constants define the permissions on sections in the program - header, p_flags. */ -#define PF_R 0x4 -#define PF_W 0x2 -#define PF_X 0x1 - -typedef struct elf32_phdr -{ - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; -} Elf32_Phdr; - -typedef struct elf64_phdr -{ - Elf64_Word p_type; - Elf64_Word p_flags; - Elf64_Off p_offset; /* Segment file offset */ - Elf64_Addr p_vaddr; /* Segment virtual address */ - Elf64_Addr p_paddr; /* Segment physical address */ - Elf64_Xword p_filesz; /* Segment size in file */ - Elf64_Xword p_memsz; /* Segment size in memory */ - Elf64_Xword p_align; /* Segment alignment, file & memory */ -} Elf64_Phdr; - -/* sh_type */ -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 -#define SHT_NUM 12 -#define SHT_LOPROC 0x70000000 -#define SHT_HIPROC 0x7fffffff -#define SHT_LOUSER 0x80000000 -#define SHT_HIUSER 0xffffffff - -/* sh_flags */ -#define SHF_WRITE 0x1 -#define SHF_ALLOC 0x2 -#define SHF_EXECINSTR 0x4 -#define SHF_MASKPROC 0xf0000000 - -/* special section indexes */ -#define SHN_UNDEF 0 -#define SHN_LORESERVE 0xff00 -#define SHN_LOPROC 0xff00 -#define SHN_HIPROC 0xff1f -#define SHN_ABS 0xfff1 -#define SHN_COMMON 0xfff2 -#define SHN_HIRESERVE 0xffff - -typedef struct -{ - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -} Elf32_Shdr; - -typedef struct elf64_shdr -{ - Elf64_Word sh_name; /* Section name, index in string tbl */ - Elf64_Word sh_type; /* Type of section */ - Elf64_Xword sh_flags; /* Miscellaneous section attributes */ - Elf64_Addr sh_addr; /* Section virtual addr at execution */ - Elf64_Off sh_offset; /* Section file offset */ - Elf64_Xword sh_size; /* Size of section in bytes */ - Elf64_Word sh_link; /* Index of another section */ - Elf64_Word sh_info; /* Additional section information */ - Elf64_Xword sh_addralign; /* Section alignment */ - Elf64_Xword sh_entsize; /* Entry size if section holds table */ -} Elf64_Shdr; - -#define EI_MAG0 0 /* e_ident[] indexes */ -#define EI_MAG1 1 -#define EI_MAG2 2 -#define EI_MAG3 3 -#define EI_CLASS 4 -#define EI_DATA 5 -#define EI_VERSION 6 -#define EI_OSABI 7 -#define EI_PAD 8 - -#define ELFMAG0 0x7f /* EI_MAG */ -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -#define ELFCLASSNONE 0 /* EI_CLASS */ -#define ELFCLASS32 1 -#define ELFCLASS64 2 -#define ELFCLASSNUM 3 - -#define ELFDATANONE 0 /* e_ident[EI_DATA] */ -#define ELFDATA2LSB 1 -#define ELFDATA2MSB 2 - -#define EV_NONE 0 /* e_version, EI_VERSION */ -#define EV_CURRENT 1 -#define EV_NUM 2 - -#define ELFOSABI_NONE 0 -#define ELFOSABI_LINUX 3 - -#ifndef ELF_OSABI -#define ELF_OSABI ELFOSABI_NONE -#endif - -/* Notes used in ET_CORE */ -#define NT_PRSTATUS 1 -#define NT_PRFPREG 2 -#define NT_PRPSINFO 3 -#define NT_TASKSTRUCT 4 -#define NT_AUXV 6 -#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ -#define NT_PPC_VMX 0x100 /* POWER Altivec/VMX registers */ -#define NT_PPC_SPE 0x101 /* POWER SPE/EVR registers */ -#define NT_PPC_VSX 0x102 /* POWER VSX registers */ -#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ -#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ -#define NT_PRXSTATUS 0x300 /* s390 upper register halves */ - -/* Note header in a PT_NOTE section */ -typedef struct elf32_note -{ - Elf32_Word n_namesz; /* Name size */ - Elf32_Word n_descsz; /* Content size */ - Elf32_Word n_type; /* Content type */ -} Elf32_Nhdr; - -/* Note header in a PT_NOTE section */ -typedef struct elf64_note -{ - Elf64_Word n_namesz; /* Name size */ - Elf64_Word n_descsz; /* Content size */ - Elf64_Word n_type; /* Content type */ -} Elf64_Nhdr; diff --git a/Common/StdKit/ErrorID.hpp b/Common/StdKit/ErrorID.hpp deleted file mode 100644 index 9f12ab2..0000000 --- a/Common/StdKit/ErrorID.hpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * ======================================================== - * - * CompilerKit - * Copyright SoftwareLabs, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -#define MPCC_EXEC_ERROR -30 -#define MPCC_FILE_NOT_FOUND -31 -#define MPCC_DIR_NOT_FOUND -32 -#define MPCC_FILE_EXISTS -33 -#define MPCC_TOO_LONG -34 -#define MPCC_INVALID_DATA -35 -#define MPCC_UNIMPLEMENTED -36 -#define MPCC_FAT_ERROR -37 diff --git a/Common/StdKit/ErrorOr.hpp b/Common/StdKit/ErrorOr.hpp deleted file mode 100644 index cf35b26..0000000 --- a/Common/StdKit/ErrorOr.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * ======================================================== - * - * CompilerKit - * Copyright SoftwareLabs, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -namespace CompilerKit -{ - 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 CompilerKit diff --git a/Common/StdKit/PEF.hpp b/Common/StdKit/PEF.hpp deleted file mode 100644 index 9fcc554..0000000 --- a/Common/StdKit/PEF.hpp +++ /dev/null @@ -1,132 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -#include - -// @file PEF.hpp -// @brief Preferred Executable Format - -#define kPefMagic "Joy!" -#define kPefMagicFat "yoJ!" - -#define kPefExt ".exec" -#define kPefDylibExt ".lib" -#define kPefLibExt ".slib" -#define kPefObjectExt ".obj" -#define kPefDebugExt ".dbg" - -#define kPefMagicLen 5 - -#define kPefVersion 2 -#define kPefNameLen 255 - -#define kPefBaseOrigin (0x1000000) - -#define kPefStart "__ImageStart" - -namespace CompilerKit -{ - enum - { - kPefArchIntel86S = 100, - kPefArchAMD64, - kPefArchRISCV, - kPefArch64000, /* 64x0 RISC architecture. */ - kPefArch32000, - kPefArchPowerPC, /* 64-bit POWER architecture. */ - kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1, - kPefArchInvalid = 0xFF, - }; - - enum - { - kPefSubArchAMD, - kPefSubArchIntel, - kPefSubArchGeneric, - kPefSubArchIBM, - }; - - enum - { - kPefKindExec = 1, /* .exe */ - kPefKindSharedObject = 2, /* .lib */ - 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; - - /* 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; - - enum - { - kPefCode = 0xC, - kPefData = 0xD, - kPefZero = 0xE, - kPefLinkerID = 0x1, - kPefCount = 4, - kPefInvalid = 0xFF, - }; -} // namespace CompilerKit - -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/Common/StdKit/Ref.hpp b/Common/StdKit/Ref.hpp deleted file mode 100644 index f4a11c0..0000000 --- a/Common/StdKit/Ref.hpp +++ /dev/null @@ -1,91 +0,0 @@ - -/* - * ======================================================== - * - * CompilerKit - * Copyright SoftwareLabs, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -namespace CompilerKit -{ - // @author SoftwareLabs - // @brief Reference class, refers to a pointer of data in static memory. - template - 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 - class NonNullRef final - { - public: - NonNullRef() = delete; - NonNullRef(nullPtr) = 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 CompilerKit diff --git a/Common/StdKit/String.hpp b/Common/StdKit/String.hpp deleted file mode 100644 index a05a31c..0000000 --- a/Common/StdKit/String.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * ======================================================== - * - * CompilerKit - * Copyright SoftwareLabs, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -namespace CompilerKit -{ - /** - * @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 char[Sz]; - assert(m_Data); - } - - ~StringView() noexcept - { - if (m_Data) - { - memset(m_Data, 0, m_Sz); - delete[] m_Data; - - m_Data = nullptr; - } - } - - MPCC_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: - char* 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 CompilerKit diff --git a/Common/StdKit/XCOFF.hxx b/Common/StdKit/XCOFF.hxx deleted file mode 100644 index a26b591..0000000 --- a/Common/StdKit/XCOFF.hxx +++ /dev/null @@ -1,41 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - - File: XCOFF.hpp - Purpose: XCOFF for NewOS. - - 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 CompilerKit -{ - /// @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 CompilerKit - -#endif // ifndef __XCOFF__ \ No newline at end of file diff --git a/Common/UUID.hpp b/Common/UUID.hpp deleted file mode 100644 index 00b153b..0000000 --- a/Common/UUID.hpp +++ /dev/null @@ -1,983 +0,0 @@ -#ifndef STDUUID_H -#define STDUUID_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus - -#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) -#define LIBUUID_CPP20_OR_GREATER -#endif - -#endif - -#ifdef LIBUUID_CPP20_OR_GREATER -#include -#else -#include -#endif - -#ifdef _WIN32 - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#ifdef UUID_SYSTEM_GENERATOR -#include -#endif - -#ifdef UUID_TIME_GENERATOR -#include -#pragma comment(lib, "IPHLPAPI.lib") -#endif - -#elif defined(__linux__) || defined(__unix__) - -#ifdef UUID_SYSTEM_GENERATOR -#include -#endif - -#elif defined(__APPLE__) - -#ifdef UUID_SYSTEM_GENERATOR -#include -#endif - -#endif - -namespace uuids -{ -#ifdef __cpp_lib_span - template - using span = std::span; -#else - template - using span = gsl::span; -#endif - - namespace detail - { - template - [[nodiscard]] constexpr inline unsigned char hex2char(TChar const ch) noexcept - { - if (ch >= static_cast('0') && ch <= static_cast('9')) - return static_cast(ch - static_cast('0')); - if (ch >= static_cast('a') && ch <= static_cast('f')) - return static_cast(10 + ch - static_cast('a')); - if (ch >= static_cast('A') && ch <= static_cast('F')) - return static_cast(10 + ch - static_cast('A')); - return 0; - } - - template - [[nodiscard]] constexpr inline bool is_hex(TChar const ch) noexcept - { - return (ch >= static_cast('0') && ch <= static_cast('9')) || - (ch >= static_cast('a') && ch <= static_cast('f')) || - (ch >= static_cast('A') && ch <= static_cast('F')); - } - - template - [[nodiscard]] constexpr std::basic_string_view to_string_view( - TChar const* str) noexcept - { - if (str) - return str; - return {}; - } - - template - [[nodiscard]] constexpr std::basic_string_view - to_string_view(StringType const& str) noexcept - { - return str; - } - - class sha1 - { - public: - using digest32_t = uint32_t[5]; - using digest8_t = uint8_t[20]; - - static constexpr unsigned int block_bytes = 64; - - [[nodiscard]] inline static uint32_t left_rotate( - uint32_t value, size_t const count) noexcept - { - return (value << count) ^ (value >> (32 - count)); - } - - sha1() - { - reset(); - } - - void reset() noexcept - { - m_digest[0] = 0x67452301; - m_digest[1] = 0xEFCDAB89; - m_digest[2] = 0x98BADCFE; - m_digest[3] = 0x10325476; - m_digest[4] = 0xC3D2E1F0; - m_blockByteIndex = 0; - m_byteCount = 0; - } - - void process_byte(uint8_t octet) - { - this->m_block[this->m_blockByteIndex++] = octet; - ++this->m_byteCount; - if (m_blockByteIndex == block_bytes) - { - this->m_blockByteIndex = 0; - process_block(); - } - } - - void process_block(void const* const start, void const* const end) - { - const uint8_t* begin = static_cast(start); - const uint8_t* finish = static_cast(end); - while (begin != finish) - { - process_byte(*begin); - begin++; - } - } - - void process_bytes(void const* const data, size_t const len) - { - const uint8_t* block = static_cast(data); - process_block(block, block + len); - } - - uint32_t const* get_digest(digest32_t digest) - { - size_t const bitCount = this->m_byteCount * 8; - process_byte(0x80); - if (this->m_blockByteIndex > 56) - { - while (m_blockByteIndex != 0) - { - process_byte(0); - } - while (m_blockByteIndex < 56) - { - process_byte(0); - } - } - else - { - while (m_blockByteIndex < 56) - { - process_byte(0); - } - } - process_byte(0); - process_byte(0); - process_byte(0); - process_byte(0); - process_byte(static_cast((bitCount >> 24) & 0xFF)); - process_byte(static_cast((bitCount >> 16) & 0xFF)); - process_byte(static_cast((bitCount >> 8) & 0xFF)); - process_byte(static_cast((bitCount)&0xFF)); - - memcpy(digest, m_digest, 5 * sizeof(uint32_t)); - return digest; - } - - uint8_t const* get_digest_bytes(digest8_t digest) - { - digest32_t d32; - get_digest(d32); - size_t di = 0; - digest[di++] = static_cast(d32[0] >> 24); - digest[di++] = static_cast(d32[0] >> 16); - digest[di++] = static_cast(d32[0] >> 8); - digest[di++] = static_cast(d32[0] >> 0); - - digest[di++] = static_cast(d32[1] >> 24); - digest[di++] = static_cast(d32[1] >> 16); - digest[di++] = static_cast(d32[1] >> 8); - digest[di++] = static_cast(d32[1] >> 0); - - digest[di++] = static_cast(d32[2] >> 24); - digest[di++] = static_cast(d32[2] >> 16); - digest[di++] = static_cast(d32[2] >> 8); - digest[di++] = static_cast(d32[2] >> 0); - - digest[di++] = static_cast(d32[3] >> 24); - digest[di++] = static_cast(d32[3] >> 16); - digest[di++] = static_cast(d32[3] >> 8); - digest[di++] = static_cast(d32[3] >> 0); - - digest[di++] = static_cast(d32[4] >> 24); - digest[di++] = static_cast(d32[4] >> 16); - digest[di++] = static_cast(d32[4] >> 8); - digest[di++] = static_cast(d32[4] >> 0); - - return digest; - } - - private: - void process_block() - { - uint32_t w[80]; - for (size_t i = 0; i < 16; i++) - { - w[i] = static_cast(m_block[i * 4 + 0] << 24); - w[i] |= static_cast(m_block[i * 4 + 1] << 16); - w[i] |= static_cast(m_block[i * 4 + 2] << 8); - w[i] |= static_cast(m_block[i * 4 + 3]); - } - for (size_t i = 16; i < 80; i++) - { - w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1); - } - - uint32_t a = m_digest[0]; - uint32_t b = m_digest[1]; - uint32_t c = m_digest[2]; - uint32_t d = m_digest[3]; - uint32_t e = m_digest[4]; - - for (std::size_t i = 0; i < 80; ++i) - { - uint32_t f = 0; - uint32_t k = 0; - - if (i < 20) - { - f = (b & c) | (~b & d); - k = 0x5A827999; - } - else if (i < 40) - { - f = b ^ c ^ d; - k = 0x6ED9EBA1; - } - else if (i < 60) - { - f = (b & c) | (b & d) | (c & d); - k = 0x8F1BBCDC; - } - else - { - f = b ^ c ^ d; - k = 0xCA62C1D6; - } - uint32_t temp = left_rotate(a, 5) + f + e + k + w[i]; - e = d; - d = c; - c = left_rotate(b, 30); - b = a; - a = temp; - } - - m_digest[0] += a; - m_digest[1] += b; - m_digest[2] += c; - m_digest[3] += d; - m_digest[4] += e; - } - - private: - digest32_t m_digest; - uint8_t m_block[64]; - size_t m_blockByteIndex; - size_t m_byteCount; - }; - - template - inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000"; - - template <> - inline constexpr wchar_t empty_guid[37] = - L"00000000-0000-0000-0000-000000000000"; - - template - inline constexpr CharT guid_encoder[17] = "0123456789abcdef"; - - template <> - inline constexpr wchar_t guid_encoder[17] = L"0123456789abcdef"; - } // namespace detail - - // -------------------------------------------------------------------------------------------------------------------------- - // UUID format https://tools.ietf.org/html/rfc4122 - // -------------------------------------------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------------------------------------------- - // Field NDR Data Type Octet # Note - // -------------------------------------------------------------------------------------------------------------------------- - // time_low unsigned long 0 - 3 The low field - // of the timestamp. time_mid unsigned short 4 - 5 - // The middle field of the timestamp. time_hi_and_version unsigned - // short 6 - 7 The high field of the timestamp multiplexed - // with the version number. clock_seq_hi_and_reserved unsigned small 8 - // The high field of the clock sequence multiplexed with the variant. - // clock_seq_low unsigned small 9 The low - // field of the clock sequence. node character 10 - // - 15 The spatially unique node identifier. - // -------------------------------------------------------------------------------------------------------------------------- - // 0 1 2 3 - // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | time_low | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | time_mid | time_hi_and_version | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // |clk_seq_hi_res | clk_seq_low | node (0-1) | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | node (2-5) | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - // -------------------------------------------------------------------------------------------------------------------------- - // enumerations - // -------------------------------------------------------------------------------------------------------------------------- - - // indicated by a bit pattern in octet 8, marked with N in - // xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx - enum class uuid_variant - { - // NCS backward compatibility (with the obsolete Apollo Network Computing - // System 1.5 UUID format) N bit pattern: 0xxx > the first 6 octets of the - // UUID are a 48-bit timestamp (the number of 4 microsecond units of time - // since 1 Jan 1980 UTC); > the next 2 octets are reserved; > the next octet - // is the "address family"; > the final 7 octets are a 56-bit host ID in the - // form specified by the address family - ncs, - - // RFC 4122/DCE 1.1 - // N bit pattern: 10xx - // > big-endian byte order - rfc, - - // Microsoft Corporation backward compatibility - // N bit pattern: 110x - // > little endian byte order - // > formely used in the Component Object Model (COM) library - microsoft, - - // reserved for possible future definition - // N bit pattern: 111x - reserved - }; - - // indicated by a bit pattern in octet 6, marked with M in - // xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx - enum class uuid_version - { - none = 0, // only possible for nil or invalid uuids - time_based = 1, // The time-based version specified in RFC 4122 - dce_security = 2, // DCE Security version, with embedded POSIX UIDs. - name_based_md5 = - 3, // The name-based version specified in RFS 4122 with MD5 hashing - random_number_based = 4, // The randomly or pseudo-randomly generated version - // specified in RFS 4122 - name_based_sha1 = - 5 // The name-based version specified in RFS 4122 with SHA1 hashing - }; - - // Forward declare uuid & to_string so that we can declare to_string as a friend - // later. - class uuid; - template , class Allocator = std::allocator> - std::basic_string to_string(uuid const& id); - - // -------------------------------------------------------------------------------------------------------------------------- - // uuid class - // -------------------------------------------------------------------------------------------------------------------------- - class uuid - { - public: - using value_type = uint8_t; - - constexpr uuid() noexcept = default; - - uuid(value_type (&arr)[16]) noexcept - { - std::copy(std::cbegin(arr), std::cend(arr), std::begin(data)); - } - - constexpr uuid(std::array const& arr) noexcept - : data{arr} - { - } - - explicit uuid(span bytes) - { - std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data)); - } - - template - explicit uuid(ForwardIterator first, ForwardIterator last) - { - if (std::distance(first, last) == 16) - std::copy(first, last, std::begin(data)); - } - - [[nodiscard]] constexpr uuid_variant variant() const noexcept - { - if ((data[8] & 0x80) == 0x00) - return uuid_variant::ncs; - else if ((data[8] & 0xC0) == 0x80) - return uuid_variant::rfc; - else if ((data[8] & 0xE0) == 0xC0) - return uuid_variant::microsoft; - else - return uuid_variant::reserved; - } - - [[nodiscard]] constexpr uuid_version version() const noexcept - { - if ((data[6] & 0xF0) == 0x10) - return uuid_version::time_based; - else if ((data[6] & 0xF0) == 0x20) - return uuid_version::dce_security; - else if ((data[6] & 0xF0) == 0x30) - return uuid_version::name_based_md5; - else if ((data[6] & 0xF0) == 0x40) - return uuid_version::random_number_based; - else if ((data[6] & 0xF0) == 0x50) - return uuid_version::name_based_sha1; - else - return uuid_version::none; - } - - [[nodiscard]] constexpr bool is_nil() const noexcept - { - for (size_t i = 0; i < data.size(); ++i) - if (data[i] != 0) - return false; - return true; - } - - void swap(uuid& other) noexcept - { - data.swap(other.data); - } - - [[nodiscard]] inline span as_bytes() const - { - return span( - reinterpret_cast(data.data()), 16); - } - - template - [[nodiscard]] constexpr static bool is_valid_uuid( - StringType const& in_str) noexcept - { - auto str = detail::to_string_view(in_str); - bool firstDigit = true; - size_t hasBraces = 0; - size_t index = 0; - - if (str.empty()) - return false; - - if (str.front() == '{') - hasBraces = 1; - if (hasBraces && str.back() != '}') - return false; - - for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) - { - if (str[i] == '-') - continue; - - if (index >= 16 || !detail::is_hex(str[i])) - { - return false; - } - - if (firstDigit) - { - firstDigit = false; - } - else - { - index++; - firstDigit = true; - } - } - - if (index < 16) - { - return false; - } - - return true; - } - - template - [[nodiscard]] constexpr static std::optional from_string( - StringType const& in_str) noexcept - { - auto str = detail::to_string_view(in_str); - bool firstDigit = true; - size_t hasBraces = 0; - size_t index = 0; - - std::array data{{0}}; - - if (str.empty()) - return {}; - - if (str.front() == '{') - hasBraces = 1; - if (hasBraces && str.back() != '}') - return {}; - - for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) - { - if (str[i] == '-') - continue; - - if (index >= 16 || !detail::is_hex(str[i])) - { - return {}; - } - - if (firstDigit) - { - data[index] = static_cast(detail::hex2char(str[i]) << 4); - firstDigit = false; - } - else - { - data[index] = - static_cast(data[index] | detail::hex2char(str[i])); - index++; - firstDigit = true; - } - } - - if (index < 16) - { - return {}; - } - - return uuid{data}; - } - - private: - std::array data{{0}}; - - friend bool operator==(uuid const& lhs, uuid const& rhs) noexcept; - friend bool operator<(uuid const& lhs, uuid const& rhs) noexcept; - - template - friend std::basic_ostream& operator<<( - std::basic_ostream& s, uuid const& id); - - template - friend std::basic_string to_string(uuid const& id); - - friend std::hash; - }; - - // -------------------------------------------------------------------------------------------------------------------------- - // operators and non-member functions - // -------------------------------------------------------------------------------------------------------------------------- - - [[nodiscard]] inline bool operator==(uuid const& lhs, - uuid const& rhs) noexcept - { - return lhs.data == rhs.data; - } - - [[nodiscard]] inline bool operator!=(uuid const& lhs, - uuid const& rhs) noexcept - { - return !(lhs == rhs); - } - - [[nodiscard]] inline bool operator<(uuid const& lhs, uuid const& rhs) noexcept - { - return lhs.data < rhs.data; - } - - template - [[nodiscard]] inline std::basic_string to_string( - uuid const& id) - { - std::basic_string uustr{detail::empty_guid}; - - for (size_t i = 0, index = 0; i < 36; ++i) - { - if (i == 8 || i == 13 || i == 18 || i == 23) - { - continue; - } - uustr[i] = detail::guid_encoder[id.data[index] >> 4 & 0x0f]; - uustr[++i] = detail::guid_encoder[id.data[index] & 0x0f]; - index++; - } - - return uustr; - } - - template - std::basic_ostream& operator<<( - std::basic_ostream& s, uuid const& id) - { - s << to_string(id); - return s; - } - - inline void swap(uuids::uuid& lhs, uuids::uuid& rhs) noexcept - { - lhs.swap(rhs); - } - - // -------------------------------------------------------------------------------------------------------------------------- - // namespace IDs that could be used for generating name-based uuids - // -------------------------------------------------------------------------------------------------------------------------- - - // Name string is a fully-qualified domain name - static uuid uuid_namespace_dns{{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // Name string is a URL - static uuid uuid_namespace_url{{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // Name string is an ISO OID (See https://oidref.com/, - // https://en.wikipedia.org/wiki/Object_identifier) - static uuid uuid_namespace_oid{{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // Name string is an X.500 DN, in DER or a text output format (See - // https://en.wikipedia.org/wiki/X.500, - // https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One) - static uuid uuid_namespace_x500{{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // -------------------------------------------------------------------------------------------------------------------------- - // uuid generators - // -------------------------------------------------------------------------------------------------------------------------- - -#ifdef UUID_SYSTEM_GENERATOR - class uuid_system_generator - { - public: - using result_type = uuid; - - uuid operator()() - { -#ifdef _WIN32 - - GUID newId; - HRESULT hr = ::CoCreateGuid(&newId); - - if (FAILED(hr)) - { - throw std::system_error(hr, std::system_category(), - "CoCreateGuid failed"); - } - - std::array bytes = { - {static_cast((newId.Data1 >> 24) & 0xFF), - static_cast((newId.Data1 >> 16) & 0xFF), - static_cast((newId.Data1 >> 8) & 0xFF), - static_cast((newId.Data1) & 0xFF), - - (unsigned char)((newId.Data2 >> 8) & 0xFF), - (unsigned char)((newId.Data2) & 0xFF), - - (unsigned char)((newId.Data3 >> 8) & 0xFF), - (unsigned char)((newId.Data3) & 0xFF), - - newId.Data4[0], newId.Data4[1], newId.Data4[2], newId.Data4[3], - newId.Data4[4], newId.Data4[5], newId.Data4[6], newId.Data4[7]}}; - - return uuid{std::begin(bytes), std::end(bytes)}; - -#elif defined(__linux__) || defined(__unix__) - - uuid_t id; - uuid_generate(id); - - std::array bytes = {{id[0], id[1], id[2], id[3], id[4], id[5], - id[6], id[7], id[8], id[9], id[10], - id[11], id[12], id[13], id[14], id[15]}}; - - return uuid{std::begin(bytes), std::end(bytes)}; - -#elif defined(__APPLE__) - auto newId = CFUUIDCreate(NULL); - auto bytes = CFUUIDGetUUIDBytes(newId); - CFRelease(newId); - - std::array arrbytes = { - {bytes.byte0, bytes.byte1, bytes.byte2, bytes.byte3, bytes.byte4, - bytes.byte5, bytes.byte6, bytes.byte7, bytes.byte8, bytes.byte9, - bytes.byte10, bytes.byte11, bytes.byte12, bytes.byte13, bytes.byte14, - bytes.byte15}}; - return uuid{std::begin(arrbytes), std::end(arrbytes)}; -#else - return uuid{}; -#endif - } - }; -#endif - - template - class basic_uuid_random_generator - { - public: - using engine_type = UniformRandomNumberGenerator; - - explicit basic_uuid_random_generator(engine_type& gen) - : generator(&gen, [](auto) {}) - { - } - explicit basic_uuid_random_generator(engine_type* gen) - : generator(gen, [](auto) {}) - { - } - - [[nodiscard]] uuid operator()() - { - alignas(uint32_t) uint8_t bytes[16]; - for (int i = 0; i < 16; i += 4) - *reinterpret_cast(bytes + i) = distribution(*generator); - - // variant must be 10xxxxxx - bytes[8] &= 0xBF; - bytes[8] |= 0x80; - - // version must be 0100xxxx - bytes[6] &= 0x4F; - bytes[6] |= 0x40; - - return uuid{std::begin(bytes), std::end(bytes)}; - } - - private: - std::uniform_int_distribution distribution; - std::shared_ptr generator; - }; - - using uuid_random_generator = basic_uuid_random_generator; - - class uuid_name_generator - { - public: - explicit uuid_name_generator(uuid const& namespace_uuid) noexcept - : nsuuid(namespace_uuid) - { - } - - template - [[nodiscard]] uuid operator()(StringType const& name) - { - reset(); - process_characters(detail::to_string_view(name)); - return make_uuid(); - } - - private: - void reset() - { - hasher.reset(); - std::byte bytes[16]; - auto nsbytes = nsuuid.as_bytes(); - std::copy(std::cbegin(nsbytes), std::cend(nsbytes), bytes); - hasher.process_bytes(bytes, 16); - } - - template - void process_characters(std::basic_string_view const str) - { - for (uint32_t c : str) - { - hasher.process_byte(static_cast(c & 0xFF)); - if constexpr (!std::is_same_v) - { - hasher.process_byte(static_cast((c >> 8) & 0xFF)); - hasher.process_byte(static_cast((c >> 16) & 0xFF)); - hasher.process_byte(static_cast((c >> 24) & 0xFF)); - } - } - } - - [[nodiscard]] uuid make_uuid() - { - detail::sha1::digest8_t digest; - hasher.get_digest_bytes(digest); - - // variant must be 0b10xxxxxx - digest[8] &= 0xBF; - digest[8] |= 0x80; - - // version must be 0b0101xxxx - digest[6] &= 0x5F; - digest[6] |= 0x50; - - return uuid{digest, digest + 16}; - } - - private: - uuid nsuuid; - detail::sha1 hasher; - }; - -#ifdef UUID_TIME_GENERATOR - // !!! DO NOT USE THIS IN PRODUCTION - // this implementation is unreliable for good uuids - class uuid_time_generator - { - using mac_address = std::array; - - std::optional device_address; - - [[nodiscard]] bool get_mac_address() - { - if (device_address.has_value()) - { - return true; - } - -#ifdef _WIN32 - DWORD len = 0; - auto ret = GetAdaptersInfo(nullptr, &len); - if (ret != ERROR_BUFFER_OVERFLOW) - return false; - std::vector buf(len); - auto pips = reinterpret_cast(&buf.front()); - ret = GetAdaptersInfo(pips, &len); - if (ret != ERROR_SUCCESS) - return false; - mac_address addr; - std::copy(pips->Address, pips->Address + 6, std::begin(addr)); - device_address = addr; -#endif - - return device_address.has_value(); - } - - [[nodiscard]] long long get_time_intervals() - { - auto start = std::chrono::system_clock::from_time_t(time_t(-12219292800)); - auto diff = std::chrono::system_clock::now() - start; - auto ns = - std::chrono::duration_cast(diff).count(); - return ns / 100; - } - - [[nodiscard]] static unsigned short get_clock_sequence() - { - static std::mt19937 clock_gen(std::random_device{}()); - static std::uniform_int_distribution clock_dis; - static std::atomic_ushort clock_sequence = clock_dis(clock_gen); - return clock_sequence++; - } - - public: - [[nodiscard]] uuid operator()() - { - if (get_mac_address()) - { - std::array data; - - auto tm = get_time_intervals(); - - auto clock_seq = get_clock_sequence(); - - auto ptm = reinterpret_cast(&tm); - - memcpy(&data[0], ptm + 4, 4); - memcpy(&data[4], ptm + 2, 2); - memcpy(&data[6], ptm, 2); - - memcpy(&data[8], &clock_seq, 2); - - // variant must be 0b10xxxxxx - data[8] &= 0xBF; - data[8] |= 0x80; - - // version must be 0b0001xxxx - data[6] &= 0x1F; - data[6] |= 0x10; - - memcpy(&data[10], &device_address.value()[0], 6); - - return uuids::uuid{std::cbegin(data), std::cend(data)}; - } - - return {}; - } - }; -#endif -} // namespace uuids - -namespace std -{ - template <> - struct hash - { - using argument_type = uuids::uuid; - using result_type = std::size_t; - - [[nodiscard]] result_type operator()(argument_type const& uuid) const - { -#ifdef UUID_HASH_STRING_BASED - std::hash hasher; - return static_cast(hasher(uuids::to_string(uuid))); -#else - uint64_t l = static_cast(uuid.data[0]) << 56 | - static_cast(uuid.data[1]) << 48 | - static_cast(uuid.data[2]) << 40 | - static_cast(uuid.data[3]) << 32 | - static_cast(uuid.data[4]) << 24 | - static_cast(uuid.data[5]) << 16 | - static_cast(uuid.data[6]) << 8 | - static_cast(uuid.data[7]); - uint64_t h = static_cast(uuid.data[8]) << 56 | - static_cast(uuid.data[9]) << 48 | - static_cast(uuid.data[10]) << 40 | - static_cast(uuid.data[11]) << 32 | - static_cast(uuid.data[12]) << 24 | - static_cast(uuid.data[13]) << 16 | - static_cast(uuid.data[14]) << 8 | - static_cast(uuid.data[15]); - - if constexpr (sizeof(result_type) > 4) - { - return result_type(l ^ h); - } - else - { - uint64_t hash64 = l ^ h; - return result_type(uint32_t(hash64 >> 32) ^ uint32_t(hash64)); - } -#endif - } - }; -} // namespace std - -#endif /* STDUUID_H */ \ No newline at end of file diff --git a/Common/Version.hxx b/Common/Version.hxx deleted file mode 100644 index 377a688..0000000 --- a/Common/Version.hxx +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#define kDistVersion "v1.20" diff --git a/Doc/Inside 64x0.pdf b/Doc/Inside 64x0.pdf new file mode 100644 index 0000000..bcd6782 Binary files /dev/null and b/Doc/Inside 64x0.pdf differ diff --git a/Doc/asm-specs.txt b/Doc/asm-specs.txt new file mode 100644 index 0000000..a0c42bf --- /dev/null +++ b/Doc/asm-specs.txt @@ -0,0 +1,11 @@ +==================== +X86 ASSEMBLER SPECS +==================== + +WHAT TO DO: + Provide a complete support of x86-64 with: + + - org directive. + - 64-bit and 32-bit registers. + - basic instructions (load, store, jump to) + - flushable into object-code and flat binary. \ No newline at end of file diff --git a/Doc/havp.txt b/Doc/havp.txt new file mode 100644 index 0000000..12fcec5 --- /dev/null +++ b/Doc/havp.txt @@ -0,0 +1,13 @@ +HAVP - Harvard Audio/Video Processor + +- Encoding: IBAD + +- Data path = 24 + - 16: sound data + - 8: information data + +- Register size: 32 +- Store strategy: shift registers. +- Standard registers: [ r0, r9 ] +- Floating point registers: [ f0, f2 ] +- Builtin SRAM: 512kb diff --git a/Doc/notice.txt b/Doc/notice.txt new file mode 100644 index 0000000..23691da --- /dev/null +++ b/Doc/notice.txt @@ -0,0 +1,4 @@ +The X64000 draft papers +They contain thing that might appear through the next iteration of 64k. + +Please look at the document shared for the latest revisions. \ No newline at end of file diff --git a/Doc/vnrp.txt b/Doc/vnrp.txt new file mode 100644 index 0000000..e17b494 --- /dev/null +++ b/Doc/vnrp.txt @@ -0,0 +1,17 @@ +VNRP - Von Neumann, RISC Processor + +- Encoding = RegToReg, Imm, Syscall, Jump, NoArgs + +- Data path = 128-bit (register data) +- Addressing = 58-bit physical address size. + +- Registers (128-bit) = r0, r19 +- Float/Vector registers (128-bit) = f0, f9 + +- Out of order (superscalar also added to the equation) = Yes +- Superscalar = Yes + +- L1 cache: 16kb (8 instr, 8 data) +- L2 cache: 1024kb (512 instr, 512 data) + +- Clock speed: 1 Ghz diff --git a/Sources/32asm.cc b/Sources/32asm.cc index 82d23e6..a3e2cbb 100644 --- a/Sources/32asm.cc +++ b/Sources/32asm.cc @@ -19,10 +19,10 @@ #define __ASM_NEED_32x0__ 1 -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include diff --git a/Sources/64asm.cc b/Sources/64asm.cc index 6287b3e..baa6ef4 100644 --- a/Sources/64asm.cc +++ b/Sources/64asm.cc @@ -19,10 +19,10 @@ #define __ASM_NEED_64x0__ 1 -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include diff --git a/Sources/64x0-cc.cc b/Sources/64x0-cc.cc index 36f56a8..75a9b10 100644 --- a/Sources/64x0-cc.cc +++ b/Sources/64x0-cc.cc @@ -10,9 +10,9 @@ /// BUGS: ? /// TODO: -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/Sources/AssemblyFactory.cc b/Sources/AssemblyFactory.cc index 1952f54..61399a4 100644 --- a/Sources/AssemblyFactory.cc +++ b/Sources/AssemblyFactory.cc @@ -4,8 +4,8 @@ ------------------------------------------- */ -#include -#include +#include +#include /** * @file AssemblyFactory.cxx diff --git a/Sources/Detail/asmutils.hxx b/Sources/Detail/asmutils.hxx index f6fdb41..240835e 100644 --- a/Sources/Detail/asmutils.hxx +++ b/Sources/Detail/asmutils.hxx @@ -6,8 +6,8 @@ #pragma once -#include -#include +#include +#include using namespace CompilerKit; diff --git a/Sources/Detail/compilerutils.hxx b/Sources/Detail/compilerutils.hxx index 9ddd3a2..acadde2 100644 --- a/Sources/Detail/compilerutils.hxx +++ b/Sources/Detail/compilerutils.hxx @@ -6,8 +6,8 @@ #pragma once -#include -#include +#include +#include #define kZero64Section ".zero64" #define kCode64Section ".code64" diff --git a/Sources/String.cc b/Sources/String.cc index 38bd444..ece3ecf 100644 --- a/Sources/String.cc +++ b/Sources/String.cc @@ -18,7 +18,7 @@ * */ -#include +#include #include namespace CompilerKit { diff --git a/Sources/bpp.cc b/Sources/bpp.cc index aa0b72a..f523597 100644 --- a/Sources/bpp.cc +++ b/Sources/bpp.cc @@ -9,8 +9,8 @@ /// BUGS: 0 -#include -#include +#include +#include #include #include #include diff --git a/Sources/coff2ae.cc b/Sources/coff2ae.cc index 349d543..2986375 100644 --- a/Sources/coff2ae.cc +++ b/Sources/coff2ae.cc @@ -4,9 +4,9 @@ ------------------------------------------- */ -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/Sources/cplusplus.cc b/Sources/cplusplus.cc index 97b6a82..9323d31 100644 --- a/Sources/cplusplus.cc +++ b/Sources/cplusplus.cc @@ -16,8 +16,8 @@ #define kSplashCxx() \ kPrintF(kWhite "%s\n", "SoftwareLabs C++ Compiler, Copyright SoftwareLabs.") -#include -#include +#include +#include #include #include #include diff --git a/Sources/elf2ae.cc b/Sources/elf2ae.cc index a451a0a..ada2830 100644 --- a/Sources/elf2ae.cc +++ b/Sources/elf2ae.cc @@ -4,9 +4,9 @@ ------------------------------------------- */ -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/Sources/i64asm.cc b/Sources/i64asm.cc index 391c63f..26269f4 100644 --- a/Sources/i64asm.cc +++ b/Sources/i64asm.cc @@ -27,10 +27,10 @@ #define kAssemblerPragmaSymStr "#" #define kAssemblerPragmaSym '#' -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include diff --git a/Sources/link.cc b/Sources/link.cc index e0a49cf..6ed2db5 100644 --- a/Sources/link.cc +++ b/Sources/link.cc @@ -13,23 +13,23 @@ /// note: Do not look up for anything with .code64/.data64/.zero64! /// It will be loaded when program will start up! -#include +#include //! Assembler Kit -#include +#include //! Preferred Executable Format -#include -#include +#include +#include #include #include #include //! Dist version -#include +#include //! Advanced Executable Object Format -#include +#include //! C++ I/O headers. #include diff --git a/Sources/power-cc.cc b/Sources/power-cc.cc index ad99611..d008296 100644 --- a/Sources/power-cc.cc +++ b/Sources/power-cc.cc @@ -7,9 +7,9 @@ * ======================================================== */ -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/Sources/ppcasm.cc b/Sources/ppcasm.cc index 89de014..1edeaaa 100644 --- a/Sources/ppcasm.cc +++ b/Sources/ppcasm.cc @@ -17,12 +17,12 @@ #define __ASM_NEED_PPC__ 1 -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/docs/Inside 64x0.pdf b/docs/Inside 64x0.pdf deleted file mode 100644 index bcd6782..0000000 Binary files a/docs/Inside 64x0.pdf and /dev/null differ diff --git a/docs/asm-specs.txt b/docs/asm-specs.txt deleted file mode 100644 index a0c42bf..0000000 --- a/docs/asm-specs.txt +++ /dev/null @@ -1,11 +0,0 @@ -==================== -X86 ASSEMBLER SPECS -==================== - -WHAT TO DO: - Provide a complete support of x86-64 with: - - - org directive. - - 64-bit and 32-bit registers. - - basic instructions (load, store, jump to) - - flushable into object-code and flat binary. \ No newline at end of file diff --git a/docs/havp.txt b/docs/havp.txt deleted file mode 100644 index 12fcec5..0000000 --- a/docs/havp.txt +++ /dev/null @@ -1,13 +0,0 @@ -HAVP - Harvard Audio/Video Processor - -- Encoding: IBAD - -- Data path = 24 - - 16: sound data - - 8: information data - -- Register size: 32 -- Store strategy: shift registers. -- Standard registers: [ r0, r9 ] -- Floating point registers: [ f0, f2 ] -- Builtin SRAM: 512kb diff --git a/docs/notice.txt b/docs/notice.txt deleted file mode 100644 index 23691da..0000000 --- a/docs/notice.txt +++ /dev/null @@ -1,4 +0,0 @@ -The X64000 draft papers -They contain thing that might appear through the next iteration of 64k. - -Please look at the document shared for the latest revisions. \ No newline at end of file diff --git a/docs/vnrp.txt b/docs/vnrp.txt deleted file mode 100644 index e17b494..0000000 --- a/docs/vnrp.txt +++ /dev/null @@ -1,17 +0,0 @@ -VNRP - Von Neumann, RISC Processor - -- Encoding = RegToReg, Imm, Syscall, Jump, NoArgs - -- Data path = 128-bit (register data) -- Addressing = 58-bit physical address size. - -- Registers (128-bit) = r0, r19 -- Float/Vector registers (128-bit) = f0, f9 - -- Out of order (superscalar also added to the equation) = Yes -- Superscalar = Yes - -- L1 cache: 16kb (8 instr, 8 data) -- L2 cache: 1024kb (512 instr, 512 data) - -- Clock speed: 1 Ghz diff --git a/posix.make b/posix.make index 119457d..be1abb8 100644 --- a/posix.make +++ b/posix.make @@ -7,7 +7,7 @@ # ======================================================== # -COMMON_INC=-I./Common -I./ -I./Sources/Detail +COMMON_INC=-I./Comm -I./ -I./Sources/Detail LINK_CC=clang++ -std=c++20 LINK_SRC=Sources/link.cc LINK_OUTPUT=Output/link.exec diff --git a/win64.make b/win64.make index 0315371..a345da0 100644 --- a/win64.make +++ b/win64.make @@ -7,7 +7,7 @@ # ======================================================== # -COMMON_INC=-I./Common -I./ -I./Sources/Detail +COMMON_INC=-I./Comm -I./ -I./Sources/Detail LINK_CC=clang++ -std=c++20 -Xlinker -s LINK_SRC=Sources/link.cc LINK_OUTPUT=Output/link.exe -- cgit v1.2.3 From 9c02ac7a15d18da351baa81b25ebd8c967b4e5ee Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Tue, 11 Jun 2024 09:56:25 +0200 Subject: MHR-21: Update copyright holder. Signed-off-by: Amlal El Mahrouss --- Comm/AsmKit/AsmKit.hpp | 2 +- Comm/AsmKit/CPU/32x0.hpp | 2 +- Comm/AsmKit/CPU/64x0.hpp | 2 +- Comm/AsmKit/CPU/amd64.hpp | 2 +- Comm/CompilerKit.hpp | 2 +- Comm/Defines.hpp | 2 +- Comm/ParserKit.hpp | 2 +- Comm/Public/SDK/CRT/__mpcc_alloca.hxx | 2 +- Comm/Public/SDK/CRT/__mpcc_defines.hxx | 2 +- Comm/Public/SDK/CRT/__mpcc_exception.hxx | 2 +- Comm/Public/SDK/CRT/__mpcc_hint.hxx | 2 +- Comm/Public/SDK/CRT/__mpcc_malloc.hxx | 2 +- Comm/StdKit/AE.hpp | 2 +- Comm/StdKit/ErrorID.hpp | 2 +- Comm/StdKit/ErrorOr.hpp | 2 +- Comm/StdKit/PEF.hpp | 2 +- Comm/StdKit/Ref.hpp | 4 ++-- Comm/StdKit/String.hpp | 2 +- Comm/StdKit/XCOFF.hxx | 4 ++-- ReadMe.md | 2 +- Sources/32asm.cc | 4 ++-- Sources/64asm.cc | 6 +++--- Sources/64x0-cc.cc | 8 ++++---- Sources/AssemblyFactory.cc | 6 +++--- Sources/Detail/asmutils.hxx | 2 +- Sources/Detail/compilerutils.hxx | 2 +- Sources/String.cc | 4 ++-- Sources/bpp.cc | 8 ++++---- Sources/coff2ae.cc | 2 +- Sources/cplusplus.cc | 16 ++++++++-------- Sources/elf2ae.cc | 2 +- Sources/i64asm.cc | 10 +++++----- Sources/link.cc | 10 +++++----- Sources/power-cc.cc | 6 +++--- Sources/ppcasm.cc | 8 ++++---- posix.make | 10 +++++----- win64.make | 4 ++-- 37 files changed, 76 insertions(+), 76 deletions(-) (limited to 'Sources/String.cc') diff --git a/Comm/AsmKit/AsmKit.hpp b/Comm/AsmKit/AsmKit.hpp index 1801130..6fbacfa 100644 --- a/Comm/AsmKit/AsmKit.hpp +++ b/Comm/AsmKit/AsmKit.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Comm/AsmKit/CPU/32x0.hpp b/Comm/AsmKit/CPU/32x0.hpp index 0013752..e469dda 100644 --- a/Comm/AsmKit/CPU/32x0.hpp +++ b/Comm/AsmKit/CPU/32x0.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Comm/AsmKit/CPU/64x0.hpp b/Comm/AsmKit/CPU/64x0.hpp index e2e03c8..10d12d8 100644 --- a/Comm/AsmKit/CPU/64x0.hpp +++ b/Comm/AsmKit/CPU/64x0.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Comm/AsmKit/CPU/amd64.hpp b/Comm/AsmKit/CPU/amd64.hpp index d461574..63ed1b3 100644 --- a/Comm/AsmKit/CPU/amd64.hpp +++ b/Comm/AsmKit/CPU/amd64.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Comm/CompilerKit.hpp b/Comm/CompilerKit.hpp index b9de089..25a1e66 100644 --- a/Comm/CompilerKit.hpp +++ b/Comm/CompilerKit.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Comm/Defines.hpp b/Comm/Defines.hpp index d76620c..8c47bd0 100644 --- a/Comm/Defines.hpp +++ b/Comm/Defines.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Comm/ParserKit.hpp b/Comm/ParserKit.hpp index 9109d32..8b66995 100644 --- a/Comm/ParserKit.hpp +++ b/Comm/ParserKit.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Comm/Public/SDK/CRT/__mpcc_alloca.hxx b/Comm/Public/SDK/CRT/__mpcc_alloca.hxx index a1c638e..19ebaaf 100644 --- a/Comm/Public/SDK/CRT/__mpcc_alloca.hxx +++ b/Comm/Public/SDK/CRT/__mpcc_alloca.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Comm/Public/SDK/CRT/__mpcc_defines.hxx b/Comm/Public/SDK/CRT/__mpcc_defines.hxx index 5560410..c05ee73 100644 --- a/Comm/Public/SDK/CRT/__mpcc_defines.hxx +++ b/Comm/Public/SDK/CRT/__mpcc_defines.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Comm/Public/SDK/CRT/__mpcc_exception.hxx b/Comm/Public/SDK/CRT/__mpcc_exception.hxx index 9366102..a2539eb 100644 --- a/Comm/Public/SDK/CRT/__mpcc_exception.hxx +++ b/Comm/Public/SDK/CRT/__mpcc_exception.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Comm/Public/SDK/CRT/__mpcc_hint.hxx b/Comm/Public/SDK/CRT/__mpcc_hint.hxx index ee14711..db58203 100644 --- a/Comm/Public/SDK/CRT/__mpcc_hint.hxx +++ b/Comm/Public/SDK/CRT/__mpcc_hint.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Comm/Public/SDK/CRT/__mpcc_malloc.hxx b/Comm/Public/SDK/CRT/__mpcc_malloc.hxx index 2731868..db3075f 100644 --- a/Comm/Public/SDK/CRT/__mpcc_malloc.hxx +++ b/Comm/Public/SDK/CRT/__mpcc_malloc.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Comm/StdKit/AE.hpp b/Comm/StdKit/AE.hpp index 505ed77..d06a8ca 100644 --- a/Comm/StdKit/AE.hpp +++ b/Comm/StdKit/AE.hpp @@ -2,7 +2,7 @@ * ======================================================== * * MPCC - * Copyright SoftwareLabs, all rights reserved. + * Copyright Zeta Electronics Corporation, all rights reserved. * * ======================================================== */ diff --git a/Comm/StdKit/ErrorID.hpp b/Comm/StdKit/ErrorID.hpp index bea70ae..698b66b 100644 --- a/Comm/StdKit/ErrorID.hpp +++ b/Comm/StdKit/ErrorID.hpp @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright SoftwareLabs, all rights reserved. + * Copyright Zeta Electronics Corporation, all rights reserved. * * ======================================================== */ diff --git a/Comm/StdKit/ErrorOr.hpp b/Comm/StdKit/ErrorOr.hpp index 0125f82..04f013d 100644 --- a/Comm/StdKit/ErrorOr.hpp +++ b/Comm/StdKit/ErrorOr.hpp @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright SoftwareLabs, all rights reserved. + * Copyright Zeta Electronics Corporation, all rights reserved. * * ======================================================== */ diff --git a/Comm/StdKit/PEF.hpp b/Comm/StdKit/PEF.hpp index e790d6a..9198b30 100644 --- a/Comm/StdKit/PEF.hpp +++ b/Comm/StdKit/PEF.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Comm/StdKit/Ref.hpp b/Comm/StdKit/Ref.hpp index f4a11c0..3ccb983 100644 --- a/Comm/StdKit/Ref.hpp +++ b/Comm/StdKit/Ref.hpp @@ -3,7 +3,7 @@ * ======================================================== * * CompilerKit - * Copyright SoftwareLabs, all rights reserved. + * Copyright Zeta Electronics Corporation, all rights reserved. * * ======================================================== */ @@ -12,7 +12,7 @@ namespace CompilerKit { - // @author SoftwareLabs + // @author Zeta Electronics Corporation // @brief Reference class, refers to a pointer of data in static memory. template class Ref final diff --git a/Comm/StdKit/String.hpp b/Comm/StdKit/String.hpp index c6589cc..e495219 100644 --- a/Comm/StdKit/String.hpp +++ b/Comm/StdKit/String.hpp @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright SoftwareLabs, all rights reserved. + * Copyright Zeta Electronics Corporation, all rights reserved. * * ======================================================== */ diff --git a/Comm/StdKit/XCOFF.hxx b/Comm/StdKit/XCOFF.hxx index fee1888..7e57514 100644 --- a/Comm/StdKit/XCOFF.hxx +++ b/Comm/StdKit/XCOFF.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation File: XCOFF.hpp Purpose: XCOFF for NewOS. @@ -38,4 +38,4 @@ namespace CompilerKit } XCoffFileHeader; } // namespace CompilerKit -#endif // ifndef __XCOFF__ \ No newline at end of file +#endif // ifndef __XCOFF__ diff --git a/ReadMe.md b/ReadMe.md index ba91d98..a8650ee 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -13,4 +13,4 @@ make -f .make all ``` -##### Copyright SoftwareLabs, all rights reserved. +##### Copyright Zeta Electronics Corporation, all rights reserved. diff --git a/Sources/32asm.cc b/Sources/32asm.cc index a3e2cbb..0dd6f7c 100644 --- a/Sources/32asm.cc +++ b/Sources/32asm.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ @@ -9,7 +9,7 @@ ///////////////////////////////////////////////////////////////////////////////////////// // @file 32asm.cxx -// @author SoftwareLabs +// @author Zeta Electronics Corporation // @brief 32x0 Assembler. // REMINDER: when dealing with an undefined symbol use (string diff --git a/Sources/64asm.cc b/Sources/64asm.cc index baa6ef4..859bfd4 100644 --- a/Sources/64asm.cc +++ b/Sources/64asm.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ @@ -9,7 +9,7 @@ ///////////////////////////////////////////////////////////////////////////////////////// // @file 64asm.cxx -// @author SoftwareLabs +// @author Zeta Electronics Corporation // @brief 64x0 Assembler. // REMINDER: when dealing with an undefined symbol use (string @@ -110,7 +110,7 @@ MPCC_MODULE(NewOSAssembler64000) { if (argv[i][0] == '-') { if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { kStdOut << "64asm: 64x0 Assembler.\n64asm: v1.10\n64asm: Copyright (c) " - "2024 SoftwareLabs.\n"; + "2024 Zeta Electronics Corporation.\n"; return 0; } else if (strcmp(argv[i], "-h") == 0) { kStdOut << "64asm: 64x0 Assembler.\n64asm: Copyright (c) 2024 Mahrouss " diff --git a/Sources/64x0-cc.cc b/Sources/64x0-cc.cc index 75a9b10..b981cb8 100644 --- a/Sources/64x0-cc.cc +++ b/Sources/64x0-cc.cc @@ -2,7 +2,7 @@ * ======================================================== * * cc - * Copyright SoftwareLabs, all rights reserved. + * Copyright Zeta Electronics Corporation, all rights reserved. * * ======================================================== */ @@ -27,9 +27,9 @@ /* C driver */ /* This is part of MPCC C SDK. */ -/* (c) SoftwareLabs */ +/* (c) Zeta Electronics Corporation */ -/// @author SoftwareLabs (amlel) +/// @author Zeta Electronics Corporation (amlel) /// @file 64x0-cc.cc /// @brief 64x0 C Compiler. @@ -1513,7 +1513,7 @@ public: #define kPrintF printf #define kSplashCxx() \ - kPrintF(kWhite "cc, %s, (c) SoftwareLabs\n", kDistVersion) + kPrintF(kWhite "cc, %s, (c) Zeta Electronics Corporation\n", kDistVersion) static void cc_print_help() { diff --git a/Sources/AssemblyFactory.cc b/Sources/AssemblyFactory.cc index 61399a4..232fcc0 100644 --- a/Sources/AssemblyFactory.cc +++ b/Sources/AssemblyFactory.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ @@ -9,12 +9,12 @@ /** * @file AssemblyFactory.cxx - * @author SoftwareLabs (amlal@mahrouss.com) + * @author Zeta Electronics Corporation (amlal@mahrouss.com) * @brief Assembler Kit * @version 0.1 * @date 2024-01-27 * - * @copyright Copyright (c) 2024, SoftwareLabs + * @copyright Copyright (c) 2024, Zeta Electronics Corporation * */ diff --git a/Sources/Detail/asmutils.hxx b/Sources/Detail/asmutils.hxx index 240835e..c531126 100644 --- a/Sources/Detail/asmutils.hxx +++ b/Sources/Detail/asmutils.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Sources/Detail/compilerutils.hxx b/Sources/Detail/compilerutils.hxx index acadde2..fdcf141 100644 --- a/Sources/Detail/compilerutils.hxx +++ b/Sources/Detail/compilerutils.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Sources/String.cc b/Sources/String.cc index ece3ecf..5a8f3ed 100644 --- a/Sources/String.cc +++ b/Sources/String.cc @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright SoftwareLabs, all rights reserved. + * Copyright Zeta Electronics Corporation, all rights reserved. * * ======================================================== */ @@ -14,7 +14,7 @@ * @version 0.2 * @date 2024-01-23 * - * @copyright Copyright (c) 2024 SoftwareLabs + * @copyright Copyright (c) 2024 Zeta Electronics Corporation * */ diff --git a/Sources/bpp.cc b/Sources/bpp.cc index f523597..9dcd2d3 100644 --- a/Sources/bpp.cc +++ b/Sources/bpp.cc @@ -2,7 +2,7 @@ * ======================================================== * * bpp - * Copyright SoftwareLabs, all rights reserved. + * Copyright Zeta Electronics Corporation, all rights reserved. * * ======================================================== */ @@ -19,7 +19,7 @@ #define kMacroPrefix '%' -// @author SoftwareLabs (amlel) +// @author Zeta Electronics Corporation (amlel) // @file bpp.cc // @brief C preprocessor. @@ -812,12 +812,12 @@ MPCC_MODULE(NewOSPreprocessor) { if (argv[index][0] == '-') { if (strcmp(argv[index], "-v") == 0) { - printf("%s\n", "bpp v1.11, (c) SoftwareLabs"); + printf("%s\n", "bpp v1.11, (c) Zeta Electronics Corporation"); return 0; } if (strcmp(argv[index], "-h") == 0) { - printf("%s\n", "bpp v1.11, (c) SoftwareLabs"); + printf("%s\n", "bpp v1.11, (c) Zeta Electronics Corporation"); printf("%s\n", "-working-dir : set directory to working path."); printf("%s\n", "-include-dir : add directory to include path."); printf("%s\n", "-def : def macro."); diff --git a/Sources/coff2ae.cc b/Sources/coff2ae.cc index 2986375..7e1cc0e 100644 --- a/Sources/coff2ae.cc +++ b/Sources/coff2ae.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Sources/cplusplus.cc b/Sources/cplusplus.cc index 9323d31..611507f 100644 --- a/Sources/cplusplus.cc +++ b/Sources/cplusplus.cc @@ -2,7 +2,7 @@ * ======================================================== * * cplusplus - * Copyright SoftwareLabs, all rights reserved. + * Copyright Zeta Electronics Corporation, all rights reserved. * * ======================================================== */ @@ -14,7 +14,7 @@ #define kPrintF printf #define kSplashCxx() \ - kPrintF(kWhite "%s\n", "SoftwareLabs C++ Compiler, Copyright SoftwareLabs.") + kPrintF(kWhite "%s\n", "Zeta Electronics Corporation C++ Compiler, Copyright Zeta Electronics Corporation.") #include #include @@ -29,11 +29,11 @@ #define kOk 0 -/* SoftwareLabs C++ driver */ +/* Zeta Electronics Corporation C++ driver */ /* This is part of MPCC C++ compiler. */ -/* (c) SoftwareLabs */ +/* (c) Zeta Electronics Corporation */ -/// @author SoftwareLabs (amlel) +/// @author Zeta Electronics Corporation (amlel) /// @file cc.cc /// @brief Optimized C++ Compiler. /// @todo Throw error for scoped inside scoped variables when they get referenced outside. @@ -170,7 +170,7 @@ static bool kOnForLoop = false; static bool kInBraces = false; static size_t kBracesCount = 0UL; -/* @brief C++ compiler backend for SoftwareLabs C++ */ +/* @brief C++ compiler backend for Zeta Electronics Corporation C++ */ class CompilerBackendCPlusPlus final : public ParserKit::CompilerBackend { public: @@ -316,7 +316,7 @@ bool CompilerBackendCPlusPlus::Compile(const std::string& text, ch = '_'; } - syntax_tree.fUserValue = "export .code64 __MPCC_" + fnName + "\n"; + syntax_tree.fUserValue = "export .code64 __MPCC_" + fnName + "\n"; ++kLevelFunction; break; @@ -704,7 +704,7 @@ static void cxx_print_help() { kSplashCxx(); kPrintF("%s", "No help available, see:\n"); - kPrintF("%s", "www.softwarelabs.com/developer/cplusplus\n"); + kPrintF("%s", "www.Zeta Electronics Corporation.com/developer/cplusplus\n"); } ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/Sources/elf2ae.cc b/Sources/elf2ae.cc index ada2830..a731431 100644 --- a/Sources/elf2ae.cc +++ b/Sources/elf2ae.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ diff --git a/Sources/i64asm.cc b/Sources/i64asm.cc index 26269f4..b805c95 100644 --- a/Sources/i64asm.cc +++ b/Sources/i64asm.cc @@ -1,13 +1,13 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ ///////////////////////////////////////////////////////////////////////////////////////// /// @file i64asm.cxx -/// @author SoftwareLabs +/// @author Zeta Electronics Corporation /// @brief AMD64 Assembler. /// REMINDER: when dealing with an undefined symbol use (string @@ -175,13 +175,13 @@ MPCC_MODULE(NewOSAssemblerAMD64) if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { kStdOut << "i64asm: AMD64 Assembler.\ni64asm: v1.10\ni64asm: Copyright " - "(c) 2024 SoftwareLabs.\n"; + "(c) 2024 Zeta Electronics Corporation.\n"; return 0; } else if (strcmp(argv[i], "-h") == 0) { kStdOut << "i64asm: AMD64 Assembler.\ni64asm: Copyright (c) 2024 " - "SoftwareLabs.\n"; + "Zeta Electronics Corporation.\n"; kStdOut << "-version: Print program version.\n"; kStdOut << "-verbose: Print verbose output.\n"; kStdOut << "-binary: Output as flat binary.\n"; @@ -1300,7 +1300,7 @@ bool CompilerKit::EncoderAMD64::WriteLine(std::string& line, } } } - + if (bits == 64 || bits == 32) { if (!hasRBasedRegs && bits >= 32) diff --git a/Sources/link.cc b/Sources/link.cc index 6ed2db5..08e9dd0 100644 --- a/Sources/link.cc +++ b/Sources/link.cc @@ -1,12 +1,12 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ /// @file link.cc -/// @author SoftwareLabs (amlel) -/// @brief SoftwareLabs Linker. +/// @author Zeta Electronics Corporation (amlel) +/// @brief Zeta Electronics Corporation Linker. /// Last Rev: Sat Feb 24 CET 2024 @@ -35,7 +35,7 @@ #include #include -#define kLinkerVersion "SoftwareLabs Linker %s, (c) SoftwareLabs 2024\n" +#define kLinkerVersion "Zeta Electronics Corporation Linker %s, (c) Zeta Electronics Corporation 2024\n" #define StringCompare(DST, SRC) strcmp(DST, SRC) @@ -184,7 +184,7 @@ MPCC_MODULE(NewOSLinker) { pef_container.Count = 0UL; pef_container.Kind = CompilerKit::kPefKindExec; pef_container.SubCpu = kSubArch; - pef_container.Linker = kLinkerId; // SoftwareLabs Linker + pef_container.Linker = kLinkerId; // Zeta Electronics Corporation Linker pef_container.Abi = kAbi; // Multi-Processor UX ABI pef_container.Magic[0] = kPefMagic[kFatBinaryEnable ? 2 : 0]; pef_container.Magic[1] = kPefMagic[1]; diff --git a/Sources/power-cc.cc b/Sources/power-cc.cc index d008296..6148ad0 100644 --- a/Sources/power-cc.cc +++ b/Sources/power-cc.cc @@ -2,7 +2,7 @@ * ======================================================== * * cc - * Copyright SoftwareLabs, all rights reserved. + * Copyright Zeta Electronics Corporation, all rights reserved. * * ======================================================== */ @@ -22,7 +22,7 @@ #define kOk 0 -/// @author SoftwareLabs (amlel) +/// @author Zeta Electronics Corporation (amlel) /// @file cc.cc /// @brief POWER C Compiler. @@ -1531,7 +1531,7 @@ public: #define kPrintF printf #define kSplashCxx() \ - kPrintF(kWhite "cc, %s, (c) SoftwareLabs\n", kDistVersion) + kPrintF(kWhite "cc, %s, (c) Zeta Electronics Corporation\n", kDistVersion) static void cc_print_help() { diff --git a/Sources/ppcasm.cc b/Sources/ppcasm.cc index 1edeaaa..53c99c1 100644 --- a/Sources/ppcasm.cc +++ b/Sources/ppcasm.cc @@ -1,13 +1,13 @@ /* ------------------------------------------- - Copyright SoftwareLabs + Copyright Zeta Electronics Corporation ------------------------------------------- */ ///////////////////////////////////////////////////////////////////////////////////////// /// @file ppcasm.cxx -/// @author SoftwareLabs +/// @author Zeta Electronics Corporation /// @brief POWER Assembler. /// REMINDER: when dealing with an undefined symbol use (string @@ -115,11 +115,11 @@ MPCC_MODULE(NewOSAssemblerPowerPC) { if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { kStdOut << "ppcasm: POWER Assembler.\nppcasm: " << kDistVersion << "\nppcasm: " "Copyright (c) " - "2024 SoftwareLabs.\n"; + "2024 Zeta Electronics Corporation.\n"; return 0; } else if (strcmp(argv[i], "-h") == 0) { kStdOut << "ppcasm: POWER Assembler.\nppcasm: Copyright (c) 2024 " - "SoftwareLabs.\n"; + "Zeta Electronics Corporation.\n"; kStdOut << "-version: Print program version.\n"; kStdOut << "-verbose: Print verbose output.\n"; kStdOut << "-binary: Output as flat binary.\n"; diff --git a/posix.make b/posix.make index be1abb8..bc8f81e 100644 --- a/posix.make +++ b/posix.make @@ -2,7 +2,7 @@ # ======================================================== # # MPCC - # Copyright SoftwareLabs, all rights reserved. + # Copyright Zeta Electronics Corporation, all rights reserved. # # ======================================================== # @@ -72,9 +72,9 @@ linker: .PHONY: help help: - @echo "Compiler - MPCC Compiler Suite." - @echo "Preprocessor - MPCC Preprocessor Suite." - @echo "linker - SoftwareLabs Linkers." + @echo "Compiler - Zeta Electronics Corporation Compiler Suite." + @echo "Preprocessor - Zeta Electronics Corporation Preprocessor Suite." + @echo "linker - Zeta Electronics Corporation Linkers." @echo "clean - Clean objects and executables." .PHONY: clean @@ -88,5 +88,5 @@ clean: rm -rf *.obj rm -rf Output/*.exec rm -rf *.exec - + # Last rev 8-1-24 diff --git a/win64.make b/win64.make index e1819a9..8493db6 100644 --- a/win64.make +++ b/win64.make @@ -2,7 +2,7 @@ # ======================================================== # # MPCC - # Copyright SoftwareLabs, all rights reserved. + # Copyright Zeta Electronics Corporation, all rights reserved. # # ======================================================== # @@ -72,7 +72,7 @@ linker: help: @echo "Compiler - MPCC Compiler Suite." @echo "Preprocessor - MPCC Preprocessor Suite." - @echo "linker - SoftwareLabs Linkers." + @echo "linker - Zeta Electronics Corporation Linkers." @echo "clean - Clean objects and executables." .PHONY: clean -- cgit v1.2.3 From 0495962407af7f89b72e41c8b099cfba51d68e08 Mon Sep 17 00:00:00 2001 From: Amlal EL Mahrouss Date: Thu, 4 Jul 2024 16:23:57 +0200 Subject: MHR-36: Finishing C++ compiler Signed-off-by: Amlal EL Mahrouss --- .gitignore | 2 ++ Sources/64x0-cc.cc | 4 ++-- Sources/String.cc | 16 +++++++++------- Sources/ppcasm.cc | 4 ++-- 4 files changed, 15 insertions(+), 11 deletions(-) (limited to 'Sources/String.cc') diff --git a/.gitignore b/.gitignore index c8ab9fa..69f191e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ local.properties .loadpath .recommenders +*.creator.user + # NewOS/MP-UX executable *.exec *.bin diff --git a/Sources/64x0-cc.cc b/Sources/64x0-cc.cc index 4be1292..9c32953 100644 --- a/Sources/64x0-cc.cc +++ b/Sources/64x0-cc.cc @@ -23,8 +23,6 @@ #include #include -#define kOk 0 - /* C driver */ /* This is part of MPCC C SDK. */ /* (c) Zeta Electronics Corporation */ @@ -41,6 +39,8 @@ ///////////////////// +#define kOk (0) + #define kBlank "\e[0;30m" #define kRed "\e[0;31m" #define kWhite "\e[0;97m" diff --git a/Sources/String.cc b/Sources/String.cc index 5a8f3ed..c7185ca 100644 --- a/Sources/String.cc +++ b/Sources/String.cc @@ -19,7 +19,6 @@ */ #include -#include namespace CompilerKit { CharType *StringView::Data() { return m_Data; } @@ -80,10 +79,13 @@ StringView StringBuilder::Construct(const CharType *data) { const char *StringBuilder::FromInt(const char *fmt, int i) { if (!fmt) return ("-1"); - char *ret = new char[8 + string_length(fmt)]; + auto ret_len = 8 + string_length(fmt); + char *ret = new char[ret_len]; if (!ret) return ("-1"); + memset(ret, 0, ret_len); + CharType result[8]; if (!to_str(result, sizeof(int), i)) { delete[] ret; @@ -150,18 +152,18 @@ bool StringBuilder::Equals(const char *lhs, const char *rhs) { return true; } -const char *StringBuilder::Format(const char *fmt, const char *fmt2) { - if (!fmt || !fmt2) return ("?"); +const char *StringBuilder::Format(const char *fmt, const char *fmtRight) { + if (!fmt || !fmtRight) return ("?"); - char *ret = new char[string_length(fmt2) + string_length(fmt2)]; + char *ret = new char[string_length(fmtRight) + string_length(fmtRight)]; 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]; + for (SizeType y_idx = 0; y_idx < string_length(fmtRight); ++y_idx) { + ret[result_cnt] = fmtRight[y_idx]; ++result_cnt; } diff --git a/Sources/ppcasm.cc b/Sources/ppcasm.cc index 8d5f088..f8e47d7 100644 --- a/Sources/ppcasm.cc +++ b/Sources/ppcasm.cc @@ -43,11 +43,11 @@ #define kStdOut (std::cout << kWhite) #define kStdErr (std::cout << kRed) +constexpr auto cPowerIPAlignment = 0x4U; + static CharType kOutputArch = CompilerKit::kPefArchPowerPC; static Boolean kOutputAsBinary = false; -constexpr auto cPowerIPAlignment = 0x4U; - static UInt32 kErrorLimit = 10; static UInt32 kAcceptableErrors = 0; -- cgit v1.2.3 From 6653cfe50690dc4f53c8bec30cdb7d40ef9b62a4 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Fri, 12 Jul 2024 04:33:08 +0200 Subject: [IMP] Needs to be merged with stable. Signed-off-by: Amlal El Mahrouss --- Comm/AsmKit/AsmKit.hpp | 2 +- Comm/AsmKit/CPU/32x0.hpp | 2 +- Comm/AsmKit/CPU/64x0.hpp | 2 +- Comm/AsmKit/CPU/amd64.hpp | 2 +- Comm/AsmKit/CPU/arm64.hpp | 3 +-- Comm/AsmKit/CPU/ppc.hpp | 4 ++-- Comm/CompilerKit.hpp | 2 +- Comm/Defines.hpp | 2 +- Comm/ParserKit.hpp | 2 +- Comm/Public/SDK/CRT/__mpcc_alloca.hxx | 2 +- Comm/Public/SDK/CRT/__mpcc_defines.hxx | 2 +- Comm/Public/SDK/CRT/__mpcc_exception.hxx | 2 +- Comm/Public/SDK/CRT/__mpcc_hint.hxx | 2 +- Comm/Public/SDK/CRT/__mpcc_malloc.hxx | 2 +- Comm/StdKit/AE.hpp | 2 +- Comm/StdKit/ErrorID.hpp | 2 +- Comm/StdKit/ErrorOr.hpp | 2 +- Comm/StdKit/PEF.hpp | 2 +- Comm/StdKit/Ref.hpp | 4 ++-- Comm/StdKit/String.hpp | 2 +- Comm/StdKit/XCOFF.hxx | 2 +- Doc/Inside 64x0.pdf | Bin 64675 -> 0 bytes Doc/asm-specs.txt | 11 ----------- Doc/havp.txt | 13 ------------- Doc/notice.txt | 4 ---- Doc/vnrp.txt | 17 ----------------- Icons/app-logo.ico | Bin 4865 -> 0 bytes Notes/Inside 64x0.pdf | Bin 0 -> 64675 bytes Notes/asm-specs.txt | 11 +++++++++++ Notes/havp.txt | 13 +++++++++++++ Notes/notice.txt | 4 ++++ Notes/vnrp.txt | 17 +++++++++++++++++ ReadMe.md | 7 +++++-- Sources/32asm.cc | 4 ++-- Sources/64asm.cc | 4 ++-- Sources/64x0-cc.cc | 6 +++--- Sources/AssemblyFactory.cc | 4 ++-- Sources/Detail/asmutils.hxx | 2 +- Sources/Detail/compilerutils.hxx | 2 +- Sources/String.cc | 4 ++-- Sources/bpp.cc | 6 +++--- Sources/coff2ae.cc | 2 +- Sources/cplusplus.cc | 6 +++--- Sources/elf2ae.cc | 2 +- Sources/i64asm.cc | 6 +++--- Sources/link.cc | 8 ++++---- Sources/power-cc.cc | 4 ++-- Sources/ppcasm.cc | 6 +++--- posix.make | 8 ++++---- win64.make | 8 ++++---- 50 files changed, 114 insertions(+), 112 deletions(-) delete mode 100644 Doc/Inside 64x0.pdf delete mode 100644 Doc/asm-specs.txt delete mode 100644 Doc/havp.txt delete mode 100644 Doc/notice.txt delete mode 100644 Doc/vnrp.txt delete mode 100644 Icons/app-logo.ico create mode 100644 Notes/Inside 64x0.pdf create mode 100644 Notes/asm-specs.txt create mode 100644 Notes/havp.txt create mode 100644 Notes/notice.txt create mode 100644 Notes/vnrp.txt (limited to 'Sources/String.cc') diff --git a/Comm/AsmKit/AsmKit.hpp b/Comm/AsmKit/AsmKit.hpp index 6fbacfa..38b418c 100644 --- a/Comm/AsmKit/AsmKit.hpp +++ b/Comm/AsmKit/AsmKit.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Comm/AsmKit/CPU/32x0.hpp b/Comm/AsmKit/CPU/32x0.hpp index e469dda..7b93a94 100644 --- a/Comm/AsmKit/CPU/32x0.hpp +++ b/Comm/AsmKit/CPU/32x0.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Comm/AsmKit/CPU/64x0.hpp b/Comm/AsmKit/CPU/64x0.hpp index 10d12d8..b8bafb9 100644 --- a/Comm/AsmKit/CPU/64x0.hpp +++ b/Comm/AsmKit/CPU/64x0.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Comm/AsmKit/CPU/amd64.hpp b/Comm/AsmKit/CPU/amd64.hpp index 17b515b..06dc1da 100644 --- a/Comm/AsmKit/CPU/amd64.hpp +++ b/Comm/AsmKit/CPU/amd64.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Comm/AsmKit/CPU/arm64.hpp b/Comm/AsmKit/CPU/arm64.hpp index a6b558a..8dd5204 100644 --- a/Comm/AsmKit/CPU/arm64.hpp +++ b/Comm/AsmKit/CPU/arm64.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- -Copyright Zeta Electronics Corporation +Copyright ZKA Technologies ------------------------------------------- */ @@ -24,4 +24,3 @@ struct CpuOpcodeArm64 final uint32_t fImmediateValue; // immediate 32-bit value bool fImmediateValueHooked; }; - diff --git a/Comm/AsmKit/CPU/ppc.hpp b/Comm/AsmKit/CPU/ppc.hpp index 4afbf5a..e3ea6c5 100644 --- a/Comm/AsmKit/CPU/ppc.hpp +++ b/Comm/AsmKit/CPU/ppc.hpp @@ -1,7 +1,7 @@ /* ------------------------------------------- - Some modifications are copyrighted under: - Zeta Electronics Corporation + Some modifications are copyrighted under: + ZKA Technologies Original author: Apple Inc diff --git a/Comm/CompilerKit.hpp b/Comm/CompilerKit.hpp index 25a1e66..177e424 100644 --- a/Comm/CompilerKit.hpp +++ b/Comm/CompilerKit.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Comm/Defines.hpp b/Comm/Defines.hpp index a6f0260..31c1998 100644 --- a/Comm/Defines.hpp +++ b/Comm/Defines.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Comm/ParserKit.hpp b/Comm/ParserKit.hpp index bc0ab54..4c3f483 100644 --- a/Comm/ParserKit.hpp +++ b/Comm/ParserKit.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Comm/Public/SDK/CRT/__mpcc_alloca.hxx b/Comm/Public/SDK/CRT/__mpcc_alloca.hxx index 19ebaaf..02b3123 100644 --- a/Comm/Public/SDK/CRT/__mpcc_alloca.hxx +++ b/Comm/Public/SDK/CRT/__mpcc_alloca.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Comm/Public/SDK/CRT/__mpcc_defines.hxx b/Comm/Public/SDK/CRT/__mpcc_defines.hxx index a526fd3..19ed8a4 100644 --- a/Comm/Public/SDK/CRT/__mpcc_defines.hxx +++ b/Comm/Public/SDK/CRT/__mpcc_defines.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Comm/Public/SDK/CRT/__mpcc_exception.hxx b/Comm/Public/SDK/CRT/__mpcc_exception.hxx index a2539eb..4a9f84a 100644 --- a/Comm/Public/SDK/CRT/__mpcc_exception.hxx +++ b/Comm/Public/SDK/CRT/__mpcc_exception.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Comm/Public/SDK/CRT/__mpcc_hint.hxx b/Comm/Public/SDK/CRT/__mpcc_hint.hxx index db58203..02dbc94 100644 --- a/Comm/Public/SDK/CRT/__mpcc_hint.hxx +++ b/Comm/Public/SDK/CRT/__mpcc_hint.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Comm/Public/SDK/CRT/__mpcc_malloc.hxx b/Comm/Public/SDK/CRT/__mpcc_malloc.hxx index db3075f..eeaa67b 100644 --- a/Comm/Public/SDK/CRT/__mpcc_malloc.hxx +++ b/Comm/Public/SDK/CRT/__mpcc_malloc.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Comm/StdKit/AE.hpp b/Comm/StdKit/AE.hpp index d06a8ca..ee39e56 100644 --- a/Comm/StdKit/AE.hpp +++ b/Comm/StdKit/AE.hpp @@ -2,7 +2,7 @@ * ======================================================== * * MPCC - * Copyright Zeta Electronics Corporation, all rights reserved. + * Copyright ZKA Technologies, all rights reserved. * * ======================================================== */ diff --git a/Comm/StdKit/ErrorID.hpp b/Comm/StdKit/ErrorID.hpp index 698b66b..abaac85 100644 --- a/Comm/StdKit/ErrorID.hpp +++ b/Comm/StdKit/ErrorID.hpp @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright Zeta Electronics Corporation, all rights reserved. + * Copyright ZKA Technologies, all rights reserved. * * ======================================================== */ diff --git a/Comm/StdKit/ErrorOr.hpp b/Comm/StdKit/ErrorOr.hpp index 04f013d..4097cc9 100644 --- a/Comm/StdKit/ErrorOr.hpp +++ b/Comm/StdKit/ErrorOr.hpp @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright Zeta Electronics Corporation, all rights reserved. + * Copyright ZKA Technologies, all rights reserved. * * ======================================================== */ diff --git a/Comm/StdKit/PEF.hpp b/Comm/StdKit/PEF.hpp index 911d903..85044b2 100644 --- a/Comm/StdKit/PEF.hpp +++ b/Comm/StdKit/PEF.hpp @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Comm/StdKit/Ref.hpp b/Comm/StdKit/Ref.hpp index 3ccb983..e655ccb 100644 --- a/Comm/StdKit/Ref.hpp +++ b/Comm/StdKit/Ref.hpp @@ -3,7 +3,7 @@ * ======================================================== * * CompilerKit - * Copyright Zeta Electronics Corporation, all rights reserved. + * Copyright ZKA Technologies, all rights reserved. * * ======================================================== */ @@ -12,7 +12,7 @@ namespace CompilerKit { - // @author Zeta Electronics Corporation + // @author ZKA Technologies // @brief Reference class, refers to a pointer of data in static memory. template class Ref final diff --git a/Comm/StdKit/String.hpp b/Comm/StdKit/String.hpp index e495219..7e62bc5 100644 --- a/Comm/StdKit/String.hpp +++ b/Comm/StdKit/String.hpp @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright Zeta Electronics Corporation, all rights reserved. + * Copyright ZKA Technologies, all rights reserved. * * ======================================================== */ diff --git a/Comm/StdKit/XCOFF.hxx b/Comm/StdKit/XCOFF.hxx index 7e57514..4b25484 100644 --- a/Comm/StdKit/XCOFF.hxx +++ b/Comm/StdKit/XCOFF.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies File: XCOFF.hpp Purpose: XCOFF for NewOS. diff --git a/Doc/Inside 64x0.pdf b/Doc/Inside 64x0.pdf deleted file mode 100644 index bcd6782..0000000 Binary files a/Doc/Inside 64x0.pdf and /dev/null differ diff --git a/Doc/asm-specs.txt b/Doc/asm-specs.txt deleted file mode 100644 index a0c42bf..0000000 --- a/Doc/asm-specs.txt +++ /dev/null @@ -1,11 +0,0 @@ -==================== -X86 ASSEMBLER SPECS -==================== - -WHAT TO DO: - Provide a complete support of x86-64 with: - - - org directive. - - 64-bit and 32-bit registers. - - basic instructions (load, store, jump to) - - flushable into object-code and flat binary. \ No newline at end of file diff --git a/Doc/havp.txt b/Doc/havp.txt deleted file mode 100644 index 12fcec5..0000000 --- a/Doc/havp.txt +++ /dev/null @@ -1,13 +0,0 @@ -HAVP - Harvard Audio/Video Processor - -- Encoding: IBAD - -- Data path = 24 - - 16: sound data - - 8: information data - -- Register size: 32 -- Store strategy: shift registers. -- Standard registers: [ r0, r9 ] -- Floating point registers: [ f0, f2 ] -- Builtin SRAM: 512kb diff --git a/Doc/notice.txt b/Doc/notice.txt deleted file mode 100644 index 23691da..0000000 --- a/Doc/notice.txt +++ /dev/null @@ -1,4 +0,0 @@ -The X64000 draft papers -They contain thing that might appear through the next iteration of 64k. - -Please look at the document shared for the latest revisions. \ No newline at end of file diff --git a/Doc/vnrp.txt b/Doc/vnrp.txt deleted file mode 100644 index e17b494..0000000 --- a/Doc/vnrp.txt +++ /dev/null @@ -1,17 +0,0 @@ -VNRP - Von Neumann, RISC Processor - -- Encoding = RegToReg, Imm, Syscall, Jump, NoArgs - -- Data path = 128-bit (register data) -- Addressing = 58-bit physical address size. - -- Registers (128-bit) = r0, r19 -- Float/Vector registers (128-bit) = f0, f9 - -- Out of order (superscalar also added to the equation) = Yes -- Superscalar = Yes - -- L1 cache: 16kb (8 instr, 8 data) -- L2 cache: 1024kb (512 instr, 512 data) - -- Clock speed: 1 Ghz diff --git a/Icons/app-logo.ico b/Icons/app-logo.ico deleted file mode 100644 index 2ab3d5b..0000000 Binary files a/Icons/app-logo.ico and /dev/null differ diff --git a/Notes/Inside 64x0.pdf b/Notes/Inside 64x0.pdf new file mode 100644 index 0000000..bcd6782 Binary files /dev/null and b/Notes/Inside 64x0.pdf differ diff --git a/Notes/asm-specs.txt b/Notes/asm-specs.txt new file mode 100644 index 0000000..a0c42bf --- /dev/null +++ b/Notes/asm-specs.txt @@ -0,0 +1,11 @@ +==================== +X86 ASSEMBLER SPECS +==================== + +WHAT TO DO: + Provide a complete support of x86-64 with: + + - org directive. + - 64-bit and 32-bit registers. + - basic instructions (load, store, jump to) + - flushable into object-code and flat binary. \ No newline at end of file diff --git a/Notes/havp.txt b/Notes/havp.txt new file mode 100644 index 0000000..12fcec5 --- /dev/null +++ b/Notes/havp.txt @@ -0,0 +1,13 @@ +HAVP - Harvard Audio/Video Processor + +- Encoding: IBAD + +- Data path = 24 + - 16: sound data + - 8: information data + +- Register size: 32 +- Store strategy: shift registers. +- Standard registers: [ r0, r9 ] +- Floating point registers: [ f0, f2 ] +- Builtin SRAM: 512kb diff --git a/Notes/notice.txt b/Notes/notice.txt new file mode 100644 index 0000000..23691da --- /dev/null +++ b/Notes/notice.txt @@ -0,0 +1,4 @@ +The X64000 draft papers +They contain thing that might appear through the next iteration of 64k. + +Please look at the document shared for the latest revisions. \ No newline at end of file diff --git a/Notes/vnrp.txt b/Notes/vnrp.txt new file mode 100644 index 0000000..e17b494 --- /dev/null +++ b/Notes/vnrp.txt @@ -0,0 +1,17 @@ +VNRP - Von Neumann, RISC Processor + +- Encoding = RegToReg, Imm, Syscall, Jump, NoArgs + +- Data path = 128-bit (register data) +- Addressing = 58-bit physical address size. + +- Registers (128-bit) = r0, r19 +- Float/Vector registers (128-bit) = f0, f9 + +- Out of order (superscalar also added to the equation) = Yes +- Superscalar = Yes + +- L1 cache: 16kb (8 instr, 8 data) +- L2 cache: 1024kb (512 instr, 512 data) + +- Clock speed: 1 Ghz diff --git a/ReadMe.md b/ReadMe.md index ae705e2..60e7433 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -1,16 +1,19 @@ # NDK +## Install + Start by cloning the repo: ``` git clone git@bitbucket.org:mahrouss/codetools.git ``` -and +And then: ``` make -f .make all ``` +You can now use the programs. -##### Copyright Zeta Electronics Corporation, all rights reserved. +##### Copyright ZKA Technologies, all rights reserved. diff --git a/Sources/32asm.cc b/Sources/32asm.cc index b043447..d32ab0b 100644 --- a/Sources/32asm.cc +++ b/Sources/32asm.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ @@ -9,7 +9,7 @@ ///////////////////////////////////////////////////////////////////////////////////////// // @file 32asm.cxx -// @author Zeta Electronics Corporation +// @author ZKA Technologies // @brief 32x0 Assembler. // REMINDER: when dealing with an undefined symbol use (string diff --git a/Sources/64asm.cc b/Sources/64asm.cc index 384a086..0a89e6a 100644 --- a/Sources/64asm.cc +++ b/Sources/64asm.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ @@ -110,7 +110,7 @@ NDK_MODULE(NewOSAssembler64000) { if (argv[i][0] == '-') { if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { kStdOut << "64asm: 64x0 Assembler.\n64asm: v1.10\n64asm: Copyright (c) " - "2024 Zeta Electronics Corporation.\n"; + "ZKA Technologies.\n"; return 0; } else if (strcmp(argv[i], "-h") == 0) { kStdOut << "64asm: 64x0 Assembler.\n64asm: Copyright (c) 2024 Mahrouss " diff --git a/Sources/64x0-cc.cc b/Sources/64x0-cc.cc index 9f73b1b..efbf68f 100644 --- a/Sources/64x0-cc.cc +++ b/Sources/64x0-cc.cc @@ -2,7 +2,7 @@ * ======================================================== * * cc - * Copyright Zeta Electronics Corporation, all rights reserved. + * Copyright ZKA Technologies, all rights reserved. * * ======================================================== */ @@ -25,7 +25,7 @@ /* C driver */ /* This is part of the NDK. */ -/* (c) Zeta Electronics Corporation */ +/* (c) ZKA Technologies */ /// @author Amlal El Mahrouss (amlel) /// @file 64x0-cc.cc @@ -1513,7 +1513,7 @@ public: #define kPrintF printf #define kSplashCxx() \ - kPrintF(kWhite "Zeta C Driver, %s, (c) Zeta Electronics Corporation\n", kDistVersion) + kPrintF(kWhite "Zeta C Driver, %s, (c) ZKA Technologies\n", kDistVersion) static void cc_print_help() { diff --git a/Sources/AssemblyFactory.cc b/Sources/AssemblyFactory.cc index faa4847..35d8cbd 100644 --- a/Sources/AssemblyFactory.cc +++ b/Sources/AssemblyFactory.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ @@ -14,7 +14,7 @@ * @version 0.1 * @date 2024-01-27 * - * @copyright Copyright (c) 2024, Zeta Electronics Corporation + * @copyright Copyright (c) 2024, ZKA Technologies * */ diff --git a/Sources/Detail/asmutils.hxx b/Sources/Detail/asmutils.hxx index c531126..00bfbd7 100644 --- a/Sources/Detail/asmutils.hxx +++ b/Sources/Detail/asmutils.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Sources/Detail/compilerutils.hxx b/Sources/Detail/compilerutils.hxx index fdcf141..4c46727 100644 --- a/Sources/Detail/compilerutils.hxx +++ b/Sources/Detail/compilerutils.hxx @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Sources/String.cc b/Sources/String.cc index c7185ca..accc1af 100644 --- a/Sources/String.cc +++ b/Sources/String.cc @@ -2,7 +2,7 @@ * ======================================================== * * CompilerKit - * Copyright Zeta Electronics Corporation, all rights reserved. + * Copyright ZKA Technologies, all rights reserved. * * ======================================================== */ @@ -14,7 +14,7 @@ * @version 0.2 * @date 2024-01-23 * - * @copyright Copyright (c) 2024 Zeta Electronics Corporation + * @copyright Copyright (c) ZKA Technologies * */ diff --git a/Sources/bpp.cc b/Sources/bpp.cc index d703748..1aefc33 100644 --- a/Sources/bpp.cc +++ b/Sources/bpp.cc @@ -2,7 +2,7 @@ * ======================================================== * * bpp - * Copyright Zeta Electronics Corporation, all rights reserved. + * Copyright ZKA Technologies, all rights reserved. * * ======================================================== */ @@ -812,12 +812,12 @@ NDK_MODULE(NewOSPreprocessor) { if (argv[index][0] == '/') { if (strcmp(argv[index], "/version") == 0) { - printf("%s\n", "bpp v1.11, (c) Zeta Electronics Corporation"); + printf("%s\n", "bpp v1.11, (c) ZKA Technologies"); return 0; } if (strcmp(argv[index], "/help") == 0) { - printf("%s\n", "Zeta Preprocessor Driver v1.11, (c) Zeta Electronics Corporation"); + printf("%s\n", "Zeta Preprocessor Driver v1.11, (c) ZKA Technologies"); printf("%s\n", "/working-dir : set directory to working path."); printf("%s\n", "/include-dir : add directory to include path."); printf("%s\n", "/def : def macro."); diff --git a/Sources/coff2ae.cc b/Sources/coff2ae.cc index 0bf17e6..71f5bba 100644 --- a/Sources/coff2ae.cc +++ b/Sources/coff2ae.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Sources/cplusplus.cc b/Sources/cplusplus.cc index 59b5dcf..4059413 100644 --- a/Sources/cplusplus.cc +++ b/Sources/cplusplus.cc @@ -2,7 +2,7 @@ * ======================================================== * * cplusplus - * Copyright Zeta Electronics Corporation, all rights reserved. + * Copyright ZKA Technologies, all rights reserved. * * ======================================================== */ @@ -32,9 +32,9 @@ kPrintF(kWhite "%s\n", "Zeta C++ Compiler Driver, (c) 2024 Zeta Electronics, all #define kOk 0 -/* Zeta Electronics Corporation C++ driver */ +/* ZKA Technologies C++ driver */ /* This is part of ZECC C++ compiler. */ -/* (c) Zeta Electronics Corporation */ +/* (c) ZKA Technologies */ /// @author Amlal El Mahrouss (amlel) /// @file cc.cc diff --git a/Sources/elf2ae.cc b/Sources/elf2ae.cc index ede28a2..70ab104 100644 --- a/Sources/elf2ae.cc +++ b/Sources/elf2ae.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ diff --git a/Sources/i64asm.cc b/Sources/i64asm.cc index f0dd459..c0dd351 100644 --- a/Sources/i64asm.cc +++ b/Sources/i64asm.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ @@ -175,13 +175,13 @@ NDK_MODULE(NewOSAssemblerAMD64) if (strcmp(argv[i], "/version") == 0 || strcmp(argv[i], "/v") == 0) { kStdOut << "i64asm: AMD64 Assembler Driver.\ni64asm: v1.10\ni64asm: Copyright " - "(c) 2024 Zeta Electronics Corporation.\n"; + "(c) ZKA Technologies.\n"; return 0; } else if (strcmp(argv[i], "/h") == 0) { kStdOut << "i64asm: AMD64 Assembler Driver.\ni64asm: Copyright (c) 2024 " - "Zeta Electronics Corporation.\n"; + "ZKA Technologies.\n"; kStdOut << "/version: Print program version.\n"; kStdOut << "/verbose: Print verbose output.\n"; kStdOut << "/binary: Output as flat binary.\n"; diff --git a/Sources/link.cc b/Sources/link.cc index 0114484..d94cbf1 100644 --- a/Sources/link.cc +++ b/Sources/link.cc @@ -1,12 +1,12 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ /// @file link.cc /// @author Amlal EL Mahrouss (amlel) -/// @brief Zeta Electronics Corporation Linker. +/// @brief ZKA Technologies Linker. /// Last Rev: Sat Feb 24 CET 2024 @@ -35,7 +35,7 @@ #include #include -#define kLinkerVersion "Zeta Linker Driver %s, (c) Zeta Electronics Corporation 2024, all rights reserved.\n" +#define kLinkerVersion "Zeta Linker Driver %s, (c) ZKA Technologies 2024, all rights reserved.\n" #define StringCompare(DST, SRC) strcmp(DST, SRC) @@ -229,7 +229,7 @@ NDK_MODULE(NewOSLinker) pef_container.Count = 0UL; pef_container.Kind = CompilerKit::kPefKindExec; pef_container.SubCpu = kSubArch; - pef_container.Linker = kLinkerId; // Zeta Electronics Corporation Linker + pef_container.Linker = kLinkerId; // ZKA Technologies Linker pef_container.Abi = kAbi; // Multi-Processor UX ABI pef_container.Magic[0] = kPefMagic[kFatBinaryEnable ? 2 : 0]; pef_container.Magic[1] = kPefMagic[1]; diff --git a/Sources/power-cc.cc b/Sources/power-cc.cc index ac5d84b..332fa53 100644 --- a/Sources/power-cc.cc +++ b/Sources/power-cc.cc @@ -2,7 +2,7 @@ * ======================================================== * * cc - * Copyright Zeta Electronics Corporation, all rights reserved. + * Copyright ZKA Technologies, all rights reserved. * * ======================================================== */ @@ -1531,7 +1531,7 @@ public: #define kPrintF printf #define kSplashCxx() \ - kPrintF(kWhite "cc, %s, (c) Zeta Electronics Corporation\n", kDistVersion) + kPrintF(kWhite "cc, %s, (c) ZKA Technologies\n", kDistVersion) static void cc_print_help() { diff --git a/Sources/ppcasm.cc b/Sources/ppcasm.cc index 0aec82d..5f015d5 100644 --- a/Sources/ppcasm.cc +++ b/Sources/ppcasm.cc @@ -1,6 +1,6 @@ /* ------------------------------------------- - Copyright Zeta Electronics Corporation + Copyright ZKA Technologies ------------------------------------------- */ @@ -114,11 +114,11 @@ NDK_MODULE(NewOSAssemblerPowerPC) { if (strcmp(argv[i], "/version") == 0 || strcmp(argv[i], "/v") == 0) { kStdOut << "ppcasm: POWER64 Assembler Driver.\nppcasm: " << kDistVersion << "\nppcasm: " "Copyright (c) " - "2024 Zeta Electronics Corporation.\n"; + "ZKA Technologies.\n"; return 0; } else if (strcmp(argv[i], "/h") == 0) { kStdOut << "ppcasm: POWER64 Assembler Driver.\nppcasm: Copyright (c) 2024 " - "Zeta Electronics Corporation.\n"; + "ZKA Technologies.\n"; kStdOut << "/version,/v: print program version.\n"; kStdOut << "/verbose: print verbose output.\n"; kStdOut << "/binary: output as flat binary.\n"; diff --git a/posix.make b/posix.make index 34fa367..8a17a58 100644 --- a/posix.make +++ b/posix.make @@ -2,7 +2,7 @@ # ======================================================== # # MPCC - # Copyright Zeta Electronics Corporation, all rights reserved. + # Copyright ZKA Technologies, all rights reserved. # # ======================================================== # @@ -72,9 +72,9 @@ linker: .PHONY: help help: - @echo "compiler - Zeta Electronics Corporation Compiler Suite." - @echo "pre-processor - Zeta Electronics Corporation Preprocessor Suite." - @echo "linker - Zeta Electronics Corporation Linkers." + @echo "compiler - ZKA Technologies Compiler Suite." + @echo "pre-processor - ZKA Technologies Preprocessor Suite." + @echo "linker - ZKA Technologies Linkers." @echo "clean - Clean objects and executables." .PHONY: clean diff --git a/win64.make b/win64.make index 8493db6..37d762a 100644 --- a/win64.make +++ b/win64.make @@ -2,7 +2,7 @@ # ======================================================== # # MPCC - # Copyright Zeta Electronics Corporation, all rights reserved. + # Copyright ZKA Technologies, all rights reserved. # # ======================================================== # @@ -70,9 +70,9 @@ linker: .PHONY: help help: - @echo "Compiler - MPCC Compiler Suite." - @echo "Preprocessor - MPCC Preprocessor Suite." - @echo "linker - Zeta Electronics Corporation Linkers." + @echo "compiler - ZKA Compiler Suite." + @echo "pre-processor - ZKA Preprocessor Suite." + @echo "linker - ZKA Linkers." @echo "clean - Clean objects and executables." .PHONY: clean -- cgit v1.2.3 From d764e44d4b43392a86a1c7c0ab1ad455fafc3294 Mon Sep 17 00:00:00 2001 From: Amlal Date: Wed, 17 Jul 2024 18:36:07 +0200 Subject: [IMP] Much better source tree. Signed-off-by: Amlal --- .vscode/c_cpp_properties.json | 60 +- Comm/AsmKit/AsmKit.hpp | 217 --- Comm/AsmKit/CPU/32x0.hpp | 95 -- Comm/AsmKit/CPU/64x0.hpp | 108 -- Comm/AsmKit/CPU/amd64.hpp | 57 - Comm/AsmKit/CPU/arm64.hpp | 26 - Comm/AsmKit/CPU/ppc.hpp | 1929 --------------------------- Comm/CompilerKit.hpp | 33 - Comm/Defines.hpp | 147 -- Comm/ParserKit.hpp | 173 --- Comm/Public/SDK/CRT/__mpcc_alloca.hxx | 15 - Comm/Public/SDK/CRT/__mpcc_defines.hxx | 83 -- Comm/Public/SDK/CRT/__mpcc_exception.hxx | 27 - Comm/Public/SDK/CRT/__mpcc_hint.hxx | 20 - Comm/Public/SDK/CRT/__mpcc_malloc.hxx | 30 - Comm/Public/SDK/CRT/__mpcc_power.inc | 35 - Comm/StdKit/AE.hpp | 143 -- Comm/StdKit/ELF.hpp | 389 ------ Comm/StdKit/ErrorID.hpp | 22 - Comm/StdKit/ErrorOr.hpp | 61 - Comm/StdKit/PEF.hpp | 133 -- Comm/StdKit/Ref.hpp | 91 -- Comm/StdKit/String.hpp | 90 -- Comm/StdKit/XCOFF.hxx | 41 - Comm/UUID.hpp | 983 -------------- Comm/Version.hxx | 3 - Examples/ExampleCDialect.S | 2 +- Headers/AsmKit/AsmKit.hpp | 217 +++ Headers/AsmKit/CPU/32x0.hpp | 95 ++ Headers/AsmKit/CPU/64x0.hpp | 108 ++ Headers/AsmKit/CPU/amd64.hpp | 57 + Headers/AsmKit/CPU/arm64.hpp | 26 + Headers/AsmKit/CPU/ppc.hpp | 1929 +++++++++++++++++++++++++++ Headers/Defines.hpp | 147 ++ Headers/Macros.hpp | 33 + Headers/ParserKit.hpp | 173 +++ Headers/Public/SDK/CRT/__mpcc_alloca.hxx | 15 + Headers/Public/SDK/CRT/__mpcc_defines.hxx | 83 ++ Headers/Public/SDK/CRT/__mpcc_exception.hxx | 27 + Headers/Public/SDK/CRT/__mpcc_hint.hxx | 20 + Headers/Public/SDK/CRT/__mpcc_malloc.hxx | 30 + Headers/Public/SDK/CRT/__mpcc_power.inc | 35 + Headers/StdKit/AE.hpp | 143 ++ Headers/StdKit/ELF.hpp | 389 ++++++ Headers/StdKit/ErrorID.hpp | 22 + Headers/StdKit/ErrorOr.hpp | 61 + Headers/StdKit/PEF.hpp | 134 ++ Headers/StdKit/Ref.hpp | 91 ++ Headers/StdKit/String.hpp | 90 ++ Headers/StdKit/XCOFF.hxx | 41 + Headers/UUID.hpp | 983 ++++++++++++++ Headers/Version.hxx | 3 + Notes/ASM specs.txt | 11 + Notes/HAVP DSP.txt | 13 + Notes/Notice.txt | 4 + Notes/RISC CPU.txt | 17 + Notes/asm-specs.txt | 11 - Notes/havp.txt | 13 - Notes/notice.txt | 4 - Notes/vnrp.txt | 17 - Sources/32asm.cc | 52 - Sources/32asm.cxx | 52 + Sources/64asm.cc | 954 ------------- Sources/64asm.cxx | 954 +++++++++++++ Sources/64x0-cc.cc | 1627 ---------------------- Sources/64x0-cc.cxx | 1627 ++++++++++++++++++++++ Sources/AssemblyFactory.cc | 59 - Sources/AssemblyFactory.cxx | 59 + Sources/Detail/asmutils.hxx | 4 +- Sources/Detail/compilerutils.hxx | 4 +- Sources/String.cc | 200 --- Sources/String.cxx | 200 +++ Sources/bpp.cc | 899 ------------- Sources/bpp.cxx | 899 +++++++++++++ Sources/coff2ae.cc | 23 - Sources/coff2ae.cxx | 23 + Sources/compile_flags.txt | 2 +- Sources/cplusplus.cc | 905 ------------- Sources/cplusplus.cxx | 905 +++++++++++++ Sources/elf2ae.cc | 22 - Sources/elf2ae.cxx | 22 + Sources/i64asm.cc | 1484 --------------------- Sources/i64asm.cxx | 1484 +++++++++++++++++++++ Sources/link.cc | 738 ---------- Sources/link.cxx | 741 ++++++++++ Sources/power-cc.cc | 1645 ----------------------- Sources/power-cc.cxx | 1645 +++++++++++++++++++++++ Sources/ppcasm.cc | 976 -------------- Sources/ppcasm.cxx | 976 ++++++++++++++ codetools.files | 78 +- codetools.includes | 2 +- posix.make | 20 +- win64.make | 20 +- 93 files changed, 14680 insertions(+), 14676 deletions(-) delete mode 100644 Comm/AsmKit/AsmKit.hpp delete mode 100644 Comm/AsmKit/CPU/32x0.hpp delete mode 100644 Comm/AsmKit/CPU/64x0.hpp delete mode 100644 Comm/AsmKit/CPU/amd64.hpp delete mode 100644 Comm/AsmKit/CPU/arm64.hpp delete mode 100644 Comm/AsmKit/CPU/ppc.hpp delete mode 100644 Comm/CompilerKit.hpp delete mode 100644 Comm/Defines.hpp delete mode 100644 Comm/ParserKit.hpp delete mode 100644 Comm/Public/SDK/CRT/__mpcc_alloca.hxx delete mode 100644 Comm/Public/SDK/CRT/__mpcc_defines.hxx delete mode 100644 Comm/Public/SDK/CRT/__mpcc_exception.hxx delete mode 100644 Comm/Public/SDK/CRT/__mpcc_hint.hxx delete mode 100644 Comm/Public/SDK/CRT/__mpcc_malloc.hxx delete mode 100644 Comm/Public/SDK/CRT/__mpcc_power.inc delete mode 100644 Comm/StdKit/AE.hpp delete mode 100644 Comm/StdKit/ELF.hpp delete mode 100644 Comm/StdKit/ErrorID.hpp delete mode 100644 Comm/StdKit/ErrorOr.hpp delete mode 100644 Comm/StdKit/PEF.hpp delete mode 100644 Comm/StdKit/Ref.hpp delete mode 100644 Comm/StdKit/String.hpp delete mode 100644 Comm/StdKit/XCOFF.hxx delete mode 100644 Comm/UUID.hpp delete mode 100644 Comm/Version.hxx create mode 100644 Headers/AsmKit/AsmKit.hpp create mode 100644 Headers/AsmKit/CPU/32x0.hpp create mode 100644 Headers/AsmKit/CPU/64x0.hpp create mode 100644 Headers/AsmKit/CPU/amd64.hpp create mode 100644 Headers/AsmKit/CPU/arm64.hpp create mode 100644 Headers/AsmKit/CPU/ppc.hpp create mode 100644 Headers/Defines.hpp create mode 100644 Headers/Macros.hpp create mode 100644 Headers/ParserKit.hpp create mode 100644 Headers/Public/SDK/CRT/__mpcc_alloca.hxx create mode 100644 Headers/Public/SDK/CRT/__mpcc_defines.hxx create mode 100644 Headers/Public/SDK/CRT/__mpcc_exception.hxx create mode 100644 Headers/Public/SDK/CRT/__mpcc_hint.hxx create mode 100644 Headers/Public/SDK/CRT/__mpcc_malloc.hxx create mode 100644 Headers/Public/SDK/CRT/__mpcc_power.inc create mode 100644 Headers/StdKit/AE.hpp create mode 100644 Headers/StdKit/ELF.hpp create mode 100644 Headers/StdKit/ErrorID.hpp create mode 100644 Headers/StdKit/ErrorOr.hpp create mode 100644 Headers/StdKit/PEF.hpp create mode 100644 Headers/StdKit/Ref.hpp create mode 100644 Headers/StdKit/String.hpp create mode 100644 Headers/StdKit/XCOFF.hxx create mode 100644 Headers/UUID.hpp create mode 100644 Headers/Version.hxx create mode 100644 Notes/ASM specs.txt create mode 100644 Notes/HAVP DSP.txt create mode 100644 Notes/Notice.txt create mode 100644 Notes/RISC CPU.txt delete mode 100644 Notes/asm-specs.txt delete mode 100644 Notes/havp.txt delete mode 100644 Notes/notice.txt delete mode 100644 Notes/vnrp.txt delete mode 100644 Sources/32asm.cc create mode 100644 Sources/32asm.cxx delete mode 100644 Sources/64asm.cc create mode 100644 Sources/64asm.cxx delete mode 100644 Sources/64x0-cc.cc create mode 100644 Sources/64x0-cc.cxx delete mode 100644 Sources/AssemblyFactory.cc create mode 100644 Sources/AssemblyFactory.cxx delete mode 100644 Sources/String.cc create mode 100644 Sources/String.cxx delete mode 100644 Sources/bpp.cc create mode 100644 Sources/bpp.cxx delete mode 100644 Sources/coff2ae.cc create mode 100644 Sources/coff2ae.cxx delete mode 100644 Sources/cplusplus.cc create mode 100644 Sources/cplusplus.cxx delete mode 100644 Sources/elf2ae.cc create mode 100644 Sources/elf2ae.cxx delete mode 100644 Sources/i64asm.cc create mode 100644 Sources/i64asm.cxx delete mode 100644 Sources/link.cc create mode 100644 Sources/link.cxx delete mode 100644 Sources/power-cc.cc create mode 100644 Sources/power-cc.cxx delete mode 100644 Sources/ppcasm.cc create mode 100644 Sources/ppcasm.cxx (limited to 'Sources/String.cc') diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 696e195..c520968 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -1,31 +1,31 @@ { - "configurations": [ - { - "name": "Macintosh (CLang)", - "includePath": [ - "${workspaceFolder}/Comm/**", - "${workspaceFolder}/Sources/Detail/**", - "${workspaceFolder}/**" - ], - "defines": [], - "compilerPath": "/usr/bin/clang", - "cStandard": "c17", - "cppStandard": "c++20", - "intelliSenseMode": "macos-clang-arm64" - }, - { - "name": "Windows (Cygwin)", - "includePath": [ - "${workspaceFolder}/Comm/**", - "${workspaceFolder}/Sources/Detail/**", - "${workspaceFolder}/**" - ], - "defines": [], - "compilerPath": "C:/cygwin64/bin/g++.exe", - "cStandard": "c17", - "cppStandard": "c++20", - "intelliSenseMode": "windows-gcc-x64" - } - ], - "version": 4 -} \ No newline at end of file + "configurations": [ + { + "name": "Macintosh (CLang)", + "includePath": [ + "${workspaceFolder}/Headers/**", + "${workspaceFolder}/Sources/Detail/**", + "${workspaceFolder}/**" + ], + "defines": [], + "compilerPath": "/usr/bin/clang", + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "macos-clang-arm64" + }, + { + "name": "Windows (Cygwin)", + "includePath": [ + "${workspaceFolder}/Headers/**", + "${workspaceFolder}/Sources/Detail/**", + "${workspaceFolder}/**" + ], + "defines": [], + "compilerPath": "C:/cygwin64/bin/g++.exe", + "cStandard": "c17", + "cppStandard": "c++20", + "intelliSenseMode": "windows-gcc-x64" + } + ], + "version": 4 +} diff --git a/Comm/AsmKit/AsmKit.hpp b/Comm/AsmKit/AsmKit.hpp deleted file mode 100644 index 38b418c..0000000 --- a/Comm/AsmKit/AsmKit.hpp +++ /dev/null @@ -1,217 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -#include -#include -#include - -namespace CompilerKit -{ - // - // @brief Frontend to Assembly mountpoint. - // - class AssemblyInterface - { - public: - explicit AssemblyInterface() = default; - virtual ~AssemblyInterface() = default; - - MPCC_COPY_DEFAULT(AssemblyInterface); - - //@ brief compile to object file. - // 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; - - MPCC_COPY_DEFAULT(AssemblyFactory); - - public: - enum - { - kArchAMD64, - kArch32x0, - kArch64x0, - kArchRISCV, - kArchPowerPC, - 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; - - MPCC_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; - - MPCC_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_64x0__ - - class Encoder64x0 final : public EncoderInterface - { - public: - explicit Encoder64x0() = default; - ~Encoder64x0() override = default; - - MPCC_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; - - MPCC_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; - - MPCC_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 CompilerKit diff --git a/Comm/AsmKit/CPU/32x0.hpp b/Comm/AsmKit/CPU/32x0.hpp deleted file mode 100644 index 7b93a94..0000000 --- a/Comm/AsmKit/CPU/32x0.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#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]; - 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 kOpcodes32x0 = { - kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. - kAsmOpcodeDecl("br", 0b1110011, 0b001, kAsmJump) // jump to branch - kAsmOpcodeDecl("mr", 0b0100011, 0b101, kAsmImmediate) // move registers - kAsmOpcodeDecl("psh", 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 - -//////////////////////////////// diff --git a/Comm/AsmKit/CPU/64x0.hpp b/Comm/AsmKit/CPU/64x0.hpp deleted file mode 100644 index b8bafb9..0000000 --- a/Comm/AsmKit/CPU/64x0.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#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("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 - -//////////////////////////////// diff --git a/Comm/AsmKit/CPU/amd64.hpp b/Comm/AsmKit/CPU/amd64.hpp deleted file mode 100644 index 06dc1da..0000000 --- a/Comm/AsmKit/CPU/amd64.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#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; - -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 15 diff --git a/Comm/AsmKit/CPU/arm64.hpp b/Comm/AsmKit/CPU/arm64.hpp deleted file mode 100644 index 8dd5204..0000000 --- a/Comm/AsmKit/CPU/arm64.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/* ------------------------------------------- - -Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -#include - -/// @brief ARM64 encoding support. -/// @file CPU/arm64.hpp - -struct CpuOpcodeArm64; - -/// @brief ARM64 opcode header. -struct CpuOpcodeArm64 final -{ - uint8_t fOpcode; // opcode - uint8_t fRegisterLeft; // left register index - uint8_t fRegisterRight; // right register index - bool fRegisterLeftHooked; - bool fRegisterRightHooked; - uint32_t fImmediateValue; // immediate 32-bit value - bool fImmediateValueHooked; -}; diff --git a/Comm/AsmKit/CPU/ppc.hpp b/Comm/AsmKit/CPU/ppc.hpp deleted file mode 100644 index e3ea6c5..0000000 --- a/Comm/AsmKit/CPU/ppc.hpp +++ /dev/null @@ -1,1929 +0,0 @@ -/* ------------------------------------------- - - Some modifications are copyrighted under: - ZKA Technologies - - Original author: - Apple Inc - -------------------------------------------- */ - -#pragma once - -#include - -/// @note Based of: -/// https://opensource.apple.com/source/cctools/cctools-750/as/ppc-opcode.h.auto.html - -/* - * 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 optype -{ - 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 SizeType size_t - -#define VoidPtr void* -#define voidPtr VoidPtr - -#define UIntPtr uintptr_t - -#define Int64 int64_t -#define UInt64 uint64_t - -#define Int32 int -#define UInt32 unsigned - -#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 -#include -#include - -#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 MPCC_COPY_DELETE(KLASS) \ - KLASS& operator=(const KLASS&) = delete; \ - KLASS(const KLASS&) = delete; - -#define MPCC_COPY_DEFAULT(KLASS) \ - KLASS& operator=(const KLASS&) = default; \ - KLASS(const KLASS&) = default; - -#define MPCC_MOVE_DELETE(KLASS) \ - KLASS& operator=(KLASS&&) = delete; \ - KLASS(KLASS&&) = delete; - -#define MPCC_MOVE_DEFAULT(KLASS) \ - KLASS& operator=(KLASS&&) = default; \ - KLASS(KLASS&&) = default; - -#include -#include -#include -#include - -namespace CompilerKit -{ - inline constexpr int BASE_YEAR = 1900; - - inline std::string current_date() noexcept - { - 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) noexcept - { - 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; - } -} // namespace CompilerKit - -#define PACKED __attribute__((packed)) - -typedef char char_type; - -#define kObjectFileExt ".obj" -#define kBinaryFileExt ".bin" - -#define kAsmFileExts \ - { \ - ".64x", ".32x", ".masm", ".s", ".S", ".asm" \ - } - -#ifdef __NDK_MODULE__ -#define NDK_MODULE(name) int name(int argc, char** argv) -#else -#define NDK_MODULE(name) int main(int argc, char** argv) -#endif /* ifdef __NDK_MODULE__ */ - -#pragma scalar_storage_order big-endian - -#endif /* ifndef __MPCC_DEFINES_HPP__ */ diff --git a/Comm/ParserKit.hpp b/Comm/ParserKit.hpp deleted file mode 100644 index 4c3f483..0000000 --- a/Comm/ParserKit.hpp +++ /dev/null @@ -1,173 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -#include -#include - -namespace ParserKit -{ - using namespace CompilerKit; - - /// @brief Compiler backend, implements a frontend, such as C, C++... - /// See Toolchain, for some examples. - class CompilerBackend - { - public: - explicit CompilerBackend() = default; - virtual ~CompilerBackend() = default; - - MPCC_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 "Invalid Language"; - } - }; - - struct SyntaxLeafList; - struct SyntaxLeafList; - struct CompilerKeyword; - - /// we want to do that because to separate keywords. - enum KeywordKind - { - eKeywordKindNamespace, - eKeywordKindFunctionStart, - eKeywordKindFunctionEnd, - eKeywordKindVariable, - eKeywordKindVariablePtr, - eKeywordKindType, - eKeywordKindTypePtr, - eKeywordKindExpressionBegin, - eKeywordKindExpressionEnd, - eKeywordKindArgSeparator, - eKeywordKindBodyStart, - eKeywordKindBodyEnd, - eKeywordKindClass, - eKeywordKindPtrAccess, - eKeywordKindAccess, - eKeywordKindIf, - eKeywordKindElse, - eKeywordKindElseIf, - eKeywordKindVariableAssign, - eKeywordKindVariableDec, - eKeywordKindVariableInc, - eKeywordKindConstant, - eKeywordKindTypedef, - eKeywordKindEndInstr, - eKeywordKindSpecifier, - eKeywordKindInvalid, - eKeywordKindReturn, - eKeywordKindCommentInline, - eKeywordKindCommentMultiLineStart, - eKeywordKindCommentMultiLineEnd, - eKeywordKindEq, - eKeywordKindNotEq, - eKeywordKindGreaterEq, - eKeywordKindLessEq, - eKeywordKindPtr, - }; - - /// \brief Compiler keyword information struct. - struct CompilerKeyword - { - std::string keyword_name; - KeywordKind keyword_kind = eKeywordKindInvalid; - }; - struct SyntaxLeafList final - { - struct SyntaxLeaf final - { - Int32 fUserType; -#ifdef __PK_USE_STRUCT_INSTEAD__ - CompilerKeyword fUserData; -#else - std::string fUserData; -#endif - - std::string fUserValue; - struct SyntaxLeaf* fNext; - }; - - std::vector fLeafList; - SizeType fNumLeafs; - - size_t SizeOf() - { - return fNumLeafs; - } - std::vector& 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; - } -} // namespace ParserKit diff --git a/Comm/Public/SDK/CRT/__mpcc_alloca.hxx b/Comm/Public/SDK/CRT/__mpcc_alloca.hxx deleted file mode 100644 index 02b3123..0000000 --- a/Comm/Public/SDK/CRT/__mpcc_alloca.hxx +++ /dev/null @@ -1,15 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -typedef void* ptr_type; -typedef __SIZE_TYPE__ size_type; - -inline void* __mpcc_alloca_gcc(size_type sz) -{ - return __builtin_alloca(sz); -} diff --git a/Comm/Public/SDK/CRT/__mpcc_defines.hxx b/Comm/Public/SDK/CRT/__mpcc_defines.hxx deleted file mode 100644 index 19ed8a4..0000000 --- a/Comm/Public/SDK/CRT/__mpcc_defines.hxx +++ /dev/null @@ -1,83 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#ifndef __MPCC_DEF__ -#define __MPCC_DEF__ - -#ifndef __GNUC__ - -typedef __SIZE_TYPE__ size_t; - -#ifdef __LP64__ -typedef long int ssize_t; -#else -typedef int ssize_t; -#endif // __LP64__ - -typedef size_t ptrdiff_t; -typedef size_t uintptr_t; -typedef void* voidptr_t; -typedef void* any_t; -typedef char* caddr_t; - -#ifndef NULL -#define NULL ((voidptr_t)0) -#endif // !null - -#ifdef __GNUC__ -#include -#define __mpcc_alloca(sz) __mpcc_alloca_gcc(sz) -#define __packed__ __attribute__((packed)) -#elif defined(__MPCC__) -#define __packed__ __mpcc_packed__ -#define __alloca(sz) __mpcc_alloca(sz) -#endif - -#define __deref(ptr) (*(ptr)) - -#ifdef __cplusplus -#define __init_decl() \ - extern "C" \ - { - - -#define __fini_decl() \ - }; \ - - -#else -#define __init_decl() -#define __fini_decl() -#endif - -typedef long long off_t; -typedef unsigned long long uoff_t; - -typedef union float_cast { - struct - { - unsigned int mantissa : 23; - unsigned int exponent : 8; - unsigned int sign : 1; - }; - - float f; -} __packed__ float_cast_t; - -typedef union double_cast { - struct - { - unsigned long long int mantissa : 52; - unsigned int exponent : 11; - unsigned int sign : 1; - }; - - double f; -} __packed__ double_cast_t; - -#endif // ifndef __GNUC__ - -#endif /* __MPCC_DEF__ */ diff --git a/Comm/Public/SDK/CRT/__mpcc_exception.hxx b/Comm/Public/SDK/CRT/__mpcc_exception.hxx deleted file mode 100644 index 4a9f84a..0000000 --- a/Comm/Public/SDK/CRT/__mpcc_exception.hxx +++ /dev/null @@ -1,27 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -/// This file is an implementation of __throw* family of functions. - -#include -#include -#include - -namespace std -{ - inline void __throw_general(void) - { - throw std::runtime_error("MPCC C++ Runtime error."); - } - - inline void __throw_domain_error(const char* error) - { - std::cout << "MPCC C++: Domain error: " << error << "\r"; - __throw_general(); - } -} // namespace std diff --git a/Comm/Public/SDK/CRT/__mpcc_hint.hxx b/Comm/Public/SDK/CRT/__mpcc_hint.hxx deleted file mode 100644 index 02dbc94..0000000 --- a/Comm/Public/SDK/CRT/__mpcc_hint.hxx +++ /dev/null @@ -1,20 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -#pragma compiler(hint_manifest) - -#define _Input -#define _Output - -#define _Optional - -#define _StrictCheckInput -#define _StrictCheckOutput - -#define _InOut -#define _StrictInOut diff --git a/Comm/Public/SDK/CRT/__mpcc_malloc.hxx b/Comm/Public/SDK/CRT/__mpcc_malloc.hxx deleted file mode 100644 index eeaa67b..0000000 --- a/Comm/Public/SDK/CRT/__mpcc_malloc.hxx +++ /dev/null @@ -1,30 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -#include - -namespace stdx -{ - /// @brief allocate a new class. - /// @tparam KindClass the class type to allocate. - template - inline void* allocate(Args&&... args) - { - return new KindClass(std::forward(args)...); - } - - /// @brief free a class. - /// @tparam KindClass the class type to allocate. - template - inline void release(KindClass ptr) - { - if (!ptr) - return; - delete ptr; - } -} // namespace stdx diff --git a/Comm/Public/SDK/CRT/__mpcc_power.inc b/Comm/Public/SDK/CRT/__mpcc_power.inc deleted file mode 100644 index 9e4928c..0000000 --- a/Comm/Public/SDK/CRT/__mpcc_power.inc +++ /dev/null @@ -1,35 +0,0 @@ -# Path: SDK/__mpcc_power.inc -# Language: MPCC POWER Assembly support for GNU. -# Build Date: 2024-6-4 - -%ifdef __CODETOOLS__ - -%def lda li -%def sta stw -%def ldw li - -%def r0 0 -%def r1 1 -%def r2 2 -%def r3 3 -%def r4 4 -%def r5 5 -%def r6 6 -%def r7 7 -%def r8 8 -%def r9 9 -%def r10 10 -%def r11 11 -%def r12 12 -%def r13 13 -%def r14 14 -%def r15 15 -%def r16 16 -%def r17 17 -%def r18 18 -%def r19 19 -%def r20 20 - -%endif - -%def nop mr 0, 0 diff --git a/Comm/StdKit/AE.hpp b/Comm/StdKit/AE.hpp deleted file mode 100644 index ee39e56..0000000 --- a/Comm/StdKit/AE.hpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * ======================================================== - * - * MPCC - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include - -#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; - 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 CompilerKit - -// 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 -{ - /** - * @brief AE Reader protocol - * - */ - class AEReadableProtocol final - { - public: - std::ifstream FP; - - public: - explicit AEReadableProtocol() = default; - ~AEReadableProtocol() = default; - - MPCC_COPY_DELETE(AEReadableProtocol); - - /** - * @brief Read AE record - * - * @param raw the containing buffer - * @param sz it's size (without sizeof(AERecordHeader) added to it.) - * @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 CompilerKit::Utils diff --git a/Comm/StdKit/ELF.hpp b/Comm/StdKit/ELF.hpp deleted file mode 100644 index 4f0d0ae..0000000 --- a/Comm/StdKit/ELF.hpp +++ /dev/null @@ -1,389 +0,0 @@ -#pragma once - -#include -#include - -struct file; - -#ifndef elf_read_implies_exec -/* Executables for which elf_read_implies_exec() returns TRUE will - have the READ_IMPLIES_EXEC personality flag set automatically. - Override in asm/elf.h as needed. */ -#define elf_read_implies_exec(ex, have_pt_gnu_stack) 0 -#endif - -/* 32-bit ELF base types. */ -typedef uint32_t Elf32_Addr; -typedef uint16_t Elf32_Half; -typedef uint32_t Elf32_Off; -typedef int32_t Elf32_Sword; -typedef uint32_t Elf32_Word; - -/* 64-bit ELF base types. */ -typedef uintptr_t Elf64_Addr; -typedef uint16_t Elf64_Half; -typedef int16_t Elf64_SHalf; -typedef uint64_t Elf64_Off; -typedef int32_t Elf64_Sword; -typedef uint32_t Elf64_Word; -typedef uint64_t Elf64_Xword; -typedef int64_t Elf64_Sxword; - -/* These constants are for the segment types stored in the image headers */ -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_TLS 7 /* Thread local storage segment */ -#define PT_LOOS 0x60000000 /* OS-specific */ -#define PT_HIOS 0x6fffffff /* OS-specific */ -#define PT_LOPROC 0x70000000 -#define PT_HIPROC 0x7fffffff -#define PT_GNU_EH_FRAME 0x6474e550 - -#define PT_GNU_STACK (PT_LOOS + 0x474e551) - -/* These constants define the different elf file types */ -#define ET_NONE 0 -#define ET_REL 1 -#define ET_EXEC 2 -#define ET_DYN 3 -#define ET_CORE 4 -#define ET_LOPROC 0xff00 -#define ET_HIPROC 0xffff - -/* This is the info that is needed to parse the dynamic section of the file */ -#define DT_NULL 0 -#define DT_NEEDED 1 -#define DT_PLTRELSZ 2 -#define DT_PLTGOT 3 -#define DT_HASH 4 -#define DT_STRTAB 5 -#define DT_SYMTAB 6 -#define DT_RELA 7 -#define DT_RELASZ 8 -#define DT_RELAENT 9 -#define DT_STRSZ 10 -#define DT_SYMENT 11 -#define DT_INIT 12 -#define DT_FINI 13 -#define DT_SONAME 14 -#define DT_RPATH 15 -#define DT_SYMBOLIC 16 -#define DT_REL 17 -#define DT_RELSZ 18 -#define DT_RELENT 19 -#define DT_PLTREL 20 -#define DT_DEBUG 21 -#define DT_TEXTREL 22 -#define DT_JMPREL 23 -#define DT_ENCODING 32 -#define OLD_DT_LOOS 0x60000000 -#define DT_LOOS 0x6000000d -#define DT_HIOS 0x6ffff000 -#define DT_VALRNGLO 0x6ffffd00 -#define DT_VALRNGHI 0x6ffffdff -#define DT_ADDRRNGLO 0x6ffffe00 -#define DT_ADDRRNGHI 0x6ffffeff -#define DT_VERSYM 0x6ffffff0 -#define DT_RELACOUNT 0x6ffffff9 -#define DT_RELCOUNT 0x6ffffffa -#define DT_FLAGS_1 0x6ffffffb -#define DT_VERDEF 0x6ffffffc -#define DT_VERDEFNUM 0x6ffffffd -#define DT_VERNEED 0x6ffffffe -#define DT_VERNEEDNUM 0x6fffffff -#define OLD_DT_HIOS 0x6fffffff -#define DT_LOPROC 0x70000000 -#define DT_HIPROC 0x7fffffff - -/* This info is needed when parsing the symbol table */ -#define STB_LOCAL 0 -#define STB_GLOBAL 1 -#define STB_WEAK 2 - -#define STT_NOTYPE 0 -#define STT_OBJECT 1 -#define STT_FUNC 2 -#define STT_SECTION 3 -#define STT_FILE 4 -#define STT_COMMON 5 -#define STT_TLS 6 - -#define ELF_ST_BIND(x) ((x) >> 4) -#define ELF_ST_TYPE(x) (((unsigned int)x) & 0xf) -#define ELF32_ST_BIND(x) ELF_ST_BIND(x) -#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) -#define ELF64_ST_BIND(x) ELF_ST_BIND(x) -#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x) - -typedef struct dynamic -{ - Elf32_Sword d_tag; - union { - Elf32_Sword d_val; - Elf32_Addr d_ptr; - } d_un; -} Elf32_Dyn; - -typedef struct -{ - Elf64_Sxword d_tag; /* entry tag value */ - union { - Elf64_Xword d_val; - Elf64_Addr d_ptr; - } d_un; -} Elf64_Dyn; - -/* The following are used with relocations */ -#define ELF32_R_SYM(x) ((x) >> 8) -#define ELF32_R_TYPE(x) ((x)&0xff) - -#define ELF64_R_SYM(i) ((i) >> 32) -#define ELF64_R_TYPE(i) ((i)&0xffffffff) - -typedef struct elf32_rel -{ - Elf32_Addr r_offset; - Elf32_Word r_info; -} Elf32_Rel; - -typedef struct elf64_rel -{ - Elf64_Addr r_offset; /* Location at which to apply the action */ - Elf64_Xword r_info; /* index and type of relocation */ -} Elf64_Rel; - -typedef struct elf32_rela -{ - Elf32_Addr r_offset; - Elf32_Word r_info; - Elf32_Sword r_addend; -} Elf32_Rela; - -typedef struct elf64_rela -{ - Elf64_Addr r_offset; /* Location at which to apply the action */ - Elf64_Xword r_info; /* index and type of relocation */ - Elf64_Sxword r_addend; /* Constant addend used to compute value */ -} Elf64_Rela; - -typedef struct elf32_sym -{ - Elf32_Word st_name; - Elf32_Addr st_value; - Elf32_Word st_size; - unsigned char st_info; - unsigned char st_other; - Elf32_Half st_shndx; -} Elf32_Sym; - -typedef struct elf64_sym -{ - Elf64_Word st_name; /* Symbol name, index in string tbl */ - unsigned char st_info; /* Type and binding attributes */ - unsigned char st_other; /* No defined meaning, 0 */ - Elf64_Half st_shndx; /* Associated section index */ - Elf64_Addr st_value; /* Value of the symbol */ - Elf64_Xword st_size; /* Associated symbol size */ -} Elf64_Sym; - -#define EI_NIDENT 16 - -typedef struct elf32_hdr -{ - unsigned char e_ident[EI_NIDENT]; - Elf32_Half e_type; - Elf32_Half e_machine; - Elf32_Word e_version; - Elf32_Addr e_entry; /* Entry point */ - Elf32_Off e_phoff; - Elf32_Off e_shoff; - Elf32_Word e_flags; - Elf32_Half e_ehsize; - Elf32_Half e_phentsize; - Elf32_Half e_phnum; - Elf32_Half e_shentsize; - Elf32_Half e_shnum; - Elf32_Half e_shstrndx; -} Elf32_Ehdr; - -typedef struct elf64_hdr -{ - unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ - Elf64_Half e_type; - Elf64_Half e_machine; - Elf64_Word e_version; - Elf64_Addr e_entry; /* Entry point virtual address */ - Elf64_Off e_phoff; /* Program header table file offset */ - Elf64_Off e_shoff; /* Section header table file offset */ - Elf64_Word e_flags; - Elf64_Half e_ehsize; - Elf64_Half e_phentsize; - Elf64_Half e_phnum; - Elf64_Half e_shentsize; - Elf64_Half e_shnum; - Elf64_Half e_shstrndx; -} Elf64_Ehdr; - -/* These constants define the permissions on sections in the program - header, p_flags. */ -#define PF_R 0x4 -#define PF_W 0x2 -#define PF_X 0x1 - -typedef struct elf32_phdr -{ - Elf32_Word p_type; - Elf32_Off p_offset; - Elf32_Addr p_vaddr; - Elf32_Addr p_paddr; - Elf32_Word p_filesz; - Elf32_Word p_memsz; - Elf32_Word p_flags; - Elf32_Word p_align; -} Elf32_Phdr; - -typedef struct elf64_phdr -{ - Elf64_Word p_type; - Elf64_Word p_flags; - Elf64_Off p_offset; /* Segment file offset */ - Elf64_Addr p_vaddr; /* Segment virtual address */ - Elf64_Addr p_paddr; /* Segment physical address */ - Elf64_Xword p_filesz; /* Segment size in file */ - Elf64_Xword p_memsz; /* Segment size in memory */ - Elf64_Xword p_align; /* Segment alignment, file & memory */ -} Elf64_Phdr; - -/* sh_type */ -#define SHT_NULL 0 -#define SHT_PROGBITS 1 -#define SHT_SYMTAB 2 -#define SHT_STRTAB 3 -#define SHT_RELA 4 -#define SHT_HASH 5 -#define SHT_DYNAMIC 6 -#define SHT_NOTE 7 -#define SHT_NOBITS 8 -#define SHT_REL 9 -#define SHT_SHLIB 10 -#define SHT_DYNSYM 11 -#define SHT_NUM 12 -#define SHT_LOPROC 0x70000000 -#define SHT_HIPROC 0x7fffffff -#define SHT_LOUSER 0x80000000 -#define SHT_HIUSER 0xffffffff - -/* sh_flags */ -#define SHF_WRITE 0x1 -#define SHF_ALLOC 0x2 -#define SHF_EXECINSTR 0x4 -#define SHF_MASKPROC 0xf0000000 - -/* special section indexes */ -#define SHN_UNDEF 0 -#define SHN_LORESERVE 0xff00 -#define SHN_LOPROC 0xff00 -#define SHN_HIPROC 0xff1f -#define SHN_ABS 0xfff1 -#define SHN_COMMON 0xfff2 -#define SHN_HIRESERVE 0xffff - -typedef struct -{ - Elf32_Word sh_name; - Elf32_Word sh_type; - Elf32_Word sh_flags; - Elf32_Addr sh_addr; - Elf32_Off sh_offset; - Elf32_Word sh_size; - Elf32_Word sh_link; - Elf32_Word sh_info; - Elf32_Word sh_addralign; - Elf32_Word sh_entsize; -} Elf32_Shdr; - -typedef struct elf64_shdr -{ - Elf64_Word sh_name; /* Section name, index in string tbl */ - Elf64_Word sh_type; /* Type of section */ - Elf64_Xword sh_flags; /* Miscellaneous section attributes */ - Elf64_Addr sh_addr; /* Section virtual addr at execution */ - Elf64_Off sh_offset; /* Section file offset */ - Elf64_Xword sh_size; /* Size of section in bytes */ - Elf64_Word sh_link; /* Index of another section */ - Elf64_Word sh_info; /* Additional section information */ - Elf64_Xword sh_addralign; /* Section alignment */ - Elf64_Xword sh_entsize; /* Entry size if section holds table */ -} Elf64_Shdr; - -#define EI_MAG0 0 /* e_ident[] indexes */ -#define EI_MAG1 1 -#define EI_MAG2 2 -#define EI_MAG3 3 -#define EI_CLASS 4 -#define EI_DATA 5 -#define EI_VERSION 6 -#define EI_OSABI 7 -#define EI_PAD 8 - -#define ELFMAG0 0x7f /* EI_MAG */ -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' -#define ELFMAG "\177ELF" -#define SELFMAG 4 - -#define ELFCLASSNONE 0 /* EI_CLASS */ -#define ELFCLASS32 1 -#define ELFCLASS64 2 -#define ELFCLASSNUM 3 - -#define ELFDATANONE 0 /* e_ident[EI_DATA] */ -#define ELFDATA2LSB 1 -#define ELFDATA2MSB 2 - -#define EV_NONE 0 /* e_version, EI_VERSION */ -#define EV_CURRENT 1 -#define EV_NUM 2 - -#define ELFOSABI_NONE 0 -#define ELFOSABI_LINUX 3 - -#ifndef ELF_OSABI -#define ELF_OSABI ELFOSABI_NONE -#endif - -/* Notes used in ET_CORE */ -#define NT_PRSTATUS 1 -#define NT_PRFPREG 2 -#define NT_PRPSINFO 3 -#define NT_TASKSTRUCT 4 -#define NT_AUXV 6 -#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ -#define NT_PPC_VMX 0x100 /* POWER Altivec/VMX registers */ -#define NT_PPC_SPE 0x101 /* POWER SPE/EVR registers */ -#define NT_PPC_VSX 0x102 /* POWER VSX registers */ -#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ -#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ -#define NT_PRXSTATUS 0x300 /* s390 upper register halves */ - -/* Note header in a PT_NOTE section */ -typedef struct elf32_note -{ - Elf32_Word n_namesz; /* Name size */ - Elf32_Word n_descsz; /* Content size */ - Elf32_Word n_type; /* Content type */ -} Elf32_Nhdr; - -/* Note header in a PT_NOTE section */ -typedef struct elf64_note -{ - Elf64_Word n_namesz; /* Name size */ - Elf64_Word n_descsz; /* Content size */ - Elf64_Word n_type; /* Content type */ -} Elf64_Nhdr; diff --git a/Comm/StdKit/ErrorID.hpp b/Comm/StdKit/ErrorID.hpp deleted file mode 100644 index abaac85..0000000 --- a/Comm/StdKit/ErrorID.hpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * ======================================================== - * - * CompilerKit - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -#define MPCC_EXEC_ERROR -30 -#define MPCC_FILE_NOT_FOUND -31 -#define MPCC_DIR_NOT_FOUND -32 -#define MPCC_FILE_EXISTS -33 -#define MPCC_TOO_LONG -34 -#define MPCC_INVALID_DATA -35 -#define MPCC_UNIMPLEMENTED -36 -#define MPCC_FAT_ERROR -37 diff --git a/Comm/StdKit/ErrorOr.hpp b/Comm/StdKit/ErrorOr.hpp deleted file mode 100644 index 4097cc9..0000000 --- a/Comm/StdKit/ErrorOr.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * ======================================================== - * - * CompilerKit - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -namespace CompilerKit -{ - 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 CompilerKit diff --git a/Comm/StdKit/PEF.hpp b/Comm/StdKit/PEF.hpp deleted file mode 100644 index 85044b2..0000000 --- a/Comm/StdKit/PEF.hpp +++ /dev/null @@ -1,133 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#pragma once - -#include - -// @file PEF.hpp -// @brief Preferred Executable Format - -#define kPefMagic "Joy!" -#define kPefMagicFat "yoJ!" - -#define kPefExt ".exec" -#define kPefDylibExt ".lib" -#define kPefLibExt ".slib" -#define kPefObjectExt ".obj" -#define kPefDebugExt ".dbg" - -#define kPefMagicLen 5 - -#define kPefVersion 2 -#define kPefNameLen 255 - -#define kPefBaseOrigin (0x1000000) - -#define kPefStart "__ImageStart" - -namespace CompilerKit -{ - enum - { - kPefArchIntel86S = 100, - kPefArchAMD64, - kPefArchRISCV, - kPefArch64000, /* 64x0 RISC architecture. */ - kPefArch32000, - kPefArchPowerPC, /* 64-bit POWER architecture. */ - kPefArchARM64, - kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1, - kPefArchInvalid = 0xFF, - }; - - enum - { - kPefSubArchAMD, - kPefSubArchIntel, - kPefSubArchGeneric, - kPefSubArchIBM, - }; - - enum - { - kPefKindExec = 1, /* .exe */ - kPefKindSharedObject = 2, /* .lib */ - 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; - - /* 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; - - enum - { - kPefCode = 0xC, - kPefData = 0xD, - kPefZero = 0xE, - kPefLinkerID = 0x1, - kPefCount = 4, - kPefInvalid = 0xFF, - }; -} // namespace CompilerKit - -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/Comm/StdKit/Ref.hpp b/Comm/StdKit/Ref.hpp deleted file mode 100644 index e655ccb..0000000 --- a/Comm/StdKit/Ref.hpp +++ /dev/null @@ -1,91 +0,0 @@ - -/* - * ======================================================== - * - * CompilerKit - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -namespace CompilerKit -{ - // @author ZKA Technologies - // @brief Reference class, refers to a pointer of data in static memory. - template - 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 - class NonNullRef final - { - public: - NonNullRef() = delete; - NonNullRef(nullPtr) = 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 CompilerKit diff --git a/Comm/StdKit/String.hpp b/Comm/StdKit/String.hpp deleted file mode 100644 index 7e62bc5..0000000 --- a/Comm/StdKit/String.hpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * ======================================================== - * - * CompilerKit - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -namespace CompilerKit -{ - /** - * @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 char[Sz]; - assert(m_Data); - } - - ~StringView() noexcept - { - if (m_Data) - { - memset(m_Data, 0, m_Sz); - delete[] m_Data; - - m_Data = nullptr; - } - } - - MPCC_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: - char* 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 CompilerKit diff --git a/Comm/StdKit/XCOFF.hxx b/Comm/StdKit/XCOFF.hxx deleted file mode 100644 index 4b25484..0000000 --- a/Comm/StdKit/XCOFF.hxx +++ /dev/null @@ -1,41 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - - File: XCOFF.hpp - Purpose: XCOFF for NewOS. - - 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 CompilerKit -{ - /// @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 CompilerKit - -#endif // ifndef __XCOFF__ diff --git a/Comm/UUID.hpp b/Comm/UUID.hpp deleted file mode 100644 index 00b153b..0000000 --- a/Comm/UUID.hpp +++ /dev/null @@ -1,983 +0,0 @@ -#ifndef STDUUID_H -#define STDUUID_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus - -#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) -#define LIBUUID_CPP20_OR_GREATER -#endif - -#endif - -#ifdef LIBUUID_CPP20_OR_GREATER -#include -#else -#include -#endif - -#ifdef _WIN32 - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#ifdef UUID_SYSTEM_GENERATOR -#include -#endif - -#ifdef UUID_TIME_GENERATOR -#include -#pragma comment(lib, "IPHLPAPI.lib") -#endif - -#elif defined(__linux__) || defined(__unix__) - -#ifdef UUID_SYSTEM_GENERATOR -#include -#endif - -#elif defined(__APPLE__) - -#ifdef UUID_SYSTEM_GENERATOR -#include -#endif - -#endif - -namespace uuids -{ -#ifdef __cpp_lib_span - template - using span = std::span; -#else - template - using span = gsl::span; -#endif - - namespace detail - { - template - [[nodiscard]] constexpr inline unsigned char hex2char(TChar const ch) noexcept - { - if (ch >= static_cast('0') && ch <= static_cast('9')) - return static_cast(ch - static_cast('0')); - if (ch >= static_cast('a') && ch <= static_cast('f')) - return static_cast(10 + ch - static_cast('a')); - if (ch >= static_cast('A') && ch <= static_cast('F')) - return static_cast(10 + ch - static_cast('A')); - return 0; - } - - template - [[nodiscard]] constexpr inline bool is_hex(TChar const ch) noexcept - { - return (ch >= static_cast('0') && ch <= static_cast('9')) || - (ch >= static_cast('a') && ch <= static_cast('f')) || - (ch >= static_cast('A') && ch <= static_cast('F')); - } - - template - [[nodiscard]] constexpr std::basic_string_view to_string_view( - TChar const* str) noexcept - { - if (str) - return str; - return {}; - } - - template - [[nodiscard]] constexpr std::basic_string_view - to_string_view(StringType const& str) noexcept - { - return str; - } - - class sha1 - { - public: - using digest32_t = uint32_t[5]; - using digest8_t = uint8_t[20]; - - static constexpr unsigned int block_bytes = 64; - - [[nodiscard]] inline static uint32_t left_rotate( - uint32_t value, size_t const count) noexcept - { - return (value << count) ^ (value >> (32 - count)); - } - - sha1() - { - reset(); - } - - void reset() noexcept - { - m_digest[0] = 0x67452301; - m_digest[1] = 0xEFCDAB89; - m_digest[2] = 0x98BADCFE; - m_digest[3] = 0x10325476; - m_digest[4] = 0xC3D2E1F0; - m_blockByteIndex = 0; - m_byteCount = 0; - } - - void process_byte(uint8_t octet) - { - this->m_block[this->m_blockByteIndex++] = octet; - ++this->m_byteCount; - if (m_blockByteIndex == block_bytes) - { - this->m_blockByteIndex = 0; - process_block(); - } - } - - void process_block(void const* const start, void const* const end) - { - const uint8_t* begin = static_cast(start); - const uint8_t* finish = static_cast(end); - while (begin != finish) - { - process_byte(*begin); - begin++; - } - } - - void process_bytes(void const* const data, size_t const len) - { - const uint8_t* block = static_cast(data); - process_block(block, block + len); - } - - uint32_t const* get_digest(digest32_t digest) - { - size_t const bitCount = this->m_byteCount * 8; - process_byte(0x80); - if (this->m_blockByteIndex > 56) - { - while (m_blockByteIndex != 0) - { - process_byte(0); - } - while (m_blockByteIndex < 56) - { - process_byte(0); - } - } - else - { - while (m_blockByteIndex < 56) - { - process_byte(0); - } - } - process_byte(0); - process_byte(0); - process_byte(0); - process_byte(0); - process_byte(static_cast((bitCount >> 24) & 0xFF)); - process_byte(static_cast((bitCount >> 16) & 0xFF)); - process_byte(static_cast((bitCount >> 8) & 0xFF)); - process_byte(static_cast((bitCount)&0xFF)); - - memcpy(digest, m_digest, 5 * sizeof(uint32_t)); - return digest; - } - - uint8_t const* get_digest_bytes(digest8_t digest) - { - digest32_t d32; - get_digest(d32); - size_t di = 0; - digest[di++] = static_cast(d32[0] >> 24); - digest[di++] = static_cast(d32[0] >> 16); - digest[di++] = static_cast(d32[0] >> 8); - digest[di++] = static_cast(d32[0] >> 0); - - digest[di++] = static_cast(d32[1] >> 24); - digest[di++] = static_cast(d32[1] >> 16); - digest[di++] = static_cast(d32[1] >> 8); - digest[di++] = static_cast(d32[1] >> 0); - - digest[di++] = static_cast(d32[2] >> 24); - digest[di++] = static_cast(d32[2] >> 16); - digest[di++] = static_cast(d32[2] >> 8); - digest[di++] = static_cast(d32[2] >> 0); - - digest[di++] = static_cast(d32[3] >> 24); - digest[di++] = static_cast(d32[3] >> 16); - digest[di++] = static_cast(d32[3] >> 8); - digest[di++] = static_cast(d32[3] >> 0); - - digest[di++] = static_cast(d32[4] >> 24); - digest[di++] = static_cast(d32[4] >> 16); - digest[di++] = static_cast(d32[4] >> 8); - digest[di++] = static_cast(d32[4] >> 0); - - return digest; - } - - private: - void process_block() - { - uint32_t w[80]; - for (size_t i = 0; i < 16; i++) - { - w[i] = static_cast(m_block[i * 4 + 0] << 24); - w[i] |= static_cast(m_block[i * 4 + 1] << 16); - w[i] |= static_cast(m_block[i * 4 + 2] << 8); - w[i] |= static_cast(m_block[i * 4 + 3]); - } - for (size_t i = 16; i < 80; i++) - { - w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1); - } - - uint32_t a = m_digest[0]; - uint32_t b = m_digest[1]; - uint32_t c = m_digest[2]; - uint32_t d = m_digest[3]; - uint32_t e = m_digest[4]; - - for (std::size_t i = 0; i < 80; ++i) - { - uint32_t f = 0; - uint32_t k = 0; - - if (i < 20) - { - f = (b & c) | (~b & d); - k = 0x5A827999; - } - else if (i < 40) - { - f = b ^ c ^ d; - k = 0x6ED9EBA1; - } - else if (i < 60) - { - f = (b & c) | (b & d) | (c & d); - k = 0x8F1BBCDC; - } - else - { - f = b ^ c ^ d; - k = 0xCA62C1D6; - } - uint32_t temp = left_rotate(a, 5) + f + e + k + w[i]; - e = d; - d = c; - c = left_rotate(b, 30); - b = a; - a = temp; - } - - m_digest[0] += a; - m_digest[1] += b; - m_digest[2] += c; - m_digest[3] += d; - m_digest[4] += e; - } - - private: - digest32_t m_digest; - uint8_t m_block[64]; - size_t m_blockByteIndex; - size_t m_byteCount; - }; - - template - inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000"; - - template <> - inline constexpr wchar_t empty_guid[37] = - L"00000000-0000-0000-0000-000000000000"; - - template - inline constexpr CharT guid_encoder[17] = "0123456789abcdef"; - - template <> - inline constexpr wchar_t guid_encoder[17] = L"0123456789abcdef"; - } // namespace detail - - // -------------------------------------------------------------------------------------------------------------------------- - // UUID format https://tools.ietf.org/html/rfc4122 - // -------------------------------------------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------------------------------------------- - // Field NDR Data Type Octet # Note - // -------------------------------------------------------------------------------------------------------------------------- - // time_low unsigned long 0 - 3 The low field - // of the timestamp. time_mid unsigned short 4 - 5 - // The middle field of the timestamp. time_hi_and_version unsigned - // short 6 - 7 The high field of the timestamp multiplexed - // with the version number. clock_seq_hi_and_reserved unsigned small 8 - // The high field of the clock sequence multiplexed with the variant. - // clock_seq_low unsigned small 9 The low - // field of the clock sequence. node character 10 - // - 15 The spatially unique node identifier. - // -------------------------------------------------------------------------------------------------------------------------- - // 0 1 2 3 - // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | time_low | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | time_mid | time_hi_and_version | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // |clk_seq_hi_res | clk_seq_low | node (0-1) | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - // | node (2-5) | - // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - // -------------------------------------------------------------------------------------------------------------------------- - // enumerations - // -------------------------------------------------------------------------------------------------------------------------- - - // indicated by a bit pattern in octet 8, marked with N in - // xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx - enum class uuid_variant - { - // NCS backward compatibility (with the obsolete Apollo Network Computing - // System 1.5 UUID format) N bit pattern: 0xxx > the first 6 octets of the - // UUID are a 48-bit timestamp (the number of 4 microsecond units of time - // since 1 Jan 1980 UTC); > the next 2 octets are reserved; > the next octet - // is the "address family"; > the final 7 octets are a 56-bit host ID in the - // form specified by the address family - ncs, - - // RFC 4122/DCE 1.1 - // N bit pattern: 10xx - // > big-endian byte order - rfc, - - // Microsoft Corporation backward compatibility - // N bit pattern: 110x - // > little endian byte order - // > formely used in the Component Object Model (COM) library - microsoft, - - // reserved for possible future definition - // N bit pattern: 111x - reserved - }; - - // indicated by a bit pattern in octet 6, marked with M in - // xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx - enum class uuid_version - { - none = 0, // only possible for nil or invalid uuids - time_based = 1, // The time-based version specified in RFC 4122 - dce_security = 2, // DCE Security version, with embedded POSIX UIDs. - name_based_md5 = - 3, // The name-based version specified in RFS 4122 with MD5 hashing - random_number_based = 4, // The randomly or pseudo-randomly generated version - // specified in RFS 4122 - name_based_sha1 = - 5 // The name-based version specified in RFS 4122 with SHA1 hashing - }; - - // Forward declare uuid & to_string so that we can declare to_string as a friend - // later. - class uuid; - template , class Allocator = std::allocator> - std::basic_string to_string(uuid const& id); - - // -------------------------------------------------------------------------------------------------------------------------- - // uuid class - // -------------------------------------------------------------------------------------------------------------------------- - class uuid - { - public: - using value_type = uint8_t; - - constexpr uuid() noexcept = default; - - uuid(value_type (&arr)[16]) noexcept - { - std::copy(std::cbegin(arr), std::cend(arr), std::begin(data)); - } - - constexpr uuid(std::array const& arr) noexcept - : data{arr} - { - } - - explicit uuid(span bytes) - { - std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data)); - } - - template - explicit uuid(ForwardIterator first, ForwardIterator last) - { - if (std::distance(first, last) == 16) - std::copy(first, last, std::begin(data)); - } - - [[nodiscard]] constexpr uuid_variant variant() const noexcept - { - if ((data[8] & 0x80) == 0x00) - return uuid_variant::ncs; - else if ((data[8] & 0xC0) == 0x80) - return uuid_variant::rfc; - else if ((data[8] & 0xE0) == 0xC0) - return uuid_variant::microsoft; - else - return uuid_variant::reserved; - } - - [[nodiscard]] constexpr uuid_version version() const noexcept - { - if ((data[6] & 0xF0) == 0x10) - return uuid_version::time_based; - else if ((data[6] & 0xF0) == 0x20) - return uuid_version::dce_security; - else if ((data[6] & 0xF0) == 0x30) - return uuid_version::name_based_md5; - else if ((data[6] & 0xF0) == 0x40) - return uuid_version::random_number_based; - else if ((data[6] & 0xF0) == 0x50) - return uuid_version::name_based_sha1; - else - return uuid_version::none; - } - - [[nodiscard]] constexpr bool is_nil() const noexcept - { - for (size_t i = 0; i < data.size(); ++i) - if (data[i] != 0) - return false; - return true; - } - - void swap(uuid& other) noexcept - { - data.swap(other.data); - } - - [[nodiscard]] inline span as_bytes() const - { - return span( - reinterpret_cast(data.data()), 16); - } - - template - [[nodiscard]] constexpr static bool is_valid_uuid( - StringType const& in_str) noexcept - { - auto str = detail::to_string_view(in_str); - bool firstDigit = true; - size_t hasBraces = 0; - size_t index = 0; - - if (str.empty()) - return false; - - if (str.front() == '{') - hasBraces = 1; - if (hasBraces && str.back() != '}') - return false; - - for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) - { - if (str[i] == '-') - continue; - - if (index >= 16 || !detail::is_hex(str[i])) - { - return false; - } - - if (firstDigit) - { - firstDigit = false; - } - else - { - index++; - firstDigit = true; - } - } - - if (index < 16) - { - return false; - } - - return true; - } - - template - [[nodiscard]] constexpr static std::optional from_string( - StringType const& in_str) noexcept - { - auto str = detail::to_string_view(in_str); - bool firstDigit = true; - size_t hasBraces = 0; - size_t index = 0; - - std::array data{{0}}; - - if (str.empty()) - return {}; - - if (str.front() == '{') - hasBraces = 1; - if (hasBraces && str.back() != '}') - return {}; - - for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) - { - if (str[i] == '-') - continue; - - if (index >= 16 || !detail::is_hex(str[i])) - { - return {}; - } - - if (firstDigit) - { - data[index] = static_cast(detail::hex2char(str[i]) << 4); - firstDigit = false; - } - else - { - data[index] = - static_cast(data[index] | detail::hex2char(str[i])); - index++; - firstDigit = true; - } - } - - if (index < 16) - { - return {}; - } - - return uuid{data}; - } - - private: - std::array data{{0}}; - - friend bool operator==(uuid const& lhs, uuid const& rhs) noexcept; - friend bool operator<(uuid const& lhs, uuid const& rhs) noexcept; - - template - friend std::basic_ostream& operator<<( - std::basic_ostream& s, uuid const& id); - - template - friend std::basic_string to_string(uuid const& id); - - friend std::hash; - }; - - // -------------------------------------------------------------------------------------------------------------------------- - // operators and non-member functions - // -------------------------------------------------------------------------------------------------------------------------- - - [[nodiscard]] inline bool operator==(uuid const& lhs, - uuid const& rhs) noexcept - { - return lhs.data == rhs.data; - } - - [[nodiscard]] inline bool operator!=(uuid const& lhs, - uuid const& rhs) noexcept - { - return !(lhs == rhs); - } - - [[nodiscard]] inline bool operator<(uuid const& lhs, uuid const& rhs) noexcept - { - return lhs.data < rhs.data; - } - - template - [[nodiscard]] inline std::basic_string to_string( - uuid const& id) - { - std::basic_string uustr{detail::empty_guid}; - - for (size_t i = 0, index = 0; i < 36; ++i) - { - if (i == 8 || i == 13 || i == 18 || i == 23) - { - continue; - } - uustr[i] = detail::guid_encoder[id.data[index] >> 4 & 0x0f]; - uustr[++i] = detail::guid_encoder[id.data[index] & 0x0f]; - index++; - } - - return uustr; - } - - template - std::basic_ostream& operator<<( - std::basic_ostream& s, uuid const& id) - { - s << to_string(id); - return s; - } - - inline void swap(uuids::uuid& lhs, uuids::uuid& rhs) noexcept - { - lhs.swap(rhs); - } - - // -------------------------------------------------------------------------------------------------------------------------- - // namespace IDs that could be used for generating name-based uuids - // -------------------------------------------------------------------------------------------------------------------------- - - // Name string is a fully-qualified domain name - static uuid uuid_namespace_dns{{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // Name string is a URL - static uuid uuid_namespace_url{{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // Name string is an ISO OID (See https://oidref.com/, - // https://en.wikipedia.org/wiki/Object_identifier) - static uuid uuid_namespace_oid{{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // Name string is an X.500 DN, in DER or a text output format (See - // https://en.wikipedia.org/wiki/X.500, - // https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One) - static uuid uuid_namespace_x500{{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, - 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, - 0xc8}}; - - // -------------------------------------------------------------------------------------------------------------------------- - // uuid generators - // -------------------------------------------------------------------------------------------------------------------------- - -#ifdef UUID_SYSTEM_GENERATOR - class uuid_system_generator - { - public: - using result_type = uuid; - - uuid operator()() - { -#ifdef _WIN32 - - GUID newId; - HRESULT hr = ::CoCreateGuid(&newId); - - if (FAILED(hr)) - { - throw std::system_error(hr, std::system_category(), - "CoCreateGuid failed"); - } - - std::array bytes = { - {static_cast((newId.Data1 >> 24) & 0xFF), - static_cast((newId.Data1 >> 16) & 0xFF), - static_cast((newId.Data1 >> 8) & 0xFF), - static_cast((newId.Data1) & 0xFF), - - (unsigned char)((newId.Data2 >> 8) & 0xFF), - (unsigned char)((newId.Data2) & 0xFF), - - (unsigned char)((newId.Data3 >> 8) & 0xFF), - (unsigned char)((newId.Data3) & 0xFF), - - newId.Data4[0], newId.Data4[1], newId.Data4[2], newId.Data4[3], - newId.Data4[4], newId.Data4[5], newId.Data4[6], newId.Data4[7]}}; - - return uuid{std::begin(bytes), std::end(bytes)}; - -#elif defined(__linux__) || defined(__unix__) - - uuid_t id; - uuid_generate(id); - - std::array bytes = {{id[0], id[1], id[2], id[3], id[4], id[5], - id[6], id[7], id[8], id[9], id[10], - id[11], id[12], id[13], id[14], id[15]}}; - - return uuid{std::begin(bytes), std::end(bytes)}; - -#elif defined(__APPLE__) - auto newId = CFUUIDCreate(NULL); - auto bytes = CFUUIDGetUUIDBytes(newId); - CFRelease(newId); - - std::array arrbytes = { - {bytes.byte0, bytes.byte1, bytes.byte2, bytes.byte3, bytes.byte4, - bytes.byte5, bytes.byte6, bytes.byte7, bytes.byte8, bytes.byte9, - bytes.byte10, bytes.byte11, bytes.byte12, bytes.byte13, bytes.byte14, - bytes.byte15}}; - return uuid{std::begin(arrbytes), std::end(arrbytes)}; -#else - return uuid{}; -#endif - } - }; -#endif - - template - class basic_uuid_random_generator - { - public: - using engine_type = UniformRandomNumberGenerator; - - explicit basic_uuid_random_generator(engine_type& gen) - : generator(&gen, [](auto) {}) - { - } - explicit basic_uuid_random_generator(engine_type* gen) - : generator(gen, [](auto) {}) - { - } - - [[nodiscard]] uuid operator()() - { - alignas(uint32_t) uint8_t bytes[16]; - for (int i = 0; i < 16; i += 4) - *reinterpret_cast(bytes + i) = distribution(*generator); - - // variant must be 10xxxxxx - bytes[8] &= 0xBF; - bytes[8] |= 0x80; - - // version must be 0100xxxx - bytes[6] &= 0x4F; - bytes[6] |= 0x40; - - return uuid{std::begin(bytes), std::end(bytes)}; - } - - private: - std::uniform_int_distribution distribution; - std::shared_ptr generator; - }; - - using uuid_random_generator = basic_uuid_random_generator; - - class uuid_name_generator - { - public: - explicit uuid_name_generator(uuid const& namespace_uuid) noexcept - : nsuuid(namespace_uuid) - { - } - - template - [[nodiscard]] uuid operator()(StringType const& name) - { - reset(); - process_characters(detail::to_string_view(name)); - return make_uuid(); - } - - private: - void reset() - { - hasher.reset(); - std::byte bytes[16]; - auto nsbytes = nsuuid.as_bytes(); - std::copy(std::cbegin(nsbytes), std::cend(nsbytes), bytes); - hasher.process_bytes(bytes, 16); - } - - template - void process_characters(std::basic_string_view const str) - { - for (uint32_t c : str) - { - hasher.process_byte(static_cast(c & 0xFF)); - if constexpr (!std::is_same_v) - { - hasher.process_byte(static_cast((c >> 8) & 0xFF)); - hasher.process_byte(static_cast((c >> 16) & 0xFF)); - hasher.process_byte(static_cast((c >> 24) & 0xFF)); - } - } - } - - [[nodiscard]] uuid make_uuid() - { - detail::sha1::digest8_t digest; - hasher.get_digest_bytes(digest); - - // variant must be 0b10xxxxxx - digest[8] &= 0xBF; - digest[8] |= 0x80; - - // version must be 0b0101xxxx - digest[6] &= 0x5F; - digest[6] |= 0x50; - - return uuid{digest, digest + 16}; - } - - private: - uuid nsuuid; - detail::sha1 hasher; - }; - -#ifdef UUID_TIME_GENERATOR - // !!! DO NOT USE THIS IN PRODUCTION - // this implementation is unreliable for good uuids - class uuid_time_generator - { - using mac_address = std::array; - - std::optional device_address; - - [[nodiscard]] bool get_mac_address() - { - if (device_address.has_value()) - { - return true; - } - -#ifdef _WIN32 - DWORD len = 0; - auto ret = GetAdaptersInfo(nullptr, &len); - if (ret != ERROR_BUFFER_OVERFLOW) - return false; - std::vector buf(len); - auto pips = reinterpret_cast(&buf.front()); - ret = GetAdaptersInfo(pips, &len); - if (ret != ERROR_SUCCESS) - return false; - mac_address addr; - std::copy(pips->Address, pips->Address + 6, std::begin(addr)); - device_address = addr; -#endif - - return device_address.has_value(); - } - - [[nodiscard]] long long get_time_intervals() - { - auto start = std::chrono::system_clock::from_time_t(time_t(-12219292800)); - auto diff = std::chrono::system_clock::now() - start; - auto ns = - std::chrono::duration_cast(diff).count(); - return ns / 100; - } - - [[nodiscard]] static unsigned short get_clock_sequence() - { - static std::mt19937 clock_gen(std::random_device{}()); - static std::uniform_int_distribution clock_dis; - static std::atomic_ushort clock_sequence = clock_dis(clock_gen); - return clock_sequence++; - } - - public: - [[nodiscard]] uuid operator()() - { - if (get_mac_address()) - { - std::array data; - - auto tm = get_time_intervals(); - - auto clock_seq = get_clock_sequence(); - - auto ptm = reinterpret_cast(&tm); - - memcpy(&data[0], ptm + 4, 4); - memcpy(&data[4], ptm + 2, 2); - memcpy(&data[6], ptm, 2); - - memcpy(&data[8], &clock_seq, 2); - - // variant must be 0b10xxxxxx - data[8] &= 0xBF; - data[8] |= 0x80; - - // version must be 0b0001xxxx - data[6] &= 0x1F; - data[6] |= 0x10; - - memcpy(&data[10], &device_address.value()[0], 6); - - return uuids::uuid{std::cbegin(data), std::cend(data)}; - } - - return {}; - } - }; -#endif -} // namespace uuids - -namespace std -{ - template <> - struct hash - { - using argument_type = uuids::uuid; - using result_type = std::size_t; - - [[nodiscard]] result_type operator()(argument_type const& uuid) const - { -#ifdef UUID_HASH_STRING_BASED - std::hash hasher; - return static_cast(hasher(uuids::to_string(uuid))); -#else - uint64_t l = static_cast(uuid.data[0]) << 56 | - static_cast(uuid.data[1]) << 48 | - static_cast(uuid.data[2]) << 40 | - static_cast(uuid.data[3]) << 32 | - static_cast(uuid.data[4]) << 24 | - static_cast(uuid.data[5]) << 16 | - static_cast(uuid.data[6]) << 8 | - static_cast(uuid.data[7]); - uint64_t h = static_cast(uuid.data[8]) << 56 | - static_cast(uuid.data[9]) << 48 | - static_cast(uuid.data[10]) << 40 | - static_cast(uuid.data[11]) << 32 | - static_cast(uuid.data[12]) << 24 | - static_cast(uuid.data[13]) << 16 | - static_cast(uuid.data[14]) << 8 | - static_cast(uuid.data[15]); - - if constexpr (sizeof(result_type) > 4) - { - return result_type(l ^ h); - } - else - { - uint64_t hash64 = l ^ h; - return result_type(uint32_t(hash64 >> 32) ^ uint32_t(hash64)); - } -#endif - } - }; -} // namespace std - -#endif /* STDUUID_H */ \ No newline at end of file diff --git a/Comm/Version.hxx b/Comm/Version.hxx deleted file mode 100644 index ab02cf6..0000000 --- a/Comm/Version.hxx +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#define kDistVersion "v1.21" diff --git a/Examples/ExampleCDialect.S b/Examples/ExampleCDialect.S index 9d90d46..1eb2f82 100644 --- a/Examples/ExampleCDialect.S +++ b/Examples/ExampleCDialect.S @@ -1,4 +1,4 @@ -; Path: Examples/ExampleCDialect.cc +; Path: Examples/ExampleCDialect.cxx ; Language: MPCC assembly. (Generated from C++) ; Date: 2024-5-14 diff --git a/Headers/AsmKit/AsmKit.hpp b/Headers/AsmKit/AsmKit.hpp new file mode 100644 index 0000000..b492ce8 --- /dev/null +++ b/Headers/AsmKit/AsmKit.hpp @@ -0,0 +1,217 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace CompilerKit +{ + // + // @brief Frontend to Assembly mountpoint. + // + class AssemblyInterface + { + public: + explicit AssemblyInterface() = default; + virtual ~AssemblyInterface() = default; + + MPCC_COPY_DEFAULT(AssemblyInterface); + + //@ brief compile to object file. + // 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; + + MPCC_COPY_DEFAULT(AssemblyFactory); + + public: + enum + { + kArchAMD64, + kArch32x0, + kArch64x0, + kArchRISCV, + kArchPowerPC, + 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; + + MPCC_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; + + MPCC_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_64x0__ + + class Encoder64x0 final : public EncoderInterface + { + public: + explicit Encoder64x0() = default; + ~Encoder64x0() override = default; + + MPCC_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; + + MPCC_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; + + MPCC_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 CompilerKit diff --git a/Headers/AsmKit/CPU/32x0.hpp b/Headers/AsmKit/CPU/32x0.hpp new file mode 100644 index 0000000..cfe4a47 --- /dev/null +++ b/Headers/AsmKit/CPU/32x0.hpp @@ -0,0 +1,95 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#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]; + 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 kOpcodes32x0 = { + kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. + kAsmOpcodeDecl("br", 0b1110011, 0b001, kAsmJump) // jump to branch + kAsmOpcodeDecl("mr", 0b0100011, 0b101, kAsmImmediate) // move registers + kAsmOpcodeDecl("psh", 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 + +//////////////////////////////// diff --git a/Headers/AsmKit/CPU/64x0.hpp b/Headers/AsmKit/CPU/64x0.hpp new file mode 100644 index 0000000..2da4f24 --- /dev/null +++ b/Headers/AsmKit/CPU/64x0.hpp @@ -0,0 +1,108 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#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("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 + +//////////////////////////////// diff --git a/Headers/AsmKit/CPU/amd64.hpp b/Headers/AsmKit/CPU/amd64.hpp new file mode 100644 index 0000000..bc4b956 --- /dev/null +++ b/Headers/AsmKit/CPU/amd64.hpp @@ -0,0 +1,57 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#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; + +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 15 diff --git a/Headers/AsmKit/CPU/arm64.hpp b/Headers/AsmKit/CPU/arm64.hpp new file mode 100644 index 0000000..e7d4f68 --- /dev/null +++ b/Headers/AsmKit/CPU/arm64.hpp @@ -0,0 +1,26 @@ +/* ------------------------------------------- + +Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +#include + +/// @brief ARM64 encoding support. +/// @file CPU/arm64.hpp + +struct CpuOpcodeArm64; + +/// @brief ARM64 opcode header. +struct CpuOpcodeArm64 final +{ + uint8_t fOpcode; // opcode + uint8_t fRegisterLeft; // left register index + uint8_t fRegisterRight; // right register index + bool fRegisterLeftHooked; + bool fRegisterRightHooked; + uint32_t fImmediateValue; // immediate 32-bit value + bool fImmediateValueHooked; +}; diff --git a/Headers/AsmKit/CPU/ppc.hpp b/Headers/AsmKit/CPU/ppc.hpp new file mode 100644 index 0000000..e3ea6c5 --- /dev/null +++ b/Headers/AsmKit/CPU/ppc.hpp @@ -0,0 +1,1929 @@ +/* ------------------------------------------- + + Some modifications are copyrighted under: + ZKA Technologies + + Original author: + Apple Inc + +------------------------------------------- */ + +#pragma once + +#include + +/// @note Based of: +/// https://opensource.apple.com/source/cctools/cctools-750/as/ppc-opcode.h.auto.html + +/* + * 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 optype +{ + 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 SizeType size_t + +#define VoidPtr void* +#define voidPtr VoidPtr + +#define UIntPtr uintptr_t + +#define Int64 int64_t +#define UInt64 uint64_t + +#define Int32 int +#define UInt32 unsigned + +#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 +#include +#include + +#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 MPCC_COPY_DELETE(KLASS) \ + KLASS& operator=(const KLASS&) = delete; \ + KLASS(const KLASS&) = delete; + +#define MPCC_COPY_DEFAULT(KLASS) \ + KLASS& operator=(const KLASS&) = default; \ + KLASS(const KLASS&) = default; + +#define MPCC_MOVE_DELETE(KLASS) \ + KLASS& operator=(KLASS&&) = delete; \ + KLASS(KLASS&&) = delete; + +#define MPCC_MOVE_DEFAULT(KLASS) \ + KLASS& operator=(KLASS&&) = default; \ + KLASS(KLASS&&) = default; + +#include +#include +#include +#include + +namespace CompilerKit +{ + inline constexpr int BASE_YEAR = 1900; + + inline std::string current_date() noexcept + { + 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) noexcept + { + 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; + } +} // namespace CompilerKit + +#define PACKED __attribute__((packed)) + +typedef char char_type; + +#define kObjectFileExt ".obj" +#define kBinaryFileExt ".bin" + +#define kAsmFileExts \ + { \ + ".64x", ".32x", ".masm", ".s", ".S", ".asm" \ + } + +#ifdef __NDK_MODULE__ +#define NDK_MODULE(name) int name(int argc, char** argv) +#else +#define NDK_MODULE(name) int main(int argc, char** argv) +#endif /* ifdef __NDK_MODULE__ */ + +#pragma scalar_storage_order big-endian + +#endif /* ifndef __MPCC_DEFINES_HPP__ */ diff --git a/Headers/Macros.hpp b/Headers/Macros.hpp new file mode 100644 index 0000000..c190cda --- /dev/null +++ b/Headers/Macros.hpp @@ -0,0 +1,33 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +/// @brief provide support for Macros.hpp header. + +#ifndef _CK_CL_HPP +#define _CK_CL_HPP + +#define MPCC_COPY_DELETE(KLASS) \ + KLASS& operator=(const KLASS&) = delete; \ + KLASS(const KLASS&) = delete; + +#define MPCC_COPY_DEFAULT(KLASS) \ + KLASS& operator=(const KLASS&) = default; \ + KLASS(const KLASS&) = default; + +#define MPCC_MOVE_DELETE(KLASS) \ + KLASS& operator=(KLASS&&) = delete; \ + KLASS(KLASS&&) = delete; + +#define MPCC_MOVE_DEFAULT(KLASS) \ + KLASS& operator=(KLASS&&) = default; \ + KLASS(KLASS&&) = default; + +/// @note xxxx is the error placeholder, in hexadecimal. +#define MPCC_ERROR_PREFIX_CXX "CXXxxxx" +#define MPCC_ERROR_PREFIX_CL "CLxxxx" +#define MPCC_ERROR_PREFIX_ASM "ASMxxxx" + +#endif /* ifndef _CK_CL_HPP */ diff --git a/Headers/ParserKit.hpp b/Headers/ParserKit.hpp new file mode 100644 index 0000000..186c9cf --- /dev/null +++ b/Headers/ParserKit.hpp @@ -0,0 +1,173 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +#include +#include + +namespace ParserKit +{ + using namespace CompilerKit; + + /// @brief Compiler backend, implements a frontend, such as C, C++... + /// See Toolchain, for some examples. + class CompilerBackend + { + public: + explicit CompilerBackend() = default; + virtual ~CompilerBackend() = default; + + MPCC_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 "Invalid Language"; + } + }; + + struct SyntaxLeafList; + struct SyntaxLeafList; + struct CompilerKeyword; + + /// we want to do that because to separate keywords. + enum KeywordKind + { + eKeywordKindNamespace, + eKeywordKindFunctionStart, + eKeywordKindFunctionEnd, + eKeywordKindVariable, + eKeywordKindVariablePtr, + eKeywordKindType, + eKeywordKindTypePtr, + eKeywordKindExpressionBegin, + eKeywordKindExpressionEnd, + eKeywordKindArgSeparator, + eKeywordKindBodyStart, + eKeywordKindBodyEnd, + eKeywordKindClass, + eKeywordKindPtrAccess, + eKeywordKindAccess, + eKeywordKindIf, + eKeywordKindElse, + eKeywordKindElseIf, + eKeywordKindVariableAssign, + eKeywordKindVariableDec, + eKeywordKindVariableInc, + eKeywordKindConstant, + eKeywordKindTypedef, + eKeywordKindEndInstr, + eKeywordKindSpecifier, + eKeywordKindInvalid, + eKeywordKindReturn, + eKeywordKindCommentInline, + eKeywordKindCommentMultiLineStart, + eKeywordKindCommentMultiLineEnd, + eKeywordKindEq, + eKeywordKindNotEq, + eKeywordKindGreaterEq, + eKeywordKindLessEq, + eKeywordKindPtr, + }; + + /// \brief Compiler keyword information struct. + struct CompilerKeyword + { + std::string keyword_name; + KeywordKind keyword_kind = eKeywordKindInvalid; + }; + struct SyntaxLeafList final + { + struct SyntaxLeaf final + { + Int32 fUserType; +#ifdef __PK_USE_STRUCT_INSTEAD__ + CompilerKeyword fUserData; +#else + std::string fUserData; +#endif + + std::string fUserValue; + struct SyntaxLeaf* fNext; + }; + + std::vector fLeafList; + SizeType fNumLeafs; + + size_t SizeOf() + { + return fNumLeafs; + } + std::vector& 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; + } +} // namespace ParserKit diff --git a/Headers/Public/SDK/CRT/__mpcc_alloca.hxx b/Headers/Public/SDK/CRT/__mpcc_alloca.hxx new file mode 100644 index 0000000..02b3123 --- /dev/null +++ b/Headers/Public/SDK/CRT/__mpcc_alloca.hxx @@ -0,0 +1,15 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +typedef void* ptr_type; +typedef __SIZE_TYPE__ size_type; + +inline void* __mpcc_alloca_gcc(size_type sz) +{ + return __builtin_alloca(sz); +} diff --git a/Headers/Public/SDK/CRT/__mpcc_defines.hxx b/Headers/Public/SDK/CRT/__mpcc_defines.hxx new file mode 100644 index 0000000..19ed8a4 --- /dev/null +++ b/Headers/Public/SDK/CRT/__mpcc_defines.hxx @@ -0,0 +1,83 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#ifndef __MPCC_DEF__ +#define __MPCC_DEF__ + +#ifndef __GNUC__ + +typedef __SIZE_TYPE__ size_t; + +#ifdef __LP64__ +typedef long int ssize_t; +#else +typedef int ssize_t; +#endif // __LP64__ + +typedef size_t ptrdiff_t; +typedef size_t uintptr_t; +typedef void* voidptr_t; +typedef void* any_t; +typedef char* caddr_t; + +#ifndef NULL +#define NULL ((voidptr_t)0) +#endif // !null + +#ifdef __GNUC__ +#include +#define __mpcc_alloca(sz) __mpcc_alloca_gcc(sz) +#define __packed__ __attribute__((packed)) +#elif defined(__MPCC__) +#define __packed__ __mpcc_packed__ +#define __alloca(sz) __mpcc_alloca(sz) +#endif + +#define __deref(ptr) (*(ptr)) + +#ifdef __cplusplus +#define __init_decl() \ + extern "C" \ + { + + +#define __fini_decl() \ + }; \ + + +#else +#define __init_decl() +#define __fini_decl() +#endif + +typedef long long off_t; +typedef unsigned long long uoff_t; + +typedef union float_cast { + struct + { + unsigned int mantissa : 23; + unsigned int exponent : 8; + unsigned int sign : 1; + }; + + float f; +} __packed__ float_cast_t; + +typedef union double_cast { + struct + { + unsigned long long int mantissa : 52; + unsigned int exponent : 11; + unsigned int sign : 1; + }; + + double f; +} __packed__ double_cast_t; + +#endif // ifndef __GNUC__ + +#endif /* __MPCC_DEF__ */ diff --git a/Headers/Public/SDK/CRT/__mpcc_exception.hxx b/Headers/Public/SDK/CRT/__mpcc_exception.hxx new file mode 100644 index 0000000..4a9f84a --- /dev/null +++ b/Headers/Public/SDK/CRT/__mpcc_exception.hxx @@ -0,0 +1,27 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +/// This file is an implementation of __throw* family of functions. + +#include +#include +#include + +namespace std +{ + inline void __throw_general(void) + { + throw std::runtime_error("MPCC C++ Runtime error."); + } + + inline void __throw_domain_error(const char* error) + { + std::cout << "MPCC C++: Domain error: " << error << "\r"; + __throw_general(); + } +} // namespace std diff --git a/Headers/Public/SDK/CRT/__mpcc_hint.hxx b/Headers/Public/SDK/CRT/__mpcc_hint.hxx new file mode 100644 index 0000000..02dbc94 --- /dev/null +++ b/Headers/Public/SDK/CRT/__mpcc_hint.hxx @@ -0,0 +1,20 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +#pragma compiler(hint_manifest) + +#define _Input +#define _Output + +#define _Optional + +#define _StrictCheckInput +#define _StrictCheckOutput + +#define _InOut +#define _StrictInOut diff --git a/Headers/Public/SDK/CRT/__mpcc_malloc.hxx b/Headers/Public/SDK/CRT/__mpcc_malloc.hxx new file mode 100644 index 0000000..eeaa67b --- /dev/null +++ b/Headers/Public/SDK/CRT/__mpcc_malloc.hxx @@ -0,0 +1,30 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +#include + +namespace stdx +{ + /// @brief allocate a new class. + /// @tparam KindClass the class type to allocate. + template + inline void* allocate(Args&&... args) + { + return new KindClass(std::forward(args)...); + } + + /// @brief free a class. + /// @tparam KindClass the class type to allocate. + template + inline void release(KindClass ptr) + { + if (!ptr) + return; + delete ptr; + } +} // namespace stdx diff --git a/Headers/Public/SDK/CRT/__mpcc_power.inc b/Headers/Public/SDK/CRT/__mpcc_power.inc new file mode 100644 index 0000000..9e4928c --- /dev/null +++ b/Headers/Public/SDK/CRT/__mpcc_power.inc @@ -0,0 +1,35 @@ +# Path: SDK/__mpcc_power.inc +# Language: MPCC POWER Assembly support for GNU. +# Build Date: 2024-6-4 + +%ifdef __CODETOOLS__ + +%def lda li +%def sta stw +%def ldw li + +%def r0 0 +%def r1 1 +%def r2 2 +%def r3 3 +%def r4 4 +%def r5 5 +%def r6 6 +%def r7 7 +%def r8 8 +%def r9 9 +%def r10 10 +%def r11 11 +%def r12 12 +%def r13 13 +%def r14 14 +%def r15 15 +%def r16 16 +%def r17 17 +%def r18 18 +%def r19 19 +%def r20 20 + +%endif + +%def nop mr 0, 0 diff --git a/Headers/StdKit/AE.hpp b/Headers/StdKit/AE.hpp new file mode 100644 index 0000000..baa4249 --- /dev/null +++ b/Headers/StdKit/AE.hpp @@ -0,0 +1,143 @@ +/* + * ======================================================== + * + * MPCC + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include + +#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; + 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 CompilerKit + +// 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 +{ + /** + * @brief AE Reader protocol + * + */ + class AEReadableProtocol final + { + public: + std::ifstream FP; + + public: + explicit AEReadableProtocol() = default; + ~AEReadableProtocol() = default; + + MPCC_COPY_DELETE(AEReadableProtocol); + + /** + * @brief Read AE record + * + * @param raw the containing buffer + * @param sz it's size (without sizeof(AERecordHeader) added to it.) + * @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 CompilerKit::Utils diff --git a/Headers/StdKit/ELF.hpp b/Headers/StdKit/ELF.hpp new file mode 100644 index 0000000..4f0d0ae --- /dev/null +++ b/Headers/StdKit/ELF.hpp @@ -0,0 +1,389 @@ +#pragma once + +#include +#include + +struct file; + +#ifndef elf_read_implies_exec +/* Executables for which elf_read_implies_exec() returns TRUE will + have the READ_IMPLIES_EXEC personality flag set automatically. + Override in asm/elf.h as needed. */ +#define elf_read_implies_exec(ex, have_pt_gnu_stack) 0 +#endif + +/* 32-bit ELF base types. */ +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +/* 64-bit ELF base types. */ +typedef uintptr_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* These constants are for the segment types stored in the image headers */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* OS-specific */ +#define PT_HIOS 0x6fffffff /* OS-specific */ +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff +#define PT_GNU_EH_FRAME 0x6474e550 + +#define PT_GNU_STACK (PT_LOOS + 0x474e551) + +/* These constants define the different elf file types */ +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +/* This is the info that is needed to parse the dynamic section of the file */ +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_ENCODING 32 +#define OLD_DT_LOOS 0x60000000 +#define DT_LOOS 0x6000000d +#define DT_HIOS 0x6ffff000 +#define DT_VALRNGLO 0x6ffffd00 +#define DT_VALRNGHI 0x6ffffdff +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_VERSYM 0x6ffffff0 +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa +#define DT_FLAGS_1 0x6ffffffb +#define DT_VERDEF 0x6ffffffc +#define DT_VERDEFNUM 0x6ffffffd +#define DT_VERNEED 0x6ffffffe +#define DT_VERNEEDNUM 0x6fffffff +#define OLD_DT_HIOS 0x6fffffff +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* This info is needed when parsing the symbol table */ +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_COMMON 5 +#define STT_TLS 6 + +#define ELF_ST_BIND(x) ((x) >> 4) +#define ELF_ST_TYPE(x) (((unsigned int)x) & 0xf) +#define ELF32_ST_BIND(x) ELF_ST_BIND(x) +#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) +#define ELF64_ST_BIND(x) ELF_ST_BIND(x) +#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x) + +typedef struct dynamic +{ + Elf32_Sword d_tag; + union { + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; /* entry tag value */ + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +/* The following are used with relocations */ +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x)&0xff) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i)&0xffffffff) + +typedef struct elf32_rel +{ + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf64_rel +{ + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ +} Elf64_Rel; + +typedef struct elf32_rela +{ + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct elf64_rela +{ + Elf64_Addr r_offset; /* Location at which to apply the action */ + Elf64_Xword r_info; /* index and type of relocation */ + Elf64_Sxword r_addend; /* Constant addend used to compute value */ +} Elf64_Rela; + +typedef struct elf32_sym +{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +typedef struct elf64_sym +{ + Elf64_Word st_name; /* Symbol name, index in string tbl */ + unsigned char st_info; /* Type and binding attributes */ + unsigned char st_other; /* No defined meaning, 0 */ + Elf64_Half st_shndx; /* Associated section index */ + Elf64_Addr st_value; /* Value of the symbol */ + Elf64_Xword st_size; /* Associated symbol size */ +} Elf64_Sym; + +#define EI_NIDENT 16 + +typedef struct elf32_hdr +{ + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; /* Entry point */ + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +typedef struct elf64_hdr +{ + unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +/* These constants define the permissions on sections in the program + header, p_flags. */ +#define PF_R 0x4 +#define PF_W 0x2 +#define PF_X 0x1 + +typedef struct elf32_phdr +{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +typedef struct elf64_phdr +{ + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment, file & memory */ +} Elf64_Phdr; + +/* sh_type */ +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* sh_flags */ +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +/* special section indexes */ +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +typedef struct +{ + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct elf64_shdr +{ + Elf64_Word sh_name; /* Section name, index in string tbl */ + Elf64_Word sh_type; /* Type of section */ + Elf64_Xword sh_flags; /* Miscellaneous section attributes */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Size of section in bytes */ + Elf64_Word sh_link; /* Index of another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +#define ELFOSABI_NONE 0 +#define ELFOSABI_LINUX 3 + +#ifndef ELF_OSABI +#define ELF_OSABI ELFOSABI_NONE +#endif + +/* Notes used in ET_CORE */ +#define NT_PRSTATUS 1 +#define NT_PRFPREG 2 +#define NT_PRPSINFO 3 +#define NT_TASKSTRUCT 4 +#define NT_AUXV 6 +#define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ +#define NT_PPC_VMX 0x100 /* POWER Altivec/VMX registers */ +#define NT_PPC_SPE 0x101 /* POWER SPE/EVR registers */ +#define NT_PPC_VSX 0x102 /* POWER VSX registers */ +#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */ +#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */ +#define NT_PRXSTATUS 0x300 /* s390 upper register halves */ + +/* Note header in a PT_NOTE section */ +typedef struct elf32_note +{ + Elf32_Word n_namesz; /* Name size */ + Elf32_Word n_descsz; /* Content size */ + Elf32_Word n_type; /* Content type */ +} Elf32_Nhdr; + +/* Note header in a PT_NOTE section */ +typedef struct elf64_note +{ + Elf64_Word n_namesz; /* Name size */ + Elf64_Word n_descsz; /* Content size */ + Elf64_Word n_type; /* Content type */ +} Elf64_Nhdr; diff --git a/Headers/StdKit/ErrorID.hpp b/Headers/StdKit/ErrorID.hpp new file mode 100644 index 0000000..41d6b2f --- /dev/null +++ b/Headers/StdKit/ErrorID.hpp @@ -0,0 +1,22 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +#define MPCC_EXEC_ERROR -30 +#define MPCC_FILE_NOT_FOUND -31 +#define MPCC_DIR_NOT_FOUND -32 +#define MPCC_FILE_EXISTS -33 +#define MPCC_TOO_LONG -34 +#define MPCC_INVALID_DATA -35 +#define MPCC_UNIMPLEMENTED -36 +#define MPCC_FAT_ERROR -37 diff --git a/Headers/StdKit/ErrorOr.hpp b/Headers/StdKit/ErrorOr.hpp new file mode 100644 index 0000000..6c8e87e --- /dev/null +++ b/Headers/StdKit/ErrorOr.hpp @@ -0,0 +1,61 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +namespace CompilerKit +{ + 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 CompilerKit diff --git a/Headers/StdKit/PEF.hpp b/Headers/StdKit/PEF.hpp new file mode 100644 index 0000000..d8709ed --- /dev/null +++ b/Headers/StdKit/PEF.hpp @@ -0,0 +1,134 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#pragma once + +#include + +// @file PEF.hpp +// @brief Preferred Executable Format + +#define kPefMagic "Joy!" +#define kPefMagicFat "yoJ!" + +#define kPefExt ".exec" +#define kPefDylibExt ".lib" +#define kPefLibExt ".slib" +#define kPefObjectExt ".obj" +#define kPefDebugExt ".dbg" + +#define kPefMagicLen 5 + +#define kPefVersion 2 +#define kPefNameLen 255 + +#define kPefBaseOrigin (0x1000000) + +#define kPefStart "__ImageStart" + +namespace CompilerKit +{ + 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, + kPefSubArchGeneric, + kPefSubArchIBM, + }; + + enum + { + kPefKindExec = 1, /* .exe */ + kPefKindSharedObject = 2, /* .lib */ + 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; + + /* 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; + + enum + { + kPefCode = 0xC, + kPefData = 0xD, + kPefZero = 0xE, + kPefLinkerID = 0x1, + kPefCount = 4, + kPefInvalid = 0xFF, + }; +} // namespace CompilerKit + +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/Headers/StdKit/Ref.hpp b/Headers/StdKit/Ref.hpp new file mode 100644 index 0000000..e655ccb --- /dev/null +++ b/Headers/StdKit/Ref.hpp @@ -0,0 +1,91 @@ + +/* + * ======================================================== + * + * CompilerKit + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +namespace CompilerKit +{ + // @author ZKA Technologies + // @brief Reference class, refers to a pointer of data in static memory. + template + 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 + class NonNullRef final + { + public: + NonNullRef() = delete; + NonNullRef(nullPtr) = 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 CompilerKit diff --git a/Headers/StdKit/String.hpp b/Headers/StdKit/String.hpp new file mode 100644 index 0000000..59a7997 --- /dev/null +++ b/Headers/StdKit/String.hpp @@ -0,0 +1,90 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +namespace CompilerKit +{ + /** + * @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 char[Sz]; + assert(m_Data); + } + + ~StringView() noexcept + { + if (m_Data) + { + memset(m_Data, 0, m_Sz); + delete[] m_Data; + + m_Data = nullptr; + } + } + + MPCC_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: + char* 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 CompilerKit diff --git a/Headers/StdKit/XCOFF.hxx b/Headers/StdKit/XCOFF.hxx new file mode 100644 index 0000000..dbc258d --- /dev/null +++ b/Headers/StdKit/XCOFF.hxx @@ -0,0 +1,41 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + + File: XCOFF.hpp + Purpose: XCOFF for NewOS. + + 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 CompilerKit +{ + /// @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 CompilerKit + +#endif // ifndef __XCOFF__ diff --git a/Headers/UUID.hpp b/Headers/UUID.hpp new file mode 100644 index 0000000..00b153b --- /dev/null +++ b/Headers/UUID.hpp @@ -0,0 +1,983 @@ +#ifndef STDUUID_H +#define STDUUID_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus + +#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) +#define LIBUUID_CPP20_OR_GREATER +#endif + +#endif + +#ifdef LIBUUID_CPP20_OR_GREATER +#include +#else +#include +#endif + +#ifdef _WIN32 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#ifdef UUID_SYSTEM_GENERATOR +#include +#endif + +#ifdef UUID_TIME_GENERATOR +#include +#pragma comment(lib, "IPHLPAPI.lib") +#endif + +#elif defined(__linux__) || defined(__unix__) + +#ifdef UUID_SYSTEM_GENERATOR +#include +#endif + +#elif defined(__APPLE__) + +#ifdef UUID_SYSTEM_GENERATOR +#include +#endif + +#endif + +namespace uuids +{ +#ifdef __cpp_lib_span + template + using span = std::span; +#else + template + using span = gsl::span; +#endif + + namespace detail + { + template + [[nodiscard]] constexpr inline unsigned char hex2char(TChar const ch) noexcept + { + if (ch >= static_cast('0') && ch <= static_cast('9')) + return static_cast(ch - static_cast('0')); + if (ch >= static_cast('a') && ch <= static_cast('f')) + return static_cast(10 + ch - static_cast('a')); + if (ch >= static_cast('A') && ch <= static_cast('F')) + return static_cast(10 + ch - static_cast('A')); + return 0; + } + + template + [[nodiscard]] constexpr inline bool is_hex(TChar const ch) noexcept + { + return (ch >= static_cast('0') && ch <= static_cast('9')) || + (ch >= static_cast('a') && ch <= static_cast('f')) || + (ch >= static_cast('A') && ch <= static_cast('F')); + } + + template + [[nodiscard]] constexpr std::basic_string_view to_string_view( + TChar const* str) noexcept + { + if (str) + return str; + return {}; + } + + template + [[nodiscard]] constexpr std::basic_string_view + to_string_view(StringType const& str) noexcept + { + return str; + } + + class sha1 + { + public: + using digest32_t = uint32_t[5]; + using digest8_t = uint8_t[20]; + + static constexpr unsigned int block_bytes = 64; + + [[nodiscard]] inline static uint32_t left_rotate( + uint32_t value, size_t const count) noexcept + { + return (value << count) ^ (value >> (32 - count)); + } + + sha1() + { + reset(); + } + + void reset() noexcept + { + m_digest[0] = 0x67452301; + m_digest[1] = 0xEFCDAB89; + m_digest[2] = 0x98BADCFE; + m_digest[3] = 0x10325476; + m_digest[4] = 0xC3D2E1F0; + m_blockByteIndex = 0; + m_byteCount = 0; + } + + void process_byte(uint8_t octet) + { + this->m_block[this->m_blockByteIndex++] = octet; + ++this->m_byteCount; + if (m_blockByteIndex == block_bytes) + { + this->m_blockByteIndex = 0; + process_block(); + } + } + + void process_block(void const* const start, void const* const end) + { + const uint8_t* begin = static_cast(start); + const uint8_t* finish = static_cast(end); + while (begin != finish) + { + process_byte(*begin); + begin++; + } + } + + void process_bytes(void const* const data, size_t const len) + { + const uint8_t* block = static_cast(data); + process_block(block, block + len); + } + + uint32_t const* get_digest(digest32_t digest) + { + size_t const bitCount = this->m_byteCount * 8; + process_byte(0x80); + if (this->m_blockByteIndex > 56) + { + while (m_blockByteIndex != 0) + { + process_byte(0); + } + while (m_blockByteIndex < 56) + { + process_byte(0); + } + } + else + { + while (m_blockByteIndex < 56) + { + process_byte(0); + } + } + process_byte(0); + process_byte(0); + process_byte(0); + process_byte(0); + process_byte(static_cast((bitCount >> 24) & 0xFF)); + process_byte(static_cast((bitCount >> 16) & 0xFF)); + process_byte(static_cast((bitCount >> 8) & 0xFF)); + process_byte(static_cast((bitCount)&0xFF)); + + memcpy(digest, m_digest, 5 * sizeof(uint32_t)); + return digest; + } + + uint8_t const* get_digest_bytes(digest8_t digest) + { + digest32_t d32; + get_digest(d32); + size_t di = 0; + digest[di++] = static_cast(d32[0] >> 24); + digest[di++] = static_cast(d32[0] >> 16); + digest[di++] = static_cast(d32[0] >> 8); + digest[di++] = static_cast(d32[0] >> 0); + + digest[di++] = static_cast(d32[1] >> 24); + digest[di++] = static_cast(d32[1] >> 16); + digest[di++] = static_cast(d32[1] >> 8); + digest[di++] = static_cast(d32[1] >> 0); + + digest[di++] = static_cast(d32[2] >> 24); + digest[di++] = static_cast(d32[2] >> 16); + digest[di++] = static_cast(d32[2] >> 8); + digest[di++] = static_cast(d32[2] >> 0); + + digest[di++] = static_cast(d32[3] >> 24); + digest[di++] = static_cast(d32[3] >> 16); + digest[di++] = static_cast(d32[3] >> 8); + digest[di++] = static_cast(d32[3] >> 0); + + digest[di++] = static_cast(d32[4] >> 24); + digest[di++] = static_cast(d32[4] >> 16); + digest[di++] = static_cast(d32[4] >> 8); + digest[di++] = static_cast(d32[4] >> 0); + + return digest; + } + + private: + void process_block() + { + uint32_t w[80]; + for (size_t i = 0; i < 16; i++) + { + w[i] = static_cast(m_block[i * 4 + 0] << 24); + w[i] |= static_cast(m_block[i * 4 + 1] << 16); + w[i] |= static_cast(m_block[i * 4 + 2] << 8); + w[i] |= static_cast(m_block[i * 4 + 3]); + } + for (size_t i = 16; i < 80; i++) + { + w[i] = left_rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1); + } + + uint32_t a = m_digest[0]; + uint32_t b = m_digest[1]; + uint32_t c = m_digest[2]; + uint32_t d = m_digest[3]; + uint32_t e = m_digest[4]; + + for (std::size_t i = 0; i < 80; ++i) + { + uint32_t f = 0; + uint32_t k = 0; + + if (i < 20) + { + f = (b & c) | (~b & d); + k = 0x5A827999; + } + else if (i < 40) + { + f = b ^ c ^ d; + k = 0x6ED9EBA1; + } + else if (i < 60) + { + f = (b & c) | (b & d) | (c & d); + k = 0x8F1BBCDC; + } + else + { + f = b ^ c ^ d; + k = 0xCA62C1D6; + } + uint32_t temp = left_rotate(a, 5) + f + e + k + w[i]; + e = d; + d = c; + c = left_rotate(b, 30); + b = a; + a = temp; + } + + m_digest[0] += a; + m_digest[1] += b; + m_digest[2] += c; + m_digest[3] += d; + m_digest[4] += e; + } + + private: + digest32_t m_digest; + uint8_t m_block[64]; + size_t m_blockByteIndex; + size_t m_byteCount; + }; + + template + inline constexpr CharT empty_guid[37] = "00000000-0000-0000-0000-000000000000"; + + template <> + inline constexpr wchar_t empty_guid[37] = + L"00000000-0000-0000-0000-000000000000"; + + template + inline constexpr CharT guid_encoder[17] = "0123456789abcdef"; + + template <> + inline constexpr wchar_t guid_encoder[17] = L"0123456789abcdef"; + } // namespace detail + + // -------------------------------------------------------------------------------------------------------------------------- + // UUID format https://tools.ietf.org/html/rfc4122 + // -------------------------------------------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------------------------------------------- + // Field NDR Data Type Octet # Note + // -------------------------------------------------------------------------------------------------------------------------- + // time_low unsigned long 0 - 3 The low field + // of the timestamp. time_mid unsigned short 4 - 5 + // The middle field of the timestamp. time_hi_and_version unsigned + // short 6 - 7 The high field of the timestamp multiplexed + // with the version number. clock_seq_hi_and_reserved unsigned small 8 + // The high field of the clock sequence multiplexed with the variant. + // clock_seq_low unsigned small 9 The low + // field of the clock sequence. node character 10 + // - 15 The spatially unique node identifier. + // -------------------------------------------------------------------------------------------------------------------------- + // 0 1 2 3 + // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | time_low | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | time_mid | time_hi_and_version | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // |clk_seq_hi_res | clk_seq_low | node (0-1) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + // | node (2-5) | + // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + // -------------------------------------------------------------------------------------------------------------------------- + // enumerations + // -------------------------------------------------------------------------------------------------------------------------- + + // indicated by a bit pattern in octet 8, marked with N in + // xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx + enum class uuid_variant + { + // NCS backward compatibility (with the obsolete Apollo Network Computing + // System 1.5 UUID format) N bit pattern: 0xxx > the first 6 octets of the + // UUID are a 48-bit timestamp (the number of 4 microsecond units of time + // since 1 Jan 1980 UTC); > the next 2 octets are reserved; > the next octet + // is the "address family"; > the final 7 octets are a 56-bit host ID in the + // form specified by the address family + ncs, + + // RFC 4122/DCE 1.1 + // N bit pattern: 10xx + // > big-endian byte order + rfc, + + // Microsoft Corporation backward compatibility + // N bit pattern: 110x + // > little endian byte order + // > formely used in the Component Object Model (COM) library + microsoft, + + // reserved for possible future definition + // N bit pattern: 111x + reserved + }; + + // indicated by a bit pattern in octet 6, marked with M in + // xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx + enum class uuid_version + { + none = 0, // only possible for nil or invalid uuids + time_based = 1, // The time-based version specified in RFC 4122 + dce_security = 2, // DCE Security version, with embedded POSIX UIDs. + name_based_md5 = + 3, // The name-based version specified in RFS 4122 with MD5 hashing + random_number_based = 4, // The randomly or pseudo-randomly generated version + // specified in RFS 4122 + name_based_sha1 = + 5 // The name-based version specified in RFS 4122 with SHA1 hashing + }; + + // Forward declare uuid & to_string so that we can declare to_string as a friend + // later. + class uuid; + template , class Allocator = std::allocator> + std::basic_string to_string(uuid const& id); + + // -------------------------------------------------------------------------------------------------------------------------- + // uuid class + // -------------------------------------------------------------------------------------------------------------------------- + class uuid + { + public: + using value_type = uint8_t; + + constexpr uuid() noexcept = default; + + uuid(value_type (&arr)[16]) noexcept + { + std::copy(std::cbegin(arr), std::cend(arr), std::begin(data)); + } + + constexpr uuid(std::array const& arr) noexcept + : data{arr} + { + } + + explicit uuid(span bytes) + { + std::copy(std::cbegin(bytes), std::cend(bytes), std::begin(data)); + } + + template + explicit uuid(ForwardIterator first, ForwardIterator last) + { + if (std::distance(first, last) == 16) + std::copy(first, last, std::begin(data)); + } + + [[nodiscard]] constexpr uuid_variant variant() const noexcept + { + if ((data[8] & 0x80) == 0x00) + return uuid_variant::ncs; + else if ((data[8] & 0xC0) == 0x80) + return uuid_variant::rfc; + else if ((data[8] & 0xE0) == 0xC0) + return uuid_variant::microsoft; + else + return uuid_variant::reserved; + } + + [[nodiscard]] constexpr uuid_version version() const noexcept + { + if ((data[6] & 0xF0) == 0x10) + return uuid_version::time_based; + else if ((data[6] & 0xF0) == 0x20) + return uuid_version::dce_security; + else if ((data[6] & 0xF0) == 0x30) + return uuid_version::name_based_md5; + else if ((data[6] & 0xF0) == 0x40) + return uuid_version::random_number_based; + else if ((data[6] & 0xF0) == 0x50) + return uuid_version::name_based_sha1; + else + return uuid_version::none; + } + + [[nodiscard]] constexpr bool is_nil() const noexcept + { + for (size_t i = 0; i < data.size(); ++i) + if (data[i] != 0) + return false; + return true; + } + + void swap(uuid& other) noexcept + { + data.swap(other.data); + } + + [[nodiscard]] inline span as_bytes() const + { + return span( + reinterpret_cast(data.data()), 16); + } + + template + [[nodiscard]] constexpr static bool is_valid_uuid( + StringType const& in_str) noexcept + { + auto str = detail::to_string_view(in_str); + bool firstDigit = true; + size_t hasBraces = 0; + size_t index = 0; + + if (str.empty()) + return false; + + if (str.front() == '{') + hasBraces = 1; + if (hasBraces && str.back() != '}') + return false; + + for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) + { + if (str[i] == '-') + continue; + + if (index >= 16 || !detail::is_hex(str[i])) + { + return false; + } + + if (firstDigit) + { + firstDigit = false; + } + else + { + index++; + firstDigit = true; + } + } + + if (index < 16) + { + return false; + } + + return true; + } + + template + [[nodiscard]] constexpr static std::optional from_string( + StringType const& in_str) noexcept + { + auto str = detail::to_string_view(in_str); + bool firstDigit = true; + size_t hasBraces = 0; + size_t index = 0; + + std::array data{{0}}; + + if (str.empty()) + return {}; + + if (str.front() == '{') + hasBraces = 1; + if (hasBraces && str.back() != '}') + return {}; + + for (size_t i = hasBraces; i < str.size() - hasBraces; ++i) + { + if (str[i] == '-') + continue; + + if (index >= 16 || !detail::is_hex(str[i])) + { + return {}; + } + + if (firstDigit) + { + data[index] = static_cast(detail::hex2char(str[i]) << 4); + firstDigit = false; + } + else + { + data[index] = + static_cast(data[index] | detail::hex2char(str[i])); + index++; + firstDigit = true; + } + } + + if (index < 16) + { + return {}; + } + + return uuid{data}; + } + + private: + std::array data{{0}}; + + friend bool operator==(uuid const& lhs, uuid const& rhs) noexcept; + friend bool operator<(uuid const& lhs, uuid const& rhs) noexcept; + + template + friend std::basic_ostream& operator<<( + std::basic_ostream& s, uuid const& id); + + template + friend std::basic_string to_string(uuid const& id); + + friend std::hash; + }; + + // -------------------------------------------------------------------------------------------------------------------------- + // operators and non-member functions + // -------------------------------------------------------------------------------------------------------------------------- + + [[nodiscard]] inline bool operator==(uuid const& lhs, + uuid const& rhs) noexcept + { + return lhs.data == rhs.data; + } + + [[nodiscard]] inline bool operator!=(uuid const& lhs, + uuid const& rhs) noexcept + { + return !(lhs == rhs); + } + + [[nodiscard]] inline bool operator<(uuid const& lhs, uuid const& rhs) noexcept + { + return lhs.data < rhs.data; + } + + template + [[nodiscard]] inline std::basic_string to_string( + uuid const& id) + { + std::basic_string uustr{detail::empty_guid}; + + for (size_t i = 0, index = 0; i < 36; ++i) + { + if (i == 8 || i == 13 || i == 18 || i == 23) + { + continue; + } + uustr[i] = detail::guid_encoder[id.data[index] >> 4 & 0x0f]; + uustr[++i] = detail::guid_encoder[id.data[index] & 0x0f]; + index++; + } + + return uustr; + } + + template + std::basic_ostream& operator<<( + std::basic_ostream& s, uuid const& id) + { + s << to_string(id); + return s; + } + + inline void swap(uuids::uuid& lhs, uuids::uuid& rhs) noexcept + { + lhs.swap(rhs); + } + + // -------------------------------------------------------------------------------------------------------------------------- + // namespace IDs that could be used for generating name-based uuids + // -------------------------------------------------------------------------------------------------------------------------- + + // Name string is a fully-qualified domain name + static uuid uuid_namespace_dns{{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // Name string is a URL + static uuid uuid_namespace_url{{0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // Name string is an ISO OID (See https://oidref.com/, + // https://en.wikipedia.org/wiki/Object_identifier) + static uuid uuid_namespace_oid{{0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // Name string is an X.500 DN, in DER or a text output format (See + // https://en.wikipedia.org/wiki/X.500, + // https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One) + static uuid uuid_namespace_x500{{0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, + 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, + 0xc8}}; + + // -------------------------------------------------------------------------------------------------------------------------- + // uuid generators + // -------------------------------------------------------------------------------------------------------------------------- + +#ifdef UUID_SYSTEM_GENERATOR + class uuid_system_generator + { + public: + using result_type = uuid; + + uuid operator()() + { +#ifdef _WIN32 + + GUID newId; + HRESULT hr = ::CoCreateGuid(&newId); + + if (FAILED(hr)) + { + throw std::system_error(hr, std::system_category(), + "CoCreateGuid failed"); + } + + std::array bytes = { + {static_cast((newId.Data1 >> 24) & 0xFF), + static_cast((newId.Data1 >> 16) & 0xFF), + static_cast((newId.Data1 >> 8) & 0xFF), + static_cast((newId.Data1) & 0xFF), + + (unsigned char)((newId.Data2 >> 8) & 0xFF), + (unsigned char)((newId.Data2) & 0xFF), + + (unsigned char)((newId.Data3 >> 8) & 0xFF), + (unsigned char)((newId.Data3) & 0xFF), + + newId.Data4[0], newId.Data4[1], newId.Data4[2], newId.Data4[3], + newId.Data4[4], newId.Data4[5], newId.Data4[6], newId.Data4[7]}}; + + return uuid{std::begin(bytes), std::end(bytes)}; + +#elif defined(__linux__) || defined(__unix__) + + uuid_t id; + uuid_generate(id); + + std::array bytes = {{id[0], id[1], id[2], id[3], id[4], id[5], + id[6], id[7], id[8], id[9], id[10], + id[11], id[12], id[13], id[14], id[15]}}; + + return uuid{std::begin(bytes), std::end(bytes)}; + +#elif defined(__APPLE__) + auto newId = CFUUIDCreate(NULL); + auto bytes = CFUUIDGetUUIDBytes(newId); + CFRelease(newId); + + std::array arrbytes = { + {bytes.byte0, bytes.byte1, bytes.byte2, bytes.byte3, bytes.byte4, + bytes.byte5, bytes.byte6, bytes.byte7, bytes.byte8, bytes.byte9, + bytes.byte10, bytes.byte11, bytes.byte12, bytes.byte13, bytes.byte14, + bytes.byte15}}; + return uuid{std::begin(arrbytes), std::end(arrbytes)}; +#else + return uuid{}; +#endif + } + }; +#endif + + template + class basic_uuid_random_generator + { + public: + using engine_type = UniformRandomNumberGenerator; + + explicit basic_uuid_random_generator(engine_type& gen) + : generator(&gen, [](auto) {}) + { + } + explicit basic_uuid_random_generator(engine_type* gen) + : generator(gen, [](auto) {}) + { + } + + [[nodiscard]] uuid operator()() + { + alignas(uint32_t) uint8_t bytes[16]; + for (int i = 0; i < 16; i += 4) + *reinterpret_cast(bytes + i) = distribution(*generator); + + // variant must be 10xxxxxx + bytes[8] &= 0xBF; + bytes[8] |= 0x80; + + // version must be 0100xxxx + bytes[6] &= 0x4F; + bytes[6] |= 0x40; + + return uuid{std::begin(bytes), std::end(bytes)}; + } + + private: + std::uniform_int_distribution distribution; + std::shared_ptr generator; + }; + + using uuid_random_generator = basic_uuid_random_generator; + + class uuid_name_generator + { + public: + explicit uuid_name_generator(uuid const& namespace_uuid) noexcept + : nsuuid(namespace_uuid) + { + } + + template + [[nodiscard]] uuid operator()(StringType const& name) + { + reset(); + process_characters(detail::to_string_view(name)); + return make_uuid(); + } + + private: + void reset() + { + hasher.reset(); + std::byte bytes[16]; + auto nsbytes = nsuuid.as_bytes(); + std::copy(std::cbegin(nsbytes), std::cend(nsbytes), bytes); + hasher.process_bytes(bytes, 16); + } + + template + void process_characters(std::basic_string_view const str) + { + for (uint32_t c : str) + { + hasher.process_byte(static_cast(c & 0xFF)); + if constexpr (!std::is_same_v) + { + hasher.process_byte(static_cast((c >> 8) & 0xFF)); + hasher.process_byte(static_cast((c >> 16) & 0xFF)); + hasher.process_byte(static_cast((c >> 24) & 0xFF)); + } + } + } + + [[nodiscard]] uuid make_uuid() + { + detail::sha1::digest8_t digest; + hasher.get_digest_bytes(digest); + + // variant must be 0b10xxxxxx + digest[8] &= 0xBF; + digest[8] |= 0x80; + + // version must be 0b0101xxxx + digest[6] &= 0x5F; + digest[6] |= 0x50; + + return uuid{digest, digest + 16}; + } + + private: + uuid nsuuid; + detail::sha1 hasher; + }; + +#ifdef UUID_TIME_GENERATOR + // !!! DO NOT USE THIS IN PRODUCTION + // this implementation is unreliable for good uuids + class uuid_time_generator + { + using mac_address = std::array; + + std::optional device_address; + + [[nodiscard]] bool get_mac_address() + { + if (device_address.has_value()) + { + return true; + } + +#ifdef _WIN32 + DWORD len = 0; + auto ret = GetAdaptersInfo(nullptr, &len); + if (ret != ERROR_BUFFER_OVERFLOW) + return false; + std::vector buf(len); + auto pips = reinterpret_cast(&buf.front()); + ret = GetAdaptersInfo(pips, &len); + if (ret != ERROR_SUCCESS) + return false; + mac_address addr; + std::copy(pips->Address, pips->Address + 6, std::begin(addr)); + device_address = addr; +#endif + + return device_address.has_value(); + } + + [[nodiscard]] long long get_time_intervals() + { + auto start = std::chrono::system_clock::from_time_t(time_t(-12219292800)); + auto diff = std::chrono::system_clock::now() - start; + auto ns = + std::chrono::duration_cast(diff).count(); + return ns / 100; + } + + [[nodiscard]] static unsigned short get_clock_sequence() + { + static std::mt19937 clock_gen(std::random_device{}()); + static std::uniform_int_distribution clock_dis; + static std::atomic_ushort clock_sequence = clock_dis(clock_gen); + return clock_sequence++; + } + + public: + [[nodiscard]] uuid operator()() + { + if (get_mac_address()) + { + std::array data; + + auto tm = get_time_intervals(); + + auto clock_seq = get_clock_sequence(); + + auto ptm = reinterpret_cast(&tm); + + memcpy(&data[0], ptm + 4, 4); + memcpy(&data[4], ptm + 2, 2); + memcpy(&data[6], ptm, 2); + + memcpy(&data[8], &clock_seq, 2); + + // variant must be 0b10xxxxxx + data[8] &= 0xBF; + data[8] |= 0x80; + + // version must be 0b0001xxxx + data[6] &= 0x1F; + data[6] |= 0x10; + + memcpy(&data[10], &device_address.value()[0], 6); + + return uuids::uuid{std::cbegin(data), std::cend(data)}; + } + + return {}; + } + }; +#endif +} // namespace uuids + +namespace std +{ + template <> + struct hash + { + using argument_type = uuids::uuid; + using result_type = std::size_t; + + [[nodiscard]] result_type operator()(argument_type const& uuid) const + { +#ifdef UUID_HASH_STRING_BASED + std::hash hasher; + return static_cast(hasher(uuids::to_string(uuid))); +#else + uint64_t l = static_cast(uuid.data[0]) << 56 | + static_cast(uuid.data[1]) << 48 | + static_cast(uuid.data[2]) << 40 | + static_cast(uuid.data[3]) << 32 | + static_cast(uuid.data[4]) << 24 | + static_cast(uuid.data[5]) << 16 | + static_cast(uuid.data[6]) << 8 | + static_cast(uuid.data[7]); + uint64_t h = static_cast(uuid.data[8]) << 56 | + static_cast(uuid.data[9]) << 48 | + static_cast(uuid.data[10]) << 40 | + static_cast(uuid.data[11]) << 32 | + static_cast(uuid.data[12]) << 24 | + static_cast(uuid.data[13]) << 16 | + static_cast(uuid.data[14]) << 8 | + static_cast(uuid.data[15]); + + if constexpr (sizeof(result_type) > 4) + { + return result_type(l ^ h); + } + else + { + uint64_t hash64 = l ^ h; + return result_type(uint32_t(hash64 >> 32) ^ uint32_t(hash64)); + } +#endif + } + }; +} // namespace std + +#endif /* STDUUID_H */ \ No newline at end of file diff --git a/Headers/Version.hxx b/Headers/Version.hxx new file mode 100644 index 0000000..639c2c6 --- /dev/null +++ b/Headers/Version.hxx @@ -0,0 +1,3 @@ +#pragma once + +#define kDistVersion "v1.22" diff --git a/Notes/ASM specs.txt b/Notes/ASM specs.txt new file mode 100644 index 0000000..a0c42bf --- /dev/null +++ b/Notes/ASM specs.txt @@ -0,0 +1,11 @@ +==================== +X86 ASSEMBLER SPECS +==================== + +WHAT TO DO: + Provide a complete support of x86-64 with: + + - org directive. + - 64-bit and 32-bit registers. + - basic instructions (load, store, jump to) + - flushable into object-code and flat binary. \ No newline at end of file diff --git a/Notes/HAVP DSP.txt b/Notes/HAVP DSP.txt new file mode 100644 index 0000000..12fcec5 --- /dev/null +++ b/Notes/HAVP DSP.txt @@ -0,0 +1,13 @@ +HAVP - Harvard Audio/Video Processor + +- Encoding: IBAD + +- Data path = 24 + - 16: sound data + - 8: information data + +- Register size: 32 +- Store strategy: shift registers. +- Standard registers: [ r0, r9 ] +- Floating point registers: [ f0, f2 ] +- Builtin SRAM: 512kb diff --git a/Notes/Notice.txt b/Notes/Notice.txt new file mode 100644 index 0000000..23691da --- /dev/null +++ b/Notes/Notice.txt @@ -0,0 +1,4 @@ +The X64000 draft papers +They contain thing that might appear through the next iteration of 64k. + +Please look at the document shared for the latest revisions. \ No newline at end of file diff --git a/Notes/RISC CPU.txt b/Notes/RISC CPU.txt new file mode 100644 index 0000000..e17b494 --- /dev/null +++ b/Notes/RISC CPU.txt @@ -0,0 +1,17 @@ +VNRP - Von Neumann, RISC Processor + +- Encoding = RegToReg, Imm, Syscall, Jump, NoArgs + +- Data path = 128-bit (register data) +- Addressing = 58-bit physical address size. + +- Registers (128-bit) = r0, r19 +- Float/Vector registers (128-bit) = f0, f9 + +- Out of order (superscalar also added to the equation) = Yes +- Superscalar = Yes + +- L1 cache: 16kb (8 instr, 8 data) +- L2 cache: 1024kb (512 instr, 512 data) + +- Clock speed: 1 Ghz diff --git a/Notes/asm-specs.txt b/Notes/asm-specs.txt deleted file mode 100644 index a0c42bf..0000000 --- a/Notes/asm-specs.txt +++ /dev/null @@ -1,11 +0,0 @@ -==================== -X86 ASSEMBLER SPECS -==================== - -WHAT TO DO: - Provide a complete support of x86-64 with: - - - org directive. - - 64-bit and 32-bit registers. - - basic instructions (load, store, jump to) - - flushable into object-code and flat binary. \ No newline at end of file diff --git a/Notes/havp.txt b/Notes/havp.txt deleted file mode 100644 index 12fcec5..0000000 --- a/Notes/havp.txt +++ /dev/null @@ -1,13 +0,0 @@ -HAVP - Harvard Audio/Video Processor - -- Encoding: IBAD - -- Data path = 24 - - 16: sound data - - 8: information data - -- Register size: 32 -- Store strategy: shift registers. -- Standard registers: [ r0, r9 ] -- Floating point registers: [ f0, f2 ] -- Builtin SRAM: 512kb diff --git a/Notes/notice.txt b/Notes/notice.txt deleted file mode 100644 index 23691da..0000000 --- a/Notes/notice.txt +++ /dev/null @@ -1,4 +0,0 @@ -The X64000 draft papers -They contain thing that might appear through the next iteration of 64k. - -Please look at the document shared for the latest revisions. \ No newline at end of file diff --git a/Notes/vnrp.txt b/Notes/vnrp.txt deleted file mode 100644 index e17b494..0000000 --- a/Notes/vnrp.txt +++ /dev/null @@ -1,17 +0,0 @@ -VNRP - Von Neumann, RISC Processor - -- Encoding = RegToReg, Imm, Syscall, Jump, NoArgs - -- Data path = 128-bit (register data) -- Addressing = 58-bit physical address size. - -- Registers (128-bit) = r0, r19 -- Float/Vector registers (128-bit) = f0, f9 - -- Out of order (superscalar also added to the equation) = Yes -- Superscalar = Yes - -- L1 cache: 16kb (8 instr, 8 data) -- L2 cache: 1024kb (512 instr, 512 data) - -- Clock speed: 1 Ghz diff --git a/Sources/32asm.cc b/Sources/32asm.cc deleted file mode 100644 index d32ab0b..0000000 --- a/Sources/32asm.cc +++ /dev/null @@ -1,52 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -/// bugs: 0 - -///////////////////////////////////////////////////////////////////////////////////////// - -// @file 32asm.cxx -// @author ZKA Technologies -// @brief 32x0 Assembler. - -// REMINDER: when dealing with an undefined symbol use (string -// size):LinkerFindSymbol:(string) so that ld will look for it. - -///////////////////////////////////////////////////////////////////////////////////////// - -#define __ASM_NEED_32x0__ 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -///////////////////// - -// ANSI ESCAPE CODES - -///////////////////// - -#define kBlank "\e[0;30m" -#define kRed "\e[0;31m" -#define kWhite "\e[0;97m" -#define kYellow "\e[0;33m" - -#define kStdOut (std::cout << kWhite) -#define kStdErr (std::cout << kRed) - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief 32x0 Assembler entrypoint, the program/module starts here. - -///////////////////////////////////////////////////////////////////////////////////////// - -NDK_MODULE(NewOSAssembler32000) { return 0; } diff --git a/Sources/32asm.cxx b/Sources/32asm.cxx new file mode 100644 index 0000000..8577722 --- /dev/null +++ b/Sources/32asm.cxx @@ -0,0 +1,52 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +/// bugs: 0 + +///////////////////////////////////////////////////////////////////////////////////////// + +// @file 32asm.cxx +// @author ZKA Technologies +// @brief 32x0 Assembler. + +// REMINDER: when dealing with an undefined symbol use (string +// size):LinkerFindSymbol:(string) so that ld will look for it. + +///////////////////////////////////////////////////////////////////////////////////////// + +#define __ASM_NEED_32x0__ 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +///////////////////// + +// ANSI ESCAPE CODES + +///////////////////// + +#define kBlank "\e[0;30m" +#define kRed "\e[0;31m" +#define kWhite "\e[0;97m" +#define kYellow "\e[0;33m" + +#define kStdOut (std::cout << kWhite) +#define kStdErr (std::cout << kRed) + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief 32x0 Assembler entrypoint, the program/module starts here. + +///////////////////////////////////////////////////////////////////////////////////////// + +NDK_MODULE(NewOSAssembler32000) { return 0; } diff --git a/Sources/64asm.cc b/Sources/64asm.cc deleted file mode 100644 index 0a89e6a..0000000 --- a/Sources/64asm.cc +++ /dev/null @@ -1,954 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -/// bugs: 0 - -///////////////////////////////////////////////////////////////////////////////////////// - -// @file 64asm.cxx -// @author Amlal EL Mahrouss -// @brief 64x000 Assembler. - -// REMINDER: when dealing with an undefined symbol use (string -// size):LinkerFindSymbol:(string) so that ld will look for it. - -///////////////////////////////////////////////////////////////////////////////////////// - -#define __ASM_NEED_64x0__ 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -///////////////////// - -// ANSI ESCAPE CODES - -///////////////////// - -#define kBlank "\e[0;30m" -#define kRed "\e[0;31m" -#define kWhite "\e[0;97m" -#define kYellow "\e[0;33m" - -#define kStdOut (std::cout << kWhite) -#define kStdErr (std::cout << kRed) - -static char kOutputArch = CompilerKit::kPefArch64000; -static Boolean kOutputAsBinary = false; - -static UInt32 kErrorLimit = 10; -static UInt32 kAcceptableErrors = 0; - -constexpr auto c64x0IPAlignment = 0x4U; - -static std::size_t kCounter = 1UL; - -static std::uintptr_t kOrigin = kPefBaseOrigin; -static std::vector> kOriginLabel; - -static bool kVerbose = false; - -static std::vector kBytes; - -static CompilerKit::AERecordHeader kCurrentRecord{ - .fName = "", .fKind = CompilerKit::kPefCode, .fSize = 0, .fOffset = 0}; - -static std::vector kRecords; -static std::vector kUndefinedSymbols; - -static const std::string kUndefinedSymbol = ":UndefinedSymbol:"; -static const std::string kRelocSymbol = ":RuntimeSymbol:"; - -// \brief forward decl. -static bool asm_read_attributes(std::string &line); - -namespace detail { -void print_error(std::string reason, const std::string &file) noexcept { - if (reason[0] == '\n') reason.erase(0, 1); - - kStdErr << kRed << "[ 64asm ] " << kWhite - << ((file == "64asm") ? "internal assembler error " - : ("in file, " + file)) - << kBlank << std::endl; - kStdErr << kRed << "[ 64asm ] " << kWhite << reason << kBlank << std::endl; - - if (kAcceptableErrors > kErrorLimit) std::exit(3); - - ++kAcceptableErrors; -} - -void print_warning(std::string reason, const std::string &file) noexcept { - if (reason[0] == '\n') reason.erase(0, 1); - - if (!file.empty()) { - kStdOut << kYellow << "[ file ] " << kWhite << file << kBlank << std::endl; - } - - kStdOut << kYellow << "[ 64asm ] " << kWhite << reason << kBlank << std::endl; -} -} // namespace detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief 64x0 assembler entrypoint, the program/module starts here. - -///////////////////////////////////////////////////////////////////////////////////////// - -NDK_MODULE(NewOSAssembler64000) { - for (size_t i = 1; i < argc; ++i) { - if (argv[i][0] == '-') { - if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { - kStdOut << "64asm: 64x0 Assembler.\n64asm: v1.10\n64asm: Copyright (c) " - "ZKA Technologies.\n"; - return 0; - } else if (strcmp(argv[i], "-h") == 0) { - kStdOut << "64asm: 64x0 Assembler.\n64asm: Copyright (c) 2024 Mahrouss " - "Logic.\n"; - kStdOut << "-version: Print program version.\n"; - kStdOut << "-verbose: Print verbose output.\n"; - kStdOut << "-binary: Output as flat binary.\n"; - kStdOut << "-64xxx: Compile for a subset of the X64000.\n"; - - return 0; - } else if (strcmp(argv[i], "-binary") == 0) { - kOutputAsBinary = true; - continue; - } else if (strcmp(argv[i], "-verbose") == 0) { - kVerbose = true; - continue; - } - - kStdOut << "64asm: ignore " << argv[i] << "\n"; - continue; - } - - if (!std::filesystem::exists(argv[i])) { - kStdOut << "64asm: can't open: " << argv[i] << std::endl; - goto asm_fail_exit; - } - - std::string object_output(argv[i]); - - for (auto &ext : kAsmFileExts) { - if (object_output.find(ext) != std::string::npos) { - object_output.erase(object_output.find(ext), std::strlen(ext)); - } - } - - object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt; - - std::ifstream file_ptr(argv[i]); - std::ofstream file_ptr_out(object_output, std::ofstream::binary); - - if (file_ptr_out.bad()) { - if (kVerbose) { - kStdOut << "64asm: error: " << strerror(errno) << "\n"; - } - } - - std::string line; - - CompilerKit::AEHeader hdr{0}; - - memset(hdr.fPad, kAEInvalidOpcode, kAEPad); - - hdr.fMagic[0] = kAEMag0; - hdr.fMagic[1] = kAEMag1; - hdr.fSize = sizeof(CompilerKit::AEHeader); - hdr.fArch = kOutputArch; - - ///////////////////////////////////////////////////////////////////////////////////////// - - // COMPILATION LOOP - - ///////////////////////////////////////////////////////////////////////////////////////// - - CompilerKit::Encoder64x0 asm64; - - while (std::getline(file_ptr, line)) { - if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) { - detail::print_error(ln, argv[i]); - continue; - } - - try { - asm_read_attributes(line); - asm64.WriteLine(line, argv[i]); - } catch (const std::exception &e) { - if (kVerbose) { - std::string what = e.what(); - detail::print_warning("exit because of: " + what, "64asm"); - } - - std::filesystem::remove(object_output); - goto asm_fail_exit; - } - } - - if (!kOutputAsBinary) { - if (kVerbose) { - kStdOut << "64asm: Writing object file...\n"; - } - - // this is the final step, write everything to the file. - - auto pos = file_ptr_out.tellp(); - - hdr.fCount = kRecords.size() + kUndefinedSymbols.size(); - - file_ptr_out << hdr; - - if (kRecords.empty()) { - kStdErr << "64asm: At least one record is needed to write an object " - "file.\n64asm: Make one using `export .code64 foo_bar`.\n"; - - std::filesystem::remove(object_output); - return -1; - } - - kRecords[kRecords.size() - 1].fSize = kBytes.size(); - - std::size_t record_count = 0UL; - - for (auto &rec : kRecords) { - if (kVerbose) - kStdOut << "64asm: Wrote record " << rec.fName << " to file...\n"; - - rec.fFlags |= CompilerKit::kKindRelocationAtRuntime; - rec.fOffset = record_count; - ++record_count; - - file_ptr_out << rec; - } - - // increment once again, so that we won't lie about the kUndefinedSymbols. - ++record_count; - - for (auto &sym : kUndefinedSymbols) { - CompilerKit::AERecordHeader _record_hdr{0}; - - if (kVerbose) - kStdOut << "64asm: Wrote symbol " << sym << " to file...\n"; - - _record_hdr.fKind = kAEInvalidOpcode; - _record_hdr.fSize = sym.size(); - _record_hdr.fOffset = record_count; - - ++record_count; - - memset(_record_hdr.fPad, kAEInvalidOpcode, kAEPad); - memcpy(_record_hdr.fName, sym.c_str(), sym.size()); - - file_ptr_out << _record_hdr; - - ++kCounter; - } - - auto pos_end = file_ptr_out.tellp(); - - file_ptr_out.seekp(pos); - - hdr.fStartCode = pos_end; - hdr.fCodeSize = kBytes.size(); - - file_ptr_out << hdr; - - file_ptr_out.seekp(pos_end); - } else { - if (kVerbose) { - kStdOut << "64asm: Write raw binary...\n"; - } - } - - // byte from byte, we write this. - for (auto &byte : kBytes) { - file_ptr_out.write(reinterpret_cast(&byte), sizeof(byte)); - } - - if (kVerbose) kStdOut << "64asm: Wrote file with program in it.\n"; - - file_ptr_out.flush(); - file_ptr_out.close(); - - if (kVerbose) kStdOut << "64asm: Exit succeeded.\n"; - - return 0; - } - -asm_fail_exit: - - if (kVerbose) kStdOut << "64asm: Exit failed.\n"; - - return -1; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief Check for attributes -// returns true if any was found. - -///////////////////////////////////////////////////////////////////////////////////////// - -static bool asm_read_attributes(std::string &line) { - // import is the opposite of export, it signals to the ld - // that we need this symbol. - if (ParserKit::find_word(line, "import")) { - if (kOutputAsBinary) { - detail::print_error("Invalid import directive in flat binary mode.", - "64asm"); - throw std::runtime_error("invalid_import_bin"); - } - - auto name = line.substr(line.find("import") + strlen("import")); - - /// sanity check to avoid stupid linker errors. - if (name.size() == 0) { - detail::print_error("Invalid import", "ppcasm"); - throw std::runtime_error("invalid_import"); - } - - std::string result = std::to_string(name.size()); - result += kUndefinedSymbol; - - // mangle this - for (char &j : name) { - if (j == ' ' || j == ',') j = '$'; - } - - result += name; - - if (name.find(".code64") != std::string::npos) { - // data is treated as code. - kCurrentRecord.fKind = CompilerKit::kPefCode; - } else if (name.find(".data64") != std::string::npos) { - // no code will be executed from here. - kCurrentRecord.fKind = CompilerKit::kPefData; - } else if (name.find(".zero64") != std::string::npos) { - // this is a bss section. - kCurrentRecord.fKind = CompilerKit::kPefZero; - } - - // this is a special case for the start stub. - // we want this so that ld can find it. - - if (name == kPefStart) { - kCurrentRecord.fKind = CompilerKit::kPefCode; - } - - // now we can tell the code size of the previous kCurrentRecord. - - if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); - - memset(kCurrentRecord.fName, 0, kAESymbolLen); - memcpy(kCurrentRecord.fName, result.c_str(), result.size()); - - ++kCounter; - - memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); - - kRecords.emplace_back(kCurrentRecord); - - return true; - } - // export is a special keyword used by 64asm to tell the AE output stage to - // mark this section as a header. it currently supports .code64, .data64., - // .zero64 - else if (ParserKit::find_word(line, "export")) { - if (kOutputAsBinary) { - detail::print_error("Invalid export directive in flat binary mode.", - "64asm"); - throw std::runtime_error("invalid_export_bin"); - } - - auto name = line.substr(line.find("export") + strlen("export")); - - std::string name_copy = name; - - for (char &j : name) { - if (j == ' ') j = '$'; - } - - if (name.find(".code64") != std::string::npos) { - // data is treated as code. - - name_copy.erase(name_copy.find(".code64"), strlen(".code64")); - kCurrentRecord.fKind = CompilerKit::kPefCode; - } else if (name.find(".data64") != std::string::npos) { - // no code will be executed from here. - - name_copy.erase(name_copy.find(".data64"), strlen(".data64")); - kCurrentRecord.fKind = CompilerKit::kPefData; - } else if (name.find(".zero64") != std::string::npos) { - // this is a bss section. - - name_copy.erase(name_copy.find(".zero64"), strlen(".zero64")); - kCurrentRecord.fKind = CompilerKit::kPefZero; - } - - // this is a special case for the start stub. - // we want this so that ld can find it. - - if (name == kPefStart) { - kCurrentRecord.fKind = CompilerKit::kPefCode; - } - - while (name_copy.find(" ") != std::string::npos) - name_copy.erase(name_copy.find(" "), 1); - - kOriginLabel.push_back(std::make_pair(name_copy, kOrigin)); - ++kOrigin; - - // now we can tell the code size of the previous kCurrentRecord. - - if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); - - memset(kCurrentRecord.fName, 0, kAESymbolLen); - memcpy(kCurrentRecord.fName, name.c_str(), name.size()); - - ++kCounter; - - memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); - - kRecords.emplace_back(kCurrentRecord); - - return true; - } - - return false; -} - -// \brief algorithms and helpers. - -namespace detail::algorithm { -// \brief authorize a brief set of characters. -static inline bool is_not_alnum_space(char c) { - return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || - (c == ',') || (c == '(') || (c == ')') || (c == '"') || - (c == '\'') || (c == '[') || (c == ']') || (c == '+') || - (c == '_') || (c == ':') || (c == '@') || (c == '.')); -} - -bool is_valid(const std::string &str) { - return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); -} -} // namespace detail::algorithm - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief Check for line (syntax check) - -///////////////////////////////////////////////////////////////////////////////////////// - -std::string CompilerKit::Encoder64x0::CheckLine(std::string &line, - const std::string &file) { - std::string err_str; - - if (line.empty() || ParserKit::find_word(line, "import") || - ParserKit::find_word(line, "export") || - line.find('#') != std::string::npos || ParserKit::find_word(line, ";")) { - if (line.find('#') != std::string::npos) { - line.erase(line.find('#')); - } else if (line.find(';') != std::string::npos) { - line.erase(line.find(';')); - } else { - // now check the line for validity - if (!detail::algorithm::is_valid(line)) { - err_str = "Line contains non alphanumeric characters.\nhere -> "; - err_str += line; - } - } - - return err_str; - } - - if (!detail::algorithm::is_valid(line)) { - err_str = "Line contains non alphanumeric characters.\nhere -> "; - err_str += line; - - return err_str; - } - - // check for a valid instruction format. - - if (line.find(',') != std::string::npos) { - if (line.find(',') + 1 == line.size()) { - err_str += "\nInstruction lacks right register, here -> "; - err_str += line.substr(line.find(',')); - - return err_str; - } else { - bool nothing_on_right = true; - - if (line.find(',') + 1 > line.size()) { - err_str += "\nInstruction not complete, here -> "; - err_str += line; - - return err_str; - } - - auto substr = line.substr(line.find(',') + 1); - - for (auto &ch : substr) { - if (ch != ' ' && ch != '\t') { - nothing_on_right = false; - } - } - - // this means we found nothing after that ',' . - if (nothing_on_right) { - err_str += "\nInstruction not complete, here -> "; - err_str += line; - - return err_str; - } - } - } - - // these do take an argument. - std::vector operands_inst = {"stw", "ldw", "lda", "sta"}; - - // these don't. - std::vector filter_inst = {"jlr", "jrl", "int"}; - - for (auto &opcode64x0 : kOpcodes64x0) { - if (line.find(opcode64x0.fName) != std::string::npos) { - if (opcode64x0.fFunct7 == kAsmNoArgs) return err_str; - - for (auto &op : operands_inst) { - // if only the instruction was found. - if (line == op) { - err_str += "\nMalformed "; - err_str += op; - err_str += " instruction, here -> "; - err_str += line; - } - } - - // if it is like that -> addr1, 0x0 - if (auto it = std::find(filter_inst.begin(), filter_inst.end(), - opcode64x0.fName); - it == filter_inst.cend()) { - if (ParserKit::find_word(line, opcode64x0.fName)) { - if (!isspace(line[line.find(opcode64x0.fName) + - strlen(opcode64x0.fName)])) { - err_str += "\nMissing space between "; - err_str += opcode64x0.fName; - err_str += " and operands.\nhere -> "; - err_str += line; - } - } - } - - return err_str; - } - } - - err_str += "Unrecognized instruction: " + line; - - return err_str; -} - -bool CompilerKit::Encoder64x0::WriteNumber(const std::size_t &pos, - std::string &jump_label) { - if (!isdigit(jump_label[pos])) return false; - - switch (jump_label[pos + 1]) { - case 'x': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); - !res) { - if (errno != 0) { - detail::print_error("invalid hex number: " + jump_label, "64asm"); - throw std::runtime_error("invalid_hex_number"); - } - } - - CompilerKit::NumberCast64 num( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16)); - - for (char &i : num.number) { - kBytes.push_back(i); - } - - if (kVerbose) { - kStdOut << "64asm: found a base 16 number here: " - << jump_label.substr(pos) << "\n"; - } - - return true; - } - case 'b': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); - !res) { - if (errno != 0) { - detail::print_error("invalid binary number: " + jump_label, "64asm"); - throw std::runtime_error("invalid_bin"); - } - } - - CompilerKit::NumberCast64 num( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2)); - - if (kVerbose) { - kStdOut << "64asm: found a base 2 number here: " - << jump_label.substr(pos) << "\n"; - } - - for (char &i : num.number) { - kBytes.push_back(i); - } - - return true; - } - case 'o': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); - !res) { - if (errno != 0) { - detail::print_error("invalid octal number: " + jump_label, "64asm"); - throw std::runtime_error("invalid_octal"); - } - } - - CompilerKit::NumberCast64 num( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7)); - - if (kVerbose) { - kStdOut << "64asm: found a base 8 number here: " - << jump_label.substr(pos) << "\n"; - } - - for (char &i : num.number) { - kBytes.push_back(i); - } - - return true; - } - default: { - break; - } - } - - /* check for errno and stuff like that */ - if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) { - if (errno != 0) { - return false; - } - } - - CompilerKit::NumberCast64 num( - strtol(jump_label.substr(pos).c_str(), nullptr, 10)); - - for (char &i : num.number) { - kBytes.push_back(i); - } - - if (kVerbose) { - kStdOut << "64asm: found a base 10 number here: " << jump_label.substr(pos) - << "\n"; - } - - return true; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief Read and write an instruction to the output array. - -///////////////////////////////////////////////////////////////////////////////////////// - -bool CompilerKit::Encoder64x0::WriteLine(std::string &line, - const std::string &file) { - if (ParserKit::find_word(line, "export ")) return true; - - for (auto &opcode64x0 : kOpcodes64x0) { - // strict check here - if (ParserKit::find_word(line, opcode64x0.fName) && - detail::algorithm::is_valid(line)) { - std::string name(opcode64x0.fName); - std::string jump_label, cpy_jump_label; - - kBytes.emplace_back(opcode64x0.fOpcode); - kBytes.emplace_back(opcode64x0.fFunct3); - kBytes.emplace_back(opcode64x0.fFunct7); - - // check funct7 type. - switch (opcode64x0.fFunct7) { - // reg to reg means register to register transfer operation. - case kAsmRegToReg: - case kAsmImmediate: { - // \brief how many registers we found. - std::size_t found_some = 0UL; - - for (size_t line_index = 0UL; line_index < line.size(); - line_index++) { - if (line[line_index] == kAsmRegisterPrefix[0] && - isdigit(line[line_index + 1])) { - std::string register_syntax = kAsmRegisterPrefix; - register_syntax += line[line_index + 1]; - - if (isdigit(line[line_index + 2])) - register_syntax += line[line_index + 2]; - - std::string reg_str; - reg_str += line[line_index + 1]; - - if (isdigit(line[line_index + 2])) - reg_str += line[line_index + 2]; - - // it ranges from r0 to r19 - // something like r190 doesn't exist in the instruction set. - if (kOutputArch == CompilerKit::kPefArch64000) { - if (isdigit(line[line_index + 3]) && - isdigit(line[line_index + 2])) { - reg_str += line[line_index + 3]; - detail::print_error( - "invalid register index, r" + reg_str + - "\nnote: The 64x0 accepts registers from r0 to r20.", - file); - throw std::runtime_error("invalid_register_index"); - } - } - - // finally cast to a size_t - std::size_t reg_index = strtol(reg_str.c_str(), nullptr, 10); - - if (reg_index > kAsmRegisterLimit) { - detail::print_error("invalid register index, r" + reg_str, - file); - throw std::runtime_error("invalid_register_index"); - } - - kBytes.emplace_back(reg_index); - ++found_some; - - if (kVerbose) { - kStdOut << "64asm: Register found: " << register_syntax << "\n"; - kStdOut << "64asm: Register amount in instruction: " - << found_some << "\n"; - } - } - } - - // we're not in immediate addressing, reg to reg. - if (opcode64x0.fFunct7 != kAsmImmediate) { - // remember! register to register! - if (found_some == 1) { - detail::print_error( - "Too few registers.\ntip: each 64asm register " - "starts with 'r'.\nline: " + - line, - file); - throw std::runtime_error("not_a_register"); - } - } - - if (found_some < 1 && name != "ldw" && name != "lda" && - name != "stw") { - detail::print_error( - "invalid combination of opcode and registers.\nline: " + line, - file); - throw std::runtime_error("invalid_comb_op_reg"); - } else if (found_some == 1 && name == "add") { - detail::print_error( - "invalid combination of opcode and registers.\nline: " + line, - file); - throw std::runtime_error("invalid_comb_op_reg"); - } else if (found_some == 1 && name == "sub") { - detail::print_error( - "invalid combination of opcode and registers.\nline: " + line, - file); - throw std::runtime_error("invalid_comb_op_reg"); - } - - if (found_some > 0 && name == "pop") { - detail::print_error( - "invalid combination for opcode 'pop'.\ntip: it expects " - "nothing.\nline: " + - line, - file); - throw std::runtime_error("invalid_comb_op_pop"); - } - } - default: - break; - } - - // try to fetch a number from the name - if (name == "stw" || name == "ldw" || name == "lda" || name == "sta") { - auto where_string = name; - - // if we load something, we'd need it's symbol/literal - if (name == "stw" || name == "sta" || name == "ldw" || name == "lda" || - name == "sta") - where_string = ","; - - jump_label = line; - - auto found_sym = false; - - while (jump_label.find(where_string) != std::string::npos) { - jump_label = jump_label.substr(jump_label.find(where_string) + - where_string.size()); - - while (jump_label.find(" ") != std::string::npos) { - jump_label.erase(jump_label.find(" "), 1); - } - - if (jump_label[0] != kAsmRegisterPrefix[0] && - !isdigit(jump_label[1])) { - if (found_sym) { - detail::print_error( - "invalid combination of opcode and operands.\nhere -> " + - jump_label, - file); - throw std::runtime_error("invalid_comb_op_ops"); - } else { - // death trap installed. - found_sym = true; - } - } - } - - cpy_jump_label = jump_label; - - // replace any spaces with $ - if (jump_label[0] == ' ') { - while (jump_label.find(' ') != std::string::npos) { - if (isalnum(jump_label[0]) || isdigit(jump_label[0])) break; - - jump_label.erase(jump_label.find(' '), 1); - } - } - - if (!this->WriteNumber(0, jump_label)) { - // sta expects this: sta 0x000000, r0 - if (name == "sta") { - detail::print_error( - "invalid combination of opcode and operands.\nHere ->" + line, - file); - throw std::runtime_error("invalid_comb_op_ops"); - } - } else { - if (name == "sta" && - cpy_jump_label.find("import ") != std::string::npos) { - detail::print_error("invalid usage import on 'sta', here: " + line, - file); - throw std::runtime_error("invalid_sta_usage"); - } - } - - goto asm_write_label; - } - - // This is the case where we jump to a label, it is also used as a goto. - if (name == "lda" || name == "sta") { - asm_write_label: - if (cpy_jump_label.find('\n') != std::string::npos) - cpy_jump_label.erase(cpy_jump_label.find('\n'), 1); - - if (cpy_jump_label.find("import") != std::string::npos) { - cpy_jump_label.erase(cpy_jump_label.find("import"), strlen("import")); - - if (name == "sta") { - detail::print_error("import is not allowed on a sta operation.", - file); - throw std::runtime_error("import_sta_op"); - } else { - goto asm_end_label_cpy; - } - } - - if (name == "lda" || name == "sta") { - for (auto &label : kOriginLabel) { - if (cpy_jump_label == label.first) { - if (kVerbose) { - kStdOut << "64asm: Replace label " << cpy_jump_label - << " to address: " << label.second << std::endl; - } - - CompilerKit::NumberCast64 num(label.second); - - for (auto &num : num.number) { - kBytes.push_back(num); - } - - goto asm_end_label_cpy; - } - } - - if (cpy_jump_label[0] == '0') { - switch (cpy_jump_label[1]) { - case 'x': - case 'o': - case 'b': - if (this->WriteNumber(0, cpy_jump_label)) - goto asm_end_label_cpy; - - break; - default: - break; - } - - if (isdigit(cpy_jump_label[0])) { - if (this->WriteNumber(0, cpy_jump_label)) goto asm_end_label_cpy; - - break; - } - } - } - - if (cpy_jump_label.size() < 1) { - detail::print_error("label is empty, can't jump on it.", file); - throw std::runtime_error("label_empty"); - } - - /// don't go any further if: - /// load word (ldw) or store word. (stw) - - if (name == "ldw" || name == "stw") break; - - auto mld_reloc_str = std::to_string(cpy_jump_label.size()); - mld_reloc_str += kUndefinedSymbol; - mld_reloc_str += cpy_jump_label; - - bool ignore_back_slash = false; - - for (auto &reloc_chr : mld_reloc_str) { - if (reloc_chr == '\\') { - ignore_back_slash = true; - continue; - } - - if (ignore_back_slash) { - ignore_back_slash = false; - continue; - } - - kBytes.push_back(reloc_chr); - } - - kBytes.push_back('\0'); - goto asm_end_label_cpy; - } - - asm_end_label_cpy: - kOrigin += c64x0IPAlignment; - - break; - } - } - - return true; -} - -// Last rev 13-1-24 diff --git a/Sources/64asm.cxx b/Sources/64asm.cxx new file mode 100644 index 0000000..777f448 --- /dev/null +++ b/Sources/64asm.cxx @@ -0,0 +1,954 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +/// bugs: 0 + +///////////////////////////////////////////////////////////////////////////////////////// + +// @file 64asm.cxx +// @author Amlal EL Mahrouss +// @brief 64x000 Assembler. + +// REMINDER: when dealing with an undefined symbol use (string +// size):LinkerFindSymbol:(string) so that ld will look for it. + +///////////////////////////////////////////////////////////////////////////////////////// + +#define __ASM_NEED_64x0__ 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +///////////////////// + +// ANSI ESCAPE CODES + +///////////////////// + +#define kBlank "\e[0;30m" +#define kRed "\e[0;31m" +#define kWhite "\e[0;97m" +#define kYellow "\e[0;33m" + +#define kStdOut (std::cout << kWhite) +#define kStdErr (std::cout << kRed) + +static char kOutputArch = CompilerKit::kPefArch64000; +static Boolean kOutputAsBinary = false; + +static UInt32 kErrorLimit = 10; +static UInt32 kAcceptableErrors = 0; + +constexpr auto c64x0IPAlignment = 0x4U; + +static std::size_t kCounter = 1UL; + +static std::uintptr_t kOrigin = kPefBaseOrigin; +static std::vector> kOriginLabel; + +static bool kVerbose = false; + +static std::vector kBytes; + +static CompilerKit::AERecordHeader kCurrentRecord{ + .fName = "", .fKind = CompilerKit::kPefCode, .fSize = 0, .fOffset = 0}; + +static std::vector kRecords; +static std::vector kUndefinedSymbols; + +static const std::string kUndefinedSymbol = ":UndefinedSymbol:"; +static const std::string kRelocSymbol = ":RuntimeSymbol:"; + +// \brief forward decl. +static bool asm_read_attributes(std::string &line); + +namespace detail { +void print_error(std::string reason, const std::string &file) noexcept { + if (reason[0] == '\n') reason.erase(0, 1); + + kStdErr << kRed << "[ 64asm ] " << kWhite + << ((file == "64asm") ? "internal assembler error " + : ("in file, " + file)) + << kBlank << std::endl; + kStdErr << kRed << "[ 64asm ] " << kWhite << reason << kBlank << std::endl; + + if (kAcceptableErrors > kErrorLimit) std::exit(3); + + ++kAcceptableErrors; +} + +void print_warning(std::string reason, const std::string &file) noexcept { + if (reason[0] == '\n') reason.erase(0, 1); + + if (!file.empty()) { + kStdOut << kYellow << "[ file ] " << kWhite << file << kBlank << std::endl; + } + + kStdOut << kYellow << "[ 64asm ] " << kWhite << reason << kBlank << std::endl; +} +} // namespace detail + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief 64x0 assembler entrypoint, the program/module starts here. + +///////////////////////////////////////////////////////////////////////////////////////// + +NDK_MODULE(NewOSAssembler64000) { + for (size_t i = 1; i < argc; ++i) { + if (argv[i][0] == '-') { + if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { + kStdOut << "64asm: 64x0 Assembler.\n64asm: v1.10\n64asm: Copyright (c) " + "ZKA Technologies.\n"; + return 0; + } else if (strcmp(argv[i], "-h") == 0) { + kStdOut << "64asm: 64x0 Assembler.\n64asm: Copyright (c) 2024 Mahrouss " + "Logic.\n"; + kStdOut << "-version: Print program version.\n"; + kStdOut << "-verbose: Print verbose output.\n"; + kStdOut << "-binary: Output as flat binary.\n"; + kStdOut << "-64xxx: Compile for a subset of the X64000.\n"; + + return 0; + } else if (strcmp(argv[i], "-binary") == 0) { + kOutputAsBinary = true; + continue; + } else if (strcmp(argv[i], "-verbose") == 0) { + kVerbose = true; + continue; + } + + kStdOut << "64asm: ignore " << argv[i] << "\n"; + continue; + } + + if (!std::filesystem::exists(argv[i])) { + kStdOut << "64asm: can't open: " << argv[i] << std::endl; + goto asm_fail_exit; + } + + std::string object_output(argv[i]); + + for (auto &ext : kAsmFileExts) { + if (object_output.find(ext) != std::string::npos) { + object_output.erase(object_output.find(ext), std::strlen(ext)); + } + } + + object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt; + + std::ifstream file_ptr(argv[i]); + std::ofstream file_ptr_out(object_output, std::ofstream::binary); + + if (file_ptr_out.bad()) { + if (kVerbose) { + kStdOut << "64asm: error: " << strerror(errno) << "\n"; + } + } + + std::string line; + + CompilerKit::AEHeader hdr{0}; + + memset(hdr.fPad, kAEInvalidOpcode, kAEPad); + + hdr.fMagic[0] = kAEMag0; + hdr.fMagic[1] = kAEMag1; + hdr.fSize = sizeof(CompilerKit::AEHeader); + hdr.fArch = kOutputArch; + + ///////////////////////////////////////////////////////////////////////////////////////// + + // COMPILATION LOOP + + ///////////////////////////////////////////////////////////////////////////////////////// + + CompilerKit::Encoder64x0 asm64; + + while (std::getline(file_ptr, line)) { + if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) { + detail::print_error(ln, argv[i]); + continue; + } + + try { + asm_read_attributes(line); + asm64.WriteLine(line, argv[i]); + } catch (const std::exception &e) { + if (kVerbose) { + std::string what = e.what(); + detail::print_warning("exit because of: " + what, "64asm"); + } + + std::filesystem::remove(object_output); + goto asm_fail_exit; + } + } + + if (!kOutputAsBinary) { + if (kVerbose) { + kStdOut << "64asm: Writing object file...\n"; + } + + // this is the final step, write everything to the file. + + auto pos = file_ptr_out.tellp(); + + hdr.fCount = kRecords.size() + kUndefinedSymbols.size(); + + file_ptr_out << hdr; + + if (kRecords.empty()) { + kStdErr << "64asm: At least one record is needed to write an object " + "file.\n64asm: Make one using `export .code64 foo_bar`.\n"; + + std::filesystem::remove(object_output); + return -1; + } + + kRecords[kRecords.size() - 1].fSize = kBytes.size(); + + std::size_t record_count = 0UL; + + for (auto &rec : kRecords) { + if (kVerbose) + kStdOut << "64asm: Wrote record " << rec.fName << " to file...\n"; + + rec.fFlags |= CompilerKit::kKindRelocationAtRuntime; + rec.fOffset = record_count; + ++record_count; + + file_ptr_out << rec; + } + + // increment once again, so that we won't lie about the kUndefinedSymbols. + ++record_count; + + for (auto &sym : kUndefinedSymbols) { + CompilerKit::AERecordHeader _record_hdr{0}; + + if (kVerbose) + kStdOut << "64asm: Wrote symbol " << sym << " to file...\n"; + + _record_hdr.fKind = kAEInvalidOpcode; + _record_hdr.fSize = sym.size(); + _record_hdr.fOffset = record_count; + + ++record_count; + + memset(_record_hdr.fPad, kAEInvalidOpcode, kAEPad); + memcpy(_record_hdr.fName, sym.c_str(), sym.size()); + + file_ptr_out << _record_hdr; + + ++kCounter; + } + + auto pos_end = file_ptr_out.tellp(); + + file_ptr_out.seekp(pos); + + hdr.fStartCode = pos_end; + hdr.fCodeSize = kBytes.size(); + + file_ptr_out << hdr; + + file_ptr_out.seekp(pos_end); + } else { + if (kVerbose) { + kStdOut << "64asm: Write raw binary...\n"; + } + } + + // byte from byte, we write this. + for (auto &byte : kBytes) { + file_ptr_out.write(reinterpret_cast(&byte), sizeof(byte)); + } + + if (kVerbose) kStdOut << "64asm: Wrote file with program in it.\n"; + + file_ptr_out.flush(); + file_ptr_out.close(); + + if (kVerbose) kStdOut << "64asm: Exit succeeded.\n"; + + return 0; + } + +asm_fail_exit: + + if (kVerbose) kStdOut << "64asm: Exit failed.\n"; + + return -1; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief Check for attributes +// returns true if any was found. + +///////////////////////////////////////////////////////////////////////////////////////// + +static bool asm_read_attributes(std::string &line) { + // import is the opposite of export, it signals to the ld + // that we need this symbol. + if (ParserKit::find_word(line, "import")) { + if (kOutputAsBinary) { + detail::print_error("Invalid import directive in flat binary mode.", + "64asm"); + throw std::runtime_error("invalid_import_bin"); + } + + auto name = line.substr(line.find("import") + strlen("import")); + + /// sanity check to avoid stupid linker errors. + if (name.size() == 0) { + detail::print_error("Invalid import", "ppcasm"); + throw std::runtime_error("invalid_import"); + } + + std::string result = std::to_string(name.size()); + result += kUndefinedSymbol; + + // mangle this + for (char &j : name) { + if (j == ' ' || j == ',') j = '$'; + } + + result += name; + + if (name.find(".code64") != std::string::npos) { + // data is treated as code. + kCurrentRecord.fKind = CompilerKit::kPefCode; + } else if (name.find(".data64") != std::string::npos) { + // no code will be executed from here. + kCurrentRecord.fKind = CompilerKit::kPefData; + } else if (name.find(".zero64") != std::string::npos) { + // this is a bss section. + kCurrentRecord.fKind = CompilerKit::kPefZero; + } + + // this is a special case for the start stub. + // we want this so that ld can find it. + + if (name == kPefStart) { + kCurrentRecord.fKind = CompilerKit::kPefCode; + } + + // now we can tell the code size of the previous kCurrentRecord. + + if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); + + memset(kCurrentRecord.fName, 0, kAESymbolLen); + memcpy(kCurrentRecord.fName, result.c_str(), result.size()); + + ++kCounter; + + memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); + + kRecords.emplace_back(kCurrentRecord); + + return true; + } + // export is a special keyword used by 64asm to tell the AE output stage to + // mark this section as a header. it currently supports .code64, .data64., + // .zero64 + else if (ParserKit::find_word(line, "export")) { + if (kOutputAsBinary) { + detail::print_error("Invalid export directive in flat binary mode.", + "64asm"); + throw std::runtime_error("invalid_export_bin"); + } + + auto name = line.substr(line.find("export") + strlen("export")); + + std::string name_copy = name; + + for (char &j : name) { + if (j == ' ') j = '$'; + } + + if (name.find(".code64") != std::string::npos) { + // data is treated as code. + + name_copy.erase(name_copy.find(".code64"), strlen(".code64")); + kCurrentRecord.fKind = CompilerKit::kPefCode; + } else if (name.find(".data64") != std::string::npos) { + // no code will be executed from here. + + name_copy.erase(name_copy.find(".data64"), strlen(".data64")); + kCurrentRecord.fKind = CompilerKit::kPefData; + } else if (name.find(".zero64") != std::string::npos) { + // this is a bss section. + + name_copy.erase(name_copy.find(".zero64"), strlen(".zero64")); + kCurrentRecord.fKind = CompilerKit::kPefZero; + } + + // this is a special case for the start stub. + // we want this so that ld can find it. + + if (name == kPefStart) { + kCurrentRecord.fKind = CompilerKit::kPefCode; + } + + while (name_copy.find(" ") != std::string::npos) + name_copy.erase(name_copy.find(" "), 1); + + kOriginLabel.push_back(std::make_pair(name_copy, kOrigin)); + ++kOrigin; + + // now we can tell the code size of the previous kCurrentRecord. + + if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); + + memset(kCurrentRecord.fName, 0, kAESymbolLen); + memcpy(kCurrentRecord.fName, name.c_str(), name.size()); + + ++kCounter; + + memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); + + kRecords.emplace_back(kCurrentRecord); + + return true; + } + + return false; +} + +// \brief algorithms and helpers. + +namespace detail::algorithm { +// \brief authorize a brief set of characters. +static inline bool is_not_alnum_space(char c) { + return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || + (c == ',') || (c == '(') || (c == ')') || (c == '"') || + (c == '\'') || (c == '[') || (c == ']') || (c == '+') || + (c == '_') || (c == ':') || (c == '@') || (c == '.')); +} + +bool is_valid(const std::string &str) { + return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); +} +} // namespace detail::algorithm + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief Check for line (syntax check) + +///////////////////////////////////////////////////////////////////////////////////////// + +std::string CompilerKit::Encoder64x0::CheckLine(std::string &line, + const std::string &file) { + std::string err_str; + + if (line.empty() || ParserKit::find_word(line, "import") || + ParserKit::find_word(line, "export") || + line.find('#') != std::string::npos || ParserKit::find_word(line, ";")) { + if (line.find('#') != std::string::npos) { + line.erase(line.find('#')); + } else if (line.find(';') != std::string::npos) { + line.erase(line.find(';')); + } else { + // now check the line for validity + if (!detail::algorithm::is_valid(line)) { + err_str = "Line contains non alphanumeric characters.\nhere -> "; + err_str += line; + } + } + + return err_str; + } + + if (!detail::algorithm::is_valid(line)) { + err_str = "Line contains non alphanumeric characters.\nhere -> "; + err_str += line; + + return err_str; + } + + // check for a valid instruction format. + + if (line.find(',') != std::string::npos) { + if (line.find(',') + 1 == line.size()) { + err_str += "\nInstruction lacks right register, here -> "; + err_str += line.substr(line.find(',')); + + return err_str; + } else { + bool nothing_on_right = true; + + if (line.find(',') + 1 > line.size()) { + err_str += "\nInstruction not complete, here -> "; + err_str += line; + + return err_str; + } + + auto substr = line.substr(line.find(',') + 1); + + for (auto &ch : substr) { + if (ch != ' ' && ch != '\t') { + nothing_on_right = false; + } + } + + // this means we found nothing after that ',' . + if (nothing_on_right) { + err_str += "\nInstruction not complete, here -> "; + err_str += line; + + return err_str; + } + } + } + + // these do take an argument. + std::vector operands_inst = {"stw", "ldw", "lda", "sta"}; + + // these don't. + std::vector filter_inst = {"jlr", "jrl", "int"}; + + for (auto &opcode64x0 : kOpcodes64x0) { + if (line.find(opcode64x0.fName) != std::string::npos) { + if (opcode64x0.fFunct7 == kAsmNoArgs) return err_str; + + for (auto &op : operands_inst) { + // if only the instruction was found. + if (line == op) { + err_str += "\nMalformed "; + err_str += op; + err_str += " instruction, here -> "; + err_str += line; + } + } + + // if it is like that -> addr1, 0x0 + if (auto it = std::find(filter_inst.begin(), filter_inst.end(), + opcode64x0.fName); + it == filter_inst.cend()) { + if (ParserKit::find_word(line, opcode64x0.fName)) { + if (!isspace(line[line.find(opcode64x0.fName) + + strlen(opcode64x0.fName)])) { + err_str += "\nMissing space between "; + err_str += opcode64x0.fName; + err_str += " and operands.\nhere -> "; + err_str += line; + } + } + } + + return err_str; + } + } + + err_str += "Unrecognized instruction: " + line; + + return err_str; +} + +bool CompilerKit::Encoder64x0::WriteNumber(const std::size_t &pos, + std::string &jump_label) { + if (!isdigit(jump_label[pos])) return false; + + switch (jump_label[pos + 1]) { + case 'x': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); + !res) { + if (errno != 0) { + detail::print_error("invalid hex number: " + jump_label, "64asm"); + throw std::runtime_error("invalid_hex_number"); + } + } + + CompilerKit::NumberCast64 num( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16)); + + for (char &i : num.number) { + kBytes.push_back(i); + } + + if (kVerbose) { + kStdOut << "64asm: found a base 16 number here: " + << jump_label.substr(pos) << "\n"; + } + + return true; + } + case 'b': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); + !res) { + if (errno != 0) { + detail::print_error("invalid binary number: " + jump_label, "64asm"); + throw std::runtime_error("invalid_bin"); + } + } + + CompilerKit::NumberCast64 num( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2)); + + if (kVerbose) { + kStdOut << "64asm: found a base 2 number here: " + << jump_label.substr(pos) << "\n"; + } + + for (char &i : num.number) { + kBytes.push_back(i); + } + + return true; + } + case 'o': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); + !res) { + if (errno != 0) { + detail::print_error("invalid octal number: " + jump_label, "64asm"); + throw std::runtime_error("invalid_octal"); + } + } + + CompilerKit::NumberCast64 num( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7)); + + if (kVerbose) { + kStdOut << "64asm: found a base 8 number here: " + << jump_label.substr(pos) << "\n"; + } + + for (char &i : num.number) { + kBytes.push_back(i); + } + + return true; + } + default: { + break; + } + } + + /* check for errno and stuff like that */ + if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) { + if (errno != 0) { + return false; + } + } + + CompilerKit::NumberCast64 num( + strtol(jump_label.substr(pos).c_str(), nullptr, 10)); + + for (char &i : num.number) { + kBytes.push_back(i); + } + + if (kVerbose) { + kStdOut << "64asm: found a base 10 number here: " << jump_label.substr(pos) + << "\n"; + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief Read and write an instruction to the output array. + +///////////////////////////////////////////////////////////////////////////////////////// + +bool CompilerKit::Encoder64x0::WriteLine(std::string &line, + const std::string &file) { + if (ParserKit::find_word(line, "export ")) return true; + + for (auto &opcode64x0 : kOpcodes64x0) { + // strict check here + if (ParserKit::find_word(line, opcode64x0.fName) && + detail::algorithm::is_valid(line)) { + std::string name(opcode64x0.fName); + std::string jump_label, cpy_jump_label; + + kBytes.emplace_back(opcode64x0.fOpcode); + kBytes.emplace_back(opcode64x0.fFunct3); + kBytes.emplace_back(opcode64x0.fFunct7); + + // check funct7 type. + switch (opcode64x0.fFunct7) { + // reg to reg means register to register transfer operation. + case kAsmRegToReg: + case kAsmImmediate: { + // \brief how many registers we found. + std::size_t found_some = 0UL; + + for (size_t line_index = 0UL; line_index < line.size(); + line_index++) { + if (line[line_index] == kAsmRegisterPrefix[0] && + isdigit(line[line_index + 1])) { + std::string register_syntax = kAsmRegisterPrefix; + register_syntax += line[line_index + 1]; + + if (isdigit(line[line_index + 2])) + register_syntax += line[line_index + 2]; + + std::string reg_str; + reg_str += line[line_index + 1]; + + if (isdigit(line[line_index + 2])) + reg_str += line[line_index + 2]; + + // it ranges from r0 to r19 + // something like r190 doesn't exist in the instruction set. + if (kOutputArch == CompilerKit::kPefArch64000) { + if (isdigit(line[line_index + 3]) && + isdigit(line[line_index + 2])) { + reg_str += line[line_index + 3]; + detail::print_error( + "invalid register index, r" + reg_str + + "\nnote: The 64x0 accepts registers from r0 to r20.", + file); + throw std::runtime_error("invalid_register_index"); + } + } + + // finally cast to a size_t + std::size_t reg_index = strtol(reg_str.c_str(), nullptr, 10); + + if (reg_index > kAsmRegisterLimit) { + detail::print_error("invalid register index, r" + reg_str, + file); + throw std::runtime_error("invalid_register_index"); + } + + kBytes.emplace_back(reg_index); + ++found_some; + + if (kVerbose) { + kStdOut << "64asm: Register found: " << register_syntax << "\n"; + kStdOut << "64asm: Register amount in instruction: " + << found_some << "\n"; + } + } + } + + // we're not in immediate addressing, reg to reg. + if (opcode64x0.fFunct7 != kAsmImmediate) { + // remember! register to register! + if (found_some == 1) { + detail::print_error( + "Too few registers.\ntip: each 64asm register " + "starts with 'r'.\nline: " + + line, + file); + throw std::runtime_error("not_a_register"); + } + } + + if (found_some < 1 && name != "ldw" && name != "lda" && + name != "stw") { + detail::print_error( + "invalid combination of opcode and registers.\nline: " + line, + file); + throw std::runtime_error("invalid_comb_op_reg"); + } else if (found_some == 1 && name == "add") { + detail::print_error( + "invalid combination of opcode and registers.\nline: " + line, + file); + throw std::runtime_error("invalid_comb_op_reg"); + } else if (found_some == 1 && name == "sub") { + detail::print_error( + "invalid combination of opcode and registers.\nline: " + line, + file); + throw std::runtime_error("invalid_comb_op_reg"); + } + + if (found_some > 0 && name == "pop") { + detail::print_error( + "invalid combination for opcode 'pop'.\ntip: it expects " + "nothing.\nline: " + + line, + file); + throw std::runtime_error("invalid_comb_op_pop"); + } + } + default: + break; + } + + // try to fetch a number from the name + if (name == "stw" || name == "ldw" || name == "lda" || name == "sta") { + auto where_string = name; + + // if we load something, we'd need it's symbol/literal + if (name == "stw" || name == "sta" || name == "ldw" || name == "lda" || + name == "sta") + where_string = ","; + + jump_label = line; + + auto found_sym = false; + + while (jump_label.find(where_string) != std::string::npos) { + jump_label = jump_label.substr(jump_label.find(where_string) + + where_string.size()); + + while (jump_label.find(" ") != std::string::npos) { + jump_label.erase(jump_label.find(" "), 1); + } + + if (jump_label[0] != kAsmRegisterPrefix[0] && + !isdigit(jump_label[1])) { + if (found_sym) { + detail::print_error( + "invalid combination of opcode and operands.\nhere -> " + + jump_label, + file); + throw std::runtime_error("invalid_comb_op_ops"); + } else { + // death trap installed. + found_sym = true; + } + } + } + + cpy_jump_label = jump_label; + + // replace any spaces with $ + if (jump_label[0] == ' ') { + while (jump_label.find(' ') != std::string::npos) { + if (isalnum(jump_label[0]) || isdigit(jump_label[0])) break; + + jump_label.erase(jump_label.find(' '), 1); + } + } + + if (!this->WriteNumber(0, jump_label)) { + // sta expects this: sta 0x000000, r0 + if (name == "sta") { + detail::print_error( + "invalid combination of opcode and operands.\nHere ->" + line, + file); + throw std::runtime_error("invalid_comb_op_ops"); + } + } else { + if (name == "sta" && + cpy_jump_label.find("import ") != std::string::npos) { + detail::print_error("invalid usage import on 'sta', here: " + line, + file); + throw std::runtime_error("invalid_sta_usage"); + } + } + + goto asm_write_label; + } + + // This is the case where we jump to a label, it is also used as a goto. + if (name == "lda" || name == "sta") { + asm_write_label: + if (cpy_jump_label.find('\n') != std::string::npos) + cpy_jump_label.erase(cpy_jump_label.find('\n'), 1); + + if (cpy_jump_label.find("import") != std::string::npos) { + cpy_jump_label.erase(cpy_jump_label.find("import"), strlen("import")); + + if (name == "sta") { + detail::print_error("import is not allowed on a sta operation.", + file); + throw std::runtime_error("import_sta_op"); + } else { + goto asm_end_label_cpy; + } + } + + if (name == "lda" || name == "sta") { + for (auto &label : kOriginLabel) { + if (cpy_jump_label == label.first) { + if (kVerbose) { + kStdOut << "64asm: Replace label " << cpy_jump_label + << " to address: " << label.second << std::endl; + } + + CompilerKit::NumberCast64 num(label.second); + + for (auto &num : num.number) { + kBytes.push_back(num); + } + + goto asm_end_label_cpy; + } + } + + if (cpy_jump_label[0] == '0') { + switch (cpy_jump_label[1]) { + case 'x': + case 'o': + case 'b': + if (this->WriteNumber(0, cpy_jump_label)) + goto asm_end_label_cpy; + + break; + default: + break; + } + + if (isdigit(cpy_jump_label[0])) { + if (this->WriteNumber(0, cpy_jump_label)) goto asm_end_label_cpy; + + break; + } + } + } + + if (cpy_jump_label.size() < 1) { + detail::print_error("label is empty, can't jump on it.", file); + throw std::runtime_error("label_empty"); + } + + /// don't go any further if: + /// load word (ldw) or store word. (stw) + + if (name == "ldw" || name == "stw") break; + + auto mld_reloc_str = std::to_string(cpy_jump_label.size()); + mld_reloc_str += kUndefinedSymbol; + mld_reloc_str += cpy_jump_label; + + bool ignore_back_slash = false; + + for (auto &reloc_chr : mld_reloc_str) { + if (reloc_chr == '\\') { + ignore_back_slash = true; + continue; + } + + if (ignore_back_slash) { + ignore_back_slash = false; + continue; + } + + kBytes.push_back(reloc_chr); + } + + kBytes.push_back('\0'); + goto asm_end_label_cpy; + } + + asm_end_label_cpy: + kOrigin += c64x0IPAlignment; + + break; + } + } + + return true; +} + +// Last rev 13-1-24 diff --git a/Sources/64x0-cc.cc b/Sources/64x0-cc.cc deleted file mode 100644 index efbf68f..0000000 --- a/Sources/64x0-cc.cc +++ /dev/null @@ -1,1627 +0,0 @@ -/* - * ======================================================== - * - * cc - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -/// BUGS: ? -/// TODO: - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* C driver */ -/* This is part of the NDK. */ -/* (c) ZKA Technologies */ - -/// @author Amlal El Mahrouss (amlel) -/// @file 64x0-cc.cc -/// @brief 64x0 C Compiler. - -/// TODO: support structures, else if, else, . and -> - -///////////////////// - -// ANSI ESCAPE CODES - -///////////////////// - -#define kOk (0) - -#define kBlank "\e[0;30m" -#define kRed "\e[0;31m" -#define kWhite "\e[0;97m" - -///////////////////////////////////// - -// INTERNAL STUFF OF THE C COMPILER - -///////////////////////////////////// - -namespace detail -{ - // \brief name to register struct. - struct CompilerRegisterMap final - { - std::string fName; - std::string fReg; - }; - - // \brief Map for C structs - // \author amlel - struct CompilerStructMap final - { - // 'my_foo' - std::string fName; - - // if instance: stores a valid register. - std::string fReg; - - // offset count - std::size_t fOffsetsCnt; - - // offset array. - std::vector> fOffsets; - }; - - struct CompilerState final - { - std::vector fSyntaxTreeList; - std::vector kStackFrame; - std::vector kStructMap; - ParserKit::SyntaxLeafList* fSyntaxTree{nullptr}; - std::unique_ptr fOutputAssembly; - std::string fLastFile; - std::string fLastError; - bool fVerbose; - }; -} // namespace detail - -static detail::CompilerState kState; -static SizeType kErrorLimit = 100; -static std::string kIfFunction = ""; -static Int32 kAcceptableErrors = 0; - -namespace detail -{ - /// @brief prints an error into stdout. - /// @param reason the reason of the error. - /// @param file where does it originate from? - void print_error(std::string reason, std::string file) noexcept - { - if (reason[0] == '\n') - reason.erase(0, 1); - - if (file.find(".pp") != std::string::npos) - { - file.erase(file.find(".pp"), 3); - } - - if (kState.fLastFile != file) - { - std::cout << kRed << "[ cc ] " << kWhite - << ((file == "cc") ? "internal compiler error " - : ("in file, " + file)) - << kBlank << std::endl; - std::cout << kRed << "[ cc ] " << kWhite << reason << kBlank << std::endl; - - kState.fLastFile = file; - } - else - { - std::cout << kRed << "[ cc ] [ " << kState.fLastFile << " ] " << kWhite - << reason << kBlank << std::endl; - } - - if (kAcceptableErrors > kErrorLimit) - std::exit(3); - - ++kAcceptableErrors; - } - - struct CompilerType final - { - std::string fName; - std::string fValue; - }; -} // namespace detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// Target architecture. -static int kMachine = 0; - -///////////////////////////////////////// - -// REGISTERS ACCORDING TO USED ASSEMBLER - -///////////////////////////////////////// - -static size_t kRegisterCnt = kAsmRegisterLimit; -static size_t kStartUsable = 2; -static size_t kUsableLimit = 15; -static size_t kRegisterCounter = kStartUsable; -static std::string kRegisterPrefix = kAsmRegisterPrefix; - -///////////////////////////////////////// - -// COMPILER PARSING UTILITIES/STATES. - -///////////////////////////////////////// - -static std::vector kFileList; -static CompilerKit::AssemblyFactory kFactory; -static bool kInStruct = false; -static bool kOnWhileLoop = false; -static bool kOnForLoop = false; -static bool kInBraces = false; -static bool kIfFound = false; -static size_t kBracesCount = 0UL; - -/* @brief C compiler backend for C */ -class CompilerBackendCLang final : public ParserKit::CompilerBackend -{ -public: - explicit CompilerBackendCLang() = default; - ~CompilerBackendCLang() override = default; - - MPCC_COPY_DEFAULT(CompilerBackendCLang); - - std::string Check(const char* text, const char* file); - bool Compile(const std::string& text, const char* file) override; - - const char* Language() override - { - return "64k C"; - } -}; - -static CompilerBackendCLang* kCompilerBackend = nullptr; -static std::vector kCompilerVariables; -static std::vector kCompilerFunctions; -static std::vector kCompilerTypes; - -namespace detail -{ - union number_cast final { - public: - number_cast(UInt64 _Raw) - : _Raw(_Raw) - { - } - - public: - char _Num[8]; - UInt64 _Raw; - }; - - union double_cast final { - public: - double_cast(float _Raw) - : _Raw(_Raw) - { - } - - public: - char _Sign; - char _Lh[8]; - char _Rh[23]; - - float _Raw; - }; -} // namespace detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// @name Compile -// @brief Generate MASM from a C assignement. - -///////////////////////////////////////////////////////////////////////////////////////// - -bool CompilerBackendCLang::Compile(const std::string& text, const char* file) -{ - std::string textBuffer = text; - - bool typeFound = false; - bool fnFound = false; - - // setup generator. - std::random_device rd; - - auto seed_data = std::array{}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); - std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); - std::mt19937 generator(seq); - - // start parsing - for (size_t text_index = 0; text_index < textBuffer.size(); ++text_index) - { - auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf(); - - auto gen = uuids::uuid_random_generator{generator}; - uuids::uuid out = gen(); - - detail::number_cast time_off = (UInt64)out.as_bytes().data(); - - if (!typeFound) - { - auto substr = textBuffer.substr(text_index); - std::string match_type; - - for (size_t y = 0; y < substr.size(); ++y) - { - if (substr[y] == ' ') - { - while (match_type.find(' ') != std::string::npos) - { - match_type.erase(match_type.find(' ')); - } - - for (auto& clType : kCompilerTypes) - { - if (clType.fName == match_type) - { - match_type.clear(); - - std::string buf; - - buf += clType.fValue; - buf += ' '; - - if (substr.find('=') != std::string::npos) - { - break; - } - - if (textBuffer.find('(') != std::string::npos) - { - syntaxLeaf.fUserValue = buf; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - typeFound = true; - break; - } - } - - break; - } - - match_type += substr[y]; - } - } - - if (textBuffer[text_index] == '{') - { - if (kInStruct) - { - continue; - } - - kInBraces = true; - ++kBracesCount; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - // return keyword handler - if (textBuffer[text_index] == 'r') - { - std::string return_keyword; - return_keyword += "return"; - - std::size_t index = 0UL; - - std::string value; - - for (size_t return_index = text_index; return_index < textBuffer.size(); - ++return_index) - { - if (textBuffer[return_index] != return_keyword[index]) - { - for (size_t value_index = return_index; - value_index < textBuffer.size(); ++value_index) - { - if (textBuffer[value_index] == ';') - break; - - value += textBuffer[value_index]; - } - - break; - } - - ++index; - } - - if (index == return_keyword.size()) - { - if (!value.empty()) - { - if (value.find('(') != std::string::npos) - { - value.erase(value.find('(')); - } - - if (!isdigit(value[value.find('(') + 2])) - { - std::string tmp = value; - bool reg_to_reg = false; - - value.clear(); - - value += " import"; - value += tmp; - } - - syntaxLeaf.fUserValue = "\tldw r19, "; - - // make it pretty. - if (value.find('\t') != std::string::npos) - value.erase(value.find('\t'), 1); - - syntaxLeaf.fUserValue += value + "\n"; - } - - syntaxLeaf.fUserValue += "\tjlr"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - break; - } - } - - if (textBuffer[text_index] == 'i' && textBuffer[text_index + 1] == 'f') - { - auto expr = textBuffer.substr(text_index + 2); - textBuffer.erase(text_index, 2); - - if (expr.find("{") != std::string::npos) - { - expr.erase(expr.find("{")); - } - - if (expr.find("(") != std::string::npos) - expr.erase(expr.find("(")); - - if (expr.find(")") != std::string::npos) - expr.erase(expr.find(")")); - - kIfFunction = "__MPCC_IF_PROC_"; - kIfFunction += std::to_string(time_off._Raw); - - syntaxLeaf.fUserValue = "\tlda r12, import "; - syntaxLeaf.fUserValue += - kIfFunction + - "\n\t#r12 = Code to jump on, r11 right cond, r10 left cond.\n\tbeq " - "r10, r11, r12\ndword export .code64 " + - kIfFunction + "\n"; - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - kIfFound = true; - } - - // Parse expressions and instructions here. - // what does this mean? - // we encounter an assignment, or we reached the end of an expression. - if (textBuffer[text_index] == '=' || textBuffer[text_index] == ';') - { - if (fnFound) - continue; - if (kIfFound) - continue; - - if (textBuffer[text_index] == ';' && kInStruct) - continue; - - if (textBuffer.find("typedef ") != std::string::npos) - continue; - - if (textBuffer[text_index] == '=' && kInStruct) - { - detail::print_error("assignement of value in struct " + textBuffer, - file); - continue; - } - - if (textBuffer[text_index] == ';' && kInStruct) - { - bool space_found_ = false; - std::string sym; - - for (auto& ch : textBuffer) - { - if (ch == ' ') - { - space_found_ = true; - } - - if (ch == ';') - break; - - if (space_found_) - sym.push_back(ch); - } - - kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back( - std::make_pair( - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, - sym)); - - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt = - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4; - - continue; - } - - if (textBuffer[text_index] == '=' && kInStruct) - { - continue; - } - - if (textBuffer[text_index + 1] == '=' || - textBuffer[text_index - 1] == '!' || - textBuffer[text_index - 1] == '<' || - textBuffer[text_index - 1] == '>') - { - continue; - } - - std::string substr; - - if (textBuffer.find('=') != std::string::npos && kInBraces && !kIfFound) - { - if (textBuffer.find("*") != std::string::npos) - { - if (textBuffer.find("=") > textBuffer.find("*")) - substr += "\tlda "; - else - substr += "\tldw "; - } - else - { - substr += "\tldw "; - } - } - else if (textBuffer.find('=') != std::string::npos && !kInBraces) - { - substr += "stw export .data64 "; - } - - int first_encountered = 0; - - std::string str_name; - - for (size_t text_index_2 = 0; text_index_2 < textBuffer.size(); - ++text_index_2) - { - if (textBuffer[text_index_2] == '\"') - { - ++text_index_2; - - // want to add this, so that the parser recognizes that this is a - // string. - substr += '"'; - - for (; text_index_2 < textBuffer.size(); ++text_index_2) - { - if (textBuffer[text_index_2] == '\"') - break; - - substr += textBuffer[text_index_2]; - } - } - - if (textBuffer[text_index_2] == '{' || textBuffer[text_index_2] == '}') - continue; - - if (textBuffer[text_index_2] == ';') - { - break; - } - - if (textBuffer[text_index_2] == ' ' || - textBuffer[text_index_2] == '\t') - { - if (first_encountered != 2) - { - if (textBuffer[text_index] != '=' && - substr.find("export .data64") == std::string::npos && - !kInStruct) - substr += "export .data64 "; - } - - ++first_encountered; - - continue; - } - - if (textBuffer[text_index_2] == '=') - { - if (!kInBraces) - { - substr.replace(substr.find("export .data64"), - strlen("export .data64"), "export .zero64 "); - } - - substr += ","; - continue; - } - - substr += textBuffer[text_index_2]; - } - - for (auto& clType : kCompilerTypes) - { - if (substr.find(clType.fName) != std::string::npos) - { - if (substr.find(clType.fName) > substr.find('"')) - continue; - - substr.erase(substr.find(clType.fName), clType.fName.size()); - } - else if (substr.find(clType.fValue) != std::string::npos) - { - if (substr.find(clType.fValue) > substr.find('"')) - continue; - - if (clType.fName == "const") - continue; - - substr.erase(substr.find(clType.fValue), clType.fValue.size()); - } - } - - if (substr.find("extern") != std::string::npos) - { - substr.replace(substr.find("extern"), strlen("extern"), "import "); - - if (substr.find("export .data64") != std::string::npos) - substr.erase(substr.find("export .data64"), strlen("export .data64")); - } - - auto var_to_find = - std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(), - [&](detail::CompilerType type) { - return type.fName.find(substr) != std::string::npos; - }); - - if (kRegisterCounter == 5 || kRegisterCounter == 6) - ++kRegisterCounter; - - std::string reg = kAsmRegisterPrefix; - reg += std::to_string(kRegisterCounter); - - if (var_to_find == kCompilerVariables.cend()) - { - ++kRegisterCounter; - - kState.kStackFrame.push_back({.fName = substr, .fReg = reg}); - kCompilerVariables.push_back({.fName = substr}); - } - - syntaxLeaf.fUserValue += substr; - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - if (textBuffer[text_index] == '=') - break; - } - - // function handler. - - if (textBuffer[text_index] == '(' && !fnFound && !kIfFound) - { - std::string substr; - std::string args_buffer; - std::string args; - - bool type_crossed = false; - - for (size_t idx = textBuffer.find('(') + 1; idx < textBuffer.size(); - ++idx) - { - if (textBuffer[idx] == ',') - continue; - - if (textBuffer[idx] == ' ') - continue; - - if (textBuffer[idx] == ')') - break; - } - - for (char substr_first_index : textBuffer) - { - if (substr_first_index != ',') - args_buffer += substr_first_index; - else - args_buffer += '$'; - - if (substr_first_index == ';') - { - args_buffer = args_buffer.erase(0, args_buffer.find('(')); - args_buffer = args_buffer.erase(args_buffer.find(';'), 1); - args_buffer = args_buffer.erase(args_buffer.find(')'), 1); - args_buffer = args_buffer.erase(args_buffer.find('('), 1); - - if (!args_buffer.empty()) - args += "\tldw r6, "; - - std::string register_type; - std::size_t index = 7UL; - - while (args_buffer.find("$") != std::string::npos) - { - register_type = kRegisterPrefix; - register_type += std::to_string(index); - - ++index; - - args_buffer.replace(args_buffer.find('$'), 1, - "\n\tldw " + register_type + ","); - } - - args += args_buffer; - args += "\n\tlda r19, "; - } - } - - for (char _text_i : textBuffer) - { - if (_text_i == '\t' || _text_i == ' ') - { - if (!type_crossed) - { - substr.clear(); - type_crossed = true; - } - - continue; - } - - if (_text_i == '(') - break; - - substr += _text_i; - } - - if (kInBraces) - { - syntaxLeaf.fUserValue = args; - syntaxLeaf.fUserValue += substr; - syntaxLeaf.fUserValue += "\n\tjrl\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - fnFound = true; - } - else - { - syntaxLeaf.fUserValue.clear(); - - syntaxLeaf.fUserValue += "export .code64 "; - - syntaxLeaf.fUserValue += substr; - syntaxLeaf.fUserValue += "\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - fnFound = true; - } - - kCompilerFunctions.push_back(textBuffer); - } - - if (textBuffer[text_index] == '-' && textBuffer[text_index + 1] == '-') - { - textBuffer = textBuffer.replace(textBuffer.find("--"), strlen("--"), ""); - - for (int _text_i = 0; _text_i < textBuffer.size(); ++_text_i) - { - if (textBuffer[_text_i] == '\t' || textBuffer[_text_i] == ' ') - textBuffer.erase(_text_i, 1); - } - - syntaxLeaf.fUserValue += "sub "; - syntaxLeaf.fUserValue += textBuffer; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - break; - } - - if (textBuffer[text_index] == '}') - { - kRegisterCounter = kStartUsable; - - --kBracesCount; - - if (kBracesCount < 1) - { - kInBraces = false; - kBracesCount = 0; - } - - if (kIfFound) - kIfFound = false; - - if (kInStruct) - kInStruct = false; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - syntaxLeaf.fUserValue.clear(); - } - - auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf(); - syntaxLeaf.fUserValue = "\n"; - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - return true; -} - -static bool kShouldHaveBraces = false; -static std::string kFnName; - -std::string CompilerBackendCLang::Check(const char* text, const char* file) -{ - std::string err_str; - std::string ln = text; - - if (ln.empty()) - { - return err_str; - } - - bool non_ascii_found = false; - - for (int i = 0; i < ln.size(); ++i) - { - if (isalnum(ln[i])) - { - non_ascii_found = true; - break; - } - } - - if (kShouldHaveBraces && ln.find('{') != std::string::npos) - { - kShouldHaveBraces = false; - } - - if (!non_ascii_found) - return err_str; - - size_t string_index = 1UL; - - if (ln.find('\'') != std::string::npos) - { - string_index = ln.find('\'') + 1; - - for (; string_index < ln.size(); ++string_index) - { - if (ln[string_index] == '\'') - { - if (ln[string_index + 1] != ';') - { - ln.erase(string_index, 1); - } - - return err_str; - } - } - } - else if (ln.find('"') != std::string::npos) - { - string_index = ln.find('"') + 1; - - for (; string_index < ln.size(); ++string_index) - { - if (ln[string_index] == '"') - { - if (ln[string_index + 1] != ';') - { - ln.erase(string_index, 1); - } - else - { - break; - } - } - } - } - else if (ln.find('"') == std::string::npos && - ln.find('\'') == std::string::npos) - { - std::vector forbidden_words; - - forbidden_words.push_back("\\"); - forbidden_words.push_back("?"); - forbidden_words.push_back("@"); - forbidden_words.push_back("~"); - forbidden_words.push_back("::"); - forbidden_words.push_back("/*"); - forbidden_words.push_back("*/"); - - // add them to avoid stupid mistakes. - forbidden_words.push_back("namespace"); - forbidden_words.push_back("class"); - forbidden_words.push_back("extern \"C\""); - - for (auto& forbidden : forbidden_words) - { - if (ln.find(forbidden) != std::string::npos) - { - err_str += "\nForbidden character detected: "; - err_str += forbidden; - - return err_str; - } - } - } - - struct CompilerVariableRange final - { - std::string fBegin; - std::string fEnd; - }; - - const std::vector variables_list = { - {.fBegin = "static ", .fEnd = "="}, - {.fBegin = "=", .fEnd = ";"}, - {.fBegin = "if(", .fEnd = "="}, - {.fBegin = "if (", .fEnd = "="}, - {.fBegin = "if(", .fEnd = "<"}, - {.fBegin = "if (", .fEnd = "<"}, - {.fBegin = "if(", .fEnd = ">"}, - {.fBegin = "if (", .fEnd = ">"}, - {.fBegin = "if(", .fEnd = ")"}, - {.fBegin = "if (", .fEnd = ")"}, - - {.fBegin = "else(", .fEnd = "="}, - {.fBegin = "else (", .fEnd = "="}, - {.fBegin = "else(", .fEnd = "<"}, - {.fBegin = "else (", .fEnd = "<"}, - {.fBegin = "else(", .fEnd = ">"}, - {.fBegin = "else (", .fEnd = ">"}, - {.fBegin = "else(", .fEnd = ")"}, - {.fBegin = "else (", .fEnd = ")"}, - }; - - for (auto& variable : variables_list) - { - if (ln.find(variable.fBegin) != std::string::npos) - { - string_index = ln.find(variable.fBegin) + variable.fBegin.size(); - - while (ln[string_index] == ' ') - ++string_index; - - std::string keyword; - - for (; string_index < ln.size(); ++string_index) - { - if (ln[string_index] == variable.fEnd[0]) - { - std::string varname = ""; - - for (size_t index_keyword = ln.find(' '); - ln[index_keyword] != variable.fBegin[0]; ++index_keyword) - { - if (ln[index_keyword] == ' ') - { - continue; - } - - if (isdigit(ln[index_keyword])) - { - goto cc_next_loop; - } - - varname += ln[index_keyword]; - } - - if (varname.find(' ') != std::string::npos) - { - varname.erase(0, varname.find(' ')); - - if (variable.fBegin == "extern") - { - varname.erase(0, varname.find(' ')); - } - } - - if (kRegisterCounter == 5 || kRegisterCounter == 6) - ++kRegisterCounter; - - std::string reg = kAsmRegisterPrefix; - reg += std::to_string(kRegisterCounter); - - kCompilerVariables.push_back({.fValue = varname}); - goto cc_check_done; - } - - keyword.push_back(ln[string_index]); - } - - goto cc_next_loop; - - cc_check_done: - - // skip digit value. - if (isdigit(keyword[0]) || keyword[0] == '"') - { - goto cc_next_loop; - } - - while (keyword.find(' ') != std::string::npos) - keyword.erase(keyword.find(' '), 1); - - for (auto& var : kCompilerVariables) - { - if (var.fValue.find(keyword) != std::string::npos) - { - err_str.clear(); - goto cc_next; - } - } - - for (auto& fn : kCompilerFunctions) - { - if (fn.find(keyword[0]) != std::string::npos) - { - auto where_begin = fn.find(keyword[0]); - auto keyword_begin = 0UL; - auto failed = false; - - for (; where_begin < keyword.size(); ++where_begin) - { - if (fn[where_begin] == '(' && keyword[keyword_begin] == '(') - break; - - if (fn[where_begin] != keyword[keyword_begin]) - { - failed = true; - break; - } - - ++keyword_begin; - } - - if (!failed) - { - err_str.clear(); - goto cc_next; - } - else - { - continue; - } - } - } - - cc_error_value: - if (keyword.find("->") != std::string::npos) - return err_str; - - if (keyword.find(".") != std::string::npos) - return err_str; - - if (isalnum(keyword[0])) - err_str += "\nUndefined value: " + keyword; - - return err_str; - } - - cc_next_loop: - continue; - } - -cc_next: - - // extern does not declare anything, it imports a variable. - // so that's why it's not declare upper. - if (ParserKit::find_word(ln, "extern")) - { - auto substr = ln.substr(ln.find("extern") + strlen("extern")); - kCompilerVariables.push_back({.fValue = substr}); - } - - if (kShouldHaveBraces && ln.find('{') == std::string::npos) - { - err_str += "Missing '{' for function "; - err_str += kFnName; - err_str += "\n"; - - kShouldHaveBraces = false; - kFnName.clear(); - } - else if (kShouldHaveBraces && ln.find('{') != std::string::npos) - { - kShouldHaveBraces = false; - kFnName.clear(); - } - - bool type_not_found = true; - - if (ln.find('\'') != std::string::npos) - { - ln.replace(ln.find('\''), 3, "0"); - } - - auto first = ln.find('"'); - if (first != std::string::npos) - { - auto second = 0UL; - bool found_second_quote = false; - - for (size_t i = first + 1; i < ln.size(); ++i) - { - if (ln[i] == '\"') - { - found_second_quote = true; - second = i; - - break; - } - } - - if (!found_second_quote) - { - err_str += "Missing terminating \"."; - err_str += " here -> " + ln.substr(ln.find('"'), second); - } - } - - if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos) - { - if (ln.find('{') == std::string::npos) - { - kFnName = ln; - kShouldHaveBraces = true; - - goto skip_braces_check; - } - else if (ln.find('{') != std::string::npos) - { - kShouldHaveBraces = false; - } - } - -skip_braces_check: - - for (auto& key : kCompilerTypes) - { - if (ParserKit::find_word(ln, key.fName)) - { - if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) - { - err_str += "\nNumber cannot be set for "; - err_str += key.fName; - err_str += "'s name. here -> "; - err_str += ln; - } - - if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' || - ln[ln.find(key.fName) - 1] == '\t') - { - type_not_found = false; - - if (ln[ln.find(key.fName) + key.fName.size()] != ' ') - { - type_not_found = true; - - if (ln[ln.find(key.fName) + key.fName.size()] == '\t') - type_not_found = false; - - goto next; - } - else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') - { - type_not_found = true; - - if (ln[ln.find(key.fName) + key.fName.size()] == ' ') - type_not_found = false; - } - } - - next: - - if (ln.find(';') == std::string::npos) - { - if (ln.find('(') != std::string::npos) - { - if (ln.find('=') == std::string::npos) - continue; - } - - err_str += "\nMissing ';', here -> "; - err_str += ln; - } - else - { - continue; - } - - if (ln.find('=') != std::string::npos) - { - if (ln.find('(') != std::string::npos) - { - if (ln.find(')') == std::string::npos) - { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } - } - } - } - } - - if (kInBraces && ln.find("struct") != std::string::npos && - ln.find("union") != std::string::npos && - ln.find("enum") != std::string::npos && - ln.find('=') != std::string::npos) - { - if (ln.find(';') == std::string::npos) - { - err_str += "\nMissing ';' after struct/union/enum declaration, here -> "; - err_str += ln; - } - } - - if (ln.find(';') != std::string::npos && - ln.find("for") == std::string::npos) - { - if (ln.find(';') + 1 != ln.size()) - { - for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) - { - if ((ln.substr(ln.find(';') + 1)[i] != ' ') || - (ln.substr(ln.find(';') + 1)[i] != '\t')) - { - if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); - !err.empty()) - { - err_str += "\nUnexpected text after ';' -> "; - err_str += ln.substr(ln.find(';')); - err_str += err; - } - } - } - } - } - - if (ln.find('(') != std::string::npos) - { - if (ln.find(';') == std::string::npos && !ParserKit::find_word(ln, "|") && - !ParserKit::find_word(ln, "||") && !ParserKit::find_word(ln, "&") && - !ParserKit::find_word(ln, "&&") && !ParserKit::find_word(ln, "~")) - { - bool found_func = false; - size_t i = ln.find('('); - std::vector opens; - std::vector closes; - - for (; i < ln.size(); ++i) - { - if (ln[i] == ')') - { - closes.push_back(1); - } - - if (ln[i] == '(') - { - opens.push_back(1); - } - } - - if (closes.size() != opens.size()) - err_str += "Unterminated (), here -> " + ln; - - bool space_found = false; - - for (int i = 0; i < ln.size(); ++i) - { - if (ln[i] == ')' && !space_found) - { - space_found = true; - continue; - } - - if (space_found) - { - if (ln[i] == ' ' && isalnum(ln[i + 1])) - { - err_str += "\nBad function format here -> "; - err_str += ln; - } - } - } - } - - if (ln.find('(') < 1) - { - err_str += "\nMissing identifier before '(' here -> "; - err_str += ln; - } - else - { - if (type_not_found && ln.find(';') == std::string::npos && - ln.find("if") == std::string::npos && - ln.find("|") == std::string::npos && - ln.find("&") == std::string::npos && - ln.find("(") == std::string::npos && - ln.find(")") == std::string::npos) - { - err_str += "\n Missing ';' or type, here -> "; - err_str += ln; - } - } - - if (ln.find(')') == std::string::npos) - { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } - } - else - { - if (ln.find("for") != std::string::npos || - ln.find("while") != std::string::npos) - { - err_str += "\nMissing '(', after \"for\", here -> "; - err_str += ln; - } - } - - if (ln.find('}') != std::string::npos && !kInBraces) - { - if (!kInStruct && ln.find(';') == std::string::npos) - { - err_str += "\nMismatched '}', here -> "; - err_str += ln; - } - } - - if (!ln.empty()) - { - if (ln.find(';') == std::string::npos && - ln.find('{') == std::string::npos && - ln.find('}') == std::string::npos && - ln.find(')') == std::string::npos && - ln.find('(') == std::string::npos && - ln.find(',') == std::string::npos) - { - if (ln.size() <= 2) - return err_str; - - err_str += "\nMissing ';', here -> "; - err_str += ln; - } - } - - return err_str; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -/** - * @brief C To Assembly mount-point. - */ - -///////////////////////////////////////////////////////////////////////////////////////// - -class AssemblyCCInterface final : public CompilerKit::AssemblyInterface -{ -public: - explicit AssemblyCCInterface() = default; - ~AssemblyCCInterface() override = default; - - MPCC_COPY_DEFAULT(AssemblyCCInterface); - - [[maybe_unused]] static Int32 Arch() noexcept - { - return CompilerKit::AssemblyFactory::kArch64x0; - } - - Int32 CompileToFormat(std::string& src, Int32 arch) override - { - if (arch != AssemblyCCInterface::Arch()) - return -1; - - if (kCompilerBackend == nullptr) - return -1; - - /* @brief copy contents wihtout extension */ - std::string src_file = src.data(); - std::ifstream src_fp = std::ifstream(src_file, std::ios::in); - std::string dest; - - for (auto& ch : src_file) - { - if (ch == '.') - { - break; - } - - dest += ch; - } - - /* According to PEF ABI. */ - std::vector exts = kAsmFileExts; - dest += exts[4]; - - kState.fOutputAssembly = std::make_unique(dest); - - auto fmt = CompilerKit::current_date(); - - (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; - (*kState.fOutputAssembly) - << "# Language: 64x0 Assembly (Generated from ANSI C)\n"; - (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n"; - - ParserKit::SyntaxLeafList syntax; - - kState.fSyntaxTreeList.push_back(syntax); - kState.fSyntaxTree = - &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; - - std::string line_src; - - while (std::getline(src_fp, line_src)) - { - if (auto err = kCompilerBackend->Check(line_src.c_str(), src.data()); - err.empty()) - { - kCompilerBackend->Compile(line_src, src.data()); - } - else - { - detail::print_error(err, src.data()); - } - } - - if (kAcceptableErrors > 0) - return -1; - - std::vector keywords = {"ldw", "stw", "lda", "sta", - "add", "sub", "mv"}; - - /// - /// Replace, optimize, fix assembly output. - /// - - for (auto& leaf : kState.fSyntaxTree->fLeafList) - { - std::vector access_keywords = {"->", "."}; - - for (auto& access_ident : access_keywords) - { - if (ParserKit::find_word(leaf.fUserValue, access_ident)) - { - for (auto& struc : kState.kStructMap) - { - /// TODO: - } - } - } - - for (auto& keyword : keywords) - { - if (ParserKit::find_word(leaf.fUserValue, keyword)) - { - std::size_t cnt = 0UL; - - for (auto& reg : kState.kStackFrame) - { - std::string needle; - - for (size_t i = 0; i < reg.fName.size(); i++) - { - if (reg.fName[i] == ' ') - { - ++i; - - for (; i < reg.fName.size(); i++) - { - if (reg.fName[i] == ',') - { - break; - } - - if (reg.fName[i] == ' ') - continue; - - needle += reg.fName[i]; - } - - break; - } - } - - if (ParserKit::find_word(leaf.fUserValue, needle)) - { - if (leaf.fUserValue.find("import " + needle) != - std::string::npos) - { - std::string range = "import " + needle; - leaf.fUserValue.replace( - leaf.fUserValue.find("import " + needle), range.size(), - needle); - } - - if (leaf.fUserValue.find("ldw r6") != std::string::npos) - { - std::string::difference_type countComma = std::count( - leaf.fUserValue.begin(), leaf.fUserValue.end(), ','); - - if (countComma == 1) - { - leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), - strlen("ldw"), "mv"); - } - } - - leaf.fUserValue.replace(leaf.fUserValue.find(needle), - needle.size(), reg.fReg); - - ++cnt; - } - } - - if (cnt > 1 && keyword != "mv" && keyword != "add" && - keyword != "sub") - { - leaf.fUserValue.replace(leaf.fUserValue.find(keyword), - keyword.size(), "mv"); - } - } - } - } - - for (auto& leaf : kState.fSyntaxTree->fLeafList) - { - (*kState.fOutputAssembly) << leaf.fUserValue; - } - - kState.fSyntaxTree = nullptr; - - kState.fOutputAssembly->flush(); - kState.fOutputAssembly.reset(); - - return kOk; - } -}; - -///////////////////////////////////////////////////////////////////////////////////////// - -#include - -#define kPrintF printf -#define kSplashCxx() \ - kPrintF(kWhite "Zeta C Driver, %s, (c) ZKA Technologies\n", kDistVersion) - -static void cc_print_help() -{ - kSplashCxx(); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -#define kExt ".c" - -NDK_MODULE(NewOSCompilerCLang64x0) -{ - kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); - kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); - kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); - kCompilerTypes.push_back({.fName = "int", .fValue = "dword"}); - kCompilerTypes.push_back({.fName = "long", .fValue = "qword"}); - kCompilerTypes.push_back({.fName = "*", .fValue = "offset"}); - - bool skip = false; - - kFactory.Mount(new AssemblyCCInterface()); - kMachine = CompilerKit::AssemblyFactory::kArch64x0; - kCompilerBackend = new CompilerBackendCLang(); - - for (auto index = 1UL; index < argc; ++index) - { - if (skip) - { - skip = false; - continue; - } - - if (argv[index][0] == '/') - { - if (strcmp(argv[index], "/v") == 0 || - strcmp(argv[index], "/version") == 0) - { - kSplashCxx(); - return kOk; - } - - if (strcmp(argv[index], "/verbose") == 0) - { - kState.fVerbose = true; - - continue; - } - - if (strcmp(argv[index], "/h") == 0 || strcmp(argv[index], "/help") == 0) - { - cc_print_help(); - - return kOk; - } - - if (strcmp(argv[index], "/dialect") == 0) - { - if (kCompilerBackend) - std::cout << kCompilerBackend->Language() << "\n"; - - return kOk; - } - - if (strcmp(argv[index], "/fmax-exceptions") == 0) - { - try - { - kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); - } - // catch anything here - catch (...) - { - kErrorLimit = 0; - } - - skip = true; - - continue; - } - - std::string err = "Unknown command: "; - err += argv[index]; - - detail::print_error(err, "cc"); - - continue; - } - - kFileList.emplace_back(argv[index]); - - std::string srcFile = argv[index]; - - if (strstr(argv[index], kExt) == nullptr) - { - if (kState.fVerbose) - { - detail::print_error(srcFile + " is not a valid C source.\n", "cc"); - } - - return 1; - } - - if (kFactory.Compile(srcFile, kMachine) != kOk) - return -1; - } - - return kOk; -} - -// Last rev 8-1-24 diff --git a/Sources/64x0-cc.cxx b/Sources/64x0-cc.cxx new file mode 100644 index 0000000..47abfb5 --- /dev/null +++ b/Sources/64x0-cc.cxx @@ -0,0 +1,1627 @@ +/* + * ======================================================== + * + * cc + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +/// BUGS: ? +/// TODO: + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* C driver */ +/* This is part of the NDK. */ +/* (c) ZKA Technologies */ + +/// @author Amlal El Mahrouss (amlel) +/// @file 64x0-cc.cxx +/// @brief 64x0 C Compiler. + +/// TODO: support structures, else if, else, . and -> + +///////////////////// + +// ANSI ESCAPE CODES + +///////////////////// + +#define kOk (0) + +#define kBlank "\e[0;30m" +#define kRed "\e[0;31m" +#define kWhite "\e[0;97m" + +///////////////////////////////////// + +// INTERNAL STUFF OF THE C COMPILER + +///////////////////////////////////// + +namespace detail +{ + // \brief name to register struct. + struct CompilerRegisterMap final + { + std::string fName; + std::string fReg; + }; + + // \brief Map for C structs + // \author amlel + struct CompilerStructMap final + { + // 'my_foo' + std::string fName; + + // if instance: stores a valid register. + std::string fReg; + + // offset count + std::size_t fOffsetsCnt; + + // offset array. + std::vector> fOffsets; + }; + + struct CompilerState final + { + std::vector fSyntaxTreeList; + std::vector kStackFrame; + std::vector kStructMap; + ParserKit::SyntaxLeafList* fSyntaxTree{nullptr}; + std::unique_ptr fOutputAssembly; + std::string fLastFile; + std::string fLastError; + bool fVerbose; + }; +} // namespace detail + +static detail::CompilerState kState; +static SizeType kErrorLimit = 100; +static std::string kIfFunction = ""; +static Int32 kAcceptableErrors = 0; + +namespace detail +{ + /// @brief prints an error into stdout. + /// @param reason the reason of the error. + /// @param file where does it originate from? + void print_error(std::string reason, std::string file) noexcept + { + if (reason[0] == '\n') + reason.erase(0, 1); + + if (file.find(".pp") != std::string::npos) + { + file.erase(file.find(".pp"), 3); + } + + if (kState.fLastFile != file) + { + std::cout << kRed << "[ cc ] " << kWhite + << ((file == "cc") ? "internal compiler error " + : ("in file, " + file)) + << kBlank << std::endl; + std::cout << kRed << "[ cc ] " << kWhite << reason << kBlank << std::endl; + + kState.fLastFile = file; + } + else + { + std::cout << kRed << "[ cc ] [ " << kState.fLastFile << " ] " << kWhite + << reason << kBlank << std::endl; + } + + if (kAcceptableErrors > kErrorLimit) + std::exit(3); + + ++kAcceptableErrors; + } + + struct CompilerType final + { + std::string fName; + std::string fValue; + }; +} // namespace detail + +///////////////////////////////////////////////////////////////////////////////////////// + +// Target architecture. +static int kMachine = 0; + +///////////////////////////////////////// + +// REGISTERS ACCORDING TO USED ASSEMBLER + +///////////////////////////////////////// + +static size_t kRegisterCnt = kAsmRegisterLimit; +static size_t kStartUsable = 2; +static size_t kUsableLimit = 15; +static size_t kRegisterCounter = kStartUsable; +static std::string kRegisterPrefix = kAsmRegisterPrefix; + +///////////////////////////////////////// + +// COMPILER PARSING UTILITIES/STATES. + +///////////////////////////////////////// + +static std::vector kFileList; +static CompilerKit::AssemblyFactory kFactory; +static bool kInStruct = false; +static bool kOnWhileLoop = false; +static bool kOnForLoop = false; +static bool kInBraces = false; +static bool kIfFound = false; +static size_t kBracesCount = 0UL; + +/* @brief C compiler backend for C */ +class CompilerBackendCLang final : public ParserKit::CompilerBackend +{ +public: + explicit CompilerBackendCLang() = default; + ~CompilerBackendCLang() override = default; + + MPCC_COPY_DEFAULT(CompilerBackendCLang); + + std::string Check(const char* text, const char* file); + bool Compile(const std::string& text, const char* file) override; + + const char* Language() override + { + return "64k C"; + } +}; + +static CompilerBackendCLang* kCompilerBackend = nullptr; +static std::vector kCompilerVariables; +static std::vector kCompilerFunctions; +static std::vector kCompilerTypes; + +namespace detail +{ + union number_cast final { + public: + number_cast(UInt64 _Raw) + : _Raw(_Raw) + { + } + + public: + char _Num[8]; + UInt64 _Raw; + }; + + union double_cast final { + public: + double_cast(float _Raw) + : _Raw(_Raw) + { + } + + public: + char _Sign; + char _Lh[8]; + char _Rh[23]; + + float _Raw; + }; +} // namespace detail + +///////////////////////////////////////////////////////////////////////////////////////// + +// @name Compile +// @brief Generate MASM from a C assignement. + +///////////////////////////////////////////////////////////////////////////////////////// + +bool CompilerBackendCLang::Compile(const std::string& text, const char* file) +{ + std::string textBuffer = text; + + bool typeFound = false; + bool fnFound = false; + + // setup generator. + std::random_device rd; + + auto seed_data = std::array{}; + std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); + std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); + std::mt19937 generator(seq); + + // start parsing + for (size_t text_index = 0; text_index < textBuffer.size(); ++text_index) + { + auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf(); + + auto gen = uuids::uuid_random_generator{generator}; + uuids::uuid out = gen(); + + detail::number_cast time_off = (UInt64)out.as_bytes().data(); + + if (!typeFound) + { + auto substr = textBuffer.substr(text_index); + std::string match_type; + + for (size_t y = 0; y < substr.size(); ++y) + { + if (substr[y] == ' ') + { + while (match_type.find(' ') != std::string::npos) + { + match_type.erase(match_type.find(' ')); + } + + for (auto& clType : kCompilerTypes) + { + if (clType.fName == match_type) + { + match_type.clear(); + + std::string buf; + + buf += clType.fValue; + buf += ' '; + + if (substr.find('=') != std::string::npos) + { + break; + } + + if (textBuffer.find('(') != std::string::npos) + { + syntaxLeaf.fUserValue = buf; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + } + + typeFound = true; + break; + } + } + + break; + } + + match_type += substr[y]; + } + } + + if (textBuffer[text_index] == '{') + { + if (kInStruct) + { + continue; + } + + kInBraces = true; + ++kBracesCount; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + } + + // return keyword handler + if (textBuffer[text_index] == 'r') + { + std::string return_keyword; + return_keyword += "return"; + + std::size_t index = 0UL; + + std::string value; + + for (size_t return_index = text_index; return_index < textBuffer.size(); + ++return_index) + { + if (textBuffer[return_index] != return_keyword[index]) + { + for (size_t value_index = return_index; + value_index < textBuffer.size(); ++value_index) + { + if (textBuffer[value_index] == ';') + break; + + value += textBuffer[value_index]; + } + + break; + } + + ++index; + } + + if (index == return_keyword.size()) + { + if (!value.empty()) + { + if (value.find('(') != std::string::npos) + { + value.erase(value.find('(')); + } + + if (!isdigit(value[value.find('(') + 2])) + { + std::string tmp = value; + bool reg_to_reg = false; + + value.clear(); + + value += " import"; + value += tmp; + } + + syntaxLeaf.fUserValue = "\tldw r19, "; + + // make it pretty. + if (value.find('\t') != std::string::npos) + value.erase(value.find('\t'), 1); + + syntaxLeaf.fUserValue += value + "\n"; + } + + syntaxLeaf.fUserValue += "\tjlr"; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + break; + } + } + + if (textBuffer[text_index] == 'i' && textBuffer[text_index + 1] == 'f') + { + auto expr = textBuffer.substr(text_index + 2); + textBuffer.erase(text_index, 2); + + if (expr.find("{") != std::string::npos) + { + expr.erase(expr.find("{")); + } + + if (expr.find("(") != std::string::npos) + expr.erase(expr.find("(")); + + if (expr.find(")") != std::string::npos) + expr.erase(expr.find(")")); + + kIfFunction = "__MPCC_IF_PROC_"; + kIfFunction += std::to_string(time_off._Raw); + + syntaxLeaf.fUserValue = "\tlda r12, import "; + syntaxLeaf.fUserValue += + kIfFunction + + "\n\t#r12 = Code to jump on, r11 right cond, r10 left cond.\n\tbeq " + "r10, r11, r12\ndword export .code64 " + + kIfFunction + "\n"; + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + kIfFound = true; + } + + // Parse expressions and instructions here. + // what does this mean? + // we encounter an assignment, or we reached the end of an expression. + if (textBuffer[text_index] == '=' || textBuffer[text_index] == ';') + { + if (fnFound) + continue; + if (kIfFound) + continue; + + if (textBuffer[text_index] == ';' && kInStruct) + continue; + + if (textBuffer.find("typedef ") != std::string::npos) + continue; + + if (textBuffer[text_index] == '=' && kInStruct) + { + detail::print_error("assignement of value in struct " + textBuffer, + file); + continue; + } + + if (textBuffer[text_index] == ';' && kInStruct) + { + bool space_found_ = false; + std::string sym; + + for (auto& ch : textBuffer) + { + if (ch == ' ') + { + space_found_ = true; + } + + if (ch == ';') + break; + + if (space_found_) + sym.push_back(ch); + } + + kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back( + std::make_pair( + kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, + sym)); + + kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt = + kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4; + + continue; + } + + if (textBuffer[text_index] == '=' && kInStruct) + { + continue; + } + + if (textBuffer[text_index + 1] == '=' || + textBuffer[text_index - 1] == '!' || + textBuffer[text_index - 1] == '<' || + textBuffer[text_index - 1] == '>') + { + continue; + } + + std::string substr; + + if (textBuffer.find('=') != std::string::npos && kInBraces && !kIfFound) + { + if (textBuffer.find("*") != std::string::npos) + { + if (textBuffer.find("=") > textBuffer.find("*")) + substr += "\tlda "; + else + substr += "\tldw "; + } + else + { + substr += "\tldw "; + } + } + else if (textBuffer.find('=') != std::string::npos && !kInBraces) + { + substr += "stw export .data64 "; + } + + int first_encountered = 0; + + std::string str_name; + + for (size_t text_index_2 = 0; text_index_2 < textBuffer.size(); + ++text_index_2) + { + if (textBuffer[text_index_2] == '\"') + { + ++text_index_2; + + // want to add this, so that the parser recognizes that this is a + // string. + substr += '"'; + + for (; text_index_2 < textBuffer.size(); ++text_index_2) + { + if (textBuffer[text_index_2] == '\"') + break; + + substr += textBuffer[text_index_2]; + } + } + + if (textBuffer[text_index_2] == '{' || textBuffer[text_index_2] == '}') + continue; + + if (textBuffer[text_index_2] == ';') + { + break; + } + + if (textBuffer[text_index_2] == ' ' || + textBuffer[text_index_2] == '\t') + { + if (first_encountered != 2) + { + if (textBuffer[text_index] != '=' && + substr.find("export .data64") == std::string::npos && + !kInStruct) + substr += "export .data64 "; + } + + ++first_encountered; + + continue; + } + + if (textBuffer[text_index_2] == '=') + { + if (!kInBraces) + { + substr.replace(substr.find("export .data64"), + strlen("export .data64"), "export .zero64 "); + } + + substr += ","; + continue; + } + + substr += textBuffer[text_index_2]; + } + + for (auto& clType : kCompilerTypes) + { + if (substr.find(clType.fName) != std::string::npos) + { + if (substr.find(clType.fName) > substr.find('"')) + continue; + + substr.erase(substr.find(clType.fName), clType.fName.size()); + } + else if (substr.find(clType.fValue) != std::string::npos) + { + if (substr.find(clType.fValue) > substr.find('"')) + continue; + + if (clType.fName == "const") + continue; + + substr.erase(substr.find(clType.fValue), clType.fValue.size()); + } + } + + if (substr.find("extern") != std::string::npos) + { + substr.replace(substr.find("extern"), strlen("extern"), "import "); + + if (substr.find("export .data64") != std::string::npos) + substr.erase(substr.find("export .data64"), strlen("export .data64")); + } + + auto var_to_find = + std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(), + [&](detail::CompilerType type) { + return type.fName.find(substr) != std::string::npos; + }); + + if (kRegisterCounter == 5 || kRegisterCounter == 6) + ++kRegisterCounter; + + std::string reg = kAsmRegisterPrefix; + reg += std::to_string(kRegisterCounter); + + if (var_to_find == kCompilerVariables.cend()) + { + ++kRegisterCounter; + + kState.kStackFrame.push_back({.fName = substr, .fReg = reg}); + kCompilerVariables.push_back({.fName = substr}); + } + + syntaxLeaf.fUserValue += substr; + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + if (textBuffer[text_index] == '=') + break; + } + + // function handler. + + if (textBuffer[text_index] == '(' && !fnFound && !kIfFound) + { + std::string substr; + std::string args_buffer; + std::string args; + + bool type_crossed = false; + + for (size_t idx = textBuffer.find('(') + 1; idx < textBuffer.size(); + ++idx) + { + if (textBuffer[idx] == ',') + continue; + + if (textBuffer[idx] == ' ') + continue; + + if (textBuffer[idx] == ')') + break; + } + + for (char substr_first_index : textBuffer) + { + if (substr_first_index != ',') + args_buffer += substr_first_index; + else + args_buffer += '$'; + + if (substr_first_index == ';') + { + args_buffer = args_buffer.erase(0, args_buffer.find('(')); + args_buffer = args_buffer.erase(args_buffer.find(';'), 1); + args_buffer = args_buffer.erase(args_buffer.find(')'), 1); + args_buffer = args_buffer.erase(args_buffer.find('('), 1); + + if (!args_buffer.empty()) + args += "\tldw r6, "; + + std::string register_type; + std::size_t index = 7UL; + + while (args_buffer.find("$") != std::string::npos) + { + register_type = kRegisterPrefix; + register_type += std::to_string(index); + + ++index; + + args_buffer.replace(args_buffer.find('$'), 1, + "\n\tldw " + register_type + ","); + } + + args += args_buffer; + args += "\n\tlda r19, "; + } + } + + for (char _text_i : textBuffer) + { + if (_text_i == '\t' || _text_i == ' ') + { + if (!type_crossed) + { + substr.clear(); + type_crossed = true; + } + + continue; + } + + if (_text_i == '(') + break; + + substr += _text_i; + } + + if (kInBraces) + { + syntaxLeaf.fUserValue = args; + syntaxLeaf.fUserValue += substr; + syntaxLeaf.fUserValue += "\n\tjrl\n"; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + fnFound = true; + } + else + { + syntaxLeaf.fUserValue.clear(); + + syntaxLeaf.fUserValue += "export .code64 "; + + syntaxLeaf.fUserValue += substr; + syntaxLeaf.fUserValue += "\n"; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + fnFound = true; + } + + kCompilerFunctions.push_back(textBuffer); + } + + if (textBuffer[text_index] == '-' && textBuffer[text_index + 1] == '-') + { + textBuffer = textBuffer.replace(textBuffer.find("--"), strlen("--"), ""); + + for (int _text_i = 0; _text_i < textBuffer.size(); ++_text_i) + { + if (textBuffer[_text_i] == '\t' || textBuffer[_text_i] == ' ') + textBuffer.erase(_text_i, 1); + } + + syntaxLeaf.fUserValue += "sub "; + syntaxLeaf.fUserValue += textBuffer; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + break; + } + + if (textBuffer[text_index] == '}') + { + kRegisterCounter = kStartUsable; + + --kBracesCount; + + if (kBracesCount < 1) + { + kInBraces = false; + kBracesCount = 0; + } + + if (kIfFound) + kIfFound = false; + + if (kInStruct) + kInStruct = false; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + } + + syntaxLeaf.fUserValue.clear(); + } + + auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf(); + syntaxLeaf.fUserValue = "\n"; + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + return true; +} + +static bool kShouldHaveBraces = false; +static std::string kFnName; + +std::string CompilerBackendCLang::Check(const char* text, const char* file) +{ + std::string err_str; + std::string ln = text; + + if (ln.empty()) + { + return err_str; + } + + bool non_ascii_found = false; + + for (int i = 0; i < ln.size(); ++i) + { + if (isalnum(ln[i])) + { + non_ascii_found = true; + break; + } + } + + if (kShouldHaveBraces && ln.find('{') != std::string::npos) + { + kShouldHaveBraces = false; + } + + if (!non_ascii_found) + return err_str; + + size_t string_index = 1UL; + + if (ln.find('\'') != std::string::npos) + { + string_index = ln.find('\'') + 1; + + for (; string_index < ln.size(); ++string_index) + { + if (ln[string_index] == '\'') + { + if (ln[string_index + 1] != ';') + { + ln.erase(string_index, 1); + } + + return err_str; + } + } + } + else if (ln.find('"') != std::string::npos) + { + string_index = ln.find('"') + 1; + + for (; string_index < ln.size(); ++string_index) + { + if (ln[string_index] == '"') + { + if (ln[string_index + 1] != ';') + { + ln.erase(string_index, 1); + } + else + { + break; + } + } + } + } + else if (ln.find('"') == std::string::npos && + ln.find('\'') == std::string::npos) + { + std::vector forbidden_words; + + forbidden_words.push_back("\\"); + forbidden_words.push_back("?"); + forbidden_words.push_back("@"); + forbidden_words.push_back("~"); + forbidden_words.push_back("::"); + forbidden_words.push_back("/*"); + forbidden_words.push_back("*/"); + + // add them to avoid stupid mistakes. + forbidden_words.push_back("namespace"); + forbidden_words.push_back("class"); + forbidden_words.push_back("extern \"C\""); + + for (auto& forbidden : forbidden_words) + { + if (ln.find(forbidden) != std::string::npos) + { + err_str += "\nForbidden character detected: "; + err_str += forbidden; + + return err_str; + } + } + } + + struct CompilerVariableRange final + { + std::string fBegin; + std::string fEnd; + }; + + const std::vector variables_list = { + {.fBegin = "static ", .fEnd = "="}, + {.fBegin = "=", .fEnd = ";"}, + {.fBegin = "if(", .fEnd = "="}, + {.fBegin = "if (", .fEnd = "="}, + {.fBegin = "if(", .fEnd = "<"}, + {.fBegin = "if (", .fEnd = "<"}, + {.fBegin = "if(", .fEnd = ">"}, + {.fBegin = "if (", .fEnd = ">"}, + {.fBegin = "if(", .fEnd = ")"}, + {.fBegin = "if (", .fEnd = ")"}, + + {.fBegin = "else(", .fEnd = "="}, + {.fBegin = "else (", .fEnd = "="}, + {.fBegin = "else(", .fEnd = "<"}, + {.fBegin = "else (", .fEnd = "<"}, + {.fBegin = "else(", .fEnd = ">"}, + {.fBegin = "else (", .fEnd = ">"}, + {.fBegin = "else(", .fEnd = ")"}, + {.fBegin = "else (", .fEnd = ")"}, + }; + + for (auto& variable : variables_list) + { + if (ln.find(variable.fBegin) != std::string::npos) + { + string_index = ln.find(variable.fBegin) + variable.fBegin.size(); + + while (ln[string_index] == ' ') + ++string_index; + + std::string keyword; + + for (; string_index < ln.size(); ++string_index) + { + if (ln[string_index] == variable.fEnd[0]) + { + std::string varname = ""; + + for (size_t index_keyword = ln.find(' '); + ln[index_keyword] != variable.fBegin[0]; ++index_keyword) + { + if (ln[index_keyword] == ' ') + { + continue; + } + + if (isdigit(ln[index_keyword])) + { + goto cc_next_loop; + } + + varname += ln[index_keyword]; + } + + if (varname.find(' ') != std::string::npos) + { + varname.erase(0, varname.find(' ')); + + if (variable.fBegin == "extern") + { + varname.erase(0, varname.find(' ')); + } + } + + if (kRegisterCounter == 5 || kRegisterCounter == 6) + ++kRegisterCounter; + + std::string reg = kAsmRegisterPrefix; + reg += std::to_string(kRegisterCounter); + + kCompilerVariables.push_back({.fValue = varname}); + goto cc_check_done; + } + + keyword.push_back(ln[string_index]); + } + + goto cc_next_loop; + + cc_check_done: + + // skip digit value. + if (isdigit(keyword[0]) || keyword[0] == '"') + { + goto cc_next_loop; + } + + while (keyword.find(' ') != std::string::npos) + keyword.erase(keyword.find(' '), 1); + + for (auto& var : kCompilerVariables) + { + if (var.fValue.find(keyword) != std::string::npos) + { + err_str.clear(); + goto cc_next; + } + } + + for (auto& fn : kCompilerFunctions) + { + if (fn.find(keyword[0]) != std::string::npos) + { + auto where_begin = fn.find(keyword[0]); + auto keyword_begin = 0UL; + auto failed = false; + + for (; where_begin < keyword.size(); ++where_begin) + { + if (fn[where_begin] == '(' && keyword[keyword_begin] == '(') + break; + + if (fn[where_begin] != keyword[keyword_begin]) + { + failed = true; + break; + } + + ++keyword_begin; + } + + if (!failed) + { + err_str.clear(); + goto cc_next; + } + else + { + continue; + } + } + } + + cc_error_value: + if (keyword.find("->") != std::string::npos) + return err_str; + + if (keyword.find(".") != std::string::npos) + return err_str; + + if (isalnum(keyword[0])) + err_str += "\nUndefined value: " + keyword; + + return err_str; + } + + cc_next_loop: + continue; + } + +cc_next: + + // extern does not declare anything, it imports a variable. + // so that's why it's not declare upper. + if (ParserKit::find_word(ln, "extern")) + { + auto substr = ln.substr(ln.find("extern") + strlen("extern")); + kCompilerVariables.push_back({.fValue = substr}); + } + + if (kShouldHaveBraces && ln.find('{') == std::string::npos) + { + err_str += "Missing '{' for function "; + err_str += kFnName; + err_str += "\n"; + + kShouldHaveBraces = false; + kFnName.clear(); + } + else if (kShouldHaveBraces && ln.find('{') != std::string::npos) + { + kShouldHaveBraces = false; + kFnName.clear(); + } + + bool type_not_found = true; + + if (ln.find('\'') != std::string::npos) + { + ln.replace(ln.find('\''), 3, "0"); + } + + auto first = ln.find('"'); + if (first != std::string::npos) + { + auto second = 0UL; + bool found_second_quote = false; + + for (size_t i = first + 1; i < ln.size(); ++i) + { + if (ln[i] == '\"') + { + found_second_quote = true; + second = i; + + break; + } + } + + if (!found_second_quote) + { + err_str += "Missing terminating \"."; + err_str += " here -> " + ln.substr(ln.find('"'), second); + } + } + + if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos) + { + if (ln.find('{') == std::string::npos) + { + kFnName = ln; + kShouldHaveBraces = true; + + goto skip_braces_check; + } + else if (ln.find('{') != std::string::npos) + { + kShouldHaveBraces = false; + } + } + +skip_braces_check: + + for (auto& key : kCompilerTypes) + { + if (ParserKit::find_word(ln, key.fName)) + { + if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) + { + err_str += "\nNumber cannot be set for "; + err_str += key.fName; + err_str += "'s name. here -> "; + err_str += ln; + } + + if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' || + ln[ln.find(key.fName) - 1] == '\t') + { + type_not_found = false; + + if (ln[ln.find(key.fName) + key.fName.size()] != ' ') + { + type_not_found = true; + + if (ln[ln.find(key.fName) + key.fName.size()] == '\t') + type_not_found = false; + + goto next; + } + else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') + { + type_not_found = true; + + if (ln[ln.find(key.fName) + key.fName.size()] == ' ') + type_not_found = false; + } + } + + next: + + if (ln.find(';') == std::string::npos) + { + if (ln.find('(') != std::string::npos) + { + if (ln.find('=') == std::string::npos) + continue; + } + + err_str += "\nMissing ';', here -> "; + err_str += ln; + } + else + { + continue; + } + + if (ln.find('=') != std::string::npos) + { + if (ln.find('(') != std::string::npos) + { + if (ln.find(')') == std::string::npos) + { + err_str += "\nMissing ')', after '(' here -> "; + err_str += ln.substr(ln.find('(')); + } + } + } + } + } + + if (kInBraces && ln.find("struct") != std::string::npos && + ln.find("union") != std::string::npos && + ln.find("enum") != std::string::npos && + ln.find('=') != std::string::npos) + { + if (ln.find(';') == std::string::npos) + { + err_str += "\nMissing ';' after struct/union/enum declaration, here -> "; + err_str += ln; + } + } + + if (ln.find(';') != std::string::npos && + ln.find("for") == std::string::npos) + { + if (ln.find(';') + 1 != ln.size()) + { + for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) + { + if ((ln.substr(ln.find(';') + 1)[i] != ' ') || + (ln.substr(ln.find(';') + 1)[i] != '\t')) + { + if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); + !err.empty()) + { + err_str += "\nUnexpected text after ';' -> "; + err_str += ln.substr(ln.find(';')); + err_str += err; + } + } + } + } + } + + if (ln.find('(') != std::string::npos) + { + if (ln.find(';') == std::string::npos && !ParserKit::find_word(ln, "|") && + !ParserKit::find_word(ln, "||") && !ParserKit::find_word(ln, "&") && + !ParserKit::find_word(ln, "&&") && !ParserKit::find_word(ln, "~")) + { + bool found_func = false; + size_t i = ln.find('('); + std::vector opens; + std::vector closes; + + for (; i < ln.size(); ++i) + { + if (ln[i] == ')') + { + closes.push_back(1); + } + + if (ln[i] == '(') + { + opens.push_back(1); + } + } + + if (closes.size() != opens.size()) + err_str += "Unterminated (), here -> " + ln; + + bool space_found = false; + + for (int i = 0; i < ln.size(); ++i) + { + if (ln[i] == ')' && !space_found) + { + space_found = true; + continue; + } + + if (space_found) + { + if (ln[i] == ' ' && isalnum(ln[i + 1])) + { + err_str += "\nBad function format here -> "; + err_str += ln; + } + } + } + } + + if (ln.find('(') < 1) + { + err_str += "\nMissing identifier before '(' here -> "; + err_str += ln; + } + else + { + if (type_not_found && ln.find(';') == std::string::npos && + ln.find("if") == std::string::npos && + ln.find("|") == std::string::npos && + ln.find("&") == std::string::npos && + ln.find("(") == std::string::npos && + ln.find(")") == std::string::npos) + { + err_str += "\n Missing ';' or type, here -> "; + err_str += ln; + } + } + + if (ln.find(')') == std::string::npos) + { + err_str += "\nMissing ')', after '(' here -> "; + err_str += ln.substr(ln.find('(')); + } + } + else + { + if (ln.find("for") != std::string::npos || + ln.find("while") != std::string::npos) + { + err_str += "\nMissing '(', after \"for\", here -> "; + err_str += ln; + } + } + + if (ln.find('}') != std::string::npos && !kInBraces) + { + if (!kInStruct && ln.find(';') == std::string::npos) + { + err_str += "\nMismatched '}', here -> "; + err_str += ln; + } + } + + if (!ln.empty()) + { + if (ln.find(';') == std::string::npos && + ln.find('{') == std::string::npos && + ln.find('}') == std::string::npos && + ln.find(')') == std::string::npos && + ln.find('(') == std::string::npos && + ln.find(',') == std::string::npos) + { + if (ln.size() <= 2) + return err_str; + + err_str += "\nMissing ';', here -> "; + err_str += ln; + } + } + + return err_str; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +/** + * @brief C To Assembly mount-point. + */ + +///////////////////////////////////////////////////////////////////////////////////////// + +class AssemblyCCInterface final : public CompilerKit::AssemblyInterface +{ +public: + explicit AssemblyCCInterface() = default; + ~AssemblyCCInterface() override = default; + + MPCC_COPY_DEFAULT(AssemblyCCInterface); + + [[maybe_unused]] static Int32 Arch() noexcept + { + return CompilerKit::AssemblyFactory::kArch64x0; + } + + Int32 CompileToFormat(std::string& src, Int32 arch) override + { + if (arch != AssemblyCCInterface::Arch()) + return -1; + + if (kCompilerBackend == nullptr) + return -1; + + /* @brief copy contents wihtout extension */ + std::string src_file = src.data(); + std::ifstream src_fp = std::ifstream(src_file, std::ios::in); + std::string dest; + + for (auto& ch : src_file) + { + if (ch == '.') + { + break; + } + + dest += ch; + } + + /* According to PEF ABI. */ + std::vector exts = kAsmFileExts; + dest += exts[4]; + + kState.fOutputAssembly = std::make_unique(dest); + + auto fmt = CompilerKit::current_date(); + + (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; + (*kState.fOutputAssembly) + << "# Language: 64x0 Assembly (Generated from ANSI C)\n"; + (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n"; + + ParserKit::SyntaxLeafList syntax; + + kState.fSyntaxTreeList.push_back(syntax); + kState.fSyntaxTree = + &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; + + std::string line_src; + + while (std::getline(src_fp, line_src)) + { + if (auto err = kCompilerBackend->Check(line_src.c_str(), src.data()); + err.empty()) + { + kCompilerBackend->Compile(line_src, src.data()); + } + else + { + detail::print_error(err, src.data()); + } + } + + if (kAcceptableErrors > 0) + return -1; + + std::vector keywords = {"ldw", "stw", "lda", "sta", + "add", "sub", "mv"}; + + /// + /// Replace, optimize, fix assembly output. + /// + + for (auto& leaf : kState.fSyntaxTree->fLeafList) + { + std::vector access_keywords = {"->", "."}; + + for (auto& access_ident : access_keywords) + { + if (ParserKit::find_word(leaf.fUserValue, access_ident)) + { + for (auto& struc : kState.kStructMap) + { + /// TODO: + } + } + } + + for (auto& keyword : keywords) + { + if (ParserKit::find_word(leaf.fUserValue, keyword)) + { + std::size_t cnt = 0UL; + + for (auto& reg : kState.kStackFrame) + { + std::string needle; + + for (size_t i = 0; i < reg.fName.size(); i++) + { + if (reg.fName[i] == ' ') + { + ++i; + + for (; i < reg.fName.size(); i++) + { + if (reg.fName[i] == ',') + { + break; + } + + if (reg.fName[i] == ' ') + continue; + + needle += reg.fName[i]; + } + + break; + } + } + + if (ParserKit::find_word(leaf.fUserValue, needle)) + { + if (leaf.fUserValue.find("import " + needle) != + std::string::npos) + { + std::string range = "import " + needle; + leaf.fUserValue.replace( + leaf.fUserValue.find("import " + needle), range.size(), + needle); + } + + if (leaf.fUserValue.find("ldw r6") != std::string::npos) + { + std::string::difference_type countComma = std::count( + leaf.fUserValue.begin(), leaf.fUserValue.end(), ','); + + if (countComma == 1) + { + leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), + strlen("ldw"), "mv"); + } + } + + leaf.fUserValue.replace(leaf.fUserValue.find(needle), + needle.size(), reg.fReg); + + ++cnt; + } + } + + if (cnt > 1 && keyword != "mv" && keyword != "add" && + keyword != "sub") + { + leaf.fUserValue.replace(leaf.fUserValue.find(keyword), + keyword.size(), "mv"); + } + } + } + } + + for (auto& leaf : kState.fSyntaxTree->fLeafList) + { + (*kState.fOutputAssembly) << leaf.fUserValue; + } + + kState.fSyntaxTree = nullptr; + + kState.fOutputAssembly->flush(); + kState.fOutputAssembly.reset(); + + return kOk; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +#include + +#define kPrintF printf +#define kSplashCxx() \ + kPrintF(kWhite "Zeta C Driver, %s, (c) ZKA Technologies\n", kDistVersion) + +static void cc_print_help() +{ + kSplashCxx(); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +#define kExt ".c" + +NDK_MODULE(NewOSCompilerCLang64x0) +{ + kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); + kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); + kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); + kCompilerTypes.push_back({.fName = "int", .fValue = "dword"}); + kCompilerTypes.push_back({.fName = "long", .fValue = "qword"}); + kCompilerTypes.push_back({.fName = "*", .fValue = "offset"}); + + bool skip = false; + + kFactory.Mount(new AssemblyCCInterface()); + kMachine = CompilerKit::AssemblyFactory::kArch64x0; + kCompilerBackend = new CompilerBackendCLang(); + + for (auto index = 1UL; index < argc; ++index) + { + if (skip) + { + skip = false; + continue; + } + + if (argv[index][0] == '/') + { + if (strcmp(argv[index], "/v") == 0 || + strcmp(argv[index], "/version") == 0) + { + kSplashCxx(); + return kOk; + } + + if (strcmp(argv[index], "/verbose") == 0) + { + kState.fVerbose = true; + + continue; + } + + if (strcmp(argv[index], "/h") == 0 || strcmp(argv[index], "/help") == 0) + { + cc_print_help(); + + return kOk; + } + + if (strcmp(argv[index], "/dialect") == 0) + { + if (kCompilerBackend) + std::cout << kCompilerBackend->Language() << "\n"; + + return kOk; + } + + if (strcmp(argv[index], "/fmax-exceptions") == 0) + { + try + { + kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); + } + // catch anything here + catch (...) + { + kErrorLimit = 0; + } + + skip = true; + + continue; + } + + std::string err = "Unknown command: "; + err += argv[index]; + + detail::print_error(err, "cc"); + + continue; + } + + kFileList.emplace_back(argv[index]); + + std::string srcFile = argv[index]; + + if (strstr(argv[index], kExt) == nullptr) + { + if (kState.fVerbose) + { + detail::print_error(srcFile + " is not a valid C source.\n", "cc"); + } + + return 1; + } + + if (kFactory.Compile(srcFile, kMachine) != kOk) + return -1; + } + + return kOk; +} + +// Last rev 8-1-24 diff --git a/Sources/AssemblyFactory.cc b/Sources/AssemblyFactory.cc deleted file mode 100644 index 35d8cbd..0000000 --- a/Sources/AssemblyFactory.cc +++ /dev/null @@ -1,59 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#include -#include - -/** - * @file AssemblyFactory.cc - * @author amlal (amlal@zeta.com) - * @brief Assembler Kit - * @version 0.1 - * @date 2024-01-27 - * - * @copyright Copyright (c) 2024, ZKA Technologies - * - */ - -#include - -//! @file AsmKit.cpp -//! @brief AssemblyKit source implementation. - -namespace CompilerKit -{ - ///! @brief Compile for specific format (ELF, PEF, ZBIN) - Int32 AssemblyFactory::Compile(std::string& sourceFile, - const Int32& arch) noexcept - { - if (sourceFile.length() < 1 || !fMounted) - return MPCC_UNIMPLEMENTED; - - return fMounted->CompileToFormat(sourceFile, arch); - } - - ///! @brief mount assembly backend. - void AssemblyFactory::Mount(AssemblyInterface* mountPtr) noexcept - { - if (mountPtr) - { - fMounted = mountPtr; - } - } - - ///! @brief Unmount assembler. - AssemblyInterface* AssemblyFactory::Unmount() noexcept - { - auto mount_prev = fMounted; - - if (mount_prev) - { - fMounted = nullptr; - } - - return mount_prev; - } -} // namespace CompilerKit diff --git a/Sources/AssemblyFactory.cxx b/Sources/AssemblyFactory.cxx new file mode 100644 index 0000000..61dbebd --- /dev/null +++ b/Sources/AssemblyFactory.cxx @@ -0,0 +1,59 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#include +#include + +/** + * @file AssemblyFactory.cxx + * @author amlal (amlal@zeta.com) + * @brief Assembler Kit + * @version 0.1 + * @date 2024-01-27 + * + * @copyright Copyright (c) 2024, ZKA Technologies + * + */ + +#include + +//! @file AsmKit.cpp +//! @brief AssemblyKit source implementation. + +namespace CompilerKit +{ + ///! @brief Compile for specific format (ELF, PEF, ZBIN) + Int32 AssemblyFactory::Compile(std::string& sourceFile, + const Int32& arch) noexcept + { + if (sourceFile.length() < 1 || !fMounted) + return MPCC_UNIMPLEMENTED; + + return fMounted->CompileToFormat(sourceFile, arch); + } + + ///! @brief mount assembly backend. + void AssemblyFactory::Mount(AssemblyInterface* mountPtr) noexcept + { + if (mountPtr) + { + fMounted = mountPtr; + } + } + + ///! @brief Unmount assembler. + AssemblyInterface* AssemblyFactory::Unmount() noexcept + { + auto mount_prev = fMounted; + + if (mount_prev) + { + fMounted = nullptr; + } + + return mount_prev; + } +} // namespace CompilerKit diff --git a/Sources/Detail/asmutils.hxx b/Sources/Detail/asmutils.hxx index 00bfbd7..bf05830 100644 --- a/Sources/Detail/asmutils.hxx +++ b/Sources/Detail/asmutils.hxx @@ -6,8 +6,8 @@ #pragma once -#include -#include +#include +#include using namespace CompilerKit; diff --git a/Sources/Detail/compilerutils.hxx b/Sources/Detail/compilerutils.hxx index 4c46727..6f6361c 100644 --- a/Sources/Detail/compilerutils.hxx +++ b/Sources/Detail/compilerutils.hxx @@ -6,8 +6,8 @@ #pragma once -#include -#include +#include +#include #define kZero64Section ".zero64" #define kCode64Section ".code64" diff --git a/Sources/String.cc b/Sources/String.cc deleted file mode 100644 index accc1af..0000000 --- a/Sources/String.cc +++ /dev/null @@ -1,200 +0,0 @@ -/* - * ======================================================== - * - * CompilerKit - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -/** - * @file String.cc - * @author Amlal (amlal@mahrouss-logic.com) - * @brief C++ string manipulation API. - * @version 0.2 - * @date 2024-01-23 - * - * @copyright Copyright (c) ZKA Technologies - * - */ - -#include - -namespace CompilerKit { -CharType *StringView::Data() { return m_Data; } - -const CharType *StringView::CData() const { return m_Data; } - -SizeType StringView::Length() const { return strlen(m_Data); } - -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"); - - auto ret_len = 8 + string_length(fmt); - char *ret = new char[ret_len]; - - if (!ret) return ("-1"); - - memset(ret, 0, ret_len); - - 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 *fmtRight) { - if (!fmt || !fmtRight) return ("?"); - - char *ret = new char[string_length(fmtRight) + string_length(fmtRight)]; - 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(fmtRight); ++y_idx) { - ret[result_cnt] = fmtRight[y_idx]; - ++result_cnt; - } - - break; - } - - ret[idx] = fmt[idx]; - } - - return ret; -} - -StringView &StringView::operator+=(const CharType *rhs) { - if (strlen(rhs) > this->m_Sz) { - throw std::runtime_error("out_of_bounds: StringView"); - } - - memcpy(this->m_Data + this->m_Cur, rhs, strlen(rhs)); - this->m_Cur += strlen(rhs); - - return *this; -} - -StringView &StringView::operator+=(const StringView &rhs) { - if (rhs.m_Cur > this->m_Sz) { - throw std::runtime_error("out_of_bounds: StringView"); - } - - memcpy(this->m_Data + this->m_Cur, rhs.CData(), strlen(rhs.CData())); - this->m_Cur += strlen(rhs.CData()); - - return *this; -} -} // namespace CompilerKit diff --git a/Sources/String.cxx b/Sources/String.cxx new file mode 100644 index 0000000..8b8cb9c --- /dev/null +++ b/Sources/String.cxx @@ -0,0 +1,200 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +/** + * @file String.cxx + * @author Amlal (amlal@mahrouss-logic.com) + * @brief C++ string manipulation API. + * @version 0.2 + * @date 2024-01-23 + * + * @copyright Copyright (c) ZKA Technologies + * + */ + +#include + +namespace CompilerKit { +CharType *StringView::Data() { return m_Data; } + +const CharType *StringView::CData() const { return m_Data; } + +SizeType StringView::Length() const { return strlen(m_Data); } + +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"); + + auto ret_len = 8 + string_length(fmt); + char *ret = new char[ret_len]; + + if (!ret) return ("-1"); + + memset(ret, 0, ret_len); + + 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 *fmtRight) { + if (!fmt || !fmtRight) return ("?"); + + char *ret = new char[string_length(fmtRight) + string_length(fmtRight)]; + 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(fmtRight); ++y_idx) { + ret[result_cnt] = fmtRight[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; +} + +StringView &StringView::operator+=(const CharType *rhs) { + if (strlen(rhs) > this->m_Sz) { + throw std::runtime_error("out_of_bounds: StringView"); + } + + memcpy(this->m_Data + this->m_Cur, rhs, strlen(rhs)); + this->m_Cur += strlen(rhs); + + return *this; +} + +StringView &StringView::operator+=(const StringView &rhs) { + if (rhs.m_Cur > this->m_Sz) { + throw std::runtime_error("out_of_bounds: StringView"); + } + + memcpy(this->m_Data + this->m_Cur, rhs.CData(), strlen(rhs.CData())); + this->m_Cur += strlen(rhs.CData()); + + return *this; +} +} // namespace CompilerKit diff --git a/Sources/bpp.cc b/Sources/bpp.cc deleted file mode 100644 index 1aefc33..0000000 --- a/Sources/bpp.cc +++ /dev/null @@ -1,899 +0,0 @@ -/* - * ======================================================== - * - * bpp - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -/// BUGS: 0 - -#include -#include -#include -#include -#include -#include -#include - -#define kMacroPrefix '%' - -/// @author Amlal El Mahrouss (amlel) -/// @file bpp.cc -/// @brief Preprocessor. - -typedef Int32 (*bpp_parser_fn_t)(std::string &line, std::ifstream &hdr_file, - std::ofstream &pp_out); - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief Preprocessor internal types. - -///////////////////////////////////////////////////////////////////////////////////////// - -namespace details { -enum { - kEqual, - kGreaterEqThan, - kLesserEqThan, - kGreaterThan, - kLesserThan, - kNotEqual, -}; - -struct bpp_macro_condition final { - int32_t fType; - std::string fTypeName; -}; - -struct bpp_macro final { - std::vector fArgs; - std::string fName; - std::string fValue; -}; - -class bpp_pragma final { - public: - explicit bpp_pragma() = default; - ~bpp_pragma() = default; - - MPCC_COPY_DEFAULT(bpp_pragma); - - std::string fMacroName; - bpp_parser_fn_t fParse; -}; -} // namespace details - -static std::vector kFiles; -static std::vector kMacros; -static std::vector kIncludes; - -static std::string kWorkingDir; - -static std::vector kKeywords = { - "include", "if", "pragma", "def", "elif", - "ifdef", "ifndef", "else", "warning", "error"}; - -#define kKeywordCxxCnt kKeywords.size() - -///////////////////////////////////////////////////////////////////////////////////////// - -// @name bpp_parse_if_condition -// @brief parse #if condition - -///////////////////////////////////////////////////////////////////////////////////////// - -int32_t bpp_parse_if_condition(details::bpp_macro_condition &cond, - details::bpp_macro ¯o, bool &inactive_code, - bool &defined, std::string ¯o_str) { - if (cond.fType == details::kEqual) { - auto substr_macro = - macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); - - if (substr_macro.find(macro.fValue) != std::string::npos) { - if (macro.fValue == "0") { - defined = false; - inactive_code = true; - - return 1; - } - - defined = true; - inactive_code = false; - - return 1; - } - } else if (cond.fType == details::kNotEqual) { - auto substr_macro = - macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); - - if (substr_macro.find(macro.fName) != std::string::npos) { - if (substr_macro.find(macro.fValue) != std::string::npos) { - defined = false; - inactive_code = true; - - return 1; - } - - defined = true; - inactive_code = false; - - return 1; - } - - return 0; - } - - auto substr_macro = - macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); - - std::string number; - - for (auto ¯o_num : kMacros) { - if (substr_macro.find(macro_num.fName) != std::string::npos) { - for (size_t i = 0; i < macro_num.fName.size(); ++i) { - if (isdigit(macro_num.fValue[i])) { - number += macro_num.fValue[i]; - } else { - number.clear(); - break; - } - } - - break; - } - } - - size_t y = 2; - - /* last try */ - for (; y < macro_str.size(); y++) { - if (isdigit(macro_str[y])) { - for (size_t x = y; x < macro_str.size(); x++) { - if (macro_str[x] == ' ') break; - - number += macro_str[x]; - } - - break; - } - } - - size_t rhs = atol(macro.fValue.c_str()); - size_t lhs = atol(number.c_str()); - - if (lhs == 0) { - number.clear(); - ++y; - - for (; y < macro_str.size(); y++) { - if (isdigit(macro_str[y])) { - for (size_t x = y; x < macro_str.size(); x++) { - if (macro_str[x] == ' ') break; - - number += macro_str[x]; - } - - break; - } - } - - lhs = atol(number.c_str()); - } - - if (cond.fType == details::kGreaterThan) { - if (lhs < rhs) { - defined = true; - inactive_code = false; - - return 1; - } - - return 0; - } - - if (cond.fType == details::kGreaterEqThan) { - if (lhs <= rhs) { - defined = true; - inactive_code = false; - - return 1; - } - - return 0; - } - - if (cond.fType == details::kLesserEqThan) { - if (lhs >= rhs) { - defined = true; - inactive_code = false; - - return 1; - } - - return 0; - } - - if (cond.fType == details::kLesserThan) { - if (lhs > rhs) { - defined = true; - inactive_code = false; - - return 1; - } - - return 0; - } - - return 0; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief stores every included file here. - -///////////////////////////////////////////////////////////////////////////////////////// - -std::vector kAllIncludes; - -///////////////////////////////////////////////////////////////////////////////////////// - -// @name bpp_parse_file -// @brief parse file to preprocess it. - -///////////////////////////////////////////////////////////////////////////////////////// - -void bpp_parse_file(std::ifstream &hdr_file, std::ofstream &pp_out) { - std::string hdr_line; - std::string line_after_include; - - bool inactive_code = false; - bool defined = false; - - try { - while (std::getline(hdr_file, hdr_line)) { - /// BPP Documentation. - if (hdr_line.find("@bdoc") != std::string::npos) { - hdr_line.erase(hdr_line.find("@bdoc")); - } - - if (hdr_line[0] == kMacroPrefix && - hdr_line.find("endif") != std::string::npos) { - if (!defined && inactive_code) { - inactive_code = false; - defined = false; - - continue; - } - - continue; - } - - if (!defined && inactive_code) { - continue; - } - - if (defined && inactive_code) { - continue; - } - - for (auto macro : kMacros) { - if (ParserKit::find_word(hdr_line, macro.fName) && - hdr_line.find("%def") == std::string::npos) { - auto value = macro.fValue; - - hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), - value); - } - } - - if (hdr_line[0] == kMacroPrefix && - hdr_line.find("def ") != std::string::npos) { - auto line_after_define = - hdr_line.substr(hdr_line.find("def ") + strlen("def ")); - - std::string macro_value; - std::string macro_key; - - std::size_t pos = 0UL; - - std::vector args; - bool on_args = false; - - for (auto &ch : line_after_define) { - ++pos; - - if (ch == '(') { - on_args = true; - continue; - } - - if (ch == ')') { - on_args = false; - continue; - } - - if (ch == '\\') continue; - - if (on_args) continue; - - if (ch == ' ') { - for (size_t i = pos; i < line_after_define.size(); i++) { - macro_value += line_after_define[i]; - } - - break; - } - - macro_key += ch; - } - - std::vector dupls; - std::string str; - - line_after_define.erase(0, line_after_define.find("(") + 1); - - for (auto &subc : line_after_define) { - if (subc == ',' || subc == ')') { - if (str.empty()) continue; - - dupls.push_back(str); - args.push_back(str); - - str.clear(); - - continue; - } - - if (isalnum(subc)) str.push_back(subc); - } - - for (auto &dupl : dupls) { - std::size_t cnt = 0; - - for (auto &arg : args) { - if (dupl == arg) ++cnt; - } - - if (cnt > 1) { - auto it = std::find(args.begin(), args.end(), dupl); - - while (it != args.end()) { - args.erase(it); - it = std::find(args.begin(), args.end(), dupl); - } - } - } - - details::bpp_macro macro; - - macro.fArgs = args; - macro.fName = macro_key; - macro.fValue = macro_value; - - kMacros.emplace_back(macro); - - continue; - } - - if (hdr_line[0] != kMacroPrefix) { - if (inactive_code) { - continue; - } - - for (auto ¯o : kMacros) { - if (hdr_line.find(macro.fName) != std::string::npos) { - std::vector arg_values; - - if (macro.fArgs.size() > 0) { - for (size_t i = 0; i < hdr_line.size(); ++i) { - if (hdr_line[i] == '(') { - std::string tmp_arg; - - for (size_t x = i; x < hdr_line.size(); x++) { - if (hdr_line[x] == ')') break; - - if (hdr_line[x] == ' ') continue; - - if (hdr_line[i] == '\\') continue; - - if (hdr_line[x] == ',') { - arg_values.push_back(tmp_arg); - tmp_arg.clear(); - continue; - } - - tmp_arg += hdr_line[x]; - } - - break; - } - } - - std::string symbol; - - for (char i : macro.fValue) { - if (i == '(') break; - - if (i == '\\') continue; - - symbol += i; - } - - hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), - symbol); - - size_t x_arg_indx = 0; - - for (size_t i = hdr_line.find(macro.fValue); i < hdr_line.size(); - ++i) { - if (hdr_line.find(macro.fArgs[x_arg_indx]) == i) { - hdr_line.replace(i, macro.fArgs[x_arg_indx].size(), - arg_values[x_arg_indx]); - ++x_arg_indx; - } - } - } else { - std::string symbol; - - for (size_t i = 0; i < macro.fValue.size(); i++) { - if (macro.fValue[i] == ' ') continue; - - if (macro.fValue[i] == '\\') continue; - - symbol += macro.fValue[i]; - } - - hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), - symbol); - } - - break; - } - } - - pp_out << hdr_line << std::endl; - - continue; - } - - if (hdr_line[0] == kMacroPrefix && - hdr_line.find("ifndef") != std::string::npos) { - auto line_after_ifndef = - hdr_line.substr(hdr_line.find("ifndef") + strlen("ifndef") + 1); - std::string macro; - - for (auto &ch : line_after_ifndef) { - if (ch == ' ') { - break; - } - - macro += ch; - } - - if (macro == "0") { - defined = true; - inactive_code = false; - continue; - } - - if (macro == "1") { - defined = false; - inactive_code = true; - - continue; - } - - bool found = false; - - defined = true; - inactive_code = false; - - for (auto ¯o_ref : kMacros) { - if (hdr_line.find(macro_ref.fName) != std::string::npos) { - found = true; - break; - } - } - - if (found) { - defined = false; - inactive_code = true; - - continue; - } - } else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("else") != std::string::npos) { - if (!defined && inactive_code) { - inactive_code = false; - defined = true; - - continue; - } else { - defined = false; - inactive_code = true; - - continue; - } - } else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("ifdef") != std::string::npos) { - auto line_after_ifdef = - hdr_line.substr(hdr_line.find("ifdef") + strlen("ifdef") + 1); - std::string macro; - - for (auto &ch : line_after_ifdef) { - if (ch == ' ') { - break; - } - - macro += ch; - } - - if (macro == "0") { - defined = false; - inactive_code = true; - - continue; - } - - if (macro == "1") { - defined = true; - inactive_code = false; - - continue; - } - - defined = false; - inactive_code = true; - - for (auto ¯o_ref : kMacros) { - if (hdr_line.find(macro_ref.fName) != std::string::npos) { - defined = true; - inactive_code = false; - - break; - } - } - } else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("pragma") != std::string::npos) { - line_after_include = hdr_line.substr(hdr_line.find("pragma once")); - - // search for this file - auto it = std::find(kAllIncludes.cbegin(), kAllIncludes.cend(), - line_after_include); - - if (it == kAllIncludes.cend()) { - goto kIncludeFile; - } - } else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("if") != std::string::npos) { - inactive_code = true; - - std::vector bpp_macro_condition_list = { - { - .fType = details::kEqual, - .fTypeName = "==", - }, - { - .fType = details::kNotEqual, - .fTypeName = "!=", - }, - { - .fType = details::kLesserThan, - .fTypeName = "<", - }, - { - .fType = details::kGreaterThan, - .fTypeName = ">", - }, - { - .fType = details::kLesserEqThan, - .fTypeName = "<=", - }, - { - .fType = details::kGreaterEqThan, - .fTypeName = ">=", - }, - }; - - int32_t good_to_go = 0; - - for (auto ¯o_condition : bpp_macro_condition_list) { - if (hdr_line.find(macro_condition.fTypeName) != std::string::npos) { - for (auto &found_macro : kMacros) { - if (hdr_line.find(found_macro.fName) != std::string::npos) { - good_to_go = - bpp_parse_if_condition(macro_condition, found_macro, - inactive_code, defined, hdr_line); - - break; - } - } - } - } - - if (good_to_go) continue; - - auto line_after_if = - hdr_line.substr(hdr_line.find("if") + strlen("if") + 1); - std::string macro; - - for (auto &ch : line_after_if) { - if (ch == ' ') { - break; - } - - macro += ch; - } - - if (macro == "0") { - defined = false; - inactive_code = true; - continue; - } - - if (macro == "1") { - defined = true; - inactive_code = false; - - continue; - } - - // last try, is it defined to be one? - for (auto ¯o_ref : kMacros) { - if (macro_ref.fName.find(macro) != std::string::npos && - macro_ref.fValue == "1") { - inactive_code = false; - defined = true; - - break; - } - } - } else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("warning") != std::string::npos) { - auto line_after_warning = - hdr_line.substr(hdr_line.find("warning") + strlen("warning") + 1); - std::string message; - - for (auto &ch : line_after_warning) { - if (ch == '\r' || ch == '\n') { - break; - } - - message += ch; - } - - std::cout << "Warning: " << message << std::endl; - } else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("error") != std::string::npos) { - auto line_after_warning = - hdr_line.substr(hdr_line.find("error") + strlen("error") + 1); - std::string message; - - for (auto &ch : line_after_warning) { - if (ch == '\r' || ch == '\n') { - break; - } - - message += ch; - } - - throw std::runtime_error("Error: " + message); - } else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("inc ") != std::string::npos) { - line_after_include = - hdr_line.substr(hdr_line.find("inc ") + strlen("inc ")); - - kIncludeFile: - auto it = std::find(kAllIncludes.cbegin(), kAllIncludes.cend(), - line_after_include); - - if (it != kAllIncludes.cend()) { - continue; - } - - std::string path; - - kAllIncludes.push_back(line_after_include); - - bool enable = false; - bool not_local = false; - - for (auto &ch : line_after_include) { - if (ch == ' ') continue; - - if (ch == '<') { - not_local = true; - enable = true; - - continue; - } - - if (ch == '\'') { - enable = true; - continue; - } - - if (enable) { - if (not_local) { - if (ch == '>') break; - } else { - if (ch == '\'') { - break; - } - } - - path += ch; - } - } - - if (not_local) { - bool open = false; - - for (auto &include : kIncludes) { - std::string header_path = include; - header_path.push_back('/'); - header_path += path; - - std::ifstream header(header_path); - - if (!header.is_open()) continue; - - open = true; - - bpp_parse_file(header, pp_out); - - break; - } - - if (!open) { - throw std::runtime_error("bpp: no such include file: " + path); - } - } else { - std::ifstream header(kWorkingDir + path); - - if (!header.is_open()) - throw std::runtime_error("bpp: no such include file: " + path); - - bpp_parse_file(header, pp_out); - } - } else { - std::cerr << ("bpp: unknown pre-processor directive, " + hdr_line) - << "\n"; - continue; - } - } - } catch (std::out_of_range &oor) { - return; - } -} - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief main entrypoint of app. - -///////////////////////////////////////////////////////////////////////////////////////// - -NDK_MODULE(NewOSPreprocessor) { - try { - bool skip = false; - bool double_skip = false; - - details::bpp_macro macro_1; - macro_1.fName = "__true"; - macro_1.fValue = "1"; - - kMacros.push_back(macro_1); - - details::bpp_macro macro_0; - macro_0.fName = "__false"; - macro_0.fValue = "0"; - - kMacros.push_back(macro_0); - - details::bpp_macro macro_hcore; - macro_hcore.fName = "__MAHROUSS__"; - macro_hcore.fValue = "1"; - - kMacros.push_back(macro_hcore); - - for (auto index = 1UL; index < argc; ++index) { - if (skip) { - skip = false; - continue; - } - - if (double_skip) { - ++index; - double_skip = false; - continue; - } - - if (argv[index][0] == '/') { - if (strcmp(argv[index], "/version") == 0) { - printf("%s\n", "bpp v1.11, (c) ZKA Technologies"); - return 0; - } - - if (strcmp(argv[index], "/help") == 0) { - printf("%s\n", "Zeta Preprocessor Driver v1.11, (c) ZKA Technologies"); - printf("%s\n", "/working-dir : set directory to working path."); - printf("%s\n", "/include-dir : add directory to include path."); - printf("%s\n", "/def : def macro."); - printf("%s\n", "/version: print the version."); - printf("%s\n", "/help: show help."); - - return 0; - } - - if (strcmp(argv[index], "/include-dir") == 0) { - std::string inc = argv[index + 1]; - - skip = true; - - kIncludes.push_back(inc); - } - - if (strcmp(argv[index], "/working-dir") == 0) { - std::string inc = argv[index + 1]; - skip = true; - kWorkingDir = inc; - } - - if (strcmp(argv[index], "/def") == 0 && argv[index + 1] != nullptr && - argv[index + 2] != nullptr) { - std::string macro_key = argv[index + 1]; - - std::string macro_value; - bool is_string = false; - - for (int argv_find_len = 0; argv_find_len < strlen(argv[index]); - ++argv_find_len) { - if (!isdigit(argv[index][argv_find_len])) { - is_string = true; - macro_value += "\""; - - break; - } - } - - macro_value += argv[index + 2]; - - if (is_string) macro_value += "\""; - - details::bpp_macro macro; - macro.fName = macro_key; - macro.fValue = macro_value; - - kMacros.push_back(macro); - - double_skip = true; - } - - continue; - } - - kFiles.emplace_back(argv[index]); - } - - if (kFiles.empty()) return MPCC_EXEC_ERROR; - - for (auto &file : kFiles) { - if (!std::filesystem::exists(file)) continue; - - std::ifstream file_descriptor(file); - std::ofstream file_descriptor_pp(file + ".pp"); - - bpp_parse_file(file_descriptor, file_descriptor_pp); - } - - return 0; - } catch (const std::runtime_error &e) { - std::cout << e.what() << '\n'; - } - - return 1; -} - -// Last rev 8-1-24 diff --git a/Sources/bpp.cxx b/Sources/bpp.cxx new file mode 100644 index 0000000..e027c47 --- /dev/null +++ b/Sources/bpp.cxx @@ -0,0 +1,899 @@ +/* + * ======================================================== + * + * bpp + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +/// BUGS: 0 + +#include +#include +#include +#include +#include +#include +#include + +#define kMacroPrefix '%' + +/// @author Amlal El Mahrouss (amlel) +/// @file bpp.cxx +/// @brief Preprocessor. + +typedef Int32 (*bpp_parser_fn_t)(std::string &line, std::ifstream &hdr_file, + std::ofstream &pp_out); + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief Preprocessor internal types. + +///////////////////////////////////////////////////////////////////////////////////////// + +namespace details { +enum { + kEqual, + kGreaterEqThan, + kLesserEqThan, + kGreaterThan, + kLesserThan, + kNotEqual, +}; + +struct bpp_macro_condition final { + int32_t fType; + std::string fTypeName; +}; + +struct bpp_macro final { + std::vector fArgs; + std::string fName; + std::string fValue; +}; + +class bpp_pragma final { + public: + explicit bpp_pragma() = default; + ~bpp_pragma() = default; + + MPCC_COPY_DEFAULT(bpp_pragma); + + std::string fMacroName; + bpp_parser_fn_t fParse; +}; +} // namespace details + +static std::vector kFiles; +static std::vector kMacros; +static std::vector kIncludes; + +static std::string kWorkingDir; + +static std::vector kKeywords = { + "include", "if", "pragma", "def", "elif", + "ifdef", "ifndef", "else", "warning", "error"}; + +#define kKeywordCxxCnt kKeywords.size() + +///////////////////////////////////////////////////////////////////////////////////////// + +// @name bpp_parse_if_condition +// @brief parse #if condition + +///////////////////////////////////////////////////////////////////////////////////////// + +int32_t bpp_parse_if_condition(details::bpp_macro_condition &cond, + details::bpp_macro ¯o, bool &inactive_code, + bool &defined, std::string ¯o_str) { + if (cond.fType == details::kEqual) { + auto substr_macro = + macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); + + if (substr_macro.find(macro.fValue) != std::string::npos) { + if (macro.fValue == "0") { + defined = false; + inactive_code = true; + + return 1; + } + + defined = true; + inactive_code = false; + + return 1; + } + } else if (cond.fType == details::kNotEqual) { + auto substr_macro = + macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); + + if (substr_macro.find(macro.fName) != std::string::npos) { + if (substr_macro.find(macro.fValue) != std::string::npos) { + defined = false; + inactive_code = true; + + return 1; + } + + defined = true; + inactive_code = false; + + return 1; + } + + return 0; + } + + auto substr_macro = + macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); + + std::string number; + + for (auto ¯o_num : kMacros) { + if (substr_macro.find(macro_num.fName) != std::string::npos) { + for (size_t i = 0; i < macro_num.fName.size(); ++i) { + if (isdigit(macro_num.fValue[i])) { + number += macro_num.fValue[i]; + } else { + number.clear(); + break; + } + } + + break; + } + } + + size_t y = 2; + + /* last try */ + for (; y < macro_str.size(); y++) { + if (isdigit(macro_str[y])) { + for (size_t x = y; x < macro_str.size(); x++) { + if (macro_str[x] == ' ') break; + + number += macro_str[x]; + } + + break; + } + } + + size_t rhs = atol(macro.fValue.c_str()); + size_t lhs = atol(number.c_str()); + + if (lhs == 0) { + number.clear(); + ++y; + + for (; y < macro_str.size(); y++) { + if (isdigit(macro_str[y])) { + for (size_t x = y; x < macro_str.size(); x++) { + if (macro_str[x] == ' ') break; + + number += macro_str[x]; + } + + break; + } + } + + lhs = atol(number.c_str()); + } + + if (cond.fType == details::kGreaterThan) { + if (lhs < rhs) { + defined = true; + inactive_code = false; + + return 1; + } + + return 0; + } + + if (cond.fType == details::kGreaterEqThan) { + if (lhs <= rhs) { + defined = true; + inactive_code = false; + + return 1; + } + + return 0; + } + + if (cond.fType == details::kLesserEqThan) { + if (lhs >= rhs) { + defined = true; + inactive_code = false; + + return 1; + } + + return 0; + } + + if (cond.fType == details::kLesserThan) { + if (lhs > rhs) { + defined = true; + inactive_code = false; + + return 1; + } + + return 0; + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief stores every included file here. + +///////////////////////////////////////////////////////////////////////////////////////// + +std::vector kAllIncludes; + +///////////////////////////////////////////////////////////////////////////////////////// + +// @name bpp_parse_file +// @brief parse file to preprocess it. + +///////////////////////////////////////////////////////////////////////////////////////// + +void bpp_parse_file(std::ifstream &hdr_file, std::ofstream &pp_out) { + std::string hdr_line; + std::string line_after_include; + + bool inactive_code = false; + bool defined = false; + + try { + while (std::getline(hdr_file, hdr_line)) { + /// BPP Documentation. + if (hdr_line.find("@bdoc") != std::string::npos) { + hdr_line.erase(hdr_line.find("@bdoc")); + } + + if (hdr_line[0] == kMacroPrefix && + hdr_line.find("endif") != std::string::npos) { + if (!defined && inactive_code) { + inactive_code = false; + defined = false; + + continue; + } + + continue; + } + + if (!defined && inactive_code) { + continue; + } + + if (defined && inactive_code) { + continue; + } + + for (auto macro : kMacros) { + if (ParserKit::find_word(hdr_line, macro.fName) && + hdr_line.find("%def") == std::string::npos) { + auto value = macro.fValue; + + hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), + value); + } + } + + if (hdr_line[0] == kMacroPrefix && + hdr_line.find("def ") != std::string::npos) { + auto line_after_define = + hdr_line.substr(hdr_line.find("def ") + strlen("def ")); + + std::string macro_value; + std::string macro_key; + + std::size_t pos = 0UL; + + std::vector args; + bool on_args = false; + + for (auto &ch : line_after_define) { + ++pos; + + if (ch == '(') { + on_args = true; + continue; + } + + if (ch == ')') { + on_args = false; + continue; + } + + if (ch == '\\') continue; + + if (on_args) continue; + + if (ch == ' ') { + for (size_t i = pos; i < line_after_define.size(); i++) { + macro_value += line_after_define[i]; + } + + break; + } + + macro_key += ch; + } + + std::vector dupls; + std::string str; + + line_after_define.erase(0, line_after_define.find("(") + 1); + + for (auto &subc : line_after_define) { + if (subc == ',' || subc == ')') { + if (str.empty()) continue; + + dupls.push_back(str); + args.push_back(str); + + str.clear(); + + continue; + } + + if (isalnum(subc)) str.push_back(subc); + } + + for (auto &dupl : dupls) { + std::size_t cnt = 0; + + for (auto &arg : args) { + if (dupl == arg) ++cnt; + } + + if (cnt > 1) { + auto it = std::find(args.begin(), args.end(), dupl); + + while (it != args.end()) { + args.erase(it); + it = std::find(args.begin(), args.end(), dupl); + } + } + } + + details::bpp_macro macro; + + macro.fArgs = args; + macro.fName = macro_key; + macro.fValue = macro_value; + + kMacros.emplace_back(macro); + + continue; + } + + if (hdr_line[0] != kMacroPrefix) { + if (inactive_code) { + continue; + } + + for (auto ¯o : kMacros) { + if (hdr_line.find(macro.fName) != std::string::npos) { + std::vector arg_values; + + if (macro.fArgs.size() > 0) { + for (size_t i = 0; i < hdr_line.size(); ++i) { + if (hdr_line[i] == '(') { + std::string tmp_arg; + + for (size_t x = i; x < hdr_line.size(); x++) { + if (hdr_line[x] == ')') break; + + if (hdr_line[x] == ' ') continue; + + if (hdr_line[i] == '\\') continue; + + if (hdr_line[x] == ',') { + arg_values.push_back(tmp_arg); + tmp_arg.clear(); + continue; + } + + tmp_arg += hdr_line[x]; + } + + break; + } + } + + std::string symbol; + + for (char i : macro.fValue) { + if (i == '(') break; + + if (i == '\\') continue; + + symbol += i; + } + + hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), + symbol); + + size_t x_arg_indx = 0; + + for (size_t i = hdr_line.find(macro.fValue); i < hdr_line.size(); + ++i) { + if (hdr_line.find(macro.fArgs[x_arg_indx]) == i) { + hdr_line.replace(i, macro.fArgs[x_arg_indx].size(), + arg_values[x_arg_indx]); + ++x_arg_indx; + } + } + } else { + std::string symbol; + + for (size_t i = 0; i < macro.fValue.size(); i++) { + if (macro.fValue[i] == ' ') continue; + + if (macro.fValue[i] == '\\') continue; + + symbol += macro.fValue[i]; + } + + hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), + symbol); + } + + break; + } + } + + pp_out << hdr_line << std::endl; + + continue; + } + + if (hdr_line[0] == kMacroPrefix && + hdr_line.find("ifndef") != std::string::npos) { + auto line_after_ifndef = + hdr_line.substr(hdr_line.find("ifndef") + strlen("ifndef") + 1); + std::string macro; + + for (auto &ch : line_after_ifndef) { + if (ch == ' ') { + break; + } + + macro += ch; + } + + if (macro == "0") { + defined = true; + inactive_code = false; + continue; + } + + if (macro == "1") { + defined = false; + inactive_code = true; + + continue; + } + + bool found = false; + + defined = true; + inactive_code = false; + + for (auto ¯o_ref : kMacros) { + if (hdr_line.find(macro_ref.fName) != std::string::npos) { + found = true; + break; + } + } + + if (found) { + defined = false; + inactive_code = true; + + continue; + } + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("else") != std::string::npos) { + if (!defined && inactive_code) { + inactive_code = false; + defined = true; + + continue; + } else { + defined = false; + inactive_code = true; + + continue; + } + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("ifdef") != std::string::npos) { + auto line_after_ifdef = + hdr_line.substr(hdr_line.find("ifdef") + strlen("ifdef") + 1); + std::string macro; + + for (auto &ch : line_after_ifdef) { + if (ch == ' ') { + break; + } + + macro += ch; + } + + if (macro == "0") { + defined = false; + inactive_code = true; + + continue; + } + + if (macro == "1") { + defined = true; + inactive_code = false; + + continue; + } + + defined = false; + inactive_code = true; + + for (auto ¯o_ref : kMacros) { + if (hdr_line.find(macro_ref.fName) != std::string::npos) { + defined = true; + inactive_code = false; + + break; + } + } + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("pragma") != std::string::npos) { + line_after_include = hdr_line.substr(hdr_line.find("pragma once")); + + // search for this file + auto it = std::find(kAllIncludes.cbegin(), kAllIncludes.cend(), + line_after_include); + + if (it == kAllIncludes.cend()) { + goto kIncludeFile; + } + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("if") != std::string::npos) { + inactive_code = true; + + std::vector bpp_macro_condition_list = { + { + .fType = details::kEqual, + .fTypeName = "==", + }, + { + .fType = details::kNotEqual, + .fTypeName = "!=", + }, + { + .fType = details::kLesserThan, + .fTypeName = "<", + }, + { + .fType = details::kGreaterThan, + .fTypeName = ">", + }, + { + .fType = details::kLesserEqThan, + .fTypeName = "<=", + }, + { + .fType = details::kGreaterEqThan, + .fTypeName = ">=", + }, + }; + + int32_t good_to_go = 0; + + for (auto ¯o_condition : bpp_macro_condition_list) { + if (hdr_line.find(macro_condition.fTypeName) != std::string::npos) { + for (auto &found_macro : kMacros) { + if (hdr_line.find(found_macro.fName) != std::string::npos) { + good_to_go = + bpp_parse_if_condition(macro_condition, found_macro, + inactive_code, defined, hdr_line); + + break; + } + } + } + } + + if (good_to_go) continue; + + auto line_after_if = + hdr_line.substr(hdr_line.find("if") + strlen("if") + 1); + std::string macro; + + for (auto &ch : line_after_if) { + if (ch == ' ') { + break; + } + + macro += ch; + } + + if (macro == "0") { + defined = false; + inactive_code = true; + continue; + } + + if (macro == "1") { + defined = true; + inactive_code = false; + + continue; + } + + // last try, is it defined to be one? + for (auto ¯o_ref : kMacros) { + if (macro_ref.fName.find(macro) != std::string::npos && + macro_ref.fValue == "1") { + inactive_code = false; + defined = true; + + break; + } + } + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("warning") != std::string::npos) { + auto line_after_warning = + hdr_line.substr(hdr_line.find("warning") + strlen("warning") + 1); + std::string message; + + for (auto &ch : line_after_warning) { + if (ch == '\r' || ch == '\n') { + break; + } + + message += ch; + } + + std::cout << "Warning: " << message << std::endl; + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("error") != std::string::npos) { + auto line_after_warning = + hdr_line.substr(hdr_line.find("error") + strlen("error") + 1); + std::string message; + + for (auto &ch : line_after_warning) { + if (ch == '\r' || ch == '\n') { + break; + } + + message += ch; + } + + throw std::runtime_error("Error: " + message); + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("inc ") != std::string::npos) { + line_after_include = + hdr_line.substr(hdr_line.find("inc ") + strlen("inc ")); + + kIncludeFile: + auto it = std::find(kAllIncludes.cbegin(), kAllIncludes.cend(), + line_after_include); + + if (it != kAllIncludes.cend()) { + continue; + } + + std::string path; + + kAllIncludes.push_back(line_after_include); + + bool enable = false; + bool not_local = false; + + for (auto &ch : line_after_include) { + if (ch == ' ') continue; + + if (ch == '<') { + not_local = true; + enable = true; + + continue; + } + + if (ch == '\'') { + enable = true; + continue; + } + + if (enable) { + if (not_local) { + if (ch == '>') break; + } else { + if (ch == '\'') { + break; + } + } + + path += ch; + } + } + + if (not_local) { + bool open = false; + + for (auto &include : kIncludes) { + std::string header_path = include; + header_path.push_back('/'); + header_path += path; + + std::ifstream header(header_path); + + if (!header.is_open()) continue; + + open = true; + + bpp_parse_file(header, pp_out); + + break; + } + + if (!open) { + throw std::runtime_error("bpp: no such include file: " + path); + } + } else { + std::ifstream header(kWorkingDir + path); + + if (!header.is_open()) + throw std::runtime_error("bpp: no such include file: " + path); + + bpp_parse_file(header, pp_out); + } + } else { + std::cerr << ("bpp: unknown pre-processor directive, " + hdr_line) + << "\n"; + continue; + } + } + } catch (std::out_of_range &oor) { + return; + } +} + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief main entrypoint of app. + +///////////////////////////////////////////////////////////////////////////////////////// + +NDK_MODULE(NewOSPreprocessor) { + try { + bool skip = false; + bool double_skip = false; + + details::bpp_macro macro_1; + macro_1.fName = "__true"; + macro_1.fValue = "1"; + + kMacros.push_back(macro_1); + + details::bpp_macro macro_0; + macro_0.fName = "__false"; + macro_0.fValue = "0"; + + kMacros.push_back(macro_0); + + details::bpp_macro macro_hcore; + macro_hcore.fName = "__MAHROUSS__"; + macro_hcore.fValue = "1"; + + kMacros.push_back(macro_hcore); + + for (auto index = 1UL; index < argc; ++index) { + if (skip) { + skip = false; + continue; + } + + if (double_skip) { + ++index; + double_skip = false; + continue; + } + + if (argv[index][0] == '/') { + if (strcmp(argv[index], "/version") == 0) { + printf("%s\n", "bpp v1.11, (c) ZKA Technologies"); + return 0; + } + + if (strcmp(argv[index], "/help") == 0) { + printf("%s\n", "Zeta Preprocessor Driver v1.11, (c) ZKA Technologies"); + printf("%s\n", "/working-dir : set directory to working path."); + printf("%s\n", "/include-dir : add directory to include path."); + printf("%s\n", "/def : def macro."); + printf("%s\n", "/version: print the version."); + printf("%s\n", "/help: show help."); + + return 0; + } + + if (strcmp(argv[index], "/include-dir") == 0) { + std::string inc = argv[index + 1]; + + skip = true; + + kIncludes.push_back(inc); + } + + if (strcmp(argv[index], "/working-dir") == 0) { + std::string inc = argv[index + 1]; + skip = true; + kWorkingDir = inc; + } + + if (strcmp(argv[index], "/def") == 0 && argv[index + 1] != nullptr && + argv[index + 2] != nullptr) { + std::string macro_key = argv[index + 1]; + + std::string macro_value; + bool is_string = false; + + for (int argv_find_len = 0; argv_find_len < strlen(argv[index]); + ++argv_find_len) { + if (!isdigit(argv[index][argv_find_len])) { + is_string = true; + macro_value += "\""; + + break; + } + } + + macro_value += argv[index + 2]; + + if (is_string) macro_value += "\""; + + details::bpp_macro macro; + macro.fName = macro_key; + macro.fValue = macro_value; + + kMacros.push_back(macro); + + double_skip = true; + } + + continue; + } + + kFiles.emplace_back(argv[index]); + } + + if (kFiles.empty()) return MPCC_EXEC_ERROR; + + for (auto &file : kFiles) { + if (!std::filesystem::exists(file)) continue; + + std::ifstream file_descriptor(file); + std::ofstream file_descriptor_pp(file + ".pp"); + + bpp_parse_file(file_descriptor, file_descriptor_pp); + } + + return 0; + } catch (const std::runtime_error &e) { + std::cout << e.what() << '\n'; + } + + return 1; +} + +// Last rev 8-1-24 diff --git a/Sources/coff2ae.cc b/Sources/coff2ae.cc deleted file mode 100644 index 71f5bba..0000000 --- a/Sources/coff2ae.cc +++ /dev/null @@ -1,23 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#include -#include -#include -#include -#include -#include -#include -#include - -///////////////////////////////////////////////////////////////////////////////////////// - -/// @file coff2ae.cc -/// @brief COFF To AE, the program/module starts here. - -///////////////////////////////////////////////////////////////////////////////////////// - -NDK_MODULE(NewOSCOFFToAE) { return 0; } diff --git a/Sources/coff2ae.cxx b/Sources/coff2ae.cxx new file mode 100644 index 0000000..2f7e062 --- /dev/null +++ b/Sources/coff2ae.cxx @@ -0,0 +1,23 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include + +///////////////////////////////////////////////////////////////////////////////////////// + +/// @file coff2ae.cxx +/// @brief COFF To AE, the program/module starts here. + +///////////////////////////////////////////////////////////////////////////////////////// + +NDK_MODULE(NewOSCOFFToAE) { return 0; } diff --git a/Sources/compile_flags.txt b/Sources/compile_flags.txt index f9acaba..6ec6b8a 100644 --- a/Sources/compile_flags.txt +++ b/Sources/compile_flags.txt @@ -1,5 +1,5 @@ -std=c++20 -I../ --I../Comm +-I../Headers -I./ -I./Detail/ diff --git a/Sources/cplusplus.cc b/Sources/cplusplus.cc deleted file mode 100644 index 4059413..0000000 --- a/Sources/cplusplus.cc +++ /dev/null @@ -1,905 +0,0 @@ -/* - * ======================================================== - * - * cplusplus - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -/// bugs: 0 - -#define __PK_USE_STRUCT_INSTEAD__ 1 - -#define kPrintF printf - -#define kSplashCxx() \ -kPrintF(kWhite "%s\n", "Zeta C++ Compiler Driver, (c) 2024 Zeta Electronics, all rights reserved.") - -// import, @MLAutoRelease { ... }, fn foo() -> auto { ... } - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define kOk 0 - -/* ZKA Technologies C++ driver */ -/* This is part of ZECC C++ compiler. */ -/* (c) ZKA Technologies */ - -/// @author Amlal El Mahrouss (amlel) -/// @file cc.cc -/// @brief Optimized C++ Compiler. -/// @todo Throw error for scoped inside scoped variables when they get referenced outside. -/// @todo Add class/struct/enum support. - -///////////////////// - -// ANSI ESCAPE CODES - -///////////////////// - -#define kBlank "\e[0;30m" -#define kRed "\e[0;31m" -#define kWhite "\e[0;97m" - -///////////////////////////////////// - -// INTERNALS OF THE C COMPILER - -///////////////////////////////////// - -/// @internal -namespace detail -{ - struct CompilerRegisterMap final - { - std::string fName; - std::string fReg; - }; - - // \brief Offset based struct/class - struct CompilerStructMap final - { - std::string fName; - std::string fReg; - - // offset counter - std::size_t fOffsetsCnt; - - // offset array - std::vector> fOffsets; - }; - - struct CompilerState final - { - std::vector fSyntaxTreeList; - std::vector kStackFrame; - std::vector kStructMap; - ParserKit::SyntaxLeafList* fSyntaxTree{nullptr}; - std::unique_ptr fOutputAssembly; - std::string fLastFile; - std::string fLastError; - bool fVerbose; - }; -} // namespace detail - -static detail::CompilerState kState; -static SizeType kErrorLimit = 100; - -static Int32 kAcceptableErrors = 0; - -namespace detail -{ - /// @brief prints an error into stdout. - /// @param reason the reason of the error. - /// @param file where does it originate from? - void print_error(std::string reason, std::string file) noexcept - { - if (reason[0] == '\n') - reason.erase(0, 1); - - if (file.find(".pp") != std::string::npos) - { - file.erase(file.find(".pp"), 3); - } - - if (kState.fLastFile != file) - { - std::cout << kRed << "[ cplusplus ] " << kWhite - << ((file == "cplusplus") ? "internal compiler error " - : ("in file, " + file)) - << kBlank << std::endl; - std::cout << kRed << "[ cplusplus ] " << kWhite << reason << kBlank - << std::endl; - - kState.fLastFile = file; - } - else - { - std::cout << kRed << "[ cplusplus ] [ " << kState.fLastFile << " ] " << kWhite - << reason << kBlank << std::endl; - } - - if (kAcceptableErrors > kErrorLimit) - std::exit(3); - - ++kAcceptableErrors; - } - - struct CompilerType - { - std::string fName; - std::string fValue; - }; -} // namespace detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// Target architecture. -static int kMachine = CompilerKit::AssemblyFactory::kArchAMD64; - -///////////////////////////////////////// - -// ARGUMENTS REGISTERS (R8, R15) - -///////////////////////////////////////// - -static size_t kRegisterCnt = kAsmRegisterLimit; -static size_t kStartUsable = 8; -static size_t kUsableLimit = 15; -static size_t kRegisterCounter = kStartUsable; -static std::vector kKeywords; - -///////////////////////////////////////// - -// COMPILER PARSING UTILITIES/STATES. - -///////////////////////////////////////// - -static std::vector kFileList; -static CompilerKit::AssemblyFactory kFactory; -static bool kInStruct = false; -static bool kOnWhileLoop = false; -static bool kOnForLoop = false; -static bool kInBraces = false; -static size_t kBracesCount = 0UL; - -/* @brief C++ compiler backend for the Zeta C++ driver */ -class CompilerBackendCPlusPlus final : public ParserKit::CompilerBackend -{ -public: - explicit CompilerBackendCPlusPlus() = default; - ~CompilerBackendCPlusPlus() override = default; - - MPCC_COPY_DEFAULT(CompilerBackendCPlusPlus); - - bool Compile(const std::string& text, const char* file) override; - - const char* Language() override; -}; - -/// @internal compiler variables - -static CompilerBackendCPlusPlus* kCompilerBackend = nullptr; -static std::vector kCompilerVariables; -static std::vector kCompilerFunctions; - -static std::vector kRegisterMap; - -static std::vector cRegisters = { - "rbx", - "rsi", - "r10", - "r11", - "r12", - "r13", - "r14", - "r15", - "xmm12", - "xmm13", - "xmm14", - "xmm15", -}; - -/// @brief The PEF calling convention (caller must save rax, rbp) -/// @note callee must return via **rax**. -static std::vector cRegistersCall = { - "rcx", - "rdx", - "r8", - "r9", - "xmm8", - "xmm9", - "xmm10", - "xmm11", -}; - -static size_t kLevelFunction = 0UL; - -/// detail namespaces - -const char* CompilerBackendCPlusPlus::Language() -{ - return "Zeta C++"; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -/// @name Compile -/// @brief Generate MASM assembly from a C++ source. - -///////////////////////////////////////////////////////////////////////////////////////// - -bool CompilerBackendCPlusPlus::Compile(const std::string& text, - const char* file) -{ - if (text.empty()) - return false; - - // if (expr) - // int name = expr; - // expr; - - std::size_t index = 0UL; - std::vector> keywords_list; - - bool found = false; - static bool commentBlock = false; - - for (auto& keyword : kKeywords) - { - if (text.find(keyword.keyword_name) != std::string::npos) - { - switch (keyword.keyword_kind) - { - case ParserKit::eKeywordKindCommentMultiLineStart: { - commentBlock = true; - return true; - } - case ParserKit::eKeywordKindCommentMultiLineEnd: { - commentBlock = false; - break; - } - case ParserKit::eKeywordKindCommentInline: { - break; - } - default: - break; - } - - if (text[text.find(keyword.keyword_name) - 1] == '+' && - keyword.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableAssign) - continue; - - if (text[text.find(keyword.keyword_name) - 1] == '-' && - keyword.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableAssign) - continue; - - if (text[text.find(keyword.keyword_name) + 1] == '=' && - keyword.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableAssign) - continue; - - keywords_list.emplace_back(std::make_pair(keyword, index)); - ++index; - - found = true; - } - } - - if (!found && !commentBlock) - { - for (size_t i = 0; i < text.size(); i++) - { - if (isalnum(text[i])) - { - detail::print_error("syntax error: " + text, file); - return false; - } - } - } - - for (auto& keyword : keywords_list) - { - auto syntax_tree = ParserKit::SyntaxLeafList::SyntaxLeaf(); - - switch (keyword.first.keyword_kind) - { - case ParserKit::KeywordKind::eKeywordKindFunctionStart: { - std::string fnName = text; - fnName.erase(fnName.find(keyword.first.keyword_name)); - - for (auto& ch : fnName) - { - if (ch == ' ') - ch = '_'; - } - - syntax_tree.fUserValue = "export .code64 __MPCC_" + fnName + "\n"; - - ++kLevelFunction; - break; - } - case ParserKit::KeywordKind::eKeywordKindFunctionEnd: { - --kLevelFunction; - - if (kRegisterMap.size() > cRegisters.size()) - { - --kLevelFunction; - } - - if (kLevelFunction < 1) - kRegisterMap.clear(); - break; - } - case ParserKit::KeywordKind::eKeywordKindEndInstr: - case ParserKit::KeywordKind::eKeywordKindVariableInc: - case ParserKit::KeywordKind::eKeywordKindVariableDec: - case ParserKit::KeywordKind::eKeywordKindVariableAssign: { - std::string valueOfVar = ""; - - if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableInc) - { - valueOfVar = text.substr(text.find("+=") + 2); - } - else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableDec) - { - valueOfVar = text.substr(text.find("-=") + 2); - } - else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableAssign) - { - valueOfVar = text.substr(text.find("=") + 1); - } - else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindEndInstr) - { - valueOfVar = "0\n"; - } - - while (valueOfVar.find(";") != std::string::npos && - keyword.first.keyword_kind != ParserKit::KeywordKind::eKeywordKindEndInstr) - { - valueOfVar.erase(valueOfVar.find(";")); - } - - std::string varName = text; - - if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableInc) - { - varName.erase(varName.find("+=")); - } - else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableDec) - { - varName.erase(varName.find("-=")); - } - else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableAssign) - { - varName.erase(varName.find("=")); - } - else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindEndInstr) - { - varName.erase(varName.find(";")); - } - - bool typeFound = false; - - for (auto& keyword : kKeywords) - { - if (keyword.keyword_kind == ParserKit::eKeywordKindType) - { - if (varName.find(keyword.keyword_name) != std::string::npos) - { - typeFound = true; - varName.erase(varName.find(keyword.keyword_name), keyword.keyword_name.size()); - } - - /// in case we goot boolX or intX - if (text.find(keyword.keyword_name) != std::string::npos) - { - if (varName[text.find(keyword.keyword_name)] == ' ') - continue; - - typeFound = false; - } - } - } - - std::string instr = "mov "; - - if (typeFound) - { - if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableInc) - { - detail::print_error("Can't increment variable when it's being created.", file); - } - else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableDec) - { - detail::print_error("Can't decrement variable when it's being created.", file); - } - - if (kRegisterMap.size() > cRegisters.size()) - { - ++kLevelFunction; - } - - while (varName.find(" ") != std::string::npos) - { - varName.erase(varName.find(" "), 1); - } - - while (varName.find("\t") != std::string::npos) - { - varName.erase(varName.find("\t"), 1); - } - - for (size_t i = 0; !isalnum(valueOfVar[i]); i++) - { - if (i > valueOfVar.size()) - break; - - valueOfVar.erase(i, 1); - } - - constexpr auto cTrueVal = "true"; - constexpr auto cFalseVal = "false"; - - if (valueOfVar == cTrueVal) - { - valueOfVar = "1"; - } - else if (valueOfVar == cFalseVal) - { - valueOfVar = "0"; - } - - std::size_t indexRight = 0UL; - - for (auto pairRight : kRegisterMap) - { - ++indexRight; - - if (pairRight != valueOfVar) - { - syntax_tree.fUserValue = instr + cRegisters[kRegisterMap.size()] + ", " + valueOfVar + "\n"; - continue; - } - - syntax_tree.fUserValue = instr + cRegisters[kRegisterMap.size()] + ", " + cRegisters[indexRight - 1] + "\n"; - break; - } - - if (((int)indexRight - 1) < 0) - { - syntax_tree.fUserValue = instr + cRegisters[kRegisterMap.size()] + ", " + valueOfVar + "\n"; - } - - kRegisterMap.push_back(varName); - } - else - { - if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindEndInstr) - { - syntax_tree.fUserValue = "\n"; - continue; - } - - if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableInc) - { - instr = "add "; - } - else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableDec) - { - instr = "sub "; - } - - std::string varErrCpy = varName; - - while (varName.find(" ") != std::string::npos) - { - varName.erase(varName.find(" "), 1); - } - - while (varName.find("\t") != std::string::npos) - { - varName.erase(varName.find("\t"), 1); - } - - std::size_t indxReg = 0UL; - - for (size_t i = 0; !isalnum(valueOfVar[i]); i++) - { - if (i > valueOfVar.size()) - break; - - valueOfVar.erase(i, 1); - } - - constexpr auto cTrueVal = "true"; - constexpr auto cFalseVal = "false"; - - /// interpet boolean values, since we're on C++ - - if (valueOfVar == cTrueVal) - { - valueOfVar = "1"; - } - else if (valueOfVar == cFalseVal) - { - valueOfVar = "0"; - } - - for (auto pair : kRegisterMap) - { - ++indxReg; - - if (pair != varName) - continue; - - std::size_t indexRight = 0ul; - - for (auto pairRight : kRegisterMap) - { - ++indexRight; - - if (pairRight != valueOfVar) - { - syntax_tree.fUserValue = instr + cRegisters[kRegisterMap.size()] + ", " + valueOfVar + "\n"; - continue; - } - - syntax_tree.fUserValue = instr + cRegisters[indxReg - 1] + ", " + cRegisters[indexRight - 1] + "\n"; - break; - } - - break; - } - - if (syntax_tree.fUserValue.empty()) - { - detail::print_error("Variable not declared: " + varErrCpy, file); - } - } - - break; - } - case ParserKit::KeywordKind::eKeywordKindReturn: { - auto pos = text.find("return") + strlen("return") + 1; - std::string subText = text.substr(pos); - subText = subText.erase(subText.find(";")); - size_t indxReg = 0UL; - - if (subText[0] != '\"' && - subText[0] != '\'') - { - if (!isdigit(subText[0])) - { - for (auto pair : kRegisterMap) - { - ++indxReg; - - if (pair != subText) - continue; - - syntax_tree.fUserValue = "mov rax, " + cRegisters[indxReg - 1] + "\r\nret\n"; - break; - } - - if (syntax_tree.fUserValue.empty()) - { - detail::print_error("Variable not declared: " + subText, file); - } - } - else - { - syntax_tree.fUserValue = "mov rax, " + subText + "\r\nret\n"; - } - } - else - { - syntax_tree.fUserValue = "mov rcx, " + subText + "\n"; - syntax_tree.fUserValue = "mov rax, rcx\r\nret\n"; - } - - break; - } - default: - break; - } - - syntax_tree.fUserData = keyword.first; - kState.fSyntaxTree->fLeafList.emplace_back(syntax_tree); - } - -_MpccOkay: - return true; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -/** - * @brief C To Assembly mount-point. - */ - -///////////////////////////////////////////////////////////////////////////////////////// - -class AssemblyCPlusPlusInterface final : public CompilerKit::AssemblyInterface -{ -public: - explicit AssemblyCPlusPlusInterface() = default; - ~AssemblyCPlusPlusInterface() override = default; - - MPCC_COPY_DEFAULT(AssemblyCPlusPlusInterface); - - [[maybe_unused]] - static Int32 Arch() noexcept - { - return CompilerKit::AssemblyFactory::kArchAMD64; - } - - Int32 CompileToFormat(std::string& src, Int32 arch) override - { - if (arch != AssemblyCPlusPlusInterface::Arch()) - return -1; - - if (kCompilerBackend == nullptr) - return -1; - - /* @brief copy contents wihtout extension */ - std::string src_file = src.data(); - std::ifstream src_fp = std::ifstream(src_file, std::ios::in); - std::string dest; - - for (auto& ch : src_file) - { - if (ch == '.') - { - break; - } - - dest += ch; - } - - if (dest.empty()) - { - dest = "CXX-MPCC-"; - - std::random_device rd; - auto seed_data = std::array {}; - - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); - - std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); - std::mt19937 generator(seq); - - auto gen = uuids::uuid_random_generator(generator); - - auto id = gen(); - dest += uuids::to_string(id); - } - - std::vector exts = kAsmFileExts; - - dest += exts[3]; - - std::cout << dest; - - kState.fOutputAssembly = std::make_unique(dest); - - auto fmt = CompilerKit::current_date(); - - (*kState.fOutputAssembly) << "; Path: " << src_file << "\n"; - (*kState.fOutputAssembly) - << "; Language: AMD64 assembly. (Generated from C++)\n"; - (*kState.fOutputAssembly) << "; Date: " << fmt << "\n"; - (*kState.fOutputAssembly) << "#bits 64\n#org 0x1000000" - << "\n"; - - ParserKit::SyntaxLeafList syntax; - - kState.fSyntaxTreeList.emplace_back(syntax); - kState.fSyntaxTree = - &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; - - std::string source; - - while (std::getline(src_fp, source)) - { - // Compile into an object file. - kCompilerBackend->Compile(source.c_str(), src.c_str()); - } - - for (auto& ast : kState.fSyntaxTree->fLeafList) - { - (*kState.fOutputAssembly) << ast.fUserValue; - } - - if (kAcceptableErrors > 0) - return -1; - - return kOk; - } -}; - -///////////////////////////////////////////////////////////////////////////////////////// - -static void cxx_print_help() -{ - kSplashCxx(); - kPrintF("%s", "No help available, see:\n"); - kPrintF("%s", "www.zeta.com/developer/cplusplus\n"); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -#define kExtListCxx \ - { \ - ".cpp", ".cxx", ".cc", ".c++", ".cp" \ - } - -NDK_MODULE(CompilerCPlusPlus) -{ - bool skip = false; - - kKeywords.push_back({.keyword_name = "class", .keyword_kind = ParserKit::eKeywordKindClass}); - kKeywords.push_back({.keyword_name = "struct", .keyword_kind = ParserKit::eKeywordKindClass}); - kKeywords.push_back({.keyword_name = "namespace", .keyword_kind = ParserKit::eKeywordKindNamespace}); - kKeywords.push_back({.keyword_name = "typedef", .keyword_kind = ParserKit::eKeywordKindTypedef}); - kKeywords.push_back({.keyword_name = "using", .keyword_kind = ParserKit::eKeywordKindTypedef}); - kKeywords.push_back({.keyword_name = "{", .keyword_kind = ParserKit::eKeywordKindBodyStart}); - kKeywords.push_back({.keyword_name = "}", .keyword_kind = ParserKit::eKeywordKindBodyEnd}); - kKeywords.push_back({.keyword_name = "auto", .keyword_kind = ParserKit::eKeywordKindVariable}); - kKeywords.push_back({.keyword_name = "int", .keyword_kind = ParserKit::eKeywordKindType}); - kKeywords.push_back({.keyword_name = "bool", .keyword_kind = ParserKit::eKeywordKindType}); - kKeywords.push_back({.keyword_name = "unsigned", .keyword_kind = ParserKit::eKeywordKindType}); - kKeywords.push_back({.keyword_name = "short", .keyword_kind = ParserKit::eKeywordKindType}); - kKeywords.push_back({.keyword_name = "char", .keyword_kind = ParserKit::eKeywordKindType}); - kKeywords.push_back({.keyword_name = "long", .keyword_kind = ParserKit::eKeywordKindType}); - kKeywords.push_back({.keyword_name = "float", .keyword_kind = ParserKit::eKeywordKindType}); - kKeywords.push_back({.keyword_name = "double", .keyword_kind = ParserKit::eKeywordKindType}); - kKeywords.push_back({.keyword_name = "void", .keyword_kind = ParserKit::eKeywordKindType}); - - kKeywords.push_back({.keyword_name = "auto*", .keyword_kind = ParserKit::eKeywordKindVariablePtr}); - kKeywords.push_back({.keyword_name = "int*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); - kKeywords.push_back({.keyword_name = "bool*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); - kKeywords.push_back({.keyword_name = "unsigned*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); - kKeywords.push_back({.keyword_name = "short*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); - kKeywords.push_back({.keyword_name = "char*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); - kKeywords.push_back({.keyword_name = "long*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); - kKeywords.push_back({.keyword_name = "float*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); - kKeywords.push_back({.keyword_name = "double*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); - kKeywords.push_back({.keyword_name = "void*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); - - kKeywords.push_back({.keyword_name = "(", .keyword_kind = ParserKit::eKeywordKindFunctionStart}); - kKeywords.push_back({.keyword_name = ")", .keyword_kind = ParserKit::eKeywordKindFunctionEnd}); - kKeywords.push_back({.keyword_name = "=", .keyword_kind = ParserKit::eKeywordKindVariableAssign}); - kKeywords.push_back({.keyword_name = "+=", .keyword_kind = ParserKit::eKeywordKindVariableInc}); - kKeywords.push_back({.keyword_name = "-=", .keyword_kind = ParserKit::eKeywordKindVariableDec}); - kKeywords.push_back({.keyword_name = "const", .keyword_kind = ParserKit::eKeywordKindConstant}); - kKeywords.push_back({.keyword_name = "*", .keyword_kind = ParserKit::eKeywordKindPtr}); - kKeywords.push_back({.keyword_name = "->", .keyword_kind = ParserKit::eKeywordKindPtrAccess}); - kKeywords.push_back({.keyword_name = ".", .keyword_kind = ParserKit::eKeywordKindAccess}); - kKeywords.push_back({.keyword_name = ",", .keyword_kind = ParserKit::eKeywordKindArgSeparator}); - kKeywords.push_back({.keyword_name = ";", .keyword_kind = ParserKit::eKeywordKindEndInstr}); - kKeywords.push_back({.keyword_name = ":", .keyword_kind = ParserKit::eKeywordKindSpecifier}); - kKeywords.push_back({.keyword_name = "public:", .keyword_kind = ParserKit::eKeywordKindSpecifier}); - kKeywords.push_back({.keyword_name = "private:", .keyword_kind = ParserKit::eKeywordKindSpecifier}); - kKeywords.push_back({.keyword_name = "protected:", .keyword_kind = ParserKit::eKeywordKindSpecifier}); - kKeywords.push_back({.keyword_name = "final", .keyword_kind = ParserKit::eKeywordKindSpecifier}); - kKeywords.push_back({.keyword_name = "return", .keyword_kind = ParserKit::eKeywordKindReturn}); - kKeywords.push_back({.keyword_name = "/*", .keyword_kind = ParserKit::eKeywordKindCommentMultiLineStart}); - kKeywords.push_back({.keyword_name = "*/", .keyword_kind = ParserKit::eKeywordKindCommentMultiLineStart}); - kKeywords.push_back({.keyword_name = "//", .keyword_kind = ParserKit::eKeywordKindCommentInline}); - kKeywords.push_back({.keyword_name = "==", .keyword_kind = ParserKit::eKeywordKindEq}); - kKeywords.push_back({.keyword_name = "!=", .keyword_kind = ParserKit::eKeywordKindNotEq}); - kKeywords.push_back({.keyword_name = ">=", .keyword_kind = ParserKit::eKeywordKindGreaterEq}); - kKeywords.push_back({.keyword_name = "<=", .keyword_kind = ParserKit::eKeywordKindLessEq}); - - kFactory.Mount(new AssemblyCPlusPlusInterface()); - kCompilerBackend = new CompilerBackendCPlusPlus(); - - for (auto index = 1UL; index < argc; ++index) - { - if (argv[index][0] == '/') - { - if (skip) - { - skip = false; - continue; - } - - if (strcmp(argv[index], "/v") == 0 || - strcmp(argv[index], "/version") == 0) - { - kSplashCxx(); - return kOk; - } - - if (strcmp(argv[index], "/verbose") == 0) - { - kState.fVerbose = true; - - continue; - } - - if (strcmp(argv[index], "/h") == 0 || strcmp(argv[index], "/help") == 0) - { - cxx_print_help(); - - return kOk; - } - - if (strcmp(argv[index], "/dialect") == 0) - { - if (kCompilerBackend) - std::cout << kCompilerBackend->Language() << "\n"; - - return kOk; - } - - if (strcmp(argv[index], "/max-errors") == 0) - { - try - { - kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); - } - // catch anything here - catch (...) - { - kErrorLimit = 0; - } - - skip = true; - - continue; - } - - std::string err = "Unknown option: "; - err += argv[index]; - - detail::print_error(err, "cplusplus"); - - continue; - } - - kFileList.emplace_back(argv[index]); - - std::string argv_i = argv[index]; - - std::vector exts = kExtListCxx; - bool found = false; - - for (std::string ext : exts) - { - if (argv_i.find(ext) != std::string::npos) - { - found = true; - break; - } - } - - if (!found) - { - if (kState.fVerbose) - { - detail::print_error(argv_i + " is not a valid C++ source.\n", "cplusplus"); - } - - return 1; - } - - if (kFactory.Compile(argv_i, kMachine) != kOk) - return -1; - } - - return kOk; -} - -// Last rev 8-1-24 diff --git a/Sources/cplusplus.cxx b/Sources/cplusplus.cxx new file mode 100644 index 0000000..3eb6e9b --- /dev/null +++ b/Sources/cplusplus.cxx @@ -0,0 +1,905 @@ +/* + * ======================================================== + * + * cplusplus + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +/// bugs: 0 + +#define __PK_USE_STRUCT_INSTEAD__ 1 + +#define kPrintF printf + +#define kSplashCxx() \ +kPrintF(kWhite "%s\n", "Zeta C++ Compiler Driver, (c) 2024 Zeta Electronics, all rights reserved.") + +// import, @MLAutoRelease { ... }, fn foo() -> auto { ... } + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define kOk 0 + +/* ZKA Technologies C++ driver */ +/* This is part of ZECC C++ compiler. */ +/* (c) ZKA Technologies */ + +/// @author Amlal El Mahrouss (amlel) +/// @file cc.cxx +/// @brief Optimized C++ Compiler. +/// @todo Throw error for scoped inside scoped variables when they get referenced outside. +/// @todo Add class/struct/enum support. + +///////////////////// + +// ANSI ESCAPE CODES + +///////////////////// + +#define kBlank "\e[0;30m" +#define kRed "\e[0;31m" +#define kWhite "\e[0;97m" + +///////////////////////////////////// + +// INTERNALS OF THE C COMPILER + +///////////////////////////////////// + +/// @internal +namespace detail +{ + struct CompilerRegisterMap final + { + std::string fName; + std::string fReg; + }; + + // \brief Offset based struct/class + struct CompilerStructMap final + { + std::string fName; + std::string fReg; + + // offset counter + std::size_t fOffsetsCnt; + + // offset array + std::vector> fOffsets; + }; + + struct CompilerState final + { + std::vector fSyntaxTreeList; + std::vector kStackFrame; + std::vector kStructMap; + ParserKit::SyntaxLeafList* fSyntaxTree{nullptr}; + std::unique_ptr fOutputAssembly; + std::string fLastFile; + std::string fLastError; + bool fVerbose; + }; +} // namespace detail + +static detail::CompilerState kState; +static SizeType kErrorLimit = 100; + +static Int32 kAcceptableErrors = 0; + +namespace detail +{ + /// @brief prints an error into stdout. + /// @param reason the reason of the error. + /// @param file where does it originate from? + void print_error(std::string reason, std::string file) noexcept + { + if (reason[0] == '\n') + reason.erase(0, 1); + + if (file.find(".pp") != std::string::npos) + { + file.erase(file.find(".pp"), 3); + } + + if (kState.fLastFile != file) + { + std::cout << kRed << "[ cplusplus ] " << kWhite + << ((file == "cplusplus") ? "internal compiler error " + : ("in file, " + file)) + << kBlank << std::endl; + std::cout << kRed << "[ cplusplus ] " << kWhite << reason << kBlank + << std::endl; + + kState.fLastFile = file; + } + else + { + std::cout << kRed << "[ cplusplus ] [ " << kState.fLastFile << " ] " << kWhite + << reason << kBlank << std::endl; + } + + if (kAcceptableErrors > kErrorLimit) + std::exit(3); + + ++kAcceptableErrors; + } + + struct CompilerType + { + std::string fName; + std::string fValue; + }; +} // namespace detail + +///////////////////////////////////////////////////////////////////////////////////////// + +// Target architecture. +static int kMachine = CompilerKit::AssemblyFactory::kArchAMD64; + +///////////////////////////////////////// + +// ARGUMENTS REGISTERS (R8, R15) + +///////////////////////////////////////// + +static size_t kRegisterCnt = kAsmRegisterLimit; +static size_t kStartUsable = 8; +static size_t kUsableLimit = 15; +static size_t kRegisterCounter = kStartUsable; +static std::vector kKeywords; + +///////////////////////////////////////// + +// COMPILER PARSING UTILITIES/STATES. + +///////////////////////////////////////// + +static std::vector kFileList; +static CompilerKit::AssemblyFactory kFactory; +static bool kInStruct = false; +static bool kOnWhileLoop = false; +static bool kOnForLoop = false; +static bool kInBraces = false; +static size_t kBracesCount = 0UL; + +/* @brief C++ compiler backend for the Zeta C++ driver */ +class CompilerBackendCPlusPlus final : public ParserKit::CompilerBackend +{ +public: + explicit CompilerBackendCPlusPlus() = default; + ~CompilerBackendCPlusPlus() override = default; + + MPCC_COPY_DEFAULT(CompilerBackendCPlusPlus); + + bool Compile(const std::string& text, const char* file) override; + + const char* Language() override; +}; + +/// @internal compiler variables + +static CompilerBackendCPlusPlus* kCompilerBackend = nullptr; +static std::vector kCompilerVariables; +static std::vector kCompilerFunctions; + +static std::vector kRegisterMap; + +static std::vector cRegisters = { + "rbx", + "rsi", + "r10", + "r11", + "r12", + "r13", + "r14", + "r15", + "xmm12", + "xmm13", + "xmm14", + "xmm15", +}; + +/// @brief The PEF calling convention (caller must save rax, rbp) +/// @note callee must return via **rax**. +static std::vector cRegistersCall = { + "rcx", + "rdx", + "r8", + "r9", + "xmm8", + "xmm9", + "xmm10", + "xmm11", +}; + +static size_t kLevelFunction = 0UL; + +/// detail namespaces + +const char* CompilerBackendCPlusPlus::Language() +{ + return "Zeta C++"; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +/// @name Compile +/// @brief Generate MASM assembly from a C++ source. + +///////////////////////////////////////////////////////////////////////////////////////// + +bool CompilerBackendCPlusPlus::Compile(const std::string& text, + const char* file) +{ + if (text.empty()) + return false; + + // if (expr) + // int name = expr; + // expr; + + std::size_t index = 0UL; + std::vector> keywords_list; + + bool found = false; + static bool commentBlock = false; + + for (auto& keyword : kKeywords) + { + if (text.find(keyword.keyword_name) != std::string::npos) + { + switch (keyword.keyword_kind) + { + case ParserKit::eKeywordKindCommentMultiLineStart: { + commentBlock = true; + return true; + } + case ParserKit::eKeywordKindCommentMultiLineEnd: { + commentBlock = false; + break; + } + case ParserKit::eKeywordKindCommentInline: { + break; + } + default: + break; + } + + if (text[text.find(keyword.keyword_name) - 1] == '+' && + keyword.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableAssign) + continue; + + if (text[text.find(keyword.keyword_name) - 1] == '-' && + keyword.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableAssign) + continue; + + if (text[text.find(keyword.keyword_name) + 1] == '=' && + keyword.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableAssign) + continue; + + keywords_list.emplace_back(std::make_pair(keyword, index)); + ++index; + + found = true; + } + } + + if (!found && !commentBlock) + { + for (size_t i = 0; i < text.size(); i++) + { + if (isalnum(text[i])) + { + detail::print_error("syntax error: " + text, file); + return false; + } + } + } + + for (auto& keyword : keywords_list) + { + auto syntax_tree = ParserKit::SyntaxLeafList::SyntaxLeaf(); + + switch (keyword.first.keyword_kind) + { + case ParserKit::KeywordKind::eKeywordKindFunctionStart: { + std::string fnName = text; + fnName.erase(fnName.find(keyword.first.keyword_name)); + + for (auto& ch : fnName) + { + if (ch == ' ') + ch = '_'; + } + + syntax_tree.fUserValue = "export .code64 __MPCC_" + fnName + "\n"; + + ++kLevelFunction; + break; + } + case ParserKit::KeywordKind::eKeywordKindFunctionEnd: { + --kLevelFunction; + + if (kRegisterMap.size() > cRegisters.size()) + { + --kLevelFunction; + } + + if (kLevelFunction < 1) + kRegisterMap.clear(); + break; + } + case ParserKit::KeywordKind::eKeywordKindEndInstr: + case ParserKit::KeywordKind::eKeywordKindVariableInc: + case ParserKit::KeywordKind::eKeywordKindVariableDec: + case ParserKit::KeywordKind::eKeywordKindVariableAssign: { + std::string valueOfVar = ""; + + if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableInc) + { + valueOfVar = text.substr(text.find("+=") + 2); + } + else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableDec) + { + valueOfVar = text.substr(text.find("-=") + 2); + } + else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableAssign) + { + valueOfVar = text.substr(text.find("=") + 1); + } + else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindEndInstr) + { + valueOfVar = "0\n"; + } + + while (valueOfVar.find(";") != std::string::npos && + keyword.first.keyword_kind != ParserKit::KeywordKind::eKeywordKindEndInstr) + { + valueOfVar.erase(valueOfVar.find(";")); + } + + std::string varName = text; + + if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableInc) + { + varName.erase(varName.find("+=")); + } + else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableDec) + { + varName.erase(varName.find("-=")); + } + else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableAssign) + { + varName.erase(varName.find("=")); + } + else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindEndInstr) + { + varName.erase(varName.find(";")); + } + + bool typeFound = false; + + for (auto& keyword : kKeywords) + { + if (keyword.keyword_kind == ParserKit::eKeywordKindType) + { + if (varName.find(keyword.keyword_name) != std::string::npos) + { + typeFound = true; + varName.erase(varName.find(keyword.keyword_name), keyword.keyword_name.size()); + } + + /// in case we goot boolX or intX + if (text.find(keyword.keyword_name) != std::string::npos) + { + if (varName[text.find(keyword.keyword_name)] == ' ') + continue; + + typeFound = false; + } + } + } + + std::string instr = "mov "; + + if (typeFound) + { + if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableInc) + { + detail::print_error("Can't increment variable when it's being created.", file); + } + else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableDec) + { + detail::print_error("Can't decrement variable when it's being created.", file); + } + + if (kRegisterMap.size() > cRegisters.size()) + { + ++kLevelFunction; + } + + while (varName.find(" ") != std::string::npos) + { + varName.erase(varName.find(" "), 1); + } + + while (varName.find("\t") != std::string::npos) + { + varName.erase(varName.find("\t"), 1); + } + + for (size_t i = 0; !isalnum(valueOfVar[i]); i++) + { + if (i > valueOfVar.size()) + break; + + valueOfVar.erase(i, 1); + } + + constexpr auto cTrueVal = "true"; + constexpr auto cFalseVal = "false"; + + if (valueOfVar == cTrueVal) + { + valueOfVar = "1"; + } + else if (valueOfVar == cFalseVal) + { + valueOfVar = "0"; + } + + std::size_t indexRight = 0UL; + + for (auto pairRight : kRegisterMap) + { + ++indexRight; + + if (pairRight != valueOfVar) + { + syntax_tree.fUserValue = instr + cRegisters[kRegisterMap.size()] + ", " + valueOfVar + "\n"; + continue; + } + + syntax_tree.fUserValue = instr + cRegisters[kRegisterMap.size()] + ", " + cRegisters[indexRight - 1] + "\n"; + break; + } + + if (((int)indexRight - 1) < 0) + { + syntax_tree.fUserValue = instr + cRegisters[kRegisterMap.size()] + ", " + valueOfVar + "\n"; + } + + kRegisterMap.push_back(varName); + } + else + { + if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindEndInstr) + { + syntax_tree.fUserValue = "\n"; + continue; + } + + if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableInc) + { + instr = "add "; + } + else if (keyword.first.keyword_kind == ParserKit::KeywordKind::eKeywordKindVariableDec) + { + instr = "sub "; + } + + std::string varErrCpy = varName; + + while (varName.find(" ") != std::string::npos) + { + varName.erase(varName.find(" "), 1); + } + + while (varName.find("\t") != std::string::npos) + { + varName.erase(varName.find("\t"), 1); + } + + std::size_t indxReg = 0UL; + + for (size_t i = 0; !isalnum(valueOfVar[i]); i++) + { + if (i > valueOfVar.size()) + break; + + valueOfVar.erase(i, 1); + } + + constexpr auto cTrueVal = "true"; + constexpr auto cFalseVal = "false"; + + /// interpet boolean values, since we're on C++ + + if (valueOfVar == cTrueVal) + { + valueOfVar = "1"; + } + else if (valueOfVar == cFalseVal) + { + valueOfVar = "0"; + } + + for (auto pair : kRegisterMap) + { + ++indxReg; + + if (pair != varName) + continue; + + std::size_t indexRight = 0ul; + + for (auto pairRight : kRegisterMap) + { + ++indexRight; + + if (pairRight != valueOfVar) + { + syntax_tree.fUserValue = instr + cRegisters[kRegisterMap.size()] + ", " + valueOfVar + "\n"; + continue; + } + + syntax_tree.fUserValue = instr + cRegisters[indxReg - 1] + ", " + cRegisters[indexRight - 1] + "\n"; + break; + } + + break; + } + + if (syntax_tree.fUserValue.empty()) + { + detail::print_error("Variable not declared: " + varErrCpy, file); + } + } + + break; + } + case ParserKit::KeywordKind::eKeywordKindReturn: { + auto pos = text.find("return") + strlen("return") + 1; + std::string subText = text.substr(pos); + subText = subText.erase(subText.find(";")); + size_t indxReg = 0UL; + + if (subText[0] != '\"' && + subText[0] != '\'') + { + if (!isdigit(subText[0])) + { + for (auto pair : kRegisterMap) + { + ++indxReg; + + if (pair != subText) + continue; + + syntax_tree.fUserValue = "mov rax, " + cRegisters[indxReg - 1] + "\r\nret\n"; + break; + } + + if (syntax_tree.fUserValue.empty()) + { + detail::print_error("Variable not declared: " + subText, file); + } + } + else + { + syntax_tree.fUserValue = "mov rax, " + subText + "\r\nret\n"; + } + } + else + { + syntax_tree.fUserValue = "mov rcx, " + subText + "\n"; + syntax_tree.fUserValue = "mov rax, rcx\r\nret\n"; + } + + break; + } + default: + break; + } + + syntax_tree.fUserData = keyword.first; + kState.fSyntaxTree->fLeafList.emplace_back(syntax_tree); + } + +_MpccOkay: + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +/** + * @brief C To Assembly mount-point. + */ + +///////////////////////////////////////////////////////////////////////////////////////// + +class AssemblyCPlusPlusInterface final : public CompilerKit::AssemblyInterface +{ +public: + explicit AssemblyCPlusPlusInterface() = default; + ~AssemblyCPlusPlusInterface() override = default; + + MPCC_COPY_DEFAULT(AssemblyCPlusPlusInterface); + + [[maybe_unused]] + static Int32 Arch() noexcept + { + return CompilerKit::AssemblyFactory::kArchAMD64; + } + + Int32 CompileToFormat(std::string& src, Int32 arch) override + { + if (arch != AssemblyCPlusPlusInterface::Arch()) + return -1; + + if (kCompilerBackend == nullptr) + return -1; + + /* @brief copy contents wihtout extension */ + std::string src_file = src.data(); + std::ifstream src_fp = std::ifstream(src_file, std::ios::in); + std::string dest; + + for (auto& ch : src_file) + { + if (ch == '.') + { + break; + } + + dest += ch; + } + + if (dest.empty()) + { + dest = "CXX-MPCC-"; + + std::random_device rd; + auto seed_data = std::array {}; + + std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); + + std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); + std::mt19937 generator(seq); + + auto gen = uuids::uuid_random_generator(generator); + + auto id = gen(); + dest += uuids::to_string(id); + } + + std::vector exts = kAsmFileExts; + + dest += exts[3]; + + std::cout << dest; + + kState.fOutputAssembly = std::make_unique(dest); + + auto fmt = CompilerKit::current_date(); + + (*kState.fOutputAssembly) << "; Path: " << src_file << "\n"; + (*kState.fOutputAssembly) + << "; Language: AMD64 assembly. (Generated from C++)\n"; + (*kState.fOutputAssembly) << "; Date: " << fmt << "\n"; + (*kState.fOutputAssembly) << "#bits 64\n#org 0x1000000" + << "\n"; + + ParserKit::SyntaxLeafList syntax; + + kState.fSyntaxTreeList.emplace_back(syntax); + kState.fSyntaxTree = + &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; + + std::string source; + + while (std::getline(src_fp, source)) + { + // Compile into an object file. + kCompilerBackend->Compile(source.c_str(), src.c_str()); + } + + for (auto& ast : kState.fSyntaxTree->fLeafList) + { + (*kState.fOutputAssembly) << ast.fUserValue; + } + + if (kAcceptableErrors > 0) + return -1; + + return kOk; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +static void cxx_print_help() +{ + kSplashCxx(); + kPrintF("%s", "No help available, see:\n"); + kPrintF("%s", "www.zeta.com/developer/cplusplus\n"); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +#define kExtListCxx \ + { \ + ".cpp", ".cxx", ".cc", ".c++", ".cp" \ + } + +NDK_MODULE(CompilerCPlusPlus) +{ + bool skip = false; + + kKeywords.push_back({.keyword_name = "class", .keyword_kind = ParserKit::eKeywordKindClass}); + kKeywords.push_back({.keyword_name = "struct", .keyword_kind = ParserKit::eKeywordKindClass}); + kKeywords.push_back({.keyword_name = "namespace", .keyword_kind = ParserKit::eKeywordKindNamespace}); + kKeywords.push_back({.keyword_name = "typedef", .keyword_kind = ParserKit::eKeywordKindTypedef}); + kKeywords.push_back({.keyword_name = "using", .keyword_kind = ParserKit::eKeywordKindTypedef}); + kKeywords.push_back({.keyword_name = "{", .keyword_kind = ParserKit::eKeywordKindBodyStart}); + kKeywords.push_back({.keyword_name = "}", .keyword_kind = ParserKit::eKeywordKindBodyEnd}); + kKeywords.push_back({.keyword_name = "auto", .keyword_kind = ParserKit::eKeywordKindVariable}); + kKeywords.push_back({.keyword_name = "int", .keyword_kind = ParserKit::eKeywordKindType}); + kKeywords.push_back({.keyword_name = "bool", .keyword_kind = ParserKit::eKeywordKindType}); + kKeywords.push_back({.keyword_name = "unsigned", .keyword_kind = ParserKit::eKeywordKindType}); + kKeywords.push_back({.keyword_name = "short", .keyword_kind = ParserKit::eKeywordKindType}); + kKeywords.push_back({.keyword_name = "char", .keyword_kind = ParserKit::eKeywordKindType}); + kKeywords.push_back({.keyword_name = "long", .keyword_kind = ParserKit::eKeywordKindType}); + kKeywords.push_back({.keyword_name = "float", .keyword_kind = ParserKit::eKeywordKindType}); + kKeywords.push_back({.keyword_name = "double", .keyword_kind = ParserKit::eKeywordKindType}); + kKeywords.push_back({.keyword_name = "void", .keyword_kind = ParserKit::eKeywordKindType}); + + kKeywords.push_back({.keyword_name = "auto*", .keyword_kind = ParserKit::eKeywordKindVariablePtr}); + kKeywords.push_back({.keyword_name = "int*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); + kKeywords.push_back({.keyword_name = "bool*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); + kKeywords.push_back({.keyword_name = "unsigned*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); + kKeywords.push_back({.keyword_name = "short*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); + kKeywords.push_back({.keyword_name = "char*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); + kKeywords.push_back({.keyword_name = "long*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); + kKeywords.push_back({.keyword_name = "float*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); + kKeywords.push_back({.keyword_name = "double*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); + kKeywords.push_back({.keyword_name = "void*", .keyword_kind = ParserKit::eKeywordKindTypePtr}); + + kKeywords.push_back({.keyword_name = "(", .keyword_kind = ParserKit::eKeywordKindFunctionStart}); + kKeywords.push_back({.keyword_name = ")", .keyword_kind = ParserKit::eKeywordKindFunctionEnd}); + kKeywords.push_back({.keyword_name = "=", .keyword_kind = ParserKit::eKeywordKindVariableAssign}); + kKeywords.push_back({.keyword_name = "+=", .keyword_kind = ParserKit::eKeywordKindVariableInc}); + kKeywords.push_back({.keyword_name = "-=", .keyword_kind = ParserKit::eKeywordKindVariableDec}); + kKeywords.push_back({.keyword_name = "const", .keyword_kind = ParserKit::eKeywordKindConstant}); + kKeywords.push_back({.keyword_name = "*", .keyword_kind = ParserKit::eKeywordKindPtr}); + kKeywords.push_back({.keyword_name = "->", .keyword_kind = ParserKit::eKeywordKindPtrAccess}); + kKeywords.push_back({.keyword_name = ".", .keyword_kind = ParserKit::eKeywordKindAccess}); + kKeywords.push_back({.keyword_name = ",", .keyword_kind = ParserKit::eKeywordKindArgSeparator}); + kKeywords.push_back({.keyword_name = ";", .keyword_kind = ParserKit::eKeywordKindEndInstr}); + kKeywords.push_back({.keyword_name = ":", .keyword_kind = ParserKit::eKeywordKindSpecifier}); + kKeywords.push_back({.keyword_name = "public:", .keyword_kind = ParserKit::eKeywordKindSpecifier}); + kKeywords.push_back({.keyword_name = "private:", .keyword_kind = ParserKit::eKeywordKindSpecifier}); + kKeywords.push_back({.keyword_name = "protected:", .keyword_kind = ParserKit::eKeywordKindSpecifier}); + kKeywords.push_back({.keyword_name = "final", .keyword_kind = ParserKit::eKeywordKindSpecifier}); + kKeywords.push_back({.keyword_name = "return", .keyword_kind = ParserKit::eKeywordKindReturn}); + kKeywords.push_back({.keyword_name = "/*", .keyword_kind = ParserKit::eKeywordKindCommentMultiLineStart}); + kKeywords.push_back({.keyword_name = "*/", .keyword_kind = ParserKit::eKeywordKindCommentMultiLineStart}); + kKeywords.push_back({.keyword_name = "//", .keyword_kind = ParserKit::eKeywordKindCommentInline}); + kKeywords.push_back({.keyword_name = "==", .keyword_kind = ParserKit::eKeywordKindEq}); + kKeywords.push_back({.keyword_name = "!=", .keyword_kind = ParserKit::eKeywordKindNotEq}); + kKeywords.push_back({.keyword_name = ">=", .keyword_kind = ParserKit::eKeywordKindGreaterEq}); + kKeywords.push_back({.keyword_name = "<=", .keyword_kind = ParserKit::eKeywordKindLessEq}); + + kFactory.Mount(new AssemblyCPlusPlusInterface()); + kCompilerBackend = new CompilerBackendCPlusPlus(); + + for (auto index = 1UL; index < argc; ++index) + { + if (argv[index][0] == '/') + { + if (skip) + { + skip = false; + continue; + } + + if (strcmp(argv[index], "/v") == 0 || + strcmp(argv[index], "/version") == 0) + { + kSplashCxx(); + return kOk; + } + + if (strcmp(argv[index], "/verbose") == 0) + { + kState.fVerbose = true; + + continue; + } + + if (strcmp(argv[index], "/h") == 0 || strcmp(argv[index], "/help") == 0) + { + cxx_print_help(); + + return kOk; + } + + if (strcmp(argv[index], "/dialect") == 0) + { + if (kCompilerBackend) + std::cout << kCompilerBackend->Language() << "\n"; + + return kOk; + } + + if (strcmp(argv[index], "/max-errors") == 0) + { + try + { + kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); + } + // catch anything here + catch (...) + { + kErrorLimit = 0; + } + + skip = true; + + continue; + } + + std::string err = "Unknown option: "; + err += argv[index]; + + detail::print_error(err, "cplusplus"); + + continue; + } + + kFileList.emplace_back(argv[index]); + + std::string argv_i = argv[index]; + + std::vector exts = kExtListCxx; + bool found = false; + + for (std::string ext : exts) + { + if (argv_i.find(ext) != std::string::npos) + { + found = true; + break; + } + } + + if (!found) + { + if (kState.fVerbose) + { + detail::print_error(argv_i + " is not a valid C++ source.\n", "cplusplus"); + } + + return 1; + } + + if (kFactory.Compile(argv_i, kMachine) != kOk) + return -1; + } + + return kOk; +} + +// Last rev 8-1-24 diff --git a/Sources/elf2ae.cc b/Sources/elf2ae.cc deleted file mode 100644 index 70ab104..0000000 --- a/Sources/elf2ae.cc +++ /dev/null @@ -1,22 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#include -#include -#include -#include -#include -#include -#include -#include - -///////////////////////////////////////////////////////////////////////////////////////// - -/// @brief COFF 2 AE entrypoint, the program/module starts here. - -///////////////////////////////////////////////////////////////////////////////////////// - -NDK_MODULE(NewOSELFToAE) { return 0; } diff --git a/Sources/elf2ae.cxx b/Sources/elf2ae.cxx new file mode 100644 index 0000000..3409f6e --- /dev/null +++ b/Sources/elf2ae.cxx @@ -0,0 +1,22 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include + +///////////////////////////////////////////////////////////////////////////////////////// + +/// @brief COFF 2 AE entrypoint, the program/module starts here. + +///////////////////////////////////////////////////////////////////////////////////////// + +NDK_MODULE(NewOSELFToAE) { return 0; } diff --git a/Sources/i64asm.cc b/Sources/i64asm.cc deleted file mode 100644 index c0dd351..0000000 --- a/Sources/i64asm.cc +++ /dev/null @@ -1,1484 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -///////////////////////////////////////////////////////////////////////////////////////// - -/// @file i64asm.cxx -/// @author Amlal EL Mahrouss -/// @brief AMD64 Assembler. - -/// REMINDER: when dealing with an undefined symbol use (string -/// size):LinkerFindSymbol:(string) so that ld will look for it. - -///////////////////////////////////////////////////////////////////////////////////////// - -/// bugs: 0 - -/// feature request: 1 -/// Encode registers in mov, add, xor... - -///////////////////////////////////////////////////////////////////////////////////////// - -#define __ASM_NEED_AMD64__ 1 - -#define kAssemblerPragmaSymStr "#" -#define kAssemblerPragmaSym '#' - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -///////////////////// - -// ANSI ESCAPE CODES - -///////////////////// - -#define kBlank "\e[0;30m" -#define kRed "\e[0;31m" -#define kWhite "\e[0;97m" -#define kYellow "\e[0;33m" - -#define kStdOut (std::cout << kWhite) -#define kStdErr (std::cout << kRed) - -static char kOutputArch = CompilerKit::kPefArchAMD64; -static Boolean kOutputAsBinary = false; - -static UInt32 kErrorLimit = 10; -static UInt32 kAcceptableErrors = 0; - -constexpr auto cAMD64IPAlignment = 0x4U; - -static std::size_t kCounter = 1UL; - -static std::uintptr_t kOrigin = kPefBaseOrigin; -static std::vector> kOriginLabel; - -/// @brief keep it simple by default. -static std::int32_t kRegisterBitWidth = 16U; - -static bool kVerbose = false; - -static std::vector kAppBytes; - -static CompilerKit::AERecordHeader kCurrentRecord{ - .fName = "", .fKind = CompilerKit::kPefCode, .fSize = 0, .fOffset = 0}; - -static std::vector kRecords; -static std::vector kDefinedSymbols; -static std::vector kUndefinedSymbols; - -static const std::string kUndefinedSymbol = ":UndefinedSymbol:"; -static const std::string kRelocSymbol = ":RuntimeSymbol:"; - -// \brief forward decl. -static bool asm_read_attributes(std::string& line); - -namespace detail -{ - void print_error(std::string reason, const std::string& file) noexcept - { - if (reason[0] == '\n') - reason.erase(0, 1); - - kStdErr << kRed << "[ i64asm ] " << kWhite - << ((file == "i64asm") ? "internal assembler error " - : ("in file, " + file)) - << kBlank << std::endl; - kStdErr << kRed << "[ i64asm ] " << kWhite << reason << kBlank << std::endl; - - if (kAcceptableErrors > kErrorLimit) - std::exit(3); - - ++kAcceptableErrors; - } - - void print_warning(std::string reason, const std::string& file) noexcept - { - if (reason[0] == '\n') - reason.erase(0, 1); - - if (!file.empty()) - { - kStdOut << kYellow << "[ file ] " << kWhite << file << kBlank << std::endl; - } - - kStdOut << kYellow << "[ i64asm ] " << kWhite << reason << kBlank - << std::endl; - } -} // namespace detail - -#include - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief AMD64 assembler entrypoint, the program/module starts here. - -///////////////////////////////////////////////////////////////////////////////////////// - -NDK_MODULE(NewOSAssemblerAMD64) -{ - //////////////// CPU OPCODES BEGIN //////////////// - - std::string opcodes_jump[kJumpLimit] = { - "ja", "jae", "jb", "jbe", "jc", "je", "jg", "jge", "jl", "jle", - "jna", "jnae", "jnb", "jnbe", "jnc", "jne", "jng", "jnge", "jnl", "jnle", - "jno", "jnp", "jns", "jnz", "jo", "jp", "jpe", "jpo", "js", "jz"}; - - for (i64_hword_t i = 0; i < kJumpLimit; i++) - { - CpuOpcodeAMD64 code{ - .fName = opcodes_jump[i], - .fOpcode = static_cast(kAsmJumpOpcode + i)}; - kOpcodesAMD64.push_back(code); - } - - CpuOpcodeAMD64 code{.fName = "jcxz", .fOpcode = 0xE3}; - kOpcodesAMD64.push_back(code); - - for (i64_hword_t i = kJumpLimitStandard; i < kJumpLimitStandardLimit; i++) - { - CpuOpcodeAMD64 code{.fName = "jmp", .fOpcode = i}; - kOpcodesAMD64.push_back(code); - } - - CpuOpcodeAMD64 lahf{.fName = "lahf", .fOpcode = 0x9F}; - kOpcodesAMD64.push_back(lahf); - - CpuOpcodeAMD64 lds{.fName = "lds", .fOpcode = 0xC5}; - kOpcodesAMD64.push_back(lds); - - CpuOpcodeAMD64 lea{.fName = "lea", .fOpcode = 0x8D}; - kOpcodesAMD64.push_back(lea); - - CpuOpcodeAMD64 nop{.fName = "nop", .fOpcode = 0x90}; - kOpcodesAMD64.push_back(nop); - - //////////////// CPU OPCODES END //////////////// - - for (size_t i = 1; i < argc; ++i) - { - if (argv[i][0] == '/') - { - if (strcmp(argv[i], "/version") == 0 || strcmp(argv[i], "/v") == 0) - { - kStdOut << "i64asm: AMD64 Assembler Driver.\ni64asm: v1.10\ni64asm: Copyright " - "(c) ZKA Technologies.\n"; - return 0; - } - else if (strcmp(argv[i], "/h") == 0) - { - kStdOut << "i64asm: AMD64 Assembler Driver.\ni64asm: Copyright (c) 2024 " - "ZKA Technologies.\n"; - kStdOut << "/version: Print program version.\n"; - kStdOut << "/verbose: Print verbose output.\n"; - kStdOut << "/binary: Output as flat binary.\n"; - - return 0; - } - else if (strcmp(argv[i], "/binary") == 0) - { - kOutputAsBinary = true; - continue; - } - else if (strcmp(argv[i], "/verbose") == 0) - { - kVerbose = true; - continue; - } - - kStdOut << "i64asm: ignore " << argv[i] << "\n"; - continue; - } - - if (!std::filesystem::exists(argv[i])) - { - kStdOut << "i64asm: can't open: " << argv[i] << std::endl; - goto asm_fail_exit; - } - - std::string object_output(argv[i]); - - for (auto& ext : kAsmFileExts) - { - if (object_output.find(ext) != std::string::npos) - { - object_output.erase(object_output.find(ext), std::strlen(ext)); - } - } - - object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt; - - std::ifstream file_ptr(argv[i]); - std::ofstream file_ptr_out(object_output, std::ofstream::binary); - - if (file_ptr_out.bad()) - { - if (kVerbose) - { - kStdOut << "i64asm: error: " << strerror(errno) << "\n"; - } - } - - std::string line; - - CompilerKit::AEHeader hdr{0}; - - memset(hdr.fPad, kAEInvalidOpcode, kAEPad); - - hdr.fMagic[0] = kAEMag0; - hdr.fMagic[1] = kAEMag1; - hdr.fSize = sizeof(CompilerKit::AEHeader); - hdr.fArch = kOutputArch; - - ///////////////////////////////////////////////////////////////////////////////////////// - - // COMPILATION LOOP - - ///////////////////////////////////////////////////////////////////////////////////////// - - CompilerKit::EncoderAMD64 asm64; - - while (std::getline(file_ptr, line)) - { - if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) - { - detail::print_error(ln, argv[i]); - continue; - } - - try - { - asm_read_attributes(line); - asm64.WriteLine(line, argv[i]); - } - catch (const std::exception& e) - { - if (kVerbose) - { - std::string what = e.what(); - detail::print_warning("exit because of: " + what, "i64asm"); - } - - try - { - std::filesystem::remove(object_output); - } - catch (...) - { - } - - goto asm_fail_exit; - } - } - - if (!kOutputAsBinary) - { - if (kVerbose) - { - kStdOut << "i64asm: Writing object file...\n"; - } - - // this is the final step, write everything to the file. - - auto pos = file_ptr_out.tellp(); - - hdr.fCount = kRecords.size() + kUndefinedSymbols.size(); - - file_ptr_out << hdr; - - if (kRecords.empty()) - { - kStdErr << "i64asm: At least one record is needed to write an object " - "file.\ni64asm: Make one using `export .code64 foo_bar`.\n"; - - std::filesystem::remove(object_output); - return -1; - } - - kRecords[kRecords.size() - 1].fSize = kAppBytes.size(); - - std::size_t record_count = 0UL; - - for (auto& rec : kRecords) - { - if (kVerbose) - kStdOut << "i64asm: Wrote record " << rec.fName << " to file...\n"; - - rec.fFlags |= CompilerKit::kKindRelocationAtRuntime; - rec.fOffset = record_count; - ++record_count; - - file_ptr_out << rec; - } - - // increment once again, so that we won't lie about the kUndefinedSymbols. - ++record_count; - - for (auto& sym : kUndefinedSymbols) - { - CompilerKit::AERecordHeader _record_hdr{0}; - - if (kVerbose) - kStdOut << "i64asm: Wrote symbol " << sym << " to file...\n"; - - _record_hdr.fKind = kAEInvalidOpcode; - _record_hdr.fSize = sym.size(); - _record_hdr.fOffset = record_count; - - ++record_count; - - memset(_record_hdr.fPad, kAEInvalidOpcode, kAEPad); - memcpy(_record_hdr.fName, sym.c_str(), sym.size()); - - file_ptr_out << _record_hdr; - - ++kCounter; - } - - auto pos_end = file_ptr_out.tellp(); - - file_ptr_out.seekp(pos); - - hdr.fStartCode = pos_end; - hdr.fCodeSize = kAppBytes.size(); - - file_ptr_out << hdr; - - file_ptr_out.seekp(pos_end); - } - else - { - if (kVerbose) - { - kStdOut << "i64asm: Write raw binary...\n"; - } - } - - // byte from byte, we write this. - for (auto& byte : kAppBytes) - { - if (byte == 0) - continue; - - if (byte == 0xFF) - { - byte = 0; - } - - file_ptr_out << reinterpret_cast(&byte)[0]; - } - - if (kVerbose) - kStdOut << "i64asm: Wrote file with program in it.\n"; - - file_ptr_out.flush(); - file_ptr_out.close(); - - if (kVerbose) - kStdOut << "i64asm: Exit succeeded.\n"; - - return 0; - } - -asm_fail_exit: - - if (kVerbose) - kStdOut << "i64asm: Exit failed.\n"; - - return -1; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief Check for attributes -// returns true if any was found. - -///////////////////////////////////////////////////////////////////////////////////////// - -static bool asm_read_attributes(std::string& line) -{ - // import is the opposite of export, it signals to the ld - // that we need this symbol. - if (ParserKit::find_word(line, "import")) - { - if (kOutputAsBinary) - { - detail::print_error("Invalid directive in flat binary mode.", "i64asm"); - throw std::runtime_error("invalid_import_bin"); - } - - auto name = line.substr(line.find("import") + strlen("import") + 1); - - if (name.size() == 0) - { - detail::print_error("Invalid import", "ppcasm"); - throw std::runtime_error("invalid_import"); - } - - std::string result = std::to_string(name.size()); - result += kUndefinedSymbol; - - // mangle this - for (char& j : name) - { - if (j == ' ' || j == ',') - j = '$'; - } - - result += name; - - if (name.find(".code64") != std::string::npos) - { - // data is treated as code. - kCurrentRecord.fKind = CompilerKit::kPefCode; - } - else if (name.find(".data64") != std::string::npos) - { - // no code will be executed from here. - kCurrentRecord.fKind = CompilerKit::kPefData; - } - else if (name.find(".zero64") != std::string::npos) - { - // this is a bss section. - kCurrentRecord.fKind = CompilerKit::kPefZero; - } - - // this is a special case for the start stub. - // we want this so that ld can find it. - - if (name == kPefStart) - { - kCurrentRecord.fKind = CompilerKit::kPefCode; - } - - // now we can tell the code size of the previous kCurrentRecord. - - if (!kRecords.empty()) - kRecords[kRecords.size() - 1].fSize = kAppBytes.size(); - - memset(kCurrentRecord.fName, 0, kAESymbolLen); - memcpy(kCurrentRecord.fName, result.c_str(), result.size()); - - ++kCounter; - - memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); - - kRecords.emplace_back(kCurrentRecord); - - return true; - } - // export is a special keyword used by i64asm to tell the AE output stage to - // mark this section as a header. it currently supports .code64, .data64 and - // .zero64. - else if (ParserKit::find_word(line, "export")) - { - if (kOutputAsBinary) - { - detail::print_error("Invalid directive in flat binary mode.", "i64asm"); - throw std::runtime_error("invalid_export_bin"); - } - - auto name = line.substr(line.find("export") + strlen("export") + 1); - - std::string name_copy = name; - - for (char& j : name) - { - if (j == ' ') - j = '$'; - } - - if (std::find(kDefinedSymbols.begin(), kDefinedSymbols.end(), name) != - kDefinedSymbols.end()) - { - detail::print_error("Symbol already defined.", "i64asm"); - throw std::runtime_error("invalid_export_bin"); - } - - kDefinedSymbols.push_back(name); - - if (name.find(".code64") != std::string::npos) - { - // data is treated as code. - - name_copy.erase(name_copy.find(".code64"), strlen(".code64")); - kCurrentRecord.fKind = CompilerKit::kPefCode; - } - else if (name.find(".data64") != std::string::npos) - { - // no code will be executed from here. - - name_copy.erase(name_copy.find(".data64"), strlen(".data64")); - kCurrentRecord.fKind = CompilerKit::kPefData; - } - else if (name.find(".zero64") != std::string::npos) - { - // this is a bss section. - - name_copy.erase(name_copy.find(".zero64"), strlen(".zero64")); - kCurrentRecord.fKind = CompilerKit::kPefZero; - } - - // this is a special case for the start stub. - // we want this so that ld can find it. - - if (name == kPefStart) - { - kCurrentRecord.fKind = CompilerKit::kPefCode; - } - - while (name_copy.find(" ") != std::string::npos) - name_copy.erase(name_copy.find(" "), 1); - - kOriginLabel.push_back(std::make_pair(name_copy, kOrigin)); - ++kOrigin; - - // now we can tell the code size of the previous kCurrentRecord. - - if (!kRecords.empty()) - kRecords[kRecords.size() - 1].fSize = kAppBytes.size(); - - memset(kCurrentRecord.fName, 0, kAESymbolLen); - memcpy(kCurrentRecord.fName, name.c_str(), name.size()); - - ++kCounter; - - memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); - - kRecords.emplace_back(kCurrentRecord); - - return true; - } - - return false; -} - -// \brief algorithms and helpers. - -namespace detail::algorithm -{ - // \brief authorize a brief set of characters. - static inline bool is_not_alnum_space(char c) - { - return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || - (c == ',') || (c == '(') || (c == ')') || (c == '"') || - (c == '\'') || (c == '[') || (c == ']') || (c == '+') || - (c == '_') || (c == ':') || (c == '@') || (c == '.') || (c == '#')); - } - - bool is_valid(const std::string& str) - { - return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); - } -} // namespace detail::algorithm - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief Check for line (syntax check) - -///////////////////////////////////////////////////////////////////////////////////////// - -std::string CompilerKit::EncoderAMD64::CheckLine(std::string& line, - const std::string& file) -{ - std::string err_str; - - if (line.empty() || ParserKit::find_word(line, "import") || - ParserKit::find_word(line, "export") || - ParserKit::find_word(line, kAssemblerPragmaSymStr) || - ParserKit::find_word(line, ";") || line[0] == kAssemblerPragmaSym) - { - if (line.find(';') != std::string::npos) - { - line.erase(line.find(';')); - } - else - { - // now check the line for validity - if (!detail::algorithm::is_valid(line)) - { - err_str = "Line contains non valid characters.\nhere -> "; - err_str += line; - } - } - - return err_str; - } - - if (!detail::algorithm::is_valid(line)) - { - err_str = "Line contains non alphanumeric characters.\nHere -> "; - err_str += line; - - return err_str; - } - - // check for a valid instruction format. - - if (line.find(',') != std::string::npos) - { - if (line.find(',') + 1 == line.size()) - { - err_str += "\nInstruction lacks right register, here -> "; - err_str += line.substr(line.find(',')); - - return err_str; - } - else - { - bool nothing_on_right = true; - - if (line.find(',') + 1 > line.size()) - { - err_str += "\nInstruction not complete, here -> "; - err_str += line; - - return err_str; - } - - auto substr = line.substr(line.find(',') + 1); - - for (auto& ch : substr) - { - if (ch != ' ' && ch != '\t') - { - nothing_on_right = false; - } - } - - // this means we found nothing after that ',' . - if (nothing_on_right) - { - err_str += "\nInstruction not complete, here -> "; - err_str += line; - - return err_str; - } - } - } - for (auto& opcodeAMD64 : kOpcodesAMD64) - { - if (ParserKit::find_word(line, opcodeAMD64.fName)) - { - return err_str; - } - } - - err_str += "\nUnrecognized instruction -> " + line; - - return err_str; -} - -bool CompilerKit::EncoderAMD64::WriteNumber(const std::size_t& pos, - std::string& jump_label) -{ - if (!isdigit(jump_label[pos])) - return false; - - switch (jump_label[pos + 1]) - { - case 'x': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); - !res) - { - if (errno != 0) - { - detail::print_error("invalid hex number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_hex"); - } - } - - CompilerKit::NumberCast64 num = CompilerKit::NumberCast64( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16)); - - for (char& i : num.number) - { - if (i == 0) - i = 0xFF; - - kAppBytes.push_back(i); - } - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 16 number here: " - << jump_label.substr(pos) << "\n"; - } - - return true; - } - case 'b': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); - !res) - { - if (errno != 0) - { - detail::print_error("invalid binary number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_bin"); - } - } - - CompilerKit::NumberCast64 num = CompilerKit::NumberCast64( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2)); - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 2 number here: " - << jump_label.substr(pos) << "\n"; - } - - for (char& i : num.number) - { - if (i == 0) - i = 0xFF; - - kAppBytes.push_back(i); - } - - return true; - } - case 'o': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); - !res) - { - if (errno != 0) - { - detail::print_error("invalid octal number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_octal"); - } - } - - CompilerKit::NumberCast64 num = CompilerKit::NumberCast64( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7)); - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 8 number here: " - << jump_label.substr(pos) << "\n"; - } - - for (char& i : num.number) - { - if (i == 0) - i = 0xFF; - - kAppBytes.push_back(i); - } - - return true; - } - default: { - break; - } - } - - /* check for errno and stuff like that */ - if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) - { - if (errno != 0) - { - return false; - } - } - - CompilerKit::NumberCast64 num = CompilerKit::NumberCast64( - strtol(jump_label.substr(pos).c_str(), nullptr, 10)); - - for (char& i : num.number) - { - if (i == 0) - i = 0xFF; - - kAppBytes.push_back(i); - } - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos) - << "\n"; - } - - return true; -} - -bool CompilerKit::EncoderAMD64::WriteNumber32(const std::size_t& pos, - std::string& jump_label) -{ - if (!isdigit(jump_label[pos])) - return false; - - switch (jump_label[pos + 1]) - { - case 'x': { - auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); - res += kOrigin; - - if (errno != 0) - { - return false; - } - - CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res); - - for (char& i : num.number) - { - if (i == 0) - i = 0xFF; - - kAppBytes.push_back(i); - } - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 16 number here: " - << jump_label.substr(pos) << "\n"; - } - - return true; - } - case 'b': { - auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); - res += kOrigin; - - if (errno != 0) - { - return false; - } - - CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res); - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 2 number here: " - << jump_label.substr(pos) << "\n"; - } - - for (char& i : num.number) - { - if (i == 0) - i = 0xFF; - - kAppBytes.push_back(i); - } - - return true; - } - case 'o': { - auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); - res += kOrigin; - - if (errno != 0) - { - return false; - } - - CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res); - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 8 number here: " - << jump_label.substr(pos) << "\n"; - } - - for (char& i : num.number) - { - if (i == 0) - i = 0xFF; - - kAppBytes.push_back(i); - } - - return true; - } - default: { - break; - } - } - - auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 10); - res += kOrigin; - - if (errno != 0) - { - return false; - } - - CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res); - - for (char& i : num.number) - { - if (i == 0) - i = 0xFF; - - kAppBytes.push_back(i); - } - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos) - << "\n"; - } - - return true; -} - -bool CompilerKit::EncoderAMD64::WriteNumber16(const std::size_t& pos, - std::string& jump_label) -{ - if (!isdigit(jump_label[pos])) - return false; - - switch (jump_label[pos + 1]) - { - case 'x': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); - !res) - { - if (errno != 0) - { - detail::print_error("invalid hex number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_hex"); - } - } - - CompilerKit::NumberCast16 num = CompilerKit::NumberCast16( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16)); - - for (char& i : num.number) - { - if (i == 0) - i = 0xFF; - - kAppBytes.push_back(i); - } - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 16 number here: " - << jump_label.substr(pos) << "\n"; - } - - return true; - } - case 'b': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); - !res) - { - if (errno != 0) - { - detail::print_error("invalid binary number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_bin"); - } - } - - CompilerKit::NumberCast16 num = CompilerKit::NumberCast16( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2)); - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 2 number here: " - << jump_label.substr(pos) << "\n"; - } - - for (char& i : num.number) - { - if (i == 0) - i = 0xFF; - - kAppBytes.push_back(i); - } - - return true; - } - case 'o': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); - !res) - { - if (errno != 0) - { - detail::print_error("invalid octal number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_octal"); - } - } - - CompilerKit::NumberCast16 num = CompilerKit::NumberCast16( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7)); - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 8 number here: " - << jump_label.substr(pos) << "\n"; - } - - for (char& i : num.number) - { - if (i == 0) - i = 0xFF; - - kAppBytes.push_back(i); - } - - return true; - } - default: { - break; - } - } - - /* check for errno and stuff like that */ - if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) - { - if (errno != 0) - { - return false; - } - } - - CompilerKit::NumberCast16 num = CompilerKit::NumberCast16( - strtol(jump_label.substr(pos).c_str(), nullptr, 10)); - - for (char& i : num.number) - { - if (i == 0) - i = 0xFF; - - kAppBytes.push_back(i); - } - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos) - << "\n"; - } - - return true; -} - -bool CompilerKit::EncoderAMD64::WriteNumber8(const std::size_t& pos, - std::string& jump_label) -{ - if (!isdigit(jump_label[pos])) - return false; - - switch (jump_label[pos + 1]) - { - case 'x': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); - !res) - { - if (errno != 0) - { - detail::print_error("invalid hex number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_hex"); - } - } - - CompilerKit::NumberCast8 num = CompilerKit::NumberCast8( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16)); - - kAppBytes.push_back(num.number); - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 16 number here: " - << jump_label.substr(pos) << "\n"; - } - - return true; - } - case 'b': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); - !res) - { - if (errno != 0) - { - detail::print_error("invalid binary number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_bin"); - } - } - - CompilerKit::NumberCast8 num = CompilerKit::NumberCast8( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2)); - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 2 number here: " - << jump_label.substr(pos) << "\n"; - } - - kAppBytes.push_back(num.number); - - return true; - } - case 'o': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); - !res) - { - if (errno != 0) - { - detail::print_error("invalid octal number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_octal"); - } - } - - CompilerKit::NumberCast8 num = CompilerKit::NumberCast8( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7)); - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 8 number here: " - << jump_label.substr(pos) << "\n"; - } - - kAppBytes.push_back(num.number); - - return true; - } - default: { - break; - } - } - - /* check for errno and stuff like that */ - if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) - { - if (errno != 0) - { - return false; - } - } - - CompilerKit::NumberCast8 num = CompilerKit::NumberCast8( - strtol(jump_label.substr(pos).c_str(), nullptr, 10)); - - kAppBytes.push_back(num.number); - - if (kVerbose) - { - kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos) - << "\n"; - } - - return true; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief Read and write an instruction to the output array. - -///////////////////////////////////////////////////////////////////////////////////////// - -bool CompilerKit::EncoderAMD64::WriteLine(std::string& line, - const std::string& file) -{ - if (ParserKit::find_word(line, "export ")) - return true; - - struct RegMapAMD64 - { - std::string fName; - i64_byte_t fModRM; - }; - - std::vector REGISTER_LIST{ - {.fName = "ax", .fModRM = 0x0}, - {.fName = "cx", .fModRM = 1}, - {.fName = "dx", .fModRM = 0x2}, - {.fName = "bx", .fModRM = 3}, - {.fName = "sp", .fModRM = 0x4}, - {.fName = "bp", .fModRM = 5}, - {.fName = "si", .fModRM = 0x6}, - {.fName = "di", .fModRM = 7}, - {.fName = "r8", .fModRM = 8}, - {.fName = "r13", .fModRM = 9}, - {.fName = "r9", .fModRM = 10}, - {.fName = "r14", .fModRM = 11}, - {.fName = "r10", .fModRM = 12}, - {.fName = "r15", .fModRM = 13}, - {.fName = "r11", .fModRM = 14}, - }; - - bool foundInstruction = false; - - for (auto& opcodeAMD64 : kOpcodesAMD64) - { - // strict check here - if (ParserKit::find_word(line, opcodeAMD64.fName) && - detail::algorithm::is_valid(line)) - { - foundInstruction = true; - std::string name(opcodeAMD64.fName); - - /// Move instruction handler. - if (name.find("mov") != std::string::npos) - { - std::string substr = line.substr(line.find(name) + name.size()); - - uint64_t bits = kRegisterBitWidth; - - if (substr.find(",") == std::string::npos) - { - detail::print_error("Syntax error.", "i64asm"); - throw std::runtime_error("syntax_err"); - } - - bool onlyOneReg = true; - - std::vector currentRegList; - - for (auto& reg : REGISTER_LIST) - { - std::vector regExt = {'e', 'r'}; - - for (auto& ext : regExt) - { - std::string registerName; - - if (bits > 16) - registerName.push_back(ext); - - registerName += reg.fName; - - while (line.find(registerName) != std::string::npos) - { - line.erase(line.find(registerName), registerName.size()); - - if (bits == 16) - { - if (registerName[0] == 'r') - { - detail::print_error( - "invalid size for register, current bit width is: " + - std::to_string(kRegisterBitWidth), - file); - throw std::runtime_error("invalid_reg_size"); - } - } - - currentRegList.push_back( - {.fName = registerName, .fModRM = reg.fModRM}); - } - } - } - - if (currentRegList.size() > 1) - onlyOneReg = false; - - bool hasRBasedRegs = false; - - if (!onlyOneReg) - { - /// very tricky to understand. - /// but this checks for a r8 through r15 register. - if (currentRegList[0].fName[0] == 'r' || - currentRegList[1].fName[0] == 'r') - { - if (isdigit(currentRegList[0].fName[1]) && - isdigit(currentRegList[1].fName[1])) - { - kAppBytes.emplace_back(0x4d); - hasRBasedRegs = true; - } - else if (isdigit(currentRegList[0].fName[1]) || - isdigit(currentRegList[1].fName[1])) - { - kAppBytes.emplace_back(0x4c); - hasRBasedRegs = true; - } - } - } - - if (bits == 64 || bits == 32) - { - if (!hasRBasedRegs && bits >= 32) - { - kAppBytes.emplace_back(opcodeAMD64.fOpcode); - } - - kAppBytes.emplace_back(0x89); - } - else if (bits == 16) - { - if (hasRBasedRegs) - { - detail::print_error( - "Invalid combination of operands and registers.", "i64asm"); - throw std::runtime_error("comb_op_reg"); - } - - kAppBytes.emplace_back(0x66); - kAppBytes.emplace_back(0x89); - } - - if (currentRegList[1].fName[0] == 'r' && - currentRegList[0].fName[0] == 'e') - { - detail::print_error("Invalid combination of operands and registers.", - "i64asm"); - throw std::runtime_error("comb_op_reg"); - } - - if (currentRegList[0].fName[0] == 'r' && - currentRegList[1].fName[0] == 'e') - { - detail::print_error("Invalid combination of operands and registers.", - "i64asm"); - throw std::runtime_error("comb_op_reg"); - } - - if (bits == 16) - { - if (currentRegList[0].fName[0] == 'r' || - currentRegList[0].fName[0] == 'e') - { - detail::print_error("Invalid combination of operands and registers.", - "i64asm"); - throw std::runtime_error("comb_op_reg"); - } - - if (currentRegList[1].fName[0] == 'r' || - currentRegList[1].fName[0] == 'e') - { - detail::print_error("Invalid combination of operands and registers.", - "i64asm"); - throw std::runtime_error("comb_op_reg"); - } - } - else - { - if (currentRegList[0].fName[0] != 'r' || - currentRegList[0].fName[0] == 'e') - { - detail::print_error("Invalid combination of operands and registers.", - "i64asm"); - throw std::runtime_error("comb_op_reg"); - } - - if (currentRegList[1].fName[0] != 'r' || - currentRegList[1].fName[0] == 'e') - { - detail::print_error("Invalid combination of operands and registers.", - "i64asm"); - throw std::runtime_error("comb_op_reg"); - } - } - - /// encode register using the modrm encoding. - - auto modrm = (0x3 << 6 | currentRegList[1].fModRM << 3 | - currentRegList[0].fModRM); - - kAppBytes.emplace_back(modrm); - - break; - } - else if (name == "int" || name == "into" || name == "intd") - { - kAppBytes.emplace_back(opcodeAMD64.fOpcode); - this->WriteNumber8(line.find(name) + name.size() + 1, line); - - break; - } - else if (name == "jmp" || name == "call") - { - kAppBytes.emplace_back(opcodeAMD64.fOpcode); - - if (!this->WriteNumber32(line.find(name) + name.size() + 1, line)) - { - throw std::runtime_error("BUG: WriteNumber32"); - } - - break; - } - else - { - kAppBytes.emplace_back(opcodeAMD64.fOpcode); - - break; - } - } - } - - if (line[0] == kAssemblerPragmaSym) - { - if (foundInstruction) - { - detail::print_error("Syntax error: " + line, "i64asm"); - throw std::runtime_error("syntax_err"); - } - - if (line.find("bits 64") != std::string::npos) - { - kRegisterBitWidth = 64U; - } - else if (line.find("bits 32") != std::string::npos) - { - kRegisterBitWidth = 32U; - } - else if (line.find("bits 16") != std::string::npos) - { - kRegisterBitWidth = 16U; - } - else if (line.find("org") != std::string::npos) - { - size_t base[] = {10, 16, 2, 7}; - - for (size_t i = 0; i < 4; i++) - { - if (kOrigin = strtol( - (line.substr(line.find("org") + strlen("org") + 1)).c_str(), - nullptr, base[i]); - kOrigin) - { - if (errno != 0) - { - continue; - } - else - { - if (kVerbose) - { - kStdOut << "i64asm: origin set: " << kOrigin << std::endl; - } - - break; - } - } - } - } - } - /// write a dword - else if (line.find(".dword") != std::string::npos) - { - this->WriteNumber32(line.find(".dword") + strlen(".dword") + 1, line); - } - /// write a long - else if (line.find(".long") != std::string::npos) - { - this->WriteNumber(line.find(".long") + strlen(".long") + 1, line); - } - /// write a 16-bit number - else if (line.find(".word") != std::string::npos) - { - this->WriteNumber16(line.find(".word") + strlen(".word") + 1, line); - } - - kOrigin += cAMD64IPAlignment; - - return true; -} - -// Last rev 13-1-24 diff --git a/Sources/i64asm.cxx b/Sources/i64asm.cxx new file mode 100644 index 0000000..a1f57b3 --- /dev/null +++ b/Sources/i64asm.cxx @@ -0,0 +1,1484 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +///////////////////////////////////////////////////////////////////////////////////////// + +/// @file i64asm.cxx +/// @author Amlal EL Mahrouss +/// @brief AMD64 Assembler. + +/// REMINDER: when dealing with an undefined symbol use (string +/// size):LinkerFindSymbol:(string) so that ld will look for it. + +///////////////////////////////////////////////////////////////////////////////////////// + +/// bugs: 0 + +/// feature request: 1 +/// Encode registers in mov, add, xor... + +///////////////////////////////////////////////////////////////////////////////////////// + +#define __ASM_NEED_AMD64__ 1 + +#define kAssemblerPragmaSymStr "#" +#define kAssemblerPragmaSym '#' + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +///////////////////// + +// ANSI ESCAPE CODES + +///////////////////// + +#define kBlank "\e[0;30m" +#define kRed "\e[0;31m" +#define kWhite "\e[0;97m" +#define kYellow "\e[0;33m" + +#define kStdOut (std::cout << kWhite) +#define kStdErr (std::cout << kRed) + +static char kOutputArch = CompilerKit::kPefArchAMD64; +static Boolean kOutputAsBinary = false; + +static UInt32 kErrorLimit = 10; +static UInt32 kAcceptableErrors = 0; + +constexpr auto cAMD64IPAlignment = 0x4U; + +static std::size_t kCounter = 1UL; + +static std::uintptr_t kOrigin = kPefBaseOrigin; +static std::vector> kOriginLabel; + +/// @brief keep it simple by default. +static std::int32_t kRegisterBitWidth = 16U; + +static bool kVerbose = false; + +static std::vector kAppBytes; + +static CompilerKit::AERecordHeader kCurrentRecord{ + .fName = "", .fKind = CompilerKit::kPefCode, .fSize = 0, .fOffset = 0}; + +static std::vector kRecords; +static std::vector kDefinedSymbols; +static std::vector kUndefinedSymbols; + +static const std::string kUndefinedSymbol = ":UndefinedSymbol:"; +static const std::string kRelocSymbol = ":RuntimeSymbol:"; + +// \brief forward decl. +static bool asm_read_attributes(std::string& line); + +namespace detail +{ + void print_error(std::string reason, const std::string& file) noexcept + { + if (reason[0] == '\n') + reason.erase(0, 1); + + kStdErr << kRed << "[ i64asm ] " << kWhite + << ((file == "i64asm") ? "internal assembler error " + : ("in file, " + file)) + << kBlank << std::endl; + kStdErr << kRed << "[ i64asm ] " << kWhite << reason << kBlank << std::endl; + + if (kAcceptableErrors > kErrorLimit) + std::exit(3); + + ++kAcceptableErrors; + } + + void print_warning(std::string reason, const std::string& file) noexcept + { + if (reason[0] == '\n') + reason.erase(0, 1); + + if (!file.empty()) + { + kStdOut << kYellow << "[ file ] " << kWhite << file << kBlank << std::endl; + } + + kStdOut << kYellow << "[ i64asm ] " << kWhite << reason << kBlank + << std::endl; + } +} // namespace detail + +#include + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief AMD64 assembler entrypoint, the program/module starts here. + +///////////////////////////////////////////////////////////////////////////////////////// + +NDK_MODULE(NewOSAssemblerAMD64) +{ + //////////////// CPU OPCODES BEGIN //////////////// + + std::string opcodes_jump[kJumpLimit] = { + "ja", "jae", "jb", "jbe", "jc", "je", "jg", "jge", "jl", "jle", + "jna", "jnae", "jnb", "jnbe", "jnc", "jne", "jng", "jnge", "jnl", "jnle", + "jno", "jnp", "jns", "jnz", "jo", "jp", "jpe", "jpo", "js", "jz"}; + + for (i64_hword_t i = 0; i < kJumpLimit; i++) + { + CpuOpcodeAMD64 code{ + .fName = opcodes_jump[i], + .fOpcode = static_cast(kAsmJumpOpcode + i)}; + kOpcodesAMD64.push_back(code); + } + + CpuOpcodeAMD64 code{.fName = "jcxz", .fOpcode = 0xE3}; + kOpcodesAMD64.push_back(code); + + for (i64_hword_t i = kJumpLimitStandard; i < kJumpLimitStandardLimit; i++) + { + CpuOpcodeAMD64 code{.fName = "jmp", .fOpcode = i}; + kOpcodesAMD64.push_back(code); + } + + CpuOpcodeAMD64 lahf{.fName = "lahf", .fOpcode = 0x9F}; + kOpcodesAMD64.push_back(lahf); + + CpuOpcodeAMD64 lds{.fName = "lds", .fOpcode = 0xC5}; + kOpcodesAMD64.push_back(lds); + + CpuOpcodeAMD64 lea{.fName = "lea", .fOpcode = 0x8D}; + kOpcodesAMD64.push_back(lea); + + CpuOpcodeAMD64 nop{.fName = "nop", .fOpcode = 0x90}; + kOpcodesAMD64.push_back(nop); + + //////////////// CPU OPCODES END //////////////// + + for (size_t i = 1; i < argc; ++i) + { + if (argv[i][0] == '/') + { + if (strcmp(argv[i], "/version") == 0 || strcmp(argv[i], "/v") == 0) + { + kStdOut << "i64asm: AMD64 Assembler Driver.\ni64asm: v1.10\ni64asm: Copyright " + "(c) ZKA Technologies.\n"; + return 0; + } + else if (strcmp(argv[i], "/h") == 0) + { + kStdOut << "i64asm: AMD64 Assembler Driver.\ni64asm: Copyright (c) 2024 " + "ZKA Technologies.\n"; + kStdOut << "/version: Print program version.\n"; + kStdOut << "/verbose: Print verbose output.\n"; + kStdOut << "/binary: Output as flat binary.\n"; + + return 0; + } + else if (strcmp(argv[i], "/binary") == 0) + { + kOutputAsBinary = true; + continue; + } + else if (strcmp(argv[i], "/verbose") == 0) + { + kVerbose = true; + continue; + } + + kStdOut << "i64asm: ignore " << argv[i] << "\n"; + continue; + } + + if (!std::filesystem::exists(argv[i])) + { + kStdOut << "i64asm: can't open: " << argv[i] << std::endl; + goto asm_fail_exit; + } + + std::string object_output(argv[i]); + + for (auto& ext : kAsmFileExts) + { + if (object_output.find(ext) != std::string::npos) + { + object_output.erase(object_output.find(ext), std::strlen(ext)); + } + } + + object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt; + + std::ifstream file_ptr(argv[i]); + std::ofstream file_ptr_out(object_output, std::ofstream::binary); + + if (file_ptr_out.bad()) + { + if (kVerbose) + { + kStdOut << "i64asm: error: " << strerror(errno) << "\n"; + } + } + + std::string line; + + CompilerKit::AEHeader hdr{0}; + + memset(hdr.fPad, kAEInvalidOpcode, kAEPad); + + hdr.fMagic[0] = kAEMag0; + hdr.fMagic[1] = kAEMag1; + hdr.fSize = sizeof(CompilerKit::AEHeader); + hdr.fArch = kOutputArch; + + ///////////////////////////////////////////////////////////////////////////////////////// + + // COMPILATION LOOP + + ///////////////////////////////////////////////////////////////////////////////////////// + + CompilerKit::EncoderAMD64 asm64; + + while (std::getline(file_ptr, line)) + { + if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) + { + detail::print_error(ln, argv[i]); + continue; + } + + try + { + asm_read_attributes(line); + asm64.WriteLine(line, argv[i]); + } + catch (const std::exception& e) + { + if (kVerbose) + { + std::string what = e.what(); + detail::print_warning("exit because of: " + what, "i64asm"); + } + + try + { + std::filesystem::remove(object_output); + } + catch (...) + { + } + + goto asm_fail_exit; + } + } + + if (!kOutputAsBinary) + { + if (kVerbose) + { + kStdOut << "i64asm: Writing object file...\n"; + } + + // this is the final step, write everything to the file. + + auto pos = file_ptr_out.tellp(); + + hdr.fCount = kRecords.size() + kUndefinedSymbols.size(); + + file_ptr_out << hdr; + + if (kRecords.empty()) + { + kStdErr << "i64asm: At least one record is needed to write an object " + "file.\ni64asm: Make one using `export .code64 foo_bar`.\n"; + + std::filesystem::remove(object_output); + return -1; + } + + kRecords[kRecords.size() - 1].fSize = kAppBytes.size(); + + std::size_t record_count = 0UL; + + for (auto& rec : kRecords) + { + if (kVerbose) + kStdOut << "i64asm: Wrote record " << rec.fName << " to file...\n"; + + rec.fFlags |= CompilerKit::kKindRelocationAtRuntime; + rec.fOffset = record_count; + ++record_count; + + file_ptr_out << rec; + } + + // increment once again, so that we won't lie about the kUndefinedSymbols. + ++record_count; + + for (auto& sym : kUndefinedSymbols) + { + CompilerKit::AERecordHeader _record_hdr{0}; + + if (kVerbose) + kStdOut << "i64asm: Wrote symbol " << sym << " to file...\n"; + + _record_hdr.fKind = kAEInvalidOpcode; + _record_hdr.fSize = sym.size(); + _record_hdr.fOffset = record_count; + + ++record_count; + + memset(_record_hdr.fPad, kAEInvalidOpcode, kAEPad); + memcpy(_record_hdr.fName, sym.c_str(), sym.size()); + + file_ptr_out << _record_hdr; + + ++kCounter; + } + + auto pos_end = file_ptr_out.tellp(); + + file_ptr_out.seekp(pos); + + hdr.fStartCode = pos_end; + hdr.fCodeSize = kAppBytes.size(); + + file_ptr_out << hdr; + + file_ptr_out.seekp(pos_end); + } + else + { + if (kVerbose) + { + kStdOut << "i64asm: Write raw binary...\n"; + } + } + + // byte from byte, we write this. + for (auto& byte : kAppBytes) + { + if (byte == 0) + continue; + + if (byte == 0xFF) + { + byte = 0; + } + + file_ptr_out << reinterpret_cast(&byte)[0]; + } + + if (kVerbose) + kStdOut << "i64asm: Wrote file with program in it.\n"; + + file_ptr_out.flush(); + file_ptr_out.close(); + + if (kVerbose) + kStdOut << "i64asm: Exit succeeded.\n"; + + return 0; + } + +asm_fail_exit: + + if (kVerbose) + kStdOut << "i64asm: Exit failed.\n"; + + return -1; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief Check for attributes +// returns true if any was found. + +///////////////////////////////////////////////////////////////////////////////////////// + +static bool asm_read_attributes(std::string& line) +{ + // import is the opposite of export, it signals to the ld + // that we need this symbol. + if (ParserKit::find_word(line, "import")) + { + if (kOutputAsBinary) + { + detail::print_error("Invalid directive in flat binary mode.", "i64asm"); + throw std::runtime_error("invalid_import_bin"); + } + + auto name = line.substr(line.find("import") + strlen("import") + 1); + + if (name.size() == 0) + { + detail::print_error("Invalid import", "ppcasm"); + throw std::runtime_error("invalid_import"); + } + + std::string result = std::to_string(name.size()); + result += kUndefinedSymbol; + + // mangle this + for (char& j : name) + { + if (j == ' ' || j == ',') + j = '$'; + } + + result += name; + + if (name.find(".code64") != std::string::npos) + { + // data is treated as code. + kCurrentRecord.fKind = CompilerKit::kPefCode; + } + else if (name.find(".data64") != std::string::npos) + { + // no code will be executed from here. + kCurrentRecord.fKind = CompilerKit::kPefData; + } + else if (name.find(".zero64") != std::string::npos) + { + // this is a bss section. + kCurrentRecord.fKind = CompilerKit::kPefZero; + } + + // this is a special case for the start stub. + // we want this so that ld can find it. + + if (name == kPefStart) + { + kCurrentRecord.fKind = CompilerKit::kPefCode; + } + + // now we can tell the code size of the previous kCurrentRecord. + + if (!kRecords.empty()) + kRecords[kRecords.size() - 1].fSize = kAppBytes.size(); + + memset(kCurrentRecord.fName, 0, kAESymbolLen); + memcpy(kCurrentRecord.fName, result.c_str(), result.size()); + + ++kCounter; + + memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); + + kRecords.emplace_back(kCurrentRecord); + + return true; + } + // export is a special keyword used by i64asm to tell the AE output stage to + // mark this section as a header. it currently supports .code64, .data64 and + // .zero64. + else if (ParserKit::find_word(line, "export")) + { + if (kOutputAsBinary) + { + detail::print_error("Invalid directive in flat binary mode.", "i64asm"); + throw std::runtime_error("invalid_export_bin"); + } + + auto name = line.substr(line.find("export") + strlen("export") + 1); + + std::string name_copy = name; + + for (char& j : name) + { + if (j == ' ') + j = '$'; + } + + if (std::find(kDefinedSymbols.begin(), kDefinedSymbols.end(), name) != + kDefinedSymbols.end()) + { + detail::print_error("Symbol already defined.", "i64asm"); + throw std::runtime_error("invalid_export_bin"); + } + + kDefinedSymbols.push_back(name); + + if (name.find(".code64") != std::string::npos) + { + // data is treated as code. + + name_copy.erase(name_copy.find(".code64"), strlen(".code64")); + kCurrentRecord.fKind = CompilerKit::kPefCode; + } + else if (name.find(".data64") != std::string::npos) + { + // no code will be executed from here. + + name_copy.erase(name_copy.find(".data64"), strlen(".data64")); + kCurrentRecord.fKind = CompilerKit::kPefData; + } + else if (name.find(".zero64") != std::string::npos) + { + // this is a bss section. + + name_copy.erase(name_copy.find(".zero64"), strlen(".zero64")); + kCurrentRecord.fKind = CompilerKit::kPefZero; + } + + // this is a special case for the start stub. + // we want this so that ld can find it. + + if (name == kPefStart) + { + kCurrentRecord.fKind = CompilerKit::kPefCode; + } + + while (name_copy.find(" ") != std::string::npos) + name_copy.erase(name_copy.find(" "), 1); + + kOriginLabel.push_back(std::make_pair(name_copy, kOrigin)); + ++kOrigin; + + // now we can tell the code size of the previous kCurrentRecord. + + if (!kRecords.empty()) + kRecords[kRecords.size() - 1].fSize = kAppBytes.size(); + + memset(kCurrentRecord.fName, 0, kAESymbolLen); + memcpy(kCurrentRecord.fName, name.c_str(), name.size()); + + ++kCounter; + + memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); + + kRecords.emplace_back(kCurrentRecord); + + return true; + } + + return false; +} + +// \brief algorithms and helpers. + +namespace detail::algorithm +{ + // \brief authorize a brief set of characters. + static inline bool is_not_alnum_space(char c) + { + return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || + (c == ',') || (c == '(') || (c == ')') || (c == '"') || + (c == '\'') || (c == '[') || (c == ']') || (c == '+') || + (c == '_') || (c == ':') || (c == '@') || (c == '.') || (c == '#')); + } + + bool is_valid(const std::string& str) + { + return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); + } +} // namespace detail::algorithm + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief Check for line (syntax check) + +///////////////////////////////////////////////////////////////////////////////////////// + +std::string CompilerKit::EncoderAMD64::CheckLine(std::string& line, + const std::string& file) +{ + std::string err_str; + + if (line.empty() || ParserKit::find_word(line, "import") || + ParserKit::find_word(line, "export") || + ParserKit::find_word(line, kAssemblerPragmaSymStr) || + ParserKit::find_word(line, ";") || line[0] == kAssemblerPragmaSym) + { + if (line.find(';') != std::string::npos) + { + line.erase(line.find(';')); + } + else + { + // now check the line for validity + if (!detail::algorithm::is_valid(line)) + { + err_str = "Line contains non valid characters.\nhere -> "; + err_str += line; + } + } + + return err_str; + } + + if (!detail::algorithm::is_valid(line)) + { + err_str = "Line contains non alphanumeric characters.\nHere -> "; + err_str += line; + + return err_str; + } + + // check for a valid instruction format. + + if (line.find(',') != std::string::npos) + { + if (line.find(',') + 1 == line.size()) + { + err_str += "\nInstruction lacks right register, here -> "; + err_str += line.substr(line.find(',')); + + return err_str; + } + else + { + bool nothing_on_right = true; + + if (line.find(',') + 1 > line.size()) + { + err_str += "\nInstruction not complete, here -> "; + err_str += line; + + return err_str; + } + + auto substr = line.substr(line.find(',') + 1); + + for (auto& ch : substr) + { + if (ch != ' ' && ch != '\t') + { + nothing_on_right = false; + } + } + + // this means we found nothing after that ',' . + if (nothing_on_right) + { + err_str += "\nInstruction not complete, here -> "; + err_str += line; + + return err_str; + } + } + } + for (auto& opcodeAMD64 : kOpcodesAMD64) + { + if (ParserKit::find_word(line, opcodeAMD64.fName)) + { + return err_str; + } + } + + err_str += "\nUnrecognized instruction -> " + line; + + return err_str; +} + +bool CompilerKit::EncoderAMD64::WriteNumber(const std::size_t& pos, + std::string& jump_label) +{ + if (!isdigit(jump_label[pos])) + return false; + + switch (jump_label[pos + 1]) + { + case 'x': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); + !res) + { + if (errno != 0) + { + detail::print_error("invalid hex number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_hex"); + } + } + + CompilerKit::NumberCast64 num = CompilerKit::NumberCast64( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16)); + + for (char& i : num.number) + { + if (i == 0) + i = 0xFF; + + kAppBytes.push_back(i); + } + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 16 number here: " + << jump_label.substr(pos) << "\n"; + } + + return true; + } + case 'b': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); + !res) + { + if (errno != 0) + { + detail::print_error("invalid binary number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_bin"); + } + } + + CompilerKit::NumberCast64 num = CompilerKit::NumberCast64( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2)); + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 2 number here: " + << jump_label.substr(pos) << "\n"; + } + + for (char& i : num.number) + { + if (i == 0) + i = 0xFF; + + kAppBytes.push_back(i); + } + + return true; + } + case 'o': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); + !res) + { + if (errno != 0) + { + detail::print_error("invalid octal number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_octal"); + } + } + + CompilerKit::NumberCast64 num = CompilerKit::NumberCast64( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7)); + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 8 number here: " + << jump_label.substr(pos) << "\n"; + } + + for (char& i : num.number) + { + if (i == 0) + i = 0xFF; + + kAppBytes.push_back(i); + } + + return true; + } + default: { + break; + } + } + + /* check for errno and stuff like that */ + if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) + { + if (errno != 0) + { + return false; + } + } + + CompilerKit::NumberCast64 num = CompilerKit::NumberCast64( + strtol(jump_label.substr(pos).c_str(), nullptr, 10)); + + for (char& i : num.number) + { + if (i == 0) + i = 0xFF; + + kAppBytes.push_back(i); + } + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos) + << "\n"; + } + + return true; +} + +bool CompilerKit::EncoderAMD64::WriteNumber32(const std::size_t& pos, + std::string& jump_label) +{ + if (!isdigit(jump_label[pos])) + return false; + + switch (jump_label[pos + 1]) + { + case 'x': { + auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); + res += kOrigin; + + if (errno != 0) + { + return false; + } + + CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res); + + for (char& i : num.number) + { + if (i == 0) + i = 0xFF; + + kAppBytes.push_back(i); + } + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 16 number here: " + << jump_label.substr(pos) << "\n"; + } + + return true; + } + case 'b': { + auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); + res += kOrigin; + + if (errno != 0) + { + return false; + } + + CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res); + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 2 number here: " + << jump_label.substr(pos) << "\n"; + } + + for (char& i : num.number) + { + if (i == 0) + i = 0xFF; + + kAppBytes.push_back(i); + } + + return true; + } + case 'o': { + auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); + res += kOrigin; + + if (errno != 0) + { + return false; + } + + CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res); + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 8 number here: " + << jump_label.substr(pos) << "\n"; + } + + for (char& i : num.number) + { + if (i == 0) + i = 0xFF; + + kAppBytes.push_back(i); + } + + return true; + } + default: { + break; + } + } + + auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 10); + res += kOrigin; + + if (errno != 0) + { + return false; + } + + CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res); + + for (char& i : num.number) + { + if (i == 0) + i = 0xFF; + + kAppBytes.push_back(i); + } + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos) + << "\n"; + } + + return true; +} + +bool CompilerKit::EncoderAMD64::WriteNumber16(const std::size_t& pos, + std::string& jump_label) +{ + if (!isdigit(jump_label[pos])) + return false; + + switch (jump_label[pos + 1]) + { + case 'x': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); + !res) + { + if (errno != 0) + { + detail::print_error("invalid hex number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_hex"); + } + } + + CompilerKit::NumberCast16 num = CompilerKit::NumberCast16( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16)); + + for (char& i : num.number) + { + if (i == 0) + i = 0xFF; + + kAppBytes.push_back(i); + } + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 16 number here: " + << jump_label.substr(pos) << "\n"; + } + + return true; + } + case 'b': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); + !res) + { + if (errno != 0) + { + detail::print_error("invalid binary number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_bin"); + } + } + + CompilerKit::NumberCast16 num = CompilerKit::NumberCast16( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2)); + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 2 number here: " + << jump_label.substr(pos) << "\n"; + } + + for (char& i : num.number) + { + if (i == 0) + i = 0xFF; + + kAppBytes.push_back(i); + } + + return true; + } + case 'o': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); + !res) + { + if (errno != 0) + { + detail::print_error("invalid octal number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_octal"); + } + } + + CompilerKit::NumberCast16 num = CompilerKit::NumberCast16( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7)); + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 8 number here: " + << jump_label.substr(pos) << "\n"; + } + + for (char& i : num.number) + { + if (i == 0) + i = 0xFF; + + kAppBytes.push_back(i); + } + + return true; + } + default: { + break; + } + } + + /* check for errno and stuff like that */ + if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) + { + if (errno != 0) + { + return false; + } + } + + CompilerKit::NumberCast16 num = CompilerKit::NumberCast16( + strtol(jump_label.substr(pos).c_str(), nullptr, 10)); + + for (char& i : num.number) + { + if (i == 0) + i = 0xFF; + + kAppBytes.push_back(i); + } + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos) + << "\n"; + } + + return true; +} + +bool CompilerKit::EncoderAMD64::WriteNumber8(const std::size_t& pos, + std::string& jump_label) +{ + if (!isdigit(jump_label[pos])) + return false; + + switch (jump_label[pos + 1]) + { + case 'x': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); + !res) + { + if (errno != 0) + { + detail::print_error("invalid hex number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_hex"); + } + } + + CompilerKit::NumberCast8 num = CompilerKit::NumberCast8( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16)); + + kAppBytes.push_back(num.number); + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 16 number here: " + << jump_label.substr(pos) << "\n"; + } + + return true; + } + case 'b': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); + !res) + { + if (errno != 0) + { + detail::print_error("invalid binary number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_bin"); + } + } + + CompilerKit::NumberCast8 num = CompilerKit::NumberCast8( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2)); + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 2 number here: " + << jump_label.substr(pos) << "\n"; + } + + kAppBytes.push_back(num.number); + + return true; + } + case 'o': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); + !res) + { + if (errno != 0) + { + detail::print_error("invalid octal number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_octal"); + } + } + + CompilerKit::NumberCast8 num = CompilerKit::NumberCast8( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7)); + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 8 number here: " + << jump_label.substr(pos) << "\n"; + } + + kAppBytes.push_back(num.number); + + return true; + } + default: { + break; + } + } + + /* check for errno and stuff like that */ + if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) + { + if (errno != 0) + { + return false; + } + } + + CompilerKit::NumberCast8 num = CompilerKit::NumberCast8( + strtol(jump_label.substr(pos).c_str(), nullptr, 10)); + + kAppBytes.push_back(num.number); + + if (kVerbose) + { + kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos) + << "\n"; + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief Read and write an instruction to the output array. + +///////////////////////////////////////////////////////////////////////////////////////// + +bool CompilerKit::EncoderAMD64::WriteLine(std::string& line, + const std::string& file) +{ + if (ParserKit::find_word(line, "export ")) + return true; + + struct RegMapAMD64 + { + std::string fName; + i64_byte_t fModRM; + }; + + std::vector REGISTER_LIST{ + {.fName = "ax", .fModRM = 0x0}, + {.fName = "cx", .fModRM = 1}, + {.fName = "dx", .fModRM = 0x2}, + {.fName = "bx", .fModRM = 3}, + {.fName = "sp", .fModRM = 0x4}, + {.fName = "bp", .fModRM = 5}, + {.fName = "si", .fModRM = 0x6}, + {.fName = "di", .fModRM = 7}, + {.fName = "r8", .fModRM = 8}, + {.fName = "r13", .fModRM = 9}, + {.fName = "r9", .fModRM = 10}, + {.fName = "r14", .fModRM = 11}, + {.fName = "r10", .fModRM = 12}, + {.fName = "r15", .fModRM = 13}, + {.fName = "r11", .fModRM = 14}, + }; + + bool foundInstruction = false; + + for (auto& opcodeAMD64 : kOpcodesAMD64) + { + // strict check here + if (ParserKit::find_word(line, opcodeAMD64.fName) && + detail::algorithm::is_valid(line)) + { + foundInstruction = true; + std::string name(opcodeAMD64.fName); + + /// Move instruction handler. + if (name.find("mov") != std::string::npos) + { + std::string substr = line.substr(line.find(name) + name.size()); + + uint64_t bits = kRegisterBitWidth; + + if (substr.find(",") == std::string::npos) + { + detail::print_error("Syntax error.", "i64asm"); + throw std::runtime_error("syntax_err"); + } + + bool onlyOneReg = true; + + std::vector currentRegList; + + for (auto& reg : REGISTER_LIST) + { + std::vector regExt = {'e', 'r'}; + + for (auto& ext : regExt) + { + std::string registerName; + + if (bits > 16) + registerName.push_back(ext); + + registerName += reg.fName; + + while (line.find(registerName) != std::string::npos) + { + line.erase(line.find(registerName), registerName.size()); + + if (bits == 16) + { + if (registerName[0] == 'r') + { + detail::print_error( + "invalid size for register, current bit width is: " + + std::to_string(kRegisterBitWidth), + file); + throw std::runtime_error("invalid_reg_size"); + } + } + + currentRegList.push_back( + {.fName = registerName, .fModRM = reg.fModRM}); + } + } + } + + if (currentRegList.size() > 1) + onlyOneReg = false; + + bool hasRBasedRegs = false; + + if (!onlyOneReg) + { + /// very tricky to understand. + /// but this checks for a r8 through r15 register. + if (currentRegList[0].fName[0] == 'r' || + currentRegList[1].fName[0] == 'r') + { + if (isdigit(currentRegList[0].fName[1]) && + isdigit(currentRegList[1].fName[1])) + { + kAppBytes.emplace_back(0x4d); + hasRBasedRegs = true; + } + else if (isdigit(currentRegList[0].fName[1]) || + isdigit(currentRegList[1].fName[1])) + { + kAppBytes.emplace_back(0x4c); + hasRBasedRegs = true; + } + } + } + + if (bits == 64 || bits == 32) + { + if (!hasRBasedRegs && bits >= 32) + { + kAppBytes.emplace_back(opcodeAMD64.fOpcode); + } + + kAppBytes.emplace_back(0x89); + } + else if (bits == 16) + { + if (hasRBasedRegs) + { + detail::print_error( + "Invalid combination of operands and registers.", "i64asm"); + throw std::runtime_error("comb_op_reg"); + } + + kAppBytes.emplace_back(0x66); + kAppBytes.emplace_back(0x89); + } + + if (currentRegList[1].fName[0] == 'r' && + currentRegList[0].fName[0] == 'e') + { + detail::print_error("Invalid combination of operands and registers.", + "i64asm"); + throw std::runtime_error("comb_op_reg"); + } + + if (currentRegList[0].fName[0] == 'r' && + currentRegList[1].fName[0] == 'e') + { + detail::print_error("Invalid combination of operands and registers.", + "i64asm"); + throw std::runtime_error("comb_op_reg"); + } + + if (bits == 16) + { + if (currentRegList[0].fName[0] == 'r' || + currentRegList[0].fName[0] == 'e') + { + detail::print_error("Invalid combination of operands and registers.", + "i64asm"); + throw std::runtime_error("comb_op_reg"); + } + + if (currentRegList[1].fName[0] == 'r' || + currentRegList[1].fName[0] == 'e') + { + detail::print_error("Invalid combination of operands and registers.", + "i64asm"); + throw std::runtime_error("comb_op_reg"); + } + } + else + { + if (currentRegList[0].fName[0] != 'r' || + currentRegList[0].fName[0] == 'e') + { + detail::print_error("Invalid combination of operands and registers.", + "i64asm"); + throw std::runtime_error("comb_op_reg"); + } + + if (currentRegList[1].fName[0] != 'r' || + currentRegList[1].fName[0] == 'e') + { + detail::print_error("Invalid combination of operands and registers.", + "i64asm"); + throw std::runtime_error("comb_op_reg"); + } + } + + /// encode register using the modrm encoding. + + auto modrm = (0x3 << 6 | currentRegList[1].fModRM << 3 | + currentRegList[0].fModRM); + + kAppBytes.emplace_back(modrm); + + break; + } + else if (name == "int" || name == "into" || name == "intd") + { + kAppBytes.emplace_back(opcodeAMD64.fOpcode); + this->WriteNumber8(line.find(name) + name.size() + 1, line); + + break; + } + else if (name == "jmp" || name == "call") + { + kAppBytes.emplace_back(opcodeAMD64.fOpcode); + + if (!this->WriteNumber32(line.find(name) + name.size() + 1, line)) + { + throw std::runtime_error("BUG: WriteNumber32"); + } + + break; + } + else + { + kAppBytes.emplace_back(opcodeAMD64.fOpcode); + + break; + } + } + } + + if (line[0] == kAssemblerPragmaSym) + { + if (foundInstruction) + { + detail::print_error("Syntax error: " + line, "i64asm"); + throw std::runtime_error("syntax_err"); + } + + if (line.find("bits 64") != std::string::npos) + { + kRegisterBitWidth = 64U; + } + else if (line.find("bits 32") != std::string::npos) + { + kRegisterBitWidth = 32U; + } + else if (line.find("bits 16") != std::string::npos) + { + kRegisterBitWidth = 16U; + } + else if (line.find("org") != std::string::npos) + { + size_t base[] = {10, 16, 2, 7}; + + for (size_t i = 0; i < 4; i++) + { + if (kOrigin = strtol( + (line.substr(line.find("org") + strlen("org") + 1)).c_str(), + nullptr, base[i]); + kOrigin) + { + if (errno != 0) + { + continue; + } + else + { + if (kVerbose) + { + kStdOut << "i64asm: origin set: " << kOrigin << std::endl; + } + + break; + } + } + } + } + } + /// write a dword + else if (line.find(".dword") != std::string::npos) + { + this->WriteNumber32(line.find(".dword") + strlen(".dword") + 1, line); + } + /// write a long + else if (line.find(".long") != std::string::npos) + { + this->WriteNumber(line.find(".long") + strlen(".long") + 1, line); + } + /// write a 16-bit number + else if (line.find(".word") != std::string::npos) + { + this->WriteNumber16(line.find(".word") + strlen(".word") + 1, line); + } + + kOrigin += cAMD64IPAlignment; + + return true; +} + +// Last rev 13-1-24 diff --git a/Sources/link.cc b/Sources/link.cc deleted file mode 100644 index d94cbf1..0000000 --- a/Sources/link.cc +++ /dev/null @@ -1,738 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -/// @file link.cc -/// @author Amlal EL Mahrouss (amlel) -/// @brief ZKA Technologies Linker. - -/// Last Rev: Sat Feb 24 CET 2024 - -/// @note Do not look up for anything with .code64/.data64/.zero64! -/// It will be loaded when program will start up! - -#include - -//! Assembler Kit -#include - -//! Preferred Executable Format -#include -#include -#include -#include -#include - -//! Dist version -#include - -//! Advanced Executable Object Format -#include - -//! C++ I/O headers. -#include -#include - -#define kLinkerVersion "Zeta Linker Driver %s, (c) ZKA Technologies 2024, all rights reserved.\n" - -#define StringCompare(DST, SRC) strcmp(DST, SRC) - -#define kPefNoCpu 0U -#define kPefNoSubCpu 0U - -#define kWhite "\e[0;97m" -#define kStdOut (std::cout << kWhite) - -#define kLinkerDefaultOrigin kPefBaseOrigin -#define kLinkerId 0x5046FF -#define kLinkerAbiContainer "Container:Abi:" - -enum -{ - kStandardAbi = 0x5046 /* PF */ -}; - -static std::string kOutput; -static Int32 kAbi = kStandardAbi; -static Int32 kSubArch = kPefNoSubCpu; -static Int32 kArch = CompilerKit::kPefArch64000; -static Bool kFatBinaryEnable = false; -static Bool kStartFound = false; -static Bool kDuplicateSymbols = false; -static Bool kVerbose = false; - -/* link is to be found, mld is to be found at runtime. */ -static const char* kLdDefineSymbol = ":UndefinedSymbol:"; -static const char* kLdDynamicSym = ":RuntimeSymbol:"; - -/* object code and list. */ -static std::vector kObjectList; -static std::vector kObjectBytes; - -#define kPrintF printf -#define kLinkerSplash() kPrintF(kWhite kLinkerVersion, kDistVersion) - -NDK_MODULE(NewOSLinker) -{ - bool is_executable = true; - - /** - * @brief parse flags and such. - * - */ - for (size_t i = 1; i < argc; ++i) - { - if (StringCompare(argv[i], "/help") == 0) - { - kLinkerSplash(); - kStdOut << "/version: Show linker version.\n"; - kStdOut << "/help: Show linker help.\n"; - kStdOut << "/verbose: Enable linker trace.\n"; - kStdOut << "/shared: Output as a shared PEF.\n"; - kStdOut << "/fat-bin: Output as a FAT PEF.\n"; - kStdOut << "/32x0: Output as a 32x0 PEF.\n"; - kStdOut << "/64x0: 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-file: Select the output file name.\n"; - - return 0; - } - else if (StringCompare(argv[i], "/version") == 0) - { - kLinkerSplash(); - return 0; - } - else if (StringCompare(argv[i], "/fat-bin") == 0) - { - kFatBinaryEnable = true; - - continue; - } - else if (StringCompare(argv[i], "/64x0") == 0) - { - kArch = CompilerKit::kPefArch64000; - - continue; - } - else if (StringCompare(argv[i], "/amd64") == 0) - { - kArch = CompilerKit::kPefArchAMD64; - - continue; - } - else if (StringCompare(argv[i], "/32x0") == 0) - { - kArch = CompilerKit::kPefArch32000; - - continue; - } - else if (StringCompare(argv[i], "/power64") == 0) - { - kArch = CompilerKit::kPefArchPowerPC; - - continue; - } - else if (StringCompare(argv[i], "/arm64") == 0) - { - kArch = CompilerKit::kPefArchARM64; - - continue; - } - else if (StringCompare(argv[i], "/verbose") == 0) - { - kVerbose = true; - - continue; - } - else if (StringCompare(argv[i], "/shared") == 0) - { - if (kOutput.empty()) - { - continue; - } - - if (kOutput.find(kPefExt) != std::string::npos) - kOutput.erase(kOutput.find(kPefExt), strlen(kPefExt)); - - kOutput += kPefDylibExt; - - is_executable = false; - - continue; - } - else if (StringCompare(argv[i], "/output-file") == 0) - { - kOutput = argv[i + 1]; - ++i; - - continue; - } - else - { - if (argv[i][0] == '/') - { - kStdOut << "link: unknown flag: " << argv[i] << "\n"; - return MPCC_EXEC_ERROR; - } - - kObjectList.emplace_back(argv[i]); - - continue; - } - } - - if (kOutput.empty()) - { - kStdOut << "link: no output filename set." << std::endl; - return MPCC_EXEC_ERROR; - } - - // sanity check. - if (kObjectList.empty()) - { - kStdOut << "link: no input files." << std::endl; - return MPCC_EXEC_ERROR; - } - else - { - namespace fs = std::filesystem; - - // check for existing files, if they don't throw an error. - for (auto& obj : kObjectList) - { - if (!fs::exists(obj)) - { - // if filesystem doesn't find file - // -> throw error. - kStdOut << "link: no such file: " << obj << std::endl; - return MPCC_EXEC_ERROR; - } - } - } - - // PEF expects a valid architecture when outputing a binary. - if (kArch == 0) - { - kStdOut << "link: no target architecture set, can't continue." << std::endl; - return MPCC_EXEC_ERROR; - } - - CompilerKit::PEFContainer pef_container{}; - - int32_t archs = kArch; - - pef_container.Count = 0UL; - pef_container.Kind = CompilerKit::kPefKindExec; - pef_container.SubCpu = kSubArch; - pef_container.Linker = kLinkerId; // ZKA Technologies Linker - pef_container.Abi = kAbi; // Multi-Processor UX ABI - pef_container.Magic[0] = kPefMagic[kFatBinaryEnable ? 2 : 0]; - pef_container.Magic[1] = kPefMagic[1]; - pef_container.Magic[2] = kPefMagic[kFatBinaryEnable ? 0 : 2]; - pef_container.Magic[3] = kPefMagic[3]; - pef_container.Version = kPefVersion; - - // specify the start address, can be 0x10000 - pef_container.Start = kLinkerDefaultOrigin; - pef_container.HdrSz = sizeof(CompilerKit::PEFContainer); - - std::ofstream outputFc(kOutput, std::ofstream::binary); - - if (outputFc.bad()) - { - if (kVerbose) - { - kStdOut << "link: error: " << strerror(errno) << "\n"; - } - - return MPCC_FILE_NOT_FOUND; - } - - //! Read AE to convert as PEF. - - std::vector commandHdrsList; - CompilerKit::Utils::AEReadableProtocol readProto{}; - - for (const auto& i : kObjectList) - { - if (!std::filesystem::exists(i)) - continue; - - CompilerKit::AEHeader hdr{}; - - readProto.FP = std::ifstream(i, std::ifstream::binary); - readProto.FP >> hdr; - - auto ae_header = hdr; - - if (ae_header.fMagic[0] == kAEMag0 && ae_header.fMagic[1] == kAEMag1 && - ae_header.fSize == sizeof(CompilerKit::AEHeader)) - { - if (ae_header.fArch != kArch) - { - if (kVerbose) - kStdOut << "link: info: is this a FAT binary? : "; - - if (!kFatBinaryEnable) - { - if (kVerbose) - kStdOut << "No.\n"; - - kStdOut << "link: error: object " << i - << " is a different kind of architecture and output isn't " - "treated as a FAT binary." - << std::endl; - - std::remove(kOutput.c_str()); - return MPCC_FAT_ERROR; - } - else - { - if (kVerbose) - { - kStdOut << "Yes.\n"; - } - } - } - - // append arch type to archs varaible. - archs |= ae_header.fArch; - std::size_t cnt = ae_header.fCount; - - if (kVerbose) - kStdOut << "link: object header found, record count: " << cnt << "\n"; - - pef_container.Count = cnt; - - char_type* raw_ae_records = - new char_type[cnt * sizeof(CompilerKit::AERecordHeader)]; - memset(raw_ae_records, 0, cnt * sizeof(CompilerKit::AERecordHeader)); - - auto* ae_records = readProto.Read(raw_ae_records, cnt); - for (size_t ae_record_index = 0; ae_record_index < cnt; - ++ae_record_index) - { - CompilerKit::PEFCommandHeader command_header{0}; - size_t offsetOfData = ae_records[ae_record_index].fOffset + ae_header.fSize; - - memcpy(command_header.Name, ae_records[ae_record_index].fName, - kPefNameLen); - - // check this header if it's any valid. - if (std::string(command_header.Name).find(".code64") == - std::string::npos && - std::string(command_header.Name).find(".data64") == - std::string::npos && - std::string(command_header.Name).find(".zero64") == - std::string::npos) - { - if (std::string(command_header.Name).find(kPefStart) == - std::string::npos && - *command_header.Name == 0) - { - if (std::string(command_header.Name).find(kLdDefineSymbol) != - std::string::npos) - { - goto ld_mark_header; - } - else - { - continue; - } - } - } - - if (std::string(command_header.Name).find(kPefStart) != - std::string::npos && - std::string(command_header.Name).find(".code64") != - std::string::npos) - { - kStartFound = true; - } - - ld_mark_header: - command_header.Offset = offsetOfData; - command_header.Kind = ae_records[ae_record_index].fKind; - command_header.Size = ae_records[ae_record_index].fSize; - command_header.Cpu = ae_header.fArch; - command_header.SubCpu = ae_header.fSubArch; - - if (kVerbose) - { - kStdOut << "link: object record: " - << ae_records[ae_record_index].fName << " was marked.\n"; - - kStdOut << "link: object record offset: " << command_header.Offset << "\n"; - } - - commandHdrsList.emplace_back(command_header); - } - - delete[] raw_ae_records; - - std::vector bytes; - bytes.resize(ae_header.fCodeSize); - - readProto.FP.seekg(std::streamsize(ae_header.fStartCode)); - readProto.FP.read(bytes.data(), std::streamsize(ae_header.fCodeSize)); - - for (auto& byte : bytes) - { - kObjectBytes.push_back(byte); - } - - readProto.FP.close(); - - continue; - } - - kStdOut << "link: not an object: " << i << std::endl; - std::remove(kOutput.c_str()); - - // don't continue, it is a fatal error. - return MPCC_EXEC_ERROR; - } - - pef_container.Cpu = archs; - - outputFc << pef_container; - - if (kVerbose) - { - kStdOut << "link: wrote container header.\n"; - } - - outputFc.seekp(std::streamsize(pef_container.HdrSz)); - - std::vector not_found; - std::vector symbols; - - // step 2: check for errors (multiple symbols, undefined ones) - - for (auto& commandHdr : commandHdrsList) - { - // check if this symbol needs to be resolved. - if (std::string(commandHdr.Name).find(kLdDefineSymbol) != - std::string::npos && - std::string(commandHdr.Name).find(kLdDynamicSym) == std::string::npos) - { - if (kVerbose) - kStdOut << "link: found undefined symbol: " << commandHdr.Name << "\n"; - - if (auto it = std::find(not_found.begin(), not_found.end(), - std::string(commandHdr.Name)); - it == not_found.end()) - { - not_found.emplace_back(commandHdr.Name); - } - } - - symbols.emplace_back(commandHdr.Name); - } - - // Now try to solve these symbols. - - for (size_t not_found_idx = 0; not_found_idx < commandHdrsList.size(); - ++not_found_idx) - { - if (auto it = std::find(not_found.begin(), not_found.end(), - std::string(commandHdrsList[not_found_idx].Name)); - it != not_found.end()) - { - std::string symbol_imp = *it; - - if (symbol_imp.find(kLdDefineSymbol) == std::string::npos) - continue; - - // erase the lookup prefix. - symbol_imp.erase( - 0, symbol_imp.find(kLdDefineSymbol) + strlen(kLdDefineSymbol)); - - // demangle everything. - while (symbol_imp.find('$') != std::string::npos) - symbol_imp.erase(symbol_imp.find('$'), 1); - - // the reason we do is because, this may not match the symbol, and we need - // to look for other matching symbols. - for (auto& commandHdr : commandHdrsList) - { - if (std::string(commandHdr.Name).find(symbol_imp) != - std::string::npos && - std::string(commandHdr.Name).find(kLdDefineSymbol) == - std::string::npos) - { - std::string undefined_symbol = commandHdr.Name; - auto result_of_sym = - undefined_symbol.substr(undefined_symbol.find(symbol_imp)); - - for (int i = 0; result_of_sym[i] != 0; ++i) - { - if (result_of_sym[i] != symbol_imp[i]) - goto ld_continue_search; - } - - not_found.erase(it); - - if (kVerbose) - kStdOut << "link: found symbol: " << commandHdr.Name << "\n"; - - break; - } - } - - ld_continue_search: - continue; - } - } - - // step 3: check for errors (recheck if we have those symbols.) - - if (!kStartFound && is_executable) - { - if (kVerbose) - kStdOut - << "link: undefined entrypoint: " << kPefStart << ", you may have forget to link " - "against your compiler's runtime library.\n"; - - kStdOut << "link: undefined entrypoint " << kPefStart - << " for executable: " << kOutput << "\n"; - } - - // step 4: write all PEF commands. - - CompilerKit::PEFCommandHeader dateHeader{}; - - time_t timestamp = time(nullptr); - - std::string timeStampStr = "Container:BuildEpoch:"; - timeStampStr += std::to_string(timestamp); - - strcpy(dateHeader.Name, timeStampStr.c_str()); - - dateHeader.Flags = 0; - dateHeader.Kind = CompilerKit::kPefZero; - dateHeader.Offset = outputFc.tellp(); - dateHeader.Size = timeStampStr.size(); - - commandHdrsList.push_back(dateHeader); - - CompilerKit::PEFCommandHeader abiHeader{}; - - std::string abi = kLinkerAbiContainer; - - switch (kArch) - { - case CompilerKit::kPefArchAMD64: { - abi += "MSFT"; - break; - } - case CompilerKit::kPefArchPowerPC: { - abi += "SYSV"; - break; - } - case CompilerKit::kPefArch32000: - case CompilerKit::kPefArch64000: { - abi += "MHRA"; - break; - } - default: { - abi += " IDK"; - break; - } - } - - memcpy(abiHeader.Name, abi.c_str(), abi.size()); - - abiHeader.Size = abi.size(); - abiHeader.Offset = outputFc.tellp(); - abiHeader.Flags = 0; - abiHeader.Kind = CompilerKit::kPefLinkerID; - - commandHdrsList.push_back(abiHeader); - - CompilerKit::PEFCommandHeader uuidHeader{}; - - std::random_device rd; - - auto seedData = std::array{}; - std::generate(std::begin(seedData), std::end(seedData), std::ref(rd)); - std::seed_seq seq(std::begin(seedData), std::end(seedData)); - std::mt19937 generator(seq); - - auto gen = uuids::uuid_random_generator{generator}; - uuids::uuid id = gen(); - auto uuidStr = uuids::to_string(id); - - memcpy(uuidHeader.Name, "Container:GUID:4:", strlen("Container:GUID:4:")); - memcpy(uuidHeader.Name + strlen("Container:GUID:4:"), uuidStr.c_str(), - uuidStr.size()); - - uuidHeader.Size = 16; - uuidHeader.Offset = outputFc.tellp(); - uuidHeader.Flags = 0; - uuidHeader.Kind = CompilerKit::kPefZero; - - commandHdrsList.push_back(uuidHeader); - - // prepare a symbol vector. - std::vector undefSymbols; - std::vector duplSymbols; - std::vector resolveSymbols; - - constexpr Int32 cPaddingOffset = 16; - - size_t previousOffset = (commandHdrsList.size() * sizeof(CompilerKit::PEFCommandHeader)) + cPaddingOffset; - - // Finally write down the command headers. - // And check for any duplications - for (size_t commandHeaderIndex = 0UL; - commandHeaderIndex < commandHdrsList.size(); ++commandHeaderIndex) - { - if (std::string(commandHdrsList[commandHeaderIndex].Name) - .find(kLdDefineSymbol) != std::string::npos && - std::string(commandHdrsList[commandHeaderIndex].Name) - .find(kLdDynamicSym) == std::string::npos) - { - // ignore :UndefinedSymbol: headers, they do not contain code. - continue; - } - - std::string symbolName = commandHdrsList[commandHeaderIndex].Name; - - if (!symbolName.empty()) - { - undefSymbols.emplace_back(symbolName); - } - - commandHdrsList[commandHeaderIndex].Offset += previousOffset; - previousOffset += commandHdrsList[commandHeaderIndex].Size; - - std::string name = commandHdrsList[commandHeaderIndex].Name; - - /// so this is valid when we get to the entrypoint. - /// it is always a code64 container. And should equal to kPefStart as well. - /// this chunk of code updates the pef_container.Start with the updated offset. - if (name.find(kPefStart) != std::string::npos && - name.find(".code64") != std::string::npos) - { - pef_container.Start = commandHdrsList[commandHeaderIndex].Offset; - auto tellCurPos = outputFc.tellp(); - - outputFc.seekp(0); - outputFc << pef_container; - - outputFc.seekp(tellCurPos); - } - - if (kVerbose) - { - kStdOut << "link: command header name: " << name << "\n"; - kStdOut << "link: real address of command header content: " << commandHdrsList[commandHeaderIndex].Offset << "\n"; - } - - outputFc << commandHdrsList[commandHeaderIndex]; - - for (size_t subCommandHeaderIndex = 0UL; - subCommandHeaderIndex < commandHdrsList.size(); - ++subCommandHeaderIndex) - { - if (subCommandHeaderIndex == commandHeaderIndex) - continue; - - if (std::string(commandHdrsList[subCommandHeaderIndex].Name) - .find(kLdDefineSymbol) != std::string::npos && - std::string(commandHdrsList[subCommandHeaderIndex].Name) - .find(kLdDynamicSym) == std::string::npos) - { - if (kVerbose) - { - kStdOut << "link: ignore :UndefinedSymbol: command header...\n"; - } - - // ignore :UndefinedSymbol: headers, they do not contain code. - continue; - } - - auto& commandHdr = commandHdrsList[subCommandHeaderIndex]; - - if (commandHdr.Name == - std::string(commandHdrsList[commandHeaderIndex].Name)) - { - if (std::find(duplSymbols.cbegin(), duplSymbols.cend(), - commandHdr.Name) == duplSymbols.cend()) - { - duplSymbols.emplace_back(commandHdr.Name); - } - - if (kVerbose) - kStdOut << "link: found duplicate symbol: " << commandHdr.Name - << "\n"; - - kDuplicateSymbols = true; - } - } - } - - if (!duplSymbols.empty()) - { - for (auto& symbol : duplSymbols) - { - kStdOut << "link: multiple symbols of " << symbol << ".\n"; - } - - std::remove(kOutput.c_str()); - return MPCC_EXEC_ERROR; - } - - // step 2.5: write program bytes. - - for (auto byte : kObjectBytes) - { - outputFc << byte; - } - - if (kVerbose) - kStdOut << "link: wrote contents of: " << kOutput << "\n"; - - // step 3: check if we have those symbols - - std::vector unrefSyms; - - for (auto& commandHdr : commandHdrsList) - { - if (auto it = std::find(not_found.begin(), not_found.end(), - std::string(commandHdr.Name)); - it != not_found.end()) - { - unrefSyms.emplace_back(commandHdr.Name); - } - } - - if (!unrefSyms.empty()) - { - for (auto& unreferenced_symbol : unrefSyms) - { - kStdOut << "link: undefined symbol " << unreferenced_symbol << "\n"; - } - } - - if (!kStartFound || kDuplicateSymbols && std::filesystem::exists(kOutput) || - !unrefSyms.empty()) - { - if (kVerbose) - kStdOut << "link: file: " << kOutput - << ", is corrupt, removing file...\n"; - - std::remove(kOutput.c_str()); - return MPCC_EXEC_ERROR; - } - - return 0; -} - -// Last rev 13-1-24 diff --git a/Sources/link.cxx b/Sources/link.cxx new file mode 100644 index 0000000..e671d84 --- /dev/null +++ b/Sources/link.cxx @@ -0,0 +1,741 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +/// @file link.cxx +/// @author Amlal EL Mahrouss (amlel) +/// @brief ZKA Technologies Linker. + +/// Last Rev: Sat Feb 24 CET 2024 + +/// @note Do not look up for anything with .code64/.data64/.zero64! +/// It will be loaded when program will start up! + +#include + +//! Assembler Kit +#include + +//! Preferred Executable Format +#include +#include +#include +#include +#include + +//! Dist version +#include + +//! Advanced Executable Object Format +#include + +//! C++ I/O headers. +#include +#include + +#define kLinkerVersion "Zeta Linker Driver %s, (c) ZKA Technologies 2024, all rights reserved.\n" + +#define StringCompare(DST, SRC) strcmp(DST, SRC) + +#define kPefNoCpu 0U +#define kPefNoSubCpu 0U + +#define kWhite "\e[0;97m" +#define kStdOut (std::cout << kWhite) + +#define kLinkerDefaultOrigin kPefBaseOrigin +#define kLinkerId 0x5046FF +#define kLinkerAbiContainer "Container:Abi:" + +enum +{ + eABIStart = 0x1010, /* Invalid ABI start of ABI list. */ + eABINewOSKrnl = 0x5046, /* PF (NewOSKrnl) */ + eABIMTL = 0x4650, /* FP (MTL firmware) */ + eABIInvalid = 1, +}; + +static std::string kOutput; +static Int32 kAbi = eABINewOSKrnl; +static Int32 kSubArch = kPefNoSubCpu; +static Int32 kArch = CompilerKit::kPefArchInvalid; +static Bool kFatBinaryEnable = false; +static Bool kStartFound = false; +static Bool kDuplicateSymbols = false; +static Bool kVerbose = false; + +/* link is to be found, mld is to be found at runtime. */ +static const char* kLdDefineSymbol = ":UndefinedSymbol:"; +static const char* kLdDynamicSym = ":RuntimeSymbol:"; + +/* object code and list. */ +static std::vector kObjectList; +static std::vector kObjectBytes; + +#define kPrintF printf +#define kLinkerSplash() kPrintF(kWhite kLinkerVersion, kDistVersion) + +NDK_MODULE(NewOSLinker) +{ + bool is_executable = true; + + /** + * @brief parse flags and such. + * + */ + for (size_t i = 1; i < argc; ++i) + { + if (StringCompare(argv[i], "/help") == 0) + { + kLinkerSplash(); + kStdOut << "/version: Show linker version.\n"; + kStdOut << "/help: Show linker help.\n"; + kStdOut << "/verbose: Enable linker trace.\n"; + kStdOut << "/shared: Output as a shared PEF.\n"; + kStdOut << "/fat-bin: Output as a FAT PEF.\n"; + kStdOut << "/32x0: Output as a 32x0 PEF.\n"; + kStdOut << "/64x0: 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-file: Select the output file name.\n"; + + return 0; + } + else if (StringCompare(argv[i], "/version") == 0) + { + kLinkerSplash(); + return 0; + } + else if (StringCompare(argv[i], "/fat-bin") == 0) + { + kFatBinaryEnable = true; + + continue; + } + else if (StringCompare(argv[i], "/64x0") == 0) + { + kArch = CompilerKit::kPefArch64000; + + continue; + } + else if (StringCompare(argv[i], "/amd64") == 0) + { + kArch = CompilerKit::kPefArchAMD64; + + continue; + } + else if (StringCompare(argv[i], "/32x0") == 0) + { + kArch = CompilerKit::kPefArch32000; + + continue; + } + else if (StringCompare(argv[i], "/power64") == 0) + { + kArch = CompilerKit::kPefArchPowerPC; + + continue; + } + else if (StringCompare(argv[i], "/arm64") == 0) + { + kArch = CompilerKit::kPefArchARM64; + + continue; + } + else if (StringCompare(argv[i], "/verbose") == 0) + { + kVerbose = true; + + continue; + } + else if (StringCompare(argv[i], "/shared") == 0) + { + if (kOutput.empty()) + { + continue; + } + + if (kOutput.find(kPefExt) != std::string::npos) + kOutput.erase(kOutput.find(kPefExt), strlen(kPefExt)); + + kOutput += kPefDylibExt; + + is_executable = false; + + continue; + } + else if (StringCompare(argv[i], "/output-file") == 0) + { + kOutput = argv[i + 1]; + ++i; + + continue; + } + else + { + if (argv[i][0] == '/') + { + kStdOut << "link: unknown flag: " << argv[i] << "\n"; + return MPCC_EXEC_ERROR; + } + + kObjectList.emplace_back(argv[i]); + + continue; + } + } + + if (kOutput.empty()) + { + kStdOut << "link: no output filename set." << std::endl; + return MPCC_EXEC_ERROR; + } + + // sanity check. + if (kObjectList.empty()) + { + kStdOut << "link: no input files." << std::endl; + return MPCC_EXEC_ERROR; + } + else + { + namespace fs = std::filesystem; + + // check for existing files, if they don't throw an error. + for (auto& obj : kObjectList) + { + if (!fs::exists(obj)) + { + // if filesystem doesn't find file + // -> throw error. + kStdOut << "link: no such file: " << obj << std::endl; + return MPCC_EXEC_ERROR; + } + } + } + + // PEF expects a valid architecture when outputing a binary. + if (kArch == 0) + { + kStdOut << "link: no target architecture set, can't continue." << std::endl; + return MPCC_EXEC_ERROR; + } + + CompilerKit::PEFContainer pef_container{}; + + int32_t archs = kArch; + + pef_container.Count = 0UL; + pef_container.Kind = CompilerKit::kPefKindExec; + pef_container.SubCpu = kSubArch; + pef_container.Linker = kLinkerId; // ZKA Technologies Linker + pef_container.Abi = kAbi; // Multi-Processor UX ABI + pef_container.Magic[0] = kPefMagic[kFatBinaryEnable ? 2 : 0]; + pef_container.Magic[1] = kPefMagic[1]; + pef_container.Magic[2] = kPefMagic[kFatBinaryEnable ? 0 : 2]; + pef_container.Magic[3] = kPefMagic[3]; + pef_container.Version = kPefVersion; + + // specify the start address, can be 0x10000 + pef_container.Start = kLinkerDefaultOrigin; + pef_container.HdrSz = sizeof(CompilerKit::PEFContainer); + + std::ofstream outputFc(kOutput, std::ofstream::binary); + + if (outputFc.bad()) + { + if (kVerbose) + { + kStdOut << "link: error: " << strerror(errno) << "\n"; + } + + return MPCC_FILE_NOT_FOUND; + } + + //! Read AE to convert as PEF. + + std::vector commandHdrsList; + CompilerKit::Utils::AEReadableProtocol readProto{}; + + for (const auto& i : kObjectList) + { + if (!std::filesystem::exists(i)) + continue; + + CompilerKit::AEHeader hdr{}; + + readProto.FP = std::ifstream(i, std::ifstream::binary); + readProto.FP >> hdr; + + auto ae_header = hdr; + + if (ae_header.fMagic[0] == kAEMag0 && ae_header.fMagic[1] == kAEMag1 && + ae_header.fSize == sizeof(CompilerKit::AEHeader)) + { + if (ae_header.fArch != kArch) + { + if (kVerbose) + kStdOut << "link: info: is this a FAT binary? : "; + + if (!kFatBinaryEnable) + { + if (kVerbose) + kStdOut << "No.\n"; + + kStdOut << "link: error: object " << i + << " is a different kind of architecture and output isn't " + "treated as a FAT binary." + << std::endl; + + std::remove(kOutput.c_str()); + return MPCC_FAT_ERROR; + } + else + { + if (kVerbose) + { + kStdOut << "Yes.\n"; + } + } + } + + // append arch type to archs varaible. + archs |= ae_header.fArch; + std::size_t cnt = ae_header.fCount; + + if (kVerbose) + kStdOut << "link: object header found, record count: " << cnt << "\n"; + + pef_container.Count = cnt; + + char_type* raw_ae_records = + new char_type[cnt * sizeof(CompilerKit::AERecordHeader)]; + memset(raw_ae_records, 0, cnt * sizeof(CompilerKit::AERecordHeader)); + + auto* ae_records = readProto.Read(raw_ae_records, cnt); + for (size_t ae_record_index = 0; ae_record_index < cnt; + ++ae_record_index) + { + CompilerKit::PEFCommandHeader command_header{0}; + size_t offsetOfData = ae_records[ae_record_index].fOffset + ae_header.fSize; + + memcpy(command_header.Name, ae_records[ae_record_index].fName, + kPefNameLen); + + // check this header if it's any valid. + if (std::string(command_header.Name).find(".code64") == + std::string::npos && + std::string(command_header.Name).find(".data64") == + std::string::npos && + std::string(command_header.Name).find(".zero64") == + std::string::npos) + { + if (std::string(command_header.Name).find(kPefStart) == + std::string::npos && + *command_header.Name == 0) + { + if (std::string(command_header.Name).find(kLdDefineSymbol) != + std::string::npos) + { + goto ld_mark_header; + } + else + { + continue; + } + } + } + + if (std::string(command_header.Name).find(kPefStart) != + std::string::npos && + std::string(command_header.Name).find(".code64") != + std::string::npos) + { + kStartFound = true; + } + + ld_mark_header: + command_header.Offset = offsetOfData; + command_header.Kind = ae_records[ae_record_index].fKind; + command_header.Size = ae_records[ae_record_index].fSize; + command_header.Cpu = ae_header.fArch; + command_header.SubCpu = ae_header.fSubArch; + + if (kVerbose) + { + kStdOut << "link: object record: " + << ae_records[ae_record_index].fName << " was marked.\n"; + + kStdOut << "link: object record offset: " << command_header.Offset << "\n"; + } + + commandHdrsList.emplace_back(command_header); + } + + delete[] raw_ae_records; + + std::vector bytes; + bytes.resize(ae_header.fCodeSize); + + readProto.FP.seekg(std::streamsize(ae_header.fStartCode)); + readProto.FP.read(bytes.data(), std::streamsize(ae_header.fCodeSize)); + + for (auto& byte : bytes) + { + kObjectBytes.push_back(byte); + } + + readProto.FP.close(); + + continue; + } + + kStdOut << "link: not an object: " << i << std::endl; + std::remove(kOutput.c_str()); + + // don't continue, it is a fatal error. + return MPCC_EXEC_ERROR; + } + + pef_container.Cpu = archs; + + outputFc << pef_container; + + if (kVerbose) + { + kStdOut << "link: wrote container header.\n"; + } + + outputFc.seekp(std::streamsize(pef_container.HdrSz)); + + std::vector not_found; + std::vector symbols; + + // step 2: check for errors (multiple symbols, undefined ones) + + for (auto& commandHdr : commandHdrsList) + { + // check if this symbol needs to be resolved. + if (std::string(commandHdr.Name).find(kLdDefineSymbol) != + std::string::npos && + std::string(commandHdr.Name).find(kLdDynamicSym) == std::string::npos) + { + if (kVerbose) + kStdOut << "link: found undefined symbol: " << commandHdr.Name << "\n"; + + if (auto it = std::find(not_found.begin(), not_found.end(), + std::string(commandHdr.Name)); + it == not_found.end()) + { + not_found.emplace_back(commandHdr.Name); + } + } + + symbols.emplace_back(commandHdr.Name); + } + + // Now try to solve these symbols. + + for (size_t not_found_idx = 0; not_found_idx < commandHdrsList.size(); + ++not_found_idx) + { + if (auto it = std::find(not_found.begin(), not_found.end(), + std::string(commandHdrsList[not_found_idx].Name)); + it != not_found.end()) + { + std::string symbol_imp = *it; + + if (symbol_imp.find(kLdDefineSymbol) == std::string::npos) + continue; + + // erase the lookup prefix. + symbol_imp.erase( + 0, symbol_imp.find(kLdDefineSymbol) + strlen(kLdDefineSymbol)); + + // demangle everything. + while (symbol_imp.find('$') != std::string::npos) + symbol_imp.erase(symbol_imp.find('$'), 1); + + // the reason we do is because, this may not match the symbol, and we need + // to look for other matching symbols. + for (auto& commandHdr : commandHdrsList) + { + if (std::string(commandHdr.Name).find(symbol_imp) != + std::string::npos && + std::string(commandHdr.Name).find(kLdDefineSymbol) == + std::string::npos) + { + std::string undefined_symbol = commandHdr.Name; + auto result_of_sym = + undefined_symbol.substr(undefined_symbol.find(symbol_imp)); + + for (int i = 0; result_of_sym[i] != 0; ++i) + { + if (result_of_sym[i] != symbol_imp[i]) + goto ld_continue_search; + } + + not_found.erase(it); + + if (kVerbose) + kStdOut << "link: found symbol: " << commandHdr.Name << "\n"; + + break; + } + } + + ld_continue_search: + continue; + } + } + + // step 3: check for errors (recheck if we have those symbols.) + + if (!kStartFound && is_executable) + { + if (kVerbose) + kStdOut + << "link: undefined entrypoint: " << kPefStart << ", you may have forget to link " + "against your compiler's runtime library.\n"; + + kStdOut << "link: undefined entrypoint " << kPefStart + << " for executable: " << kOutput << "\n"; + } + + // step 4: write all PEF commands. + + CompilerKit::PEFCommandHeader dateHeader{}; + + time_t timestamp = time(nullptr); + + std::string timeStampStr = "Container:BuildEpoch:"; + timeStampStr += std::to_string(timestamp); + + strcpy(dateHeader.Name, timeStampStr.c_str()); + + dateHeader.Flags = 0; + dateHeader.Kind = CompilerKit::kPefZero; + dateHeader.Offset = outputFc.tellp(); + dateHeader.Size = timeStampStr.size(); + + commandHdrsList.push_back(dateHeader); + + CompilerKit::PEFCommandHeader abiHeader{}; + + std::string abi = kLinkerAbiContainer; + + switch (kArch) + { + case CompilerKit::kPefArchAMD64: { + abi += "MSFT"; + break; + } + case CompilerKit::kPefArchPowerPC: { + abi += "SYSV"; + break; + } + case CompilerKit::kPefArch32000: + case CompilerKit::kPefArch64000: { + abi += "MHRA"; + break; + } + default: { + abi += " IDK"; + break; + } + } + + memcpy(abiHeader.Name, abi.c_str(), abi.size()); + + abiHeader.Size = abi.size(); + abiHeader.Offset = outputFc.tellp(); + abiHeader.Flags = 0; + abiHeader.Kind = CompilerKit::kPefLinkerID; + + commandHdrsList.push_back(abiHeader); + + CompilerKit::PEFCommandHeader uuidHeader{}; + + std::random_device rd; + + auto seedData = std::array{}; + std::generate(std::begin(seedData), std::end(seedData), std::ref(rd)); + std::seed_seq seq(std::begin(seedData), std::end(seedData)); + std::mt19937 generator(seq); + + auto gen = uuids::uuid_random_generator{generator}; + uuids::uuid id = gen(); + auto uuidStr = uuids::to_string(id); + + memcpy(uuidHeader.Name, "Container:GUID:4:", strlen("Container:GUID:4:")); + memcpy(uuidHeader.Name + strlen("Container:GUID:4:"), uuidStr.c_str(), + uuidStr.size()); + + uuidHeader.Size = 16; + uuidHeader.Offset = outputFc.tellp(); + uuidHeader.Flags = 0; + uuidHeader.Kind = CompilerKit::kPefZero; + + commandHdrsList.push_back(uuidHeader); + + // prepare a symbol vector. + std::vector undefSymbols; + std::vector duplSymbols; + std::vector resolveSymbols; + + constexpr Int32 cPaddingOffset = 16; + + size_t previousOffset = (commandHdrsList.size() * sizeof(CompilerKit::PEFCommandHeader)) + cPaddingOffset; + + // Finally write down the command headers. + // And check for any duplications + for (size_t commandHeaderIndex = 0UL; + commandHeaderIndex < commandHdrsList.size(); ++commandHeaderIndex) + { + if (std::string(commandHdrsList[commandHeaderIndex].Name) + .find(kLdDefineSymbol) != std::string::npos && + std::string(commandHdrsList[commandHeaderIndex].Name) + .find(kLdDynamicSym) == std::string::npos) + { + // ignore :UndefinedSymbol: headers, they do not contain code. + continue; + } + + std::string symbolName = commandHdrsList[commandHeaderIndex].Name; + + if (!symbolName.empty()) + { + undefSymbols.emplace_back(symbolName); + } + + commandHdrsList[commandHeaderIndex].Offset += previousOffset; + previousOffset += commandHdrsList[commandHeaderIndex].Size; + + std::string name = commandHdrsList[commandHeaderIndex].Name; + + /// so this is valid when we get to the entrypoint. + /// it is always a code64 container. And should equal to kPefStart as well. + /// this chunk of code updates the pef_container.Start with the updated offset. + if (name.find(kPefStart) != std::string::npos && + name.find(".code64") != std::string::npos) + { + pef_container.Start = commandHdrsList[commandHeaderIndex].Offset; + auto tellCurPos = outputFc.tellp(); + + outputFc.seekp(0); + outputFc << pef_container; + + outputFc.seekp(tellCurPos); + } + + if (kVerbose) + { + kStdOut << "link: command header name: " << name << "\n"; + kStdOut << "link: real address of command header content: " << commandHdrsList[commandHeaderIndex].Offset << "\n"; + } + + outputFc << commandHdrsList[commandHeaderIndex]; + + for (size_t subCommandHeaderIndex = 0UL; + subCommandHeaderIndex < commandHdrsList.size(); + ++subCommandHeaderIndex) + { + if (subCommandHeaderIndex == commandHeaderIndex) + continue; + + if (std::string(commandHdrsList[subCommandHeaderIndex].Name) + .find(kLdDefineSymbol) != std::string::npos && + std::string(commandHdrsList[subCommandHeaderIndex].Name) + .find(kLdDynamicSym) == std::string::npos) + { + if (kVerbose) + { + kStdOut << "link: ignore :UndefinedSymbol: command header...\n"; + } + + // ignore :UndefinedSymbol: headers, they do not contain code. + continue; + } + + auto& commandHdr = commandHdrsList[subCommandHeaderIndex]; + + if (commandHdr.Name == + std::string(commandHdrsList[commandHeaderIndex].Name)) + { + if (std::find(duplSymbols.cbegin(), duplSymbols.cend(), + commandHdr.Name) == duplSymbols.cend()) + { + duplSymbols.emplace_back(commandHdr.Name); + } + + if (kVerbose) + kStdOut << "link: found duplicate symbol: " << commandHdr.Name + << "\n"; + + kDuplicateSymbols = true; + } + } + } + + if (!duplSymbols.empty()) + { + for (auto& symbol : duplSymbols) + { + kStdOut << "link: multiple symbols of " << symbol << ".\n"; + } + + std::remove(kOutput.c_str()); + return MPCC_EXEC_ERROR; + } + + // step 2.5: write program bytes. + + for (auto byte : kObjectBytes) + { + outputFc << byte; + } + + if (kVerbose) + kStdOut << "link: wrote contents of: " << kOutput << "\n"; + + // step 3: check if we have those symbols + + std::vector unrefSyms; + + for (auto& commandHdr : commandHdrsList) + { + if (auto it = std::find(not_found.begin(), not_found.end(), + std::string(commandHdr.Name)); + it != not_found.end()) + { + unrefSyms.emplace_back(commandHdr.Name); + } + } + + if (!unrefSyms.empty()) + { + for (auto& unreferenced_symbol : unrefSyms) + { + kStdOut << "link: undefined symbol " << unreferenced_symbol << "\n"; + } + } + + if (!kStartFound || kDuplicateSymbols && std::filesystem::exists(kOutput) || + !unrefSyms.empty()) + { + if (kVerbose) + kStdOut << "link: file: " << kOutput + << ", is corrupt, removing file...\n"; + + std::remove(kOutput.c_str()); + return MPCC_EXEC_ERROR; + } + + return 0; +} + +// Last rev 13-1-24 diff --git a/Sources/power-cc.cc b/Sources/power-cc.cc deleted file mode 100644 index 332fa53..0000000 --- a/Sources/power-cc.cc +++ /dev/null @@ -1,1645 +0,0 @@ -/* - * ======================================================== - * - * cc - * Copyright ZKA Technologies, all rights reserved. - * - * ======================================================== - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define kOk 0 - -/// @author Amlal El Mahrouss (amlel) -/// @file cc.cc -/// @brief POWER C Compiler. - -///////////////////// - -/// ANSI ESCAPE CODES - -///////////////////// - -#define kBlank "\e[0;30m" -#define kRed "\e[0;31m" -#define kWhite "\e[0;97m" - -///////////////////////////////////// - -/// INTERNAL STRUCT OF THE C COMPILER - -///////////////////////////////////// - -namespace detail -{ - // \brief name to register struct. - struct CompilerRegisterMap final - { - std::string fName; - std::string fReg; - }; - - // \brief Map for C structs - // \author amlel - struct CompilerStructMap final - { - /// 'struct::my_foo' - std::string fName; - - /// if instance: stores a valid register. - std::string fReg; - - /// offset count - std::size_t fOffsetsCnt; - - /// offset array. - std::vector> fOffsets; - }; - - struct CompilerState final - { - std::vector fSyntaxTreeList; - std::vector kStackFrame; - std::vector kStructMap; - ParserKit::SyntaxLeafList* fSyntaxTree{nullptr}; - std::unique_ptr fOutputAssembly; - std::string fLastFile; - std::string fLastError; - bool fVerbose; - }; -} // namespace detail - -static detail::CompilerState kState; -static SizeType kErrorLimit = 100; -static std::string kIfFunction = ""; -static Int32 kAcceptableErrors = 0; - -namespace detail -{ - /// @brief prints an error into stdout. - /// @param reason the reason of the error. - /// @param file where does it originate from? - void print_error(std::string reason, std::string file) noexcept - { - if (reason[0] == '\n') - reason.erase(0, 1); - - if (file.find(".pp") != std::string::npos) - file.erase(file.find(".pp"), 3); - - if (kState.fLastFile != file) - { - std::cout << kRed << "[ cc ] " << kWhite - << ((file == "cc") ? "internal compiler error " - : ("in file, " + file)) - << kBlank << std::endl; - std::cout << kRed << "[ cc ] " << kWhite << reason << kBlank << std::endl; - - kState.fLastFile = file; - } - else - { - std::cout << kRed << "[ cc ] [ " << kState.fLastFile << " ] " << kWhite - << reason << kBlank << std::endl; - } - - if (kAcceptableErrors > kErrorLimit) - std::exit(3); - - ++kAcceptableErrors; - } - - struct CompilerType final - { - std::string fName; - std::string fValue; - }; -} // namespace detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// Target architecture. -static int kMachine = 0; - -///////////////////////////////////////// - -// REGISTERS ACCORDING TO USED ASSEMBLER - -///////////////////////////////////////// - -static size_t kRegisterCnt = kAsmRegisterLimit; -static size_t kStartUsable = 2; -static size_t kUsableLimit = 15; -static size_t kRegisterCounter = kStartUsable; -static std::string kRegisterPrefix = kAsmRegisterPrefix; - -///////////////////////////////////////// - -// COMPILER PARSING UTILITIES/STATES. - -///////////////////////////////////////// - -static std::vector kFileList; -static CompilerKit::AssemblyFactory kFactory; -static bool kInStruct = false; -static bool kOnWhileLoop = false; -static bool kOnForLoop = false; -static bool kInBraces = false; -static bool kIfFound = false; -static size_t kBracesCount = 0UL; - -/* @brief C compiler backend for C */ -class CompilerBackendCLang final : public ParserKit::CompilerBackend -{ -public: - explicit CompilerBackendCLang() = default; - ~CompilerBackendCLang() override = default; - - MPCC_COPY_DEFAULT(CompilerBackendCLang); - - std::string Check(const char* text, const char* file); - bool Compile(const std::string& text, const char* file) override; - - const char* Language() override - { - return "POWER C"; - } -}; - -static CompilerBackendCLang* kCompilerBackend = nullptr; -static std::vector kCompilerVariables; -static std::vector kCompilerFunctions; -static std::vector kCompilerTypes; - -namespace detail -{ - union number_cast final { - public: - number_cast(UInt64 _Raw) - : _Raw(_Raw) - { - } - - public: - char _Num[8]; - UInt64 _Raw; - }; - - union double_cast final { - public: - double_cast(float _Raw) - : _Raw(_Raw) - { - } - - public: - char _Sign; - char _Lh[8]; - char _Rh[23]; - - float _Raw; - }; -} // namespace detail - -///////////////////////////////////////////////////////////////////////////////////////// - -// @name Compile -// @brief Generate MASM from a C assignement. - -///////////////////////////////////////////////////////////////////////////////////////// - -bool CompilerBackendCLang::Compile(const std::string& text, const char* file) -{ - std::string textBuffer = text; - - bool typeFound = false; - bool fnFound = false; - - // setup generator. - std::random_device rd; - - auto seed_data = std::array{}; - std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); - std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); - std::mt19937 generator(seq); - - // start parsing - for (size_t text_index = 0; text_index < textBuffer.size(); ++text_index) - { - auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf(); - - auto gen = uuids::uuid_random_generator{generator}; - uuids::uuid out = gen(); - - detail::number_cast time_off = (UInt64)out.as_bytes().data(); - - if (!typeFound) - { - auto substr = textBuffer.substr(text_index); - std::string match_type; - - for (size_t y = 0; y < substr.size(); ++y) - { - if (substr[y] == ' ') - { - while (match_type.find(' ') != std::string::npos) - { - match_type.erase(match_type.find(' ')); - } - - for (auto& clType : kCompilerTypes) - { - if (clType.fName == match_type) - { - match_type.clear(); - - std::string buf; - - buf += clType.fValue; - buf += ' '; - - if (substr.find('=') != std::string::npos) - { - break; - } - - if (textBuffer.find('(') != std::string::npos) - { - syntaxLeaf.fUserValue = buf; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - typeFound = true; - break; - } - } - - break; - } - - match_type += substr[y]; - } - } - - if (textBuffer[text_index] == '{') - { - if (kInStruct) - { - continue; - } - - kInBraces = true; - ++kBracesCount; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - // return keyword handler - if (textBuffer[text_index] == 'r') - { - std::string return_keyword; - return_keyword += "return"; - - std::size_t index = 0UL; - - std::string value; - - for (size_t return_index = text_index; return_index < textBuffer.size(); - ++return_index) - { - if (textBuffer[return_index] != return_keyword[index]) - { - for (size_t value_index = return_index; - value_index < textBuffer.size(); ++value_index) - { - if (textBuffer[value_index] == ';') - break; - - value += textBuffer[value_index]; - } - - break; - } - - ++index; - } - - if (index == return_keyword.size()) - { - if (!value.empty()) - { - if (value.find('(') != std::string::npos) - { - value.erase(value.find('(')); - } - - if (!isdigit(value[value.find('(') + 2])) - { - std::string tmp = value; - bool reg_to_reg = false; - - value.clear(); - - value += " import"; - value += tmp; - } - - syntaxLeaf.fUserValue = "\tmr r31, "; - - // make it pretty. - while (value.find('\t') != std::string::npos) - value.erase(value.find('\t'), 1); - - while (value.find(' ') != std::string::npos) - value.erase(value.find(' '), 1); - - while (value.find("import") != std::string::npos) - value.erase(value.find("import"), strlen("import")); - - bool found = false; - - for (auto& reg : kState.kStackFrame) - { - if (value.find(reg.fName) != std::string::npos) - { - found = true; - syntaxLeaf.fUserValue += reg.fReg; - break; - } - } - - if (!found) - syntaxLeaf.fUserValue += "r0"; - } - - syntaxLeaf.fUserValue += "\n\tblr"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - break; - } - } - - if (textBuffer[text_index] == 'i' && textBuffer[text_index + 1] == 'f') - { - auto expr = textBuffer.substr(text_index + 2); - textBuffer.erase(text_index, 2); - - if (expr.find("{") != std::string::npos) - { - expr.erase(expr.find("{")); - } - - if (expr.find("(") != std::string::npos) - expr.erase(expr.find("(")); - - if (expr.find(")") != std::string::npos) - expr.erase(expr.find(")")); - - kIfFunction = "__MPCC_IF_PROC_"; - kIfFunction += std::to_string(time_off._Raw); - - syntaxLeaf.fUserValue = - "\tcmpw " - "r10, r11"; - - syntaxLeaf.fUserValue += "\n\tbeq import " + kIfFunction + - " \ndword export .code64 " + kIfFunction + "\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - kIfFound = true; - } - - // Parse expressions and instructions here. - // what does this mean? - // we encounter an assignment, or we reached the end of an expression. - if (textBuffer[text_index] == '=' || textBuffer[text_index] == ';') - { - if (fnFound) - continue; - if (kIfFound) - continue; - - if (textBuffer[text_index] == ';' && kInStruct) - continue; - - if (textBuffer.find("typedef ") != std::string::npos) - continue; - - if (textBuffer[text_index] == '=' && kInStruct) - { - detail::print_error( - "assignement of value inside a struct " + textBuffer, file); - continue; - } - - if (textBuffer[text_index] == ';' && kInStruct) - { - bool space_found_ = false; - std::string sym; - - for (auto& ch : textBuffer) - { - if (ch == ' ') - { - space_found_ = true; - } - - if (ch == ';') - break; - - if (space_found_) - sym.push_back(ch); - } - - kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back( - std::make_pair( - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, - sym)); - - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt = - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4; - - continue; - } - - if (textBuffer[text_index] == '=' && kInStruct) - { - continue; - } - - if (textBuffer[text_index + 1] == '=' || - textBuffer[text_index - 1] == '!' || - textBuffer[text_index - 1] == '<' || - textBuffer[text_index - 1] == '>') - { - continue; - } - - std::string substr; - - if (textBuffer.find('=') != std::string::npos && kInBraces && !kIfFound) - { - if (textBuffer.find("*") != std::string::npos) - { - if (textBuffer.find("=") > textBuffer.find("*")) - substr += "\tli "; - else - substr += "\tli "; - } - else - { - substr += "\tli "; - } - } - else if (textBuffer.find('=') != std::string::npos && !kInBraces) - { - substr += "stw export .data64 "; - } - - int first_encountered = 0; - - std::string str_name; - - for (size_t text_index_2 = 0; text_index_2 < textBuffer.size(); - ++text_index_2) - { - if (textBuffer[text_index_2] == '\"') - { - ++text_index_2; - - // want to add this, so that the parser recognizes that this is a - // string. - substr += '"'; - - for (; text_index_2 < textBuffer.size(); ++text_index_2) - { - if (textBuffer[text_index_2] == '\"') - break; - - substr += textBuffer[text_index_2]; - } - } - - if (textBuffer[text_index_2] == '{' || textBuffer[text_index_2] == '}') - continue; - - if (textBuffer[text_index_2] == ';') - { - break; - } - - if (textBuffer[text_index_2] == ' ' || - textBuffer[text_index_2] == '\t') - { - if (first_encountered != 2) - { - if (textBuffer[text_index] != '=' && - substr.find("export .data64") == std::string::npos && - !kInStruct) - substr += "export .data64 "; - } - - ++first_encountered; - - continue; - } - - if (textBuffer[text_index_2] == '=') - { - if (!kInBraces) - { - substr.replace(substr.find("export .data64"), - strlen("export .data64"), "export .zero64 "); - } - - substr += ","; - continue; - } - - substr += textBuffer[text_index_2]; - } - - for (auto& clType : kCompilerTypes) - { - if (substr.find(clType.fName) != std::string::npos) - { - if (substr.find(clType.fName) > substr.find('"')) - continue; - - substr.erase(substr.find(clType.fName), clType.fName.size()); - } - else if (substr.find(clType.fValue) != std::string::npos) - { - if (substr.find(clType.fValue) > substr.find('"')) - continue; - - if (clType.fName == "const") - continue; - - substr.erase(substr.find(clType.fValue), clType.fValue.size()); - } - } - - if (substr.find("extern") != std::string::npos) - { - substr.replace(substr.find("extern"), strlen("extern"), "import "); - - if (substr.find("export .data64") != std::string::npos) - substr.erase(substr.find("export .data64"), strlen("export .data64")); - } - - auto var_to_find = - std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(), - [&](detail::CompilerType type) { - return type.fName.find(substr) != std::string::npos; - }); - - kCompilerVariables.push_back({.fName = substr}); - - if (textBuffer[text_index] == ';') - break; - - std::string reg = kAsmRegisterPrefix; - - ++kRegisterCounter; - reg += std::to_string(kRegisterCounter); - - auto newSubstr = substr.substr(substr.find(" ")); - - std::string symbol; - - for (size_t start = 0; start < newSubstr.size(); ++start) - { - if (newSubstr[start] == ',') - break; - - if (newSubstr[start] == ' ') - continue; - - symbol += (newSubstr[start]); - } - - kState.kStackFrame.push_back({.fName = symbol, .fReg = reg}); - - syntaxLeaf.fUserValue += - "\n\tli " + reg + substr.substr(substr.find(',')); - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - // function handler. - - if (textBuffer[text_index] == '(' && !fnFound && !kIfFound) - { - std::string substr; - std::string args_buffer; - std::string args; - - bool type_crossed = false; - - for (size_t idx = textBuffer.find('(') + 1; idx < textBuffer.size(); - ++idx) - { - if (textBuffer[idx] == ',') - continue; - - if (textBuffer[idx] == ' ') - continue; - - if (textBuffer[idx] == ')') - break; - } - - for (char substr_first_index : textBuffer) - { - if (substr_first_index != ',') - args_buffer += substr_first_index; - else - args_buffer += '$'; - - if (substr_first_index == ';') - { - args_buffer = args_buffer.erase(0, args_buffer.find('(')); - args_buffer = args_buffer.erase(args_buffer.find(';'), 1); - args_buffer = args_buffer.erase(args_buffer.find(')'), 1); - args_buffer = args_buffer.erase(args_buffer.find('('), 1); - - if (!args_buffer.empty()) - args += "\tldw r6, "; - - std::string register_type; - std::size_t index = 7UL; - - while (args_buffer.find("$") != std::string::npos) - { - register_type = kRegisterPrefix; - register_type += std::to_string(index); - - ++index; - - args_buffer.replace(args_buffer.find('$'), 1, - "\n\tldw " + register_type + ","); - } - - args += args_buffer; - args += "\n\tli r31, "; - } - } - - for (char _text_i : textBuffer) - { - if (_text_i == '\t' || _text_i == ' ') - { - if (!type_crossed) - { - substr.clear(); - type_crossed = true; - } - - continue; - } - - if (_text_i == '(') - break; - - substr += _text_i; - } - - if (kInBraces) - { - syntaxLeaf.fUserValue = args; - syntaxLeaf.fUserValue += substr; - - syntaxLeaf.fUserValue += "\n\tblr\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - fnFound = true; - } - else - { - syntaxLeaf.fUserValue.clear(); - - syntaxLeaf.fUserValue += "export .code64 "; - - syntaxLeaf.fUserValue += substr; - syntaxLeaf.fUserValue += "\n"; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - fnFound = true; - } - - kCompilerFunctions.push_back(textBuffer); - } - - if (textBuffer[text_index] == '-' && textBuffer[text_index + 1] == '-') - { - textBuffer = textBuffer.replace(textBuffer.find("--"), strlen("--"), ""); - - for (int _text_i = 0; _text_i < textBuffer.size(); ++_text_i) - { - if (textBuffer[_text_i] == '\t' || textBuffer[_text_i] == ' ') - textBuffer.erase(_text_i, 1); - } - - syntaxLeaf.fUserValue += "dec "; - syntaxLeaf.fUserValue += textBuffer; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - break; - } - - if (textBuffer[text_index] == '}') - { - kRegisterCounter = kStartUsable; - - --kBracesCount; - - if (kBracesCount < 1) - { - kInBraces = false; - kBracesCount = 0; - } - - if (kIfFound) - kIfFound = false; - - if (kInStruct) - kInStruct = false; - - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - } - - syntaxLeaf.fUserValue.clear(); - } - - auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf(); - syntaxLeaf.fUserValue = "\n"; - kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); - - return true; -} - -static bool kShouldHaveBraces = false; -static std::string kFnName; - -std::string CompilerBackendCLang::Check(const char* text, const char* file) -{ - std::string err_str; - std::string ln = text; - - if (ln.empty()) - { - return err_str; - } - - bool non_ascii_found = false; - - for (int i = 0; i < ln.size(); ++i) - { - if (isalnum(ln[i])) - { - non_ascii_found = true; - break; - } - } - - if (kShouldHaveBraces && ln.find('{') != std::string::npos) - { - kShouldHaveBraces = false; - } - - if (!non_ascii_found) - return err_str; - - size_t string_index = 1UL; - - if (ln.find('\'') != std::string::npos) - { - string_index = ln.find('\'') + 1; - - for (; string_index < ln.size(); ++string_index) - { - if (ln[string_index] == '\'') - { - if (ln[string_index + 1] != ';') - { - ln.erase(string_index, 1); - } - - return err_str; - } - } - } - else if (ln.find('"') != std::string::npos) - { - string_index = ln.find('"') + 1; - - for (; string_index < ln.size(); ++string_index) - { - if (ln[string_index] == '"') - { - if (ln[string_index + 1] != ';') - { - ln.erase(string_index, 1); - } - else - { - break; - } - } - } - } - else if (ln.find('"') == std::string::npos && - ln.find('\'') == std::string::npos) - { - std::vector forbidden_words; - - forbidden_words.push_back("\\"); - forbidden_words.push_back("?"); - forbidden_words.push_back("@"); - forbidden_words.push_back("~"); - forbidden_words.push_back("::"); - forbidden_words.push_back("/*"); - forbidden_words.push_back("*/"); - - // add them to avoid stupid mistakes. - forbidden_words.push_back("namespace"); - forbidden_words.push_back("class"); - forbidden_words.push_back("extern \"C\""); - - for (auto& forbidden : forbidden_words) - { - if (ln.find(forbidden) != std::string::npos) - { - err_str += "\nForbidden character detected: "; - err_str += forbidden; - - return err_str; - } - } - } - - struct CompilerVariableRange final - { - std::string fBegin; - std::string fEnd; - }; - - const std::vector variables_list = { - {.fBegin = "static ", .fEnd = "="}, - {.fBegin = "=", .fEnd = ";"}, - {.fBegin = "if(", .fEnd = "="}, - {.fBegin = "if (", .fEnd = "="}, - {.fBegin = "if(", .fEnd = "<"}, - {.fBegin = "if (", .fEnd = "<"}, - {.fBegin = "if(", .fEnd = ">"}, - {.fBegin = "if (", .fEnd = ">"}, - {.fBegin = "if(", .fEnd = ")"}, - {.fBegin = "if (", .fEnd = ")"}, - - {.fBegin = "else(", .fEnd = "="}, - {.fBegin = "else (", .fEnd = "="}, - {.fBegin = "else(", .fEnd = "<"}, - {.fBegin = "else (", .fEnd = "<"}, - {.fBegin = "else(", .fEnd = ">"}, - {.fBegin = "else (", .fEnd = ">"}, - {.fBegin = "else(", .fEnd = ")"}, - {.fBegin = "else (", .fEnd = ")"}, - }; - - for (auto& variable : variables_list) - { - if (ln.find(variable.fBegin) != std::string::npos) - { - string_index = ln.find(variable.fBegin) + variable.fBegin.size(); - - while (ln[string_index] == ' ') - ++string_index; - - std::string keyword; - - for (; string_index < ln.size(); ++string_index) - { - if (ln[string_index] == variable.fEnd[0]) - { - std::string varname = ""; - - for (size_t index_keyword = ln.find(' '); - ln[index_keyword] != variable.fBegin[0]; ++index_keyword) - { - if (ln[index_keyword] == ' ') - { - continue; - } - - if (isdigit(ln[index_keyword])) - { - goto cc_next_loop; - } - - varname += ln[index_keyword]; - } - - if (varname.find(' ') != std::string::npos) - { - varname.erase(0, varname.find(' ')); - - if (variable.fBegin == "extern") - { - varname.erase(0, varname.find(' ')); - } - } - - if (kRegisterCounter == 5 || kRegisterCounter == 6) - ++kRegisterCounter; - - std::string reg = kAsmRegisterPrefix; - reg += std::to_string(kRegisterCounter); - - kCompilerVariables.push_back({.fValue = varname}); - goto cc_check_done; - } - - keyword.push_back(ln[string_index]); - } - - goto cc_next_loop; - - cc_check_done: - - // skip digit value. - if (isdigit(keyword[0]) || keyword[0] == '"') - { - goto cc_next_loop; - } - - while (keyword.find(' ') != std::string::npos) - keyword.erase(keyword.find(' '), 1); - - for (auto& var : kCompilerVariables) - { - if (var.fValue.find(keyword) != std::string::npos) - { - err_str.clear(); - goto cc_next; - } - } - - for (auto& fn : kCompilerFunctions) - { - if (fn.find(keyword[0]) != std::string::npos) - { - auto where_begin = fn.find(keyword[0]); - auto keyword_begin = 0UL; - auto failed = false; - - for (; where_begin < keyword.size(); ++where_begin) - { - if (fn[where_begin] == '(' && keyword[keyword_begin] == '(') - break; - - if (fn[where_begin] != keyword[keyword_begin]) - { - failed = true; - break; - } - - ++keyword_begin; - } - - if (!failed) - { - err_str.clear(); - goto cc_next; - } - else - { - continue; - } - } - } - - cc_error_value: - if (keyword.find("->") != std::string::npos) - return err_str; - - if (keyword.find(".") != std::string::npos) - return err_str; - - if (isalnum(keyword[0])) - err_str += "\nUndefined value: " + keyword; - - return err_str; - } - - cc_next_loop: - continue; - } - -cc_next: - - // extern does not declare anything, it imports a variable. - // so that's why it's not declare upper. - if (ParserKit::find_word(ln, "extern")) - { - auto substr = ln.substr(ln.find("extern") + strlen("extern")); - kCompilerVariables.push_back({.fValue = substr}); - } - - if (kShouldHaveBraces && ln.find('{') == std::string::npos) - { - err_str += "Missing '{' for function "; - err_str += kFnName; - err_str += "\n"; - - kShouldHaveBraces = false; - kFnName.clear(); - } - else if (kShouldHaveBraces && ln.find('{') != std::string::npos) - { - kShouldHaveBraces = false; - kFnName.clear(); - } - - bool type_not_found = true; - - if (ln.find('\'') != std::string::npos) - { - ln.replace(ln.find('\''), 3, "0"); - } - - auto first = ln.find('"'); - if (first != std::string::npos) - { - auto second = 0UL; - bool found_second_quote = false; - - for (size_t i = first + 1; i < ln.size(); ++i) - { - if (ln[i] == '\"') - { - found_second_quote = true; - second = i; - - break; - } - } - - if (!found_second_quote) - { - err_str += "Missing terminating \"."; - err_str += " here -> " + ln.substr(ln.find('"'), second); - } - } - - if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos) - { - if (ln.find('{') == std::string::npos) - { - kFnName = ln; - kShouldHaveBraces = true; - - goto skip_braces_check; - } - else if (ln.find('{') != std::string::npos) - { - kShouldHaveBraces = false; - } - } - -skip_braces_check: - - for (auto& key : kCompilerTypes) - { - if (ParserKit::find_word(ln, key.fName)) - { - if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) - { - err_str += "\nNumber cannot be set for "; - err_str += key.fName; - err_str += "'s name. here -> "; - err_str += ln; - } - - if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' || - ln[ln.find(key.fName) - 1] == '\t') - { - type_not_found = false; - - if (ln[ln.find(key.fName) + key.fName.size()] != ' ') - { - type_not_found = true; - - if (ln[ln.find(key.fName) + key.fName.size()] == '\t') - type_not_found = false; - - goto next; - } - else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') - { - type_not_found = true; - - if (ln[ln.find(key.fName) + key.fName.size()] == ' ') - type_not_found = false; - } - } - - next: - - if (ln.find(';') == std::string::npos) - { - if (ln.find('(') != std::string::npos) - { - if (ln.find('=') == std::string::npos) - continue; - } - - err_str += "\nMissing ';', here -> "; - err_str += ln; - } - else - { - continue; - } - - if (ln.find('=') != std::string::npos) - { - if (ln.find('(') != std::string::npos) - { - if (ln.find(')') == std::string::npos) - { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } - } - } - } - } - - if (kInBraces && ln.find("struct") != std::string::npos && - ln.find("union") != std::string::npos && - ln.find("enum") != std::string::npos && - ln.find('=') != std::string::npos) - { - if (ln.find(';') == std::string::npos) - { - err_str += "\nMissing ';' after struct/union/enum declaration, here -> "; - err_str += ln; - } - } - - if (ln.find(';') != std::string::npos && - ln.find("for") == std::string::npos) - { - if (ln.find(';') + 1 != ln.size()) - { - for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) - { - if ((ln.substr(ln.find(';') + 1)[i] != ' ') || - (ln.substr(ln.find(';') + 1)[i] != '\t')) - { - if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); - !err.empty()) - { - err_str += "\nUnexpected text after ';' -> "; - err_str += ln.substr(ln.find(';')); - err_str += err; - } - } - } - } - } - - if (ln.find('(') != std::string::npos) - { - if (ln.find(';') == std::string::npos && !ParserKit::find_word(ln, "|") && - !ParserKit::find_word(ln, "||") && !ParserKit::find_word(ln, "&") && - !ParserKit::find_word(ln, "&&") && !ParserKit::find_word(ln, "~")) - { - bool found_func = false; - size_t i = ln.find('('); - std::vector opens; - std::vector closes; - - for (; i < ln.size(); ++i) - { - if (ln[i] == ')') - { - closes.push_back(1); - } - - if (ln[i] == '(') - { - opens.push_back(1); - } - } - - if (closes.size() != opens.size()) - err_str += "Unterminated (), here -> " + ln; - - bool space_found = false; - - for (int i = 0; i < ln.size(); ++i) - { - if (ln[i] == ')' && !space_found) - { - space_found = true; - continue; - } - - if (space_found) - { - if (ln[i] == ' ' && isalnum(ln[i + 1])) - { - err_str += "\nBad function format here -> "; - err_str += ln; - } - } - } - } - - if (ln.find('(') < 1) - { - err_str += "\nMissing identifier before '(' here -> "; - err_str += ln; - } - else - { - if (type_not_found && ln.find(';') == std::string::npos && - ln.find("if") == std::string::npos && - ln.find("|") == std::string::npos && - ln.find("&") == std::string::npos && - ln.find("(") == std::string::npos && - ln.find(")") == std::string::npos) - { - err_str += "\n Missing ';' or type, here -> "; - err_str += ln; - } - } - - if (ln.find(')') == std::string::npos) - { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } - } - else - { - if (ln.find("for") != std::string::npos || - ln.find("while") != std::string::npos) - { - err_str += "\nMissing '(', after \"for\", here -> "; - err_str += ln; - } - } - - if (ln.find('}') != std::string::npos && !kInBraces) - { - if (!kInStruct && ln.find(';') == std::string::npos) - { - err_str += "\nMismatched '}', here -> "; - err_str += ln; - } - } - - if (!ln.empty()) - { - if (ln.find(';') == std::string::npos && - ln.find('{') == std::string::npos && - ln.find('}') == std::string::npos && - ln.find(')') == std::string::npos && - ln.find('(') == std::string::npos && - ln.find(',') == std::string::npos) - { - if (ln.size() <= 2) - return err_str; - - err_str += "\nMissing ';', here -> "; - err_str += ln; - } - } - - return err_str; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -/** - * @brief C To Assembly mount-point. - */ - -///////////////////////////////////////////////////////////////////////////////////////// - -class AssemblyMountpointCLang final : public CompilerKit::AssemblyInterface -{ -public: - explicit AssemblyMountpointCLang() = default; - ~AssemblyMountpointCLang() override = default; - - MPCC_COPY_DEFAULT(AssemblyMountpointCLang); - - [[maybe_unused]] static Int32 Arch() noexcept - { - return CompilerKit::AssemblyFactory::kArchPowerPC; - } - - Int32 CompileToFormat(std::string& src, Int32 arch) override - { - if (arch != AssemblyMountpointCLang::Arch()) - return -1; - - if (kCompilerBackend == nullptr) - return -1; - - /* @brief copy contents wihtout extension */ - std::string src_file = src.data(); - std::ifstream src_fp = std::ifstream(src_file, std::ios::in); - std::string dest; - - for (auto& ch : src_file) - { - if (ch == '.') - { - break; - } - - dest += ch; - } - - /* According to PEF ABI. */ - std::vector exts = kAsmFileExts; - dest += exts[4]; - - kState.fOutputAssembly = std::make_unique(dest); - - auto fmt = CompilerKit::current_date(); - - (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; - (*kState.fOutputAssembly) - << "# Language: POWER Assembly (Generated from C)\n"; - (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n"; - - ParserKit::SyntaxLeafList syntax; - - kState.fSyntaxTreeList.push_back(syntax); - kState.fSyntaxTree = - &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; - - std::string line_src; - - while (std::getline(src_fp, line_src)) - { - if (auto err = kCompilerBackend->Check(line_src.c_str(), src.data()); - err.empty()) - { - kCompilerBackend->Compile(line_src, src.data()); - } - else - { - detail::print_error(err, src.data()); - } - } - - if (kAcceptableErrors > 0) - return -1; - - std::vector keywords = {"ld", "stw", "add", "sub", "or"}; - - /// - /// Replace, optimize, fix assembly output. - /// - - for (auto& leaf : kState.fSyntaxTree->fLeafList) - { - std::vector access_keywords = {"->", "."}; - - for (auto& access_ident : access_keywords) - { - if (ParserKit::find_word(leaf.fUserValue, access_ident)) - { - for (auto& struc : kState.kStructMap) - { - /// TODO: - } - } - } - - for (auto& keyword : keywords) - { - if (ParserKit::find_word(leaf.fUserValue, keyword)) - { - std::size_t cnt = 0UL; - - for (auto& reg : kState.kStackFrame) - { - std::string needle; - - for (size_t i = 0; i < reg.fName.size(); i++) - { - if (reg.fName[i] == ' ') - { - ++i; - - for (; i < reg.fName.size(); i++) - { - if (reg.fName[i] == ',') - { - break; - } - - if (reg.fName[i] == ' ') - continue; - - needle += reg.fName[i]; - } - - break; - } - } - - if (ParserKit::find_word(leaf.fUserValue, needle)) - { - if (leaf.fUserValue.find("import ") != std::string::npos) - { - std::string range = "import "; - leaf.fUserValue.replace(leaf.fUserValue.find(range), - range.size(), ""); - } - - if (leaf.fUserValue.find("ldw r6") != std::string::npos) - { - std::string::difference_type countComma = std::count( - leaf.fUserValue.begin(), leaf.fUserValue.end(), ','); - - if (countComma == 1) - { - leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), - strlen("ldw"), "mr"); - } - } - - leaf.fUserValue.replace(leaf.fUserValue.find(needle), - needle.size(), reg.fReg); - - ++cnt; - } - } - - if (cnt > 1 && keyword != "mr" && keyword != "add" && - keyword != "dec") - { - leaf.fUserValue.replace(leaf.fUserValue.find(keyword), - keyword.size(), "mr"); - } - } - } - } - - for (auto& leaf : kState.fSyntaxTree->fLeafList) - { - (*kState.fOutputAssembly) << leaf.fUserValue; - } - - kState.fSyntaxTree = nullptr; - - kState.fOutputAssembly->flush(); - kState.fOutputAssembly.reset(); - - return kOk; - } -}; - -///////////////////////////////////////////////////////////////////////////////////////// - -#include - -#define kPrintF printf -#define kSplashCxx() \ - kPrintF(kWhite "cc, %s, (c) ZKA Technologies\n", kDistVersion) - -static void cc_print_help() -{ - kSplashCxx(); -} - -///////////////////////////////////////////////////////////////////////////////////////// - -#define kExt ".c" - -NDK_MODULE(NewOSCompilerCLangPowerPC) -{ - kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); - kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); - kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); - kCompilerTypes.push_back({.fName = "int", .fValue = "dword"}); - kCompilerTypes.push_back({.fName = "long", .fValue = "qword"}); - kCompilerTypes.push_back({.fName = "*", .fValue = "offset"}); - - bool skip = false; - - kFactory.Mount(new AssemblyMountpointCLang()); - kMachine = CompilerKit::AssemblyFactory::kArchPowerPC; - kCompilerBackend = new CompilerBackendCLang(); - - for (auto index = 1UL; index < argc; ++index) - { - if (skip) - { - skip = false; - continue; - } - - if (argv[index][0] == '-') - { - if (strcmp(argv[index], "-v") == 0 || - strcmp(argv[index], "-version") == 0) - { - kSplashCxx(); - return kOk; - } - - if (strcmp(argv[index], "-verbose") == 0) - { - kState.fVerbose = true; - - continue; - } - - if (strcmp(argv[index], "-h") == 0 || strcmp(argv[index], "-help") == 0) - { - cc_print_help(); - - return kOk; - } - - if (strcmp(argv[index], "-dialect") == 0) - { - if (kCompilerBackend) - std::cout << kCompilerBackend->Language() << "\n"; - - return kOk; - } - - if (strcmp(argv[index], "-fmax-exceptions") == 0) - { - try - { - kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); - } - // catch anything here - catch (...) - { - kErrorLimit = 0; - } - - skip = true; - - continue; - } - - std::string err = "Unknown command: "; - err += argv[index]; - - detail::print_error(err, "cc"); - - continue; - } - - kFileList.emplace_back(argv[index]); - - std::string srcFile = argv[index]; - - if (strstr(argv[index], kExt) == nullptr) - { - if (kState.fVerbose) - { - detail::print_error(srcFile + " is not a valid C source.\n", "cc"); - } - - return 1; - } - - if (kFactory.Compile(srcFile, kMachine) != kOk) - return -1; - } - - return kOk; -} - -// Last rev 8-1-24 diff --git a/Sources/power-cc.cxx b/Sources/power-cc.cxx new file mode 100644 index 0000000..41cb334 --- /dev/null +++ b/Sources/power-cc.cxx @@ -0,0 +1,1645 @@ +/* + * ======================================================== + * + * cc + * Copyright ZKA Technologies, all rights reserved. + * + * ======================================================== + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define kOk 0 + +/// @author Amlal El Mahrouss (amlel) +/// @file cc.cxx +/// @brief POWER C Compiler. + +///////////////////// + +/// ANSI ESCAPE CODES + +///////////////////// + +#define kBlank "\e[0;30m" +#define kRed "\e[0;31m" +#define kWhite "\e[0;97m" + +///////////////////////////////////// + +/// INTERNAL STRUCT OF THE C COMPILER + +///////////////////////////////////// + +namespace detail +{ + // \brief name to register struct. + struct CompilerRegisterMap final + { + std::string fName; + std::string fReg; + }; + + // \brief Map for C structs + // \author amlel + struct CompilerStructMap final + { + /// 'struct::my_foo' + std::string fName; + + /// if instance: stores a valid register. + std::string fReg; + + /// offset count + std::size_t fOffsetsCnt; + + /// offset array. + std::vector> fOffsets; + }; + + struct CompilerState final + { + std::vector fSyntaxTreeList; + std::vector kStackFrame; + std::vector kStructMap; + ParserKit::SyntaxLeafList* fSyntaxTree{nullptr}; + std::unique_ptr fOutputAssembly; + std::string fLastFile; + std::string fLastError; + bool fVerbose; + }; +} // namespace detail + +static detail::CompilerState kState; +static SizeType kErrorLimit = 100; +static std::string kIfFunction = ""; +static Int32 kAcceptableErrors = 0; + +namespace detail +{ + /// @brief prints an error into stdout. + /// @param reason the reason of the error. + /// @param file where does it originate from? + void print_error(std::string reason, std::string file) noexcept + { + if (reason[0] == '\n') + reason.erase(0, 1); + + if (file.find(".pp") != std::string::npos) + file.erase(file.find(".pp"), 3); + + if (kState.fLastFile != file) + { + std::cout << kRed << "[ cc ] " << kWhite + << ((file == "cc") ? "internal compiler error " + : ("in file, " + file)) + << kBlank << std::endl; + std::cout << kRed << "[ cc ] " << kWhite << reason << kBlank << std::endl; + + kState.fLastFile = file; + } + else + { + std::cout << kRed << "[ cc ] [ " << kState.fLastFile << " ] " << kWhite + << reason << kBlank << std::endl; + } + + if (kAcceptableErrors > kErrorLimit) + std::exit(3); + + ++kAcceptableErrors; + } + + struct CompilerType final + { + std::string fName; + std::string fValue; + }; +} // namespace detail + +///////////////////////////////////////////////////////////////////////////////////////// + +// Target architecture. +static int kMachine = 0; + +///////////////////////////////////////// + +// REGISTERS ACCORDING TO USED ASSEMBLER + +///////////////////////////////////////// + +static size_t kRegisterCnt = kAsmRegisterLimit; +static size_t kStartUsable = 2; +static size_t kUsableLimit = 15; +static size_t kRegisterCounter = kStartUsable; +static std::string kRegisterPrefix = kAsmRegisterPrefix; + +///////////////////////////////////////// + +// COMPILER PARSING UTILITIES/STATES. + +///////////////////////////////////////// + +static std::vector kFileList; +static CompilerKit::AssemblyFactory kFactory; +static bool kInStruct = false; +static bool kOnWhileLoop = false; +static bool kOnForLoop = false; +static bool kInBraces = false; +static bool kIfFound = false; +static size_t kBracesCount = 0UL; + +/* @brief C compiler backend for C */ +class CompilerBackendCLang final : public ParserKit::CompilerBackend +{ +public: + explicit CompilerBackendCLang() = default; + ~CompilerBackendCLang() override = default; + + MPCC_COPY_DEFAULT(CompilerBackendCLang); + + std::string Check(const char* text, const char* file); + bool Compile(const std::string& text, const char* file) override; + + const char* Language() override + { + return "POWER C"; + } +}; + +static CompilerBackendCLang* kCompilerBackend = nullptr; +static std::vector kCompilerVariables; +static std::vector kCompilerFunctions; +static std::vector kCompilerTypes; + +namespace detail +{ + union number_cast final { + public: + number_cast(UInt64 _Raw) + : _Raw(_Raw) + { + } + + public: + char _Num[8]; + UInt64 _Raw; + }; + + union double_cast final { + public: + double_cast(float _Raw) + : _Raw(_Raw) + { + } + + public: + char _Sign; + char _Lh[8]; + char _Rh[23]; + + float _Raw; + }; +} // namespace detail + +///////////////////////////////////////////////////////////////////////////////////////// + +// @name Compile +// @brief Generate MASM from a C assignement. + +///////////////////////////////////////////////////////////////////////////////////////// + +bool CompilerBackendCLang::Compile(const std::string& text, const char* file) +{ + std::string textBuffer = text; + + bool typeFound = false; + bool fnFound = false; + + // setup generator. + std::random_device rd; + + auto seed_data = std::array{}; + std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd)); + std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); + std::mt19937 generator(seq); + + // start parsing + for (size_t text_index = 0; text_index < textBuffer.size(); ++text_index) + { + auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf(); + + auto gen = uuids::uuid_random_generator{generator}; + uuids::uuid out = gen(); + + detail::number_cast time_off = (UInt64)out.as_bytes().data(); + + if (!typeFound) + { + auto substr = textBuffer.substr(text_index); + std::string match_type; + + for (size_t y = 0; y < substr.size(); ++y) + { + if (substr[y] == ' ') + { + while (match_type.find(' ') != std::string::npos) + { + match_type.erase(match_type.find(' ')); + } + + for (auto& clType : kCompilerTypes) + { + if (clType.fName == match_type) + { + match_type.clear(); + + std::string buf; + + buf += clType.fValue; + buf += ' '; + + if (substr.find('=') != std::string::npos) + { + break; + } + + if (textBuffer.find('(') != std::string::npos) + { + syntaxLeaf.fUserValue = buf; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + } + + typeFound = true; + break; + } + } + + break; + } + + match_type += substr[y]; + } + } + + if (textBuffer[text_index] == '{') + { + if (kInStruct) + { + continue; + } + + kInBraces = true; + ++kBracesCount; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + } + + // return keyword handler + if (textBuffer[text_index] == 'r') + { + std::string return_keyword; + return_keyword += "return"; + + std::size_t index = 0UL; + + std::string value; + + for (size_t return_index = text_index; return_index < textBuffer.size(); + ++return_index) + { + if (textBuffer[return_index] != return_keyword[index]) + { + for (size_t value_index = return_index; + value_index < textBuffer.size(); ++value_index) + { + if (textBuffer[value_index] == ';') + break; + + value += textBuffer[value_index]; + } + + break; + } + + ++index; + } + + if (index == return_keyword.size()) + { + if (!value.empty()) + { + if (value.find('(') != std::string::npos) + { + value.erase(value.find('(')); + } + + if (!isdigit(value[value.find('(') + 2])) + { + std::string tmp = value; + bool reg_to_reg = false; + + value.clear(); + + value += " import"; + value += tmp; + } + + syntaxLeaf.fUserValue = "\tmr r31, "; + + // make it pretty. + while (value.find('\t') != std::string::npos) + value.erase(value.find('\t'), 1); + + while (value.find(' ') != std::string::npos) + value.erase(value.find(' '), 1); + + while (value.find("import") != std::string::npos) + value.erase(value.find("import"), strlen("import")); + + bool found = false; + + for (auto& reg : kState.kStackFrame) + { + if (value.find(reg.fName) != std::string::npos) + { + found = true; + syntaxLeaf.fUserValue += reg.fReg; + break; + } + } + + if (!found) + syntaxLeaf.fUserValue += "r0"; + } + + syntaxLeaf.fUserValue += "\n\tblr"; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + break; + } + } + + if (textBuffer[text_index] == 'i' && textBuffer[text_index + 1] == 'f') + { + auto expr = textBuffer.substr(text_index + 2); + textBuffer.erase(text_index, 2); + + if (expr.find("{") != std::string::npos) + { + expr.erase(expr.find("{")); + } + + if (expr.find("(") != std::string::npos) + expr.erase(expr.find("(")); + + if (expr.find(")") != std::string::npos) + expr.erase(expr.find(")")); + + kIfFunction = "__MPCC_IF_PROC_"; + kIfFunction += std::to_string(time_off._Raw); + + syntaxLeaf.fUserValue = + "\tcmpw " + "r10, r11"; + + syntaxLeaf.fUserValue += "\n\tbeq import " + kIfFunction + + " \ndword export .code64 " + kIfFunction + "\n"; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + kIfFound = true; + } + + // Parse expressions and instructions here. + // what does this mean? + // we encounter an assignment, or we reached the end of an expression. + if (textBuffer[text_index] == '=' || textBuffer[text_index] == ';') + { + if (fnFound) + continue; + if (kIfFound) + continue; + + if (textBuffer[text_index] == ';' && kInStruct) + continue; + + if (textBuffer.find("typedef ") != std::string::npos) + continue; + + if (textBuffer[text_index] == '=' && kInStruct) + { + detail::print_error( + "assignement of value inside a struct " + textBuffer, file); + continue; + } + + if (textBuffer[text_index] == ';' && kInStruct) + { + bool space_found_ = false; + std::string sym; + + for (auto& ch : textBuffer) + { + if (ch == ' ') + { + space_found_ = true; + } + + if (ch == ';') + break; + + if (space_found_) + sym.push_back(ch); + } + + kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back( + std::make_pair( + kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, + sym)); + + kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt = + kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4; + + continue; + } + + if (textBuffer[text_index] == '=' && kInStruct) + { + continue; + } + + if (textBuffer[text_index + 1] == '=' || + textBuffer[text_index - 1] == '!' || + textBuffer[text_index - 1] == '<' || + textBuffer[text_index - 1] == '>') + { + continue; + } + + std::string substr; + + if (textBuffer.find('=') != std::string::npos && kInBraces && !kIfFound) + { + if (textBuffer.find("*") != std::string::npos) + { + if (textBuffer.find("=") > textBuffer.find("*")) + substr += "\tli "; + else + substr += "\tli "; + } + else + { + substr += "\tli "; + } + } + else if (textBuffer.find('=') != std::string::npos && !kInBraces) + { + substr += "stw export .data64 "; + } + + int first_encountered = 0; + + std::string str_name; + + for (size_t text_index_2 = 0; text_index_2 < textBuffer.size(); + ++text_index_2) + { + if (textBuffer[text_index_2] == '\"') + { + ++text_index_2; + + // want to add this, so that the parser recognizes that this is a + // string. + substr += '"'; + + for (; text_index_2 < textBuffer.size(); ++text_index_2) + { + if (textBuffer[text_index_2] == '\"') + break; + + substr += textBuffer[text_index_2]; + } + } + + if (textBuffer[text_index_2] == '{' || textBuffer[text_index_2] == '}') + continue; + + if (textBuffer[text_index_2] == ';') + { + break; + } + + if (textBuffer[text_index_2] == ' ' || + textBuffer[text_index_2] == '\t') + { + if (first_encountered != 2) + { + if (textBuffer[text_index] != '=' && + substr.find("export .data64") == std::string::npos && + !kInStruct) + substr += "export .data64 "; + } + + ++first_encountered; + + continue; + } + + if (textBuffer[text_index_2] == '=') + { + if (!kInBraces) + { + substr.replace(substr.find("export .data64"), + strlen("export .data64"), "export .zero64 "); + } + + substr += ","; + continue; + } + + substr += textBuffer[text_index_2]; + } + + for (auto& clType : kCompilerTypes) + { + if (substr.find(clType.fName) != std::string::npos) + { + if (substr.find(clType.fName) > substr.find('"')) + continue; + + substr.erase(substr.find(clType.fName), clType.fName.size()); + } + else if (substr.find(clType.fValue) != std::string::npos) + { + if (substr.find(clType.fValue) > substr.find('"')) + continue; + + if (clType.fName == "const") + continue; + + substr.erase(substr.find(clType.fValue), clType.fValue.size()); + } + } + + if (substr.find("extern") != std::string::npos) + { + substr.replace(substr.find("extern"), strlen("extern"), "import "); + + if (substr.find("export .data64") != std::string::npos) + substr.erase(substr.find("export .data64"), strlen("export .data64")); + } + + auto var_to_find = + std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(), + [&](detail::CompilerType type) { + return type.fName.find(substr) != std::string::npos; + }); + + kCompilerVariables.push_back({.fName = substr}); + + if (textBuffer[text_index] == ';') + break; + + std::string reg = kAsmRegisterPrefix; + + ++kRegisterCounter; + reg += std::to_string(kRegisterCounter); + + auto newSubstr = substr.substr(substr.find(" ")); + + std::string symbol; + + for (size_t start = 0; start < newSubstr.size(); ++start) + { + if (newSubstr[start] == ',') + break; + + if (newSubstr[start] == ' ') + continue; + + symbol += (newSubstr[start]); + } + + kState.kStackFrame.push_back({.fName = symbol, .fReg = reg}); + + syntaxLeaf.fUserValue += + "\n\tli " + reg + substr.substr(substr.find(',')); + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + } + + // function handler. + + if (textBuffer[text_index] == '(' && !fnFound && !kIfFound) + { + std::string substr; + std::string args_buffer; + std::string args; + + bool type_crossed = false; + + for (size_t idx = textBuffer.find('(') + 1; idx < textBuffer.size(); + ++idx) + { + if (textBuffer[idx] == ',') + continue; + + if (textBuffer[idx] == ' ') + continue; + + if (textBuffer[idx] == ')') + break; + } + + for (char substr_first_index : textBuffer) + { + if (substr_first_index != ',') + args_buffer += substr_first_index; + else + args_buffer += '$'; + + if (substr_first_index == ';') + { + args_buffer = args_buffer.erase(0, args_buffer.find('(')); + args_buffer = args_buffer.erase(args_buffer.find(';'), 1); + args_buffer = args_buffer.erase(args_buffer.find(')'), 1); + args_buffer = args_buffer.erase(args_buffer.find('('), 1); + + if (!args_buffer.empty()) + args += "\tldw r6, "; + + std::string register_type; + std::size_t index = 7UL; + + while (args_buffer.find("$") != std::string::npos) + { + register_type = kRegisterPrefix; + register_type += std::to_string(index); + + ++index; + + args_buffer.replace(args_buffer.find('$'), 1, + "\n\tldw " + register_type + ","); + } + + args += args_buffer; + args += "\n\tli r31, "; + } + } + + for (char _text_i : textBuffer) + { + if (_text_i == '\t' || _text_i == ' ') + { + if (!type_crossed) + { + substr.clear(); + type_crossed = true; + } + + continue; + } + + if (_text_i == '(') + break; + + substr += _text_i; + } + + if (kInBraces) + { + syntaxLeaf.fUserValue = args; + syntaxLeaf.fUserValue += substr; + + syntaxLeaf.fUserValue += "\n\tblr\n"; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + fnFound = true; + } + else + { + syntaxLeaf.fUserValue.clear(); + + syntaxLeaf.fUserValue += "export .code64 "; + + syntaxLeaf.fUserValue += substr; + syntaxLeaf.fUserValue += "\n"; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + fnFound = true; + } + + kCompilerFunctions.push_back(textBuffer); + } + + if (textBuffer[text_index] == '-' && textBuffer[text_index + 1] == '-') + { + textBuffer = textBuffer.replace(textBuffer.find("--"), strlen("--"), ""); + + for (int _text_i = 0; _text_i < textBuffer.size(); ++_text_i) + { + if (textBuffer[_text_i] == '\t' || textBuffer[_text_i] == ' ') + textBuffer.erase(_text_i, 1); + } + + syntaxLeaf.fUserValue += "dec "; + syntaxLeaf.fUserValue += textBuffer; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + break; + } + + if (textBuffer[text_index] == '}') + { + kRegisterCounter = kStartUsable; + + --kBracesCount; + + if (kBracesCount < 1) + { + kInBraces = false; + kBracesCount = 0; + } + + if (kIfFound) + kIfFound = false; + + if (kInStruct) + kInStruct = false; + + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + } + + syntaxLeaf.fUserValue.clear(); + } + + auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf(); + syntaxLeaf.fUserValue = "\n"; + kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf); + + return true; +} + +static bool kShouldHaveBraces = false; +static std::string kFnName; + +std::string CompilerBackendCLang::Check(const char* text, const char* file) +{ + std::string err_str; + std::string ln = text; + + if (ln.empty()) + { + return err_str; + } + + bool non_ascii_found = false; + + for (int i = 0; i < ln.size(); ++i) + { + if (isalnum(ln[i])) + { + non_ascii_found = true; + break; + } + } + + if (kShouldHaveBraces && ln.find('{') != std::string::npos) + { + kShouldHaveBraces = false; + } + + if (!non_ascii_found) + return err_str; + + size_t string_index = 1UL; + + if (ln.find('\'') != std::string::npos) + { + string_index = ln.find('\'') + 1; + + for (; string_index < ln.size(); ++string_index) + { + if (ln[string_index] == '\'') + { + if (ln[string_index + 1] != ';') + { + ln.erase(string_index, 1); + } + + return err_str; + } + } + } + else if (ln.find('"') != std::string::npos) + { + string_index = ln.find('"') + 1; + + for (; string_index < ln.size(); ++string_index) + { + if (ln[string_index] == '"') + { + if (ln[string_index + 1] != ';') + { + ln.erase(string_index, 1); + } + else + { + break; + } + } + } + } + else if (ln.find('"') == std::string::npos && + ln.find('\'') == std::string::npos) + { + std::vector forbidden_words; + + forbidden_words.push_back("\\"); + forbidden_words.push_back("?"); + forbidden_words.push_back("@"); + forbidden_words.push_back("~"); + forbidden_words.push_back("::"); + forbidden_words.push_back("/*"); + forbidden_words.push_back("*/"); + + // add them to avoid stupid mistakes. + forbidden_words.push_back("namespace"); + forbidden_words.push_back("class"); + forbidden_words.push_back("extern \"C\""); + + for (auto& forbidden : forbidden_words) + { + if (ln.find(forbidden) != std::string::npos) + { + err_str += "\nForbidden character detected: "; + err_str += forbidden; + + return err_str; + } + } + } + + struct CompilerVariableRange final + { + std::string fBegin; + std::string fEnd; + }; + + const std::vector variables_list = { + {.fBegin = "static ", .fEnd = "="}, + {.fBegin = "=", .fEnd = ";"}, + {.fBegin = "if(", .fEnd = "="}, + {.fBegin = "if (", .fEnd = "="}, + {.fBegin = "if(", .fEnd = "<"}, + {.fBegin = "if (", .fEnd = "<"}, + {.fBegin = "if(", .fEnd = ">"}, + {.fBegin = "if (", .fEnd = ">"}, + {.fBegin = "if(", .fEnd = ")"}, + {.fBegin = "if (", .fEnd = ")"}, + + {.fBegin = "else(", .fEnd = "="}, + {.fBegin = "else (", .fEnd = "="}, + {.fBegin = "else(", .fEnd = "<"}, + {.fBegin = "else (", .fEnd = "<"}, + {.fBegin = "else(", .fEnd = ">"}, + {.fBegin = "else (", .fEnd = ">"}, + {.fBegin = "else(", .fEnd = ")"}, + {.fBegin = "else (", .fEnd = ")"}, + }; + + for (auto& variable : variables_list) + { + if (ln.find(variable.fBegin) != std::string::npos) + { + string_index = ln.find(variable.fBegin) + variable.fBegin.size(); + + while (ln[string_index] == ' ') + ++string_index; + + std::string keyword; + + for (; string_index < ln.size(); ++string_index) + { + if (ln[string_index] == variable.fEnd[0]) + { + std::string varname = ""; + + for (size_t index_keyword = ln.find(' '); + ln[index_keyword] != variable.fBegin[0]; ++index_keyword) + { + if (ln[index_keyword] == ' ') + { + continue; + } + + if (isdigit(ln[index_keyword])) + { + goto cc_next_loop; + } + + varname += ln[index_keyword]; + } + + if (varname.find(' ') != std::string::npos) + { + varname.erase(0, varname.find(' ')); + + if (variable.fBegin == "extern") + { + varname.erase(0, varname.find(' ')); + } + } + + if (kRegisterCounter == 5 || kRegisterCounter == 6) + ++kRegisterCounter; + + std::string reg = kAsmRegisterPrefix; + reg += std::to_string(kRegisterCounter); + + kCompilerVariables.push_back({.fValue = varname}); + goto cc_check_done; + } + + keyword.push_back(ln[string_index]); + } + + goto cc_next_loop; + + cc_check_done: + + // skip digit value. + if (isdigit(keyword[0]) || keyword[0] == '"') + { + goto cc_next_loop; + } + + while (keyword.find(' ') != std::string::npos) + keyword.erase(keyword.find(' '), 1); + + for (auto& var : kCompilerVariables) + { + if (var.fValue.find(keyword) != std::string::npos) + { + err_str.clear(); + goto cc_next; + } + } + + for (auto& fn : kCompilerFunctions) + { + if (fn.find(keyword[0]) != std::string::npos) + { + auto where_begin = fn.find(keyword[0]); + auto keyword_begin = 0UL; + auto failed = false; + + for (; where_begin < keyword.size(); ++where_begin) + { + if (fn[where_begin] == '(' && keyword[keyword_begin] == '(') + break; + + if (fn[where_begin] != keyword[keyword_begin]) + { + failed = true; + break; + } + + ++keyword_begin; + } + + if (!failed) + { + err_str.clear(); + goto cc_next; + } + else + { + continue; + } + } + } + + cc_error_value: + if (keyword.find("->") != std::string::npos) + return err_str; + + if (keyword.find(".") != std::string::npos) + return err_str; + + if (isalnum(keyword[0])) + err_str += "\nUndefined value: " + keyword; + + return err_str; + } + + cc_next_loop: + continue; + } + +cc_next: + + // extern does not declare anything, it imports a variable. + // so that's why it's not declare upper. + if (ParserKit::find_word(ln, "extern")) + { + auto substr = ln.substr(ln.find("extern") + strlen("extern")); + kCompilerVariables.push_back({.fValue = substr}); + } + + if (kShouldHaveBraces && ln.find('{') == std::string::npos) + { + err_str += "Missing '{' for function "; + err_str += kFnName; + err_str += "\n"; + + kShouldHaveBraces = false; + kFnName.clear(); + } + else if (kShouldHaveBraces && ln.find('{') != std::string::npos) + { + kShouldHaveBraces = false; + kFnName.clear(); + } + + bool type_not_found = true; + + if (ln.find('\'') != std::string::npos) + { + ln.replace(ln.find('\''), 3, "0"); + } + + auto first = ln.find('"'); + if (first != std::string::npos) + { + auto second = 0UL; + bool found_second_quote = false; + + for (size_t i = first + 1; i < ln.size(); ++i) + { + if (ln[i] == '\"') + { + found_second_quote = true; + second = i; + + break; + } + } + + if (!found_second_quote) + { + err_str += "Missing terminating \"."; + err_str += " here -> " + ln.substr(ln.find('"'), second); + } + } + + if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos) + { + if (ln.find('{') == std::string::npos) + { + kFnName = ln; + kShouldHaveBraces = true; + + goto skip_braces_check; + } + else if (ln.find('{') != std::string::npos) + { + kShouldHaveBraces = false; + } + } + +skip_braces_check: + + for (auto& key : kCompilerTypes) + { + if (ParserKit::find_word(ln, key.fName)) + { + if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) + { + err_str += "\nNumber cannot be set for "; + err_str += key.fName; + err_str += "'s name. here -> "; + err_str += ln; + } + + if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' || + ln[ln.find(key.fName) - 1] == '\t') + { + type_not_found = false; + + if (ln[ln.find(key.fName) + key.fName.size()] != ' ') + { + type_not_found = true; + + if (ln[ln.find(key.fName) + key.fName.size()] == '\t') + type_not_found = false; + + goto next; + } + else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') + { + type_not_found = true; + + if (ln[ln.find(key.fName) + key.fName.size()] == ' ') + type_not_found = false; + } + } + + next: + + if (ln.find(';') == std::string::npos) + { + if (ln.find('(') != std::string::npos) + { + if (ln.find('=') == std::string::npos) + continue; + } + + err_str += "\nMissing ';', here -> "; + err_str += ln; + } + else + { + continue; + } + + if (ln.find('=') != std::string::npos) + { + if (ln.find('(') != std::string::npos) + { + if (ln.find(')') == std::string::npos) + { + err_str += "\nMissing ')', after '(' here -> "; + err_str += ln.substr(ln.find('(')); + } + } + } + } + } + + if (kInBraces && ln.find("struct") != std::string::npos && + ln.find("union") != std::string::npos && + ln.find("enum") != std::string::npos && + ln.find('=') != std::string::npos) + { + if (ln.find(';') == std::string::npos) + { + err_str += "\nMissing ';' after struct/union/enum declaration, here -> "; + err_str += ln; + } + } + + if (ln.find(';') != std::string::npos && + ln.find("for") == std::string::npos) + { + if (ln.find(';') + 1 != ln.size()) + { + for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) + { + if ((ln.substr(ln.find(';') + 1)[i] != ' ') || + (ln.substr(ln.find(';') + 1)[i] != '\t')) + { + if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); + !err.empty()) + { + err_str += "\nUnexpected text after ';' -> "; + err_str += ln.substr(ln.find(';')); + err_str += err; + } + } + } + } + } + + if (ln.find('(') != std::string::npos) + { + if (ln.find(';') == std::string::npos && !ParserKit::find_word(ln, "|") && + !ParserKit::find_word(ln, "||") && !ParserKit::find_word(ln, "&") && + !ParserKit::find_word(ln, "&&") && !ParserKit::find_word(ln, "~")) + { + bool found_func = false; + size_t i = ln.find('('); + std::vector opens; + std::vector closes; + + for (; i < ln.size(); ++i) + { + if (ln[i] == ')') + { + closes.push_back(1); + } + + if (ln[i] == '(') + { + opens.push_back(1); + } + } + + if (closes.size() != opens.size()) + err_str += "Unterminated (), here -> " + ln; + + bool space_found = false; + + for (int i = 0; i < ln.size(); ++i) + { + if (ln[i] == ')' && !space_found) + { + space_found = true; + continue; + } + + if (space_found) + { + if (ln[i] == ' ' && isalnum(ln[i + 1])) + { + err_str += "\nBad function format here -> "; + err_str += ln; + } + } + } + } + + if (ln.find('(') < 1) + { + err_str += "\nMissing identifier before '(' here -> "; + err_str += ln; + } + else + { + if (type_not_found && ln.find(';') == std::string::npos && + ln.find("if") == std::string::npos && + ln.find("|") == std::string::npos && + ln.find("&") == std::string::npos && + ln.find("(") == std::string::npos && + ln.find(")") == std::string::npos) + { + err_str += "\n Missing ';' or type, here -> "; + err_str += ln; + } + } + + if (ln.find(')') == std::string::npos) + { + err_str += "\nMissing ')', after '(' here -> "; + err_str += ln.substr(ln.find('(')); + } + } + else + { + if (ln.find("for") != std::string::npos || + ln.find("while") != std::string::npos) + { + err_str += "\nMissing '(', after \"for\", here -> "; + err_str += ln; + } + } + + if (ln.find('}') != std::string::npos && !kInBraces) + { + if (!kInStruct && ln.find(';') == std::string::npos) + { + err_str += "\nMismatched '}', here -> "; + err_str += ln; + } + } + + if (!ln.empty()) + { + if (ln.find(';') == std::string::npos && + ln.find('{') == std::string::npos && + ln.find('}') == std::string::npos && + ln.find(')') == std::string::npos && + ln.find('(') == std::string::npos && + ln.find(',') == std::string::npos) + { + if (ln.size() <= 2) + return err_str; + + err_str += "\nMissing ';', here -> "; + err_str += ln; + } + } + + return err_str; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +/** + * @brief C To Assembly mount-point. + */ + +///////////////////////////////////////////////////////////////////////////////////////// + +class AssemblyMountpointCLang final : public CompilerKit::AssemblyInterface +{ +public: + explicit AssemblyMountpointCLang() = default; + ~AssemblyMountpointCLang() override = default; + + MPCC_COPY_DEFAULT(AssemblyMountpointCLang); + + [[maybe_unused]] static Int32 Arch() noexcept + { + return CompilerKit::AssemblyFactory::kArchPowerPC; + } + + Int32 CompileToFormat(std::string& src, Int32 arch) override + { + if (arch != AssemblyMountpointCLang::Arch()) + return -1; + + if (kCompilerBackend == nullptr) + return -1; + + /* @brief copy contents wihtout extension */ + std::string src_file = src.data(); + std::ifstream src_fp = std::ifstream(src_file, std::ios::in); + std::string dest; + + for (auto& ch : src_file) + { + if (ch == '.') + { + break; + } + + dest += ch; + } + + /* According to PEF ABI. */ + std::vector exts = kAsmFileExts; + dest += exts[4]; + + kState.fOutputAssembly = std::make_unique(dest); + + auto fmt = CompilerKit::current_date(); + + (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; + (*kState.fOutputAssembly) + << "# Language: POWER Assembly (Generated from C)\n"; + (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n"; + + ParserKit::SyntaxLeafList syntax; + + kState.fSyntaxTreeList.push_back(syntax); + kState.fSyntaxTree = + &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; + + std::string line_src; + + while (std::getline(src_fp, line_src)) + { + if (auto err = kCompilerBackend->Check(line_src.c_str(), src.data()); + err.empty()) + { + kCompilerBackend->Compile(line_src, src.data()); + } + else + { + detail::print_error(err, src.data()); + } + } + + if (kAcceptableErrors > 0) + return -1; + + std::vector keywords = {"ld", "stw", "add", "sub", "or"}; + + /// + /// Replace, optimize, fix assembly output. + /// + + for (auto& leaf : kState.fSyntaxTree->fLeafList) + { + std::vector access_keywords = {"->", "."}; + + for (auto& access_ident : access_keywords) + { + if (ParserKit::find_word(leaf.fUserValue, access_ident)) + { + for (auto& struc : kState.kStructMap) + { + /// TODO: + } + } + } + + for (auto& keyword : keywords) + { + if (ParserKit::find_word(leaf.fUserValue, keyword)) + { + std::size_t cnt = 0UL; + + for (auto& reg : kState.kStackFrame) + { + std::string needle; + + for (size_t i = 0; i < reg.fName.size(); i++) + { + if (reg.fName[i] == ' ') + { + ++i; + + for (; i < reg.fName.size(); i++) + { + if (reg.fName[i] == ',') + { + break; + } + + if (reg.fName[i] == ' ') + continue; + + needle += reg.fName[i]; + } + + break; + } + } + + if (ParserKit::find_word(leaf.fUserValue, needle)) + { + if (leaf.fUserValue.find("import ") != std::string::npos) + { + std::string range = "import "; + leaf.fUserValue.replace(leaf.fUserValue.find(range), + range.size(), ""); + } + + if (leaf.fUserValue.find("ldw r6") != std::string::npos) + { + std::string::difference_type countComma = std::count( + leaf.fUserValue.begin(), leaf.fUserValue.end(), ','); + + if (countComma == 1) + { + leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), + strlen("ldw"), "mr"); + } + } + + leaf.fUserValue.replace(leaf.fUserValue.find(needle), + needle.size(), reg.fReg); + + ++cnt; + } + } + + if (cnt > 1 && keyword != "mr" && keyword != "add" && + keyword != "dec") + { + leaf.fUserValue.replace(leaf.fUserValue.find(keyword), + keyword.size(), "mr"); + } + } + } + } + + for (auto& leaf : kState.fSyntaxTree->fLeafList) + { + (*kState.fOutputAssembly) << leaf.fUserValue; + } + + kState.fSyntaxTree = nullptr; + + kState.fOutputAssembly->flush(); + kState.fOutputAssembly.reset(); + + return kOk; + } +}; + +///////////////////////////////////////////////////////////////////////////////////////// + +#include + +#define kPrintF printf +#define kSplashCxx() \ + kPrintF(kWhite "cc, %s, (c) ZKA Technologies\n", kDistVersion) + +static void cc_print_help() +{ + kSplashCxx(); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +#define kExt ".c" + +NDK_MODULE(NewOSCompilerCLangPowerPC) +{ + kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); + kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); + kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); + kCompilerTypes.push_back({.fName = "int", .fValue = "dword"}); + kCompilerTypes.push_back({.fName = "long", .fValue = "qword"}); + kCompilerTypes.push_back({.fName = "*", .fValue = "offset"}); + + bool skip = false; + + kFactory.Mount(new AssemblyMountpointCLang()); + kMachine = CompilerKit::AssemblyFactory::kArchPowerPC; + kCompilerBackend = new CompilerBackendCLang(); + + for (auto index = 1UL; index < argc; ++index) + { + if (skip) + { + skip = false; + continue; + } + + if (argv[index][0] == '-') + { + if (strcmp(argv[index], "-v") == 0 || + strcmp(argv[index], "-version") == 0) + { + kSplashCxx(); + return kOk; + } + + if (strcmp(argv[index], "-verbose") == 0) + { + kState.fVerbose = true; + + continue; + } + + if (strcmp(argv[index], "-h") == 0 || strcmp(argv[index], "-help") == 0) + { + cc_print_help(); + + return kOk; + } + + if (strcmp(argv[index], "-dialect") == 0) + { + if (kCompilerBackend) + std::cout << kCompilerBackend->Language() << "\n"; + + return kOk; + } + + if (strcmp(argv[index], "-fmax-exceptions") == 0) + { + try + { + kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); + } + // catch anything here + catch (...) + { + kErrorLimit = 0; + } + + skip = true; + + continue; + } + + std::string err = "Unknown command: "; + err += argv[index]; + + detail::print_error(err, "cc"); + + continue; + } + + kFileList.emplace_back(argv[index]); + + std::string srcFile = argv[index]; + + if (strstr(argv[index], kExt) == nullptr) + { + if (kState.fVerbose) + { + detail::print_error(srcFile + " is not a valid C source.\n", "cc"); + } + + return 1; + } + + if (kFactory.Compile(srcFile, kMachine) != kOk) + return -1; + } + + return kOk; +} + +// Last rev 8-1-24 diff --git a/Sources/ppcasm.cc b/Sources/ppcasm.cc deleted file mode 100644 index 5f015d5..0000000 --- a/Sources/ppcasm.cc +++ /dev/null @@ -1,976 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -///////////////////////////////////////////////////////////////////////////////////////// - -/// @file ppcasm.cxx -/// @author Amlal EL Mahrouss -/// @brief POWER Assembler. - -/// REMINDER: when dealing with an undefined symbol use (string -/// size):LinkerFindSymbol:(string) so that li will look for it. - -///////////////////////////////////////////////////////////////////////////////////////// - -#define __ASM_NEED_PPC__ 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -///////////////////// - -// ANSI ESCAPE CODES - -///////////////////// - -#define kBlank "\e[0;30m" -#define kRed "\e[0;31m" -#define kWhite "\e[0;97m" -#define kYellow "\e[0;33m" - -#define kStdOut (std::cout << kWhite) -#define kStdErr (std::cout << kRed) - -constexpr auto cPowerIPAlignment = 0x4U; - -static CharType kOutputArch = CompilerKit::kPefArchPowerPC; -static Boolean kOutputAsBinary = false; - -static UInt32 kErrorLimit = 10; -static UInt32 kAcceptableErrors = 0; - -static std::size_t kCounter = 1UL; - -static std::uintptr_t kOrigin = kPefBaseOrigin; -static std::vector> kOriginLabel; - -static bool kVerbose = false; - -static std::vector kBytes; - -static CompilerKit::AERecordHeader kCurrentRecord{ - .fName = "", .fKind = CompilerKit::kPefCode, .fSize = 0, .fOffset = 0}; - -static std::vector kRecords; -static std::vector kUndefinedSymbols; - -static const std::string kUndefinedSymbol = ":UndefinedSymbol:"; -static const std::string kRelocSymbol = ":RuntimeSymbol:"; - -// \brief forward decl. -static bool asm_read_attributes(std::string &line); - -namespace detail { -void print_error(std::string reason, const std::string &file) noexcept { - if (reason[0] == '\n') reason.erase(0, 1); - - kStdErr << kRed << "[ ppcasm ] " << kWhite - << ((file == "ppcasm") ? "internal assembler error " - : ("in file, " + file)) - << kBlank << std::endl; - kStdErr << kRed << "[ ppcasm ] " << kWhite << reason << kBlank << std::endl; - - if (kAcceptableErrors > kErrorLimit) std::exit(3); - - ++kAcceptableErrors; -} - -void print_warning(std::string reason, const std::string &file) noexcept { - if (reason[0] == '\n') reason.erase(0, 1); - - if (!file.empty()) { - kStdOut << kYellow << "[ file ] " << kWhite << file << kBlank << std::endl; - } - - kStdOut << kYellow << "[ ppcasm ] " << kWhite << reason << kBlank - << std::endl; -} -} // namespace detail - -/// Do not move it on top! it uses the assembler detail namespace! -#include - -///////////////////////////////////////////////////////////////////////////////////////// - -/// @brief POWER assembler entrypoint, the program/module starts here. - -///////////////////////////////////////////////////////////////////////////////////////// - -NDK_MODULE(NewOSAssemblerPowerPC) { - for (size_t i = 1; i < argc; ++i) { - if (argv[i][0] == '/') { - if (strcmp(argv[i], "/version") == 0 || strcmp(argv[i], "/v") == 0) { - kStdOut << "ppcasm: POWER64 Assembler Driver.\nppcasm: " << kDistVersion << "\nppcasm: " - "Copyright (c) " - "ZKA Technologies.\n"; - return 0; - } else if (strcmp(argv[i], "/h") == 0) { - kStdOut << "ppcasm: POWER64 Assembler Driver.\nppcasm: Copyright (c) 2024 " - "ZKA Technologies.\n"; - kStdOut << "/version,/v: print program version.\n"; - kStdOut << "/verbose: print verbose output.\n"; - kStdOut << "/binary: output as flat binary.\n"; - - return 0; - } else if (strcmp(argv[i], "/binary") == 0) { - kOutputAsBinary = true; - continue; - } else if (strcmp(argv[i], "/verbose") == 0) { - kVerbose = true; - continue; - } - - kStdOut << "ppcasm: ignore " << argv[i] << "\n"; - continue; - } - - if (!std::filesystem::exists(argv[i])) { - kStdOut << "ppcasm: can't open: " << argv[i] << std::endl; - goto asm_fail_exit; - } - - std::string object_output(argv[i]); - - for (auto &ext : kAsmFileExts) { - if (object_output.find(ext) != std::string::npos) { - object_output.erase(object_output.find(ext), std::strlen(ext)); - } - } - - object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt; - - std::ifstream file_ptr(argv[i]); - std::ofstream file_ptr_out(object_output, std::ofstream::binary); - - if (file_ptr_out.bad()) { - if (kVerbose) { - kStdOut << "ppcasm: error: " << strerror(errno) << "\n"; - } - } - - std::string line; - - CompilerKit::AEHeader hdr{0}; - - memset(hdr.fPad, kAEInvalidOpcode, kAEPad); - - hdr.fMagic[0] = kAEMag0; - hdr.fMagic[1] = kAEMag1; - hdr.fSize = sizeof(CompilerKit::AEHeader); - hdr.fArch = kOutputArch; - - ///////////////////////////////////////////////////////////////////////////////////////// - - // COMPILATION LOOP - - ///////////////////////////////////////////////////////////////////////////////////////// - - CompilerKit::EncoderPowerPC asm64; - - while (std::getline(file_ptr, line)) { - if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) { - detail::print_error(ln, argv[i]); - continue; - } - - try { - asm_read_attributes(line); - asm64.WriteLine(line, argv[i]); - } catch (const std::exception &e) { - if (kVerbose) { - std::string what = e.what(); - detail::print_warning("exit because of: " + what, "ppcasm"); - } - - std::filesystem::remove(object_output); - goto asm_fail_exit; - } - } - - if (!kOutputAsBinary) { - if (kVerbose) { - kStdOut << "ppcasm: Writing object file...\n"; - } - - // this is the final step, write everything to the file. - - auto pos = file_ptr_out.tellp(); - - hdr.fCount = kRecords.size() + kUndefinedSymbols.size(); - - file_ptr_out << hdr; - - if (kRecords.empty()) { - kStdErr << "ppcasm: At least one record is needed to write an object " - "file.\nppcasm: Make one using `export .code64 foo_bar`.\n"; - - std::filesystem::remove(object_output); - return -1; - } - - kRecords[kRecords.size() - 1].fSize = kBytes.size(); - - std::size_t record_count = 0UL; - - for (auto &record_hdr : kRecords) { - record_hdr.fFlags |= CompilerKit::kKindRelocationAtRuntime; - record_hdr.fOffset = record_count; - ++record_count; - - file_ptr_out << record_hdr; - - if (kVerbose) - kStdOut << "ppcasm: Wrote record " << record_hdr.fName << "...\n"; - } - - // increment once again, so that we won't lie about the kUndefinedSymbols. - ++record_count; - - for (auto &sym : kUndefinedSymbols) { - CompilerKit::AERecordHeader undefined_sym{0}; - - if (kVerbose) - kStdOut << "ppcasm: Wrote symbol " << sym << " to file...\n"; - - undefined_sym.fKind = kAEInvalidOpcode; - undefined_sym.fSize = sym.size(); - undefined_sym.fOffset = record_count; - - ++record_count; - - memset(undefined_sym.fPad, kAEInvalidOpcode, kAEPad); - memcpy(undefined_sym.fName, sym.c_str(), sym.size()); - - file_ptr_out << undefined_sym; - - ++kCounter; - } - - auto pos_end = file_ptr_out.tellp(); - - file_ptr_out.seekp(pos); - - hdr.fStartCode = pos_end; - hdr.fCodeSize = kBytes.size(); - - file_ptr_out << hdr; - - file_ptr_out.seekp(pos_end); - } else { - if (kVerbose) { - kStdOut << "ppcasm: Write raw binary...\n"; - } - } - - // byte from byte, we write this. - for (auto &byte : kBytes) { - file_ptr_out.write(reinterpret_cast(&byte), sizeof(byte)); - } - - if (kVerbose) kStdOut << "ppcasm: Wrote file with program in it.\n"; - - file_ptr_out.flush(); - file_ptr_out.close(); - - if (kVerbose) kStdOut << "ppcasm: Exit succeeded.\n"; - - return 0; - } - -asm_fail_exit: - - if (kVerbose) kStdOut << "ppcasm: Exit failed.\n"; - - return MPCC_EXEC_ERROR; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief Check for attributes -// returns true if any was found. - -///////////////////////////////////////////////////////////////////////////////////////// - -static bool asm_read_attributes(std::string &line) { - // import is the opposite of export, it signals to the li - // that we need this symbol. - if (ParserKit::find_word(line, "import")) { - if (kOutputAsBinary) { - detail::print_error("Invalid import directive in flat binary mode.", - "ppcasm"); - throw std::runtime_error("invalid_import_bin"); - } - - auto name = line.substr(line.find("import") + strlen("import") + 1); - - if (name.size() == 0) { - detail::print_error("Invalid import", "ppcasm"); - throw std::runtime_error("invalid_import"); - } - - std::string result = std::to_string(name.size()); - result += kUndefinedSymbol; - - // mangle this - for (char &j : name) { - if (j == ' ' || j == ',') j = '$'; - } - - result += name; - - if (name.find(".code64") != std::string::npos) { - // data is treated as code. - kCurrentRecord.fKind = CompilerKit::kPefCode; - } else if (name.find(".data64") != std::string::npos) { - // no code will be executed from here. - kCurrentRecord.fKind = CompilerKit::kPefData; - } else if (name.find(".zero64") != std::string::npos) { - // this is a bss section. - kCurrentRecord.fKind = CompilerKit::kPefZero; - } - - // this is a special case for the start stub. - // we want this so that li can find it. - - if (name == kPefStart) { - kCurrentRecord.fKind = CompilerKit::kPefCode; - } - - // now we can tell the code size of the previous kCurrentRecord. - - if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); - - memset(kCurrentRecord.fName, 0, kAESymbolLen); - memcpy(kCurrentRecord.fName, result.c_str(), result.size()); - - ++kCounter; - - memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); - - kRecords.emplace_back(kCurrentRecord); - - return true; - } - // export is a special keyword used by ppcasm to tell the AE output stage to - // mark this section as a header. it currently supports .code64, .data64., - // .zero64 - else if (ParserKit::find_word(line, "export")) { - if (kOutputAsBinary) { - detail::print_error("Invalid export directive in flat binary mode.", - "ppcasm"); - throw std::runtime_error("invalid_export_bin"); - } - - auto name = line.substr(line.find("export") + strlen("export")); - - std::string name_copy = name; - - for (char &j : name) { - if (j == ' ') j = '$'; - } - - if (name.find(".code64") != std::string::npos) { - // data is treated as code. - - name_copy.erase(name_copy.find(".code64"), strlen(".code64")); - kCurrentRecord.fKind = CompilerKit::kPefCode; - } else if (name.find(".data64") != std::string::npos) { - // no code will be executed from here. - - name_copy.erase(name_copy.find(".data64"), strlen(".data64")); - kCurrentRecord.fKind = CompilerKit::kPefData; - } else if (name.find(".zero64") != std::string::npos) { - // this is a bss section. - - name_copy.erase(name_copy.find(".zero64"), strlen(".zero64")); - kCurrentRecord.fKind = CompilerKit::kPefZero; - } - - // this is a special case for the start stub. - // we want this so that li can find it. - - if (name == kPefStart) { - kCurrentRecord.fKind = CompilerKit::kPefCode; - } - - while (name_copy.find(" ") != std::string::npos) - name_copy.erase(name_copy.find(" "), 1); - - kOriginLabel.push_back(std::make_pair(name_copy, kOrigin)); - ++kOrigin; - - // now we can tell the code size of the previous kCurrentRecord. - - if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); - - memset(kCurrentRecord.fName, 0, kAESymbolLen); - memcpy(kCurrentRecord.fName, name.c_str(), name.size()); - - ++kCounter; - - memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); - - kRecords.emplace_back(kCurrentRecord); - - return true; - } - - return false; -} - -// \brief algorithms and helpers. - -namespace detail::algorithm { -// \brief authorize a brief set of characters. -static inline bool is_not_alnum_space(char c) { - return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || - (c == ',') || (c == '(') || (c == ')') || (c == '"') || - (c == '\'') || (c == '[') || (c == ']') || (c == '+') || - (c == '_') || (c == ':') || (c == '@') || (c == '.')); -} - -bool is_valid(const std::string &str) { - return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); -} -} // namespace detail::algorithm - -///////////////////////////////////////////////////////////////////////////////////////// - -// @brief Check for line (syntax check) - -///////////////////////////////////////////////////////////////////////////////////////// - -std::string CompilerKit::EncoderPowerPC::CheckLine(std::string &line, - const std::string &file) { - std::string err_str; - - if (line.empty() || ParserKit::find_word(line, "import") || - ParserKit::find_word(line, "export") || - line.find('#') != std::string::npos || ParserKit::find_word(line, ";")) { - if (line.find('#') != std::string::npos) { - line.erase(line.find('#')); - } else if (line.find(';') != std::string::npos) { - line.erase(line.find(';')); - } else { - /// does the line contains valid input? - if (!detail::algorithm::is_valid(line)) { - err_str = "Line contains non alphanumeric characters.\nhere -> "; - err_str += line; - } - } - - return err_str; - } - - if (!detail::algorithm::is_valid(line)) { - err_str = "Line contains non alphanumeric characters.\nhere -> "; - err_str += line; - - return err_str; - } - - // check for a valid instruction format. - - if (line.find(',') != std::string::npos) { - if (line.find(',') + 1 == line.size()) { - err_str += "\nInstruction lacks right register, here -> "; - err_str += line.substr(line.find(',')); - - return err_str; - } else { - bool nothing_on_right = true; - - if (line.find(',') + 1 > line.size()) { - err_str += "\nInstruction not complete, here -> "; - err_str += line; - - return err_str; - } - - auto substr = line.substr(line.find(',') + 1); - - for (auto &ch : substr) { - if (ch != ' ' && ch != '\t') { - nothing_on_right = false; - } - } - - // this means we found nothing after that ',' . - if (nothing_on_right) { - err_str += "\nInstruction not complete, here -> "; - err_str += line; - - return err_str; - } - } - } - - // these do take an argument. - std::vector operands_inst = {"stw", "li"}; - - // these don't. - std::vector filter_inst = {"blr", "bl", "sc"}; - - for (auto &opcodePPC : kOpcodesPowerPC) { - if (ParserKit::find_word(line, opcodePPC.name)) { - for (auto &op : operands_inst) { - // if only the instruction was found. - if (line == op) { - err_str += "\nMalformed "; - err_str += op; - err_str += " instruction, here -> "; - err_str += line; - } - } - - // if it is like that -> addr1, 0x0 - if (auto it = - std::find(filter_inst.begin(), filter_inst.end(), opcodePPC.name); - it == filter_inst.cend()) { - if (ParserKit::find_word(line, opcodePPC.name)) { - if (!isspace( - line[line.find(opcodePPC.name) + strlen(opcodePPC.name)])) { - err_str += "\nMissing space between "; - err_str += opcodePPC.name; - err_str += " and operands.\nhere -> "; - err_str += line; - } - } - } - - return err_str; - } - } - - err_str += "Unrecognized instruction: " + line; - - return err_str; -} - -bool CompilerKit::EncoderPowerPC::WriteNumber(const std::size_t &pos, - std::string &jump_label) { - if (!isdigit(jump_label[pos])) return false; - - switch (jump_label[pos + 1]) { - case 'x': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); - !res) { - if (errno != 0) { - detail::print_error("invalid hex number: " + jump_label, "ppcasm"); - throw std::runtime_error("invalid_hex"); - } - } - - CompilerKit::NumberCast64 num( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16)); - - for (char &i : num.number) { - kBytes.push_back(i); - } - - if (kVerbose) { - kStdOut << "ppcasm: found a base 16 number here: " - << jump_label.substr(pos) << "\n"; - } - - return true; - } - case 'b': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); - !res) { - if (errno != 0) { - detail::print_error("invalid binary number: " + jump_label, "ppcasm"); - throw std::runtime_error("invalid_bin"); - } - } - - CompilerKit::NumberCast64 num( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2)); - - if (kVerbose) { - kStdOut << "ppcasm: found a base 2 number here: " - << jump_label.substr(pos) << "\n"; - } - - for (char &i : num.number) { - kBytes.push_back(i); - } - - return true; - } - case 'o': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); - !res) { - if (errno != 0) { - detail::print_error("invalid octal number: " + jump_label, "ppcasm"); - throw std::runtime_error("invalid_octal"); - } - } - - CompilerKit::NumberCast64 num( - strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7)); - - if (kVerbose) { - kStdOut << "ppcasm: found a base 8 number here: " - << jump_label.substr(pos) << "\n"; - } - - for (char &i : num.number) { - kBytes.push_back(i); - } - - return true; - } - default: { - break; - } - } - - /* check for errno and stuff like that */ - if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) { - if (errno != 0) { - return false; - } - } - - CompilerKit::NumberCast64 num( - strtol(jump_label.substr(pos).c_str(), nullptr, 10)); - - for (char &i : num.number) { - kBytes.push_back(i); - } - - if (kVerbose) { - kStdOut << "ppcasm: found a base 10 number here: " << jump_label.substr(pos) - << "\n"; - } - - return true; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -/// @brief Read and write an instruction to the output array. - -///////////////////////////////////////////////////////////////////////////////////////// - -bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line, - const std::string &file) { - if (ParserKit::find_word(line, "export")) return true; - if (!detail::algorithm::is_valid(line)) return true; - - for (auto &opcodePPC : kOpcodesPowerPC) { - // strict check here - if (ParserKit::find_word(line, opcodePPC.name)) { - std::string name(opcodePPC.name); - std::string jump_label, cpy_jump_label; - std::vector found_registers_index; - - // check funct7 type. - switch (opcodePPC.ops->type) { - default: { - NumberCast32 num(opcodePPC.opcode); - - for (auto ch : num.number) { - kBytes.emplace_back(ch); - } - break; - } - case BADDR: - case PCREL: { - auto num = GetNumber32(line, name); - - kBytes.emplace_back(num.number[0]); - kBytes.emplace_back(num.number[1]); - kBytes.emplace_back(num.number[2]); - kBytes.emplace_back(0x48); - - break; - } - /// General purpose, float, vector operations. Everything that involve - /// registers. - case G0REG: - case FREG: - case VREG: - case GREG: { - // \brief how many registers we found. - std::size_t found_some_count = 0UL; - std::size_t register_count = 0UL; - std::string opcodeName = opcodePPC.name; - std::size_t register_sum = 0; - - NumberCast64 num(opcodePPC.opcode); - - for (size_t line_index = 0UL; line_index < line.size(); - line_index++) { - if (line[line_index] == kAsmRegisterPrefix[0] && - isdigit(line[line_index + 1])) { - std::string register_syntax = kAsmRegisterPrefix; - register_syntax += line[line_index + 1]; - - if (isdigit(line[line_index + 2])) - register_syntax += line[line_index + 2]; - - std::string reg_str; - reg_str += line[line_index + 1]; - - if (isdigit(line[line_index + 2])) - reg_str += line[line_index + 2]; - - // it ranges from r0 to r19 - // something like r190 doesn't exist in the instruction set. - if (isdigit(line[line_index + 3]) && - isdigit(line[line_index + 2])) { - reg_str += line[line_index + 3]; - detail::print_error( - "invalid register index, r" + reg_str + - "\nnote: The POWER accepts registers from r0 to r32.", - file); - throw std::runtime_error("invalid_register_index"); - } - - // finally cast to a size_t - std::size_t reg_index = strtol(reg_str.c_str(), nullptr, 10); - - if (reg_index > kAsmRegisterLimit) { - detail::print_error("invalid register index, r" + reg_str, - file); - throw std::runtime_error("invalid_register_index"); - } - - if (opcodeName == "li") { - char numIndex = 0; - - for (size_t i = 0; i != reg_index; i++) { - numIndex += 0x20; - } - - auto num = GetNumber32(line, reg_str); - - kBytes.push_back(num.number[0]); - kBytes.push_back(num.number[1]); - kBytes.push_back(numIndex); - kBytes.push_back(0x38); - - // check if bigger than two. - for (size_t i = 2; i < 4; i++) { - if (num.number[i] > 0) { - detail::print_warning("number overflow on li operation.", - file); - break; - } - } - - break; - } - - if ((opcodeName[0] == 's' && opcodeName[1] == 't')) { - if (register_sum == 0) { - for (size_t indexReg = 0UL; indexReg < reg_index; - ++indexReg) { - register_sum += 0x20; - } - } else { - register_sum += reg_index; - } - } - - if (opcodeName == "mr") { - switch (register_count) { - case 0: { - kBytes.push_back(0x78); - - char numIndex = 0x3; - - for (size_t i = 0; i != reg_index; i++) { - numIndex += 0x8; - } - - kBytes.push_back(numIndex); - - break; - } - case 1: { - char numIndex = 0x1; - - for (size_t i = 0; i != reg_index; i++) { - numIndex += 0x20; - } - - for (size_t i = 0; i != reg_index; i++) { - kBytes[kBytes.size() - 1] += 0x8; - } - - kBytes[kBytes.size() - 1] -= 0x8; - - kBytes.push_back(numIndex); - - if (reg_index >= 10 && reg_index < 20) - kBytes.push_back(0x7d); - else if (reg_index >= 20 && reg_index < 30) - kBytes.push_back(0x7e); - else if (reg_index >= 30) - kBytes.push_back(0x7f); - else - kBytes.push_back(0x7c); - - break; - } - default: - break; - } - - ++register_count; - ++found_some_count; - } - - if (opcodeName == "addi") { - if (found_some_count == 2 || found_some_count == 0) - kBytes.emplace_back(reg_index); - else if (found_some_count == 1) - kBytes.emplace_back(0x00); - - ++found_some_count; - - if (found_some_count > 3) { - detail::print_error("Too much registers. -> " + line, file); - throw std::runtime_error("too_much_regs"); - } - } - - if (opcodeName.find("cmp") != std::string::npos) { - ++found_some_count; - - if (found_some_count > 3) { - detail::print_error("Too much registers. -> " + line, file); - throw std::runtime_error("too_much_regs"); - } - } - - if (opcodeName.find("mf") != std::string::npos || - opcodeName.find("mt") != std::string::npos) { - char numIndex = 0; - - for (size_t i = 0; i != reg_index; i++) { - numIndex += 0x20; - } - - num.number[2] += numIndex; - - ++found_some_count; - - if (found_some_count > 1) { - detail::print_error("Too much registers. -> " + line, file); - throw std::runtime_error("too_much_regs"); - } - - if (kVerbose) { - kStdOut << "ppcasm: Found register: " << register_syntax - << "\n"; - kStdOut << "ppcasm: Amount of registers in instruction: " - << found_some_count << "\n"; - } - - if (reg_index >= 10 && reg_index < 20) - num.number[3] = 0x7d; - else if (reg_index >= 20 && reg_index < 30) - num.number[3] = 0x7e; - else if (reg_index >= 30) - num.number[3] = 0x7f; - else - num.number[3] = 0x7c; - - for (auto ch : num.number) { - kBytes.emplace_back(ch); - } - } - - found_registers_index.push_back(reg_index); - } - } - - if (opcodeName == "addi") { - kBytes.emplace_back(0x38); - } - - if (opcodeName.find("cmp") != std::string::npos) { - char rightReg = 0x0; - - for (size_t i = 0; i != found_registers_index[1]; i++) { - rightReg += 0x08; - } - - kBytes.emplace_back(0x00); - kBytes.emplace_back(rightReg); - kBytes.emplace_back(found_registers_index[0]); - kBytes.emplace_back(0x7c); - } - - if ((opcodeName[0] == 's' && opcodeName[1] == 't')) { - size_t offset = 0UL; - - if (line.find('+') != std::string::npos) { - auto number = GetNumber32(line.substr(line.find("+")), "+"); - offset = number.raw; - } - - kBytes.push_back(offset); - kBytes.push_back(0x00); - kBytes.push_back(register_sum); - - kBytes.emplace_back(0x90); - } - - if (opcodeName == "mr") { - if (register_count == 1) { - detail::print_error("Too few registers. -> " + line, file); - throw std::runtime_error("too_few_registers"); - } - } - - // we're not in immediate addressing, reg to reg. - if (opcodePPC.ops->type != GREG) { - // remember! register to register! - if (found_some_count == 1) { - detail::print_error( - "Unrecognized register found.\ntip: each ppcasm register " - "starts with 'r'.\nline: " + - line, - file); - - throw std::runtime_error("not_a_register"); - } - } - - if (found_some_count < 1 && name[0] != 'l' && name[0] != 's') { - detail::print_error( - "invalid combination of opcode and registers.\nline: " + line, - file); - throw std::runtime_error("invalid_comb_op_reg"); - } - - break; - } - } - - kOrigin += cPowerIPAlignment; - break; - } - } - - return true; -} - -// Last rev 13-1-24 diff --git a/Sources/ppcasm.cxx b/Sources/ppcasm.cxx new file mode 100644 index 0000000..01e8124 --- /dev/null +++ b/Sources/ppcasm.cxx @@ -0,0 +1,976 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +///////////////////////////////////////////////////////////////////////////////////////// + +/// @file ppcasm.cxx +/// @author Amlal EL Mahrouss +/// @brief POWER Assembler. + +/// REMINDER: when dealing with an undefined symbol use (string +/// size):LinkerFindSymbol:(string) so that li will look for it. + +///////////////////////////////////////////////////////////////////////////////////////// + +#define __ASM_NEED_PPC__ 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +///////////////////// + +// ANSI ESCAPE CODES + +///////////////////// + +#define kBlank "\e[0;30m" +#define kRed "\e[0;31m" +#define kWhite "\e[0;97m" +#define kYellow "\e[0;33m" + +#define kStdOut (std::cout << kWhite) +#define kStdErr (std::cout << kRed) + +constexpr auto cPowerIPAlignment = 0x4U; + +static CharType kOutputArch = CompilerKit::kPefArchPowerPC; +static Boolean kOutputAsBinary = false; + +static UInt32 kErrorLimit = 10; +static UInt32 kAcceptableErrors = 0; + +static std::size_t kCounter = 1UL; + +static std::uintptr_t kOrigin = kPefBaseOrigin; +static std::vector> kOriginLabel; + +static bool kVerbose = false; + +static std::vector kBytes; + +static CompilerKit::AERecordHeader kCurrentRecord{ + .fName = "", .fKind = CompilerKit::kPefCode, .fSize = 0, .fOffset = 0}; + +static std::vector kRecords; +static std::vector kUndefinedSymbols; + +static const std::string kUndefinedSymbol = ":UndefinedSymbol:"; +static const std::string kRelocSymbol = ":RuntimeSymbol:"; + +// \brief forward decl. +static bool asm_read_attributes(std::string &line); + +namespace detail { +void print_error(std::string reason, const std::string &file) noexcept { + if (reason[0] == '\n') reason.erase(0, 1); + + kStdErr << kRed << "[ ppcasm ] " << kWhite + << ((file == "ppcasm") ? "internal assembler error " + : ("in file, " + file)) + << kBlank << std::endl; + kStdErr << kRed << "[ ppcasm ] " << kWhite << reason << kBlank << std::endl; + + if (kAcceptableErrors > kErrorLimit) std::exit(3); + + ++kAcceptableErrors; +} + +void print_warning(std::string reason, const std::string &file) noexcept { + if (reason[0] == '\n') reason.erase(0, 1); + + if (!file.empty()) { + kStdOut << kYellow << "[ file ] " << kWhite << file << kBlank << std::endl; + } + + kStdOut << kYellow << "[ ppcasm ] " << kWhite << reason << kBlank + << std::endl; +} +} // namespace detail + +/// Do not move it on top! it uses the assembler detail namespace! +#include + +///////////////////////////////////////////////////////////////////////////////////////// + +/// @brief POWER assembler entrypoint, the program/module starts here. + +///////////////////////////////////////////////////////////////////////////////////////// + +NDK_MODULE(NewOSAssemblerPowerPC) { + for (size_t i = 1; i < argc; ++i) { + if (argv[i][0] == '/') { + if (strcmp(argv[i], "/version") == 0 || strcmp(argv[i], "/v") == 0) { + kStdOut << "ppcasm: POWER64 Assembler Driver.\nppcasm: " << kDistVersion << "\nppcasm: " + "Copyright (c) " + "ZKA Technologies.\n"; + return 0; + } else if (strcmp(argv[i], "/h") == 0) { + kStdOut << "ppcasm: POWER64 Assembler Driver.\nppcasm: Copyright (c) 2024 " + "ZKA Technologies.\n"; + kStdOut << "/version,/v: print program version.\n"; + kStdOut << "/verbose: print verbose output.\n"; + kStdOut << "/binary: output as flat binary.\n"; + + return 0; + } else if (strcmp(argv[i], "/binary") == 0) { + kOutputAsBinary = true; + continue; + } else if (strcmp(argv[i], "/verbose") == 0) { + kVerbose = true; + continue; + } + + kStdOut << "ppcasm: ignore " << argv[i] << "\n"; + continue; + } + + if (!std::filesystem::exists(argv[i])) { + kStdOut << "ppcasm: can't open: " << argv[i] << std::endl; + goto asm_fail_exit; + } + + std::string object_output(argv[i]); + + for (auto &ext : kAsmFileExts) { + if (object_output.find(ext) != std::string::npos) { + object_output.erase(object_output.find(ext), std::strlen(ext)); + } + } + + object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt; + + std::ifstream file_ptr(argv[i]); + std::ofstream file_ptr_out(object_output, std::ofstream::binary); + + if (file_ptr_out.bad()) { + if (kVerbose) { + kStdOut << "ppcasm: error: " << strerror(errno) << "\n"; + } + } + + std::string line; + + CompilerKit::AEHeader hdr{0}; + + memset(hdr.fPad, kAEInvalidOpcode, kAEPad); + + hdr.fMagic[0] = kAEMag0; + hdr.fMagic[1] = kAEMag1; + hdr.fSize = sizeof(CompilerKit::AEHeader); + hdr.fArch = kOutputArch; + + ///////////////////////////////////////////////////////////////////////////////////////// + + // COMPILATION LOOP + + ///////////////////////////////////////////////////////////////////////////////////////// + + CompilerKit::EncoderPowerPC asm64; + + while (std::getline(file_ptr, line)) { + if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) { + detail::print_error(ln, argv[i]); + continue; + } + + try { + asm_read_attributes(line); + asm64.WriteLine(line, argv[i]); + } catch (const std::exception &e) { + if (kVerbose) { + std::string what = e.what(); + detail::print_warning("exit because of: " + what, "ppcasm"); + } + + std::filesystem::remove(object_output); + goto asm_fail_exit; + } + } + + if (!kOutputAsBinary) { + if (kVerbose) { + kStdOut << "ppcasm: Writing object file...\n"; + } + + // this is the final step, write everything to the file. + + auto pos = file_ptr_out.tellp(); + + hdr.fCount = kRecords.size() + kUndefinedSymbols.size(); + + file_ptr_out << hdr; + + if (kRecords.empty()) { + kStdErr << "ppcasm: At least one record is needed to write an object " + "file.\nppcasm: Make one using `export .code64 foo_bar`.\n"; + + std::filesystem::remove(object_output); + return -1; + } + + kRecords[kRecords.size() - 1].fSize = kBytes.size(); + + std::size_t record_count = 0UL; + + for (auto &record_hdr : kRecords) { + record_hdr.fFlags |= CompilerKit::kKindRelocationAtRuntime; + record_hdr.fOffset = record_count; + ++record_count; + + file_ptr_out << record_hdr; + + if (kVerbose) + kStdOut << "ppcasm: Wrote record " << record_hdr.fName << "...\n"; + } + + // increment once again, so that we won't lie about the kUndefinedSymbols. + ++record_count; + + for (auto &sym : kUndefinedSymbols) { + CompilerKit::AERecordHeader undefined_sym{0}; + + if (kVerbose) + kStdOut << "ppcasm: Wrote symbol " << sym << " to file...\n"; + + undefined_sym.fKind = kAEInvalidOpcode; + undefined_sym.fSize = sym.size(); + undefined_sym.fOffset = record_count; + + ++record_count; + + memset(undefined_sym.fPad, kAEInvalidOpcode, kAEPad); + memcpy(undefined_sym.fName, sym.c_str(), sym.size()); + + file_ptr_out << undefined_sym; + + ++kCounter; + } + + auto pos_end = file_ptr_out.tellp(); + + file_ptr_out.seekp(pos); + + hdr.fStartCode = pos_end; + hdr.fCodeSize = kBytes.size(); + + file_ptr_out << hdr; + + file_ptr_out.seekp(pos_end); + } else { + if (kVerbose) { + kStdOut << "ppcasm: Write raw binary...\n"; + } + } + + // byte from byte, we write this. + for (auto &byte : kBytes) { + file_ptr_out.write(reinterpret_cast(&byte), sizeof(byte)); + } + + if (kVerbose) kStdOut << "ppcasm: Wrote file with program in it.\n"; + + file_ptr_out.flush(); + file_ptr_out.close(); + + if (kVerbose) kStdOut << "ppcasm: Exit succeeded.\n"; + + return 0; + } + +asm_fail_exit: + + if (kVerbose) kStdOut << "ppcasm: Exit failed.\n"; + + return MPCC_EXEC_ERROR; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief Check for attributes +// returns true if any was found. + +///////////////////////////////////////////////////////////////////////////////////////// + +static bool asm_read_attributes(std::string &line) { + // import is the opposite of export, it signals to the li + // that we need this symbol. + if (ParserKit::find_word(line, "import")) { + if (kOutputAsBinary) { + detail::print_error("Invalid import directive in flat binary mode.", + "ppcasm"); + throw std::runtime_error("invalid_import_bin"); + } + + auto name = line.substr(line.find("import") + strlen("import") + 1); + + if (name.size() == 0) { + detail::print_error("Invalid import", "ppcasm"); + throw std::runtime_error("invalid_import"); + } + + std::string result = std::to_string(name.size()); + result += kUndefinedSymbol; + + // mangle this + for (char &j : name) { + if (j == ' ' || j == ',') j = '$'; + } + + result += name; + + if (name.find(".code64") != std::string::npos) { + // data is treated as code. + kCurrentRecord.fKind = CompilerKit::kPefCode; + } else if (name.find(".data64") != std::string::npos) { + // no code will be executed from here. + kCurrentRecord.fKind = CompilerKit::kPefData; + } else if (name.find(".zero64") != std::string::npos) { + // this is a bss section. + kCurrentRecord.fKind = CompilerKit::kPefZero; + } + + // this is a special case for the start stub. + // we want this so that li can find it. + + if (name == kPefStart) { + kCurrentRecord.fKind = CompilerKit::kPefCode; + } + + // now we can tell the code size of the previous kCurrentRecord. + + if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); + + memset(kCurrentRecord.fName, 0, kAESymbolLen); + memcpy(kCurrentRecord.fName, result.c_str(), result.size()); + + ++kCounter; + + memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); + + kRecords.emplace_back(kCurrentRecord); + + return true; + } + // export is a special keyword used by ppcasm to tell the AE output stage to + // mark this section as a header. it currently supports .code64, .data64., + // .zero64 + else if (ParserKit::find_word(line, "export")) { + if (kOutputAsBinary) { + detail::print_error("Invalid export directive in flat binary mode.", + "ppcasm"); + throw std::runtime_error("invalid_export_bin"); + } + + auto name = line.substr(line.find("export") + strlen("export")); + + std::string name_copy = name; + + for (char &j : name) { + if (j == ' ') j = '$'; + } + + if (name.find(".code64") != std::string::npos) { + // data is treated as code. + + name_copy.erase(name_copy.find(".code64"), strlen(".code64")); + kCurrentRecord.fKind = CompilerKit::kPefCode; + } else if (name.find(".data64") != std::string::npos) { + // no code will be executed from here. + + name_copy.erase(name_copy.find(".data64"), strlen(".data64")); + kCurrentRecord.fKind = CompilerKit::kPefData; + } else if (name.find(".zero64") != std::string::npos) { + // this is a bss section. + + name_copy.erase(name_copy.find(".zero64"), strlen(".zero64")); + kCurrentRecord.fKind = CompilerKit::kPefZero; + } + + // this is a special case for the start stub. + // we want this so that li can find it. + + if (name == kPefStart) { + kCurrentRecord.fKind = CompilerKit::kPefCode; + } + + while (name_copy.find(" ") != std::string::npos) + name_copy.erase(name_copy.find(" "), 1); + + kOriginLabel.push_back(std::make_pair(name_copy, kOrigin)); + ++kOrigin; + + // now we can tell the code size of the previous kCurrentRecord. + + if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); + + memset(kCurrentRecord.fName, 0, kAESymbolLen); + memcpy(kCurrentRecord.fName, name.c_str(), name.size()); + + ++kCounter; + + memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); + + kRecords.emplace_back(kCurrentRecord); + + return true; + } + + return false; +} + +// \brief algorithms and helpers. + +namespace detail::algorithm { +// \brief authorize a brief set of characters. +static inline bool is_not_alnum_space(char c) { + return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || + (c == ',') || (c == '(') || (c == ')') || (c == '"') || + (c == '\'') || (c == '[') || (c == ']') || (c == '+') || + (c == '_') || (c == ':') || (c == '@') || (c == '.')); +} + +bool is_valid(const std::string &str) { + return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); +} +} // namespace detail::algorithm + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief Check for line (syntax check) + +///////////////////////////////////////////////////////////////////////////////////////// + +std::string CompilerKit::EncoderPowerPC::CheckLine(std::string &line, + const std::string &file) { + std::string err_str; + + if (line.empty() || ParserKit::find_word(line, "import") || + ParserKit::find_word(line, "export") || + line.find('#') != std::string::npos || ParserKit::find_word(line, ";")) { + if (line.find('#') != std::string::npos) { + line.erase(line.find('#')); + } else if (line.find(';') != std::string::npos) { + line.erase(line.find(';')); + } else { + /// does the line contains valid input? + if (!detail::algorithm::is_valid(line)) { + err_str = "Line contains non alphanumeric characters.\nhere -> "; + err_str += line; + } + } + + return err_str; + } + + if (!detail::algorithm::is_valid(line)) { + err_str = "Line contains non alphanumeric characters.\nhere -> "; + err_str += line; + + return err_str; + } + + // check for a valid instruction format. + + if (line.find(',') != std::string::npos) { + if (line.find(',') + 1 == line.size()) { + err_str += "\nInstruction lacks right register, here -> "; + err_str += line.substr(line.find(',')); + + return err_str; + } else { + bool nothing_on_right = true; + + if (line.find(',') + 1 > line.size()) { + err_str += "\nInstruction not complete, here -> "; + err_str += line; + + return err_str; + } + + auto substr = line.substr(line.find(',') + 1); + + for (auto &ch : substr) { + if (ch != ' ' && ch != '\t') { + nothing_on_right = false; + } + } + + // this means we found nothing after that ',' . + if (nothing_on_right) { + err_str += "\nInstruction not complete, here -> "; + err_str += line; + + return err_str; + } + } + } + + // these do take an argument. + std::vector operands_inst = {"stw", "li"}; + + // these don't. + std::vector filter_inst = {"blr", "bl", "sc"}; + + for (auto &opcodePPC : kOpcodesPowerPC) { + if (ParserKit::find_word(line, opcodePPC.name)) { + for (auto &op : operands_inst) { + // if only the instruction was found. + if (line == op) { + err_str += "\nMalformed "; + err_str += op; + err_str += " instruction, here -> "; + err_str += line; + } + } + + // if it is like that -> addr1, 0x0 + if (auto it = + std::find(filter_inst.begin(), filter_inst.end(), opcodePPC.name); + it == filter_inst.cend()) { + if (ParserKit::find_word(line, opcodePPC.name)) { + if (!isspace( + line[line.find(opcodePPC.name) + strlen(opcodePPC.name)])) { + err_str += "\nMissing space between "; + err_str += opcodePPC.name; + err_str += " and operands.\nhere -> "; + err_str += line; + } + } + } + + return err_str; + } + } + + err_str += "Unrecognized instruction: " + line; + + return err_str; +} + +bool CompilerKit::EncoderPowerPC::WriteNumber(const std::size_t &pos, + std::string &jump_label) { + if (!isdigit(jump_label[pos])) return false; + + switch (jump_label[pos + 1]) { + case 'x': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); + !res) { + if (errno != 0) { + detail::print_error("invalid hex number: " + jump_label, "ppcasm"); + throw std::runtime_error("invalid_hex"); + } + } + + CompilerKit::NumberCast64 num( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16)); + + for (char &i : num.number) { + kBytes.push_back(i); + } + + if (kVerbose) { + kStdOut << "ppcasm: found a base 16 number here: " + << jump_label.substr(pos) << "\n"; + } + + return true; + } + case 'b': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); + !res) { + if (errno != 0) { + detail::print_error("invalid binary number: " + jump_label, "ppcasm"); + throw std::runtime_error("invalid_bin"); + } + } + + CompilerKit::NumberCast64 num( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2)); + + if (kVerbose) { + kStdOut << "ppcasm: found a base 2 number here: " + << jump_label.substr(pos) << "\n"; + } + + for (char &i : num.number) { + kBytes.push_back(i); + } + + return true; + } + case 'o': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); + !res) { + if (errno != 0) { + detail::print_error("invalid octal number: " + jump_label, "ppcasm"); + throw std::runtime_error("invalid_octal"); + } + } + + CompilerKit::NumberCast64 num( + strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7)); + + if (kVerbose) { + kStdOut << "ppcasm: found a base 8 number here: " + << jump_label.substr(pos) << "\n"; + } + + for (char &i : num.number) { + kBytes.push_back(i); + } + + return true; + } + default: { + break; + } + } + + /* check for errno and stuff like that */ + if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) { + if (errno != 0) { + return false; + } + } + + CompilerKit::NumberCast64 num( + strtol(jump_label.substr(pos).c_str(), nullptr, 10)); + + for (char &i : num.number) { + kBytes.push_back(i); + } + + if (kVerbose) { + kStdOut << "ppcasm: found a base 10 number here: " << jump_label.substr(pos) + << "\n"; + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +/// @brief Read and write an instruction to the output array. + +///////////////////////////////////////////////////////////////////////////////////////// + +bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line, + const std::string &file) { + if (ParserKit::find_word(line, "export")) return true; + if (!detail::algorithm::is_valid(line)) return true; + + for (auto &opcodePPC : kOpcodesPowerPC) { + // strict check here + if (ParserKit::find_word(line, opcodePPC.name)) { + std::string name(opcodePPC.name); + std::string jump_label, cpy_jump_label; + std::vector found_registers_index; + + // check funct7 type. + switch (opcodePPC.ops->type) { + default: { + NumberCast32 num(opcodePPC.opcode); + + for (auto ch : num.number) { + kBytes.emplace_back(ch); + } + break; + } + case BADDR: + case PCREL: { + auto num = GetNumber32(line, name); + + kBytes.emplace_back(num.number[0]); + kBytes.emplace_back(num.number[1]); + kBytes.emplace_back(num.number[2]); + kBytes.emplace_back(0x48); + + break; + } + /// General purpose, float, vector operations. Everything that involve + /// registers. + case G0REG: + case FREG: + case VREG: + case GREG: { + // \brief how many registers we found. + std::size_t found_some_count = 0UL; + std::size_t register_count = 0UL; + std::string opcodeName = opcodePPC.name; + std::size_t register_sum = 0; + + NumberCast64 num(opcodePPC.opcode); + + for (size_t line_index = 0UL; line_index < line.size(); + line_index++) { + if (line[line_index] == kAsmRegisterPrefix[0] && + isdigit(line[line_index + 1])) { + std::string register_syntax = kAsmRegisterPrefix; + register_syntax += line[line_index + 1]; + + if (isdigit(line[line_index + 2])) + register_syntax += line[line_index + 2]; + + std::string reg_str; + reg_str += line[line_index + 1]; + + if (isdigit(line[line_index + 2])) + reg_str += line[line_index + 2]; + + // it ranges from r0 to r19 + // something like r190 doesn't exist in the instruction set. + if (isdigit(line[line_index + 3]) && + isdigit(line[line_index + 2])) { + reg_str += line[line_index + 3]; + detail::print_error( + "invalid register index, r" + reg_str + + "\nnote: The POWER accepts registers from r0 to r32.", + file); + throw std::runtime_error("invalid_register_index"); + } + + // finally cast to a size_t + std::size_t reg_index = strtol(reg_str.c_str(), nullptr, 10); + + if (reg_index > kAsmRegisterLimit) { + detail::print_error("invalid register index, r" + reg_str, + file); + throw std::runtime_error("invalid_register_index"); + } + + if (opcodeName == "li") { + char numIndex = 0; + + for (size_t i = 0; i != reg_index; i++) { + numIndex += 0x20; + } + + auto num = GetNumber32(line, reg_str); + + kBytes.push_back(num.number[0]); + kBytes.push_back(num.number[1]); + kBytes.push_back(numIndex); + kBytes.push_back(0x38); + + // check if bigger than two. + for (size_t i = 2; i < 4; i++) { + if (num.number[i] > 0) { + detail::print_warning("number overflow on li operation.", + file); + break; + } + } + + break; + } + + if ((opcodeName[0] == 's' && opcodeName[1] == 't')) { + if (register_sum == 0) { + for (size_t indexReg = 0UL; indexReg < reg_index; + ++indexReg) { + register_sum += 0x20; + } + } else { + register_sum += reg_index; + } + } + + if (opcodeName == "mr") { + switch (register_count) { + case 0: { + kBytes.push_back(0x78); + + char numIndex = 0x3; + + for (size_t i = 0; i != reg_index; i++) { + numIndex += 0x8; + } + + kBytes.push_back(numIndex); + + break; + } + case 1: { + char numIndex = 0x1; + + for (size_t i = 0; i != reg_index; i++) { + numIndex += 0x20; + } + + for (size_t i = 0; i != reg_index; i++) { + kBytes[kBytes.size() - 1] += 0x8; + } + + kBytes[kBytes.size() - 1] -= 0x8; + + kBytes.push_back(numIndex); + + if (reg_index >= 10 && reg_index < 20) + kBytes.push_back(0x7d); + else if (reg_index >= 20 && reg_index < 30) + kBytes.push_back(0x7e); + else if (reg_index >= 30) + kBytes.push_back(0x7f); + else + kBytes.push_back(0x7c); + + break; + } + default: + break; + } + + ++register_count; + ++found_some_count; + } + + if (opcodeName == "addi") { + if (found_some_count == 2 || found_some_count == 0) + kBytes.emplace_back(reg_index); + else if (found_some_count == 1) + kBytes.emplace_back(0x00); + + ++found_some_count; + + if (found_some_count > 3) { + detail::print_error("Too much registers. -> " + line, file); + throw std::runtime_error("too_much_regs"); + } + } + + if (opcodeName.find("cmp") != std::string::npos) { + ++found_some_count; + + if (found_some_count > 3) { + detail::print_error("Too much registers. -> " + line, file); + throw std::runtime_error("too_much_regs"); + } + } + + if (opcodeName.find("mf") != std::string::npos || + opcodeName.find("mt") != std::string::npos) { + char numIndex = 0; + + for (size_t i = 0; i != reg_index; i++) { + numIndex += 0x20; + } + + num.number[2] += numIndex; + + ++found_some_count; + + if (found_some_count > 1) { + detail::print_error("Too much registers. -> " + line, file); + throw std::runtime_error("too_much_regs"); + } + + if (kVerbose) { + kStdOut << "ppcasm: Found register: " << register_syntax + << "\n"; + kStdOut << "ppcasm: Amount of registers in instruction: " + << found_some_count << "\n"; + } + + if (reg_index >= 10 && reg_index < 20) + num.number[3] = 0x7d; + else if (reg_index >= 20 && reg_index < 30) + num.number[3] = 0x7e; + else if (reg_index >= 30) + num.number[3] = 0x7f; + else + num.number[3] = 0x7c; + + for (auto ch : num.number) { + kBytes.emplace_back(ch); + } + } + + found_registers_index.push_back(reg_index); + } + } + + if (opcodeName == "addi") { + kBytes.emplace_back(0x38); + } + + if (opcodeName.find("cmp") != std::string::npos) { + char rightReg = 0x0; + + for (size_t i = 0; i != found_registers_index[1]; i++) { + rightReg += 0x08; + } + + kBytes.emplace_back(0x00); + kBytes.emplace_back(rightReg); + kBytes.emplace_back(found_registers_index[0]); + kBytes.emplace_back(0x7c); + } + + if ((opcodeName[0] == 's' && opcodeName[1] == 't')) { + size_t offset = 0UL; + + if (line.find('+') != std::string::npos) { + auto number = GetNumber32(line.substr(line.find("+")), "+"); + offset = number.raw; + } + + kBytes.push_back(offset); + kBytes.push_back(0x00); + kBytes.push_back(register_sum); + + kBytes.emplace_back(0x90); + } + + if (opcodeName == "mr") { + if (register_count == 1) { + detail::print_error("Too few registers. -> " + line, file); + throw std::runtime_error("too_few_registers"); + } + } + + // we're not in immediate addressing, reg to reg. + if (opcodePPC.ops->type != GREG) { + // remember! register to register! + if (found_some_count == 1) { + detail::print_error( + "Unrecognized register found.\ntip: each ppcasm register " + "starts with 'r'.\nline: " + + line, + file); + + throw std::runtime_error("not_a_register"); + } + } + + if (found_some_count < 1 && name[0] != 'l' && name[0] != 's') { + detail::print_error( + "invalid combination of opcode and registers.\nline: " + line, + file); + throw std::runtime_error("invalid_comb_op_reg"); + } + + break; + } + } + + kOrigin += cPowerIPAlignment; + break; + } + } + + return true; +} + +// Last rev 13-1-24 diff --git a/codetools.files b/codetools.files index 211a290..d895485 100644 --- a/codetools.files +++ b/codetools.files @@ -1,29 +1,29 @@ .clang-format -Comm/AsmKit/AsmKit.hpp -Comm/AsmKit/CPU/32x0.hpp -Comm/AsmKit/CPU/64x0.hpp -Comm/AsmKit/CPU/amd64.hpp -Comm/AsmKit/CPU/arm64.hpp -Comm/AsmKit/CPU/ppc.hpp -Comm/CompilerKit.hpp -Comm/Defines.hpp -Comm/ParserKit.hpp -Comm/Public/SDK/CRT/__mpcc_alloca.hxx -Comm/Public/SDK/CRT/__mpcc_defines.hxx -Comm/Public/SDK/CRT/__mpcc_exception.hxx -Comm/Public/SDK/CRT/__mpcc_hint.hxx -Comm/Public/SDK/CRT/__mpcc_malloc.hxx -Comm/Public/SDK/CRT/__mpcc_power.inc -Comm/StdKit/AE.hpp -Comm/StdKit/ELF.hpp -Comm/StdKit/ErrorID.hpp -Comm/StdKit/ErrorOr.hpp -Comm/StdKit/PEF.hpp -Comm/StdKit/Ref.hpp -Comm/StdKit/String.hpp -Comm/StdKit/XCOFF.hxx -Comm/UUID.hpp -Comm/Version.hxx +Headers/AsmKit/AsmKit.hpp +Headers/AsmKit/CPU/32x0.hpp +Headers/AsmKit/CPU/64x0.hpp +Headers/AsmKit/CPU/amd64.hpp +Headers/AsmKit/CPU/arm64.hpp +Headers/AsmKit/CPU/ppc.hpp +Headers/Macros.hpp +Headers/Defines.hpp +Headers/ParserKit.hpp +Headers/Public/SDK/CRT/__mpcc_alloca.hxx +Headers/Public/SDK/CRT/__mpcc_defines.hxx +Headers/Public/SDK/CRT/__mpcc_exception.hxx +Headers/Public/SDK/CRT/__mpcc_hint.hxx +Headers/Public/SDK/CRT/__mpcc_malloc.hxx +Headers/Public/SDK/CRT/__mpcc_power.inc +Headers/StdKit/AE.hpp +Headers/StdKit/ELF.hpp +Headers/StdKit/ErrorID.hpp +Headers/StdKit/ErrorOr.hpp +Headers/StdKit/PEF.hpp +Headers/StdKit/Ref.hpp +Headers/StdKit/String.hpp +Headers/StdKit/XCOFF.hxx +Headers/UUID.hpp +Headers/Version.hxx Doc/asm-specs.txt Doc/havp.txt Doc/notice.txt @@ -33,29 +33,29 @@ Examples/Example64k.s Examples/ExampleAMD64.asm Examples/ExampleAMD64_Return.asm Examples/ExampleCDialect.S -Examples/ExampleCDialect.cc +Examples/ExampleCDialect.cxx Examples/ExampleCPlusPlus.cxx Examples/ExampleCPlusPlus.s Examples/ExamplePowerPC.S MailMap ReadMe.md -Sources/32asm.cc -Sources/64asm.cc -Sources/64x0-cc.cc -Sources/AssemblyFactory.cc +Sources/32asm.cxx +Sources/64asm.cxx +Sources/64x0-cc.cxx +Sources/AssemblyFactory.cxx Sources/Detail/ReadMe.md Sources/Detail/asmutils.hxx Sources/Detail/compilerutils.hxx -Sources/String.cc -Sources/bpp.cc -Sources/coff2ae.cc +Sources/String.cxx +Sources/bpp.cxx +Sources/coff2ae.cxx Sources/compile_flags.txt -Sources/cplusplus.cc -Sources/elf2ae.cc -Sources/i64asm.cc -Sources/link.cc -Sources/power-cc.cc -Sources/ppcasm.cc +Sources/cplusplus.cxx +Sources/elf2ae.cxx +Sources/i64asm.cxx +Sources/link.cxx +Sources/power-cc.cxx +Sources/ppcasm.cxx posix.make run_format.sh win64.make diff --git a/codetools.includes b/codetools.includes index a9a0fb5..cb0237d 100644 --- a/codetools.includes +++ b/codetools.includes @@ -1,2 +1,2 @@ -./Comm +./Headers ./ diff --git a/posix.make b/posix.make index 8a17a58..9a11054 100644 --- a/posix.make +++ b/posix.make @@ -7,42 +7,42 @@ # ======================================================== # -COMMON_INC=-I./Comm -I./ -I./Sources/Detail +COMMON_INC=-I./Headers -I./ -I./Sources/Detail LINK_CC=clang++ -std=c++20 -LINK_SRC=Sources/link.cc +LINK_SRC=Sources/link.cxx LINK_OUTPUT=Output/link LINK_ALT_OUTPUT=Output/64link LINK_ALT_3_OUTPUT=Output/i64link LINK_ALT_2_OUTPUT=Output/32link LINK_ALT_4_OUTPUT=Output/ppclink -PP_SRC=Sources/bpp.cc +PP_SRC=Sources/bpp.cxx PP_OUTPUT=Output/bpp -SRC_COMMON=Sources/String.cc Sources/AssemblyFactory.cc +SRC_COMMON=Sources/String.cxx Sources/AssemblyFactory.cxx # C++ Compiler (AMD64) -AMD64_CXX_SRC=Sources/cplusplus.cc $(SRC_COMMON) +AMD64_CXX_SRC=Sources/cplusplus.cxx $(SRC_COMMON) AMD64_CXX_OUTPUT=Output/cplusplus # C Compiler (POWER) -64X0_CC_SRC=Sources/64x0-cc.cc $(SRC_COMMON) +64X0_CC_SRC=Sources/64x0-cc.cxx $(SRC_COMMON) 64X0_CC_OUTPUT=Output/64x0-cc # C Compiler (Our own RISC) -PPC_CC_SRC=Sources/power-cc.cc $(SRC_COMMON) +PPC_CC_SRC=Sources/power-cc.cxx $(SRC_COMMON) PPC_CC_OUTPUT=Output/power-cc # 64x0 Assembler (Our Own RISC) -ASM_SRC=Sources/64asm.cc $(SRC_COMMON) +ASM_SRC=Sources/64asm.cxx $(SRC_COMMON) ASM_OUTPUT=Output/64asm # AMD64 Assembler (Intel CISC) -IASM_SRC=Sources/i64asm.cc $(SRC_COMMON) +IASM_SRC=Sources/i64asm.cxx $(SRC_COMMON) IASM_OUTPUT=Output/i64asm # Power4 Assembler (IBM RISC) -PPCASM_SRC=Sources/ppcasm.cc $(SRC_COMMON) +PPCASM_SRC=Sources/ppcasm.cxx $(SRC_COMMON) PPCASM_OUTPUT=Output/ppcasm .PHONY: all diff --git a/win64.make b/win64.make index 37d762a..70d9381 100644 --- a/win64.make +++ b/win64.make @@ -7,41 +7,41 @@ # ======================================================== # -COMMON_INC=-I./Comm -I./ -I./Sources/Detail +COMMON_INC=-I./Headers -I./ -I./Sources/Detail LINK_CC=clang++ -std=c++20 -Xlinker -s -LINK_SRC=Sources/link.cc +LINK_SRC=Sources/link.cxx LINK_OUTPUT=Output/link.exe LINK_ALT_OUTPUT=Output/64link.exe LINK_ALT_3_OUTPUT=Output/i64link.exe LINK_ALT_2_OUTPUT=Output/32link.exe -PP_SRC=Sources/bpp.cc +PP_SRC=Sources/bpp.cxx PP_OUTPUT=Output/bpp.exe -SRC_COMMON=Sources/String.cc Sources/AssemblyFactory.cc +SRC_COMMON=Sources/String.cxx Sources/AssemblyFactory.cxx # C++ Compiler (AMD64) -AMD64_CXX_SRC=Sources/cplusplus.cc $(SRC_COMMON) +AMD64_CXX_SRC=Sources/cplusplus.cxx $(SRC_COMMON) AMD64_CXX_OUTPUT=Output/cplusplus.exe # C Compiler (POWER) -64X0_CC_SRC=Sources/64x0-cc.cc $(SRC_COMMON) +64X0_CC_SRC=Sources/64x0-cc.cxx $(SRC_COMMON) 64X0_CC_OUTPUT=Output/64x0-cc.exe # C Compiler -PPC_CC_SRC=Sources/power-cc.cc $(SRC_COMMON) +PPC_CC_SRC=Sources/power-cc.cxx $(SRC_COMMON) PPC_CC_OUTPUT=Output/power-cc.exe # 64x0 Assembler -ASM_SRC=Sources/64asm.cc $(SRC_COMMON) +ASM_SRC=Sources/64asm.cxx $(SRC_COMMON) ASM_OUTPUT=Output/64asm.exe # AMD64 Assembler -IASM_SRC=Sources/i64asm.cc $(SRC_COMMON) +IASM_SRC=Sources/i64asm.cxx $(SRC_COMMON) IASM_OUTPUT=Output/i64asm.exe # POWER Assembler -PPCASM_SRC=Sources/ppcasm.cc $(SRC_COMMON) +PPCASM_SRC=Sources/ppcasm.cxx $(SRC_COMMON) PPCASM_OUTPUT=Output/ppcasm.exe .PHONY: all -- cgit v1.2.3