From 6cda526bd4efcee31b1ea7405dc46d7985ba64e6 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Thu, 4 Jan 2024 21:36:54 +0100 Subject: masm: fix assembler bug where addr1, 0x0 (add r1, 0x0) doesn't error out. cc/ccplus: minor compiler changes, will get to them very soon... refactor: rename C++Kit to CompilerKit. Signed-off-by: Amlal El Mahrouss --- C++Kit/AsmKit/Arch/32k.hpp | 92 ---------------- C++Kit/AsmKit/Arch/64k.hpp | 102 ------------------ C++Kit/AsmKit/AsmKit.cc | 47 -------- C++Kit/AsmKit/AsmKit.hpp | 63 ----------- C++Kit/Defines.hpp | 135 ----------------------- C++Kit/ParserKit.hpp | 87 --------------- C++Kit/StdKit/AE.hpp | 61 ----------- C++Kit/StdKit/ErrorID.hpp | 22 ---- C++Kit/StdKit/ErrorOr.hpp | 58 ---------- C++Kit/StdKit/PEF.hpp | 85 --------------- C++Kit/StdKit/Ref.hpp | 89 ---------------- C++Kit/StdKit/String.cc | 230 ---------------------------------------- C++Kit/StdKit/String.hpp | 72 ------------- CompilerDriver/.gitignore | 1 + CompilerDriver/cc.cc | 22 ++-- CompilerDriver/ccplus.cc | 136 ++++++++++++------------ CompilerDriver/cpp.cc | 38 +++---- CompilerDriver/ld.cc | 50 ++++----- CompilerDriver/makefile | 10 +- CompilerDriver/masm.cc | 121 ++++++++++++--------- CompilerKit/AsmKit/Arch/32k.hpp | 92 ++++++++++++++++ CompilerKit/AsmKit/Arch/64k.hpp | 102 ++++++++++++++++++ CompilerKit/AsmKit/AsmKit.cc | 47 ++++++++ CompilerKit/AsmKit/AsmKit.hpp | 63 +++++++++++ CompilerKit/Defines.hpp | 135 +++++++++++++++++++++++ CompilerKit/ParserKit.hpp | 93 ++++++++++++++++ CompilerKit/StdKit/AE.hpp | 61 +++++++++++ CompilerKit/StdKit/ErrorID.hpp | 22 ++++ CompilerKit/StdKit/ErrorOr.hpp | 58 ++++++++++ CompilerKit/StdKit/PEF.hpp | 85 +++++++++++++++ CompilerKit/StdKit/Ref.hpp | 89 ++++++++++++++++ CompilerKit/StdKit/String.cc | 230 ++++++++++++++++++++++++++++++++++++++++ CompilerKit/StdKit/String.hpp | 72 +++++++++++++ 33 files changed, 1349 insertions(+), 1321 deletions(-) delete mode 100644 C++Kit/AsmKit/Arch/32k.hpp delete mode 100644 C++Kit/AsmKit/Arch/64k.hpp delete mode 100644 C++Kit/AsmKit/AsmKit.cc delete mode 100644 C++Kit/AsmKit/AsmKit.hpp delete mode 100644 C++Kit/Defines.hpp delete mode 100644 C++Kit/ParserKit.hpp delete mode 100644 C++Kit/StdKit/AE.hpp delete mode 100644 C++Kit/StdKit/ErrorID.hpp delete mode 100644 C++Kit/StdKit/ErrorOr.hpp delete mode 100644 C++Kit/StdKit/PEF.hpp delete mode 100644 C++Kit/StdKit/Ref.hpp delete mode 100644 C++Kit/StdKit/String.cc delete mode 100644 C++Kit/StdKit/String.hpp create mode 100644 CompilerKit/AsmKit/Arch/32k.hpp create mode 100644 CompilerKit/AsmKit/Arch/64k.hpp create mode 100644 CompilerKit/AsmKit/AsmKit.cc create mode 100644 CompilerKit/AsmKit/AsmKit.hpp create mode 100644 CompilerKit/Defines.hpp create mode 100644 CompilerKit/ParserKit.hpp create mode 100644 CompilerKit/StdKit/AE.hpp create mode 100644 CompilerKit/StdKit/ErrorID.hpp create mode 100644 CompilerKit/StdKit/ErrorOr.hpp create mode 100644 CompilerKit/StdKit/PEF.hpp create mode 100644 CompilerKit/StdKit/Ref.hpp create mode 100644 CompilerKit/StdKit/String.cc create mode 100644 CompilerKit/StdKit/String.hpp diff --git a/C++Kit/AsmKit/Arch/32k.hpp b/C++Kit/AsmKit/Arch/32k.hpp deleted file mode 100644 index 2e73efa..0000000 --- a/C++Kit/AsmKit/Arch/32k.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * ======================================================== - * - * C++Kit - * Copyright Western Company, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include - -// @brief 32x0 support. -// @file Arch/64k.hpp - -#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ - { .fName = __NAME, .fOpcode = __OPCODE, .fFunct3 = __FUNCT3, .fFunct7 = __FUNCT7 }, - - - -// placeholder for funct7/funct7-rs2 -#define kAsmImmediate 0x00 -#define kAsmSyscall 0x02 -#define kAsmJump 0x03 - -#define kAsmByte 0 -#define kAsmHWord 1 -#define kAsmWord 2 - -struct CpuCode32x0 -{ - const char fName[16]; - char fOpcode; - char fSize; - char fFunct3; - char fFunct7; -}; - -#define kAsmWordStr ".w" -#define kAsmHWordStr ".h" -#define kAsmByteStr ".b" - -inline std::vector kOpcodes32x0 = { - kAsmOpcodeDecl("nop", 0b0100011, 0b0000000, kAsmImmediate) // nothing to do. - kAsmOpcodeDecl("jmp", 0b1110011, 0b0000011, kAsmJump) // jump to branch - kAsmOpcodeDecl("move", 0b0100011, 0b101, kAsmImmediate) - kAsmOpcodeDecl("push", 0b0111011, 0b0, kAsmImmediate) // push to sp - kAsmOpcodeDecl("pop", 0b0111011, 0b1, kAsmImmediate) // pop from sp. - kAsmOpcodeDecl("int", 0b0111111, 0b0, kAsmSyscall) // raise interrupt -}; - -// \brief NewCPU register prefix -// example: r32, r0 -// r32 -> sp -// r0 -> hw zero - -#define kAsmRegisterPrefix "r" -#define kAsmRegisterLimit 20 -#define kAsmPcRegister 17 -#define kAsmCrRegister 18 -#define kAsmSpRegister 5 - -/* return address register */ -#define kAsmRetRegister 19 - -///////////////////////////////////////////////////////////////////////////// - -// SYSTEM CALL ADDRESSING - -// | OPCODE | FUNCT3 | FUNCT7 | OFF | - -// IMMEDIATE ADDRESSING - -// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | -// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | REG | -// | OPCODE | FUNCT3 | FUNCT7 | REG | REG | OFF | - -// REG TO REG ADDRESSING - -// | OPCODE | FUNCT3 | FUNCT7 | REG | REG2 | - -//////////////////////////////// - -// LOAD/CALL INTERRUPTS - -// SET A HANDLER IN ADDRESS: TODO: find one -// DISABLE INTERRUPTS -// PROCESS INTERRUPT -// ENABLE INTERRUPTS - -//////////////////////////////// \ No newline at end of file diff --git a/C++Kit/AsmKit/Arch/64k.hpp b/C++Kit/AsmKit/Arch/64k.hpp deleted file mode 100644 index 00ab973..0000000 --- a/C++Kit/AsmKit/Arch/64k.hpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * ======================================================== - * - * C++Kit - * Copyright Western Company, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include - -// @brief 64x0 support. -// @file Arch/64k.hpp - -#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ - { .fName = __NAME, .fOpcode = __OPCODE, .fFunct3 = __FUNCT3, .fFunct7 = __FUNCT7 }, - - - -// placeholder for funct7/funct7-rs2 -#define kAsmImmediate 0x00 -#define kAsmRegToReg 0x01 -#define kAsmSyscall 0x02 -#define kAsmJump 0x03 - -struct CpuCode64x0 -{ - const char fName[16]; - char fOpcode; - char fFunct3; - char fFunct7; -}; - -inline std::vector kOpcodes64x0 = { - kAsmOpcodeDecl("np", 0b0100011, 0b0000000, kAsmImmediate) // mv r0, r0 - kAsmOpcodeDecl("jb", 0b1110011, 0b0000011, kAsmJump) // jump to branch - kAsmOpcodeDecl("jlr", 0b1110011, 0b0000111, kAsmJump) // jump and link return register - kAsmOpcodeDecl("jrl", 0b1110011, 0b0001111, kAsmJump) // jump to register link - kAsmOpcodeDecl("jr", 0b1110011, 0b0001011, kAsmJump) // jump to register - kAsmOpcodeDecl("jal", 0b1110011, 0b0000001, kAsmJump) - kAsmOpcodeDecl("mv", 0b0100011, 0b101, kAsmRegToReg) - kAsmOpcodeDecl("psh", 0b0111011, 0b0, kAsmImmediate) // push to sp - kAsmOpcodeDecl("pop", 0b0111011, 0b1, kAsmImmediate) // pop from sp. - 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) - kAsmOpcodeDecl("add", 0b0101011, 0b100, kAsmImmediate) - kAsmOpcodeDecl("dec", 0b0101011, 0b101, kAsmImmediate) - kAsmOpcodeDecl("scall", 0b1110011, 0b00, kAsmSyscall) - kAsmOpcodeDecl("sbreak", 0b1110011, 0b01, kAsmSyscall) - kAsmOpcodeDecl("mh", 0b1110011, 0b1111111, kAsmJump) -}; - -// \brief NewCPU register prefix -// example: r32, r0 -// r32 -> sp -// r0 -> hw zero - -#define kAsmRegisterPrefix "r" -#define kAsmRegisterLimit 20 -#define kAsmPcRegister 17 -#define kAsmCrRegister 18 -#define kAsmSpRegister 5 - -/* return address register */ -#define kAsmRetRegister 19 - -///////////////////////////////////////////////////////////////////////////// - -// SYSTEM CALL ADDRESSING - -// | OPCODE | FUNCT3 | FUNCT7 | OFF | - -// IMMEDIATE ADDRESSING - -// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | -// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | REG | -// | OPCODE | FUNCT3 | FUNCT7 | REG | REG | OFF | - -// REG TO REG ADDRESSING - -// | OPCODE | FUNCT3 | FUNCT7 | REG | REG2 | - -//////////////////////////////// - -// LOAD/CALL INTERRUPTS - -// SET A HANDLER IN ADDRESS: TODO: find one -// DISABLE INTERRUPTS -// PROCESS INTERRUPT -// ENABLE INTERRUPTS - -//////////////////////////////// \ No newline at end of file diff --git a/C++Kit/AsmKit/AsmKit.cc b/C++Kit/AsmKit/AsmKit.cc deleted file mode 100644 index d44874d..0000000 --- a/C++Kit/AsmKit/AsmKit.cc +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ======================================================== - * - * C++Kit - * Copyright Western Company, all rights reserved. - * - * ======================================================== - */ - -#include -#include - -#include - -//! @file AsmKit.cpp -//! @brief AssemblyKit - -namespace CxxKit -{ - //! @brief Compile for specific format (ELF, PEF, ZBIN) - Int32 AssemblyFactory::Compile(StringView& sourceFile, - const Int32& arch) noexcept - { - if (sourceFile.Length() < 1 || - !fMounted) - return CXXKIT_UNIMPLEMENTED; - - return fMounted->CompileToFormat(sourceFile, arch); - } - - //! @brief mount assembly backend. - void AssemblyFactory::Mount(AssemblyMountpoint* mountPtr) noexcept - { - if (mountPtr) - fMounted = mountPtr; - } - - AssemblyMountpoint* AssemblyFactory::Unmount() noexcept - { - auto mount_prev = fMounted; - - if (mount_prev) - fMounted = nullptr; - - return mount_prev; - } -} diff --git a/C++Kit/AsmKit/AsmKit.hpp b/C++Kit/AsmKit/AsmKit.hpp deleted file mode 100644 index 68ea4c0..0000000 --- a/C++Kit/AsmKit/AsmKit.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * ======================================================== - * - * C++Kit - * Copyright Western Company, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include -#include - -namespace CxxKit -{ - // - // @brief Frontend to Assembly mountpoint. - // - class AssemblyMountpoint - { - public: - explicit AssemblyMountpoint() = default; - virtual ~AssemblyMountpoint() = default; - - CXXKIT_COPY_DEFAULT(AssemblyMountpoint); - - //@ brief compile to object file. - // Example C++ -> MASM -> AE object. - virtual Int32 CompileToFormat(StringView& src, Int32 arch) = 0; - - }; - - /// @brief Simple assembly factory - class AssemblyFactory final - { - public: - explicit AssemblyFactory() = default; - ~AssemblyFactory() = default; - - CXXKIT_COPY_DEFAULT(AssemblyFactory); - - public: - enum - { - kArchAMD64, - kArch32x0, - kArch64x0, - kArchRISCV, - kArchUnknown, - }; - - Int32 Compile(StringView& sourceFile, const Int32& arch) noexcept; - - void Mount(AssemblyMountpoint* mountPtr) noexcept; - AssemblyMountpoint* Unmount() noexcept; - - private: - AssemblyMountpoint* fMounted{ nullptr }; - - }; -} diff --git a/C++Kit/Defines.hpp b/C++Kit/Defines.hpp deleted file mode 100644 index 8e92639..0000000 --- a/C++Kit/Defines.hpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - * ======================================================== - * - * C++Kit - * Copyright Western Company, all rights reserved. - * - * ======================================================== - */ - -#ifndef __CXXKIT_DEFINES_HPP__ -#define __CXXKIT_DEFINES_HPP__ - -#ifndef Yes -#define Yes true -#endif // ifndef Yes - -#ifndef No -#define No false -#endif // ifndef No - -#include - -#define SizeType size_t - -#define VoidPtr void* -#define voidPtr VoidPtr - -#define UIntPtr uintptr_t - -#define Int64 int64_t -#define UInt64 uint64_t - -#define Int32 int32_t -#define UInt32 uint32_t - -#define Bool bool - -#define Int16 int16_t -#define UInt16 uint16_t - -#define Int8 int8_t -#define UInt8 uint8_t - -#define CharType char -#define Boolean bool - -#include -#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 CXXKIT_COPY_DELETE(KLASS) \ - KLASS &operator=(const KLASS &) = delete; \ - KLASS(const KLASS &) = delete; - - -#define CXXKIT_COPY_DEFAULT(KLASS) \ - KLASS &operator=(const KLASS &) = default; \ - KLASS(const KLASS &) = default; - - -#define CXXKIT_MOVE_DELETE(KLASS) \ - KLASS &operator=(KLASS &&) = delete; \ - KLASS(KLASS &&) = delete; - - -#define CXXKIT_MOVE_DEFAULT(KLASS) \ - KLASS &operator=(KLASS &&) = default; \ - KLASS(KLASS &&) = default; - - - -#include -#include - -namespace CxxKit -{ - inline constexpr int BASE_YEAR = 1900; - - inline std::string current_date() - { - auto time_data = time(nullptr); - auto time_struct = gmtime(&time_data); - - std::string fmt = std::to_string(BASE_YEAR + time_struct->tm_year); - fmt += "-"; - fmt += std::to_string(time_struct->tm_mon + 1); - fmt += "-"; - fmt += std::to_string(time_struct->tm_mday); - - return fmt; - } - - inline bool to_str(CharType *str, Int32 limit, Int32 base) - { - if (limit == 0) - return false; - - Int32 copy_limit = limit; - Int32 cnt = 0; - Int32 ret = base; - - while (limit != 1) { - ret = ret % 10; - str[cnt] = ret; - - ++cnt; - --limit; - --ret; - } - - str[copy_limit] = '\0'; - return true; - } -} - -#define kObjectFileExt ".o" -#define kAsmFileExt64x0 ".64x" - -#endif /* ifndef __CXXKIT_DEFINES_HPP__ */ diff --git a/C++Kit/ParserKit.hpp b/C++Kit/ParserKit.hpp deleted file mode 100644 index 0d81080..0000000 --- a/C++Kit/ParserKit.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * ======================================================== - * - * C++Kit - * Copyright Western Company, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include - -namespace ParserKit -{ - using namespace CxxKit; - - class CompilerBackend - { - public: - explicit CompilerBackend() = default; - virtual ~CompilerBackend() = default; - - CXXKIT_COPY_DEFAULT(CompilerBackend); - - // NOTE: cast this to your user defined ast. - typedef void* AstType; - - //! @brief Compile a syntax tree ouf of the text. - //! Also takes the source file name for metadata. - - virtual bool Compile(const std::string& text, const char* file) = 0; - - //! @brief What language are we dealing with? - virtual const char* Language() { return "Generic Language"; } - - }; - - struct SyntaxLeafList; - struct SyntaxLeafList; - - struct SyntaxLeafList final - { - struct SyntaxLeaf final - { - Int32 fUserType; - std::string fUserData; - std::string fUserValue; - struct SyntaxLeaf* fNext; - }; - - std::vector 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()); - } -} \ No newline at end of file diff --git a/C++Kit/StdKit/AE.hpp b/C++Kit/StdKit/AE.hpp deleted file mode 100644 index a659e90..0000000 --- a/C++Kit/StdKit/AE.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * ======================================================== - * - * C++Kit - * Copyright Western Company, 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 CxxKit -{ - // @brief Advanced Executable Header - // One thing to keep in mind. - // This object format, is reloctable. - typedef struct AEHeader final - { - CharType fMagic[kAEMagLen]; - CharType fArch; - SizeType fCount; - CharType fSize; - SizeType fStartCode; - SizeType fCodeSize; - CharType fPad[kAEPad]; - } __attribute__((packed)) AEHeader, *AEHeaderPtr; - - // @brief Advanced Executable Record. - // Could be data, code or bss. - // fKind must be filled with PEF fields. - - typedef struct AERecordHeader final - { - CharType fName[kAESymbolLen]; - SizeType fKind; - SizeType fSize; - SizeType fFlags; - UIntPtr fOffset; - CharType fPad[kAEPad]; - } __attribute__((packed)) AERecordHeader, *AERecordHeaderPtr; - - enum - { - kKindRelocationByOffset = 0x23f, - kKindRelocationAtRuntime = 0x34f, - }; -} diff --git a/C++Kit/StdKit/ErrorID.hpp b/C++Kit/StdKit/ErrorID.hpp deleted file mode 100644 index ddbf83b..0000000 --- a/C++Kit/StdKit/ErrorID.hpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * ======================================================== - * - * CxxKit - * Copyright Western Company, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -#define CXXKIT_EXEC_ERROR -30 -#define CXXKIT_FILE_NOT_FOUND -31 -#define CXXKIT_DIR_NOT_FOUND -32 -#define CXXKIT_FILE_EXISTS -33 -#define CXXKIT_TOO_LONG -34 -#define CXXKIT_INVALID_DATA -35 -#define CXXKIT_UNIMPLEMENTED -36 -#define CXXKIT_FAT_ERROR -37 diff --git a/C++Kit/StdKit/ErrorOr.hpp b/C++Kit/StdKit/ErrorOr.hpp deleted file mode 100644 index 4b5d1d2..0000000 --- a/C++Kit/StdKit/ErrorOr.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * ======================================================== - * - * CxxKit - * Copyright Western Company, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -namespace CxxKit -{ -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 CxxKit diff --git a/C++Kit/StdKit/PEF.hpp b/C++Kit/StdKit/PEF.hpp deleted file mode 100644 index e61b636..0000000 --- a/C++Kit/StdKit/PEF.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * ======================================================== - * - * C++Kit - * Copyright Western Company, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include - -#define kPefMagic "PEF" -#define kPefMagicFat "FEP" - -#define kPefMagicLen 3 - -#define kPefVersion 1 -#define kPefNameLen 64 - -// Protable Executable Format, a format designed for any computer. - -namespace CxxKit -{ - enum - { - kPefArchIntel86S = 100, - kPefArchAMD64, - kPefArchRISCV, - kPefArch64000, /* Advanced RISC architecture. */ - kPefArch32000, - kPefArchInvalid = 0xFF, - }; - - enum - { - kPefKindExec = 1, /* .o/.pef/ */ - kPefKindSharedObject = 2, /* .lib */ - kPefKindObject = 4, /* .obj */ - kPefKindDwarf = 5, /* .dsym */ - }; - - /* PEF container */ - typedef struct PEFContainer final - { - CharType Magic[kPefMagicLen]; - UInt32 Linker; - UInt32 Version; - UInt32 Kind; - UInt32 Abi; - UInt32 Cpu; - UInt32 SubCpu; /* Cpu specific information */ - UIntPtr Start; - SizeType HdrSz; /* Size of header */ - SizeType Count; /* container header count */ - } __attribute__((packed)) PEFContainer; - - /* First PEFCommandHeader starts after PEFContainer */ - /* Last container is __exec_end */ - - /* PEF executable section and commands. */ - - typedef struct PEFCommandHeader final - { - CharType Name[kPefNameLen]; /* container name */ - UInt32 Flags; /* container flags */ - UInt16 Kind; /* container kind */ - UIntPtr Offset; /* file offset */ - SizeType Size; /* file size */ - } __attribute__((packed)) PEFCommandHeader; - - enum - { - kPefCode = 0xC, - kPefData = 0xD, - kPefZero = 0xE, - kPefLinkerID = 0x1, - }; -} - -#define kPefExt ".o" -#define kPefDylibExt ".so" -#define kPefObjectExt ".o" -#define kPefDebugExt ".dbg" \ No newline at end of file diff --git a/C++Kit/StdKit/Ref.hpp b/C++Kit/StdKit/Ref.hpp deleted file mode 100644 index 4f4e822..0000000 --- a/C++Kit/StdKit/Ref.hpp +++ /dev/null @@ -1,89 +0,0 @@ - -/* - * ======================================================== - * - * CxxKit - * Copyright Western Company, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include - -namespace CxxKit -{ - // @author Western Company - // @brief Reference class, refers to a pointer of data in static memory. - template - class Ref final - { - public: - Ref() = default; - ~Ref() = default; - - public: - 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; - - 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 CxxKit diff --git a/C++Kit/StdKit/String.cc b/C++Kit/StdKit/String.cc deleted file mode 100644 index be07c26..0000000 --- a/C++Kit/StdKit/String.cc +++ /dev/null @@ -1,230 +0,0 @@ -/* - * ======================================================== - * - * CxxKit - * Copyright Western Company, all rights reserved. - * - * ======================================================== - */ - -#include "String.hpp" -#include - -namespace CxxKit -{ - CharType* StringView::Data() - { - return m_Data.data(); - } - - const CharType* StringView::CData() const - { - return m_Data.c_str(); - } - - SizeType StringView::Length() const - { - return m_Data.size(); - } - - bool StringView::operator==(const StringView &rhs) const - { - if (rhs.Length() != Length()) - return false; - - for (SizeType index = 0; index < Length(); ++index) - { - if (rhs.m_Data[index] != m_Data[index]) - return false; - } - - return true; - } - - bool StringView::operator==(const CharType *rhs) const - { - if (string_length(rhs) != Length()) - return false; - - for (SizeType index = 0; index < string_length(rhs); ++index) - { - if (rhs[index] != m_Data[index]) - return false; - } - - return true; - } - - bool StringView::operator!=(const StringView &rhs) const - { - if (rhs.Length() != Length()) - return false; - - for (SizeType index = 0; index < rhs.Length(); ++index) - { - if (rhs.m_Data[index] == m_Data[index]) - return false; - } - - return true; - } - - bool StringView::operator!=(const CharType *rhs) const - { - if (string_length(rhs) != Length()) - return false; - - for (SizeType index = 0; index < string_length(rhs); ++index) - { - if (rhs[index] == m_Data[index]) - return false; - } - - return true; - } - - StringView StringBuilder::Construct(const CharType *data) - { - if (!data || - *data == 0) - return StringView(0); - - StringView view(strlen(data)); - view += data; - - return view; - } - - const char* StringBuilder::FromInt(const char *fmt, int i) - { - if (!fmt) - return ("-1"); - - char *ret = new char[8 + string_length(fmt)]; - - if (!ret) - return ("-1"); - - CharType result[8]; - if (!to_str(result, sizeof(int), i)) - { - delete[] ret; - return ("-1"); - } - - const auto fmt_len = string_length(fmt); - const auto res_len = string_length(result); - - for (SizeType idx = 0; idx < fmt_len; ++idx) - { - if (fmt[idx] == '%') { - SizeType result_cnt = idx; - - for (auto y_idx = idx; y_idx < res_len; ++y_idx) { - ret[result_cnt] = result[y_idx]; - ++result_cnt; - } - - break; - } - - ret[idx] = fmt[idx]; - } - - return ret; /* Copy that ret into a buffer, Alloca allocates to the stack */ - } - - const char* StringBuilder::FromBool(const char *fmt, bool i) - { - if (!fmt) - return ("?"); - - const char *boolean_expr = i ? "true" : "false"; - char *ret = new char[i ? 4 : 5 + string_length(fmt)]; - - if (!ret) - return ("?"); - - const auto fmt_len = string_length(fmt); - const auto res_len = string_length(boolean_expr); - - for (SizeType idx = 0; idx < fmt_len; ++idx) - { - if (fmt[idx] == '%') { - SizeType result_cnt = idx; - - for (auto y_idx = idx; y_idx < res_len; ++y_idx) - { - ret[result_cnt] = boolean_expr[y_idx]; - ++result_cnt; - } - - break; - } - - ret[idx] = fmt[idx]; - } - - return ret; - } - - bool StringBuilder::Equals(const char *lhs, const char *rhs) - { - if (string_length(rhs) != string_length(lhs)) - return false; - - for (SizeType index = 0; index < string_length(rhs); ++index) - { - if (rhs[index] != lhs[index]) - return false; - } - - return true; - } - - const char *StringBuilder::Format(const char *fmt, const char *fmt2) - { - if (!fmt || !fmt2) - return ("?"); - - char *ret = new char[string_length(fmt2) + string_length(fmt2)]; - if (!ret) - return ("?"); - - for (SizeType idx = 0; idx < string_length(fmt); ++idx) - { - if (fmt[idx] == '%') { - SizeType result_cnt = idx; - for (SizeType y_idx = 0; y_idx < string_length(fmt2); ++y_idx) - { - ret[result_cnt] = fmt2[y_idx]; - ++result_cnt; - } - - break; - } - - ret[idx] = fmt[idx]; - } - - return ret; - } - - StringView &StringView::operator+=(const CharType *rhs) - { - this->m_Data += rhs; - this->m_Cur = this->m_Data.size(); - this->m_Sz = this->m_Data.size(); - - return *this; - } - - StringView &StringView::operator+=(const StringView &rhs) - { - this->m_Data += rhs.CData(); - this->m_Cur = this->m_Data.size(); - this->m_Sz = this->m_Data.size(); - - return *this; - } -} // namespace CxxKit diff --git a/C++Kit/StdKit/String.hpp b/C++Kit/StdKit/String.hpp deleted file mode 100644 index 4addea8..0000000 --- a/C++Kit/StdKit/String.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * ======================================================== - * - * CxxKit - * Copyright Western Company, all rights reserved. - * - * ======================================================== - */ - -#pragma once - -#include -#include - -namespace CxxKit -{ - class StringView final - { - public: - StringView() = delete; - - explicit StringView(SizeType Sz) : m_Sz(Sz) - { - - } - - ~StringView() = default; - - CXXKIT_COPY_DEFAULT(StringView); - - CharType *Data(); - const CharType *CData() const; - SizeType Length() const; - - bool operator==(const CharType *rhs) const; - bool operator!=(const CharType *rhs) const; - - bool operator==(const StringView &rhs) const; - bool operator!=(const StringView &rhs) const; - - StringView &operator+=(const CharType *rhs); - StringView &operator+=(const StringView &rhs); - - operator bool() - { - return m_Data.empty() == false; - } - - bool operator!() - { - return m_Data.empty() == true; - } - - private: - std::basic_string m_Data{""}; - SizeType m_Sz{0}; - SizeType m_Cur{0}; - - friend class StringBuilder; - - }; - - struct StringBuilder final - { - static StringView Construct(const CharType *data); - static const char* FromInt(const char *fmt, int n); - static const char* FromBool(const char *fmt, bool n); - static const char* Format(const char *fmt, const char* from); - static bool Equals(const char *lhs, const char *rhs); - - }; -} // namespace CxxKit diff --git a/CompilerDriver/.gitignore b/CompilerDriver/.gitignore index 23a095f..021e796 100644 --- a/CompilerDriver/.gitignore +++ b/CompilerDriver/.gitignore @@ -15,5 +15,6 @@ bin/SourceUnitTest/*.cxx.pp bin/SourceUnitTest/*.cxx bin/SourceUnitTest/*.masm bin/SourceUnitTest/*.h +bin/SourceUnitTest/*.64x *.cxx.pp \ No newline at end of file diff --git a/CompilerDriver/cc.cc b/CompilerDriver/cc.cc index 4135be0..d3f48d8 100644 --- a/CompilerDriver/cc.cc +++ b/CompilerDriver/cc.cc @@ -13,8 +13,8 @@ #include #include #include -#include -#include +#include +#include #define kOk 0 @@ -134,7 +134,7 @@ static std::string kRegisterPrefix = kAsmRegisterPrefix; ///////////////////////////////////////// static std::vector kFileList; -static CxxKit::AssemblyFactory kFactory; +static CompilerKit::AssemblyFactory kFactory; static bool kInStruct = false; static bool kOnWhileLoop = false; static bool kOnForLoop = false; @@ -1619,7 +1619,7 @@ next: ///////////////////////////////////////////////////////////////////////////////////////// -class AssemblyMountpointClang final : public CxxKit::AssemblyMountpoint +class AssemblyMountpointClang final : public CompilerKit::AssemblyMountpoint { public: explicit AssemblyMountpointClang() = default; @@ -1627,9 +1627,9 @@ public: CXXKIT_COPY_DEFAULT(AssemblyMountpointClang); - [[maybe_unused]] static Int32 Arch() noexcept { return CxxKit::AssemblyFactory::kArchRISCV; } + [[maybe_unused]] static Int32 Arch() noexcept { return CompilerKit::AssemblyFactory::kArchRISCV; } - Int32 CompileToFormat(CxxKit::StringView& src, Int32 arch) override + Int32 CompileToFormat(CompilerKit::StringView& src, Int32 arch) override { if (arch != AssemblyMountpointClang::Arch()) return -1; @@ -1657,7 +1657,7 @@ public: kState.fOutputAssembly = std::make_unique(dest); - auto fmt = CxxKit::current_date(); + auto fmt = CompilerKit::current_date(); (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; (*kState.fOutputAssembly) << "# Language: MP-UX Assembly\n"; @@ -1688,6 +1688,10 @@ public: std::vector keywords = { "ldw", "stw", "lda", "sta", "add", "dec", "mv"}; + /// + /// Replace, optimize, fix assembly output. + /// + for (auto& leaf : kState.fSyntaxTree->fLeafList) { for (auto& keyword : keywords) @@ -1835,7 +1839,7 @@ int main(int argc, char** argv) delete kFactory.Unmount(); kFactory.Mount(new AssemblyMountpointClang()); - kMachine = CxxKit::AssemblyFactory::kArchRISCV; + kMachine = CompilerKit::AssemblyFactory::kArchRISCV; continue; } @@ -1875,7 +1879,7 @@ int main(int argc, char** argv) kFileList.emplace_back(argv[index]); - CxxKit::StringView srcFile = CxxKit::StringBuilder::Construct(argv[index]); + CompilerKit::StringView srcFile = CompilerKit::StringBuilder::Construct(argv[index]); if (strstr(argv[index], kExt) == nullptr) { diff --git a/CompilerDriver/ccplus.cc b/CompilerDriver/ccplus.cc index c87b8ee..fc8ab3a 100644 --- a/CompilerDriver/ccplus.cc +++ b/CompilerDriver/ccplus.cc @@ -15,8 +15,8 @@ #include #include #include -#include -#include +#include +#include #define kOk 0 @@ -131,7 +131,7 @@ static std::vector kKeywords; ///////////////////////////////////////// static std::vector kFileList; -static CxxKit::AssemblyFactory kFactory; +static CompilerKit::AssemblyFactory kFactory; static bool kInStruct = false; static bool kOnWhileLoop = false; static bool kOnForLoop = false; @@ -220,7 +220,7 @@ bool CompilerBackendClang::Compile(const std::string& text, const char* file) auto syntax_tree = ParserKit::SyntaxLeafList::SyntaxLeaf(); syntax_tree.fUserData = text; - kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + kState.fSyntaxTree->fLeafList.emplace_back(syntax_tree); std::string text_cpy = text; @@ -230,7 +230,7 @@ bool CompilerBackendClang::Compile(const std::string& text, const char* file) { while (text_cpy.find(keyword) != std::string::npos) { - keywords_list.push_back(std::make_pair(keyword, index)); + keywords_list.emplace_back(std::make_pair(keyword, index)); ++index; text_cpy.erase(text_cpy.find(keyword), keyword.size()); @@ -242,7 +242,7 @@ bool CompilerBackendClang::Compile(const std::string& text, const char* file) for (auto& keyword : keywords_list) { syntax_tree.fUserData = keyword.first; - kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + kState.fSyntaxTree->fLeafList.emplace_back(syntax_tree); std::cout << keyword.first << "\n"; } @@ -258,7 +258,7 @@ bool CompilerBackendClang::Compile(const std::string& text, const char* file) ///////////////////////////////////////////////////////////////////////////////////////// -class AssemblyMountpointClang final : public CxxKit::AssemblyMountpoint +class AssemblyMountpointClang final : public CompilerKit::AssemblyMountpoint { public: explicit AssemblyMountpointClang() = default; @@ -266,9 +266,9 @@ public: CXXKIT_COPY_DEFAULT(AssemblyMountpointClang); - [[maybe_unused]] static Int32 Arch() noexcept { return CxxKit::AssemblyFactory::kArchRISCV; } + [[maybe_unused]] static Int32 Arch() noexcept { return CompilerKit::AssemblyFactory::kArchRISCV; } - Int32 CompileToFormat(CxxKit::StringView& src, Int32 arch) override + Int32 CompileToFormat(CompilerKit::StringView& src, Int32 arch) override { if (arch != AssemblyMountpointClang::Arch()) return -1; @@ -296,7 +296,7 @@ public: kState.fOutputAssembly = std::make_unique(dest); - auto fmt = CxxKit::current_date(); + auto fmt = CompilerKit::current_date(); (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; (*kState.fOutputAssembly) << "# Language: MP-UX Assembly\n"; @@ -304,7 +304,7 @@ public: ParserKit::SyntaxLeafList syntax; - kState.fSyntaxTreeList.push_back(syntax); + kState.fSyntaxTreeList.emplace_back(syntax); kState.fSyntaxTree = &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; std::string source; @@ -338,7 +338,7 @@ public: { if (leaf.fUserData == "{") { - scope.push_back({}); + scope.emplace_back(); } if (leaf.fUserData == "{") @@ -447,7 +447,7 @@ public: continue; } - lines.push_back(leaf.fUserData); + lines.emplace_back(leaf.fUserData); } for (auto& leaf : kState.fSyntaxTree->fLeafList) @@ -483,59 +483,59 @@ static void cxx_print_help() int main(int argc, char** argv) { - kKeywords.push_back("auto"); - kKeywords.push_back("else"); - kKeywords.push_back("break"); - kKeywords.push_back("switch"); - kKeywords.push_back("enum"); - kKeywords.push_back("register"); - kKeywords.push_back("do"); - kKeywords.push_back("return"); - kKeywords.push_back("if"); - kKeywords.push_back("default"); - kKeywords.push_back("struct"); - kKeywords.push_back("_Packed"); - kKeywords.push_back("extern"); - kKeywords.push_back("volatile"); - kKeywords.push_back("static"); - kKeywords.push_back("for"); - kKeywords.push_back("class"); - kKeywords.push_back("{"); - kKeywords.push_back("}"); - kKeywords.push_back("("); - kKeywords.push_back(")"); - kKeywords.push_back("char"); - kKeywords.push_back("int"); - kKeywords.push_back("short"); - kKeywords.push_back("long"); - kKeywords.push_back("float"); - kKeywords.push_back("double"); - kKeywords.push_back("unsigned"); - kKeywords.push_back("__export__"); - kKeywords.push_back("__packed__"); - kKeywords.push_back("namespace"); - kKeywords.push_back("while"); - kKeywords.push_back("sizeof"); - kKeywords.push_back("private"); - kKeywords.push_back("->"); - kKeywords.push_back("."); - kKeywords.push_back("::"); - kKeywords.push_back("*"); - kKeywords.push_back("+"); - kKeywords.push_back("-"); - kKeywords.push_back("/"); - kKeywords.push_back("="); - kKeywords.push_back("=="); - kKeywords.push_back("!="); - kKeywords.push_back(">="); - kKeywords.push_back("<="); - kKeywords.push_back(">"); - kKeywords.push_back("<"); - kKeywords.push_back(":"); - kKeywords.push_back(","); - kKeywords.push_back(";"); - kKeywords.push_back("public"); - kKeywords.push_back("protected"); + kKeywords.emplace_back("auto"); + kKeywords.emplace_back("else"); + kKeywords.emplace_back("break"); + kKeywords.emplace_back("switch"); + kKeywords.emplace_back("enum"); + kKeywords.emplace_back("register"); + kKeywords.emplace_back("do"); + kKeywords.emplace_back("return"); + kKeywords.emplace_back("if"); + kKeywords.emplace_back("default"); + kKeywords.emplace_back("struct"); + kKeywords.emplace_back("_Packed"); + kKeywords.emplace_back("extern"); + kKeywords.emplace_back("volatile"); + kKeywords.emplace_back("static"); + kKeywords.emplace_back("for"); + kKeywords.emplace_back("class"); + kKeywords.emplace_back("{"); + kKeywords.emplace_back("}"); + kKeywords.emplace_back("("); + kKeywords.emplace_back(")"); + kKeywords.emplace_back("char"); + kKeywords.emplace_back("int"); + kKeywords.emplace_back("short"); + kKeywords.emplace_back("long"); + kKeywords.emplace_back("float"); + kKeywords.emplace_back("double"); + kKeywords.emplace_back("unsigned"); + kKeywords.emplace_back("__export__"); + kKeywords.emplace_back("__packed__"); + kKeywords.emplace_back("namespace"); + kKeywords.emplace_back("while"); + kKeywords.emplace_back("sizeof"); + kKeywords.emplace_back("private"); + kKeywords.emplace_back("->"); + kKeywords.emplace_back("."); + kKeywords.emplace_back("::"); + kKeywords.emplace_back("*"); + kKeywords.emplace_back("+"); + kKeywords.emplace_back("-"); + kKeywords.emplace_back("/"); + kKeywords.emplace_back("="); + kKeywords.emplace_back("=="); + kKeywords.emplace_back("!="); + kKeywords.emplace_back(">="); + kKeywords.emplace_back("<="); + kKeywords.emplace_back(">"); + kKeywords.emplace_back("<"); + kKeywords.emplace_back(":"); + kKeywords.emplace_back(","); + kKeywords.emplace_back(";"); + kKeywords.emplace_back("public"); + kKeywords.emplace_back("protected"); bool skip = false; @@ -584,7 +584,7 @@ int main(int argc, char** argv) delete kFactory.Unmount(); kFactory.Mount(new AssemblyMountpointClang()); - kMachine = CxxKit::AssemblyFactory::kArchRISCV; + kMachine = CompilerKit::AssemblyFactory::kArchRISCV; continue; } @@ -624,7 +624,7 @@ int main(int argc, char** argv) kFileList.emplace_back(argv[index]); - CxxKit::StringView srcFile = CxxKit::StringBuilder::Construct(argv[index]); + CompilerKit::StringView srcFile = CompilerKit::StringBuilder::Construct(argv[index]); if (strstr(argv[index], kExt) == nullptr) { diff --git a/CompilerDriver/cpp.cc b/CompilerDriver/cpp.cc index 29507b7..3b6d914 100644 --- a/CompilerDriver/cpp.cc +++ b/CompilerDriver/cpp.cc @@ -7,8 +7,8 @@ * ======================================================== */ -#include -#include +#include +#include #include #include #include @@ -58,8 +58,8 @@ namespace details CXXKIT_COPY_DEFAULT(cpp_pragma); - std::string fMacroName{ "" }; - Int32(*fParse)(std::string& line, std::ifstream& hdr_file, std::ofstream& pp_out); + std::string fMacroName; + cpp_parser_fn_t fParse; }; } @@ -144,15 +144,15 @@ int32_t cpp_parse_if_condition(details::cpp_macro_condition& cond, std::string number; - for (auto& macro : kMacros) + for (auto& macro_num : kMacros) { - if (substr_macro.find(macro.fName) != std::string::npos) + if (substr_macro.find(macro_num.fName) != std::string::npos) { - for (size_t i = 0; i < macro.fName.size(); ++i) + for (size_t i = 0; i < macro_num.fName.size(); ++i) { - if (isdigit(macro.fValue[i])) + if (isdigit(macro_num.fValue[i])) { - number += macro.fValue[i]; + number += macro_num.fValue[i]; } else { @@ -287,9 +287,7 @@ void cpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) std::string line_after_include; bool inactive_code = false; - bool comment = false; bool defined = false; - bool else_branch = false; try { @@ -473,15 +471,15 @@ void cpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) std::string symbol; - for (size_t i = 0; i < macro.fValue.size(); i++) + for (char i : macro.fValue) { - if (macro.fValue[i] == '(') + if (i == '(') break; - if (macro.fValue[i] == '\\') + if (i == '\\') continue; - symbol += macro.fValue[i]; + symbol += i; } hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), symbol); @@ -596,8 +594,6 @@ void cpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) continue; } - - else_branch = true; } else if (hdr_line[0] == '#' && hdr_line.find("ifdef") != std::string::npos) @@ -845,7 +841,11 @@ kIncludeFile: for (auto& include : kIncludes) { - std::ifstream header(include + '/' + path); + std::string header_path = include; + header_path.push_back('/'); + header_path += path; + + std::ifstream header(header_path); if (!header.is_open()) continue; @@ -857,7 +857,7 @@ kIncludeFile: break; } - if (open == false) + if (!open) { throw std::runtime_error("cpp: no such include file: " + path); } diff --git a/CompilerDriver/ld.cc b/CompilerDriver/ld.cc index f3a2225..e32c03d 100644 --- a/CompilerDriver/ld.cc +++ b/CompilerDriver/ld.cc @@ -16,17 +16,17 @@ // It will be loaded when program will start up! // Unlike $$dynamic$$ these containers will be loaded before CUS will do its job. -#include +#include #include #include #include //! Portable Executable Format -#include +#include //! Advanced Executable Object Format -#include +#include //! @brief standard PEF entry. #define kPefStart "__start" @@ -47,15 +47,15 @@ enum { kAbiMpUx = 0x5046 /* PF */ }; -std::ofstream& operator<<(std::ofstream& fp, CxxKit::PEFContainer& container) +std::ofstream& operator<<(std::ofstream& fp, CompilerKit::PEFContainer& container) { - fp.write((char*)&container, sizeof(CxxKit::PEFContainer)); + fp.write((char*)&container, sizeof(CompilerKit::PEFContainer)); return fp; } -std::ofstream& operator<<(std::ofstream& fp, CxxKit::PEFCommandHeader& container) +std::ofstream& operator<<(std::ofstream& fp, CompilerKit::PEFCommandHeader& container) { - fp.write((char*)&container, sizeof(CxxKit::PEFCommandHeader)); + fp.write((char*)&container, sizeof(CompilerKit::PEFCommandHeader)); return fp; } @@ -109,7 +109,7 @@ int main(int argc, char** argv) // else if (StringCompare(argv[i], "-m64000") == 0) { - kArch = CxxKit::kPefArch64000; + kArch = CompilerKit::kPefArch64000; continue; } @@ -184,12 +184,12 @@ int main(int argc, char** argv) return CXXKIT_EXEC_ERROR; } - CxxKit::PEFContainer pef_container{}; + CompilerKit::PEFContainer pef_container{}; int32_t archs = kArch; pef_container.Count = 0UL; - pef_container.Kind = CxxKit::kPefKindExec; + pef_container.Kind = CompilerKit::kPefKindExec; pef_container.SubCpu = kSubArch; pef_container.Linker = kPefLinkerNumId; // Western Company Linker pef_container.Abi = kAbi; // Multi-Processor UX ABI @@ -200,7 +200,7 @@ int main(int argc, char** argv) // specify the start address, can be 0x10000 pef_container.Start = kPefDeaultOrg; - pef_container.HdrSz = sizeof(CxxKit::PEFContainer); + pef_container.HdrSz = sizeof(CompilerKit::PEFContainer); std::ofstream output_fc(kOutput, std::ofstream::binary); @@ -216,18 +216,18 @@ int main(int argc, char** argv) //! Read AE to convert as PEF. - std::vector pef_command_hdrs; + std::vector pef_command_hdrs; for (const auto& i : kObjectList) { if (!std::filesystem::exists(i)) continue; - CxxKit::AEHeader hdr{}; + CompilerKit::AEHeader hdr{}; std::ifstream input_object(i, std::ifstream::binary); - input_object.read((char*)&hdr, sizeof(CxxKit::AEHeader)); + input_object.read((char*)&hdr, sizeof(CompilerKit::AEHeader)); auto ae_header = hdr; @@ -257,7 +257,7 @@ int main(int argc, char** argv) if (ae_header.fMagic[0] == kAEMag0 && ae_header.fMagic[1] == kAEMag1 && - ae_header.fSize == sizeof(CxxKit::AEHeader)) + ae_header.fSize == sizeof(CompilerKit::AEHeader)) { // append arch type to archs varaible. archs |= ae_header.fArch; @@ -268,16 +268,16 @@ int main(int argc, char** argv) pef_container.Count = cnt; - char* raw_ae_records = new char[cnt * sizeof(CxxKit::AERecordHeader)]; - memset(raw_ae_records, 0, cnt * sizeof(CxxKit::AERecordHeader)); + char* raw_ae_records = new char[cnt * sizeof(CompilerKit::AERecordHeader)]; + memset(raw_ae_records, 0, cnt * sizeof(CompilerKit::AERecordHeader)); - input_object.read(raw_ae_records, std::streamsize(cnt * sizeof(CxxKit::AERecordHeader))); + input_object.read(raw_ae_records, std::streamsize(cnt * sizeof(CompilerKit::AERecordHeader))); - auto* ae_records = (CxxKit::AERecordHeader*)raw_ae_records; + auto* ae_records = (CompilerKit::AERecordHeader*)raw_ae_records; for (size_t ae_record_index = 0; ae_record_index < cnt; ++ae_record_index) { - CxxKit::PEFCommandHeader command_header{ 0 }; + CompilerKit::PEFCommandHeader command_header{ 0 }; memcpy(command_header.Name, ae_records[ae_record_index].fName, kPefNameLen); @@ -440,7 +440,7 @@ ld_continue_search: // step 4: write some pef commands. - CxxKit::PEFCommandHeader date_header{}; + CompilerKit::PEFCommandHeader date_header{}; time_t timestamp = time(nullptr); @@ -450,24 +450,24 @@ ld_continue_search: strcpy(date_header.Name, timestamp_str.c_str()); date_header.Flags = 0; - date_header.Kind = CxxKit::kPefData; + date_header.Kind = CompilerKit::kPefData; date_header.Offset = output_fc.tellp(); date_header.Size = timestamp_str.size(); output_fc << date_header; - CxxKit::PEFCommandHeader abi_header{}; + CompilerKit::PEFCommandHeader abi_header{}; memcpy(abi_header.Name, kPefAbiId, strlen(kPefAbiId)); abi_header.Size = strlen(kPefAbiId); abi_header.Offset = output_fc.tellp(); abi_header.Flags = 0; - abi_header.Kind = CxxKit::kPefLinkerID; + abi_header.Kind = CompilerKit::kPefLinkerID; output_fc << abi_header; - CxxKit::PEFCommandHeader uuid_header{}; + CompilerKit::PEFCommandHeader uuid_header{}; uuid_t uuid{ 0 }; uuid_generate_random(uuid); diff --git a/CompilerDriver/makefile b/CompilerDriver/makefile index e1060d5..9dffbf1 100644 --- a/CompilerDriver/makefile +++ b/CompilerDriver/makefile @@ -8,7 +8,7 @@ # LINK_CC=g++ -std=c++20 -LINK_INC=-I../ -I../C++Kit +LINK_INC=-I../ -I../CompilerKit LINK_SRC=ld.cc LINK_OUTPUT=bin/ld LINK_ALT_OUTPUT=bin/mld @@ -19,16 +19,16 @@ PP_OUTPUT=bin/cpp CC2_OUTPUT=bin/cppfront CC2_SRC=cc2/source/cppfront.cpp -CC_SRC=ccplus.cc ../C++Kit/StdKit/*.cc ../C++Kit/AsmKit/*.cc +CC_SRC=ccplus.cc ../CompilerKit/StdKit/*.cc ../CompilerKit/AsmKit/*.cc CC_OUTPUT=bin/ccplus -CC_SRC=cc.cc ../C++Kit/StdKit/*.cc ../C++Kit/AsmKit/*.cc +CC_SRC=cc.cc ../CompilerKit/StdKit/*.cc ../CompilerKit/AsmKit/*.cc CC_OUTPUT=bin/cc -CXX_SRC=ccplus.cc ../C++Kit/StdKit/*.cc ../C++Kit/AsmKit/*.cc +CXX_SRC=ccplus.cc ../CompilerKit/StdKit/*.cc ../CompilerKit/AsmKit/*.cc CXX_OUTPUT=bin/ccplus -MASM_SRC=masm.cc ../C++Kit/StdKit/*.cc ../C++Kit/AsmKit/*.cc +MASM_SRC=masm.cc ../CompilerKit/StdKit/*.cc ../CompilerKit/AsmKit/*.cc MASM_OUTPUT=bin/masm .PHONY: all diff --git a/CompilerDriver/masm.cc b/CompilerDriver/masm.cc index 0675dba..f60c716 100644 --- a/CompilerDriver/masm.cc +++ b/CompilerDriver/masm.cc @@ -18,10 +18,10 @@ ///////////////////////////////////////////////////////////////////////////////////////// -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include @@ -39,7 +39,7 @@ #define kStdOut (std::cout << kWhite) -static char kOutputArch = CxxKit::kPefArch64000; +static char kOutputArch = CompilerKit::kPefArch64000; //! base relocation address for every mp-ux app. static UInt32 kErrorLimit = 10; @@ -50,9 +50,9 @@ static std::size_t kCounter = 1UL; static bool kVerbose = false; static std::vector kBytes; -static CxxKit::AERecordHeader kCurrentRecord{ .fName = "", .fKind = CxxKit::kPefCode, .fSize = 0, .fOffset = 0 }; +static CompilerKit::AERecordHeader kCurrentRecord{ .fName = "", .fKind = CompilerKit::kPefCode, .fSize = 0, .fOffset = 0 }; -static std::vector kRecords; +static std::vector kRecords; static std::vector kUndefinedSymbols; static const std::string kUndefinedSymbol = ":ld:"; @@ -95,16 +95,16 @@ namespace detail // provide operator<< for AE -std::ofstream& operator<<(std::ofstream& fp, CxxKit::AEHeader& container) +std::ofstream& operator<<(std::ofstream& fp, CompilerKit::AEHeader& container) { - fp.write((char*)&container, sizeof(CxxKit::AEHeader)); + fp.write((char*)&container, sizeof(CompilerKit::AEHeader)); return fp; } -std::ofstream& operator<<(std::ofstream& fp, CxxKit::AERecordHeader& container) +std::ofstream& operator<<(std::ofstream& fp, CompilerKit::AERecordHeader& container) { - fp.write((char*)&container, sizeof(CxxKit::AERecordHeader)); + fp.write((char*)&container, sizeof(CompilerKit::AERecordHeader)); return fp; } @@ -139,7 +139,7 @@ int main(int argc, char** argv) else if (strcmp(argv[i], "-m64000") == 0 || strcmp(argv[i], "-m64x0") == 0) { - kOutputArch = CxxKit::kPefArch64000; + kOutputArch = CompilerKit::kPefArch64000; if (kVerbose) { @@ -184,13 +184,13 @@ int main(int argc, char** argv) std::string line; - CxxKit::AEHeader hdr{ 0 }; + CompilerKit::AEHeader hdr{ 0 }; memset(hdr.fPad, kAEInvalidOpcode, kAEPad); hdr.fMagic[0] = kAEMag0; hdr.fMagic[1] = kAEMag1; - hdr.fSize = sizeof(CxxKit::AEHeader); + hdr.fSize = sizeof(CompilerKit::AEHeader); hdr.fArch = kOutputArch; ///////////////////////////////////////////////////////////////////////////////////////// @@ -253,7 +253,7 @@ int main(int argc, char** argv) if (kVerbose) kStdOut << "masm: wrote record " << rec.fName << " to file...\n"; - rec.fFlags |= CxxKit::kKindRelocationAtRuntime; + rec.fFlags |= CompilerKit::kKindRelocationAtRuntime; rec.fOffset = record_count; ++record_count; @@ -265,7 +265,7 @@ int main(int argc, char** argv) for (auto& sym : kUndefinedSymbols) { - CxxKit::AERecordHeader _record_hdr{ 0 }; + CompilerKit::AERecordHeader _record_hdr{ 0 }; if (kVerbose) kStdOut << "masm: wrote symbol " << sym << " to file...\n"; @@ -353,17 +353,17 @@ static bool masm_read_attributes(std::string& line) if (name.find(".text") != std::string::npos) { // data is treated as code. - kCurrentRecord.fKind = CxxKit::kPefCode; + kCurrentRecord.fKind = CompilerKit::kPefCode; } else if (name.find(".data") != std::string::npos) { // no code will be executed from here. - kCurrentRecord.fKind = CxxKit::kPefData; + kCurrentRecord.fKind = CompilerKit::kPefData; } else if (name.find(".page_zero") != std::string::npos) { // this is a bss section. - kCurrentRecord.fKind = CxxKit::kPefZero; + kCurrentRecord.fKind = CompilerKit::kPefZero; } // this is a special case for the start stub. @@ -371,7 +371,7 @@ static bool masm_read_attributes(std::string& line) if (name == "__start") { - kCurrentRecord.fKind = CxxKit::kPefCode; + kCurrentRecord.fKind = CompilerKit::kPefCode; } // now we can tell the code size of the previous kCurrentRecord. @@ -410,17 +410,17 @@ static bool masm_read_attributes(std::string& line) if (name.find(".text") != std::string::npos) { // data is treated as code. - kCurrentRecord.fKind = CxxKit::kPefCode; + kCurrentRecord.fKind = CompilerKit::kPefCode; } else if (name.find(".data") != std::string::npos) { // no code will be executed from here. - kCurrentRecord.fKind = CxxKit::kPefData; + kCurrentRecord.fKind = CompilerKit::kPefData; } else if (name.find(".page_zero") != std::string::npos) { // this is a bss section. - kCurrentRecord.fKind = CxxKit::kPefZero; + kCurrentRecord.fKind = CompilerKit::kPefZero; } // this is a special case for the start stub. @@ -428,7 +428,7 @@ static bool masm_read_attributes(std::string& line) if (name == "__start") { - kCurrentRecord.fKind = CxxKit::kPefCode; + kCurrentRecord.fKind = CompilerKit::kPefCode; } // now we can tell the code size of the previous kCurrentRecord. @@ -563,15 +563,14 @@ static std::string masm_check_line(std::string& line, const std::string& file) std::vector opcodes_list = { "jb", "psh", "stw", "ldw", "lda", "sta" }; - for (auto& opcodes : kOpcodes64x0) + for (auto& opcode64x0 : kOpcodes64x0) { - if (line.find(opcodes.fName) != std::string::npos) + if (line.find(opcode64x0.fName) != std::string::npos) { for (auto& op : opcodes_list) { - if (line == op || - line.find(op) != std::string::npos && - !isspace(line[line.find(op) + op.size()])) + // if only instruction found. + if (line == op) { err_str += "\nmalformed "; err_str += op; @@ -580,11 +579,20 @@ static std::string masm_check_line(std::string& line, const std::string& file) } } + // if it is like that -> addr1, 0x0 + 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 += "Unknown syntax: "; + err_str += "unknown syntax: "; err_str += line; return err_str; @@ -626,8 +634,6 @@ static bool masm_write_number(std::size_t pos, std::string& jump_label) { detail::print_error("invalid hex number: " + jump_label, "masm"); throw std::runtime_error("invalid_hex"); - - return false; } } @@ -656,8 +662,6 @@ static bool masm_write_number(std::size_t pos, std::string& jump_label) { detail::print_error("invalid binary number: " + jump_label, "masm"); throw std::runtime_error("invalid_bin"); - - return false; } } @@ -686,8 +690,6 @@ static bool masm_write_number(std::size_t pos, std::string& jump_label) { detail::print_error("invalid octal number: " + jump_label, "masm"); throw std::runtime_error("invalid_octal"); - - return false; } } @@ -747,19 +749,23 @@ static bool masm_write_number(std::size_t pos, std::string& jump_label) static void masm_read_instruction(std::string& line, const std::string& file) { - for (auto& opcodes : kOpcodes64x0) + if (ParserKit::find_word(line, "__export")) + return; + + for (auto& opcode64x0 : kOpcodes64x0) { - if (ParserKit::find_word(line, opcodes.fName)) + // strict check here + if (ParserKit::find_word(line, opcode64x0.fName)) { - std::string name(opcodes.fName); + std::string name(opcode64x0.fName); std::string jump_label, cpy_jump_label; - kBytes.emplace_back(opcodes.fOpcode); - kBytes.emplace_back(opcodes.fFunct3); - kBytes.emplace_back(opcodes.fFunct7); + kBytes.emplace_back(opcode64x0.fOpcode); + kBytes.emplace_back(opcode64x0.fFunct3); + kBytes.emplace_back(opcode64x0.fFunct7); // check funct7 - switch (opcodes.fFunct7) + switch (opcode64x0.fFunct7) { // reg to reg means register to register transfer operation. case kAsmRegToReg: @@ -784,6 +790,16 @@ static void masm_read_instruction(std::string& line, const std::string& file) if (isdigit(line[line_index + 2])) reg_str += line[line_index + 2]; + + if (kOutputArch == CompilerKit::kPefArch64000) + { + if (isdigit(line[line_index + 3])) + { + reg_str += line[line_index + 3]; + detail::print_error("invalid register index, r" + reg_str + "\nnote: 64x0 accepts registers from r0 to r20.", file); + throw std::runtime_error("invalid_register_index"); + } + } std::size_t reg_index = strtoq( reg_str.c_str(), @@ -808,7 +824,7 @@ static void masm_read_instruction(std::string& line, const std::string& file) } // we're not in immediate addressing, reg to reg. - if (opcodes.fFunct7 != kAsmImmediate) + if (opcode64x0.fFunct7 != kAsmImmediate) { // remember! register to register! if (found_some == 1) @@ -846,13 +862,17 @@ static void masm_read_instruction(std::string& line, const std::string& file) name == "stw" || name == "ldw" || name == "lda" || - name == "sta") + name == "sta" || + name == "add" || + name == "dec") { auto where_string = name; if (name == "stw" || name == "ldw" || - name == "lda") + name == "lda" || + name == "add" || + name == "dec") where_string = ","; jump_label = line.substr(line.find(where_string) + where_string.size()); @@ -878,8 +898,6 @@ static void masm_read_instruction(std::string& line, const std::string& file) { detail::print_error("invalid combination of opcode and operands.\nhere ->" + line, file); throw std::runtime_error("invalid_comb_op_ops"); - - break; } goto masm_write_label; @@ -891,12 +909,11 @@ static void masm_read_instruction(std::string& line, const std::string& file) { detail::print_error("invalid usage __import on 'sta', here: " + line, file); throw std::runtime_error("invalid_sta_usage"); - break; } } } - // if jump to branch + // This is the case where we jump to a label, it is also used as a goto. if (name == "jb") { masm_write_label: @@ -908,14 +925,14 @@ masm_write_label: cpy_jump_label.find("__import") == std::string::npos && name == "jb") { - detail::print_error("__import not found on jump label, please add one.", file.c_str()); + detail::print_error("__import not found on jump label, please add one.", file); throw std::runtime_error("import_jmp_lbl"); } else if (cpy_jump_label.find("__import") != std::string::npos) { if (name == "sta") { - detail::print_error("__import is not allowed on a sta operation.", file.c_str()); + detail::print_error("__import is not allowed on a sta operation.", file); throw std::runtime_error("import_sta_op"); } diff --git a/CompilerKit/AsmKit/Arch/32k.hpp b/CompilerKit/AsmKit/Arch/32k.hpp new file mode 100644 index 0000000..460a905 --- /dev/null +++ b/CompilerKit/AsmKit/Arch/32k.hpp @@ -0,0 +1,92 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include + +// @brief 32x0 support. +// @file Arch/64k.hpp + +#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ + { .fName = __NAME, .fOpcode = __OPCODE, .fFunct3 = __FUNCT3, .fFunct7 = __FUNCT7 }, + + + +// placeholder for funct7/funct7-rs2 +#define kAsmImmediate 0x00 +#define kAsmSyscall 0x02 +#define kAsmJump 0x03 + +#define kAsmByte 0 +#define kAsmHWord 1 +#define kAsmWord 2 + +struct CpuCode32x0 +{ + const char fName[16]; + char fOpcode; + char fSize; + char fFunct3; + char fFunct7; +}; + +#define kAsmWordStr ".w" +#define kAsmHWordStr ".h" +#define kAsmByteStr ".b" + +inline std::vector kOpcodes32x0 = { + kAsmOpcodeDecl("nop", 0b0100011, 0b0000000, kAsmImmediate) // nothing to do. + kAsmOpcodeDecl("jmp", 0b1110011, 0b0000011, kAsmJump) // jump to branch + kAsmOpcodeDecl("move", 0b0100011, 0b101, kAsmImmediate) + kAsmOpcodeDecl("push", 0b0111011, 0b0, kAsmImmediate) // push to sp + kAsmOpcodeDecl("pop", 0b0111011, 0b1, kAsmImmediate) // pop from sp. + kAsmOpcodeDecl("int", 0b0111111, 0b0, kAsmSyscall) // raise interrupt +}; + +// \brief NewCPU register prefix +// example: r32, r0 +// r32 -> sp +// r0 -> hw zero + +#define kAsmRegisterPrefix "r" +#define kAsmRegisterLimit 20 +#define kAsmPcRegister 17 +#define kAsmCrRegister 18 +#define kAsmSpRegister 5 + +/* return address register */ +#define kAsmRetRegister 19 + +///////////////////////////////////////////////////////////////////////////// + +// SYSTEM CALL ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | OFF | + +// IMMEDIATE ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | REG | +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG | OFF | + +// REG TO REG ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG2 | + +//////////////////////////////// + +// LOAD/CALL INTERRUPTS + +// SET A HANDLER IN ADDRESS: TODO: find one +// DISABLE INTERRUPTS +// PROCESS INTERRUPT +// ENABLE INTERRUPTS + +//////////////////////////////// \ No newline at end of file diff --git a/CompilerKit/AsmKit/Arch/64k.hpp b/CompilerKit/AsmKit/Arch/64k.hpp new file mode 100644 index 0000000..e5c5253 --- /dev/null +++ b/CompilerKit/AsmKit/Arch/64k.hpp @@ -0,0 +1,102 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include + +// @brief 64x0 support. +// @file Arch/64k.hpp + +#define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ + { .fName = __NAME, .fOpcode = __OPCODE, .fFunct3 = __FUNCT3, .fFunct7 = __FUNCT7 }, + + + +// placeholder for funct7/funct7-rs2 +#define kAsmImmediate 0x00 +#define kAsmRegToReg 0x01 +#define kAsmSyscall 0x02 +#define kAsmJump 0x03 + +struct CpuCode64x0 +{ + const char fName[16]; + char fOpcode; + char fFunct3; + char fFunct7; +}; + +inline std::vector kOpcodes64x0 = { + kAsmOpcodeDecl("np", 0b0100011, 0b0000000, kAsmImmediate) // mv r0, r0 + kAsmOpcodeDecl("jb", 0b1110011, 0b0000011, kAsmJump) // jump to branch + kAsmOpcodeDecl("jlr", 0b1110011, 0b0000111, kAsmJump) // jump and link return register + kAsmOpcodeDecl("jrl", 0b1110011, 0b0001111, kAsmJump) // jump to register link + kAsmOpcodeDecl("jr", 0b1110011, 0b0001011, kAsmJump) // jump to register + kAsmOpcodeDecl("jal", 0b1110011, 0b0000001, kAsmJump) + kAsmOpcodeDecl("mv", 0b0100011, 0b101, kAsmRegToReg) + kAsmOpcodeDecl("psh", 0b0111011, 0b0, kAsmImmediate) // push to sp + kAsmOpcodeDecl("pop", 0b0111011, 0b1, kAsmImmediate) // pop from sp. + 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) + kAsmOpcodeDecl("add", 0b0101011, 0b100, kAsmImmediate) + kAsmOpcodeDecl("dec", 0b0101011, 0b101, kAsmImmediate) + kAsmOpcodeDecl("scall", 0b1110011, 0b00, kAsmSyscall) + kAsmOpcodeDecl("sbreak", 0b1110011, 0b01, kAsmSyscall) + kAsmOpcodeDecl("mh", 0b1110011, 0b1111111, kAsmJump) +}; + +// \brief NewCPU register prefix +// example: r32, r0 +// r32 -> sp +// r0 -> hw zero + +#define kAsmRegisterPrefix "r" +#define kAsmRegisterLimit 20 +#define kAsmPcRegister 17 +#define kAsmCrRegister 18 +#define kAsmSpRegister 5 + +/* return address register */ +#define kAsmRetRegister 19 + +///////////////////////////////////////////////////////////////////////////// + +// SYSTEM CALL ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | OFF | + +// IMMEDIATE ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | +// | OPCODE | FUNCT3 | FUNCT7 | REG | OFF | REG | +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG | OFF | + +// REG TO REG ADDRESSING + +// | OPCODE | FUNCT3 | FUNCT7 | REG | REG2 | + +//////////////////////////////// + +// LOAD/CALL INTERRUPTS + +// SET A HANDLER IN ADDRESS: TODO: find one +// DISABLE INTERRUPTS +// PROCESS INTERRUPT +// ENABLE INTERRUPTS + +//////////////////////////////// \ No newline at end of file diff --git a/CompilerKit/AsmKit/AsmKit.cc b/CompilerKit/AsmKit/AsmKit.cc new file mode 100644 index 0000000..4ee031f --- /dev/null +++ b/CompilerKit/AsmKit/AsmKit.cc @@ -0,0 +1,47 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#include +#include + +#include + +//! @file AsmKit.cpp +//! @brief AssemblyKit + +namespace CompilerKit +{ + //! @brief Compile for specific format (ELF, PEF, ZBIN) + Int32 AssemblyFactory::Compile(StringView& sourceFile, + const Int32& arch) noexcept + { + if (sourceFile.Length() < 1 || + !fMounted) + return CXXKIT_UNIMPLEMENTED; + + return fMounted->CompileToFormat(sourceFile, arch); + } + + //! @brief mount assembly backend. + void AssemblyFactory::Mount(AssemblyMountpoint* mountPtr) noexcept + { + if (mountPtr) + fMounted = mountPtr; + } + + AssemblyMountpoint* AssemblyFactory::Unmount() noexcept + { + auto mount_prev = fMounted; + + if (mount_prev) + fMounted = nullptr; + + return mount_prev; + } +} diff --git a/CompilerKit/AsmKit/AsmKit.hpp b/CompilerKit/AsmKit/AsmKit.hpp new file mode 100644 index 0000000..f512507 --- /dev/null +++ b/CompilerKit/AsmKit/AsmKit.hpp @@ -0,0 +1,63 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include +#include + +namespace CompilerKit +{ + // + // @brief Frontend to Assembly mountpoint. + // + class AssemblyMountpoint + { + public: + explicit AssemblyMountpoint() = default; + virtual ~AssemblyMountpoint() = default; + + CXXKIT_COPY_DEFAULT(AssemblyMountpoint); + + //@ brief compile to object file. + // Example C++ -> MASM -> AE object. + virtual Int32 CompileToFormat(StringView& src, Int32 arch) = 0; + + }; + + /// @brief Simple assembly factory + class AssemblyFactory final + { + public: + explicit AssemblyFactory() = default; + ~AssemblyFactory() = default; + + CXXKIT_COPY_DEFAULT(AssemblyFactory); + + public: + enum + { + kArchAMD64, + kArch32x0, + kArch64x0, + kArchRISCV, + kArchUnknown, + }; + + Int32 Compile(StringView& sourceFile, const Int32& arch) noexcept; + + void Mount(AssemblyMountpoint* mountPtr) noexcept; + AssemblyMountpoint* Unmount() noexcept; + + private: + AssemblyMountpoint* fMounted{ nullptr }; + + }; +} diff --git a/CompilerKit/Defines.hpp b/CompilerKit/Defines.hpp new file mode 100644 index 0000000..00c75f6 --- /dev/null +++ b/CompilerKit/Defines.hpp @@ -0,0 +1,135 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#ifndef __CXXKIT_DEFINES_HPP__ +#define __CXXKIT_DEFINES_HPP__ + +#ifndef Yes +#define Yes true +#endif // ifndef Yes + +#ifndef No +#define No false +#endif // ifndef No + +#include + +#define SizeType size_t + +#define VoidPtr void* +#define voidPtr VoidPtr + +#define UIntPtr uintptr_t + +#define Int64 int64_t +#define UInt64 uint64_t + +#define Int32 int32_t +#define UInt32 uint32_t + +#define Bool bool + +#define Int16 int16_t +#define UInt16 uint16_t + +#define Int8 int8_t +#define UInt8 uint8_t + +#define CharType char +#define Boolean bool + +#include +#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 CXXKIT_COPY_DELETE(KLASS) \ + KLASS &operator=(const KLASS &) = delete; \ + KLASS(const KLASS &) = delete; + + +#define CXXKIT_COPY_DEFAULT(KLASS) \ + KLASS &operator=(const KLASS &) = default; \ + KLASS(const KLASS &) = default; + + +#define CXXKIT_MOVE_DELETE(KLASS) \ + KLASS &operator=(KLASS &&) = delete; \ + KLASS(KLASS &&) = delete; + + +#define CXXKIT_MOVE_DEFAULT(KLASS) \ + KLASS &operator=(KLASS &&) = default; \ + KLASS(KLASS &&) = default; + + + +#include +#include + +namespace CompilerKit +{ + inline constexpr int BASE_YEAR = 1900; + + inline std::string current_date() + { + auto time_data = time(nullptr); + auto time_struct = gmtime(&time_data); + + std::string fmt = std::to_string(BASE_YEAR + time_struct->tm_year); + fmt += "-"; + fmt += std::to_string(time_struct->tm_mon + 1); + fmt += "-"; + fmt += std::to_string(time_struct->tm_mday); + + return fmt; + } + + inline bool to_str(CharType *str, Int32 limit, Int32 base) + { + if (limit == 0) + return false; + + Int32 copy_limit = limit; + Int32 cnt = 0; + Int32 ret = base; + + while (limit != 1) { + ret = ret % 10; + str[cnt] = ret; + + ++cnt; + --limit; + --ret; + } + + str[copy_limit] = '\0'; + return true; + } +} + +#define kObjectFileExt ".o" +#define kAsmFileExt64x0 ".64x" + +#endif /* ifndef __CXXKIT_DEFINES_HPP__ */ diff --git a/CompilerKit/ParserKit.hpp b/CompilerKit/ParserKit.hpp new file mode 100644 index 0000000..ce207a1 --- /dev/null +++ b/CompilerKit/ParserKit.hpp @@ -0,0 +1,93 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include + +namespace ParserKit +{ + using namespace CompilerKit; + + class CompilerBackend + { + public: + explicit CompilerBackend() = default; + virtual ~CompilerBackend() = default; + + CXXKIT_COPY_DEFAULT(CompilerBackend); + + // NOTE: cast this to your user defined ast. + typedef void* AstType; + + //! @brief Compile a syntax tree ouf of the text. + //! Also takes the source file name for metadata. + + virtual bool Compile(const std::string& text, const char* file) = 0; + + //! @brief What language are we dealing with? + virtual const char* Language() { return "Generic Language"; } + + }; + + struct SyntaxLeafList; + struct SyntaxLeafList; + + struct SyntaxLeafList final + { + struct SyntaxLeaf final + { + Int32 fUserType; + std::string fUserData; + std::string fUserValue; + struct SyntaxLeaf* fNext; + }; + + std::vector 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()); + } + + inline bool find_word_strict(const std::string& haystack, const std::string& needle) noexcept + { + return ParserKit::find_word(haystack, needle) && + isspace(haystack[haystack.find(needle) + needle.size() + 1]); + } +} \ No newline at end of file diff --git a/CompilerKit/StdKit/AE.hpp b/CompilerKit/StdKit/AE.hpp new file mode 100644 index 0000000..3aafc20 --- /dev/null +++ b/CompilerKit/StdKit/AE.hpp @@ -0,0 +1,61 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, 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; + SizeType fCount; + CharType fSize; + SizeType fStartCode; + SizeType fCodeSize; + CharType fPad[kAEPad]; + } __attribute__((packed)) AEHeader, *AEHeaderPtr; + + // @brief Advanced Executable Record. + // Could be data, code or bss. + // fKind must be filled with PEF fields. + + typedef struct AERecordHeader final + { + CharType fName[kAESymbolLen]; + SizeType fKind; + SizeType fSize; + SizeType fFlags; + UIntPtr fOffset; + CharType fPad[kAEPad]; + } __attribute__((packed)) AERecordHeader, *AERecordHeaderPtr; + + enum + { + kKindRelocationByOffset = 0x23f, + kKindRelocationAtRuntime = 0x34f, + }; +} diff --git a/CompilerKit/StdKit/ErrorID.hpp b/CompilerKit/StdKit/ErrorID.hpp new file mode 100644 index 0000000..b4b204c --- /dev/null +++ b/CompilerKit/StdKit/ErrorID.hpp @@ -0,0 +1,22 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +#define CXXKIT_EXEC_ERROR -30 +#define CXXKIT_FILE_NOT_FOUND -31 +#define CXXKIT_DIR_NOT_FOUND -32 +#define CXXKIT_FILE_EXISTS -33 +#define CXXKIT_TOO_LONG -34 +#define CXXKIT_INVALID_DATA -35 +#define CXXKIT_UNIMPLEMENTED -36 +#define CXXKIT_FAT_ERROR -37 diff --git a/CompilerKit/StdKit/ErrorOr.hpp b/CompilerKit/StdKit/ErrorOr.hpp new file mode 100644 index 0000000..c2457df --- /dev/null +++ b/CompilerKit/StdKit/ErrorOr.hpp @@ -0,0 +1,58 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright Western Company, 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/CompilerKit/StdKit/PEF.hpp b/CompilerKit/StdKit/PEF.hpp new file mode 100644 index 0000000..5ff77f8 --- /dev/null +++ b/CompilerKit/StdKit/PEF.hpp @@ -0,0 +1,85 @@ +/* + * ======================================================== + * + * C++Kit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include + +#define kPefMagic "PEF" +#define kPefMagicFat "FEP" + +#define kPefMagicLen 3 + +#define kPefVersion 1 +#define kPefNameLen 64 + +// Protable Executable Format, a format designed for any computer. + +namespace CompilerKit +{ + enum + { + kPefArchIntel86S = 100, + kPefArchAMD64, + kPefArchRISCV, + kPefArch64000, /* Advanced RISC architecture. */ + kPefArch32000, + kPefArchInvalid = 0xFF, + }; + + enum + { + kPefKindExec = 1, /* .o/.pef/ */ + kPefKindSharedObject = 2, /* .lib */ + kPefKindObject = 4, /* .obj */ + kPefKindDwarf = 5, /* .dsym */ + }; + + /* PEF container */ + typedef struct PEFContainer final + { + CharType Magic[kPefMagicLen]; + UInt32 Linker; + UInt32 Version; + UInt32 Kind; + UInt32 Abi; + UInt32 Cpu; + UInt32 SubCpu; /* Cpu specific information */ + UIntPtr Start; + SizeType HdrSz; /* Size of header */ + SizeType Count; /* container header count */ + } __attribute__((packed)) PEFContainer; + + /* First PEFCommandHeader starts after PEFContainer */ + /* Last container is __exec_end */ + + /* PEF executable section and commands. */ + + typedef struct PEFCommandHeader final + { + CharType Name[kPefNameLen]; /* container name */ + UInt32 Flags; /* container flags */ + UInt16 Kind; /* container kind */ + UIntPtr Offset; /* file offset */ + SizeType Size; /* file size */ + } __attribute__((packed)) PEFCommandHeader; + + enum + { + kPefCode = 0xC, + kPefData = 0xD, + kPefZero = 0xE, + kPefLinkerID = 0x1, + }; +} + +#define kPefExt ".o" +#define kPefDylibExt ".so" +#define kPefObjectExt ".o" +#define kPefDebugExt ".dbg" \ No newline at end of file diff --git a/CompilerKit/StdKit/Ref.hpp b/CompilerKit/StdKit/Ref.hpp new file mode 100644 index 0000000..2ca540a --- /dev/null +++ b/CompilerKit/StdKit/Ref.hpp @@ -0,0 +1,89 @@ + +/* + * ======================================================== + * + * CompilerKit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include + +namespace CompilerKit +{ + // @author Western Company + // @brief Reference class, refers to a pointer of data in static memory. + template + class Ref final + { + public: + Ref() = default; + ~Ref() = default; + + public: + 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; + + 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/CompilerKit/StdKit/String.cc b/CompilerKit/StdKit/String.cc new file mode 100644 index 0000000..6f11404 --- /dev/null +++ b/CompilerKit/StdKit/String.cc @@ -0,0 +1,230 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#include "String.hpp" +#include + +namespace CompilerKit +{ + CharType* StringView::Data() + { + return m_Data.data(); + } + + const CharType* StringView::CData() const + { + return m_Data.c_str(); + } + + SizeType StringView::Length() const + { + return m_Data.size(); + } + + bool StringView::operator==(const StringView &rhs) const + { + if (rhs.Length() != Length()) + return false; + + for (SizeType index = 0; index < Length(); ++index) + { + if (rhs.m_Data[index] != m_Data[index]) + return false; + } + + return true; + } + + bool StringView::operator==(const CharType *rhs) const + { + if (string_length(rhs) != Length()) + return false; + + for (SizeType index = 0; index < string_length(rhs); ++index) + { + if (rhs[index] != m_Data[index]) + return false; + } + + return true; + } + + bool StringView::operator!=(const StringView &rhs) const + { + if (rhs.Length() != Length()) + return false; + + for (SizeType index = 0; index < rhs.Length(); ++index) + { + if (rhs.m_Data[index] == m_Data[index]) + return false; + } + + return true; + } + + bool StringView::operator!=(const CharType *rhs) const + { + if (string_length(rhs) != Length()) + return false; + + for (SizeType index = 0; index < string_length(rhs); ++index) + { + if (rhs[index] == m_Data[index]) + return false; + } + + return true; + } + + StringView StringBuilder::Construct(const CharType *data) + { + if (!data || + *data == 0) + return StringView(0); + + StringView view(strlen(data)); + view += data; + + return view; + } + + const char* StringBuilder::FromInt(const char *fmt, int i) + { + if (!fmt) + return ("-1"); + + char *ret = new char[8 + string_length(fmt)]; + + if (!ret) + return ("-1"); + + CharType result[8]; + if (!to_str(result, sizeof(int), i)) + { + delete[] ret; + return ("-1"); + } + + const auto fmt_len = string_length(fmt); + const auto res_len = string_length(result); + + for (SizeType idx = 0; idx < fmt_len; ++idx) + { + if (fmt[idx] == '%') { + SizeType result_cnt = idx; + + for (auto y_idx = idx; y_idx < res_len; ++y_idx) { + ret[result_cnt] = result[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; /* Copy that ret into a buffer, Alloca allocates to the stack */ + } + + const char* StringBuilder::FromBool(const char *fmt, bool i) + { + if (!fmt) + return ("?"); + + const char *boolean_expr = i ? "true" : "false"; + char *ret = new char[i ? 4 : 5 + string_length(fmt)]; + + if (!ret) + return ("?"); + + const auto fmt_len = string_length(fmt); + const auto res_len = string_length(boolean_expr); + + for (SizeType idx = 0; idx < fmt_len; ++idx) + { + if (fmt[idx] == '%') { + SizeType result_cnt = idx; + + for (auto y_idx = idx; y_idx < res_len; ++y_idx) + { + ret[result_cnt] = boolean_expr[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; + } + + bool StringBuilder::Equals(const char *lhs, const char *rhs) + { + if (string_length(rhs) != string_length(lhs)) + return false; + + for (SizeType index = 0; index < string_length(rhs); ++index) + { + if (rhs[index] != lhs[index]) + return false; + } + + return true; + } + + const char *StringBuilder::Format(const char *fmt, const char *fmt2) + { + if (!fmt || !fmt2) + return ("?"); + + char *ret = new char[string_length(fmt2) + string_length(fmt2)]; + if (!ret) + return ("?"); + + for (SizeType idx = 0; idx < string_length(fmt); ++idx) + { + if (fmt[idx] == '%') { + SizeType result_cnt = idx; + for (SizeType y_idx = 0; y_idx < string_length(fmt2); ++y_idx) + { + ret[result_cnt] = fmt2[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; + } + + StringView &StringView::operator+=(const CharType *rhs) + { + this->m_Data += rhs; + this->m_Cur = this->m_Data.size(); + this->m_Sz = this->m_Data.size(); + + return *this; + } + + StringView &StringView::operator+=(const StringView &rhs) + { + this->m_Data += rhs.CData(); + this->m_Cur = this->m_Data.size(); + this->m_Sz = this->m_Data.size(); + + return *this; + } +} // namespace CompilerKit diff --git a/CompilerKit/StdKit/String.hpp b/CompilerKit/StdKit/String.hpp new file mode 100644 index 0000000..592c244 --- /dev/null +++ b/CompilerKit/StdKit/String.hpp @@ -0,0 +1,72 @@ +/* + * ======================================================== + * + * CompilerKit + * Copyright Western Company, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include +#include + +namespace CompilerKit +{ + class StringView final + { + public: + StringView() = delete; + + explicit StringView(SizeType Sz) : m_Sz(Sz) + { + + } + + ~StringView() = default; + + CXXKIT_COPY_DEFAULT(StringView); + + CharType *Data(); + const CharType *CData() const; + SizeType Length() const; + + bool operator==(const CharType *rhs) const; + bool operator!=(const CharType *rhs) const; + + bool operator==(const StringView &rhs) const; + bool operator!=(const StringView &rhs) const; + + StringView &operator+=(const CharType *rhs); + StringView &operator+=(const StringView &rhs); + + operator bool() + { + return m_Data.empty() == false; + } + + bool operator!() + { + return m_Data.empty() == true; + } + + private: + std::basic_string m_Data{""}; + SizeType m_Sz{0}; + SizeType m_Cur{0}; + + friend class StringBuilder; + + }; + + struct StringBuilder final + { + static StringView Construct(const CharType *data); + static const char* FromInt(const char *fmt, int n); + static const char* FromBool(const char *fmt, bool n); + static const char* Format(const char *fmt, const char* from); + static bool Equals(const char *lhs, const char *rhs); + + }; +} // namespace CompilerKit -- cgit v1.2.3