diff --git a/core/c/libc/setjmp.odin b/core/c/libc/setjmp.odin index c2cd1d047..68f5ac010 100644 --- a/core/c/libc/setjmp.odin +++ b/core/c/libc/setjmp.odin @@ -63,4 +63,4 @@ foreign libc { // strictly conformant C implementation is 16 on the platforms we care about. // The choice of 4096 bytes for storage of this type is more than enough on all // relevant platforms. -jmp_buf :: struct #align 16 { _: [4096]char, } +jmp_buf :: struct #align(16) { _: [4096]char, } diff --git a/core/c/libc/stdarg.odin b/core/c/libc/stdarg.odin index 36d16e24f..b79b22b5a 100644 --- a/core/c/libc/stdarg.odin +++ b/core/c/libc/stdarg.odin @@ -18,7 +18,7 @@ foreign _ { // strictly conformant C implementation is 16 on the platforms we care about. // The choice of 4096 bytes for storage of this type is more than enough on all // relevant platforms. -va_list :: struct #align 16 { +va_list :: struct #align(16) { _: [4096]u8, } diff --git a/core/c/libc/time.odin b/core/c/libc/time.odin index b337e139a..72b899546 100644 --- a/core/c/libc/time.odin +++ b/core/c/libc/time.odin @@ -35,12 +35,12 @@ when ODIN_OS == .Windows { clock_t :: distinct long time_t :: distinct i64 - timespec :: struct #align 8 { + timespec :: struct #align(8) { tv_sec: time_t, tv_nsec: long, } - tm :: struct #align 8 { + tm :: struct #align(8) { tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, tm_yday, tm_isdst: int, } } diff --git a/core/c/libc/wchar.odin b/core/c/libc/wchar.odin index f2aa8410e..f0dae720e 100644 --- a/core/c/libc/wchar.odin +++ b/core/c/libc/wchar.odin @@ -98,7 +98,7 @@ foreign libc { } // Large enough and aligned enough for any wide-spread in-use libc. -mbstate_t :: struct #align 16 { _: [32]char, } +mbstate_t :: struct #align(16) { _: [32]char, } // Odin does not have default argument promotion so the need for a separate type // here isn't necessary, though make it distinct just to be safe. diff --git a/core/os/os2/heap_linux.odin b/core/os/os2/heap_linux.odin index 136c3e6cb..74528f242 100644 --- a/core/os/os2/heap_linux.odin +++ b/core/os/os2/heap_linux.odin @@ -124,7 +124,7 @@ Allocation_Header :: struct #raw_union { requested: u64, } -Region_Header :: struct #align 16 { +Region_Header :: struct #align(16) { next_region: ^Region, // points to next region in global_heap (linked list) local_addr: ^^Region, // tracks region ownership via address of _local_region reset_addr: ^^Region, // tracks old local addr for reset diff --git a/core/reflect/types.odin b/core/reflect/types.odin index 21f75580c..cbe108d82 100644 --- a/core/reflect/types.odin +++ b/core/reflect/types.odin @@ -580,9 +580,9 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) - if info.is_packed { io.write_string(w, "#packed ", &n) or_return } if info.is_raw_union { io.write_string(w, "#raw_union ", &n) or_return } if info.custom_align { - io.write_string(w, "#align ", &n) or_return + io.write_string(w, "#align(", &n) or_return io.write_i64(w, i64(ti.align), 10, &n) or_return - io.write_byte(w, ' ', &n) or_return + io.write_string(w, ") ", &n) or_return } io.write_byte(w, '{', &n) or_return for name, i in info.names { @@ -598,9 +598,9 @@ write_type_writer :: proc(w: io.Writer, ti: ^Type_Info, n_written: ^int = nil) - if info.no_nil { io.write_string(w, "#no_nil ", &n) or_return } if info.shared_nil { io.write_string(w, "#shared_nil ", &n) or_return } if info.custom_align { - io.write_string(w, "#align ", &n) or_return + io.write_string(w, "#align(", &n) or_return io.write_i64(w, i64(ti.align), 10, &n) or_return - io.write_byte(w, ' ', &n) or_return + io.write_string(w, ") ", &n) or_return } io.write_byte(w, '{', &n) or_return for variant, i in info.variants { diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 13676b0d7..4f85cf50e 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -257,7 +257,7 @@ Typeid_Kind :: enum u8 { } #assert(len(Typeid_Kind) < 32) -// Typeid_Bit_Field :: bit_field #align align_of(uintptr) { +// Typeid_Bit_Field :: bit_field #align(align_of(uintptr)) { // index: 8*size_of(uintptr) - 8, // kind: 5, // Typeid_Kind // named: 1, diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin index d34c29d4b..3c986fb62 100644 --- a/core/runtime/dynamic_map_internal.odin +++ b/core/runtime/dynamic_map_internal.odin @@ -87,7 +87,7 @@ MAP_CACHE_LINE_SIZE :: 1 << MAP_CACHE_LINE_LOG2 // // In the optimal case, len(Map_Cell(T){}.data) = 1 so the cell array can be treated // as a regular array of T, which is the case for hashes. -Map_Cell :: struct($T: typeid) #align MAP_CACHE_LINE_SIZE { +Map_Cell :: struct($T: typeid) #align(MAP_CACHE_LINE_SIZE) { data: [MAP_CACHE_LINE_SIZE / size_of(T) when 0 < size_of(T) && size_of(T) < MAP_CACHE_LINE_SIZE else 1]T, } diff --git a/core/runtime/print.odin b/core/runtime/print.odin index 6b1555f52..87c8757d5 100644 --- a/core/runtime/print.odin +++ b/core/runtime/print.odin @@ -398,9 +398,9 @@ print_type :: proc "contextless" (ti: ^Type_Info) { if info.is_packed { print_string("#packed ") } if info.is_raw_union { print_string("#raw_union ") } if info.custom_align { - print_string("#align ") + print_string("#align(") print_u64(u64(ti.align)) - print_byte(' ') + print_string(") ") } print_byte('{') for name, i in info.names { @@ -414,8 +414,9 @@ print_type :: proc "contextless" (ti: ^Type_Info) { case Type_Info_Union: print_string("union ") if info.custom_align { - print_string("#align ") + print_string("#align(") print_u64(u64(ti.align)) + print_string(") ") } if info.no_nil { print_string("#no_nil ") diff --git a/core/sys/unix/pthread_darwin.odin b/core/sys/unix/pthread_darwin.odin index e138b8610..a28de4ad0 100644 --- a/core/sys/unix/pthread_darwin.odin +++ b/core/sys/unix/pthread_darwin.odin @@ -17,42 +17,42 @@ PTHREAD_RWLOCKATTR_SIZE :: 16 pthread_t :: distinct u64 -pthread_attr_t :: struct #align 16 { +pthread_attr_t :: struct #align(16) { sig: c.long, _: [PTHREAD_ATTR_SIZE] c.char, } -pthread_cond_t :: struct #align 16 { +pthread_cond_t :: struct #align(16) { sig: c.long, _: [PTHREAD_COND_SIZE] c.char, } -pthread_condattr_t :: struct #align 16 { +pthread_condattr_t :: struct #align(16) { sig: c.long, _: [PTHREAD_CONDATTR_SIZE] c.char, } -pthread_mutex_t :: struct #align 16 { +pthread_mutex_t :: struct #align(16) { sig: c.long, _: [PTHREAD_MUTEX_SIZE] c.char, } -pthread_mutexattr_t :: struct #align 16 { +pthread_mutexattr_t :: struct #align(16) { sig: c.long, _: [PTHREAD_MUTEXATTR_SIZE] c.char, } -pthread_once_t :: struct #align 16 { +pthread_once_t :: struct #align(16) { sig: c.long, _: [PTHREAD_ONCE_SIZE] c.char, } -pthread_rwlock_t :: struct #align 16 { +pthread_rwlock_t :: struct #align(16) { sig: c.long, _: [PTHREAD_RWLOCK_SIZE] c.char, } -pthread_rwlockattr_t :: struct #align 16 { +pthread_rwlockattr_t :: struct #align(16) { sig: c.long, _: [PTHREAD_RWLOCKATTR_SIZE] c.char, } diff --git a/core/sys/unix/pthread_freebsd.odin b/core/sys/unix/pthread_freebsd.odin index e02345cad..3417d3943 100644 --- a/core/sys/unix/pthread_freebsd.odin +++ b/core/sys/unix/pthread_freebsd.odin @@ -4,7 +4,7 @@ package unix import "core:c" pthread_t :: distinct u64 -// pthread_t :: struct #align 16 { x: u64 } +// pthread_t :: struct #align(16) { x: u64 } PTHREAD_COND_T_SIZE :: 8 @@ -27,32 +27,32 @@ when size_of(int) == 8 { PTHREAD_BARRIER_T_SIZE :: 20 } -pthread_cond_t :: struct #align 16 { +pthread_cond_t :: struct #align(16) { _: [PTHREAD_COND_T_SIZE] c.char, } -pthread_mutex_t :: struct #align 16 { +pthread_mutex_t :: struct #align(16) { _: [PTHREAD_MUTEX_T_SIZE] c.char, } -pthread_rwlock_t :: struct #align 16 { +pthread_rwlock_t :: struct #align(16) { _: [PTHREAD_RWLOCK_T_SIZE] c.char, } -pthread_barrier_t :: struct #align 16 { +pthread_barrier_t :: struct #align(16) { _: [PTHREAD_BARRIER_T_SIZE] c.char, } -pthread_attr_t :: struct #align 16 { +pthread_attr_t :: struct #align(16) { _: [PTHREAD_ATTR_T_SIZE] c.char, } -pthread_condattr_t :: struct #align 16 { +pthread_condattr_t :: struct #align(16) { _: [PTHREAD_CONDATTR_T_SIZE] c.char, } -pthread_mutexattr_t :: struct #align 16 { +pthread_mutexattr_t :: struct #align(16) { _: [PTHREAD_MUTEXATTR_T_SIZE] c.char, } -pthread_rwlockattr_t :: struct #align 16 { +pthread_rwlockattr_t :: struct #align(16) { _: [PTHREAD_RWLOCKATTR_T_SIZE] c.char, } -pthread_barrierattr_t :: struct #align 16 { +pthread_barrierattr_t :: struct #align(16) { _: [PTHREAD_BARRIERATTR_T_SIZE] c.char, } diff --git a/core/sys/unix/pthread_linux.odin b/core/sys/unix/pthread_linux.odin index 9c297ef22..f4ded7464 100644 --- a/core/sys/unix/pthread_linux.odin +++ b/core/sys/unix/pthread_linux.odin @@ -8,7 +8,7 @@ import "core:c" // And at the time of writing there is a bug with putting it // as the only field in a struct. pthread_t :: distinct u64 -// pthread_t :: struct #align 16 { x: u64 }; +// pthread_t :: struct #align(16) { x: u64 }; // NOTE(tetra): Got all the size constants from pthreadtypes-arch.h on my // Linux machine. @@ -34,32 +34,32 @@ when size_of(int) == 8 { PTHREAD_BARRIER_T_SIZE :: 20 } -pthread_cond_t :: struct #align 16 { +pthread_cond_t :: struct #align(16) { _: [PTHREAD_COND_T_SIZE] c.char, } -pthread_mutex_t :: struct #align 16 { +pthread_mutex_t :: struct #align(16) { _: [PTHREAD_MUTEX_T_SIZE] c.char, } -pthread_rwlock_t :: struct #align 16 { +pthread_rwlock_t :: struct #align(16) { _: [PTHREAD_RWLOCK_T_SIZE] c.char, } -pthread_barrier_t :: struct #align 16 { +pthread_barrier_t :: struct #align(16) { _: [PTHREAD_BARRIER_T_SIZE] c.char, } -pthread_attr_t :: struct #align 16 { +pthread_attr_t :: struct #align(16) { _: [PTHREAD_ATTR_T_SIZE] c.char, } -pthread_condattr_t :: struct #align 16 { +pthread_condattr_t :: struct #align(16) { _: [PTHREAD_CONDATTR_T_SIZE] c.char, } -pthread_mutexattr_t :: struct #align 16 { +pthread_mutexattr_t :: struct #align(16) { _: [PTHREAD_MUTEXATTR_T_SIZE] c.char, } -pthread_rwlockattr_t :: struct #align 16 { +pthread_rwlockattr_t :: struct #align(16) { _: [PTHREAD_RWLOCKATTR_T_SIZE] c.char, } -pthread_barrierattr_t :: struct #align 16 { +pthread_barrierattr_t :: struct #align(16) { _: [PTHREAD_BARRIERATTR_T_SIZE] c.char, } @@ -84,7 +84,7 @@ sched_param :: struct { sched_priority: c.int, } -sem_t :: struct #align 16 { +sem_t :: struct #align(16) { _: [SEM_T_SIZE] c.char, } diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index 4c0d47a64..2b63595a4 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -886,7 +886,7 @@ WIN32_MEMORY_REGION_INFORMATION_u_s :: struct { Bitfield: ULONG, } WIN32_MEMORY_REGION_INFORMATION_u_s_Bitfield :: distinct ULONG -/*bit_field #align align_of(ULONG) { +/*bit_field #align(align_of(ULONG)) { Private : 1-0, MappedDataFile : 2-1, MappedImage : 3-2, diff --git a/core/thread/thread_unix.odin b/core/thread/thread_unix.odin index 6e734a03a..c73085ef6 100644 --- a/core/thread/thread_unix.odin +++ b/core/thread/thread_unix.odin @@ -10,7 +10,7 @@ CAS :: intrinsics.atomic_compare_exchange_strong // NOTE(tetra): Aligned here because of core/unix/pthread_linux.odin/pthread_t. // Also see core/sys/darwin/mach_darwin.odin/semaphore_t. -Thread_Os_Specific :: struct #align 16 { +Thread_Os_Specific :: struct #align(16) { unix_thread: unix.pthread_t, // NOTE: very large on Darwin, small on Linux. cond: sync.Cond, mutex: sync.Mutex, diff --git a/src/parser.cpp b/src/parser.cpp index dd75399ad..13e5f6130 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2485,6 +2485,13 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string)); } align = parse_expr(f, true); + if (align && align->kind != Ast_ParenExpr) { + ERROR_BLOCK(); + gbString s = expr_to_string(align); + syntax_warning(tag, "#align requires parentheses around the expression"); + error_line("\tSuggestion: #align(%s)", s); + gb_string_free(s); + } } else if (tag.string == "raw_union") { if (is_raw_union) { syntax_error(tag, "Duplicate struct tag '#%.*s'", LIT(tag.string)); @@ -2566,6 +2573,13 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) { syntax_error(tag, "Duplicate union tag '#%.*s'", LIT(tag.string)); } align = parse_expr(f, true); + if (align && align->kind != Ast_ParenExpr) { + ERROR_BLOCK(); + gbString s = expr_to_string(align); + syntax_warning(tag, "#align requires parentheses around the expression"); + error_line("\tSuggestion: #align(%s)", s); + gb_string_free(s); + } } else if (tag.string == "no_nil") { if (no_nil) { syntax_error(tag, "Duplicate union tag '#%.*s'", LIT(tag.string)); diff --git a/vendor/wasm/js/events.odin b/vendor/wasm/js/events.odin index f14d7054e..0d20531df 100644 --- a/vendor/wasm/js/events.odin +++ b/vendor/wasm/js/events.odin @@ -209,7 +209,7 @@ Event :: struct { is_composing: bool, is_trusted: bool, - using data: struct #raw_union #align 8 { + using data: struct #raw_union #align(8) { scroll: struct { delta: [2]f64, }, diff --git a/vendor/wasm/js/events_all_targets.odin b/vendor/wasm/js/events_all_targets.odin index 2bc7e8ceb..19a004250 100644 --- a/vendor/wasm/js/events_all_targets.odin +++ b/vendor/wasm/js/events_all_targets.odin @@ -208,7 +208,7 @@ Event :: struct { is_composing: bool, is_trusted: bool, - using data: struct #raw_union #align 8 { + using data: struct #raw_union #align(8) { scroll: struct { delta: [2]f64, },