diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 525a13ce0..6079fa202 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2508,9 +2508,9 @@ bool check_index_value(CheckerContext *c, bool open_range, Ast *index_value, i64 if (value) *value = i; bool out_of_bounds = false; if (open_range) { - out_of_bounds = i >= max_count; - } else { out_of_bounds = i > max_count; + } else { + out_of_bounds = i >= max_count; } if (out_of_bounds) { gbString expr_str = expr_to_string(operand.expr); @@ -2757,21 +2757,6 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } } - if (ce->args.count > 0) { - if (ce->args[0]->kind == Ast_FieldValue) { - error(call, "'field = value' calling is not allowed on built-in procedures"); - return false; - } - } - - - bool vari_expand = (ce->ellipsis.pos.line != 0); - // if (vari_expand && id != BuiltinProc_append) { - // error(ce->ellipsis, "Invalid use of '...' with built-in procedure 'append'"); - // return false; - // } - - switch (id) { // case BuiltinProc_new: case BuiltinProc_make: @@ -2789,6 +2774,14 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 break; } + + if (ce->args.count > 0) { + if (ce->args[0]->kind == Ast_FieldValue) { + error(call, "'field = value' calling is not allowed on built-in procedures"); + return false; + } + } + switch (id) { default: GB_PANIC("Implement built-in procedure: %.*s", LIT(builtin_procs[id].name)); @@ -2845,8 +2838,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_len: case BuiltinProc_cap: { - // proc len(Type) -> int - // proc cap(Type) -> int + // len :: proc(Type) -> int + // cap :: proc(Type) -> int Type *op_type = type_deref(operand->type); Type *type = t_int; AddressingMode mode = Addressing_Invalid; @@ -2892,7 +2885,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 #if 0 case BuiltinProc_new: { - // proc new(Type) -> ^Type + // new :: proc(Type) -> ^Type Operand op = {}; check_expr_or_type(c, &op, ce->args[0]); Type *type = op.type; @@ -2908,7 +2901,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 #endif #if 0 case BuiltinProc_new_slice: { - // proc new_slice(Type, len: int) -> []Type + // new_slice :: proc(Type, len: int) -> []Type // proc new_slice(Type, len, cap: int) -> []Type Operand op = {}; check_expr_or_type(c, &op, ce->args[0]); @@ -2948,7 +2941,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } #endif case BuiltinProc_make: { - // proc make(Type, len: int) -> Type + // make :: proc(Type, len: int) -> Type // proc make(Type, len, cap: int) -> Type Operand op = {}; check_expr_or_type(c, &op, ce->args[0]); @@ -3010,7 +3003,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 #if 0 case BuiltinProc_free: { - // proc free(^Type) + // free :: proc(^Type) // proc free([]Type) // proc free(string) // proc free(map[K]T) @@ -3045,8 +3038,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 #if 0 case BuiltinProc_reserve: { - // proc reserve([dynamic]Type, count: int) { - // proc reserve(map[Key]Type, count: int) { + // reserve :: proc([dynamic]Type, count: int) { + // reserve :: proc(map[Key]Type, count: int) { Type *type = operand->type; if (!is_type_dynamic_array(type) && !is_type_dynamic_map(type)) { gbString str = type_to_string(type); @@ -3093,7 +3086,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 #endif #if 0 case BuiltinProc_append: { - // proc append([dynamic]Type, item: ..Type) + // append :: proc([dynamic]Type, item: ..Type) // proc append([]Type, item: ..Type) Operand prev_operand = *operand; @@ -3144,7 +3137,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 #endif #if 0 case BuiltinProc_delete: { - // proc delete(map[Key]Value, key: Key) + // delete :: proc(map[Key]Value, key: Key) Type *type = operand->type; if (!is_type_map(type)) { gbString str = type_to_string(type); @@ -3179,7 +3172,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_size_of: { - // proc size_of(Type or expr) -> untyped int + // size_of :: proc(Type or expr) -> untyped int Operand o = {}; check_expr_or_type(c, &o, ce->args[0]); if (o.mode == Addressing_Invalid) { @@ -3200,7 +3193,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } case BuiltinProc_align_of: { - // proc align_of(Type or expr) -> untyped int + // align_of :: proc(Type or expr) -> untyped int Operand o = {}; check_expr_or_type(c, &o, ce->args[0]); if (o.mode == Addressing_Invalid) { @@ -3222,7 +3215,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_offset_of: { - // proc offset_of(Type, field) -> uintptr + // offset_of :: proc(Type, field) -> uintptr Operand op = {}; Type *bt = check_type(c, ce->args[0]); Type *type = base_type(bt); @@ -3269,7 +3262,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_type_of: { - // proc type_of(val: Type) -> type(Type) + // type_of :: proc(val: Type) -> type(Type) Ast *expr = ce->args[0]; Operand o = {}; check_expr_or_type(c, &o, expr); @@ -3304,7 +3297,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } case BuiltinProc_type_info_of: { - // proc type_info_of(Type) -> ^Type_Info + // type_info_of :: proc(Type) -> ^Type_Info if (c->scope->flags&ScopeFlag_Global) { compiler_error("'type_info_of' Cannot be declared within the runtime package due to how the internals of the compiler works"); } @@ -3339,7 +3332,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } case BuiltinProc_typeid_of: { - // proc typeid_of(Type) -> typeid + // typeid_of :: proc(Type) -> typeid if (c->scope->flags&ScopeFlag_Global) { compiler_error("'typeid_of' Cannot be declared within the runtime package due to how the internals of the compiler works"); } @@ -3375,7 +3368,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } case BuiltinProc_swizzle: { - // proc swizzle(v: [N]T, ...int) -> [M]T + // swizzle :: proc(v: [N]T, ...int) -> [M]T Type *type = base_type(operand->type); if (!is_type_array(type)) { gbString type_str = type_to_string(operand->type); @@ -3433,7 +3426,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } case BuiltinProc_complex: { - // proc complex(real, imag: float_type) -> complex_type + // complex :: proc(real, imag: float_type) -> complex_type Operand x = *operand; Operand y = {}; @@ -3495,7 +3488,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_real: case BuiltinProc_imag: { - // proc real(x: type) -> float_type + // real :: proc(x: type) -> float_type // proc imag(x: type) -> float_type Operand *x = operand; @@ -3540,7 +3533,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } case BuiltinProc_conj: { - // proc conj(x: type) -> type + // conj :: proc(x: type) -> type Operand *x = operand; if (is_type_complex(x->type)) { if (x->mode == Addressing_Constant) { @@ -3565,7 +3558,7 @@ break; #if 0 case BuiltinProc_slice_ptr: { - // proc slice_ptr(a: ^T, len: int) -> []T + // slice_ptr :: proc(a: ^T, len: int) -> []T // proc slice_ptr(a: ^T, len, cap: int) -> []T // ^T cannot be rawptr Type *ptr_type = base_type(operand->type); @@ -3610,7 +3603,7 @@ break; } case BuiltinProc_slice_to_bytes: { - // proc slice_to_bytes(a: []T) -> []u8 + // slice_to_bytes :: proc(a: []T) -> []u8 Type *slice_type = base_type(operand->type); if (!is_type_slice(slice_type)) { gbString type_str = type_to_string(operand->type); @@ -3649,7 +3642,7 @@ break; } case BuiltinProc_min: { - // proc min(a, b: ordered) -> ordered + // min :: proc(a, b: ordered) -> ordered Type *type = base_type(operand->type); if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) { gbString type_str = type_to_string(operand->type); @@ -3724,7 +3717,7 @@ break; } case BuiltinProc_max: { - // proc min(a, b: ordered) -> ordered + // min :: proc(a, b: ordered) -> ordered Type *type = base_type(operand->type); if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) { gbString type_str = type_to_string(operand->type); @@ -3800,7 +3793,7 @@ break; } case BuiltinProc_abs: { - // proc abs(n: numeric) -> numeric + // abs :: proc(n: numeric) -> numeric if (!is_type_numeric(operand->type)) { gbString type_str = type_to_string(operand->type); error(call, "Expected a numeric type to 'abs', got '%s'", type_str); @@ -3848,7 +3841,7 @@ break; } case BuiltinProc_clamp: { - // proc clamp(a, min, max: ordered) -> ordered + // clamp :: proc(a, min, max: ordered) -> ordered Type *type = base_type(operand->type); if (!is_type_ordered(type) || !(is_type_numeric(type) || is_type_string(type))) { gbString type_str = type_to_string(operand->type); diff --git a/src/ir.cpp b/src/ir.cpp index 9103b5491..c98cec5f4 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -2192,6 +2192,8 @@ irValue *ir_map_cap(irProcedure *proc, irValue *value) { +void ir_emit_increment(irProcedure *proc, irValue *addr); +irValue *ir_emit_array_ep(irProcedure *proc, irValue *s, irValue *index); irValue *ir_emit_array_epi(irProcedure *proc, irValue *s, i32 index); irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index); @@ -2253,11 +2255,43 @@ irValue *ir_emit_arith(irProcedure *proc, TokenKind op, irValue *left, irValue * irValue *res = ir_add_local_generated(proc, type); i64 count = base_type(type)->Array.count; - for (i32 i = 0; i < count; i++) { - irValue *x = ir_emit_load(proc, ir_emit_array_epi(proc, lhs, i)); - irValue *y = ir_emit_load(proc, ir_emit_array_epi(proc, rhs, i)); + + bool inline_array_arith = type_size_of(type) <= build_context.max_align; + + if (inline_array_arith) { + // inline + for (i32 i = 0; i < count; i++) { + irValue *x = ir_emit_load(proc, ir_emit_array_epi(proc, lhs, i)); + irValue *y = ir_emit_load(proc, ir_emit_array_epi(proc, rhs, i)); + irValue *z = ir_emit_arith(proc, op, x, y, elem_type); + ir_emit_store(proc, ir_emit_array_epi(proc, res, i), z); + } + } else { + irValue *idx_addr = ir_add_local_generated(proc, t_int); + irValue *max = ir_const_int(proc->module->allocator, count); + + irBlock *body = ir_new_block(proc, nullptr, "array.arith.body"); + irBlock *done = ir_new_block(proc, nullptr, "array.arith.done"); + irBlock *loop = ir_new_block(proc, nullptr, "array.arith.loop"); + + ir_emit_jump(proc, loop); + ir_start_block(proc, loop); + + irValue *idx = ir_emit_load(proc, idx_addr); + + irValue *cond = ir_emit_comp(proc, Token_Lt, idx, max); + ir_emit_if(proc, cond, body, done); + ir_start_block(proc, body); + + irValue *x = ir_emit_load(proc, ir_emit_array_ep(proc, lhs, idx)); + irValue *y = ir_emit_load(proc, ir_emit_array_ep(proc, rhs, idx)); irValue *z = ir_emit_arith(proc, op, x, y, elem_type); - ir_emit_store(proc, ir_emit_array_epi(proc, res, i), z); + ir_emit_store(proc, ir_emit_array_ep(proc, res, idx), z); + + ir_emit_increment(proc, idx_addr); + ir_emit_jump(proc, loop); + + ir_start_block(proc, done); } ir_emit_comment(proc, str_lit("array.arith.end")); return ir_emit_load(proc, res); diff --git a/src/main.cpp b/src/main.cpp index 25ebc9dea..996d33089 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,4 @@ // #define NO_ARRAY_BOUNDS_CHECK -#define NO_POINTER_ARITHMETIC -#define NO_DEFAULT_STRUCT_VALUES #include "common.cpp" #include "timings.cpp"