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

📄 compile.c

📁 nVidia开发的图形语言 Cg
💻 C
📖 第 1 页 / 共 5 页
字号:
            break;
        case DISCARD_STMT:
            lStmt = (stmt *) NewDiscardStmt(&fStmt->commonst.loc, fStmt->discardst.cond);
            break;
        case COMMENT_STMT:
            lStmt = (stmt *) NewCommentStmt(&fStmt->commonst.loc,
                                            GetAtomString(atable, fStmt->commentst.str));
            break;
        default:
            lStmt = fStmt;
            assert(!"DuplicateStatement() - not yet finished");
            break;
        }
        PreApplyToExpressions(DuplicateNode, lStmt, arg1, arg2);
    } else {
        lStmt = NULL;
    }
    return lStmt;
} // DuplicateStatement

///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////// Named Constant Substitution /////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

/*
 * ConvertNamedConstantsExpr() - Replace references to names constants with a const node.
 *
 */

expr *ConvertNamedConstantsExpr(expr *fExpr, void *arg1, int arg2)
{
    Symbol *lSymb;
    Type *lType;
    expr *lExpr;
    int base;

    lExpr = fExpr;
    if (fExpr) {
        switch (fExpr->common.kind) {
        case SYMB_N:

            // The only named constants are "true" and "false":

            lSymb = fExpr->sym.symbol;
            lType = lSymb->type;
            if (lSymb->kind == CONSTANT_S) {
                if (IsScalar(lType)) {
                    base = GetBase(lType);
                    switch (base) {
                    case TYPE_BASE_BOOLEAN:
                        lExpr = (expr *) NewBConstNode(BCONST_OP, lSymb->details.con.value,
                                                       TYPE_BASE_BOOLEAN);
                        break;
                    }
                }
            }
            break;
        case CONST_N:
        case UNARY_N:
        case BINARY_N:
        case TRINARY_N:
            break;
        default:
            FatalError("bad kind to ConvertNamedConstantsExpr()");
            break;
        }
    } else {
        lExpr = NULL;
    }
    return lExpr;
} // ConvertNamedConstantsExpr

///////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// Remove Empty Statements //////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

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

stmt *RemoveEmptyStatementsStmt(stmt *fStmt, void *arg1, int arg2)
{
    if (fStmt->commonst.kind == EXPR_STMT) {
        if (!fStmt->exprst.exp)
            fStmt = NULL;
    }
    return fStmt;
} // RemoveEmptyStatementsStmt

///////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// Remove Empty Statements //////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

typedef struct DebugFunctionData_Rec {
    Symbol *color;
    Symbol *flag;
    Symbol *outConnector;
    Symbol *COLSymb;
} DebugFunctionData;

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

stmt *ConvertDebugCallsStmt(stmt *fStmt, void *arg1, int arg2)
{
    DebugFunctionData *lDebugData = (DebugFunctionData *) arg1;
    expr *eExpr, *sExpr, *lExpr, *mExpr, *bExpr, *rExpr;
    stmt *lStmt, *mStmt;
    Symbol *lSymb;

    if (fStmt->commonst.kind == EXPR_STMT) {

        // Look for a call to "debug(float4)":

        eExpr = fStmt->exprst.exp;
        if (eExpr && eExpr->common.kind == BINARY_N && eExpr->bin.op == FUN_BUILTIN_OP) {
            sExpr = eExpr->bin.left;
            if (sExpr->common.kind == SYMB_N) {
                lSymb = sExpr->sym.symbol;
#define BUILTIN_GROUP_NV30FP_DBG     0
                if (lSymb->details.fun.group == BUILTIN_GROUP_NV30FP_DBG &&
                    lSymb->details.fun.index == 0x444)
                {
                    if (arg2) {

                        // Turn: "debug(arg);" statements into:
                        //
                        //     $debug-color@@(!$debug-set) = arg;
                        //     $debug-set = true;

                        rExpr = eExpr->bin.right->bin.left;
                        mExpr = GenSymb(lDebugData->flag);
                        mExpr = GenBoolNot(mExpr);
                        lExpr = GenSymb(lDebugData->color);
                        lExpr = GenCondSVAssign(lExpr, mExpr, rExpr, TYPE_BASE_FLOAT, 4);
                        lStmt = (stmt *) NewExprStmt(Cg->pLastSourceLoc, lExpr);
                        lExpr = GenSymb(lDebugData->flag);
                        rExpr = GenBoolConst(1);
                        lExpr = GenBoolAssign(lExpr, rExpr);
                        mStmt = (stmt *) NewExprStmt(Cg->pLastSourceLoc, lExpr);
                        lStmt->commonst.next = mStmt;
                        fStmt = lStmt;
                    } else {

                        // Eliminate: "debug(arg);" statements:

                        fStmt = NULL;
                    }
                }
            }
        }
    } else if (arg2 && fStmt->commonst.kind == RETURN_STMT) {
        rExpr = GenSymb(lDebugData->color);
        mExpr = GenSymb(lDebugData->flag);
        lExpr = GenSymb(lDebugData->outConnector);
        bExpr = GenMember(lDebugData->COLSymb);
        lExpr = GenMemberSelector(lExpr, bExpr);
        lExpr = GenCondSVAssign(lExpr, mExpr, rExpr, TYPE_BASE_FLOAT, 4);
        lStmt = (stmt *) NewExprStmt(Cg->pLastSourceLoc, lExpr);
        lStmt->commonst.next = fStmt;
        fStmt = lStmt;
    }
    return fStmt;
} // ConvertDebugCallsStmt

/*
 * ConvertDebugCalls() - Convert calls to debug to either assignments to global variables, or
 *         delete them, depending on the value of DebugFlag.  Also defines global variables.
 *
 */

stmt *ConvertDebugCalls(SourceLoc *loc, Scope *fScope, stmt *fStmt, int DebugFlag)
{
    Symbol *debugColor, *debugSet;
    DebugFunctionData debugData;
    expr *lExpr, *rExpr;
    stmt *lStmt, *rStmt;
    StmtList lStatements;
    Type *lType;
    int vname, COLname;
    float fdata[4];

    rStmt = fStmt;
    if (DebugFlag) {
        lStatements.first = lStatements.last = NULL;
        //outputSymb = fScope->outConnector;

        // 1) Define global vars used by "-debug" mode:
        //
        //     float $debug-color[4];
        //     bool  $debug-set = 0.0f;

        vname = AddAtom(atable, "$debug-color");
        lType = GetStandardType(TYPE_BASE_FLOAT, 4, 0);
        debugColor = DefineVar(loc, fScope, vname, lType);
        vname = AddAtom(atable, "$debug-set");
        debugSet = DefineVar(loc, fScope, vname, BooleanType);
        lExpr = GenSymb(debugSet);
        rExpr = GenBoolConst(0);
        lExpr = GenBoolAssign(lExpr, rExpr);
        lStmt = (stmt *) NewExprStmt(loc, lExpr);
        AppendStatements(&lStatements, lStmt);

        // 1A) Must initialize $debug-color to something or else the code generator
        //     gets all bent out of shape:
        //
        //     $debug-color = { 0.0f, 0.0f, 0.0f, .0f };

        fdata[0] = fdata[1] = fdata[2] = fdata[3] = 0.0f;
        rExpr = GenFConstV(fdata, 4, TYPE_BASE_FLOAT);
        lExpr = GenSymb(debugColor);
        lExpr = GenVAssign(lExpr, rExpr, TYPE_BASE_FLOAT, 4);
        lStmt = (stmt *) NewExprStmt(loc, lExpr);
        AppendStatements(&lStatements, lStmt);

        // 2) Expand calls to "debug(float4);" into the following code:
        //
        //     $debug-color@@(!$debug-set) = float4;
        //     $debug-set = true;

        debugData.color = debugColor;
        debugData.flag = debugSet;
        debugData.outConnector = Cg->theHAL->varyingOut;
        assert(debugData.outConnector);
        COLname = AddAtom(atable, "COL");
        lType = debugData.outConnector->type;
        assert(IsCategory(lType, TYPE_CATEGORY_CONNECTOR));
        debugData.COLSymb = LookUpLocalSymbol(lType->str.members, COLname);

        // 3) And add the following statement to the end of the program (i.e. before each
        //    "return" statement):
        //
        //     output.COL@@($debug-set) = $debug-color;

        lStmt = PostApplyToStatements(ConvertDebugCallsStmt, fStmt, &debugData, 1);
        AppendStatements(&lStatements, lStmt);

        rStmt = lStatements.first;
    } else {
        rStmt = PostApplyToStatements(ConvertDebugCallsStmt, fStmt, NULL, 0);
    }
    return rStmt;
} // ConvertDebugCalls

///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Flatten Chained Assignment Statements ///////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

int IsAssignSVOp(expr *fExpr)
{
    int lop;

    if (fExpr) {
        if (fExpr->common.kind == BINARY_N) {
            lop = fExpr->bin.op;
            if (lop == ASSIGN_OP || lop == ASSIGN_V_OP || lop == ASSIGN_GEN_OP ||
                lop == ASSIGN_MASKED_KV_OP)
            {
                return 1;
            }
        }
    }
    return 0;
} // IsAssignSVOp

int IsAssignCondSVOp(expr *fExpr)
{
    int lop;

    if (fExpr) {
        if (fExpr->common.kind == TRINARY_N) {
            lop = fExpr->tri.op;
            if (lop == ASSIGN_COND_OP || lop == ASSIGN_COND_V_OP || lop == ASSIGN_COND_SV_OP ||
                lop == ASSIGN_COND_GEN_OP)
            {
                return 1;
            }
        }
    }
    return 0;
} // IsAssignCondSVOp

int IsCastOp(expr *fExpr)
{
    int lop;

    if (fExpr) {
        if (fExpr->common.kind == UNARY_N) {
            lop = fExpr->un.op;
            if (lop == CAST_CS_OP || lop == CAST_CV_OP || lop == CAST_CM_OP)
            {
                return 1;
            }
        }
    }
    return 0;
} // IsCastOp

/*
 * NewTmp() - Return a symbol expression for a temp symbol that can
 * hold the value of fExpr.
 *
 */

symb *NewTmp(const expr *fExpr)
{
    Symbol *tmpSym;
    Type *tmpType = DupType(fExpr->common.type);
    tmpType->co.properties &= ~(TYPE_DOMAIN_MASK | TYPE_QUALIFIER_MASK);
    tmpSym = UniqueSymbol(CurrentScope, tmpType, VARIABLE_S);
    return NewSymbNode(VARIABLE_OP, tmpSym);
} // NewTmp

/*
 * FlattenChainedAssignmentsStmt() - Transform chained assignments into multiple simple
 *         assignments.
 *
 *  float3 A, C;  half B;
 *
 *  Simle case:
 *
 *  A = B = C;    (which is equivanemt to:)     A = (float) ( B = (half) C ) ;
 *
 *      =                        =               =
 *    /   \                    /   \           /   \
 *  A      (f)     >>-->>     B     (h)      A      (f)
 *            \                        \               \
 *              =                        C               B'
 *            /   \
 *          B      (h)
 *                    \
 *                      C
 *
 *  where B' is a duplicate of B.
 *
 *  If B contains any function calls, they must be hoisted prior to this step.
 *  
 */

stmt *FlattenChainedAssignmentsStmt(stmt *fStmt, void *arg1, int arg2)
{
    stmt *bStmt, *rStmt;
    expr *assigna, *assignb;
    expr *pb, **ppassignb;

    if (fStmt->commonst.kind == EXPR_STMT) {
        rStmt = fStmt;
        assigna = fStmt->exprst.exp;
        while (1) {
            if (IsAssignSVOp(assigna)) {
                ppassignb = &assigna->bin.right;
            } else if (IsAssignCondSVOp(assigna)) {
                ppassignb = &assigna->tri.arg3;
            } else {
                break;
            }
            // Traverse list of type casts, if any:
            while (IsCastOp(*ppassignb))
                ppassignb = &((**ppassignb).un.arg);
            if (IsAssignSVOp(*ppassignb)) {
                pb = (**ppassignb).bin.left;
            } else if (IsAssignCondSVOp(*ppassignb)) {
                pb = (**ppassignb).tri.arg1;
            } else {
                break;
            }
            assignb = *ppassignb;
            bStmt = (stmt *) NewExprStmt(&fStmt->commonst.loc, assignb);
            *ppassignb = PreApplyToNodes(DuplicateNode, pb, arg1, arg2);
            bStmt->commonst.next = rStmt;
            rStmt = bStmt;
            assigna = assignb;
        }
    } else {
        rStmt = fStmt;
    }
    return rStmt;
} // FlattenChainedAssignmentsStmt

/*
 * PutIndexEpxrsInTemps() - Puts all array indicies in temps and
 * builds a comma list of assignments of the indices to the
 * temporaries.
 *
 * A[e1]...[eN] -> t1 = e1, ..., tN = eN : A[t1]...[tN]
 */
expr *PutIndexEpxrsInTemps(expr *fExpr)
{
    expr *assignments = NULL;
    expr *assign;
    expr *tmp;
    
    assert(IsArrayIndex(fExpr));
    if (IsArrayIndex(fExpr->bin.left))
        assignments = PutIndexEpxrsInTemps(fExpr->bin.left);

    tmp = (expr *) NewTmp(fExpr->bin.right);
    assign = NewSimpleAssignment(Cg->pLastSourceLoc, DupNode(tmp), fExpr->bin.right, 0);

    if (!assignments)
        assignments = assign;
    else
        assignments = (expr *) NewBinopNode(COMMA_OP, assignments, assign);

    if (IsArrayIndex(fExpr->bin.right))
        assignments = (expr *) NewBinopNode(COMMA_OP, assignments,
                                            PutIndexEpxrsInTemps(fExpr->bin.right));

    fExpr->bin.right = tmp;
    return assignments;
} // PutIndexEpxrsInTemps

///////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////// Expand Increment/Decrement Expressions ////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

/*

⌨️ 快捷键说明

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