Skip to content

result location: ability to refer to the return result location before the return statement #2765

Open
@andrewrk

Description

@andrewrk

This issue is split from #287.

Now that we have result location semantics, the following code does not introduce an intermediate value with a copy:

const Point = struct {
    x: i32,
    y: i32,
};

fn foo() Point {
    return bar();
}

fn bar() Point {
    return Point{
        .x = 1,
        .y = 2,
    };
}

test "result location" {
    var point = foo();
}

Previously, the code return bar() would introduce an extra copy, so the body of the function foo would needlessly copy the point before returning it. This copying would happen at every expression, recursively when the type is an aggregate type (such as struct). Now that the result location mechanism is merged into master, you can see that the foo function does not introduce an extra copy:

define internal fastcc void @foo(%Point* nonnull sret) unnamed_addr #2 !dbg !35 {
Entry:
  call fastcc void @bar(%Point* sret %0), !dbg !44
  ret void, !dbg !46
}

However, if you capture the result in a variable and then return the variable, there is an intermediate value - the result variable - which is copied at the return statement:

fn foo() Point {
    const result = bar();
    return result;
}

Now there is a copy, because the Result Location of bar() is the result local variable, rather than the return result location:

define internal fastcc void @foo(%Point* nonnull sret) unnamed_addr #2 !dbg !35 {
Entry:
  %result = alloca %Point, align 4
  call fastcc void @bar(%Point* sret %result), !dbg !47
  call void @llvm.dbg.declare(metadata %Point* %result, metadata !45, metadata !DIExpression()), !dbg !48
  %1 = bitcast %Point* %result to i8*, !dbg !49
  %2 = bitcast %Point* %0 to i8*, !dbg !49
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %2, i8* align 4 %1, i64 8, i1 false), !dbg !49
  ret void, !dbg !50
}

This issue is to make it so that there is a way to refer to the result location, and even call methods on it, before returning it, all without introducing an intermediate value.

For the issue about getting rid of intermediate values when optionals and error unions are involved, see #2761.

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions