mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 19:30:12 +01:00
Support pass-by-move when calling a C++ function taking by value. (#7135)
Previously, we picked a single Carbon parameter pattern for each C++ parameter pattern. This doesn't work well in cases where the Carbon semantics and the C++ semantics are not perfectly aligned. In particular, when a parameter is passed by value in C++, that might mean either pass-by-move (which in Carbon would best be modeled by a `var` pattern, as no other form of parameter would perform a move) or pass-by-copy (which in Carbon would best be modeled by a value parameter, as a `var` parameter would force an extra copy). After this change, we compute a passing mode for each parameter based on the implicit conversion sequence from the argument to the parameter as determined by C++ overload resolution, and use that to determine the Carbon pattern corresponding to each C++ parameter. This results in potentially generating multiple different thunks for the same C++ function if it's called in different ways, but we already did that to handle default arguments and list-initialization. The passing modes are included in the thunk mangling. Add a new value store for clang decl signatures, which capture the information about parameter passing mode as well as the other existing information about different ways that a C++ function might be imported to Carbon. Most of the rules for computing passing modes are the same as before: const references use pass by value, non-const lvalue references use pass-by-ref, non-const rvalue references use pass-by-var. But for C++ non-reference parameters, pick between pass-by-value and pass-by-var based on whether the implicit conversion sequence was effectively performing a copy. Prefer pass-by-value if either would work and they'd do the same thing. We still use pass-by-value for const references, even when the argument is an lvalue and we could pass a reference; we may want to change this in future. For virtual functions, we try to pick a worst-case passing mode, as we can only pick a single signature for what goes in the vtable. Calls to virtual functions will still use a thunk to C++, allowing variance in the calling convention at call sites. We don't allow variance in the overriders as we don't implement support for thunks for virtual functions yet. We currently use pass-by-value for const reference parameters here, but that should probably change at some point. Assisted-by: Gemini via Antigravity
This commit is contained in:
@@ -357,6 +357,9 @@ class Context {
|
||||
auto clang_decls() -> SemIR::ClangDeclStore& {
|
||||
return sem_ir().clang_decls();
|
||||
}
|
||||
auto clang_decl_signatures() -> SemIR::ClangDeclSignatureStore& {
|
||||
return sem_ir().clang_decl_signatures();
|
||||
}
|
||||
auto names() -> SemIR::NameStoreWrapper { return sem_ir().names(); }
|
||||
auto name_scopes() -> SemIR::NameScopeStore& {
|
||||
return sem_ir().name_scopes();
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace {
|
||||
struct DeclInfo {
|
||||
// If null, no C++ decl was found and no witness can be created.
|
||||
clang::NamedDecl* decl = nullptr;
|
||||
SemIR::ClangDeclKey::Signature signature;
|
||||
SemIR::ClangDeclSignatureId signature_id;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@@ -98,7 +98,7 @@ static auto GetFunctionId(Context& context, SemIR::LocId loc_id,
|
||||
}
|
||||
|
||||
auto fn_id =
|
||||
ImportCppFunctionDecl(context, loc_id, cpp_fn, decl_info.signature);
|
||||
ImportCppFunctionDecl(context, loc_id, cpp_fn, decl_info.signature_id);
|
||||
if (fn_id == SemIR::ErrorInst::InstId) {
|
||||
return SemIR::ErrorInst::InstId;
|
||||
}
|
||||
@@ -109,6 +109,18 @@ static auto GetFunctionId(Context& context, SemIR::LocId loc_id,
|
||||
return fn_id;
|
||||
}
|
||||
|
||||
// Creates a signature with `Normal` kind and the given parameter passing
|
||||
// modes, and adds it to the value store.
|
||||
static auto MakeSignature(
|
||||
Context& context,
|
||||
std::initializer_list<SemIR::ClangDeclSignature::PassingMode> modes,
|
||||
SemIR::ClangDeclSignature::PassingMode self_passing_mode =
|
||||
SemIR::ClangDeclSignature::PassingMode::ByRef)
|
||||
-> SemIR::ClangDeclSignatureId {
|
||||
return context.clang_decl_signatures().Add(SemIR::ClangDeclSignature::Make(
|
||||
modes, SemIR::ClangDeclSignature::Normal, self_passing_mode));
|
||||
}
|
||||
|
||||
static auto BuildCopyWitness(
|
||||
Context& context, SemIR::LocId loc_id,
|
||||
SemIR::ConstantId query_self_const_id,
|
||||
@@ -131,9 +143,12 @@ static auto BuildCopyWitness(
|
||||
})) {
|
||||
return SemIR::ErrorInst::InstId;
|
||||
}
|
||||
|
||||
SemIR::ClangDeclSignatureId signature_id = MakeSignature(
|
||||
context, {SemIR::ClangDeclSignature::PassingMode::ByValue});
|
||||
auto decl_info = DeclInfo{.decl = clang_sema.LookupCopyingConstructor(
|
||||
class_decl, clang::Qualifiers::Const),
|
||||
.signature = {.num_params = 1}};
|
||||
.signature_id = signature_id};
|
||||
auto fn_id = GetFunctionId(context, loc_id, decl_info);
|
||||
if (fn_id == SemIR::ErrorInst::InstId || fn_id == SemIR::InstId::None) {
|
||||
return fn_id;
|
||||
@@ -168,8 +183,14 @@ static auto BuildCppUnsafeDerefWitness(
|
||||
context.TODO(loc_id, "operator* overload sets not implemented yet");
|
||||
return SemIR::ErrorInst::InstId;
|
||||
}
|
||||
|
||||
// TODO: Parameterize the interface by the form of the operand and compute the
|
||||
// appropriate passing mode here.
|
||||
SemIR::ClangDeclSignatureId signature_id =
|
||||
MakeSignature(context, {}, SemIR::ClangDeclSignature::PassingMode::ByRef);
|
||||
|
||||
auto decl_info =
|
||||
DeclInfo{.decl = *candidates.begin(), .signature = {.num_params = 0}};
|
||||
DeclInfo{.decl = *candidates.begin(), .signature_id = signature_id};
|
||||
auto fn_id = GetFunctionId(context, loc_id, decl_info);
|
||||
if (fn_id == SemIR::ErrorInst::InstId || fn_id == SemIR::InstId::None) {
|
||||
return fn_id;
|
||||
@@ -204,9 +225,11 @@ static auto BuildDefaultWitness(
|
||||
// That happens if class_decl->hasUninitializedExplicitInitFields() is true.
|
||||
//
|
||||
// TODO: Consider treating such types as not implementing `Default`.
|
||||
SemIR::ClangDeclSignatureId signature_id = MakeSignature(context, {});
|
||||
|
||||
auto decl_info =
|
||||
DeclInfo{.decl = clang_sema.LookupDefaultConstructor(class_decl),
|
||||
.signature = {.num_params = 0}};
|
||||
.signature_id = signature_id};
|
||||
auto fn_id = GetFunctionId(context, loc_id, decl_info);
|
||||
if (fn_id == SemIR::ErrorInst::InstId || fn_id == SemIR::InstId::None) {
|
||||
return fn_id;
|
||||
@@ -227,8 +250,10 @@ static auto BuildDestroyWitness(
|
||||
if (!class_decl) {
|
||||
return SemIR::InstId::None;
|
||||
}
|
||||
SemIR::ClangDeclSignatureId signature_id = MakeSignature(context, {});
|
||||
|
||||
auto decl_info = DeclInfo{.decl = clang_sema.LookupDestructor(class_decl),
|
||||
.signature = {.num_params = 0}};
|
||||
.signature_id = signature_id};
|
||||
auto fn_id = GetFunctionId(context, loc_id, decl_info);
|
||||
if (fn_id == SemIR::ErrorInst::InstId || fn_id == SemIR::InstId::None) {
|
||||
return fn_id;
|
||||
@@ -375,8 +400,8 @@ static auto LookupCppMethod(
|
||||
|
||||
auto decl_info = DeclInfo{
|
||||
.decl = *lookup_info.begin(),
|
||||
.signature = {.num_params = 0},
|
||||
};
|
||||
.signature_id = MakeSignature(
|
||||
context, {}, SemIR::ClangDeclSignature::PassingMode::ByValue)};
|
||||
return GetFunctionId(context, loc_id, decl_info);
|
||||
}
|
||||
|
||||
|
||||
+145
-63
@@ -70,6 +70,12 @@
|
||||
|
||||
namespace Carbon::Check {
|
||||
|
||||
auto IsObjectMemberFunction(const clang::FunctionDecl& decl) -> bool {
|
||||
const auto* method = dyn_cast<clang::CXXMethodDecl>(&decl);
|
||||
return method && !method->isStatic() &&
|
||||
!isa<clang::CXXConstructorDecl>(&decl);
|
||||
}
|
||||
|
||||
// Adds the name to the scope with the given `access_kind` and `inst_id`.
|
||||
// `inst_id` must have a value.
|
||||
static auto AddNameToScope(Context& context, SemIR::NameScopeId scope_id,
|
||||
@@ -504,6 +510,7 @@ static auto ImportNamespaceDecl(Context& context,
|
||||
clang::NamespaceDecl* clang_decl)
|
||||
-> SemIR::InstId {
|
||||
auto key = SemIR::ClangDeclKey(clang_decl);
|
||||
|
||||
// Check if the declaration is already mapped.
|
||||
if (SemIR::InstId existing_inst_id = LookupClangDeclInstId(context, key);
|
||||
existing_inst_id.has_value()) {
|
||||
@@ -833,6 +840,75 @@ static auto ImportClassObjectRepr(Context& context, SemIR::ClassId class_id,
|
||||
.layout_id = context.custom_layouts().Add(layout)}));
|
||||
}
|
||||
|
||||
// Returns the passing mode to use for a given virtual function's object
|
||||
// parameter.
|
||||
static auto GetVirtualFunctionSelfPassingMode(
|
||||
const clang::CXXMethodDecl* method_decl)
|
||||
-> SemIR::ClangDeclSignature::PassingMode {
|
||||
if (method_decl->getMethodQualifiers().hasConst()) {
|
||||
// Map these signatures to pass-by-value:
|
||||
//
|
||||
// virtual void f() const;
|
||||
// virtual void f() const&;
|
||||
// virtual void f() const&&;
|
||||
//
|
||||
// In each case, we expect `self` to not be modified.
|
||||
return SemIR::ClangDeclSignature::PassingMode::ByValue;
|
||||
}
|
||||
|
||||
// Map anything else to pass-by-reference. This includes `&&`-qualified
|
||||
// functions, which we can't map to pass-by-var since that would perform a
|
||||
// slicing copy at the call site, which would be disastrous for a virtual
|
||||
// function call.
|
||||
// TODO: Find a better way to handle such cases, perhaps with a library type
|
||||
// representing a `&&` parameter.
|
||||
return SemIR::ClangDeclSignature::PassingMode::ByRef;
|
||||
}
|
||||
|
||||
// Returns the passing mode to use for a virtual function parameter of the given
|
||||
// type.
|
||||
static auto GetVirtualFunctionParamPassingMode(clang::QualType type)
|
||||
-> SemIR::ClangDeclSignature::PassingMode {
|
||||
if (type->isReferenceType() &&
|
||||
type.getNonReferenceType().isConstQualified()) {
|
||||
// For `const &`, `const &&`, use pass by value.
|
||||
return SemIR::ClangDeclSignature::PassingMode::ByValue;
|
||||
}
|
||||
|
||||
if (type->isLValueReferenceType()) {
|
||||
// For non-const `&`, use pass by reference.
|
||||
return SemIR::ClangDeclSignature::PassingMode::ByRef;
|
||||
}
|
||||
|
||||
// Map everything else to pass by var. That's the closest match we have to C++
|
||||
// parameter semantics, and is necessary to support parameters that are passed
|
||||
// by move.
|
||||
return SemIR::ClangDeclSignature::PassingMode::ByVar;
|
||||
}
|
||||
|
||||
// Computes the signature to use for the given imported virtual function. Unlike
|
||||
// with regular imported functions, we can only use a single signature here, so
|
||||
// we pick one conservatively.
|
||||
static auto MakeVirtualFunctionSignature(
|
||||
Context& context, const clang::CXXMethodDecl* method_decl)
|
||||
-> SemIR::ClangDeclSignatureId {
|
||||
SemIR::ClangDeclSignature signature = {
|
||||
.kind = SemIR::ClangDeclSignature::Normal,
|
||||
// Include all parameters. Virtual calls do not support using default
|
||||
// arguments.
|
||||
.num_params = static_cast<int32_t>(method_decl->getNumNonObjectParams()),
|
||||
.self_passing_mode = GetVirtualFunctionSelfPassingMode(method_decl),
|
||||
};
|
||||
signature.passing_modes.reserve(signature.num_params);
|
||||
for (auto i : llvm::seq(signature.num_params)) {
|
||||
const auto* param = method_decl->getNonObjectParameter(i);
|
||||
signature.passing_modes.push_back(
|
||||
GetVirtualFunctionParamPassingMode(param->getType()));
|
||||
}
|
||||
|
||||
return context.clang_decl_signatures().Add(signature);
|
||||
}
|
||||
|
||||
// Creates a Carbon class definition based on the information in the given Clang
|
||||
// class declaration, which is assumed to be for a class definition.
|
||||
static auto BuildClassDefinition(Context& context,
|
||||
@@ -879,7 +955,7 @@ static auto BuildClassDefinition(Context& context,
|
||||
vtable.push_back(ImportCppFunctionDecl(
|
||||
context, SemIR::LocId(import_ir_inst_id),
|
||||
const_cast<clang::CXXMethodDecl*>(method_decl),
|
||||
{.num_params = static_cast<int32_t>(method_decl->getNumParams())}));
|
||||
MakeVirtualFunctionSignature(context, method_decl)));
|
||||
}
|
||||
vtable.truncate(num_components);
|
||||
auto vtable_id = context.vtables().Add(
|
||||
@@ -1304,47 +1380,38 @@ struct ParameterTypeInfo {
|
||||
};
|
||||
} // namespace
|
||||
|
||||
// Maps a C++ parameter passing mode to a Carbon pattern kind.
|
||||
static auto GetParamPatternKindForPassingMode(
|
||||
SemIR::ClangDeclSignature::PassingMode mode) -> ParamPatternKind {
|
||||
switch (mode) {
|
||||
case SemIR::ClangDeclSignature::PassingMode::ByValue:
|
||||
return ParamPatternKind::Value;
|
||||
case SemIR::ClangDeclSignature::PassingMode::ByVar:
|
||||
return ParamPatternKind::Var;
|
||||
case SemIR::ClangDeclSignature::PassingMode::ByRef:
|
||||
return ParamPatternKind::Ref;
|
||||
}
|
||||
}
|
||||
|
||||
// Given the type of a C++ function parameter, returns information about the
|
||||
// type to use for the corresponding Carbon parameter.
|
||||
//
|
||||
// Note that if the parameter has a type for which `IsSimpleAbiType` returns
|
||||
// true, we must produce a parameter type that has the same calling convention
|
||||
// as the C++ type.
|
||||
static auto MapParameterType(Context& context, SemIR::LocId loc_id,
|
||||
clang::QualType param_type) -> ParameterTypeInfo {
|
||||
ParameterTypeInfo info = {.type = TypeExpr::None,
|
||||
.kind = ParamPatternKind::Value};
|
||||
|
||||
// Perform some custom mapping for parameters of reference type:
|
||||
//
|
||||
// * `T& x` -> `ref x: T`.
|
||||
// * `T&& x` -> `var x: T`.
|
||||
// * `const T& x` -> `x: T`.
|
||||
// * `const T&& x` -> `x: T`.
|
||||
static auto MapParameterType(
|
||||
Context& context, SemIR::LocId loc_id, clang::QualType param_type,
|
||||
SemIR::ClangDeclSignature::PassingMode passing_mode) -> ParameterTypeInfo {
|
||||
if (param_type->isReferenceType()) {
|
||||
clang::QualType pointee_type = param_type->getPointeeType();
|
||||
if (pointee_type.isConstQualified()) {
|
||||
// TODO: Consider only doing this if `const` is the only qualifier. For
|
||||
// now, any other qualifier will fail when mapping the type.
|
||||
auto split_type = pointee_type.getSplitUnqualifiedType();
|
||||
split_type.Quals.removeConst();
|
||||
pointee_type = context.ast_context().getQualifiedType(split_type);
|
||||
} else if (param_type->isLValueReferenceType()) {
|
||||
// Lvalue references map to a `ref` pattern.
|
||||
info.kind = ParamPatternKind::Ref;
|
||||
} else {
|
||||
// Rvalue references map to a `var` pattern. When given a value expression
|
||||
// as an argument, this will result in a copy. However, if the argument is
|
||||
// of class type, we will map its type to `const T`, which means overload
|
||||
// resolution won't allow the call anyway, so this only permits passing
|
||||
// value expressions of non-class type to a `T&&` parameter.
|
||||
info.kind = ParamPatternKind::Var;
|
||||
}
|
||||
param_type = pointee_type;
|
||||
// TODO: For now, we only remove `const`; any other qualifier will fail when
|
||||
// mapping the type.
|
||||
auto split_type =
|
||||
param_type.getNonReferenceType().getSplitUnqualifiedType();
|
||||
split_type.Quals.removeConst();
|
||||
param_type = context.ast_context().getQualifiedType(split_type);
|
||||
}
|
||||
|
||||
info.type = MapType(context, loc_id, param_type);
|
||||
return info;
|
||||
return {.type = MapType(context, loc_id, param_type),
|
||||
.kind = GetParamPatternKindForPassingMode(passing_mode)};
|
||||
}
|
||||
|
||||
// Returns a block for the implicit parameters of the given function
|
||||
@@ -1354,19 +1421,22 @@ static auto MapParameterType(Context& context, SemIR::LocId loc_id,
|
||||
static auto MakeImplicitParamPatternsBlockId(
|
||||
Context& context, SemIR::LocId loc_id,
|
||||
SemIR::ImportIRInstId import_ir_inst_id,
|
||||
const clang::FunctionDecl& clang_decl) -> SemIR::InstBlockId {
|
||||
const auto* method_decl = dyn_cast<clang::CXXMethodDecl>(&clang_decl);
|
||||
if (!method_decl || method_decl->isStatic() ||
|
||||
isa<clang::CXXConstructorDecl>(clang_decl)) {
|
||||
const clang::FunctionDecl& clang_decl,
|
||||
SemIR::ClangDeclSignatureId signature_id) -> SemIR::InstBlockId {
|
||||
if (!IsObjectMemberFunction(clang_decl)) {
|
||||
return SemIR::InstBlockId::Empty;
|
||||
}
|
||||
const auto* method_decl = cast<clang::CXXMethodDecl>(&clang_decl);
|
||||
|
||||
// Build a `self` parameter from the object parameter.
|
||||
BeginSubpattern(context);
|
||||
|
||||
clang::QualType param_type =
|
||||
method_decl->getFunctionObjectParameterReferenceType();
|
||||
auto param_info = MapParameterType(context, loc_id, param_type);
|
||||
const auto& signature = context.clang_decl_signatures().Get(signature_id);
|
||||
SemIR::ClangDeclSignature::PassingMode passing_mode =
|
||||
signature.self_passing_mode;
|
||||
auto param_info = MapParameterType(context, loc_id, param_type, passing_mode);
|
||||
auto [type_inst_id, type_id] = param_info.type;
|
||||
SemIR::ExprRegionId type_expr_region_id =
|
||||
ConsumeSubpatternExpr(context, type_inst_id);
|
||||
@@ -1399,8 +1469,9 @@ static auto MakeImplicitParamPatternsBlockId(
|
||||
static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::ImportIRInstId import_ir_inst_id,
|
||||
const clang::FunctionDecl& clang_decl,
|
||||
SemIR::ClangDeclKey::Signature signature)
|
||||
SemIR::ClangDeclSignatureId signature_id)
|
||||
-> SemIR::InstBlockId {
|
||||
const auto& signature = context.clang_decl_signatures().Get(signature_id);
|
||||
llvm::SmallVector<SemIR::InstId> param_ids;
|
||||
llvm::SmallVector<SemIR::InstId> param_type_ids;
|
||||
param_ids.reserve(signature.num_params);
|
||||
@@ -1411,7 +1482,7 @@ static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id,
|
||||
clang_decl.getNumNonObjectParams(), signature.num_params);
|
||||
const auto* function_type =
|
||||
clang_decl.getType()->castAs<clang::FunctionProtoType>();
|
||||
for (int i : llvm::seq(signature.num_params)) {
|
||||
for (auto i : llvm::seq(signature.num_params)) {
|
||||
const auto* param = clang_decl.getNonObjectParameter(i);
|
||||
clang::QualType orig_param_type = function_type->getParamType(
|
||||
clang_decl.hasCXXExplicitFunctionObjectParameter() + i);
|
||||
@@ -1425,7 +1496,8 @@ static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id,
|
||||
// Mark the start of a region of insts, needed for the type expression
|
||||
// created later with the call of `ConsumeSubpatternExpr()`.
|
||||
BeginSubpattern(context);
|
||||
auto param_info = MapParameterType(context, loc_id, param_type);
|
||||
auto param_info = MapParameterType(context, loc_id, param_type,
|
||||
signature.GetPassingMode(i));
|
||||
auto [type_inst_id, type_id] = param_info.type;
|
||||
// Type expression of the binding pattern - a single-entry/single-exit
|
||||
// region that allows control flow in the type expression e.g. fn F(x: if C
|
||||
@@ -1460,12 +1532,12 @@ static auto MakeParamPatternsBlockId(Context& context, SemIR::LocId loc_id,
|
||||
}
|
||||
|
||||
switch (signature.kind) {
|
||||
case SemIR::ClangDeclKey::Signature::Normal: {
|
||||
case SemIR::ClangDeclSignature::Normal: {
|
||||
// Use the converted parameter list as-is.
|
||||
break;
|
||||
}
|
||||
|
||||
case SemIR::ClangDeclKey::Signature::TuplePattern: {
|
||||
case SemIR::ClangDeclSignature::TuplePattern: {
|
||||
// Replace the parameters with a single tuple pattern containing the
|
||||
// converted parameter list.
|
||||
auto param_block_id = context.inst_blocks().Add(param_ids);
|
||||
@@ -1629,18 +1701,18 @@ struct FunctionSignatureInsts {
|
||||
static auto CreateFunctionSignatureInsts(
|
||||
Context& context, SemIR::LocId loc_id,
|
||||
SemIR::ImportIRInstId import_ir_inst_id, clang::FunctionDecl* clang_decl,
|
||||
SemIR::ClangDeclKey::Signature signature)
|
||||
SemIR::ClangDeclSignatureId signature_id)
|
||||
-> std::optional<FunctionSignatureInsts> {
|
||||
context.full_pattern_stack().StartImplicitParamList();
|
||||
auto implicit_param_patterns_id = MakeImplicitParamPatternsBlockId(
|
||||
context, loc_id, import_ir_inst_id, *clang_decl);
|
||||
context, loc_id, import_ir_inst_id, *clang_decl, signature_id);
|
||||
if (!implicit_param_patterns_id.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
context.full_pattern_stack().EndImplicitParamList();
|
||||
context.full_pattern_stack().StartExplicitParamList();
|
||||
auto param_patterns_id = MakeParamPatternsBlockId(
|
||||
context, loc_id, import_ir_inst_id, *clang_decl, signature);
|
||||
context, loc_id, import_ir_inst_id, *clang_decl, signature_id);
|
||||
if (!param_patterns_id.has_value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -1705,12 +1777,12 @@ static auto GetFunctionName(Context& context, clang::FunctionDecl* clang_decl)
|
||||
static auto ImportFunction(Context& context, SemIR::LocId loc_id,
|
||||
SemIR::ImportIRInstId import_ir_inst_id,
|
||||
clang::FunctionDecl* clang_decl,
|
||||
SemIR::ClangDeclKey::Signature signature)
|
||||
SemIR::ClangDeclSignatureId signature_id)
|
||||
-> std::optional<SemIR::FunctionId> {
|
||||
StartFunctionSignature(context);
|
||||
|
||||
auto function_params_insts = CreateFunctionSignatureInsts(
|
||||
context, loc_id, import_ir_inst_id, clang_decl, signature);
|
||||
context, loc_id, import_ir_inst_id, clang_decl, signature_id);
|
||||
|
||||
auto [pattern_block_id, decl_block_id] =
|
||||
FinishFunctionSignature(context, /*check_unused=*/false);
|
||||
@@ -1780,9 +1852,9 @@ static auto ImportFunction(Context& context, SemIR::LocId loc_id,
|
||||
context.imports().push_back(decl_id);
|
||||
|
||||
context.functions().Get(function_id).clang_decl_id =
|
||||
context.clang_decls().Add(
|
||||
{.key = SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature),
|
||||
.inst_id = decl_id});
|
||||
context.clang_decls().Add({.key = SemIR::ClangDeclKey::ForFunctionDecl(
|
||||
clang_decl, signature_id),
|
||||
.inst_id = decl_id});
|
||||
|
||||
return function_id;
|
||||
}
|
||||
@@ -1794,9 +1866,9 @@ static auto ImportFunction(Context& context, SemIR::LocId loc_id,
|
||||
// the trailing parameters.
|
||||
static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id,
|
||||
clang::FunctionDecl* clang_decl,
|
||||
SemIR::ClangDeclKey::Signature signature)
|
||||
SemIR::ClangDeclSignatureId signature_id)
|
||||
-> SemIR::InstId {
|
||||
auto key = SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature);
|
||||
auto key = SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature_id);
|
||||
|
||||
// Check if the declaration is already mapped.
|
||||
if (SemIR::InstId existing_inst_id = LookupClangDeclInstId(context, key);
|
||||
@@ -1822,8 +1894,8 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id,
|
||||
|
||||
CARBON_CHECK(clang_decl->getFunctionType()->isFunctionProtoType(),
|
||||
"Not Prototype function (non-C++ code)");
|
||||
auto function_id =
|
||||
ImportFunction(context, loc_id, import_ir_inst_id, clang_decl, signature);
|
||||
auto function_id = ImportFunction(context, loc_id, import_ir_inst_id,
|
||||
clang_decl, signature_id);
|
||||
if (!function_id) {
|
||||
MarkFailedDecl(context, key);
|
||||
return SemIR::ErrorInst::InstId;
|
||||
@@ -1840,10 +1912,19 @@ static auto ImportFunctionDecl(Context& context, SemIR::LocId loc_id,
|
||||
|
||||
if (clang::FunctionDecl* thunk_clang_decl =
|
||||
BuildCppThunk(context, function_info)) {
|
||||
if (auto thunk_function_id = ImportFunction(
|
||||
context, loc_id, import_ir_inst_id, thunk_clang_decl,
|
||||
{.num_params =
|
||||
static_cast<int32_t>(thunk_clang_decl->getNumParams())})) {
|
||||
SemIR::ClangDeclSignature thunk_signature;
|
||||
thunk_signature.kind = SemIR::ClangDeclSignature::Normal;
|
||||
thunk_signature.num_params =
|
||||
static_cast<int32_t>(thunk_clang_decl->getNumParams());
|
||||
thunk_signature.passing_modes.assign(
|
||||
thunk_signature.num_params,
|
||||
SemIR::ClangDeclSignature::PassingMode::ByValue);
|
||||
SemIR::ClangDeclSignatureId thunk_signature_id =
|
||||
context.clang_decl_signatures().Add(std::move(thunk_signature));
|
||||
|
||||
if (auto thunk_function_id =
|
||||
ImportFunction(context, loc_id, import_ir_inst_id,
|
||||
thunk_clang_decl, thunk_signature_id)) {
|
||||
auto& thunk_function = context.functions().Get(*thunk_function_id);
|
||||
thunk_function.SetCppThunk(function_info.first_owning_decl_id);
|
||||
SemIR::InstId thunk_function_decl_id =
|
||||
@@ -1922,8 +2003,9 @@ static auto AddDependentUnimportedTypeDecls(Context& context,
|
||||
// and adds them to the given set.
|
||||
static auto AddDependentUnimportedFunctionDecls(
|
||||
Context& context, const clang::FunctionDecl& clang_decl,
|
||||
SemIR::ClangDeclKey::Signature signature, ImportWorklist& worklist)
|
||||
SemIR::ClangDeclSignatureId signature_id, ImportWorklist& worklist)
|
||||
-> void {
|
||||
const auto& signature = context.clang_decl_signatures().Get(signature_id);
|
||||
const auto* function_type =
|
||||
clang_decl.getType()->castAs<clang::FunctionProtoType>();
|
||||
for (int i : llvm::seq(clang_decl.hasCXXExplicitFunctionObjectParameter() +
|
||||
@@ -1943,7 +2025,7 @@ static auto AddDependentUnimportedDecls(Context& context,
|
||||
clang::Decl* clang_decl = key.decl;
|
||||
if (auto* clang_function_decl = clang_decl->getAsFunction()) {
|
||||
AddDependentUnimportedFunctionDecls(context, *clang_function_decl,
|
||||
key.signature, worklist);
|
||||
key.signature_id, worklist);
|
||||
} else if (auto* type_decl = dyn_cast<clang::TypeDecl>(clang_decl)) {
|
||||
if (!isa<clang::TagDecl>(clang_decl)) {
|
||||
AddDependentUnimportedTypeDecls(
|
||||
@@ -2063,7 +2145,7 @@ static auto ImportDeclAfterDependencies(Context& context, SemIR::LocId loc_id,
|
||||
clang::Decl* clang_decl = key.decl;
|
||||
if (auto* clang_function_decl = clang_decl->getAsFunction()) {
|
||||
return ImportFunctionDecl(context, loc_id, clang_function_decl,
|
||||
key.signature);
|
||||
key.signature_id);
|
||||
}
|
||||
if (auto* clang_namespace_decl = dyn_cast<clang::NamespaceDecl>(clang_decl)) {
|
||||
return ImportNamespaceDecl(context, clang_namespace_decl);
|
||||
|
||||
@@ -18,6 +18,12 @@
|
||||
|
||||
namespace Carbon::Check {
|
||||
|
||||
// Returns whether the given function is an object member function. This is true
|
||||
// if it's a non-static member function and not a constructor. Object member
|
||||
// functions correspond to Carbon functions with a `self` parameter.
|
||||
// TODO: Find a better home for this function.
|
||||
auto IsObjectMemberFunction(const clang::FunctionDecl& decl) -> bool;
|
||||
|
||||
// Generates a C++ header that includes the imported cpp files, parses it,
|
||||
// generates the AST from it and links `SemIR::File` to it. Reports C++ errors
|
||||
// and warnings. If successful, adds a `Cpp` namespace.
|
||||
@@ -59,11 +65,11 @@ auto ImportCppDecl(Context& context, SemIR::LocId loc_id,
|
||||
// imported, returns the mapped instruction.
|
||||
inline auto ImportCppFunctionDecl(Context& context, SemIR::LocId loc_id,
|
||||
clang::FunctionDecl* clang_decl,
|
||||
SemIR::ClangDeclKey::Signature signature)
|
||||
SemIR::ClangDeclSignatureId signature_id)
|
||||
-> SemIR::InstId {
|
||||
return ImportCppDecl(
|
||||
context, loc_id,
|
||||
SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature));
|
||||
SemIR::ClangDeclKey::ForFunctionDecl(clang_decl, signature_id));
|
||||
}
|
||||
|
||||
// Imports a function declaration from Clang to Carbon. If successful, returns
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "toolchain/check/type.h"
|
||||
#include "toolchain/check/type_completion.h"
|
||||
#include "toolchain/sem_ir/builtin_function_kind.h"
|
||||
#include "toolchain/sem_ir/clang_decl.h"
|
||||
#include "toolchain/sem_ir/cpp_initializer_list.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
#include "toolchain/sem_ir/inst.h"
|
||||
@@ -285,44 +286,67 @@ static auto MakeCppStdInitializerListMake(Context& context, SemIR::LocId loc_id,
|
||||
static auto GetConversionSignatureToImport(
|
||||
Context& context, SemIR::InstId source_id,
|
||||
clang::InitializationSequence::StepKind step_kind,
|
||||
clang::FunctionDecl* function_decl) -> SemIR::ClangDeclKey::Signature {
|
||||
clang::FunctionDecl* function_decl, clang::DeclAccessPair found_decl,
|
||||
clang::Expr* arg_expr) -> SemIR::ClangDeclSignatureId {
|
||||
auto signature_kind = SemIR::ClangDeclSignature::Normal;
|
||||
clang::Expr* self_expr = nullptr;
|
||||
llvm::ArrayRef<clang::Expr*> arg_exprs(arg_expr);
|
||||
|
||||
// If we're performing a constructor initialization from a list, form a
|
||||
// function signature that takes a single tuple or struct pattern
|
||||
// instead of a function signature with one parameter per C++ parameter.
|
||||
if (step_kind ==
|
||||
clang::InitializationSequence::SK_ConstructorInitializationFromList) {
|
||||
// Initialization from a tuple `(a, b, c)` results in a constructor
|
||||
// function that takes a tuple pattern:
|
||||
//
|
||||
// fn Class.Class((a: A, b: B, c: C)) -> Class;
|
||||
//
|
||||
// The source type should always be a tuple type, because we don't support
|
||||
// C++ initialization from struct types.
|
||||
auto tuple_type = context.types().TryGetAs<SemIR::TupleType>(
|
||||
context.insts().Get(source_id).type_id());
|
||||
CARBON_CHECK(tuple_type, "List initialization from non-tuple type");
|
||||
|
||||
// Initialization from a tuple `(a, b, c)` results in a constructor
|
||||
// function that takes a tuple pattern:
|
||||
//
|
||||
// fn Class.Class((a: A, b: B, c: C)) -> Class;
|
||||
return {
|
||||
.kind = SemIR::ClangDeclKey::Signature::Kind::TuplePattern,
|
||||
.num_params = static_cast<int32_t>(
|
||||
context.inst_blocks().Get(tuple_type->type_elements_id).size())};
|
||||
arg_exprs = cast<clang::InitListExpr>(arg_expr)->inits();
|
||||
signature_kind = SemIR::ClangDeclSignature::TuplePattern;
|
||||
}
|
||||
|
||||
// Any other initialization using a constructor is calling a converting
|
||||
// constructor:
|
||||
//
|
||||
// fn Class.Class(a: A) -> Class;
|
||||
// In order to determine how to map the parameters, we need to build the
|
||||
// conversion sequence(s) again. Clang already threw them away. The only way
|
||||
// to do this is to "redo" overload resolution with our single candidate.
|
||||
clang::OverloadCandidateSet candidates(
|
||||
function_decl->getLocation(),
|
||||
clang::OverloadCandidateSet::CSK_InitByUserDefinedConversion);
|
||||
|
||||
if (isa<clang::CXXConstructorDecl>(function_decl)) {
|
||||
return {.kind = SemIR::ClangDeclKey::Signature::Kind::Normal,
|
||||
.num_params = 1};
|
||||
// This is either tuple list initialization as described above or a
|
||||
// constructor call:
|
||||
//
|
||||
// fn Class.Class(a: A) -> Class;
|
||||
context.clang_sema().AddOverloadCandidate(function_decl, found_decl,
|
||||
arg_exprs, candidates);
|
||||
} else {
|
||||
// Otherwise, the initialization is calling a conversion function
|
||||
// `Source::operator Dest`:
|
||||
//
|
||||
// fn Source.<conversion function>[self: Source]() -> Dest;
|
||||
auto* conversion_decl = cast<clang::CXXConversionDecl>(function_decl);
|
||||
self_expr = arg_expr;
|
||||
arg_exprs = {};
|
||||
context.clang_sema().AddMethodCandidate(
|
||||
conversion_decl, found_decl, conversion_decl->getParent(),
|
||||
self_expr->getType(), self_expr->Classify(context.ast_context()),
|
||||
arg_exprs, candidates);
|
||||
}
|
||||
|
||||
// Otherwise, the initialization is calling a conversion function
|
||||
// `Source::operator Dest`:
|
||||
//
|
||||
// fn Source.<conversion function>[self: Source]() -> Dest;
|
||||
CARBON_CHECK(isa<clang::CXXConversionDecl>(function_decl));
|
||||
return {.kind = SemIR::ClangDeclKey::Signature::Kind::Normal,
|
||||
.num_params = 0};
|
||||
clang::OverloadCandidateSet::iterator best;
|
||||
auto result = candidates.BestViableFunction(
|
||||
context.clang_sema(), function_decl->getLocation(), best);
|
||||
CARBON_CHECK(result == clang::OverloadingResult::OR_Success ||
|
||||
result == clang::OverloadingResult::OR_Deleted);
|
||||
|
||||
return ComputeClangDeclSignatureFromBestViableFunction(
|
||||
context, best, self_expr, arg_exprs, signature_kind);
|
||||
}
|
||||
|
||||
static auto LookupCppConversion(Context& context, SemIR::LocId loc_id,
|
||||
@@ -402,10 +426,12 @@ static auto LookupCppConversion(Context& context, SemIR::LocId loc_id,
|
||||
|
||||
sema.MarkFunctionReferenced(loc, step.Function.Function);
|
||||
|
||||
auto signature = GetConversionSignatureToImport(
|
||||
context, source_id, step.Kind, step.Function.Function);
|
||||
SemIR::ClangDeclSignatureId signature_id =
|
||||
GetConversionSignatureToImport(context, source_id, step.Kind,
|
||||
step.Function.Function,
|
||||
step.Function.FoundDecl, arg_expr);
|
||||
auto result_id = ImportCppFunctionDecl(
|
||||
context, loc_id, step.Function.Function, signature);
|
||||
context, loc_id, step.Function.Function, signature_id);
|
||||
if (auto fn_decl = context.insts().TryGetAsWithId<SemIR::FunctionDecl>(
|
||||
result_id)) {
|
||||
CheckCppOverloadAccess(context, loc_id, step.Function.FoundDecl,
|
||||
@@ -637,14 +663,18 @@ static auto FindClangOperator(Context& context, SemIR::LocId loc_id,
|
||||
sema.MarkFunctionReferenced(loc, best_viable_fn->Function);
|
||||
|
||||
// If this is an operator method, the first arg will be used as self.
|
||||
int32_t num_params = arg_exprs.size();
|
||||
if (isa<clang::CXXMethodDecl>(best_viable_fn->Function)) {
|
||||
--num_params;
|
||||
clang::Expr* self_expr = nullptr;
|
||||
auto arg_exprs_for_signature = arg_exprs;
|
||||
if (IsObjectMemberFunction(*best_viable_fn->Function)) {
|
||||
self_expr = arg_exprs_for_signature.consume_front();
|
||||
}
|
||||
|
||||
auto result_id =
|
||||
ImportCppFunctionDecl(context, loc_id, best_viable_fn->Function,
|
||||
{.num_params = num_params});
|
||||
SemIR::ClangDeclSignatureId signature_id =
|
||||
ComputeClangDeclSignatureFromBestViableFunction(
|
||||
context, best_viable_fn, self_expr, arg_exprs_for_signature);
|
||||
|
||||
auto result_id = ImportCppFunctionDecl(
|
||||
context, loc_id, best_viable_fn->Function, signature_id);
|
||||
if (result_id != SemIR::ErrorInst::InstId) {
|
||||
CheckCppOverloadAccess(
|
||||
context, loc_id, best_viable_fn->FoundDecl,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "toolchain/check/cpp/overload_resolution.h"
|
||||
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/Basic/DiagnosticSema.h"
|
||||
#include "clang/Sema/Overload.h"
|
||||
#include "clang/Sema/Sema.h"
|
||||
@@ -68,9 +69,8 @@ static auto AddOverloadCandidates(
|
||||
|
||||
auto* fn_decl = template_decl ? template_decl->getTemplatedDecl()
|
||||
: cast<clang::FunctionDecl>(decl);
|
||||
auto* method_decl = dyn_cast<clang::CXXMethodDecl>(fn_decl);
|
||||
if (method_decl && !method_decl->isStatic() &&
|
||||
!isa<clang::CXXConstructorDecl>(fn_decl)) {
|
||||
if (IsObjectMemberFunction(*fn_decl)) {
|
||||
auto* method_decl = cast<clang::CXXMethodDecl>(fn_decl);
|
||||
clang::QualType self_type;
|
||||
clang::Expr::Classification self_classification;
|
||||
if (self_arg) {
|
||||
@@ -130,6 +130,139 @@ auto CheckCppOverloadAccess(
|
||||
.highest_allowed_access = allowed_access_kind});
|
||||
}
|
||||
|
||||
// Computes the passing mode for a C++ function parameter that is a reference.
|
||||
static auto ComputePassingModeForReferenceBinding(
|
||||
const clang::StandardConversionSequence& scs)
|
||||
-> SemIR::ClangDeclSignature::PassingMode {
|
||||
CARBON_CHECK(scs.ReferenceBinding);
|
||||
auto pointee_type = scs.getToType(2);
|
||||
if (pointee_type.isConstQualified() ||
|
||||
(scs.IsLvalueReference && scs.BindsToRvalue)) {
|
||||
// Reference to const is always mapped to Carbon pass by value. A non-const
|
||||
// lvalue reference bound to an rvalue only happens when initializing an
|
||||
// object parameter with no ref-qualifier from an rvalue, which we also
|
||||
// model as pass-by-value.
|
||||
return SemIR::ClangDeclSignature::PassingMode::ByValue;
|
||||
}
|
||||
// Rvalue reference to non-const is passed as a `var` to force a copy or move
|
||||
// in the caller. Lvalue reference to non-const is passed by reference.
|
||||
return scs.IsLvalueReference ? SemIR::ClangDeclSignature::PassingMode::ByRef
|
||||
: SemIR::ClangDeclSignature::PassingMode::ByVar;
|
||||
}
|
||||
|
||||
// Returns whether move-construction of type `type` is known to be equivalent to
|
||||
// a copy. If so, it's safe to map C++ pass-by-value into Carbon pass-by-value
|
||||
// instead of pass-by-var.
|
||||
static auto IsMoveEquivalentToCopy(clang::QualType type) {
|
||||
// We can pass by copy instead of by move if:
|
||||
// - The type is not a class type.
|
||||
auto* record_decl = type->getAsCXXRecordDecl();
|
||||
if (!record_decl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// - The move constructor is defaulted and deleted or non-existent, in
|
||||
// which case overload resolution for a move will call the copy
|
||||
// constructor.
|
||||
if (!record_decl->hasMoveConstructor() ||
|
||||
(!record_decl->hasUserDeclaredMoveConstructor() &&
|
||||
record_decl->defaultedMoveConstructorIsDeleted())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// - Both move and copy are trivial and not deleted, in which case they
|
||||
// are equivalent.
|
||||
if (record_decl->hasTrivialMoveConstructor() &&
|
||||
!record_decl->defaultedMoveConstructorIsDeleted() &&
|
||||
record_decl->hasTrivialCopyConstructor() &&
|
||||
!record_decl->defaultedCopyConstructorIsDeleted()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise we need a move, so we pass by var.
|
||||
return false;
|
||||
}
|
||||
|
||||
auto GetPassingModeForCppParameter(const clang::ImplicitConversionSequence& ics,
|
||||
const clang::Expr* arg_expr)
|
||||
-> SemIR::ClangDeclSignature::PassingMode {
|
||||
if (ics.isStandard()) {
|
||||
const auto& scs = ics.Standard;
|
||||
if (scs.ReferenceBinding) {
|
||||
return ComputePassingModeForReferenceBinding(scs);
|
||||
}
|
||||
|
||||
// Most standard conversions can be mapped to Carbon pass by value. The
|
||||
// exception is where the source is an initializing expression of record
|
||||
// type, which we map to pass by var, unless a copy would do the same thing.
|
||||
if (arg_expr->isXValue() && !IsMoveEquivalentToCopy(arg_expr->getType())) {
|
||||
return SemIR::ClangDeclSignature::PassingMode::ByVar;
|
||||
}
|
||||
|
||||
return SemIR::ClangDeclSignature::PassingMode::ByValue;
|
||||
}
|
||||
|
||||
if (ics.isUserDefined()) {
|
||||
const auto& ucs = ics.UserDefined;
|
||||
if (ucs.After.ReferenceBinding) {
|
||||
return ComputePassingModeForReferenceBinding(ucs.After);
|
||||
}
|
||||
|
||||
const auto* ctor =
|
||||
dyn_cast_or_null<clang::CXXConstructorDecl>(ucs.ConversionFunction);
|
||||
if (ctor && ctor->isCopyConstructor()) {
|
||||
// Overload resolution wanted to call a copy constructor to initialize
|
||||
// this parameter. Pass by value instead; we'll copy in the thunk.
|
||||
return SemIR::ClangDeclSignature::PassingMode::ByValue;
|
||||
}
|
||||
|
||||
// We're calling a user-defined conversion, so we're performing
|
||||
// initialization. Pass by move unless the type being initialized doesn't
|
||||
// distinguish moves and copies.
|
||||
return IsMoveEquivalentToCopy(ucs.After.getToType(2))
|
||||
? SemIR::ClangDeclSignature::PassingMode::ByValue
|
||||
: SemIR::ClangDeclSignature::PassingMode::ByVar;
|
||||
}
|
||||
|
||||
// TODO: Support ellipsis conversion sequences.
|
||||
CARBON_FATAL("Unexpected kind of implicit conversion sequence");
|
||||
}
|
||||
|
||||
// Computes the signature for a C++ function candidate based on the conversions
|
||||
// performed on the arguments.
|
||||
auto ComputeClangDeclSignatureFromBestViableFunction(
|
||||
Context& context, clang::OverloadCandidateSet::iterator candidate,
|
||||
clang::Expr* self_expr, llvm::ArrayRef<clang::Expr*> arg_exprs,
|
||||
SemIR::ClangDeclSignature::Kind kind) -> SemIR::ClangDeclSignatureId {
|
||||
SemIR::ClangDeclSignature signature;
|
||||
signature.kind = kind;
|
||||
signature.num_params = static_cast<int32_t>(arg_exprs.size());
|
||||
signature.passing_modes.reserve(signature.num_params);
|
||||
|
||||
for (auto [i, arg_expr] : llvm::enumerate(arg_exprs)) {
|
||||
// Compute which conversion sequence corresponds to this argument.
|
||||
// TODO: Clang should expose a way to compute this.
|
||||
int conversion_index = i;
|
||||
if (auto* method = dyn_cast<clang::CXXMethodDecl>(candidate->Function)) {
|
||||
if (method->isStatic()) {
|
||||
// Static methods get an object parameter conversion at index 0, even
|
||||
// though there's no argument.
|
||||
++conversion_index;
|
||||
}
|
||||
}
|
||||
|
||||
signature.passing_modes.push_back(GetPassingModeForCppParameter(
|
||||
candidate->Conversions[conversion_index], arg_expr));
|
||||
}
|
||||
|
||||
if (IsObjectMemberFunction(*candidate->Function)) {
|
||||
signature.self_passing_mode =
|
||||
GetPassingModeForCppParameter(candidate->Conversions[0], self_expr);
|
||||
}
|
||||
|
||||
return context.clang_decl_signatures().Add(std::move(signature));
|
||||
}
|
||||
|
||||
auto PerformCppOverloadResolution(
|
||||
Context& context, SemIR::LocId loc_id,
|
||||
const SemIR::CppOverloadSet& overload_set,
|
||||
@@ -179,9 +312,12 @@ auto PerformCppOverloadResolution(
|
||||
case clang::OverloadingResult::OR_Success: {
|
||||
CARBON_CHECK(best_viable_fn->Function);
|
||||
CARBON_CHECK(!best_viable_fn->RewriteKind);
|
||||
SemIR::ClangDeclSignatureId signature_id =
|
||||
ComputeClangDeclSignatureFromBestViableFunction(
|
||||
context, best_viable_fn, self_expr, arg_exprs);
|
||||
|
||||
SemIR::InstId result_id = ImportCppFunctionDecl(
|
||||
context, loc_id, best_viable_fn->Function,
|
||||
{.num_params = static_cast<int32_t>(arg_exprs.size())});
|
||||
context, loc_id, best_viable_fn->Function, signature_id);
|
||||
if (result_id != SemIR::ErrorInst::InstId) {
|
||||
CheckCppOverloadAccess(
|
||||
context, loc_id, best_viable_fn->FoundDecl,
|
||||
|
||||
@@ -20,6 +20,18 @@ auto CheckCppOverloadAccess(
|
||||
SemIR::KnownInstId<SemIR::FunctionDecl> overload_inst_id,
|
||||
SemIR::NameScopeId parent_scope_id = SemIR::NameScopeId::None) -> void;
|
||||
|
||||
// Returns the passing mode to use for a parameter given the implicit
|
||||
// conversion sequence and the argument expression.
|
||||
auto GetPassingModeForCppParameter(const clang::ImplicitConversionSequence& ics,
|
||||
const clang::Expr* arg_expr)
|
||||
-> SemIR::ClangDeclSignature::PassingMode;
|
||||
|
||||
auto ComputeClangDeclSignatureFromBestViableFunction(
|
||||
Context& context, clang::OverloadCandidateSet::iterator candidate,
|
||||
clang::Expr* self_expr, llvm::ArrayRef<clang::Expr*> arg_exprs,
|
||||
SemIR::ClangDeclSignature::Kind kind = SemIR::ClangDeclSignature::Normal)
|
||||
-> SemIR::ClangDeclSignatureId;
|
||||
|
||||
// Resolves which function to call using Clang overload resolution. Returns an
|
||||
// instruction referring to that function, or an error instruction if overload
|
||||
// resolution failed.
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "toolchain/check/control_flow.h"
|
||||
#include "toolchain/check/convert.h"
|
||||
#include "toolchain/check/cpp/context.h"
|
||||
#include "toolchain/check/cpp/import.h"
|
||||
#include "toolchain/check/literal.h"
|
||||
#include "toolchain/check/type.h"
|
||||
#include "toolchain/check/type_completion.h"
|
||||
@@ -74,23 +75,42 @@ static auto GetGlobalDecl(const clang::FunctionDecl* decl)
|
||||
static auto GenerateThunkMangledName(
|
||||
clang::MangleContext& mangle_context,
|
||||
const clang::FunctionDecl& callee_function_decl,
|
||||
SemIR::ClangDeclKey::Signature::Kind signature_kind, int num_params)
|
||||
-> std::string {
|
||||
const SemIR::ClangDeclSignature& signature) -> std::string {
|
||||
RawStringOstream mangled_name_stream;
|
||||
mangle_context.mangleName(GetGlobalDecl(&callee_function_decl),
|
||||
mangled_name_stream);
|
||||
switch (signature_kind) {
|
||||
case SemIR::ClangDeclKey::Signature::Normal:
|
||||
switch (signature.kind) {
|
||||
case SemIR::ClangDeclSignature::Normal:
|
||||
mangled_name_stream << ".carbon_thunk";
|
||||
break;
|
||||
case SemIR::ClangDeclKey::Signature::TuplePattern:
|
||||
case SemIR::ClangDeclSignature::TuplePattern:
|
||||
mangled_name_stream << ".carbon_thunk_tuple";
|
||||
break;
|
||||
}
|
||||
|
||||
if (num_params !=
|
||||
static_cast<int>(callee_function_decl.getNumNonObjectParams())) {
|
||||
mangled_name_stream << num_params;
|
||||
// Append passing modes.
|
||||
// TODO: Pick one "likely" set of passing modes for the function and omit the
|
||||
// suffix for that signature.
|
||||
mangled_name_stream << ".";
|
||||
auto append_mode = [&](SemIR::ClangDeclSignature::PassingMode mode) {
|
||||
switch (mode) {
|
||||
case SemIR::ClangDeclSignature::PassingMode::ByValue:
|
||||
mangled_name_stream << "_";
|
||||
break;
|
||||
case SemIR::ClangDeclSignature::PassingMode::ByVar:
|
||||
mangled_name_stream << "v";
|
||||
break;
|
||||
case SemIR::ClangDeclSignature::PassingMode::ByRef:
|
||||
mangled_name_stream << "r";
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if (IsObjectMemberFunction(callee_function_decl)) {
|
||||
append_mode(signature.self_passing_mode);
|
||||
}
|
||||
for (auto mode : signature.passing_modes) {
|
||||
append_mode(mode);
|
||||
}
|
||||
|
||||
return mangled_name_stream.TakeStr();
|
||||
@@ -143,15 +163,15 @@ namespace {
|
||||
// Information about the callee of a thunk.
|
||||
struct CalleeFunctionInfo {
|
||||
explicit CalleeFunctionInfo(clang::FunctionDecl* decl,
|
||||
SemIR::ClangDeclKey::Signature signature)
|
||||
const SemIR::ClangDeclSignature* signature)
|
||||
: decl(decl),
|
||||
signature_kind(signature.kind),
|
||||
num_params(signature.num_params +
|
||||
signature(signature),
|
||||
num_params(signature->num_params +
|
||||
decl->hasCXXExplicitFunctionObjectParameter()) {
|
||||
auto& ast_context = decl->getASTContext();
|
||||
const auto* method_decl = dyn_cast<clang::CXXMethodDecl>(decl);
|
||||
bool is_ctor = isa<clang::CXXConstructorDecl>(decl);
|
||||
has_object_parameter = method_decl && !method_decl->isStatic() && !is_ctor;
|
||||
has_object_parameter = IsObjectMemberFunction(*decl);
|
||||
if (has_object_parameter && method_decl->isImplicitObjectMemberFunction()) {
|
||||
implicit_object_parameter_type =
|
||||
method_decl->getFunctionObjectParameterReferenceType();
|
||||
@@ -195,8 +215,8 @@ struct CalleeFunctionInfo {
|
||||
// The callee function.
|
||||
clang::FunctionDecl* decl;
|
||||
|
||||
// The kind of function signature being imported.
|
||||
SemIR::ClangDeclKey::Signature::Kind signature_kind;
|
||||
// The signature of the function being imported.
|
||||
const SemIR::ClangDeclSignature* signature;
|
||||
|
||||
// The number of explicit parameters to import. This may be less than the
|
||||
// number of parameters that the function has if default arguments are being
|
||||
@@ -229,25 +249,28 @@ auto IsCppThunkRequired(Context& context, const SemIR::Function& function)
|
||||
}
|
||||
|
||||
const auto& decl_info = context.clang_decls().Get(function.clang_decl_id);
|
||||
const auto& signature =
|
||||
context.clang_decl_signatures().Get(decl_info.key.signature_id);
|
||||
auto* decl = cast<clang::FunctionDecl>(decl_info.key.decl);
|
||||
if (decl_info.key.signature.kind != SemIR::ClangDeclKey::Signature::Normal ||
|
||||
decl_info.key.signature.num_params !=
|
||||
static_cast<int>(decl->getNumNonObjectParams())) {
|
||||
if (signature.kind != SemIR::ClangDeclSignature::Normal ||
|
||||
signature.num_params != static_cast<int>(decl->getNumNonObjectParams())) {
|
||||
// We require a thunk if the number of parameters we want isn't all of them.
|
||||
// This happens if default arguments are in use, or (eventually) when
|
||||
// calling a varargs function.
|
||||
return true;
|
||||
}
|
||||
|
||||
CalleeFunctionInfo callee_info(decl, decl_info.key.signature);
|
||||
CalleeFunctionInfo callee_info(decl, &signature);
|
||||
if (!callee_info.has_simple_return_type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& ast_context = context.ast_context();
|
||||
if (callee_info.has_implicit_object_parameter() &&
|
||||
!IsSimpleAbiType(ast_context, callee_info.implicit_object_parameter_type,
|
||||
/*for_parameter=*/true)) {
|
||||
(!IsSimpleAbiType(ast_context, callee_info.implicit_object_parameter_type,
|
||||
/*for_parameter=*/true) ||
|
||||
signature.self_passing_mode ==
|
||||
SemIR::ClangDeclSignature::PassingMode::ByVar)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -255,7 +278,9 @@ auto IsCppThunkRequired(Context& context, const SemIR::Function& function)
|
||||
decl->getType()->castAs<clang::FunctionProtoType>();
|
||||
for (int i : llvm::seq(decl->getNumParams())) {
|
||||
if (!IsSimpleAbiType(ast_context, function_type->getParamType(i),
|
||||
/*for_parameter=*/true)) {
|
||||
/*for_parameter=*/true) ||
|
||||
signature.GetPassingMode(i) ==
|
||||
SemIR::ClangDeclSignature::PassingMode::ByVar) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -437,10 +462,8 @@ static auto CreateThunkFunctionDecl(
|
||||
// Set asm("<callee function mangled name>.carbon_thunk").
|
||||
thunk_function_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(
|
||||
ast_context,
|
||||
GenerateThunkMangledName(
|
||||
context.cpp_context()->clang_mangle_context(), *callee_info.decl,
|
||||
callee_info.signature_kind,
|
||||
callee_info.num_params - callee_info.has_explicit_object_parameter()),
|
||||
GenerateThunkMangledName(context.cpp_context()->clang_mangle_context(),
|
||||
*callee_info.decl, *callee_info.signature),
|
||||
clang_loc));
|
||||
|
||||
// Set function declaration type source info.
|
||||
@@ -453,11 +476,10 @@ static auto CreateThunkFunctionDecl(
|
||||
// Builds a reference to the given parameter thunk. If `type` is specified, that
|
||||
// is the callee parameter type that's being held by the parameter, and
|
||||
// conversions will be performed as necessary to recover a value of that type.
|
||||
static auto BuildThunkParamRef(clang::Sema& sema,
|
||||
clang::FunctionDecl* thunk_function_decl,
|
||||
unsigned thunk_index,
|
||||
clang::QualType type = clang::QualType())
|
||||
-> clang::Expr* {
|
||||
static auto BuildThunkParamRef(
|
||||
clang::Sema& sema, clang::FunctionDecl* thunk_function_decl,
|
||||
unsigned thunk_index, SemIR::ClangDeclSignature::PassingMode passing_mode,
|
||||
clang::QualType type = clang::QualType()) -> clang::Expr* {
|
||||
clang::ParmVarDecl* thunk_param =
|
||||
thunk_function_decl->getParamDecl(thunk_index);
|
||||
clang::SourceLocation clang_loc = thunk_param->getLocation();
|
||||
@@ -472,15 +494,10 @@ static auto BuildThunkParamRef(clang::Sema& sema,
|
||||
call_arg = deref_result.get();
|
||||
}
|
||||
|
||||
// Cast to an rvalue when initializing an rvalue reference. The validity of
|
||||
// the initialization of the reference should be validated by the caller of
|
||||
// the thunk.
|
||||
//
|
||||
// TODO: Consider inserting a cast to an rvalue in more cases. Note that we
|
||||
// currently pass pointers to non-temporary objects as the argument when
|
||||
// calling a thunk, so we'll need to either change that or generate
|
||||
// different thunks depending on whether we're moving from each parameter.
|
||||
if (!type.isNull() && type->isRValueReferenceType()) {
|
||||
// Cast to an xvalue when using pass-by-`var` or when initializing an rvalue
|
||||
// reference (which might be passed by value if it's const-qualified).
|
||||
if (passing_mode == SemIR::ClangDeclSignature::PassingMode::ByVar ||
|
||||
thunk_param->getType()->isRValueReferenceType()) {
|
||||
call_arg = clang::ImplicitCastExpr::Create(
|
||||
sema.getASTContext(), call_arg->getType(), clang::CK_NoOp, call_arg,
|
||||
nullptr, clang::ExprValueKind::VK_XValue, clang::FPOptionsOverride());
|
||||
@@ -497,6 +514,7 @@ static auto BuildParamRefForCalleeArg(clang::Sema& sema,
|
||||
unsigned thunk_index = callee_info.GetThunkParamIndex(callee_index);
|
||||
return BuildThunkParamRef(
|
||||
sema, thunk_function_decl, thunk_index,
|
||||
callee_info.signature->GetPassingMode(callee_index),
|
||||
callee_info.decl->getParamDecl(callee_index)->getType());
|
||||
}
|
||||
|
||||
@@ -538,8 +556,9 @@ static auto BuildThunkBody(CppContext& cpp_context, clang::Sema& sema,
|
||||
clang::QualType object_param_type =
|
||||
cast<clang::CXXMethodDecl>(callee_info.decl)
|
||||
->getFunctionObjectParameterReferenceType();
|
||||
auto* object_param_ref =
|
||||
BuildThunkParamRef(sema, thunk_function_decl, 0, object_param_type);
|
||||
auto* object_param_ref = BuildThunkParamRef(
|
||||
sema, thunk_function_decl, 0, callee_info.signature->self_passing_mode,
|
||||
object_param_type);
|
||||
constexpr bool IsArrow = false;
|
||||
auto object =
|
||||
sema.PerformMemberExprBaseConversion(object_param_ref, IsArrow);
|
||||
@@ -597,7 +616,8 @@ static auto BuildThunkBody(CppContext& cpp_context, clang::Sema& sema,
|
||||
}
|
||||
|
||||
auto* return_object_addr = BuildThunkParamRef(
|
||||
sema, thunk_function_decl, callee_info.GetThunkReturnParamIndex());
|
||||
sema, thunk_function_decl, callee_info.GetThunkReturnParamIndex(),
|
||||
SemIR::ClangDeclSignature::PassingMode::ByValue);
|
||||
auto return_type = callee_info.effective_return_type.getNonReferenceType();
|
||||
auto* return_type_info =
|
||||
sema.Context.getTrivialTypeSourceInfo(return_type, clang_loc);
|
||||
@@ -635,8 +655,9 @@ auto BuildCppThunk(Context& context, const SemIR::Function& callee_function)
|
||||
// shouldn't consider it here. However, to do that, we would need to cache the
|
||||
// thunks we build so that we don't build the same thunk multiple times if
|
||||
// it's used with multiple different signature kinds.
|
||||
CalleeFunctionInfo callee_info(callee_function_decl,
|
||||
clang_decl_key.signature);
|
||||
const auto& signature =
|
||||
context.clang_decl_signatures().Get(clang_decl_key.signature_id);
|
||||
CalleeFunctionInfo callee_info(callee_function_decl, &signature);
|
||||
|
||||
// Build the thunk function declaration.
|
||||
auto thunk_param_types =
|
||||
|
||||
@@ -518,7 +518,10 @@ static auto InventPrimitiveClangArg(Context& context, FormInfo form)
|
||||
|
||||
case SemIR::ExprCategory::ReprInitializing:
|
||||
case SemIR::ExprCategory::InPlaceInitializing:
|
||||
value_kind = clang::ExprValueKind::VK_PRValue;
|
||||
// A Carbon initializing expression is much more similar to a C++ prvalue
|
||||
// than a C++ xvalue, but we encode it as an xvalue expression to request
|
||||
// that it be passed through the thunk by move rather than by copy.
|
||||
value_kind = clang::ExprValueKind::VK_XValue;
|
||||
break;
|
||||
|
||||
case SemIR::ExprCategory::Mixed:
|
||||
|
||||
@@ -2521,7 +2521,7 @@ static auto TryResolveTypedInst(ImportRefResolver& resolver,
|
||||
resolver.import_functions().Get(inst.function_id).first_decl_id());
|
||||
|
||||
auto specific_data = GetLocalSpecificData(resolver, inst.specific_id);
|
||||
if (resolver.HasNewWork() || !fn_val_id.has_value()) {
|
||||
if (resolver.HasNewWork()) {
|
||||
return ResolveResult::Retry();
|
||||
}
|
||||
auto fn_type_id = resolver.local_insts().Get(fn_val_id).type_id();
|
||||
@@ -4150,9 +4150,11 @@ static auto TryResolveInstCanonical(ImportRefResolver& resolver,
|
||||
CARBON_CHECK(!const_id.has_value());
|
||||
|
||||
auto inst_constant_id = resolver.import_constant_values().Get(inst_id);
|
||||
if (!inst_constant_id.has_value() || !inst_constant_id.is_constant()) {
|
||||
if (!inst_constant_id.is_constant()) {
|
||||
// TODO: Import of non-constant BindNames happens when importing `let`
|
||||
// declarations.
|
||||
CARBON_CHECK(resolver.import_insts().Is<SemIR::AnyBinding>(inst_id),
|
||||
"TryResolveInst on non-constant instruction {0}", inst_id);
|
||||
return ResolveResult::Done(SemIR::ConstantId::NotConstant);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
// CHECK:STDOUT: 'import_ir(Cpp)': {decl_id: inst<none>, is_export: false}
|
||||
// CHECK:STDOUT: import_ir_insts: {}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
|
||||
// CHECK:STDOUT: entity_names: {}
|
||||
|
||||
@@ -34,6 +34,7 @@ fn F(Form:! Core.Form()) ->? Form;
|
||||
// CHECK:STDOUT: import_ir_inst4: {ir_id: import_ir70000003, inst_id: inst50000010}
|
||||
// CHECK:STDOUT: import_ir_inst5: {ir_id: import_ir70000003, inst_id: inst50000011}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name(Core): inst70000011, name0: inst7000003B}}
|
||||
// CHECK:STDOUT: name_scope70000001: {inst: inst70000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000016}}
|
||||
|
||||
@@ -53,15 +53,18 @@ fn G(x: Cpp.X) {
|
||||
// CHECK:STDOUT: import_ir_inst3: {ir_id: import_ir(Cpp), clang_source_loc_id: clang_source_loc50000003}
|
||||
// CHECK:STDOUT: import_ir_inst4: {ir_id: import_ir(Cpp), clang_source_loc_id: clang_source_loc50000004}
|
||||
// CHECK:STDOUT: clang_decls:
|
||||
// CHECK:STDOUT: clang_decl_id50000000: {key: "namespace Carbon {\n}", inst_id: instF}
|
||||
// CHECK:STDOUT: clang_decl_id50000001: {key: "<translation unit>", inst_id: inst50000011}
|
||||
// CHECK:STDOUT: clang_decl_id50000002: {key: "struct X {}", inst_id: inst50000013}
|
||||
// CHECK:STDOUT: clang_decl_id50000003: {key: "X * _Nonnull p", inst_id: inst50000022}
|
||||
// CHECK:STDOUT: clang_decl_id50000004: {key: {decl: "void f(X x = {})", kind: normal, num_params: 0}, inst_id: inst5000002D}
|
||||
// CHECK:STDOUT: clang_decl_id50000005: {key: {decl: "inline void f__carbon_thunk()", kind: normal, num_params: 0}, inst_id: inst50000030}
|
||||
// CHECK:STDOUT: clang_decl_id50000006: {key: {decl: "void f(X x = {})", kind: normal, num_params: 1}, inst_id: inst5000003B}
|
||||
// CHECK:STDOUT: clang_decl_id50000007: {key: {decl: "inline void f__carbon_thunk(X * _Nonnull x)", kind: normal, num_params: 1}, inst_id: inst50000043}
|
||||
// CHECK:STDOUT: clang_decl_id50000008: {key: "X * _Nonnull global", inst_id: inst5000004E}
|
||||
// CHECK:STDOUT: clang_decl_id50000000: {key: {decl: "namespace Carbon {\n}"}, inst_id: instF}
|
||||
// CHECK:STDOUT: clang_decl_id50000001: {key: {decl: "<translation unit>"}, inst_id: inst50000011}
|
||||
// CHECK:STDOUT: clang_decl_id50000002: {key: {decl: "struct X {}"}, inst_id: inst50000013}
|
||||
// CHECK:STDOUT: clang_decl_id50000003: {key: {decl: "X * _Nonnull p"}, inst_id: inst50000022}
|
||||
// CHECK:STDOUT: clang_decl_id50000004: {key: {decl: "void f(X x = {})", clang_decl_signature_id: clang_decl_signature_id50000000}, inst_id: inst5000002D}
|
||||
// CHECK:STDOUT: clang_decl_id50000005: {key: {decl: "inline void f__carbon_thunk()", clang_decl_signature_id: clang_decl_signature_id50000000}, inst_id: inst50000030}
|
||||
// CHECK:STDOUT: clang_decl_id50000006: {key: {decl: "void f(X x = {})", clang_decl_signature_id: clang_decl_signature_id50000001}, inst_id: inst5000003B}
|
||||
// CHECK:STDOUT: clang_decl_id50000007: {key: {decl: "inline void f__carbon_thunk(X * _Nonnull x)", clang_decl_signature_id: clang_decl_signature_id50000001}, inst_id: inst50000043}
|
||||
// CHECK:STDOUT: clang_decl_id50000008: {key: {decl: "X * _Nonnull global"}, inst_id: inst5000004E}
|
||||
// CHECK:STDOUT: clang_decl_signatures:
|
||||
// CHECK:STDOUT: clang_decl_signature_id50000000: {kind: normal, num_params: 0}
|
||||
// CHECK:STDOUT: clang_decl_signature_id50000001: {kind: normal, num_params: 1, modes: [value]}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name(Cpp): inst50000011, name0: inst5000001C}}
|
||||
// CHECK:STDOUT: name_scope50000001: {inst: inst50000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name2: inst50000013, name3: inst5000002A, name4: inst5000004E}}
|
||||
|
||||
@@ -37,6 +37,7 @@ fn B() {
|
||||
// CHECK:STDOUT: 'import_ir(Cpp)': {decl_id: inst<none>, is_export: false}
|
||||
// CHECK:STDOUT: import_ir_insts: {}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name0: inst50000010}}
|
||||
// CHECK:STDOUT: entity_names: {}
|
||||
@@ -141,6 +142,7 @@ fn B() {
|
||||
// CHECK:STDOUT: import_ir_inst0: {ir_id: import_ir70000002, inst_id: inst50000010}
|
||||
// CHECK:STDOUT: import_ir_inst1: {ir_id: import_ir70000002, inst_id: inst50000010}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name1: inst70000011, name0: inst70000012}}
|
||||
// CHECK:STDOUT: name_scope70000001: {inst: inst70000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000017}}
|
||||
|
||||
@@ -37,6 +37,7 @@ fn B() {
|
||||
// CHECK:STDOUT: 'import_ir(Cpp)': {decl_id: inst<none>, is_export: false}
|
||||
// CHECK:STDOUT: import_ir_insts: {}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name0: inst50000010}}
|
||||
// CHECK:STDOUT: entity_names: {}
|
||||
@@ -160,6 +161,7 @@ fn B() {
|
||||
// CHECK:STDOUT: import_ir_inst0: {ir_id: import_ir70000002, inst_id: inst50000010}
|
||||
// CHECK:STDOUT: import_ir_inst1: {ir_id: import_ir70000002, inst_id: inst50000010}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name1: inst70000011, name0: inst70000012}}
|
||||
// CHECK:STDOUT: name_scope70000001: {inst: inst70000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name1: inst70000017}}
|
||||
|
||||
@@ -46,6 +46,7 @@ fn UseLocalCopy[T:! Copy](_: T.T1, _: T.T2) {}
|
||||
// CHECK:STDOUT: 'import_ir(Cpp)': {decl_id: inst<none>, is_export: false}
|
||||
// CHECK:STDOUT: import_ir_insts: {}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name1: inst60000010}}
|
||||
// CHECK:STDOUT: name_scope60000001: {inst: inst60000010, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name(SelfType): inst60000012}}
|
||||
@@ -210,6 +211,7 @@ fn UseLocalCopy[T:! Copy](_: T.T1, _: T.T2) {}
|
||||
// CHECK:STDOUT: import_ir_instB: {ir_id: import_ir50000002, inst_id: inst6000001C}
|
||||
// CHECK:STDOUT: import_ir_instC: {ir_id: import_ir50000002, inst_id: inst6000001C}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name0: inst50000011, name1: inst50000012, name4: inst50000060, name7: inst50000095}}
|
||||
// CHECK:STDOUT: name_scope50000001: {inst: inst50000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name6: inst50000025}}
|
||||
|
||||
@@ -255,6 +255,7 @@ fn Foo[T:! type](p: T*) -> (T*, ()) {
|
||||
// CHECK:STDOUT: import_ir_instD6: {ir_id: import_ir78000004, inst_id: inst70000259}
|
||||
// CHECK:STDOUT: import_ir_instD7: {ir_id: import_ir78000004, inst_id: inst7000025A}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name(Core): inst78000011, name0: inst7800003E}}
|
||||
// CHECK:STDOUT: name_scope78000001: {inst: inst78000011, parent_scope: name_scope0, has_error: false, extended_scopes: [], names: {name3: inst7800004E}}
|
||||
|
||||
@@ -28,6 +28,7 @@ fn Foo(n: ()) -> ((), ()) {
|
||||
// CHECK:STDOUT: 'import_ir(Cpp)': {decl_id: inst<none>, is_export: false}
|
||||
// CHECK:STDOUT: import_ir_insts: {}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {name0: inst5000002A}}
|
||||
// CHECK:STDOUT: entity_names:
|
||||
|
||||
@@ -201,7 +201,8 @@ fn UseZ() -> Cpp.A.Z {
|
||||
// CHECK:STDOUT: %.loc15_12.2: ref %X = temporary %.loc15_12.1, %F.call
|
||||
// CHECK:STDOUT: %g.ref: %X.g.cpp_overload_set.type = name_ref g, imports.%X.g.cpp_overload_set.value [concrete = constants.%X.g.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %.loc15_12.2, %g.ref
|
||||
// CHECK:STDOUT: %X.g.call: init %i32 = call imports.%X.g.decl(%.loc15_12.2)
|
||||
// CHECK:STDOUT: %.loc15_12.3: %X = acquire_value %.loc15_12.2
|
||||
// CHECK:STDOUT: %X.g.call: init %i32 = call imports.%X.g.decl(%.loc15_12.3)
|
||||
// CHECK:STDOUT: %X.cpp_destructor.bound: <bound method> = bound_method %.loc15_12.2, constants.%X.cpp_destructor
|
||||
// CHECK:STDOUT: %X.cpp_destructor.call: init %empty_tuple.type = call %X.cpp_destructor.bound(%.loc15_12.2)
|
||||
// CHECK:STDOUT: return %X.g.call
|
||||
|
||||
+24
-16
@@ -288,12 +288,14 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
|
||||
// CHECK:STDOUT: %const_ref_ref_this__carbon_thunk: %const_ref_ref_this__carbon_thunk.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.cpp_overload_set.type: type = cpp_overload_set_type @HasQualifiers.plain.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.cpp_overload_set.value: %HasQualifiers.plain.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.plain.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.type: type = fn_type @HasQualifiers.plain [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.plain: %HasQualifiers.plain.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.type.b9c87a.1: type = fn_type @HasQualifiers.plain.1 [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.4829ab.1: %HasQualifiers.plain.type.b9c87a.1 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.ref_this.cpp_overload_set.type: type = cpp_overload_set_type @HasQualifiers.ref_this.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.ref_this.cpp_overload_set.value: %HasQualifiers.ref_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.ref_this.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.ref_this.type: type = fn_type @HasQualifiers.ref_this [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.ref_this: %HasQualifiers.ref_this.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.type.b9c87a.2: type = fn_type @HasQualifiers.plain.2 [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.4829ab.2: %HasQualifiers.plain.type.b9c87a.2 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.ref_ref_this.cpp_overload_set.type: type = cpp_overload_set_type @HasQualifiers.ref_ref_this.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %HasQualifiers.ref_ref_this.cpp_overload_set.value: %HasQualifiers.ref_ref_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.ref_ref_this.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %ref_ref_this__carbon_thunk.type: type = fn_type @ref_ref_this__carbon_thunk [concrete]
|
||||
@@ -337,7 +339,7 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.cpp_overload_set.value: %HasQualifiers.plain.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.plain.cpp_overload_set [concrete = constants.%HasQualifiers.plain.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.decl: %HasQualifiers.plain.type = fn_decl @HasQualifiers.plain [concrete = constants.%HasQualifiers.plain] {
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.decl.020d0d.1: %HasQualifiers.plain.type.b9c87a.1 = fn_decl @HasQualifiers.plain.1 [concrete = constants.%HasQualifiers.plain.4829ab.1] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
@@ -348,6 +350,11 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.decl.020d0d.2: %HasQualifiers.plain.type.b9c87a.2 = fn_decl @HasQualifiers.plain.2 [concrete = constants.%HasQualifiers.plain.4829ab.2] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %HasQualifiers.ref_ref_this.cpp_overload_set.value: %HasQualifiers.ref_ref_this.cpp_overload_set.type = cpp_overload_set_value @HasQualifiers.ref_ref_this.cpp_overload_set [concrete = constants.%HasQualifiers.ref_ref_this.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %ref_ref_this__carbon_thunk.decl: %ref_ref_this__carbon_thunk.type = fn_decl @ref_ref_this__carbon_thunk [concrete = constants.%ref_ref_this__carbon_thunk] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
@@ -389,7 +396,7 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
|
||||
// CHECK:STDOUT: %.loc14: ref %HasQualifiers = deref %p.ref.loc14
|
||||
// CHECK:STDOUT: %plain.ref.loc14: %HasQualifiers.plain.cpp_overload_set.type = name_ref plain, imports.%HasQualifiers.plain.cpp_overload_set.value [concrete = constants.%HasQualifiers.plain.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %bound_method.loc14: <bound method> = bound_method %.loc14, %plain.ref.loc14
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.call.loc14: init %empty_tuple.type = call imports.%HasQualifiers.plain.decl(%.loc14)
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.call.loc14: init %empty_tuple.type = call imports.%HasQualifiers.plain.decl.020d0d.1(%.loc14)
|
||||
// CHECK:STDOUT: %p.ref.loc15: %ptr.ec3 = name_ref p, %p
|
||||
// CHECK:STDOUT: %.loc15: ref %HasQualifiers = deref %p.ref.loc15
|
||||
// CHECK:STDOUT: %ref_this.ref: %HasQualifiers.ref_this.cpp_overload_set.type = name_ref ref_this, imports.%HasQualifiers.ref_this.cpp_overload_set.value [concrete = constants.%HasQualifiers.ref_this.cpp_overload_set.value]
|
||||
@@ -413,7 +420,8 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
|
||||
// CHECK:STDOUT: %.loc19_8.2: ref %HasQualifiers = temporary %.loc19_8.1, %Make.call.loc19
|
||||
// CHECK:STDOUT: %plain.ref.loc19: %HasQualifiers.plain.cpp_overload_set.type = name_ref plain, imports.%HasQualifiers.plain.cpp_overload_set.value [concrete = constants.%HasQualifiers.plain.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %bound_method.loc19: <bound method> = bound_method %.loc19_8.2, %plain.ref.loc19
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.call.loc19: init %empty_tuple.type = call imports.%HasQualifiers.plain.decl(%.loc19_8.2)
|
||||
// CHECK:STDOUT: %.loc19_8.3: %HasQualifiers = acquire_value %.loc19_8.2
|
||||
// CHECK:STDOUT: %HasQualifiers.plain.call.loc19: init %empty_tuple.type = call imports.%HasQualifiers.plain.decl.020d0d.2(%.loc19_8.3)
|
||||
// CHECK:STDOUT: %Make.ref.loc20: %Make.type = name_ref Make, file.%Make.decl [concrete = constants.%Make]
|
||||
// CHECK:STDOUT: %.loc20_8.1: ref %HasQualifiers = temporary_storage
|
||||
// CHECK:STDOUT: %Make.call.loc20: init %HasQualifiers to %.loc20_8.1 = call %Make.ref.loc20()
|
||||
@@ -640,8 +648,8 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
|
||||
// CHECK:STDOUT: %F__carbon_thunk: %F__carbon_thunk.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.G.cpp_overload_set.type: type = cpp_overload_set_type @ExplicitObjectParam.G.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.G.cpp_overload_set.value: %ExplicitObjectParam.G.cpp_overload_set.type = cpp_overload_set_value @ExplicitObjectParam.G.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.G.type: type = fn_type @ExplicitObjectParam.G [concrete]
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.G: %ExplicitObjectParam.G.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %G__carbon_thunk.type: type = fn_type @G__carbon_thunk [concrete]
|
||||
// CHECK:STDOUT: %G__carbon_thunk: %G__carbon_thunk.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.H.cpp_overload_set.type: type = cpp_overload_set_type @ExplicitObjectParam.H.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.H.cpp_overload_set.value: %ExplicitObjectParam.H.cpp_overload_set.type = cpp_overload_set_value @ExplicitObjectParam.H.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %ptr.289: type = ptr_type %Another [concrete]
|
||||
@@ -664,7 +672,7 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.G.cpp_overload_set.value: %ExplicitObjectParam.G.cpp_overload_set.type = cpp_overload_set_value @ExplicitObjectParam.G.cpp_overload_set [concrete = constants.%ExplicitObjectParam.G.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.G.decl: %ExplicitObjectParam.G.type = fn_decl @ExplicitObjectParam.G [concrete = constants.%ExplicitObjectParam.G] {
|
||||
// CHECK:STDOUT: %G__carbon_thunk.decl: %G__carbon_thunk.type = fn_decl @G__carbon_thunk [concrete = constants.%G__carbon_thunk] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
@@ -690,7 +698,7 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.ref.loc9: type = name_ref ExplicitObjectParam, imports.%ExplicitObjectParam.decl [concrete = constants.%ExplicitObjectParam]
|
||||
// CHECK:STDOUT: %G.ref: %ExplicitObjectParam.G.cpp_overload_set.type = name_ref G, imports.%ExplicitObjectParam.G.cpp_overload_set.value [concrete = constants.%ExplicitObjectParam.G.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %bound_method.loc9: <bound method> = bound_method %n.ref, %G.ref
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.G.call: init %empty_tuple.type = call imports.%ExplicitObjectParam.G.decl(%n.ref)
|
||||
// CHECK:STDOUT: %G__carbon_thunk.call: init %empty_tuple.type = call imports.%G__carbon_thunk.decl(%n.ref)
|
||||
// CHECK:STDOUT: %a.ref: %Another = name_ref a, %a
|
||||
// CHECK:STDOUT: %Cpp.ref.loc10: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.ref.loc10: type = name_ref ExplicitObjectParam, imports.%ExplicitObjectParam.decl [concrete = constants.%ExplicitObjectParam]
|
||||
@@ -715,11 +723,11 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
|
||||
// CHECK:STDOUT: %ptr.7f5: type = ptr_type %ExplicitObjectParam [concrete]
|
||||
// CHECK:STDOUT: %F__carbon_thunk.type.eda1ac.1: type = fn_type @F__carbon_thunk.1 [concrete]
|
||||
// CHECK:STDOUT: %F__carbon_thunk.0cd6a8.1: %F__carbon_thunk.type.eda1ac.1 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.F.type.5d25a8.2: type = fn_type @ExplicitObjectParam.F.2 [concrete]
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.F.28cf2e.2: %ExplicitObjectParam.F.type.5d25a8.2 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.289: type = ptr_type %Another [concrete]
|
||||
// CHECK:STDOUT: %F__carbon_thunk.type.eda1ac.2: type = fn_type @F__carbon_thunk.2 [concrete]
|
||||
// CHECK:STDOUT: %F__carbon_thunk.0cd6a8.2: %F__carbon_thunk.type.eda1ac.2 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.289: type = ptr_type %Another [concrete]
|
||||
// CHECK:STDOUT: %F__carbon_thunk.type.eda1ac.3: type = fn_type @F__carbon_thunk.3 [concrete]
|
||||
// CHECK:STDOUT: %F__carbon_thunk.0cd6a8.3: %F__carbon_thunk.type.eda1ac.3 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
@@ -736,12 +744,12 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.F.decl.28f5af.2: %ExplicitObjectParam.F.type.5d25a8.2 = fn_decl @ExplicitObjectParam.F.2 [concrete = constants.%ExplicitObjectParam.F.28cf2e.2] {
|
||||
// CHECK:STDOUT: %F__carbon_thunk.decl.e1b8ec.2: %F__carbon_thunk.type.eda1ac.2 = fn_decl @F__carbon_thunk.2 [concrete = constants.%F__carbon_thunk.0cd6a8.2] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %F__carbon_thunk.decl.e1b8ec.2: %F__carbon_thunk.type.eda1ac.2 = fn_decl @F__carbon_thunk.2 [concrete = constants.%F__carbon_thunk.0cd6a8.2] {
|
||||
// CHECK:STDOUT: %F__carbon_thunk.decl.e1b8ec.3: %F__carbon_thunk.type.eda1ac.3 = fn_decl @F__carbon_thunk.3 [concrete = constants.%F__carbon_thunk.0cd6a8.3] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
@@ -761,7 +769,7 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.ref.loc9: type = name_ref ExplicitObjectParam, imports.%ExplicitObjectParam.decl [concrete = constants.%ExplicitObjectParam]
|
||||
// CHECK:STDOUT: %F.ref.loc9: %ExplicitObjectParam.F.cpp_overload_set.type = name_ref F, imports.%ExplicitObjectParam.F.cpp_overload_set.value [concrete = constants.%ExplicitObjectParam.F.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %bound_method.loc9: <bound method> = bound_method %n.ref, %F.ref.loc9
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.F.call: init %empty_tuple.type = call imports.%ExplicitObjectParam.F.decl.28f5af.2(%n.ref)
|
||||
// CHECK:STDOUT: %F__carbon_thunk.call.loc9: init %empty_tuple.type = call imports.%F__carbon_thunk.decl.e1b8ec.2(%n.ref)
|
||||
// CHECK:STDOUT: %a.ref: %Another = name_ref a, %a
|
||||
// CHECK:STDOUT: %Cpp.ref.loc10: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %ExplicitObjectParam.ref.loc10: type = name_ref ExplicitObjectParam, imports.%ExplicitObjectParam.decl [concrete = constants.%ExplicitObjectParam]
|
||||
@@ -769,7 +777,7 @@ fn Call(e: Cpp.ExplicitObjectParam, n: i32, a: Cpp.Another) {
|
||||
// CHECK:STDOUT: %bound_method.loc10: <bound method> = bound_method %a.ref, %F.ref.loc10
|
||||
// CHECK:STDOUT: %.loc10: ref %Another = value_as_ref %a.ref
|
||||
// CHECK:STDOUT: %addr.loc10: %ptr.289 = addr_of %.loc10
|
||||
// CHECK:STDOUT: %F__carbon_thunk.call.loc10: init %empty_tuple.type = call imports.%F__carbon_thunk.decl.e1b8ec.2(%addr.loc10)
|
||||
// CHECK:STDOUT: %F__carbon_thunk.call.loc10: init %empty_tuple.type = call imports.%F__carbon_thunk.decl.e1b8ec.3(%addr.loc10)
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
@@ -119,7 +119,8 @@ fn G() {
|
||||
// CHECK:STDOUT: %Cpp.ref.loc10_15: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %C.ref.loc10_18: type = name_ref C, imports.%C.decl [concrete = constants.%C]
|
||||
// CHECK:STDOUT: %e.ref: %.bb7 = name_ref e, imports.%int_1.1d6 [concrete = constants.%int_1.1d6]
|
||||
// CHECK:STDOUT: %C.F.call: init %empty_tuple.type = call imports.%C.F.decl(%.loc10_11.3, %e.ref)
|
||||
// CHECK:STDOUT: %.loc10_11.4: %C = acquire_value %.loc10_11.3
|
||||
// CHECK:STDOUT: %C.F.call: init %empty_tuple.type = call imports.%C.F.decl(%.loc10_11.4, %e.ref)
|
||||
// CHECK:STDOUT: %C.cpp_destructor.bound: <bound method> = bound_method %.loc10_11.3, constants.%C.cpp_destructor
|
||||
// CHECK:STDOUT: %C.cpp_destructor.call: init %empty_tuple.type = call %C.cpp_destructor.bound(%.loc10_11.3)
|
||||
// CHECK:STDOUT: return
|
||||
|
||||
@@ -142,6 +142,110 @@ fn F(c: Cpp.C) {
|
||||
//@dump-sem-ir-end
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Move-only class as parameter type
|
||||
// ============================================================================
|
||||
|
||||
// --- move_only_param_type.h
|
||||
|
||||
struct C {
|
||||
C(C&&);
|
||||
};
|
||||
|
||||
auto foo(C) -> void;
|
||||
auto make() -> C;
|
||||
auto move(C&) -> C&&;
|
||||
|
||||
// --- pass_move_only_param_temporary.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
import Cpp library "move_only_param_type.h";
|
||||
|
||||
fn F() {
|
||||
//@dump-sem-ir-begin
|
||||
Cpp.foo(Cpp.make());
|
||||
//@dump-sem-ir-end
|
||||
}
|
||||
|
||||
// --- fail_pass_move_only_param_value.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
// CHECK:STDERR: fail_pass_move_only_param_value.carbon:[[@LINE+12]]:10: in file included here [InCppInclude]
|
||||
// CHECK:STDERR: ./move_only_param_type.h:6:6: error: call to implicitly-deleted copy constructor of 'C' [CppInteropParseError]
|
||||
// CHECK:STDERR: 6 | auto foo(C) -> void;
|
||||
// CHECK:STDERR: | ^~~
|
||||
// CHECK:STDERR: fail_pass_move_only_param_value.carbon:[[@LINE+8]]:10: in file included here [InCppInclude]
|
||||
// CHECK:STDERR: ./move_only_param_type.h:3:3: note: copy constructor is implicitly deleted because 'C' has a user-declared move constructor [CppInteropParseNote]
|
||||
// CHECK:STDERR: 3 | C(C&&);
|
||||
// CHECK:STDERR: | ^
|
||||
// CHECK:STDERR: fail_pass_move_only_param_value.carbon:[[@LINE+4]]:10: in file included here [InCppInclude]
|
||||
// CHECK:STDERR: ./move_only_param_type.h:6:11: note: passing argument to parameter here [CppInteropParseNote]
|
||||
// CHECK:STDERR: 6 | auto foo(C) -> void;
|
||||
// CHECK:STDERR: | ^
|
||||
import Cpp library "move_only_param_type.h";
|
||||
|
||||
fn F(c: Cpp.C) {
|
||||
// CHECK:STDERR: fail_pass_move_only_param_value.carbon:[[@LINE+4]]:3: note: in thunk for C++ function used here [InCppThunk]
|
||||
// CHECK:STDERR: Cpp.foo(c);
|
||||
// CHECK:STDERR: ^~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
Cpp.foo(c);
|
||||
}
|
||||
|
||||
// --- fail_pass_move_only_param_ref.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
// CHECK:STDERR: fail_pass_move_only_param_ref.carbon:[[@LINE+12]]:10: in file included here [InCppInclude]
|
||||
// CHECK:STDERR: ./move_only_param_type.h:6:6: error: call to implicitly-deleted copy constructor of 'C' [CppInteropParseError]
|
||||
// CHECK:STDERR: 6 | auto foo(C) -> void;
|
||||
// CHECK:STDERR: | ^~~
|
||||
// CHECK:STDERR: fail_pass_move_only_param_ref.carbon:[[@LINE+8]]:10: in file included here [InCppInclude]
|
||||
// CHECK:STDERR: ./move_only_param_type.h:3:3: note: copy constructor is implicitly deleted because 'C' has a user-declared move constructor [CppInteropParseNote]
|
||||
// CHECK:STDERR: 3 | C(C&&);
|
||||
// CHECK:STDERR: | ^
|
||||
// CHECK:STDERR: fail_pass_move_only_param_ref.carbon:[[@LINE+4]]:10: in file included here [InCppInclude]
|
||||
// CHECK:STDERR: ./move_only_param_type.h:6:11: note: passing argument to parameter here [CppInteropParseNote]
|
||||
// CHECK:STDERR: 6 | auto foo(C) -> void;
|
||||
// CHECK:STDERR: | ^
|
||||
import Cpp library "move_only_param_type.h";
|
||||
|
||||
fn F(ref c: Cpp.C) {
|
||||
// CHECK:STDERR: fail_pass_move_only_param_ref.carbon:[[@LINE+4]]:3: note: in thunk for C++ function used here [InCppThunk]
|
||||
// CHECK:STDERR: Cpp.foo(c);
|
||||
// CHECK:STDERR: ^~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
Cpp.foo(c);
|
||||
}
|
||||
|
||||
// --- fail_todo_pass_move_only_param_ref_by_move.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
// CHECK:STDERR: fail_todo_pass_move_only_param_ref_by_move.carbon:[[@LINE+12]]:10: in file included here [InCppInclude]
|
||||
// CHECK:STDERR: ./move_only_param_type.h:6:6: error: call to implicitly-deleted copy constructor of 'C' [CppInteropParseError]
|
||||
// CHECK:STDERR: 6 | auto foo(C) -> void;
|
||||
// CHECK:STDERR: | ^~~
|
||||
// CHECK:STDERR: fail_todo_pass_move_only_param_ref_by_move.carbon:[[@LINE+8]]:10: in file included here [InCppInclude]
|
||||
// CHECK:STDERR: ./move_only_param_type.h:3:3: note: copy constructor is implicitly deleted because 'C' has a user-declared move constructor [CppInteropParseNote]
|
||||
// CHECK:STDERR: 3 | C(C&&);
|
||||
// CHECK:STDERR: | ^
|
||||
// CHECK:STDERR: fail_todo_pass_move_only_param_ref_by_move.carbon:[[@LINE+4]]:10: in file included here [InCppInclude]
|
||||
// CHECK:STDERR: ./move_only_param_type.h:6:11: note: passing argument to parameter here [CppInteropParseNote]
|
||||
// CHECK:STDERR: 6 | auto foo(C) -> void;
|
||||
// CHECK:STDERR: | ^
|
||||
import Cpp library "move_only_param_type.h";
|
||||
|
||||
fn F(ref c: Cpp.C) {
|
||||
// CHECK:STDERR: fail_todo_pass_move_only_param_ref_by_move.carbon:[[@LINE+4]]:3: note: in thunk for C++ function used here [InCppThunk]
|
||||
// CHECK:STDERR: Cpp.foo(Cpp.move(ref c));
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
Cpp.foo(Cpp.move(ref c));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Defined class with a single data member as parameter type
|
||||
// ============================================================================
|
||||
@@ -565,6 +669,58 @@ fn F() {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- pass_move_only_param_temporary.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
|
||||
// CHECK:STDOUT: %foo.cpp_overload_set.type: type = cpp_overload_set_type @foo.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %make.cpp_overload_set.type: type = cpp_overload_set_type @make.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %make.cpp_overload_set.value: %make.cpp_overload_set.type = cpp_overload_set_value @make.cpp_overload_set [concrete]
|
||||
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
||||
// CHECK:STDOUT: %ptr.d9e: type = ptr_type %C [concrete]
|
||||
// CHECK:STDOUT: %make__carbon_thunk.type: type = fn_type @make__carbon_thunk [concrete]
|
||||
// CHECK:STDOUT: %make__carbon_thunk: %make__carbon_thunk.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %foo__carbon_thunk.type: type = fn_type @foo__carbon_thunk [concrete]
|
||||
// CHECK:STDOUT: %foo__carbon_thunk: %foo__carbon_thunk.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
|
||||
// CHECK:STDOUT: .foo = %foo.cpp_overload_set.value
|
||||
// CHECK:STDOUT: .make = %make.cpp_overload_set.value
|
||||
// CHECK:STDOUT: import Cpp//...
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %foo.cpp_overload_set.value: %foo.cpp_overload_set.type = cpp_overload_set_value @foo.cpp_overload_set [concrete = constants.%foo.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %make.cpp_overload_set.value: %make.cpp_overload_set.type = cpp_overload_set_value @make.cpp_overload_set [concrete = constants.%make.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %make__carbon_thunk.decl: %make__carbon_thunk.type = fn_decl @make__carbon_thunk [concrete = constants.%make__carbon_thunk] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %foo__carbon_thunk.decl: %foo__carbon_thunk.type = fn_decl @foo__carbon_thunk [concrete = constants.%foo__carbon_thunk] {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %Cpp.ref.loc8_3: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %foo.ref: %foo.cpp_overload_set.type = name_ref foo, imports.%foo.cpp_overload_set.value [concrete = constants.%foo.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %Cpp.ref.loc8_11: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %make.ref: %make.cpp_overload_set.type = name_ref make, imports.%make.cpp_overload_set.value [concrete = constants.%make.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: %addr.loc8_20: %ptr.d9e = addr_of %_.var
|
||||
// CHECK:STDOUT: %make__carbon_thunk.call: init %empty_tuple.type = call imports.%make__carbon_thunk.decl(%addr.loc8_20)
|
||||
// CHECK:STDOUT: %.loc8: init %C to %_.var = mark_in_place_init %make__carbon_thunk.call
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: %addr.loc8_21: %ptr.d9e = addr_of %_.var
|
||||
// CHECK:STDOUT: %foo__carbon_thunk.call: init %empty_tuple.type = call imports.%foo__carbon_thunk.decl(%addr.loc8_21)
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- import_definition_single_data_member_value_param_type.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
|
||||
@@ -338,6 +338,7 @@ fn Call() {
|
||||
// CHECK:STDOUT: %bound_method.loc10_16: <bound method> = bound_method %.loc10_7.2, %B.ref [concrete = constants.%bound_method.a5d]
|
||||
// CHECK:STDOUT: %int_1.loc10: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
|
||||
// CHECK:STDOUT: %int_2.loc10: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]
|
||||
// CHECK:STDOUT: %.loc10_7.3: %X = acquire_value %.loc10_7.2 [concrete = constants.%X.val]
|
||||
// CHECK:STDOUT: %impl.elem0.loc10_19: %.9db = impl_witness_access constants.%ImplicitAs.impl_witness.ac5, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.f1a]
|
||||
// CHECK:STDOUT: %bound_method.loc10_19.1: <bound method> = bound_method %int_1.loc10, %impl.elem0.loc10_19 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.d43]
|
||||
// CHECK:STDOUT: %specific_fn.loc10_19: <specific function> = specific_function %impl.elem0.loc10_19, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]
|
||||
@@ -352,7 +353,7 @@ fn Call() {
|
||||
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_22: init %i32 = call %bound_method.loc10_22.2(%int_2.loc10) [concrete = constants.%int_2.ef8]
|
||||
// CHECK:STDOUT: %.loc10_22.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc10_22 [concrete = constants.%int_2.ef8]
|
||||
// CHECK:STDOUT: %.loc10_22.2: %i32 = converted %int_2.loc10, %.loc10_22.1 [concrete = constants.%int_2.ef8]
|
||||
// CHECK:STDOUT: %X.B.call: init %empty_tuple.type = call imports.%X.B.decl(%.loc10_7.2, %.loc10_19.2, %.loc10_22.2)
|
||||
// CHECK:STDOUT: %X.B.call: init %empty_tuple.type = call imports.%X.B.decl(%.loc10_7.3, %.loc10_19.2, %.loc10_22.2)
|
||||
// CHECK:STDOUT: %Cpp.ref.loc11: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %X.ref.loc11: type = name_ref X, imports.%X.decl [concrete = constants.%X]
|
||||
// CHECK:STDOUT: %C.ref: %X.C.cpp_overload_set.type = name_ref C, imports.%X.C.cpp_overload_set.value [concrete = constants.%X.C.cpp_overload_set.value]
|
||||
@@ -591,13 +592,13 @@ fn Call() {
|
||||
// CHECK:STDOUT: %X.decl: type = class_decl @X [concrete = constants.%X] {} {}
|
||||
// CHECK:STDOUT: %X.B.cpp_overload_set.value: %X.B.cpp_overload_set.type = cpp_overload_set_value @X.B.cpp_overload_set [concrete = constants.%X.B.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %B__carbon_thunk.decl: %B__carbon_thunk.type = fn_decl @B__carbon_thunk [concrete = constants.%B__carbon_thunk] {
|
||||
// CHECK:STDOUT: %this.param_patt: %pattern_type.46b = ref_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %this.param_patt: %pattern_type.46b = value_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %this.patt: %pattern_type.46b = at_binding_pattern this, %this.param_patt [concrete]
|
||||
// CHECK:STDOUT: %a.param_patt: %pattern_type.7ce = value_param_pattern [concrete]
|
||||
// CHECK:STDOUT: %a.patt: %pattern_type.7ce = at_binding_pattern a, %a.param_patt [concrete]
|
||||
// CHECK:STDOUT: } {
|
||||
// CHECK:STDOUT: %this.param: ref %X = ref_param call_param0
|
||||
// CHECK:STDOUT: %this: ref %X = ref_binding this, %this.param
|
||||
// CHECK:STDOUT: %this.param: %X = value_param call_param0
|
||||
// CHECK:STDOUT: %this: %X = value_binding this, %this.param
|
||||
// CHECK:STDOUT: %a.param: %i32 = value_param call_param1
|
||||
// CHECK:STDOUT: %.1: type = splice_block %i32.2 [concrete = constants.%i32] {
|
||||
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
|
||||
@@ -756,6 +757,7 @@ fn Call() {
|
||||
// CHECK:STDOUT: %B.ref: %X.B.cpp_overload_set.type = name_ref B, imports.%X.B.cpp_overload_set.value [concrete = constants.%X.B.cpp_overload_set.value]
|
||||
// CHECK:STDOUT: %bound_method.loc11_16: <bound method> = bound_method %.loc11_7.2, %B.ref [concrete = constants.%bound_method.a5d]
|
||||
// CHECK:STDOUT: %int_1.loc11: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
|
||||
// CHECK:STDOUT: %.loc11_7.3: %X = acquire_value %.loc11_7.2 [concrete = constants.%X.val]
|
||||
// CHECK:STDOUT: %impl.elem0.loc11: %.9db = impl_witness_access constants.%ImplicitAs.impl_witness.ac5, element0 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.f1a]
|
||||
// CHECK:STDOUT: %bound_method.loc11_19.1: <bound method> = bound_method %int_1.loc11, %impl.elem0.loc11 [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.d43]
|
||||
// CHECK:STDOUT: %specific_fn.loc11: <specific function> = specific_function %impl.elem0.loc11, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]
|
||||
@@ -763,7 +765,7 @@ fn Call() {
|
||||
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11: init %i32 = call %bound_method.loc11_19.2(%int_1.loc11) [concrete = constants.%int_1.5d2]
|
||||
// CHECK:STDOUT: %.loc11_19.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc11 [concrete = constants.%int_1.5d2]
|
||||
// CHECK:STDOUT: %.loc11_19.2: %i32 = converted %int_1.loc11, %.loc11_19.1 [concrete = constants.%int_1.5d2]
|
||||
// CHECK:STDOUT: %B__carbon_thunk.call: init %empty_tuple.type = call imports.%B__carbon_thunk.decl(%.loc11_7.2, %.loc11_19.2)
|
||||
// CHECK:STDOUT: %B__carbon_thunk.call: init %empty_tuple.type = call imports.%B__carbon_thunk.decl(%.loc11_7.3, %.loc11_19.2)
|
||||
// CHECK:STDOUT: %Cpp.ref.loc12: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
|
||||
// CHECK:STDOUT: %X.ref.loc12: type = name_ref X, imports.%X.decl [concrete = constants.%X]
|
||||
// CHECK:STDOUT: %C.ref: %X.C.cpp_overload_set.type = name_ref C, imports.%X.C.cpp_overload_set.value [concrete = constants.%X.C.cpp_overload_set.value]
|
||||
@@ -821,9 +823,9 @@ fn Call() {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @GlobalNoReturn__carbon_thunk.2(%a.param: %i32, %b.param: %i32, %c.param: %i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @X.B(%self.param: ref %X, %a.param: %i32);
|
||||
// CHECK:STDOUT: fn @X.B(%self.param: %X, %a.param: %i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @B__carbon_thunk(%this.param: ref %X, %a.param: %i32);
|
||||
// CHECK:STDOUT: fn @B__carbon_thunk(%this.param: %X, %a.param: %i32);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @X.C(%a.param: %i32);
|
||||
// CHECK:STDOUT:
|
||||
|
||||
@@ -31,7 +31,7 @@ auto foo(short a) -> void;
|
||||
// CHECK:STDOUT: | `-DeclRefExpr {{0x[a-f0-9]+}} <col:6> 'short * _Nonnull':'short *' lvalue ParmVar {{0x[a-f0-9]+}} 'a' 'short * _Nonnull':'short *'
|
||||
// CHECK:STDOUT: |-AlwaysInlineAttr {{0x[a-f0-9]+}} <<invalid sloc>> Implicit always_inline
|
||||
// CHECK:STDOUT: |-InternalLinkageAttr {{0x[a-f0-9]+}} <<invalid sloc>> Implicit
|
||||
// CHECK:STDOUT: `-AsmLabelAttr {{0x[a-f0-9]+}} <col:6> Implicit "_Z3foos.carbon_thunk"
|
||||
// CHECK:STDOUT: `-AsmLabelAttr {{0x[a-f0-9]+}} <col:6> Implicit "_Z3foos.carbon_thunk._"
|
||||
// CHECK:STDOUT: TranslationUnitDecl {{0x[a-f0-9]+}} <<invalid sloc>> <invalid sloc>
|
||||
// CHECK:STDOUT: |-NamespaceDecl {{0x[a-f0-9]+}} <<invalid sloc>> <invalid sloc> Carbon
|
||||
|
||||
@@ -58,7 +58,7 @@ auto foo() -> short;
|
||||
// CHECK:STDOUT: | `-DeclRefExpr {{0x[a-f0-9]+}} <col:6> 'short * _Nonnull':'short *' lvalue ParmVar {{0x[a-f0-9]+}} 'return' 'short * _Nonnull':'short *'
|
||||
// CHECK:STDOUT: |-AlwaysInlineAttr {{0x[a-f0-9]+}} <<invalid sloc>> Implicit always_inline
|
||||
// CHECK:STDOUT: |-InternalLinkageAttr {{0x[a-f0-9]+}} <<invalid sloc>> Implicit
|
||||
// CHECK:STDOUT: `-AsmLabelAttr {{0x[a-f0-9]+}} <col:6> Implicit "_Z3foov.carbon_thunk"
|
||||
// CHECK:STDOUT: `-AsmLabelAttr {{0x[a-f0-9]+}} <col:6> Implicit "_Z3foov.carbon_thunk."
|
||||
|
||||
// --- import_return_thunk_required.carbon
|
||||
|
||||
|
||||
+31
-31
@@ -1128,14 +1128,14 @@ fn TestUnaryOperators(a: Cpp.Int16, b: Cpp.Int32) {
|
||||
// CHECK:STDOUT: %.0d7: type = fn_type_with_self_type %Negate.WithSelf.Op.type.899, %Negate.facet.758 [symbolic]
|
||||
// CHECK:STDOUT: %impl.elem1.ec8: %.0d7 = impl_witness_access %Negate.lookup_impl_witness.783, element1 [symbolic]
|
||||
// CHECK:STDOUT: %specific_impl_fn.f22: <specific function> = specific_impl_function %impl.elem1.ec8, @Negate.WithSelf.Op(%Negate.facet.758) [symbolic]
|
||||
// CHECK:STDOUT: %Int32.cpp_operator.type.49e401.16: type = fn_type @Int32.cpp_operator.16 [concrete]
|
||||
// CHECK:STDOUT: %Int32.cpp_operator.0010d3.16: %Int32.cpp_operator.type.49e401.16 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %custom_witness.934: <witness> = custom_witness (%Int32.cpp_operator.0010d3.16), @Inc [concrete]
|
||||
// CHECK:STDOUT: %Inc.facet.390: %Inc.type = facet_value %Int32, (%custom_witness.934) [concrete]
|
||||
// CHECK:STDOUT: %Int32.cpp_operator.type.49e401.17: type = fn_type @Int32.cpp_operator.17 [concrete]
|
||||
// CHECK:STDOUT: %Int32.cpp_operator.0010d3.17: %Int32.cpp_operator.type.49e401.17 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %custom_witness.99f: <witness> = custom_witness (%Int32.cpp_operator.0010d3.17), @Dec [concrete]
|
||||
// CHECK:STDOUT: %Dec.facet.961: %Dec.type = facet_value %Int32, (%custom_witness.99f) [concrete]
|
||||
// CHECK:STDOUT: %Int32.Op.type.68b858.18: type = fn_type @Int32.Op.18 [concrete]
|
||||
// CHECK:STDOUT: %Int32.Op.6afff1.18: %Int32.Op.type.68b858.18 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %custom_witness.50d: <witness> = custom_witness (%Int32.Op.6afff1.18), @Inc [concrete]
|
||||
// CHECK:STDOUT: %Inc.facet.9db: %Inc.type = facet_value %Int32, (%custom_witness.50d) [concrete]
|
||||
// CHECK:STDOUT: %Int32.Op.type.68b858.19: type = fn_type @Int32.Op.19 [concrete]
|
||||
// CHECK:STDOUT: %Int32.Op.6afff1.19: %Int32.Op.type.68b858.19 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %custom_witness.e76: <witness> = custom_witness (%Int32.Op.6afff1.19), @Dec [concrete]
|
||||
// CHECK:STDOUT: %Dec.facet.bed: %Dec.type = facet_value %Int32, (%custom_witness.e76) [concrete]
|
||||
// CHECK:STDOUT: %facet_type.89a: type = facet_type <@Destroy & @Negate where %impl.elem0.f00 = %Int64> [concrete]
|
||||
// CHECK:STDOUT: %Int16.Op.type.180c8b.18: type = fn_type @Int16.Op.18 [concrete]
|
||||
// CHECK:STDOUT: %Int16.Op.c3e49c.18: %Int16.Op.type.180c8b.18 = struct_value () [concrete]
|
||||
@@ -1143,9 +1143,9 @@ fn TestUnaryOperators(a: Cpp.Int16, b: Cpp.Int32) {
|
||||
// CHECK:STDOUT: %facet_value.70a: %facet_type.89a = facet_value %Int16, (%custom_witness.e5b, %custom_witness.e58) [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.c49: type = pattern_type %facet_type.89a [concrete]
|
||||
// CHECK:STDOUT: %facet_type.d5d: type = facet_type <@Destroy & @Negate where %impl.elem0.f00 = %Int32> [concrete]
|
||||
// CHECK:STDOUT: %Int32.Op.type.68b858.18: type = fn_type @Int32.Op.18 [concrete]
|
||||
// CHECK:STDOUT: %Int32.Op.6afff1.18: %Int32.Op.type.68b858.18 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %custom_witness.e8a: <witness> = custom_witness (%Int32, %Int32.Op.6afff1.18), @Negate [concrete]
|
||||
// CHECK:STDOUT: %Int32.Op.type.68b858.20: type = fn_type @Int32.Op.20 [concrete]
|
||||
// CHECK:STDOUT: %Int32.Op.6afff1.20: %Int32.Op.type.68b858.20 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %custom_witness.e8a: <witness> = custom_witness (%Int32, %Int32.Op.6afff1.20), @Negate [concrete]
|
||||
// CHECK:STDOUT: %facet_value.396: %facet_type.d5d = facet_value %Int32, (%custom_witness.ce1, %custom_witness.e8a) [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.0ec: type = pattern_type %facet_type.d5d [concrete]
|
||||
// CHECK:STDOUT: %complete_type.f1c: <witness> = complete_type_witness %AddWith.type.344 [concrete]
|
||||
@@ -1313,10 +1313,10 @@ fn TestUnaryOperators(a: Cpp.Int16, b: Cpp.Int32) {
|
||||
// CHECK:STDOUT: %.384: type = fn_type_with_self_type %DivAssignWith.WithSelf.Op.type.646, %DivAssignWith.facet.d3b [concrete]
|
||||
// CHECK:STDOUT: %ModAssignWith.WithSelf.Op.type.a34: type = fn_type @ModAssignWith.WithSelf.Op, @ModAssignWith.WithSelf(%Int32, %ModAssignWith.facet.1c6) [concrete]
|
||||
// CHECK:STDOUT: %.ee0: type = fn_type_with_self_type %ModAssignWith.WithSelf.Op.type.a34, %ModAssignWith.facet.1c6 [concrete]
|
||||
// CHECK:STDOUT: %Inc.WithSelf.Op.type.eaa: type = fn_type @Inc.WithSelf.Op, @Inc.WithSelf(%Inc.facet.390) [concrete]
|
||||
// CHECK:STDOUT: %.696: type = fn_type_with_self_type %Inc.WithSelf.Op.type.eaa, %Inc.facet.390 [concrete]
|
||||
// CHECK:STDOUT: %Dec.WithSelf.Op.type.6fb: type = fn_type @Dec.WithSelf.Op, @Dec.WithSelf(%Dec.facet.961) [concrete]
|
||||
// CHECK:STDOUT: %.cdd: type = fn_type_with_self_type %Dec.WithSelf.Op.type.6fb, %Dec.facet.961 [concrete]
|
||||
// CHECK:STDOUT: %Inc.WithSelf.Op.type.755: type = fn_type @Inc.WithSelf.Op, @Inc.WithSelf(%Inc.facet.9db) [concrete]
|
||||
// CHECK:STDOUT: %.cfd3: type = fn_type_with_self_type %Inc.WithSelf.Op.type.755, %Inc.facet.9db [concrete]
|
||||
// CHECK:STDOUT: %Dec.WithSelf.Op.type.e71: type = fn_type @Dec.WithSelf.Op, @Dec.WithSelf(%Dec.facet.bed) [concrete]
|
||||
// CHECK:STDOUT: %.b6e: type = fn_type_with_self_type %Dec.WithSelf.Op.type.e71, %Dec.facet.bed [concrete]
|
||||
// CHECK:STDOUT: %Negate.facet.0a5: %Negate.type = facet_value %Int16, (%custom_witness.e58) [concrete]
|
||||
// CHECK:STDOUT: %Negate.WithSelf.Op.type.d7d: type = fn_type @Negate.WithSelf.Op, @Negate.WithSelf(%Negate.facet.0a5) [concrete]
|
||||
// CHECK:STDOUT: %.3e7: type = fn_type_with_self_type %Negate.WithSelf.Op.type.d7d, %Negate.facet.0a5 [concrete]
|
||||
@@ -3763,32 +3763,32 @@ fn TestUnaryOperators(a: Cpp.Int16, b: Cpp.Int32) {
|
||||
// CHECK:STDOUT: %pattern_type.loc294_22 => constants.%pattern_type.ece
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @TestInc(constants.%Inc.facet.390) {
|
||||
// CHECK:STDOUT: %T.loc278_13.1 => constants.%Inc.facet.390
|
||||
// CHECK:STDOUT: specific @TestInc(constants.%Inc.facet.9db) {
|
||||
// CHECK:STDOUT: %T.loc278_13.1 => constants.%Inc.facet.9db
|
||||
// CHECK:STDOUT: %T.as_type.loc278_33.1 => constants.%Int32
|
||||
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.9c9
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !definition:
|
||||
// CHECK:STDOUT: %require_complete => constants.%complete_type.357
|
||||
// CHECK:STDOUT: %Inc.WithSelf.Op.type => constants.%Inc.WithSelf.Op.type.eaa
|
||||
// CHECK:STDOUT: %.loc280 => constants.%.696
|
||||
// CHECK:STDOUT: %Inc.lookup_impl_witness => constants.%custom_witness.934
|
||||
// CHECK:STDOUT: %impl.elem0.loc280_3.2 => constants.%Int32.cpp_operator.0010d3.16
|
||||
// CHECK:STDOUT: %specific_impl_fn.loc280_3.2 => constants.%Int32.cpp_operator.0010d3.16
|
||||
// CHECK:STDOUT: %Inc.WithSelf.Op.type => constants.%Inc.WithSelf.Op.type.755
|
||||
// CHECK:STDOUT: %.loc280 => constants.%.cfd3
|
||||
// CHECK:STDOUT: %Inc.lookup_impl_witness => constants.%custom_witness.50d
|
||||
// CHECK:STDOUT: %impl.elem0.loc280_3.2 => constants.%Int32.Op.6afff1.18
|
||||
// CHECK:STDOUT: %specific_impl_fn.loc280_3.2 => constants.%Int32.Op.6afff1.18
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @TestDec(constants.%Dec.facet.961) {
|
||||
// CHECK:STDOUT: %T.loc284_13.1 => constants.%Dec.facet.961
|
||||
// CHECK:STDOUT: specific @TestDec(constants.%Dec.facet.bed) {
|
||||
// CHECK:STDOUT: %T.loc284_13.1 => constants.%Dec.facet.bed
|
||||
// CHECK:STDOUT: %T.as_type.loc284_33.1 => constants.%Int32
|
||||
// CHECK:STDOUT: %pattern_type => constants.%pattern_type.9c9
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !definition:
|
||||
// CHECK:STDOUT: %require_complete => constants.%complete_type.357
|
||||
// CHECK:STDOUT: %Dec.WithSelf.Op.type => constants.%Dec.WithSelf.Op.type.6fb
|
||||
// CHECK:STDOUT: %.loc286 => constants.%.cdd
|
||||
// CHECK:STDOUT: %Dec.lookup_impl_witness => constants.%custom_witness.99f
|
||||
// CHECK:STDOUT: %impl.elem0.loc286_3.2 => constants.%Int32.cpp_operator.0010d3.17
|
||||
// CHECK:STDOUT: %specific_impl_fn.loc286_3.2 => constants.%Int32.cpp_operator.0010d3.17
|
||||
// CHECK:STDOUT: %Dec.WithSelf.Op.type => constants.%Dec.WithSelf.Op.type.e71
|
||||
// CHECK:STDOUT: %.loc286 => constants.%.b6e
|
||||
// CHECK:STDOUT: %Dec.lookup_impl_witness => constants.%custom_witness.e76
|
||||
// CHECK:STDOUT: %impl.elem0.loc286_3.2 => constants.%Int32.Op.6afff1.19
|
||||
// CHECK:STDOUT: %specific_impl_fn.loc286_3.2 => constants.%Int32.Op.6afff1.19
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @TestNegate(constants.%Destroy.facet.b0a, constants.%facet_value.70a) {
|
||||
@@ -3834,8 +3834,8 @@ fn TestUnaryOperators(a: Cpp.Int16, b: Cpp.Int32) {
|
||||
// CHECK:STDOUT: %Negate.facet => constants.%Negate.facet.3c9
|
||||
// CHECK:STDOUT: %Negate.WithSelf.Op.type => constants.%Negate.WithSelf.Op.type.1bc
|
||||
// CHECK:STDOUT: %.loc296_3.3 => constants.%.19b
|
||||
// CHECK:STDOUT: %impl.elem1.loc296_3.2 => constants.%Int32.Op.6afff1.18
|
||||
// CHECK:STDOUT: %specific_impl_fn.loc296_3.3 => constants.%Int32.Op.6afff1.18
|
||||
// CHECK:STDOUT: %impl.elem1.loc296_3.2 => constants.%Int32.Op.6afff1.20
|
||||
// CHECK:STDOUT: %specific_impl_fn.loc296_3.3 => constants.%Int32.Op.6afff1.20
|
||||
// CHECK:STDOUT: %Destroy.WithSelf.Op.type => constants.%Destroy.WithSelf.Op.type.2e1
|
||||
// CHECK:STDOUT: %.loc296_3.4 => constants.%.e6c
|
||||
// CHECK:STDOUT: %Destroy.lookup_impl_witness => constants.%custom_witness.ce1
|
||||
|
||||
@@ -175,8 +175,7 @@ fn TestDerefFail(not_ptr: Cpp.NotAPtr) {
|
||||
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %int_ptr.ref, %impl.elem1
|
||||
// CHECK:STDOUT: %Op.ref.loc13_43: %ConstDeref.cpp_operator.type = name_ref Op, imports.%ConstDeref.cpp_operator.decl [concrete = constants.%ConstDeref.cpp_operator]
|
||||
// CHECK:STDOUT: %ConstDeref.cpp_operator.bound: <bound method> = bound_method %int_ptr.ref, %Op.ref.loc13_43
|
||||
// CHECK:STDOUT: %.loc13: %ConstDeref = acquire_value %int_ptr.ref
|
||||
// CHECK:STDOUT: %operator_Star__carbon_thunk.call: ref %i32 = call imports.%operator_Star__carbon_thunk.decl(%.loc13)
|
||||
// CHECK:STDOUT: %operator_Star__carbon_thunk.call: ref %i32 = call imports.%operator_Star__carbon_thunk.decl(%int_ptr.ref)
|
||||
// CHECK:STDOUT: return %operator_Star__carbon_thunk.call
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
+27
-15
@@ -1189,6 +1189,7 @@ fn F() {
|
||||
// CHECK:STDOUT: %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]
|
||||
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
|
||||
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete]
|
||||
// CHECK:STDOUT: %i32.builtin: type = int_type signed, %int_32 [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.7ce: type = pattern_type %i32 [concrete]
|
||||
// CHECK:STDOUT: %operator_LessLess__carbon_thunk.type: type = fn_type @operator_LessLess__carbon_thunk [concrete]
|
||||
// CHECK:STDOUT: %operator_LessLess__carbon_thunk: %operator_LessLess__carbon_thunk.type = struct_value () [concrete]
|
||||
@@ -1252,8 +1253,12 @@ fn F() {
|
||||
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.bound.577: <bound method> = bound_method %int_42.20e, %Core.IntLiteral.as.ImplicitAs.impl.Convert.f1a [concrete]
|
||||
// CHECK:STDOUT: %bound_method.cd5: <bound method> = bound_method %int_42.20e, %Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn [concrete]
|
||||
// CHECK:STDOUT: %int_42.c68: %i32 = int_value 42 [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.type: type = fn_type @Destroy.Op [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op: %Destroy.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %.1a9: ref %i32 = temporary invalid, %int_42.c68 [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.type.bae255.2: type = fn_type @Destroy.Op.loc48_30.2 [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.651ba6.2: %Destroy.Op.type.bae255.2 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.bound: <bound method> = bound_method %.1a9, %Destroy.Op.651ba6.2 [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.type.bae255.3: type = fn_type @Destroy.Op.loc45 [concrete]
|
||||
// CHECK:STDOUT: %Destroy.Op.651ba6.3: %Destroy.Op.type.bae255.3 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %C.cpp_destructor.type: type = fn_type @C.cpp_destructor [concrete]
|
||||
// CHECK:STDOUT: %C.cpp_destructor: %C.cpp_destructor.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %C.Op.type: type = fn_type @C.Op [concrete]
|
||||
@@ -1875,24 +1880,26 @@ fn F() {
|
||||
// CHECK:STDOUT: %specific_fn.loc48: <specific function> = specific_function %impl.elem0.loc48, @Core.IntLiteral.as.ImplicitAs.impl.Convert(constants.%int_32) [concrete = constants.%Core.IntLiteral.as.ImplicitAs.impl.Convert.specific_fn]
|
||||
// CHECK:STDOUT: %bound_method.loc48_30.2: <bound method> = bound_method %int_42, %specific_fn.loc48 [concrete = constants.%bound_method.cd5]
|
||||
// CHECK:STDOUT: %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc48: init %i32 = call %bound_method.loc48_30.2(%int_42) [concrete = constants.%int_42.c68]
|
||||
// CHECK:STDOUT: %.loc48_30.1: %i32 = value_of_initializer %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc48 [concrete = constants.%int_42.c68]
|
||||
// CHECK:STDOUT: %.loc48_30.2: %i32 = converted %int_42, %.loc48_30.1 [concrete = constants.%int_42.c68]
|
||||
// CHECK:STDOUT: %C.cpp_operator.call: init %i32 = call %C.cpp_operator.bound(%c1.ref.loc48, %.loc48_30.2)
|
||||
// CHECK:STDOUT: %.loc48_30.1: init %i32 = converted %int_42, %Core.IntLiteral.as.ImplicitAs.impl.Convert.call.loc48 [concrete = constants.%int_42.c68]
|
||||
// CHECK:STDOUT: %.loc48_30.2: ref %i32 = temporary_storage
|
||||
// CHECK:STDOUT: %.loc48_30.3: ref %i32 = temporary %.loc48_30.2, %.loc48_30.1 [concrete = constants.%.1a9]
|
||||
// CHECK:STDOUT: %C.cpp_operator.call: init %i32 = call %C.cpp_operator.bound(%c1.ref.loc48, %.loc48_30.3)
|
||||
// CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32]
|
||||
// CHECK:STDOUT: %.loc48_32.1: %i32 = value_of_initializer %C.cpp_operator.call
|
||||
// CHECK:STDOUT: %.loc48_32.2: %i32 = converted %C.cpp_operator.call, %.loc48_32.1
|
||||
// CHECK:STDOUT: %index: %i32 = value_binding index, %.loc48_32.2
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc45: <bound method> = bound_method %.loc45_44.3, constants.%Destroy.Op
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc48: init %empty_tuple.type = call constants.%Destroy.Op.bound(constants.%.1a9)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc45: <bound method> = bound_method %.loc45_44.3, constants.%Destroy.Op.651ba6.3
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc45: init %empty_tuple.type = call %Destroy.Op.bound.loc45(%.loc45_44.3)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc44: <bound method> = bound_method %.loc44_47.3, constants.%Destroy.Op
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc44: <bound method> = bound_method %.loc44_47.3, constants.%Destroy.Op.651ba6.3
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc44: init %empty_tuple.type = call %Destroy.Op.bound.loc44(%.loc44_47.3)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc43: <bound method> = bound_method %.loc43_35.3, constants.%Destroy.Op
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc43: <bound method> = bound_method %.loc43_35.3, constants.%Destroy.Op.651ba6.3
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc43: init %empty_tuple.type = call %Destroy.Op.bound.loc43(%.loc43_35.3)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc42: <bound method> = bound_method %.loc42_38.3, constants.%Destroy.Op
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc42: <bound method> = bound_method %.loc42_38.3, constants.%Destroy.Op.651ba6.3
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc42: init %empty_tuple.type = call %Destroy.Op.bound.loc42(%.loc42_38.3)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc41: <bound method> = bound_method %.loc41_35.3, constants.%Destroy.Op
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc41: <bound method> = bound_method %.loc41_35.3, constants.%Destroy.Op.651ba6.3
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc41: init %empty_tuple.type = call %Destroy.Op.bound.loc41(%.loc41_35.3)
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc40: <bound method> = bound_method %.loc40_31.3, constants.%Destroy.Op
|
||||
// CHECK:STDOUT: %Destroy.Op.bound.loc40: <bound method> = bound_method %.loc40_31.3, constants.%Destroy.Op.651ba6.3
|
||||
// CHECK:STDOUT: %Destroy.Op.call.loc40: init %empty_tuple.type = call %Destroy.Op.bound.loc40(%.loc40_31.3)
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: %C.Op.bound.loc23: <bound method> = bound_method %.loc23_38.3, constants.%C.Op
|
||||
@@ -1946,7 +1953,14 @@ fn F() {
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Destroy.Op(%self.param: ref bool) = "no_op";
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc48_30.1(%self.param: ref %i32.builtin) = "no_op";
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc48_30.2(%self.param: ref %i32) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Destroy.Op.loc45(%self.param: ref bool) = "no_op";
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- multiple_calls.carbon
|
||||
// CHECK:STDOUT:
|
||||
@@ -3175,9 +3189,7 @@ fn F() {
|
||||
// CHECK:STDOUT: %c2.ref: ref %C = name_ref c2, %c2
|
||||
// CHECK:STDOUT: %C.cpp_operator.bound.loc10: <bound method> = bound_method %c1.ref.loc10, imports.%C.cpp_operator.decl.828f43.2
|
||||
// CHECK:STDOUT: %.loc10_3: ref %C = splice_block %c3.var {}
|
||||
// CHECK:STDOUT: %.loc10_31.1: %C = acquire_value %c2.ref
|
||||
// CHECK:STDOUT: %.loc10_31.2: ref %C = value_as_ref %.loc10_31.1
|
||||
// CHECK:STDOUT: %addr.loc10_29.1: %ptr.d9e = addr_of %.loc10_31.2
|
||||
// CHECK:STDOUT: %addr.loc10_29.1: %ptr.d9e = addr_of %c2.ref
|
||||
// CHECK:STDOUT: %addr.loc10_29.2: %ptr.d9e = addr_of %.loc10_3
|
||||
// CHECK:STDOUT: %operator_Plus__carbon_thunk.call: init %empty_tuple.type = call imports.%operator_Plus__carbon_thunk.decl(%c1.ref.loc10, %addr.loc10_29.1, %addr.loc10_29.2)
|
||||
// CHECK:STDOUT: %.loc10_29: init %C to %.loc10_3 = mark_in_place_init %operator_Plus__carbon_thunk.call
|
||||
|
||||
@@ -377,26 +377,13 @@ fn Test(missing_less: Cpp.MissingLess,
|
||||
// CHECK:STDERR:
|
||||
OrderedWith(no_relevant_members, no_relevant_members);
|
||||
|
||||
// CHECK:STDERR: fail_never_valid.carbon:[[@LINE+20]]:3: error: cannot convert type `Cpp.LessReturnsVoid` into type implementing `Core.OrderedWith(Cpp.LessReturnsVoid)` [ConversionFailureTypeToFacet]
|
||||
// CHECK:STDERR: fail_never_valid.carbon:[[@LINE+7]]:3: error: cannot convert type `Cpp.LessReturnsVoid` into type implementing `Core.OrderedWith(Cpp.LessReturnsVoid)` [ConversionFailureTypeToFacet]
|
||||
// CHECK:STDERR: OrderedWith(less_returns_void, less_returns_void);
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_never_valid.carbon:[[@LINE-62]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
|
||||
// CHECK:STDERR: fn OrderedWith[U:! type, T:! Core.OrderedWith(U)](x: T, y: U) {
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
// CHECK:STDERR: {{.*}}/prelude/operators/comparison.carbon:26:11: error: value expression passed to reference parameter [ValueForRefParam]
|
||||
// CHECK:STDERR: fn Less[self: Self](other: Other) -> bool;
|
||||
// CHECK:STDERR: ^~~~~~~~~~
|
||||
// CHECK:STDERR: fail_never_valid.carbon:[[@LINE-76]]:8: note: initializing function parameter [InCallToFunctionParam]
|
||||
// CHECK:STDERR: auto operator<(LessNonConst) -> bool;
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR: {{.*}}/prelude/operators/comparison.carbon:26:3: note: while building thunk to match the signature of this function [ThunkSignature]
|
||||
// CHECK:STDERR: fn Less[self: Self](other: Other) -> bool;
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_never_valid.carbon:[[@LINE-75]]:1: note: while deducing parameters of generic declared here [DeductionGenericHere]
|
||||
// CHECK:STDERR: fn OrderedWith[U:! type, T:! Core.OrderedWith(U)](x: T, y: U) {
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
OrderedWith(less_returns_void, less_returns_void);
|
||||
|
||||
OrderedWith(less_non_const, less_non_const);
|
||||
|
||||
+1
@@ -32,6 +32,7 @@
|
||||
// CHECK:STDOUT: 'import_ir(Cpp)': {decl_id: inst<none>, is_export: false}
|
||||
// CHECK:STDOUT: import_ir_insts: {}
|
||||
// CHECK:STDOUT: clang_decls: {}
|
||||
// CHECK:STDOUT: clang_decl_signatures: {}
|
||||
// CHECK:STDOUT: name_scopes:
|
||||
// CHECK:STDOUT: name_scope0: {inst: instF, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
|
||||
// CHECK:STDOUT: entity_names: {}
|
||||
|
||||
+39
-39
@@ -181,12 +181,12 @@ fn Four() {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc7_26.1.temp = alloca [8 x i8], align 1, !dbg !14
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_26.1.temp), !dbg !14
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk(ptr %.loc7_26.1.temp), !dbg !14
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk.(ptr %.loc7_26.1.temp), !dbg !14
|
||||
// CHECK:STDOUT: ret void, !dbg !15
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !16
|
||||
@@ -200,12 +200,12 @@ fn Four() {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc11_19.2.temp = alloca [8 x i8], align 1, !dbg !20
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc11_19.2.temp), !dbg !20
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk_tuple(ptr %.loc11_19.2.temp), !dbg !20
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk_tuple.(ptr %.loc11_19.2.temp), !dbg !20
|
||||
// CHECK:STDOUT: ret void, !dbg !21
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk_tuple(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk_tuple.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !16
|
||||
@@ -286,7 +286,7 @@ fn Four() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !16
|
||||
@@ -298,7 +298,7 @@ fn Four() {
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind
|
||||
// CHECK:STDOUT: define void @"_COp:thunk:Default.7b1e6a57c714cdb7.Core:C.Cpp"(ptr sret([8 x i8]) %return) #2 !dbg !19 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk(ptr %return), !dbg !24
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk.(ptr %return), !dbg !24
|
||||
// CHECK:STDOUT: ret void, !dbg !24
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -386,18 +386,18 @@ fn Four() {
|
||||
// CHECK:STDOUT: %.loc12_65.1.temp = alloca [4 x i8], align 1, !dbg !16
|
||||
// CHECK:STDOUT: %_.var.loc13 = alloca [4 x i8], align 1, !dbg !17
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc8_65.1.temp), !dbg !14
|
||||
// CHECK:STDOUT: call void @_ZN26ImplicitlyDefaultedDefaultC1Ev.carbon_thunk(ptr %.loc8_65.1.temp), !dbg !14
|
||||
// CHECK:STDOUT: call void @_ZN26ImplicitlyDefaultedDefaultC1Ev.carbon_thunk.(ptr %.loc8_65.1.temp), !dbg !14
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc9), !dbg !15
|
||||
// CHECK:STDOUT: call void @"_COp.d288d62be0e5d791:DefaultOrUnformed.Core.22b4681b019423d7"(ptr %_.var.loc9), !dbg !15
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc12_65.1.temp), !dbg !16
|
||||
// CHECK:STDOUT: call void @_ZN26ExplicitlyDefaultedDefaultC1Ev.carbon_thunk(ptr %.loc12_65.1.temp), !dbg !16
|
||||
// CHECK:STDOUT: call void @_ZN26ExplicitlyDefaultedDefaultC1Ev.carbon_thunk.(ptr %.loc12_65.1.temp), !dbg !16
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.loc13), !dbg !17
|
||||
// CHECK:STDOUT: call void @"_COp.d288d62be0e5d791:DefaultOrUnformed.Core.1a27c303748a2360"(ptr %_.var.loc13), !dbg !17
|
||||
// CHECK:STDOUT: ret void, !dbg !18
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN26ImplicitlyDefaultedDefaultC1Ev.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN26ImplicitlyDefaultedDefaultC1Ev.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !19
|
||||
@@ -409,12 +409,12 @@ fn Four() {
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind
|
||||
// CHECK:STDOUT: define void @"_COp:thunk:Default.2e5fb550c65543cf.Core:ImplicitlyDefaultedDefault.Cpp"(ptr sret([4 x i8]) %return) #2 !dbg !22 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_ZN26ImplicitlyDefaultedDefaultC1Ev.carbon_thunk(ptr %return), !dbg !27
|
||||
// CHECK:STDOUT: call void @_ZN26ImplicitlyDefaultedDefaultC1Ev.carbon_thunk.(ptr %return), !dbg !27
|
||||
// CHECK:STDOUT: ret void, !dbg !27
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN26ExplicitlyDefaultedDefaultC1Ev.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN26ExplicitlyDefaultedDefaultC1Ev.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !28
|
||||
@@ -426,7 +426,7 @@ fn Four() {
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind
|
||||
// CHECK:STDOUT: define void @"_COp:thunk:Default.cad83ce9b7db87bf.Core:ExplicitlyDefaultedDefault.Cpp"(ptr sret([4 x i8]) %return) #2 !dbg !30 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_ZN26ExplicitlyDefaultedDefaultC1Ev.carbon_thunk(ptr %return), !dbg !31
|
||||
// CHECK:STDOUT: call void @_ZN26ExplicitlyDefaultedDefaultC1Ev.carbon_thunk.(ptr %return), !dbg !31
|
||||
// CHECK:STDOUT: ret void, !dbg !31
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -534,12 +534,12 @@ fn Four() {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc7_10.1.temp = alloca [4 x i8], align 1, !dbg !17
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_10.1.temp), !dbg !17
|
||||
// CHECK:STDOUT: call void @_ZN4CopyC1ERKS_.carbon_thunk(ptr %c, ptr %return), !dbg !17
|
||||
// CHECK:STDOUT: call void @_ZN4CopyC1ERKS_.carbon_thunk._(ptr %c, ptr %return), !dbg !17
|
||||
// CHECK:STDOUT: ret void, !dbg !18
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN4CopyC1ERKS_.carbon_thunk(ptr noundef %0, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN4CopyC1ERKS_.carbon_thunk._(ptr noundef %0, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
@@ -554,7 +554,7 @@ fn Four() {
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind
|
||||
// CHECK:STDOUT: define void @"_COp:thunk:Copy.692da64e78c7deec.Core:Copy.Cpp"(ptr sret([4 x i8]) %return, ptr %self) #2 !dbg !22 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_ZN4CopyC1ERKS_.carbon_thunk(ptr %self, ptr %return), !dbg !26
|
||||
// CHECK:STDOUT: call void @_ZN4CopyC1ERKS_.carbon_thunk._(ptr %self, ptr %return), !dbg !26
|
||||
// CHECK:STDOUT: ret void, !dbg !26
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -633,12 +633,12 @@ fn Four() {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc7_44.1.temp = alloca [8 x i8], align 1, !dbg !14
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_44.1.temp), !dbg !14
|
||||
// CHECK:STDOUT: call void @_ZN7DerivedC1Ev.carbon_thunk(ptr %.loc7_44.1.temp), !dbg !14
|
||||
// CHECK:STDOUT: call void @_ZN7DerivedC1Ev.carbon_thunk.(ptr %.loc7_44.1.temp), !dbg !14
|
||||
// CHECK:STDOUT: ret void, !dbg !15
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN7DerivedC1Ev.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN7DerivedC1Ev.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !16
|
||||
@@ -712,14 +712,14 @@ fn Four() {
|
||||
// CHECK:STDOUT: %.loc7_26.1.temp = alloca [1 x i8], align 1, !dbg !14
|
||||
// CHECK:STDOUT: %.loc8_19.2.temp = alloca [1 x i8], align 1, !dbg !15
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_26.1.temp), !dbg !14
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk(ptr %.loc7_26.1.temp), !dbg !14
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk.(ptr %.loc7_26.1.temp), !dbg !14
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc8_19.2.temp), !dbg !15
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk_tuple(ptr %.loc8_19.2.temp), !dbg !15
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk_tuple.(ptr %.loc8_19.2.temp), !dbg !15
|
||||
// CHECK:STDOUT: ret void, !dbg !16
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !17
|
||||
@@ -729,7 +729,7 @@ fn Four() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk_tuple(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk_tuple.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !17
|
||||
@@ -745,16 +745,16 @@ fn Four() {
|
||||
// CHECK:STDOUT: %.loc13_18.1.temp = alloca [1 x i8], align 1, !dbg !22
|
||||
// CHECK:STDOUT: %.loc14_21.2.temp = alloca [1 x i8], align 1, !dbg !23
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc12_27.1.temp), !dbg !21
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk(i32 1, ptr %.loc12_27.1.temp), !dbg !21
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk._(i32 1, ptr %.loc12_27.1.temp), !dbg !21
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc13_18.1.temp), !dbg !22
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk(i32 2, ptr %.loc13_18.1.temp), !dbg !22
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk._(i32 2, ptr %.loc13_18.1.temp), !dbg !22
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc14_21.2.temp), !dbg !23
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk_tuple(i32 3, ptr %.loc14_21.2.temp), !dbg !23
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ei.carbon_thunk_tuple._(i32 3, ptr %.loc14_21.2.temp), !dbg !23
|
||||
// CHECK:STDOUT: ret void, !dbg !24
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ei.carbon_thunk(i32 noundef %0, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ei.carbon_thunk._(i32 noundef %0, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca i32, align 4
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
@@ -767,7 +767,7 @@ fn Four() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ei.carbon_thunk_tuple(i32 noundef %0, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ei.carbon_thunk_tuple._(i32 noundef %0, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca i32, align 4
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
@@ -785,14 +785,14 @@ fn Four() {
|
||||
// CHECK:STDOUT: %.loc18_30.1.temp = alloca [1 x i8], align 1, !dbg !26
|
||||
// CHECK:STDOUT: %.loc19_23.2.temp = alloca [1 x i8], align 1, !dbg !27
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc18_30.1.temp), !dbg !26
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Eii.carbon_thunk(i32 1, i32 2, ptr %.loc18_30.1.temp), !dbg !26
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Eii.carbon_thunk.__(i32 1, i32 2, ptr %.loc18_30.1.temp), !dbg !26
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc19_23.2.temp), !dbg !27
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Eii.carbon_thunk_tuple(i32 3, i32 4, ptr %.loc19_23.2.temp), !dbg !27
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Eii.carbon_thunk_tuple.__(i32 3, i32 4, ptr %.loc19_23.2.temp), !dbg !27
|
||||
// CHECK:STDOUT: ret void, !dbg !28
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Eii.carbon_thunk(i32 noundef %0, i32 noundef %1, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Eii.carbon_thunk.__(i32 noundef %0, i32 noundef %1, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca i32, align 4
|
||||
// CHECK:STDOUT: %.addr1 = alloca i32, align 4
|
||||
@@ -808,7 +808,7 @@ fn Four() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Eii.carbon_thunk_tuple(i32 noundef %0, i32 noundef %1, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Eii.carbon_thunk_tuple.__(i32 noundef %0, i32 noundef %1, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca i32, align 4
|
||||
// CHECK:STDOUT: %.addr1 = alloca i32, align 4
|
||||
@@ -829,14 +829,14 @@ fn Four() {
|
||||
// CHECK:STDOUT: %.loc23_33.1.temp = alloca [1 x i8], align 1, !dbg !30
|
||||
// CHECK:STDOUT: %.loc24_26.2.temp = alloca [1 x i8], align 1, !dbg !31
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc23_33.1.temp), !dbg !30
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk3(i32 1, i32 2, i32 3, ptr %.loc23_33.1.temp), !dbg !30
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk.___(i32 1, i32 2, i32 3, ptr %.loc23_33.1.temp), !dbg !30
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc24_26.2.temp), !dbg !31
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk_tuple3(i32 4, i32 5, i32 6, ptr %.loc24_26.2.temp), !dbg !31
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk_tuple.___(i32 4, i32 5, i32 6, ptr %.loc24_26.2.temp), !dbg !31
|
||||
// CHECK:STDOUT: ret void, !dbg !32
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk3(i32 noundef %0, i32 noundef %1, i32 noundef %2, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk.___(i32 noundef %0, i32 noundef %1, i32 noundef %2, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca i32, align 4
|
||||
// CHECK:STDOUT: %.addr1 = alloca i32, align 4
|
||||
@@ -855,7 +855,7 @@ fn Four() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk_tuple3(i32 noundef %0, i32 noundef %1, i32 noundef %2, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk_tuple.___(i32 noundef %0, i32 noundef %1, i32 noundef %2, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca i32, align 4
|
||||
// CHECK:STDOUT: %.addr1 = alloca i32, align 4
|
||||
@@ -879,14 +879,14 @@ fn Four() {
|
||||
// CHECK:STDOUT: %.loc28_36.1.temp = alloca [1 x i8], align 1, !dbg !34
|
||||
// CHECK:STDOUT: %.loc29_29.2.temp = alloca [1 x i8], align 1, !dbg !35
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc28_36.1.temp), !dbg !34
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk(i32 1, i32 2, i32 3, i32 4, ptr %.loc28_36.1.temp), !dbg !34
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk.____(i32 1, i32 2, i32 3, i32 4, ptr %.loc28_36.1.temp), !dbg !34
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc29_29.2.temp), !dbg !35
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk_tuple(i32 5, i32 6, i32 7, i32 8, ptr %.loc29_29.2.temp), !dbg !35
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Eiiii.carbon_thunk_tuple.____(i32 5, i32 6, i32 7, i32 8, ptr %.loc29_29.2.temp), !dbg !35
|
||||
// CHECK:STDOUT: ret void, !dbg !36
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk(i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk.____(i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca i32, align 4
|
||||
// CHECK:STDOUT: %.addr1 = alloca i32, align 4
|
||||
@@ -908,7 +908,7 @@ fn Four() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk_tuple(i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Eiiii.carbon_thunk_tuple.____(i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca i32, align 4
|
||||
// CHECK:STDOUT: %.addr1 = alloca i32, align 4
|
||||
@@ -983,7 +983,7 @@ fn Four() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; uselistorder directives
|
||||
// CHECK:STDOUT: uselistorder ptr @_ZN1CC1Ei.carbon_thunk, { 1, 0 }
|
||||
// CHECK:STDOUT: uselistorder ptr @_ZN1CC1Ei.carbon_thunk._, { 1, 0 }
|
||||
// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: attributes #0 = { nounwind }
|
||||
|
||||
@@ -0,0 +1,504 @@
|
||||
// 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-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon
|
||||
// EXTRA-ARGS: --clang-arg=-fno-exceptions
|
||||
//
|
||||
// AUTOUPDATE
|
||||
// TIP: To test this file alone, run:
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/lower/testdata/interop/cpp/copy_vs_move.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lower/testdata/interop/cpp/copy_vs_move.carbon
|
||||
|
||||
// --- copyable.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
import Cpp;
|
||||
inline Cpp '''
|
||||
struct Copyable {
|
||||
Copyable(const Copyable&);
|
||||
Copyable& operator=(const Copyable&);
|
||||
~Copyable();
|
||||
};
|
||||
Copyable make();
|
||||
void pass(Copyable);
|
||||
''';
|
||||
|
||||
var c: Cpp.Copyable = Cpp.make();
|
||||
|
||||
fn PassGlobal() {
|
||||
Cpp.pass(c);
|
||||
}
|
||||
|
||||
fn PassTemporary() {
|
||||
Cpp.pass(Cpp.make());
|
||||
}
|
||||
|
||||
fn PassValue(c: Cpp.Copyable) {
|
||||
Cpp.pass(c);
|
||||
}
|
||||
|
||||
fn PassRef(ref c: Cpp.Copyable) {
|
||||
Cpp.pass(c);
|
||||
}
|
||||
|
||||
// --- copy_or_move.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
import Cpp;
|
||||
inline Cpp '''
|
||||
struct CopyOrMove {
|
||||
CopyOrMove(const CopyOrMove&);
|
||||
CopyOrMove& operator=(const CopyOrMove&);
|
||||
CopyOrMove(CopyOrMove&&);
|
||||
CopyOrMove& operator=(CopyOrMove&&);
|
||||
~CopyOrMove();
|
||||
};
|
||||
CopyOrMove make();
|
||||
void pass(CopyOrMove);
|
||||
''';
|
||||
|
||||
var c: Cpp.CopyOrMove = Cpp.make();
|
||||
|
||||
fn PassGlobal() {
|
||||
Cpp.pass(c);
|
||||
}
|
||||
|
||||
fn PassTemporary() {
|
||||
Cpp.pass(Cpp.make());
|
||||
}
|
||||
|
||||
fn PassValue(c: Cpp.CopyOrMove) {
|
||||
Cpp.pass(c);
|
||||
}
|
||||
|
||||
fn PassRef(ref c: Cpp.CopyOrMove) {
|
||||
Cpp.pass(c);
|
||||
}
|
||||
|
||||
// --- move_only.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
import Cpp;
|
||||
inline Cpp '''
|
||||
namespace std {
|
||||
template<typename T> T&& move(T& t) { return static_cast<T&&>(t); }
|
||||
}
|
||||
|
||||
struct MoveOnly {
|
||||
MoveOnly(const MoveOnly&) = delete;
|
||||
MoveOnly& operator=(const MoveOnly&) = delete;
|
||||
MoveOnly(MoveOnly&&);
|
||||
MoveOnly& operator=(MoveOnly&&);
|
||||
~MoveOnly();
|
||||
};
|
||||
MoveOnly make();
|
||||
void pass(MoveOnly);
|
||||
''';
|
||||
|
||||
var c: Cpp.MoveOnly = Cpp.make();
|
||||
|
||||
fn PassGlobalByMove() {
|
||||
// TODO: This should be accepted.
|
||||
// Cpp.pass(Cpp.std.move(ref c));
|
||||
}
|
||||
|
||||
fn PassTemporary() {
|
||||
Cpp.pass(Cpp.make());
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: ; ModuleID = 'copyable.carbon'
|
||||
// CHECK:STDOUT: source_filename = "copyable.carbon"
|
||||
// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
|
||||
// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu"
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: %struct.Copyable = type { i8 }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: @_Cc.Main = global [1 x i8] zeroinitializer
|
||||
// CHECK:STDOUT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @_C__global_init.Main, ptr null }]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z4makev.carbon_thunk.(ptr noundef %return) #0 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: %0 = load ptr, ptr %return.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: call void @_Z4makev(ptr dead_on_unwind writable sret(%struct.Copyable) align 1 %0)
|
||||
// CHECK:STDOUT: ret void
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CPassGlobal.Main() #1 !dbg !14 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z4pass8Copyable.carbon_thunk._(ptr @_Cc.Main), !dbg !17
|
||||
// CHECK:STDOUT: ret void, !dbg !18
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z4pass8Copyable.carbon_thunk._(ptr noundef %0) #0 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %struct.Copyable, align 1
|
||||
// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: %1 = load ptr, ptr %.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: call void @_ZN8CopyableC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp, ptr noundef nonnull align 1 dereferenceable(1) %1)
|
||||
// CHECK:STDOUT: call void @_Z4pass8Copyable(ptr noundef %agg.tmp)
|
||||
// CHECK:STDOUT: call void @_ZN8CopyableD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp) #1
|
||||
// CHECK:STDOUT: ret void
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CPassTemporary.Main() #1 !dbg !19 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc21_21.1.temp = alloca [1 x i8], align 1, !dbg !20
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc21_21.1.temp), !dbg !20
|
||||
// CHECK:STDOUT: call void @_Z4makev.carbon_thunk.(ptr %.loc21_21.1.temp), !dbg !20
|
||||
// CHECK:STDOUT: call void @_Z4pass8Copyable.carbon_thunk._(ptr %.loc21_21.1.temp), !dbg !21
|
||||
// CHECK:STDOUT: call void @_ZN8CopyableD1Ev(ptr %.loc21_21.1.temp), !dbg !20
|
||||
// CHECK:STDOUT: ret void, !dbg !22
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: declare void @_ZN8CopyableD1Ev(ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #2
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CPassValue.Main(ptr %c) #1 !dbg !23 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z4pass8Copyable.carbon_thunk._(ptr %c), !dbg !29
|
||||
// CHECK:STDOUT: ret void, !dbg !30
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CPassRef.Main(ptr %c) #1 !dbg !31 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z4pass8Copyable.carbon_thunk._(ptr %c), !dbg !34
|
||||
// CHECK:STDOUT: ret void, !dbg !35
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||
// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #3
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define internal void @_C__global_init.Main() #1 !dbg !36 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z4makev.carbon_thunk.(ptr @_Cc.Main), !dbg !37
|
||||
// CHECK:STDOUT: ret void, !dbg !38
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare void @_Z4makev(ptr dead_on_unwind writable sret(%struct.Copyable) align 1) #4
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare void @_Z4pass8Copyable(ptr noundef) #4
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare void @_ZN8CopyableC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1), ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #4
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: attributes #0 = { alwaysinline mustprogress nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
|
||||
// CHECK:STDOUT: attributes #1 = { nounwind }
|
||||
// CHECK:STDOUT: attributes #2 = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
|
||||
// CHECK:STDOUT: attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
|
||||
// CHECK:STDOUT: attributes #4 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4}
|
||||
// CHECK:STDOUT: !llvm.dbg.cu = !{!5}
|
||||
// CHECK:STDOUT: !llvm.errno.tbaa = !{!7}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
|
||||
// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
// CHECK:STDOUT: !2 = !{i32 8, !"PIC Level", i32 2}
|
||||
// CHECK:STDOUT: !3 = !{i32 7, !"PIE Level", i32 2}
|
||||
// CHECK:STDOUT: !4 = !{i32 7, !"uwtable", i32 2}
|
||||
// CHECK:STDOUT: !5 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !6, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
|
||||
// CHECK:STDOUT: !6 = !DIFile(filename: "copyable.carbon", directory: "")
|
||||
// CHECK:STDOUT: !7 = !{!8, !8, i64 0}
|
||||
// CHECK:STDOUT: !8 = !{!"int", !9, i64 0}
|
||||
// CHECK:STDOUT: !9 = !{!"omnipotent char", !10, i64 0}
|
||||
// CHECK:STDOUT: !10 = !{!"Simple C++ TBAA"}
|
||||
// CHECK:STDOUT: !11 = !{!12, !12, i64 0}
|
||||
// CHECK:STDOUT: !12 = !{!"p1 _ZTS8Copyable", !13, i64 0}
|
||||
// CHECK:STDOUT: !13 = !{!"any pointer", !9, i64 0}
|
||||
// CHECK:STDOUT: !14 = distinct !DISubprogram(name: "PassGlobal", linkageName: "_CPassGlobal.Main", scope: null, file: !6, line: 16, type: !15, spFlags: DISPFlagDefinition, unit: !5)
|
||||
// CHECK:STDOUT: !15 = !DISubroutineType(types: !16)
|
||||
// CHECK:STDOUT: !16 = !{null}
|
||||
// CHECK:STDOUT: !17 = !DILocation(line: 17, column: 3, scope: !14)
|
||||
// CHECK:STDOUT: !18 = !DILocation(line: 16, column: 1, scope: !14)
|
||||
// CHECK:STDOUT: !19 = distinct !DISubprogram(name: "PassTemporary", linkageName: "_CPassTemporary.Main", scope: null, file: !6, line: 20, type: !15, spFlags: DISPFlagDefinition, unit: !5)
|
||||
// CHECK:STDOUT: !20 = !DILocation(line: 21, column: 12, scope: !19)
|
||||
// CHECK:STDOUT: !21 = !DILocation(line: 21, column: 3, scope: !19)
|
||||
// CHECK:STDOUT: !22 = !DILocation(line: 20, column: 1, scope: !19)
|
||||
// CHECK:STDOUT: !23 = distinct !DISubprogram(name: "PassValue", linkageName: "_CPassValue.Main", scope: null, file: !6, line: 24, type: !24, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !27)
|
||||
// CHECK:STDOUT: !24 = !DISubroutineType(types: !25)
|
||||
// CHECK:STDOUT: !25 = !{null, !26}
|
||||
// CHECK:STDOUT: !26 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
|
||||
// CHECK:STDOUT: !27 = !{!28}
|
||||
// CHECK:STDOUT: !28 = !DILocalVariable(arg: 1, scope: !23, type: !26)
|
||||
// CHECK:STDOUT: !29 = !DILocation(line: 25, column: 3, scope: !23)
|
||||
// CHECK:STDOUT: !30 = !DILocation(line: 24, column: 1, scope: !23)
|
||||
// CHECK:STDOUT: !31 = distinct !DISubprogram(name: "PassRef", linkageName: "_CPassRef.Main", scope: null, file: !6, line: 28, type: !24, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !32)
|
||||
// CHECK:STDOUT: !32 = !{!33}
|
||||
// CHECK:STDOUT: !33 = !DILocalVariable(arg: 1, scope: !31, type: !26)
|
||||
// CHECK:STDOUT: !34 = !DILocation(line: 29, column: 3, scope: !31)
|
||||
// CHECK:STDOUT: !35 = !DILocation(line: 28, column: 1, scope: !31)
|
||||
// CHECK:STDOUT: !36 = distinct !DISubprogram(name: "__global_init", linkageName: "_C__global_init.Main", scope: null, file: !6, type: !15, spFlags: DISPFlagDefinition, unit: !5)
|
||||
// CHECK:STDOUT: !37 = !DILocation(line: 14, column: 23, scope: !36)
|
||||
// CHECK:STDOUT: !38 = !DILocation(line: 0, scope: !36)
|
||||
// CHECK:STDOUT: ; ModuleID = 'copy_or_move.carbon'
|
||||
// CHECK:STDOUT: source_filename = "copy_or_move.carbon"
|
||||
// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
|
||||
// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu"
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: %struct.CopyOrMove = type { i8 }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: @_Cc.Main = global [1 x i8] zeroinitializer
|
||||
// CHECK:STDOUT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @_C__global_init.Main, ptr null }]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z4makev.carbon_thunk.(ptr noundef %return) #0 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: %0 = load ptr, ptr %return.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: call void @_Z4makev(ptr dead_on_unwind writable sret(%struct.CopyOrMove) align 1 %0)
|
||||
// CHECK:STDOUT: ret void
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CPassGlobal.Main() #1 !dbg !14 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z4pass10CopyOrMove.carbon_thunk._(ptr @_Cc.Main), !dbg !17
|
||||
// CHECK:STDOUT: ret void, !dbg !18
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z4pass10CopyOrMove.carbon_thunk._(ptr noundef %0) #0 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %struct.CopyOrMove, align 1
|
||||
// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: %1 = load ptr, ptr %.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: call void @_ZN10CopyOrMoveC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp, ptr noundef nonnull align 1 dereferenceable(1) %1)
|
||||
// CHECK:STDOUT: call void @_Z4pass10CopyOrMove(ptr noundef %agg.tmp)
|
||||
// CHECK:STDOUT: call void @_ZN10CopyOrMoveD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp) #1
|
||||
// CHECK:STDOUT: ret void
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CPassTemporary.Main() #1 !dbg !19 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %_.var = alloca [1 x i8], align 1, !dbg !20
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !20
|
||||
// CHECK:STDOUT: call void @_Z4makev.carbon_thunk.(ptr %_.var), !dbg !21
|
||||
// CHECK:STDOUT: call void @_Z4pass10CopyOrMove.carbon_thunk.v(ptr %_.var), !dbg !22
|
||||
// CHECK:STDOUT: call void @_ZN10CopyOrMoveD1Ev(ptr %_.var), !dbg !20
|
||||
// CHECK:STDOUT: ret void, !dbg !23
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z4pass10CopyOrMove.carbon_thunk.v(ptr noundef %0) #0 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %struct.CopyOrMove, align 1
|
||||
// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: %1 = load ptr, ptr %.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: call void @_ZN10CopyOrMoveC1EOS_(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp, ptr noundef nonnull align 1 dereferenceable(1) %1)
|
||||
// CHECK:STDOUT: call void @_Z4pass10CopyOrMove(ptr noundef %agg.tmp)
|
||||
// CHECK:STDOUT: call void @_ZN10CopyOrMoveD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp) #1
|
||||
// CHECK:STDOUT: ret void
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: declare void @_ZN10CopyOrMoveD1Ev(ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #2
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CPassValue.Main(ptr %c) #1 !dbg !24 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z4pass10CopyOrMove.carbon_thunk._(ptr %c), !dbg !30
|
||||
// CHECK:STDOUT: ret void, !dbg !31
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CPassRef.Main(ptr %c) #1 !dbg !32 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z4pass10CopyOrMove.carbon_thunk._(ptr %c), !dbg !35
|
||||
// CHECK:STDOUT: ret void, !dbg !36
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||
// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #3
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define internal void @_C__global_init.Main() #1 !dbg !37 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z4makev.carbon_thunk.(ptr @_Cc.Main), !dbg !38
|
||||
// CHECK:STDOUT: ret void, !dbg !39
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare void @_Z4makev(ptr dead_on_unwind writable sret(%struct.CopyOrMove) align 1) #4
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare void @_Z4pass10CopyOrMove(ptr noundef) #4
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare void @_ZN10CopyOrMoveC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1), ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #4
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare void @_ZN10CopyOrMoveC1EOS_(ptr noundef nonnull align 1 dereferenceable(1), ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #4
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; uselistorder directives
|
||||
// CHECK:STDOUT: uselistorder ptr @_ZN10CopyOrMoveD1Ev, { 1, 2, 0 }
|
||||
// CHECK:STDOUT: uselistorder ptr @_Z4pass10CopyOrMove, { 1, 0 }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: attributes #0 = { alwaysinline mustprogress nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
|
||||
// CHECK:STDOUT: attributes #1 = { nounwind }
|
||||
// CHECK:STDOUT: attributes #2 = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
|
||||
// CHECK:STDOUT: attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
|
||||
// CHECK:STDOUT: attributes #4 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4}
|
||||
// CHECK:STDOUT: !llvm.dbg.cu = !{!5}
|
||||
// CHECK:STDOUT: !llvm.errno.tbaa = !{!7}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
|
||||
// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
// CHECK:STDOUT: !2 = !{i32 8, !"PIC Level", i32 2}
|
||||
// CHECK:STDOUT: !3 = !{i32 7, !"PIE Level", i32 2}
|
||||
// CHECK:STDOUT: !4 = !{i32 7, !"uwtable", i32 2}
|
||||
// CHECK:STDOUT: !5 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !6, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
|
||||
// CHECK:STDOUT: !6 = !DIFile(filename: "copy_or_move.carbon", directory: "")
|
||||
// CHECK:STDOUT: !7 = !{!8, !8, i64 0}
|
||||
// CHECK:STDOUT: !8 = !{!"int", !9, i64 0}
|
||||
// CHECK:STDOUT: !9 = !{!"omnipotent char", !10, i64 0}
|
||||
// CHECK:STDOUT: !10 = !{!"Simple C++ TBAA"}
|
||||
// CHECK:STDOUT: !11 = !{!12, !12, i64 0}
|
||||
// CHECK:STDOUT: !12 = !{!"p1 _ZTS10CopyOrMove", !13, i64 0}
|
||||
// CHECK:STDOUT: !13 = !{!"any pointer", !9, i64 0}
|
||||
// CHECK:STDOUT: !14 = distinct !DISubprogram(name: "PassGlobal", linkageName: "_CPassGlobal.Main", scope: null, file: !6, line: 18, type: !15, spFlags: DISPFlagDefinition, unit: !5)
|
||||
// CHECK:STDOUT: !15 = !DISubroutineType(types: !16)
|
||||
// CHECK:STDOUT: !16 = !{null}
|
||||
// CHECK:STDOUT: !17 = !DILocation(line: 19, column: 3, scope: !14)
|
||||
// CHECK:STDOUT: !18 = !DILocation(line: 18, column: 1, scope: !14)
|
||||
// CHECK:STDOUT: !19 = distinct !DISubprogram(name: "PassTemporary", linkageName: "_CPassTemporary.Main", scope: null, file: !6, line: 22, type: !15, spFlags: DISPFlagDefinition, unit: !5)
|
||||
// CHECK:STDOUT: !20 = !DILocation(line: 13, column: 21, scope: !19)
|
||||
// CHECK:STDOUT: !21 = !DILocation(line: 23, column: 12, scope: !19)
|
||||
// CHECK:STDOUT: !22 = !DILocation(line: 23, column: 3, scope: !19)
|
||||
// CHECK:STDOUT: !23 = !DILocation(line: 22, column: 1, scope: !19)
|
||||
// CHECK:STDOUT: !24 = distinct !DISubprogram(name: "PassValue", linkageName: "_CPassValue.Main", scope: null, file: !6, line: 26, type: !25, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !28)
|
||||
// CHECK:STDOUT: !25 = !DISubroutineType(types: !26)
|
||||
// CHECK:STDOUT: !26 = !{null, !27}
|
||||
// CHECK:STDOUT: !27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
|
||||
// CHECK:STDOUT: !28 = !{!29}
|
||||
// CHECK:STDOUT: !29 = !DILocalVariable(arg: 1, scope: !24, type: !27)
|
||||
// CHECK:STDOUT: !30 = !DILocation(line: 27, column: 3, scope: !24)
|
||||
// CHECK:STDOUT: !31 = !DILocation(line: 26, column: 1, scope: !24)
|
||||
// CHECK:STDOUT: !32 = distinct !DISubprogram(name: "PassRef", linkageName: "_CPassRef.Main", scope: null, file: !6, line: 30, type: !25, spFlags: DISPFlagDefinition, unit: !5, retainedNodes: !33)
|
||||
// CHECK:STDOUT: !33 = !{!34}
|
||||
// CHECK:STDOUT: !34 = !DILocalVariable(arg: 1, scope: !32, type: !27)
|
||||
// CHECK:STDOUT: !35 = !DILocation(line: 31, column: 3, scope: !32)
|
||||
// CHECK:STDOUT: !36 = !DILocation(line: 30, column: 1, scope: !32)
|
||||
// CHECK:STDOUT: !37 = distinct !DISubprogram(name: "__global_init", linkageName: "_C__global_init.Main", scope: null, file: !6, type: !15, spFlags: DISPFlagDefinition, unit: !5)
|
||||
// CHECK:STDOUT: !38 = !DILocation(line: 16, column: 25, scope: !37)
|
||||
// CHECK:STDOUT: !39 = !DILocation(line: 0, scope: !37)
|
||||
// CHECK:STDOUT: ; ModuleID = 'move_only.carbon'
|
||||
// CHECK:STDOUT: source_filename = "move_only.carbon"
|
||||
// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
|
||||
// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu"
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: %struct.MoveOnly = type { i8 }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: @_Cc.Main = global [1 x i8] zeroinitializer
|
||||
// CHECK:STDOUT: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @_C__global_init.Main, ptr null }]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z4makev.carbon_thunk.(ptr noundef %return) #0 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: %0 = load ptr, ptr %return.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: call void @_Z4makev(ptr dead_on_unwind writable sret(%struct.MoveOnly) align 1 %0)
|
||||
// CHECK:STDOUT: ret void
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CPassGlobalByMove.Main() #1 !dbg !14 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: ret void, !dbg !17
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CPassTemporary.Main() #1 !dbg !18 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %_.var = alloca [1 x i8], align 1, !dbg !19
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !19
|
||||
// CHECK:STDOUT: call void @_Z4makev.carbon_thunk.(ptr %_.var), !dbg !20
|
||||
// CHECK:STDOUT: call void @_Z4pass8MoveOnly.carbon_thunk.v(ptr %_.var), !dbg !21
|
||||
// CHECK:STDOUT: call void @_ZN8MoveOnlyD1Ev(ptr %_.var), !dbg !19
|
||||
// CHECK:STDOUT: ret void, !dbg !22
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z4pass8MoveOnly.carbon_thunk.v(ptr noundef %0) #0 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %struct.MoveOnly, align 1
|
||||
// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: %1 = load ptr, ptr %.addr, align 8, !tbaa !11
|
||||
// CHECK:STDOUT: call void @_ZN8MoveOnlyC1EOS_(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp, ptr noundef nonnull align 1 dereferenceable(1) %1)
|
||||
// CHECK:STDOUT: call void @_Z4pass8MoveOnly(ptr noundef %agg.tmp)
|
||||
// CHECK:STDOUT: call void @_ZN8MoveOnlyD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %agg.tmp) #1
|
||||
// CHECK:STDOUT: ret void
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: declare void @_ZN8MoveOnlyD1Ev(ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #2
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
|
||||
// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(ptr captures(none)) #3
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define internal void @_C__global_init.Main() #1 !dbg !23 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z4makev.carbon_thunk.(ptr @_Cc.Main), !dbg !24
|
||||
// CHECK:STDOUT: ret void, !dbg !25
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare void @_Z4makev(ptr dead_on_unwind writable sret(%struct.MoveOnly) align 1) #4
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare void @_Z4pass8MoveOnly(ptr noundef) #4
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare void @_ZN8MoveOnlyC1EOS_(ptr noundef nonnull align 1 dereferenceable(1), ptr noundef nonnull align 1 dereferenceable(1)) unnamed_addr #4
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; uselistorder directives
|
||||
// CHECK:STDOUT: uselistorder ptr @_ZN8MoveOnlyD1Ev, { 1, 0 }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: attributes #0 = { alwaysinline mustprogress nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
|
||||
// CHECK:STDOUT: attributes #1 = { nounwind }
|
||||
// CHECK:STDOUT: attributes #2 = { nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
|
||||
// CHECK:STDOUT: attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
|
||||
// CHECK:STDOUT: attributes #4 = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4}
|
||||
// CHECK:STDOUT: !llvm.dbg.cu = !{!5}
|
||||
// CHECK:STDOUT: !llvm.errno.tbaa = !{!7}
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
|
||||
// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
// CHECK:STDOUT: !2 = !{i32 8, !"PIC Level", i32 2}
|
||||
// CHECK:STDOUT: !3 = !{i32 7, !"PIE Level", i32 2}
|
||||
// CHECK:STDOUT: !4 = !{i32 7, !"uwtable", i32 2}
|
||||
// CHECK:STDOUT: !5 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !6, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
|
||||
// CHECK:STDOUT: !6 = !DIFile(filename: "move_only.carbon", directory: "")
|
||||
// CHECK:STDOUT: !7 = !{!8, !8, i64 0}
|
||||
// CHECK:STDOUT: !8 = !{!"int", !9, i64 0}
|
||||
// CHECK:STDOUT: !9 = !{!"omnipotent char", !10, i64 0}
|
||||
// CHECK:STDOUT: !10 = !{!"Simple C++ TBAA"}
|
||||
// CHECK:STDOUT: !11 = !{!12, !12, i64 0}
|
||||
// CHECK:STDOUT: !12 = !{!"p1 _ZTS8MoveOnly", !13, i64 0}
|
||||
// CHECK:STDOUT: !13 = !{!"any pointer", !9, i64 0}
|
||||
// CHECK:STDOUT: !14 = distinct !DISubprogram(name: "PassGlobalByMove", linkageName: "_CPassGlobalByMove.Main", scope: null, file: !6, line: 22, type: !15, spFlags: DISPFlagDefinition, unit: !5)
|
||||
// CHECK:STDOUT: !15 = !DISubroutineType(types: !16)
|
||||
// CHECK:STDOUT: !16 = !{null}
|
||||
// CHECK:STDOUT: !17 = !DILocation(line: 22, column: 1, scope: !14)
|
||||
// CHECK:STDOUT: !18 = distinct !DISubprogram(name: "PassTemporary", linkageName: "_CPassTemporary.Main", scope: null, file: !6, line: 27, type: !15, spFlags: DISPFlagDefinition, unit: !5)
|
||||
// CHECK:STDOUT: !19 = !DILocation(line: 17, column: 19, scope: !18)
|
||||
// CHECK:STDOUT: !20 = !DILocation(line: 28, column: 12, scope: !18)
|
||||
// CHECK:STDOUT: !21 = !DILocation(line: 28, column: 3, scope: !18)
|
||||
// CHECK:STDOUT: !22 = !DILocation(line: 27, column: 1, scope: !18)
|
||||
// CHECK:STDOUT: !23 = distinct !DISubprogram(name: "__global_init", linkageName: "_C__global_init.Main", scope: null, file: !6, type: !15, spFlags: DISPFlagDefinition, unit: !5)
|
||||
// CHECK:STDOUT: !24 = !DILocation(line: 20, column: 23, scope: !23)
|
||||
// CHECK:STDOUT: !25 = !DILocation(line: 0, scope: !23)
|
||||
+2
-2
@@ -227,12 +227,12 @@ fn MyF() {
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CMyF.Main(ptr sret({}) %return, ptr %a, ptr %b) #0 !dbg !11 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Zpl1XS_.carbon_thunk(ptr %a, ptr %b, ptr %return), !dbg !18
|
||||
// CHECK:STDOUT: call void @_Zpl1XS_.carbon_thunk.__(ptr %a, ptr %b, ptr %return), !dbg !18
|
||||
// CHECK:STDOUT: ret void, !dbg !19
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Zpl1XS_.carbon_thunk(ptr noundef %0, ptr noundef %1, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Zpl1XS_.carbon_thunk.__(ptr noundef %0, ptr noundef %1, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %.addr1 = alloca ptr, align 8
|
||||
|
||||
@@ -385,13 +385,13 @@ fn MyF() -> i32 {
|
||||
// CHECK:STDOUT: define i32 @_CMyF.Main() #0 !dbg !11 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %value.var = alloca i32, align 4, !dbg !15
|
||||
// CHECK:STDOUT: call void @_Z13NoReturnValueii.carbon_thunk0(), !dbg !16
|
||||
// CHECK:STDOUT: call void @_Z13NoReturnValueii.carbon_thunk1(i32 3), !dbg !17
|
||||
// CHECK:STDOUT: call void @_Z13NoReturnValueii.carbon_thunk.(), !dbg !16
|
||||
// CHECK:STDOUT: call void @_Z13NoReturnValueii.carbon_thunk._(i32 3), !dbg !17
|
||||
// CHECK:STDOUT: call void @_Z13NoReturnValueii(i32 3, i32 4), !dbg !18
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %value.var), !dbg !15
|
||||
// CHECK:STDOUT: %SimpleReturnValue__carbon_thunk.call.loc11 = call i32 @_Z17SimpleReturnValueii.carbon_thunk0(), !dbg !19
|
||||
// CHECK:STDOUT: %SimpleReturnValue__carbon_thunk.call.loc11 = call i32 @_Z17SimpleReturnValueii.carbon_thunk.(), !dbg !19
|
||||
// CHECK:STDOUT: store i32 %SimpleReturnValue__carbon_thunk.call.loc11, ptr %value.var, align 4, !dbg !15
|
||||
// CHECK:STDOUT: %SimpleReturnValue__carbon_thunk.call.loc12 = call i32 @_Z17SimpleReturnValueii.carbon_thunk1(i32 3), !dbg !20
|
||||
// CHECK:STDOUT: %SimpleReturnValue__carbon_thunk.call.loc12 = call i32 @_Z17SimpleReturnValueii.carbon_thunk._(i32 3), !dbg !20
|
||||
// CHECK:STDOUT: store i32 %SimpleReturnValue__carbon_thunk.call.loc12, ptr %value.var, align 4, !dbg !21
|
||||
// CHECK:STDOUT: %SimpleReturnValue.call = call i32 @_Z17SimpleReturnValueii(i32 3, i32 4), !dbg !22
|
||||
// CHECK:STDOUT: store i32 %SimpleReturnValue.call, ptr %value.var, align 4, !dbg !23
|
||||
@@ -401,14 +401,14 @@ fn MyF() -> i32 {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z13NoReturnValueii.carbon_thunk0() #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z13NoReturnValueii.carbon_thunk.() #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z13NoReturnValueii(i32 noundef 1, i32 noundef 2)
|
||||
// CHECK:STDOUT: ret void
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z13NoReturnValueii.carbon_thunk1(i32 noundef %a) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z13NoReturnValueii.carbon_thunk._(i32 noundef %a) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %a.addr = alloca i32, align 4
|
||||
// CHECK:STDOUT: store i32 %a, ptr %a.addr, align 4, !tbaa !7
|
||||
@@ -420,14 +420,14 @@ fn MyF() -> i32 {
|
||||
// CHECK:STDOUT: declare void @_Z13NoReturnValueii(i32 noundef, i32 noundef) #2
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal noundef i32 @_Z17SimpleReturnValueii.carbon_thunk0() #1 {
|
||||
// CHECK:STDOUT: define internal noundef i32 @_Z17SimpleReturnValueii.carbon_thunk.() #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %call = call noundef i32 @_Z17SimpleReturnValueii(i32 noundef 1, i32 noundef 2)
|
||||
// CHECK:STDOUT: ret i32 %call
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal noundef i32 @_Z17SimpleReturnValueii.carbon_thunk1(i32 noundef %a) #1 {
|
||||
// CHECK:STDOUT: define internal noundef i32 @_Z17SimpleReturnValueii.carbon_thunk._(i32 noundef %a) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %a.addr = alloca i32, align 4
|
||||
// CHECK:STDOUT: store i32 %a, ptr %a.addr, align 4, !tbaa !7
|
||||
|
||||
+6
-6
@@ -86,7 +86,7 @@ fn Call(n: Cpp.NeedThunk) {
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define i32 @_CUseVal.Main(ptr %a) #0 !dbg !11 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %by_val__carbon_thunk.call = call i32 @_ZNK1A6by_valEv.carbon_thunk(ptr %a), !dbg !18
|
||||
// CHECK:STDOUT: %by_val__carbon_thunk.call = call i32 @_ZNK1A6by_valEv.carbon_thunk._(ptr %a), !dbg !18
|
||||
// CHECK:STDOUT: ret i32 %by_val__carbon_thunk.call, !dbg !19
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -95,7 +95,7 @@ fn Call(n: Cpp.NeedThunk) {
|
||||
// CHECK:STDOUT: declare void @_ZN1A5virt1Ev(ptr noundef nonnull align 8 dereferenceable(12)) unnamed_addr #1
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal noundef i32 @_ZNK1A6by_valEv.carbon_thunk(ptr noundef nonnull align 8 dereferenceable(12) %this) #2 {
|
||||
// CHECK:STDOUT: define internal noundef i32 @_ZNK1A6by_valEv.carbon_thunk._(ptr noundef nonnull align 8 dereferenceable(12) %this) #2 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %this.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %this, ptr %this.addr, align 8, !tbaa !20
|
||||
@@ -284,16 +284,16 @@ fn Call(n: Cpp.NeedThunk) {
|
||||
// CHECK:STDOUT: %.loc7_14.3.temp = alloca i8, align 1, !dbg !17
|
||||
// CHECK:STDOUT: %.loc8_14.3.temp = alloca i8, align 1, !dbg !18
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_14.3.temp), !dbg !17
|
||||
// CHECK:STDOUT: call void @_ZNK9NeedThunk8ImplicitEa.carbon_thunk(ptr %n, ptr @int_1.30e), !dbg !19
|
||||
// CHECK:STDOUT: call void @_ZNK9NeedThunk8ImplicitEa.carbon_thunk.__(ptr %n, ptr @int_1.30e), !dbg !19
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc8_14.3.temp), !dbg !18
|
||||
// CHECK:STDOUT: call void @_ZNH9NeedThunk8ExplicitES_a.carbon_thunk(ptr %n, ptr @int_1.30e), !dbg !20
|
||||
// CHECK:STDOUT: call void @_ZNH9NeedThunk8ExplicitES_a.carbon_thunk.__(ptr %n, ptr @int_1.30e), !dbg !20
|
||||
// CHECK:STDOUT: call void @"_COp.43bece552030817c:core.Destroy.Core"(ptr @int_1.30e), !dbg !18
|
||||
// CHECK:STDOUT: call void @"_COp.43bece552030817c:core.Destroy.Core"(ptr @int_1.30e), !dbg !17
|
||||
// CHECK:STDOUT: ret void, !dbg !21
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZNK9NeedThunk8ImplicitEa.carbon_thunk(ptr noundef nonnull align 1 dereferenceable(1) %this, ptr noundef %c) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZNK9NeedThunk8ImplicitEa.carbon_thunk.__(ptr noundef nonnull align 1 dereferenceable(1) %this, ptr noundef %c) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %this.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %c.addr = alloca ptr, align 8
|
||||
@@ -307,7 +307,7 @@ fn Call(n: Cpp.NeedThunk) {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZNH9NeedThunk8ExplicitES_a.carbon_thunk(ptr noundef %0, ptr noundef %c) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZNH9NeedThunk8ExplicitES_a.carbon_thunk.__(ptr noundef %0, ptr noundef %c) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %c.addr = alloca ptr, align 8
|
||||
|
||||
+5
-5
@@ -67,7 +67,7 @@ fn ConvertNullptrConstant() -> Core.Optional(i32*) {
|
||||
// CHECK:STDOUT: %Cpp.nullptr_t.as.Copy.impl.Op.call = call ptr @"_COp.NullptrT.CppCompat.Core:Copy.Core"(ptr poison), !dbg !15
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc14_22.1.temp), !dbg !15
|
||||
// CHECK:STDOUT: store ptr %Cpp.nullptr_t.as.Copy.impl.Op.call, ptr %.loc14_22.1.temp, align 8, !dbg !15
|
||||
// CHECK:STDOUT: call void @_Z11TakeNullptrDn.carbon_thunk(ptr %.loc14_22.1.temp), !dbg !17
|
||||
// CHECK:STDOUT: call void @_Z11TakeNullptrDn.carbon_thunk._(ptr %.loc14_22.1.temp), !dbg !17
|
||||
// CHECK:STDOUT: call void @"_COp.705e422c84320121:core.Destroy.Core"(ptr %.loc14_22.1.temp), !dbg !15
|
||||
// CHECK:STDOUT: call void @"_COp.e34c165b4a1e692a:core.Destroy.Core"(ptr %.loc12_18.2.temp), !dbg !14
|
||||
// CHECK:STDOUT: ret void, !dbg !18
|
||||
@@ -76,7 +76,7 @@ fn ConvertNullptrConstant() -> Core.Optional(i32*) {
|
||||
// CHECK:STDOUT: declare void @_Z7TakePtrPi(ptr noundef) #1
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z11TakeNullptrDn.carbon_thunk(ptr noundef %n) #2 {
|
||||
// CHECK:STDOUT: define internal void @_Z11TakeNullptrDn.carbon_thunk._(ptr noundef %n) #2 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %n.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %n, ptr %n.addr, align 8, !tbaa !19
|
||||
@@ -130,7 +130,7 @@ fn ConvertNullptrConstant() -> Core.Optional(i32*) {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %a.var = alloca ptr, align 8, !dbg !48
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %a.var), !dbg !48
|
||||
// CHECK:STDOUT: call void @_Z13ReturnNullptrv.carbon_thunk(ptr %a.var), !dbg !49
|
||||
// CHECK:STDOUT: call void @_Z13ReturnNullptrv.carbon_thunk.(ptr %a.var), !dbg !49
|
||||
// CHECK:STDOUT: %.loc28_10 = load ptr, ptr %a.var, align 8, !dbg !50
|
||||
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call = call ptr @"_CConvert.NullptrT.CppCompat.Core:ImplicitAs.a5972e826b98ae3c.Core.b88d1103f417c6d4"(ptr %.loc28_10), !dbg !51
|
||||
// CHECK:STDOUT: call void @"_COp.705e422c84320121:core.Destroy.Core"(ptr %a.var), !dbg !48
|
||||
@@ -138,7 +138,7 @@ fn ConvertNullptrConstant() -> Core.Optional(i32*) {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z13ReturnNullptrv.carbon_thunk(ptr noundef %return) #2 {
|
||||
// CHECK:STDOUT: define internal void @_Z13ReturnNullptrv.carbon_thunk.(ptr noundef %return) #2 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !19
|
||||
@@ -153,7 +153,7 @@ fn ConvertNullptrConstant() -> Core.Optional(i32*) {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc32_28.1.temp = alloca ptr, align 8, !dbg !55
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc32_28.1.temp), !dbg !55
|
||||
// CHECK:STDOUT: call void @_Z13ReturnNullptrv.carbon_thunk(ptr %.loc32_28.1.temp), !dbg !55
|
||||
// CHECK:STDOUT: call void @_Z13ReturnNullptrv.carbon_thunk.(ptr %.loc32_28.1.temp), !dbg !55
|
||||
// CHECK:STDOUT: %.loc32_28.4 = load ptr, ptr %.loc32_28.1.temp, align 8, !dbg !55
|
||||
// CHECK:STDOUT: %Cpp.nullptr_t.as.ImplicitAs.impl.Convert.call = call ptr @"_CConvert.NullptrT.CppCompat.Core:ImplicitAs.a5972e826b98ae3c.Core.b88d1103f417c6d4"(ptr %.loc32_28.4), !dbg !56
|
||||
// CHECK:STDOUT: call void @"_COp.705e422c84320121:core.Destroy.Core"(ptr %.loc32_28.1.temp), !dbg !55
|
||||
|
||||
+12
-12
@@ -93,7 +93,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Zeq1AS_.carbon_thunk(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Zeq1AS_.carbon_thunk.__(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %x.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %y.addr = alloca ptr, align 8
|
||||
@@ -119,7 +119,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Zne1AS_.carbon_thunk(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Zne1AS_.carbon_thunk.__(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %x.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %y.addr = alloca ptr, align 8
|
||||
@@ -149,7 +149,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.3.temp = alloca i1, align 1, !dbg !34
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.3.temp), !dbg !34
|
||||
// CHECK:STDOUT: call void @_Zeq1AS_.carbon_thunk(ptr %self, ptr %other, ptr %.3.temp), !dbg !34
|
||||
// CHECK:STDOUT: call void @_Zeq1AS_.carbon_thunk.__(ptr %self, ptr %other, ptr %.3.temp), !dbg !34
|
||||
// CHECK:STDOUT: %0 = load i1, ptr %.3.temp, align 1, !dbg !34
|
||||
// CHECK:STDOUT: ret i1 %0, !dbg !34
|
||||
// CHECK:STDOUT: }
|
||||
@@ -159,7 +159,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.3.temp = alloca i1, align 1, !dbg !39
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.3.temp), !dbg !39
|
||||
// CHECK:STDOUT: call void @_Zne1AS_.carbon_thunk(ptr %self, ptr %other, ptr %.3.temp), !dbg !39
|
||||
// CHECK:STDOUT: call void @_Zne1AS_.carbon_thunk.__(ptr %self, ptr %other, ptr %.3.temp), !dbg !39
|
||||
// CHECK:STDOUT: %0 = load i1, ptr %.3.temp, align 1, !dbg !39
|
||||
// CHECK:STDOUT: ret i1 %0, !dbg !39
|
||||
// CHECK:STDOUT: }
|
||||
@@ -304,7 +304,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Zlt1AS_.carbon_thunk(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Zlt1AS_.carbon_thunk.__(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %x.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %y.addr = alloca ptr, align 8
|
||||
@@ -330,7 +330,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Zle1AS_.carbon_thunk(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Zle1AS_.carbon_thunk.__(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %x.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %y.addr = alloca ptr, align 8
|
||||
@@ -356,7 +356,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Zgt1AS_.carbon_thunk(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Zgt1AS_.carbon_thunk.__(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %x.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %y.addr = alloca ptr, align 8
|
||||
@@ -382,7 +382,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Zge1AS_.carbon_thunk(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Zge1AS_.carbon_thunk.__(ptr noundef %x, ptr noundef %y, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %x.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %y.addr = alloca ptr, align 8
|
||||
@@ -412,7 +412,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.3.temp = alloca i1, align 1, !dbg !34
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.3.temp), !dbg !34
|
||||
// CHECK:STDOUT: call void @_Zlt1AS_.carbon_thunk(ptr %self, ptr %other, ptr %.3.temp), !dbg !34
|
||||
// CHECK:STDOUT: call void @_Zlt1AS_.carbon_thunk.__(ptr %self, ptr %other, ptr %.3.temp), !dbg !34
|
||||
// CHECK:STDOUT: %0 = load i1, ptr %.3.temp, align 1, !dbg !34
|
||||
// CHECK:STDOUT: ret i1 %0, !dbg !34
|
||||
// CHECK:STDOUT: }
|
||||
@@ -422,7 +422,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.3.temp = alloca i1, align 1, !dbg !39
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.3.temp), !dbg !39
|
||||
// CHECK:STDOUT: call void @_Zle1AS_.carbon_thunk(ptr %self, ptr %other, ptr %.3.temp), !dbg !39
|
||||
// CHECK:STDOUT: call void @_Zle1AS_.carbon_thunk.__(ptr %self, ptr %other, ptr %.3.temp), !dbg !39
|
||||
// CHECK:STDOUT: %0 = load i1, ptr %.3.temp, align 1, !dbg !39
|
||||
// CHECK:STDOUT: ret i1 %0, !dbg !39
|
||||
// CHECK:STDOUT: }
|
||||
@@ -432,7 +432,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.3.temp = alloca i1, align 1, !dbg !44
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.3.temp), !dbg !44
|
||||
// CHECK:STDOUT: call void @_Zgt1AS_.carbon_thunk(ptr %self, ptr %other, ptr %.3.temp), !dbg !44
|
||||
// CHECK:STDOUT: call void @_Zgt1AS_.carbon_thunk.__(ptr %self, ptr %other, ptr %.3.temp), !dbg !44
|
||||
// CHECK:STDOUT: %0 = load i1, ptr %.3.temp, align 1, !dbg !44
|
||||
// CHECK:STDOUT: ret i1 %0, !dbg !44
|
||||
// CHECK:STDOUT: }
|
||||
@@ -442,7 +442,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.3.temp = alloca i1, align 1, !dbg !49
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.3.temp), !dbg !49
|
||||
// CHECK:STDOUT: call void @_Zge1AS_.carbon_thunk(ptr %self, ptr %other, ptr %.3.temp), !dbg !49
|
||||
// CHECK:STDOUT: call void @_Zge1AS_.carbon_thunk.__(ptr %self, ptr %other, ptr %.3.temp), !dbg !49
|
||||
// CHECK:STDOUT: %0 = load i1, ptr %.3.temp, align 1, !dbg !49
|
||||
// CHECK:STDOUT: ret i1 %0, !dbg !49
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
+18
-18
@@ -129,10 +129,10 @@ fn PassValueExpr(y: Cpp.Y) {
|
||||
// CHECK:STDOUT: %.loc9_24.3.temp = alloca i16, align 2, !dbg !17
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_19.3.temp), !dbg !14
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_22.3.temp), !dbg !15
|
||||
// CHECK:STDOUT: call void @_Z11pass_signedasil.carbon_thunk(ptr @int_1.30e, ptr @int_2.305, i32 3, i64 4), !dbg !18
|
||||
// CHECK:STDOUT: call void @_Z11pass_signedasil.carbon_thunk.____(ptr @int_1.30e, ptr @int_2.305, i32 3, i64 4), !dbg !18
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc9_21.3.temp), !dbg !16
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc9_24.3.temp), !dbg !17
|
||||
// CHECK:STDOUT: call void @_Z13pass_unsignedhtjm.carbon_thunk(ptr @int_1.e80, ptr @int_2.fb2, i32 3, i64 4), !dbg !19
|
||||
// CHECK:STDOUT: call void @_Z13pass_unsignedhtjm.carbon_thunk.____(ptr @int_1.e80, ptr @int_2.fb2, i32 3, i64 4), !dbg !19
|
||||
// CHECK:STDOUT: call void @"_COp.ecaf8c3e76291eee:core.Destroy.Core"(ptr @int_2.fb2), !dbg !17
|
||||
// CHECK:STDOUT: call void @"_COp.3de38e83520d6bec:core.Destroy.Core"(ptr @int_1.e80), !dbg !16
|
||||
// CHECK:STDOUT: call void @"_COp.406738f1b62008ed:core.Destroy.Core"(ptr @int_2.305), !dbg !15
|
||||
@@ -141,7 +141,7 @@ fn PassValueExpr(y: Cpp.Y) {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z11pass_signedasil.carbon_thunk(ptr noundef %0, ptr noundef %1, i32 noundef %2, i64 noundef %3) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z11pass_signedasil.carbon_thunk.____(ptr noundef %0, ptr noundef %1, i32 noundef %2, i64 noundef %3) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %.addr1 = alloca ptr, align 8
|
||||
@@ -162,7 +162,7 @@ fn PassValueExpr(y: Cpp.Y) {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z13pass_unsignedhtjm.carbon_thunk(ptr noundef %0, ptr noundef %1, i32 noundef %2, i64 noundef %3) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z13pass_unsignedhtjm.carbon_thunk.____(ptr noundef %0, ptr noundef %1, i32 noundef %2, i64 noundef %3) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %.addr1 = alloca ptr, align 8
|
||||
@@ -217,19 +217,19 @@ fn PassValueExpr(y: Cpp.Y) {
|
||||
// CHECK:STDOUT: %.loc20_28.3.temp = alloca i16, align 2, !dbg !69
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc17_18.1.temp), !dbg !66
|
||||
// CHECK:STDOUT: store i16 %a, ptr %.loc17_18.1.temp, align 2, !dbg !66
|
||||
// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk(ptr %.loc17_18.1.temp), !dbg !70
|
||||
// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk._(ptr %.loc17_18.1.temp), !dbg !70
|
||||
// CHECK:STDOUT: %.loc18_18.2 = load i16, ptr %b, align 2, !dbg !67
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc18_18.3.temp), !dbg !67
|
||||
// CHECK:STDOUT: store i16 %.loc18_18.2, ptr %.loc18_18.3.temp, align 2, !dbg !67
|
||||
// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk(ptr %.loc18_18.3.temp), !dbg !71
|
||||
// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk._(ptr %.loc18_18.3.temp), !dbg !71
|
||||
// CHECK:STDOUT: %.loc19_18.1 = load i16, ptr @_Cc.Main, align 2, !dbg !68
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc19_18.2.temp), !dbg !68
|
||||
// CHECK:STDOUT: store i16 %.loc19_18.1, ptr %.loc19_18.2.temp, align 2, !dbg !68
|
||||
// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk(ptr %.loc19_18.2.temp), !dbg !72
|
||||
// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk._(ptr %.loc19_18.2.temp), !dbg !72
|
||||
// CHECK:STDOUT: %MakeShort.call = call i16 @_CMakeShort.Main(), !dbg !69
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc20_28.3.temp), !dbg !69
|
||||
// CHECK:STDOUT: store i16 %MakeShort.call, ptr %.loc20_28.3.temp, align 2, !dbg !69
|
||||
// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk(ptr %.loc20_28.3.temp), !dbg !73
|
||||
// CHECK:STDOUT: call void @_Z10pass_shorts.carbon_thunk._(ptr %.loc20_28.3.temp), !dbg !73
|
||||
// CHECK:STDOUT: call void @"_COp.406738f1b62008ed:core.Destroy.Core"(ptr %.loc20_28.3.temp), !dbg !69
|
||||
// CHECK:STDOUT: call void @"_COp.406738f1b62008ed:core.Destroy.Core"(ptr %.loc19_18.2.temp), !dbg !68
|
||||
// CHECK:STDOUT: call void @"_COp.406738f1b62008ed:core.Destroy.Core"(ptr %.loc18_18.3.temp), !dbg !67
|
||||
@@ -238,7 +238,7 @@ fn PassValueExpr(y: Cpp.Y) {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z10pass_shorts.carbon_thunk(ptr noundef %0) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z10pass_shorts.carbon_thunk._(ptr noundef %0) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !24
|
||||
@@ -265,7 +265,7 @@ fn PassValueExpr(y: Cpp.Y) {
|
||||
// CHECK:STDOUT: declare void @_Z10pass_shorts(i16 noundef signext) #3
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; uselistorder directives
|
||||
// CHECK:STDOUT: uselistorder ptr @_Z10pass_shorts.carbon_thunk, { 3, 2, 1, 0 }
|
||||
// CHECK:STDOUT: uselistorder ptr @_Z10pass_shorts.carbon_thunk._, { 3, 2, 1, 0 }
|
||||
// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 7, 6, 5, 4, 3, 2, 1, 0 }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: attributes #0 = { nounwind }
|
||||
@@ -374,12 +374,12 @@ fn PassValueExpr(y: Cpp.Y) {
|
||||
// CHECK:STDOUT: store i32 2, ptr %.loc9_4.b, align 4, !dbg !16
|
||||
// CHECK:STDOUT: %.loc10_4.c = getelementptr inbounds nuw [12 x i8], ptr %x.var, i32 0, i32 8, !dbg !17
|
||||
// CHECK:STDOUT: store i32 3, ptr %.loc10_4.c, align 4, !dbg !17
|
||||
// CHECK:STDOUT: call void @_Z11pass_struct1X.carbon_thunk(ptr %x.var), !dbg !18
|
||||
// CHECK:STDOUT: call void @_Z11pass_struct1X.carbon_thunk._(ptr %x.var), !dbg !18
|
||||
// CHECK:STDOUT: ret void, !dbg !19
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1XC1Ev.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1XC1Ev.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !20
|
||||
@@ -390,12 +390,12 @@ fn PassValueExpr(y: Cpp.Y) {
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind
|
||||
// CHECK:STDOUT: define void @"_COp:thunk:Default.17a84649916546b3.Core:X.Cpp"(ptr sret([12 x i8]) %return) #2 !dbg !23 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_ZN1XC1Ev.carbon_thunk(ptr %return), !dbg !28
|
||||
// CHECK:STDOUT: call void @_ZN1XC1Ev.carbon_thunk.(ptr %return), !dbg !28
|
||||
// CHECK:STDOUT: ret void, !dbg !28
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z11pass_struct1X.carbon_thunk(ptr noundef %0) #3 {
|
||||
// CHECK:STDOUT: define internal void @_Z11pass_struct1X.carbon_thunk._(ptr noundef %0) #3 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %struct.X, align 4
|
||||
@@ -493,12 +493,12 @@ fn PassValueExpr(y: Cpp.Y) {
|
||||
// CHECK:STDOUT: store i32 2, ptr %.loc9_4.b, align 4, !dbg !16
|
||||
// CHECK:STDOUT: %.loc10_4.c = getelementptr inbounds nuw [12 x i8], ptr %y.var, i32 0, i32 8, !dbg !17
|
||||
// CHECK:STDOUT: store i32 3, ptr %.loc10_4.c, align 4, !dbg !17
|
||||
// CHECK:STDOUT: call void @_Z11pass_struct1Y.carbon_thunk(ptr %y.var), !dbg !18
|
||||
// CHECK:STDOUT: call void @_Z11pass_struct1Y.carbon_thunk._(ptr %y.var), !dbg !18
|
||||
// CHECK:STDOUT: ret void, !dbg !19
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z11pass_struct1Y.carbon_thunk(ptr noundef %0) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z11pass_struct1Y.carbon_thunk._(ptr noundef %0) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.Y, align 4
|
||||
@@ -517,14 +517,14 @@ fn PassValueExpr(y: Cpp.Y) {
|
||||
// CHECK:STDOUT: %.loc17_24.1.temp = alloca [12 x i8], align 1, !dbg !24
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc17_24.1.temp), !dbg !24
|
||||
// CHECK:STDOUT: call void @_CMake.Main(ptr %.loc17_24.1.temp), !dbg !24
|
||||
// CHECK:STDOUT: call void @_Z11pass_struct1Y.carbon_thunk(ptr %.loc17_24.1.temp), !dbg !25
|
||||
// CHECK:STDOUT: call void @_Z11pass_struct1Y.carbon_thunk._(ptr %.loc17_24.1.temp), !dbg !25
|
||||
// CHECK:STDOUT: ret void, !dbg !26
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CPassValueExpr.Main(ptr %y) #0 !dbg !27 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z11pass_struct1Y.carbon_thunk(ptr %y), !dbg !33
|
||||
// CHECK:STDOUT: call void @_Z11pass_struct1Y.carbon_thunk._(ptr %y), !dbg !33
|
||||
// CHECK:STDOUT: ret void, !dbg !34
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
+8
-8
@@ -128,12 +128,12 @@ fn Convert() {
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CPassPtrWithThunk.Main(ptr %p) #0 !dbg !24 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z16TakePtrWithThunkP1Ci.carbon_thunk1(ptr %p), !dbg !27
|
||||
// CHECK:STDOUT: call void @_Z16TakePtrWithThunkP1Ci.carbon_thunk._(ptr %p), !dbg !27
|
||||
// CHECK:STDOUT: ret void, !dbg !28
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z16TakePtrWithThunkP1Ci.carbon_thunk1(ptr noundef %0) #2 {
|
||||
// CHECK:STDOUT: define internal void @_Z16TakePtrWithThunkP1Ci.carbon_thunk._(ptr noundef %0) #2 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !29
|
||||
@@ -145,12 +145,12 @@ fn Convert() {
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define ptr @_CReturnPtrWithThunk.Main() #0 !dbg !32 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %ReturnPtrWithThunk__carbon_thunk.call = call ptr @_Z18ReturnPtrWithThunki.carbon_thunk0(), !dbg !33
|
||||
// CHECK:STDOUT: %ReturnPtrWithThunk__carbon_thunk.call = call ptr @_Z18ReturnPtrWithThunki.carbon_thunk.(), !dbg !33
|
||||
// CHECK:STDOUT: ret ptr %ReturnPtrWithThunk__carbon_thunk.call, !dbg !34
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal noundef ptr @_Z18ReturnPtrWithThunki.carbon_thunk0() #2 {
|
||||
// CHECK:STDOUT: define internal noundef ptr @_Z18ReturnPtrWithThunki.carbon_thunk.() #2 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %call = call noundef ptr @_Z18ReturnPtrWithThunki(i32 noundef 0)
|
||||
// CHECK:STDOUT: ret ptr %call
|
||||
@@ -264,13 +264,13 @@ fn Convert() {
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc35_24.2.temp), !dbg !44
|
||||
// CHECK:STDOUT: store ptr %U.as_type.as.ImplicitAs.impl.Convert.call, ptr %.loc35_24.2.temp, align 8, !dbg !44
|
||||
// CHECK:STDOUT: %.loc35_24.4 = load ptr, ptr %.loc35_24.2.temp, align 8, !dbg !44
|
||||
// CHECK:STDOUT: call void @_Z16TakePtrWithThunkP1Ci.carbon_thunk1(ptr %.loc35_24.4), !dbg !45
|
||||
// CHECK:STDOUT: call void @_Z16TakePtrWithThunkP1Ci.carbon_thunk._(ptr %.loc35_24.4), !dbg !45
|
||||
// CHECK:STDOUT: call void @"_COp.f6ed00b54444c4a3:core.Destroy.Core"(ptr %.loc35_24.2.temp), !dbg !44
|
||||
// CHECK:STDOUT: ret void, !dbg !46
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z16TakePtrWithThunkP1Ci.carbon_thunk1(ptr noundef %0) #2 {
|
||||
// CHECK:STDOUT: define internal void @_Z16TakePtrWithThunkP1Ci.carbon_thunk._(ptr noundef %0) #2 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !47
|
||||
@@ -282,12 +282,12 @@ fn Convert() {
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define ptr @_CReturnPtrWithThunk.Main() #0 !dbg !50 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %ReturnPtrWithThunk__carbon_thunk.call = call ptr @_Z18ReturnPtrWithThunki.carbon_thunk0(), !dbg !51
|
||||
// CHECK:STDOUT: %ReturnPtrWithThunk__carbon_thunk.call = call ptr @_Z18ReturnPtrWithThunki.carbon_thunk.(), !dbg !51
|
||||
// CHECK:STDOUT: ret ptr %ReturnPtrWithThunk__carbon_thunk.call, !dbg !52
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal noundef ptr @_Z18ReturnPtrWithThunki.carbon_thunk0() #2 {
|
||||
// CHECK:STDOUT: define internal noundef ptr @_Z18ReturnPtrWithThunki.carbon_thunk.() #2 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %call = call noundef ptr @_Z18ReturnPtrWithThunki(i32 noundef 0)
|
||||
// CHECK:STDOUT: ret ptr %call
|
||||
|
||||
+36
-36
@@ -148,18 +148,18 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: call void @_Z8TakeCRefR1C(ptr %c.var), !dbg !19
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.1), !dbg !15
|
||||
// CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %_.var.1, ptr align 1 @C.val.loc19_20, i64 0, i1 false), !dbg !15
|
||||
// CHECK:STDOUT: call void @_Z9TakeCRRefO1C.carbon_thunk(ptr %_.var.1), !dbg !20
|
||||
// CHECK:STDOUT: call void @_Z13TakeConstCRefRK1C.carbon_thunk(ptr %c.var), !dbg !21
|
||||
// CHECK:STDOUT: call void @_Z9TakeCRRefO1C.carbon_thunk.v(ptr %_.var.1), !dbg !20
|
||||
// CHECK:STDOUT: call void @_Z13TakeConstCRefRK1C.carbon_thunk._(ptr %c.var), !dbg !21
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %n.var), !dbg !16
|
||||
// CHECK:STDOUT: store i32 poison, ptr %n.var, align 4, !dbg !16
|
||||
// CHECK:STDOUT: call void @_Z10TakeIntRefRi(ptr %n.var), !dbg !22
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var.2), !dbg !17
|
||||
// CHECK:STDOUT: store i32 42, ptr %_.var.2, align 4, !dbg !17
|
||||
// CHECK:STDOUT: call void @_Z11TakeIntRRefOi.carbon_thunk(ptr %_.var.2), !dbg !23
|
||||
// CHECK:STDOUT: call void @_Z11TakeIntRRefOi.carbon_thunk.v(ptr %_.var.2), !dbg !23
|
||||
// CHECK:STDOUT: %.loc25_23.1 = load i32, ptr %n.var, align 4, !dbg !18
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc25_23.2.temp), !dbg !18
|
||||
// CHECK:STDOUT: store i32 %.loc25_23.1, ptr %.loc25_23.2.temp, align 4, !dbg !18
|
||||
// CHECK:STDOUT: call void @_Z15TakeConstIntRefRKi.carbon_thunk(ptr %.loc25_23.2.temp), !dbg !24
|
||||
// CHECK:STDOUT: call void @_Z15TakeConstIntRefRKi.carbon_thunk._(ptr %.loc25_23.2.temp), !dbg !24
|
||||
// CHECK:STDOUT: call void @"_COp.7e389eab4a7e5487:core.Destroy.Core"(ptr %.loc25_23.2.temp), !dbg !18
|
||||
// CHECK:STDOUT: call void @"_COp.7e389eab4a7e5487:core.Destroy.Core"(ptr %_.var.2), !dbg !17
|
||||
// CHECK:STDOUT: call void @"_COp.7e389eab4a7e5487:core.Destroy.Core"(ptr %n.var), !dbg !16
|
||||
@@ -167,7 +167,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !26
|
||||
@@ -178,14 +178,14 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind
|
||||
// CHECK:STDOUT: define void @"_COp:thunk:Default.7b1e6a57c714cdb7.Core:C.Cpp"(ptr sret({}) %return) #2 !dbg !29 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk(ptr %return), !dbg !33
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk.(ptr %return), !dbg !33
|
||||
// CHECK:STDOUT: ret void, !dbg !33
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: declare void @_Z8TakeCRefR1C(ptr noundef nonnull align 1 dereferenceable(1)) #3
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z9TakeCRRefO1C.carbon_thunk(ptr noundef %0) #4 {
|
||||
// CHECK:STDOUT: define internal void @_Z9TakeCRRefO1C.carbon_thunk.v(ptr noundef %0) #4 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !26
|
||||
@@ -195,7 +195,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z13TakeConstCRefRK1C.carbon_thunk(ptr noundef %0) #4 {
|
||||
// CHECK:STDOUT: define internal void @_Z13TakeConstCRefRK1C.carbon_thunk._(ptr noundef %0) #4 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !26
|
||||
@@ -207,7 +207,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: declare void @_Z10TakeIntRefRi(ptr noundef nonnull align 4 dereferenceable(4)) #3
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z11TakeIntRRefOi.carbon_thunk(ptr noundef %0) #4 {
|
||||
// CHECK:STDOUT: define internal void @_Z11TakeIntRRefOi.carbon_thunk.v(ptr noundef %0) #4 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !34
|
||||
@@ -217,7 +217,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z15TakeConstIntRefRKi.carbon_thunk(ptr noundef %0) #4 {
|
||||
// CHECK:STDOUT: define internal void @_Z15TakeConstIntRefRKi.carbon_thunk._(ptr noundef %0) #4 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !34
|
||||
@@ -335,20 +335,20 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: %.loc26_23.2.temp = alloca i32, align 4, !dbg !18
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %c.var), !dbg !14
|
||||
// CHECK:STDOUT: call void @"_COp.d288d62be0e5d791:DefaultOrUnformed.Core.93349b0fe912a29b"(ptr %c.var), !dbg !14
|
||||
// CHECK:STDOUT: call void @_Z8TakeCRefR1C10ForceThunk.carbon_thunk1(ptr %c.var), !dbg !19
|
||||
// CHECK:STDOUT: call void @_Z8TakeCRefR1C10ForceThunk.carbon_thunk.r(ptr %c.var), !dbg !19
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc20_18.2.temp), !dbg !15
|
||||
// CHECK:STDOUT: call void @_Z9TakeCRRefRK1C10ForceThunk.carbon_thunk1(ptr @C.val.loc20_20.3), !dbg !20
|
||||
// CHECK:STDOUT: call void @_Z13TakeConstCRefRK1C10ForceThunk.carbon_thunk1(ptr %c.var), !dbg !21
|
||||
// CHECK:STDOUT: call void @_Z9TakeCRRefRK1C10ForceThunk.carbon_thunk._(ptr @C.val.loc20_20.3), !dbg !20
|
||||
// CHECK:STDOUT: call void @_Z13TakeConstCRefRK1C10ForceThunk.carbon_thunk._(ptr %c.var), !dbg !21
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %n.var), !dbg !16
|
||||
// CHECK:STDOUT: store i32 poison, ptr %n.var, align 4, !dbg !16
|
||||
// CHECK:STDOUT: call void @_Z10TakeIntRefRi10ForceThunk.carbon_thunk1(ptr %n.var), !dbg !22
|
||||
// CHECK:STDOUT: call void @_Z10TakeIntRefRi10ForceThunk.carbon_thunk.r(ptr %n.var), !dbg !22
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !17
|
||||
// CHECK:STDOUT: store i32 42, ptr %_.var, align 4, !dbg !17
|
||||
// CHECK:STDOUT: call void @_Z11TakeIntRRefOi10ForceThunk.carbon_thunk1(ptr %_.var), !dbg !23
|
||||
// CHECK:STDOUT: call void @_Z11TakeIntRRefOi10ForceThunk.carbon_thunk.v(ptr %_.var), !dbg !23
|
||||
// CHECK:STDOUT: %.loc26_23.1 = load i32, ptr %n.var, align 4, !dbg !18
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc26_23.2.temp), !dbg !18
|
||||
// CHECK:STDOUT: store i32 %.loc26_23.1, ptr %.loc26_23.2.temp, align 4, !dbg !18
|
||||
// CHECK:STDOUT: call void @_Z15TakeConstIntRefRKi10ForceThunk.carbon_thunk1(ptr %.loc26_23.2.temp), !dbg !24
|
||||
// CHECK:STDOUT: call void @_Z15TakeConstIntRefRKi10ForceThunk.carbon_thunk._(ptr %.loc26_23.2.temp), !dbg !24
|
||||
// CHECK:STDOUT: call void @"_COp.7e389eab4a7e5487:core.Destroy.Core"(ptr %.loc26_23.2.temp), !dbg !18
|
||||
// CHECK:STDOUT: call void @"_COp.7e389eab4a7e5487:core.Destroy.Core"(ptr %_.var), !dbg !17
|
||||
// CHECK:STDOUT: call void @"_COp.7e389eab4a7e5487:core.Destroy.Core"(ptr %n.var), !dbg !16
|
||||
@@ -356,7 +356,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress nounwind uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1CC1Ev.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !26
|
||||
@@ -367,12 +367,12 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind
|
||||
// CHECK:STDOUT: define void @"_COp:thunk:Default.7b1e6a57c714cdb7.Core:C.Cpp"(ptr sret({}) %return) #2 !dbg !29 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk(ptr %return), !dbg !33
|
||||
// CHECK:STDOUT: call void @_ZN1CC1Ev.carbon_thunk.(ptr %return), !dbg !33
|
||||
// CHECK:STDOUT: ret void, !dbg !33
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z8TakeCRefR1C10ForceThunk.carbon_thunk1(ptr noundef nonnull align 1 dereferenceable(1) %0) #3 {
|
||||
// CHECK:STDOUT: define internal void @_Z8TakeCRefR1C10ForceThunk.carbon_thunk.r(ptr noundef nonnull align 1 dereferenceable(1) %0) #3 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1
|
||||
@@ -383,7 +383,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z9TakeCRRefRK1C10ForceThunk.carbon_thunk1(ptr noundef %0) #3 {
|
||||
// CHECK:STDOUT: define internal void @_Z9TakeCRRefRK1C10ForceThunk.carbon_thunk._(ptr noundef %0) #3 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1
|
||||
@@ -394,7 +394,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z13TakeConstCRefRK1C10ForceThunk.carbon_thunk1(ptr noundef %0) #3 {
|
||||
// CHECK:STDOUT: define internal void @_Z13TakeConstCRefRK1C10ForceThunk.carbon_thunk._(ptr noundef %0) #3 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1
|
||||
@@ -405,7 +405,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z10TakeIntRefRi10ForceThunk.carbon_thunk1(ptr noundef nonnull align 4 dereferenceable(4) %0) #3 {
|
||||
// CHECK:STDOUT: define internal void @_Z10TakeIntRefRi10ForceThunk.carbon_thunk.r(ptr noundef nonnull align 4 dereferenceable(4) %0) #3 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1
|
||||
@@ -416,7 +416,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z11TakeIntRRefOi10ForceThunk.carbon_thunk1(ptr noundef %0) #3 {
|
||||
// CHECK:STDOUT: define internal void @_Z11TakeIntRRefOi10ForceThunk.carbon_thunk.v(ptr noundef %0) #3 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1
|
||||
@@ -427,7 +427,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z15TakeConstIntRefRKi10ForceThunk.carbon_thunk1(ptr noundef %0) #3 {
|
||||
// CHECK:STDOUT: define internal void @_Z15TakeConstIntRefRKi10ForceThunk.carbon_thunk._(ptr noundef %0) #3 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1
|
||||
@@ -595,17 +595,17 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CGetRefs.Main() #0 !dbg !11 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %ReturnCRef__carbon_thunk.call = call ptr @_Z10ReturnCRef10ForceThunk.carbon_thunk0(), !dbg !14
|
||||
// CHECK:STDOUT: %ReturnCRRef__carbon_thunk.call = call ptr @_Z11ReturnCRRef10ForceThunk.carbon_thunk0(), !dbg !15
|
||||
// CHECK:STDOUT: %ReturnConstCRef__carbon_thunk.call = call ptr @_Z15ReturnConstCRef10ForceThunk.carbon_thunk0(), !dbg !16
|
||||
// CHECK:STDOUT: %ReturnIntRef__carbon_thunk.call = call ptr @_Z12ReturnIntRef10ForceThunk.carbon_thunk0(), !dbg !17
|
||||
// CHECK:STDOUT: %ReturnIntRRef__carbon_thunk.call = call ptr @_Z13ReturnIntRRef10ForceThunk.carbon_thunk0(), !dbg !18
|
||||
// CHECK:STDOUT: %ReturnConstIntRef__carbon_thunk.call = call ptr @_Z17ReturnConstIntRef10ForceThunk.carbon_thunk0(), !dbg !19
|
||||
// CHECK:STDOUT: %ReturnCRef__carbon_thunk.call = call ptr @_Z10ReturnCRef10ForceThunk.carbon_thunk.(), !dbg !14
|
||||
// CHECK:STDOUT: %ReturnCRRef__carbon_thunk.call = call ptr @_Z11ReturnCRRef10ForceThunk.carbon_thunk.(), !dbg !15
|
||||
// CHECK:STDOUT: %ReturnConstCRef__carbon_thunk.call = call ptr @_Z15ReturnConstCRef10ForceThunk.carbon_thunk.(), !dbg !16
|
||||
// CHECK:STDOUT: %ReturnIntRef__carbon_thunk.call = call ptr @_Z12ReturnIntRef10ForceThunk.carbon_thunk.(), !dbg !17
|
||||
// CHECK:STDOUT: %ReturnIntRRef__carbon_thunk.call = call ptr @_Z13ReturnIntRRef10ForceThunk.carbon_thunk.(), !dbg !18
|
||||
// CHECK:STDOUT: %ReturnConstIntRef__carbon_thunk.call = call ptr @_Z17ReturnConstIntRef10ForceThunk.carbon_thunk.(), !dbg !19
|
||||
// CHECK:STDOUT: ret void, !dbg !20
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal noundef nonnull align 1 dereferenceable(1) ptr @_Z10ReturnCRef10ForceThunk.carbon_thunk0() #1 {
|
||||
// CHECK:STDOUT: define internal noundef nonnull align 1 dereferenceable(1) ptr @_Z10ReturnCRef10ForceThunk.carbon_thunk.() #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1
|
||||
// CHECK:STDOUT: %call = call noundef nonnull align 1 dereferenceable(1) ptr @_Z10ReturnCRef10ForceThunk()
|
||||
@@ -613,7 +613,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal noundef nonnull align 1 dereferenceable(1) ptr @_Z11ReturnCRRef10ForceThunk.carbon_thunk0() #1 {
|
||||
// CHECK:STDOUT: define internal noundef nonnull align 1 dereferenceable(1) ptr @_Z11ReturnCRRef10ForceThunk.carbon_thunk.() #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1
|
||||
// CHECK:STDOUT: %call = call noundef nonnull align 1 dereferenceable(1) ptr @_Z11ReturnCRRef10ForceThunk()
|
||||
@@ -621,7 +621,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal noundef nonnull align 1 dereferenceable(1) ptr @_Z15ReturnConstCRef10ForceThunk.carbon_thunk0() #1 {
|
||||
// CHECK:STDOUT: define internal noundef nonnull align 1 dereferenceable(1) ptr @_Z15ReturnConstCRef10ForceThunk.carbon_thunk.() #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1
|
||||
// CHECK:STDOUT: %call = call noundef nonnull align 1 dereferenceable(1) ptr @_Z15ReturnConstCRef10ForceThunk()
|
||||
@@ -629,7 +629,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal noundef nonnull align 4 dereferenceable(4) ptr @_Z12ReturnIntRef10ForceThunk.carbon_thunk0() #1 {
|
||||
// CHECK:STDOUT: define internal noundef nonnull align 4 dereferenceable(4) ptr @_Z12ReturnIntRef10ForceThunk.carbon_thunk.() #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1
|
||||
// CHECK:STDOUT: %call = call noundef nonnull align 4 dereferenceable(4) ptr @_Z12ReturnIntRef10ForceThunk()
|
||||
@@ -637,7 +637,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal noundef nonnull align 4 dereferenceable(4) ptr @_Z13ReturnIntRRef10ForceThunk.carbon_thunk0() #1 {
|
||||
// CHECK:STDOUT: define internal noundef nonnull align 4 dereferenceable(4) ptr @_Z13ReturnIntRRef10ForceThunk.carbon_thunk.() #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1
|
||||
// CHECK:STDOUT: %call = call noundef nonnull align 4 dereferenceable(4) ptr @_Z13ReturnIntRRef10ForceThunk()
|
||||
@@ -645,7 +645,7 @@ fn GetRefs() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal noundef nonnull align 4 dereferenceable(4) ptr @_Z17ReturnConstIntRef10ForceThunk.carbon_thunk0() #1 {
|
||||
// CHECK:STDOUT: define internal noundef nonnull align 4 dereferenceable(4) ptr @_Z17ReturnConstIntRef10ForceThunk.carbon_thunk.() #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.ForceThunk, align 1
|
||||
// CHECK:STDOUT: %call = call noundef nonnull align 4 dereferenceable(4) ptr @_Z17ReturnConstIntRef10ForceThunk()
|
||||
|
||||
+22
-22
@@ -122,13 +122,13 @@ fn Call(x: Cpp.D) -> Cpp.C {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc6_40.1.temp = alloca i8, align 1, !dbg !15
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc6_40.1.temp), !dbg !15
|
||||
// CHECK:STDOUT: call void @_Z8ReturnU8v.carbon_thunk(ptr %.loc6_40.1.temp), !dbg !15
|
||||
// CHECK:STDOUT: call void @_Z8ReturnU8v.carbon_thunk.(ptr %.loc6_40.1.temp), !dbg !15
|
||||
// CHECK:STDOUT: %0 = load i8, ptr %.loc6_40.1.temp, align 1, !dbg !16
|
||||
// CHECK:STDOUT: ret i8 %0, !dbg !16
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z8ReturnU8v.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z8ReturnU8v.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !17
|
||||
@@ -143,13 +143,13 @@ fn Call(x: Cpp.D) -> Cpp.C {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc7_43.1.temp = alloca i16, align 2, !dbg !25
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc7_43.1.temp), !dbg !25
|
||||
// CHECK:STDOUT: call void @_Z9ReturnU16v.carbon_thunk(ptr %.loc7_43.1.temp), !dbg !25
|
||||
// CHECK:STDOUT: call void @_Z9ReturnU16v.carbon_thunk.(ptr %.loc7_43.1.temp), !dbg !25
|
||||
// CHECK:STDOUT: %0 = load i16, ptr %.loc7_43.1.temp, align 2, !dbg !26
|
||||
// CHECK:STDOUT: ret i16 %0, !dbg !26
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z9ReturnU16v.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z9ReturnU16v.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !27
|
||||
@@ -182,13 +182,13 @@ fn Call(x: Cpp.D) -> Cpp.C {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc11_40.1.temp = alloca i8, align 1, !dbg !47
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc11_40.1.temp), !dbg !47
|
||||
// CHECK:STDOUT: call void @_Z8ReturnI8v.carbon_thunk(ptr %.loc11_40.1.temp), !dbg !47
|
||||
// CHECK:STDOUT: call void @_Z8ReturnI8v.carbon_thunk.(ptr %.loc11_40.1.temp), !dbg !47
|
||||
// CHECK:STDOUT: %0 = load i8, ptr %.loc11_40.1.temp, align 1, !dbg !48
|
||||
// CHECK:STDOUT: ret i8 %0, !dbg !48
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z8ReturnI8v.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z8ReturnI8v.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !17
|
||||
@@ -203,13 +203,13 @@ fn Call(x: Cpp.D) -> Cpp.C {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc12_43.1.temp = alloca i16, align 2, !dbg !53
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc12_43.1.temp), !dbg !53
|
||||
// CHECK:STDOUT: call void @_Z9ReturnI16v.carbon_thunk(ptr %.loc12_43.1.temp), !dbg !53
|
||||
// CHECK:STDOUT: call void @_Z9ReturnI16v.carbon_thunk.(ptr %.loc12_43.1.temp), !dbg !53
|
||||
// CHECK:STDOUT: %0 = load i16, ptr %.loc12_43.1.temp, align 2, !dbg !54
|
||||
// CHECK:STDOUT: ret i16 %0, !dbg !54
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z9ReturnI16v.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z9ReturnI16v.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !27
|
||||
@@ -247,18 +247,18 @@ fn Call(x: Cpp.D) -> Cpp.C {
|
||||
// CHECK:STDOUT: %.loc24_32.1.temp = alloca i8, align 1, !dbg !72
|
||||
// CHECK:STDOUT: %.loc25_35.1.temp = alloca i16, align 2, !dbg !73
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc19_32.1.temp), !dbg !70
|
||||
// CHECK:STDOUT: call void @_Z8ReturnU8v.carbon_thunk(ptr %.loc19_32.1.temp), !dbg !70
|
||||
// CHECK:STDOUT: call void @_Z8ReturnU8v.carbon_thunk.(ptr %.loc19_32.1.temp), !dbg !70
|
||||
// CHECK:STDOUT: %.loc19_32.4 = load i8, ptr %.loc19_32.1.temp, align 1, !dbg !70
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc20_35.1.temp), !dbg !71
|
||||
// CHECK:STDOUT: call void @_Z9ReturnU16v.carbon_thunk(ptr %.loc20_35.1.temp), !dbg !71
|
||||
// CHECK:STDOUT: call void @_Z9ReturnU16v.carbon_thunk.(ptr %.loc20_35.1.temp), !dbg !71
|
||||
// CHECK:STDOUT: %.loc20_35.4 = load i16, ptr %.loc20_35.1.temp, align 2, !dbg !71
|
||||
// CHECK:STDOUT: %ReturnU32.call = call i32 @_Z9ReturnU32v(), !dbg !74
|
||||
// CHECK:STDOUT: %ReturnU64.call = call i64 @_Z9ReturnU64v(), !dbg !75
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc24_32.1.temp), !dbg !72
|
||||
// CHECK:STDOUT: call void @_Z8ReturnI8v.carbon_thunk(ptr %.loc24_32.1.temp), !dbg !72
|
||||
// CHECK:STDOUT: call void @_Z8ReturnI8v.carbon_thunk.(ptr %.loc24_32.1.temp), !dbg !72
|
||||
// CHECK:STDOUT: %.loc24_32.4 = load i8, ptr %.loc24_32.1.temp, align 1, !dbg !72
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc25_35.1.temp), !dbg !73
|
||||
// CHECK:STDOUT: call void @_Z9ReturnI16v.carbon_thunk(ptr %.loc25_35.1.temp), !dbg !73
|
||||
// CHECK:STDOUT: call void @_Z9ReturnI16v.carbon_thunk.(ptr %.loc25_35.1.temp), !dbg !73
|
||||
// CHECK:STDOUT: %.loc25_35.4 = load i16, ptr %.loc25_35.1.temp, align 2, !dbg !73
|
||||
// CHECK:STDOUT: %ReturnI32.call = call i32 @_Z9ReturnI32v(), !dbg !76
|
||||
// CHECK:STDOUT: %ReturnI64.call = call i64 @_Z9ReturnI64v(), !dbg !77
|
||||
@@ -306,9 +306,9 @@ fn Call(x: Cpp.D) -> Cpp.C {
|
||||
// CHECK:STDOUT: %my_i32.var = alloca i32, align 4, !dbg !111
|
||||
// CHECK:STDOUT: %my_i64.var = alloca i64, align 8, !dbg !112
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %my_u8.var), !dbg !105
|
||||
// CHECK:STDOUT: call void @_Z8ReturnU8v.carbon_thunk(ptr %my_u8.var), !dbg !113
|
||||
// CHECK:STDOUT: call void @_Z8ReturnU8v.carbon_thunk.(ptr %my_u8.var), !dbg !113
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %my_u16.var), !dbg !106
|
||||
// CHECK:STDOUT: call void @_Z9ReturnU16v.carbon_thunk(ptr %my_u16.var), !dbg !114
|
||||
// CHECK:STDOUT: call void @_Z9ReturnU16v.carbon_thunk.(ptr %my_u16.var), !dbg !114
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %my_u32.var), !dbg !107
|
||||
// CHECK:STDOUT: %ReturnU32.call = call i32 @_Z9ReturnU32v(), !dbg !115
|
||||
// CHECK:STDOUT: store i32 %ReturnU32.call, ptr %my_u32.var, align 4, !dbg !107
|
||||
@@ -316,9 +316,9 @@ fn Call(x: Cpp.D) -> Cpp.C {
|
||||
// CHECK:STDOUT: %ReturnU64.call = call i64 @_Z9ReturnU64v(), !dbg !116
|
||||
// CHECK:STDOUT: store i64 %ReturnU64.call, ptr %my_u64.var, align 8, !dbg !108
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %my_i8.var), !dbg !109
|
||||
// CHECK:STDOUT: call void @_Z8ReturnI8v.carbon_thunk(ptr %my_i8.var), !dbg !117
|
||||
// CHECK:STDOUT: call void @_Z8ReturnI8v.carbon_thunk.(ptr %my_i8.var), !dbg !117
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %my_i16.var), !dbg !110
|
||||
// CHECK:STDOUT: call void @_Z9ReturnI16v.carbon_thunk(ptr %my_i16.var), !dbg !118
|
||||
// CHECK:STDOUT: call void @_Z9ReturnI16v.carbon_thunk.(ptr %my_i16.var), !dbg !118
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %my_i32.var), !dbg !111
|
||||
// CHECK:STDOUT: %ReturnI32.call = call i32 @_Z9ReturnI32v(), !dbg !119
|
||||
// CHECK:STDOUT: store i32 %ReturnI32.call, ptr %my_i32.var, align 4, !dbg !111
|
||||
@@ -557,12 +557,12 @@ fn Call(x: Cpp.D) -> Cpp.C {
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CGetX.Main(ptr sret([16 x i8]) %return) #0 !dbg !11 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z4Makev.carbon_thunk(ptr %return), !dbg !15
|
||||
// CHECK:STDOUT: call void @_Z4Makev.carbon_thunk.(ptr %return), !dbg !15
|
||||
// CHECK:STDOUT: ret void, !dbg !16
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z4Makev.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z4Makev.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !17
|
||||
@@ -576,7 +576,7 @@ fn Call(x: Cpp.D) -> Cpp.C {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc9_27.1.temp = alloca [16 x i8], align 1, !dbg !23
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc9_27.1.temp), !dbg !23
|
||||
// CHECK:STDOUT: call void @_Z4Makev.carbon_thunk(ptr %.loc9_27.1.temp), !dbg !23
|
||||
// CHECK:STDOUT: call void @_Z4Makev.carbon_thunk.(ptr %.loc9_27.1.temp), !dbg !23
|
||||
// CHECK:STDOUT: call void @_ZN1XD1Ev(ptr %.loc9_27.1.temp), !dbg !23
|
||||
// CHECK:STDOUT: ret void, !dbg !24
|
||||
// CHECK:STDOUT: }
|
||||
@@ -589,7 +589,7 @@ fn Call(x: Cpp.D) -> Cpp.C {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %_.var = alloca [16 x i8], align 1, !dbg !26
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !26
|
||||
// CHECK:STDOUT: call void @_Z4Makev.carbon_thunk(ptr %_.var), !dbg !27
|
||||
// CHECK:STDOUT: call void @_Z4Makev.carbon_thunk.(ptr %_.var), !dbg !27
|
||||
// CHECK:STDOUT: call void @_ZN1XD1Ev(ptr %_.var), !dbg !26
|
||||
// CHECK:STDOUT: ret void, !dbg !28
|
||||
// CHECK:STDOUT: }
|
||||
@@ -652,12 +652,12 @@ fn Call(x: Cpp.D) -> Cpp.C {
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CCall.Main(ptr sret({}) %return, ptr %x) #0 !dbg !11 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z1f1D.carbon_thunk(ptr %x, ptr %return), !dbg !17
|
||||
// CHECK:STDOUT: call void @_Z1f1D.carbon_thunk._(ptr %x, ptr %return), !dbg !17
|
||||
// CHECK:STDOUT: ret void, !dbg !18
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z1f1D.carbon_thunk(ptr noundef %0, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z1f1D.carbon_thunk._(ptr noundef %0, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
|
||||
@@ -178,7 +178,7 @@ fn InitNontrivialDtor() {
|
||||
// CHECK:STDOUT: store ptr @array.loc13_50.15, ptr %initializer_list.initializer_list.call.init_list.begin, align 8, !dbg !34
|
||||
// CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.end = getelementptr inbounds nuw [16 x i8], ptr %.loc18_36.2.temp, i32 0, i32 8, !dbg !34
|
||||
// CHECK:STDOUT: store ptr getelementptr inbounds ([3 x i32], ptr @array.loc13_50.15, i32 1), ptr %initializer_list.initializer_list.call.init_list.end, align 8, !dbg !34
|
||||
// CHECK:STDOUT: call void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk(ptr %.loc18_36.2.temp, ptr %_.var), !dbg !33
|
||||
// CHECK:STDOUT: call void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk._(ptr %.loc18_36.2.temp, ptr %_.var), !dbg !33
|
||||
// CHECK:STDOUT: call void @_CWithinLifetime.Main(), !dbg !35
|
||||
// CHECK:STDOUT: call void @"_COp.bfd302cd235977c4:core.Destroy.Core"(ptr @array), !dbg !34
|
||||
// CHECK:STDOUT: call void @_ZN11vector_likeD2Ev(ptr %_.var), !dbg !33
|
||||
@@ -186,7 +186,7 @@ fn InitNontrivialDtor() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk(ptr noundef %list, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk._(ptr noundef %list, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %list.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
@@ -221,11 +221,11 @@ fn InitNontrivialDtor() {
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !46
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc23_69.17.temp), !dbg !47
|
||||
// CHECK:STDOUT: %.loc23_69.18.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 0, !dbg !47
|
||||
// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.18.array.index), !dbg !47
|
||||
// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr %.loc23_69.18.array.index), !dbg !47
|
||||
// CHECK:STDOUT: %.loc23_69.16.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 1, !dbg !47
|
||||
// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.16.array.index), !dbg !47
|
||||
// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr %.loc23_69.16.array.index), !dbg !47
|
||||
// CHECK:STDOUT: %.loc23_69.15.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 2, !dbg !47
|
||||
// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.15.array.index), !dbg !47
|
||||
// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr %.loc23_69.15.array.index), !dbg !47
|
||||
// CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.begin = getelementptr inbounds nuw [16 x i8], ptr %_.var, i32 0, i32 0, !dbg !46
|
||||
// CHECK:STDOUT: store ptr %.loc23_69.17.temp, ptr %initializer_list.initializer_list.call.init_list.begin, align 8, !dbg !46
|
||||
// CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.end = getelementptr inbounds nuw [16 x i8], ptr %_.var, i32 0, i32 8, !dbg !46
|
||||
@@ -237,7 +237,7 @@ fn InitNontrivialDtor() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !50
|
||||
@@ -291,7 +291,7 @@ fn InitNontrivialDtor() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; uselistorder directives
|
||||
// CHECK:STDOUT: uselistorder ptr @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple, { 2, 1, 0 }
|
||||
// CHECK:STDOUT: uselistorder ptr @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple., { 2, 1, 0 }
|
||||
// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 6, 5, 4, 3, 2, 1, 0 }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: attributes #0 = { nounwind }
|
||||
@@ -427,7 +427,7 @@ fn InitNontrivialDtor() {
|
||||
// CHECK:STDOUT: store ptr @array.loc13_50.15, ptr %initializer_list.initializer_list.call.init_list.begin, align 8, !dbg !34
|
||||
// CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.size = getelementptr inbounds nuw [16 x i8], ptr %.loc18_36.2.temp, i32 0, i32 8, !dbg !34
|
||||
// CHECK:STDOUT: store i64 3, ptr %initializer_list.initializer_list.call.init_list.size, align 8, !dbg !34
|
||||
// CHECK:STDOUT: call void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk(ptr %.loc18_36.2.temp, ptr %_.var), !dbg !33
|
||||
// CHECK:STDOUT: call void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk._(ptr %.loc18_36.2.temp, ptr %_.var), !dbg !33
|
||||
// CHECK:STDOUT: call void @_CWithinLifetime.Main(), !dbg !35
|
||||
// CHECK:STDOUT: call void @"_COp.bfd302cd235977c4:core.Destroy.Core"(ptr @array), !dbg !34
|
||||
// CHECK:STDOUT: call void @_ZN11vector_likeD2Ev(ptr %_.var), !dbg !33
|
||||
@@ -435,7 +435,7 @@ fn InitNontrivialDtor() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk(ptr noundef %list, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN11vector_likeC1ESt16initializer_listIiE.carbon_thunk._(ptr noundef %list, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %list.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
@@ -470,11 +470,11 @@ fn InitNontrivialDtor() {
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !48
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc23_69.17.temp), !dbg !49
|
||||
// CHECK:STDOUT: %.loc23_69.18.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 0, !dbg !49
|
||||
// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.18.array.index), !dbg !49
|
||||
// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr %.loc23_69.18.array.index), !dbg !49
|
||||
// CHECK:STDOUT: %.loc23_69.16.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 1, !dbg !49
|
||||
// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.16.array.index), !dbg !49
|
||||
// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr %.loc23_69.16.array.index), !dbg !49
|
||||
// CHECK:STDOUT: %.loc23_69.15.array.index = getelementptr inbounds [3 x [1 x i8]], ptr %.loc23_69.17.temp, i32 0, i64 2, !dbg !49
|
||||
// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr %.loc23_69.15.array.index), !dbg !49
|
||||
// CHECK:STDOUT: call void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr %.loc23_69.15.array.index), !dbg !49
|
||||
// CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.begin = getelementptr inbounds nuw [16 x i8], ptr %_.var, i32 0, i32 0, !dbg !48
|
||||
// CHECK:STDOUT: store ptr %.loc23_69.17.temp, ptr %initializer_list.initializer_list.call.init_list.begin, align 8, !dbg !48
|
||||
// CHECK:STDOUT: %initializer_list.initializer_list.call.init_list.size = getelementptr inbounds nuw [16 x i8], ptr %_.var, i32 0, i32 8, !dbg !48
|
||||
@@ -485,7 +485,7 @@ fn InitNontrivialDtor() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !52
|
||||
@@ -539,7 +539,7 @@ fn InitNontrivialDtor() {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; uselistorder directives
|
||||
// CHECK:STDOUT: uselistorder ptr @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple, { 2, 1, 0 }
|
||||
// CHECK:STDOUT: uselistorder ptr @_ZN15nontrivial_dtorC1Ev.carbon_thunk_tuple., { 2, 1, 0 }
|
||||
// CHECK:STDOUT: uselistorder ptr @llvm.lifetime.start.p0, { 6, 5, 4, 3, 2, 1, 0 }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: attributes #0 = { nounwind }
|
||||
|
||||
+8
-8
@@ -126,12 +126,12 @@ fn Call3() {
|
||||
// CHECK:STDOUT: ; Function Attrs: nounwind
|
||||
// CHECK:STDOUT: define void @_CPassClass.Main(ptr sret({}) %return, ptr %a) #0 !dbg !24 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_Z8identityI5ClassET_S1_.carbon_thunk(ptr %a, ptr %return), !dbg !30
|
||||
// CHECK:STDOUT: call void @_Z8identityI5ClassET_S1_.carbon_thunk._(ptr %a, ptr %return), !dbg !30
|
||||
// CHECK:STDOUT: ret void, !dbg !31
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z8identityI5ClassET_S1_.carbon_thunk(ptr noundef %x, ptr noundef %return) #2 {
|
||||
// CHECK:STDOUT: define internal void @_Z8identityI5ClassET_S1_.carbon_thunk._(ptr noundef %x, ptr noundef %return) #2 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %x.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
@@ -271,12 +271,12 @@ fn Call3() {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc12_12.2.temp = alloca {}, align 8, !dbg !14
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc12_12.2.temp), !dbg !14
|
||||
// CHECK:STDOUT: call void @_Z3fooIJEEv1XDpT_.carbon_thunk(ptr @X.val.loc12_14.3), !dbg !15
|
||||
// CHECK:STDOUT: call void @_Z3fooIJEEv1XDpT_.carbon_thunk._(ptr @X.val.loc12_14.3), !dbg !15
|
||||
// CHECK:STDOUT: ret void, !dbg !16
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z3fooIJEEv1XDpT_.carbon_thunk(ptr noundef %0) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z3fooIJEEv1XDpT_.carbon_thunk._(ptr noundef %0) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %agg.tmp = alloca %class.X, align 1
|
||||
@@ -291,12 +291,12 @@ fn Call3() {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc18_12.2.temp = alloca {}, align 8, !dbg !21
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc18_12.2.temp), !dbg !21
|
||||
// CHECK:STDOUT: call void @_Z3fooIJiEEv1XDpT_.carbon_thunk(ptr @X.val.loc12_14.3, i32 2), !dbg !22
|
||||
// CHECK:STDOUT: call void @_Z3fooIJiEEv1XDpT_.carbon_thunk.__(ptr @X.val.loc12_14.3, i32 2), !dbg !22
|
||||
// CHECK:STDOUT: ret void, !dbg !23
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z3fooIJiEEv1XDpT_.carbon_thunk(ptr noundef %0, i32 noundef %1) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z3fooIJiEEv1XDpT_.carbon_thunk.__(ptr noundef %0, i32 noundef %1) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %.addr1 = alloca i32, align 4
|
||||
@@ -314,12 +314,12 @@ fn Call3() {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.loc24_12.2.temp = alloca {}, align 8, !dbg !25
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc24_12.2.temp), !dbg !25
|
||||
// CHECK:STDOUT: call void @_Z3fooIJiiEEv1XDpT_.carbon_thunk(ptr @X.val.loc12_14.3, i32 2, i32 3), !dbg !26
|
||||
// CHECK:STDOUT: call void @_Z3fooIJiiEEv1XDpT_.carbon_thunk.___(ptr @X.val.loc12_14.3, i32 2, i32 3), !dbg !26
|
||||
// CHECK:STDOUT: ret void, !dbg !27
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_Z3fooIJiiEEv1XDpT_.carbon_thunk(ptr noundef %0, i32 noundef %1, i32 noundef %2) #1 {
|
||||
// CHECK:STDOUT: define internal void @_Z3fooIJiiEEv1XDpT_.carbon_thunk.___(ptr noundef %0, i32 noundef %1, i32 noundef %2) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %.addr1 = alloca i32, align 4
|
||||
|
||||
+3
-3
@@ -43,12 +43,12 @@ fn Call(n: Cpp.NeedThunk) {
|
||||
// CHECK:STDOUT: %.loc9_34.1.temp = alloca [1 x i8], align 1, !dbg !18
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %n2.var), !dbg !17
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %.loc9_34.1.temp), !dbg !18
|
||||
// CHECK:STDOUT: call void @_ZN9NeedThunkC1ERKS_.carbon_thunk(ptr %n, ptr %n2.var), !dbg !18
|
||||
// CHECK:STDOUT: call void @_ZN9NeedThunkC1ERKS_.carbon_thunk._(ptr %n, ptr %n2.var), !dbg !18
|
||||
// CHECK:STDOUT: ret void, !dbg !19
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN9NeedThunkC1ERKS_.carbon_thunk(ptr noundef %0, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN9NeedThunkC1ERKS_.carbon_thunk._(ptr noundef %0, ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
@@ -63,7 +63,7 @@ fn Call(n: Cpp.NeedThunk) {
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline nounwind
|
||||
// CHECK:STDOUT: define void @"_COp:thunk:Copy.fdeb6dbda014bd1f.Core:NeedThunk.Cpp"(ptr sret([1 x i8]) %return, ptr %self) #2 !dbg !23 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: call void @_ZN9NeedThunkC1ERKS_.carbon_thunk(ptr %self, ptr %return), !dbg !29
|
||||
// CHECK:STDOUT: call void @_ZN9NeedThunkC1ERKS_.carbon_thunk._(ptr %self, ptr %return), !dbg !29
|
||||
// CHECK:STDOUT: ret void, !dbg !29
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
@@ -113,12 +113,12 @@ fn AccessD(d: Cpp.D) -> i32 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %_.var = alloca [40 x i8], align 1, !dbg !14
|
||||
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(ptr %_.var), !dbg !14
|
||||
// CHECK:STDOUT: call void @_ZN1DC1Ev.carbon_thunk(ptr %_.var), !dbg !15
|
||||
// CHECK:STDOUT: call void @_ZN1DC1Ev.carbon_thunk.(ptr %_.var), !dbg !15
|
||||
// CHECK:STDOUT: ret void, !dbg !16
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: ; Function Attrs: alwaysinline mustprogress uwtable
|
||||
// CHECK:STDOUT: define internal void @_ZN1DC1Ev.carbon_thunk(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: define internal void @_ZN1DC1Ev.carbon_thunk.(ptr noundef %return) #1 {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: %return.addr = alloca ptr, align 8
|
||||
// CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !17
|
||||
|
||||
@@ -11,6 +11,50 @@
|
||||
|
||||
namespace Carbon::SemIR {
|
||||
|
||||
auto ClangDeclSignature::Print(llvm::raw_ostream& out) const -> void {
|
||||
out << "{kind: ";
|
||||
switch (kind) {
|
||||
case Normal:
|
||||
out << "normal";
|
||||
break;
|
||||
case TuplePattern:
|
||||
out << "tuple";
|
||||
break;
|
||||
}
|
||||
out << ", num_params: " << num_params;
|
||||
|
||||
auto print_mode = [&](PassingMode mode) {
|
||||
switch (mode) {
|
||||
case PassingMode::ByValue:
|
||||
out << "value";
|
||||
break;
|
||||
case PassingMode::ByVar:
|
||||
out << "var";
|
||||
break;
|
||||
case PassingMode::ByRef:
|
||||
out << "ref";
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
if (!passing_modes.empty() && llvm::any_of(passing_modes, [](auto mode) {
|
||||
return mode != PassingMode::ByVar;
|
||||
})) {
|
||||
out << ", modes: [";
|
||||
llvm::ListSeparator sep;
|
||||
for (auto mode : passing_modes) {
|
||||
out << sep;
|
||||
print_mode(mode);
|
||||
}
|
||||
out << "]";
|
||||
}
|
||||
if (self_passing_mode != PassingMode::ByRef) {
|
||||
out << ", self_mode: ";
|
||||
print_mode(self_passing_mode);
|
||||
}
|
||||
out << "}";
|
||||
}
|
||||
|
||||
auto ClangDeclKey::Print(llvm::raw_ostream& out) const -> void {
|
||||
RawStringOstream decl_stream;
|
||||
auto policy = decl->getASTContext().getPrintingPolicy();
|
||||
@@ -21,20 +65,11 @@ auto ClangDeclKey::Print(llvm::raw_ostream& out) const -> void {
|
||||
decl->print(decl_stream, policy);
|
||||
}
|
||||
|
||||
if (signature.num_params != -1) {
|
||||
out << "{decl: \"" << FormatEscaped(decl_stream.TakeStr()) << "\", kind: ";
|
||||
switch (signature.kind) {
|
||||
case ClangDeclKey::Signature::Normal:
|
||||
out << "normal";
|
||||
break;
|
||||
case ClangDeclKey::Signature::TuplePattern:
|
||||
out << "tuple";
|
||||
break;
|
||||
}
|
||||
out << ", num_params: " << signature.num_params << "}";
|
||||
} else {
|
||||
out << "\"" << FormatEscaped(decl_stream.TakeStr()) << "\"";
|
||||
out << "{decl: \"" << FormatEscaped(decl_stream.TakeStr()) << "\"";
|
||||
if (signature_id != ClangDeclSignatureId::None) {
|
||||
out << ", clang_decl_signature_id: " << signature_id;
|
||||
}
|
||||
out << "}";
|
||||
}
|
||||
|
||||
auto ClangDecl::Print(llvm::raw_ostream& out) const -> void {
|
||||
|
||||
+107
-37
@@ -15,6 +15,95 @@
|
||||
|
||||
namespace Carbon::SemIR {
|
||||
|
||||
// Information about how to form the Carbon function signature from the Clang
|
||||
// function declaration.
|
||||
struct ClangDeclSignature : public Printable<ClangDeclSignature> {
|
||||
// A passing mode for a parameter in a C++ function signature.
|
||||
enum class PassingMode : int8_t {
|
||||
// This parameter is passed by Carbon value. This is used for a C++
|
||||
// non-reference parameter that would be copied at the call site, and for a
|
||||
// C++ const reference parameter (either lvalue or rvalue reference).
|
||||
ByValue,
|
||||
// This parameter is passed as a Carbon var parameter. This is used for a
|
||||
// C++ non-reference parameter that would be moved or constructed in-place
|
||||
// at the call site, or for a C++ non-const rvalue reference parameter.
|
||||
ByVar,
|
||||
// This parameter is passed as a Carbon ref parameter. This is used for a
|
||||
// C++ non-const lvalue reference parameter.
|
||||
ByRef,
|
||||
};
|
||||
|
||||
enum Kind : int8_t {
|
||||
// A normal function signature: each C++ parameter maps into a Carbon
|
||||
// parameter.
|
||||
Normal,
|
||||
// A function signature taking a tuple pattern that contains the C++
|
||||
// parameters. This is used when importing a constructor that is used for
|
||||
// list initialization from a Carbon tuple.
|
||||
TuplePattern,
|
||||
};
|
||||
|
||||
// The kind of function signature being imported.
|
||||
Kind kind = Normal;
|
||||
|
||||
// The number of parameters to import. This can be less than the number of
|
||||
// parameters in the Clang declaration if the Clang declaration has default
|
||||
// arguments. Excludes the (implicit or explicit) object parameter, if there
|
||||
// is one.
|
||||
// TODO: Remove in favor of `passing_modes`.
|
||||
int32_t num_params = -1;
|
||||
|
||||
// The passing mode for the (implicit or explicit) object parameter, if there
|
||||
// is one. Otherwise PassingMode::ByRef.
|
||||
PassingMode self_passing_mode = PassingMode::ByRef;
|
||||
|
||||
// The passing mode for each parameter. Excludes the (implicit or explicit)
|
||||
// object parameter, if there is one. This must be the same size as
|
||||
// `num_params`.
|
||||
// TODO: Generalize this to be parameter info, not just passing mode.
|
||||
llvm::SmallVector<PassingMode, 4> passing_modes;
|
||||
|
||||
// Convenience function to make a fixed signature.
|
||||
static auto Make(
|
||||
std::initializer_list<SemIR::ClangDeclSignature::PassingMode> modes,
|
||||
Kind kind = Normal, PassingMode self_passing_mode = PassingMode::ByRef)
|
||||
-> ClangDeclSignature {
|
||||
ClangDeclSignature signature;
|
||||
signature.kind = kind;
|
||||
signature.num_params = static_cast<int32_t>(modes.size());
|
||||
signature.self_passing_mode = self_passing_mode;
|
||||
signature.passing_modes.assign(modes.begin(), modes.end());
|
||||
return signature;
|
||||
}
|
||||
|
||||
// Returns the passing mode for the i-th parameter.
|
||||
auto GetPassingMode(int32_t i) const -> PassingMode {
|
||||
return i < static_cast<int32_t>(passing_modes.size()) ? passing_modes[i]
|
||||
: PassingMode::ByVar;
|
||||
}
|
||||
|
||||
auto Print(llvm::raw_ostream& out) const -> void;
|
||||
|
||||
auto operator==(const ClangDeclSignature& rhs) const -> bool {
|
||||
return kind == rhs.kind && num_params == rhs.num_params &&
|
||||
passing_modes == rhs.passing_modes &&
|
||||
self_passing_mode == rhs.self_passing_mode;
|
||||
}
|
||||
|
||||
// Hashing for ClangDeclSignature.
|
||||
friend auto CarbonHashValue(const ClangDeclSignature& value, uint64_t seed)
|
||||
-> HashCode {
|
||||
HashCode code =
|
||||
HashValue(std::tuple{value.kind, value.num_params,
|
||||
static_cast<int8_t>(value.self_passing_mode)},
|
||||
seed);
|
||||
for (auto mode : value.passing_modes) {
|
||||
code = HashValue(static_cast<int8_t>(mode), static_cast<uint64_t>(code));
|
||||
}
|
||||
return code;
|
||||
}
|
||||
};
|
||||
|
||||
// A key describing a Clang declaration that can be looked up in the value
|
||||
// store. This is a `clang::Decl*` pointing to a canonical declaration, plus any
|
||||
// other information that affects the mapping into Carbon. Currently this
|
||||
@@ -24,29 +113,6 @@ namespace Carbon::SemIR {
|
||||
// A canonical declaration pointer is used so that we can perform direct address
|
||||
// comparisons and hash this structure based on its contents.
|
||||
struct ClangDeclKey : public Printable<ClangDeclKey> {
|
||||
// Information about how to form the Carbon function signature from the Clang
|
||||
// function declaration.
|
||||
struct Signature {
|
||||
enum Kind : int8_t {
|
||||
// A normal function signature: each C++ parameter maps into a Carbon
|
||||
// parameter.
|
||||
Normal,
|
||||
// A function signature taking a tuple pattern that contains the C++
|
||||
// parameters. This is used when importing a constructor that is used for
|
||||
// list initialization from a Carbon tuple.
|
||||
TuplePattern,
|
||||
};
|
||||
// The kind of function signature being imported.
|
||||
Kind kind = Normal;
|
||||
// The number of parameters to import. This can be less than the number of
|
||||
// parameters in the Clang declaration if the Clang declaration has default
|
||||
// arguments. Excludes the implicit object parameter, if there is one.
|
||||
int32_t num_params = -1;
|
||||
|
||||
friend auto operator==(const Signature& lhs, const Signature& rhs)
|
||||
-> bool = default;
|
||||
};
|
||||
|
||||
// For declaration classes that are unrelated to FunctionDecl, no parameter
|
||||
// count is expected.
|
||||
template <typename DeclT>
|
||||
@@ -54,35 +120,33 @@ struct ClangDeclKey : public Printable<ClangDeclKey> {
|
||||
!std::derived_from<clang::FunctionDecl, DeclT> &&
|
||||
!std::derived_from<DeclT, clang::FunctionDecl>)
|
||||
explicit ClangDeclKey(DeclT* decl)
|
||||
: ClangDeclKey(decl, Signature{}, UncheckedTag()) {}
|
||||
: ClangDeclKey(decl, ClangDeclSignatureId::None, UncheckedTag()) {}
|
||||
|
||||
// For declaration classes that are derived from FunctionDecl, a parameter
|
||||
// count is required.
|
||||
static auto ForFunctionDecl(clang::FunctionDecl* decl, Signature signature)
|
||||
static auto ForFunctionDecl(clang::FunctionDecl* decl,
|
||||
ClangDeclSignatureId signature_id)
|
||||
-> ClangDeclKey {
|
||||
return ClangDeclKey(decl, signature, UncheckedTag());
|
||||
return ClangDeclKey(decl, signature_id, UncheckedTag());
|
||||
}
|
||||
|
||||
// Factory function for clang declaration that is dynamically known to not be
|
||||
// a function declaration.
|
||||
static auto ForNonFunctionDecl(clang::Decl* decl) -> ClangDeclKey {
|
||||
CARBON_CHECK(!isa<clang::FunctionDecl>(decl));
|
||||
return ClangDeclKey(decl, Signature{}, UncheckedTag());
|
||||
return ClangDeclKey(decl, ClangDeclSignatureId::None, UncheckedTag());
|
||||
}
|
||||
|
||||
auto Print(llvm::raw_ostream& out) const -> void;
|
||||
|
||||
auto operator==(const ClangDeclKey& rhs) const -> bool {
|
||||
return decl == rhs.decl && signature == rhs.signature;
|
||||
return decl == rhs.decl && signature_id == rhs.signature_id;
|
||||
}
|
||||
|
||||
// Hashing for ClangDecl. See common/hashing.h.
|
||||
friend auto CarbonHashValue(const ClangDeclKey& value, uint64_t seed)
|
||||
-> HashCode {
|
||||
// Manual hashing support is required because `Signature` has padding.
|
||||
return HashValue(std::tuple{value.decl, value.signature.num_params,
|
||||
value.signature.kind},
|
||||
seed);
|
||||
return HashValue(std::tuple{value.decl, value.signature_id}, seed);
|
||||
}
|
||||
|
||||
// The Clang declaration pointing to the Clang AST.
|
||||
@@ -90,16 +154,17 @@ struct ClangDeclKey : public Printable<ClangDeclKey> {
|
||||
// `clang::LazyDeclPtr`.
|
||||
clang::Decl* decl;
|
||||
|
||||
// The parameters to import for a function declaration. Otherwise a
|
||||
// default-constructed value.
|
||||
Signature signature;
|
||||
// The parameters to import for a function declaration. Otherwise
|
||||
// ClangDeclSignatureId::None.
|
||||
ClangDeclSignatureId signature_id;
|
||||
|
||||
private:
|
||||
struct UncheckedTag {
|
||||
explicit UncheckedTag() = default;
|
||||
};
|
||||
ClangDeclKey(clang::Decl* decl, Signature signature, UncheckedTag /*_*/)
|
||||
: decl(decl->getCanonicalDecl()), signature(signature) {}
|
||||
ClangDeclKey(clang::Decl* decl, ClangDeclSignatureId signature_id,
|
||||
UncheckedTag /*_*/)
|
||||
: decl(decl->getCanonicalDecl()), signature_id(signature_id) {}
|
||||
};
|
||||
|
||||
// A Clang declaration mapped to a Carbon instruction.
|
||||
@@ -151,6 +216,11 @@ class ClangDeclStore {
|
||||
Map<InstId, ClangDeclId> inst_id_to_clang_decl_id_;
|
||||
};
|
||||
|
||||
// A ClangDeclSignature mapped to an ID.
|
||||
using ClangDeclSignatureStore =
|
||||
CanonicalValueStore<ClangDeclSignatureId, ClangDeclSignature,
|
||||
Tag<CheckIRId>, ClangDeclSignature>;
|
||||
|
||||
} // namespace Carbon::SemIR
|
||||
|
||||
#endif // CARBON_TOOLCHAIN_SEM_IR_CLANG_DECL_H_
|
||||
|
||||
+40
-36
@@ -56,6 +56,7 @@ File::File(const Parse::Tree* parse_tree, CheckIRId check_ir_id,
|
||||
// `ImportIRId::{ApiForImpl,Cpp}`.
|
||||
import_irs_(check_ir_id, 2),
|
||||
clang_decls_(check_ir_id),
|
||||
clang_decl_signatures_(check_ir_id),
|
||||
// The `+1` prevents adding a tag to the global `NameSpace::PackageInstId`
|
||||
// instruction. It's not a "singleton" instruction, but it's a unique
|
||||
// instruction id that comes right after the singletons.
|
||||
@@ -143,42 +144,43 @@ auto File::OutputYaml(bool include_singletons) const -> Yaml::OutputMapping {
|
||||
return Yaml::OutputMapping([this, include_singletons](
|
||||
Yaml::OutputMapping::Map map) {
|
||||
map.Add("filename", filename_);
|
||||
map.Add("sem_ir", Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) {
|
||||
map.Add("names", names().OutputYaml());
|
||||
map.Add("import_irs", import_irs_.OutputYaml());
|
||||
map.Add("import_ir_insts", import_ir_insts_.OutputYaml());
|
||||
map.Add("clang_decls", clang_decls_.OutputYaml());
|
||||
map.Add("name_scopes", name_scopes_.OutputYaml());
|
||||
map.Add("entity_names", entity_names_.OutputYaml());
|
||||
map.Add("cpp_global_vars", cpp_global_vars_.OutputYaml());
|
||||
map.Add("functions", functions_.OutputYaml());
|
||||
map.Add("classes", classes_.OutputYaml());
|
||||
map.Add("interfaces", interfaces_.OutputYaml());
|
||||
map.Add("associated_constants",
|
||||
associated_constants_.OutputYaml());
|
||||
map.Add("impls", impls_.OutputYaml());
|
||||
map.Add("generics", generics_.OutputYaml());
|
||||
map.Add("specifics", specifics_.OutputYaml());
|
||||
map.Add("specific_interfaces", specific_interfaces_.OutputYaml());
|
||||
map.Add("struct_type_fields", struct_type_fields_.OutputYaml());
|
||||
map.Add("types", types_.OutputYaml());
|
||||
map.Add("facet_types", facet_types_.OutputYaml());
|
||||
map.Add("insts",
|
||||
Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) {
|
||||
for (auto [id, inst] : insts_.enumerate()) {
|
||||
inst.CacheBundleDebugKinds(bundles_);
|
||||
if (!include_singletons && IsSingletonInstId(id)) {
|
||||
continue;
|
||||
}
|
||||
map.Add(PrintToString(id), Yaml::OutputScalar(inst));
|
||||
}
|
||||
}));
|
||||
map.Add("bundles", bundles_.OutputYaml());
|
||||
map.Add("constant_values",
|
||||
constant_values_.OutputYaml(include_singletons));
|
||||
map.Add("inst_blocks", inst_blocks_.OutputYaml());
|
||||
map.Add("value_stores", value_stores_->OutputYaml());
|
||||
}));
|
||||
map.Add(
|
||||
"sem_ir", Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) {
|
||||
map.Add("names", names().OutputYaml());
|
||||
map.Add("import_irs", import_irs_.OutputYaml());
|
||||
map.Add("import_ir_insts", import_ir_insts_.OutputYaml());
|
||||
map.Add("clang_decls", clang_decls_.OutputYaml());
|
||||
map.Add("clang_decl_signatures", clang_decl_signatures_.OutputYaml());
|
||||
map.Add("name_scopes", name_scopes_.OutputYaml());
|
||||
map.Add("entity_names", entity_names_.OutputYaml());
|
||||
map.Add("cpp_global_vars", cpp_global_vars_.OutputYaml());
|
||||
map.Add("functions", functions_.OutputYaml());
|
||||
map.Add("classes", classes_.OutputYaml());
|
||||
map.Add("interfaces", interfaces_.OutputYaml());
|
||||
map.Add("associated_constants", associated_constants_.OutputYaml());
|
||||
map.Add("impls", impls_.OutputYaml());
|
||||
map.Add("generics", generics_.OutputYaml());
|
||||
map.Add("specifics", specifics_.OutputYaml());
|
||||
map.Add("specific_interfaces", specific_interfaces_.OutputYaml());
|
||||
map.Add("struct_type_fields", struct_type_fields_.OutputYaml());
|
||||
map.Add("types", types_.OutputYaml());
|
||||
map.Add("facet_types", facet_types_.OutputYaml());
|
||||
map.Add("insts",
|
||||
Yaml::OutputMapping([&](Yaml::OutputMapping::Map map) {
|
||||
for (auto [id, inst] : insts_.enumerate()) {
|
||||
inst.CacheBundleDebugKinds(bundles_);
|
||||
if (!include_singletons && IsSingletonInstId(id)) {
|
||||
continue;
|
||||
}
|
||||
map.Add(PrintToString(id), Yaml::OutputScalar(inst));
|
||||
}
|
||||
}));
|
||||
map.Add("bundles", bundles_.OutputYaml());
|
||||
map.Add("constant_values",
|
||||
constant_values_.OutputYaml(include_singletons));
|
||||
map.Add("inst_blocks", inst_blocks_.OutputYaml());
|
||||
map.Add("value_stores", value_stores_->OutputYaml());
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -200,6 +202,8 @@ auto File::CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const
|
||||
mem_usage.Collect(MemUsage::ConcatLabel(label, "import_ir_insts_"),
|
||||
import_ir_insts_);
|
||||
mem_usage.Collect(MemUsage::ConcatLabel(label, "clang_decls_"), clang_decls_);
|
||||
mem_usage.Collect(MemUsage::ConcatLabel(label, "clang_decl_signatures_"),
|
||||
clang_decl_signatures_);
|
||||
mem_usage.Collect(MemUsage::ConcatLabel(label, "struct_type_fields_"),
|
||||
struct_type_fields_);
|
||||
mem_usage.Collect(MemUsage::ConcatLabel(label, "insts_"), insts_);
|
||||
|
||||
@@ -238,6 +238,12 @@ class File : public Printable<File> {
|
||||
auto set_cpp_file(std::unique_ptr<SemIR::CppFile> cpp_file) -> void;
|
||||
auto clang_decls() -> ClangDeclStore& { return clang_decls_; }
|
||||
auto clang_decls() const -> const ClangDeclStore& { return clang_decls_; }
|
||||
auto clang_decl_signatures() -> ClangDeclSignatureStore& {
|
||||
return clang_decl_signatures_;
|
||||
}
|
||||
auto clang_decl_signatures() const -> const ClangDeclSignatureStore& {
|
||||
return clang_decl_signatures_;
|
||||
}
|
||||
auto names() const -> NameStoreWrapper {
|
||||
return NameStoreWrapper(&identifiers());
|
||||
}
|
||||
@@ -393,6 +399,9 @@ class File : public Printable<File> {
|
||||
// not add multiple entries with the same `decl` and different `inst_id`.
|
||||
ClangDeclStore clang_decls_ = ClangDeclStore(check_ir_id());
|
||||
|
||||
// Storage for function signatures used in C++ interop.
|
||||
ClangDeclSignatureStore clang_decl_signatures_;
|
||||
|
||||
// All instructions. The first entries will always be the singleton
|
||||
// instructions.
|
||||
InstStore insts_;
|
||||
|
||||
@@ -493,6 +493,13 @@ struct ClangDeclId : public IdBase<ClangDeclId> {
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
// The ID of a `ClangDeclSignature`.
|
||||
struct ClangDeclSignatureId : public IdBase<ClangDeclSignatureId> {
|
||||
static constexpr llvm::StringLiteral Label = "clang_decl_signature_id";
|
||||
|
||||
using IdBase::IdBase;
|
||||
};
|
||||
|
||||
// A boolean value.
|
||||
struct BoolValue : public IdBase<BoolValue> {
|
||||
// Not used by `Print`, but for `IdKind`.
|
||||
|
||||
@@ -61,6 +61,7 @@ TEST(SemIRTest, Yaml) {
|
||||
Pair("import_irs", Yaml::Mapping(SizeIs(2))),
|
||||
Pair("import_ir_insts", Yaml::Mapping(SizeIs(0))),
|
||||
Pair("clang_decls", Yaml::Mapping(SizeIs(0))),
|
||||
Pair("clang_decl_signatures", Yaml::Mapping(SizeIs(0))),
|
||||
Pair("name_scopes", Yaml::Mapping(SizeIs(1))),
|
||||
Pair("entity_names", Yaml::Mapping(SizeIs(1))),
|
||||
Pair("cpp_global_vars", Yaml::Mapping(SizeIs(0))),
|
||||
|
||||
Reference in New Issue
Block a user