def p_unary_expression_4(p): 'unary_expression : unary_operator unary_expression' if p[1] == '+': p[0] = ast.UnaryExp(p[2], ast.UnaryExp.PLUS, line_no=str(p.lineno(1) + __start_line_no - 1)) elif p[1] == '-': p[0] = ast.UnaryExp(p[2], ast.UnaryExp.MINUS, line_no=str(p.lineno(1) + __start_line_no - 1)) elif p[1] == '!': p[0] = ast.UnaryExp(p[2], ast.UnaryExp.LNOT, line_no=str(p.lineno(1) + __start_line_no - 1)) else: err('orio.module.loop.parser internal error: unknown unary operator')
def p_unary_expression_4(p): 'unary_expression : unary_operator unary_expression' if p[1] == '+': p[0] = ast.UnaryExp(p[2], ast.UnaryExp.PLUS, getLineNumber(p.lineno(1))) elif p[1] == '-': p[0] = ast.UnaryExp(p[2], ast.UnaryExp.MINUS, getLineNumber(p.lineno(1))) elif p[1] == '!': p[0] = ast.UnaryExp(p[2], ast.UnaryExp.LNOT, getLineNumber(p.lineno(1))) else: err('orio.module.ortildriver.code_parser internal error: unknown unary operator')
def p_unary_expression_4(p): 'unary_expression : unary_operator unary_expression' if p[1] == '+': p[0] = ast.UnaryExp(p[2], ast.UnaryExp.PLUS) elif p[1] == '-': p[0] = ast.UnaryExp(p[2], ast.UnaryExp.MINUS) elif p[1] == '!': p[0] = ast.UnaryExp(p[2], ast.UnaryExp.LNOT) else: err('orio.module.tilic.code_parser internal error: unknown unary operator')
def p_unary_expression_4(p): "unary_expression : unary_operator unary_expression" if p[1] == "+": p[0] = ast.UnaryExp(p[2], ast.UnaryExp.PLUS) elif p[1] == "-": p[0] = ast.UnaryExp(p[2], ast.UnaryExp.MINUS) elif p[1] == "!": p[0] = ast.UnaryExp(p[2], ast.UnaryExp.LNOT) else: err("orio.module.tilic.code_parser internal error: unknown unary operator")
def p_unary_expression_4(p): 'unary_expression : unary_operator unary_expression' if p[1] == '+': p[0] = ast.UnaryExp(p[2], ast.UnaryExp.PLUS, p.lineno(1) + __start_line_no - 1) elif p[1] == '-': p[0] = ast.UnaryExp(p[2], ast.UnaryExp.MINUS, p.lineno(1) + __start_line_no - 1) elif p[1] == '!': p[0] = ast.UnaryExp(p[2], ast.UnaryExp.LNOT, p.lineno(1) + __start_line_no - 1) else: print 'internal error: unknown unary operator' sys.exit(1)
def p_unary_expression_4(p): "unary_expression : unary_operator unary_expression" if p[1] == "+": p[0] = ast.UnaryExp(p[2], ast.UnaryExp.PLUS, getLineNumber(p.lineno(1))) elif p[1] == "-": p[0] = ast.UnaryExp(p[2], ast.UnaryExp.MINUS, getLineNumber(p.lineno(1))) elif p[1] == "!": p[0] = ast.UnaryExp(p[2], ast.UnaryExp.LNOT, getLineNumber(p.lineno(1))) else: err("orio.module.ortil.code_parser internal error:OrTil: unknown unary operator" )
def p_unary_expression_4(p): "unary_expression : unary_operator unary_expression" if p[1] == "+": p[0] = ast.UnaryExp( p[2], ast.UnaryExp.PLUS, line_no=str(p.lineno(1) + __start_line_no - 1) ) elif p[1] == "-": p[0] = ast.UnaryExp( p[2], ast.UnaryExp.MINUS, line_no=str(p.lineno(1) + __start_line_no - 1) ) elif p[1] == "!": p[0] = ast.UnaryExp( p[2], ast.UnaryExp.LNOT, line_no=str(p.lineno(1) + __start_line_no - 1) ) else: err("orio.module.loop.parser internal error: unknown unary operator")
def p_unary_expression_3(p): "unary_expression : MINUSMINUS unary_expression" p[0] = ast.UnaryExp(p[2], ast.UnaryExp.PRE_DEC)
def p_unary_expression_2(p): "unary_expression : PLUSPLUS unary_expression" p[0] = ast.UnaryExp(p[2], ast.UnaryExp.PRE_INC)
def __normalizeExp(self, exp): """ To convert <list> and <tuple> back to addition and multiplication (respectively), after performing constant folding """ if isinstance(exp, ast.NumLitExp): if exp.val < 0: exp.val *= -1 return ast.UnaryExp(exp, ast.UnaryExp.MINUS) else: return exp elif isinstance(exp, ast.StringLitExp): return exp elif isinstance(exp, ast.IdentExp): return exp elif isinstance(exp, ast.ArrayRefExp): exp.exp = self.__normalizeExp(exp.exp) exp.sub_exp = self.__normalizeExp(exp.sub_exp) return exp elif isinstance(exp, ast.FunCallExp): exp.exp = self.__normalizeExp(exp.exp) exp.args = [self.__normalizeExp(a) for a in exp.args] return exp elif isinstance(exp, ast.UnaryExp): exp.exp = self.__normalizeExp(exp.exp) return exp elif isinstance(exp, ast.BinOpExp): exp.lhs = self.__normalizeExp(exp.lhs) exp.rhs = self.__normalizeExp(exp.rhs) return exp elif isinstance(exp, ast.ParenthExp): exp.exp = self.__normalizeExp(exp.exp) return exp # addition elif isinstance(exp, list): n_exp = [] for e in exp: n_exp.append(self.__normalizeExp(e)) exp = n_exp lhs = exp[0] for e in exp[1:]: if isinstance( e, ast.UnaryExp) and e.op_type == ast.UnaryExp.MINUS: lhs = ast.BinOpExp(lhs, e.exp, ast.BinOpExp.SUB) else: lhs = ast.BinOpExp(lhs, e, ast.BinOpExp.ADD) return lhs # multiplication elif isinstance(exp, tuple): exp = list(exp) n_exp = [] for e in exp: n_exp.append(self.__normalizeExp(e)) exp = n_exp sign = 1 n_exp = [] for e in exp: if isinstance( e, ast.UnaryExp) and e.op_type == ast.UnaryExp.MINUS: n_exp.append(e.exp) sign *= -1 else: n_exp.append(e) exp = n_exp lhs = ast.BinOpExp(exp[0], exp[1], ast.BinOpExp.MUL) for e in exp[2:]: lhs = ast.BinOpExp(lhs, e, ast.BinOpExp.MUL) if sign == -1: return ast.UnaryExp(lhs, ast.UnaryExp.MINUS) return lhs else: err("orio.module.ortildriver.transformation internal error: unknown type of expression: %s" % exp.__class__.__name__)
def p_unary_expression_2(p): 'unary_expression : PLUSPLUS unary_expression' p[0] = ast.UnaryExp(p[2], ast.UnaryExp.PRE_INC, p.lineno(1) + __start_line_no - 1)
def p_postfix_expression_5(p): "postfix_expression : postfix_expression MINUSMINUS" p[0] = ast.UnaryExp(p[1], ast.UnaryExp.POST_DEC, getLineNumber(p.lineno(1)))
def p_postfix_expression_4(p): "postfix_expression : postfix_expression PLUSPLUS" p[0] = ast.UnaryExp(p[1], ast.UnaryExp.POST_INC, getLineNumber(p.lineno(1)))
def p_unary_expression_3(p): "unary_expression : MINUSMINUS unary_expression" p[0] = ast.UnaryExp(p[2], ast.UnaryExp.PRE_DEC, getLineNumber(p.lineno(1)))
def p_unary_expression_2(p): "unary_expression : PLUSPLUS unary_expression" p[0] = ast.UnaryExp(p[2], ast.UnaryExp.PRE_INC, getLineNumber(p.lineno(1)))
def p_postfix_expression_4(p): "postfix_expression : postfix_expression PLUSPLUS" p[0] = ast.UnaryExp( p[1], ast.UnaryExp.POST_INC, line_no=str(p.lineno(1) + __start_line_no - 1) )
def p_postfix_expression_4(p): "postfix_expression : postfix_expression PLUSPLUS" p[0] = ast.UnaryExp(p[1], ast.UnaryExp.POST_INC)
def p_postfix_expression_5(p): "postfix_expression : postfix_expression MINUSMINUS" p[0] = ast.UnaryExp(p[1], ast.UnaryExp.POST_DEC)
def p_postfix_expression_5(p): 'postfix_expression : postfix_expression MINUSMINUS' p[0] = ast.UnaryExp(p[1], ast.UnaryExp.POST_DEC, p.lineno(1) + __start_line_no - 1)
def p_unary_expression_3(p): 'unary_expression : MINUSMINUS unary_expression' p[0] = ast.UnaryExp(p[2], ast.UnaryExp.PRE_DEC, p.lineno(1) + __start_line_no - 1)
def p_unary_expression_2(p): "unary_expression : PLUSPLUS unary_expression" p[0] = ast.UnaryExp( p[2], ast.UnaryExp.PRE_INC, line_no=str(p.lineno(1) + __start_line_no - 1) )
def p_postfix_expression_4(p): 'postfix_expression : postfix_expression PLUSPLUS' p[0] = ast.UnaryExp(p[1], ast.UnaryExp.POST_INC, p.lineno(1) + __start_line_no - 1)
def p_unary_expression_3(p): "unary_expression : MINUSMINUS unary_expression" p[0] = ast.UnaryExp( p[2], ast.UnaryExp.PRE_DEC, line_no=str(p.lineno(1) + __start_line_no - 1) )
def getForLoopInfo(self, stmt): ''' Given a for-loop statement, extract information about its loop structure. Note that the for-loop must be in the following form: for (<id> = <exp>; <id> <= <exp>; <id> += <exp>) <stmt> Subtraction is not considered at the iteration expression for the sake of the implementation simplicity. ''' # get rid of compound statement that contains only a single statement while isinstance(stmt, ast.CompStmt) and len(stmt.stmts) == 1: stmt = stmt.stmts[0] # check if it is a for-loop statement if not isinstance(stmt, ast.ForStmt): err('orio.module.ortil.ast_util: OrTil:%s: not a for-loop statement' % stmt.line_no) # check initialization expression if stmt.init: while True: while isinstance(stmt.init, ast.ParenthExp): stmt.init = stmt.init.exp if (isinstance(stmt.init, ast.BinOpExp) and stmt.init.op_type == ast.BinOpExp.EQ_ASGN): while isinstance(stmt.init.lhs, ast.ParenthExp): stmt.init.lhs = stmt.init.lhs.exp while isinstance(stmt.init.rhs, ast.ParenthExp): stmt.init.rhs = stmt.init.rhs.exp if isinstance(stmt.init.lhs, ast.IdentExp): break err('orio.module.ortil.ast_util:%s: loop initialization expression not in "<id> = <exp>" form' % stmt.init.line_no) # check test expression if stmt.test: while True: while isinstance(stmt.test, ast.ParenthExp): stmt.test = stmt.test.exp if (isinstance(stmt.test, ast.BinOpExp) and stmt.test.op_type in (ast.BinOpExp.LT, ast.BinOpExp.LE)): while isinstance(stmt.test.lhs, ast.ParenthExp): stmt.test.lhs = stmt.test.lhs.exp while isinstance(stmt.test.rhs, ast.ParenthExp): stmt.test.rhs = stmt.test.rhs.exp if isinstance(stmt.test.lhs, ast.IdentExp): break err('orio.module.ortil.ast_util:%s: loop test expression not in "<id> <= <exp>" or ' + '"<id> < <exp>"form' % stmt.test.line_no) # check iteration expression if stmt.iter: while True: while isinstance(stmt.iter, ast.ParenthExp): stmt.iter = stmt.iter.exp if (isinstance(stmt.iter, ast.BinOpExp) and stmt.iter.op_type == ast.BinOpExp.EQ_ASGN): while isinstance(stmt.iter.lhs, ast.ParenthExp): stmt.iter.lhs = stmt.iter.lhs.exp while isinstance(stmt.iter.rhs, ast.ParenthExp): stmt.iter.rhs = stmt.iter.rhs.exp if isinstance(stmt.iter.lhs, ast.IdentExp): if (isinstance(stmt.iter.rhs, ast.BinOpExp) and stmt.iter.rhs.op_type in (ast.BinOpExp.ADD, ast.BinOpExp.SUB)): while isinstance(stmt.iter.rhs.lhs, ast.ParenthExp): stmt.iter.rhs.lhs = stmt.iter.rhs.lhs.exp while isinstance(stmt.iter.rhs.rhs, ast.ParenthExp): stmt.iter.rhs.rhs = stmt.iter.rhs.rhs.exp if (isinstance(stmt.iter.rhs.lhs, ast.IdentExp) and stmt.iter.lhs.name == stmt.iter.rhs.lhs.name): break elif (isinstance(stmt.iter, ast.UnaryExp) and stmt.iter.op_type in (ast.UnaryExp.POST_INC, ast.UnaryExp.PRE_INC, ast.UnaryExp.POST_DEC, ast.UnaryExp.PRE_DEC)): while isinstance(stmt.iter.exp, ast.ParenthExp): stmt.iter.exp = stmt.iter.exp.exp if isinstance(stmt.iter.exp, ast.IdentExp): break err(( 'orio.module.ortil.ast_util:%s: loop iteration expression not in "<id>++" or "<id>--" or ' + '"<id> += <exp>" or "<id> = <id> + <exp>" form') % stmt.iter.line_no) # check if the control expressions are all empty if not stmt.init and not stmt.test and not stmt.iter: err('orio.module.ortil.ast_util:%s: a loop with an empty control expression cannot be handled' % stmt.line_no) # check if the iterator names are all the same init_iname = None test_iname = None iter_iname = None if stmt.init: init_iname = stmt.init.lhs.name if stmt.test: test_iname = stmt.test.lhs.name if stmt.iter: if isinstance(stmt.iter, ast.BinOpExp): iter_iname = stmt.iter.lhs.name else: assert (isinstance( stmt.iter, ast.UnaryExp)), 'internal error:OrTil: not unary' iter_iname = stmt.iter.exp.name inames = [] if init_iname: inames.append(init_iname) if test_iname: inames.append(test_iname) if iter_iname: inames.append(iter_iname) if inames.count(inames[0]) != len(inames): err('orio.module.ortil.ast_util:%s: iterator names across init, test, and iter exps must be the same' % stmt.line_no) # extract for-loop structure information index_id = ast.IdentExp(inames[0]) lbound_exp = None ubound_exp = None stride_exp = None if stmt.init: lbound_exp = stmt.init.rhs.replicate() if stmt.test: if stmt.test.op_type == ast.BinOpExp.LT: ubound_exp = ast.BinOpExp(stmt.test.rhs.replicate(), ast.NumLitExp(1, ast.NumLitExp.INT), ast.BinOpExp.SUB) else: ubound_exp = stmt.test.rhs.replicate() if stmt.iter: if isinstance(stmt.iter, ast.BinOpExp): stride_exp = stmt.iter.rhs.rhs.replicate() if isinstance(stride_exp, ast.BinOpExp): stride_exp = ast.ParenthExp(stride_exp) if stmt.iter.rhs.op_type == ast.BinOpExp.SUB: stride_exp = ast.UnaryExp(stride_exp, ast.UnaryExp.MINUS) elif isinstance(stmt.iter, ast.UnaryExp): if stmt.iter.op_type in (ast.UnaryExp.POST_INC, ast.UnaryExp.PRE_INC): stride_exp = ast.NumLitExp(1, ast.NumLitExp.INT) elif stmt.iter.op_type in (ast.UnaryExp.POST_DEC, ast.UnaryExp.PRE_DEC): stride_exp = ast.NumLitExp(-1, ast.NumLitExp.INT) else: err('orio.module.ortil.ast_util internal error:OrTil: unexpected unary operation type' ) else: err('orio.module.ortil.ast_utilinternal error:OrTil: unexpected type of iteration expression' ) loop_body = stmt.stmt.replicate() for_loop_info = (index_id, lbound_exp, ubound_exp, stride_exp, loop_body) # return the for-loop structure information return for_loop_info
def __foldConstantExp(self, exp, up_sign): """ To perform a simple (not full-fledged) constant folding optimization on the given expression A list is used to represent a k-ary addition. A tuple is used to represent a k-ary multiplication. """ if isinstance(exp, ast.NumLitExp): if up_sign == -1: exp.val *= -1 return exp elif isinstance(exp, ast.StringLitExp): if up_sign == -1: return ast.UnaryExp(exp, ast.UnaryExp.MINUS) return exp elif isinstance(exp, ast.IdentExp): if up_sign == -1: return ast.UnaryExp(exp, ast.UnaryExp.MINUS) return exp elif isinstance(exp, ast.ArrayRefExp): exp.exp = self.__foldConstantExp(exp.exp, 1) exp.sub_exp = self.__foldConstantExp(exp.sub_exp, 1) if up_sign == -1: return ast.UnaryExp(exp, ast.UnaryExp.MINUS) return exp elif isinstance(exp, ast.FunCallExp): exp.exp = self.__foldConstantExp(exp.exp, 1) exp.args = [self.__foldConstantExp(a, 1) for a in exp.args] if up_sign == -1: return ast.UnaryExp(exp, ast.UnaryExp.MINUS) return exp elif isinstance(exp, ast.UnaryExp): if exp.op_type == ast.UnaryExp.MINUS: up_sign *= -1 return self.__foldConstantExp(exp.exp, up_sign) elif isinstance(exp, ast.BinOpExp): if exp.op_type in (ast.BinOpExp.ADD, ast.BinOpExp.SUB): if exp.op_type == ast.BinOpExp.ADD: if up_sign == -1: lhs_sign = -1 rhs_sign = -1 else: lhs_sign = 1 rhs_sign = 1 else: if up_sign == -1: lhs_sign = -1 rhs_sign = 1 else: lhs_sign = 1 rhs_sign = -1 lhs = self.__foldConstantExp(exp.lhs, lhs_sign) rhs = self.__foldConstantExp(exp.rhs, rhs_sign) ops = [] for e in [lhs, rhs]: if isinstance(e, list): ops.extend(e) else: ops.append(e) add_num = 0 n_ops = [] for o in ops: if isinstance(o, ast.NumLitExp): add_num += o.val else: n_ops.append(o) ops = n_ops if add_num != 0: ops.append(ast.NumLitExp(add_num, ast.NumLitExp.INT)) if len(ops) == 0: return ast.NumLitExp(0, ast.NumLitExp.INT) elif len(ops) == 1: return ops[0] else: return ops elif exp.op_type == ast.BinOpExp.MUL: lhs = self.__foldConstantExp(exp.lhs, up_sign) rhs = self.__foldConstantExp(exp.rhs, 1) ops1 = [] ops2 = [] if isinstance(lhs, list): ops1.extend(lhs) else: ops1.append(lhs) if isinstance(rhs, list): ops2.extend(rhs) else: ops2.append(rhs) ops = [] for o1 in ops1: if isinstance(o1, tuple): o1 = list(o1) else: o1 = [o1] for o2 in ops2: if isinstance(o2, tuple): o2 = list(o2) else: o2 = [o2] o1 = [o.replicate() for o in o1] o2 = [o.replicate() for o in o2] o = [] mul_num = 1 for i in o1 + o2: if isinstance(i, ast.NumLitExp): mul_num *= i.val else: o.append(i) if mul_num != 0: if mul_num != 1: o.insert( 0, ast.NumLitExp(mul_num, ast.NumLitExp.INT)) if len(o) == 0: ops.append(ast.NumLitExp(1, ast.NumLitExp.INT)) elif len(o) == 1: ops.append(o[0]) else: ops.append(tuple(o)) add_num = 0 n_ops = [] for o in ops: if isinstance(o, ast.NumLitExp): add_num += o.val else: n_ops.append(o) ops = n_ops if add_num != 0: ops.append(ast.NumLitExp(add_num, ast.NumLitExp.INT)) if len(ops) == 0: return ast.NumLitExp(0, ast.NumLitExp.INT) elif len(ops) == 1: return ops[0] else: return ops else: err("orio.module.ortildriver.transformation: constant folding cannot handle binary operations other " + "than +,-,*") elif isinstance(exp, ast.ParenthExp): return self.__foldConstantExp(exp.exp, up_sign) else: err("orio.module.ortildriver.transformation internal error: unknown type of expression: %s" % exp.__class__.__name__)