diff options
author | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2024-10-08 04:16:27 +0330 |
---|---|---|
committer | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2024-10-08 04:17:08 +0330 |
commit | addd54dc31603dc204773d3108dba4e000cd7657 (patch) | |
tree | 621620c4ca5634680d7655e3474cf0b0bcec8e01 /src/fasm/linker | |
parent | bf84010e01bb11874689ce53ea4df853b2e41c2b (diff) |
added fasm support
added compiler options
tried to compile to fasm first
Diffstat (limited to 'src/fasm/linker')
-rw-r--r-- | src/fasm/linker/linker.c | 870 | ||||
-rw-r--r-- | src/fasm/linker/linker.h | 78 |
2 files changed, 948 insertions, 0 deletions
diff --git a/src/fasm/linker/linker.c b/src/fasm/linker/linker.c new file mode 100644 index 0000000..faa3cd8 --- /dev/null +++ b/src/fasm/linker/linker.c @@ -0,0 +1,870 @@ +#include "linker.h" + +#include <compiler/error_helper/error_helper.h> +#include <compiler/source_code/source_code.h> +#include <fasm/lexer/lexer.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <utils/memory/memory.h> + +void fasmVariablePrint(FasmVariable variable) { + printf(" {name='%.*s',value=0x%ld}\n", (int)(variable.end - variable.begin), + variable.begin, variable.value); +} + +void fasmLinkedLinePrint(FasmLinkedLine line) { + printf(" {instruction='%s',operands=[\n", + FASM_TOKEN_STRINGS[line.instruction]); + for (size_t i = 0; i < line.operands_size; ++i) { + printf(" 0x%x,\n", line.operands[i]); + } + printf(" ]}\n"); +} + +void fasmLinkedLinesPrint(FasmLinkedLines lines) { + printf("{lines=[\n"); + for (size_t i = 0; i < lines.lines_size; ++i) { + fasmLinkedLinePrint(lines.lines[i]); + } + printf("],\ndata=[\n"); + for (size_t i = 0; i < lines.data_size; ++i) { + printf(" 0x%.2x,\n", lines.data[i]); + } + printf("],\nvariable=[\n"); + for (size_t i = 0; i < lines.variables_size; ++i) { + fasmVariablePrint(lines.variables[i]); + } + printf("]}\n"); +} + +void fasmLinkedLineDeleteInner(FasmLinkedLine line) { free(line.operands); } + +void fasmLinkedLinesDeleteInner(FasmLinkedLines lines) { + for (size_t i = 0; i < lines.lines_size; ++i) { + fasmLinkedLineDeleteInner(lines.lines[i]); + } + free(lines.lines); + free(lines.variables); + free(lines.data); +} + +FasmLinkedLines fasmLinker(const FasmLines *lines, SourceCode *sourceCode) { + FasmLinkedLines linkedLines = { + .lines = a404m_malloc(0), + .lines_size = 0, + .variables = a404m_malloc(0), + .variables_size = 0, + .data = a404m_malloc(0), + .data_size = 0, + }; + + fasmLinesSetVariables(&linkedLines, lines, sourceCode); + fasmLinesSetLines(&linkedLines, lines, sourceCode); + fasmLinesSetData(&linkedLines, lines, sourceCode); + + return linkedLines; + + // RETURN_ERROR: + const FasmLinkedLines ERROR = { + .lines = NULL, + .lines_size = ERROR_SIZE, + .variables = NULL, + .variables_size = ERROR_SIZE, + .data = NULL, + .data_size = ERROR_SIZE, + }; + + return ERROR; +} + +void fasmLinesSetVariables(FasmLinkedLines *linkedLines, const FasmLines *lines, + SourceCode *sourceCode) { + size_t inserted = 0; + + for (size_t i = 0; i < sourceCode->size; ++i) { + const FasmLines linesHolder = lines[i]; + for (size_t j = 0; j < linesHolder.lines_size; ++j) { + const FasmLine line = lines->lines[j]; + if (line.labelBegin != line.labelEnd) { + const FasmVariable variable = { + .begin = line.labelBegin, + .end = line.labelEnd, + .value = inserted, + }; + fasmLinesPushVariable(linkedLines, variable); + } + inserted += getSizeOfLine(line); + } + } + + inserted = 0; + + for (size_t i = 0; i < sourceCode->size; ++i) { + const FasmLines linesHolder = lines[i]; + for (size_t j = 0; j < linesHolder.data_size; ++j) { + const FasmLine line = lines->data[j]; + if (line.labelBegin != line.labelEnd) { + const FasmVariable variable = { + .begin = line.labelBegin, + .end = line.labelEnd, + .value = inserted, + }; + fasmLinesPushVariable(linkedLines, variable); + } + inserted += getSizeOfLine(line); + } + } +} + +void fasmLinesSetLines(FasmLinkedLines *linkedLines, const FasmLines *lines, + SourceCode *sourceCode) { + for (size_t i = 0; i < sourceCode->size; ++i) { + const FasmLines linesHolder = lines[i]; + for (size_t j = 0; j < linesHolder.lines_size; ++j) { + const FasmLine line = lines->lines[j]; + fasmLinesPushLine(linkedLines, + fasmLinesParseLine(linkedLines, line, sourceCode)); + } + } +} + +extern void fasmLinesSetData(FasmLinkedLines *linkedLines, + const FasmLines *lines, SourceCode *sourceCode) { + for (size_t i = 0; i < sourceCode->size; ++i) { + const FasmLines linesHolder = lines[i]; + for (size_t j = 0; j < linesHolder.data_size; ++j) { + const FasmLine line = lines->data[j]; + FasmLinkedLine linkedLine = + fasmLinesParseLine(linkedLines, line, sourceCode); + fasmLinesPushData(linkedLines, linkedLine.operands, + linkedLine.operands_size); + fasmLinkedLineDeleteInner(linkedLine); + } + } +} + +FasmLinkedLine fasmLinesParseLine(FasmLinkedLines *linkedLines, FasmLine line, + SourceCode *sourceCode) { + const FasmLinkedLine linkedLine = { + .begin = line.begin, + .end = line.end, + .instruction = line.instruction, + .operands = a404m_malloc(getSizeOfLineOperands(line)), + .operands_size = getSizeOfLineOperands(line), + }; + + const size_t elementSize = getSizeOfLineOperandElementSize(line); + + size_t inserted = 0; + + for (size_t i = 0; i < line.operands_size; ++i) { + const FasmOperand operand = line.operands[i]; + if (isOperandString(operand)) { + for (char *iter = operand.begin + 1; iter + 1 < operand.end; ++iter) { + switch (elementSize) { + case 1: + ((uint8_t *)linkedLine.operands)[inserted] = *iter; + break; + case 2: + ((uint16_t *)linkedLine.operands)[inserted] = *iter; + break; + case 4: + ((uint32_t *)linkedLine.operands)[inserted] = *iter; + break; + case 8: + ((uint64_t *)linkedLine.operands)[inserted] = *iter; + break; + } + inserted += 1; + } + } else { + switch (elementSize) { + case 1: + ((uint8_t *)linkedLine.operands)[inserted] = + getOperandValue(linkedLines, operand, sourceCode); + break; + case 2: + ((uint16_t *)linkedLine.operands)[inserted] = + getOperandValue(linkedLines, operand, sourceCode); + break; + case 4: + ((uint32_t *)linkedLine.operands)[inserted] = + getOperandValue(linkedLines, operand, sourceCode); + break; + case 8: + ((uint64_t *)linkedLine.operands)[inserted] = + getOperandValue(linkedLines, operand, sourceCode); + break; + } + inserted += 1; + } + } + + return linkedLine; +} + +bool fasmLinkerOperandSizeCorrect(FasmToken token, int size) { + switch (token) { + case FASM_TOKEN_NOOP: + return size == 0; + case FASM_TOKEN_PUSH8: + case FASM_TOKEN_PUSH16: + case FASM_TOKEN_PUSH32: + case FASM_TOKEN_PUSH64: + return size == 1; + case FASM_TOKEN_LOAD8: + case FASM_TOKEN_LOAD16: + case FASM_TOKEN_LOAD32: + case FASM_TOKEN_LOAD64: + case FASM_TOKEN_POP8: + case FASM_TOKEN_POP16: + case FASM_TOKEN_POP32: + case FASM_TOKEN_POP64: + case FASM_TOKEN_DUP8: + case FASM_TOKEN_DUP16: + case FASM_TOKEN_DUP32: + case FASM_TOKEN_DUP64: + case FASM_TOKEN_SWAP8: + case FASM_TOKEN_SWAP16: + case FASM_TOKEN_SWAP32: + case FASM_TOKEN_SWAP64: + case FASM_TOKEN_DROP8: + case FASM_TOKEN_DROP16: + case FASM_TOKEN_DROP32: + case FASM_TOKEN_DROP64: + case FASM_TOKEN_ADD_I8: + case FASM_TOKEN_ADD_I16: + case FASM_TOKEN_ADD_I32: + case FASM_TOKEN_ADD_I64: + case FASM_TOKEN_ADD_F32: + case FASM_TOKEN_ADD_F64: + case FASM_TOKEN_SUB_I8: + case FASM_TOKEN_SUB_I16: + case FASM_TOKEN_SUB_I32: + case FASM_TOKEN_SUB_I64: + case FASM_TOKEN_SUB_F32: + case FASM_TOKEN_SUB_F64: + case FASM_TOKEN_NEG_I8: + case FASM_TOKEN_NEG_I16: + case FASM_TOKEN_NEG_I32: + case FASM_TOKEN_NEG_I64: + case FASM_TOKEN_NEG_F32: + case FASM_TOKEN_NEG_F64: + case FASM_TOKEN_MUL_I8: + case FASM_TOKEN_MUL_I16: + case FASM_TOKEN_MUL_I32: + case FASM_TOKEN_MUL_I64: + case FASM_TOKEN_MUL_U8: + case FASM_TOKEN_MUL_U16: + case FASM_TOKEN_MUL_U32: + case FASM_TOKEN_MUL_U64: + case FASM_TOKEN_MUL_F32: + case FASM_TOKEN_MUL_F64: + case FASM_TOKEN_DIV_I8: + case FASM_TOKEN_DIV_I16: + case FASM_TOKEN_DIV_I32: + case FASM_TOKEN_DIV_I64: + case FASM_TOKEN_DIV_U8: + case FASM_TOKEN_DIV_U16: + case FASM_TOKEN_DIV_U32: + case FASM_TOKEN_DIV_U64: + case FASM_TOKEN_DIV_F32: + case FASM_TOKEN_DIV_F64: + case FASM_TOKEN_REM_I8: + case FASM_TOKEN_REM_I16: + case FASM_TOKEN_REM_I32: + case FASM_TOKEN_REM_I64: + case FASM_TOKEN_REM_U8: + case FASM_TOKEN_REM_U16: + case FASM_TOKEN_REM_U32: + case FASM_TOKEN_REM_U64: + case FASM_TOKEN_CAST_I8_I64: + case FASM_TOKEN_CAST_I16_I64: + case FASM_TOKEN_CAST_I32_I64: + case FASM_TOKEN_CAST_I64_I8: + case FASM_TOKEN_CAST_I64_I16: + case FASM_TOKEN_CAST_I64_I32: + case FASM_TOKEN_CAST_F64_I64: + case FASM_TOKEN_CAST_I64_F64: + case FASM_TOKEN_CAST_U8_U64: + case FASM_TOKEN_CAST_U16_U64: + case FASM_TOKEN_CAST_U32_U64: + case FASM_TOKEN_CAST_U64_U8: + case FASM_TOKEN_CAST_U64_U16: + case FASM_TOKEN_CAST_U64_U32: + case FASM_TOKEN_CAST_F64_U64: + case FASM_TOKEN_CAST_U64_F64: + case FASM_TOKEN_CAST_F32_F64: + case FASM_TOKEN_CAST_F64_F32: + case FASM_TOKEN_JUMP: + case FASM_TOKEN_JZ_I8: + case FASM_TOKEN_JNZ_I8: + case FASM_TOKEN_JN_I8: + case FASM_TOKEN_JNN_I8: + case FASM_TOKEN_JP_I8: + case FASM_TOKEN_JNP_I8: + case FASM_TOKEN_JZ_I16: + case FASM_TOKEN_JNZ_I16: + case FASM_TOKEN_JN_I16: + case FASM_TOKEN_JNN_I16: + case FASM_TOKEN_JP_I16: + case FASM_TOKEN_JNP_I16: + case FASM_TOKEN_JZ_I32: + case FASM_TOKEN_JNZ_I32: + case FASM_TOKEN_JN_I32: + case FASM_TOKEN_JNN_I32: + case FASM_TOKEN_JP_I32: + case FASM_TOKEN_JNP_I32: + case FASM_TOKEN_JZ_I64: + case FASM_TOKEN_JNZ_I64: + case FASM_TOKEN_JN_I64: + case FASM_TOKEN_JNN_I64: + case FASM_TOKEN_JP_I64: + case FASM_TOKEN_JNP_I64: + case FASM_TOKEN_JZ_F32: + case FASM_TOKEN_JNZ_F32: + case FASM_TOKEN_JN_F32: + case FASM_TOKEN_JNN_F32: + case FASM_TOKEN_JP_F32: + case FASM_TOKEN_JNP_F32: + case FASM_TOKEN_JZ_F64: + case FASM_TOKEN_JNZ_F64: + case FASM_TOKEN_JN_F64: + case FASM_TOKEN_JNN_F64: + case FASM_TOKEN_JP_F64: + case FASM_TOKEN_JNP_F64: + case FASM_TOKEN_ALLOC_HEAP: + case FASM_TOKEN_ALLOC_STACK: + case FASM_TOKEN_FREE_HEAP: + case FASM_TOKEN_GET_STACK_ADDRESS: + case FASM_TOKEN_GET_GLOBAL_ADDRESS: + case FASM_TOKEN_CALL: + case FASM_TOKEN_RET: + return size == 0; + case FASM_TOKEN_SYSCALL: + return size == 1; + case FASM_TOKEN_DEFINE_BYTE: + case FASM_TOKEN_DEFINE_WORD: + case FASM_TOKEN_DEFINE_DWORD: + case FASM_TOKEN_DEFINE_QWORD: + return size > 1; + case FASM_TOKEN_NONE: + return false; + } + fprintf(stderr, "Bad fasm token '%d' at %s:%d", token, __FILE_NAME__, + __LINE__); + exit(1); +} + +size_t getSizeOfLine(const FasmLine line) { + return sizeof(line.instruction) + getSizeOfLineOperands(line); +} + +size_t getSizeOfLineOperands(const FasmLine line) { + switch (line.instruction) { + case FASM_TOKEN_PUSH8: + return 1; + case FASM_TOKEN_PUSH16: + return 2; + case FASM_TOKEN_PUSH32: + return 4; + case FASM_TOKEN_PUSH64: + return 8; + case FASM_TOKEN_LOAD8: + case FASM_TOKEN_LOAD16: + case FASM_TOKEN_LOAD32: + case FASM_TOKEN_LOAD64: + case FASM_TOKEN_POP8: + case FASM_TOKEN_POP16: + case FASM_TOKEN_POP32: + case FASM_TOKEN_POP64: + case FASM_TOKEN_DUP8: + case FASM_TOKEN_DUP16: + case FASM_TOKEN_DUP32: + case FASM_TOKEN_DUP64: + case FASM_TOKEN_SWAP8: + case FASM_TOKEN_SWAP16: + case FASM_TOKEN_SWAP32: + case FASM_TOKEN_SWAP64: + case FASM_TOKEN_DROP8: + case FASM_TOKEN_DROP16: + case FASM_TOKEN_DROP32: + case FASM_TOKEN_DROP64: + case FASM_TOKEN_ADD_I8: + case FASM_TOKEN_ADD_I16: + case FASM_TOKEN_ADD_I32: + case FASM_TOKEN_ADD_I64: + case FASM_TOKEN_ADD_F32: + case FASM_TOKEN_ADD_F64: + case FASM_TOKEN_SUB_I8: + case FASM_TOKEN_SUB_I16: + case FASM_TOKEN_SUB_I32: + case FASM_TOKEN_SUB_I64: + case FASM_TOKEN_SUB_F32: + case FASM_TOKEN_SUB_F64: + case FASM_TOKEN_NEG_I8: + case FASM_TOKEN_NEG_I16: + case FASM_TOKEN_NEG_I32: + case FASM_TOKEN_NEG_I64: + case FASM_TOKEN_NEG_F32: + case FASM_TOKEN_NEG_F64: + case FASM_TOKEN_MUL_I8: + case FASM_TOKEN_MUL_I16: + case FASM_TOKEN_MUL_I32: + case FASM_TOKEN_MUL_I64: + case FASM_TOKEN_MUL_U8: + case FASM_TOKEN_MUL_U16: + case FASM_TOKEN_MUL_U32: + case FASM_TOKEN_MUL_U64: + case FASM_TOKEN_MUL_F32: + case FASM_TOKEN_MUL_F64: + case FASM_TOKEN_DIV_I8: + case FASM_TOKEN_DIV_I16: + case FASM_TOKEN_DIV_I32: + case FASM_TOKEN_DIV_I64: + case FASM_TOKEN_DIV_U8: + case FASM_TOKEN_DIV_U16: + case FASM_TOKEN_DIV_U32: + case FASM_TOKEN_DIV_U64: + case FASM_TOKEN_DIV_F32: + case FASM_TOKEN_DIV_F64: + case FASM_TOKEN_REM_I8: + case FASM_TOKEN_REM_I16: + case FASM_TOKEN_REM_I32: + case FASM_TOKEN_REM_I64: + case FASM_TOKEN_REM_U8: + case FASM_TOKEN_REM_U16: + case FASM_TOKEN_REM_U32: + case FASM_TOKEN_REM_U64: + case FASM_TOKEN_CAST_I8_I64: + case FASM_TOKEN_CAST_I16_I64: + case FASM_TOKEN_CAST_I32_I64: + case FASM_TOKEN_CAST_I64_I8: + case FASM_TOKEN_CAST_I64_I16: + case FASM_TOKEN_CAST_I64_I32: + case FASM_TOKEN_CAST_F64_I64: + case FASM_TOKEN_CAST_I64_F64: + case FASM_TOKEN_CAST_U8_U64: + case FASM_TOKEN_CAST_U16_U64: + case FASM_TOKEN_CAST_U32_U64: + case FASM_TOKEN_CAST_U64_U8: + case FASM_TOKEN_CAST_U64_U16: + case FASM_TOKEN_CAST_U64_U32: + case FASM_TOKEN_CAST_F64_U64: + case FASM_TOKEN_CAST_U64_F64: + case FASM_TOKEN_CAST_F32_F64: + case FASM_TOKEN_CAST_F64_F32: + case FASM_TOKEN_JUMP: + case FASM_TOKEN_JZ_I8: + case FASM_TOKEN_JNZ_I8: + case FASM_TOKEN_JN_I8: + case FASM_TOKEN_JNN_I8: + case FASM_TOKEN_JP_I8: + case FASM_TOKEN_JNP_I8: + case FASM_TOKEN_JZ_I16: + case FASM_TOKEN_JNZ_I16: + case FASM_TOKEN_JN_I16: + case FASM_TOKEN_JNN_I16: + case FASM_TOKEN_JP_I16: + case FASM_TOKEN_JNP_I16: + case FASM_TOKEN_JZ_I32: + case FASM_TOKEN_JNZ_I32: + case FASM_TOKEN_JN_I32: + case FASM_TOKEN_JNN_I32: + case FASM_TOKEN_JP_I32: + case FASM_TOKEN_JNP_I32: + case FASM_TOKEN_JZ_I64: + case FASM_TOKEN_JNZ_I64: + case FASM_TOKEN_JN_I64: + case FASM_TOKEN_JNN_I64: + case FASM_TOKEN_JP_I64: + case FASM_TOKEN_JNP_I64: + case FASM_TOKEN_JZ_F32: + case FASM_TOKEN_JNZ_F32: + case FASM_TOKEN_JN_F32: + case FASM_TOKEN_JNN_F32: + case FASM_TOKEN_JP_F32: + case FASM_TOKEN_JNP_F32: + case FASM_TOKEN_JZ_F64: + case FASM_TOKEN_JNZ_F64: + case FASM_TOKEN_JN_F64: + case FASM_TOKEN_JNN_F64: + case FASM_TOKEN_JP_F64: + case FASM_TOKEN_JNP_F64: + case FASM_TOKEN_ALLOC_HEAP: + case FASM_TOKEN_ALLOC_STACK: + case FASM_TOKEN_FREE_HEAP: + case FASM_TOKEN_GET_STACK_ADDRESS: + case FASM_TOKEN_GET_GLOBAL_ADDRESS: + case FASM_TOKEN_CALL: + case FASM_TOKEN_RET: + case FASM_TOKEN_NOOP: + case FASM_TOKEN_SYSCALL: + return 0; + case FASM_TOKEN_DEFINE_BYTE: + case FASM_TOKEN_DEFINE_WORD: + case FASM_TOKEN_DEFINE_DWORD: + case FASM_TOKEN_DEFINE_QWORD: { + size_t elementSize; + + switch (line.instruction) { + case FASM_TOKEN_DEFINE_BYTE: + elementSize = 1; + break; + case FASM_TOKEN_DEFINE_WORD: + elementSize = 2; + break; + case FASM_TOKEN_DEFINE_DWORD: + elementSize = 4; + break; + case FASM_TOKEN_DEFINE_QWORD: + elementSize = 8; + break; + default: + } + + size_t size = 0; + + for (size_t i = 0; i < line.operands_size; ++i) { + const FasmOperand operand = line.operands[i]; + if (isOperandString(operand)) { + size += (operand.end - operand.begin - 2) * elementSize; + } else { + size += elementSize; + } + } + + return size; + } + case FASM_TOKEN_NONE: + } + fprintf(stderr, "Bad fasm token '%d' at %s:%d", line.instruction, + __FILE_NAME__, __LINE__); + exit(1); +} + +size_t getSizeOfLineOperandElementSize(const FasmLine line) { + switch (line.instruction) { + case FASM_TOKEN_NOOP: + return 0; + case FASM_TOKEN_PUSH8: + return 1; + case FASM_TOKEN_PUSH16: + return 2; + case FASM_TOKEN_PUSH32: + return 4; + case FASM_TOKEN_PUSH64: + return 8; + case FASM_TOKEN_LOAD8: + case FASM_TOKEN_LOAD16: + case FASM_TOKEN_LOAD32: + case FASM_TOKEN_LOAD64: + case FASM_TOKEN_POP8: + case FASM_TOKEN_POP16: + case FASM_TOKEN_POP32: + case FASM_TOKEN_POP64: + case FASM_TOKEN_DUP8: + case FASM_TOKEN_DUP16: + case FASM_TOKEN_DUP32: + case FASM_TOKEN_DUP64: + case FASM_TOKEN_SWAP8: + case FASM_TOKEN_SWAP16: + case FASM_TOKEN_SWAP32: + case FASM_TOKEN_SWAP64: + case FASM_TOKEN_DROP8: + case FASM_TOKEN_DROP16: + case FASM_TOKEN_DROP32: + case FASM_TOKEN_DROP64: + case FASM_TOKEN_ADD_I8: + case FASM_TOKEN_ADD_I16: + case FASM_TOKEN_ADD_I32: + case FASM_TOKEN_ADD_I64: + case FASM_TOKEN_ADD_F32: + case FASM_TOKEN_ADD_F64: + case FASM_TOKEN_SUB_I8: + case FASM_TOKEN_SUB_I16: + case FASM_TOKEN_SUB_I32: + case FASM_TOKEN_SUB_I64: + case FASM_TOKEN_SUB_F32: + case FASM_TOKEN_SUB_F64: + case FASM_TOKEN_NEG_I8: + case FASM_TOKEN_NEG_I16: + case FASM_TOKEN_NEG_I32: + case FASM_TOKEN_NEG_I64: + case FASM_TOKEN_NEG_F32: + case FASM_TOKEN_NEG_F64: + case FASM_TOKEN_MUL_I8: + case FASM_TOKEN_MUL_I16: + case FASM_TOKEN_MUL_I32: + case FASM_TOKEN_MUL_I64: + case FASM_TOKEN_MUL_U8: + case FASM_TOKEN_MUL_U16: + case FASM_TOKEN_MUL_U32: + case FASM_TOKEN_MUL_U64: + case FASM_TOKEN_MUL_F32: + case FASM_TOKEN_MUL_F64: + case FASM_TOKEN_DIV_I8: + case FASM_TOKEN_DIV_I16: + case FASM_TOKEN_DIV_I32: + case FASM_TOKEN_DIV_I64: + case FASM_TOKEN_DIV_U8: + case FASM_TOKEN_DIV_U16: + case FASM_TOKEN_DIV_U32: + case FASM_TOKEN_DIV_U64: + case FASM_TOKEN_DIV_F32: + case FASM_TOKEN_DIV_F64: + case FASM_TOKEN_REM_I8: + case FASM_TOKEN_REM_I16: + case FASM_TOKEN_REM_I32: + case FASM_TOKEN_REM_I64: + case FASM_TOKEN_REM_U8: + case FASM_TOKEN_REM_U16: + case FASM_TOKEN_REM_U32: + case FASM_TOKEN_REM_U64: + case FASM_TOKEN_CAST_I8_I64: + case FASM_TOKEN_CAST_I16_I64: + case FASM_TOKEN_CAST_I32_I64: + case FASM_TOKEN_CAST_I64_I8: + case FASM_TOKEN_CAST_I64_I16: + case FASM_TOKEN_CAST_I64_I32: + case FASM_TOKEN_CAST_F64_I64: + case FASM_TOKEN_CAST_I64_F64: + case FASM_TOKEN_CAST_U8_U64: + case FASM_TOKEN_CAST_U16_U64: + case FASM_TOKEN_CAST_U32_U64: + case FASM_TOKEN_CAST_U64_U8: + case FASM_TOKEN_CAST_U64_U16: + case FASM_TOKEN_CAST_U64_U32: + case FASM_TOKEN_CAST_F64_U64: + case FASM_TOKEN_CAST_U64_F64: + case FASM_TOKEN_CAST_F32_F64: + case FASM_TOKEN_CAST_F64_F32: + case FASM_TOKEN_JUMP: + case FASM_TOKEN_JZ_I8: + case FASM_TOKEN_JNZ_I8: + case FASM_TOKEN_JN_I8: + case FASM_TOKEN_JNN_I8: + case FASM_TOKEN_JP_I8: + case FASM_TOKEN_JNP_I8: + case FASM_TOKEN_JZ_I16: + case FASM_TOKEN_JNZ_I16: + case FASM_TOKEN_JN_I16: + case FASM_TOKEN_JNN_I16: + case FASM_TOKEN_JP_I16: + case FASM_TOKEN_JNP_I16: + case FASM_TOKEN_JZ_I32: + case FASM_TOKEN_JNZ_I32: + case FASM_TOKEN_JN_I32: + case FASM_TOKEN_JNN_I32: + case FASM_TOKEN_JP_I32: + case FASM_TOKEN_JNP_I32: + case FASM_TOKEN_JZ_I64: + case FASM_TOKEN_JNZ_I64: + case FASM_TOKEN_JN_I64: + case FASM_TOKEN_JNN_I64: + case FASM_TOKEN_JP_I64: + case FASM_TOKEN_JNP_I64: + case FASM_TOKEN_JZ_F32: + case FASM_TOKEN_JNZ_F32: + case FASM_TOKEN_JN_F32: + case FASM_TOKEN_JNN_F32: + case FASM_TOKEN_JP_F32: + case FASM_TOKEN_JNP_F32: + case FASM_TOKEN_JZ_F64: + case FASM_TOKEN_JNZ_F64: + case FASM_TOKEN_JN_F64: + case FASM_TOKEN_JNN_F64: + case FASM_TOKEN_JP_F64: + case FASM_TOKEN_JNP_F64: + case FASM_TOKEN_ALLOC_HEAP: + case FASM_TOKEN_ALLOC_STACK: + case FASM_TOKEN_FREE_HEAP: + case FASM_TOKEN_GET_STACK_ADDRESS: + case FASM_TOKEN_GET_GLOBAL_ADDRESS: + case FASM_TOKEN_CALL: + case FASM_TOKEN_RET: + case FASM_TOKEN_SYSCALL: + return 0; + case FASM_TOKEN_DEFINE_BYTE: + return 1; + case FASM_TOKEN_DEFINE_WORD: + return 2; + case FASM_TOKEN_DEFINE_DWORD: + return 4; + case FASM_TOKEN_DEFINE_QWORD: + return 8; + case FASM_TOKEN_NONE: + } + + fprintf(stderr, "Bad fasm token '%d' at %s:%d", line.instruction, + __FILE_NAME__, __LINE__); + exit(1); +} + +void fasmLinesPushVariable(FasmLinkedLines *linkedLines, + FasmVariable variable) { + const size_t size = a404m_malloc_usable_size(linkedLines->variables) / + sizeof(*linkedLines->variables); + if (size == linkedLines->variables_size) { + linkedLines->variables = + a404m_realloc(linkedLines->variables, + (size + size / 2 + 1) * sizeof(*linkedLines->variables)); + } + linkedLines->variables[linkedLines->variables_size] = variable; + linkedLines->variables_size += 1; +} + +void fasmLinesPushLine(FasmLinkedLines *linkedLines, FasmLinkedLine line) { + const size_t size = a404m_malloc_usable_size(linkedLines->lines) / + sizeof(*linkedLines->lines); + if (size == linkedLines->lines_size) { + linkedLines->lines = + a404m_realloc(linkedLines->lines, + (size + size / 2 + 1) * sizeof(*linkedLines->lines)); + } + linkedLines->lines[linkedLines->lines_size] = line; + linkedLines->lines_size += 1; +} + +void fasmLinesPushData(FasmLinkedLines *linkedLines, uint8_t *data, + size_t size) { + linkedLines->data = + a404m_realloc(linkedLines->data, (linkedLines->data_size + size) * + sizeof(*linkedLines->data)); + memcpy(linkedLines->data + linkedLines->data_size, data, size); + linkedLines->data_size += size; +} + +FasmVariable fasmLinesGetVariable(const FasmLinkedLines *linkedLines, + char const *nameBegin, char const *nameEnd) { + const size_t size = nameEnd - nameBegin; + for (size_t i = 0; i < linkedLines->variables_size; ++i) { + const FasmVariable variable = linkedLines->variables[i]; + const size_t variable_str_size = variable.end - variable.begin; + if (size == variable_str_size && + strncmp(variable.begin, nameBegin, size) == 0) { + return variable; + } + } + + FasmVariable ERROR = { + .begin = NULL, + .end = NULL, + .value = 0, + }; + + return ERROR; +} + +bool isOperandString(FasmOperand operand) { return *(operand.begin) == '"'; } + +uint64_t getOperandValue(FasmLinkedLines *linkedLines, FasmOperand operand, + SourceCode *sourceCode) { + char c = *(operand.begin); + + if (c == '"') { + fprintf(stderr, "It shoulden't be here"); + exit(1); + } else if (c == '0') { + ++(operand.begin); + if (operand.begin == operand.end) { + return 0; + } + c = *(operand.begin); + if (c == 'x') { + return hexStrToInt(operand.begin + 1, operand.end, sourceCode); + } else if (c == 'b') { + return binStrToInt(operand.begin + 1, operand.end, sourceCode); + } else { + return strToInt(operand.begin + 1, operand.end, sourceCode); + } + } else if (c == '-') { + ++(operand.begin); + if (operand.begin == operand.end) { + printError("Expected value after -", sourceCode, operand.begin, + operand.end); + exit(1); + } + c = *(operand.begin); + if (c == '0') { + ++(operand.begin); + if (operand.begin == operand.end) { + return 0; + } + c = *(operand.begin); + if (c == 'x') { + return -hexStrToInt(operand.begin + 1, operand.end, sourceCode); + } else if (c == 'b') { + return -binStrToInt(operand.begin + 1, operand.end, sourceCode); + } else { + return -strToInt(operand.begin + 1, operand.end, sourceCode); + } + } + } else if ('0' <= c && c <= '9') { + return strToInt(operand.begin, operand.end, sourceCode); + } else { + const FasmVariable variable = + fasmLinesGetVariable(linkedLines, operand.begin, operand.end); + if (variable.begin == NULL) { + printError("Label '%.*s' not found", sourceCode, operand.begin, + operand.end, (int)(operand.end - operand.begin), + operand.begin); + exit(1); + } + return variable.value; + } + printError("Should not come here %s:%d", sourceCode, operand.begin, + operand.end, __FILE_NAME__, __LINE__); + exit(1); +} + +uint64_t strToInt(const char *begin, const char *end, SourceCode *sourceCode) { + uint64_t result = 0; + for (char const *iter = begin; iter < end; ++iter) { + const char c = *iter; + result *= 10; + if ('0' <= c && c <= '9') { + result += c - '0'; + } else { + printError("Unexpected character", sourceCode, iter, iter + 1); + exit(1); + } + } + return result; +} +uint64_t hexStrToInt(const char *begin, const char *end, + SourceCode *sourceCode) { + uint64_t result = 0; + for (char const *iter = begin; iter < end; ++iter) { + const char c = *iter; + result *= 16; + if ('0' <= c && c <= '9') { + result += c - '0'; + } else if ('A' <= c && c < 'F') { + result += c - 'A' + 10; + } else if ('a' <= c && c < 'f') { + result += c - 'a' + 10; + } else { + printError("Unexpected character", sourceCode, iter, iter + 1); + exit(1); + } + } + return result; +} +uint64_t binStrToInt(const char *begin, const char *end, + SourceCode *sourceCode) { + uint64_t result = 0; + for (char const *iter = begin; iter < end; ++iter) { + const char c = *iter; + result *= 2; + if ('0' <= c && c <= '1') { + result += c - '0'; + } else { + printError("Unexpected character", sourceCode, iter, iter + 1); + exit(1); + } + } + return result; +} diff --git a/src/fasm/linker/linker.h b/src/fasm/linker/linker.h new file mode 100644 index 0000000..fd7813b --- /dev/null +++ b/src/fasm/linker/linker.h @@ -0,0 +1,78 @@ +#pragma once + +#include <fasm/lexer/lexer.h> +#include <stdint.h> + +typedef struct FasmLinkedLine { + char const *begin; + char const *end; + FasmToken instruction; + uint8_t *operands; + size_t operands_size; +} FasmLinkedLine; + +typedef struct FasmVariable { + char const *begin; + char const *end; + uint64_t value; +} FasmVariable; + +typedef struct FasmLinkedLines { + FasmLinkedLine *lines; + size_t lines_size; + + FasmVariable *variables; + size_t variables_size; + + uint8_t *data; + size_t data_size; +} FasmLinkedLines; + +extern void fasmVariablePrint(FasmVariable variable); +extern void fasmLinkedLinePrint(FasmLinkedLine line); +extern void fasmLinkedLinesPrint(FasmLinkedLines lines); + +extern void fasmLinkedLineDeleteInner(FasmLinkedLine line); +extern void fasmLinkedLinesDeleteInner(FasmLinkedLines lines); + +extern FasmLinkedLines fasmLinker(const FasmLines *lines, + SourceCode *sourceCode); + +extern void fasmLinesSetVariables(FasmLinkedLines *linkedLines, + const FasmLines *lines, + SourceCode *sourceCode); +extern void fasmLinesSetLines(FasmLinkedLines *linkedLines, + const FasmLines *lines, SourceCode *sourceCode); +extern void fasmLinesSetData(FasmLinkedLines *linkedLines, + const FasmLines *lines, SourceCode *sourceCode); + +extern FasmLinkedLine fasmLinesParseLine(FasmLinkedLines *linkedLines, + FasmLine line, SourceCode *sourceCode); + +extern bool fasmLinkerOperandSizeCorrect(FasmToken token, int size); + +extern size_t getSizeOfLine(const FasmLine line); +extern size_t getSizeOfLineOperands(const FasmLine line); +extern size_t getSizeOfLineOperandElementSize(const FasmLine line); + +extern void fasmLinesPushVariable(FasmLinkedLines *linkedLines, + FasmVariable variable); +extern void fasmLinesPushLine(FasmLinkedLines *linkedLines, + FasmLinkedLine line); +extern void fasmLinesPushData(FasmLinkedLines *linkedLines, uint8_t *data, + size_t size); +extern FasmVariable fasmLinesGetVariable(const FasmLinkedLines *linkedLines, + char const *nameBegin, + char const *nameEnd); + +extern bool isOperandString(FasmOperand operand); + +extern uint64_t getOperandValue(FasmLinkedLines *linkedLines, + FasmOperand operand, SourceCode *sourceCode); + +extern uint64_t strToInt(const char *begin, const char *end, + SourceCode *sourceCode); +extern uint64_t hexStrToInt(const char *begin, const char *end, + SourceCode *sourceCode); +extern uint64_t binStrToInt(const char *begin, const char *end, + SourceCode *sourceCode); |