Reverting patch rL323952 due to build errors that I
haven't encountered in local builds.
llvm-svn: 323956
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index d60b5fb..5f73d4c 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -1479,8 +1479,8 @@
const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);
if (capture.isConstant()) {
auto addr = LocalDeclMap.find(variable)->second;
- (void)DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(),
- Builder);
+ DI->EmitDeclareOfAutoVariable(variable, addr.getPointer(),
+ Builder);
continue;
}
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index e766ccc..d29e079 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2292,14 +2292,12 @@
llvm::DIFile *Unit) {
llvm::DIType *ElementTy = getOrCreateType(Ty->getElementType(), Unit);
int64_t Count = Ty->getNumElements();
+ if (Count == 0)
+ // If number of elements are not known then this is an unbounded array.
+ // Use Count == -1 to express such arrays.
+ Count = -1;
- llvm::Metadata *Subscript;
- QualType QTy(Ty, 0);
- auto SizeExpr = SizeExprCache.find(QTy);
- if (SizeExpr != SizeExprCache.end())
- Subscript = DBuilder.getOrCreateSubrange(0, SizeExpr->getSecond());
- else
- Subscript = DBuilder.getOrCreateSubrange(0, Count ? Count : -1);
+ llvm::Metadata *Subscript = DBuilder.getOrCreateSubrange(0, Count);
llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
@@ -2356,12 +2354,8 @@
}
}
- auto SizeNode = SizeExprCache.find(EltTy);
- if (SizeNode != SizeExprCache.end())
- Subscripts.push_back(
- DBuilder.getOrCreateSubrange(0, SizeNode->getSecond()));
- else
- Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count));
+ // FIXME: Verify this is right for VLAs.
+ Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count));
EltTy = Ty->getElementType();
}
@@ -3479,14 +3473,13 @@
nullptr, Elements);
}
-llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
- llvm::Value *Storage,
- llvm::Optional<unsigned> ArgNo,
- CGBuilderTy &Builder) {
+void CGDebugInfo::EmitDeclare(const VarDecl *VD, llvm::Value *Storage,
+ llvm::Optional<unsigned> ArgNo,
+ CGBuilderTy &Builder) {
assert(DebugKind >= codegenoptions::LimitedDebugInfo);
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
if (VD->hasAttr<NoDebugAttr>())
- return nullptr;
+ return;
bool Unwritten =
VD->isImplicit() || (isa<Decl>(VD->getDeclContext()) &&
@@ -3504,7 +3497,7 @@
// If there is no debug info for this type then do not emit debug info
// for this variable.
if (!Ty)
- return nullptr;
+ return;
// Get location information.
unsigned Line = 0;
@@ -3600,15 +3593,13 @@
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
llvm::DebugLoc::get(Line, Column, Scope, CurInlinedAt),
Builder.GetInsertBlock());
-
- return D;
}
-llvm::DILocalVariable *
-CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD, llvm::Value *Storage,
- CGBuilderTy &Builder) {
+void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
+ llvm::Value *Storage,
+ CGBuilderTy &Builder) {
assert(DebugKind >= codegenoptions::LimitedDebugInfo);
- return EmitDeclare(VD, Storage, llvm::None, Builder);
+ EmitDeclare(VD, Storage, llvm::None, Builder);
}
llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy,
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index de6dbdc..4f7b7f2 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -81,10 +81,6 @@
llvm::SmallDenseMap<llvm::StringRef, llvm::StringRef> DebugPrefixMap;
- /// Cache that maps VLA types to size expressions for that type,
- /// represented by instantiated Metadata nodes.
- llvm::SmallDenseMap<QualType, llvm::Metadata *> SizeExprCache;
-
struct ObjCInterfaceCacheEntry {
const ObjCInterfaceType *Type;
llvm::DIType *Decl;
@@ -313,11 +309,6 @@
void finalize();
- /// Register VLA size expression debug node with the qualified type.
- void registerVLASizeExpression(QualType Ty, llvm::Metadata *SizeExpr) {
- SizeExprCache[Ty] = SizeExpr;
- }
-
/// Module debugging: Support for building PCMs.
/// @{
/// Set the main CU's DwoId field to \p Signature.
@@ -388,11 +379,8 @@
/// Emit call to \c llvm.dbg.declare for an automatic variable
/// declaration.
- /// Returns a pointer to the DILocalVariable associated with the
- /// llvm.dbg.declare, or nullptr otherwise.
- llvm::DILocalVariable *EmitDeclareOfAutoVariable(const VarDecl *Decl,
- llvm::Value *AI,
- CGBuilderTy &Builder);
+ void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI,
+ CGBuilderTy &Builder);
/// Emit call to \c llvm.dbg.declare for an imported variable
/// declaration in a block.
@@ -463,14 +451,10 @@
llvm::DIMacroFile *CreateTempMacroFile(llvm::DIMacroFile *Parent,
SourceLocation LineLoc,
SourceLocation FileLoc);
-
private:
/// Emit call to llvm.dbg.declare for a variable declaration.
- /// Returns a pointer to the DILocalVariable associated with the
- /// llvm.dbg.declare, or nullptr otherwise.
- llvm::DILocalVariable *EmitDeclare(const VarDecl *decl, llvm::Value *AI,
- llvm::Optional<unsigned> ArgNo,
- CGBuilderTy &Builder);
+ void EmitDeclare(const VarDecl *decl, llvm::Value *AI,
+ llvm::Optional<unsigned> ArgNo, CGBuilderTy &Builder);
/// Build up structure info for the byref. See \a BuildByRefType.
llvm::DIType *EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 6a20048..04585a8 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -955,58 +955,6 @@
C->setDoesNotThrow();
}
-void CodeGenFunction::EmitAndRegisterVariableArrayDimensions(
- CGDebugInfo *DI, const VarDecl &D, bool EmitDebugInfo) {
- // For each dimension stores its QualType and corresponding
- // size-expression Value.
- SmallVector<CodeGenFunction::VlaSizePair, 4> Dimensions;
-
- // Break down the array into individual dimensions.
- QualType Type1D = D.getType();
- while (getContext().getAsVariableArrayType(Type1D)) {
- auto VlaSize = getVLAElements1D(Type1D);
- if (auto *C = dyn_cast<llvm::ConstantInt>(VlaSize.NumElts))
- Dimensions.emplace_back(C, Type1D.getUnqualifiedType());
- else {
- auto SizeExprAddr =
- CreateDefaultAlignTempAlloca(VlaSize.NumElts->getType(), "vla_expr");
- Builder.CreateStore(VlaSize.NumElts, SizeExprAddr);
- Dimensions.emplace_back(SizeExprAddr.getPointer(),
- Type1D.getUnqualifiedType());
- }
- Type1D = VlaSize.Type;
- }
-
- if (!EmitDebugInfo)
- return;
-
- // Register each dimension's size-expression with a DILocalVariable,
- // so that it can be used by CGDebugInfo when instantiating a DISubrange
- // to describe this array.
- for (auto &VlaSize : Dimensions) {
- llvm::Metadata *MD;
- if (auto *C = dyn_cast<llvm::ConstantInt>(VlaSize.NumElts))
- MD = llvm::ConstantAsMetadata::get(C);
- else {
- // Create an artificial VarDecl to generate debug info for.
- IdentifierInfo &NameIdent = getContext().Idents.getOwn(
- cast<llvm::AllocaInst>(VlaSize.NumElts)->getName());
- auto VlaExprTy = VlaSize.NumElts->getType()->getPointerElementType();
- auto QT = getContext().getIntTypeForBitwidth(
- VlaExprTy->getScalarSizeInBits(), false);
- auto *ArtificialDecl = VarDecl::Create(
- getContext(), const_cast<DeclContext *>(D.getDeclContext()),
- D.getLocation(), D.getLocation(), &NameIdent, QT,
- getContext().CreateTypeSourceInfo(QT), SC_Auto);
-
- MD = DI->EmitDeclareOfAutoVariable(ArtificialDecl, VlaSize.NumElts,
- Builder);
- }
- assert(MD && "No Size expression debug node created");
- DI->registerVLASizeExpression(VlaSize.Type, MD);
- }
-}
-
/// EmitAutoVarAlloca - Emit the alloca and debug information for a
/// local variable. Does not emit initialization or destruction.
CodeGenFunction::AutoVarEmission
@@ -1027,10 +975,6 @@
if (Ty->isVariablyModifiedType())
EmitVariablyModifiedType(Ty);
- auto *DI = getDebugInfo();
- bool EmitDebugInfo = DI && CGM.getCodeGenOpts().getDebugInfo() >=
- codegenoptions::LimitedDebugInfo;
-
Address address = Address::invalid();
if (Ty->isConstantSizeType()) {
bool NRVO = getLangOpts().ElideConstructors &&
@@ -1164,26 +1108,28 @@
pushStackRestore(NormalCleanup, Stack);
}
- auto VlaSize = getVLASize(Ty);
- llvm::Type *llvmTy = ConvertTypeForMem(VlaSize.Type);
+ llvm::Value *elementCount;
+ QualType elementType;
+ std::tie(elementCount, elementType) = getVLASize(Ty);
+
+ llvm::Type *llvmTy = ConvertTypeForMem(elementType);
// Allocate memory for the array.
- address = CreateTempAlloca(llvmTy, alignment, "vla", VlaSize.NumElts);
-
- // If we have debug info enabled, properly describe the VLA dimensions for
- // this type by registering the vla size expression for each of the
- // dimensions.
- EmitAndRegisterVariableArrayDimensions(DI, D, EmitDebugInfo);
+ address = CreateTempAlloca(llvmTy, alignment, "vla", elementCount);
}
setAddrOfLocalVar(&D, address);
emission.Addr = address;
// Emit debug info for local var declaration.
- if (EmitDebugInfo && HaveInsertPoint()) {
- DI->setLocation(D.getLocation());
- (void)DI->EmitDeclareOfAutoVariable(&D, address.getPointer(), Builder);
- }
+ if (HaveInsertPoint())
+ if (CGDebugInfo *DI = getDebugInfo()) {
+ if (CGM.getCodeGenOpts().getDebugInfo() >=
+ codegenoptions::LimitedDebugInfo) {
+ DI->setLocation(D.getLocation());
+ DI->EmitDeclareOfAutoVariable(&D, address.getPointer(), Builder);
+ }
+ }
if (D.hasAttr<AnnotateAttr>())
EmitVarAnnotations(&D, address.getPointer());
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index d8fc270..73354cd 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -873,7 +873,7 @@
if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
return CGF.Builder.getInt(CAT->getSize());
else if (const auto *VAT = dyn_cast<VariableArrayType>(AT))
- return CGF.getVLASize(VAT).NumElts;
+ return CGF.getVLASize(VAT).first;
// Ignore pass_object_size here. It's not applicable on decayed pointers.
}
}
@@ -3313,7 +3313,7 @@
auto *Idx = EmitIdxAfterBase(/*Promote*/true);
// The element count here is the total number of non-VLA elements.
- llvm::Value *numElements = getVLASize(vla).NumElts;
+ llvm::Value *numElements = getVLASize(vla).first;
// Effectively, the multiply by the VLA size is part of the GEP.
// GEP indexes are signed, and scaling an index isn't permitted to
@@ -3547,7 +3547,7 @@
emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, TBAAInfo,
BaseTy, VLA->getElementType(), IsLowerBound);
// The element count here is the total number of non-VLA elements.
- llvm::Value *NumElements = getVLASize(VLA).NumElts;
+ llvm::Value *NumElements = getVLASize(VLA).first;
// Effectively, the multiply by the VLA size is part of the GEP.
// GEP indexes are signed, and scaling an index isn't permitted to
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 2a0dd4a..668c572 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -1973,7 +1973,7 @@
// VLA types don't have constant size.
if (const VariableArrayType *vla
= CGF.getContext().getAsVariableArrayType(type)) {
- llvm::Value *numElts = CGF.getVLASize(vla).NumElts;
+ llvm::Value *numElts = CGF.getVLASize(vla).first;
if (!isInc) numElts = Builder.CreateNSWNeg(numElts, "vla.negsize");
if (CGF.getLangOpts().isSignedOverflowDefined())
value = Builder.CreateGEP(value, numElts, "vla.inc");
@@ -2271,13 +2271,16 @@
CGF.EmitIgnoredExpr(E->getArgumentExpr());
}
- auto VlaSize = CGF.getVLASize(VAT);
- llvm::Value *size = VlaSize.NumElts;
+ QualType eltType;
+ llvm::Value *numElts;
+ std::tie(numElts, eltType) = CGF.getVLASize(VAT);
+
+ llvm::Value *size = numElts;
// Scale the number of non-VLA elements by the non-VLA element size.
- CharUnits eltSize = CGF.getContext().getTypeSizeInChars(VlaSize.Type);
+ CharUnits eltSize = CGF.getContext().getTypeSizeInChars(eltType);
if (!eltSize.isOne())
- size = CGF.Builder.CreateNUWMul(CGF.CGM.getSize(eltSize), size);
+ size = CGF.Builder.CreateNUWMul(CGF.CGM.getSize(eltSize), numElts);
return size;
}
@@ -2764,7 +2767,7 @@
if (const VariableArrayType *vla
= CGF.getContext().getAsVariableArrayType(elementType)) {
// The element count here is the total number of non-VLA elements.
- llvm::Value *numElements = CGF.getVLASize(vla).NumElts;
+ llvm::Value *numElements = CGF.getVLASize(vla).first;
// Effectively, the multiply by the VLA size is part of the GEP.
// GEP indexes are signed, and scaling an index isn't permitted to
@@ -2959,9 +2962,10 @@
// For a variable-length array, this is going to be non-constant.
if (const VariableArrayType *vla
= CGF.getContext().getAsVariableArrayType(elementType)) {
- auto VlaSize = CGF.getVLASize(vla);
- elementType = VlaSize.Type;
- divisor = VlaSize.NumElts;
+ llvm::Value *numElements;
+ std::tie(numElements, elementType) = CGF.getVLASize(vla);
+
+ divisor = numElements;
// Scale the number of non-VLA elements by the non-VLA element size.
CharUnits eltSize = CGF.getContext().getTypeSizeInChars(elementType);
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 1eae838..e85590b 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -5154,7 +5154,7 @@
llvm::Value *Size = CGF.Builder.CreateIntCast(
CGF.getVLASize(
CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
- .NumElts,
+ .first,
CGF.SizeTy, /*isSigned=*/false);
CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
Elem);
diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
index 674e843..7da8915 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp
@@ -2232,7 +2232,7 @@
llvm::Value *Size = CGF.Builder.CreateIntCast(
CGF.getVLASize(
CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
- .NumElts,
+ .first,
CGF.SizeTy, /*isSigned=*/false);
CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
Elem);
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 052ebca..fb919d7 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -237,10 +237,9 @@
if (SizeInChars.isZero()) {
// getTypeSizeInChars() returns 0 for a VLA.
while (auto *VAT = C.getAsVariableArrayType(Ty)) {
- auto VlaSize = getVLASize(VAT);
- Ty = VlaSize.Type;
- Size = Size ? Builder.CreateNUWMul(Size, VlaSize.NumElts)
- : VlaSize.NumElts;
+ llvm::Value *ArraySize;
+ std::tie(ArraySize, Ty) = getVLASize(VAT);
+ Size = Size ? Builder.CreateNUWMul(Size, ArraySize) : ArraySize;
}
SizeInChars = C.getTypeSizeInChars(Ty);
if (SizeInChars.isZero())
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index a7591b1..e62d3e7 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1758,9 +1758,12 @@
if (const VariableArrayType *vlaType =
dyn_cast_or_null<VariableArrayType>(
getContext().getAsArrayType(Ty))) {
- auto VlaSize = getVLASize(vlaType);
- SizeVal = VlaSize.NumElts;
- CharUnits eltSize = getContext().getTypeSizeInChars(VlaSize.Type);
+ QualType eltType;
+ llvm::Value *numElts;
+ std::tie(numElts, eltType) = getVLASize(vlaType);
+
+ SizeVal = numElts;
+ CharUnits eltSize = getContext().getTypeSizeInChars(eltType);
if (!eltSize.isOne())
SizeVal = Builder.CreateNUWMul(SizeVal, CGM.getSize(eltSize));
vla = vlaType;
@@ -1843,7 +1846,7 @@
// this is the size of the VLA in bytes, not its size in elements.
llvm::Value *numVLAElements = nullptr;
if (isa<VariableArrayType>(arrayType)) {
- numVLAElements = getVLASize(cast<VariableArrayType>(arrayType)).NumElts;
+ numVLAElements = getVLASize(cast<VariableArrayType>(arrayType)).first;
// Walk into all VLAs. This doesn't require changes to addr,
// which has type T* where T is the first non-VLA element type.
@@ -1924,13 +1927,14 @@
return numElements;
}
-CodeGenFunction::VlaSizePair CodeGenFunction::getVLASize(QualType type) {
+std::pair<llvm::Value*, QualType>
+CodeGenFunction::getVLASize(QualType type) {
const VariableArrayType *vla = getContext().getAsVariableArrayType(type);
assert(vla && "type was not a variable array type!");
return getVLASize(vla);
}
-CodeGenFunction::VlaSizePair
+std::pair<llvm::Value*, QualType>
CodeGenFunction::getVLASize(const VariableArrayType *type) {
// The number of elements so far; always size_t.
llvm::Value *numElements = nullptr;
@@ -1951,22 +1955,7 @@
}
} while ((type = getContext().getAsVariableArrayType(elementType)));
- return { numElements, elementType };
-}
-
-CodeGenFunction::VlaSizePair
-CodeGenFunction::getVLAElements1D(QualType type) {
- const VariableArrayType *vla = getContext().getAsVariableArrayType(type);
- assert(vla && "type was not a variable array type!");
- return getVLAElements1D(vla);
-}
-
-CodeGenFunction::VlaSizePair
-CodeGenFunction::getVLAElements1D(const VariableArrayType *Vla) {
- llvm::Value *VlaSize = VLASizeMap[Vla->getSizeExpr()];
- assert(VlaSize && "no size for VLA!");
- assert(VlaSize->getType() == SizeTy);
- return { VlaSize, Vla->getElementType() };
+ return std::pair<llvm::Value*,QualType>(numElements, elementType);
}
void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 35ecf4d..75071a8 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -2198,24 +2198,12 @@
/// This function can be called with a null (unreachable) insert point.
void EmitVariablyModifiedType(QualType Ty);
- struct VlaSizePair {
- llvm::Value *NumElts;
- QualType Type;
-
- VlaSizePair(llvm::Value *NE, QualType T) : NumElts(NE), Type(T) {}
- };
-
- /// Return the number of elements for a single dimension
- /// for the given array type.
- VlaSizePair getVLAElements1D(const VariableArrayType *vla);
- VlaSizePair getVLAElements1D(QualType vla);
-
- /// Returns an LLVM value that corresponds to the size,
+ /// getVLASize - Returns an LLVM value that corresponds to the size,
/// in non-variably-sized elements, of a variable length array type,
/// plus that largest non-variably-sized element type. Assumes that
/// the type has already been emitted with EmitVariablyModifiedType.
- VlaSizePair getVLASize(const VariableArrayType *vla);
- VlaSizePair getVLASize(QualType vla);
+ std::pair<llvm::Value*,QualType> getVLASize(const VariableArrayType *vla);
+ std::pair<llvm::Value*,QualType> getVLASize(QualType vla);
/// LoadCXXThis - Load the value of 'this'. This function is only valid while
/// generating code for an C++ member function.
@@ -2523,15 +2511,6 @@
void emitAutoVarTypeCleanup(const AutoVarEmission &emission,
QualType::DestructionKind dtorKind);
- /// Emits the alloca and debug information for the size expressions for each
- /// dimension of an array. It registers the association of its (1-dimensional)
- /// QualTypes and size expression's debug node, so that CGDebugInfo can
- /// reference this node when creating the DISubrange object to describe the
- /// array types.
- void EmitAndRegisterVariableArrayDimensions(CGDebugInfo *DI,
- const VarDecl &D,
- bool EmitDebugInfo);
-
void EmitStaticVarDecl(const VarDecl &D,
llvm::GlobalValue::LinkageTypes Linkage);