📄 support.c
字号:
int DiffParamTypes, DiffParamQualifiers, DiffParamCount, DiffReturnType;
TypeList *oldArgType, *newArgType;
Symbol *lSymb;
int index, group, OK;
if (fSymb) {
if (GetCategory(fSymb->type) != TYPE_CATEGORY_FUNCTION) {
SemanticError(loc, ERROR_S_NAME_ALREADY_DEFINED, GetAtomString(atable, atom));
lSymb = fSymb;
} else {
OK = 1;
lSymb = fSymb;
while (lSymb) {
if (GetCategory(fSymb->type) != TYPE_CATEGORY_FUNCTION) {
InternalError(loc, ERROR_S_SYMBOL_TYPE_NOT_FUNCTION,
GetAtomString(atable, lSymb->name));
return fSymb;
}
DiffParamTypes = DiffParamQualifiers = DiffParamCount = DiffReturnType = 0;
if (!IsSameUnqualifiedType(lSymb->type->fun.rettype, fType->fun.rettype))
DiffReturnType = 1;
oldArgType = lSymb->type->fun.paramtypes;
newArgType = fType->fun.paramtypes;
while (newArgType && oldArgType) {
if (!IsSameUnqualifiedType(oldArgType->type, newArgType->type)) {
DiffParamTypes = 1;
} else if (GetQualifiers(oldArgType->type) != GetQualifiers(newArgType->type)) {
DiffParamQualifiers = 1;
}
oldArgType = oldArgType->next;
newArgType = newArgType->next;
}
if (newArgType || oldArgType)
DiffParamCount = 1;
if (!DiffParamCount && !DiffParamTypes) {
if (DiffParamQualifiers) {
SemanticError(loc, ERROR_S_OVERLOAD_DIFF_ONLY_QUALS,
GetAtomString(atable, atom));
OK = 0;
break;
}
if (DiffReturnType) {
SemanticError(loc, ERROR_S_OVERLOAD_DIFF_ONLY_RETURN,
GetAtomString(atable, atom));
OK = 0;
break;
}
break; // Found the matching function
}
lSymb = lSymb->details.fun.overload;
}
if (OK) {
if (DiffParamCount || DiffParamTypes) {
lSymb = NewSymbol(loc, fScope, atom, fType, FUNCTION_S);
lSymb->details.fun.params = params;
lSymb->details.fun.locals = locals;
lSymb->details.fun.overload = fSymb->details.fun.overload;
fSymb->details.fun.overload = lSymb;
if (GetCategory(fType) == TYPE_CATEGORY_FUNCTION) {
locals->returnType = fType->fun.rettype;
} else {
locals->returnType = UndefinedType;
}
} else {
if (!(lSymb->properties & SYMB_IS_DEFINED)) {
// Overwrite previous definitions if this function is not yet defined.
// Prototype parameter names are ignored.
lSymb->details.fun.params = params;
lSymb->details.fun.locals = locals;
} else {
// Declarator for a function that's already been defined. Not an error.
}
}
} else {
// Found a function that differs only by qualifiers or return type. Error arleady issued.
// lSymb = fSymb;
}
}
} else {
lSymb = AddSymbol(loc, fScope, atom, fType, FUNCTION_S);
lSymb->details.fun.params = params;
lSymb->details.fun.locals = locals;
if (GetCategory(fType) == TYPE_CATEGORY_FUNCTION) {
locals->returnType = fType->fun.rettype;
} else {
locals->returnType = UndefinedType;
}
}
if (lSymb->type->properties & TYPE_MISC_INTERNAL) {
index = Cg->theHAL->CheckInternalFunction(lSymb, &group);
if (index) {
//
// lSymb->InternalIndex = index; etc.
//
lSymb->properties |= SYMB_IS_DEFINED | SYMB_IS_BUILTIN;
lSymb->details.fun.group = group;
lSymb->details.fun.index = index;
} else {
SemanticError(loc, ERROR_S_INVALID_INTERNAL_FUNCTION, GetAtomString(atable, atom));
}
}
return lSymb;
} // DeclareFunc
/*
* DefineFunction() - Set the body of the function "func" to the statements in "body".
*
*/
void DefineFunction(SourceLoc *loc, Scope *fScope, decl *func, stmt *body)
{
Symbol *lSymb = func->symb;
SymbolList *lSymbList;
Scope *globals;
Type *lType;
if (IsFunction(lSymb)) {
if (body) {
if (lSymb->properties & SYMB_IS_DEFINED) {
SemanticError(loc, ERROR_S_FUN_ALREADY_DEFINED,
GetAtomString(atable, lSymb->name));
} else {
lSymb->properties |= SYMB_IS_DEFINED;
lSymb->details.fun.statements = body;
lType = lSymb->type;
if ((lType->properties & TYPE_MISC_INLINE) ||
Cg->theHAL->GetCapsBit(CAPS_INLINE_ALL_FUNCTIONS))
{
lSymb->properties |= SYMB_IS_INLINE_FUNCTION;
}
}
if (!fScope->HasReturnStmt && !IsVoid(fScope->returnType)) {
SemanticError(loc, ERROR_S_FUNCTION_HAS_NO_RETURN,
GetAtomString(atable, lSymb->name));
}
if (func->type.type.properties & TYPE_MISC_PROGRAM) {
globals = fScope->parent;
if (!globals->programs) {
lSymbList = (SymbolList *) malloc(sizeof(SymbolList));
lSymbList->next = globals->programs;
lSymbList->symb = lSymb;
globals->programs = lSymbList;
} else {
SemanticError(loc, ERROR_S_ONE_PROGRAM,
GetAtomString(atable, globals->programs->symb->name));
}
}
} else {
SemanticError(loc, ERROR_S_NO_STATEMENTS, GetAtomString(atable, func->name));
}
if (Cg->options.DumpParseTree) {
PrintScopeDeclarations();
PrintFunction(lSymb);
}
}
} // DefineFunction
/*
* GlobalInitStatements()
*
*/
int GlobalInitStatements(Scope *fScope, stmt *fStmt)
{
stmt *lStmt;
if (fStmt) {
if (fScope->initStmts) {
lStmt = fScope->initStmts;
while (lStmt->commonst.next)
lStmt = lStmt->commonst.next;
lStmt->commonst.next = fStmt;
} else {
fScope->initStmts = fStmt;
}
}
return 1;
} // GlobalInitStatements
/*
* BasicVariable() - A variable identifier has been encountered.
*
*/
expr *BasicVariable(SourceLoc *loc, int name)
{
Symbol *lSymb;
lSymb = LookUpSymbol(CurrentScope, name);
if (!lSymb) {
SemanticError(loc, ERROR_S_UNDEFINED_VAR, GetAtomString(atable, name));
lSymb = DefineVar(loc, CurrentScope, name, UndefinedType);
}
return (expr *) NewSymbNode(VARIABLE_OP, lSymb);
} // BasicVariable
/*
* IsLValue() - Is this expression an l-value?
*
*/
int IsLValue(const expr *fExpr)
{
if (fExpr) {
return fExpr->common.IsLValue;
} else {
return 0;
}
} // IsLValue
/*
* IsConst() - Is this expression an l-value?
*
*/
int IsConst(const expr *fExpr)
{
if (fExpr) {
return fExpr->common.IsConst;
} else {
return 0;
}
} // IsConst
/*
* IsArrayIndex() - Is this expression an array index expression?
*
*/
int IsArrayIndex(const expr *fExpr)
{
if (fExpr) {
return fExpr->common.kind == BINARY_N && fExpr->bin.op == ARRAY_INDEX_OP;
} else {
return 0;
}
} // IsArrayIndex
/*
* lIsBaseCastValid() - Is it O.K. to cast the base type fromBase to toBase?
*
*/
static int lIsBaseCastValid(int toBase, int fromBase, int Explicit)
{
if (toBase == TYPE_BASE_NO_TYPE || fromBase == TYPE_BASE_NO_TYPE)
return 0;
if (toBase == TYPE_BASE_VOID || fromBase == TYPE_BASE_VOID)
return 0;
if (toBase == fromBase)
return 1;
if (Cg->theHAL->IsValidScalarCast(toBase, fromBase, Explicit)) {
return 1;
} else {
return 0;
}
} // lIsBaseCastValid
/*
* ConvertType() - Type cast fExpr from fromType to toType if needed. Ignore qualifiers.
*
* If "result" is NULL just check validity of cast; don't allocate cast operator node.
*
*/
int ConvertType(expr *fExpr, Type *toType, Type *fromType, expr **result, int IgnorePacked, int Explicit)
{
int fcategory, tcategory;
int fbase, tbase;
Type *feltype, *teltype;
unary *unnode;
int ToPacked, FromPacked;
ToPacked = (toType->properties & TYPE_MISC_PACKED) != 0;
FromPacked = (fromType->properties & TYPE_MISC_PACKED) != 0;
if (IsSameUnqualifiedType(toType, fromType) &&
((ToPacked == FromPacked) || IgnorePacked))
{
if (result)
*result = fExpr;
return 1;
} else {
fcategory = GetCategory(fromType);
tcategory = GetCategory(toType);
if (fcategory == tcategory) {
switch (fcategory) {
case TYPE_CATEGORY_SCALAR:
fbase = GetBase(fromType);
tbase = GetBase(toType);
if (lIsBaseCastValid(tbase, fbase, Explicit)) {
if (result) {
unnode = NewUnopSubNode(CAST_CS_OP, SUBOP_CS(tbase, fbase), fExpr);
unnode->type = GetStandardType(tbase, 0, 0);
unnode->HasSideEffects = fExpr->common.HasSideEffects;
*result = (expr *) unnode;
}
return 1;
} else {
return 0;
}
break;
case TYPE_CATEGORY_ARRAY:
if (toType->arr.numels != fromType->arr.numels)
return 0;
if (toType->arr.numels > 4)
return 0;
if (!IgnorePacked && (ToPacked != FromPacked))
return 0;
feltype = fromType->arr.eltype;
teltype = toType->arr.eltype;
fcategory = GetCategory(feltype);
tcategory = GetCategory(teltype);
if (tcategory != TYPE_CATEGORY_SCALAR || fcategory != TYPE_CATEGORY_SCALAR)
return 0;
fbase = GetBase(feltype);
tbase = GetBase(teltype);
if (lIsBaseCastValid(tbase, fbase, Explicit)) {
if (result) {
unnode = NewUnopSubNode(CAST_CV_OP, SUBOP_CV(tbase, toType->arr.numels, fbase), fExpr);
unnode->type = GetStandardType(tbase, toType->arr.numels, 0);
unnode->HasSideEffects = fExpr->common.HasSideEffects;
*result = (expr *) unnode;
}
return 1;
} else {
return 0;
}
break;
default:
return 0;
}
} else {
return 0;
}
}
} // ConvertType
/*
* CastScalarVectorMatrix() - Cast a scalar, vector, or matrix expression.
*
* Scalar: len = 0.
* Vector: len >= 1 and len2 = 0
* Matrix: len >= 1 and len2 >= 1
*
* len = 1 means "float f[1]" not "float f"
*
*/
expr *CastScalarVectorMatrix(expr *fExpr, int fbase, int tbase, int len, int len2)
{
int op, subop;
expr *lExpr;
if (len == 0) {
op = CAST_CS_OP;
subop = SUBOP_CS(tbase, fbase);
} else if (len2 == 0) {
op = CAST_CV_OP;
subop = SUBOP_CV(tbase, len, fbase);
} else {
op = CAST_CM_OP;
subop = SUBOP_CM(len2, tbase, len, fbase);
}
lExpr = (expr *) NewUnopSubNode(op, subop, fExpr);
lExpr->common.type = GetStandardType(tbase, len, len2);
return lExpr;
} // CastScalarVectorMatrix
/*
* ConvertNumericOperands() - Convert two scalar, vector, or matrix expressions to the same type
* for use in an expression. Number of dimensions and lengths may differ.
*
* Returns: base type of resulting values.
*
*/
int ConvertNumericOperands(int baseop, expr **lExpr, expr **rexpr, int lbase, int rbase,
int llen, int rlen, int llen2, int rlen2)
{
int nbase;
nbase = Cg->theHAL->GetBinOpBase(baseop, lbase, rbase, llen, rlen);
if (nbase != lbase)
*lExpr = CastScalarVectorMatrix(*lExpr, lbase, nbase, llen, llen2);
if (nbase != rbase)
*rexpr = CastScalarVectorMatrix(*rexpr, rbase, nbase, rlen, rlen2);
return nbase;
} // ConvertNumericOperands
/*
* CheckBooleanExpr()
*
*/
expr *CheckBooleanExpr(SourceLoc *loc, expr *fExpr, int AllowVector)
{
int len = 0, HasError = 0;
Type *lType, *leltype;
lType = leltype = fExpr->common.type;
if (IsScalar(lType)) {
if (!IsBoolean(lType)) {
SemanticError(loc, ERROR___BOOL_EXPR_EXPECTED);
HasError = 1;
}
} else if (IsVector(lType, &len)) {
leltype = lType->arr.eltype;
if (AllowVector) {
if (len > 4) {
SemanticError(loc, ERROR___VECTOR_EXPR_LEN_GR_4);
HasError = 1;
len = 4;
}
if (!IsBoolean(lType)) {
Semant
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -