diff options
| author | Amlal El Mahrouss <amlal@nekernel.org> | 2026-01-18 19:40:59 +0100 |
|---|---|---|
| committer | Amlal El Mahrouss <amlal@nekernel.org> | 2026-01-18 19:49:20 +0100 |
| commit | 300eb04e2567a284f23edff7a8eef96bcd267254 (patch) | |
| tree | fb3c5e1a8bfa74613fddfe345a5f765a97de6c88 /src | |
| parent | bfc06a997671134e7b747557251d2434f8cb8c2e (diff) | |
feat: compiler_kit: improvements on the assembler and linker.
Signed-off-by: Amlal El Mahrouss <amlal@nekernel.org>
Diffstat (limited to 'src')
| -rw-r--r-- | src/CompilerKit/src/Assemblers/Assembler+AMD64.cc | 540 | ||||
| -rw-r--r-- | src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc | 101 | ||||
| -rw-r--r-- | src/CompilerKit/src/Linkers/DynamicLinker64+MachO.cc | 14 | ||||
| -rw-r--r-- | src/CompilerKit/src/Linkers/DynamicLinker64+PEF.cc | 8 |
4 files changed, 560 insertions, 103 deletions
diff --git a/src/CompilerKit/src/Assemblers/Assembler+AMD64.cc b/src/CompilerKit/src/Assemblers/Assembler+AMD64.cc index a4c8d1f..d90791c 100644 --- a/src/CompilerKit/src/Assemblers/Assembler+AMD64.cc +++ b/src/CompilerKit/src/Assemblers/Assembler+AMD64.cc @@ -569,17 +569,16 @@ bool CompilerKit::EncoderAMD64::WriteNumber(const std::size_t& pos, std::string& switch (jump_label[pos + 1]) { case 'x': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); !res) { - if (errno != 0) { - CompilerKit::Detail::print_error("Invalid hex number: " + jump_label, "CompilerKit"); - throw std::runtime_error("invalid_hex"); - } + auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); + res += kOrigin; + + if (errno != 0) { + return false; } - CompilerKit::NumberCast64 num = - CompilerKit::NumberCast64(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16)); + CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(res); - for (auto& i : num.number) { + for (char& i : num.number) { if (i == 0) continue; kAppBytes.push_back(i); @@ -593,15 +592,14 @@ bool CompilerKit::EncoderAMD64::WriteNumber(const std::size_t& pos, std::string& return true; } case 'b': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); !res) { - if (errno != 0) { - CompilerKit::Detail::print_error("Invalid binary number: " + jump_label, "CompilerKit"); - throw std::runtime_error("invalid_bin"); - } + auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); + res += kOrigin; + + if (errno != 0) { + return false; } - CompilerKit::NumberCast64 num = - CompilerKit::NumberCast64(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2)); + CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(res); if (kVerbose) { kStdOut << "AssemblerAMD64: Found a base 2 number here: " << jump_label.substr(pos) << "\n"; @@ -616,15 +614,14 @@ bool CompilerKit::EncoderAMD64::WriteNumber(const std::size_t& pos, std::string& return true; } case 'o': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); !res) { - if (errno != 0) { - CompilerKit::Detail::print_error("Invalid octal number: " + jump_label, "CompilerKit"); - throw std::runtime_error("invalid_octal"); - } + auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); + res += kOrigin; + + if (errno != 0) { + return false; } - CompilerKit::NumberCast64 num = - CompilerKit::NumberCast64(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7)); + CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(res); if (kVerbose) { kStdOut << "AssemblerAMD64: Found a base 8 number here: " << jump_label.substr(pos) << "\n"; @@ -643,15 +640,14 @@ bool CompilerKit::EncoderAMD64::WriteNumber(const std::size_t& pos, std::string& } } - /* check for errno and stuff like that */ - if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) { - if (errno != 0) { - return false; - } + auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); + res += kOrigin; + + if (errno != 0) { + return false; } - CompilerKit::NumberCast64 num = - CompilerKit::NumberCast64(strtol(jump_label.substr(pos).c_str(), nullptr, 10)); + CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(res); for (char& i : num.number) { if (i == 0) continue; @@ -871,15 +867,14 @@ bool CompilerKit::EncoderAMD64::WriteNumber8(const std::size_t& pos, std::string switch (jump_label[pos + 1]) { case 'x': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); !res) { - if (errno != 0) { - CompilerKit::Detail::print_error("Invalid hex number: " + jump_label, "CompilerKit"); - throw std::runtime_error("invalid_hex"); - } + auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); + res += kOrigin; + + if (errno != 0) { + return false; } - CompilerKit::NumberCast8 num = - CompilerKit::NumberCast8(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16)); + CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(res); kAppBytes.push_back(num.number); @@ -891,15 +886,14 @@ bool CompilerKit::EncoderAMD64::WriteNumber8(const std::size_t& pos, std::string return true; } case 'b': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); !res) { - if (errno != 0) { - CompilerKit::Detail::print_error("Invalid binary number: " + jump_label, "CompilerKit"); - throw std::runtime_error("invalid_bin"); - } + auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); + res += kOrigin; + + if (errno != 0) { + return false; } - CompilerKit::NumberCast8 num = - CompilerKit::NumberCast8(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2)); + CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(res); if (kVerbose) { kStdOut << "AssemblerAMD64: Found a base 2 number here: " << jump_label.substr(pos) << "\n"; @@ -910,15 +904,14 @@ bool CompilerKit::EncoderAMD64::WriteNumber8(const std::size_t& pos, std::string return true; } case 'o': { - if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); !res) { - if (errno != 0) { - CompilerKit::Detail::print_error("Invalid octal number: " + jump_label, "CompilerKit"); - throw std::runtime_error("invalid_octal"); - } + auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); + res += kOrigin; + + if (errno != 0) { + return false; } - CompilerKit::NumberCast8 num = - CompilerKit::NumberCast8(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7)); + CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(res); if (kVerbose) { kStdOut << "AssemblerAMD64: Found a base 8 number here: " << jump_label.substr(pos) << "\n"; @@ -933,15 +926,14 @@ bool CompilerKit::EncoderAMD64::WriteNumber8(const std::size_t& pos, std::string } } - /* check for errno and stuff like that */ - if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) { - if (errno != 0) { - return false; - } + auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); + res += kOrigin; + + if (errno != 0) { + return false; } - CompilerKit::NumberCast8 num = - CompilerKit::NumberCast8(strtol(jump_label.substr(pos).c_str(), nullptr, 10)); + CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(res); kAppBytes.push_back(num.number); @@ -994,6 +986,194 @@ bool CompilerKit::EncoderAMD64::WriteLine(std::string line, std::string file) { throw std::runtime_error("syntax_err"); } + /// Handle [reg+n] or [reg-n] memory addressing for any register + if (substr.find('[') != std::string::npos) { + // Parse the memory operand + auto bracketStart = substr.find('['); + auto bracketEnd = substr.find(']'); + + if (bracketStart == std::string::npos || bracketEnd == std::string::npos) { + CompilerKit::Detail::print_error("Syntax error: malformed memory operand.", file); + throw std::runtime_error("syntax_err"); + } + + std::string memOperand = substr.substr(bracketStart + 1, bracketEnd - bracketStart - 1); + + // Register lookup table + struct RegInfo { + const char* name; + i64_byte_t code; + }; + + RegInfo regs64[] = {{"rax", 0}, {"rcx", 1}, {"rdx", 2}, {"rbx", 3}, + {"rsp", 4}, {"rbp", 5}, {"rsi", 6}, {"rdi", 7}}; + + // Find base register in memory operand + i64_byte_t baseReg = 0; + bool foundBase = false; + + for (auto& reg : regs64) { + if (memOperand.find(reg.name) != std::string::npos) { + baseReg = reg.code; + foundBase = true; + break; + } + } + + if (!foundBase) { + CompilerKit::Detail::print_error("Invalid base register in memory operand.", file); + throw std::runtime_error("invalid_base_reg"); + } + + bool isRbp = (baseReg == 5); + bool isRsp = (baseReg == 4); + + // Parse displacement + int32_t displacement = 0; + bool hasDisp = false; + + auto plusPos = memOperand.find('+'); + auto minusPos = memOperand.find('-'); + + if (plusPos != std::string::npos) { + std::string dispStr = memOperand.substr(plusPos + 1); + displacement = static_cast<int32_t>(strtol(dispStr.c_str(), nullptr, 0)); + hasDisp = true; + } else if (minusPos != std::string::npos) { + std::string dispStr = memOperand.substr(minusPos + 1); + displacement = -static_cast<int32_t>(strtol(dispStr.c_str(), nullptr, 0)); + hasDisp = true; + } + + // Determine if destination is memory or register + auto commaPos = substr.find(','); + bool destIsMemory = bracketStart < commaPos; + + // Find register in the other operand + std::string otherOperand; + if (destIsMemory) { + otherOperand = substr.substr(commaPos + 1); + } else { + otherOperand = substr.substr(0, commaPos); + } + + // Remove whitespace + while (!otherOperand.empty() && (otherOperand[0] == ' ' || otherOperand[0] == '\t')) { + otherOperand.erase(0, 1); + } + + // Check for register in other operand + i64_byte_t regCode = 0; + bool foundReg = false; + bool isImmediate = false; + int64_t immValue = 0; + + for (auto& reg : regs64) { + if (otherOperand.find(reg.name) != std::string::npos) { + regCode = reg.code; + foundReg = true; + break; + } + } + + if (!foundReg) { + // Check if it's an immediate value + std::string immStr = otherOperand; + while (!immStr.empty() && (immStr[0] == ' ' || immStr[0] == '\t')) { + immStr.erase(0, 1); + } + if (!immStr.empty() && (isdigit(immStr[0]) || immStr[0] == '-')) { + isImmediate = true; + immValue = strtol(immStr.c_str(), nullptr, 0); + } + } + + // Determine mod field based on displacement size + // mod=00: [reg] no displacement (except rbp which requires disp8) + // mod=01: [reg+disp8] + // mod=10: [reg+disp32] + i64_byte_t mod = 0; + if (!hasDisp && displacement == 0) { + // [rbp] requires disp8 with 0, can't use mod=00 (it means RIP-relative) + mod = isRbp ? 0x01 : 0x00; + } else if (displacement >= -128 && displacement <= 127) { + mod = 0x01; // 8-bit displacement + } else { + mod = 0x02; // 32-bit displacement + } + + if (destIsMemory) { + if (foundReg) { + // mov [reg+n], reg + kAppBytes.emplace_back(0x48); // REX.W + kAppBytes.emplace_back(0x89); // MOV r/m64, r64 + + // ModR/M: mod | reg << 3 | r/m + i64_byte_t modrm = (mod << 6) | (regCode << 3) | baseReg; + kAppBytes.emplace_back(modrm); + + // RSP needs SIB byte + if (isRsp) { + kAppBytes.emplace_back(0x24); // SIB: scale=0, index=4(none), base=4(rsp) + } + } else if (isImmediate) { + // mov qword [reg+n], imm32 + kAppBytes.emplace_back(0x48); // REX.W + kAppBytes.emplace_back(0xC7); // MOV r/m64, imm32 + + // ModR/M: mod | 0 << 3 | r/m (reg field is 0 for this opcode) + i64_byte_t modrm = (mod << 6) | (0 << 3) | baseReg; + kAppBytes.emplace_back(modrm); + + // RSP needs SIB byte + if (isRsp) { + kAppBytes.emplace_back(0x24); + } + } else { + CompilerKit::Detail::print_error("Invalid source operand for mov to memory.", file); + throw std::runtime_error("invalid_operand"); + } + } else { + // mov reg, [reg+n] + kAppBytes.emplace_back(0x48); // REX.W + kAppBytes.emplace_back(0x8B); // MOV r64, r/m64 + + // ModR/M: mod | reg << 3 | r/m + i64_byte_t modrm = (mod << 6) | (regCode << 3) | baseReg; + kAppBytes.emplace_back(modrm); + + // RSP needs SIB byte + if (isRsp) { + kAppBytes.emplace_back(0x24); + } + } + + // Write displacement + if (mod == 0x01) { + // 8-bit displacement + kAppBytes.emplace_back(static_cast<i64_byte_t>(displacement & 0xFF)); + } else if (mod == 0x02) { + // 32-bit displacement + kAppBytes.emplace_back(static_cast<i64_byte_t>(displacement & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((displacement >> 8) & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((displacement >> 16) & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((displacement >> 24) & 0xFF)); + } else if (isRbp) { + // rbp with mod=00 still needs disp8=0 + kAppBytes.emplace_back(0x00); + } + + // Write immediate if present + if (destIsMemory && isImmediate) { + kAppBytes.emplace_back(static_cast<i64_byte_t>(immValue & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((immValue >> 8) & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((immValue >> 16) & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((immValue >> 24) & 0xFF)); + } + + break; + } + bool onlyOneReg = true; std::vector<RegMapAMD64> currentRegList; @@ -1144,6 +1324,252 @@ bool CompilerKit::EncoderAMD64::WriteLine(std::string line, std::string file) { break; } + /// Compare instruction handler. + if (name == "cmp") { + std::string substr = line.substr(line.find(name) + name.size()); + + if (substr.find(",") == std::string::npos) { + CompilerKit::Detail::print_error("Syntax error: missing right operand.", "CompilerKit"); + throw std::runtime_error("syntax_err"); + } + + // Register lookup table + struct RegInfo { + const char* name; + i64_byte_t code; + }; + + RegInfo regs64[] = {{"rax", 0}, {"rcx", 1}, {"rdx", 2}, {"rbx", 3}, + {"rsp", 4}, {"rbp", 5}, {"rsi", 6}, {"rdi", 7}}; + + /// Handle [reg+n] memory addressing + if (substr.find('[') != std::string::npos) { + auto bracketStart = substr.find('['); + auto bracketEnd = substr.find(']'); + + if (bracketEnd == std::string::npos) { + CompilerKit::Detail::print_error("Syntax error: malformed memory operand.", file); + throw std::runtime_error("syntax_err"); + } + + std::string memOperand = substr.substr(bracketStart + 1, bracketEnd - bracketStart - 1); + + // Find base register + i64_byte_t baseReg = 0; + bool foundBase = false; + + for (auto& reg : regs64) { + if (memOperand.find(reg.name) != std::string::npos) { + baseReg = reg.code; + foundBase = true; + break; + } + } + + if (!foundBase) { + CompilerKit::Detail::print_error("Invalid base register in memory operand.", file); + throw std::runtime_error("invalid_base_reg"); + } + + bool isRbp = (baseReg == 5); + bool isRsp = (baseReg == 4); + + // Parse displacement + int32_t displacement = 0; + bool hasDisp = false; + + auto plusPos = memOperand.find('+'); + auto minusPos = memOperand.find('-'); + + if (plusPos != std::string::npos) { + std::string dispStr = memOperand.substr(plusPos + 1); + displacement = static_cast<int32_t>(strtol(dispStr.c_str(), nullptr, 0)); + hasDisp = true; + } else if (minusPos != std::string::npos) { + std::string dispStr = memOperand.substr(minusPos + 1); + displacement = -static_cast<int32_t>(strtol(dispStr.c_str(), nullptr, 0)); + hasDisp = true; + } + + auto commaPos = substr.find(','); + bool destIsMemory = bracketStart < commaPos; + + std::string otherOperand; + if (destIsMemory) { + otherOperand = substr.substr(commaPos + 1); + } else { + otherOperand = substr.substr(0, commaPos); + } + + while (!otherOperand.empty() && (otherOperand[0] == ' ' || otherOperand[0] == '\t')) { + otherOperand.erase(0, 1); + } + + i64_byte_t regCode = 0; + bool foundReg = false; + bool isImmediate = false; + int64_t immValue = 0; + + for (auto& reg : regs64) { + if (otherOperand.find(reg.name) != std::string::npos) { + regCode = reg.code; + foundReg = true; + break; + } + } + + if (!foundReg) { + std::string immStr = otherOperand; + while (!immStr.empty() && (immStr[0] == ' ' || immStr[0] == '\t')) { + immStr.erase(0, 1); + } + if (!immStr.empty() && (isdigit(immStr[0]) || immStr[0] == '-')) { + isImmediate = true; + immValue = strtol(immStr.c_str(), nullptr, 0); + } + } + + // Determine mod field + i64_byte_t mod = 0; + if (!hasDisp && displacement == 0) { + mod = isRbp ? 0x01 : 0x00; + } else if (displacement >= -128 && displacement <= 127) { + mod = 0x01; + } else { + mod = 0x02; + } + + if (destIsMemory) { + if (foundReg) { + // cmp [reg+n], reg + kAppBytes.emplace_back(0x48); // REX.W + kAppBytes.emplace_back(0x39); // CMP r/m64, r64 + + i64_byte_t modrm = (mod << 6) | (regCode << 3) | baseReg; + kAppBytes.emplace_back(modrm); + + if (isRsp) { + kAppBytes.emplace_back(0x24); + } + } else if (isImmediate) { + // cmp qword [reg+n], imm32 + kAppBytes.emplace_back(0x48); // REX.W + kAppBytes.emplace_back(0x81); // CMP r/m64, imm32 + + // reg field = 7 for CMP + i64_byte_t modrm = (mod << 6) | (7 << 3) | baseReg; + kAppBytes.emplace_back(modrm); + + if (isRsp) { + kAppBytes.emplace_back(0x24); + } + } + } else { + // cmp reg, [reg+n] + kAppBytes.emplace_back(0x48); // REX.W + kAppBytes.emplace_back(0x3B); // CMP r64, r/m64 + + i64_byte_t modrm = (mod << 6) | (regCode << 3) | baseReg; + kAppBytes.emplace_back(modrm); + + if (isRsp) { + kAppBytes.emplace_back(0x24); + } + } + + // Write displacement + if (mod == 0x01) { + kAppBytes.emplace_back(static_cast<i64_byte_t>(displacement & 0xFF)); + } else if (mod == 0x02) { + kAppBytes.emplace_back(static_cast<i64_byte_t>(displacement & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((displacement >> 8) & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((displacement >> 16) & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((displacement >> 24) & 0xFF)); + } else if (isRbp) { + kAppBytes.emplace_back(0x00); + } + + // Write immediate + if (destIsMemory && isImmediate) { + kAppBytes.emplace_back(static_cast<i64_byte_t>(immValue & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((immValue >> 8) & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((immValue >> 16) & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((immValue >> 24) & 0xFF)); + } + + break; + } + + // Handle register-to-register and register-to-immediate + i64_byte_t reg1Code = 0; + i64_byte_t reg2Code = 0; + bool foundReg1 = false; + bool foundReg2 = false; + bool isImmediate = false; + int64_t immValue = 0; + + auto commaPos = substr.find(','); + std::string leftOperand = substr.substr(0, commaPos); + std::string rightOperand = substr.substr(commaPos + 1); + + while (!leftOperand.empty() && (leftOperand[0] == ' ' || leftOperand[0] == '\t')) { + leftOperand.erase(0, 1); + } + while (!rightOperand.empty() && (rightOperand[0] == ' ' || rightOperand[0] == '\t')) { + rightOperand.erase(0, 1); + } + + for (auto& reg : regs64) { + if (leftOperand.find(reg.name) != std::string::npos) { + reg1Code = reg.code; + foundReg1 = true; + break; + } + } + + for (auto& reg : regs64) { + if (rightOperand.find(reg.name) != std::string::npos) { + reg2Code = reg.code; + foundReg2 = true; + break; + } + } + + if (!foundReg2) { + if (!rightOperand.empty() && (isdigit(rightOperand[0]) || rightOperand[0] == '-')) { + isImmediate = true; + immValue = strtol(rightOperand.c_str(), nullptr, 0); + } + } + + if (foundReg1 && foundReg2) { + // cmp reg1, reg2 + kAppBytes.emplace_back(0x48); // REX.W + kAppBytes.emplace_back(0x39); // CMP r/m64, r64 + + i64_byte_t modrm = (0x3 << 6) | (reg2Code << 3) | reg1Code; + kAppBytes.emplace_back(modrm); + } else if (foundReg1 && isImmediate) { + // cmp reg, imm + kAppBytes.emplace_back(0x48); // REX.W + kAppBytes.emplace_back(0x81); // CMP r/m64, imm32 + + // reg field = 7 for CMP + i64_byte_t modrm = (0x3 << 6) | (7 << 3) | reg1Code; + kAppBytes.emplace_back(modrm); + + kAppBytes.emplace_back(static_cast<i64_byte_t>(immValue & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((immValue >> 8) & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((immValue >> 16) & 0xFF)); + kAppBytes.emplace_back(static_cast<i64_byte_t>((immValue >> 24) & 0xFF)); + } else { + CompilerKit::Detail::print_error("Invalid operands for cmp instruction.", file); + throw std::runtime_error("invalid_cmp_operands"); + } + + break; + } + /// Push instruction handler. if (name == "push" || name == "pop") { std::string substr = line.substr(line.find(name) + name.size()); diff --git a/src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc b/src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc index 720fdee..1889035 100644 --- a/src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc +++ b/src/CompilerKit/src/Compilers/NectarCompiler+AMD64.cc @@ -345,33 +345,59 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile( left.erase(left.find(" "), 1); } - auto right = left.substr(left.find_first_of("==") + 2); - - auto tmp = left.substr(0, left.find_first_of("==")); - left = std::move(tmp); - - syntax_tree.fUserValue += - "mov rdi, " + - (isnumber(left[0]) - ? left - : (nectar_get_variable_ref(left).empty() ? left : nectar_get_variable_ref(left))) + - "\n"; - - syntax_tree.fUserValue += "mov rsi, " + - (isnumber(right[0]) ? right - : (nectar_get_variable_ref(right).empty() - ? right - : nectar_get_variable_ref(right))) + - "\n"; + std::vector<std::pair<CompilerKit::STLString, CompilerKit::STLString>> operators = { + {"==", "je"}, {"!=", "jne"}, {">=", "jge"}, {"<=", "jle"}, {">", "jg"}, {"<", "jl"}, + }; + + for (auto& op : operators) { + if (left.find(op.first) == CompilerKit::STLString::npos) continue; + + auto right = left.substr(left.find(op.first) + op.first.size()); + + auto tmp = left.substr(0, left.find(op.first)); + left = std::move(tmp); + + if (!nectar_get_variable_ref(left).empty()) + syntax_tree.fUserValue += "mov rdi, " + + (isnumber(left[0]) ? left + : (nectar_get_variable_ref(left).empty() + ? left + : nectar_get_variable_ref(left))) + + "\n"; + else + syntax_tree.fUserValue += "mov rdi, " + + (isnumber(left[0]) ? left + : (nectar_get_variable_ref(left).empty() + ? left + : nectar_get_variable_ref(left))) + + "\n"; + + if (!nectar_get_variable_ref(left).empty()) + syntax_tree.fUserValue += + "lea rsi, " + + (isnumber(right[0]) + ? right + : (nectar_get_variable_ref(right).empty() ? right + : nectar_get_variable_ref(right))) + + "\n"; + else + syntax_tree.fUserValue += + "mov rsi, " + + (isnumber(right[0]) + ? right + : (nectar_get_variable_ref(right).empty() ? right + : nectar_get_variable_ref(right))) + + "\n"; - syntax_tree.fUserValue += "cmp rdi, rsi\n"; + syntax_tree.fUserValue += "cmp rdi, rsi\n"; - syntax_tree.fUserValue += - "jne __ret_" + std::to_string(kOrigin) + "_" + kCurrentFunctionName + "\n"; + syntax_tree.fUserValue += + op.second + " __ret_" + std::to_string(kOrigin) + "_" + kCurrentFunctionName + "\n"; - kCurrentFunctionName = std::to_string(kOrigin) + "_" + kCurrentFunctionName; + kCurrentFunctionName = std::to_string(kOrigin) + "_" + kCurrentFunctionName; - ++kOrigin; + ++kOrigin; + } break; } @@ -776,8 +802,12 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile( kExternalSymbols.insert(mangled + valueOfVar); if (!kNasmOutput) { - syntax_tree.fUserValue += instr + nectar_get_variable_ref(varName) + ", __thiscall " + - mangled + valueOfVar + "\n"; + if (valueOfVar.ends_with(")")) + syntax_tree.fUserValue += instr + nectar_get_variable_ref(varName) + + ", __thiscall " + mangled + valueOfVar + "\n"; + else + syntax_tree.fUserValue += + instr + nectar_get_variable_ref(varName) + ", " + mangled + valueOfVar + "\n"; } else { // NASM: Generate call and move result syntax_tree.fUserValue += "call " + mangled + valueOfVar + "\n"; @@ -816,7 +846,7 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile( auto ref = nectar_get_variable_ref(subText); - if (ref.empty() == false) syntax_tree.fUserValue += "mov rax, " + ref + "\n"; + if (ref.empty() == false) syntax_tree.fUserValue += "lea rax, " + ref + "\n"; if (subText.starts_with("'") || isnumber(subText[0])) syntax_tree.fUserValue += "mov rax, " + subText + "\n"; @@ -841,7 +871,8 @@ CompilerKit::SyntaxLeafList::SyntaxLeaf CompilerFrontendNectarAMD64::Compile( } if (!kNasmOutput) - syntax_tree.fUserValue += "public_segment .code64 __ret_" + kCurrentFunctionName + "\n"; + syntax_tree.fUserValue += + "public_segment .code64 __ret_" + kCurrentFunctionName + "\nnop\n"; else syntax_tree.fUserValue += "__ret_" + kCurrentFunctionName + ":\n"; @@ -1033,12 +1064,12 @@ static CompilerKit::STLString nectar_mangle_name(const CompilerKit::STLString& i /// \brief Generate function prologue static CompilerKit::STLString nectar_generate_prologue() { - return "push rbp\nmov rbp, rsp\n"; + return ""; } /// \brief Generate function epilogue static CompilerKit::STLString nectar_generate_epilogue() { - return "mov rsp, rbp\npop rbp\n"; + return ""; } /// \brief Allocate a variable on the stack @@ -1107,7 +1138,7 @@ static CompilerKit::STLString nectar_get_variable_ref(const CompilerKit::STLStri return varInfo->fRegister; } else { // Stack or spilled - return "qword [rbp" + std::to_string(varInfo->fStackOffset) + "]"; + return "qword [rbp+" + std::to_string(-varInfo->fStackOffset) + "]"; } } @@ -1188,10 +1219,10 @@ static CompilerKit::STLString nectar_spill_lru_variable() { /// if impl init if (!lruVar->fRegister.ends_with("{}")) - spillCode = - "mov qword [rbp" + std::to_string(kContext.fStackOffset) + "], " + lruVar->fRegister + "\n"; + spillCode = "mov qword [rbp+" + std::to_string(-kContext.fStackOffset) + "], " + + lruVar->fRegister + "\n"; else - spillCode = "mov qword [rbp" + std::to_string(kContext.fStackOffset) + "], rax\n"; + spillCode = "mov qword [rbp+" + std::to_string(-kContext.fStackOffset) + "], rax\n"; // Update variable info lruVar->fLocation = VarLocation::kStackSpill; @@ -1255,7 +1286,7 @@ static CompilerKit::STLString nectar_generate_constructor_call( nectar_pop_scope(); CompilerKit::STLString code; - code += "lea r8, [rbp" + std::to_string(offset) + "]\n"; + code += "lea r8, [rbp+" + std::to_string(offset) + "]\n"; code += "call " + ctor_mangled + "\n"; return code; } @@ -1274,7 +1305,7 @@ static CompilerKit::STLString nectar_generate_destructor_call( CompilerKit::STLString code; if (varInfo->fLocation == VarLocation::kStack || varInfo->fLocation == VarLocation::kStackSpill) { - code += "lea r8, [rbp" + std::to_string(varInfo->fStackOffset) + "]\n"; + code += "lea r8, [rbp+" + std::to_string(varInfo->fStackOffset) + "]\n"; } else { code += "mov r8, " + varInfo->fRegister + "\n"; } diff --git a/src/CompilerKit/src/Linkers/DynamicLinker64+MachO.cc b/src/CompilerKit/src/Linkers/DynamicLinker64+MachO.cc index f87e2fc..f076d3c 100644 --- a/src/CompilerKit/src/Linkers/DynamicLinker64+MachO.cc +++ b/src/CompilerKit/src/Linkers/DynamicLinker64+MachO.cc @@ -46,17 +46,17 @@ static std::vector<CompilerKit::Detail::Blob> kTextBytes; static std::vector<CompilerKit::Detail::Blob> kDataBytes; /* symbol table */ -static std::vector<nlist_64> kSymbolTable; -static std::vector<Char> kStringTable; +static std::vector<nlist_64> kSymbolTable; +static std::vector<Char> kStringTable; static std::map<CompilerKit::STLString, UInt64> kSymbolOffsets; /// @brief Structure to hold section information from AE records struct SectionInfo { CompilerKit::STLString name; - UInt32 kind; + UInt32 kind; std::vector<Char> bytes; - UInt64 address; - UInt64 size; + UInt64 address; + UInt64 size; }; /// @brief Extract clean symbol name from AE record name @@ -87,7 +87,7 @@ static CompilerKit::STLString ExtractSymbolName(const CompilerKit::STLString& ae /// @brief Add a symbol to the symbol table static UInt32 AddSymbol(const CompilerKit::STLString& name, uint8_t type, uint8_t sect, - UInt64 value) { + UInt64 value) { // Add name to string table (offset 0 is reserved for empty string) if (kStringTable.empty()) { kStringTable.push_back('\0'); // First byte is null @@ -345,7 +345,7 @@ NECTAR_MODULE(DynamicLinker64MachO) { using namespace CompilerKit::MachO; UInt32 numCommands = 8; // __PAGEZERO, LC_BUILD_VERSION, __TEXT, __LINKEDIT, LC_LOAD_DYLINKER, - // LC_UUID, LC_SYMTAB, LC_DYSYMTAB + // LC_UUID, LC_SYMTAB, LC_DYSYMTAB if (!kIsDylib) { numCommands += 1; // LC_MAIN diff --git a/src/CompilerKit/src/Linkers/DynamicLinker64+PEF.cc b/src/CompilerKit/src/Linkers/DynamicLinker64+PEF.cc index ea513c5..b0a142e 100644 --- a/src/CompilerKit/src/Linkers/DynamicLinker64+PEF.cc +++ b/src/CompilerKit/src/Linkers/DynamicLinker64+PEF.cc @@ -202,8 +202,8 @@ NECTAR_MODULE(DynamicLinker64PEF) { pef_container.Count = 0UL; pef_container.Kind = is_executable ? CompilerKit::kPefKindExec : CompilerKit::kPefKindDylib; pef_container.SubCpu = kSubArch; - pef_container.Linker = kLinkerId; // Amlal El Mahrouss Linker - pef_container.Abi = static_cast<Int32>(kAbi); // Multi-Processor UX ABI + pef_container.Linker = kLinkerId; // Nectar Linker + pef_container.Abi = static_cast<Int32>(kAbi); // Multi-Processor UX ABI pef_container.Magic[0] = kPefMagic[kFatBinaryEnable ? 2 : 0]; pef_container.Magic[1] = kPefMagic[1]; pef_container.Magic[2] = kPefMagic[kFatBinaryEnable ? 0 : 2]; @@ -552,8 +552,8 @@ NECTAR_MODULE(DynamicLinker64PEF) { // And check for any duplications for (size_t commandHeaderIndex = 0UL; commandHeaderIndex < command_headers.size(); ++commandHeaderIndex) { - if (CompilerKit::STLString(command_headers[commandHeaderIndex].Name).find(kLinkerDefineSymbol) != - CompilerKit::STLString::npos && + if (CompilerKit::STLString(command_headers[commandHeaderIndex].Name) + .find(kLinkerDefineSymbol) != CompilerKit::STLString::npos && CompilerKit::STLString(command_headers[commandHeaderIndex].Name).find(kLinkerDynamicSym) == CompilerKit::STLString::npos) { // ignore :UndefinedSymbol: headers, they do not contain code. |
