no-copy semantics for if expr

```zig
export fn entry() void {
    var c = true;
    var x = if (c) u8(4) else u32(10);
}
```

```llvm
define void @entry() #2 !dbg !35 {
Entry:
  %c = alloca i1, align 1
  %x = alloca i32, align 4
  store i1 true, i1* %c, align 1, !dbg !44
  call void @llvm.dbg.declare(metadata i1* %c, metadata !39, metadata !DIExpression()), !dbg !45
  %0 = load i1, i1* %c, align 1, !dbg !46
  br i1 %0, label %Then, label %Else, !dbg !46

Then:                                             ; preds = %Entry
  br label %EndIf, !dbg !47

Else:                                             ; preds = %Entry
  br label %EndIf, !dbg !47

EndIf:                                            ; preds = %Else, %Then
  %1 = phi i32 [ 4, %Then ], [ 10, %Else ], !dbg !47
  store i32 %1, i32* %x, align 4, !dbg !47
  call void @llvm.dbg.declare(metadata i32* %x, metadata !42, metadata !DIExpression()), !dbg !48
  ret void, !dbg !49
}
```
This commit is contained in:
Andrew Kelley 2019-05-30 17:05:06 -04:00
parent 5e1003bc81
commit a4aca78722
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
5 changed files with 404 additions and 172 deletions

View File

@ -8,3 +8,21 @@ migrate all the alloca_list to alloca_gen_list
migrate ir_build_var_decl_src to use ir_build_alloca_src and explicitly initialize
inferred comptime
if (lval == LValNone) {
if (result_loc->id == ResultLocIdNone)
return value;
}
assert(lval == LValPtr);
// We needed a pointer to a value, but we got a value. So we create
// an instruction which just makes a pointer of it.
return ir_build_ref(irb, scope, value->source_node, value, false, false);
handle if with no else
handle comptime if condition
handle mixed runtime and comptime peers

View File

@ -42,6 +42,7 @@ struct Tld;
struct TldExport;
struct IrAnalyze;
struct ResultLoc;
struct ResultLocPeer;
enum X64CABIClass {
X64CABIClass_Unknown,
@ -2127,6 +2128,8 @@ struct IrBasicBlock {
const char *name_hint;
size_t debug_id;
size_t ref_count;
// index into the basic block list
size_t index;
LLVMBasicBlockRef llvm_block;
LLVMBasicBlockRef llvm_exit_block;
// The instruction that referenced this basic block and caused us to
@ -2315,10 +2318,14 @@ enum IrInstructionId {
IrInstructionIdUndeclaredIdent,
IrInstructionIdAllocaSrc,
IrInstructionIdAllocaGen,
IrInstructionIdEndExpr,
};
struct IrInstruction {
IrInstructionId id;
// true if this instruction was generated by zig and not from user code
bool is_gen;
Scope *scope;
AstNode *source_node;
ConstExprValue value;
@ -2332,8 +2339,6 @@ struct IrInstruction {
// with this child field.
IrInstruction *child;
IrBasicBlock *owner_bb;
// true if this instruction was generated by zig and not from user code
bool is_gen;
};
struct IrInstructionDeclVarSrc {
@ -3571,16 +3576,28 @@ struct IrInstructionAllocaGen {
const char *name_hint;
};
struct IrInstructionEndExpr {
IrInstruction base;
IrInstruction *value;
ResultLoc *result_loc;
LVal lval;
};
enum ResultLocId {
ResultLocIdInvalid,
ResultLocIdNone,
ResultLocIdVar,
ResultLocIdReturn,
ResultLocIdPeer,
ResultLocIdPeerParent,
};
struct ResultLoc {
ResultLocId id;
IrInstruction *source_instruction;
IrInstruction *gen_instruction;
ZigType *implicit_elem_type;
};
struct ResultLocNone {
@ -3597,6 +3614,28 @@ struct ResultLocReturn {
ResultLoc base;
};
struct ResultLocPeerParent {
ResultLoc base;
ResultLoc *parent;
ResultLocPeer *peers;
size_t peer_count;
ZigType *resolved_type;
};
struct IrSuspendPosition {
size_t basic_block_index;
size_t instruction_index;
};
struct ResultLocPeer {
ResultLoc base;
ResultLocPeerParent *parent;
IrBasicBlock *next_bb;
IrSuspendPosition suspend_pos;
};
static const size_t slice_ptr_index = 0;
static const size_t slice_len_index = 1;

View File

@ -5606,10 +5606,9 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdUndeclaredIdent:
case IrInstructionIdCallSrc:
case IrInstructionIdAllocaSrc:
zig_unreachable();
case IrInstructionIdEndExpr:
case IrInstructionIdAllocaGen:
return nullptr;
zig_unreachable();
case IrInstructionIdDeclVarGen:
return ir_render_decl_var(g, executable, (IrInstructionDeclVarGen *)instruction);

File diff suppressed because it is too large Load Diff

View File

@ -158,6 +158,16 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {
zig_unreachable();
}
static const char *ir_lval_str(LVal lval) {
switch (lval) {
case LValNone:
return "None";
case LValPtr:
return "Ptr";
}
zig_unreachable();
}
static void ir_print_un_op(IrPrint *irp, IrInstructionUnOp *un_op_instruction) {
fprintf(irp->f, "%s ", ir_un_op_id_str(un_op_instruction->op_id));
ir_print_other_instruction(irp, un_op_instruction->value);
@ -219,6 +229,12 @@ static void ir_print_result_loc(IrPrint *irp, ResultLoc *result_loc) {
return;
case ResultLocIdVar:
return ir_print_result_loc_var(irp, (ResultLocVar *)result_loc);
case ResultLocIdPeer:
fprintf(irp->f, "peer");
return;
case ResultLocIdPeerParent:
fprintf(irp->f, "peer_parent");
return;
}
zig_unreachable();
}
@ -1128,6 +1144,14 @@ static void ir_print_alloca_gen(IrPrint *irp, IrInstructionAllocaGen *instructio
fprintf(irp->f, "Alloca(align=%" PRIu32 ",name=%s)", instruction->align, instruction->name_hint);
}
static void ir_print_end_expr(IrPrint *irp, IrInstructionEndExpr *instruction) {
fprintf(irp->f, "EndExpr(result=");
ir_print_result_loc(irp, instruction->result_loc);
fprintf(irp->f, ",value=");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ",lval=%s)", ir_lval_str(instruction->lval));
}
static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
fprintf(irp->f, "inttoerr ");
ir_print_other_instruction(irp, instruction->target);
@ -2014,6 +2038,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdAllocaGen:
ir_print_alloca_gen(irp, (IrInstructionAllocaGen *)instruction);
break;
case IrInstructionIdEndExpr:
ir_print_end_expr(irp, (IrInstructionEndExpr *)instruction);
break;
}
fprintf(irp->f, "\n");
}