Skip to content

Commit

Permalink
arithmetic operations (a5)
Browse files Browse the repository at this point in the history
  • Loading branch information
SantriptaSharma committed Dec 7, 2023
1 parent 933c6b5 commit bc72324
Show file tree
Hide file tree
Showing 8 changed files with 279 additions and 169 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ lexer.c
parser.c
*.tab.*
*.o
*.asm
*.s

#debugger files
counterexamples
Expand Down
11 changes: 4 additions & 7 deletions 15_A5_translator.c
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ int main(int argc, const char *argv[]) {
char *out_filename = malloc(filename_len + 5);
char *asm_filename = malloc(filename_len + 5);
sprintf(out_filename, "%s.out", argv[1]);
sprintf(asm_filename, "%s.asm", argv[1]);
sprintf(asm_filename, "%s.s", argv[1]);

FILE *quads_file = fopen(out_filename, "w");
free(out_filename);
Expand Down Expand Up @@ -809,14 +809,11 @@ int main(int argc, const char *argv[]) {
WriteDataSeg(file);

// generate entry point, emit all global instructions
fprintf(file, ".text\n");
fprintf(file, ".global main\n");

WriteEntryPoint(file);
WriteFunctions(file);

// TODO: generate asm from quads

// TODO: write asm to file
// GAS syntax requires ending the file with a newline, not EOF
fprintf(file, "\n");

fclose(file);
FreeTables();
Expand Down
4 changes: 2 additions & 2 deletions A4_tests/testthing.nc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
int a = 5 + 3 + "garbo king";
int a = 5 + 3;
int *d = a + 5;
int *make_fib_list(int a, int b, int n);
int b = 110 + 'c' + "garbo king" + a;
int b = 110 + 'c' + a;
void garbo();
char c = (d[10] + 12) * 32 - 3 * 4 * "okiii";
void garbo();
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ CC=gcc
l=flex
yy=bison
CFLAGS=-Werror -lfl -g
SFLAGS=-no-pie -g

o=compiler
lx=lexer
Expand Down Expand Up @@ -34,11 +35,16 @@ $(lx).c: $(fname).l $(fname).tab.c
%.o: %.c
$(CC) -c $^ $(CFLAGS)

test: build
./$(o) test < compilertest.nc
gcc -c test.s $(SFLAGS)
gcc -o testexec test.o $(SFLAGS)

clean:
rm -rf $(o)
rm -rf $(o).exe
rm -rf $(lx)*
rm -rf *.o
rm -rf $(fname).tab.*

.PHONY: default clean build lex
.PHONY: default clean build lex test
261 changes: 257 additions & 4 deletions compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@

#include "compiler.h"

#define MAX(a, b) ((a) > (b) ? (a) : (b))

const char *CONST_DIRECTIVES[] = {
[1] = ".byte",
[2] = ".short",
[4] = ".long",
[8] = ".quad"
};

static void WriteConstSym(Symbol *sym, FILE *file) {
static void WriteGlobalSym(Symbol *sym, FILE *file) {
static int strings_count = 0;

if (!sym->is_temp && sym->type.kind != ARRAY_T) {
Expand All @@ -21,6 +23,7 @@ static void WriteConstSym(Symbol *sym, FILE *file) {
switch (sym->type.kind) {
case PRIMITIVE_T:
case PRIMITIVE_PTR:
if (sym->initial_value != 0) { break; } // will be a literal in the assembly code
fprintf(file, "%s:\n\t%s %d\n", sym->name, CONST_DIRECTIVES[sym->size], sym->initial_value);
break;

Expand Down Expand Up @@ -59,7 +62,7 @@ void WriteDataSeg(FILE *file) {

while (sym != NULL) {
if (sym->type.kind != FUNC_T) {
WriteConstSym(sym, file);
WriteGlobalSym(sym, file);
} else {
if (strcmp(sym->name, "main") == 0) {
char *main_label = malloc(strlen(sym->name) + 2);
Expand Down Expand Up @@ -134,8 +137,241 @@ static void FindQuadExtents() {
ext_count = next;
}

static const char postfixes[] = {
[1] = 'b', [2] = 'w', [4] = 'l', [8] = 'q'
};

static const char movpostfix[] = {
[1] = 'l', [2] = 'l', [4] = 'l', [8] = 'q'
};

static const char regprefixes[] = {
[1] = 'e', [4] = 'e', [8] = 'r'
};

static const char *arithmetic_ops[] ={
[ADD] = "add",
[SUB] = "sub",
[MUL] = "imul",
[DIV] = "idiv",
[MOD] = "idiv"
};

// holds context for the current function being translated
struct {
int argc;
//
int argstartoff;
int localsoff;
} func_context;

static void TranslateOperand(Addr a, FILE *file) {
switch (a.kind) {
case SYMBOL_A:
if (a.sym->initial_value != 0) {
fprintf(file, "$%d", a.sym->initial_value);
return;
}

// check for string
if (a.sym->type.kind == ARRAY_T && a.sym->type.array.base == CHAR_T) {
size_t it = 0;
const char *pref = "__str_";

while (a.sym->name[it] == pref[it]) {
it++;
}

if (pref[it] == '\0') {
fprintf(file, "$_user_string_%d", a.sym->initial_value);
return;
}
}

if(current_table == &glb_table) {
fprintf(file, "%s", a.sym->name);
return;
}

// check if symbol in glb table, if so, use variable

// otherwise, check if symbol is a parameter, if so, use +offset(%rbp)

// otherwise, use -offset(%rbp)
break;

case IMMEDIATE:
fprintf(file, "$%d", a.imm);
break;
}
}

static void LoadBinOps(Quad q, FILE *file) {
size_t sd = q.rd.sym->size;
size_t ss = q.rs.sym->size;
size_t st = q.rt.sym->size;

// for sign extension char -> 32/64 requires movsx, int -> 64 requires movsxd
const char *extension_instr = q.rs.sym->initial_value == 0 ?
(ss == 1 ? "movsx" : "movsxd")
: "mov";
// sorry

if (q.opcode == DIV || q.opcode == MOD) {
fprintf(file, "xor %%rdx, %%rdx\n\t");
fprintf(file, "%s ", extension_instr);
TranslateOperand(q.rs, file);
fprintf(file, ", %%rax\n\t");

extension_instr = q.rt.sym->initial_value == 0 ?
(st == 1 ? "movsx" : "movsxd")
: "mov";

fprintf(file, "%s ", extension_instr);
TranslateOperand(q.rt, file);
fprintf(file, ", %%%cbx\n\t", regprefixes[st]);
return;
}

fprintf(file, "mov%c ", movpostfix[ss]);
TranslateOperand(q.rs, file);
fprintf(file, ", %%%cax\n\t", regprefixes[ss]);

// sign extension

if (ss < sd && q.rs.sym->initial_value == 0) {
fprintf(file, "%s %%%cax, %%%cax\n\t", extension_instr, regprefixes[ss], regprefixes[sd]);
}

fprintf(file, "mov%c ", movpostfix[st]);
TranslateOperand(q.rt, file);
fprintf(file, ", %%%cbx\n\t", regprefixes[st]);

if (st < sd && q.rt.sym->initial_value == 0) {
extension_instr = st == 1 ? "movsx" : "movsxd";

fprintf(file, "%s %%%cbx, %%%cbx\n\t", extension_instr, regprefixes[st], regprefixes[sd]);
}
}

static void TranslateQuad(Quad q, FILE *file, SymbolTable *tab) {
SymbolTable *saved = current_table;
current_table = tab;

switch (q.opcode) {
size_t sd, ss, st;

case ADD:
case SUB:
case MUL:
case DIV:
case MOD:
sd = q.rd.sym->size;
ss = q.rs.sym->size;
st = q.rt.sym->size;

// first we get the operands in rbx/ebx and rax/eax respectively (except for division, where it's flipped)
LoadBinOps(q, file);
// size for the operation
int size = MAX(q.rs.sym->size, q.rt.sym->size);

// now we perform the operation

if (q.opcode == DIV || q.opcode == MOD) {
fprintf(file, "idiv %%%cbx\n\t", regprefixes[st]);

if (q.opcode == DIV) {
fprintf(file, "mov%c %%rax, ", movpostfix[sd]);
TranslateOperand(q.rd, file);
fprintf(file, "\n\t");
} else {
fprintf(file, "mov%c %%rdx, ", movpostfix[sd]);
TranslateOperand(q.rd, file);
fprintf(file, "\n\t");
}
break;
}

fprintf(file, "%s%c %%%cbx, %%%cax\n\t", arithmetic_ops[q.opcode], postfixes[size], regprefixes[sd], regprefixes[sd]);

// now we store the result
fprintf(file, "mov%c %%%cax, ", movpostfix[sd], regprefixes[sd]);
TranslateOperand(q.rd, file);
break;

case ADDR:
case DEREF:
break;

case NEG:
case POS:
fprintf(file, "%s%c\t", q.opcode == NEG ? "neg" : "not", postfixes[q.rd.sym->size]);
TranslateOperand(q.rs, file);
break;

case JMP:

break;

case JIF:
case JNT:
break;

case JLT:
case JLE:
break;

case JGT:
case JGE:
break;

case JEQ:
case JNE:
break;

case MOV:
sd = q.rd.sym->size;
ss = q.rs.sym->size;

if (strcmp(q.rd.sym->name, "__retval") == 0) {
fprintf(file, "mov%c ", movpostfix[sd]);
TranslateOperand(q.rs, file);
fprintf(file, ", %%%cax", regprefixes[sd]);
break;
}

fprintf(file, "mov%c ", movpostfix[sd]);
TranslateOperand(q.rs, file);
fprintf(file, ", %%%cbx\n\t", regprefixes[sd]);
fprintf(file, "mov%c %%%cbx, ", movpostfix[sd], regprefixes[sd]);
TranslateOperand(q.rd, file);
break;

case INDR:
case INDW:
break;

case PTRW:
break;

case FN_LABEL:
fprintf(file, "%s:\n", q.rd.sym->name);
break;

case RET:
fprintf(file, "ret\n");
break;

case PAR:

break;

case CAL:
fprintf(file, "call %s\n", q.rd.sym->name);
break;
}

current_table = saved;
}

void WriteEntryPoint(FILE *file) {
Expand All @@ -156,14 +392,31 @@ void WriteEntryPoint(FILE *file) {
// first, write the external quad blocks
for (int i = 0; i < ext_count; i++) {
for (int j = ext_quad_blocks[i].start; j <= ext_quad_blocks[i].end; j++) {
fprintf(file, "\t");
fprintf(file, "#\t");
DisplayQuad(quads[j], file);
fprintf(file, "\n\t");
TranslateQuad(quads[j], file, &glb_table);
fprintf(file, "\n");
fprintf(file, "\n\n");
}
}

fprintf(file, "\n");

// jump to nanoC file's entry point, main, now called _main
fprintf(file, "\tcall _main\n");

// when _main returns, exit w exit code returned by main (in eax)
fprintf(file, "\texit_loop:\n");
fprintf(file, "\tmovl %%eax, %%ebx\n");
fprintf(file, "\tmovl $0x1, %%eax\n");
fprintf(file, "\tint $0x80\n");
fprintf(file, "\tjmp exit_loop\n");
}

void WriteFunction(FILE *file) {

}

void WriteFunctions(FILE *file) {

}
1 change: 1 addition & 0 deletions compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@

void WriteDataSeg(FILE *file);
void WriteEntryPoint(FILE *file);
void WriteFunctions(FILE *file);

#endif
Loading

0 comments on commit bc72324

Please sign in to comment.