示例#1
0
def Canonicalize(ast: c_ast.FileAST, meta_info: meta.MetaInfo,
                 skip_constant_casts):
    global_id_gen = common.UniqueId()

    for node in ast:
        if isinstance(node, c_ast.FuncDef):
            CanonicalizeFun(node, meta_info)

    meta_info.CheckConsistency(ast)

    transform_arrayref.ConvertConvertAddressTakenScalarsToArray(ast, meta_info)
    meta_info.CheckConsistency(ast)

    transform_arrayref.ConvertArrayIndexToPointerDereference(ast, meta_info)
    transform_arrayref.SimplifyAddressExpressions(ast, meta_info)
    meta_info.CheckConsistency(ast)

    ConvertCompoundAssignment(ast, meta_info, global_id_gen)

    # This should go last so that we do not have worry to mess this
    # up in other phases.
    AddExplicitCasts(ast, ast, meta_info, skip_constant_casts)

    transform_rename.LiftStaticAndExternToGlobalScope(ast, meta_info,
                                                      global_id_gen)
    meta_info.CheckConsistency(ast)

    ConfirmAbsenceOfUnsupportedFeatures(ast, ast)
示例#2
0
def ConvertConvertAddressTakenScalarsToArray(ast, meta_info: meta.MetaInfo):
    """
    Rewrite address taken scalar vars as one element arrays

    After this transform we can keep all scalars in registers.
    """

    def IsAddressTakenScalarOrGlobalScalar(node, parent):
        if isinstance(node, c_ast.Decl) and IsScalarType(node.type):
            # return isinstance(parent, c_ast.FileAST)
            return (isinstance(parent, c_ast.FileAST) or
                    "static" in node.storage)

        if not isinstance(node, c_ast.UnaryOp): return False
        if node.op != "&": return False
        if not isinstance(node.expr, c_ast.ID): return False
        type = meta_info.type_links[node.expr]
        return IsScalarType(type)

    candidates = common.FindMatchingNodesPreOrder(ast, ast, IsAddressTakenScalarOrGlobalScalar)
    ids = set()
    for node, _ in candidates:
        if isinstance(node, c_ast.UnaryOp):
            ids.add(meta_info.sym_links[node.expr])
        else:
            ids.add(node)
    one = c_ast.Constant("int", "1")
    meta_info.type_links[one] = meta.INT_IDENTIFIER_TYPE

    for node in ids:
        assert isinstance(node, c_ast.Decl)
        node.type = c_ast.ArrayDecl(node.type, one, [])
        if node.init:
            node.init = c_ast.InitList([node.init])

    def IsAddressTakenScalarId(node, _):
        return isinstance(node, c_ast.ID) and meta_info.sym_links[node] in ids

    candidates = common.FindMatchingNodesPreOrder(ast, ast, IsAddressTakenScalarId)

    for node, parent in candidates:
        original_type = meta_info.type_links[node]
        meta_info.type_links[node] = meta.GetTypeForDecl(meta_info.sym_links[node].type)
        array_ref = c_ast.UnaryOp("*", node)
        meta_info.type_links[array_ref] = original_type
        common.ReplaceNode(parent, node, array_ref)
示例#3
0
def ConvertCompoundAssignment(ast: c_ast.Node, meta_info: meta.MetaInfo, _id_gen):
    """This works best after ConvertArrayIndexToPointerDereference"""
    candidates = common.FindMatchingNodesPostOrder(ast, ast, lambda n, _: isinstance(n, c_ast.Assignment))
    for assign, parent in candidates:
        if assign.op == "=":
            continue
        lvalue = assign.lvalue
        if isinstance(lvalue, c_ast.ID):
            node = c_ast.BinaryOp(assign.op[:-1], lvalue, assign.rvalue)
            meta_info.type_links[node] = meta_info.type_links[assign]
            assign.rvalue = node
            assign.op = "="
        elif isinstance(lvalue, c_ast.UnaryOp) and lvalue.op == "*":
            # TODO
            pass
示例#4
0
def CanonicalizeFun(ast: c_ast.FuncDef, meta_info: meta.MetaInfo):
    id_gen = common.UniqueId()
    ConvertPostToPreIncDec(ast)
    meta_info.CheckConsistency(ast)

    ConvertPreIncDecToCompoundAssignment(ast, meta_info)
    meta_info.CheckConsistency(ast)

    ConvertWhileLoop(ast, id_gen)
    ConvertForLoop(ast, id_gen)
    meta_info.CheckConsistency(ast)

    EliminateExpressionLists(ast)

    transform_if.IfTransform(ast, id_gen)
    transform_if.ShortCircuitIfTransform(ast, id_gen)
    meta_info.CheckConsistency(ast)

    transform_label.PruneUselessLabels(ast)

    transform_rename.UniquifyLocalVars(ast, meta_info, id_gen)
    FixNodeRequiringBoolInt(ast, meta_info)
    meta_info.CheckConsistency(ast)

    # if return type is void
    decl: c_ast.FuncDecl = ast.decl

    type_decl: c_ast.TypeDecl = decl.type.type
    if not isinstance(type_decl.type, c_ast.IdentifierType):
        return
    if "void" not in type_decl.type.names:
        return

    if ast.body.block_items is None:
        ast.body.block_items = []
    stmts = ast.body.block_items

    if not stmts or not isinstance(stmts[-1], c_ast.Return):
        ret = c_ast.Return(None)
        meta_info.type_links[ret] = meta.GetTypeForDecl(ast.decl.type)
        stmts.append(ret)