From 4152cf720a6b4c0ead2bfdc1bb2c9e84af2a4174 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Thu, 1 Jun 2023 14:44:57 -0700 Subject: [PATCH] Add loads for data. (#2860) Start inserting loads when getting a value. This is done conditionally, but in theory we could start tracking nodes which need loading differently if the `isa` is considered cumbersome. --- toolchain/lowering/lowering_context.cpp | 15 ++++++++-- toolchain/lowering/lowering_context.h | 4 +++ toolchain/lowering/lowering_handle.cpp | 6 ++-- .../function/call/empty_struct.carbon | 30 +++++++++++++++++++ .../testdata/function/call/var_param.carbon | 28 +++++++++++++++++ toolchain/lowering/testdata/return/var.carbon | 20 +++++++++++++ .../lowering/testdata/struct/empty.carbon | 6 ++-- .../testdata/struct/member_access.carbon | 9 ++++-- .../lowering/testdata/struct/one_entry.carbon | 6 ++-- .../testdata/struct/two_entries.carbon | 6 ++-- toolchain/lowering/testdata/var/local.carbon | 3 +- 11 files changed, 118 insertions(+), 15 deletions(-) create mode 100644 toolchain/lowering/testdata/function/call/empty_struct.carbon create mode 100644 toolchain/lowering/testdata/function/call/var_param.carbon create mode 100644 toolchain/lowering/testdata/return/var.carbon diff --git a/toolchain/lowering/lowering_context.cpp b/toolchain/lowering/lowering_context.cpp index ed56d117a8dd..d13799eadab9 100644 --- a/toolchain/lowering/lowering_context.cpp +++ b/toolchain/lowering/lowering_context.cpp @@ -46,10 +46,10 @@ auto LoweringContext::Run() -> std::unique_ptr { } auto LoweringContext::LowerBlock(SemanticsNodeBlockId block_id) -> void { - CARBON_VLOG() << "Lowering block " << block_id << "\n"; + CARBON_VLOG() << "Lowering " << block_id << "\n"; for (const auto& node_id : semantics_ir_->GetNodeBlock(block_id)) { auto node = semantics_ir_->GetNode(node_id); - CARBON_VLOG() << "Lowering node" << node_id << ": " << node << "\n"; + CARBON_VLOG() << "Lowering " << node_id << ": " << node << "\n"; switch (node.kind()) { #define CARBON_SEMANTICS_NODE_KIND(Name) \ case SemanticsNodeKind::Name: \ @@ -102,4 +102,15 @@ auto LoweringContext::BuildType(SemanticsNodeId node_id) -> llvm::Type* { } } +auto LoweringContext::GetNodeLoaded(SemanticsNodeId node_id) -> llvm::Value* { + auto* value = GetNode(node_id); + if (llvm::isa(value)) { + auto* load_type = GetType(semantics_ir().GetNode(node_id).type_id()); + return builder().CreateLoad(load_type, value); + } else { + // No load is needed. + return value; + } +} + } // namespace Carbon diff --git a/toolchain/lowering/lowering_context.h b/toolchain/lowering/lowering_context.h index ebd987f5dd2d..3906c70262ec 100644 --- a/toolchain/lowering/lowering_context.h +++ b/toolchain/lowering/lowering_context.h @@ -31,6 +31,10 @@ class LoweringContext { return nodes_[node_id.index]; } + // Returns a value for the given node in loaded state. Loads will only be + // inserted on an as-needed basis. + auto GetNodeLoaded(SemanticsNodeId node_id) -> llvm::Value*; + // Sets the value for the given node. auto SetNode(SemanticsNodeId node_id, llvm::Value* value) { CARBON_CHECK(!nodes_[node_id.index]) << node_id; diff --git a/toolchain/lowering/lowering_handle.cpp b/toolchain/lowering/lowering_handle.cpp index b1edb195ed39..a1d0bfcbd8e4 100644 --- a/toolchain/lowering/lowering_handle.cpp +++ b/toolchain/lowering/lowering_handle.cpp @@ -21,7 +21,7 @@ auto LoweringHandleCrossReference(LoweringContext& /*context*/, auto LoweringHandleAssign(LoweringContext& context, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { auto [storage_id, value_id] = node.GetAsAssign(); - context.builder().CreateStore(context.GetNode(value_id), + context.builder().CreateStore(context.GetNodeLoaded(value_id), context.GetNode(storage_id)); } @@ -49,7 +49,7 @@ auto LoweringHandleCall(LoweringContext& context, SemanticsNodeId node_id, auto* function = context.GetCallable(callable_id); std::vector args; for (auto ref_id : context.semantics_ir().GetNodeBlock(refs_id)) { - args.push_back(context.GetNode(ref_id)); + args.push_back(context.GetNodeLoaded(ref_id)); } auto* value = context.builder().CreateCall(function, args, function->getName()); @@ -147,7 +147,7 @@ auto LoweringHandleReturnExpression(LoweringContext& context, SemanticsNodeId /*node_id*/, SemanticsNode node) -> void { SemanticsNodeId expr_id = node.GetAsReturnExpression(); - context.builder().CreateRet(context.GetNode(expr_id)); + context.builder().CreateRet(context.GetNodeLoaded(expr_id)); } auto LoweringHandleStringLiteral(LoweringContext& /*context*/, diff --git a/toolchain/lowering/testdata/function/call/empty_struct.carbon b/toolchain/lowering/testdata/function/call/empty_struct.carbon new file mode 100644 index 000000000000..68acfe1cf623 --- /dev/null +++ b/toolchain/lowering/testdata/function/call/empty_struct.carbon @@ -0,0 +1,30 @@ +// 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 +// CHECK:STDOUT: ; ModuleID = 'empty_struct.carbon' +// CHECK:STDOUT: source_filename = "empty_struct.carbon" +// CHECK:STDOUT: +// CHECK:STDOUT: %EmptyTupleType = type {} +// CHECK:STDOUT: %StructLiteralType = type {} +// CHECK:STDOUT: +// CHECK:STDOUT: define %EmptyTupleType @Echo(%StructLiteralType %a) { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: define %EmptyTupleType @Main() { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %StructLiteralValue = alloca %StructLiteralType, align 8 +// CHECK:STDOUT: %0 = load %StructLiteralType, ptr %StructLiteralValue, align 1 +// CHECK:STDOUT: %Echo = call %EmptyTupleType @Echo(%StructLiteralType %0) +// CHECK:STDOUT: } + +fn Echo(a: {}) { + // TODO: Set return type to `{}` and return `a` back. +} + +fn Main() { + // TODO: Store the returned `{}`. + Echo({}); +} diff --git a/toolchain/lowering/testdata/function/call/var_param.carbon b/toolchain/lowering/testdata/function/call/var_param.carbon new file mode 100644 index 000000000000..8b7ca9353656 --- /dev/null +++ b/toolchain/lowering/testdata/function/call/var_param.carbon @@ -0,0 +1,28 @@ +// 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 +// CHECK:STDOUT: ; ModuleID = 'var_param.carbon' +// CHECK:STDOUT: source_filename = "var_param.carbon" +// CHECK:STDOUT: +// CHECK:STDOUT: %EmptyTupleType = type {} +// CHECK:STDOUT: +// CHECK:STDOUT: define %EmptyTupleType @DoNothing(i32 %a) { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: define %EmptyTupleType @Main() { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %var = alloca i32, align 4 +// CHECK:STDOUT: store i32 0, ptr %var, align 4 +// CHECK:STDOUT: %0 = load i32, ptr %var, align 4 +// CHECK:STDOUT: %DoNothing = call %EmptyTupleType @DoNothing(i32 %0) +// CHECK:STDOUT: } + +fn DoNothing(a: i32) {} + +fn Main() { + var a: i32 = 0; + DoNothing(a); +} diff --git a/toolchain/lowering/testdata/return/var.carbon b/toolchain/lowering/testdata/return/var.carbon new file mode 100644 index 000000000000..05606674dbaa --- /dev/null +++ b/toolchain/lowering/testdata/return/var.carbon @@ -0,0 +1,20 @@ +// 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 +// CHECK:STDOUT: ; ModuleID = 'var.carbon' +// CHECK:STDOUT: source_filename = "var.carbon" +// CHECK:STDOUT: +// CHECK:STDOUT: define i32 @Main() { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %var = alloca i32, align 4 +// CHECK:STDOUT: store i32 0, ptr %var, align 4 +// CHECK:STDOUT: %0 = load i32, ptr %var, align 4 +// CHECK:STDOUT: ret i32 %0 +// CHECK:STDOUT: } + +fn Main() -> i32 { + var x: i32 = 0; + return x; +} diff --git a/toolchain/lowering/testdata/struct/empty.carbon b/toolchain/lowering/testdata/struct/empty.carbon index 418253f5f296..bef9a7ad3512 100644 --- a/toolchain/lowering/testdata/struct/empty.carbon +++ b/toolchain/lowering/testdata/struct/empty.carbon @@ -13,10 +13,12 @@ // CHECK:STDOUT: %StructLiteralValue = alloca %StructLiteralType, align 8 // CHECK:STDOUT: %var = alloca %StructLiteralType, align 8 // CHECK:STDOUT: %StructLiteralValue1 = alloca %StructLiteralType, align 8 -// CHECK:STDOUT: store ptr %StructLiteralValue1, ptr %var, align 8 +// CHECK:STDOUT: %0 = load %StructLiteralType, ptr %StructLiteralValue1, align 1 +// CHECK:STDOUT: store %StructLiteralType %0, ptr %var, align 1 // CHECK:STDOUT: %StructLiteralValue2 = alloca %StructLiteralType, align 8 // CHECK:STDOUT: %var3 = alloca %StructLiteralType, align 8 -// CHECK:STDOUT: store ptr %var, ptr %var3, align 8 +// CHECK:STDOUT: %1 = load %StructLiteralType, ptr %var, align 1 +// CHECK:STDOUT: store %StructLiteralType %1, ptr %var3, align 1 // CHECK:STDOUT: ret i32 0 // CHECK:STDOUT: } diff --git a/toolchain/lowering/testdata/struct/member_access.carbon b/toolchain/lowering/testdata/struct/member_access.carbon index 5527b171f45b..353a391023be 100644 --- a/toolchain/lowering/testdata/struct/member_access.carbon +++ b/toolchain/lowering/testdata/struct/member_access.carbon @@ -16,12 +16,15 @@ // CHECK:STDOUT: store double 0.000000e+00, ptr %a, align 8 // CHECK:STDOUT: %b = getelementptr inbounds %StructLiteralType, ptr %StructLiteralValue, i32 0, i32 1 // CHECK:STDOUT: store i32 1, ptr %b, align 4 -// CHECK:STDOUT: store ptr %StructLiteralValue, ptr %var, align 8 +// CHECK:STDOUT: %0 = load %StructLiteralType, ptr %StructLiteralValue, align 8 +// CHECK:STDOUT: store %StructLiteralType %0, ptr %var, align 8 // CHECK:STDOUT: %var1 = alloca i32, align 4 // CHECK:STDOUT: %b2 = getelementptr inbounds %StructLiteralType, ptr %var, i32 0, i32 1 -// CHECK:STDOUT: store ptr %b2, ptr %var1, align 8 +// CHECK:STDOUT: %1 = load i32, ptr %b2, align 4 +// CHECK:STDOUT: store i32 %1, ptr %var1, align 4 // CHECK:STDOUT: %var3 = alloca i32, align 4 -// CHECK:STDOUT: store ptr %var1, ptr %var3, align 8 +// CHECK:STDOUT: %2 = load i32, ptr %var1, align 4 +// CHECK:STDOUT: store i32 %2, ptr %var3, align 4 // CHECK:STDOUT: ret i32 0 // CHECK:STDOUT: } diff --git a/toolchain/lowering/testdata/struct/one_entry.carbon b/toolchain/lowering/testdata/struct/one_entry.carbon index a41f45e8c68c..e0c5541ed9c8 100644 --- a/toolchain/lowering/testdata/struct/one_entry.carbon +++ b/toolchain/lowering/testdata/struct/one_entry.carbon @@ -14,9 +14,11 @@ // CHECK:STDOUT: %StructLiteralValue = alloca %StructLiteralType, align 8 // CHECK:STDOUT: %a = getelementptr inbounds %StructLiteralType, ptr %StructLiteralValue, i32 0, i32 0 // CHECK:STDOUT: store i32 4, ptr %a, align 4 -// CHECK:STDOUT: store ptr %StructLiteralValue, ptr %var, align 8 +// CHECK:STDOUT: %0 = load %StructLiteralType, ptr %StructLiteralValue, align 4 +// CHECK:STDOUT: store %StructLiteralType %0, ptr %var, align 4 // CHECK:STDOUT: %var1 = alloca %StructLiteralType, align 8 -// CHECK:STDOUT: store ptr %var, ptr %var1, align 8 +// CHECK:STDOUT: %1 = load %StructLiteralType, ptr %var, align 4 +// CHECK:STDOUT: store %StructLiteralType %1, ptr %var1, align 4 // CHECK:STDOUT: ret i32 0 // CHECK:STDOUT: } diff --git a/toolchain/lowering/testdata/struct/two_entries.carbon b/toolchain/lowering/testdata/struct/two_entries.carbon index b09214aa9d61..46087677bafa 100644 --- a/toolchain/lowering/testdata/struct/two_entries.carbon +++ b/toolchain/lowering/testdata/struct/two_entries.carbon @@ -16,9 +16,11 @@ // CHECK:STDOUT: store i32 1, ptr %a, align 4 // CHECK:STDOUT: %b = getelementptr inbounds %StructLiteralType, ptr %StructLiteralValue, i32 0, i32 1 // CHECK:STDOUT: store i32 2, ptr %b, align 4 -// CHECK:STDOUT: store ptr %StructLiteralValue, ptr %var, align 8 +// CHECK:STDOUT: %0 = load %StructLiteralType, ptr %StructLiteralValue, align 4 +// CHECK:STDOUT: store %StructLiteralType %0, ptr %var, align 4 // CHECK:STDOUT: %var1 = alloca %StructLiteralType, align 8 -// CHECK:STDOUT: store ptr %var, ptr %var1, align 8 +// CHECK:STDOUT: %1 = load %StructLiteralType, ptr %var, align 4 +// CHECK:STDOUT: store %StructLiteralType %1, ptr %var1, align 4 // CHECK:STDOUT: ret i32 0 // CHECK:STDOUT: } diff --git a/toolchain/lowering/testdata/var/local.carbon b/toolchain/lowering/testdata/var/local.carbon index 02dc19504671..f98b51ab6d3a 100644 --- a/toolchain/lowering/testdata/var/local.carbon +++ b/toolchain/lowering/testdata/var/local.carbon @@ -10,7 +10,8 @@ // CHECK:STDOUT: entry: // CHECK:STDOUT: %var = alloca i32, align 4 // CHECK:STDOUT: store i32 1, ptr %var, align 4 -// CHECK:STDOUT: ret ptr %var +// CHECK:STDOUT: %0 = load i32, ptr %var, align 4 +// CHECK:STDOUT: ret i32 %0 // CHECK:STDOUT: } fn Run() -> i32 {