⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inline.c

📁 cg编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
    return lExpr;
} // ConvertLocalReferences

/*
 * ExpandInlineFunction() - Expand a function inline by duplicating it's statements.
 *
 */

static void ExpandInlineFunction(InlineFunData *fFunData, Symbol *funSymb, Symbol *retSymb, expr *fActuals)
{
    stmt *body;
    stmt *nStmt;
    expr *lExpr, *lActual;
    Symbol *lFormal;
    StmtList newStmts;

    // Bump function counter:

    fFunData->funInlineIndex = (*fFunData->nextFunInlineIndex)++;

    // Duplicate the body of the function:

    body = DuplicateStatementTree(funSymb->details.fun.statements);

    // Change return statements into assignments:

    body = PostApplyToStatements(ConvertReturnStatement, body, retSymb, 0);

    // Add numbered copies of expanded function's local variables to current scope,
    // and convert any references in copied body of function to new symbols:

    SetSymbolFlagsList(ScopeList/*GlobalScope*/, NOT_DUPLICATED);
    SetSymbolFlags(fFunData->masterScope->symbols, IN_MASTER_SCOPE);
    SetSymbolFlags(fFunData->globalScope->symbols, IN_GLOBAL_SCOPE);
    SetSymbolFlags(fFunData->superGlobalScope->symbols, IN_SUPER_GLOBAL_SCOPE);

    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    // !!! BEGIN !!! Temporary patch for "texobj" parameters!!! Don't assign!!!
    #define TYPE_BASE_TEXOBJ_FP30   (TYPE_BASE_FIRST_USER + 2)
    lFormal = funSymb->details.fun.params;
    lActual = fActuals;
    while (lFormal) {
        if (GetBase(lFormal->type) == TYPE_BASE_TEXOBJ_FP30) {
            assert(lActual->bin.left->common.kind == SYMB_N);
            lFormal->tempptr = (void *) lActual->bin.left->sym.symbol;
            lFormal->flags = ALREADY_DUPLICATED;
        }
        lFormal = lFormal->next;
        lActual = lActual->bin.right;
    }
    // !!! END !!! Temporary patch for "texobj" parameters!!! Don't assign!!!
    //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    PostApplyToExpressions(ConvertLocalReferences, body, fFunData, 0);

    // Assign actual parameter expressions to parameters:

    newStmts.first = newStmts.last = NULL;
    lFormal = funSymb->details.fun.params;
    lActual = fActuals;
    while (lFormal) {
        assert(lActual->common.kind == BINARY_N);
        assert(lActual->bin.op == FUN_ARG_OP);
        if (((GetQualifiers(lFormal->type) & TYPE_QUALIFIER_IN) ||
             !(GetQualifiers(lFormal->type) & TYPE_QUALIFIER_OUT)) &&
            //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
            //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
            //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
            // !!! BEGIN !!! Temporary patch for "texobj" parameters!!! Don't assign!!!
             (GetBase(lFormal->type) != TYPE_BASE_TEXOBJ_FP30) &&
            // !!! Temporary patch for "texobj" parameters!!! Don't assign!!!
            //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
            //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
             1)
        {
            lExpr = (expr *) NewSymbNode(VARIABLE_OP, lFormal);
            lExpr = ConvertLocalReferences(lExpr, fFunData, 0);
            nStmt = NewSimpleAssignmentStmt(Cg->pLastSourceLoc, lExpr, lActual->bin.left, 1);
            AppendStatements(&newStmts, nStmt);
        }
        lFormal = lFormal->next;
        lActual = lActual->bin.right;
    }
    AppendStatements(&newStmts, body);

    // Build assignment statements to copy "out" param's final values to actual parameters:

    lFormal = funSymb->details.fun.params;
    lActual = fActuals;
    while (lFormal) {
        if (GetQualifiers(lFormal->type) & TYPE_QUALIFIER_OUT) {
            lExpr = (expr *) NewSymbNode(VARIABLE_OP, lFormal);
            lExpr = ConvertLocalReferences(lExpr, fFunData, 0);
            nStmt = NewSimpleAssignmentStmt(Cg->pLastSourceLoc, lActual->bin.left, lExpr, 0);
            AppendStatements(&newStmts, nStmt);
        }
        lFormal = lFormal->next;
        lActual = lActual->bin.right;
    }

    // Recursively expands calls in newly inlined finction:

    body = ExpandInlineFunctionCalls(funSymb->details.fun.locals, newStmts.first, fFunData);

    // Do some more stuff here...

    // Append the new statements:

    AppendStatements(&fFunData->statements, body);

} // ExpandInlineFunction

/*
 * ExpandInlineFunctionCallsNode() - Expand inline function calls in an expression.
 *
 */

static expr *ExpandInlineFunctionCallsNode(expr *fExpr, void *arg1, int arg2)
{
#define TEMP_ROOT      "$temp"

    InlineFunData *lFunData = (InlineFunData *) arg1;
    Symbol *lSymb, *retSymb;
    expr *lExpr;
    Type *funType, *retType;
    int vname;

    switch (fExpr->common.kind) {
    case DECL_N:
    case SYMB_N:
    case CONST_N:
    case UNARY_N:
        break;
    case BINARY_N:
        if (fExpr->bin.op == FUN_CALL_OP) {
            lExpr = fExpr->bin.left;
            if (lExpr->common.kind == SYMB_N) {
                lSymb = lExpr->sym.symbol;
                assert(IsFunction(lSymb));
                if (IsInline(lSymb)) {
                    funType = lSymb->type;
                    retType = funType->fun.rettype;
                    if (!IsVoid(retType)) {
                        vname = GetNumberedAtom(TEMP_ROOT, (*lFunData->nextTempIndex)++, 4, '\0');
                        retSymb = DefineVar(&lSymb->loc, lFunData->masterScope, vname, retType);
                    } else {
                        retSymb = NULL;
                    }
                    if (Cg->options.Comments) {
                        AddComment(lFunData, Cg->pLastSourceLoc, "Begin inline function");
                        AddComment(lFunData, Cg->pLastSourceLoc, GetAtomString(atable, lSymb->name));
                    }
                    ExpandInlineFunction(lFunData, lSymb, retSymb, fExpr->bin.right);
                    if (Cg->options.Comments) {
                        AddComment(lFunData, Cg->pLastSourceLoc, "End inline function");
                        AddComment(lFunData, Cg->pLastSourceLoc, GetAtomString(atable, lSymb->name));
                    }
                    if (retSymb) {
                        fExpr = (expr *) NewSymbNode(VARIABLE_OP, retSymb);
                    } else {
                        fExpr = NULL; // function returning void
                    }
                } else {
                    // Not done yet:  Must continue to traverse call tree to find other
                    // functions that are called and inline their calls as needed.
                    // Or some such stuff...
                }
            }
        }
    case TRINARY_N:
        break;
    default:
        assert(!"bad kind to ExpandInlineFunctionCallsNode()");
        break;
    }
    return fExpr;
} // ExpandInlineFunctionCallsNode

/*
 * ExpandInlineFunctionCallsStmt() - Expand inline function calls in a statement.
 *
 */

static stmt *ExpandInlineFunctionCallsStmt(stmt *fStmt, void *arg1, int arg2)
{
    InlineFunData *lFunData = (InlineFunData *) arg1;

    lFunData->statements.first = NULL;
    lFunData->statements.last = NULL;
    PostApplyToExpressionsLocal(ExpandInlineFunctionCallsNode, fStmt, arg1, arg2);
    if (lFunData->statements.first) {
        lFunData->statements.last->commonst.next = fStmt;
        fStmt = lFunData->statements.first;
    }
    lFunData->statements.first = NULL;
    lFunData->statements.last = NULL;
    return fStmt;
} // ExpandInlineFunctionCallsStmt

/*
 * ExpandInlineFunctionCalls() - Recursively walk a program'm call graph from main
 *         expanding function calls that have the attribute "inline".
 *
 * Assumes no recursion in inlined functions.
 *
 */

stmt *ExpandInlineFunctionCalls(Scope *fscope, stmt *body, InlineFunData *fFunData)
{
    int funcount = 0, tempcount = 0;
    InlineFunData lFunData;
    stmt *lStmt;

    if (fFunData) {
        lFunData.superGlobalScope = fFunData->superGlobalScope;
        lFunData.globalScope = fFunData->globalScope;
        lFunData.masterScope = fFunData->masterScope;
        lFunData.calleeScope = fscope;
        lFunData.nextFunInlineIndex = fFunData->nextFunInlineIndex;
        lFunData.nextTempIndex = fFunData->nextTempIndex;
        lFunData.funInlineIndex = fFunData->funInlineIndex;
    } else {
        lFunData.superGlobalScope = fscope->parent->parent;
        lFunData.globalScope = fscope->parent;
        lFunData.masterScope = fscope;
        lFunData.calleeScope = NULL;
        lFunData.nextFunInlineIndex = &funcount;
        lFunData.nextTempIndex = &tempcount;
        lFunData.funInlineIndex = 999;
    }
    lFunData.funIndex = 0;
    lFunData.statements.first = NULL;
    lFunData.statements.last = NULL;
    lFunData.scratch = NULL;

    lStmt = PostApplyToStatements(ExpandInlineFunctionCallsStmt, body, &lFunData, 0);
    return lStmt;

} // ExpandInlineFunctionCalls

///////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////// End of inline.c ///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -