MethodCallExprAST.py revision 8644
16657Snate@binkert.org# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 26657Snate@binkert.org# Copyright (c) 2009 The Hewlett-Packard Development Company 36657Snate@binkert.org# All rights reserved. 46657Snate@binkert.org# 56657Snate@binkert.org# Redistribution and use in source and binary forms, with or without 66657Snate@binkert.org# modification, are permitted provided that the following conditions are 76657Snate@binkert.org# met: redistributions of source code must retain the above copyright 86657Snate@binkert.org# notice, this list of conditions and the following disclaimer; 96657Snate@binkert.org# redistributions in binary form must reproduce the above copyright 106657Snate@binkert.org# notice, this list of conditions and the following disclaimer in the 116657Snate@binkert.org# documentation and/or other materials provided with the distribution; 126657Snate@binkert.org# neither the name of the copyright holders nor the names of its 136657Snate@binkert.org# contributors may be used to endorse or promote products derived from 146657Snate@binkert.org# this software without specific prior written permission. 156657Snate@binkert.org# 166657Snate@binkert.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176657Snate@binkert.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186657Snate@binkert.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196657Snate@binkert.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206657Snate@binkert.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216657Snate@binkert.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226657Snate@binkert.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236657Snate@binkert.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246657Snate@binkert.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256657Snate@binkert.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266657Snate@binkert.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276657Snate@binkert.org 286657Snate@binkert.orgfrom slicc.ast.ExprAST import ExprAST 296657Snate@binkert.org 306657Snate@binkert.orgclass MethodCallExprAST(ExprAST): 316657Snate@binkert.org def __init__(self, slicc, proc_name, expr_ast_vec): 326657Snate@binkert.org super(MethodCallExprAST, self).__init__(slicc) 336657Snate@binkert.org self.proc_name = proc_name 346657Snate@binkert.org self.expr_ast_vec = expr_ast_vec 356657Snate@binkert.org 366657Snate@binkert.org def generate(self, code): 376999Snate@binkert.org tmp = self.slicc.codeFormatter() 386657Snate@binkert.org paramTypes = [] 396657Snate@binkert.org for expr_ast in self.expr_ast_vec: 406657Snate@binkert.org return_type = expr_ast.generate(tmp) 416657Snate@binkert.org paramTypes.append(return_type) 426657Snate@binkert.org 436657Snate@binkert.org obj_type, methodId, prefix = self.generate_prefix(paramTypes) 446657Snate@binkert.org 456657Snate@binkert.org # generate code 466657Snate@binkert.org params = [] 476657Snate@binkert.org for expr_ast in self.expr_ast_vec: 486657Snate@binkert.org return_type,tcode = expr_ast.inline(True) 496657Snate@binkert.org params.append(str(tcode)) 506657Snate@binkert.org fix = code.nofix() 516657Snate@binkert.org code("$prefix${{self.proc_name}}(${{', '.join(params)}}))") 526657Snate@binkert.org code.fix(fix) 536657Snate@binkert.org 546657Snate@binkert.org # Verify that this is a method of the object 556657Snate@binkert.org if methodId not in obj_type.methods: 566690SBrad.Beckmann@amd.com self.error("Invalid method call: Type '%s' does not have a method '%s'", 576690SBrad.Beckmann@amd.com obj_type, methodId) 586657Snate@binkert.org 596657Snate@binkert.org if len(self.expr_ast_vec) != \ 606657Snate@binkert.org len(obj_type.methods[methodId].param_types): 616657Snate@binkert.org # Right number of parameters 626690SBrad.Beckmann@amd.com self.error("Wrong number of parameters for function name: '%s', " + \ 636690SBrad.Beckmann@amd.com "expected: , actual: ", proc_name, 646657Snate@binkert.org len(obj_type.methods[methodId].param_types), 656657Snate@binkert.org len(self.expr_ast_vec)) 666657Snate@binkert.org 676657Snate@binkert.org for actual_type, expected_type in \ 686657Snate@binkert.org zip(paramTypes, obj_type.methods[methodId].param_types): 696882SBrad.Beckmann@amd.com if actual_type != expected_type and \ 706882SBrad.Beckmann@amd.com str(actual_type["interface"]) != str(expected_type): 716690SBrad.Beckmann@amd.com self.error("Type mismatch: expected: %s actual: %s", 726690SBrad.Beckmann@amd.com expected_type, actual_type) 736657Snate@binkert.org 746657Snate@binkert.org # Return the return type of the method 756657Snate@binkert.org return obj_type.methods[methodId].return_type 766657Snate@binkert.org 776657Snate@binkert.org def findResources(self, resources): 786657Snate@binkert.org pass 796657Snate@binkert.org 806657Snate@binkert.orgclass MemberMethodCallExprAST(MethodCallExprAST): 816657Snate@binkert.org def __init__(self, slicc, obj_expr_ast, proc_name, expr_ast_vec): 826657Snate@binkert.org s = super(MemberMethodCallExprAST, self) 836657Snate@binkert.org s.__init__(slicc, proc_name, expr_ast_vec) 846657Snate@binkert.org 856657Snate@binkert.org self.obj_expr_ast = obj_expr_ast 866657Snate@binkert.org 876657Snate@binkert.org def __repr__(self): 886657Snate@binkert.org return "[MethodCallExpr: %r%r %r]" % (self.proc_name, 896657Snate@binkert.org self.obj_expr_ast, 906657Snate@binkert.org self.expr_ast_vec) 916657Snate@binkert.org def generate_prefix(self, paramTypes): 926999Snate@binkert.org code = self.slicc.codeFormatter() 936657Snate@binkert.org 946657Snate@binkert.org # member method call 956657Snate@binkert.org obj_type = self.obj_expr_ast.generate(code) 966657Snate@binkert.org methodId = obj_type.methodId(self.proc_name, paramTypes) 976657Snate@binkert.org 986657Snate@binkert.org prefix = "" 996882SBrad.Beckmann@amd.com implements_interface = False 1007839Snilay@cs.wisc.edu 1017839Snilay@cs.wisc.edu if methodId in obj_type.methods: 1027839Snilay@cs.wisc.edu return_type = obj_type.methods[methodId].return_type 1037839Snilay@cs.wisc.edu 1047839Snilay@cs.wisc.edu else: 1056882SBrad.Beckmann@amd.com # 1067839Snilay@cs.wisc.edu # Check whether the method is implemented by the super class 1077839Snilay@cs.wisc.edu if "interface" in obj_type: 1087839Snilay@cs.wisc.edu interface_type = self.symtab.find(obj_type["interface"]); 1097839Snilay@cs.wisc.edu 1107839Snilay@cs.wisc.edu if methodId in interface_type.methods: 1117839Snilay@cs.wisc.edu return_type = interface_type.methods[methodId].return_type 1127839Snilay@cs.wisc.edu obj_type = interface_type 1137839Snilay@cs.wisc.edu 1146882SBrad.Beckmann@amd.com else: 1157839Snilay@cs.wisc.edu self.error("Invalid method call: " \ 1167839Snilay@cs.wisc.edu "Type '%s' does not have a method %s, '%s'", 1177839Snilay@cs.wisc.edu obj_type, self.proc_name, methodId) 1186882SBrad.Beckmann@amd.com 1196882SBrad.Beckmann@amd.com else: 1207839Snilay@cs.wisc.edu # 1217839Snilay@cs.wisc.edu # The initial method check has failed, but before generating an 1227839Snilay@cs.wisc.edu # error we must check whether any of the paramTypes implement 1237839Snilay@cs.wisc.edu # an interface. If so, we must check if the method ids using 1247839Snilay@cs.wisc.edu # the inherited types exist. 1257839Snilay@cs.wisc.edu # 1267839Snilay@cs.wisc.edu # This code is a temporary fix and only checks for the methodId 1277839Snilay@cs.wisc.edu # where all paramTypes are converted to their inherited type. The 1287839Snilay@cs.wisc.edu # right way to do this is to replace slicc's simple string 1297839Snilay@cs.wisc.edu # comparison for determining the correct overloaded method, with a 1307839Snilay@cs.wisc.edu # more robust param by param check. 1317839Snilay@cs.wisc.edu # 1327839Snilay@cs.wisc.edu implemented_paramTypes = [] 1337839Snilay@cs.wisc.edu for paramType in paramTypes: 1347839Snilay@cs.wisc.edu implemented_paramType = paramType 1357839Snilay@cs.wisc.edu if paramType.isInterface: 1367839Snilay@cs.wisc.edu implements_interface = True 1377839Snilay@cs.wisc.edu implemented_paramType.abstract_ident = paramType["interface"] 1387839Snilay@cs.wisc.edu else: 1397839Snilay@cs.wisc.edu implemented_paramType.abstract_ident = paramType.c_ident 1407839Snilay@cs.wisc.edu 1417839Snilay@cs.wisc.edu implemented_paramTypes.append(implemented_paramType) 1427839Snilay@cs.wisc.edu 1437839Snilay@cs.wisc.edu if implements_interface: 1447839Snilay@cs.wisc.edu implementedMethodId = obj_type.methodIdAbstract(self.proc_name, 1457839Snilay@cs.wisc.edu implemented_paramTypes) 1467839Snilay@cs.wisc.edu else: 1477839Snilay@cs.wisc.edu implementedMethodId = "" 1487839Snilay@cs.wisc.edu 1497839Snilay@cs.wisc.edu if implementedMethodId not in obj_type.methods: 1507839Snilay@cs.wisc.edu self.error("Invalid method call: " \ 1517839Snilay@cs.wisc.edu "Type '%s' does not have a method %s, '%s' nor '%s'", 1527839Snilay@cs.wisc.edu obj_type, self.proc_name, methodId, implementedMethodId) 1537839Snilay@cs.wisc.edu else: 1547839Snilay@cs.wisc.edu # 1557839Snilay@cs.wisc.edu # Replace the methodId with the implementedMethodId found in 1567839Snilay@cs.wisc.edu # the method list. 1577839Snilay@cs.wisc.edu # 1587839Snilay@cs.wisc.edu methodId = implementedMethodId 1597839Snilay@cs.wisc.edu return_type = obj_type.methods[methodId].return_type 1607839Snilay@cs.wisc.edu 1616657Snate@binkert.org if return_type.isInterface: 1626657Snate@binkert.org prefix = "static_cast<%s &>" % return_type.c_ident 1638341Snilay@cs.wisc.edu 1648341Snilay@cs.wisc.edu if str(obj_type) == "AbstractCacheEntry" or \ 1658644Snilay@cs.wisc.edu str(obj_type) == "AbstractEntry" or \ 1668644Snilay@cs.wisc.edu ("interface" in obj_type and ( 1678644Snilay@cs.wisc.edu obj_type["interface"] == "AbstractCacheEntry" or 1688644Snilay@cs.wisc.edu obj_type["interface"] == "AbstractEntry")): 1698341Snilay@cs.wisc.edu prefix = "%s((*(%s))." % (prefix, code) 1708341Snilay@cs.wisc.edu else: 1718341Snilay@cs.wisc.edu prefix = "%s((%s)." % (prefix, code) 1726657Snate@binkert.org 1736657Snate@binkert.org return obj_type, methodId, prefix 1746657Snate@binkert.org 1756657Snate@binkert.org 1766657Snate@binkert.orgclass ClassMethodCallExprAST(MethodCallExprAST): 1776657Snate@binkert.org def __init__(self, slicc, type_ast, proc_name, expr_ast_vec): 1786657Snate@binkert.org s = super(ClassMethodCallExprAST, self) 1796657Snate@binkert.org s.__init__(slicc, proc_name, expr_ast_vec) 1806657Snate@binkert.org 1816657Snate@binkert.org self.type_ast = type_ast 1826657Snate@binkert.org 1836657Snate@binkert.org def __repr__(self): 1846657Snate@binkert.org return "[MethodCallExpr: %r %r]" % (self.proc_name, self.expr_ast_vec) 1856657Snate@binkert.org 1866657Snate@binkert.org def generate_prefix(self, paramTypes): 1876657Snate@binkert.org 1886657Snate@binkert.org # class method call 1896657Snate@binkert.org prefix = "(%s::" % self.type_ast 1906657Snate@binkert.org obj_type = self.type_ast.type 1916657Snate@binkert.org methodId = obj_type.methodId(self.proc_name, paramTypes) 1926657Snate@binkert.org 1936657Snate@binkert.org return obj_type, methodId, prefix 1946657Snate@binkert.org 1956657Snate@binkert.org__all__ = [ "MemberMethodCallExprAST", "ClassMethodCallExprAST" ] 196