diff --git a/toolchain/lowering/lowering_handle.cpp b/toolchain/lowering/lowering_handle.cpp index 45a0a3ce5745..694f56f700b6 100644 --- a/toolchain/lowering/lowering_handle.cpp +++ b/toolchain/lowering/lowering_handle.cpp @@ -273,15 +273,23 @@ auto LoweringHandleTupleIndex(LoweringFunctionContext& context, SemanticsNodeId node_id, SemanticsNode node) -> void { auto [tuple_node_id, index_node_id] = node.GetAsTupleIndex(); - auto* llvm_type = - context.GetType(context.semantics_ir().GetNode(tuple_node_id).type_id()); + auto* tuple_value = context.GetLocal(tuple_node_id); auto index_node = context.semantics_ir().GetNode(index_node_id); const auto index = context.semantics_ir() .GetIntegerLiteral(index_node.GetAsIntegerLiteral()) .getZExtValue(); - auto* gep = context.builder().CreateStructGEP( - llvm_type, context.GetLocal(tuple_node_id), index, "tuple.index"); - context.SetLocal(node_id, gep); + llvm::Value* value; + if (tuple_value->getType()->isPointerTy()) { + auto* llvm_type = context.GetType( + context.semantics_ir().GetNode(tuple_node_id).type_id()); + value = context.builder().CreateStructGEP(llvm_type, tuple_value, index, + "tuple.index"); + } else { + // For non pointer types such as call or return, using extract value as + // gep cannot be used. + value = context.builder().CreateExtractValue(tuple_value, index); + } + context.SetLocal(node_id, value); } auto LoweringHandleTupleValue(LoweringFunctionContext& context, diff --git a/toolchain/lowering/testdata/index/member_access.carbon b/toolchain/lowering/testdata/index/tuple_element_access.carbon similarity index 94% rename from toolchain/lowering/testdata/index/member_access.carbon rename to toolchain/lowering/testdata/index/tuple_element_access.carbon index 81c45843dd66..ede4b5cbdc81 100644 --- a/toolchain/lowering/testdata/index/member_access.carbon +++ b/toolchain/lowering/testdata/index/tuple_element_access.carbon @@ -11,8 +11,8 @@ fn Run() -> i32 { return 0; } -// CHECK:STDOUT: ; ModuleID = 'member_access.carbon' -// CHECK:STDOUT: source_filename = "member_access.carbon" +// CHECK:STDOUT: ; ModuleID = 'tuple_element_access.carbon' +// CHECK:STDOUT: source_filename = "tuple_element_access.carbon" // CHECK:STDOUT: // CHECK:STDOUT: %type = type {} // CHECK:STDOUT: diff --git a/toolchain/lowering/testdata/index/tuple_return_value_access.carbon b/toolchain/lowering/testdata/index/tuple_return_value_access.carbon new file mode 100644 index 000000000000..99d95b5dc907 --- /dev/null +++ b/toolchain/lowering/testdata/index/tuple_return_value_access.carbon @@ -0,0 +1,32 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE + +fn F() -> (i32, i32) { return (12, 24); } + +fn Run() { + var t: i32 = F()[1]; +} + +// CHECK:STDOUT: ; ModuleID = 'tuple_return_value_access.carbon' +// CHECK:STDOUT: source_filename = "tuple_return_value_access.carbon" +// CHECK:STDOUT: +// CHECK:STDOUT: define { i32, i32 } @F() { +// CHECK:STDOUT: %tuple = alloca { i32, i32 }, align 8 +// CHECK:STDOUT: %1 = getelementptr inbounds { i32, i32 }, ptr %tuple, i32 0, i32 0 +// CHECK:STDOUT: store i32 12, ptr %1, align 4 +// CHECK:STDOUT: %2 = getelementptr inbounds { i32, i32 }, ptr %tuple, i32 0, i32 1 +// CHECK:STDOUT: store i32 24, ptr %2, align 4 +// CHECK:STDOUT: %3 = load { i32, i32 }, ptr %tuple, align 4 +// CHECK:STDOUT: ret { i32, i32 } %3 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: define void @Run() { +// CHECK:STDOUT: %var = alloca i32, align 4 +// CHECK:STDOUT: %F = call { i32, i32 } @F() +// CHECK:STDOUT: %1 = extractvalue { i32, i32 } %F, 1 +// CHECK:STDOUT: store i32 %1, ptr %var, align 4 +// CHECK:STDOUT: ret void +// CHECK:STDOUT: }