mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
- Detect unaligned loads #1951.
- Fix issue where aligned bitstructs did not store/load with the given alignment.
This commit is contained in:
@@ -13,7 +13,6 @@ enum IntrospectIndex
|
||||
};
|
||||
|
||||
bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements);
|
||||
static inline Type *type_reduced_from_expr(Expr *expr);
|
||||
static inline bool abi_type_is_type(AbiType type);
|
||||
|
||||
static inline bool abi_type_is_valid(AbiType type);
|
||||
@@ -90,11 +89,6 @@ static inline Type *type_lowering(Type *type)
|
||||
}
|
||||
}
|
||||
|
||||
static inline Type *type_reduced_from_expr(Expr *expr)
|
||||
{
|
||||
return type_lowering(expr->type);
|
||||
}
|
||||
|
||||
static inline bool abi_type_is_type(AbiType type)
|
||||
{
|
||||
return !(type.int_bits_plus_1 & 0x01);
|
||||
|
||||
@@ -160,12 +160,15 @@ INLINE void llvm_emit_atomic_store(GenContext *c, BEValue *result_value, Expr *e
|
||||
|
||||
INLINE void llvm_emit_unaligned_store(GenContext *c, BEValue *result_value, Expr *expr)
|
||||
{
|
||||
bool emit_check = c->emitting_load_store_check;
|
||||
c->emitting_load_store_check = true;
|
||||
BEValue value;
|
||||
llvm_emit_expr(c, &value, expr->call_expr.arguments[0]);
|
||||
llvm_emit_expr(c, result_value, expr->call_expr.arguments[1]);
|
||||
llvm_value_deref(c, &value);
|
||||
value.alignment = expr->call_expr.arguments[2]->const_expr.ixx.i.low;
|
||||
llvm_store(c, &value, result_value);
|
||||
c->emitting_load_store_check = emit_check;
|
||||
}
|
||||
|
||||
INLINE void llvm_emit_atomic_fetch(GenContext *c, BuiltinFunction func, BEValue *result_value, Expr *expr)
|
||||
@@ -241,10 +244,13 @@ INLINE void llvm_emit_atomic_load(GenContext *c, BEValue *result_value, Expr *ex
|
||||
|
||||
INLINE void llvm_emit_unaligned_load(GenContext *c, BEValue *result_value, Expr *expr)
|
||||
{
|
||||
bool emit_check = c->emitting_load_store_check;
|
||||
c->emitting_load_store_check = true;
|
||||
llvm_emit_expr(c, result_value, expr->call_expr.arguments[0]);
|
||||
llvm_value_deref(c, result_value);
|
||||
result_value->alignment = expr->call_expr.arguments[1]->const_expr.ixx.i.low;
|
||||
llvm_value_rvalue(c, result_value);
|
||||
c->emitting_load_store_check = emit_check;
|
||||
}
|
||||
|
||||
static inline LLVMValueRef llvm_syscall_asm(LLVMTypeRef func_type, char *call)
|
||||
|
||||
@@ -2286,6 +2286,7 @@ static inline void llvm_emit_deref(GenContext *c, BEValue *value, Expr *inner, T
|
||||
}
|
||||
llvm_emit_expr(c, value, inner);
|
||||
llvm_value_rvalue(c, value);
|
||||
AlignSize alignment = type_abi_alignment(type);
|
||||
if (safe_mode_enabled())
|
||||
{
|
||||
LLVMValueRef check = LLVMBuildICmp(c->builder, LLVMIntEQ, value->value, llvm_get_zero(c, inner->type), "checknull");
|
||||
@@ -2294,11 +2295,28 @@ static inline void llvm_emit_deref(GenContext *c, BEValue *value, Expr *inner, T
|
||||
span_to_scratch(inner->span);
|
||||
scratch_buffer_append("' was null.");
|
||||
llvm_emit_panic_on_true(c, check, scratch_buffer_to_string(), inner->span, NULL, NULL, NULL);
|
||||
if (alignment > 1 && !c->emitting_load_store_check)
|
||||
{
|
||||
LLVMValueRef as_int = LLVMBuildPtrToInt(c->builder, value->value, llvm_get_type(c, type_usz), "");
|
||||
LLVMValueRef align = llvm_const_int(c, type_usz, alignment);
|
||||
LLVMValueRef rem = LLVMBuildURem(c->builder, as_int, align, "");
|
||||
LLVMValueRef is_not_zero = LLVMBuildICmp(c->builder, LLVMIntNE, rem, llvm_get_zero(c, type_usz), "");
|
||||
c->emitting_load_store_check = true;
|
||||
BEValue value1;
|
||||
BEValue value2;
|
||||
if (inner->type->name )
|
||||
llvm_value_set(&value1, align, type_usz);
|
||||
llvm_value_set(&value2, rem, type_usz);
|
||||
llvm_emit_panic_on_true(c, is_not_zero, "Unaligned pointer access detected", inner->span, "Unaligned access: ptr %% %s = %s, use @unaligned_load / @unaligned_store for unaligned access.",
|
||||
&value1, &value2);
|
||||
c->emitting_load_store_check = false;
|
||||
}
|
||||
|
||||
}
|
||||
// Convert pointer to address
|
||||
value->kind = BE_ADDRESS;
|
||||
value->type = type;
|
||||
value->alignment = type_abi_alignment(type);
|
||||
value->type = type_lowering(type);
|
||||
value->alignment = alignment;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2342,7 +2360,7 @@ static void llvm_emit_dynamic_method_addr(GenContext *c, BEValue *value, Expr *e
|
||||
|
||||
static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
{
|
||||
Type *type = type_reduced_from_expr(expr->unary_expr.expr);
|
||||
Type *type = type_lowering(expr->unary_expr.expr->type);
|
||||
Expr *inner = expr->unary_expr.expr;
|
||||
|
||||
switch (expr->unary_expr.operator)
|
||||
@@ -2430,7 +2448,7 @@ static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||
value->type = type_lowering(expr->type);
|
||||
return;
|
||||
case UNARYOP_DEREF:
|
||||
llvm_emit_deref(c, value, inner, type_lowering(expr->type));
|
||||
llvm_emit_deref(c, value, inner, expr->type);
|
||||
return;
|
||||
case UNARYOP_INC:
|
||||
llvm_emit_pre_inc_dec(c, value, inner, 1, !expr->unary_expr.no_wrap);
|
||||
@@ -4506,7 +4524,7 @@ static inline void llvm_emit_const_initializer_list_expr(GenContext *c, BEValue
|
||||
|
||||
static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
{
|
||||
Type *type = type_reduced_from_expr(expr)->canonical;
|
||||
Type *type = type_lowering(expr->type)->canonical;
|
||||
bool is_bytes = false;
|
||||
switch (expr->const_expr.const_kind)
|
||||
{
|
||||
|
||||
@@ -84,6 +84,7 @@ typedef struct GenContext_
|
||||
bool shared_context;
|
||||
bool in_init_ref;
|
||||
bool weaken;
|
||||
bool emitting_load_store_check;
|
||||
LLVMModuleRef module;
|
||||
LLVMBuilderRef global_builder;
|
||||
LLVMTargetMachineRef machine;
|
||||
|
||||
@@ -683,6 +683,7 @@ AlignSize type_abi_alignment(Type *type)
|
||||
case TYPE_WILDCARD:
|
||||
UNREACHABLE;
|
||||
case TYPE_BITSTRUCT:
|
||||
if (type->decl->alignment) return type->decl->alignment;
|
||||
type = type->decl->strukt.container_type->type;
|
||||
goto RETRY;
|
||||
case TYPE_INFERRED_VECTOR:
|
||||
|
||||
Reference in New Issue
Block a user