From 593233bedea855012096229d92d74b3fe41c4063 Mon Sep 17 00:00:00 2001 From: Xun Yang <x299yang@uwaterloo.ca> Date: Fri, 10 Apr 2020 21:31:40 -0400 Subject: [PATCH] initial SIT --- AstBuilding.py | 16 ++++++++++++-- TypeNodes.py | 59 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/AstBuilding.py b/AstBuilding.py index c7b6dcd..9f1d446 100644 --- a/AstBuilding.py +++ b/AstBuilding.py @@ -58,17 +58,29 @@ def reachabilityChecking(ASTs): #################################################### # Preparation before code Gen: -# 1. Calculating the size of the object from each class +# 1. Calculating the size of the object from each class # (also simultaneosly creating fieldOffset because fieldOffset table is required to generate size) def codeGenPrep(ASTs): + interM = [] for t in ASTs: classInterNode = t[1].typeDcl if classInterNode and classInterNode.__class__.__name__ == "ClassNode": classInterNode.populateSizeAndFieldOffset() + else: # interfaceNode, get their methods to prep for SIT + interM += classInterNode.method + + if interM: # prep SIT + for i in range(len(interM)): + interM[i].SIToffset = i + for t in ASTs: + classInterNode = t[1].typeDcl + if classInterNode and classInterNode.__class__.__name__ == "ClassNode": + classInterNode.SITsize = len(interM) + def codeGen(ASTs, output="output"): ASTs = ASTs[:1] # TOREMOVE: don't compile stdlib for now - codeGenPrep(ASTs) + codeGenPrep(ASTs) for t in ASTs: t[1].codeGen() # Outputting the generated code into className.s diff --git a/TypeNodes.py b/TypeNodes.py index 14b6f8f..cea934d 100644 --- a/TypeNodes.py +++ b/TypeNodes.py @@ -16,6 +16,7 @@ class ClassInterNode(ASTNode): self.env = None self.children = [] self.canonName = '' + self.SITsize = 0 # sets self.inherits = [] @@ -305,7 +306,7 @@ class ClassNode(ClassInterNode): return - self.code = "" # For read-only section + self.code = "" # For read-only section self.data = "" # For writeable data section # print("This is the super class: {}".format(self.superClass)) @@ -314,12 +315,15 @@ class ClassNode(ClassInterNode): self.data += ";START OF CLASS MEMORY LAYOUT FOR CLASS: " + self.canonName + "\n" self.data += self.label + # SIT + self.data += pLabel("SIT_spot_"+ self.name, "local") + self.data += p("dd", "42") - # TODO: SIT and subtype testing tables + # TODO: subtype testing tables ####### ADDING METHODS TO CLASS MEMORY LAYOUT AND FIELDS TO FIELD OFFSET TABLE ######### # Copying over the offsets of methods from superclass and DECLARING memory segment for the methods - lastMethodOffset = -4 # stores the largest method offset in the superCalss + lastMethodOffset = 0 # 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 @@ -355,15 +359,20 @@ class ClassNode(ClassInterNode): self.methodOffset[(method.name, method.paramTypes)] = lastMethodOffset self.data += pLabel(name=self.name + "_" + method.name + "_" + method.paramTypes, type="vtable") self.data += p(instruction="dd", arg1=64) # just declaring a memory segment with a random number - - # Adding inherited method to the methodDict + + # Adding inherited method to the methodDict for i in self.inherits: if isinstance(i, MethodNode): key = (i.name, i.paramTypes) if not key in methodDict: methodDict[(i.name, i.paramTypes)] = i - # print(self.methodOffset) + # Layout SIT + self.code += pLabel("SIT_" + self.name, "local") + for i in range(self.SITsize): + self.code += pLabel("SIT_" + i, "local") + self.data += p("dd", "42") + self.data += ";END OF CLASS MEMORY LAYOUT FOR CLASS " + self.name + "\n" @@ -385,9 +394,37 @@ class ClassNode(ClassInterNode): self.code += p(instruction="extern", arg1=mLabel, comment="importing method implementation label") 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="dword " + mLabel) + + self.code += "; End of function for filling in methods in class memory layout\n" + + # fill in SIT + self.code += "\n; Filling in SIT\n" + self.code += p("mov", "eax", "_SIT_spot" + self.name) + self.code += p("mov", "[eax]", "dword _SIT_" + self.name) + + interM = [] + for s in self.super: + if s.__class__.__name__ == "InterNode": + interM += s.methods + for m in interM: + imple = methodDict[(m.name, m.paramTypes)] + className = imple.typeName + + dlabel = "_SIT_" + m.SIToffset + imLabel = "M_" + className + "_" + m.name + "_" + m.paramTypes + if className != self.typeName: + self.code += p("extern", imLabel) + self.code += p("mov", "eax", dlabel) + self.code += p("mov", "[eax]", "dword " + imLabel) + self.code += "; End of fill in SIT.\n" + self.code += p(instruction="ret", arg1="") self.code += "; End of function for filling in class memory layout\n" + + + + # print(self.name) # print(self.fieldOffset) @@ -395,22 +432,22 @@ class ClassNode(ClassInterNode): ########################################################### - # Generating a function that allocates and initializes all static fields - # Note: 1. saving and restoring ebx, a callee-save register + # Generating a function that allocates and initializes all static fields + # Note: 1. saving and restoring ebx, a callee-save register # 2. static fields are intialized in the order of declaration within the class and has to be intialized # before the test() method is being called self.code += "; Function for filling allocating space and initializing static fields for class " + self.name + "\n" self.code += pLabel(name=self.name + "_" + "staticFieldMemoryInit", type="helper") - self.code += p(instruction="push", arg1="ebx", comment="saving ebx") + self.code += p(instruction="push", arg1="ebx", comment="saving ebx") for field in self.fields: if not hasattr(field, "code"): field.codeGen() self.code += field.code self.data += field.data - self.code += p(instruction="pop", arg1="ebx", comment="restoring ebx") + self.code += p(instruction="pop", arg1="ebx", comment="restoring ebx") self.code += p(instruction="ret", arg1="") self.code += "; End of function for filling allocating space and initializing static fields for class " + self.name + "\n" - + # Generating a function that calls both the class memory init and static field init functions self.code += "; Function that calls staticFieldMemoryInit and classMemoryInit \n" self.code += pLabel(name=self.name + "_" + "classAndStaticFieldInit", type="helper") -- GitLab