mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add experimental @noalias attribute.
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -824,6 +824,7 @@ typedef enum
|
||||
ATTRIBUTE_LOCAL,
|
||||
ATTRIBUTE_MAYDISCARD,
|
||||
ATTRIBUTE_NAKED,
|
||||
ATTRIBUTE_NOALIAS,
|
||||
ATTRIBUTE_NODISCARD,
|
||||
ATTRIBUTE_NOINIT,
|
||||
ATTRIBUTE_NOINLINE,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user