implement @frameSize
This commit is contained in:
parent
70bced5dcf
commit
538c0cd225
|
@ -2,3 +2,4 @@
|
|||
* await of a non async function
|
||||
* async call on a non async function
|
||||
* safety for resuming when it is awaiting
|
||||
* implicit cast of normal function to async function should be allowed when it is inferred to be async
|
||||
|
|
|
@ -1508,6 +1508,7 @@ enum BuiltinFnId {
|
|||
BuiltinFnIdFrameAddress,
|
||||
BuiltinFnIdFrameType,
|
||||
BuiltinFnIdFrameHandle,
|
||||
BuiltinFnIdFrameSize,
|
||||
};
|
||||
|
||||
struct BuiltinFnEntry {
|
||||
|
@ -2255,6 +2256,8 @@ enum IrInstructionId {
|
|||
IrInstructionIdFrameAddress,
|
||||
IrInstructionIdFrameHandle,
|
||||
IrInstructionIdFrameType,
|
||||
IrInstructionIdFrameSizeSrc,
|
||||
IrInstructionIdFrameSizeGen,
|
||||
IrInstructionIdAlignOf,
|
||||
IrInstructionIdOverflowOp,
|
||||
IrInstructionIdTestErrSrc,
|
||||
|
@ -3050,6 +3053,19 @@ struct IrInstructionFrameType {
|
|||
IrInstruction *fn;
|
||||
};
|
||||
|
||||
struct IrInstructionFrameSizeSrc {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *fn;
|
||||
};
|
||||
|
||||
struct IrInstructionFrameSizeGen {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *fn;
|
||||
IrInstruction *frame_ptr;
|
||||
};
|
||||
|
||||
enum IrOverflowOp {
|
||||
IrOverflowOpAdd,
|
||||
IrOverflowOpSub,
|
||||
|
|
|
@ -4914,6 +4914,15 @@ static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_frame_size(CodeGen *g, IrExecutable *executable, IrInstructionFrameSizeGen *instruction) {
|
||||
LLVMValueRef fn_val = ir_llvm_value(g, instruction->fn);
|
||||
LLVMValueRef frame_ptr = ir_llvm_value(g, instruction->frame_ptr);
|
||||
LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_ptr, coro_resume_index_index, "");
|
||||
LLVMValueRef one = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 1, false);
|
||||
LLVMBuildStore(g->builder, one, resume_index_ptr);
|
||||
return ZigLLVMBuildCall(g->builder, fn_val, &frame_ptr, 1, LLVMFastCallConv, ZigLLVM_FnInlineAuto, "");
|
||||
}
|
||||
|
||||
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
|
||||
AstNode *source_node = instruction->source_node;
|
||||
Scope *scope = instruction->scope;
|
||||
|
@ -5007,6 +5016,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||
case IrInstructionIdTestErrSrc:
|
||||
case IrInstructionIdUnionInitNamedField:
|
||||
case IrInstructionIdFrameType:
|
||||
case IrInstructionIdFrameSizeSrc:
|
||||
zig_unreachable();
|
||||
|
||||
case IrInstructionIdDeclVarGen:
|
||||
|
@ -5161,6 +5171,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||
return ir_render_suspend_br(g, executable, (IrInstructionSuspendBr *)instruction);
|
||||
case IrInstructionIdCoroResume:
|
||||
return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);
|
||||
case IrInstructionIdFrameSizeGen:
|
||||
return ir_render_frame_size(g, executable, (IrInstructionFrameSizeGen *)instruction);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -6856,6 +6868,7 @@ static void define_builtin_fns(CodeGen *g) {
|
|||
create_builtin_fn(g, BuiltinFnIdFrameHandle, "frame", 0);
|
||||
create_builtin_fn(g, BuiltinFnIdFrameType, "Frame", 1);
|
||||
create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0);
|
||||
create_builtin_fn(g, BuiltinFnIdFrameSize, "frameSize", 1);
|
||||
}
|
||||
|
||||
static const char *bool_to_str(bool b) {
|
||||
|
|
70
src/ir.cpp
70
src/ir.cpp
|
@ -763,6 +763,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameType *) {
|
|||
return IrInstructionIdFrameType;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameSizeSrc *) {
|
||||
return IrInstructionIdFrameSizeSrc;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameSizeGen *) {
|
||||
return IrInstructionIdFrameSizeGen;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) {
|
||||
return IrInstructionIdAlignOf;
|
||||
}
|
||||
|
@ -2379,6 +2387,28 @@ static IrInstruction *ir_build_frame_type(IrBuilder *irb, Scope *scope, AstNode
|
|||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_frame_size_src(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn) {
|
||||
IrInstructionFrameSizeSrc *instruction = ir_build_instruction<IrInstructionFrameSizeSrc>(irb, scope, source_node);
|
||||
instruction->fn = fn;
|
||||
|
||||
ir_ref_instruction(fn, irb->current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_frame_size_gen(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn,
|
||||
IrInstruction *frame_ptr)
|
||||
{
|
||||
IrInstructionFrameSizeGen *instruction = ir_build_instruction<IrInstructionFrameSizeGen>(irb, scope, source_node);
|
||||
instruction->fn = fn;
|
||||
instruction->frame_ptr = frame_ptr;
|
||||
|
||||
ir_ref_instruction(fn, irb->current_basic_block);
|
||||
ir_ref_instruction(frame_ptr, irb->current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrOverflowOp op, IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2,
|
||||
IrInstruction *result_ptr, ZigType *result_ptr_type)
|
||||
|
@ -4923,6 +4953,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
|
|||
IrInstruction *frame_type = ir_build_frame_type(irb, scope, node, arg0_value);
|
||||
return ir_lval_wrap(irb, scope, frame_type, lval, result_loc);
|
||||
}
|
||||
case BuiltinFnIdFrameSize: {
|
||||
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
|
||||
IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
|
||||
if (arg0_value == irb->codegen->invalid_instruction)
|
||||
return arg0_value;
|
||||
|
||||
IrInstruction *frame_size = ir_build_frame_size_src(irb, scope, node, arg0_value);
|
||||
return ir_lval_wrap(irb, scope, frame_size, lval, result_loc);
|
||||
}
|
||||
case BuiltinFnIdAlignOf:
|
||||
{
|
||||
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
|
||||
|
@ -21758,6 +21797,28 @@ static IrInstruction *ir_analyze_instruction_frame_type(IrAnalyze *ira, IrInstru
|
|||
return ir_const_type(ira, &instruction->base, ty);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_frame_size(IrAnalyze *ira, IrInstructionFrameSizeSrc *instruction) {
|
||||
IrInstruction *fn = instruction->fn->child;
|
||||
if (type_is_invalid(fn->value.type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
if (fn->value.type->id != ZigTypeIdFn) {
|
||||
ir_add_error(ira, fn,
|
||||
buf_sprintf("expected function, found '%s'", buf_ptr(&fn->value.type->name)));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
IrInstruction *frame_ptr = ir_resolve_result(ira, &instruction->base, no_result_loc(),
|
||||
ira->codegen->builtin_types.entry_frame_header, nullptr, true, false);
|
||||
if (frame_ptr != nullptr && (type_is_invalid(frame_ptr->value.type) || instr_is_unreachable(frame_ptr)))
|
||||
return frame_ptr;
|
||||
|
||||
IrInstruction *result = ir_build_frame_size_gen(&ira->new_irb, instruction->base.scope,
|
||||
instruction->base.source_node, fn, frame_ptr);
|
||||
result->value.type = ira->codegen->builtin_types.entry_usize;
|
||||
return result;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {
|
||||
Error err;
|
||||
IrInstruction *type_value = instruction->type_value->child;
|
||||
|
@ -22348,10 +22409,6 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct
|
|||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
if (fn_type_id.cc == CallingConventionAsync) {
|
||||
zig_panic("TODO");
|
||||
}
|
||||
|
||||
return ir_const_type(ira, &instruction->base, get_fn_type(ira->codegen, &fn_type_id));
|
||||
}
|
||||
|
||||
|
@ -24237,6 +24294,7 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
|
|||
case IrInstructionIdSliceGen:
|
||||
case IrInstructionIdRefGen:
|
||||
case IrInstructionIdTestErrGen:
|
||||
case IrInstructionIdFrameSizeGen:
|
||||
zig_unreachable();
|
||||
|
||||
case IrInstructionIdReturn:
|
||||
|
@ -24387,6 +24445,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
|
|||
return ir_analyze_instruction_frame_handle(ira, (IrInstructionFrameHandle *)instruction);
|
||||
case IrInstructionIdFrameType:
|
||||
return ir_analyze_instruction_frame_type(ira, (IrInstructionFrameType *)instruction);
|
||||
case IrInstructionIdFrameSizeSrc:
|
||||
return ir_analyze_instruction_frame_size(ira, (IrInstructionFrameSizeSrc *)instruction);
|
||||
case IrInstructionIdAlignOf:
|
||||
return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction);
|
||||
case IrInstructionIdOverflowOp:
|
||||
|
@ -24682,6 +24742,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
|||
case IrInstructionIdFrameAddress:
|
||||
case IrInstructionIdFrameHandle:
|
||||
case IrInstructionIdFrameType:
|
||||
case IrInstructionIdFrameSizeSrc:
|
||||
case IrInstructionIdFrameSizeGen:
|
||||
case IrInstructionIdTestErrSrc:
|
||||
case IrInstructionIdTestErrGen:
|
||||
case IrInstructionIdFnProto:
|
||||
|
|
|
@ -916,6 +916,20 @@ static void ir_print_frame_type(IrPrint *irp, IrInstructionFrameType *instructio
|
|||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_frame_size_src(IrPrint *irp, IrInstructionFrameSizeSrc *instruction) {
|
||||
fprintf(irp->f, "@frameSize(");
|
||||
ir_print_other_instruction(irp, instruction->fn);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_frame_size_gen(IrPrint *irp, IrInstructionFrameSizeGen *instruction) {
|
||||
fprintf(irp->f, "@frameSize(");
|
||||
ir_print_other_instruction(irp, instruction->fn);
|
||||
fprintf(irp->f, ",");
|
||||
ir_print_other_instruction(irp, instruction->frame_ptr);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *instruction) {
|
||||
fprintf(irp->f, "@returnAddress()");
|
||||
}
|
||||
|
@ -1776,6 +1790,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|||
case IrInstructionIdFrameType:
|
||||
ir_print_frame_type(irp, (IrInstructionFrameType *)instruction);
|
||||
break;
|
||||
case IrInstructionIdFrameSizeSrc:
|
||||
ir_print_frame_size_src(irp, (IrInstructionFrameSizeSrc *)instruction);
|
||||
break;
|
||||
case IrInstructionIdFrameSizeGen:
|
||||
ir_print_frame_size_gen(irp, (IrInstructionFrameSizeGen *)instruction);
|
||||
break;
|
||||
case IrInstructionIdAlignOf:
|
||||
ir_print_align_of(irp, (IrInstructionAlignOf *)instruction);
|
||||
break;
|
||||
|
|
|
@ -101,6 +101,32 @@ test "calling an inferred async function" {
|
|||
S.doTheTest();
|
||||
}
|
||||
|
||||
test "@frameSize" {
|
||||
const S = struct {
|
||||
fn doTheTest() void {
|
||||
{
|
||||
var ptr = @ptrCast(async fn(i32) void, other);
|
||||
const size = @frameSize(ptr);
|
||||
expect(size == @sizeOf(@Frame(other)));
|
||||
}
|
||||
{
|
||||
var ptr = @ptrCast(async fn() void, first);
|
||||
const size = @frameSize(ptr);
|
||||
expect(size == @sizeOf(@Frame(first)));
|
||||
}
|
||||
}
|
||||
|
||||
fn first() void {
|
||||
other(1);
|
||||
}
|
||||
fn other(param: i32) void {
|
||||
var local: i32 = undefined;
|
||||
suspend;
|
||||
}
|
||||
};
|
||||
S.doTheTest();
|
||||
}
|
||||
|
||||
//test "coroutine suspend, resume" {
|
||||
// seq('a');
|
||||
// const p = try async<allocator> testAsyncSeq();
|
||||
|
|
Loading…
Reference in New Issue
Block a user