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_inline : 1;
|
||||||
bool attr_noinline : 1;
|
bool attr_noinline : 1;
|
||||||
bool attr_extname : 1;
|
bool attr_extname : 1;
|
||||||
|
bool attr_naked : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
TypeInfo *type_parent;
|
TypeInfo *type_parent;
|
||||||
|
|||||||
@@ -628,6 +628,7 @@ unsigned attribute_zext;
|
|||||||
unsigned attribute_sext;
|
unsigned attribute_sext;
|
||||||
unsigned attribute_byval;
|
unsigned attribute_byval;
|
||||||
unsigned attribute_inreg;
|
unsigned attribute_inreg;
|
||||||
|
unsigned attribute_naked;
|
||||||
|
|
||||||
void llvm_codegen_setup()
|
void llvm_codegen_setup()
|
||||||
{
|
{
|
||||||
@@ -709,6 +710,7 @@ void llvm_codegen_setup()
|
|||||||
attribute_align = lookup_attribute("align");
|
attribute_align = lookup_attribute("align");
|
||||||
attribute_byval = lookup_attribute("byval");
|
attribute_byval = lookup_attribute("byval");
|
||||||
attribute_inreg = lookup_attribute("inreg");
|
attribute_inreg = lookup_attribute("inreg");
|
||||||
|
attribute_naked = lookup_attribute("naked");
|
||||||
intrinsics_setup = true;
|
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
|
if (!decl->func_decl.attr_naked)
|
||||||
VECEACH(decl->func_decl.function_signature.params, i)
|
|
||||||
{
|
{
|
||||||
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);
|
LLVMSetCurrentDebugLocation2(context->builder, NULL);
|
||||||
@@ -575,7 +578,10 @@ void llvm_emit_function_decl(GenContext *c, Decl *decl)
|
|||||||
LLVMSetSection(function, decl->section);
|
LLVMSetSection(function, decl->section);
|
||||||
}
|
}
|
||||||
llvm_attribute_add(c, function, attribute_nounwind, -1);
|
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 (decl->func_decl.function_signature.call_abi == CALL_X86_STD)
|
||||||
{
|
{
|
||||||
if (platform_target.os == OS_TYPE_WIN32)
|
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_sext; // sign extend
|
||||||
extern unsigned attribute_byval; // ByVal (param)
|
extern unsigned attribute_byval; // ByVal (param)
|
||||||
extern unsigned attribute_inreg; // inreg (param)
|
extern unsigned attribute_inreg; // inreg (param)
|
||||||
|
extern unsigned attribute_naked; // naked function
|
||||||
|
|
||||||
void gencontext_begin_module(GenContext *c);
|
void gencontext_begin_module(GenContext *c);
|
||||||
void gencontext_init_file_emit(GenContext *c, Context *ast);
|
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_INLINE: SET_ATTR(attr_inline);
|
||||||
case ATTRIBUTE_NORETURN: SET_ATTR(attr_noreturn);
|
case ATTRIBUTE_NORETURN: SET_ATTR(attr_noreturn);
|
||||||
case ATTRIBUTE_WEAK: SET_ATTR(attr_weak);
|
case ATTRIBUTE_WEAK: SET_ATTR(attr_weak);
|
||||||
|
case ATTRIBUTE_NAKED: SET_ATTR(attr_naked);
|
||||||
default:
|
default:
|
||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2426,16 +2426,32 @@ bool sema_analyse_function_body(Context *context, Decl *func)
|
|||||||
}
|
}
|
||||||
Ast **asserts = NULL;
|
Ast **asserts = NULL;
|
||||||
if (!sema_analyse_requires(context, func->docs, &asserts)) return false;
|
if (!sema_analyse_requires(context, func->docs, &asserts)) return false;
|
||||||
if (!sema_analyse_compound_statement_no_scope(context, func->func_decl.body)) return false;
|
if (func->func_decl.attr_naked)
|
||||||
assert(context->active_scope.depth == 1);
|
|
||||||
if (!context->active_scope.jump_end)
|
|
||||||
{
|
{
|
||||||
Type *canonical_rtype = signature->rtype->type->canonical;
|
Ast **stmts = func->func_decl.body->compound_stmt.stmts;
|
||||||
if (canonical_rtype != type_void)
|
VECEACH(stmts, i)
|
||||||
{
|
{
|
||||||
// IMPROVE better pointer to end.
|
if (stmts[i]->ast_kind != AST_ASM_STMT)
|
||||||
SEMA_ERROR(func, "Missing return statement at the end of the function.");
|
{
|
||||||
return false;
|
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)
|
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