mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-25 15:05:00 -07:00
intrinsics.vector type (Experimental)
This commit is contained in:
@@ -1008,6 +1008,20 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
|
||||
fmt_arg(fi, any{rawptr(data), info.elem.id}, verb);
|
||||
}
|
||||
|
||||
case runtime.Type_Info_Simd_Vector:
|
||||
if info.is_x86_mmx {
|
||||
strings.write_string(fi.buf, "intrinsics.x86_mmx<>");
|
||||
}
|
||||
strings.write_byte(fi.buf, '<');
|
||||
defer strings.write_byte(fi.buf, '>');
|
||||
for i in 0..info.count-1 {
|
||||
if i > 0 do strings.write_string(fi.buf, ", ");
|
||||
|
||||
data := uintptr(v.data) + uintptr(i*info.elem_size);
|
||||
fmt_arg(fi, any{rawptr(data), info.elem.id}, verb);
|
||||
}
|
||||
|
||||
|
||||
case runtime.Type_Info_Slice:
|
||||
strings.write_byte(fi.buf, '[');
|
||||
defer strings.write_byte(fi.buf, ']');
|
||||
@@ -1448,5 +1462,15 @@ write_type :: proc(buf: ^strings.Builder, ti: ^runtime.Type_Info) {
|
||||
write_string(buf, "opaque ");
|
||||
write_type(buf, info.elem);
|
||||
|
||||
case runtime.Type_Info_Simd_Vector:
|
||||
if info.is_x86_mmx {
|
||||
write_string(buf, "intrinsics.x86_mmx");
|
||||
} else {
|
||||
write_string(buf, "intrinsics.vector(");
|
||||
write_i64(buf, i64(info.count));
|
||||
write_string(buf, ", ");
|
||||
write_type(buf, info.elem);
|
||||
write_byte(buf, ')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,9 +112,14 @@ Type_Info_Bit_Set :: struct {
|
||||
lower: i64,
|
||||
upper: i64,
|
||||
};
|
||||
|
||||
Type_Info_Opaque :: struct {
|
||||
elem: ^Type_Info,
|
||||
};
|
||||
Type_Info_Simd_Vector :: struct {
|
||||
elem: ^Type_Info,
|
||||
elem_size: int,
|
||||
count: int,
|
||||
is_x86_mmx: bool,
|
||||
}
|
||||
|
||||
Type_Info :: struct {
|
||||
@@ -145,6 +150,7 @@ Type_Info :: struct {
|
||||
Type_Info_Bit_Field,
|
||||
Type_Info_Bit_Set,
|
||||
Type_Info_Opaque,
|
||||
Type_Info_Simd_Vector,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -267,3 +267,8 @@ is_opaque :: proc(info: ^rt.Type_Info) -> bool {
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Opaque);
|
||||
return ok;
|
||||
}
|
||||
is_simd_vector :: proc(info: ^rt.Type_Info) -> bool {
|
||||
if info == nil do return false;
|
||||
_, ok := rt.type_info_base(info).variant.(rt.Type_Info_Simd_Vector);
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -4072,6 +4072,46 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_vector: {
|
||||
Operand x = {};
|
||||
Operand y = {};
|
||||
x = *operand;
|
||||
if (!is_type_integer(x.type) || x.mode != Addressing_Constant) {
|
||||
error(call, "Expected a constant integer for 'intrinsics.vector'");
|
||||
operand->mode = Addressing_Type;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
if (x.value.value_integer.neg) {
|
||||
error(call, "Negative vector element length");
|
||||
operand->mode = Addressing_Type;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
i64 count = big_int_to_i64(&x.value.value_integer);
|
||||
|
||||
check_expr_or_type(c, &y, ce->args[1]);
|
||||
if (y.mode != Addressing_Type) {
|
||||
error(call, "Expected a type 'intrinsics.vector'");
|
||||
operand->mode = Addressing_Type;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
Type *elem = y.type;
|
||||
if (!is_type_valid_vector_elem(elem)) {
|
||||
gbString str = type_to_string(elem);
|
||||
error(call, "Invalid element type for 'intrinsics.vector', expected an integer or float with no specific endianness, got '%s'", str);
|
||||
gb_string_free(str);
|
||||
operand->mode = Addressing_Type;
|
||||
operand->type = t_invalid;
|
||||
return false;
|
||||
}
|
||||
|
||||
operand->mode = Addressing_Type;
|
||||
operand->type = alloc_type_simd_vector(count, elem);
|
||||
break;
|
||||
}
|
||||
|
||||
case BuiltinProc_atomic_fence:
|
||||
case BuiltinProc_atomic_fence_acq:
|
||||
case BuiltinProc_atomic_fence_rel:
|
||||
@@ -5902,6 +5942,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
||||
case Type_Slice:
|
||||
case Type_Array:
|
||||
case Type_DynamicArray:
|
||||
case Type_SimdVector:
|
||||
{
|
||||
Type *elem_type = nullptr;
|
||||
String context_name = {};
|
||||
@@ -5922,6 +5963,10 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
||||
|
||||
add_package_dependency(c, "runtime", "__dynamic_array_reserve");
|
||||
add_package_dependency(c, "runtime", "__dynamic_array_append");
|
||||
} else if (t->kind == Type_SimdVector) {
|
||||
elem_type = t->SimdVector.elem;
|
||||
context_name = str_lit("simd vector literal");
|
||||
max_type_count = t->SimdVector.count;
|
||||
} else {
|
||||
GB_PANIC("unreachable");
|
||||
}
|
||||
@@ -5972,6 +6017,15 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
||||
error(node, "Expected %lld values for this array literal, got %lld", cast(long long)t->Array.count, cast(long long)max);
|
||||
}
|
||||
}
|
||||
|
||||
if (t->kind == Type_SimdVector) {
|
||||
if (!is_constant) {
|
||||
error(node, "Expected all constant elements for a simd vector");
|
||||
}
|
||||
if (t->SimdVector.is_x86_mmx) {
|
||||
error(node, "Compound literals are not allowed with intrinsics.x86_mmx");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -712,6 +712,15 @@ void init_universal(void) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(bill): Set the correct arch for this
|
||||
if (bc->metrics.arch == TargetArch_amd64 || bc->metrics.arch == TargetArch_386) {
|
||||
t_vector_x86_mmx = alloc_type(Type_SimdVector);
|
||||
t_vector_x86_mmx->SimdVector.is_x86_mmx = true;
|
||||
|
||||
Entity *entity = alloc_entity(Entity_TypeName, nullptr, make_token_ident(str_lit("x86_mmx")), t_vector_x86_mmx);
|
||||
add_global_entity(entity, intrinsics_pkg->scope);
|
||||
}
|
||||
|
||||
|
||||
t_u8_ptr = alloc_type_pointer(t_u8);
|
||||
t_int_ptr = alloc_type_pointer(t_int);
|
||||
@@ -1248,6 +1257,10 @@ void add_type_info_type(CheckerContext *c, Type *t) {
|
||||
add_type_info_type(c, bt->Proc.results);
|
||||
break;
|
||||
|
||||
case Type_SimdVector:
|
||||
add_type_info_type(c, bt->SimdVector.elem);
|
||||
break;
|
||||
|
||||
default:
|
||||
GB_PANIC("Unhandled type: %*.s %d", LIT(type_strings[bt->kind]), bt->kind);
|
||||
break;
|
||||
@@ -1419,6 +1432,10 @@ void add_min_dep_type_info(Checker *c, Type *t) {
|
||||
add_min_dep_type_info(c, bt->Proc.results);
|
||||
break;
|
||||
|
||||
case Type_SimdVector:
|
||||
add_min_dep_type_info(c, bt->SimdVector.elem);
|
||||
break;
|
||||
|
||||
default:
|
||||
GB_PANIC("Unhandled type: %*.s", LIT(type_strings[bt->kind]));
|
||||
break;
|
||||
@@ -1795,6 +1812,7 @@ void init_core_type_info(Checker *c) {
|
||||
t_type_info_bit_field = find_core_type(c, str_lit("Type_Info_Bit_Field"));
|
||||
t_type_info_bit_set = find_core_type(c, str_lit("Type_Info_Bit_Set"));
|
||||
t_type_info_opaque = find_core_type(c, str_lit("Type_Info_Opaque"));
|
||||
t_type_info_simd_vector = find_core_type(c, str_lit("Type_Info_Simd_Vector"));
|
||||
|
||||
t_type_info_named_ptr = alloc_type_pointer(t_type_info_named);
|
||||
t_type_info_integer_ptr = alloc_type_pointer(t_type_info_integer);
|
||||
@@ -1818,6 +1836,7 @@ void init_core_type_info(Checker *c) {
|
||||
t_type_info_bit_field_ptr = alloc_type_pointer(t_type_info_bit_field);
|
||||
t_type_info_bit_set_ptr = alloc_type_pointer(t_type_info_bit_set);
|
||||
t_type_info_opaque_ptr = alloc_type_pointer(t_type_info_opaque);
|
||||
t_type_info_simd_vector_ptr = alloc_type_pointer(t_type_info_simd_vector);
|
||||
}
|
||||
|
||||
void init_mem_allocator(Checker *c) {
|
||||
|
||||
@@ -89,6 +89,8 @@ enum BuiltinProcId {
|
||||
BuiltinProc_DIRECTIVE, // NOTE(bill): This is used for specialized hash-prefixed procedures
|
||||
|
||||
// "Intrinsics"
|
||||
BuiltinProc_vector,
|
||||
|
||||
BuiltinProc_atomic_fence,
|
||||
BuiltinProc_atomic_fence_acq,
|
||||
BuiltinProc_atomic_fence_rel,
|
||||
@@ -194,6 +196,9 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
|
||||
|
||||
// "Intrinsics"
|
||||
{STR_LIT("vector"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, // Type
|
||||
|
||||
|
||||
{STR_LIT("atomic_fence"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("atomic_fence_acq"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("atomic_fence_rel"), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||
|
||||
+13
@@ -7268,6 +7268,7 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) {
|
||||
case Type_Array: et = bt->Array.elem; break;
|
||||
case Type_Slice: et = bt->Slice.elem; break;
|
||||
case Type_BitSet: et = bt->BitSet.elem; break;
|
||||
case Type_SimdVector: et = bt->SimdVector.elem; break;
|
||||
}
|
||||
|
||||
String proc_name = {};
|
||||
@@ -9995,6 +9996,18 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_opaque_ptr);
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), ir_get_type_info_ptr(proc, t->Opaque.elem));
|
||||
break;
|
||||
|
||||
case Type_SimdVector:
|
||||
ir_emit_comment(proc, str_lit("Type_SimdVector"));
|
||||
tag = ir_emit_conv(proc, variant_ptr, t_type_info_simd_vector_ptr);
|
||||
if (t->SimdVector.is_x86_mmx) {
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 3), v_true);
|
||||
} else {
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 0), ir_get_type_info_ptr(proc, t->SimdVector.elem));
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 1), ir_const_int(type_size_of(t->SimdVector.elem)));
|
||||
ir_emit_store(proc, ir_emit_struct_ep(proc, tag, 2), ir_const_int(t->SimdVector.count));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -574,6 +574,16 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t, bool in_struct) {
|
||||
case Type_Opaque:
|
||||
ir_print_type(f, m, strip_opaque_type(t));
|
||||
return;
|
||||
|
||||
case Type_SimdVector:
|
||||
if (t->SimdVector.is_x86_mmx) {
|
||||
ir_write_str_lit(f, "x86_mmx");
|
||||
} else {
|
||||
ir_fprintf(f, "<%lld x ", t->SimdVector.count);;
|
||||
ir_print_type(f, m, t->SimdVector.elem);
|
||||
ir_write_byte(f, '>');
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -802,6 +812,31 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
|
||||
}
|
||||
|
||||
ir_write_byte(f, ']');
|
||||
} else if (is_type_simd_vector(type)) {
|
||||
ast_node(cl, CompoundLit, value.value_compound);
|
||||
|
||||
Type *elem_type = type->SimdVector.elem;
|
||||
isize elem_count = cl->elems.count;
|
||||
if (elem_count == 0) {
|
||||
ir_write_str_lit(f, "zeroinitializer");
|
||||
break;
|
||||
}
|
||||
GB_ASSERT_MSG(elem_count == type->SimdVector.count, "%td != %td", elem_count, type->SimdVector.count);
|
||||
|
||||
ir_write_byte(f, '<');
|
||||
|
||||
for (isize i = 0; i < elem_count; i++) {
|
||||
if (i > 0) ir_write_str_lit(f, ", ");
|
||||
TypeAndValue tav = cl->elems[i]->tav;
|
||||
GB_ASSERT(tav.mode != Addressing_Invalid);
|
||||
ir_print_compound_element(f, m, tav.value, elem_type);
|
||||
}
|
||||
for (isize i = elem_count; i < type->SimdVector.count; i++) {
|
||||
if (i >= elem_count) ir_write_str_lit(f, ", ");
|
||||
ir_print_compound_element(f, m, empty_exact_value, elem_type);
|
||||
}
|
||||
|
||||
ir_write_byte(f, '>');
|
||||
} else if (is_type_struct(type)) {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||
defer (gb_temp_arena_memory_end(tmp));
|
||||
|
||||
+84
-60
@@ -215,6 +215,12 @@ struct TypeUnion {
|
||||
i64 lower; \
|
||||
i64 upper; \
|
||||
}) \
|
||||
TYPE_KIND(SimdVector, struct { \
|
||||
i64 count; \
|
||||
Type *elem; \
|
||||
bool is_x86_mmx; \
|
||||
}) \
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -460,13 +466,13 @@ gb_global Type *t_type_info_map = nullptr;
|
||||
gb_global Type *t_type_info_bit_field = nullptr;
|
||||
gb_global Type *t_type_info_bit_set = nullptr;
|
||||
gb_global Type *t_type_info_opaque = nullptr;
|
||||
gb_global Type *t_type_info_simd_vector = nullptr;
|
||||
|
||||
gb_global Type *t_type_info_named_ptr = nullptr;
|
||||
gb_global Type *t_type_info_integer_ptr = nullptr;
|
||||
gb_global Type *t_type_info_rune_ptr = nullptr;
|
||||
gb_global Type *t_type_info_float_ptr = nullptr;
|
||||
gb_global Type *t_type_info_complex_ptr = nullptr;
|
||||
gb_global Type *t_type_info_quaternion_ptr = nullptr;
|
||||
gb_global Type *t_type_info_any_ptr = nullptr;
|
||||
gb_global Type *t_type_info_typeid_ptr = nullptr;
|
||||
gb_global Type *t_type_info_string_ptr = nullptr;
|
||||
@@ -484,6 +490,7 @@ gb_global Type *t_type_info_map_ptr = nullptr;
|
||||
gb_global Type *t_type_info_bit_field_ptr = nullptr;
|
||||
gb_global Type *t_type_info_bit_set_ptr = nullptr;
|
||||
gb_global Type *t_type_info_opaque_ptr = nullptr;
|
||||
gb_global Type *t_type_info_simd_vector_ptr = nullptr;
|
||||
|
||||
gb_global Type *t_allocator = nullptr;
|
||||
gb_global Type *t_allocator_ptr = nullptr;
|
||||
@@ -496,6 +503,8 @@ gb_global Type *t_source_code_location_ptr = nullptr;
|
||||
gb_global Type *t_map_key = nullptr;
|
||||
gb_global Type *t_map_header = nullptr;
|
||||
|
||||
gb_global Type *t_vector_x86_mmx = nullptr;
|
||||
|
||||
|
||||
|
||||
i64 type_size_of (Type *t);
|
||||
@@ -722,6 +731,13 @@ Type *alloc_type_bit_set() {
|
||||
|
||||
|
||||
|
||||
Type *alloc_type_simd_vector(i64 count, Type *elem) {
|
||||
Type *t = alloc_type(Type_SimdVector);
|
||||
t->SimdVector.count = count;
|
||||
t->SimdVector.elem = elem;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
@@ -971,6 +987,11 @@ bool is_type_generic(Type *t) {
|
||||
return t->kind == Type_Generic;
|
||||
}
|
||||
|
||||
bool is_type_simd_vector(Type *t) {
|
||||
t = base_type(t);
|
||||
return t->kind == Type_SimdVector;
|
||||
}
|
||||
|
||||
|
||||
Type *core_array_type(Type *t) {
|
||||
for (;;) {
|
||||
@@ -1193,6 +1214,25 @@ Type *bit_set_to_int(Type *t) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool is_type_valid_vector_elem(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t->kind == Type_Basic) {
|
||||
if (t->Basic.flags & BasicFlag_EndianLittle) {
|
||||
return false;
|
||||
}
|
||||
if (t->Basic.flags & BasicFlag_EndianBig) {
|
||||
return false;
|
||||
}
|
||||
if (is_type_integer(t)) {
|
||||
return true;
|
||||
}
|
||||
if (is_type_float(t)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool is_type_indexable(Type *t) {
|
||||
Type *bt = base_type(t);
|
||||
@@ -1637,6 +1677,18 @@ bool are_types_identical(Type *x, Type *y) {
|
||||
are_types_identical(x->Map.value, y->Map.value);
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_SimdVector:
|
||||
if (y->kind == Type_SimdVector) {
|
||||
if (x->SimdVector.is_x86_mmx == y->SimdVector.is_x86_mmx) {
|
||||
if (x->SimdVector.is_x86_mmx) {
|
||||
return true;
|
||||
} else if (x->SimdVector.count == y->SimdVector.count) {
|
||||
return are_types_identical(x->SimdVector.elem, y->SimdVector.elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1681,65 +1733,6 @@ Type *default_type(Type *type) {
|
||||
return type;
|
||||
}
|
||||
|
||||
/*
|
||||
// NOTE(bill): Valid Compile time execution #run type
|
||||
bool is_type_cte_safe(Type *type) {
|
||||
type = default_type(base_type(type));
|
||||
switch (type->kind) {
|
||||
case Type_Basic:
|
||||
switch (type->Basic.kind) {
|
||||
case Basic_rawptr:
|
||||
case Basic_any:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
case Type_Pointer:
|
||||
return false;
|
||||
|
||||
case Type_Array:
|
||||
return is_type_cte_safe(type->Array.elem);
|
||||
|
||||
case Type_DynamicArray:
|
||||
return false;
|
||||
case Type_Map:
|
||||
return false;
|
||||
|
||||
case Type_Slice:
|
||||
return false;
|
||||
|
||||
case Type_Struct: {
|
||||
if (type->Struct.is_raw_union) {
|
||||
return false;
|
||||
}
|
||||
for_array(i, type->Struct.fields) {
|
||||
Entity *v = type->Struct.fields[i];
|
||||
if (!is_type_cte_safe(v->type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case Type_Tuple: {
|
||||
for_array(i, type->Tuple.variables) {
|
||||
Entity *v = type->Tuple.variables[i];
|
||||
if (!is_type_cte_safe(v->type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case Type_Proc:
|
||||
// TODO(bill): How should I handle procedures in the CTE stage?
|
||||
// return type->Proc.calling_convention == ProcCC_Odin;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
i64 union_variant_index(Type *u, Type *v) {
|
||||
u = base_type(u);
|
||||
GB_ASSERT(u->kind == Type_Union);
|
||||
@@ -2389,7 +2382,18 @@ i64 type_align_of_internal(Type *t, TypePath *path) {
|
||||
if (bits <= 32) return 4;
|
||||
if (bits <= 64) return 8;
|
||||
return 8; // NOTE(bill): Could be an invalid range so limit it for now
|
||||
}
|
||||
|
||||
case Type_SimdVector: {
|
||||
if (t->SimdVector.is_x86_mmx) {
|
||||
return 8;
|
||||
}
|
||||
// align of
|
||||
i64 count = t->SimdVector.count;
|
||||
Type *elem = t->SimdVector.elem;
|
||||
i64 size = count * type_size_of_internal(elem, path);
|
||||
// IMPORTANT TODO(bill): Figure out the alignment of vector types
|
||||
return gb_clamp(next_pow2(type_size_of_internal(t, path)), 1, build_context.max_align);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2622,6 +2626,15 @@ i64 type_size_of_internal(Type *t, TypePath *path) {
|
||||
if (bits <= 64) return 8;
|
||||
return 8; // NOTE(bill): Could be an invalid range so limit it for now
|
||||
}
|
||||
|
||||
case Type_SimdVector: {
|
||||
if (t->SimdVector.is_x86_mmx) {
|
||||
return 8;
|
||||
}
|
||||
i64 count = t->SimdVector.count;
|
||||
Type *elem = t->SimdVector.elem;
|
||||
return count * type_size_of_internal(elem, path);
|
||||
}
|
||||
}
|
||||
|
||||
// Catch all
|
||||
@@ -2950,6 +2963,17 @@ gbString write_type_to_string(gbString str, Type *type) {
|
||||
}
|
||||
str = gb_string_appendc(str, "]");
|
||||
break;
|
||||
|
||||
case Type_SimdVector:
|
||||
if (type->SimdVector.is_x86_mmx) {
|
||||
return "intrinsics.x86_mmx";
|
||||
} else {
|
||||
str = gb_string_appendc(str, "intrinsics.vector(");
|
||||
str = gb_string_append_fmt(str, "%d, ", cast(int)type->SimdVector.count);
|
||||
str = write_type_to_string(str, type->SimdVector.elem);
|
||||
str = gb_string_appendc(str, ")");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return str;
|
||||
|
||||
Reference in New Issue
Block a user