From 0bbd98b0064e4344b9b6f3ce63b55a6e8397ceff Mon Sep 17 00:00:00 2001
From: Xun Yang <x299yang@uwaterloo.ca>
Date: Mon, 13 Apr 2020 00:47:44 -0400
Subject: [PATCH] array subtype table

---
 AstBuilding.py | 41 +++++++++++++++++++++++++++++++++++++----
 TypeNodes.py   |  8 ++++++++
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/AstBuilding.py b/AstBuilding.py
index 2d3409c..3508248 100644
--- a/AstBuilding.py
+++ b/AstBuilding.py
@@ -1,6 +1,7 @@
 from CompNode import CompNode
 from pprint import pprint
 from Environment import GlobalEnv
+from TypeNodes import getSupers
 from CodeGenUtils import p, genProcedure, used_labels, local_labels, pLabel, genericHelperFunctions, globalImport
 
 # tree: (filename, parseTree)
@@ -62,23 +63,47 @@ def reachabilityChecking(ASTs):
 # Returns a dictionary (type e.g. "boolean") -> str (the assembly code generated)
 def arrayClassMemory(types):
     # All method labels from java.lang.Object
-    # TODO: add subtype testing table
     methods = ["M_Object_Object_", "M_Object_equals_Object", "M_Object_toString_", "M_Object_hashCode_", "M_Object_clone_", "M_Object_getClass_"]
-    typeDict = {}
     primTypes = ['boolean', 'byte', 'char', 'int', 'short'] # All possible types
-    for t in types:
+    typeDict = {}
+    # assignable = dict({"java.lang.Object" : 0,
+    # "java.lang.Cloneable" : 4,
+    # "java.io.Serializable" : 8
+    # })
+
+    for tt in types:
         # Class memory layout
         # Label: "A_type"
         # Label for SIT pointer: "I_SIT_spot_typeName_array"
         # Label for method pointers: "V_typeName_methodName_param_array"
+        if tt.__class__.__name__ == "ClassNode":
+            t = tt.name
+        else:
+            t = tt
+
         code = "section .data\n"
         code += "; Start of class memory layout\n"
         code += pLabel(name=t, type="array") + \
                 pLabel("SIT_spot_"+ t + "_array", "inter") + \
                 p(instruction="dd", arg1=64)
+
+        # point to subtype table
+        code += pLabel("subT_spot_" + t, "inter")
+        code += p("dd", "42")
+
         for m in methods:
             code += pLabel(name=t+"_"+m+"_array", type="vtable") + \
                     p(instruction="dd", arg1=64)
+
+        # layout subtype table
+        code += pLabel("subT_" + t, "inter")
+        code += p("dd", "0") # row 0 = false for all other objects
+        for i in range(3):
+            code += p("dd", "1") # True for 3 objects
+
+        for i in range (len(types) - 5): # non primtype arrays
+            code += pLabel("subT_" + str(i), "inter")
+            code += p("dd", "0")
         code += "; End of class memory layout\n"
 
         # Creating a function to initialize class memory layout
@@ -94,6 +119,14 @@ def arrayClassMemory(types):
             code += p(instruction="extern", arg1=m) + \
                     p(instruction="mov", arg1="eax", arg2="dword V_"+t+"_"+m+"_array") + \
                     p(instruction="mov", arg1="[eax]", arg2="dword "+m, comment="points to method implementation")
+
+        # fill in SubT for non-primType arrays
+        if tt.__class__.__name__ == "ClassNode":
+            for s in getSupers(tt):
+                dlabel = "I_subT_" + str(s.subTypeOffset // 4) # 9 = 4 objects + 5 primtype arrays
+                code += p("mov", "eax", dlabel, "self is a subType of array " + s.canonName)
+                code += p("mov", "[eax]", "dword 1")
+
         code += p(instruction="ret", arg1="")
         code += "; End of function to initialize class memory layout\n"
         if t in primTypes:
@@ -118,7 +151,7 @@ def codeGenPrep(ASTs):
         classInterNode = t[1].typeDcl
         if classInterNode.__class__.__name__ == "ClassNode":
 
-            types.append(classInterNode.name)
+            types.append(classInterNode)
             classNodes.append(classInterNode)
         else: # interfaceNode, get their methods to prep for SIT
             interM += classInterNode.methods
diff --git a/TypeNodes.py b/TypeNodes.py
index 99fab64..e3bca58 100644
--- a/TypeNodes.py
+++ b/TypeNodes.py
@@ -19,6 +19,7 @@ class ClassInterNode(ASTNode):
         self.SITsize = 0
         self.subTypeSize = 0
         self.subTypeOffset = 0
+        self.arrayTypeOffset = 0 # only array assignable classes will have this field set
 
         # sets
         self.inherits = []
@@ -307,6 +308,13 @@ class ClassNode(ClassInterNode):
         # Calculating the size of objects of this class
         self.size += (len(self.fieldOffset))*4
 
+        assignable = dict({"java.lang.Object" : 4,
+        "java.lang.Cloneable" : 8,
+        "java.io.Serializable" : 12
+        }) # fix offsets for array assignable classes, 0 row is reserve for all the non assignable ones
+        if self.canonName in assignable.keys():
+            self.arrayTypeOffset = assignable[self.canonName]
+
     # Populating method offset and creating class memory layout
     def populateMethodOffset(self):
         if hasattr(self, "data"):
-- 
GitLab