📄 check.c
字号:
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 + -