}
-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;
}
- 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
int declaration_dllimport = parsed_dllimport;
int declaration_noreturn = parsed_noreturn;
+ int declaration_alignment = parsed_alignment;
int declared_pointer_depth;
int declared_pointed_size;
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) {
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);
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);
}
}
-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;
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);
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;
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;
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;
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);
}
}
-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
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;
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) {
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);
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);
}
+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);
}
-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;
switch_section (SECTION_BSS);
+ emit_global_alignment (explicit_align);
emit_global_data_label (name, is_static);
emit_global_space (total);
}
switch_section (SECTION_DATA);
+
+ emit_global_alignment (explicit_align);
emit_global_data_label (name, is_static);
value_index = 0;
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;
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;
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);
}
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;
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;
}
+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")) {
}
+ } 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) {
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);
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));
declarator_dllimport = 0;
declarator_noreturn = 0;
declarator_naked = 0;
+ declarator_alignment = 0;
captured_declarator_name_location = 0;
captured_declarator_name_start = 0;
declarator_dllimport = saved_declarator_dllimport;
declarator_noreturn = saved_declarator_noreturn;
declarator_naked = saved_declarator_naked;
+ declarator_alignment = saved_declarator_alignment;
}
parsed_dllimport = 0;
parsed_noreturn = 0;
parsed_naked = 0;
+ parsed_alignment = 0;
clear_parsed_fields ();
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;
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;