Added aligned attribute support
authorRobert Pengelly <robertapengelly@hotmail.com>
Mon, 7 Sep 2026 20:18:24 +0000 (21:18 +0100)
committerRobert Pengelly <robertapengelly@hotmail.com>
Mon, 7 Sep 2026 20:18:24 +0000 (21:18 +0100)
amd64.c
i386.c
parse.c
parse.h

diff --git a/amd64.c b/amd64.c
index 332ff49c6649cfe188696d1bdca55fbdb563ded8..2384ba8c62ad726be8ffb66332fe7a5bd7005d6b 100644 (file)
--- a/amd64.c
+++ b/amd64.c
@@ -8646,11 +8646,11 @@ static void make_local_static_label (char *buf, size_t bufsz, const char *name)
 
 }
 
-static void emit_global_object (const char *name, int size, int is_array, long array_count, const int *field_sizes, int field_count, const int64_s *values, char **symbols, int value_count, int is_aggregate, int is_static);
+static void emit_global_object (const char *name, int size, int is_array, long array_count, const int *field_sizes, int field_count, const int64_s *values, char **symbols, int value_count, int is_aggregate, int is_static, int explicit_align);
 static void emit_extern_symbol (const char *name, int size, int is_function);
 static void emit_extern_reference_symbol (const char *name, int size);
 
-static void emit_block_static_object (const char *label, int size, int is_array, long array_count, const int *field_sizes, int field_count, const int64_s *values, char **symbols, int value_count, int is_aggregate) {
+static void emit_block_static_object (const char *label, int size, int is_array, long array_count, const int *field_sizes, int field_count, const int64_s *values, char **symbols, int value_count, int is_aggregate, int explicit_align) {
 
     int skip_label = anon_label++;
     int need_code_skip = current_parse_block_depth > 0;
@@ -8679,7 +8679,7 @@ static void emit_block_static_object (const char *label, int size, int is_array,
     
     }
     
-    emit_global_object (label, size, is_array, array_count, field_sizes, field_count, values, symbols, value_count, is_aggregate, 1);
+    emit_global_object (label, size, is_array, array_count, field_sizes, field_count, values, symbols, value_count, is_aggregate, 1, explicit_align);
     
     /*
      * We may have switched to .data/.data? to emit the static object while
@@ -8854,6 +8854,7 @@ static void parse_block (void) {
                 
                 int declaration_dllimport = parsed_dllimport;
                 int declaration_noreturn = parsed_noreturn;
+                int declaration_alignment = parsed_alignment;
                 
                 int declared_pointer_depth;
                 int declared_pointed_size;
@@ -8869,6 +8870,10 @@ static void parse_block (void) {
                 declaration_dllimport = declaration_dllimport || parsed_dllimport || declarator_dllimport;
                 declaration_noreturn = declaration_noreturn || parsed_noreturn || declarator_noreturn;
                 
+                if (declarator_alignment > declaration_alignment) {
+                    declaration_alignment = declarator_alignment;
+                }
+                
                 apply_typedef_array_to_declarator ();
                 
                 if (declarator_has_array && declarator_array_unsized && tok.kind == TOK_ASSIGN) {
@@ -8963,6 +8968,10 @@ static void parse_block (void) {
                     object_size = declarator_object_size (parsed_type_size);
                     object_align = declarator_is_pointer ? type_alignment (DATA_PTR) : type_alignment (parsed_type_is_aggregate ? DATA_PTR : parsed_type_size);
                     
+                    if (declaration_alignment > object_align) {
+                        object_align = declaration_alignment;
+                    }
+                    
                     object_offset = add_local_symbol (name, object_size, object_align,
                         (declarator_is_pointer ? 0 : parsed_type_is_unsigned),
                             block_scope_start, name_line, name_start, name_caret);
@@ -9378,7 +9387,7 @@ static void parse_block (void) {
                                 declarator_has_array, declarator_array_count,
                                     object_fields, object_field_count,
                                         init_values, init_symbols, init_value_count,
-                                            (!declarator_is_pointer && parsed_type_is_aggregate));
+                                            (!declarator_is_pointer && parsed_type_is_aggregate), declaration_alignment);
                     
                     }
                     
@@ -40158,7 +40167,7 @@ static void emit_global_data_label (const char *name, int is_static) {
 
 }
 
-static void emit_global_object (const char *name, int size, int is_array, long array_count, const int *field_sizes, int field_count, const int64_s *values, char **symbols, int value_count, int is_aggregate, int is_static) {
+static void emit_global_object (const char *name, int size, int is_array, long array_count, const int *field_sizes, int field_count, const int64_s *values, char **symbols, int value_count, int is_aggregate, int is_static, int explicit_align) {
 
     int64_s zero;
     
@@ -40187,7 +40196,7 @@ static void emit_global_object (const char *name, int size, int is_array, long a
     
         switch_section (SECTION_BSS);
         
-        emit_global_alignment (global_object_alignment (size, is_array, field_sizes, field_count, is_aggregate));
+        emit_global_alignment (explicit_align > global_object_alignment (size, is_array, field_sizes, field_count, is_aggregate) ? explicit_align : global_object_alignment (size, is_array, field_sizes, field_count, is_aggregate));
         emit_global_data_label (name, is_static);
         emit_global_space (total);
         
@@ -40197,7 +40206,7 @@ static void emit_global_object (const char *name, int size, int is_array, long a
     
     switch_section (SECTION_DATA);
     
-    emit_global_alignment (global_object_alignment (size, is_array, field_sizes, field_count, is_aggregate));
+    emit_global_alignment (explicit_align > global_object_alignment (size, is_array, field_sizes, field_count, is_aggregate) ? explicit_align : global_object_alignment (size, is_array, field_sizes, field_count, is_aggregate));
     emit_global_data_label (name, is_static);
     
     value_index = 0;
@@ -40523,6 +40532,8 @@ static void parse_external_after_type (void) {
         int declaration_dllimport = 0;
         int declaration_dllexport = 0;
         
+        int declaration_alignment = parsed_alignment;
+        
         int decl_is_pointer;
         int decl_pointer_depth;
         int decl_has_array;
@@ -40547,6 +40558,11 @@ static void parse_external_after_type (void) {
         declaration_is_inline = parsed_type_is_inline;
         declaration_storage = parsed_storage_class;
         declaration_noreturn = parsed_noreturn;
+        
+        if (declarator_alignment > declaration_alignment) {
+            declaration_alignment = declarator_alignment;
+        }
+        
         declaration_dllimport = parsed_dllimport;
         declaration_dllexport = parsed_dllexport;
         
@@ -40840,7 +40856,7 @@ static void parse_external_after_type (void) {
                     emit_global_object (name, declarator_is_pointer ? DATA_PTR : (declarator_has_array ? parsed_type_size : (parsed_type_is_aggregate ? parsed_type_size : (parsed_type_size & 0x1f))),
                         declarator_has_array, declarator_array_count, object_fields, object_field_count,
                             init_values, init_symbols, init_value_count, (!declarator_is_pointer && parsed_type_is_aggregate),
-                                declaration_storage == STORAGE_STATIC);
+                                declaration_storage == STORAGE_STATIC, declaration_alignment);
                 
                 }
             
diff --git a/i386.c b/i386.c
index dda688755668c2005820af56a6f5cf9dbf030482..91a2e8b24f9383f5bab412f02d971164253e25d5 100644 (file)
--- a/i386.c
+++ b/i386.c
@@ -7853,13 +7853,13 @@ static void make_local_static_label (char *buf, size_t bufsz, const char *name)
 
 }
 
-static void emit_global_object (const char *name, int size, int is_array, long array_count, const int *field_sizes, int field_count, const int64_s *values, char **symbols, int value_count, int is_aggregate, int is_static);
+static void emit_global_object (const char *name, int size, int is_array, long array_count, const int *field_sizes, int field_count, const int64_s *values, char **symbols, int value_count, int is_aggregate, int is_static, int explicit_align);
 static void emit_extern_symbol (const char *name, int size, int is_function);
 static void emit_extern_reference_symbol (const char *name, int size);
 
-static void emit_block_static_object (const char *label, int size, int is_array, long array_count, const int *field_sizes, int field_count, const int64_s *values, char **symbols, int value_count, int is_aggregate) {
+static void emit_block_static_object (const char *label, int size, int is_array, long array_count, const int *field_sizes, int field_count, const int64_s *values, char **symbols, int value_count, int is_aggregate, int explicit_align) {
     
-    emit_global_object (label, size, is_array, array_count, field_sizes, field_count, values, symbols, value_count, is_aggregate, 1);
+    emit_global_object (label, size, is_array, array_count, field_sizes, field_count, values, symbols, value_count, is_aggregate, 1, explicit_align);
     
     /**
      * We may have switched to .data/.data? to emit the static object while
@@ -8024,6 +8024,7 @@ static void parse_block (void) {
                 
                 int declaration_dllimport = parsed_dllimport;
                 int declaration_noreturn = parsed_noreturn;
+                int declaration_alignment = parsed_alignment;
                 
                 for (i = 0; i < MAX_AGG_FIELDS; i++) {
                     init_symbols[i] = 0;
@@ -8034,6 +8035,10 @@ static void parse_block (void) {
                 declaration_dllimport = declaration_dllimport || parsed_dllimport || declarator_dllimport;
                 declaration_noreturn = declaration_noreturn || parsed_noreturn || declarator_noreturn;
                 
+                if (declarator_alignment > declaration_alignment) {
+                    declaration_alignment = declarator_alignment;
+                }
+                
                 apply_typedef_array_to_declarator ();
                 
                 if (declarator_has_array && declarator_array_unsized && tok.kind == TOK_ASSIGN) {
@@ -8113,6 +8118,10 @@ static void parse_block (void) {
                     object_size = declarator_object_size (parsed_type_size);
                     object_align = declarator_is_pointer ? type_alignment (DATA_PTR) : type_alignment (parsed_type_is_aggregate ? DATA_PTR : parsed_type_size);
                     
+                    if (declaration_alignment > object_align) {
+                        object_align = declaration_alignment;
+                    }
+                    
                     object_offset = add_local_symbol (name, object_size, object_align,
                         (declarator_is_pointer ? 0 : parsed_type_is_unsigned),
                             block_scope_start, name_line, name_start, name_caret);
@@ -8531,13 +8540,13 @@ static void parse_block (void) {
                                 declarator_has_array, declarator_array_count,
                                     object_fields, object_field_count,
                                         init_values, init_symbols, init_value_count,
-                                            (!declarator_is_pointer && parsed_type_is_aggregate));
+                                            (!declarator_is_pointer && parsed_type_is_aggregate), declaration_alignment);
                     
                     }
                     
                     add_static_local_symbol (name, static_label,
                         declarator_object_size (parsed_type_size),
-                            type_alignment (declarator_is_pointer ? DATA_PTR : parsed_type_size),
+                            (declaration_alignment > type_alignment (declarator_is_pointer ? DATA_PTR : parsed_type_size) ? declaration_alignment : type_alignment (declarator_is_pointer ? DATA_PTR : parsed_type_size)),
                                 (declarator_is_pointer ? 0 : parsed_type_is_unsigned),
                                     block_scope_start, name_line, name_start, name_caret);
                     
@@ -37690,6 +37699,25 @@ static void emit_global_label (const char *name, int is_static) {
 
 }
 
+static void emit_global_alignment (int align) {
+
+    if (align <= 1) {
+        return;
+    }
+    
+    if (state->syntax & ASM_SYNTAX_MASM) {
+    
+        masm_flush_data_line ();
+        fprintf (state->ofp, "align %d\n", align);
+    
+    } else if (state->syntax & ASM_SYNTAX_NASM) {
+        fprintf (state->ofp, "align %d\n", align);
+    } else {
+        fprintf (state->ofp, "    .balign %d\n", align);
+    }
+
+}
+
 static void emit_global_data_label (const char *name, int is_static) {
 
     const char *asm_name = asm_global_symbol_name (name);
@@ -37710,7 +37738,7 @@ static void emit_global_data_label (const char *name, int is_static) {
 
 }
 
-static void emit_global_object (const char *name, int size, int is_array, long array_count, const int *field_sizes, int field_count, const int64_s *values, char **symbols, int value_count, int is_aggregate, int is_static) {
+static void emit_global_object (const char *name, int size, int is_array, long array_count, const int *field_sizes, int field_count, const int64_s *values, char **symbols, int value_count, int is_aggregate, int is_static, int explicit_align) {
 
     int64_s zero;
     
@@ -37739,6 +37767,7 @@ static void emit_global_object (const char *name, int size, int is_array, long a
     
         switch_section (SECTION_BSS);
         
+        emit_global_alignment (explicit_align);
         emit_global_data_label (name, is_static);
         emit_global_space (total);
         
@@ -37747,6 +37776,8 @@ static void emit_global_object (const char *name, int size, int is_array, long a
     }
     
     switch_section (SECTION_DATA);
+    
+    emit_global_alignment (explicit_align);
     emit_global_data_label (name, is_static);
     
     value_index = 0;
@@ -38023,6 +38054,8 @@ static void parse_external_after_type (void) {
         int declaration_dllimport = 0;
         int declaration_dllexport = 0;
         
+        int declaration_alignment = parsed_alignment;
+        
         int decl_is_pointer;
         int decl_pointer_depth;
         int decl_has_array;
@@ -38050,6 +38083,10 @@ static void parse_external_after_type (void) {
         declaration_dllexport = parsed_dllexport;
         declaration_noreturn = parsed_noreturn;
         
+        if (declarator_alignment > declaration_alignment) {
+            declaration_alignment = declarator_alignment;
+        }
+        
         parse_declarator (&name);
         
         declaration_dllimport = declaration_dllimport || parsed_dllimport || declarator_dllimport;
@@ -38340,7 +38377,7 @@ static void parse_external_after_type (void) {
                     emit_global_object (name, declarator_is_pointer ? DATA_PTR : (declarator_has_array ? parsed_type_size : (parsed_type_is_aggregate ? parsed_type_size : (parsed_type_size & 0x1f))),
                         declarator_has_array, declarator_array_count, object_fields, object_field_count,
                             init_values, init_symbols, init_value_count, (!declarator_is_pointer && parsed_type_is_aggregate),
-                                declaration_storage == STORAGE_STATIC);
+                                declaration_storage == STORAGE_STATIC, declaration_alignment);
                 
                 }
             
diff --git a/parse.c b/parse.c
index 1706e24f6710f931d0dab3684ed87577c009f4ed..f61509be4f1d6ef7e6a071d42470b328d4e60894 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -29,6 +29,7 @@ int parsed_dllexport = 0;
 int parsed_dllimport = 0;
 int parsed_noreturn = 0;
 int parsed_naked = 0;
+int parsed_alignment = 0;
 
 int parsed_type_size = DATA_NONE;
 int parsed_type_is_inline = 0;
@@ -67,6 +68,7 @@ int declarator_is_pointer = 0;
 int declarator_has_array = 0;
 int declarator_noreturn = 0;
 int declarator_naked = 0;
+int declarator_alignment = 0;
 
 int declarator_dllexport = 0;
 int declarator_dllimport = 0;
@@ -522,6 +524,46 @@ static int parse_alias_attribute_argument (void) {
 
 }
 
+static int parse_aligned_attribute_argument (void) {
+
+    enum token_kind kill[2];
+    
+    int64_s value;
+    unsigned long align;
+    
+    if (!_accept (TOK_LPAREN)) {
+    
+        report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "expected '(' after 'aligned'");
+        return 0;
+    
+    }
+    
+    kill[0] = TOK_RPAREN;
+    kill[1] = 0;
+    
+    value = expr_const64 (kill);
+    expect (TOK_RPAREN, ")");
+    
+    if (value.high != 0 || value.low == 0) {
+    
+        report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "alignment must be a positive power of two");
+        return 0;
+    
+    }
+    
+    align = value.low;
+    
+    if ((align & (align - 1)) != 0) {
+    
+        report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "alignment must be a positive power of two");
+        return 0;
+    
+    }
+    
+    return (int) align;
+
+}
+
 static void apply_decl_attribute (const char *spelling, int is_gnu) {
 
     if (attribute_name_is (spelling, "dllexport")) {
@@ -580,6 +622,22 @@ static void apply_decl_attribute (const char *spelling, int is_gnu) {
         
         }
     
+    } else if (is_gnu && attribute_name_is (spelling, "aligned")) {
+    
+        int align = parse_aligned_attribute_argument ();
+        
+        if (align > 0) {
+        
+            int *slot = declarator_depth == 0 ? &parsed_alignment : &declarator_alignment;
+            
+            if (*slot > 0 && *slot != align) {
+                report_line_at (get_filename (), get_line_number (), REPORT_ERROR, tok.report_start, tok.report_caret, "conflicting 'aligned' attributes");
+            } else {
+                *slot = align;
+            }
+        
+        }
+
     } else if (is_gnu && attribute_name_is (spelling, "stdcall")) {
     
         if (parsed_calling_convention == TOK_EOF && declarator_calling_convention == TOK_EOF) {
@@ -649,6 +707,8 @@ static void parse_decl_modifier (void) {
                 
                 if (attribute_name_is (name, "alias")) {
                     parse_alias_attribute_argument ();
+                } else if (attribute_name_is (name, "aligned")) {
+                    apply_decl_attribute (name, 1);
                 } else {
                 
                     apply_decl_attribute (name, 1);
@@ -859,6 +919,7 @@ void parse_declarator (char **out_name) {
     int saved_declarator_dllimport = declarator_dllimport;
     int saved_declarator_noreturn = declarator_noreturn;
     int saved_declarator_naked = declarator_naked;
+    int saved_declarator_alignment = declarator_alignment;
     
     unsigned long saved_captured_declarator_name_line = captured_declarator_name_line;
     memcpy (saved_declarator_alias_target, declarator_alias_target, sizeof (declarator_alias_target));
@@ -878,6 +939,7 @@ void parse_declarator (char **out_name) {
         declarator_dllimport = 0;
         declarator_noreturn = 0;
         declarator_naked = 0;
+        declarator_alignment = 0;
         
         captured_declarator_name_location = 0;
         captured_declarator_name_start = 0;
@@ -944,6 +1006,7 @@ void parse_declarator (char **out_name) {
         declarator_dllimport = saved_declarator_dllimport;
         declarator_noreturn = saved_declarator_noreturn;
         declarator_naked = saved_declarator_naked;
+        declarator_alignment = saved_declarator_alignment;
     
     }
 
@@ -2933,6 +2996,7 @@ void parse_type_spec (void) {
     parsed_dllimport = 0;
     parsed_noreturn = 0;
     parsed_naked = 0;
+    parsed_alignment = 0;
     
     clear_parsed_fields ();
     
diff --git a/parse.h b/parse.h
index 16e3d79c543e93524b487c136e474274de358af2..bf38cd64f9b00817464654f1a69d529c4a704dc1 100644 (file)
--- a/parse.h
+++ b/parse.h
@@ -32,6 +32,7 @@ extern int parsed_dllexport;
 extern int parsed_dllimport;
 extern int parsed_noreturn;
 extern int parsed_naked;
+extern int parsed_alignment;
 
 extern int parsed_type_size;
 extern int parsed_type_is_inline;
@@ -74,6 +75,7 @@ extern int declarator_dllexport;
 extern int declarator_dllimport;
 extern int declarator_noreturn;
 extern int declarator_naked;
+extern int declarator_alignment;
 
 extern enum token_kind declarator_calling_convention;
 extern int global_initializer_accept_symbol_addresses;