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

📄 compile.c

📁 cg编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
} // DeconstructMatricesExpr

/*
 * DeconstructMatricesStmt()
 *
 */

stmt *DeconstructMatricesStmt(stmt *fStmt, void *arg1, int arg2)
{
    MData *mdata;

    mdata = (MData *) arg1;
    mdata->statements.first = mdata->statements.last = NULL;
    PostApplyToExpressionsLocal(DeconstructMatricesExpr, fStmt, arg1, arg2);
    if (mdata->statements.first) {
        mdata->statements.last->commonst.next = fStmt;
        fStmt = mdata->statements.first;
    }
    return fStmt;
} // DeconstructMatricesStmt

/*
 * DeconstructMatrices()
 *
 */

stmt *DeconstructMatrices(Scope *fscope, stmt *fStmt)
{
    MData mdata;

    InternalError(Cg->pLastSourceLoc, ERROR___NO_MATRIX_DECONSTRUCTION);
    mdata.scope = fscope;
    mdata.numtemps = 0;
    fStmt = PreApplyToStatements(DeconstructMatricesStmt, fStmt, &mdata, 0);
    return fStmt;
} // DeconstructMatrices

///////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// Flatten Struct Assignments ////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

/*
 * AssignStructMembers() - Assign individual memebers of one struct to another.
 *
 */

static void AssignStructMembers(StmtList *fStatements, int fop, Type *fType, expr *varExpr,
                                expr *valExpr, expr *condExpr, int VectorCond)
{
    expr *lExpr, *mExpr, *rExpr;
    int base, len, len2;
    Symbol *lSymb;
    Type *lType;
    stmt *lStmt;

    lSymb = fType->str.members->symbols;
    while (lSymb) {
        len = len2 = 0;
        lType = lSymb->type;
        if (IsScalar(lType) || IsVector(lType, &len) || IsMatrix(lType, &len, &len2)) {
            base = GetBase(lType);
            lExpr = DupExpr(varExpr);
            mExpr = GenMember(lSymb);
            lExpr = GenMemberSelector(lExpr, mExpr);
            rExpr = DupExpr(valExpr);
            mExpr = GenMember(lSymb);
            rExpr = GenMemberSelector(rExpr, mExpr);
            if (condExpr != NULL) {
                if (len2 > 0) {
                    lExpr = GenCondGenAssign(lExpr, rExpr, condExpr);
                } else if (len > 0) {
                    if (VectorCond) {
                        lExpr = GenCondSVAssign(lExpr, rExpr, condExpr, base, len);
                    } else {
                        lExpr = GenCondVAssign(lExpr, rExpr, condExpr, base, len);
                    }
                } else {
                    lExpr = GenCondSAssign(lExpr, rExpr, condExpr, base);
                }
                lStmt = (stmt *) NewExprStmt(Cg->pLastSourceLoc, lExpr);
            } else {
                if (len2 > 0) {
                    lExpr = GenMAssign(lExpr, rExpr, base, len, len2);
                } else if (len > 0) {
                    lExpr = GenVAssign(lExpr, rExpr, base, len);
                } else {
                    lExpr = GenSAssign(lExpr, rExpr, base);
                }
                lStmt = (stmt *) NewExprStmt(Cg->pLastSourceLoc, lExpr);
            }
            AppendStatements(fStatements, lStmt);
        } else {
            switch (GetCategory(lType)) {
            case TYPE_CATEGORY_STRUCT:
                lExpr = DupExpr(varExpr);
                mExpr = GenMember(lSymb);
                lExpr = GenMemberSelector(lExpr, mExpr);
                rExpr = DupExpr(valExpr);
                mExpr = GenMember(lSymb);
                rExpr = GenMemberSelector(rExpr, mExpr);
                AssignStructMembers(fStatements, fop, lType, lExpr, rExpr, condExpr, VectorCond);
                break;
            case TYPE_CATEGORY_ARRAY:
                // XYZZY Not Done Yet XYZZY //
                break;
            default:
                break;
            }
        }
        lSymb = lSymb->next;
    }
} // AssignStructMembers

/*
 * FlattenStructAssignment() - Convert struct assignments into multiple assignments of members.
 *
 */

stmt *FlattenStructAssignment(stmt *fStmt, void *arg1, int flevel)
{
    stmt *rStmt;
    expr *eExpr, *lExpr, *rExpr, *cExpr;
    int lop, lsubop;
    StmtList lStatements;
    Type *lType;

    if (fStmt) {
        switch (fStmt->commonst.kind) {
        case EXPR_STMT:
            eExpr = fStmt->exprst.exp;
            if (IsAssignSVOp(eExpr)) {
                lType = eExpr->bin.type;
                if (IsStruct(lType)) {
                    if (IsAssignCondSVOp(eExpr)) {
                        lop = eExpr->tri.op;
                        lExpr = eExpr->tri.arg1;
                        cExpr = eExpr->tri.arg2;
                        rExpr = eExpr->tri.arg3;
                        if (IsScalar(cExpr->common.type)) {
                            AssignStructMembers(&lStatements, lop, lType, lExpr, rExpr, cExpr, 0);
                        } else {
                            AssignStructMembers(&lStatements, lop, lType, lExpr, rExpr, cExpr, 1);
                        }
                        rStmt = lStatements.first;
                    } else {
                        lop = eExpr->bin.op;
                        lExpr = eExpr->bin.left;
                        rExpr = eExpr->bin.right;
                        lsubop = eExpr->bin.subop;
                        lStatements.first = NULL;
                        lStatements.last = NULL;
                        AssignStructMembers(&lStatements, lop, lType, lExpr, rExpr, NULL, 0);
                        rStmt = lStatements.first;
                    }
                } else {
                    rStmt = fStmt;
                }
            } else {
                rStmt = fStmt;
            }
            break;
        default:
            rStmt = fStmt;
            break;
        }
    } else {
        rStmt = fStmt;
    }
    return rStmt;
} // FlattenStructAssignment

/*
 * FlattenStructAssignments() - Convert struct assignments into multiple member assignments.
 *  
 */

static stmt *FlattenStructAssignments(Scope *fScope, stmt *fStmt)
{
    stmt *lStmt;

    lStmt = PreApplyToStatements(FlattenStructAssignment, fStmt, NULL, 0);
    return lStmt;
} // FlattenStructAssignments


///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////// Flatten If Statements ///////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

/*
 * FlattenIfStatementsStmt() - Convert if statements into conditional assignments.
 *
 *     if (A > B)
 *         C = D;
 *     else
 *         E = F;
 *
 * becomes:
 *
 *     $if1 = A > B;
 *     C@@($if1) = D;
 *     E@@(!$if1) = F;
 *
 * and:
 *
 *     if (A > B)
 *         if (C > D)
 *             E = F;
 *         else
 *             G = H;
 *     else
 *         if (J > K)
 *             L = M;
 *         else
 *             N = P;
 *
 * becomes:
 *
 *     $if1 = A > B;
 *     $ife2 = C > D;
 *     $if2 = $if1 && $ife2;
 *     E@@($if2) = F;
 *     $if2 = $if1 && !$ife2;
 *     G@@($if2) = H;
 *     $ife2 = J > K;
 *     $if2 = !$if1 && $ife2;
 *     L@@($if2) = M;
 *     $if2 = !$if1 && !$ife2;
 *     N@@($if2) = P;
 *
 * Existing conditional assignments:
 *
 *     A@@XZ = B;
 *     C@@(D) = E;
 *
 * become:
 *
 *     A@@({ $if1, 0, $if1, 0 }) = B;
 *     C@@($if1@xyzw && D) = E;     or:        C@@($if1 && D) = E;
 *
 * Issues:
 *
 *   1) "out" parameters to function calls: not a problem if function calls
 *      have been previously inlined.
 *   2) Assumes "chained" assignments have already been split into simple assignments.
 *   3) Assumes all large asignments (structs, matrices, vectors > 4) have been eliminated.
 *
 */

typedef struct FlattenIf_Rec {
    Scope *funScope;
    Symbol *ifSymbTotal;  // Current combined if value: "$if2" for level 2, NULL for level 0.
    Symbol *ifSymbParent; // Enclosing if's combined value: "$if1" for level 2, NULL for level <= 1.
    Symbol *ifSymbLocal;  // Current level's simple if value:  "$ife2" for level 2
} FlattenIf;

static stmt *FlattenIfStatementsStmt(stmt *fStmt, void *arg1, int flevel)
{
#define IF_ROOT "$if"
#define IF_ROOT_E "$iflocal"

    stmt *rStmt, *lStmt, *nStmt;
    expr *eExpr, *lExpr, *rExpr, *ifvar, *nExpr, *mExpr, *tExpr;
    int level, lop, lsubop, nop, nsubop, vname, mask, len, base, ii;
    FlattenIf *lFlatten;
    Symbol *lSymbTotal, *lSymbLocal, *ifSymbTotalSave, *ifSymbParentSave;
    StmtList lStatements;
    Type *lType;

    if (fStmt) {
        lFlatten = (FlattenIf *) arg1;
        level = flevel >= 0 ? flevel : -flevel;
        switch (fStmt->commonst.kind) {
        case IF_STMT:
            
            // Find $if1 variable(s) for this level:

            vname = GetNumberedAtom(IF_ROOT, level + 1, 1, '\0');
            lSymbTotal = LookUpSymbol(lFlatten->funScope, vname);
            if (!lSymbTotal) {
                lSymbTotal = DefineVar(&fStmt->commonst.loc, lFlatten->funScope, vname, BooleanType);
            }
            if (level > 0) {
                vname = GetNumberedAtom(IF_ROOT_E, level + 1, 1, '\0');
                lSymbLocal = LookUpSymbol(lFlatten->funScope, vname);
                if (!lSymbLocal) {
                    lSymbLocal = DefineVar(&fStmt->commonst.loc, lFlatten->funScope, vname, BooleanType);
                }
            } else {
                lSymbLocal = lSymbTotal;
            }

            // Create assignment statement for local expression:

            lStatements.first = NULL;
            lStatements.last = NULL;
            lExpr = GenSymb(lSymbLocal);
            lExpr = GenBoolAssign(lExpr, fStmt->ifst.cond);
            lStmt = (stmt *) NewExprStmt(&fStmt->commonst.loc, lExpr);
            AppendStatements(&lStatements, lStmt);

            ifSymbTotalSave = lFlatten->ifSymbTotal;
            ifSymbParentSave = lFlatten->ifSymbParent;
            lFlatten->ifSymbParent = lFlatten->ifSymbLocal;
            lFlatten->ifSymbLocal = lSymbLocal;
            lFlatten->ifSymbTotal = lSymbTotal;

            // Compute effective Boolean expression if necessary:

            if (level > 0) {
                lExpr = GenSymb(lFlatten->ifSymbParent);
                if (flevel == -1) {
                    // Top level if's don't create a negated value:
                    lExpr = GenBoolNot(lExpr);
                }
                rExpr = GenSymb(lSymbLocal);
                rExpr = GenBoolAnd(lExpr, rExpr);
                lExpr = GenSymb(lFlatten->ifSymbTotal);
                lExpr = GenBoolAssign(lExpr, rExpr);
                lStmt = (stmt *) NewExprStmt(&fStmt->commonst.loc, lExpr);
                AppendStatements(&lStatements, lStmt);
            }

            // Walk sub-statements and transform assignments into conditional assignments:

            lStmt = fStmt->ifst.thenstmt;
            fStmt->ifst.thenstmt = NULL;
            while (lStmt) {
                nStmt = lStmt->commonst.next;
                lStmt->commonst.next = NULL;
                lStmt = FlattenIfStatementsStmt(lStmt, arg1, level + 1);
                AppendStatements(&lStatements, lStmt);
                lStmt = nStmt;
            }
            if (fStmt->ifst.elsestmt) {

                // Compute effective Boolean expression if necessary:

                if (level > 0) {
                    lExpr = GenSymb(lFlatten->ifSymbParent);
                    if (flevel == -1)
                        lExpr = GenBoolNot(lExpr);
                    rExpr = GenSymb(lSymbLocal);
                    rExpr = GenBoolNot(rExpr);
                    rExpr = GenBoolAnd(lExpr, rExpr);
                    lExpr = GenSymb(lFlatten->ifSymbTotal);
                    lExpr = GenBoolAssign(lExpr, rExpr);
                    lStmt = (stmt *) NewExprStmt(&fStmt->commonst.loc, lExpr);
                    AppendStatements(&lStatements, lStmt);
                }
                lStmt = fStmt->ifst.elsestmt;
                fStmt->ifst.elsestmt = NULL;
                while (lStmt) {
                    nStmt = lStmt->commonst.next;
                    lStmt->commonst.next = NULL;
                    lStmt = FlattenIfStatementsStmt(lStmt, arg1, -(level + 1));
                    AppendStatements(&lStatements, lStmt);
                    lStmt = nStmt;
                }
            }
            lFlatten->ifSymbTotal = ifSymbTotalSave;
            lFlatten->ifSymbLocal = lFlatten->ifSymbParent;
            lFlatten->ifSymbParent = ifSymbParentSave;
            rStmt = lStatements.first;
            break;
        case EXPR_STMT:
            if (level > 0) {
                eExpr = fStmt->exprst.exp;
                if (IsAssignSVOp(eExpr)) {
                    lExpr = eExpr->bin.left;
                    rExpr = eExpr->bin.right;
                    lop = eExpr->bin.op;
                    lsubop = eExpr->bin.subop;
                    lType = eExpr->bin.type;
                    ifvar = GenSymb(lFlatten->ifSymbTotal);
                    if (flevel == -1)
                        ifvar = GenBoolNot(ifvar);
                    if (lop == ASSIGN_MASKED_KV_OP) {
                        mask = SUBOP_GET_MASK(lsubop);
                        len = SUBOP_GET_S(lsubop);
                        base = SUBOP_GET_T(lsubop);
                        // Create vector of $if/FALSE values:
                        mExpr = NULL;
                        for (ii = 0; ii < len; ii++) {
                            if (mask & 1) {
                                tExpr = GenSymb(lFlatten->ifSymbTotal);
                            } else {
                                tExpr = GenBoolConst(0);
                            }
                            mExpr = GenExprList(mExpr, tExpr, BooleanType);
                            mask >>= 1;
                        }
                        ifvar = (expr *) NewUnopSubNode(VECTOR_V_OP, SUBOP_V(len, TYPE_BASE_BOOLEAN), mExpr);
                        ifvar->un.type = GetStandardType(TYPE_BASE_BOOLEAN, len, 0);
                        nop = ASSIGN_COND_V_OP;
                        nsubop = SUBOP_V(len, base);
                    } else {
                        // Normal assign.  Convert it to simple conditional assignment:
                        switch (lop) {
                        case ASSIGN_OP:
                            nop = ASSIGN_COND_OP;
                            nsubop = lsubop;
                            break;
                        case ASSIGN_V_OP:
                            nop = ASSIGN_COND_SV_OP;
                            nsubop = lsubop;
                            break;
                        case ASSIGN_GEN_OP:
                            nop = ASSIGN_COND_GEN_OP;
                            nsubop = lsubop;
                            break;
                        default:
                            assert(0);
                            break;
                        }
                    }
                    nExpr = (expr *) NewTriopSubNode(nop, nsubop, lExpr, ifvar, rExpr);
                

⌨️ 快捷键说明

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