mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add @naked attribute
This commit is contained in:
committed by
Christoffer Lerno
parent
fdcc189f41
commit
f7803fd192
@@ -396,6 +396,7 @@ typedef struct
|
||||
bool attr_inline : 1;
|
||||
bool attr_noinline : 1;
|
||||
bool attr_extname : 1;
|
||||
bool attr_naked : 1;
|
||||
};
|
||||
|
||||
TypeInfo *type_parent;
|
||||
|
||||
@@ -628,6 +628,7 @@ unsigned attribute_zext;
|
||||
unsigned attribute_sext;
|
||||
unsigned attribute_byval;
|
||||
unsigned attribute_inreg;
|
||||
unsigned attribute_naked;
|
||||
|
||||
void llvm_codegen_setup()
|
||||
{
|
||||
@@ -709,6 +710,7 @@ void llvm_codegen_setup()
|
||||
attribute_align = lookup_attribute("align");
|
||||
attribute_byval = lookup_attribute("byval");
|
||||
attribute_inreg = lookup_attribute("inreg");
|
||||
attribute_naked = lookup_attribute("naked");
|
||||
intrinsics_setup = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -422,10 +422,13 @@ void llvm_emit_function_body(GenContext *context, Decl *decl)
|
||||
}
|
||||
|
||||
|
||||
// Generate LLVMValueRef's for all parameters, so we can use them as local vars in code
|
||||
VECEACH(decl->func_decl.function_signature.params, i)
|
||||
if (!decl->func_decl.attr_naked)
|
||||
{
|
||||
llvm_emit_parameter(context, decl->func_decl.function_signature.params[i], &arg, i);
|
||||
// Generate LLVMValueRef's for all parameters, so we can use them as local vars in code
|
||||
VECEACH(decl->func_decl.function_signature.params, i)
|
||||
{
|
||||
llvm_emit_parameter(context, decl->func_decl.function_signature.params[i], &arg, i);
|
||||
}
|
||||
}
|
||||
|
||||
LLVMSetCurrentDebugLocation2(context->builder, NULL);
|
||||
@@ -575,7 +578,10 @@ void llvm_emit_function_decl(GenContext *c, Decl *decl)
|
||||
LLVMSetSection(function, decl->section);
|
||||
}
|
||||
llvm_attribute_add(c, function, attribute_nounwind, -1);
|
||||
|
||||
if (decl->func_decl.attr_naked)
|
||||
{
|
||||
llvm_attribute_add(c, function, attribute_naked, -1);
|
||||
}
|
||||
if (decl->func_decl.function_signature.call_abi == CALL_X86_STD)
|
||||
{
|
||||
if (platform_target.os == OS_TYPE_WIN32)
|
||||
|
||||
@@ -177,6 +177,7 @@ extern unsigned attribute_zext; // zero extend
|
||||
extern unsigned attribute_sext; // sign extend
|
||||
extern unsigned attribute_byval; // ByVal (param)
|
||||
extern unsigned attribute_inreg; // inreg (param)
|
||||
extern unsigned attribute_naked; // naked function
|
||||
|
||||
void gencontext_begin_module(GenContext *c);
|
||||
void gencontext_init_file_emit(GenContext *c, Context *ast);
|
||||
|
||||
@@ -1086,6 +1086,7 @@ static inline bool sema_analyse_func(Context *context, Decl *decl)
|
||||
case ATTRIBUTE_INLINE: SET_ATTR(attr_inline);
|
||||
case ATTRIBUTE_NORETURN: SET_ATTR(attr_noreturn);
|
||||
case ATTRIBUTE_WEAK: SET_ATTR(attr_weak);
|
||||
case ATTRIBUTE_NAKED: SET_ATTR(attr_naked);
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
@@ -2426,16 +2426,32 @@ bool sema_analyse_function_body(Context *context, Decl *func)
|
||||
}
|
||||
Ast **asserts = NULL;
|
||||
if (!sema_analyse_requires(context, func->docs, &asserts)) return false;
|
||||
if (!sema_analyse_compound_statement_no_scope(context, func->func_decl.body)) return false;
|
||||
assert(context->active_scope.depth == 1);
|
||||
if (!context->active_scope.jump_end)
|
||||
if (func->func_decl.attr_naked)
|
||||
{
|
||||
Type *canonical_rtype = signature->rtype->type->canonical;
|
||||
if (canonical_rtype != type_void)
|
||||
Ast **stmts = func->func_decl.body->compound_stmt.stmts;
|
||||
VECEACH(stmts, i)
|
||||
{
|
||||
// IMPROVE better pointer to end.
|
||||
SEMA_ERROR(func, "Missing return statement at the end of the function.");
|
||||
return false;
|
||||
if (stmts[i]->ast_kind != AST_ASM_STMT)
|
||||
{
|
||||
SEMA_ERROR(stmts[i], "Only asm statements are allowed inside of a naked function.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
asserts = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!sema_analyse_compound_statement_no_scope(context, func->func_decl.body)) return false;
|
||||
assert(context->active_scope.depth == 1);
|
||||
if (!context->active_scope.jump_end)
|
||||
{
|
||||
Type *canonical_rtype = signature->rtype->type->canonical;
|
||||
if (canonical_rtype != type_void)
|
||||
{
|
||||
// IMPROVE better pointer to end.
|
||||
SEMA_ERROR(func, "Missing return statement at the end of the function.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (asserts)
|
||||
|
||||
15
test/test_suite/functions/naked_function.c3t
Normal file
15
test/test_suite/functions/naked_function.c3t
Normal file
@@ -0,0 +1,15 @@
|
||||
// #target: x64-darwin
|
||||
|
||||
func void test(int i) @naked
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// #expect: naked_function.ll
|
||||
|
||||
define void @naked_function.test(i32 %0) #0 {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
attributes #0 = { naked nounwind }
|
||||
4
test/test_suite/functions/naked_function_fail.c3
Normal file
4
test/test_suite/functions/naked_function_fail.c3
Normal file
@@ -0,0 +1,4 @@
|
||||
func void test() @naked
|
||||
{
|
||||
int i; // #error: Only asm statements are allowed inside of a naked function
|
||||
}
|
||||
Reference in New Issue
Block a user