mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 01:21:38 -07:00
Merge branch 'master' into bill/new-slice-sort
This commit is contained in:
@@ -636,6 +636,8 @@ _cleanup_runtime_contextless :: proc "contextless" () {
|
||||
/////////////////////////////
|
||||
|
||||
|
||||
// type_info_base returns the base-type of a `^Type_Info` stripping the `distinct`ness from the first level
|
||||
@(require_results)
|
||||
type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
||||
if info == nil {
|
||||
return nil
|
||||
@@ -652,6 +654,10 @@ type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
||||
}
|
||||
|
||||
|
||||
// type_info_core returns the core-type of a `^Type_Info` stripping the `distinct`ness from the first level AND/OR
|
||||
// returns the backing integer type of an enum or bit_set `^Type_Info`.
|
||||
// This is also aliased as `type_info_base_without_enum`
|
||||
@(require_results)
|
||||
type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
||||
if info == nil {
|
||||
return nil
|
||||
@@ -668,6 +674,10 @@ type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
||||
}
|
||||
return base
|
||||
}
|
||||
|
||||
// type_info_base_without_enum returns the core-type of a `^Type_Info` stripping the `distinct`ness from the first level AND/OR
|
||||
// returns the backing integer type of an enum or bit_set `^Type_Info`.
|
||||
// This is also aliased as `type_info_core`
|
||||
type_info_base_without_enum :: type_info_core
|
||||
|
||||
__type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check {
|
||||
@@ -684,15 +694,23 @@ __type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check
|
||||
}
|
||||
|
||||
when !ODIN_NO_RTTI {
|
||||
// typeid_base returns the base-type of a `typeid` stripping the `distinct`ness from the first level
|
||||
typeid_base :: proc "contextless" (id: typeid) -> typeid {
|
||||
ti := type_info_of(id)
|
||||
ti = type_info_base(ti)
|
||||
return ti.id
|
||||
}
|
||||
// typeid_core returns the core-type of a `typeid` stripping the `distinct`ness from the first level AND/OR
|
||||
// returns the backing integer type of an enum or bit_set `typeid`.
|
||||
// This is also aliased as `typeid_base_without_enum`
|
||||
typeid_core :: proc "contextless" (id: typeid) -> typeid {
|
||||
ti := type_info_core(type_info_of(id))
|
||||
return ti.id
|
||||
}
|
||||
|
||||
// typeid_base_without_enum returns the core-type of a `typeid` stripping the `distinct`ness from the first level AND/OR
|
||||
// returns the backing integer type of an enum or bit_set `typeid`.
|
||||
// This is also aliased as `typeid_core`
|
||||
typeid_base_without_enum :: typeid_core
|
||||
}
|
||||
|
||||
@@ -708,11 +726,15 @@ default_logger_proc :: proc(data: rawptr, level: Logger_Level, text: string, opt
|
||||
// Nothing
|
||||
}
|
||||
|
||||
// Returns the default logger used by `context.logger`
|
||||
@(require_results)
|
||||
default_logger :: proc() -> Logger {
|
||||
return Logger{default_logger_proc, nil, Logger_Level.Debug, nil}
|
||||
}
|
||||
|
||||
|
||||
// Returns the default `context`
|
||||
@(require_results)
|
||||
default_context :: proc "contextless" () -> Context {
|
||||
c: Context
|
||||
__init_context(&c)
|
||||
|
||||
@@ -134,8 +134,13 @@ equal_fold :: proc(u, v: []byte) -> bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO(bill): Unicode folding
|
||||
|
||||
r := unicode.simple_fold(sr)
|
||||
for r != sr && r < tr {
|
||||
r = unicode.simple_fold(sr)
|
||||
}
|
||||
if r == tr {
|
||||
continue loop
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -128,9 +128,9 @@ find_value :: proc(t: ^$T/Tree($Key, $Value), key: Key) -> (value: Value, ok: bo
|
||||
return
|
||||
}
|
||||
|
||||
// find_or_insert attempts to insert the value into the tree, and returns
|
||||
// the node, a boolean indicating if the value was inserted, and the
|
||||
// node allocator error if relevant. If the value is already present, the existing node is updated.
|
||||
// find_or_insert attempts to insert the key-value pair into the tree, and returns
|
||||
// the node, a boolean indicating if a new node was inserted, and the
|
||||
// node allocator error if relevant. If the key is already present, the existing node is updated and returned.
|
||||
find_or_insert :: proc(t: ^$T/Tree($Key, $Value), key: Key, value: Value) -> (n: ^Node(Key, Value), inserted: bool, err: runtime.Allocator_Error) {
|
||||
n_ptr := &t._root
|
||||
for n_ptr^ != nil {
|
||||
@@ -141,6 +141,7 @@ find_or_insert :: proc(t: ^$T/Tree($Key, $Value), key: Key, value: Value) -> (n:
|
||||
case .Greater:
|
||||
n_ptr = &n._right
|
||||
case .Equal:
|
||||
n.value = value
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
+6
-1
@@ -402,7 +402,12 @@ remap :: proc "contextless" (old_value, old_min, old_max, new_min, new_max: $T)
|
||||
if old_range == 0 {
|
||||
return new_range / 2
|
||||
}
|
||||
return ((old_value - old_min) / old_range) * new_range + new_min
|
||||
|
||||
when intrinsics.type_is_integer(T) {
|
||||
return (((old_value - old_min)) * new_range) / old_range + new_min
|
||||
} else {
|
||||
return ((old_value - old_min) / old_range) * new_range + new_min
|
||||
}
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
|
||||
+46
-24
@@ -153,7 +153,7 @@ when !ODIN_NO_RTTI {
|
||||
}
|
||||
|
||||
|
||||
// any_base returns an `any` whether the `typeid` has been replaced with the `base-type` equivalent
|
||||
// any_base returns an `any` where the `typeid` has been replaced with the `base-type` equivalent
|
||||
@(require_results)
|
||||
any_base :: proc(v: any) -> any {
|
||||
v := v
|
||||
@@ -163,7 +163,7 @@ any_base :: proc(v: any) -> any {
|
||||
return v
|
||||
}
|
||||
|
||||
// any_core returns an `any` whether the `typeid` has been replaced with the `core-type` equivalent
|
||||
// any_core returns an `any` where the `typeid` has been replaced with the `core-type` equivalent
|
||||
@(require_results)
|
||||
any_core :: proc(v: any) -> any {
|
||||
v := v
|
||||
@@ -368,7 +368,7 @@ capacity :: proc(val: any) -> int {
|
||||
}
|
||||
|
||||
|
||||
// Dynamically indexes `any` as an indexable-type if possbiel. Returns `nil` if not possible
|
||||
// Dynamically indexes `any` as an indexable-type if possible. Returns `nil` if not possible
|
||||
@(require_results)
|
||||
index :: proc(val: any, i: int, loc := #caller_location) -> any {
|
||||
if val == nil { return nil }
|
||||
@@ -455,13 +455,13 @@ deref :: proc(val: any) -> any {
|
||||
|
||||
|
||||
|
||||
// Struct_Tag represents the type of the string of a struct field
|
||||
// `Struct_Tag` represents the type of the `string` of a struct field
|
||||
//
|
||||
// Through convention, tags are the concatenation of optionally space separationed key:"value" pairs.
|
||||
// Through convention, tags are the concatenation of optionally space-separated key:"value" pairs.
|
||||
// Each key is a non-empty string which contains no control characters other than space, quotes, and colon.
|
||||
Struct_Tag :: distinct string
|
||||
|
||||
// Struct_Field represents a information of a field of a struct
|
||||
// `Struct_Field` represents a information of a field of a struct
|
||||
Struct_Field :: struct {
|
||||
name: string,
|
||||
type: ^Type_Info,
|
||||
@@ -541,8 +541,8 @@ struct_field_value_by_name :: proc(a: any, field: string, allow_using := false)
|
||||
|
||||
// Returns an `any` of a struct field specified by a `Struct_Field`
|
||||
// Example:
|
||||
// v := struct_field_value_by_name(the_struct, field)
|
||||
// nested_value_through_using := struct_field_value_by_name(the_struct, field, allow_using=true)
|
||||
// field := struct_field_value_by_name(the_struct, "field_name")
|
||||
// value_by_field := struct_field_value(the_struct, field)
|
||||
@(require_results)
|
||||
struct_field_value :: proc(a: any, field: Struct_Field) -> any {
|
||||
if a == nil { return nil }
|
||||
@@ -573,7 +573,7 @@ struct_field_types :: proc(T: typeid) -> []^Type_Info {
|
||||
}
|
||||
|
||||
|
||||
// Returns a `[]Struct_Type` of the tags of the struct fields of type `T`
|
||||
// Returns a `[]Struct_Tag` of the tags of the struct fields of type `T`
|
||||
@(require_results)
|
||||
struct_field_tags :: proc(T: typeid) -> []Struct_Tag {
|
||||
ti := runtime.type_info_base(type_info_of(T))
|
||||
@@ -673,23 +673,23 @@ struct_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Struct_Field) {
|
||||
|
||||
|
||||
// struct_tag_get returns the value associated with a key in the tag string.
|
||||
// If the key is present in the tag, the value (which might be empty) is return. Otherwise an empty string is returned.
|
||||
// If the key is present in the tag, the value (which might be empty) is returned. Otherwise an empty string is returned.
|
||||
// This is just a wrapper around `struct_tag_lookup` with the `ok` value being ignored.
|
||||
//
|
||||
// The convention for is usually of the form:
|
||||
// The convention for struct tags is usually of the form:
|
||||
//
|
||||
// `key:"value" another:"set" and:"whatever"`
|
||||
@(require_results)
|
||||
struct_tag_get :: proc(tag: Struct_Tag, key: string) -> (value: string) {
|
||||
v, _ := struct_tag_lookup(tag, key)
|
||||
return string(v)
|
||||
return v
|
||||
}
|
||||
|
||||
// struct_tag_lookup returns the value associated with a key in the tag string.
|
||||
// If the key is present in the tag, the value (which might be empty) is return. Otherwise an empty string is returned.
|
||||
// The `ok` value returns whether the value was explicit set in the tag string.
|
||||
//
|
||||
// The convention for is usually of the form:
|
||||
// The convention for struct tags is usually of the form:
|
||||
//
|
||||
// `key:"value" another:"set" and:"whatever"`
|
||||
@(require_results)
|
||||
@@ -770,7 +770,7 @@ enum_string :: proc(a: any) -> string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Given a enum type and a value name, get the enum value.
|
||||
// Given an enum type and a value name, get the enum value.
|
||||
@(require_results)
|
||||
enum_from_name :: proc($Enum_Type: typeid, name: string) -> (value: Enum_Type, ok: bool) {
|
||||
ti := type_info_base(type_info_of(Enum_Type))
|
||||
@@ -917,7 +917,7 @@ type_info_union_is_pure_maybe :: proc(info: runtime.Type_Info_Union) -> bool {
|
||||
return len(info.variants) == 1 && is_pointer_internally(info.variants[0])
|
||||
}
|
||||
|
||||
// Returns `typeid` of a any-encoded union type. Panics if a union was not passed.
|
||||
// UNSAFE: Returns `typeid` of a any-encoded union type. Panics if a union was not passed.
|
||||
@(require_results)
|
||||
union_variant_typeid :: proc(a: any) -> typeid {
|
||||
if a == nil { return nil }
|
||||
@@ -1003,7 +1003,7 @@ get_union_variant :: proc(a: any) -> any {
|
||||
return any{a.data, id}
|
||||
}
|
||||
|
||||
// Converts a pointer to a union to a union containing the pointers to the variant types, and stores a pointer of the variant value in the new union
|
||||
// Converts a pointer to a union, to a union containing the pointers to the variant types, and stores a pointer of the variant value in the new union
|
||||
//
|
||||
// Example:
|
||||
// val: union{i32, f32, string}
|
||||
@@ -1114,7 +1114,7 @@ set_union_variant_type_info :: proc(a: any, tag_ti: ^Type_Info) {
|
||||
panic("expected a union to reflect.set_union_variant_type_info")
|
||||
}
|
||||
|
||||
// UNSAFE: Manually set the variant value of a union using an any. Panics if a union was not passed.
|
||||
// UNSAFE: Manually set the variant value of a union using an `any`. Panics if a union was not passed.
|
||||
set_union_value :: proc(dst: any, value: any) -> bool {
|
||||
if dst == nil { return false }
|
||||
|
||||
@@ -1153,7 +1153,7 @@ set_union_value :: proc(dst: any, value: any) -> bool {
|
||||
panic("expected a union to reflect.set_union_variant_typeid")
|
||||
}
|
||||
|
||||
// Checks to see if the data stored is a bit_set and is big_ending. Panics if a bit_set was not passed.
|
||||
// UNSAFE: Checks to see if the data stored is a `bit_set` and is big endian. Panics if a `bit_set` was not passed.
|
||||
@(require_results)
|
||||
bit_set_is_big_endian :: proc(value: any, loc := #caller_location) -> bool {
|
||||
if value == nil { return ODIN_ENDIAN == .Big }
|
||||
@@ -1185,7 +1185,7 @@ Bit_Field :: struct {
|
||||
tag: Struct_Tag,
|
||||
}
|
||||
|
||||
// Returns the fields of a bit_field type `T` as an `#soa` slice.
|
||||
// Returns the fields of a `bit_field` type `T` as an `#soa` slice.
|
||||
// This is useful to iterate over.
|
||||
// Example:
|
||||
// for field, i in reflect.bit_fields_zipped(Foo_Bit_Field) { ... }
|
||||
@@ -1204,7 +1204,7 @@ bit_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Bit_Field) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// bit_field_names returns a `[]string` of the field names of a bit_field type `T`
|
||||
// bit_field_names returns a `[]string` of the field names of a `bit_field` type `T`
|
||||
@(require_results)
|
||||
bit_field_names :: proc(T: typeid) -> []string {
|
||||
ti := runtime.type_info_base(type_info_of(T))
|
||||
@@ -1214,7 +1214,7 @@ bit_field_names :: proc(T: typeid) -> []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// bit_field_types returns a `[]^Type_Info` of the field representation types of a bit_field type `T`, not the backing integer-bit-width types
|
||||
// bit_field_types returns a `[]^Type_Info` of the field representation types of a `bit_field` type `T`, not the backing integer-bit-width types
|
||||
@(require_results)
|
||||
bit_field_types :: proc(T: typeid) -> []^Type_Info {
|
||||
ti := runtime.type_info_base(type_info_of(T))
|
||||
@@ -1224,7 +1224,7 @@ bit_field_types :: proc(T: typeid) -> []^Type_Info {
|
||||
return nil
|
||||
}
|
||||
|
||||
// bit_field_types returns a `[]uintptr` of the field bit-width-sizes of a bit_field type `T`
|
||||
// bit_field_types returns a `[]uintptr` of the field bit-width-sizes of a `bit_field` type `T`
|
||||
@(require_results)
|
||||
bit_field_sizes :: proc(T: typeid) -> []uintptr {
|
||||
ti := runtime.type_info_base(type_info_of(T))
|
||||
@@ -1234,7 +1234,7 @@ bit_field_sizes :: proc(T: typeid) -> []uintptr {
|
||||
return nil
|
||||
}
|
||||
|
||||
// bit_field_types returns a `[]uintptr` of the field offsets in bits of a bit_field type `T`
|
||||
// bit_field_types returns a `[]uintptr` of the field offsets in bits of a `bit_field` type `T`
|
||||
@(require_results)
|
||||
bit_field_offsets :: proc(T: typeid) -> []uintptr {
|
||||
ti := runtime.type_info_base(type_info_of(T))
|
||||
@@ -1244,7 +1244,7 @@ bit_field_offsets :: proc(T: typeid) -> []uintptr {
|
||||
return nil
|
||||
}
|
||||
|
||||
// bit_field_types returns a `[]Struct_Tag` of the field tags of a bit_field type `T`
|
||||
// bit_field_types returns a `[]Struct_Tag` of the field tags of a `bit_field` type `T`
|
||||
@(require_results)
|
||||
bit_field_tags :: proc(T: typeid) -> []Struct_Tag {
|
||||
ti := runtime.type_info_base(type_info_of(T))
|
||||
@@ -1655,6 +1655,27 @@ as_string :: proc(a: any) -> (value: string, valid: bool) {
|
||||
return
|
||||
}
|
||||
|
||||
// as_string16 attempts to convert an `any` to a `string16`.
|
||||
@(require_results)
|
||||
as_string16 :: proc(a: any) -> (value: string16, valid: bool) {
|
||||
if a == nil { return }
|
||||
a := a
|
||||
ti := runtime.type_info_core(type_info_of(a.id))
|
||||
a.id = ti.id
|
||||
|
||||
#partial switch info in ti.variant {
|
||||
case Type_Info_String:
|
||||
valid = true
|
||||
switch v in a {
|
||||
case string16: value = v
|
||||
case cstring16: value = string16(v)
|
||||
case: valid = false
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
relative_pointer_to_absolute_raw :: proc(data: rawptr, base_integer_id: typeid) -> rawptr {
|
||||
_handle :: proc(ptr: ^$T) -> rawptr where intrinsics.type_is_integer(T) {
|
||||
@@ -1770,6 +1791,7 @@ DEFAULT_EQUAL_MAX_RECURSION_LEVEL :: 32
|
||||
not_equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_level := 0) -> bool {
|
||||
return !equal(a, b, including_indirect_array_recursion, recursion_level)
|
||||
}
|
||||
|
||||
// Checks to see if two `any` values are semantically equivalent
|
||||
@(require_results)
|
||||
equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_level := 0) -> bool {
|
||||
|
||||
@@ -436,8 +436,13 @@ equal_fold :: proc(u, v: string) -> (res: bool) {
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO(bill): Unicode folding
|
||||
|
||||
r := unicode.simple_fold(sr)
|
||||
for r != sr && r < tr {
|
||||
r = unicode.simple_fold(sr)
|
||||
}
|
||||
if r == tr {
|
||||
continue loop
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -6211,7 +6211,6 @@ gb_internal isize get_procedure_param_count_excluding_defaults(Type *pt, isize *
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7483,8 +7482,6 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c,
|
||||
Entity *e = proc_entities[valids[0].index];
|
||||
GB_ASSERT(e != nullptr);
|
||||
|
||||
Array<Operand> named_operands = {};
|
||||
|
||||
check_call_arguments_single(c, call, operand,
|
||||
e, e->type,
|
||||
positional_operands, named_operands,
|
||||
|
||||
+111
-18
@@ -81,7 +81,7 @@ gb_internal String lb_get_const_string(lbModule *m, lbValue value) {
|
||||
}
|
||||
|
||||
|
||||
gb_internal LLVMValueRef llvm_const_cast(LLVMValueRef val, LLVMTypeRef dst, bool *failure_) {
|
||||
gb_internal LLVMValueRef llvm_const_cast(lbModule *m, LLVMValueRef val, LLVMTypeRef dst, bool *failure_) {
|
||||
LLVMTypeRef src = LLVMTypeOf(val);
|
||||
if (src == dst) {
|
||||
return val;
|
||||
@@ -93,14 +93,33 @@ gb_internal LLVMValueRef llvm_const_cast(LLVMValueRef val, LLVMTypeRef dst, bool
|
||||
GB_ASSERT_MSG(lb_sizeof(dst) == lb_sizeof(src), "%s vs %s", LLVMPrintTypeToString(dst), LLVMPrintTypeToString(src));
|
||||
LLVMTypeKind kind = LLVMGetTypeKind(dst);
|
||||
switch (kind) {
|
||||
case LLVMPointerTypeKind:
|
||||
case LLVMPointerTypeKind: {
|
||||
return LLVMConstPointerCast(val, dst);
|
||||
case LLVMStructTypeKind:
|
||||
if (LLVMTypeOf(val) != dst) {
|
||||
if (failure_) *failure_ = true;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
case LLVMStructTypeKind: {
|
||||
unsigned src_n = LLVMCountStructElementTypes(src);
|
||||
unsigned dst_n = LLVMCountStructElementTypes(dst);
|
||||
if (src_n != dst_n) goto failure;
|
||||
|
||||
LLVMValueRef *field_vals = temporary_alloc_array<LLVMValueRef>(dst_n);
|
||||
for (unsigned i = 0; i < dst_n; i++) {
|
||||
LLVMValueRef field_val = llvm_const_extract_value(m, val, i);
|
||||
if (field_val == nullptr) goto failure;
|
||||
|
||||
LLVMTypeRef dst_elem_ty = LLVMStructGetTypeAtIndex(dst, i);
|
||||
field_vals[i] = llvm_const_cast(m, field_val, dst_elem_ty, failure_);
|
||||
if (failure_ && *failure_) goto failure;
|
||||
}
|
||||
|
||||
if (!LLVMIsLiteralStruct(dst)) {
|
||||
return LLVMConstNamedStruct(dst, field_vals, dst_n);
|
||||
} else {
|
||||
return LLVMConstStructInContext(m->ctx, field_vals, dst_n, LLVMIsPackedStruct(dst));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
failure:
|
||||
if (failure_) *failure_ = true;
|
||||
return val;
|
||||
}
|
||||
@@ -192,7 +211,7 @@ gb_internal LLVMValueRef llvm_const_named_struct_internal(lbModule *m, LLVMTypeR
|
||||
bool failure = false;
|
||||
for (unsigned i = 0; i < elem_count; i++) {
|
||||
LLVMTypeRef elem_type = LLVMStructGetTypeAtIndex(t, i);
|
||||
values[i] = llvm_const_cast(values[i], elem_type, &failure);
|
||||
values[i] = llvm_const_cast(m, values[i], elem_type, &failure);
|
||||
}
|
||||
|
||||
if (failure) {
|
||||
@@ -205,7 +224,7 @@ gb_internal LLVMValueRef llvm_const_array(lbModule *m, LLVMTypeRef elem_type, LL
|
||||
unsigned value_count = cast(unsigned)value_count_;
|
||||
bool failure = false;
|
||||
for (unsigned i = 0; i < value_count; i++) {
|
||||
values[i] = llvm_const_cast(values[i], elem_type, &failure);
|
||||
values[i] = llvm_const_cast(m, values[i], elem_type, &failure);
|
||||
}
|
||||
if (failure) {
|
||||
return LLVMConstStructInContext(m->ctx, values, value_count, false);
|
||||
@@ -549,6 +568,83 @@ gb_internal bool lb_is_nested_possibly_constant(Type *ft, Selection const &sel,
|
||||
return lb_is_elem_const(elem, ft);
|
||||
}
|
||||
|
||||
LLVMValueRef llvm_const_pad_to_size(lbModule *m, LLVMValueRef val, LLVMTypeRef dst_ty) {
|
||||
LLVMContextRef ctx = m->ctx;
|
||||
LLVMTargetDataRef td = LLVMGetModuleDataLayout(m->mod);
|
||||
LLVMTypeRef src_ty = LLVMTypeOf(val);
|
||||
unsigned src_bits = (unsigned)LLVMSizeOfTypeInBits(td, src_ty);
|
||||
unsigned dst_bits = (unsigned)LLVMSizeOfTypeInBits(td, dst_ty);
|
||||
|
||||
LLVMValueRef as_int = nullptr;
|
||||
LLVMTypeKind src_kind = LLVMGetTypeKind(src_ty);
|
||||
|
||||
if (src_kind == LLVMIntegerTypeKind ||
|
||||
src_kind == LLVMFloatTypeKind ||
|
||||
src_kind == LLVMDoubleTypeKind ||
|
||||
src_kind == LLVMPointerTypeKind ||
|
||||
src_kind == LLVMVectorTypeKind) {
|
||||
LLVMTypeRef src_int_ty = LLVMIntTypeInContext(ctx, src_bits);
|
||||
as_int = LLVMConstBitCast(val, src_int_ty);
|
||||
|
||||
} else if (src_kind == LLVMArrayTypeKind) {
|
||||
unsigned elem_count = LLVMGetArrayLength(src_ty);
|
||||
LLVMTypeRef elem_ty = LLVMGetElementType(src_ty);
|
||||
unsigned elem_bits = (unsigned)LLVMSizeOfTypeInBits(td, elem_ty);
|
||||
LLVMTypeRef src_int_ty = LLVMIntTypeInContext(ctx, src_bits);
|
||||
as_int = LLVMConstInt(src_int_ty, 0, false);
|
||||
|
||||
for (unsigned i = 0; i < elem_count; i++) {
|
||||
LLVMValueRef elem = llvm_const_extract_value(m, val, i);
|
||||
LLVMTypeRef elem_int_ty = LLVMIntTypeInContext(ctx, elem_bits);
|
||||
LLVMValueRef elem_int = llvm_const_pad_to_size(m, elem, elem_int_ty);
|
||||
LLVMValueRef shifted = llvm_const_shl(m, llvm_const_zext(m, elem_int, src_int_ty), LLVMConstInt(src_int_ty, i * elem_bits, false));
|
||||
as_int = llvm_const_or(m, as_int, shifted);
|
||||
}
|
||||
} else {
|
||||
gb_printf_err("unsupported const_pad source type: %s\n", LLVMPrintTypeToString(src_ty));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (src_bits != dst_bits) {
|
||||
LLVMTypeRef dst_int_ty = LLVMIntTypeInContext(ctx, dst_bits);
|
||||
if (src_bits < dst_bits) {
|
||||
as_int = llvm_const_zext(m, as_int, dst_int_ty);
|
||||
} else {
|
||||
as_int = LLVMConstTrunc(as_int, dst_int_ty);
|
||||
}
|
||||
}
|
||||
|
||||
LLVMTypeKind dst_kind = LLVMGetTypeKind(dst_ty);
|
||||
|
||||
if (dst_kind == LLVMIntegerTypeKind ||
|
||||
dst_kind == LLVMFloatTypeKind ||
|
||||
dst_kind == LLVMDoubleTypeKind ||
|
||||
dst_kind == LLVMPointerTypeKind ||
|
||||
dst_kind == LLVMVectorTypeKind) {
|
||||
return LLVMConstBitCast(as_int, dst_ty);
|
||||
|
||||
} else if (dst_kind == LLVMArrayTypeKind) {
|
||||
unsigned elem_count = LLVMGetArrayLength(dst_ty);
|
||||
LLVMTypeRef elem_ty = LLVMGetElementType(dst_ty);
|
||||
unsigned elem_bits = (unsigned)LLVMSizeOfTypeInBits(td, elem_ty);
|
||||
|
||||
LLVMValueRef *elems = temporary_alloc_array<LLVMValueRef>(elem_count);
|
||||
LLVMTypeRef as_int_ty = LLVMTypeOf(as_int);
|
||||
|
||||
for (unsigned i = 0; i < elem_count; i++) {
|
||||
LLVMValueRef shifted = llvm_const_lshr(m, as_int, LLVMConstInt(as_int_ty, i * elem_bits, false));
|
||||
LLVMTypeRef elem_int_ty = LLVMIntTypeInContext(ctx, elem_bits);
|
||||
LLVMValueRef trunc = LLVMConstTrunc(shifted, elem_int_ty);
|
||||
elems[i] = llvm_const_pad_to_size(m, trunc, elem_ty);
|
||||
}
|
||||
|
||||
return LLVMConstArray(elem_ty, elems, elem_count);
|
||||
}
|
||||
|
||||
gb_printf_err("unsupported const_pad destination type: %s\n", LLVMPrintTypeToString(dst_ty));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lbConstContext cc, Type *value_type) {
|
||||
if (cc.allow_local) {
|
||||
cc.is_rodata = false;
|
||||
@@ -634,14 +730,11 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
|
||||
lbValue cv = lb_const_value(m, value_type, value, cc, value_type);
|
||||
Type *variant_type = cv.type;
|
||||
|
||||
LLVMValueRef values[4] = {};
|
||||
LLVMValueRef values[3] = {};
|
||||
unsigned value_count = 0;
|
||||
|
||||
values[value_count++] = cv.value;
|
||||
if (type_size_of(variant_type) != block_size) {
|
||||
LLVMTypeRef padding_type = lb_type_padding_filler(m, block_size - type_size_of(variant_type), 1);
|
||||
values[value_count++] = LLVMConstNull(padding_type);
|
||||
}
|
||||
LLVMTypeRef block_type = lb_type_internal_union_block_type(m, bt);
|
||||
values[value_count++] = llvm_const_pad_to_size(m, cv.value, block_type);
|
||||
|
||||
Type *tag_type = union_tag_type(bt);
|
||||
LLVMTypeRef llvm_tag_type = lb_type(m, tag_type);
|
||||
@@ -870,7 +963,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
|
||||
Type *elem = type->Matrix.elem;
|
||||
|
||||
lbValue single_elem = lb_const_value(m, elem, value, cc);
|
||||
single_elem.value = llvm_const_cast(single_elem.value, lb_type(m, elem), /*failure_*/nullptr);
|
||||
single_elem.value = llvm_const_cast(m, single_elem.value, lb_type(m, elem), /*failure_*/nullptr);
|
||||
|
||||
i64 total_elem_count = matrix_type_total_internal_elems(type);
|
||||
LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, cast(isize)total_elem_count);
|
||||
@@ -892,7 +985,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
|
||||
Type *elem = type->SimdVector.elem;
|
||||
|
||||
lbValue single_elem = lb_const_value(m, elem, value, cc);
|
||||
single_elem.value = llvm_const_cast(single_elem.value, lb_type(m, elem), /*failure_*/nullptr);
|
||||
single_elem.value = llvm_const_cast(m, single_elem.value, lb_type(m, elem), /*failure_*/nullptr);
|
||||
|
||||
LLVMValueRef *elems = gb_alloc_array(permanent_allocator(), LLVMValueRef, count);
|
||||
for (i64 i = 0; i < count; i++) {
|
||||
@@ -1472,7 +1565,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
|
||||
values[i] = LLVMConstNull(et);
|
||||
}
|
||||
for (isize i = 0; i < total_elem_count; i++) {
|
||||
values[i] = llvm_const_cast(values[i], et, /*failure_*/nullptr);
|
||||
values[i] = llvm_const_cast(m, values[i], et, /*failure_*/nullptr);
|
||||
}
|
||||
|
||||
res.value = LLVMConstVector(values, cast(unsigned)total_elem_count);
|
||||
|
||||
@@ -449,6 +449,31 @@ gb_internal LLVMValueRef llvm_const_insert_value(lbModule *m, LLVMValueRef agg,
|
||||
}
|
||||
|
||||
|
||||
gb_internal LLVMValueRef llvm_const_shl(lbModule *m, LLVMValueRef a, LLVMValueRef b) {
|
||||
LLVMValueRef res = LLVMBuildShl(m->const_dummy_builder, a, b, "");
|
||||
GB_ASSERT(LLVMIsConstant(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
gb_internal LLVMValueRef llvm_const_lshr(lbModule *m, LLVMValueRef a, LLVMValueRef b) {
|
||||
LLVMValueRef res = LLVMBuildLShr(m->const_dummy_builder, a, b, "");
|
||||
GB_ASSERT(LLVMIsConstant(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
gb_internal LLVMValueRef llvm_const_or(lbModule *m, LLVMValueRef a, LLVMValueRef b) {
|
||||
LLVMValueRef res = LLVMBuildOr(m->const_dummy_builder, a, b, "");
|
||||
GB_ASSERT(LLVMIsConstant(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
gb_internal LLVMValueRef llvm_const_zext(lbModule *m, LLVMValueRef a, LLVMTypeRef b) {
|
||||
LLVMValueRef res = LLVMBuildZExt(m->const_dummy_builder, a, b, "");
|
||||
GB_ASSERT(LLVMIsConstant(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
gb_internal LLVMValueRef llvm_cstring(lbModule *m, String const &str) {
|
||||
|
||||
+2
-2
@@ -566,9 +566,9 @@ foreign lib {
|
||||
pcm_rb_uninit :: proc(pRB: ^pcm_rb) ---
|
||||
pcm_rb_reset :: proc(pRB: ^pcm_rb) ---
|
||||
pcm_rb_acquire_read :: proc(pRB: ^pcm_rb, pSizeInFrames: ^u32, ppBufferOut: ^rawptr) -> result ---
|
||||
pcm_rb_commit_read :: proc(pRB: ^pcm_rb, sizeInFrames: u32, pBufferOut: rawptr) -> result ---
|
||||
pcm_rb_commit_read :: proc(pRB: ^pcm_rb, sizeInFrames: u32) -> result ---
|
||||
pcm_rb_acquire_write :: proc(pRB: ^pcm_rb, pSizeInFrames: ^u32, ppBufferOut: ^rawptr) -> result ---
|
||||
pcm_rb_commit_write :: proc(pRB: ^pcm_rb, sizeInFrames: u32, pBufferOut: rawptr) -> result ---
|
||||
pcm_rb_commit_write :: proc(pRB: ^pcm_rb, sizeInFrames: u32) -> result ---
|
||||
pcm_rb_seek_read :: proc(pRB: ^pcm_rb, offsetInFrames: u32) -> result ---
|
||||
pcm_rb_seek_write :: proc(pRB: ^pcm_rb, offsetInFrames: u32) -> result ---
|
||||
pcm_rb_pointer_distance :: proc(pRB: ^pcm_rb) -> i32 --- /* Return value is in frames. */
|
||||
|
||||
+6
-4
@@ -301,7 +301,7 @@ def parse_constants(f):
|
||||
|
||||
f.write("\n// Vendor Constants\n")
|
||||
fixes = '|'.join(ext_suffixes)
|
||||
inner = r"((?:(?:" + fixes + r")\w+)|(?:\w+" + fixes + r"))"
|
||||
inner = r"((?:(?:" + fixes + r")\w+)|(?:\w+(?:" + fixes + r")\b))"
|
||||
pattern = r"#define\s+VK_" + inner + r"\s*(.*?)\n"
|
||||
data = re.findall(pattern, src, re.S)
|
||||
|
||||
@@ -311,7 +311,11 @@ def parse_constants(f):
|
||||
for name, value in data:
|
||||
value = remove_prefix(value, 'VK_')
|
||||
v = number_suffix_re.findall(value)
|
||||
if v:
|
||||
if value == "(~0U)":
|
||||
value = "~u32(0)"
|
||||
elif value == "(~0ULL)":
|
||||
value = "~u64(0)"
|
||||
elif v:
|
||||
value = v[0]
|
||||
f.write("{}{} :: {}\n".format(name, "".rjust(max_len-len(name)), value))
|
||||
f.write("\n")
|
||||
@@ -935,7 +939,6 @@ FALSE :: 0
|
||||
QUEUE_FAMILY_IGNORED :: ~u32(0)
|
||||
SUBPASS_EXTERNAL :: ~u32(0)
|
||||
MAX_PHYSICAL_DEVICE_NAME_SIZE :: 256
|
||||
MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT :: 32
|
||||
UUID_SIZE :: 16
|
||||
MAX_MEMORY_TYPES :: 32
|
||||
MAX_MEMORY_HEAPS :: 16
|
||||
@@ -946,7 +949,6 @@ LUID_SIZE_KHX :: 8
|
||||
LUID_SIZE :: 8
|
||||
MAX_QUEUE_FAMILY_EXTERNAL :: ~u32(1)
|
||||
MAX_GLOBAL_PRIORITY_SIZE :: 16
|
||||
MAX_GLOBAL_PRIORITY_SIZE_EXT :: MAX_GLOBAL_PRIORITY_SIZE
|
||||
QUEUE_FAMILY_EXTERNAL :: MAX_QUEUE_FAMILY_EXTERNAL
|
||||
|
||||
// Vulkan Video API Constants
|
||||
|
||||
Vendored
+1069
-1065
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user