mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-10 23:13:15 +00:00
Merge branch 'master' into windows-llvm-11.1.0
This commit is contained in:
@@ -1,8 +1,5 @@
|
||||
package debug_pe
|
||||
|
||||
import "core:runtime"
|
||||
import "core:io"
|
||||
|
||||
Section_Header32 :: struct {
|
||||
name: [8]u8,
|
||||
virtual_size: u32le,
|
||||
|
||||
@@ -1142,6 +1142,11 @@ _pad :: proc(fi: ^Info, s: string) {
|
||||
if fi.minus { // right pad
|
||||
io.write_string(fi.writer, s, &fi.n)
|
||||
fmt_write_padding(fi, width)
|
||||
} else if !fi.space && s != "" && s[0] == '-' {
|
||||
// left pad accounting for zero pad of negative number
|
||||
io.write_byte(fi.writer, '-', &fi.n)
|
||||
fmt_write_padding(fi, width)
|
||||
io.write_string(fi.writer, s[1:], &fi.n)
|
||||
} else { // left pad
|
||||
fmt_write_padding(fi, width)
|
||||
io.write_string(fi.writer, s, &fi.n)
|
||||
@@ -1961,11 +1966,22 @@ fmt_named :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Named)
|
||||
switch a in v {
|
||||
case runtime.Source_Code_Location:
|
||||
io.write_string(fi.writer, a.file_path, &fi.n)
|
||||
io.write_byte(fi.writer, '(', &fi.n)
|
||||
io.write_int(fi.writer, int(a.line), 10, &fi.n)
|
||||
io.write_byte(fi.writer, ':', &fi.n)
|
||||
io.write_int(fi.writer, int(a.column), 10, &fi.n)
|
||||
io.write_byte(fi.writer, ')', &fi.n)
|
||||
|
||||
when ODIN_ERROR_POS_STYLE == .Default {
|
||||
io.write_byte(fi.writer, '(', &fi.n)
|
||||
io.write_int(fi.writer, int(a.line), 10, &fi.n)
|
||||
io.write_byte(fi.writer, ':', &fi.n)
|
||||
io.write_int(fi.writer, int(a.column), 10, &fi.n)
|
||||
io.write_byte(fi.writer, ')', &fi.n)
|
||||
} else when ODIN_ERROR_POS_STYLE == .Unix {
|
||||
io.write_byte(fi.writer, ':', &fi.n)
|
||||
io.write_int(fi.writer, int(a.line), 10, &fi.n)
|
||||
io.write_byte(fi.writer, ':', &fi.n)
|
||||
io.write_int(fi.writer, int(a.column), 10, &fi.n)
|
||||
io.write_byte(fi.writer, ':', &fi.n)
|
||||
} else {
|
||||
#panic("Unhandled ODIN_ERROR_POS_STYLE")
|
||||
}
|
||||
return
|
||||
|
||||
case time.Duration:
|
||||
|
||||
@@ -7,7 +7,7 @@ foreign import "odin_env"
|
||||
|
||||
@(private="file")
|
||||
foreign odin_env {
|
||||
write :: proc "c" (fd: u32, p: []byte) ---
|
||||
write :: proc "contextless" (fd: u32, p: []byte) ---
|
||||
}
|
||||
|
||||
@(private="file")
|
||||
|
||||
@@ -56,7 +56,7 @@ Allocator :: struct {
|
||||
DEFAULT_ALIGNMENT :: 2*align_of(rawptr)
|
||||
|
||||
DEFAULT_PAGE_SIZE ::
|
||||
64 * 1024 when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64 else
|
||||
64 * 1024 when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 else
|
||||
16 * 1024 when ODIN_OS == .Darwin && ODIN_ARCH == .arm64 else
|
||||
4 * 1024
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ _main :: proc() {
|
||||
main :: proc() {
|
||||
track: mem.Tracking_Allocator
|
||||
mem.tracking_allocator_init(&track, context.allocator)
|
||||
defer mem.tracking_allocator_destroy(&track)
|
||||
context.allocator = mem.tracking_allocator(&track)
|
||||
|
||||
_main()
|
||||
@@ -31,4 +32,4 @@ main :: proc() {
|
||||
}
|
||||
```
|
||||
*/
|
||||
package mem
|
||||
package mem
|
||||
|
||||
24
core/mem/virtual/virtual_bsd.odin
Normal file
24
core/mem/virtual/virtual_bsd.odin
Normal file
@@ -0,0 +1,24 @@
|
||||
//+build freebsd, openbsd
|
||||
//+private
|
||||
package mem_virtual
|
||||
|
||||
|
||||
|
||||
_reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
_commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
|
||||
return nil
|
||||
}
|
||||
_decommit :: proc "contextless" (data: rawptr, size: uint) {
|
||||
}
|
||||
_release :: proc "contextless" (data: rawptr, size: uint) {
|
||||
}
|
||||
_protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) -> bool {
|
||||
return false
|
||||
}
|
||||
|
||||
_platform_memory_init :: proc() {
|
||||
|
||||
}
|
||||
@@ -44,9 +44,6 @@ _get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator :
|
||||
if !hosts_ok {
|
||||
return nil, .Invalid_Hosts_Config_Error
|
||||
}
|
||||
if len(hosts) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
host_overrides := make([dynamic]DNS_Record)
|
||||
for host in hosts {
|
||||
@@ -80,4 +77,4 @@ _get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator :
|
||||
}
|
||||
|
||||
return get_dns_records_from_nameservers(hostname, type, name_servers, host_overrides[:])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,9 +268,9 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
|
||||
t, ok := value.(time.Duration)
|
||||
if !ok do panic("set_option() value must be a time.Duration here", loc)
|
||||
|
||||
nanos := time.duration_nanoseconds(t)
|
||||
timeval_value.nanoseconds = int(nanos % 1e9)
|
||||
timeval_value.seconds = (nanos - i64(timeval_value.nanoseconds)) / 1e9
|
||||
micros := i64(time.duration_microseconds(t))
|
||||
timeval_value.microseconds = int(micros % 1e6)
|
||||
timeval_value.seconds = (micros - i64(timeval_value.microseconds)) / 1e6
|
||||
|
||||
ptr = &timeval_value
|
||||
len = size_of(timeval_value)
|
||||
@@ -368,4 +368,4 @@ _sockaddr_to_endpoint :: proc(native_addr: ^os.SOCKADDR_STORAGE_LH) -> (ep: Endp
|
||||
panic("native_addr is neither IP4 or IP6 address")
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,9 +283,9 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
|
||||
t, ok := value.(time.Duration)
|
||||
if !ok do panic("set_option() value must be a time.Duration here", loc)
|
||||
|
||||
nanos := time.duration_nanoseconds(t)
|
||||
timeval_value.nanoseconds = int(nanos % 1e9)
|
||||
timeval_value.seconds = (nanos - i64(timeval_value.nanoseconds)) / 1e9
|
||||
micros := i64(time.duration_microseconds(t))
|
||||
timeval_value.microseconds = int(micros % 1e6)
|
||||
timeval_value.seconds = (micros - i64(timeval_value.microseconds)) / 1e6
|
||||
|
||||
ptr = &timeval_value
|
||||
len = size_of(timeval_value)
|
||||
@@ -404,4 +404,4 @@ _sockaddr_basic_to_endpoint :: proc(native_addr: ^os.SOCKADDR) -> (ep: Endpoint)
|
||||
panic("native_addr is neither IP4 or IP6 address")
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,7 +355,7 @@ in6_addr :: struct #packed {
|
||||
|
||||
Timeval :: struct {
|
||||
seconds: i64,
|
||||
nanoseconds: int,
|
||||
microseconds: int,
|
||||
}
|
||||
|
||||
Linger :: struct {
|
||||
@@ -965,8 +965,8 @@ _processor_core_count :: proc() -> int {
|
||||
|
||||
_alloc_command_line_arguments :: proc() -> []string {
|
||||
res := make([]string, len(runtime.args__))
|
||||
for arg, i in runtime.args__ {
|
||||
res[i] = string(arg)
|
||||
for _, i in res {
|
||||
res[i] = string(runtime.args__[i])
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ socklen_t :: c.int
|
||||
|
||||
Timeval :: struct {
|
||||
seconds: i64,
|
||||
nanoseconds: int,
|
||||
microseconds: int,
|
||||
}
|
||||
|
||||
// "Argv" arguments converted to Odin strings
|
||||
@@ -1086,4 +1086,4 @@ fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Errno) {
|
||||
return 0, _get_errno(result)
|
||||
}
|
||||
return result, ERROR_NONE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,7 +425,7 @@ Raw_Map :: struct {
|
||||
// Map_Hash directly, though for consistency sake it's written as if it were
|
||||
// an array of Map_Cell(Map_Hash).
|
||||
data: uintptr, // 8-bytes on 64-bits, 4-bytes on 32-bits
|
||||
len: int, // 8-bytes on 64-bits, 4-bytes on 32-bits
|
||||
len: uintptr, // 8-bytes on 64-bits, 4-bytes on 32-bits
|
||||
allocator: Allocator, // 16-bytes on 64-bits, 8-bytes on 32-bits
|
||||
}
|
||||
|
||||
@@ -471,7 +471,7 @@ Odin_OS_Type :: type_of(ODIN_OS)
|
||||
arm32,
|
||||
arm64,
|
||||
wasm32,
|
||||
wasm64,
|
||||
wasm64p32,
|
||||
}
|
||||
*/
|
||||
Odin_Arch_Type :: type_of(ODIN_ARCH)
|
||||
|
||||
@@ -145,26 +145,25 @@ make_soa_slice :: proc($T: typeid/#soa[]$E, length: int, allocator := context.al
|
||||
}
|
||||
|
||||
@(builtin, require_results)
|
||||
make_soa_dynamic_array :: proc($T: typeid/#soa[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (array: T) {
|
||||
make_soa_dynamic_array :: proc($T: typeid/#soa[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
|
||||
context.allocator = allocator
|
||||
reserve_soa(&array, DEFAULT_RESERVE_CAPACITY, loc)
|
||||
return
|
||||
reserve_soa(&array, DEFAULT_RESERVE_CAPACITY, loc) or_return
|
||||
return array, nil
|
||||
}
|
||||
|
||||
@(builtin, require_results)
|
||||
make_soa_dynamic_array_len :: proc($T: typeid/#soa[dynamic]$E, #any_int length: int, allocator := context.allocator, loc := #caller_location) -> (array: T) {
|
||||
make_soa_dynamic_array_len :: proc($T: typeid/#soa[dynamic]$E, #any_int length: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
|
||||
context.allocator = allocator
|
||||
resize_soa(&array, length, loc)
|
||||
return
|
||||
resize_soa(&array, length, loc) or_return
|
||||
return array, nil
|
||||
}
|
||||
|
||||
@(builtin, require_results)
|
||||
make_soa_dynamic_array_len_cap :: proc($T: typeid/#soa[dynamic]$E, #any_int length, capacity: int, allocator := context.allocator, loc := #caller_location) -> (array: T) {
|
||||
make_soa_dynamic_array_len_cap :: proc($T: typeid/#soa[dynamic]$E, #any_int length, capacity: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
|
||||
context.allocator = allocator
|
||||
if reserve_soa(&array, capacity, loc) {
|
||||
resize_soa(&array, length, loc)
|
||||
}
|
||||
return
|
||||
reserve_soa(&array, capacity, loc) or_return
|
||||
resize_soa(&array, length, loc) or_return
|
||||
return array, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -178,27 +177,25 @@ make_soa :: proc{
|
||||
|
||||
|
||||
@builtin
|
||||
resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_location) -> bool {
|
||||
resize_soa :: proc(array: ^$T/#soa[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
|
||||
if array == nil {
|
||||
return false
|
||||
}
|
||||
if !reserve_soa(array, length, loc) {
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
reserve_soa(array, length, loc) or_return
|
||||
footer := raw_soa_footer(array)
|
||||
footer.len = length
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
@builtin
|
||||
reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> bool {
|
||||
reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
|
||||
if array == nil {
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
|
||||
old_cap := cap(array)
|
||||
if capacity <= old_cap {
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
if array.allocator.procedure == nil {
|
||||
@@ -209,7 +206,7 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo
|
||||
footer := raw_soa_footer(array)
|
||||
if size_of(E) == 0 {
|
||||
footer.cap = capacity
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
ti := type_info_of(typeid_of(T))
|
||||
@@ -240,13 +237,10 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo
|
||||
|
||||
old_data := (^rawptr)(array)^
|
||||
|
||||
new_bytes, err := array.allocator.procedure(
|
||||
new_bytes := array.allocator.procedure(
|
||||
array.allocator.data, .Alloc, new_size, max_align,
|
||||
nil, old_size, loc,
|
||||
)
|
||||
if new_bytes == nil || err != nil {
|
||||
return false
|
||||
}
|
||||
) or_return
|
||||
new_data := raw_data(new_bytes)
|
||||
|
||||
|
||||
@@ -271,31 +265,28 @@ reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, loc := #caller_lo
|
||||
new_offset += type.size * capacity
|
||||
}
|
||||
|
||||
_, err = array.allocator.procedure(
|
||||
array.allocator.procedure(
|
||||
array.allocator.data, .Free, 0, max_align,
|
||||
old_data, old_size, loc,
|
||||
)
|
||||
) or_return
|
||||
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
@builtin
|
||||
append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_location) {
|
||||
append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||
if array == nil {
|
||||
return
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
arg_len := 1
|
||||
|
||||
if cap(array) <= len(array)+arg_len {
|
||||
cap := 2 * cap(array) + max(8, arg_len)
|
||||
_ = reserve_soa(array, cap, loc)
|
||||
if cap(array) <= len(array) + 1 {
|
||||
cap := 2 * cap(array) + 8
|
||||
err = reserve_soa(array, cap, loc) // do not 'or_return' here as it could be a partial success
|
||||
}
|
||||
arg_len = min(cap(array)-len(array), arg_len)
|
||||
|
||||
footer := raw_soa_footer(array)
|
||||
|
||||
if size_of(E) > 0 && arg_len > 0 {
|
||||
if size_of(E) > 0 && cap(array)-len(array) > 0 {
|
||||
ti := type_info_of(typeid_of(T))
|
||||
ti = type_info_base(ti)
|
||||
si := &ti.variant.(Type_Info_Struct)
|
||||
@@ -328,12 +319,14 @@ append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, arg: E, loc := #caller_locat
|
||||
soa_offset += type.size * cap(array)
|
||||
item_offset += type.size
|
||||
}
|
||||
footer.len += 1
|
||||
return 1, err
|
||||
}
|
||||
footer.len += arg_len
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@builtin
|
||||
append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_location) {
|
||||
append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||
if array == nil {
|
||||
return
|
||||
}
|
||||
@@ -345,7 +338,7 @@ append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_l
|
||||
|
||||
if cap(array) <= len(array)+arg_len {
|
||||
cap := 2 * cap(array) + max(8, arg_len)
|
||||
_ = reserve_soa(array, cap, loc)
|
||||
err = reserve_soa(array, cap, loc) // do not 'or_return' here as it could be a partial success
|
||||
}
|
||||
arg_len = min(cap(array)-len(array), arg_len)
|
||||
|
||||
@@ -382,8 +375,8 @@ append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, args: ..E, loc := #caller_l
|
||||
item_offset += type.size
|
||||
}
|
||||
}
|
||||
|
||||
footer.len += arg_len
|
||||
return arg_len, err
|
||||
}
|
||||
|
||||
|
||||
@@ -395,21 +388,23 @@ append_soa :: proc{
|
||||
}
|
||||
|
||||
|
||||
delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc := #caller_location) {
|
||||
delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
||||
when intrinsics.type_struct_field_count(E) != 0 {
|
||||
array := array
|
||||
ptr := (^rawptr)(&array)^
|
||||
free(ptr, allocator, loc)
|
||||
free(ptr, allocator, loc) or_return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
delete_soa_dynamic_array :: proc(array: $T/#soa[dynamic]$E, loc := #caller_location) {
|
||||
delete_soa_dynamic_array :: proc(array: $T/#soa[dynamic]$E, loc := #caller_location) -> Allocator_Error {
|
||||
when intrinsics.type_struct_field_count(E) != 0 {
|
||||
array := array
|
||||
ptr := (^rawptr)(&array)^
|
||||
footer := raw_soa_footer(&array)
|
||||
free(ptr, footer.allocator, loc)
|
||||
free(ptr, footer.allocator, loc) or_return
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ map_cell_index_static :: #force_inline proc "contextless" (cells: [^]Map_Cell($T
|
||||
// len() for map
|
||||
@(require_results)
|
||||
map_len :: #force_inline proc "contextless" (m: Raw_Map) -> int {
|
||||
return m.len
|
||||
return int(m.len)
|
||||
}
|
||||
|
||||
// cap() for map
|
||||
@@ -207,8 +207,8 @@ map_load_factor :: #force_inline proc "contextless" (log2_capacity: uintptr) ->
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
map_resize_threshold :: #force_inline proc "contextless" (m: Raw_Map) -> int {
|
||||
return int(map_load_factor(map_log2_cap(m)))
|
||||
map_resize_threshold :: #force_inline proc "contextless" (m: Raw_Map) -> uintptr {
|
||||
return map_load_factor(map_log2_cap(m))
|
||||
}
|
||||
|
||||
// The data stores the log2 capacity in the lower six bits. This is primarily
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+private
|
||||
//+build wasm32, wasm64
|
||||
//+build wasm32, wasm64p32
|
||||
package runtime
|
||||
|
||||
import "core:intrinsics"
|
||||
|
||||
@@ -3,7 +3,7 @@ package runtime
|
||||
import "core:intrinsics"
|
||||
|
||||
@(private="file")
|
||||
IS_WASM :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64
|
||||
IS_WASM :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
|
||||
|
||||
@(private)
|
||||
RUNTIME_LINKAGE :: "strong" when (
|
||||
|
||||
@@ -25,7 +25,7 @@ when ODIN_NO_CRT && ODIN_OS == .Windows {
|
||||
RtlMoveMemory(dst, src, len)
|
||||
return dst
|
||||
}
|
||||
} else when ODIN_NO_CRT || (ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64) {
|
||||
} else when ODIN_NO_CRT || (ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32) {
|
||||
@(link_name="memset", linkage="strong", require)
|
||||
memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr {
|
||||
if ptr != nil && len != 0 {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build js wasm32
|
||||
//+build js
|
||||
package runtime
|
||||
|
||||
init_default_context_for_js: Context
|
||||
@@ -1,4 +1,4 @@
|
||||
//+build wasm32
|
||||
//+build wasm32, wasm64p32
|
||||
package runtime
|
||||
|
||||
@(private="file")
|
||||
@@ -1,5 +1,5 @@
|
||||
//+private
|
||||
//+build wasm32, wasm64
|
||||
//+build wasm32, wasm64p32
|
||||
package sync
|
||||
|
||||
import "core:intrinsics"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//+private
|
||||
//+build wasm32, wasm64
|
||||
//+build wasm32, wasm64p32
|
||||
package sync
|
||||
|
||||
_current_thread_id :: proc "contextless" () -> int {
|
||||
|
||||
@@ -113,15 +113,16 @@ set_text :: proc(s: ^State, text: string) {
|
||||
}
|
||||
|
||||
|
||||
undo_state_push :: proc(s: ^State, undo: ^[dynamic]^Undo_State) {
|
||||
undo_state_push :: proc(s: ^State, undo: ^[dynamic]^Undo_State) -> mem.Allocator_Error {
|
||||
text := string(s.builder.buf[:])
|
||||
item := (^Undo_State)(mem.alloc(size_of(Undo_State) + len(text), align_of(Undo_State), s.undo_text_allocator))
|
||||
item := (^Undo_State)(mem.alloc(size_of(Undo_State) + len(text), align_of(Undo_State), s.undo_text_allocator) or_return)
|
||||
item.selection = s.selection
|
||||
item.len = len(text)
|
||||
#no_bounds_check {
|
||||
runtime.copy(item.text[:len(text)], text)
|
||||
}
|
||||
append(undo, item)
|
||||
append(undo, item) or_return
|
||||
return nil
|
||||
}
|
||||
|
||||
undo :: proc(s: ^State, undo, redo: ^[dynamic]^Undo_State) {
|
||||
|
||||
@@ -266,6 +266,7 @@ match_balance :: proc(ms: ^Match_State, s, p: int) -> (unused: int, err: Error)
|
||||
return INVALID, .Invalid_Pattern_Capture
|
||||
}
|
||||
|
||||
|
||||
schar, ssize := utf8_peek(ms.src[s:]) or_return
|
||||
pchar, psize := utf8_peek(ms.pattern[p:]) or_return
|
||||
|
||||
@@ -274,9 +275,9 @@ match_balance :: proc(ms: ^Match_State, s, p: int) -> (unused: int, err: Error)
|
||||
return INVALID, .OK
|
||||
}
|
||||
|
||||
s_begin := s
|
||||
cont := 1
|
||||
s := s + ssize
|
||||
s := s
|
||||
s += ssize
|
||||
begin := pchar
|
||||
end, _ := utf8_peek(ms.pattern[p + psize:]) or_return
|
||||
|
||||
|
||||
@@ -9,12 +9,10 @@
|
||||
package text_table
|
||||
|
||||
import "core:io"
|
||||
import "core:os"
|
||||
import "core:fmt"
|
||||
import "core:mem"
|
||||
import "core:mem/virtual"
|
||||
import "core:runtime"
|
||||
import "core:strings"
|
||||
|
||||
Cell :: struct {
|
||||
text: string,
|
||||
|
||||
@@ -14,10 +14,37 @@ Thread :: struct {
|
||||
using specific: Thread_Os_Specific,
|
||||
id: int,
|
||||
procedure: Thread_Proc,
|
||||
|
||||
/*
|
||||
These are values that the user can set as they wish, after the thread has been created.
|
||||
This data is easily available to the thread proc.
|
||||
|
||||
These fields can be assigned to directly.
|
||||
|
||||
Should be set after the thread is created, but before it is started.
|
||||
*/
|
||||
data: rawptr,
|
||||
user_index: int,
|
||||
user_args: [MAX_USER_ARGUMENTS]rawptr,
|
||||
|
||||
/*
|
||||
The context to be used as 'context' in the thread proc.
|
||||
|
||||
This field can be assigned to directly, after the thread has been created, but __before__ the thread has been started.
|
||||
This field must not be changed after the thread has started.
|
||||
|
||||
NOTE: If you __don't__ set this, the temp allocator will be managed for you;
|
||||
If you __do__ set this, then you're expected to handle whatever allocators you set, yourself.
|
||||
|
||||
IMPORTANT:
|
||||
By default, the thread proc will get the same context as `main()` gets.
|
||||
In this sitation, the thread will get a new temporary allocator which will be cleaned up when the thread dies.
|
||||
***This does NOT happen when you set `init_context`.***
|
||||
This means that if you set `init_context`, but still have the `temp_allocator` field set to the default temp allocator,
|
||||
then you'll need to call `runtime.default_temp_allocator_destroy(auto_cast the_thread.init_context.temp_allocator.data)` manually,
|
||||
in order to prevent any memory leaks.
|
||||
This call ***must*** be done ***in the thread proc*** because the default temporary allocator uses thread local state!
|
||||
*/
|
||||
init_context: Maybe(runtime.Context),
|
||||
|
||||
|
||||
@@ -32,6 +59,12 @@ Thread_Priority :: enum {
|
||||
High,
|
||||
}
|
||||
|
||||
/*
|
||||
Creates a thread in a suspended state with the given priority.
|
||||
To start the thread, call `thread.start()`.
|
||||
|
||||
See `thread.create_and_start()`.
|
||||
*/
|
||||
create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread {
|
||||
return _create(procedure, priority)
|
||||
}
|
||||
@@ -298,3 +331,33 @@ create_and_start_with_poly_data4 :: proc(arg1: $T1, arg2: $T2, arg3: $T3, arg4:
|
||||
start(t)
|
||||
return t
|
||||
}
|
||||
|
||||
|
||||
_select_context_for_thread :: proc(init_context: Maybe(runtime.Context)) -> runtime.Context {
|
||||
ctx, ok := init_context.?
|
||||
if !ok {
|
||||
return runtime.default_context()
|
||||
}
|
||||
|
||||
/*
|
||||
NOTE(tetra, 2023-05-31):
|
||||
Ensure that the temp allocator is thread-safe when the user provides a specific initial context to use.
|
||||
Without this, the thread will use the same temp allocator state as the parent thread, and thus, bork it up.
|
||||
*/
|
||||
if ctx.temp_allocator.procedure == runtime.default_temp_allocator_proc {
|
||||
ctx.temp_allocator.data = &runtime.global_default_temp_allocator_data
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
_maybe_destroy_default_temp_allocator :: proc(init_context: Maybe(runtime.Context)) {
|
||||
if init_context != nil {
|
||||
// NOTE(tetra, 2023-05-31): If the user specifies a custom context for the thread,
|
||||
// then it's entirely up to them to handle whatever allocators they're using.
|
||||
return
|
||||
}
|
||||
|
||||
if context.temp_allocator.procedure == runtime.default_temp_allocator_proc {
|
||||
runtime.default_temp_allocator_destroy(auto_cast context.temp_allocator.data)
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
// +private
|
||||
package thread
|
||||
|
||||
import "core:runtime"
|
||||
import "core:intrinsics"
|
||||
import "core:sync"
|
||||
import "core:sys/unix"
|
||||
@@ -27,7 +26,7 @@ Thread_Os_Specific :: struct #align 16 {
|
||||
// Creates a thread which will run the given procedure.
|
||||
// It then waits for `start` to be called.
|
||||
//
|
||||
_create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread {
|
||||
_create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
|
||||
__linux_thread_entry_proc :: proc "c" (t: rawptr) -> rawptr {
|
||||
t := (^Thread)(t)
|
||||
|
||||
@@ -36,8 +35,6 @@ _create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^
|
||||
can_set_thread_cancel_state := unix.pthread_setcancelstate(unix.PTHREAD_CANCEL_DISABLE, nil) == 0
|
||||
}
|
||||
|
||||
context = runtime.default_context()
|
||||
|
||||
sync.lock(&t.mutex)
|
||||
|
||||
t.id = sync.current_thread_id()
|
||||
@@ -46,9 +43,6 @@ _create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^
|
||||
sync.wait(&t.cond, &t.mutex)
|
||||
}
|
||||
|
||||
init_context := t.init_context
|
||||
context = init_context.? or_else runtime.default_context()
|
||||
|
||||
when ODIN_OS != .Darwin {
|
||||
// Enable thread's cancelability.
|
||||
if can_set_thread_cancel_state {
|
||||
@@ -57,16 +51,22 @@ _create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^
|
||||
}
|
||||
}
|
||||
|
||||
t.procedure(t)
|
||||
{
|
||||
init_context := t.init_context
|
||||
|
||||
// NOTE(tetra, 2023-05-31): Must do this AFTER thread.start() is called, so that the user can set the init_context, etc!
|
||||
// Here on Unix, we start the OS thread in a running state, and so we manually have it wait on a condition
|
||||
// variable above. We must perform that waiting BEFORE we select the context!
|
||||
context = _select_context_for_thread(init_context)
|
||||
defer _maybe_destroy_default_temp_allocator(init_context)
|
||||
|
||||
t.procedure(t)
|
||||
}
|
||||
|
||||
intrinsics.atomic_store(&t.flags, t.flags + { .Done })
|
||||
|
||||
sync.unlock(&t.mutex)
|
||||
|
||||
if init_context == nil && context.temp_allocator.data == &runtime.global_default_temp_allocator_data {
|
||||
runtime.default_temp_allocator_destroy(auto_cast context.temp_allocator.data)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
//+private
|
||||
package thread
|
||||
|
||||
import "core:runtime"
|
||||
import "core:intrinsics"
|
||||
import "core:sync"
|
||||
import win32 "core:sys/windows"
|
||||
@@ -26,24 +25,28 @@ _thread_priority_map := [Thread_Priority]i32{
|
||||
.High = +2,
|
||||
}
|
||||
|
||||
_create :: proc(procedure: Thread_Proc, priority := Thread_Priority.Normal) -> ^Thread {
|
||||
_create :: proc(procedure: Thread_Proc, priority: Thread_Priority) -> ^Thread {
|
||||
win32_thread_id: win32.DWORD
|
||||
|
||||
__windows_thread_entry_proc :: proc "stdcall" (t_: rawptr) -> win32.DWORD {
|
||||
t := (^Thread)(t_)
|
||||
context = t.init_context.? or_else runtime.default_context()
|
||||
|
||||
|
||||
t.id = sync.current_thread_id()
|
||||
|
||||
t.procedure(t)
|
||||
{
|
||||
init_context := t.init_context
|
||||
|
||||
// NOTE(tetra, 2023-05-31): Must do this AFTER thread.start() is called, so that the user can set the init_context, etc!
|
||||
// Here on Windows, the thread is created in a suspended state, and so we can select the context anywhere before the call
|
||||
// to t.procedure().
|
||||
context = _select_context_for_thread(init_context)
|
||||
defer _maybe_destroy_default_temp_allocator(init_context)
|
||||
|
||||
t.procedure(t)
|
||||
}
|
||||
|
||||
intrinsics.atomic_store(&t.flags, t.flags + {.Done})
|
||||
|
||||
if t.init_context == nil {
|
||||
if context.temp_allocator.data == &runtime.global_default_temp_allocator_data {
|
||||
runtime.default_temp_allocator_destroy(auto_cast context.temp_allocator.data)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ import priority_queue "core:container/priority_queue"
|
||||
import queue "core:container/queue"
|
||||
import small_array "core:container/small_array"
|
||||
import lru "core:container/lru"
|
||||
import list "core:container/intrusive/list"
|
||||
import topological_sort "core:container/topological_sort"
|
||||
|
||||
import crypto "core:crypto"
|
||||
import blake "core:crypto/blake"
|
||||
@@ -48,6 +50,8 @@ import crypto_util "core:crypto/util"
|
||||
import whirlpool "core:crypto/whirlpool"
|
||||
import x25519 "core:crypto/x25519"
|
||||
|
||||
import pe "core:debug/pe"
|
||||
|
||||
import dynlib "core:dynlib"
|
||||
import net "core:net"
|
||||
|
||||
@@ -58,9 +62,11 @@ import hxa "core:encoding/hxa"
|
||||
import json "core:encoding/json"
|
||||
import varint "core:encoding/varint"
|
||||
import xml "core:encoding/xml"
|
||||
import endian "core:encoding/endian"
|
||||
|
||||
import fmt "core:fmt"
|
||||
import hash "core:hash"
|
||||
import xxhash "core:hash/xxhash"
|
||||
|
||||
import image "core:image"
|
||||
import netpbm "core:image/netpbm"
|
||||
@@ -80,9 +86,10 @@ import glm "core:math/linalg/glsl"
|
||||
import hlm "core:math/linalg/hlsl"
|
||||
import noise "core:math/noise"
|
||||
import rand "core:math/rand"
|
||||
import ease "core:math/ease"
|
||||
|
||||
import mem "core:mem"
|
||||
// import virtual "core:mem/virtual"
|
||||
import virtual "core:mem/virtual"
|
||||
|
||||
import ast "core:odin/ast"
|
||||
import doc_format "core:odin/doc-format"
|
||||
@@ -91,6 +98,8 @@ import odin_parser "core:odin/parser"
|
||||
import odin_printer "core:odin/printer"
|
||||
import odin_tokenizer "core:odin/tokenizer"
|
||||
|
||||
import spall "core:prof/spall"
|
||||
|
||||
import os "core:os"
|
||||
|
||||
import slashpath "core:path/slashpath"
|
||||
@@ -108,6 +117,9 @@ import sync "core:sync"
|
||||
import testing "core:testing"
|
||||
import scanner "core:text/scanner"
|
||||
import i18n "core:text/i18n"
|
||||
import match "core:text/match"
|
||||
import table "core:text/table"
|
||||
import edit "core:text/edit"
|
||||
import thread "core:thread"
|
||||
import time "core:time"
|
||||
|
||||
@@ -134,6 +146,8 @@ _ :: priority_queue
|
||||
_ :: queue
|
||||
_ :: small_array
|
||||
_ :: lru
|
||||
_ :: list
|
||||
_ :: topological_sort
|
||||
_ :: crypto
|
||||
_ :: blake
|
||||
_ :: blake2b
|
||||
@@ -161,6 +175,7 @@ _ :: tiger2
|
||||
_ :: crypto_util
|
||||
_ :: whirlpool
|
||||
_ :: x25519
|
||||
_ :: pe
|
||||
_ :: dynlib
|
||||
_ :: net
|
||||
_ :: base32
|
||||
@@ -170,8 +185,10 @@ _ :: hxa
|
||||
_ :: json
|
||||
_ :: varint
|
||||
_ :: xml
|
||||
_ :: endian
|
||||
_ :: fmt
|
||||
_ :: hash
|
||||
_ :: xxhash
|
||||
_ :: image
|
||||
_ :: netpbm
|
||||
_ :: png
|
||||
@@ -188,7 +205,9 @@ _ :: glm
|
||||
_ :: hlm
|
||||
_ :: noise
|
||||
_ :: rand
|
||||
_ :: ease
|
||||
_ :: mem
|
||||
_ :: virtual
|
||||
_ :: ast
|
||||
_ :: doc_format
|
||||
_ :: odin_format
|
||||
@@ -196,6 +215,7 @@ _ :: odin_parser
|
||||
_ :: odin_printer
|
||||
_ :: odin_tokenizer
|
||||
_ :: os
|
||||
_ :: spall
|
||||
_ :: slashpath
|
||||
_ :: filepath
|
||||
_ :: reflect
|
||||
@@ -210,6 +230,9 @@ _ :: sync
|
||||
_ :: testing
|
||||
_ :: scanner
|
||||
_ :: i18n
|
||||
_ :: match
|
||||
_ :: table
|
||||
_ :: edit
|
||||
_ :: thread
|
||||
_ :: time
|
||||
_ :: sysinfo
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
package all
|
||||
|
||||
import botan "vendor:botan"
|
||||
import botan_bindings "vendor:botan/bindings"
|
||||
import botan_blake2b "vendor:botan/blake2b"
|
||||
import gost "vendor:botan/gost"
|
||||
import keccak "vendor:botan/keccak"
|
||||
import md4 "vendor:botan/md4"
|
||||
import md5 "vendor:botan/md5"
|
||||
import ripemd "vendor:botan/ripemd"
|
||||
import sha1 "vendor:botan/sha1"
|
||||
import sha2 "vendor:botan/sha2"
|
||||
import sha3 "vendor:botan/sha3"
|
||||
import shake "vendor:botan/shake"
|
||||
import siphash "vendor:botan/siphash"
|
||||
import skein512 "vendor:botan/skein512"
|
||||
import sm3 "vendor:botan/sm3"
|
||||
import streebog "vendor:botan/streebog"
|
||||
import tiger "vendor:botan/tiger"
|
||||
import whirlpool "vendor:botan/whirlpool"
|
||||
|
||||
import cgltf "vendor:cgltf"
|
||||
// import commonmark "vendor:commonmark"
|
||||
import ENet "vendor:ENet"
|
||||
@@ -30,7 +47,25 @@ import CA "vendor:darwin/QuartzCore"
|
||||
// NOTE(bill): only one can be checked at a time
|
||||
import lua_5_4 "vendor:lua/5.4"
|
||||
|
||||
_ :: botan
|
||||
_ :: botan_bindings
|
||||
_ :: botan_blake2b
|
||||
_ :: gost
|
||||
_ :: keccak
|
||||
_ :: md4
|
||||
_ :: md5
|
||||
_ :: ripemd
|
||||
_ :: sha1
|
||||
_ :: sha2
|
||||
_ :: sha3
|
||||
_ :: shake
|
||||
_ :: siphash
|
||||
_ :: skein512
|
||||
_ :: sm3
|
||||
_ :: streebog
|
||||
_ :: tiger
|
||||
_ :: whirlpool
|
||||
|
||||
|
||||
_ :: cgltf
|
||||
// _ :: commonmark
|
||||
_ :: ENet
|
||||
|
||||
@@ -35,14 +35,12 @@ enum TargetArchKind : u16 {
|
||||
TargetArch_arm32,
|
||||
TargetArch_arm64,
|
||||
TargetArch_wasm32,
|
||||
TargetArch_wasm64,
|
||||
TargetArch_wasm64p32,
|
||||
|
||||
TargetArch_COUNT,
|
||||
};
|
||||
|
||||
enum TargetEndianKind : u8 {
|
||||
TargetEndian_Invalid,
|
||||
|
||||
TargetEndian_Little,
|
||||
TargetEndian_Big,
|
||||
|
||||
@@ -81,11 +79,10 @@ gb_global String target_arch_names[TargetArch_COUNT] = {
|
||||
str_lit("arm32"),
|
||||
str_lit("arm64"),
|
||||
str_lit("wasm32"),
|
||||
str_lit("wasm64"),
|
||||
str_lit("wasm64p32"),
|
||||
};
|
||||
|
||||
gb_global String target_endian_names[TargetEndian_COUNT] = {
|
||||
str_lit(""),
|
||||
str_lit("little"),
|
||||
str_lit("big"),
|
||||
};
|
||||
@@ -97,7 +94,8 @@ gb_global String target_abi_names[TargetABI_COUNT] = {
|
||||
};
|
||||
|
||||
gb_global TargetEndianKind target_endians[TargetArch_COUNT] = {
|
||||
TargetEndian_Invalid,
|
||||
TargetEndian_Little,
|
||||
TargetEndian_Little,
|
||||
TargetEndian_Little,
|
||||
TargetEndian_Little,
|
||||
TargetEndian_Little,
|
||||
@@ -116,7 +114,8 @@ gb_global String const ODIN_VERSION = str_lit(ODIN_VERSION_RAW);
|
||||
struct TargetMetrics {
|
||||
TargetOsKind os;
|
||||
TargetArchKind arch;
|
||||
isize word_size;
|
||||
isize ptr_size;
|
||||
isize int_size;
|
||||
isize max_align;
|
||||
isize max_simd_align;
|
||||
String target_triplet;
|
||||
@@ -237,9 +236,10 @@ struct BuildContext {
|
||||
TargetEndianKind endian_kind;
|
||||
|
||||
// In bytes
|
||||
i64 word_size; // Size of a pointer, must be >= 4
|
||||
i64 max_align; // max alignment, must be >= 1 (and typically >= word_size)
|
||||
i64 max_simd_align; // max alignment, must be >= 1 (and typically >= word_size)
|
||||
i64 ptr_size; // Size of a pointer, must be >= 4
|
||||
i64 int_size; // Size of a int/uint, must be >= 4
|
||||
i64 max_align; // max alignment, must be >= 1 (and typically >= ptr_size)
|
||||
i64 max_simd_align; // max alignment, must be >= 1 (and typically >= ptr_size)
|
||||
|
||||
CommandKind command_kind;
|
||||
String command;
|
||||
@@ -361,13 +361,13 @@ gb_internal isize MAX_ERROR_COLLECTOR_COUNT(void) {
|
||||
gb_global TargetMetrics target_windows_i386 = {
|
||||
TargetOs_windows,
|
||||
TargetArch_i386,
|
||||
4, 4, 8,
|
||||
4, 4, 4, 8,
|
||||
str_lit("i386-pc-windows-msvc"),
|
||||
};
|
||||
gb_global TargetMetrics target_windows_amd64 = {
|
||||
TargetOs_windows,
|
||||
TargetArch_amd64,
|
||||
8, 8, 16,
|
||||
8, 8, 8, 16,
|
||||
str_lit("x86_64-pc-windows-msvc"),
|
||||
str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"),
|
||||
};
|
||||
@@ -375,21 +375,21 @@ gb_global TargetMetrics target_windows_amd64 = {
|
||||
gb_global TargetMetrics target_linux_i386 = {
|
||||
TargetOs_linux,
|
||||
TargetArch_i386,
|
||||
4, 4, 8,
|
||||
4, 4, 4, 8,
|
||||
str_lit("i386-pc-linux-gnu"),
|
||||
|
||||
};
|
||||
gb_global TargetMetrics target_linux_amd64 = {
|
||||
TargetOs_linux,
|
||||
TargetArch_amd64,
|
||||
8, 8, 16,
|
||||
8, 8, 8, 16,
|
||||
str_lit("x86_64-pc-linux-gnu"),
|
||||
str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"),
|
||||
};
|
||||
gb_global TargetMetrics target_linux_arm64 = {
|
||||
TargetOs_linux,
|
||||
TargetArch_arm64,
|
||||
8, 8, 16,
|
||||
8, 8, 8, 16,
|
||||
str_lit("aarch64-linux-elf"),
|
||||
str_lit("e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"),
|
||||
};
|
||||
@@ -397,7 +397,7 @@ gb_global TargetMetrics target_linux_arm64 = {
|
||||
gb_global TargetMetrics target_linux_arm32 = {
|
||||
TargetOs_linux,
|
||||
TargetArch_arm32,
|
||||
4, 4, 8,
|
||||
4, 4, 4, 8,
|
||||
str_lit("arm-linux-gnu"),
|
||||
str_lit("e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"),
|
||||
};
|
||||
@@ -405,7 +405,7 @@ gb_global TargetMetrics target_linux_arm32 = {
|
||||
gb_global TargetMetrics target_darwin_amd64 = {
|
||||
TargetOs_darwin,
|
||||
TargetArch_amd64,
|
||||
8, 8, 16,
|
||||
8, 8, 8, 16,
|
||||
str_lit("x86_64-apple-darwin"),
|
||||
str_lit("e-m:o-i64:64-f80:128-n8:16:32:64-S128"),
|
||||
};
|
||||
@@ -413,7 +413,7 @@ gb_global TargetMetrics target_darwin_amd64 = {
|
||||
gb_global TargetMetrics target_darwin_arm64 = {
|
||||
TargetOs_darwin,
|
||||
TargetArch_arm64,
|
||||
8, 8, 16,
|
||||
8, 8, 8, 16,
|
||||
str_lit("arm64-apple-macosx11.0.0"),
|
||||
str_lit("e-m:o-i64:64-i128:128-n32:64-S128"),
|
||||
};
|
||||
@@ -421,14 +421,14 @@ gb_global TargetMetrics target_darwin_arm64 = {
|
||||
gb_global TargetMetrics target_freebsd_i386 = {
|
||||
TargetOs_freebsd,
|
||||
TargetArch_i386,
|
||||
4, 4, 8,
|
||||
4, 4, 4, 8,
|
||||
str_lit("i386-unknown-freebsd-elf"),
|
||||
};
|
||||
|
||||
gb_global TargetMetrics target_freebsd_amd64 = {
|
||||
TargetOs_freebsd,
|
||||
TargetArch_amd64,
|
||||
8, 8, 16,
|
||||
8, 8, 8, 16,
|
||||
str_lit("x86_64-unknown-freebsd-elf"),
|
||||
str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"),
|
||||
};
|
||||
@@ -436,7 +436,7 @@ gb_global TargetMetrics target_freebsd_amd64 = {
|
||||
gb_global TargetMetrics target_openbsd_amd64 = {
|
||||
TargetOs_openbsd,
|
||||
TargetArch_amd64,
|
||||
8, 8, 16,
|
||||
8, 8, 8, 16,
|
||||
str_lit("x86_64-unknown-openbsd-elf"),
|
||||
str_lit("e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"),
|
||||
};
|
||||
@@ -444,7 +444,7 @@ gb_global TargetMetrics target_openbsd_amd64 = {
|
||||
gb_global TargetMetrics target_essence_amd64 = {
|
||||
TargetOs_essence,
|
||||
TargetArch_amd64,
|
||||
8, 8, 16,
|
||||
8, 8, 8, 16,
|
||||
str_lit("x86_64-pc-none-elf"),
|
||||
};
|
||||
|
||||
@@ -452,7 +452,7 @@ gb_global TargetMetrics target_essence_amd64 = {
|
||||
gb_global TargetMetrics target_freestanding_wasm32 = {
|
||||
TargetOs_freestanding,
|
||||
TargetArch_wasm32,
|
||||
4, 8, 16,
|
||||
4, 4, 8, 16,
|
||||
str_lit("wasm32-freestanding-js"),
|
||||
str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"),
|
||||
};
|
||||
@@ -460,7 +460,7 @@ gb_global TargetMetrics target_freestanding_wasm32 = {
|
||||
gb_global TargetMetrics target_js_wasm32 = {
|
||||
TargetOs_js,
|
||||
TargetArch_wasm32,
|
||||
4, 8, 16,
|
||||
4, 4, 8, 16,
|
||||
str_lit("wasm32-js-js"),
|
||||
str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"),
|
||||
};
|
||||
@@ -468,24 +468,42 @@ gb_global TargetMetrics target_js_wasm32 = {
|
||||
gb_global TargetMetrics target_wasi_wasm32 = {
|
||||
TargetOs_wasi,
|
||||
TargetArch_wasm32,
|
||||
4, 8, 16,
|
||||
4, 4, 8, 16,
|
||||
str_lit("wasm32-wasi-js"),
|
||||
str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"),
|
||||
};
|
||||
|
||||
|
||||
gb_global TargetMetrics target_js_wasm64 = {
|
||||
TargetOs_js,
|
||||
TargetArch_wasm64,
|
||||
8, 8, 16,
|
||||
str_lit("wasm64-js-js"),
|
||||
str_lit(""),
|
||||
gb_global TargetMetrics target_freestanding_wasm64p32 = {
|
||||
TargetOs_freestanding,
|
||||
TargetArch_wasm64p32,
|
||||
4, 8, 8, 16,
|
||||
str_lit("wasm32-freestanding-js"),
|
||||
str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"),
|
||||
};
|
||||
|
||||
gb_global TargetMetrics target_js_wasm64p32 = {
|
||||
TargetOs_js,
|
||||
TargetArch_wasm64p32,
|
||||
4, 8, 8, 16,
|
||||
str_lit("wasm32-js-js"),
|
||||
str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"),
|
||||
};
|
||||
|
||||
gb_global TargetMetrics target_wasi_wasm64p32 = {
|
||||
TargetOs_wasi,
|
||||
TargetArch_wasm32,
|
||||
4, 8, 8, 16,
|
||||
str_lit("wasm32-wasi-js"),
|
||||
str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"),
|
||||
};
|
||||
|
||||
|
||||
|
||||
gb_global TargetMetrics target_freestanding_amd64_sysv = {
|
||||
TargetOs_freestanding,
|
||||
TargetArch_amd64,
|
||||
8, 8, 16,
|
||||
8, 8, 8, 16,
|
||||
str_lit("x86_64-pc-none-gnu"),
|
||||
str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"),
|
||||
TargetABI_SysV,
|
||||
@@ -501,20 +519,29 @@ struct NamedTargetMetrics {
|
||||
gb_global NamedTargetMetrics named_targets[] = {
|
||||
{ str_lit("darwin_amd64"), &target_darwin_amd64 },
|
||||
{ str_lit("darwin_arm64"), &target_darwin_arm64 },
|
||||
|
||||
{ str_lit("essence_amd64"), &target_essence_amd64 },
|
||||
|
||||
{ str_lit("linux_i386"), &target_linux_i386 },
|
||||
{ str_lit("linux_amd64"), &target_linux_amd64 },
|
||||
{ str_lit("linux_arm64"), &target_linux_arm64 },
|
||||
{ str_lit("linux_arm32"), &target_linux_arm32 },
|
||||
|
||||
{ str_lit("windows_i386"), &target_windows_i386 },
|
||||
{ str_lit("windows_amd64"), &target_windows_amd64 },
|
||||
|
||||
{ str_lit("freebsd_i386"), &target_freebsd_i386 },
|
||||
{ str_lit("freebsd_amd64"), &target_freebsd_amd64 },
|
||||
|
||||
{ str_lit("openbsd_amd64"), &target_openbsd_amd64 },
|
||||
|
||||
{ str_lit("freestanding_wasm32"), &target_freestanding_wasm32 },
|
||||
{ str_lit("wasi_wasm32"), &target_wasi_wasm32 },
|
||||
{ str_lit("js_wasm32"), &target_js_wasm32 },
|
||||
// { str_lit("js_wasm64"), &target_js_wasm64 },
|
||||
|
||||
{ str_lit("freestanding_wasm64p32"), &target_freestanding_wasm64p32 },
|
||||
{ str_lit("js_wasm64p32"), &target_js_wasm64p32 },
|
||||
{ str_lit("wasi_wasm64p32"), &target_wasi_wasm64p32 },
|
||||
|
||||
{ str_lit("freestanding_amd64_sysv"), &target_freestanding_amd64_sysv },
|
||||
};
|
||||
@@ -623,7 +650,7 @@ gb_internal bool find_library_collection_path(String name, String *path) {
|
||||
gb_internal bool is_arch_wasm(void) {
|
||||
switch (build_context.metrics.arch) {
|
||||
case TargetArch_wasm32:
|
||||
case TargetArch_wasm64:
|
||||
case TargetArch_wasm64p32:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -641,7 +668,7 @@ gb_internal bool is_arch_x86(void) {
|
||||
gb_internal bool allow_check_foreign_filepath(void) {
|
||||
switch (build_context.metrics.arch) {
|
||||
case TargetArch_wasm32:
|
||||
case TargetArch_wasm64:
|
||||
case TargetArch_wasm64p32:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -1164,16 +1191,24 @@ gb_internal void init_build_context(TargetMetrics *cross_target) {
|
||||
|
||||
GB_ASSERT(metrics->os != TargetOs_Invalid);
|
||||
GB_ASSERT(metrics->arch != TargetArch_Invalid);
|
||||
GB_ASSERT(metrics->word_size > 1);
|
||||
GB_ASSERT(metrics->ptr_size > 1);
|
||||
GB_ASSERT(metrics->int_size > 1);
|
||||
GB_ASSERT(metrics->max_align > 1);
|
||||
GB_ASSERT(metrics->max_simd_align > 1);
|
||||
|
||||
GB_ASSERT(metrics->int_size >= metrics->ptr_size);
|
||||
if (metrics->int_size > metrics->ptr_size) {
|
||||
GB_ASSERT(metrics->int_size == 2*metrics->ptr_size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bc->metrics = *metrics;
|
||||
bc->ODIN_OS = target_os_names[metrics->os];
|
||||
bc->ODIN_ARCH = target_arch_names[metrics->arch];
|
||||
bc->endian_kind = target_endians[metrics->arch];
|
||||
bc->word_size = metrics->word_size;
|
||||
bc->ptr_size = metrics->ptr_size;
|
||||
bc->int_size = metrics->int_size;
|
||||
bc->max_align = metrics->max_align;
|
||||
bc->max_simd_align = metrics->max_simd_align;
|
||||
bc->link_flags = str_lit(" ");
|
||||
@@ -1257,9 +1292,9 @@ gb_internal void init_build_context(TargetMetrics *cross_target) {
|
||||
// link_flags = gb_string_appendc(link_flags, "--export-all ");
|
||||
// link_flags = gb_string_appendc(link_flags, "--export-table ");
|
||||
link_flags = gb_string_appendc(link_flags, "--allow-undefined ");
|
||||
if (bc->metrics.arch == TargetArch_wasm64) {
|
||||
link_flags = gb_string_appendc(link_flags, "-mwasm64 ");
|
||||
}
|
||||
// if (bc->metrics.arch == TargetArch_wasm64) {
|
||||
// link_flags = gb_string_appendc(link_flags, "-mwasm64 ");
|
||||
// }
|
||||
if (bc->no_entry_point) {
|
||||
link_flags = gb_string_appendc(link_flags, "--no-entry ");
|
||||
}
|
||||
|
||||
@@ -239,6 +239,10 @@ gb_internal bool check_is_terminating(Ast *node, String const &label) {
|
||||
return check_is_terminating(unparen_expr(es->expr), label);
|
||||
case_end;
|
||||
|
||||
case_ast_node(bs, BranchStmt, node);
|
||||
return bs->token.kind == Token_fallthrough;
|
||||
case_end;
|
||||
|
||||
case_ast_node(is, IfStmt, node);
|
||||
if (is->else_stmt != nullptr) {
|
||||
if (check_is_terminating(is->body, label) &&
|
||||
|
||||
@@ -651,6 +651,9 @@ gb_internal bool check_vet_unused(Checker *c, Entity *e, VettedEntity *ve) {
|
||||
case Entity_Variable:
|
||||
if (e->scope->flags & (ScopeFlag_Global|ScopeFlag_Type|ScopeFlag_File)) {
|
||||
return false;
|
||||
} else if (e->flags & EntityFlag_Static) {
|
||||
// ignore these for the time being
|
||||
return false;
|
||||
}
|
||||
case Entity_ImportName:
|
||||
case Entity_LibraryName:
|
||||
@@ -912,6 +915,13 @@ gb_internal Type *add_global_type_name(Scope *scope, String const &type_name, Ty
|
||||
return named_type;
|
||||
}
|
||||
|
||||
gb_internal i64 odin_compile_timestamp(void) {
|
||||
i64 us_after_1601 = cast(i64)gb_utc_time_now();
|
||||
i64 us_after_1970 = us_after_1601 - 11644473600000000ll;
|
||||
i64 ns_after_1970 = us_after_1970*1000ll;
|
||||
return ns_after_1970;
|
||||
}
|
||||
|
||||
|
||||
gb_internal void init_universal(void) {
|
||||
BuildContext *bc = &build_context;
|
||||
@@ -971,13 +981,13 @@ gb_internal void init_universal(void) {
|
||||
|
||||
{
|
||||
GlobalEnumValue values[TargetArch_COUNT] = {
|
||||
{"Unknown", TargetArch_Invalid},
|
||||
{"amd64", TargetArch_amd64},
|
||||
{"i386", TargetArch_i386},
|
||||
{"arm32", TargetArch_arm32},
|
||||
{"arm64", TargetArch_arm64},
|
||||
{"wasm32", TargetArch_wasm32},
|
||||
{"wasm64", TargetArch_wasm64},
|
||||
{"Unknown", TargetArch_Invalid},
|
||||
{"amd64", TargetArch_amd64},
|
||||
{"i386", TargetArch_i386},
|
||||
{"arm32", TargetArch_arm32},
|
||||
{"arm64", TargetArch_arm64},
|
||||
{"wasm32", TargetArch_wasm32},
|
||||
{"wasm64p32", TargetArch_wasm64p32},
|
||||
};
|
||||
|
||||
auto fields = add_global_enum_type(str_lit("Odin_Arch_Type"), values, gb_count_of(values));
|
||||
@@ -1000,8 +1010,6 @@ gb_internal void init_universal(void) {
|
||||
|
||||
{
|
||||
GlobalEnumValue values[TargetEndian_COUNT] = {
|
||||
{"Unknown", TargetEndian_Invalid},
|
||||
|
||||
{"Little", TargetEndian_Little},
|
||||
{"Big", TargetEndian_Big},
|
||||
};
|
||||
@@ -1050,6 +1058,7 @@ gb_internal void init_universal(void) {
|
||||
|
||||
add_global_bool_constant("ODIN_VALGRIND_SUPPORT", bc->ODIN_VALGRIND_SUPPORT);
|
||||
|
||||
add_global_constant("ODIN_COMPILE_TIMESTAMP", t_untyped_integer, exact_value_i64(odin_compile_timestamp()));
|
||||
|
||||
|
||||
// Builtin Procedures
|
||||
@@ -3889,7 +3898,10 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
||||
GB_ASSERT(pl->type->kind == Ast_ProcType);
|
||||
auto cc = pl->type->ProcType.calling_convention;
|
||||
if (cc == ProcCC_ForeignBlockDefault) {
|
||||
if (is_arch_wasm()) {
|
||||
cc = ProcCC_CDecl;
|
||||
if (c->foreign_context.default_cc > 0) {
|
||||
cc = c->foreign_context.default_cc;
|
||||
} else if (is_arch_wasm()) {
|
||||
begin_error_block();
|
||||
error(init, "For wasm related targets, it is required that you either define the"
|
||||
" @(default_calling_convention=<string>) on the foreign block or"
|
||||
@@ -3897,10 +3909,6 @@ gb_internal void check_collect_value_decl(CheckerContext *c, Ast *decl) {
|
||||
error_line("\tSuggestion: when dealing with normal Odin code (e.g. js_wasm32), use \"contextless\"; when dealing with Emscripten like code, use \"c\"\n");
|
||||
end_error_block();
|
||||
}
|
||||
cc = ProcCC_CDecl;
|
||||
if (c->foreign_context.default_cc > 0) {
|
||||
cc = c->foreign_context.default_cc;
|
||||
}
|
||||
}
|
||||
e->Procedure.link_prefix = c->foreign_context.link_prefix;
|
||||
|
||||
|
||||
@@ -342,9 +342,6 @@ gb_internal ExactValue exact_value_from_basic_literal(TokenKind kind, String con
|
||||
utf8_decode(string.text, string.len, &r);
|
||||
return exact_value_i64(r);
|
||||
}
|
||||
default:
|
||||
GB_PANIC("Invalid token for basic literal");
|
||||
break;
|
||||
}
|
||||
|
||||
ExactValue result = {ExactValue_Invalid};
|
||||
|
||||
@@ -218,7 +218,7 @@ gb_internal i64 lb_sizeof(LLVMTypeRef type) {
|
||||
case LLVMDoubleTypeKind:
|
||||
return 8;
|
||||
case LLVMPointerTypeKind:
|
||||
return build_context.word_size;
|
||||
return build_context.ptr_size;
|
||||
case LLVMStructTypeKind:
|
||||
{
|
||||
unsigned field_count = LLVMCountStructElementTypes(type);
|
||||
@@ -275,7 +275,7 @@ gb_internal i64 lb_alignof(LLVMTypeRef type) {
|
||||
case LLVMIntegerTypeKind:
|
||||
{
|
||||
unsigned w = LLVMGetIntTypeWidth(type);
|
||||
return gb_clamp((w + 7)/8, 1, build_context.word_size);
|
||||
return gb_clamp((w + 7)/8, 1, build_context.ptr_size);
|
||||
}
|
||||
case LLVMHalfTypeKind:
|
||||
return 2;
|
||||
@@ -284,7 +284,7 @@ gb_internal i64 lb_alignof(LLVMTypeRef type) {
|
||||
case LLVMDoubleTypeKind:
|
||||
return 8;
|
||||
case LLVMPointerTypeKind:
|
||||
return build_context.word_size;
|
||||
return build_context.ptr_size;
|
||||
case LLVMStructTypeKind:
|
||||
{
|
||||
if (LLVMIsPackedStruct(type)) {
|
||||
@@ -326,7 +326,7 @@ gb_internal i64 lb_alignof(LLVMTypeRef type) {
|
||||
}
|
||||
|
||||
|
||||
#define LB_ABI_INFO(name) lbFunctionType *name(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, LLVMTypeRef return_type, bool return_is_defined, bool return_is_tuple, ProcCallingConvention calling_convention)
|
||||
#define LB_ABI_INFO(name) lbFunctionType *name(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, LLVMTypeRef return_type, bool return_is_defined, bool return_is_tuple, ProcCallingConvention calling_convention, Type *original_type)
|
||||
typedef LB_ABI_INFO(lbAbiInfoType);
|
||||
|
||||
#define LB_ABI_COMPUTE_RETURN_TYPE(name) lbArgType name(lbFunctionType *ft, LLVMContextRef c, LLVMTypeRef return_type, bool return_is_defined, bool return_is_tuple)
|
||||
@@ -388,7 +388,7 @@ namespace lbAbi386 {
|
||||
}
|
||||
|
||||
if (build_context.metrics.os == TargetOs_windows &&
|
||||
build_context.word_size == 8 &&
|
||||
build_context.ptr_size == 8 &&
|
||||
lb_is_type_kind(type, LLVMIntegerTypeKind) &&
|
||||
type == LLVMIntTypeInContext(c, 128)) {
|
||||
// NOTE(bill): Because Windows AMD64 is weird
|
||||
@@ -1217,7 +1217,7 @@ namespace lbAbiWasm {
|
||||
The approach taken optimizes for passing things in multiple
|
||||
registers/arguments if possible rather than by pointer.
|
||||
*/
|
||||
gb_internal Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention);
|
||||
gb_internal Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention, Type *original_type);
|
||||
gb_internal LB_ABI_COMPUTE_RETURN_TYPE(compute_return_type);
|
||||
|
||||
enum {MAX_DIRECT_STRUCT_SIZE = 32};
|
||||
@@ -1225,7 +1225,7 @@ namespace lbAbiWasm {
|
||||
gb_internal LB_ABI_INFO(abi_info) {
|
||||
lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType);
|
||||
ft->ctx = c;
|
||||
ft->args = compute_arg_types(c, arg_types, arg_count, calling_convention);
|
||||
ft->args = compute_arg_types(c, arg_types, arg_count, calling_convention, original_type);
|
||||
ft->ret = compute_return_type(ft, c, return_type, return_is_defined, return_is_tuple);
|
||||
ft->calling_convention = calling_convention;
|
||||
return ft;
|
||||
@@ -1315,15 +1315,42 @@ namespace lbAbiWasm {
|
||||
return lb_arg_type_indirect(type, nullptr);
|
||||
}
|
||||
|
||||
gb_internal lbArgType pseudo_slice(LLVMContextRef c, LLVMTypeRef type, ProcCallingConvention calling_convention) {
|
||||
if (build_context.metrics.ptr_size < build_context.metrics.int_size &&
|
||||
type_can_be_direct(type, calling_convention)) {
|
||||
LLVMTypeRef types[2] = {
|
||||
LLVMStructGetTypeAtIndex(type, 0),
|
||||
// ignore padding
|
||||
LLVMStructGetTypeAtIndex(type, 2)
|
||||
};
|
||||
LLVMTypeRef new_type = LLVMStructTypeInContext(c, types, gb_count_of(types), false);
|
||||
return lb_arg_type_direct(type, new_type, nullptr, nullptr);
|
||||
} else {
|
||||
return is_struct(c, type, calling_convention);
|
||||
}
|
||||
}
|
||||
|
||||
gb_internal Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention) {
|
||||
gb_internal Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention,
|
||||
Type *original_type) {
|
||||
auto args = array_make<lbArgType>(lb_function_type_args_allocator(), arg_count);
|
||||
|
||||
for (unsigned i = 0; i < arg_count; i++) {
|
||||
GB_ASSERT(original_type->kind == Type_Proc);
|
||||
GB_ASSERT(cast(isize)arg_count <= original_type->Proc.param_count);
|
||||
auto const ¶ms = original_type->Proc.params->Tuple.variables;
|
||||
|
||||
for (unsigned i = 0, j = 0; i < arg_count; i++, j++) {
|
||||
while (params[j]->kind != Entity_Variable) {
|
||||
j++;
|
||||
}
|
||||
Type *ptype = params[j]->type;
|
||||
LLVMTypeRef t = arg_types[i];
|
||||
LLVMTypeKind kind = LLVMGetTypeKind(t);
|
||||
if (kind == LLVMStructTypeKind || kind == LLVMArrayTypeKind) {
|
||||
args[i] = is_struct(c, t, calling_convention);
|
||||
if (is_type_slice(ptype) || is_type_string(ptype)) {
|
||||
args[i] = pseudo_slice(c, t, calling_convention);
|
||||
} else {
|
||||
args[i] = is_struct(c, t, calling_convention);
|
||||
}
|
||||
} else {
|
||||
args[i] = non_struct(c, t, false);
|
||||
}
|
||||
@@ -1460,32 +1487,33 @@ gb_internal LB_ABI_INFO(lb_get_abi_info_internal) {
|
||||
}
|
||||
case ProcCC_Win64:
|
||||
GB_ASSERT(build_context.metrics.arch == TargetArch_amd64);
|
||||
return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention);
|
||||
return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type);
|
||||
case ProcCC_SysV:
|
||||
GB_ASSERT(build_context.metrics.arch == TargetArch_amd64);
|
||||
return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention);
|
||||
return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type);
|
||||
}
|
||||
|
||||
switch (build_context.metrics.arch) {
|
||||
case TargetArch_amd64:
|
||||
if (build_context.metrics.os == TargetOs_windows) {
|
||||
return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention);
|
||||
return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type);
|
||||
} else if (build_context.metrics.abi == TargetABI_Win64) {
|
||||
return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention);
|
||||
return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type);
|
||||
} else if (build_context.metrics.abi == TargetABI_SysV) {
|
||||
return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention);
|
||||
return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type);
|
||||
} else {
|
||||
return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention);
|
||||
return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type);
|
||||
}
|
||||
case TargetArch_i386:
|
||||
return lbAbi386::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention);
|
||||
return lbAbi386::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type);
|
||||
case TargetArch_arm32:
|
||||
return lbAbiArm32::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention);
|
||||
return lbAbiArm32::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type);
|
||||
case TargetArch_arm64:
|
||||
return lbAbiArm64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention);
|
||||
return lbAbiArm64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type);
|
||||
case TargetArch_wasm32:
|
||||
case TargetArch_wasm64:
|
||||
return lbAbiWasm::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention);
|
||||
return lbAbiWasm::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type);
|
||||
case TargetArch_wasm64p32:
|
||||
return lbAbiWasm::abi_info(c, arg_types, arg_count, return_type, return_is_defined, return_is_tuple, calling_convention, original_type);
|
||||
}
|
||||
|
||||
GB_PANIC("Unsupported ABI");
|
||||
@@ -1499,7 +1527,8 @@ gb_internal LB_ABI_INFO(lb_get_abi_info) {
|
||||
arg_types, arg_count,
|
||||
return_type, return_is_defined,
|
||||
ALLOW_SPLIT_MULTI_RETURNS && return_is_tuple && is_calling_convention_odin(calling_convention),
|
||||
calling_convention);
|
||||
calling_convention,
|
||||
base_type(original_type));
|
||||
|
||||
|
||||
// NOTE(bill): this is handled here rather than when developing the type in `lb_type_internal_for_procedures_raw`
|
||||
|
||||
@@ -1987,7 +1987,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
|
||||
LLVMInitializeAArch64Disassembler();
|
||||
break;
|
||||
case TargetArch_wasm32:
|
||||
case TargetArch_wasm64:
|
||||
case TargetArch_wasm64p32:
|
||||
LLVMInitializeWebAssemblyTargetInfo();
|
||||
LLVMInitializeWebAssemblyTarget();
|
||||
LLVMInitializeWebAssemblyTargetMC();
|
||||
|
||||
@@ -539,7 +539,7 @@ gb_internal void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValu
|
||||
gb_internal LLVMValueRef lb_mem_zero_ptr_internal(lbProcedure *p, LLVMValueRef ptr, LLVMValueRef len, unsigned alignment, bool is_volatile);
|
||||
|
||||
gb_internal gb_inline i64 lb_max_zero_init_size(void) {
|
||||
return cast(i64)(4*build_context.word_size);
|
||||
return cast(i64)(4*build_context.int_size);
|
||||
}
|
||||
|
||||
gb_internal LLVMTypeRef OdinLLVMGetArrayElementType(LLVMTypeRef type);
|
||||
|
||||
@@ -131,6 +131,25 @@ gb_internal lbValue lb_const_ptr_cast(lbModule *m, lbValue value, Type *t) {
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
gb_internal LLVMValueRef llvm_const_string_internal(lbModule *m, Type *t, LLVMValueRef data, LLVMValueRef len) {
|
||||
if (build_context.metrics.ptr_size < build_context.metrics.int_size) {
|
||||
LLVMValueRef values[3] = {
|
||||
data,
|
||||
LLVMConstNull(lb_type(m, t_i32)),
|
||||
len,
|
||||
};
|
||||
return llvm_const_named_struct_internal(lb_type(m, t), values, 3);
|
||||
} else {
|
||||
LLVMValueRef values[2] = {
|
||||
data,
|
||||
len,
|
||||
};
|
||||
return llvm_const_named_struct_internal(lb_type(m, t), values, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
gb_internal LLVMValueRef llvm_const_named_struct(lbModule *m, Type *t, LLVMValueRef *values, isize value_count_) {
|
||||
LLVMTypeRef struct_type = lb_type(m, t);
|
||||
GB_ASSERT(LLVMGetTypeKind(struct_type) == LLVMStructTypeKind);
|
||||
@@ -180,17 +199,33 @@ gb_internal LLVMValueRef llvm_const_array(LLVMTypeRef elem_type, LLVMValueRef *v
|
||||
return LLVMConstArray(elem_type, values, value_count);
|
||||
}
|
||||
|
||||
gb_internal LLVMValueRef llvm_const_slice_internal(lbModule *m, LLVMValueRef data, LLVMValueRef len) {
|
||||
if (build_context.metrics.ptr_size < build_context.metrics.int_size) {
|
||||
GB_ASSERT(build_context.metrics.ptr_size == 4);
|
||||
GB_ASSERT(build_context.metrics.int_size == 8);
|
||||
LLVMValueRef vals[3] = {
|
||||
data,
|
||||
LLVMConstNull(lb_type(m, t_u32)),
|
||||
len,
|
||||
};
|
||||
return LLVMConstStructInContext(m->ctx, vals, gb_count_of(vals), false);
|
||||
} else {
|
||||
LLVMValueRef vals[2] = {
|
||||
data,
|
||||
len,
|
||||
};
|
||||
return LLVMConstStructInContext(m->ctx, vals, gb_count_of(vals), false);
|
||||
}
|
||||
}
|
||||
gb_internal LLVMValueRef llvm_const_slice(lbModule *m, lbValue data, lbValue len) {
|
||||
GB_ASSERT(is_type_pointer(data.type) || is_type_multi_pointer(data.type));
|
||||
GB_ASSERT(are_types_identical(len.type, t_int));
|
||||
LLVMValueRef vals[2] = {
|
||||
data.value,
|
||||
len.value,
|
||||
};
|
||||
return LLVMConstStructInContext(m->ctx, vals, gb_count_of(vals), false);
|
||||
|
||||
return llvm_const_slice_internal(m, data.value, len.value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
gb_internal lbValue lb_const_nil(lbModule *m, Type *type) {
|
||||
LLVMValueRef v = LLVMConstNull(lb_type(m, type));
|
||||
return lbValue{v, type};
|
||||
@@ -643,10 +678,9 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo
|
||||
ptr = LLVMConstNull(lb_type(m, t_u8_ptr));
|
||||
}
|
||||
LLVMValueRef str_len = LLVMConstInt(lb_type(m, t_int), value.value_string.len, true);
|
||||
LLVMValueRef values[2] = {ptr, str_len};
|
||||
GB_ASSERT(is_type_string(original_type));
|
||||
|
||||
res.value = llvm_const_named_struct(m, original_type, values, 2);
|
||||
res.value = llvm_const_string_internal(m, original_type, ptr, str_len);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
@@ -52,8 +52,8 @@ gb_internal LLVMMetadataRef lb_debug_type_internal_proc(lbModule *m, Type *type)
|
||||
|
||||
GB_ASSERT(type != t_invalid);
|
||||
|
||||
/* unsigned const word_size = cast(unsigned)build_context.word_size;
|
||||
unsigned const word_bits = cast(unsigned)(8*build_context.word_size); */
|
||||
/* unsigned const ptr_size = cast(unsigned)build_context.ptr_size;
|
||||
unsigned const ptr_bits = cast(unsigned)(8*build_context.ptr_size); */
|
||||
|
||||
GB_ASSERT(type->kind == Type_Proc);
|
||||
unsigned parameter_count = 1;
|
||||
@@ -131,8 +131,9 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
|
||||
|
||||
GB_ASSERT(type != t_invalid);
|
||||
|
||||
/* unsigned const word_size = cast(unsigned)build_context.word_size; */
|
||||
unsigned const word_bits = cast(unsigned)(8*build_context.word_size);
|
||||
/* unsigned const ptr_size = cast(unsigned)build_context.ptr_size; */
|
||||
unsigned const int_bits = cast(unsigned)(8*build_context.int_size);
|
||||
unsigned const ptr_bits = cast(unsigned)(8*build_context.ptr_size);
|
||||
|
||||
switch (type->kind) {
|
||||
case Type_Basic:
|
||||
@@ -162,12 +163,12 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
|
||||
case Basic_f32: return lb_debug_type_basic_type(m, str_lit("f32"), 32, LLVMDWARFTypeEncoding_Float);
|
||||
case Basic_f64: return lb_debug_type_basic_type(m, str_lit("f64"), 64, LLVMDWARFTypeEncoding_Float);
|
||||
|
||||
case Basic_int: return lb_debug_type_basic_type(m, str_lit("int"), word_bits, LLVMDWARFTypeEncoding_Signed);
|
||||
case Basic_uint: return lb_debug_type_basic_type(m, str_lit("uint"), word_bits, LLVMDWARFTypeEncoding_Unsigned);
|
||||
case Basic_uintptr: return lb_debug_type_basic_type(m, str_lit("uintptr"), word_bits, LLVMDWARFTypeEncoding_Unsigned);
|
||||
case Basic_int: return lb_debug_type_basic_type(m, str_lit("int"), int_bits, LLVMDWARFTypeEncoding_Signed);
|
||||
case Basic_uint: return lb_debug_type_basic_type(m, str_lit("uint"), int_bits, LLVMDWARFTypeEncoding_Unsigned);
|
||||
case Basic_uintptr: return lb_debug_type_basic_type(m, str_lit("uintptr"), ptr_bits, LLVMDWARFTypeEncoding_Unsigned);
|
||||
|
||||
case Basic_typeid:
|
||||
return lb_debug_type_basic_type(m, str_lit("typeid"), word_bits, LLVMDWARFTypeEncoding_Unsigned);
|
||||
return lb_debug_type_basic_type(m, str_lit("typeid"), ptr_bits, LLVMDWARFTypeEncoding_Unsigned);
|
||||
|
||||
// Endian Specific Types
|
||||
case Basic_i16le: return lb_debug_type_basic_type(m, str_lit("i16le"), 16, LLVMDWARFTypeEncoding_Signed, LLVMDIFlagLittleEndian);
|
||||
@@ -251,26 +252,26 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
|
||||
case Basic_rawptr:
|
||||
{
|
||||
LLVMMetadataRef void_type = lb_debug_type_basic_type(m, str_lit("void"), 8, LLVMDWARFTypeEncoding_Unsigned);
|
||||
return LLVMDIBuilderCreatePointerType(m->debug_builder, void_type, word_bits, word_bits, LLVMDWARFTypeEncoding_Address, "rawptr", 6);
|
||||
return LLVMDIBuilderCreatePointerType(m->debug_builder, void_type, ptr_bits, ptr_bits, LLVMDWARFTypeEncoding_Address, "rawptr", 6);
|
||||
}
|
||||
case Basic_string:
|
||||
{
|
||||
LLVMMetadataRef elements[2] = {};
|
||||
elements[0] = lb_debug_struct_field(m, str_lit("data"), t_u8_ptr, 0);
|
||||
elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, word_bits);
|
||||
return lb_debug_basic_struct(m, str_lit("string"), 2*word_bits, word_bits, elements, gb_count_of(elements));
|
||||
elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, int_bits);
|
||||
return lb_debug_basic_struct(m, str_lit("string"), 2*int_bits, int_bits, elements, gb_count_of(elements));
|
||||
}
|
||||
case Basic_cstring:
|
||||
{
|
||||
LLVMMetadataRef char_type = lb_debug_type_basic_type(m, str_lit("char"), 8, LLVMDWARFTypeEncoding_Unsigned);
|
||||
return LLVMDIBuilderCreatePointerType(m->debug_builder, char_type, word_bits, word_bits, 0, "cstring", 7);
|
||||
return LLVMDIBuilderCreatePointerType(m->debug_builder, char_type, ptr_bits, ptr_bits, 0, "cstring", 7);
|
||||
}
|
||||
case Basic_any:
|
||||
{
|
||||
LLVMMetadataRef elements[2] = {};
|
||||
elements[0] = lb_debug_struct_field(m, str_lit("data"), t_rawptr, 0);
|
||||
elements[1] = lb_debug_struct_field(m, str_lit("id"), t_typeid, word_bits);
|
||||
return lb_debug_basic_struct(m, str_lit("any"), 2*word_bits, word_bits, elements, gb_count_of(elements));
|
||||
elements[1] = lb_debug_struct_field(m, str_lit("id"), t_typeid, ptr_bits);
|
||||
return lb_debug_basic_struct(m, str_lit("any"), 2*ptr_bits, ptr_bits, elements, gb_count_of(elements));
|
||||
}
|
||||
|
||||
// Untyped types
|
||||
@@ -292,11 +293,11 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
|
||||
GB_PANIC("Type_Named should be handled in lb_debug_type separately");
|
||||
|
||||
case Type_SoaPointer:
|
||||
return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->SoaPointer.elem), word_bits, word_bits, 0, nullptr, 0);
|
||||
return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->SoaPointer.elem), int_bits, int_bits, 0, nullptr, 0);
|
||||
case Type_Pointer:
|
||||
return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->Pointer.elem), word_bits, word_bits, 0, nullptr, 0);
|
||||
return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->Pointer.elem), ptr_bits, ptr_bits, 0, nullptr, 0);
|
||||
case Type_MultiPointer:
|
||||
return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->MultiPointer.elem), word_bits, word_bits, 0, nullptr, 0);
|
||||
return LLVMDIBuilderCreatePointerType(m->debug_builder, lb_debug_type(m, type->MultiPointer.elem), ptr_bits, ptr_bits, 0, nullptr, 0);
|
||||
|
||||
case Type_Array: {
|
||||
LLVMMetadataRef subscripts[1] = {};
|
||||
@@ -416,7 +417,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
|
||||
case Type_Proc:
|
||||
{
|
||||
LLVMMetadataRef proc_underlying_type = lb_debug_type_internal_proc(m, type);
|
||||
LLVMMetadataRef pointer_type = LLVMDIBuilderCreatePointerType(m->debug_builder, proc_underlying_type, word_bits, word_bits, 0, nullptr, 0);
|
||||
LLVMMetadataRef pointer_type = LLVMDIBuilderCreatePointerType(m->debug_builder, proc_underlying_type, ptr_bits, ptr_bits, 0, nullptr, 0);
|
||||
gbString name = type_to_string(type, temporary_allocator());
|
||||
return LLVMDIBuilderCreateTypedef(m->debug_builder, pointer_type, name, gb_string_length(name), nullptr, 0, nullptr, cast(u32)(8*type_align_of(type)));
|
||||
}
|
||||
@@ -447,10 +448,11 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
|
||||
unsigned element_count = 0;
|
||||
LLVMMetadataRef elements[2] = {};
|
||||
Type *base_integer = type->RelativeSlice.base_integer;
|
||||
unsigned base_bits = cast(unsigned)(8*type_size_of(base_integer));
|
||||
elements[0] = lb_debug_struct_field(m, str_lit("data_offset"), base_integer, 0);
|
||||
elements[1] = lb_debug_struct_field(m, str_lit("len"), base_integer, 8*type_size_of(base_integer));
|
||||
elements[1] = lb_debug_struct_field(m, str_lit("len"), base_integer, base_bits);
|
||||
gbString name = type_to_string(type, temporary_allocator());
|
||||
return LLVMDIBuilderCreateStructType(m->debug_builder, nullptr, name, gb_string_length(name), nullptr, 0, 2*word_bits, word_bits, LLVMDIFlagZero, nullptr, elements, element_count, 0, nullptr, "", 0);
|
||||
return LLVMDIBuilderCreateStructType(m->debug_builder, nullptr, name, gb_string_length(name), nullptr, 0, 2*base_bits, base_bits, LLVMDIFlagZero, nullptr, elements, element_count, 0, nullptr, "", 0);
|
||||
}
|
||||
|
||||
case Type_Matrix: {
|
||||
@@ -616,8 +618,7 @@ gb_internal LLVMMetadataRef lb_debug_type(lbModule *m, Type *type) {
|
||||
}
|
||||
|
||||
gb_internal void lb_debug_complete_types(lbModule *m) {
|
||||
/* unsigned const word_size = cast(unsigned)build_context.word_size; */
|
||||
unsigned const word_bits = cast(unsigned)(8*build_context.word_size);
|
||||
unsigned const int_bits = cast(unsigned)(8*build_context.int_size);
|
||||
|
||||
for_array(debug_incomplete_type_index, m->debug_incomplete_types) {
|
||||
TEMPORARY_ALLOCATOR_GUARD();
|
||||
@@ -691,27 +692,27 @@ gb_internal void lb_debug_complete_types(lbModule *m) {
|
||||
element_count = 2;
|
||||
elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count);
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
elements[0] = lb_debug_struct_field(m, str_lit("data"), alloc_type_pointer(bt->Slice.elem), 0*word_bits);
|
||||
elements[0] = lb_debug_struct_field(m, str_lit("data"), alloc_type_pointer(bt->Slice.elem), 0*int_bits);
|
||||
#else
|
||||
// FIX HACK TODO(bill): For some reason this causes a crash in *nix systems due to the reference counting
|
||||
// of the debug type information
|
||||
elements[0] = lb_debug_struct_field(m, str_lit("data"), t_rawptr, 0*word_bits);
|
||||
elements[0] = lb_debug_struct_field(m, str_lit("data"), t_rawptr, 0*int_bits);
|
||||
#endif
|
||||
elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, 1*word_bits);
|
||||
elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, 1*int_bits);
|
||||
break;
|
||||
case Type_DynamicArray:
|
||||
element_count = 4;
|
||||
elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count);
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
elements[0] = lb_debug_struct_field(m, str_lit("data"), alloc_type_pointer(bt->DynamicArray.elem), 0*word_bits);
|
||||
elements[0] = lb_debug_struct_field(m, str_lit("data"), alloc_type_pointer(bt->DynamicArray.elem), 0*int_bits);
|
||||
#else
|
||||
// FIX HACK TODO(bill): For some reason this causes a crash in *nix systems due to the reference counting
|
||||
// of the debug type information
|
||||
elements[0] = lb_debug_struct_field(m, str_lit("data"), t_rawptr, 0*word_bits);
|
||||
elements[0] = lb_debug_struct_field(m, str_lit("data"), t_rawptr, 0*int_bits);
|
||||
#endif
|
||||
elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, 1*word_bits);
|
||||
elements[2] = lb_debug_struct_field(m, str_lit("cap"), t_int, 2*word_bits);
|
||||
elements[3] = lb_debug_struct_field(m, str_lit("allocator"), t_allocator, 3*word_bits);
|
||||
elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, 1*int_bits);
|
||||
elements[2] = lb_debug_struct_field(m, str_lit("cap"), t_int, 2*int_bits);
|
||||
elements[3] = lb_debug_struct_field(m, str_lit("allocator"), t_allocator, 3*int_bits);
|
||||
break;
|
||||
|
||||
case Type_Map:
|
||||
@@ -737,7 +738,7 @@ gb_internal void lb_debug_complete_types(lbModule *m) {
|
||||
element_count = cast(unsigned)(bt->Struct.fields.count + element_offset);
|
||||
elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count);
|
||||
|
||||
isize field_size_bits = 8*type_size_of(bt) - element_offset*word_bits;
|
||||
isize field_size_bits = 8*type_size_of(bt) - element_offset*int_bits;
|
||||
|
||||
switch (bt->Struct.soa_kind) {
|
||||
case StructSoa_Slice:
|
||||
@@ -756,7 +757,7 @@ gb_internal void lb_debug_complete_types(lbModule *m) {
|
||||
".len", 4,
|
||||
file, 0,
|
||||
8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int),
|
||||
field_size_bits + 0*word_bits,
|
||||
field_size_bits + 0*int_bits,
|
||||
LLVMDIFlagZero, lb_debug_type(m, t_int)
|
||||
);
|
||||
elements[1] = LLVMDIBuilderCreateMemberType(
|
||||
@@ -764,7 +765,7 @@ gb_internal void lb_debug_complete_types(lbModule *m) {
|
||||
".cap", 4,
|
||||
file, 0,
|
||||
8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int),
|
||||
field_size_bits + 1*word_bits,
|
||||
field_size_bits + 1*int_bits,
|
||||
LLVMDIFlagZero, lb_debug_type(m, t_int)
|
||||
);
|
||||
elements[2] = LLVMDIBuilderCreateMemberType(
|
||||
@@ -772,7 +773,7 @@ gb_internal void lb_debug_complete_types(lbModule *m) {
|
||||
".allocator", 10,
|
||||
file, 0,
|
||||
8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int),
|
||||
field_size_bits + 2*word_bits,
|
||||
field_size_bits + 2*int_bits,
|
||||
LLVMDIFlagZero, lb_debug_type(m, t_allocator)
|
||||
);
|
||||
break;
|
||||
|
||||
@@ -518,7 +518,7 @@ gb_internal bool lb_is_matrix_simdable(Type *t) {
|
||||
return true;
|
||||
case TargetArch_i386:
|
||||
case TargetArch_wasm32:
|
||||
case TargetArch_wasm64:
|
||||
case TargetArch_wasm64p32:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -4230,11 +4230,12 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
|
||||
lbValue count = {};
|
||||
count.type = t_int;
|
||||
|
||||
unsigned len_index = lb_convert_struct_index(p->module, type, 1);
|
||||
if (lb_is_const(slice)) {
|
||||
unsigned indices[1] = {1};
|
||||
unsigned indices[1] = {len_index};
|
||||
count.value = LLVMConstExtractValue(slice.value, indices, gb_count_of(indices));
|
||||
} else {
|
||||
count.value = LLVMBuildExtractValue(p->builder, slice.value, 1, "");
|
||||
count.value = LLVMBuildExtractValue(p->builder, slice.value, len_index, "");
|
||||
}
|
||||
lb_fill_slice(p, v, data, count);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
gb_internal void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, Token const &token);
|
||||
gb_internal LLVMValueRef llvm_const_string_internal(lbModule *m, Type *t, LLVMValueRef data, LLVMValueRef len);
|
||||
|
||||
gb_global Entity *lb_global_type_info_data_entity = {};
|
||||
gb_global lbAddr lb_global_type_info_member_types = {};
|
||||
@@ -1579,7 +1580,7 @@ gb_internal LLVMTypeRef lb_type_internal_for_procedures_raw(lbModule *m, Type *t
|
||||
}
|
||||
}
|
||||
GB_ASSERT(param_index == param_count);
|
||||
lbFunctionType *ft = lb_get_abi_info(m->ctx, params, param_count, ret, ret != nullptr, return_is_tuple, type->Proc.calling_convention);
|
||||
lbFunctionType *ft = lb_get_abi_info(m->ctx, params, param_count, ret, ret != nullptr, return_is_tuple, type->Proc.calling_convention, type);
|
||||
{
|
||||
for_array(j, ft->args) {
|
||||
auto arg = ft->args[j];
|
||||
@@ -1626,6 +1627,8 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
|
||||
GB_ASSERT(type != t_invalid);
|
||||
|
||||
bool bigger_int = build_context.ptr_size != build_context.int_size;
|
||||
|
||||
switch (type->kind) {
|
||||
case Type_Basic:
|
||||
switch (type->Basic.kind) {
|
||||
@@ -1760,10 +1763,10 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
return type;
|
||||
}
|
||||
|
||||
case Basic_int: return LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.word_size);
|
||||
case Basic_uint: return LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.word_size);
|
||||
case Basic_int: return LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.int_size);
|
||||
case Basic_uint: return LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.int_size);
|
||||
|
||||
case Basic_uintptr: return LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.word_size);
|
||||
case Basic_uintptr: return LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.ptr_size);
|
||||
|
||||
case Basic_rawptr: return LLVMPointerType(LLVMInt8TypeInContext(ctx), 0);
|
||||
case Basic_string:
|
||||
@@ -1774,11 +1777,23 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
return type;
|
||||
}
|
||||
type = LLVMStructCreateNamed(ctx, name);
|
||||
LLVMTypeRef fields[2] = {
|
||||
LLVMPointerType(lb_type(m, t_u8), 0),
|
||||
lb_type(m, t_int),
|
||||
};
|
||||
LLVMStructSetBody(type, fields, 2, false);
|
||||
|
||||
if (build_context.metrics.ptr_size < build_context.metrics.int_size) {
|
||||
GB_ASSERT(build_context.metrics.ptr_size == 4);
|
||||
GB_ASSERT(build_context.metrics.int_size == 8);
|
||||
LLVMTypeRef fields[3] = {
|
||||
LLVMPointerType(lb_type(m, t_u8), 0),
|
||||
lb_type(m, t_i32),
|
||||
lb_type(m, t_int),
|
||||
};
|
||||
LLVMStructSetBody(type, fields, 3, false);
|
||||
} else {
|
||||
LLVMTypeRef fields[2] = {
|
||||
LLVMPointerType(lb_type(m, t_u8), 0),
|
||||
lb_type(m, t_int),
|
||||
};
|
||||
LLVMStructSetBody(type, fields, 2, false);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
case Basic_cstring: return LLVMPointerType(LLVMInt8TypeInContext(ctx), 0);
|
||||
@@ -1798,7 +1813,7 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
return type;
|
||||
}
|
||||
|
||||
case Basic_typeid: return LLVMIntTypeInContext(m->ctx, 8*cast(unsigned)build_context.word_size);
|
||||
case Basic_typeid: return LLVMIntTypeInContext(m->ctx, 8*cast(unsigned)build_context.ptr_size);
|
||||
|
||||
// Endian Specific Types
|
||||
case Basic_i16le: return LLVMInt16TypeInContext(ctx);
|
||||
@@ -1922,23 +1937,43 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
|
||||
case Type_Slice:
|
||||
{
|
||||
LLVMTypeRef fields[2] = {
|
||||
LLVMPointerType(lb_type(m, type->Slice.elem), 0), // data
|
||||
lb_type(m, t_int), // len
|
||||
};
|
||||
return LLVMStructTypeInContext(ctx, fields, 2, false);
|
||||
if (bigger_int) {
|
||||
LLVMTypeRef fields[3] = {
|
||||
LLVMPointerType(lb_type(m, type->Slice.elem), 0), // data
|
||||
lb_type_padding_filler(m, build_context.ptr_size, build_context.ptr_size), // padding
|
||||
lb_type(m, t_int), // len
|
||||
};
|
||||
return LLVMStructTypeInContext(ctx, fields, gb_count_of(fields), false);
|
||||
} else {
|
||||
LLVMTypeRef fields[2] = {
|
||||
LLVMPointerType(lb_type(m, type->Slice.elem), 0), // data
|
||||
lb_type(m, t_int), // len
|
||||
};
|
||||
return LLVMStructTypeInContext(ctx, fields, gb_count_of(fields), false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_DynamicArray:
|
||||
{
|
||||
LLVMTypeRef fields[4] = {
|
||||
LLVMPointerType(lb_type(m, type->DynamicArray.elem), 0), // data
|
||||
lb_type(m, t_int), // len
|
||||
lb_type(m, t_int), // cap
|
||||
lb_type(m, t_allocator), // allocator
|
||||
};
|
||||
return LLVMStructTypeInContext(ctx, fields, 4, false);
|
||||
if (bigger_int) {
|
||||
LLVMTypeRef fields[5] = {
|
||||
LLVMPointerType(lb_type(m, type->DynamicArray.elem), 0), // data
|
||||
lb_type_padding_filler(m, build_context.ptr_size, build_context.ptr_size), // padding
|
||||
lb_type(m, t_int), // len
|
||||
lb_type(m, t_int), // cap
|
||||
lb_type(m, t_allocator), // allocator
|
||||
};
|
||||
return LLVMStructTypeInContext(ctx, fields, gb_count_of(fields), false);
|
||||
} else {
|
||||
LLVMTypeRef fields[4] = {
|
||||
LLVMPointerType(lb_type(m, type->DynamicArray.elem), 0), // data
|
||||
lb_type(m, t_int), // len
|
||||
lb_type(m, t_int), // cap
|
||||
lb_type(m, t_allocator), // allocator
|
||||
};
|
||||
return LLVMStructTypeInContext(ctx, fields, gb_count_of(fields), false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2145,9 +2180,17 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
||||
case Type_SoaPointer:
|
||||
{
|
||||
unsigned field_count = 2;
|
||||
if (bigger_int) {
|
||||
field_count = 3;
|
||||
}
|
||||
LLVMTypeRef *fields = gb_alloc_array(permanent_allocator(), LLVMTypeRef, field_count);
|
||||
fields[0] = LLVMPointerType(lb_type(m, type->Pointer.elem), 0);
|
||||
fields[1] = LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.word_size);
|
||||
if (bigger_int) {
|
||||
fields[1] = lb_type_padding_filler(m, build_context.ptr_size, build_context.ptr_size);
|
||||
fields[2] = LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.int_size);
|
||||
} else {
|
||||
fields[1] = LLVMIntTypeInContext(ctx, 8*cast(unsigned)build_context.int_size);
|
||||
}
|
||||
return LLVMStructTypeInContext(ctx, fields, field_count, false);
|
||||
}
|
||||
|
||||
@@ -2503,10 +2546,9 @@ gb_internal lbValue lb_find_or_add_entity_string(lbModule *m, String const &str)
|
||||
ptr = LLVMConstNull(lb_type(m, t_u8_ptr));
|
||||
}
|
||||
LLVMValueRef str_len = LLVMConstInt(lb_type(m, t_int), str.len, true);
|
||||
LLVMValueRef values[2] = {ptr, str_len};
|
||||
|
||||
lbValue res = {};
|
||||
res.value = llvm_const_named_struct(m, t_string, values, 2);
|
||||
res.value = llvm_const_string_internal(m, t_string, ptr, str_len);
|
||||
res.type = t_string;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ gb_internal void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue sr
|
||||
char const *name = "llvm.memmove";
|
||||
if (LLVMIsConstant(len.value)) {
|
||||
i64 const_len = cast(i64)LLVMConstIntGetSExtValue(len.value);
|
||||
if (const_len <= 4*build_context.word_size) {
|
||||
if (const_len <= 4*build_context.int_size) {
|
||||
name = "llvm.memmove.inline";
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ gb_internal void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValu
|
||||
char const *name = "llvm.memcpy";
|
||||
if (LLVMIsConstant(len.value)) {
|
||||
i64 const_len = cast(i64)LLVMConstIntGetSExtValue(len.value);
|
||||
if (const_len <= 4*build_context.word_size) {
|
||||
if (const_len <= 4*build_context.int_size) {
|
||||
name = "llvm.memcpy.inline";
|
||||
}
|
||||
}
|
||||
@@ -2660,10 +2660,26 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
|
||||
{
|
||||
GB_ASSERT(arg_count <= 7);
|
||||
|
||||
// FreeBSD additionally clobbers r8, r9, r10, but they
|
||||
// can also be used to pass in arguments, so this needs
|
||||
// to be handled in two parts.
|
||||
bool clobber_arg_regs[7] = {
|
||||
false, false, false, false, false, false, false
|
||||
};
|
||||
if (build_context.metrics.os == TargetOs_freebsd) {
|
||||
clobber_arg_regs[4] = true; // r10
|
||||
clobber_arg_regs[5] = true; // r8
|
||||
clobber_arg_regs[6] = true; // r9
|
||||
}
|
||||
|
||||
char asm_string[] = "syscall";
|
||||
gbString constraints = gb_string_make(heap_allocator(), "={rax}");
|
||||
for (unsigned i = 0; i < arg_count; i++) {
|
||||
constraints = gb_string_appendc(constraints, ",{");
|
||||
if (!clobber_arg_regs[i]) {
|
||||
constraints = gb_string_appendc(constraints, ",{");
|
||||
} else {
|
||||
constraints = gb_string_appendc(constraints, ",+{");
|
||||
}
|
||||
static char const *regs[] = {
|
||||
"rax",
|
||||
"rdi",
|
||||
@@ -2687,10 +2703,35 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
|
||||
// Some but not all system calls will additionally
|
||||
// clobber memory.
|
||||
//
|
||||
// TODO: FreeBSD is different and will also clobber
|
||||
// R8, R9, and R10. Additionally CF is used to
|
||||
// indicate an error instead of -errno.
|
||||
// As a fix for CVE-2019-5595, FreeBSD started
|
||||
// clobbering R8, R9, and R10, instead of restoring
|
||||
// them. Additionally unlike Linux, instead of
|
||||
// returning negative errno, positive errno is
|
||||
// returned and CF is set.
|
||||
//
|
||||
// TODO:
|
||||
// * Figure out what Darwin does.
|
||||
// * Add some extra handling to propagate CF back
|
||||
// up to the caller on FreeBSD systems so that
|
||||
// the caller knows that the return value is
|
||||
// positive errno.
|
||||
constraints = gb_string_appendc(constraints, ",~{rcx},~{r11},~{memory}");
|
||||
if (build_context.metrics.os == TargetOs_freebsd) {
|
||||
// Second half of dealing with FreeBSD's system
|
||||
// call semantics. Explicitly clobber the registers
|
||||
// that were not used to pass in arguments, and
|
||||
// then clobber RFLAGS.
|
||||
if (arg_count < 5) {
|
||||
constraints = gb_string_appendc(constraints, ",~{r10}");
|
||||
}
|
||||
if (arg_count < 6) {
|
||||
constraints = gb_string_appendc(constraints, ",~{r8}");
|
||||
}
|
||||
if (arg_count < 7) {
|
||||
constraints = gb_string_appendc(constraints, ",~{r9}");
|
||||
}
|
||||
constraints = gb_string_appendc(constraints, ",~{cc}");
|
||||
}
|
||||
|
||||
inline_asm = llvm_get_inline_asm(func_type, make_string_c(asm_string), make_string_c(constraints));
|
||||
}
|
||||
@@ -2890,7 +2931,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
|
||||
{
|
||||
char const *name = "llvm.wasm.memory.grow";
|
||||
LLVMTypeRef types[1] = {
|
||||
lb_type(p->module, t_uintptr),
|
||||
lb_type(p->module, t_i32),
|
||||
};
|
||||
|
||||
LLVMValueRef args[2] = {};
|
||||
@@ -2898,24 +2939,24 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu
|
||||
args[1] = lb_emit_conv(p, lb_build_expr(p, ce->args[1]), t_uintptr).value;
|
||||
|
||||
lbValue res = {};
|
||||
res.type = tv.type;
|
||||
res.type = t_i32;
|
||||
res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
|
||||
return res;
|
||||
return lb_emit_conv(p, res, tv.type);
|
||||
}
|
||||
case BuiltinProc_wasm_memory_size:
|
||||
{
|
||||
char const *name = "llvm.wasm.memory.size";
|
||||
LLVMTypeRef types[1] = {
|
||||
lb_type(p->module, t_uintptr),
|
||||
lb_type(p->module, t_i32),
|
||||
};
|
||||
|
||||
LLVMValueRef args[1] = {};
|
||||
args[0] = lb_emit_conv(p, lb_build_expr(p, ce->args[0]), t_uintptr).value;
|
||||
|
||||
lbValue res = {};
|
||||
res.type = tv.type;
|
||||
res.type = t_i32;
|
||||
res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types));
|
||||
return res;
|
||||
return lb_emit_conv(p, res, tv.type);
|
||||
}
|
||||
|
||||
case BuiltinProc_wasm_memory_atomic_wait32:
|
||||
|
||||
@@ -1812,7 +1812,7 @@ gb_internal void lb_build_return_stmt_internal(lbProcedure *p, lbValue res) {
|
||||
if (res.value != nullptr) {
|
||||
LLVMValueRef res_val = res.value;
|
||||
i64 sz = type_size_of(res.type);
|
||||
if (LLVMIsALoadInst(res_val) && sz > build_context.word_size) {
|
||||
if (LLVMIsALoadInst(res_val) && sz > build_context.int_size) {
|
||||
lbValue ptr = lb_address_from_load_or_generate_local(p, res);
|
||||
lb_mem_copy_non_overlapping(p, p->return_ptr.addr, ptr, lb_const_int(p->module, t_int, sz));
|
||||
} else {
|
||||
@@ -2463,6 +2463,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
|
||||
lb_add_entity(p->module, e, val);
|
||||
lb_add_debug_local_variable(p, val.value, e->type, e->token);
|
||||
lvals_preused[lval_index] = true;
|
||||
lvals[lval_index] = *comp_lit_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2471,6 +2472,7 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) {
|
||||
}
|
||||
GB_ASSERT(lval_index == lvals.count);
|
||||
|
||||
|
||||
for_array(i, vd->names) {
|
||||
Ast *name = vd->names[i];
|
||||
if (!is_blank_ident(name) && !lvals_preused[i]) {
|
||||
|
||||
@@ -68,21 +68,21 @@ gb_internal lbValue lb_typeid(lbModule *m, Type *type) {
|
||||
}
|
||||
|
||||
u64 data = 0;
|
||||
if (build_context.word_size == 4) {
|
||||
if (build_context.ptr_size == 4) {
|
||||
GB_ASSERT(id <= (1u<<24u));
|
||||
data |= (id &~ (1u<<24)) << 0u; // index
|
||||
data |= (kind &~ (1u<<5)) << 24u; // kind
|
||||
data |= (named &~ (1u<<1)) << 29u; // kind
|
||||
data |= (special &~ (1u<<1)) << 30u; // kind
|
||||
data |= (reserved &~ (1u<<1)) << 31u; // kind
|
||||
data |= (named &~ (1u<<1)) << 29u; // named
|
||||
data |= (special &~ (1u<<1)) << 30u; // special
|
||||
data |= (reserved &~ (1u<<1)) << 31u; // reserved
|
||||
} else {
|
||||
GB_ASSERT(build_context.word_size == 8);
|
||||
GB_ASSERT(build_context.ptr_size == 8);
|
||||
GB_ASSERT(id <= (1ull<<56u));
|
||||
data |= (id &~ (1ull<<56)) << 0ul; // index
|
||||
data |= (kind &~ (1ull<<5)) << 56ull; // kind
|
||||
data |= (named &~ (1ull<<1)) << 61ull; // kind
|
||||
data |= (special &~ (1ull<<1)) << 62ull; // kind
|
||||
data |= (reserved &~ (1ull<<1)) << 63ull; // kind
|
||||
data |= (named &~ (1ull<<1)) << 61ull; // named
|
||||
data |= (special &~ (1ull<<1)) << 62ull; // special
|
||||
data |= (reserved &~ (1ull<<1)) << 63ull; // reserved
|
||||
}
|
||||
|
||||
lbValue res = {};
|
||||
@@ -157,11 +157,11 @@ gb_internal void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup
|
||||
global_type_info_data_entity_count = type->Array.count;
|
||||
|
||||
LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)};
|
||||
LLVMValueRef values[2] = {
|
||||
LLVMConstInBoundsGEP2(lb_type(m, lb_global_type_info_data_entity->type), lb_global_type_info_data_ptr(m).value, indices, gb_count_of(indices)),
|
||||
LLVMConstInt(lb_type(m, t_int), type->Array.count, true),
|
||||
};
|
||||
LLVMValueRef slice = llvm_const_named_struct_internal(lb_type(m, type_deref(global_type_table.type)), values, gb_count_of(values));
|
||||
LLVMValueRef data = LLVMConstInBoundsGEP2(lb_type(m, lb_global_type_info_data_entity->type), lb_global_type_info_data_ptr(m).value, indices, gb_count_of(indices));
|
||||
LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), type->Array.count, true);
|
||||
Type *t = type_deref(global_type_table.type);
|
||||
GB_ASSERT(is_type_slice(t));
|
||||
LLVMValueRef slice = llvm_const_slice_internal(m, data, len);
|
||||
|
||||
LLVMSetInitializer(global_type_table.value, slice);
|
||||
}
|
||||
|
||||
@@ -929,7 +929,38 @@ gb_internal lbStructFieldRemapping lb_get_struct_remapping(lbModule *m, Type *t)
|
||||
gb_internal i32 lb_convert_struct_index(lbModule *m, Type *t, i32 index) {
|
||||
if (t->kind == Type_Struct) {
|
||||
auto field_remapping = lb_get_struct_remapping(m, t);
|
||||
index = field_remapping[index];
|
||||
return field_remapping[index];
|
||||
} else if (build_context.ptr_size != build_context.int_size) {
|
||||
switch (t->kind) {
|
||||
case Type_Basic:
|
||||
if (t->Basic.kind != Basic_string) {
|
||||
break;
|
||||
}
|
||||
/*fallthrough*/
|
||||
case Type_Slice:
|
||||
GB_ASSERT(build_context.ptr_size*2 == build_context.int_size);
|
||||
switch (index) {
|
||||
case 0: return 0; // data
|
||||
case 1: return 2; // len
|
||||
}
|
||||
break;
|
||||
case Type_DynamicArray:
|
||||
GB_ASSERT(build_context.ptr_size*2 == build_context.int_size);
|
||||
switch (index) {
|
||||
case 0: return 0; // data
|
||||
case 1: return 2; // len
|
||||
case 2: return 3; // cap
|
||||
case 3: return 4; // allocator
|
||||
}
|
||||
break;
|
||||
case Type_SoaPointer:
|
||||
GB_ASSERT(build_context.ptr_size*2 == build_context.int_size);
|
||||
switch (index) {
|
||||
case 0: return 0; // data
|
||||
case 1: return 2; // offset
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
@@ -1563,7 +1594,7 @@ gb_internal lbValue lb_map_data_uintptr(lbProcedure *p, lbValue value) {
|
||||
GB_ASSERT(is_type_map(value.type) || are_types_identical(value.type, t_raw_map));
|
||||
lbValue data = lb_emit_struct_ev(p, value, 0);
|
||||
u64 mask_value = 0;
|
||||
if (build_context.word_size == 4) {
|
||||
if (build_context.ptr_size == 4) {
|
||||
mask_value = 0xfffffffful & ~(MAP_CACHE_LINE_SIZE-1);
|
||||
} else {
|
||||
mask_value = 0xffffffffffffffffull & ~(MAP_CACHE_LINE_SIZE-1);
|
||||
@@ -1659,7 +1690,7 @@ gb_internal lbValue lb_emit_mul_add(lbProcedure *p, lbValue a, lbValue b, lbValu
|
||||
break;
|
||||
case TargetArch_i386:
|
||||
case TargetArch_wasm32:
|
||||
case TargetArch_wasm64:
|
||||
case TargetArch_wasm64p32:
|
||||
is_possible = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -666,7 +666,11 @@ gb_internal ExactValue exact_value_from_token(AstFile *f, Token const &token) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
return exact_value_from_basic_literal(token.kind, s);
|
||||
ExactValue value = exact_value_from_basic_literal(token.kind, s);
|
||||
if (value.kind == ExactValue_Invalid) {
|
||||
syntax_error(token, "Invalid token literal");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
gb_internal String string_value_from_token(AstFile *f, Token const &token) {
|
||||
|
||||
@@ -3417,13 +3417,16 @@ gb_internal i64 type_size_of(Type *t) {
|
||||
if (t->kind == Type_Basic) {
|
||||
GB_ASSERT_MSG(is_type_typed(t), "%s", type_to_string(t));
|
||||
switch (t->Basic.kind) {
|
||||
case Basic_string: size = 2*build_context.word_size; break;
|
||||
case Basic_cstring: size = build_context.word_size; break;
|
||||
case Basic_any: size = 2*build_context.word_size; break;
|
||||
case Basic_typeid: size = build_context.word_size; break;
|
||||
case Basic_string: size = 2*build_context.int_size; break;
|
||||
case Basic_cstring: size = build_context.ptr_size; break;
|
||||
case Basic_any: size = 2*build_context.ptr_size; break;
|
||||
case Basic_typeid: size = build_context.ptr_size; break;
|
||||
|
||||
case Basic_int: case Basic_uint: case Basic_uintptr: case Basic_rawptr:
|
||||
size = build_context.word_size;
|
||||
case Basic_int: case Basic_uint:
|
||||
size = build_context.int_size;
|
||||
break;
|
||||
case Basic_uintptr: case Basic_rawptr:
|
||||
size = build_context.ptr_size;
|
||||
break;
|
||||
default:
|
||||
size = t->Basic.size;
|
||||
@@ -3477,13 +3480,15 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) {
|
||||
case Type_Basic: {
|
||||
GB_ASSERT(is_type_typed(t));
|
||||
switch (t->Basic.kind) {
|
||||
case Basic_string: return build_context.word_size;
|
||||
case Basic_cstring: return build_context.word_size;
|
||||
case Basic_any: return build_context.word_size;
|
||||
case Basic_typeid: return build_context.word_size;
|
||||
case Basic_string: return build_context.int_size;
|
||||
case Basic_cstring: return build_context.ptr_size;
|
||||
case Basic_any: return build_context.ptr_size;
|
||||
case Basic_typeid: return build_context.ptr_size;
|
||||
|
||||
case Basic_int: case Basic_uint: case Basic_uintptr: case Basic_rawptr:
|
||||
return build_context.word_size;
|
||||
case Basic_int: case Basic_uint:
|
||||
return build_context.int_size;
|
||||
case Basic_uintptr: case Basic_rawptr:
|
||||
return build_context.ptr_size;
|
||||
|
||||
case Basic_complex32: case Basic_complex64: case Basic_complex128:
|
||||
return type_size_of_internal(t, path) / 2;
|
||||
@@ -3516,10 +3521,10 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) {
|
||||
|
||||
case Type_DynamicArray:
|
||||
// data, count, capacity, allocator
|
||||
return build_context.word_size;
|
||||
return build_context.int_size;
|
||||
|
||||
case Type_Slice:
|
||||
return build_context.word_size;
|
||||
return build_context.int_size;
|
||||
|
||||
|
||||
case Type_Tuple: {
|
||||
@@ -3534,7 +3539,7 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) {
|
||||
} break;
|
||||
|
||||
case Type_Map:
|
||||
return build_context.word_size;
|
||||
return build_context.ptr_size;
|
||||
case Type_Enum:
|
||||
return type_align_of_internal(t->Enum.base_type, path);
|
||||
|
||||
@@ -3614,10 +3619,10 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) {
|
||||
return type_align_of_internal(t->RelativeSlice.base_integer, path);
|
||||
|
||||
case Type_SoaPointer:
|
||||
return build_context.word_size;
|
||||
return build_context.int_size;
|
||||
}
|
||||
|
||||
// NOTE(bill): Things that are bigger than build_context.word_size, are actually comprised of smaller types
|
||||
// NOTE(bill): Things that are bigger than build_context.ptr_size, are actually comprised of smaller types
|
||||
// TODO(bill): Is this correct for 128-bit types (integers)?
|
||||
return gb_clamp(next_pow2(type_size_of_internal(t, path)), 1, build_context.max_align);
|
||||
}
|
||||
@@ -3699,24 +3704,26 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) {
|
||||
return size;
|
||||
}
|
||||
switch (kind) {
|
||||
case Basic_string: return 2*build_context.word_size;
|
||||
case Basic_cstring: return build_context.word_size;
|
||||
case Basic_any: return 2*build_context.word_size;
|
||||
case Basic_typeid: return build_context.word_size;
|
||||
case Basic_string: return 2*build_context.int_size;
|
||||
case Basic_cstring: return build_context.ptr_size;
|
||||
case Basic_any: return 2*build_context.ptr_size;
|
||||
case Basic_typeid: return build_context.ptr_size;
|
||||
|
||||
case Basic_int: case Basic_uint: case Basic_uintptr: case Basic_rawptr:
|
||||
return build_context.word_size;
|
||||
case Basic_int: case Basic_uint:
|
||||
return build_context.int_size;
|
||||
case Basic_uintptr: case Basic_rawptr:
|
||||
return build_context.ptr_size;
|
||||
}
|
||||
} break;
|
||||
|
||||
case Type_Pointer:
|
||||
return build_context.word_size;
|
||||
return build_context.ptr_size;
|
||||
|
||||
case Type_MultiPointer:
|
||||
return build_context.word_size;
|
||||
return build_context.ptr_size;
|
||||
|
||||
case Type_SoaPointer:
|
||||
return build_context.word_size*2;
|
||||
return build_context.int_size*2;
|
||||
|
||||
case Type_Array: {
|
||||
i64 count, align, size, alignment;
|
||||
@@ -3749,11 +3756,11 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) {
|
||||
} break;
|
||||
|
||||
case Type_Slice: // ptr + len
|
||||
return 2 * build_context.word_size;
|
||||
return 2 * build_context.int_size;
|
||||
|
||||
case Type_DynamicArray:
|
||||
// data + len + cap + allocator(procedure+data)
|
||||
return (3 + 2)*build_context.word_size;
|
||||
return 3*build_context.int_size + 2*build_context.ptr_size;
|
||||
|
||||
case Type_Map:
|
||||
/*
|
||||
@@ -3763,7 +3770,7 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) {
|
||||
allocator: runtime.Allocator, // 2 words
|
||||
}
|
||||
*/
|
||||
return (1 + 1 + 2)*build_context.word_size;
|
||||
return (1 + 1 + 2)*build_context.ptr_size;
|
||||
|
||||
case Type_Tuple: {
|
||||
i64 count, align, size;
|
||||
@@ -3889,7 +3896,7 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) {
|
||||
}
|
||||
|
||||
// Catch all
|
||||
return build_context.word_size;
|
||||
return build_context.ptr_size;
|
||||
}
|
||||
|
||||
gb_internal i64 type_offset_of(Type *t, i32 index) {
|
||||
@@ -3909,32 +3916,32 @@ gb_internal i64 type_offset_of(Type *t, i32 index) {
|
||||
} else if (t->kind == Type_Basic) {
|
||||
if (t->Basic.kind == Basic_string) {
|
||||
switch (index) {
|
||||
case 0: return 0; // data
|
||||
case 1: return build_context.word_size; // len
|
||||
case 0: return 0; // data
|
||||
case 1: return build_context.int_size; // len
|
||||
}
|
||||
} else if (t->Basic.kind == Basic_any) {
|
||||
switch (index) {
|
||||
case 0: return 0; // type_info
|
||||
case 1: return build_context.word_size; // data
|
||||
case 0: return 0; // type_info
|
||||
case 1: return build_context.ptr_size; // data
|
||||
}
|
||||
}
|
||||
} else if (t->kind == Type_Slice) {
|
||||
switch (index) {
|
||||
case 0: return 0; // data
|
||||
case 1: return 1*build_context.word_size; // len
|
||||
case 2: return 2*build_context.word_size; // cap
|
||||
case 0: return 0; // data
|
||||
case 1: return 1*build_context.int_size; // len
|
||||
case 2: return 2*build_context.int_size; // cap
|
||||
}
|
||||
} else if (t->kind == Type_DynamicArray) {
|
||||
switch (index) {
|
||||
case 0: return 0; // data
|
||||
case 1: return 1*build_context.word_size; // len
|
||||
case 2: return 2*build_context.word_size; // cap
|
||||
case 3: return 3*build_context.word_size; // allocator
|
||||
case 0: return 0; // data
|
||||
case 1: return 1*build_context.int_size; // len
|
||||
case 2: return 2*build_context.int_size; // cap
|
||||
case 3: return 3*build_context.int_size; // allocator
|
||||
}
|
||||
} else if (t->kind == Type_Union) {
|
||||
/* i64 s = */ type_size_of(t);
|
||||
switch (index) {
|
||||
case -1: return align_formula(t->Union.variant_block_size, build_context.word_size); // __type_info
|
||||
case -1: return align_formula(t->Union.variant_block_size, build_context.ptr_size); // __type_info
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -12,6 +12,7 @@ set COMMON=-collection:tests=..\..
|
||||
..\..\..\odin test ..\test_issue_2056.odin %COMMON% -file || exit /b
|
||||
..\..\..\odin test ..\test_issue_2087.odin %COMMON% -file || exit /b
|
||||
..\..\..\odin build ..\test_issue_2113.odin %COMMON% -file -debug || exit /b
|
||||
..\..\..\odin test ..\test_issue_2466.odin %COMMON% -file || exit /b
|
||||
|
||||
@echo off
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ $ODIN test ../test_issue_1592.odin $COMMON -file
|
||||
$ODIN test ../test_issue_2056.odin $COMMON -file
|
||||
$ODIN test ../test_issue_2087.odin $COMMON -file
|
||||
$ODIN build ../test_issue_2113.odin $COMMON -file -debug
|
||||
$ODIN test ../test_issue_2466.odin $COMMON -file
|
||||
|
||||
set +x
|
||||
|
||||
|
||||
22
tests/issues/test_issue_2466.odin
Normal file
22
tests/issues/test_issue_2466.odin
Normal file
@@ -0,0 +1,22 @@
|
||||
// Tests issue #2466 https://github.com/odin-lang/Odin/issues/2466
|
||||
package test_issues
|
||||
|
||||
import "core:fmt"
|
||||
import "core:testing"
|
||||
|
||||
Bug :: struct {
|
||||
val: int,
|
||||
arr: []int,
|
||||
}
|
||||
|
||||
@test
|
||||
test_compound_literal_local_reuse :: proc(t: ^testing.T) {
|
||||
v: int = 123
|
||||
bug := Bug {
|
||||
val = v,
|
||||
arr = {42},
|
||||
}
|
||||
testing.expect(t, bug.val == 123, fmt.tprintf("expected 123, found %d", bug.val))
|
||||
testing.expect(t, bug.arr[0] == 42, fmt.tprintf("expected 42, found %d", bug.arr[0]))
|
||||
}
|
||||
|
||||
2189
vendor/darwin/Metal/MetalClasses.odin
vendored
2189
vendor/darwin/Metal/MetalClasses.odin
vendored
File diff suppressed because it is too large
Load Diff
2
vendor/wasm/js/dom.odin
vendored
2
vendor/wasm/js/dom.odin
vendored
@@ -1,4 +1,4 @@
|
||||
//+build js wasm32, js wasm64
|
||||
//+build js wasm32, js wasm64p32
|
||||
package wasm_js_interface
|
||||
|
||||
foreign import dom_lib "odin_dom"
|
||||
|
||||
2
vendor/wasm/js/events.odin
vendored
2
vendor/wasm/js/events.odin
vendored
@@ -1,4 +1,4 @@
|
||||
//+build js wasm32, js wasm64
|
||||
//+build js wasm32, js wasm64p32
|
||||
package wasm_js_interface
|
||||
|
||||
foreign import dom_lib "odin_dom"
|
||||
|
||||
2
vendor/wasm/js/general.odin
vendored
2
vendor/wasm/js/general.odin
vendored
@@ -1,4 +1,4 @@
|
||||
//+build js wasm32, js wasm64
|
||||
//+build js wasm32, js wasm64p32
|
||||
package wasm_js_interface
|
||||
|
||||
foreign import "odin_env"
|
||||
|
||||
2
vendor/wasm/js/memory_js.odin
vendored
2
vendor/wasm/js/memory_js.odin
vendored
@@ -1,4 +1,4 @@
|
||||
//+build js wasm32, js wasm64
|
||||
//+build js wasm32, js wasm64p32
|
||||
package wasm_js_interface
|
||||
|
||||
import "core:mem"
|
||||
|
||||
4
vendor/wasm/js/runtime.js
vendored
4
vendor/wasm/js/runtime.js
vendored
@@ -313,8 +313,8 @@ class WebGLInterface {
|
||||
this.ctx.bindBuffer(target, bufferObj)
|
||||
}
|
||||
},
|
||||
BindFramebuffer: (target, buffer) => {
|
||||
// TODO: BindFramebuffer
|
||||
BindFramebuffer: (target, framebuffer) => {
|
||||
this.ctx.bindFramebuffer(target, framebuffer ? this.framebuffers[framebuffer] : null)
|
||||
},
|
||||
BindTexture: (target, texture) => {
|
||||
this.ctx.bindTexture(target, texture ? this.textures[texture] : null)
|
||||
|
||||
Reference in New Issue
Block a user