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.
This commit is contained in:
Jon Ross-Perkins
2023-06-01 14:44:57 -07:00
committed by GitHub
parent a7939ab22f
commit 4152cf720a
11 changed files with 118 additions and 15 deletions
+13 -2
View File
@@ -46,10 +46,10 @@ auto LoweringContext::Run() -> std::unique_ptr<llvm::Module> {
}
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<llvm::AllocaInst, llvm::GetElementPtrInst>(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
+4
View File
@@ -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;
+3 -3
View File
@@ -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<llvm::Value*> 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*/,
@@ -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({});
}
@@ -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);
}
+20
View File
@@ -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;
}
+4 -2
View File
@@ -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: }
+6 -3
View File
@@ -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: }
+4 -2
View File
@@ -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: }
+4 -2
View File
@@ -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: }
+2 -1
View File
@@ -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 {