Files
carbon-lang/toolchain/lower/handle_expr_category.cpp
T
Richard Smith b7f11e4c61 Propagate Carbon type alignments into LLVM IR. (#7290)
Use the Carbon-computed alignment for allocas, loads, stores, and
memcpys. Previously we used whatever LLVM felt like giving us, which
would result in ABI mismatches and runtime crashes due to misalignment
when creating objects of imported C++ class types, as well as resulting
in some surprising choices like `(i32, i32)` and `()` having 8-byte
alignment instead of 4 and 1, respectively.
2026-06-02 01:35:03 +00:00

85 lines
3.4 KiB
C++

// 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
#include "toolchain/lower/function_context.h"
#include "toolchain/sem_ir/expr_info.h"
#include "toolchain/sem_ir/file.h"
namespace Carbon::Lower {
auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
SemIR::AcquireValue inst) -> void {
auto inst_type = context.GetTypeIdOfInst(inst_id);
switch (context.GetValueRepr(inst_type).repr.kind) {
case SemIR::ValueRepr::Unknown:
CARBON_FATAL(
"Value acquisition for type with incomplete value representation");
case SemIR::ValueRepr::Dependent:
CARBON_FATAL(
"Value acquisition for type with dependent value representation");
case SemIR::ValueRepr::None:
// Nothing should use this value, but StubRef needs a value to
// propagate.
// TODO: Remove this now the StubRefs are gone.
context.SetLocal(inst_id,
llvm::PoisonValue::get(context.GetType(inst_type)));
break;
case SemIR::ValueRepr::Copy:
context.SetLocal(
inst_id,
context.LoadObject(inst_type, context.GetValue(inst.value_id)));
break;
case SemIR::ValueRepr::Pointer:
context.SetLocal(inst_id, context.GetValue(inst.value_id));
break;
case SemIR::ValueRepr::Custom:
CARBON_FATAL("TODO: Add support for AcquireValue with custom value rep");
}
}
auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
SemIR::MarkInPlaceInit inst) -> void {
context.SetLocal(inst_id, context.GetValue(inst.dest_id));
}
auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
SemIR::Temporary inst) -> void {
if (SemIR::GetExprCategory(context.sem_ir(), inst.init_id) !=
SemIR::ExprCategory::InPlaceInitializing) {
context.InitializeStorage(context.GetTypeIdOfInst(inst_id), inst.storage_id,
inst.init_id);
}
context.SetLocal(inst_id, context.GetValue(inst.storage_id));
}
auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
SemIR::TemporaryStorage /*inst*/) -> void {
context.SetLocal(
inst_id, context.CreateAlloca(context.GetTypeIdOfInst(inst_id), "temp"));
}
auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
SemIR::ValueAsRef inst) -> void {
CARBON_CHECK(SemIR::GetExprCategory(context.sem_ir(), inst.value_id) ==
SemIR::ExprCategory::Value);
auto inst_type = context.GetTypeIdOfInst(inst_id);
auto value_repr = context.GetValueRepr(inst_type);
CARBON_CHECK(value_repr.repr.kind == SemIR::ValueRepr::Pointer);
context.SetLocal(inst_id, context.GetValue(inst.value_id));
}
auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
SemIR::ValueOfInitializer inst) -> void {
CARBON_CHECK(SemIR::GetExprCategory(context.sem_ir(), inst.init_id) ==
SemIR::ExprCategory::ReprInitializing);
auto inst_type = context.GetTypeIdOfInst(inst_id);
auto value_repr = context.GetValueRepr(inst_type);
auto init_repr = context.GetInitRepr(inst_type);
CARBON_CHECK(value_repr.repr.kind == SemIR::ValueRepr::Copy);
CARBON_CHECK(init_repr.kind == SemIR::InitRepr::ByCopy);
context.SetLocal(inst_id, context.GetValue(inst.init_id));
}
} // namespace Carbon::Lower