/*e * Computes the classification for an expression * * This function effectively performs abstract interpretation over the expression. It serves * as transfer function interpreter. * * @param sym The function within which we perform the analysis (needed to detect local variables) * @param locals Bindings for all local variables * @param node The node to analyse */ static classification_t cla_expression(symtab_entry_t *sym, classification_t *locals, ast_node_t *node) { switch (NODE_TY(node)) { case AST_VALUE_INT: return cla_int(AV_INT(node)); case AST_VALUE_ID: { const int var = data_flow_is_local_var(sym, node); if (var >= 0) { return locals[var]; } return cla_top(); } case AST_NODE_ARRAYVAL: { int size = node->children[0]->children_nr; if (node->children[1]) { //e explicit size specification size = AV_INT(node->children[1]); } return cla_array(size); } case AST_NODE_METHODAPP: { //e are we observing array.size()? const int var = data_flow_is_local_var(sym, node->children[0]); if (var >= 0 && node->children[1]->sym->selector == symtab_selector_size) { return cla_sizeof(var); } return cla_top(); } case AST_NODE_FUNAPP: { if (AST_CALLABLE_SYMREF(node)->symtab_flags & SYMTAB_BUILTIN) { const int args_nr = node->children[1]->children_nr; classification_t args[args_nr]; //e prepare arguments for (int i = 0; i < args_nr; i++) { args[i] = cla_expression(sym, locals, node->children[1]->children[i]); //e Any bottom yields a bottom, ant top yields a top if (args[i].vartype == VARTYPE_BOT || args[i].vartype == VARTYPE_TOP) { return args[i]; } } //e symbolically interpret functions switch (AST_CALLABLE_SYMREF(node)->id) { case BUILTIN_OP_CONVERT: return args[0]; case BUILTIN_OP_ADD: return cla_add(args[0], args[1]); case BUILTIN_OP_SUB: return cla_add(args[0], cla_negate(args[1])); //e we don't support the others and fall through } } } // otherwise, fall through default: //e unknown/dangerous return cla_top(); } }
void addStandardVariables(Unit *unit) { Context *ctx = unit->ctx; NativeTypes *nt = ctx->nt; Type *type_int = ctx->tr->type_int; Type *type_float = ctx->tr->type_float; Type *type_double = ctx->tr->type_double; Type *type_ldbl = ctx->tr->type_longdouble; AV_INT("JMP_BUF_SIZE", sizeof (jmp_buf)); AV_INT("FPOS_T", sizeof (fpos_t)); AV_INT("TIME_T", sizeof (time_t)); AV_INT("CLOCK_T", sizeof (clock_t)); AV_INT("SIZEOF_LONG", sizeof (long)); AV_INT("SIZEOF_LONG_LONG", sizeof (long long)); AV_INT("FLT_RADIX", FLT_RADIX); AV_INT("FLT_MANT_DIG", FLT_MANT_DIG); AV_INT("FLT_DIG", FLT_DIG); AV_INT("FLT_ROUNDS", FLT_ROUNDS); AV_INT("FLT_MIN_EXP", FLT_MIN_EXP); AV_INT("FLT_MAX_EXP", FLT_MAX_EXP); AV_INT("LDBL_MANT_DIG", LDBL_MANT_DIG); AV_INT("LDBL_DIG", LDBL_DIG); AV_INT("DBL_MANT_DIG", DBL_MANT_DIG); AV_INT("DBL_DIG", DBL_DIG); AV_INT("DBL_MIN_EXP", DBL_MIN_EXP); AV_INT("DBL_MAX_EXP", DBL_MAX_EXP); AV_INT("LDBL_MIN_EXP", LDBL_MIN_EXP); AV_INT("LDBL_MAX_EXP", LDBL_MAX_EXP); AV_INT("L_tmpnam", L_tmpnam); AV_INT("TMP_MAX", TMP_MAX); AV_INT("FILENAME_MAX", FILENAME_MAX); AV_INT("FOPEN_MAX", FOPEN_MAX); AV_INT("RAND_MAX", RAND_MAX); AV_INT("EXIT_FAILURE", EXIT_FAILURE); AV_INT("EXIT_SUCCESS", EXIT_SUCCESS); addVariable(unit, "FLT_EPSILON", type_float, CFP_FLOAT(FLT_EPSILON)); addVariable(unit, "FLT_MIN", type_float, CFP_FLOAT(FLT_MIN)); addVariable(unit, "FLT_MAX", type_float, CFP_FLOAT(FLT_MAX)); addVariable(unit, "DBL_EPSILON", type_double, CFP_DBL(DBL_EPSILON)); addVariable(unit, "DBL_MIN", type_double, CFP_DBL(DBL_MIN)); addVariable(unit, "DBL_MAX", type_double, CFP_DBL(DBL_MAX)); addVariable(unit, "LDBL_EPSILON", type_ldbl, CFP_FP80(LDBL_EPSILON)); addVariable(unit, "LDBL_MIN", type_ldbl, CFP_FP80(LDBL_MIN)); addVariable(unit, "LDBL_MAX", type_ldbl, CFP_FP80(LDBL_MAX)); addVariable(unit, "HUGE_VAL", type_double, llvm::ConstantFP::getInfinity( llvm::Type::getDoubleTy(llvm::getGlobalContext()) )); addVariable(unit, "HUGE_VALF", type_float, llvm::ConstantFP::getInfinity( llvm::Type::getFloatTy(llvm::getGlobalContext()) )); addVariable(unit, "HUGE_VALL", type_ldbl, llvm::ConstantFP::getInfinity( llvm::Type::getX86_FP80Ty(llvm::getGlobalContext()) )); return; }