Skip to content
Snippets Groups Projects
Commit 59ff3526 authored by pycsham's avatar pycsham
Browse files

Merge branch 'master' of https://git.uwaterloo.ca/x299yang/cs444

parents 9501b41b f43e96ab
No related branches found
No related tags found
No related merge requests found
......@@ -3,3 +3,4 @@ __pycache__/
ErrorTest.py
Test.py
*.zip
output/
from CompNode import CompNode
from pprint import pprint
from Environment import GlobalEnv
from CodeGenUtils import p, genProcedure
from CodeGenUtils import p, genProcedure, used_labels, local_labels
# tree: (filename, parseTree)
def astBuild(trees):
......@@ -57,26 +57,30 @@ def reachabilityChecking(ASTs):
t[1].reachCheck()
####################################################
def codeGen(ASTs):
def codeGen(ASTs, output="output"):
for t in ASTs:
t[1].codeGen()
# Outputting the generated code into className.s
# Outputting the generated code into className.s
# Note: Interfaces do not generate any code
for t in ASTs:
classInterNode = t[1].typeDcl
if classInterNode and classInterNode.__class__.__name__ == "ClassNode":
fileName = "output/" + classInterNode.name + ".s"
fileName = output + "/" + classInterNode.name + ".s"
f = open(fileName, "w")
f.write(classInterNode.code)
f.close()
# ASTs[0][1].codeGen()
startGen(ASTs[0][1]) # pass in the first AST that contains the test method
startGen(ASTs[0][1], output) # pass in the first AST that contains the test method
def startGen(ast):
# reset lables for running multiple testCases
used_labels = set()
local_labels = 0
def startGen(ast, output):
className = ast.typeDcl.name
method_label = "M_" + className + "_test_None"
f = open("output/RunTest.s","w")
f = open( output + "/RunTest.s","w")
result = " global _start\n_start:\n" \
+ p("extern", method_label, None, None) \
......
import sys
import time
from os import listdir, scandir, walk
from os.path import isfile, join
from os import listdir, scandir, walk, makedirs
from os.path import isfile, join, exists
from shutil import rmtree, copyfile
import traceback
from Scanning import scan
......@@ -45,7 +46,13 @@ def a2Multiple():
testFiles = [join(dp, f) for dp, dn, filenames in walk(c) for f in filenames] + testFiles
ret = run(testFiles)
testOutput = "output/" + c.split("/")[-1]
if exists(testOutput):
rmtree(testOutput)
makedirs(testOutput)
copyfile('stdlib/5.0/runtime.s', testOutput + "/runtime.s")
ret = run(testFiles, testOutput)
total += 1
if ret == "":
......@@ -67,7 +74,7 @@ def a2Multiple():
print("\nTime Elapsed: {}".format(time.strftime('%H:%M:%S', time.gmtime(end - start))))
print("SCORE: {} / {} -> {:.3g}%".format(correct, total, (correct/total)*100))
def run(testFiles):
def run(testFiles, testOutput):
parseTrees = []
for f in testFiles:
......@@ -140,7 +147,7 @@ def run(testFiles):
except Exception as e:
return "reachabilityChecking: " + e.args[0]
try:
codeGen(ASTs)
codeGen(ASTs, testOutput)
except Exception as e:
return "code generation: " + e.args[0]
......
......@@ -165,7 +165,7 @@ class ClassNode(ClassInterNode):
self.label = "" # label in assembly
self.methodOffset = {} # a dictionary that maps method signatures (method.name, method.paramTypes) to offsets in the CLASS memory layout
self.fieldOffset = {} # a dictionary that maps field names to offsets in OBJECT memory layout
self.staticFieldLabels = [] # a list of static field labels
self.staticFieldLabels = [] # a list of static field labels
for node in parseTree.children:
if node.name == 'classMod':
......@@ -257,7 +257,12 @@ class ClassNode(ClassInterNode):
# overlapping class/interface logic
super().checkHierarchy()
# point superClass to java.lang.Object after hierarchy checking is done
if self.canonName != 'java.lang.Object' and not self.superClass:
self.superClass = self.env.getNode('java.lang.Object', 'type')
def checkType(self):
super().checkType()
......@@ -278,19 +283,19 @@ class ClassNode(ClassInterNode):
self.label = pLabel(name=self.name, type="class")
self.code += ";START OF CLASS MEMORY LAYOUT FOR CLASS: " + self.canonName + "\n"
self.code += self.label
# TODO: SIT and subtype testing tables
####### ADDING METHODS TO CLASS MEMORY LAYOUT AND FIELDS TO FIELD OFFSET TABLE #########
# 1.
# a) Copying over the offsets of methods from superclass and DECLARING memory segment for the methods
# 1.
# a) Copying over the offsets of methods from superclass and DECLARING memory segment for the methods
# b) copying over the offsets of fields from superclass (TO BE USED LATER FOR OBJECT MEMORY LAYOUT)
lastMethodOffset = -4 # stores the largest method offset in the superCalss
lastMethodOffset = -4 # stores the largest method offset in the superCalss
# TODO: set this to 4 after the implemntation of both the SIT and subtype testing table
# Note: This is 4 less than the offset of where the next method would be located
# This is to accomodate for the addition of 4 to lastMethodOffset in EVERY (including the first) iteration in the
# This is to accomodate for the addition of 4 to lastMethodOffset in EVERY (including the first) iteration in the
# loops that loops through self.constructors and self.methods, in the case where there is no superClass
lastFieldOffset = 0
lastFieldOffset = 0
if self.superClass:
if not hasattr(self.superClass, "code"):
......@@ -301,20 +306,20 @@ class ClassNode(ClassInterNode):
self.code += pLabel(name=self.name + "_" + key[0] + "_" + key[1], type="vtable")
self.code += p(instruction="dd", arg1=64) # just declaring a memory segment with a random number
lastMethodOffset = max(value, lastMethodOffset)
# Iterating through field offset table sorted by offset
for key,value in self.superClass.fieldOffset.items():
self.fieldOffset[key] = value
lastFieldOffset = max(value, lastFieldOffset)
# 2. Assigning offsets to constructors and DECLARING memory segment for the methods
# 2. Assigning offsets to constructors and DECLARING memory segment for the methods
for method in self.constructors:
lastMethodOffset += 4
self.methodOffset[(method.name, method.paramTypes)] = lastMethodOffset
self.code += pLabel(name=self.name + "_" + method.name + "_" + method.paramTypes, type="vtable")
self.code += p(instruction="dd", arg1=64) # just declaring a memory segment with a random number
# 3. Assigning offsets to methods that aren't in the super class DECLARING memory segment for the methods
# 3. Assigning offsets to methods that aren't in the super class DECLARING memory segment for the methods
for method in self.methods:
if not (method.name, method.paramTypes) in self.methodOffset:
lastMethodOffset += 4
......@@ -324,13 +329,13 @@ class ClassNode(ClassInterNode):
# print(self.methodOffset)
self.code += ";END OF CLASS MEMORY LAYOUT FOR CLASS " + self.name + "\n"
# 4. Fill in the memory segment declared in step 1 and 2 with the addresses of the method implementations
# 4. Fill in the memory segment declared in step 1 and 2 with the addresses of the method implementations
for key,value in self.methodOffset.items():
vLabel = "V_" + self.name + "_" + key[0] + "_" + key[1]+"" # method at class's vtable
mLabel = "M_" + self.name + "_" + key[0] + "_" + key[1] # method implementation
self.code += p(instruction="mov", arg1="eax", arg2=vLabel, comment="Filling in class memory segment for method " + mLabel)
self.code += p(instruction="mov", arg1="[eax]", arg2=mLabel)
#5. Adding in fields that are not inherited from parent class to offset table
# Note: excluding static fields
for field in self.fields:
......@@ -339,7 +344,7 @@ class ClassNode(ClassInterNode):
self.fieldOffset[field.name] = lastFieldOffset
# print(self.name)
# print(self.fieldOffset)
# print(self.code)
###########################################################
......@@ -350,7 +355,7 @@ class ClassNode(ClassInterNode):
if c and hasattr(c, "codeGen"):
if not hasattr(c, "code"): # children hasn't generated code yet
c.codeGen()
self.code += c.code
self.code += c.code
#####################################################################
......
#!/bin/bash
# can supply folder name as argument to run 1 test test case
# run one case: ./testAssemble.sh J1_00_Step0.java
# run all cases: ./testAssemble.sh
cd output
if [ "$#" -eq 0 ]; then
# assemble and link and output results of running each test case
for d in ./*/; do
cd $d
echo "-----------------------------------"
echo "Run generated code for " + $d
for filename in ./*.s; do
/u/cs444/bin/nasm -O1 -f elf -g -F dwarf $filename
done
ld -melf_i386 -o main ./*.o
# run main
./main
# echo the exit code
echo $?
echo "-----------------------------------"
cd ..
done
else
cd $1
for filename in ./*.s; do
/u/cs444/bin/nasm -O1 -f elf -g -F dwarf $filename
done
ld -melf_i386 -o main ./*.o
# run main
./main
# echo the exit code
echo $?
fi
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment