Skip to content

fix union initialization of type void#2751

Closed
mikdusan wants to merge 1 commit intoziglang:copy-elision-3from
mikdusan:result-location-union-init-void
Closed

fix union initialization of type void#2751
mikdusan wants to merge 1 commit intoziglang:copy-elision-3from
mikdusan:result-location-union-init-void

Conversation

@mikdusan
Copy link
Member

reduction

const State = union(enum) {
    one: void,
    two: u32,
};

fn make1() State {
    return State{ .one = {} }; // regression: copy-elision-3
}

fn make2() State {
    return State{ .two = 99 };
}

export fn foobar() void {
    _ = make1(); 
    _ = make2();
}

const builtin = @import("builtin");
pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
    while (true) {}
}

broken IR (branch: copy-elision-3)

fn make1() { // (analyzed)
Entry_0:
    #8  | *State      | 3 | @ReturnPtr
    #9  | *void       | 0 | @UnionFieldPtr(&#8.one)
    #14 | State       | 0 | loadptr(#8)result=(null)
    #16 | State       | 0 | loadptr(#8)result=(null)
    #20 | noreturn    | - | return 
}

fn make2() { // (analyzed)
Entry_0:
    #8  | *State      | 3 | @ReturnPtr
    #9  | *u32        | 1 | @UnionFieldPtr(&#8.two)
    #13 | void        | - | *#9 = 99
    #15 | State       | 0 | loadptr(#8)result=(null)
    #17 | State       | 0 | loadptr(#8)result=(null)
    #21 | noreturn    | - | return 
}

broken LLVM-IR (branch: copy-elision-3)

; Function Attrs: nobuiltin nounwind sspstrong
define internal fastcc void @make1(%State* nonnull sret) unnamed_addr #2 !dbg !48 {
Entry:
  ret void, !dbg !60
}

; Function Attrs: nobuiltin nounwind sspstrong
define internal fastcc void @make2(%State* nonnull sret) unnamed_addr #2 !dbg !62 {
Entry:
  %1 = getelementptr inbounds %State, %State* %0, i32 0, i32 1, !dbg !63
  store i1 true, i1* %1, !dbg !63
  %2 = getelementptr inbounds %State, %State* %0, i32 0, i32 0, !dbg !63
  store i32 99, i32* %2, align 4, !dbg !63
  ret void, !dbg !65
}

patched IR

fn make1() { // (analyzed)
Entry_0:
    #8  | *State      | 3 | @ReturnPtr
    #9  | *void       | 1 | @UnionFieldPtr(&#8.one)
    #12 | void        | - | *#9 = {}
    #14 | State       | 0 | loadptr(#8)result=(null)
    #16 | State       | 0 | loadptr(#8)result=(null)
    #20 | noreturn    | - | return 
}

fn make2() { // (analyzed)
Entry_0:
    #8  | *State      | 3 | @ReturnPtr
    #9  | *u32        | 1 | @UnionFieldPtr(&#8.two)
    #13 | void        | - | *#9 = 99
    #15 | State       | 0 | loadptr(#8)result=(null)
    #17 | State       | 0 | loadptr(#8)result=(null)
    #21 | noreturn    | - | return 
}

patched LLVM-IR

; Function Attrs: nobuiltin nounwind sspstrong
define internal fastcc void @make1(%State* nonnull sret) unnamed_addr #2 !dbg !48 {
Entry:
  %1 = getelementptr inbounds %State, %State* %0, i32 0, i32 1, !dbg !60
  store i1 false, i1* %1, !dbg !60
  ret void, !dbg !62
}

; Function Attrs: nobuiltin nounwind sspstrong
define internal fastcc void @make2(%State* nonnull sret) unnamed_addr #2 !dbg !63 {
Entry:
  %1 = getelementptr inbounds %State, %State* %0, i32 0, i32 1, !dbg !64
  store i1 true, i1* %1, !dbg !64
  %2 = getelementptr inbounds %State, %State* %0, i32 0, i32 0, !dbg !64
  store i32 99, i32* %2, align 4, !dbg !64
  ret void, !dbg !66
}

reference IR (branch: master)

fn make1() { // (analyzed)
Entry_0:
    #8  | noreturn    | - | return State { .one = {}}
}

fn make2() { // (analyzed)
Entry_0:
    #9  | noreturn    | - | return State { .two = 99}
}

reference LLVM-IR (branch: master)

@0 = internal unnamed_addr constant %State { i32 undef, i1 false }, align 4
@1 = internal unnamed_addr constant %State { i32 99, i1 true }, align 4

; Function Attrs: nobuiltin nounwind sspstrong
define internal fastcc void @make1(%State* nonnull sret) unnamed_addr #2 !dbg !48 {
Entry:
  %1 = bitcast %State* %0 to i8*, !dbg !60
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %1, i8* align 4 bitcast (%State* @0 to i8*), i64 8, i1 false), !dbg !60
  ret void, !dbg !60
}

; Function Attrs: nobuiltin nounwind sspstrong
define internal fastcc void @make2(%State* nonnull sret) unnamed_addr #2 !dbg !62 {
Entry:
  %1 = bitcast %State* %0 to i8*, !dbg !63
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %1, i8* align 4 bitcast (%State* @1 to i8*), i64 8, i1 false), !dbg !63
  ret void, !dbg !63
}

@mikdusan
Copy link
Member Author

closing issue: better fix committed c61e0a0

@mikdusan mikdusan closed this Jun 25, 2019
@andrewrk
Copy link
Member

Ah, sorry, I actually hadn't seen this yet when I coded my solution.

@mikdusan mikdusan deleted the result-location-union-init-void branch November 28, 2019 00:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants