diff options
| author | gingerBill <bill@gingerbill.org> | 2020-08-02 14:59:39 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2020-08-02 14:59:39 +0100 |
| commit | d1d5f61230608ed818fc832cbb5979da312db5d1 (patch) | |
| tree | 8b122fe2daa69a06e101dea181a4e6df68e31ee8 /src/check_expr.cpp | |
| parent | 0aaab849382aa0cbce7234ec386f88161b79ca07 (diff) | |
Add `intrinsics.alloca`
Diffstat (limited to 'src/check_expr.cpp')
| -rw-r--r-- | src/check_expr.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp index a29cdac36..0633b20ea 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -5408,6 +5408,60 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 break; } + case BuiltinProc_alloca: + { + Operand sz = {}; + Operand al = {}; + + check_expr(c, &sz, ce->args[0]); + if (sz.mode == Addressing_Invalid) { + return false; + } + check_expr(c, &al, ce->args[1]); + if (al.mode == Addressing_Invalid) { + return false; + } + convert_to_typed(c, &sz, t_int); if (sz.mode == Addressing_Invalid) return false; + convert_to_typed(c, &al, t_int); if (al.mode == Addressing_Invalid) return false; + + if (!is_type_integer(sz.type) || !is_type_integer(al.type)) { + error(operand->expr, "Both parameters to '%.*s' must integers", LIT(builtin_name)); + return false; + } + + if (sz.mode == Addressing_Constant) { + i64 i_sz = exact_value_to_i64(sz.value); + if (i_sz < 0) { + error(sz.expr, "Size parameter to '%.*s' must be non-negative, got %lld", LIT(builtin_name), cast(long long)i_sz); + return false; + } + } + if (al.mode == Addressing_Constant) { + i64 i_al = exact_value_to_i64(al.value); + if (i_al < 0) { + error(al.expr, "Alignment parameter to '%.*s' must be non-negative, got %lld", LIT(builtin_name), cast(long long)i_al); + return false; + } + + if (i_al > 1<<29) { + error(al.expr, "Alignment parameter to '%.*s' must not exceed '1<<29', got %lld", LIT(builtin_name), cast(long long)i_al); + return false; + } + + if (!gb_is_power_of_two(cast(isize)i_al) && i_al != 0) { + error(al.expr, "Alignment parameter to '%.*s' must be a power of 2 or 0, got %lld", LIT(builtin_name), cast(long long)i_al); + return false; + } + } else { + error(al.expr, "Alignment parameter to '%.*s' must be constant", LIT(builtin_name)); + } + + operand->type = t_u8_ptr; + operand->mode = Addressing_Value; + break; + } + + case BuiltinProc_cpu_relax: operand->mode = Addressing_NoValue; break; |