Skip to content

Commit

Permalink
operators
Browse files Browse the repository at this point in the history
  • Loading branch information
pedrommaiaa committed Jun 18, 2021
1 parent 218e674 commit 3a11914
Show file tree
Hide file tree
Showing 15 changed files with 474 additions and 96 deletions.
Binary file modified flow
Binary file not shown.
31 changes: 21 additions & 10 deletions grammar.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ additive_expression:
| additive_expression '-' multiplicative_expression
;

multiplicative_expression:
number
| number '*' multiplicative_expression
| number '/' multiplicative_expression
multiplicative_expression: prefix_expression
| multiplicative_expression '*' prefix_expression
| multiplicative_expression '/' prefix_expression
| multiplicative_expression '%' prefix_expression
;

number: INTLIT_T
Expand Down Expand Up @@ -99,17 +99,28 @@ function_call : identifier '(' expression ')'
return_statement: 'return' '(' expression ')'
;

prefix_expression: primary
| '*' prefix_expression
| '%' prefix_expression
prefix_expression: postfix_expression
| '++' prefix_expression
| '--' prefix_expression
| prefix_operator prefix_expression
;

primary_expression: IDENTIFIER
| CONSTANT
| STRING_LITERAL
primary_expression: T_IDENT
| T_INTLIT
| T_STRLIT
| '(' expression ')'
;

postfix_expression : primary_expression
| postfix_expression '[' expression ']'
| postfix_expression '(' expression ')'
| postfix_expression '++'
| postfix_expression '--'
;

prefix_operator: '&'
| '*'
| '-'
| '~'
| '!'
;
126 changes: 110 additions & 16 deletions src/cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,34 +76,59 @@ int cgloadint(int value, int type) {
}

// Load a value from a variable into a register.
// Return the number of the register
int cgloadglob(int id) {
// Return the number of the register. If the
// operation is pre- or post-increment/decrement,
// also perform this action.
int cgloadglob(int id, int op) {
// Get a new register
int r = alloc_register();

// Print out the code to initialise it
switch (Gsym[id].type) {
case P_CHAR:
if (op == A_PREINC)
fprintf(Outfile, "\tincb\t%s(\%%rip)\n", Gsym[id].name);
if (op == A_PREDEC)
fprintf(Outfile, "\tdecb\t%s(\%%rip)\n", Gsym[id].name);
fprintf(Outfile, "\tmovzbq\t%s(%%rip), %s\n", Gsym[id].name,
reglist[r]);
if (op == A_POSTINC)
fprintf(Outfile, "\tincb\t%s(\%%rip)\n", Gsym[id].name);
if (op == A_POSTDEC)
fprintf(Outfile, "\tdecb\t%s(\%%rip)\n", Gsym[id].name);
break;
case P_INT:
fprintf(Outfile, "\tmovzbl\t%s(\%%rip), %s\n", Gsym[id].name,
if (op == A_PREINC)
fprintf(Outfile, "\tincl\t%s(\%%rip)\n", Gsym[id].name);
if (op == A_PREDEC)
fprintf(Outfile, "\tdecl\t%s(\%%rip)\n", Gsym[id].name);
fprintf(Outfile, "\tmovslq\t%s(\%%rip), %s\n", Gsym[id].name,
reglist[r]);
if (op == A_POSTINC)
fprintf(Outfile, "\tincl\t%s(\%%rip)\n", Gsym[id].name);
if (op == A_POSTDEC)
fprintf(Outfile, "\tdecl\t%s(\%%rip)\n", Gsym[id].name);
break;
case P_LONG:
case P_CHARPTR:
case P_INTPTR:
case P_LONGPTR:
if (op == A_PREINC)
fprintf(Outfile, "\tincq\t%s(\%%rip)\n", Gsym[id].name);
if (op == A_PREDEC)
fprintf(Outfile, "\tdecq\t%s(\%%rip)\n", Gsym[id].name);
fprintf(Outfile, "\tmovq\t%s(\%%rip), %s\n", Gsym[id].name, reglist[r]);
if (op == A_POSTINC)
fprintf(Outfile, "\tincq\t%s(\%%rip)\n", Gsym[id].name);
if (op == A_POSTDEC)
fprintf(Outfile, "\tdecq\t%s(\%%rip)\n", Gsym[id].name);
break;
default:
fatald("Bad type in cgloadglob:", Gsym[id].type);
}
return (r);
}


// Given the label number of a global string,
// load its address into a new register
int cgloadglobstr(int id) {
Expand All @@ -113,7 +138,6 @@ int cgloadglobstr(int id) {
return (r);
}


// Add two registers together and return
// the number of the register with the result
int cgadd(int r1, int r2) {
Expand Down Expand Up @@ -149,6 +173,71 @@ int cgdiv(int r1, int r2) {
return (r1);
}

int cgand(int r1, int r2) {
fprintf(Outfile, "\tandq\t%s, %s\n", reglist[r1], reglist[r2]);
free_register(r1);
return (r2);
}

int cgor(int r1, int r2) {
fprintf(Outfile, "\torq\t%s, %s\n", reglist[r1], reglist[r2]);
free_register(r1);
return (r2);
}

int cgxor(int r1, int r2) {
fprintf(Outfile, "\txorq\t%s, %s\n", reglist[r1], reglist[r2]);
free_register(r1);
return (r2);
}

int cgshl(int r1, int r2) {
fprintf(Outfile, "\tmovb\t%s, %%cl\n", breglist[r2]);
fprintf(Outfile, "\tshlq\t%%cl, %s\n", reglist[r1]);
free_register(r2);
return (r1);
}

int cgshr(int r1, int r2) {
fprintf(Outfile, "\tmovb\t%s, %%cl\n", breglist[r2]);
fprintf(Outfile, "\tshrq\t%%cl, %s\n", reglist[r1]);
free_register(r2);
return (r1);
}

// Negate a register's value
int cgnegate(int r) {
fprintf(Outfile, "\tnegq\t%s\n", reglist[r]);
return (r);
}

// Invert a register's value
int cginvert(int r) {
fprintf(Outfile, "\tnotq\t%s\n", reglist[r]);
return (r);
}

// Logically negate a register's value
int cglognot(int r) {
fprintf(Outfile, "\ttest\t%s, %s\n", reglist[r], reglist[r]);
fprintf(Outfile, "\tsete\t%s\n", breglist[r]);
fprintf(Outfile, "\tmovzbq\t%s, %s\n", breglist[r], reglist[r]);
return (r);
}

// Convert an integer value to a boolean value. Jump if
// it's an IF or WHILE operation
int cgboolean(int r, int op, int label) {
fprintf(Outfile, "\ttest\t%s, %s\n", reglist[r], reglist[r]);
if (op == A_IF || op == A_WHILE)
fprintf(Outfile, "\tje\tL%d\n", label);
else {
fprintf(Outfile, "\tsetnz\t%s\n", breglist[r]);
fprintf(Outfile, "\tmovzbq\t%s, %s\n", breglist[r], reglist[r]);
}
return (r);
}

// Call a function with one argument from the given register
// Return the register with the result
int cgcall(int r, int id) {
Expand All @@ -164,7 +253,7 @@ int cgcall(int r, int id) {
// Shift a register left by a constant
int cgshlconst(int r, int val) {
fprintf(Outfile, "\tsalq\t$%d, %s\n", val, reglist[r]);
return(r);
return (r);
}

// Store a register's value into a variable
Expand Down Expand Up @@ -214,28 +303,33 @@ void cgglobsym(int id) {
fprintf(Outfile, "%s:", Gsym[id].name);

// Generate the space
for (int i=0; i < Gsym[id].size; i++) {
switch(typesize) {
case 1: fprintf(Outfile, "\t.byte\t0\n"); break;
case 4: fprintf(Outfile, "\t.long\t0\n"); break;
case 8: fprintf(Outfile, "\t.quad\t0\n"); break;
default: fatald("Unknown typesize in cgglobsym: ", typesize);
for (int i = 0; i < Gsym[id].size; i++) {
switch (typesize) {
case 1:
fprintf(Outfile, "\t.byte\t0\n");
break;
case 4:
fprintf(Outfile, "\t.long\t0\n");
break;
case 8:
fprintf(Outfile, "\t.quad\t0\n");
break;
default:
fatald("Unknown typesize in cgglobsym: ", typesize);
}
}
}


// Generate a global string and its start label
void cgglobstr(int l, char *strvalue) {
char *cptr;
cglabel(l);
for (cptr= strvalue; *cptr; cptr++) {
for (cptr = strvalue; *cptr; cptr++) {
fprintf(Outfile, "\t.byte\t%d\n", *cptr);
}
fprintf(Outfile, "\t.byte\t0\n");
}


// List of comparison instructions,
// in AST order: A_EQ, A_NE, A_LT, A_GT, A_LE, A_GE
static char *cmplist[] =
Expand Down Expand Up @@ -327,7 +421,7 @@ int cgderef(int r, int type) {
fprintf(Outfile, "\tmovzbq\t(%s), %s\n", reglist[r], reglist[r]);
break;
case P_INTPTR:
fprintf(Outfile, "\tmovq\t(%s), %s\n", reglist[r], reglist[r]);
fprintf(Outfile, "\tmovslq\t(%s), %s\n", reglist[r], reglist[r]);
break;
case P_LONGPTR:
fprintf(Outfile, "\tmovq\t(%s), %s\n", reglist[r], reglist[r]);
Expand Down
Loading

0 comments on commit 3a11914

Please sign in to comment.