16657SN/A# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
26657SN/A# Copyright (c) 2009 The Hewlett-Packard Development Company
36657SN/A# All rights reserved.
46657SN/A#
56657SN/A# Redistribution and use in source and binary forms, with or without
66657SN/A# modification, are permitted provided that the following conditions are
76657SN/A# met: redistributions of source code must retain the above copyright
86657SN/A# notice, this list of conditions and the following disclaimer;
96657SN/A# redistributions in binary form must reproduce the above copyright
106657SN/A# notice, this list of conditions and the following disclaimer in the
116657SN/A# documentation and/or other materials provided with the distribution;
126657SN/A# neither the name of the copyright holders nor the names of its
136657SN/A# contributors may be used to endorse or promote products derived from
146657SN/A# this software without specific prior written permission.
156657SN/A#
166657SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176657SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186657SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196657SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206657SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216657SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226657SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236657SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246657SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256657SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266657SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276657SN/A
286657SN/Afrom slicc.ast.ExprAST import ExprAST
296657SN/Afrom slicc.symbols import Type
306657SN/A
316657SN/Aclass InfixOperatorExprAST(ExprAST):
326657SN/A    def __init__(self, slicc, left, op, right):
336657SN/A        super(InfixOperatorExprAST, self).__init__(slicc)
346657SN/A
356657SN/A        self.left = left
366657SN/A        self.op = op
376657SN/A        self.right = right
386657SN/A
396657SN/A    def __repr__(self):
406657SN/A        return "[InfixExpr: %r %s %r]" % (self.left, self.op, self.right)
416657SN/A
426657SN/A    def generate(self, code):
436999SN/A        lcode = self.slicc.codeFormatter()
446999SN/A        rcode = self.slicc.codeFormatter()
456657SN/A
466657SN/A        ltype = self.left.generate(lcode)
476657SN/A        rtype = self.right.generate(rcode)
486657SN/A
496657SN/A        # Figure out what the input and output types should be
509499SN/A        if self.op in ("==", "!=", ">=", "<=", ">", "<"):
516657SN/A            output = "bool"
526657SN/A            if (ltype != rtype):
536657SN/A                self.error("Type mismatch: left and right operands of " +
546657SN/A                           "operator '%s' must be the same type. " +
556657SN/A                           "left: '%s', right: '%s'",
566657SN/A                           self.op, ltype, rtype)
576657SN/A        else:
589499SN/A            expected_types = []
599499SN/A            output = None
609499SN/A
616657SN/A            if self.op in ("&&", "||"):
626657SN/A                # boolean inputs and output
639499SN/A                expected_types = [("bool", "bool", "bool")]
649499SN/A            elif self.op in ("<<", ">>"):
659499SN/A                expected_types = [("int", "int", "int"),
669499SN/A                                  ("Cycles", "int", "Cycles")]
679499SN/A            elif self.op in ("+", "-", "*", "/"):
689499SN/A                expected_types = [("int", "int", "int"),
699499SN/A                                  ("Cycles", "Cycles", "Cycles"),
7011016Snilay@cs.wisc.edu                                  ("Tick", "Tick", "Tick"),
719499SN/A                                  ("Cycles", "int", "Cycles"),
729692Snilay@cs.wisc.edu                                  ("Scalar", "int", "Scalar"),
7310521Snilay@cs.wisc.edu                                  ("int", "bool", "int"),
7410521Snilay@cs.wisc.edu                                  ("bool", "int", "int"),
759499SN/A                                  ("int", "Cycles", "Cycles")]
766657SN/A            else:
779499SN/A                self.error("No operator matched with {0}!" .format(self.op))
786657SN/A
799499SN/A            for expected_type in expected_types:
809499SN/A                left_input_type = self.symtab.find(expected_type[0], Type)
819499SN/A                right_input_type = self.symtab.find(expected_type[1], Type)
826657SN/A
839499SN/A                if (left_input_type == ltype) and (right_input_type == rtype):
849499SN/A                    output = expected_type[2]
856657SN/A
869499SN/A            if output == None:
879499SN/A                self.error("Type mismatch: operands ({0}, {1}) for operator " \
889499SN/A                           "'{2}' failed to match with the expected types" .
899499SN/A                           format(ltype, rtype, self.op))
906657SN/A
916657SN/A        # All is well
926657SN/A        fix = code.nofix()
936657SN/A        code("($lcode ${{self.op}} $rcode)")
946657SN/A        code.fix(fix)
956657SN/A        return self.symtab.find(output, Type)
969692Snilay@cs.wisc.edu
979692Snilay@cs.wisc.educlass PrefixOperatorExprAST(ExprAST):
989692Snilay@cs.wisc.edu    def __init__(self, slicc, op, operand):
999692Snilay@cs.wisc.edu        super(PrefixOperatorExprAST, self).__init__(slicc)
1009692Snilay@cs.wisc.edu
1019692Snilay@cs.wisc.edu        self.op = op
1029692Snilay@cs.wisc.edu        self.operand = operand
1039692Snilay@cs.wisc.edu
1049692Snilay@cs.wisc.edu    def __repr__(self):
1059692Snilay@cs.wisc.edu        return "[PrefixExpr: %s %r]" % (self.op, self.operand)
1069692Snilay@cs.wisc.edu
1079692Snilay@cs.wisc.edu    def generate(self, code):
1089692Snilay@cs.wisc.edu        opcode = self.slicc.codeFormatter()
1099692Snilay@cs.wisc.edu        optype = self.operand.generate(opcode)
1109692Snilay@cs.wisc.edu
11110965Sdavid.hashe@amd.com        # Figure out what the input and output types should be
11210965Sdavid.hashe@amd.com        opmap = {"!": "bool", "-": "int", "++": "Scalar"}
11310965Sdavid.hashe@amd.com        if self.op in opmap:
11410965Sdavid.hashe@amd.com            output = opmap[self.op]
11510965Sdavid.hashe@amd.com            type_in_symtab = self.symtab.find(opmap[self.op], Type)
11610965Sdavid.hashe@amd.com            if (optype != type_in_symtab):
11710965Sdavid.hashe@amd.com                self.error("Type mismatch: right operand of " +
11810965Sdavid.hashe@amd.com                           "unary operator '%s' must be of type '%s'. ",
11910965Sdavid.hashe@amd.com                           self.op, type_in_symtab)
12010965Sdavid.hashe@amd.com        else:
12110965Sdavid.hashe@amd.com            self.error("Invalid prefix operator '%s'",
12210965Sdavid.hashe@amd.com                       self.op)
12310965Sdavid.hashe@amd.com
12410965Sdavid.hashe@amd.com        # All is well
1259692Snilay@cs.wisc.edu        fix = code.nofix()
1269692Snilay@cs.wisc.edu        code("(${{self.op}} $opcode)")
1279692Snilay@cs.wisc.edu        code.fix(fix)
1289692Snilay@cs.wisc.edu
12910965Sdavid.hashe@amd.com        return self.symtab.find(output, Type)
130