mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 10:31:03 +01:00
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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user