C backend: fix ptrtoint and wrap_errunion_err

This commit is contained in:
Andrew Kelley 2021-10-28 17:05:17 -07:00
parent 9ed955e5ca
commit c59ee3157f
4 changed files with 45 additions and 24 deletions

View File

@ -1117,9 +1117,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
.float_to_int,
.fptrunc,
.fpext,
.ptrtoint,
=> try airSimpleCast(f, inst),
.ptrtoint => try airPtrToInt(f, inst),
.atomic_store_unordered => try airAtomicStore(f, inst, toMemoryOrder(.Unordered)),
.atomic_store_monotonic => try airAtomicStore(f, inst, toMemoryOrder(.Monotonic)),
.atomic_store_release => try airAtomicStore(f, inst, toMemoryOrder(.Release)),
@ -2264,15 +2265,18 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
return local;
}
fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.liveness.isUnused(inst))
return CValue.none;
if (f.liveness.isUnused(inst)) return CValue.none;
const writer = f.object.writer();
const ty_op = f.air.instructions.items(.data)[inst].ty_op;
const operand = try f.resolveInst(ty_op.operand);
const err_un_ty = f.air.typeOfIndex(inst);
const payload_ty = err_un_ty.errorUnionPayload();
if (!payload_ty.hasCodeGenBits()) {
return operand;
}
const inst_ty = f.air.typeOfIndex(inst);
const local = try f.allocLocal(inst_ty, .Const);
const local = try f.allocLocal(err_un_ty, .Const);
try writer.writeAll(" = { .error = ");
try f.writeCValue(writer, operand);
try writer.writeAll(" };\n");
@ -2343,8 +2347,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
/// Emits a local variable with the result type and initializes it
/// with the operand.
fn airSimpleCast(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.liveness.isUnused(inst))
return CValue.none;
if (f.liveness.isUnused(inst)) return CValue.none;
const inst_ty = f.air.typeOfIndex(inst);
const local = try f.allocLocal(inst_ty, .Const);
@ -2358,6 +2361,21 @@ fn airSimpleCast(f: *Function, inst: Air.Inst.Index) !CValue {
return local;
}
fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {
if (f.liveness.isUnused(inst)) return CValue.none;
const inst_ty = f.air.typeOfIndex(inst);
const local = try f.allocLocal(inst_ty, .Const);
const un_op = f.air.instructions.items(.data)[inst].un_op;
const writer = f.object.writer();
const operand = try f.resolveInst(un_op);
try writer.writeAll(" = ");
try f.writeCValue(writer, operand);
try writer.writeAll(";\n");
return local;
}
fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !CValue {
if (f.liveness.isUnused(inst)) return CValue.none;

View File

@ -2,7 +2,7 @@ const builtin = @import("builtin");
test {
// Tests that pass for stage1, stage2, and the C backend.
{}
_ = @import("behavior/if.zig");
if (builtin.object_format != .c) {
// Tests that pass for stage1 and stage2 but not the C backend.
@ -43,7 +43,7 @@ test {
_ = @import("behavior/generics.zig");
_ = @import("behavior/hasdecl.zig");
_ = @import("behavior/hasfield.zig");
_ = @import("behavior/if.zig");
_ = @import("behavior/if_llvm.zig");
_ = @import("behavior/math.zig");
_ = @import("behavior/maximum_minimum.zig");
_ = @import("behavior/member_func.zig");

View File

@ -73,18 +73,3 @@ test "const result loc, runtime if cond, else unreachable" {
const x = if (t) Num.Two else unreachable;
try expect(x == .Two);
}
test "if copies its payload" {
const S = struct {
fn doTheTest() !void {
var tmp: ?i32 = 10;
if (tmp) |value| {
// Modify the original variable
tmp = null;
try expect(value == 10);
} else unreachable;
}
};
try S.doTheTest();
comptime try S.doTheTest();
}

18
test/behavior/if_llvm.zig Normal file
View File

@ -0,0 +1,18 @@
const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
test "if copies its payload" {
const S = struct {
fn doTheTest() !void {
var tmp: ?i32 = 10;
if (tmp) |value| {
// Modify the original variable
tmp = null;
try expect(value == 10);
} else unreachable;
}
};
try S.doTheTest();
comptime try S.doTheTest();
}