Add experimental @noalias attribute.

This commit is contained in:
Christoffer Lerno
2024-08-01 22:57:26 +02:00
parent ebf071ac51
commit 1aab8b87ec
6 changed files with 26 additions and 6 deletions

View File

@@ -20,6 +20,7 @@
- `$expand` macro, to expand a string into code.
- && doesn't work correctly with lambdas #1279.
- Fix incorrect override of optimization levels when using projects.
- Add experimental `@noalias` attribute.
### Fixes

View File

@@ -472,6 +472,7 @@ typedef struct VarDecl_
bool is_addr : 1;
bool is_threadlocal : 1;
bool no_init : 1;
bool no_alias : 1;
bool bit_is_expr : 1;
TypeInfoId type_info;
union

View File

@@ -824,6 +824,7 @@ typedef enum
ATTRIBUTE_LOCAL,
ATTRIBUTE_MAYDISCARD,
ATTRIBUTE_NAKED,
ATTRIBUTE_NOALIAS,
ATTRIBUTE_NODISCARD,
ATTRIBUTE_NOINIT,
ATTRIBUTE_NOINLINE,

View File

@@ -1069,7 +1069,8 @@ LLVMValueRef llvm_get_opt_ref(GenContext *c, Decl *decl)
return decl->var.optional_ref;
}
static void llvm_emit_param_attributes(GenContext *c, LLVMValueRef function, ABIArgInfo *info, bool is_return, int index, int last_index)
static void llvm_emit_param_attributes(GenContext *c, LLVMValueRef function, ABIArgInfo *info, bool is_return,
int index, int last_index, Decl *decl)
{
assert(last_index == index || info->kind == ABI_ARG_DIRECT_PAIR || info->kind == ABI_ARG_IGNORE
|| info->kind == ABI_ARG_EXPAND || info->kind == ABI_ARG_DIRECT || info->kind == ABI_ARG_DIRECT_COERCE
@@ -1094,13 +1095,18 @@ static void llvm_emit_param_attributes(GenContext *c, LLVMValueRef function, ABI
}
switch (info->kind)
{
case ABI_ARG_DIRECT:
if (decl && decl->var.no_alias)
{
llvm_attribute_add(c, function, attribute_id.noalias, 1);
}
break;
case ABI_ARG_EXPAND:
case ABI_ARG_IGNORE:
case ABI_ARG_DIRECT_SPLIT_STRUCT_I32:
case ABI_ARG_DIRECT_COERCE:
case ABI_ARG_DIRECT_COERCE_INT:
case ABI_ARG_DIRECT_PAIR:
case ABI_ARG_DIRECT:
case ABI_ARG_EXPAND_COERCE:
break;
case ABI_ARG_INDIRECT:
@@ -1127,7 +1133,7 @@ void llvm_append_function_attributes(GenContext *c, Decl *decl)
LLVMValueRef function = decl->backend_ref;
ABIArgInfo *ret_abi_info = prototype->ret_abi_info;
llvm_emit_param_attributes(c, function, ret_abi_info, true, 0, 0);
llvm_emit_param_attributes(c, function, ret_abi_info, true, 0, 0, NULL);
unsigned params = vec_size(prototype->param_types);
if (c->debug.enable_stacktrace)
{
@@ -1140,12 +1146,13 @@ void llvm_append_function_attributes(GenContext *c, Decl *decl)
if (prototype->ret_by_ref)
{
ABIArgInfo *info = prototype->ret_by_ref_abi_info;
llvm_emit_param_attributes(c, function, prototype->ret_by_ref_abi_info, false, info->param_index_start + 1, info->param_index_end);
llvm_emit_param_attributes(c, function, prototype->ret_by_ref_abi_info, false, info->param_index_start + 1,
info->param_index_end, NULL);
}
for (unsigned i = 0; i < params; i++)
{
ABIArgInfo *info = prototype->abi_args[i];
llvm_emit_param_attributes(c, function, info, false, info->param_index_start + 1, info->param_index_end);
llvm_emit_param_attributes(c, function, info, false, info->param_index_start + 1, info->param_index_end, decl->func_decl.signature.params[i]);
}
// We ignore decl->func_decl.attr_inline and place it in every call instead.
if (decl->func_decl.attr_noinline)

View File

@@ -1200,12 +1200,17 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig,
: RESOLVE_TYPE_DEFAULT)) return decl_poison(param);
param->type = type_info->type;
}
if (type_info && param->var.no_alias && !type_is_pointer(param->type) && type_flatten(param->type)->type_kind != TYPE_SLICE)
{
SEMA_ERROR(param, "The parameter was set to @noalias, but it was neither a slice nor a pointer. You need to either remove '@noalias' or use pointer/slice type.");
return decl_poison(param);
}
switch (var_kind)
{
case VARDECL_PARAM_REF:
if (type_info && !type_is_pointer(param->type))
{
RETURN_SEMA_ERROR(type_info, "A pointer type was expected for a ref argument, did you mean %s?",
SEMA_ERROR(type_info, "A pointer type was expected for a ref argument, did you mean %s?",
type_quoted_error_string(type_get_ptr(param->type)));
return decl_poison(param);
}
@@ -2359,6 +2364,7 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr,
[ATTRIBUTE_LOCAL] = ATTR_FUNC | ATTR_MACRO | ATTR_GLOBAL | ATTR_CONST | USER_DEFINED_TYPES | ATTR_DEF | ATTR_INTERFACE,
[ATTRIBUTE_MAYDISCARD] = CALLABLE_TYPE,
[ATTRIBUTE_NAKED] = ATTR_FUNC,
[ATTRIBUTE_NOALIAS] = ATTR_PARAM,
[ATTRIBUTE_NODISCARD] = CALLABLE_TYPE,
[ATTRIBUTE_NOINIT] = ATTR_GLOBAL | ATTR_LOCAL,
[ATTRIBUTE_NOINLINE] = ATTR_FUNC | ATTR_CALL,
@@ -2519,6 +2525,9 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr,
case ATTRIBUTE_NOSTRIP:
decl->no_strip = true;
return true;
case ATTRIBUTE_NOALIAS:
decl->var.no_alias = true;
return true;
case ATTRIBUTE_IF:
if (!expr) RETURN_SEMA_ERROR(attr, "'@if' requires a boolean argument.");
if (!sema_analyse_expr(context, expr)) return false;

View File

@@ -326,6 +326,7 @@ void symtab_init(uint32_t capacity)
attribute_list[ATTRIBUTE_LOCAL] = KW_DEF("@local");
attribute_list[ATTRIBUTE_MAYDISCARD] = KW_DEF("@maydiscard");
attribute_list[ATTRIBUTE_NAKED] = KW_DEF("@naked");
attribute_list[ATTRIBUTE_NOALIAS] = KW_DEF("@noalias");
attribute_list[ATTRIBUTE_NODISCARD] = KW_DEF("@nodiscard");
attribute_list[ATTRIBUTE_NOINIT] = KW_DEF("@noinit");
attribute_list[ATTRIBUTE_NOINLINE] = KW_DEF("@noinline");