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

📄 check.c

📁 cg编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
            lType = fExpr->sym.type;
            category = GetCategory(lType);
            domain = GetDomain(lSymb->type);
            qualifiers = GetQualifiers(lSymb->type);
            if (lSymb->properties & SYMB_NEEDS_BINDING) {
                // This is a non-static global and has not yet been bound
                gname = 0;
                BindDefaultSemantic(lSymb, category, gname);
            }
        }
        break;
        default:
        break;
    }
    return fExpr;
} // CheckForGlobalUniformReferences

/*
 * CheckForReturnStmts() - Issue an error if a return statement is encountered.
 *
 */

static stmt *CheckForReturnStmts(stmt *fStmt, void *arg1, int arg2)
{
    if (fStmt->commonst.kind == RETURN_STMT)
        SemanticError(&fStmt->commonst.loc, ERROR___RETURN_NOT_LAST);
    return fStmt;
} // CheckForReturnStmts

/*
 * CheckForUnsupportedStatements() - Issue an error if an unsupported statement is encountered.
 *
 */

static stmt *CheckForUnsupportedStatements(stmt *fStmt, void *arg1, int arg2)
{
    if (fStmt) {
        if (!Cg->theHAL->CheckStatement(&fStmt->commonst.loc, fStmt))
            ++(int *) arg1;
    }
    return fStmt;
} // CheckForUnsupportedStatements

/*
 * BindUnboundUniformMembers() - Bind any members that are currently unbound.  Must be a
 *         uniform pseudo-connector.
 */

static void BindUnboundUniformMembers(SymbolList *fList)
{
    Symbol *lSymb;
    Binding *lBind;

    while (fList != NULL) {
        lSymb = fList->symb;
        if (lSymb) {
            lBind = lSymb->details.var.bind;
            if (lBind && !(lBind->none.properties & BIND_IS_BOUND)) {
                if (!Cg->theHAL->BindUniformUnbound(&lSymb->loc, lSymb, lBind)) {
                    SemanticWarning(&lSymb->loc, WARNING_S_CANT_BIND_UNIFORM_VAR,
                                    GetAtomString(atable, lSymb->name));
                }
            }
        }
        fList = fList->next;
    }
} // BindUnboundUniformMembers

/*
 * CheckFunctionDefinition()
 *
 */

static int CheckFunctionDefinition(Scope *fScope, Symbol *funSymb, int IsProgram)
{
    int count = 0;
    stmt *lStmt;

    if (funSymb->flags == NOT_CHECKED) {
        funSymb->flags = BEING_CHECKED;
        lStmt = funSymb->details.fun.statements;
        CheckParamsAndLocals(funSymb, IsProgram);
        if (IsProgram) {
            struct BuildReturnAssignments lstr;

            lstr.globalScope = fScope;
            lstr.program = funSymb;
            lStmt = PreApplyToStatements(BuildProgramReturnAssignments, lStmt, &lstr, 0);
        }
        ApplyToTopExpressions(CheckExpressionForUndefinedFunctions, lStmt, &count, 0);
        PostApplyToExpressions(CheckNodeForUnsupportedOperators, lStmt, &count, 0);
        PostApplyToExpressions(CheckForUnsupportedVariables, lStmt, &count, 0);
        PostApplyToExpressions(CheckForGlobalUniformReferences, lStmt, 0, 0);
        PreApplyToStatements(CheckForUnsupportedStatements, lStmt, &count, 0);
        if (Cg->theHAL->GetCapsBit(CAPS_RESTRICT_RETURNS)) {
            while (lStmt) {
                if (lStmt->commonst.next)
                    CheckForReturnStmts(lStmt, NULL, 0);
                PostApplyToChildStatements(CheckForReturnStmts, lStmt, NULL, 0);
                lStmt = lStmt->commonst.next;
            }
        }
        funSymb->flags = ALREADY_CHECKED;
    }
    return count;
} // CheckFunctionDefinition

/*
 * CheckFunctionDefinitions() - Walk a function and check for errors:
 *     1. see if any functions it calls aren't defined,
 *     2. detect recursion,
 *     3. detect early return statements,
 *     4. check for unsupported operators in the target profile.
 *     5. Build uniform and varying pseudo structs: $vin. $vout. $main, $global
 */

int CheckFunctionDefinitions(SourceLoc *loc, Scope *fScope, Symbol *program)
{
    int count;

    SetSymbolFlagsList(fScope, NOT_CHECKED);
    count = CheckFunctionDefinition(fScope, program, 1);
    SetStructMemberOffsets(Cg->theHAL->varyingIn->type);
    SetStructMemberOffsets(Cg->theHAL->varyingOut->type);
    BindUnboundUniformMembers(Cg->theHAL->uniformParam);
    BindUnboundUniformMembers(Cg->theHAL->uniformGlobal);
    return count;
} // CheckFunctionDefinitions

///////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////// Check Connector Usage ////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

/*
 * CheckConnectorUsage() - Check connector usage for illegal references.
 *
 */

static expr *CheckConnectorUsage(expr *fExpr, void *arg1, int arg2)
{
    int WeAreWriting = arg2;
    Symbol *lSymb;
    expr *lExpr;
    Binding *lBind;

    lExpr = fExpr;
    if (fExpr) {
        switch (fExpr->common.kind) {
        case SYMB_N:
            lSymb = lExpr->sym.symbol;
            if (lSymb->properties & SYMB_IS_CONNECTOR_REGISTER) {
                if (!(lSymb->properties & (SYMB_CONNECTOR_CAN_WRITE | SYMB_CONNECTOR_CAN_READ))) {
                    SemanticError(Cg->pLastSourceLoc, ERROR_S_CMEMBER_NOT_VISIBLE,
                                  GetAtomString(atable, lSymb->name));
                } else {
                    if (WeAreWriting) {
                        if (!(lSymb->properties & SYMB_CONNECTOR_CAN_WRITE)) {
                            SemanticError(Cg->pLastSourceLoc, ERROR_S_CMEMBER_NOT_WRITABLE,
                                          GetAtomString(atable, lSymb->name));
                        }
                    } else {
                        if (!(lSymb->properties & SYMB_CONNECTOR_CAN_READ)) {
                            SemanticError(Cg->pLastSourceLoc, ERROR_S_CMEMBER_NOT_READABLE,
                                          GetAtomString(atable, lSymb->name));
                        }
                    }
                }
            }
            break;
        case CONST_N:
            break;
        case UNARY_N:
            fExpr->un.arg = CheckConnectorUsage(fExpr->un.arg, arg1, arg2);
            break;
        case BINARY_N:
            switch (fExpr->bin.op) {
            case MEMBER_SELECTOR_OP:
                lExpr = fExpr->bin.right;
                if (lExpr && lExpr->common.kind == SYMB_N && WeAreWriting) {
                    // Mark connector registers that are written.
                    lSymb = lExpr->sym.symbol;
                    lBind = lSymb->details.var.bind;
                    if (lBind)
                        lBind->none.properties |= BIND_WAS_WRITTEN;
                }
                fExpr->bin.left = CheckConnectorUsage(fExpr->bin.left, arg1, arg2);
                fExpr->bin.right = CheckConnectorUsage(fExpr->bin.right, arg1, arg2);
                lExpr = fExpr;
                break;
            case ASSIGN_OP:
            case ASSIGN_V_OP:
            case ASSIGN_GEN_OP:
            case ASSIGN_MASKED_KV_OP:
                fExpr->bin.left = CheckConnectorUsage(fExpr->bin.left, arg1, 1);
                fExpr->bin.right = CheckConnectorUsage(fExpr->bin.right, arg1, 0);
                break;
            case FUN_ARG_OP:
                arg2 = SUBOP_GET_MASK(fExpr->bin.subop) & 2 ? 1 : 0;
                fExpr->bin.left = CheckConnectorUsage(fExpr->bin.left, arg1, arg2);
                fExpr->bin.right = CheckConnectorUsage(fExpr->bin.right, arg1, 0);
                break;
            default:
                fExpr->bin.left = CheckConnectorUsage(fExpr->bin.left, arg1, arg2);
                fExpr->bin.right = CheckConnectorUsage(fExpr->bin.right, arg1, arg2);
                break;
            }
            break;
        case TRINARY_N:
            switch (fExpr->bin.op) {
            case ASSIGN_COND_OP:
            case ASSIGN_COND_V_OP:
            case ASSIGN_COND_SV_OP:
            case ASSIGN_COND_GEN_OP:
                fExpr->tri.arg1 = CheckConnectorUsage(fExpr->tri.arg1, arg1, 1);
                fExpr->tri.arg2 = CheckConnectorUsage(fExpr->tri.arg2, arg1, 0);
                fExpr->tri.arg3 = CheckConnectorUsage(fExpr->tri.arg3, arg1, 0);
                break;
            default:
                fExpr->tri.arg1 = CheckConnectorUsage(fExpr->tri.arg1, arg1, arg2);
                fExpr->tri.arg2 = CheckConnectorUsage(fExpr->tri.arg2, arg1, arg2);
                fExpr->tri.arg3 = CheckConnectorUsage(fExpr->tri.arg3, arg1, arg2);
                break;
            }
            break;
        default:
            FatalError("bad kind to CheckConnectorUsage()");
            break;
        }
    } else {
        lExpr = NULL;
    }
    return lExpr;
} // CheckConnectorUsage

/*
 * CheckConnectorUsageMain() - Check connector usage for illegal references.
 *
 */

void CheckConnectorUsageMain(Symbol *program, stmt *fStmt)
{
    Symbol *outConn, *lSymb;
    Type *cType;
    int len, cid;
    Binding *lBind;

    outConn = Cg->theHAL->varyingOut;
    if (!outConn || !outConn->type)
        return;
    cType = outConn->type;
    cid = cType->str.variety;
    len = Cg->theHAL->GetConnectorRegister(cid, 1, -1, NULL);
    ApplyToTopExpressions(CheckConnectorUsage, fStmt, NULL, 0);
    lSymb = Cg->theHAL->varyingOut->type->str.members->symbols;
    // This doesn't work!  The output value is always written by the return statement!  RSG
    while (lSymb) {
        lBind = lSymb->details.var.bind;
        if (lBind) {
            if ((lBind->none.properties & BIND_WRITE_REQUIRED) &&
                !(lBind->none.properties & BIND_WAS_WRITTEN))
            {
                SemanticWarning(&program->loc, WARNING_S_CMEMBER_NOT_WRITTEN,
                    GetAtomString(atable, lBind->conn.rname));
            }
        }
        lSymb = lSymb->next;
    }
} // CheckConnectorUsageMain

///////////////////////////////////////////////////////////////////////////////////////////////

/*
 * CheckForHiddenVaryingReferences() - Check for references to varying l-values with the
 *         "hidden" semantic bit set.  These shouldn't be referenced in this profile.
 */

expr *CheckForHiddenVaryingReferences(expr *fExpr, void *arg1, int arg2)
{
    Binding *lBind;
    Symbol *lSymb;
    Type *lType;

    switch (fExpr->common.kind) {
    case SYMB_N:
        if (fExpr->sym.op == VARIABLE_OP || fExpr->sym.op == MEMBER_OP) {
            lSymb = fExpr->sym.symbol;
            if (lSymb->kind == VARIABLE_S) {
                lType = fExpr->sym.type;
                lBind = lSymb->details.var.bind;
                if (lBind && lBind->none.properties & BIND_HIDDEN) {
                    SemanticError(Cg->pLastSourceLoc, ERROR_SS_VAR_SEMANTIC_NOT_VISIBLE,
                        GetAtomString(atable, lSymb->name),
                        GetAtomString(atable, lBind->conn.rname));
                }
            }
        }
        break;
        default:
        break;
    }
    return fExpr;
} // CheckForHiddenVaryingReferences

///////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////// End of check.c ///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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