Skip to content

Commit

Permalink
Merge pull request #55 from the-grue/nasm
Browse files Browse the repository at this point in the history
Nasm code generator
  • Loading branch information
DoctorWkt authored Feb 8, 2023
2 parents 1603e2f + 59d7d0b commit 14e9397
Show file tree
Hide file tree
Showing 239 changed files with 38,506 additions and 116 deletions.
15 changes: 14 additions & 1 deletion 04_Assembly/Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
comp1: cg.c expr.c gen.c interp.c main.c scan.c tree.c
cc -o comp1 -g cg.c expr.c gen.c interp.c main.c scan.c tree.c

compn: cgn.c expr.c gen.c interp.c main.c scan.c tree.c
cc -o compn -g cgn.c expr.c gen.c interp.c main.c scan.c tree.c

clean:
rm -f comp1 *.o *.s out
rm -f comp1 compn *.o *.s out

test: comp1
./comp1 input01
Expand All @@ -11,3 +14,13 @@ test: comp1
./comp1 input02
cc -o out out.s
./out

testn: compn
./compn input01
nasm -f elf64 out.s
cc -no-pie -o out out.o
./out
./compn input02
nasm -f elf64 out.s
cc -no-pie -o out out.o
./out
136 changes: 136 additions & 0 deletions 04_Assembly/cgn.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#include "defs.h"
#include "data.h"
#include "decl.h"

// Code generator for x86-64
// Copyright (c) 2019 Warren Toomey, GPL3


// List of available registers
// and their names
static int freereg[4];
static char *reglist[4]= { "r8", "r9", "r10", "r11" };

// Set all registers as available
void freeall_registers(void)
{
freereg[0]= freereg[1]= freereg[2]= freereg[3]= 1;
}

// Allocate a free register. Return the number of
// the register. Die if no available registers.
static int alloc_register(void)
{
for (int i=0; i<4; i++) {
if (freereg[i]) {
freereg[i]= 0;
return(i);
}
}
fprintf(stderr, "Out of registers!\n");
exit(1);
}

// Return a register to the list of available registers.
// Check to see if it's not already there.
static void free_register(int reg)
{
if (freereg[reg] != 0) {
fprintf(stderr, "Error trying to free register %d\n", reg);
exit(1);
}
freereg[reg]= 1;
}

// Print out the assembly preamble
void cgpreamble()
{
freeall_registers();
fputs(
"\tglobal\tmain\n"
"\textern\tprintf\n"
"\tsection\t.text\n"
"LC0:\tdb\t\"%d\",10,0\n"
"printint:\n"
"\tpush\trbp\n"
"\tmov\trbp, rsp\n"
"\tsub\trsp, 16\n"
"\tmov\t[rbp-4], edi\n"
"\tmov\teax, [rbp-4]\n"
"\tmov\tesi, eax\n"
"\tlea rdi, [rel LC0]\n"
"\tmov eax, 0\n"
"\tcall printf\n"
"\tnop\n"
"\tleave\n"
"\tret\n"
"\n"
"main:\n"
"\tpush\trbp\n"
"\tmov rbp, rsp\n",
Outfile);
}

// Print out the assembly postamble
void cgpostamble()
{
fputs(
"\tmov eax, 0\n"
"\tpop rbp\n"
"\tret\n",
Outfile);
}

// Load an integer literal value into a register.
// Return the number of the register
int cgload(int value) {

// Get a new register
int r= alloc_register();

// Print out the code to initialise it
fprintf(Outfile, "\tmov\t%s, %d\n", reglist[r], value);
return(r);
}

// Add two registers together and return
// the number of the register with the result
int cgadd(int r1, int r2) {
fprintf(Outfile, "\tadd\t%s, %s\n", reglist[r2], reglist[r1]);
free_register(r1);
return(r2);
}

// Subtract the second register from the first and
// return the number of the register with the result
int cgsub(int r1, int r2) {
fprintf(Outfile, "\tsub\t%s, %s\n", reglist[r1], reglist[r2]);
free_register(r2);
return(r1);
}

// Multiply two registers together and return
// the number of the register with the result
int cgmul(int r1, int r2) {
fprintf(Outfile, "\timul\t%s, %s\n", reglist[r2], reglist[r1]);
free_register(r1);
return(r2);
}

// Divide the first register by the second and
// return the number of the register with the result
int cgdiv(int r1, int r2) {
fprintf(Outfile, "\tmov\trax, %s\n", reglist[r1]);
fprintf(Outfile, "\tcqo\n");
fprintf(Outfile, "\tidiv\t%s\n", reglist[r2]);
fprintf(Outfile, "\tmov\t%s, rax\n", reglist[r1]);
free_register(r2);
return(r1);
}

// Call printint() with the given register
void cgprintint(int r) {
fprintf(Outfile, "\tmov\trdi, %s\n", reglist[r]);
fprintf(Outfile, "\tcall\tprintint\n");
free_register(r);
}
11 changes: 10 additions & 1 deletion 05_Statements/Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
comp1: cg.c expr.c gen.c main.c misc.c scan.c stmt.c tree.c
cc -o comp1 -g cg.c expr.c gen.c main.c misc.c scan.c stmt.c tree.c

compn: cgn.c expr.c gen.c main.c misc.c scan.c stmt.c tree.c
cc -o compn -g cgn.c expr.c gen.c main.c misc.c scan.c stmt.c tree.c

clean:
rm -f comp1 *.o *.s out
rm -f comp1 compn *.o *.s out

test: comp1 input01
./comp1 input01
cc -o out out.s
./out

testn: compn input01
./compn input01
nasm -f elf64 out.s
cc -no-pie -o out out.o
./out
123 changes: 123 additions & 0 deletions 05_Statements/cgn.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#include "defs.h"
#include "data.h"
#include "decl.h"

// Code generator for x86-64
// Copyright (c) 2019 Warren Toomey, GPL3


// List of available registers
// and their names
static int freereg[4];
static char *reglist[4] = { "r8", "r9", "r10", "r11" };

// Set all registers as available
void freeall_registers(void) {
freereg[0] = freereg[1] = freereg[2] = freereg[3] = 1;
}

// Allocate a free register. Return the number of
// the register. Die if no available registers.
static int alloc_register(void) {
for (int i = 0; i < 4; i++) {
if (freereg[i]) {
freereg[i] = 0;
return (i);
}
}
fprintf(stderr, "Out of registers!\n");
exit(1);
}

// Return a register to the list of available registers.
// Check to see if it's not already there.
static void free_register(int reg) {
if (freereg[reg] != 0) {
fprintf(stderr, "Error trying to free register %d\n", reg);
exit(1);
}
freereg[reg] = 1;
}

// Print out the assembly preamble
void cgpreamble() {
freeall_registers();
fputs("\tglobal\tmain\n"
"\textern\tprintf\n"
"\tsection\t.text\n"
"LC0:\tdb\t\"%d\",10,0\n"
"printint:\n"
"\tpush\trbp\n"
"\tmov\trbp, rsp\n"
"\tsub\trsp, 16\n"
"\tmov\t[rbp-4], edi\n"
"\tmov\teax, [rbp-4]\n"
"\tmov\tesi, eax\n"
"\tlea rdi, [rel LC0]\n"
"\tmov eax, 0\n"
"\tcall printf\n"
"\tnop\n"
"\tleave\n"
"\tret\n"
"\n"
"main:\n" "\tpush\trbp\n" "\tmov rbp, rsp\n", Outfile);
}

// Print out the assembly postamble
void cgpostamble() {
fputs("\tmov eax, 0\n" "\tpop rbp\n" "\tret\n", Outfile);
}

// Load an integer literal value into a register.
// Return the number of the register
int cgload(int value) {

// Get a new register
int r = alloc_register();

// Print out the code to initialise it
fprintf(Outfile, "\tmov\t%s, %d\n", reglist[r], value);
return (r);
}

// Add two registers together and return
// the number of the register with the result
int cgadd(int r1, int r2) {
fprintf(Outfile, "\tadd\t%s, %s\n", reglist[r2], reglist[r1]);
free_register(r1);
return (r2);
}

// Subtract the second register from the first and
// return the number of the register with the result
int cgsub(int r1, int r2) {
fprintf(Outfile, "\tsub\t%s, %s\n", reglist[r1], reglist[r2]);
free_register(r2);
return (r1);
}

// Multiply two registers together and return
// the number of the register with the result
int cgmul(int r1, int r2) {
fprintf(Outfile, "\timul\t%s, %s\n", reglist[r2], reglist[r1]);
free_register(r1);
return (r2);
}

// Divide the first register by the second and
// return the number of the register with the result
int cgdiv(int r1, int r2) {
fprintf(Outfile, "\tmov\trax, %s\n", reglist[r1]);
fprintf(Outfile, "\tcqo\n");
fprintf(Outfile, "\tidiv\t%s\n", reglist[r2]);
fprintf(Outfile, "\tmov\t%s, rax\n", reglist[r1]);
free_register(r2);
return (r1);
}

// Call printint() with the given register
void cgprintint(int r) {
fprintf(Outfile, "\tmov\trdi, %s\n", reglist[r]);
fprintf(Outfile, "\tcall\tprintint\n");
free_register(r);
}
17 changes: 16 additions & 1 deletion 06_Variables/Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
SRCS= cg.c decl.c expr.c gen.c main.c misc.c scan.c stmt.c sym.c tree.c
SRCN= cgn.c decl.c expr.c gen.c main.c misc.c scan.c stmt.c sym.c tree.c

comp1: $(SRCS)
cc -o comp1 -g $(SRCS)

compn: $(SRCN)
cc -o compn -g $(SRCN)

clean:
rm -f comp1 *.o *.s out
rm -f comp1 compn *.o *.s out

test: comp1 input01 input02
./comp1 input01
Expand All @@ -12,3 +17,13 @@ test: comp1 input01 input02
./comp1 input02
cc -o out out.s
./out

testn: compn input01 input02
./compn input01
nasm -f elf64 out.s
cc -no-pie -o out out.o
./out
./compn input02
nasm -f elf64 out.s
cc -no-pie -o out out.o
./out
Loading

0 comments on commit 14e9397

Please sign in to comment.