/*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();
	}
}
Exemple #2
0
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;
}