summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal@nekernel.org>2026-01-21 22:14:31 +0100
committerAmlal El Mahrouss <amlal@nekernel.org>2026-01-21 22:14:31 +0100
commit6c2b1b2f83c492db1e38879719502668276442f6 (patch)
treea3b057c2eef7759010beca6b859eb0e0854026fa
parent470f065bc61bc3dbebe342d426e49a4f70ff335b (diff)
feat: CompilerKit: Assembler and Linker improvements.
Signed-off-by: Amlal El Mahrouss <amlal@nekernel.org>
-rw-r--r--include/CompilerKit/AE.h9
-rw-r--r--include/CompilerKit/Utilities/Compiler.h10
-rw-r--r--src/CompilerKit/src/Assemblers/Assembler+AMD64.cc52
-rw-r--r--src/CompilerKit/src/Assemblers/Assembler+PowerPC.cc34
-rw-r--r--src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc10
-rw-r--r--src/CompilerKit/src/Linkers/DynamicLinker64+MachO.cc10
-rw-r--r--src/CompilerKit/src/Preprocessors/Preprocessor+Generic.cc24
-rw-r--r--src/CompilerKit/test/Linkers/DynamicLinker64+MachO.test.cc28
-rw-r--r--src/CompilerKit/test/Linkers/DynamicLinker64+PEF.test.cc (renamed from src/CompilerKit/test/Linkers/DynamicLinker+PEF64.test.cc)2
-rw-r--r--src/CompilerKit/test/Linkers/ck-linker-test-posix.json3
10 files changed, 97 insertions, 85 deletions
diff --git a/include/CompilerKit/AE.h b/include/CompilerKit/AE.h
index e96861c..777dc0b 100644
--- a/include/CompilerKit/AE.h
+++ b/include/CompilerKit/AE.h
@@ -11,9 +11,9 @@
#define kAEIdentVersion (0x0123)
-#define kAEMag0 'H'
+#define kAEMag0 'A'
#define kAEMag1 'E'
-#define kAEMag2 'Y'
+#define kAEMag2 'O'
#define kAESymbolLen (256)
#define kAEPad (8)
@@ -58,6 +58,11 @@ typedef struct AERecordHeader final {
} PACKED AERecordHeader, *AERecordHeaderPtr;
enum {
+ kKindImportSymbol = 0x356,
+ kKindExportSymbol = 0x237,
+};
+
+enum {
kKindRelocationByOffset = 0x23f,
kKindRelocationAtRuntime = 0x34f,
};
diff --git a/include/CompilerKit/Utilities/Compiler.h b/include/CompilerKit/Utilities/Compiler.h
index 97d1e9c..621f229 100644
--- a/include/CompilerKit/Utilities/Compiler.h
+++ b/include/CompilerKit/Utilities/Compiler.h
@@ -91,15 +91,7 @@ inline void drvi_crash_handler(std::int32_t id) {
switch (id) {
default: {
- kStdOut << "SIGNAL: Unknown Signal (" << id << ")." << kBlank << std::endl;
- break;
- }
- case SIGSEGV: {
- kStdOut << "SIGNAL: Segmentation Fault." << kBlank << std::endl;
- break;
- }
- case SIGABRT: {
- kStdOut << "SIGNAL: Aborted." << kBlank << std::endl;
+ kStdOut << "SIGNAL: Signal (" << id << ")." << kBlank << std::endl;
break;
}
}
diff --git a/src/CompilerKit/src/Assemblers/Assembler+AMD64.cc b/src/CompilerKit/src/Assemblers/Assembler+AMD64.cc
index f6bbf2e..efe9b8c 100644
--- a/src/CompilerKit/src/Assemblers/Assembler+AMD64.cc
+++ b/src/CompilerKit/src/Assemblers/Assembler+AMD64.cc
@@ -115,23 +115,24 @@ NECTAR_MODULE(AssemblerMainAMD64) {
for (size_t i = 1; i < argc; ++i) {
if (argv[i][0] == '-') {
- if (strcmp(argv[i], "--amd64:ver") == 0 || strcmp(argv[i], "--amd64:v") == 0) {
- kStdOut << "AssemblerAMD64: AMD64 Assembler Driver.\nAssemblerAMD64: "
- "v1.10\nAssemblerAMD64: Copyright "
- "(c) Amlal El Mahrouss\n";
+ if (strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-v") == 0) {
+ kStdOut << "AssemblerAMD64: AMD64 Assembler Driver.\nAssemblerAMD64: Copyright (c) 2024-2026 "
+ "Amlal El Mahrouss\n";
+ kStdOut << "AssemblerAMD64: This Software is part of the NeKernel project. (nekernel.org)\n";
return 0;
- } else if (strcmp(argv[i], "--amd64:h") == 0) {
- kStdOut << "AssemblerAMD64: AMD64 Assembler Driver.\nAssemblerAMD64: Copyright (c) 2024 "
+ } else if (strcmp(argv[i], "-help") == 0) {
+ kStdOut << "AssemblerAMD64: AMD64 Assembler Driver.\nAssemblerAMD64: Copyright (c) 2024-2026 "
"Amlal El Mahrouss\n";
+ kStdOut << "AssemblerAMD64: This Software is part of the NeKernel project. (nekernel.org)\n";
kStdOut << "--version: Print program version.\n";
kStdOut << "--verbose: Print verbose output.\n";
kStdOut << "--binary: Output as flat binary.\n";
return 0;
- } else if (strcmp(argv[i], "--amd64:binary") == 0) {
+ } else if (strcmp(argv[i], "--fbinary") == 0) {
kOutputAsBinary = true;
continue;
- } else if (strcmp(argv[i], "--amd64:verbose") == 0) {
+ } else if (strcmp(argv[i], "--fverbose") == 0) {
kVerbose = true;
continue;
}
@@ -192,7 +193,6 @@ NECTAR_MODULE(AssemblerMainAMD64) {
if (kVerbose) {
kStdOut << "Compiling: " + asm_input << "\n";
- kStdOut << "From: " + line << "\n";
}
while (std::getline(file_ptr, line)) {
@@ -366,13 +366,6 @@ static bool asm_read_attributes(std::string line) {
kCurrentRecord.fKind = CompilerKit::kPefZero;
}
- // this is a special case for the start stub.
- // we want this so that ld can find it.
-
- if (name == kPefStart) {
- kCurrentRecord.fKind = CompilerKit::kPefCode;
- }
-
// now we can tell the code size of the previous kCurrentRecord.
if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kAppBytes.size();
@@ -418,30 +411,17 @@ static bool asm_read_attributes(std::string line) {
kDefinedSymbols.push_back(name);
- if (name.find(".code64") != std::string::npos) {
+ if (name.find(kPefCode64) != std::string::npos) {
// data is treated as code.
-
- name_copy.erase(name_copy.find(".code64"), strlen(".code64"));
kCurrentRecord.fKind = CompilerKit::kPefCode;
- } else if (name.find(".data64") != std::string::npos) {
+ } else if (name.find(kPefData64) != std::string::npos) {
// no code will be executed from here.
-
- name_copy.erase(name_copy.find(".data64"), strlen(".data64"));
kCurrentRecord.fKind = CompilerKit::kPefData;
- } else if (name.find(".zero64") != std::string::npos) {
+ } else if (name.find(kPefZero64) != std::string::npos) {
// this is a bss section.
-
- name_copy.erase(name_copy.find(".zero64"), strlen(".zero64"));
kCurrentRecord.fKind = CompilerKit::kPefZero;
}
- // this is a special case for the start stub.
- // we want this so that ld can find it.
-
- if (name == kPefStart) {
- kCurrentRecord.fKind = CompilerKit::kPefCode;
- }
-
while (name_copy.find(" ") != std::string::npos) name_copy.erase(name_copy.find(" "), 1);
kOriginLabel.push_back(std::make_pair(name_copy, kOrigin));
@@ -1204,6 +1184,10 @@ bool CompilerKit::EncoderAMD64::WriteLine(std::string line, std::string file) {
if (bits == 64 || bits == 32) {
if (!hasRBasedRegs && bits >= 32) {
kAppBytes.emplace_back(opcodeAMD64.fOpcode);
+ } else if (hasRBasedRegs && bits == 32) {
+ CompilerKit::Detail::print_error("Invalid combination of operands and registers.",
+ "CompilerKit");
+ throw std::runtime_error("comb_op_reg");
}
if (!onlyOneReg) kAppBytes.emplace_back(0x89);
@@ -1808,7 +1792,9 @@ bool CompilerKit::EncoderAMD64::WriteLine(std::string line, std::string file) {
kRegisterBitWidth = 32U;
} else if (line.find("bits 16") != std::string::npos) {
kRegisterBitWidth = 16U;
- } else if (auto org_pos = line.find("org"); org_pos != std::string::npos) {
+ }
+
+ if (auto org_pos = line.find("org"); org_pos != std::string::npos) {
auto value_pos = org_pos + strlen("org") + 1;
if (value_pos >= line.size()) {
diff --git a/src/CompilerKit/src/Assemblers/Assembler+PowerPC.cc b/src/CompilerKit/src/Assemblers/Assembler+PowerPC.cc
index 8f6119c..35d81b8 100644
--- a/src/CompilerKit/src/Assemblers/Assembler+PowerPC.cc
+++ b/src/CompilerKit/src/Assemblers/Assembler+PowerPC.cc
@@ -290,15 +290,17 @@ static bool asm_read_attributes(std::string line) {
result += name;
- if (name.find(".code64") != std::string::npos) {
+ kCurrentRecord.fKind = CompilerKit::kKindImportSymbol;
+
+ if (name.find(kPefCode64) != std::string::npos) {
// data is treated as code.
- kCurrentRecord.fKind = CompilerKit::kPefCode;
- } else if (name.find(".data64") != std::string::npos) {
+ kCurrentRecord.fKind |= CompilerKit::kPefCode;
+ } else if (name.find(kPefData64) != std::string::npos) {
// no code will be executed from here.
- kCurrentRecord.fKind = CompilerKit::kPefData;
- } else if (name.find(".zero64") != std::string::npos) {
+ kCurrentRecord.fKind |= CompilerKit::kPefData;
+ } else if (name.find(kPefZero64) != std::string::npos) {
// this is a bss section.
- kCurrentRecord.fKind = CompilerKit::kPefZero;
+ kCurrentRecord.fKind |= CompilerKit::kPefZero;
}
// this is a special case for the start stub.
@@ -341,21 +343,17 @@ static bool asm_read_attributes(std::string line) {
if (j == ' ') j = '$';
}
- if (name.find(".code64") != std::string::npos) {
- // data is treated as code.
+ kCurrentRecord.fKind = CompilerKit::kKindExportSymbol;
- name_copy.erase(name_copy.find(".code64"), strlen(".code64"));
- kCurrentRecord.fKind = CompilerKit::kPefCode;
- } else if (name.find(".data64") != std::string::npos) {
+ if (name.find(kPefCode64) != std::string::npos) {
+ // data is treated as code.
+ kCurrentRecord.fKind |= CompilerKit::kPefCode;
+ } else if (name.find(kPefData64) != std::string::npos) {
// no code will be executed from here.
-
- name_copy.erase(name_copy.find(".data64"), strlen(".data64"));
- kCurrentRecord.fKind = CompilerKit::kPefData;
- } else if (name.find(".zero64") != std::string::npos) {
+ kCurrentRecord.fKind |= CompilerKit::kPefData;
+ } else if (name.find(kPefZero64) != std::string::npos) {
// this is a bss section.
-
- name_copy.erase(name_copy.find(".zero64"), strlen(".zero64"));
- kCurrentRecord.fKind = CompilerKit::kPefZero;
+ kCurrentRecord.fKind |= CompilerKit::kPefZero;
}
// this is a special case for the start stub.
diff --git a/src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc b/src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc
index f2cbc04..53a27d2 100644
--- a/src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc
+++ b/src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc
@@ -525,7 +525,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile(
++kFunctionEmbedLevel;
kOriginMap.push_back({mangled_name, kOrigin});
- kOrigin += 2UL; // Account for prologue instructions
+ ++kOrigin;
break;
}
@@ -836,7 +836,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile(
break;
}
- if (valueOfVar.ends_with("{}")) valueOfVar = "rax"; // impl init.
+ if (valueOfVar.ends_with("{}")) valueOfVar = "rax"; // impl init returns back to rax.
syntax_tree.fUserValue +=
instr + nectar_get_variable_ref(varName) + ", " + valueOfVar + "\n";
@@ -849,7 +849,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile(
if (pos == CompilerKit::STLString::npos) {
syntax_tree.fUserValue += nectar_generate_epilogue() + "ret\n";
- kOrigin += 2UL;
+ ++kOrigin;
break;
}
@@ -882,10 +882,10 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile(
}
syntax_tree.fUserValue += nectar_generate_epilogue() + "ret\n";
- kOrigin += 2UL;
+ ++kOrigin;
} catch (...) {
syntax_tree.fUserValue += nectar_generate_epilogue() + "ret\n";
- kOrigin += 2UL;
+ ++kOrigin;
}
if (kCurrentIfCondition) {
diff --git a/src/CompilerKit/src/Linkers/DynamicLinker64+MachO.cc b/src/CompilerKit/src/Linkers/DynamicLinker64+MachO.cc
index 0068350..87b14af 100644
--- a/src/CompilerKit/src/Linkers/DynamicLinker64+MachO.cc
+++ b/src/CompilerKit/src/Linkers/DynamicLinker64+MachO.cc
@@ -86,7 +86,7 @@ static CompilerKit::STLString macho_extract_symbol_name(const CompilerKit::STLSt
}
/// @brief Add a symbol to the symbol table
-static UInt32 AddSymbol(const CompilerKit::STLString& name, uint8_t type, uint8_t sect,
+static UInt32 macho_add_symbol(const CompilerKit::STLString& name, uint8_t type, uint8_t sect,
UInt64 value) {
// Add name to string table (offset 0 is reserved for empty string)
if (kStringTable.empty()) {
@@ -256,16 +256,18 @@ NECTAR_MODULE(DynamicLinker64MachO) {
if (!symbolName.empty()) {
// Determine section number (1 = __text, 2 = __data)
uint8_t sectNum = 0;
- if (section.kind == CompilerKit::kPefCode) {
+ if (section.kind & CompilerKit::kPefCode) {
sectNum = 1; // __text section
- } else if (section.kind == CompilerKit::kPefData) {
+ } else if (section.kind & CompilerKit::kPefData) {
sectNum = 2; // __data section
+ } else if (section.kind & CompilerKit::kPefZero) {
+ sectNum = 3; // __bss section
}
// N_EXT = external, N_SECT = defined in section
uint8_t symType = N_EXT | N_SECT;
- AddSymbol(symbolName, symType, sectNum, ae_records[ae_record_index].fOffset);
+ macho_add_symbol(symbolName, symType, sectNum, ae_records[ae_record_index].fOffset);
if (kVerbose) {
kConsoleOut << "Added symbol: " << symbolName
diff --git a/src/CompilerKit/src/Preprocessors/Preprocessor+Generic.cc b/src/CompilerKit/src/Preprocessors/Preprocessor+Generic.cc
index ab6a9fa..c2c17a8 100644
--- a/src/CompilerKit/src/Preprocessors/Preprocessor+Generic.cc
+++ b/src/CompilerKit/src/Preprocessors/Preprocessor+Generic.cc
@@ -30,7 +30,7 @@ typedef Int32 (*pp_parser_fn_t)(CompilerKit::STLString& line, std::ifstream& hdr
/////////////////////////////////////////////////////////////////////////////////////////
namespace Detail {
-enum {
+enum PPOperatorType : Int32 {
kInvalid = 0,
kEqual = 100,
kGreaterEqThan,
@@ -83,7 +83,7 @@ static CompilerKit::STLString kWorkingDir = "";
int32_t pp_parse_if_condition(Detail::pp_macro_condition& cond, Detail::pp_macro& macro,
bool& inactive_code, bool& defined,
CompilerKit::STLString& macro_str) {
- if (cond.fType == Detail::kEqual) {
+ if (cond.fType == Detail::PPOperatorType::kEqual) {
auto pos = macro_str.find(macro.fName);
if (pos == CompilerKit::STLString::npos) return 0;
@@ -184,7 +184,7 @@ int32_t pp_parse_if_condition(Detail::pp_macro_condition& cond, Detail::pp_macro
lhs = atol(number.c_str());
}
- if (cond.fType == Detail::kGreaterThan) {
+ if (cond.fType == Detail::PPOperatorType::kGreaterThan) {
if (lhs > rhs) {
defined = true;
inactive_code = false;
@@ -195,7 +195,7 @@ int32_t pp_parse_if_condition(Detail::pp_macro_condition& cond, Detail::pp_macro
return 0;
}
- if (cond.fType == Detail::kGreaterEqThan) {
+ if (cond.fType == Detail::PPOperatorType::kGreaterEqThan) {
if (lhs >= rhs) {
defined = true;
inactive_code = false;
@@ -206,7 +206,7 @@ int32_t pp_parse_if_condition(Detail::pp_macro_condition& cond, Detail::pp_macro
return 0;
}
- if (cond.fType == Detail::kLesserEqThan) {
+ if (cond.fType == Detail::PPOperatorType::kLesserEqThan) {
if (lhs <= rhs) {
defined = true;
inactive_code = false;
@@ -217,7 +217,7 @@ int32_t pp_parse_if_condition(Detail::pp_macro_condition& cond, Detail::pp_macro
return 0;
}
- if (cond.fType == Detail::kLesserThan) {
+ if (cond.fType == Detail::PPOperatorType::kLesserThan) {
if (lhs < rhs) {
defined = true;
inactive_code = false;
@@ -550,27 +550,27 @@ void pp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) {
std::vector<Detail::pp_macro_condition> pp_macro_condition_list = {
{
- .fType = Detail::kEqual,
+ .fType = Detail::PPOperatorType::kEqual,
.fTypeName = "==",
},
{
- .fType = Detail::kNotEqual,
+ .fType = Detail::PPOperatorType::kNotEqual,
.fTypeName = "!=",
},
{
- .fType = Detail::kLesserThan,
+ .fType = Detail::PPOperatorType::kLesserThan,
.fTypeName = "<",
},
{
- .fType = Detail::kGreaterThan,
+ .fType = Detail::PPOperatorType::kGreaterThan,
.fTypeName = ">",
},
{
- .fType = Detail::kLesserEqThan,
+ .fType = Detail::PPOperatorType::kLesserEqThan,
.fTypeName = "<=",
},
{
- .fType = Detail::kGreaterEqThan,
+ .fType = Detail::PPOperatorType::kGreaterEqThan,
.fTypeName = ">=",
},
};
diff --git a/src/CompilerKit/test/Linkers/DynamicLinker64+MachO.test.cc b/src/CompilerKit/test/Linkers/DynamicLinker64+MachO.test.cc
new file mode 100644
index 0000000..c6592dd
--- /dev/null
+++ b/src/CompilerKit/test/Linkers/DynamicLinker64+MachO.test.cc
@@ -0,0 +1,28 @@
+// Copyright 2025-2026, Amlal El Mahrouss (amlal@nekernel.org)
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Official repository: https://github.com/nekernel-org/nectar
+
+/// @author Amlal El Mahrouss
+
+#include <CompilerKit/Detail/Config.h>
+#include <gtest/gtest.h>
+
+CK_IMPORT_C Int32 DynamicLinker64MachO(Int32 argc, Char** argv);
+
+static Int32 kArgc{};
+static Char** kArgv{};
+
+Int32 main(Int32 argc, Char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+
+ kArgc = argc;
+ kArgv = argv;
+
+ return RUN_ALL_TESTS();
+}
+
+TEST(LinkerRunMachO, LinkerExitsCorrectly) {
+ EXPECT_TRUE(kArgc > 1);
+ EXPECT_TRUE(DynamicLinker64MachO(kArgc, kArgv) == 0);
+}
diff --git a/src/CompilerKit/test/Linkers/DynamicLinker+PEF64.test.cc b/src/CompilerKit/test/Linkers/DynamicLinker64+PEF.test.cc
index 1277cae..a32bae2 100644
--- a/src/CompilerKit/test/Linkers/DynamicLinker+PEF64.test.cc
+++ b/src/CompilerKit/test/Linkers/DynamicLinker64+PEF.test.cc
@@ -22,7 +22,7 @@ Int32 main(Int32 argc, Char** argv) {
return RUN_ALL_TESTS();
}
-TEST(LinkerRun, LinkerExitsCorrectly) {
+TEST(LinkerRunPEF, LinkerExitsCorrectly) {
EXPECT_TRUE(kArgc > 1);
EXPECT_TRUE(DynamicLinker64PEF(kArgc, kArgv) == 0);
}
diff --git a/src/CompilerKit/test/Linkers/ck-linker-test-posix.json b/src/CompilerKit/test/Linkers/ck-linker-test-posix.json
index 754367b..bebd381 100644
--- a/src/CompilerKit/test/Linkers/ck-linker-test-posix.json
+++ b/src/CompilerKit/test/Linkers/ck-linker-test-posix.json
@@ -9,7 +9,8 @@
"/usr/include/"
],
"sources_path": [
- "DynamicLinker+PEF64.test.cc"
+ "DynamicLinker64+PEF64.test.cc",
+ "DynamicLinker64+MachO.test.cc"
],
"output_name": "LinkerTest.o",
"compiler_flags": [