aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp1
-rw-r--r--src/analyze.cpp27
-rw-r--r--src/analyze.hpp2
-rw-r--r--src/ir.cpp17
4 files changed, 38 insertions, 9 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index b43ecedcd6..461270357b 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -913,6 +913,7 @@ struct FnTypeId {
size_t next_param_index;
bool is_var_args;
CallingConvention cc;
+ uint32_t alignment;
};
uint32_t fn_type_id_hash(FnTypeId*);
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 69a50253d2..35ccd3b4d3 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -2899,14 +2899,29 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
}
}
-bool type_is_codegen_pointer(TypeTableEntry *type) {
- if (type->id == TypeTableEntryIdPointer) return true;
- if (type->id == TypeTableEntryIdFn) return true;
+TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type) {
+ if (type->id == TypeTableEntryIdPointer) return type;
+ if (type->id == TypeTableEntryIdFn) return type;
if (type->id == TypeTableEntryIdMaybe) {
- if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return true;
- if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return true;
+ if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return type->data.maybe.child_type;
+ if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return type->data.maybe.child_type;
+ }
+ return nullptr;
+}
+
+bool type_is_codegen_pointer(TypeTableEntry *type) {
+ return get_codegen_ptr_type(type) != nullptr;
+}
+
+uint32_t get_ptr_align(TypeTableEntry *type) {
+ TypeTableEntry *ptr_type = get_codegen_ptr_type(type);
+ if (ptr_type->id == TypeTableEntryIdPointer) {
+ return ptr_type->data.pointer.alignment;
+ } else if (ptr_type->id == TypeTableEntryIdFn) {
+ return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment;
+ } else {
+ zig_unreachable();
}
- return false;
}
AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index) {
diff --git a/src/analyze.hpp b/src/analyze.hpp
index 79a2cf1daf..9e9e066126 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -52,6 +52,8 @@ VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);
Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node);
bool type_is_codegen_pointer(TypeTableEntry *type);
+TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type);
+uint32_t get_ptr_align(TypeTableEntry *type);
TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry);
TypeTableEntry *container_ref_type(TypeTableEntry *type_entry);
bool type_is_complete(TypeTableEntry *type_entry);
diff --git a/src/ir.cpp b/src/ir.cpp
index 37877e1b34..f7f097e99d 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -10830,7 +10830,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
if (ptr_type->data.pointer.unaligned_bit_count == 0) {
return_type = get_pointer_to_type_extra(ira->codegen, child_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
- get_abi_alignment(ira->codegen, child_type), 0, 0);
+ ptr_type->data.pointer.alignment, 0, 0);
} else {
uint64_t elem_val_scalar;
if (!ir_resolve_usize(ira, elem_index, &elem_val_scalar))
@@ -10841,8 +10841,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
return_type = get_pointer_to_type_extra(ira->codegen, child_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
- get_abi_alignment(ira->codegen, child_type),
- (uint32_t)bit_offset, (uint32_t)bit_width);
+ 1, (uint32_t)bit_offset, (uint32_t)bit_width);
}
} else if (array_type->id == TypeTableEntryIdPointer) {
return_type = array_type;
@@ -14457,6 +14456,18 @@ static TypeTableEntry *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruc
return dest_type;
}
+ uint32_t src_align_bytes = get_ptr_align(src_type);
+ uint32_t dest_align_bytes = get_ptr_align(dest_type);
+
+ if (dest_align_bytes > src_align_bytes) {
+ ErrorMsg *msg = ir_add_error(ira, &instruction->base, buf_sprintf("cast increases pointer alignment"));
+ add_error_note(ira->codegen, msg, ptr->source_node,
+ buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_type->name), src_align_bytes));
+ add_error_note(ira->codegen, msg, dest_type_value->source_node,
+ buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&dest_type->name), dest_align_bytes));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+
IrInstruction *result = ir_build_ptr_cast(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, nullptr, ptr);
ir_link_new_instruction(result, &instruction->base);