summaryrefslogtreecommitdiffhomepage
path: root/CompilerKit
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2024-01-04 21:36:54 +0100
committerAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2024-01-04 21:48:09 +0100
commit6cda526bd4efcee31b1ea7405dc46d7985ba64e6 (patch)
treef7d138fd5652cdc0e7a2c4918b36d754969d6cf5 /CompilerKit
parent60271b79a91a06772241aed737426f5d097ca533 (diff)
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 <amlal.elmahrouss@icloud.com>
Diffstat (limited to 'CompilerKit')
-rw-r--r--CompilerKit/AsmKit/Arch/32k.hpp92
-rw-r--r--CompilerKit/AsmKit/Arch/64k.hpp102
-rw-r--r--CompilerKit/AsmKit/AsmKit.cc47
-rw-r--r--CompilerKit/AsmKit/AsmKit.hpp63
-rw-r--r--CompilerKit/Defines.hpp135
-rw-r--r--CompilerKit/ParserKit.hpp93
-rw-r--r--CompilerKit/StdKit/AE.hpp61
-rw-r--r--CompilerKit/StdKit/ErrorID.hpp22
-rw-r--r--CompilerKit/StdKit/ErrorOr.hpp58
-rw-r--r--CompilerKit/StdKit/PEF.hpp85
-rw-r--r--CompilerKit/StdKit/Ref.hpp89
-rw-r--r--CompilerKit/StdKit/String.cc230
-rw-r--r--CompilerKit/StdKit/String.hpp72
13 files changed, 1149 insertions, 0 deletions
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 <CompilerKit/Defines.hpp>
+
+// @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<CpuCode32x0> 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 <CompilerKit/Defines.hpp>
+
+// @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<CpuCode64x0> 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 <AsmKit/AsmKit.hpp>
+#include <StdKit/ErrorID.hpp>
+
+#include <iostream>
+
+//! @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 <CompilerKit/Compiler.hpp>
+#include <CompilerKit/Defines.hpp>
+#include <CompilerKit/StdKit/String.hpp>
+
+namespace CompilerKit
+{
+ //
+ // @brief Frontend to Assembly mountpoint.
+ //
+ class AssemblyMountpoint
+ {
+ public:
+ explicit AssemblyMountpoint() = default;
+ virtual ~AssemblyMountpoint() = default;
+
+ CXXKIT_COPY_DEFAULT(AssemblyMountpoint);
+
+ //@ brief compile to object file.
+ // Example C++ -> MASM -> AE object.
+ virtual Int32 CompileToFormat(StringView& src, Int32 arch) = 0;
+
+ };
+
+ /// @brief Simple assembly factory
+ class AssemblyFactory final
+ {
+ public:
+ explicit AssemblyFactory() = default;
+ ~AssemblyFactory() = default;
+
+ CXXKIT_COPY_DEFAULT(AssemblyFactory);
+
+ public:
+ enum
+ {
+ kArchAMD64,
+ kArch32x0,
+ kArch64x0,
+ kArchRISCV,
+ kArchUnknown,
+ };
+
+ Int32 Compile(StringView& sourceFile, const Int32& arch) noexcept;
+
+ void Mount(AssemblyMountpoint* mountPtr) noexcept;
+ AssemblyMountpoint* Unmount() noexcept;
+
+ private:
+ AssemblyMountpoint* fMounted{ nullptr };
+
+ };
+}
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 <stdint.h>
+
+#define SizeType size_t
+
+#define VoidPtr void*
+#define voidPtr VoidPtr
+
+#define UIntPtr uintptr_t
+
+#define Int64 int64_t
+#define UInt64 uint64_t
+
+#define Int32 int32_t
+#define UInt32 uint32_t
+
+#define Bool bool
+
+#define Int16 int16_t
+#define UInt16 uint16_t
+
+#define Int8 int8_t
+#define UInt8 uint8_t
+
+#define CharType char
+#define Boolean bool
+
+#include <new>
+#include <cstring>
+#include <cassert>
+
+#define nullPtr std::nullptr_t
+
+#define MUST_PASS(E) assert(E)
+
+#ifndef __FORCE_STRLEN
+# define __FORCE_STRLEN 1
+
+# define string_length(len) strlen(len)
+#endif
+
+#ifndef __FORCE_MEMCPY
+# define __FORCE_MEMCPY 1
+
+# define rt_copy_memory(dst, src, len) memcpy(dst, src, len)
+#endif
+
+#define CXXKIT_COPY_DELETE(KLASS) \
+ KLASS &operator=(const KLASS &) = delete; \
+ KLASS(const KLASS &) = delete;
+
+
+#define CXXKIT_COPY_DEFAULT(KLASS) \
+ KLASS &operator=(const KLASS &) = default; \
+ KLASS(const KLASS &) = default;
+
+
+#define CXXKIT_MOVE_DELETE(KLASS) \
+ KLASS &operator=(KLASS &&) = delete; \
+ KLASS(KLASS &&) = delete;
+
+
+#define CXXKIT_MOVE_DEFAULT(KLASS) \
+ KLASS &operator=(KLASS &&) = default; \
+ KLASS(KLASS &&) = default;
+
+
+
+#include <ctime>
+#include <string>
+
+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 <CompilerKit/AsmKit/AsmKit.hpp>
+
+namespace ParserKit
+{
+ using namespace CompilerKit;
+
+ class CompilerBackend
+ {
+ public:
+ explicit CompilerBackend() = default;
+ virtual ~CompilerBackend() = default;
+
+ CXXKIT_COPY_DEFAULT(CompilerBackend);
+
+ // NOTE: cast this to your user defined ast.
+ typedef void* AstType;
+
+ //! @brief Compile a syntax tree ouf of the text.
+ //! Also takes the source file name for metadata.
+
+ virtual bool Compile(const std::string& text, const char* file) = 0;
+
+ //! @brief What language are we dealing with?
+ virtual const char* Language() { return "Generic Language"; }
+
+ };
+
+ struct SyntaxLeafList;
+ struct SyntaxLeafList;
+
+ struct SyntaxLeafList final
+ {
+ struct SyntaxLeaf final
+ {
+ Int32 fUserType;
+ std::string fUserData;
+ std::string fUserValue;
+ struct SyntaxLeaf* fNext;
+ };
+
+ std::vector<SyntaxLeaf> fLeafList;
+ SizeType fNumLeafs;
+
+ size_t SizeOf() { return fNumLeafs; }
+ std::vector<SyntaxLeaf>& Get() { return fLeafList; }
+ SyntaxLeaf& At(size_t index) { return fLeafList[index]; }
+
+ };
+
+ /// find the perfect matching word in a haystack.
+ /// \param haystack base string
+ /// \param needle the string we search for.
+ /// \return if we found it or not.
+ inline bool find_word(const std::string& haystack,const std::string& needle) noexcept
+ {
+ auto index = haystack.find(needle);
+
+ // check for needle validity.
+ if (index == std::string::npos)
+ return false;
+
+ // declare lambda
+ auto not_part_of_word = [&](int index){
+ if (std::isspace(haystack[index]) || std::ispunct(haystack[index]))
+ return true;
+
+ if (index < 0 || index >= haystack.size())
+ return true;
+
+ return false;
+ };
+
+ return not_part_of_word(index - 1) &&
+ not_part_of_word(index + needle.size());
+ }
+
+ 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 <CompilerKit/Defines.hpp>
+
+#define kAEMag0 'A'
+#define kAEMag1 'E'
+
+#define kAESymbolLen 64
+#define kAEPad 8
+#define kAEMagLen 2
+#define kAEInvalidOpcode 0x00
+
+// Advanced Executable File Format for MetroLink.
+// Reloctable by offset is the default strategy.
+// You can also relocate at runtime but that's up to the operating system loader.
+
+namespace CompilerKit
+{
+ // @brief Advanced Executable Header
+ // One thing to keep in mind.
+ // This object format, is reloctable.
+ typedef struct AEHeader final
+ {
+ CharType fMagic[kAEMagLen];
+ CharType fArch;
+ SizeType fCount;
+ CharType fSize;
+ SizeType fStartCode;
+ SizeType fCodeSize;
+ CharType fPad[kAEPad];
+ } __attribute__((packed)) AEHeader, *AEHeaderPtr;
+
+ // @brief Advanced Executable Record.
+ // Could be data, code or bss.
+ // fKind must be filled with PEF fields.
+
+ typedef struct AERecordHeader final
+ {
+ CharType fName[kAESymbolLen];
+ SizeType fKind;
+ SizeType fSize;
+ SizeType fFlags;
+ UIntPtr fOffset;
+ CharType fPad[kAEPad];
+ } __attribute__((packed)) AERecordHeader, *AERecordHeaderPtr;
+
+ enum
+ {
+ kKindRelocationByOffset = 0x23f,
+ kKindRelocationAtRuntime = 0x34f,
+ };
+}
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 <StdKit/ErrorOr.hpp>
+#include <Defines.hpp>
+
+#define CXXKIT_EXEC_ERROR -30
+#define CXXKIT_FILE_NOT_FOUND -31
+#define CXXKIT_DIR_NOT_FOUND -32
+#define CXXKIT_FILE_EXISTS -33
+#define CXXKIT_TOO_LONG -34
+#define CXXKIT_INVALID_DATA -35
+#define CXXKIT_UNIMPLEMENTED -36
+#define CXXKIT_FAT_ERROR -37
diff --git a/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 <CompilerKit/Defines.hpp>
+#include <CompilerKit/StdKit/Ref.hpp>
+
+namespace CompilerKit
+{
+using ErrorT = UInt32;
+
+template <typename T>
+class ErrorOr final
+{
+ public:
+ ErrorOr() = default;
+ ~ErrorOr() = default;
+
+ public:
+ explicit ErrorOr(Int32 err)
+ : mId(err)
+ {}
+
+ explicit ErrorOr(nullPtr Null)
+ {}
+
+ explicit ErrorOr(T Class)
+ : mRef(Class)
+ {}
+
+ ErrorOr &operator=(const ErrorOr &) = default;
+ ErrorOr(const ErrorOr &) = default;
+
+ Ref<T> Leak()
+ {
+ return mRef;
+ }
+
+ operator bool()
+ {
+ return mRef;
+ }
+
+ private:
+ Ref<T> mRef;
+ Int32 mId{0};
+};
+
+using ErrorOrAny = ErrorOr<voidPtr>;
+
+} // namespace CompilerKit
diff --git a/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 <CompilerKit/Defines.hpp>
+
+#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/<none> */
+ kPefKindSharedObject = 2, /* .lib */
+ kPefKindObject = 4, /* .obj */
+ kPefKindDwarf = 5, /* .dsym */
+ };
+
+ /* PEF container */
+ typedef struct PEFContainer final
+ {
+ CharType Magic[kPefMagicLen];
+ UInt32 Linker;
+ UInt32 Version;
+ UInt32 Kind;
+ UInt32 Abi;
+ UInt32 Cpu;
+ UInt32 SubCpu; /* Cpu specific information */
+ UIntPtr Start;
+ 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 <CompilerKit/Defines.hpp>
+
+namespace CompilerKit
+{
+ // @author Western Company
+ // @brief Reference class, refers to a pointer of data in static memory.
+ template <typename T>
+ 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 <typename T>
+ class NonNullRef final
+ {
+ public:
+ NonNullRef() = delete;
+ NonNullRef(nullPtr) = delete;
+
+ NonNullRef(T *ref) : m_Ref(ref, true) {}
+
+ Ref<T> &operator->()
+ {
+ MUST_PASS(m_Ref);
+ return m_Ref;
+ }
+
+ NonNullRef &operator=(const NonNullRef<T> &ref) = delete;
+ NonNullRef(const NonNullRef<T> &ref) = default;
+
+ private:
+ Ref<T> m_Ref{ nullptr };
+
+ };
+} // namespace CompilerKit
diff --git a/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 <utility>
+
+namespace CompilerKit
+{
+ CharType* StringView::Data()
+ {
+ return m_Data.data();
+ }
+
+ const CharType* StringView::CData() const
+ {
+ return m_Data.c_str();
+ }
+
+ SizeType StringView::Length() const
+ {
+ return m_Data.size();
+ }
+
+ bool StringView::operator==(const StringView &rhs) const
+ {
+ if (rhs.Length() != Length())
+ return false;
+
+ for (SizeType index = 0; index < Length(); ++index)
+ {
+ if (rhs.m_Data[index] != m_Data[index])
+ return false;
+ }
+
+ return true;
+ }
+
+ bool StringView::operator==(const CharType *rhs) const
+ {
+ if (string_length(rhs) != Length())
+ return false;
+
+ for (SizeType index = 0; index < string_length(rhs); ++index)
+ {
+ if (rhs[index] != m_Data[index])
+ return false;
+ }
+
+ return true;
+ }
+
+ bool StringView::operator!=(const StringView &rhs) const
+ {
+ if (rhs.Length() != Length())
+ return false;
+
+ for (SizeType index = 0; index < rhs.Length(); ++index)
+ {
+ if (rhs.m_Data[index] == m_Data[index])
+ return false;
+ }
+
+ return true;
+ }
+
+ bool StringView::operator!=(const CharType *rhs) const
+ {
+ if (string_length(rhs) != Length())
+ return false;
+
+ for (SizeType index = 0; index < string_length(rhs); ++index)
+ {
+ if (rhs[index] == m_Data[index])
+ return false;
+ }
+
+ return true;
+ }
+
+ StringView StringBuilder::Construct(const CharType *data)
+ {
+ if (!data ||
+ *data == 0)
+ return StringView(0);
+
+ StringView view(strlen(data));
+ view += data;
+
+ return view;
+ }
+
+ const char* StringBuilder::FromInt(const char *fmt, int i)
+ {
+ if (!fmt)
+ return ("-1");
+
+ char *ret = new char[8 + string_length(fmt)];
+
+ if (!ret)
+ return ("-1");
+
+ CharType result[8];
+ if (!to_str(result, sizeof(int), i))
+ {
+ delete[] ret;
+ return ("-1");
+ }
+
+ const auto fmt_len = string_length(fmt);
+ const auto res_len = string_length(result);
+
+ for (SizeType idx = 0; idx < fmt_len; ++idx)
+ {
+ if (fmt[idx] == '%') {
+ SizeType result_cnt = idx;
+
+ for (auto y_idx = idx; y_idx < res_len; ++y_idx) {
+ ret[result_cnt] = result[y_idx];
+ ++result_cnt;
+ }
+
+ break;
+ }
+
+ ret[idx] = fmt[idx];
+ }
+
+ return ret; /* Copy that ret into a buffer, Alloca allocates to the stack */
+ }
+
+ const char* StringBuilder::FromBool(const char *fmt, bool i)
+ {
+ if (!fmt)
+ return ("?");
+
+ const char *boolean_expr = i ? "true" : "false";
+ char *ret = new char[i ? 4 : 5 + string_length(fmt)];
+
+ if (!ret)
+ return ("?");
+
+ const auto fmt_len = string_length(fmt);
+ const auto res_len = string_length(boolean_expr);
+
+ for (SizeType idx = 0; idx < fmt_len; ++idx)
+ {
+ if (fmt[idx] == '%') {
+ SizeType result_cnt = idx;
+
+ for (auto y_idx = idx; y_idx < res_len; ++y_idx)
+ {
+ ret[result_cnt] = boolean_expr[y_idx];
+ ++result_cnt;
+ }
+
+ break;
+ }
+
+ ret[idx] = fmt[idx];
+ }
+
+ return ret;
+ }
+
+ bool StringBuilder::Equals(const char *lhs, const char *rhs)
+ {
+ if (string_length(rhs) != string_length(lhs))
+ return false;
+
+ for (SizeType index = 0; index < string_length(rhs); ++index)
+ {
+ if (rhs[index] != lhs[index])
+ return false;
+ }
+
+ return true;
+ }
+
+ const char *StringBuilder::Format(const char *fmt, const char *fmt2)
+ {
+ if (!fmt || !fmt2)
+ return ("?");
+
+ char *ret = new char[string_length(fmt2) + string_length(fmt2)];
+ if (!ret)
+ return ("?");
+
+ for (SizeType idx = 0; idx < string_length(fmt); ++idx)
+ {
+ if (fmt[idx] == '%') {
+ SizeType result_cnt = idx;
+ for (SizeType y_idx = 0; y_idx < string_length(fmt2); ++y_idx)
+ {
+ ret[result_cnt] = fmt2[y_idx];
+ ++result_cnt;
+ }
+
+ break;
+ }
+
+ ret[idx] = fmt[idx];
+ }
+
+ return ret;
+ }
+
+ StringView &StringView::operator+=(const CharType *rhs)
+ {
+ this->m_Data += rhs;
+ this->m_Cur = this->m_Data.size();
+ this->m_Sz = this->m_Data.size();
+
+ return *this;
+ }
+
+ StringView &StringView::operator+=(const StringView &rhs)
+ {
+ this->m_Data += rhs.CData();
+ this->m_Cur = this->m_Data.size();
+ this->m_Sz = this->m_Data.size();
+
+ return *this;
+ }
+} // namespace CompilerKit
diff --git a/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 <CompilerKit/Defines.hpp>
+#include <CompilerKit/StdKit/ErrorOr.hpp>
+
+namespace CompilerKit
+{
+ class StringView final
+ {
+ public:
+ StringView() = delete;
+
+ explicit StringView(SizeType Sz) : m_Sz(Sz)
+ {
+
+ }
+
+ ~StringView() = default;
+
+ CXXKIT_COPY_DEFAULT(StringView);
+
+ CharType *Data();
+ const CharType *CData() const;
+ SizeType Length() const;
+
+ bool operator==(const CharType *rhs) const;
+ bool operator!=(const CharType *rhs) const;
+
+ bool operator==(const StringView &rhs) const;
+ bool operator!=(const StringView &rhs) const;
+
+ StringView &operator+=(const CharType *rhs);
+ StringView &operator+=(const StringView &rhs);
+
+ operator bool()
+ {
+ return m_Data.empty() == false;
+ }
+
+ bool operator!()
+ {
+ return m_Data.empty() == true;
+ }
+
+ private:
+ std::basic_string<char> m_Data{""};
+ SizeType m_Sz{0};
+ SizeType m_Cur{0};
+
+ friend class StringBuilder;
+
+ };
+
+ struct StringBuilder final
+ {
+ static StringView Construct(const CharType *data);
+ static const char* FromInt(const char *fmt, int n);
+ static const char* FromBool(const char *fmt, bool n);
+ static const char* Format(const char *fmt, const char* from);
+ static bool Equals(const char *lhs, const char *rhs);
+
+ };
+} // namespace CompilerKit