OperatorExprAST.py revision 11016:bc759340631f
12SN/A# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
21762SN/A# Copyright (c) 2009 The Hewlett-Packard Development Company
32SN/A# All rights reserved.
42SN/A#
52SN/A# Redistribution and use in source and binary forms, with or without
62SN/A# modification, are permitted provided that the following conditions are
72SN/A# met: redistributions of source code must retain the above copyright
82SN/A# notice, this list of conditions and the following disclaimer;
92SN/A# redistributions in binary form must reproduce the above copyright
102SN/A# notice, this list of conditions and the following disclaimer in the
112SN/A# documentation and/or other materials provided with the distribution;
122SN/A# neither the name of the copyright holders nor the names of its
132SN/A# contributors may be used to endorse or promote products derived from
142SN/A# this software without specific prior written permission.
152SN/A#
162SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu
282665Ssaidi@eecs.umich.edufrom slicc.ast.ExprAST import ExprAST
292665Ssaidi@eecs.umich.edufrom slicc.symbols import Type
302SN/A
312SN/Aclass InfixOperatorExprAST(ExprAST):
326216Snate@binkert.org    def __init__(self, slicc, left, op, right):
336216Snate@binkert.org        super(InfixOperatorExprAST, self).__init__(slicc)
342SN/A
354046Sbinkertn@umich.edu        self.left = left
366216Snate@binkert.org        self.op = op
374046Sbinkertn@umich.edu        self.right = right
387680Sgblack@eecs.umich.edu
398232Snate@binkert.org    def __repr__(self):
408232Snate@binkert.org        return "[InfixExpr: %r %s %r]" % (self.left, self.op, self.right)
416216Snate@binkert.org
424776Sgblack@eecs.umich.edu    def generate(self, code):
432SN/A        lcode = self.slicc.codeFormatter()
443064Sgblack@eecs.umich.edu        rcode = self.slicc.codeFormatter()
452SN/A
462SN/A        ltype = self.left.generate(lcode)
472SN/A        rtype = self.right.generate(rcode)
484776Sgblack@eecs.umich.edu
492SN/A        # Figure out what the input and output types should be
502SN/A        if self.op in ("==", "!=", ">=", "<=", ">", "<"):
514776Sgblack@eecs.umich.edu            output = "bool"
527720Sgblack@eecs.umich.edu            if (ltype != rtype):
537720Sgblack@eecs.umich.edu                self.error("Type mismatch: left and right operands of " +
545784Sgblack@eecs.umich.edu                           "operator '%s' must be the same type. " +
557720Sgblack@eecs.umich.edu                           "left: '%s', right: '%s'",
562SN/A                           self.op, ltype, rtype)
572SN/A        else:
582SN/A            expected_types = []
595784Sgblack@eecs.umich.edu            output = None
605784Sgblack@eecs.umich.edu
614046Sbinkertn@umich.edu            if self.op in ("&&", "||"):
625866Sksewell@umich.edu                # boolean inputs and output
632SN/A                expected_types = [("bool", "bool", "bool")]
642SN/A            elif self.op in ("<<", ">>"):
654776Sgblack@eecs.umich.edu                expected_types = [("int", "int", "int"),
664776Sgblack@eecs.umich.edu                                  ("Cycles", "int", "Cycles")]
674776Sgblack@eecs.umich.edu            elif self.op in ("+", "-", "*", "/"):
685034Smilesck@eecs.umich.edu                expected_types = [("int", "int", "int"),
695034Smilesck@eecs.umich.edu                                  ("Cycles", "Cycles", "Cycles"),
704776Sgblack@eecs.umich.edu                                  ("Tick", "Tick", "Tick"),
712SN/A                                  ("Cycles", "int", "Cycles"),
724776Sgblack@eecs.umich.edu                                  ("Scalar", "int", "Scalar"),
734776Sgblack@eecs.umich.edu                                  ("int", "bool", "int"),
747720Sgblack@eecs.umich.edu                                  ("bool", "int", "int"),
757720Sgblack@eecs.umich.edu                                  ("int", "Cycles", "Cycles")]
764776Sgblack@eecs.umich.edu            else:
778232Snate@binkert.org                self.error("No operator matched with {0}!" .format(self.op))
784776Sgblack@eecs.umich.edu
792SN/A            for expected_type in expected_types:
804776Sgblack@eecs.umich.edu                left_input_type = self.symtab.find(expected_type[0], Type)
814776Sgblack@eecs.umich.edu                right_input_type = self.symtab.find(expected_type[1], Type)
822SN/A
838232Snate@binkert.org                if (left_input_type == ltype) and (right_input_type == rtype):
844776Sgblack@eecs.umich.edu                    output = expected_type[2]
854074Sbinkertn@umich.edu
864776Sgblack@eecs.umich.edu            if output == None:
877720Sgblack@eecs.umich.edu                self.error("Type mismatch: operands ({0}, {1}) for operator " \
884776Sgblack@eecs.umich.edu                           "'{2}' failed to match with the expected types" .
894776Sgblack@eecs.umich.edu                           format(ltype, rtype, self.op))
902SN/A
917811Ssteve.reinhardt@amd.com        # All is well
922SN/A        fix = code.nofix()
936216Snate@binkert.org        code("($lcode ${{self.op}} $rcode)")
94        code.fix(fix)
95        return self.symtab.find(output, Type)
96
97class PrefixOperatorExprAST(ExprAST):
98    def __init__(self, slicc, op, operand):
99        super(PrefixOperatorExprAST, self).__init__(slicc)
100
101        self.op = op
102        self.operand = operand
103
104    def __repr__(self):
105        return "[PrefixExpr: %s %r]" % (self.op, self.operand)
106
107    def generate(self, code):
108        opcode = self.slicc.codeFormatter()
109        optype = self.operand.generate(opcode)
110
111        # Figure out what the input and output types should be
112        opmap = {"!": "bool", "-": "int", "++": "Scalar"}
113        if self.op in opmap:
114            output = opmap[self.op]
115            type_in_symtab = self.symtab.find(opmap[self.op], Type)
116            if (optype != type_in_symtab):
117                self.error("Type mismatch: right operand of " +
118                           "unary operator '%s' must be of type '%s'. ",
119                           self.op, type_in_symtab)
120        else:
121            self.error("Invalid prefix operator '%s'",
122                       self.op)
123
124        # All is well
125        fix = code.nofix()
126        code("(${{self.op}} $opcode)")
127        code.fix(fix)
128
129        return self.symtab.find(output, Type)
130