def generate(self, cls): # keeps track of information on variables used in this method name = self.node.id.name rtype = str(self.node.type) args = env.getMethodType(cls, name) varinfo = { 'used': 0, 'labels': 0, 'class': cls } body = "\n\ndefine %s {" % methoddefstring(cls, name, args) body += "\nentry:" for i, formal in enumerate(self.node.formals.children): fty = formal.id.type body += "\n %s = alloca %%obj_%s*" % (formal.id.static, fty) body += "\n store %%obj_%s* %%a%d, %%obj_%s** %s" % (fty, i, fty, formal.id.static) body += self.node.value.codegen.generate(varinfo) body += bitcast_if_necessary(varinfo, rtype, varinfo['result_type'], varinfo['result']) body += "\n ret %%obj_%s* %s" % (rtype, varinfo['result']) body += "\n}" code = string_const_code(varinfo) code += body return code
def generate(self, varinfo): cls = str(self.node.type) code = "" name = "@%s.%s" % (cls, "_constructor") argtypes = env.getMethodType(cls, "_constructor") args = ['null'] for actual,argtype in zip(self.node.actuals.children, argtypes): code += actual.codegen.generate(varinfo) code += bitcast_if_necessary(varinfo, argtype, varinfo['result_type'], varinfo['result']) args.append(varinfo['result']) varinfo['result'] = get_next_temp(varinfo) varinfo['result_type'] = cls code += "\n ; Calling %s._constructor" %cls code += "\n %s = call %s" % (varinfo['result'], methodcallstring(cls, name, argtypes, args)) return code
def generate(self): cls = str(self.node.type) code = "" form = """ %%class_%(name)s = type { %%class_%(superclass)s*, i8*, %(method_types)s } @._str.%(name)s = constant [%(len)s x i8] c"%(name)s\\00" @.str.%(name)s = alias i8* bitcast ([%(len)s x i8]* @._str.%(name)s to i8*) @%(name)s = global %%class_%(name)s { %%class_%(superclass)s* @%(superclass)s, i8* @.str.%(name)s, %(methods)s } %%obj_%(name)s = type { %%class_%(name)s*%(field_types)s } """ m = env.getClassMethods(cls) alias_strs = [] alias_form = ("\n@%(class)s.%(method)s = alias %(type)s bitcast "+ "(%(supertype)s @%(super)s.%(method)s to %(type)s)\n") method_consts = [None]*len(m) method_types = list(method_consts) methods = {} for name, (args, pos, inherited_from) in m.iteritems(): typestr = methodtypestring(cls, args) method_types[pos] = typestr method_consts[pos] = "%s %s" % (typestr, "@%s.%s" % (cls, name)) methods[name] = typestr if inherited_from != cls: supertypestr = methodtypestring(inherited_from, args) alias_strs.append(alias_form % { 'class': cls, 'method': name, 'type' : typestr, 'super' : inherited_from, 'supertype' : supertypestr }) v = env.getClassVars(cls) fields = [None]*len(v) for name, (ty, pos) in v.iteritems(): fields[pos] = ",\n " + (OBJ_PTR % ty) code += form % { 'name': cls, 'len': len(cls)+1, 'superclass' : self.node.superclass.name, 'method_types': ",\n ".join(method_types), 'methods': ",\n ".join(method_consts), 'field_types' : "".join(fields) } for alias in alias_strs: code += alias # Constructor... constructor = { 'body': "", 'class': cls, 'superclass': self.node.superclass.name, 'malloc_bytes': (len(fields)+1)*4 } constr_form = """ define %(def)s { entry: %%objstk = alloca %%obj_%(class)s* store %%obj_%(class)s* %%child, %%obj_%(class)s** %%objstk %%isnull = icmp eq %%obj_%(class)s* %%child, null br i1 %%isnull, label %%allocate, label %%initialize allocate: %%space = call i8* @malloc(i32 %(malloc_bytes)d) %%newobj = bitcast i8* %%space to %%obj_%(class)s* %%cls_field = getelementptr inbounds %%obj_%(class)s* %%newobj, i32 0, i32 0 store %%obj_%(class)s* %%newobj, %%obj_%(class)s** %%objstk store %%class_%(class)s* @%(class)s, %%class_%(class)s** %%cls_field br label %%initialize initialize: %%this = load %%obj_%(class)s** %%objstk ; Recursively call our superclass' constructor %%as_super = bitcast %%obj_%(class)s* %%this to %%obj_%(superclass)s* call %%obj_%(superclass)s* @%(superclass)s._constructor(%%obj_%(superclass)s* %%as_super) ;;;; %(class)s class initialization ;;;; %(body)s ret %%obj_%(class)s* %%this } """ args = env.getMethodType(cls, "_constructor") constructor['def'] = methoddefstring(cls, '_constructor', args, '%child') varinfo = { 'used': 1, 'labels': 0, 'class': cls } for arg, formal in enumerate(self.node.formals.children): argname = "%%a%d" % arg constructor['body'] += STORE_FIELD % { 'temp': get_next_temp(varinfo), 'class': cls, 'loc': formal.id.static + 1, 'type': str(formal.type), 'addr': argname } defs = [] for feature in self.node.body.children: if isinstance(feature, tree.Def): defs.append(feature) if isinstance(feature, tree.Block): constructor['body'] += feature.codegen.generate(varinfo) if isinstance(feature, tree.VarInit): # Generate code for the expression... constructor['body'] += feature.value.codegen.generate(varinfo) result = varinfo['result'] temp = get_next_temp(varinfo) constructor['body'] += STORE_FIELD % { 'temp': temp, 'class': cls, 'loc': feature.id.static + 1, 'type': str(feature.type), 'addr': result } defcode = "" defcode += string_const_code(varinfo) defcode += constr_form % constructor for method in defs: defcode += method.codegen.generate(cls) return code, defcode