static AstExpression CheckEqualityOP(AstExpression expr) { Type ty1, ty2; expr->ty = T(INT); ty1 = expr->kids[0]->ty; ty2 = expr->kids[1]->ty; if (BothArithType(ty1, ty2)) { PERFORM_ARITH_CONVERSION(expr); expr->ty = T(INT); return FoldConstant(expr); } if (IsCompatiblePtr(ty1, ty2) || NotFunctionPtr(ty1) && IsVoidPtr(ty2) || NotFunctionPtr(ty2) && IsVoidPtr(ty1) || IsPtrType(ty1) && IsNullConstant(expr->kids[1]) || IsPtrType(ty2) && IsNullConstant(expr->kids[0])) { return expr; } REPORT_OP_ERROR; }
static AstExpression CheckConditionalExpression(AstExpression expr) { int qual; Type ty1, ty2; expr->kids[0] = Adjust(CheckExpression(expr->kids[0]), 1); if (! IsScalarType(expr->kids[0]->ty)) { Error(&expr->coord, "The first expression shall be scalar type."); } expr->kids[1]->kids[0] = Adjust(CheckExpression(expr->kids[1]->kids[0]), 1); expr->kids[1]->kids[1] = Adjust(CheckExpression(expr->kids[1]->kids[1]), 1); ty1 = expr->kids[1]->kids[0]->ty; ty2 = expr->kids[1]->kids[1]->ty; if (BothArithType(ty1, ty2)) { expr->ty = CommonRealType(ty1, ty2); expr->kids[1]->kids[0] = Cast(expr->ty, expr->kids[1]->kids[0]); expr->kids[1]->kids[1] = Cast(expr->ty, expr->kids[1]->kids[1]); return FoldConstant(expr); } else if (IsRecordType(ty1) && ty1 == ty2) { expr->ty = ty1; } else if (ty1->categ == VOID && ty2->categ == VOID) { expr->ty = T(VOID); } else if (IsCompatiblePtr(ty1, ty2)) { qual = ty1->bty->qual | ty2->bty->qual; expr->ty = PointerTo(Qualify(qual, CompositeType(Unqual(ty1->bty), Unqual(ty2->bty)))); } else if (IsPtrType(ty1) && IsNullConstant(expr->kids[1]->kids[1])) { expr->ty = ty1; } else if (IsPtrType(ty2) && IsNullConstant(expr->kids[1]->kids[0])) { expr->ty = ty2; } else if (NotFunctionPtr(ty1) && IsVoidPtr(ty2) || NotFunctionPtr(ty2) && IsVoidPtr(ty1)) { qual = ty1->bty->qual | ty2->bty->qual; expr->ty = PointerTo(Qualify(qual, T(VOID))); } else { Error(&expr->coord, "invalid operand for ? operator."); expr->ty = T(INT); } return expr; }
static AstExpression CheckFunctionCall(AstExpression expr) { AstExpression arg; Type ty; AstNode *tail; int argNo, argFull; if (expr->kids[0]->op == OP_ID && LookupID(expr->kids[0]->val.p) == NULL) { expr->kids[0]->ty = DefaultFunctionType; expr->kids[0]->val.p = AddFunction(expr->kids[0]->val.p, DefaultFunctionType, TK_EXTERN); } else { expr->kids[0] = CheckExpression(expr->kids[0]); } expr->kids[0] = Adjust(expr->kids[0], 1); ty = expr->kids[0]->ty; if (! (IsPtrType(ty) && IsFunctionType(ty->bty))) { Error(&expr->coord, "The left operand must be function or function pointer"); ty = DefaultFunctionType; } else { ty = ty->bty; } tail = (AstNode *)&expr->kids[1]; arg = expr->kids[1]; argNo = 1; argFull = 0; while (arg != NULL && ! argFull) { *tail = (AstNode)CheckArgument((FunctionType)ty, arg, argNo, &argFull); tail = &(*tail)->next; arg = (AstExpression)arg->next; argNo++; } *tail = NULL; if (arg != NULL) { while (arg != NULL) { CheckExpression(arg); arg = (AstExpression)arg->next; } Error(&expr->coord, "Too many arguments"); } else if (argNo < LEN(((FunctionType)ty)->sig->params)) { Error(&expr->coord, "Too few arguments"); } expr->ty = ty->bty; return expr; }
/** * Check if the initializer expression is address constant. * e.g. * int a; * int b = &a; */ static AstExpression CheckAddressConstant(AstExpression expr) { AstExpression addr; AstExpression p; int offset = 0; if (! IsPtrType(expr->ty)) return NULL; if (expr->op == OP_ADD || expr->op == OP_SUB) { addr = CheckAddressConstant(expr->kids[0]); if (addr == NULL || expr->kids[1]->op != OP_CONST) return NULL; expr->kids[0] = addr->kids[0]; expr->kids[1]->val.i[0] += (expr->op == OP_ADD ? 1 : -1) * addr->kids[1]->val.i[0]; return expr; } if (expr->op == OP_ADDRESS) addr = expr->kids[0]; else addr = expr; while (addr->op == OP_INDEX || addr->op == OP_MEMBER) { if (addr->op == OP_INDEX) { if (addr->kids[1]->op != OP_CONST) return NULL; offset += addr->kids[1]->val.i[0] * addr->ty->size; } else { Field fld = addr->val.p; offset += fld->offset; } addr = addr->kids[0]; } if (addr->op != OP_ID || (expr->op != OP_ADDRESS && ! addr->isarray && ! addr->isfunc)) return NULL; ((Symbol)addr->val.p)->ref++; CREATE_AST_NODE(p, Expression); p->op = OP_ADD; p->ty = expr->ty; p->kids[0] = addr; p->kids[1] = Constant(addr->coord, T(INT), p->val); return p; }
int CanAssign(Type lty, AstExpression expr) { Type rty = expr->ty; lty = Unqual(lty); rty = Unqual(rty); if (lty == rty) { return 1; } if (BothArithType(lty, rty)) { return 1; } if (IsCompatiblePtr(lty, rty) && ((lty->bty->qual & rty->bty->qual) == rty->bty->qual)) { return 1; } if ((NotFunctionPtr(lty) && IsVoidPtr(rty) || NotFunctionPtr(rty) && IsVoidPtr(lty))&& ((lty->bty->qual & rty->bty->qual) == rty->bty->qual)) { return 1; } if (IsPtrType(lty) && IsNullConstant(expr)) { return 1; } if (IsPtrType(lty) && IsPtrType(rty)) { //Warning(&expr->coord, "assignment from incompatible pointer type"); return 1; } if ((IsPtrType(lty) && IsIntegType(rty) || IsPtrType(rty) && IsIntegType(lty))&& (lty->size == rty->size)) { Warning(&expr->coord, "conversion between pointer and integer without a cast"); return 1; } return 0; }
/* 添加常量到符号表中 */ Symbol AddConstant (Type ty, union value val) { unsigned h = (unsigned)val.i[0] & SYM_HASH_MASK; Symbol p; /* 去掉修饰符 */ ty = Unqual (ty); if (IsIntegType (ty)) { ty = T (INT); } else if (IsPtrType (ty)) { ty = T (POINTER); } else if (LONGDOUBLE == ty->categ) { ty = T (DOUBLE); } /* 如果已经添加直接返回 */ for (p = Constants.buckets[h]; p; p = p->link) { if (p->ty == ty && p->val.i[0] == val.i[0] && p->val.i[1] == val.i[1]) return p; } /* 将常量添加到符号表中 */ CALLOC (p); p->kind = SK_Constant; switch (ty->categ) { case INT: p->name = FormatName ("%d", val.i[0]); break; case POINTER: p->name = (val.i[0] ? FormatName ("0x%x", val.i[0]) : "0"); break; case FLOAT: /* %g可以省略浮点多余的0 */ p->name = FormatName ("%g", val.f); break; case DOUBLE: p->name = FormatName ("%g", val.d); break; default: assert (0); } p->ty = ty; p->sclass = TK_STATIC; p->val = val; p->link = Constants.buckets[h]; Constants.buckets[h] = p; if (FLOAT == ty->categ || DOUBLE == ty->categ) { *FloatTail = p; FloatTail = &p->next; } return p; }
static AstExpression CheckMemberAccess(AstExpression expr) { Type ty; Field fld; expr->kids[0] = CheckExpression(expr->kids[0]); if (expr->op == OP_MEMBER) { expr->kids[0] = Adjust(expr->kids[0], 0); ty = expr->kids[0]->ty; if (! IsRecordType(ty)) { REPORT_OP_ERROR; } expr->lvalue = expr->kids[0]->lvalue; } else { expr->kids[0] = Adjust(expr->kids[0], 1); ty = expr->kids[0]->ty; if (! (IsPtrType(ty) && IsRecordType(ty->bty))) { REPORT_OP_ERROR; } ty = ty->bty; expr->lvalue = 1; } fld = LookupField(Unqual(ty), expr->val.p); if (fld == NULL) { Error(&expr->coord, "struct or union member %s doesn't exsist", expr->val.p); expr->ty = T(INT); return expr; } expr->ty = Qualify(ty->qual, fld->ty); expr->val.p = fld; expr->bitfld = fld->bits != 0; return expr; }
static AstExpression CheckUnaryExpression(AstExpression expr) { Type ty; switch (expr->op) { case OP_PREINC: case OP_PREDEC: return TransformIncrement(expr); case OP_ADDRESS: expr->kids[0] = CheckExpression(expr->kids[0]); ty = expr->kids[0]->ty; if (expr->kids[0]->op == OP_DEREF) { expr->kids[0]->kids[0]->lvalue = 0; return expr->kids[0]->kids[0]; } else if (expr->kids[0]->op == OP_INDEX) { expr->kids[0]->op = OP_ADD; expr->kids[0]->ty = PointerTo(ty); expr->kids[0]->lvalue = 0; return expr->kids[0]; } else if (IsFunctionType(ty) || (expr->kids[0]->lvalue && ! expr->kids[0]->bitfld && ! expr->kids[0]->inreg)) { expr->ty = PointerTo(ty); return expr; } break; case OP_DEREF: expr->kids[0] = Adjust(CheckExpression(expr->kids[0]), 1); ty = expr->kids[0]->ty; if (expr->kids[0]->op == OP_ADDRESS) { expr->kids[0]->kids[0]->ty = ty->bty; return expr->kids[0]->kids[0]; } else if (expr->kids[0]->op == OP_ADD && expr->kids[0]->kids[0]->isarray) { expr->kids[0]->op = OP_INDEX; expr->kids[0]->ty = ty->bty; expr->kids[0]->lvalue = 1; return expr->kids[0]; } if (IsPtrType(ty)) { expr->ty = ty->bty; if (IsFunctionType(expr->ty)) { return expr->kids[0]; } expr->lvalue = 1; return expr; } break; case OP_POS: case OP_NEG: expr->kids[0] = Adjust(CheckExpression(expr->kids[0]), 1); if (IsArithType(expr->kids[0]->ty)) { expr->kids[0] = DoIntegerPromotion(expr->kids[0]); expr->ty = expr->kids[0]->ty; return expr->op == OP_POS ? expr->kids[0] : FoldConstant(expr); } break; case OP_COMP: expr->kids[0] = Adjust(CheckExpression(expr->kids[0]), 1); if (IsIntegType(expr->kids[0]->ty)) { expr->kids[0] = DoIntegerPromotion(expr->kids[0]); expr->ty = expr->kids[0]->ty; return FoldConstant(expr); } break; case OP_NOT: expr->kids[0] = Adjust(CheckExpression(expr->kids[0]), 1); if (IsScalarType(expr->kids[0]->ty)) { expr->ty = T(INT); return FoldConstant(expr); } break; case OP_SIZEOF: if (expr->kids[0]->kind == NK_Expression) { expr->kids[0] = CheckExpression(expr->kids[0]); if (expr->kids[0]->bitfld) goto err; ty = expr->kids[0]->ty; } else { ty = CheckTypeName((AstTypeName)expr->kids[0]); } if (IsFunctionType(ty) || ty->size == 0) goto err; expr->ty = T(UINT); expr->op = OP_CONST; expr->val.i[0] = ty->size; return expr; case OP_CAST: return CheckTypeCast(expr); default: assert(0); } err: REPORT_OP_ERROR; }