typed alloc
This commit is contained in:
@@ -281,13 +281,15 @@ is_ptr_cast_call :: proc(checker: ^Checker, expr: ast.Expr) -> bool {
|
||||
symbol_text(checker, expr.name) == "ptr_cast"
|
||||
}
|
||||
|
||||
Layout_Builtin :: enum u8 {
|
||||
Type_Builtin :: enum u8 {
|
||||
None,
|
||||
Size_Of,
|
||||
Align_Of,
|
||||
Min_Value,
|
||||
Max_Value,
|
||||
}
|
||||
|
||||
layout_builtin_call :: proc(checker: ^Checker, expr: ast.Expr) -> Layout_Builtin {
|
||||
type_builtin_call :: proc(checker: ^Checker, expr: ast.Expr) -> Type_Builtin {
|
||||
if expr.kind != .Call || expr.left != ast.INVALID_EXPR || symbol.is_valid(expr.qualifier) {
|
||||
return .None
|
||||
}
|
||||
@@ -298,6 +300,12 @@ layout_builtin_call :: proc(checker: ^Checker, expr: ast.Expr) -> Layout_Builtin
|
||||
if name == "align_of" {
|
||||
return .Align_Of
|
||||
}
|
||||
if name == "min_value" {
|
||||
return .Min_Value
|
||||
}
|
||||
if name == "max_value" {
|
||||
return .Max_Value
|
||||
}
|
||||
return .None
|
||||
}
|
||||
|
||||
@@ -314,21 +322,30 @@ valid_layout_type :: proc(checker: ^Checker, value: types.Type) -> bool {
|
||||
return types.is_runtime_value(value, &checker.module.types)
|
||||
}
|
||||
|
||||
layout_builtin_value :: proc(checker: ^Checker, kind: Layout_Builtin, value: types.Type) -> i128 {
|
||||
type_builtin_value :: proc(checker: ^Checker, kind: Type_Builtin, value: types.Type) -> i128 {
|
||||
#partial switch kind {
|
||||
case .Size_Of:
|
||||
return i128(types.size(value, &checker.module.types, checker.target))
|
||||
case .Align_Of:
|
||||
return i128(types.alignment_of(value, &checker.module.types, checker.target))
|
||||
case .Min_Value:
|
||||
if types.is_unsigned(value, checker.target) {
|
||||
return 0
|
||||
}
|
||||
return -(i128(1) << u32(types.bits(value, checker.target)-1))
|
||||
case .Max_Value:
|
||||
bit_count := types.bits(value, checker.target)
|
||||
sign_bit_count := 1 if types.is_signed(value, checker.target) else 0
|
||||
return (i128(1) << u32(bit_count-sign_bit_count))-1
|
||||
case:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
build_layout_builtin :: proc(
|
||||
build_type_builtin :: proc(
|
||||
checker: ^Checker,
|
||||
expr: ast.Expr,
|
||||
kind: Layout_Builtin,
|
||||
kind: Type_Builtin,
|
||||
pkg: ast.Package_Id,
|
||||
file: ast.File_Id,
|
||||
) -> hir.Expr_Id {
|
||||
@@ -338,18 +355,24 @@ build_layout_builtin :: proc(
|
||||
}
|
||||
target, target_ok := resolve_type_argument(checker, expr.args[0], pkg, file)
|
||||
if !target_ok {
|
||||
id := source.add(checker.diagnostics, checker.ast_module.exprs[expr.args[0]].span, "layout target must be a type")
|
||||
label := "layout" if kind == .Size_Of || kind == .Align_Of else "integer bound"
|
||||
id := source.addf(checker.diagnostics, checker.ast_module.exprs[expr.args[0]].span, "%s target must be a type", label)
|
||||
return invalid_hir_expr(checker, expr.span, id, types.USIZE)
|
||||
}
|
||||
if !valid_layout_type(checker, target) {
|
||||
if (kind == .Size_Of || kind == .Align_Of) && !valid_layout_type(checker, target) {
|
||||
id := source.addf(checker.diagnostics, checker.ast_module.exprs[expr.args[0]].span, "layout target must be a sized runtime value type, got %s", type_label(checker, target))
|
||||
return invalid_hir_expr(checker, expr.span, id, types.USIZE)
|
||||
}
|
||||
if (kind == .Min_Value || kind == .Max_Value) && !types.is_concrete_integer(target) {
|
||||
id := source.addf(checker.diagnostics, checker.ast_module.exprs[expr.args[0]].span, "integer bound target must be a concrete integer type, got %s", type_label(checker, target))
|
||||
return invalid_hir_expr(checker, expr.span, id, types.USIZE)
|
||||
}
|
||||
result_type := types.USIZE if kind == .Size_Of || kind == .Align_Of else target
|
||||
return build_constant_expr(
|
||||
checker,
|
||||
expr,
|
||||
Constant{kind=.Value, value=layout_builtin_value(checker, kind, target)},
|
||||
types.USIZE,
|
||||
Constant{kind=.Value, value=type_builtin_value(checker, kind, target)},
|
||||
result_type,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2201,8 +2224,15 @@ infer_expr :: proc(
|
||||
}
|
||||
continue
|
||||
}
|
||||
if builtin := layout_builtin_call(checker, expr); builtin != .None {
|
||||
last = types.USIZE
|
||||
if builtin := type_builtin_call(checker, expr); builtin != .None {
|
||||
if builtin == .Size_Of || builtin == .Align_Of {
|
||||
last = types.USIZE
|
||||
} else if len(expr.args) == 1 {
|
||||
target, ok := resolve_type_argument(checker, expr.args[0], pkg, file)
|
||||
last = target if ok && types.is_concrete_integer(target) else types.INVALID
|
||||
} else {
|
||||
last = types.INVALID
|
||||
}
|
||||
_ = pop(&stack)
|
||||
continue
|
||||
}
|
||||
@@ -3188,10 +3218,19 @@ infer_all :: proc(checker: ^Checker) {
|
||||
if global.external {
|
||||
continue
|
||||
}
|
||||
if global.expr != ast.INVALID_EXPR && int(global.expr) < len(checker.ast_module.exprs) &&
|
||||
layout_builtin_call(checker, checker.ast_module.exprs[global.expr]) != .None {
|
||||
checker.global_types[index] = types.USIZE
|
||||
continue
|
||||
if global.expr != ast.INVALID_EXPR && int(global.expr) < len(checker.ast_module.exprs) {
|
||||
expr := checker.ast_module.exprs[global.expr]
|
||||
if builtin := type_builtin_call(checker, expr); builtin != .None {
|
||||
if builtin == .Size_Of || builtin == .Align_Of {
|
||||
checker.global_types[index] = types.USIZE
|
||||
} else if len(expr.args) == 1 {
|
||||
target, ok := resolve_type_argument(checker, expr.args[0], global.pkg, global.file)
|
||||
if ok && types.is_concrete_integer(target) {
|
||||
checker.global_types[index] = target
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
constant := eval_integer_constant_in_context(checker, global.expr, global.pkg, global.file)
|
||||
if constant.kind == .Value && fits_i64(constant.value) {
|
||||
@@ -4998,8 +5037,8 @@ build_expr :: proc(
|
||||
append(&stack, Build_Expr_Frame{expr=expr.left, expected=types.INVALID, template=ast.INVALID_FUNCTION})
|
||||
continue
|
||||
}
|
||||
if builtin := layout_builtin_call(checker, expr); builtin != .None {
|
||||
last = build_layout_builtin(checker, expr, builtin, pkg, file)
|
||||
if builtin := type_builtin_call(checker, expr); builtin != .None {
|
||||
last = build_type_builtin(checker, expr, builtin, pkg, file)
|
||||
_ = pop(&stack)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -1909,18 +1909,23 @@ ct_eval_call_expr :: proc(state: ^Ct_State, expr: ast.Expr, expected: types.Type
|
||||
}
|
||||
return ct_eval_template_call(state, ast.Function_Id(u32(state.values[callee].index)), expr.args, expr.span, expected, depth+1)
|
||||
}
|
||||
if builtin := layout_builtin_call(checker, expr); builtin != .None {
|
||||
if builtin := type_builtin_call(checker, expr); builtin != .None {
|
||||
if len(expr.args) != 1 {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, expr.span, "%s expects 1 argument, got %d", symbol_text(checker, expr.name), len(expr.args))
|
||||
}
|
||||
target, target_ok := resolve_type_argument(checker, expr.args[0], state.pkg, state.file)
|
||||
if !target_ok {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_fail(state, .Not_Comptime, checker.ast_module.exprs[expr.args[0]].span, "layout target must be a type")
|
||||
label := "layout" if builtin == .Size_Of || builtin == .Align_Of else "integer bound"
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, checker.ast_module.exprs[expr.args[0]].span, "%s target must be a type", label)
|
||||
}
|
||||
if !valid_layout_type(checker, target) {
|
||||
if (builtin == .Size_Of || builtin == .Align_Of) && !valid_layout_type(checker, target) {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, checker.ast_module.exprs[expr.args[0]].span, "layout target must be a sized runtime value type, got %s", type_label(checker, target))
|
||||
}
|
||||
return ct_add_value(state, Ct_Value{kind=.Integer, type=types.USIZE, integer=layout_builtin_value(checker, builtin, target)}), ct_flow(.Normal), true
|
||||
if (builtin == .Min_Value || builtin == .Max_Value) && !types.is_concrete_integer(target) {
|
||||
return INVALID_CT_VALUE, ct_flow(.Normal), ct_failf(state, .Not_Comptime, checker.ast_module.exprs[expr.args[0]].span, "integer bound target must be a concrete integer type, got %s", type_label(checker, target))
|
||||
}
|
||||
result_type := types.USIZE if builtin == .Size_Of || builtin == .Align_Of else target
|
||||
return ct_add_value(state, Ct_Value{kind=.Integer, type=result_type, integer=type_builtin_value(checker, builtin, target)}), ct_flow(.Normal), true
|
||||
}
|
||||
target_pkg, available := expr_package(checker, expr, state.pkg, state.file, false)
|
||||
if !available {
|
||||
|
||||
Reference in New Issue
Block a user