mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Added some explicit casts. Added sret at call site.
This commit is contained in:
@@ -572,7 +572,7 @@ ArchOsTarget arch_os_target_from_string(const char *target)
|
||||
{
|
||||
if (strcasecmp(arch_os_target[i], target) == 0)
|
||||
{
|
||||
return i;
|
||||
return (ArchOsTarget)i;
|
||||
}
|
||||
}
|
||||
return ARCH_OS_TARGET_DEFAULT;
|
||||
|
||||
@@ -1752,8 +1752,8 @@ static inline TokenData *tokendata_from_token(Token token) { return tokdataptr(t
|
||||
|
||||
#define TOKREAL(T) TOKDATA(T)->value
|
||||
|
||||
static inline TokenType tokenid_type(TokenId token) { return toktypeptr(token.index)[0]; }
|
||||
static inline TokenType token_type(Token token) { return toktypeptr(token.id.index)[0]; }
|
||||
static inline TokenType tokenid_type(TokenId token) { return (TokenType)toktypeptr(token.index)[0]; }
|
||||
static inline TokenType token_type(Token token) { return (TokenType)toktypeptr(token.id.index)[0]; }
|
||||
#define TOKTYPE(T) _Generic((T), TokenId: tokenid_type, Token: token_type)(T)
|
||||
|
||||
#define TOKLEN(T) TOKLOC(T)->length
|
||||
|
||||
@@ -271,7 +271,7 @@ static void skip_whitespace(Lexer *lexer, LexMode lex_type)
|
||||
// we split identifiers into 2 types + find keywords.
|
||||
static inline bool scan_ident(Lexer *lexer, TokenType normal, TokenType const_token, TokenType type_token, char prefix)
|
||||
{
|
||||
TokenType type = 0;
|
||||
TokenType type = (TokenType)0;
|
||||
uint32_t hash = FNV1_SEED;
|
||||
if (prefix)
|
||||
{
|
||||
@@ -414,7 +414,6 @@ static inline bool scan_hex(Lexer *lexer)
|
||||
char c = peek(lexer);
|
||||
if (c == 'p' || c == 'P')
|
||||
{
|
||||
is_float = true;
|
||||
is_float = true;
|
||||
if (!scan_exponent(lexer)) return false;
|
||||
}
|
||||
|
||||
@@ -1039,6 +1039,12 @@ void llvm_attribute_add(GenContext *context, LLVMValueRef value_to_add_attribute
|
||||
llvm_attribute_add_int(context, value_to_add_attribute_to, attribute_id, 0, index);
|
||||
}
|
||||
|
||||
void llvm_attribute_add_call(GenContext *context, LLVMValueRef call, unsigned attribute_id, int index, int64_t value)
|
||||
{
|
||||
LLVMAttributeRef llvm_attr = LLVMCreateEnumAttribute(context->context, attribute_id, value);
|
||||
LLVMAddCallSiteAttribute(call, index, llvm_attr);
|
||||
}
|
||||
|
||||
void llvm_attribute_add_range(GenContext *context, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, int index_start, int index_end)
|
||||
{
|
||||
for (int i = index_start; i <= index_end; i++)
|
||||
|
||||
@@ -2712,6 +2712,7 @@ static void llvm_emit_unpacked_variadic_arg(GenContext *c, Expr *expr, BEValue *
|
||||
UNREACHABLE
|
||||
}
|
||||
}
|
||||
|
||||
void llvm_emit_call_expr(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
{
|
||||
Expr *function = expr->call_expr.function;
|
||||
@@ -2791,7 +2792,7 @@ void llvm_emit_call_expr(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
{
|
||||
case ABI_ARG_INDIRECT:
|
||||
// 6a. We can use the stored error var if there is no redirect.
|
||||
if (signature->failable && c->error_var && ret_info->attributes.realign)
|
||||
if (signature->failable && c->error_var && !ret_info->attributes.realign)
|
||||
{
|
||||
error_var = c->error_var;
|
||||
vec_add(values, error_var);
|
||||
@@ -2931,7 +2932,8 @@ void llvm_emit_call_expr(GenContext *c, BEValue *be_value, Expr *expr)
|
||||
*be_value = (BEValue) { .type = type_void, .kind = BE_VALUE };
|
||||
return;
|
||||
case ABI_ARG_INDIRECT:
|
||||
|
||||
llvm_attribute_add_call(c, call_value, attribute_sret, 1, 0);
|
||||
llvm_attribute_add_call(c, call_value, attribute_align, 1, ret_info->indirect.alignment);
|
||||
// 13. Indirect, that is passing the result through an out parameter.
|
||||
|
||||
// 13a. In the case of an already present error_var, we don't need to do a load here.
|
||||
|
||||
@@ -203,6 +203,7 @@ unsigned llvm_abi_size(GenContext *c, LLVMTypeRef type);
|
||||
AlignSize llvm_abi_alignment(GenContext *c, LLVMTypeRef type);
|
||||
void llvm_attribute_add_range(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, int index_start, int index_end);
|
||||
void llvm_attribute_add(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, int index);
|
||||
void llvm_attribute_add_call(GenContext *context, LLVMValueRef call, unsigned attribute_id, int index, int64_t value);
|
||||
void llvm_attribute_add_string(GenContext *c, LLVMValueRef value_to_add_attribute_to, const char *attribute, const char *value, int index);
|
||||
void llvm_attribute_add_int(GenContext *c, LLVMValueRef value_to_add_attribute_to, unsigned attribute_id, uint64_t val, int index);
|
||||
LLVMBasicBlockRef llvm_basic_block_new(GenContext *c, const char *name);
|
||||
|
||||
@@ -337,7 +337,6 @@ Type *type_by_expr_range(ExprConst *expr)
|
||||
return type_double;
|
||||
}
|
||||
assert(expr->kind == TYPE_IXX);
|
||||
BigInt *b = &expr->i;
|
||||
// 1. Does it fit in a C int? If so, that's the type.
|
||||
Type *type = type_cint();
|
||||
if (!expr_const_will_overflow(expr, type->type_kind)) return type;
|
||||
|
||||
@@ -1260,7 +1260,7 @@ static bool sema_analyse_parameterized_define(Context *c, Decl *decl)
|
||||
if (define_type->resolve_status == RESOLVE_DONE && type_is_user_defined(define_type->type))
|
||||
{
|
||||
SEMA_ERROR(define_type, "Expected a user defined type for parameterization.");
|
||||
return poisoned_decl;
|
||||
return decl_poison(decl);
|
||||
}
|
||||
decl_path = define_type->unresolved.path;
|
||||
name = define_type->unresolved.name_loc;
|
||||
@@ -1291,7 +1291,7 @@ static bool sema_analyse_parameterized_define(Context *c, Decl *decl)
|
||||
VECEACH(decl->define_decl.generic_params, i)
|
||||
{
|
||||
TypeInfo *type_info = decl->define_decl.generic_params[i];
|
||||
if (!sema_resolve_type_info(c, type_info)) return poisoned_decl;
|
||||
if (!sema_resolve_type_info(c, type_info)) return decl_poison(decl);
|
||||
if (i != 0) scratch_buffer_append_char('.');
|
||||
const char *type_name = type_info->type->canonical->name;
|
||||
scratch_buffer_append(type_name);
|
||||
|
||||
@@ -547,7 +547,7 @@ static inline bool sema_expr_analyse_identifier(Context *context, Type *to, Expr
|
||||
}
|
||||
if (decl->resolve_status != RESOLVE_DONE)
|
||||
{
|
||||
if (!sema_analyse_decl(context, decl)) return poisoned_decl;
|
||||
if (!sema_analyse_decl(context, decl)) return decl_poison(decl);
|
||||
}
|
||||
if (decl->decl_kind == DECL_VAR && decl->var.failable)
|
||||
{
|
||||
|
||||
37
test/test_suite/abi/pass_large_aarch.c3t
Normal file
37
test/test_suite/abi/pass_large_aarch.c3t
Normal file
@@ -0,0 +1,37 @@
|
||||
// #target: aarch64_linux
|
||||
|
||||
module pass_large;
|
||||
|
||||
|
||||
struct Large
|
||||
{
|
||||
void*[8] pointers;
|
||||
}
|
||||
|
||||
extern func void pass_large(Large large);
|
||||
|
||||
func void example()
|
||||
{
|
||||
Large l = {};
|
||||
pass_large(l);
|
||||
pass_large(l);
|
||||
}
|
||||
|
||||
// #expect: pass_large.ll
|
||||
|
||||
define void @pass_large.example()
|
||||
entry:
|
||||
%l = alloca %Large, align 8
|
||||
%indirectarg = alloca %Large, align 8
|
||||
%indirectarg1 = alloca %Large, align 8
|
||||
%0 = bitcast %Large* %l to i8*
|
||||
call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 64, i1 false)
|
||||
%1 = bitcast %Large* %indirectarg to i8*
|
||||
%2 = bitcast %Large* %l to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %1, i8* align 8 %2, i32 64, i1 false)
|
||||
call void @pass_large(%Large* %indirectarg)
|
||||
%3 = bitcast %Large* %indirectarg1 to i8*
|
||||
%4 = bitcast %Large* %l to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %3, i8* align 8 %4, i32 64, i1 false)
|
||||
call void @pass_large(%Large* %indirectarg1)
|
||||
ret void
|
||||
39
test/test_suite/abi/test_sret.c3t
Normal file
39
test/test_suite/abi/test_sret.c3t
Normal file
@@ -0,0 +1,39 @@
|
||||
// #target: x64_darwin
|
||||
|
||||
struct Abc {
|
||||
long a;
|
||||
long b;
|
||||
long c;
|
||||
long d;
|
||||
long e;
|
||||
}
|
||||
|
||||
extern func Abc foo1();
|
||||
extern func Abc foo2();
|
||||
|
||||
func void bar() {
|
||||
Abc dummy1 = foo1();
|
||||
Abc dummy2 = foo2();
|
||||
}
|
||||
|
||||
// Cleanup for this result, since it's creating an unnecessary sret.
|
||||
|
||||
// #expect: test_sret.ll
|
||||
|
||||
declare void @foo1(%Abc* sret align 8)
|
||||
|
||||
declare void @foo2(%Abc* sret align 8)
|
||||
|
||||
%dummy1 = alloca %Abc, align 8
|
||||
%sretparam = alloca %Abc, align 8
|
||||
%dummy2 = alloca %Abc, align 8
|
||||
%sretparam1 = alloca %Abc, align 8
|
||||
call void @foo1(%Abc* sret align 8 %sretparam)
|
||||
%0 = bitcast %Abc* %dummy1 to i8*
|
||||
%1 = bitcast %Abc* %sretparam to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %0, i8* align 8 %1, i32 40, i1 false)
|
||||
call void @foo2(%Abc* sret align 8 %sretparam1)
|
||||
%2 = bitcast %Abc* %dummy2 to i8*
|
||||
%3 = bitcast %Abc* %sretparam1 to i8*
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %2, i8* align 8 %3, i32 40, i1 false)
|
||||
ret void
|
||||
Reference in New Issue
Block a user