using namespace clang;
using namespace clang::CodeGen;
+static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) {
+ auto TI = Ctx.getTypeInfo(Ty);
+ return TI.AlignIsRequired ? TI.Align : 0;
+}
+
+static uint32_t getTypeAlignIfRequired(QualType Ty, const ASTContext &Ctx) {
+ return getTypeAlignIfRequired(Ty.getTypePtr(), Ctx);
+}
+
+static uint32_t getDeclAlignIfRequired(const Decl *D, const ASTContext &Ctx) {
+ return D->hasAttr<AlignedAttr>() ? D->getMaxAlignment() : 0;
+}
+
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
: CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()),
DebugTypeExtRefs(CGM.getCodeGenOpts().DebugTypeExtRefs),
BTName = BT->getName(CGM.getLangOpts());
break;
}
- // Bit size, align and offset of the type.
+ // Bit size and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(BT);
- uint32_t Align = CGM.getContext().getTypeAlign(BT);
- return DBuilder.createBasicType(BTName, Size, Align, Encoding);
+ return DBuilder.createBasicType(BTName, Size, Encoding);
}
llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) {
- // Bit size, align and offset of the type.
+ // Bit size and offset of the type.
llvm::dwarf::TypeKind Encoding = llvm::dwarf::DW_ATE_complex_float;
if (Ty->isComplexIntegerType())
Encoding = llvm::dwarf::DW_ATE_lo_user;
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint32_t Align = CGM.getContext().getTypeAlign(Ty);
- return DBuilder.createBasicType("complex", Size, Align, Encoding);
+ return DBuilder.createBasicType("complex", Size, Encoding);
}
llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty,
const RecordDecl *D = RD->getDefinition();
if (D && D->isCompleteDefinition()) {
Size = CGM.getContext().getTypeSize(Ty);
- Align = CGM.getContext().getTypeAlign(Ty);
+ Align = getDeclAlignIfRequired(D, CGM.getContext());
}
// Create the type.
// because that does not return the correct value for references.
unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
uint64_t Size = CGM.getTarget().getPointerWidth(AS);
- uint32_t Align = CGM.getContext().getTypeAlign(Ty);
+ auto Align = getTypeAlignIfRequired(Ty, CGM.getContext());
if (Tag == llvm::dwarf::DW_TAG_reference_type ||
Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
CGM.getTypes().getCGRecordLayout(RD).getBitFieldInfo(BitFieldDecl);
uint64_t SizeInBits = BitFieldInfo.Size;
assert(SizeInBits > 0 && "found named 0-width bitfield");
- uint32_t AlignInBits = CGM.getContext().getTypeAlign(Ty);
uint64_t StorageOffsetInBits =
CGM.getContext().toBits(BitFieldInfo.StorageOffset);
uint64_t OffsetInBits = StorageOffsetInBits + BitFieldInfo.Offset;
llvm::DINode::DIFlags Flags = getAccessFlag(BitFieldDecl->getAccess(), RD);
return DBuilder.createBitFieldMemberType(
- RecordTy, Name, File, Line, SizeInBits, AlignInBits, OffsetInBits,
- StorageOffsetInBits, Flags, DebugType);
+ RecordTy, Name, File, Line, SizeInBits, OffsetInBits, StorageOffsetInBits,
+ Flags, DebugType);
}
llvm::DIType *
CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc,
AccessSpecifier AS, uint64_t offsetInBits,
- llvm::DIFile *tunit, llvm::DIScope *scope,
- const RecordDecl *RD) {
+ uint32_t AlignInBits, llvm::DIFile *tunit,
+ llvm::DIScope *scope, const RecordDecl *RD) {
llvm::DIType *debugType = getOrCreateType(type, tunit);
// Get the location for the field.
unsigned line = getLineNumber(loc);
uint64_t SizeInBits = 0;
- uint32_t AlignInBits = 0;
+ auto Align = AlignInBits;
if (!type->isIncompleteArrayType()) {
TypeInfo TI = CGM.getContext().getTypeInfo(type);
SizeInBits = TI.Width;
- AlignInBits = TI.Align;
+ if (!Align)
+ Align = getTypeAlignIfRequired(type, CGM.getContext());
}
llvm::DINode::DIFlags flags = getAccessFlag(AS, RD);
return DBuilder.createMemberType(scope, name, file, line, SizeInBits,
- AlignInBits, offsetInBits, flags, debugType);
+ Align, offsetInBits, flags, debugType);
}
void CGDebugInfo::CollectRecordLambdaFields(
VarDecl *V = C.getCapturedVar();
StringRef VName = V->getName();
llvm::DIFile *VUnit = getOrCreateFile(Loc);
+ auto Align = getDeclAlignIfRequired(V, CGM.getContext());
llvm::DIType *FieldType = createFieldType(
VName, Field->getType(), Loc, Field->getAccess(),
- layout.getFieldOffset(fieldno), VUnit, RecordTy, CXXDecl);
+ layout.getFieldOffset(fieldno), Align, VUnit, RecordTy, CXXDecl);
elements.push_back(FieldType);
} else if (C.capturesThis()) {
// TODO: Need to handle 'this' in some way by probably renaming the
}
llvm::DINode::DIFlags Flags = getAccessFlag(Var->getAccess(), RD);
+ auto Align = getDeclAlignIfRequired(Var, CGM.getContext());
llvm::DIDerivedType *GV = DBuilder.createStaticMemberType(
- RecordTy, VName, VUnit, LineNumber, VTy, Flags, C);
+ RecordTy, VName, VUnit, LineNumber, VTy, Flags, C, Align);
StaticDataMemberCache[Var->getCanonicalDecl()].reset(GV);
return GV;
}
if (field->isBitField()) {
FieldType = createBitFieldType(field, RecordTy, RD);
} else {
+ auto Align = getDeclAlignIfRequired(field, CGM.getContext());
FieldType =
createFieldType(name, type, field->getLocation(), field->getAccess(),
- OffsetInBits, tunit, RecordTy, RD);
+ OffsetInBits, Align, tunit, RecordTy, RD);
}
elements.push_back(FieldType);
QualType PointeeTy = ThisPtrTy->getPointeeType();
unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
uint64_t Size = CGM.getTarget().getPointerWidth(AS);
- uint32_t Align = CGM.getContext().getTypeAlign(ThisPtrTy);
+ auto Align = getTypeAlignIfRequired(ThisPtrTy, CGM.getContext());
llvm::DIType *PointeeType = getOrCreateType(PointeeTy, Unit);
llvm::DIType *ThisPtrType =
DBuilder.createPointerType(PointeeType, Size, Align);
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint32_t Align = CGM.getContext().getTypeAlign(Ty);
+ auto Align = getTypeAlignIfRequired(Ty, CGM.getContext());
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
if (ID->getImplementation())
FieldSize = Field->isBitField()
? Field->getBitWidthValue(CGM.getContext())
: CGM.getContext().getTypeSize(FType);
- FieldAlign = CGM.getContext().getTypeAlign(FType);
+ FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext());
}
uint64_t FieldOffset;
llvm::DINodeArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint32_t Align = CGM.getContext().getTypeAlign(Ty);
+ auto Align = getTypeAlignIfRequired(Ty, CGM.getContext());
return DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);
}
// FIXME: make getTypeAlign() aware of VLAs and incomplete array types
if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) {
Size = 0;
- Align =
- CGM.getContext().getTypeAlign(CGM.getContext().getBaseElementType(VAT));
+ Align = getTypeAlignIfRequired(CGM.getContext().getBaseElementType(VAT),
+ CGM.getContext());
} else if (Ty->isIncompleteArrayType()) {
Size = 0;
if (Ty->getElementType()->isIncompleteType())
Align = 0;
else
- Align = CGM.getContext().getTypeAlign(Ty->getElementType());
+ Align = getTypeAlignIfRequired(Ty->getElementType(), CGM.getContext());
} else if (Ty->isIncompleteType()) {
Size = 0;
Align = 0;
} else {
// Size and align of the whole array, not the element type.
Size = CGM.getContext().getTypeSize(Ty);
- Align = CGM.getContext().getTypeAlign(Ty);
+ Align = getTypeAlignIfRequired(Ty, CGM.getContext());
}
// Add the dimensions of the array. FIXME: This loses CV qualifiers from
uint32_t Align = 0;
if (!ED->getTypeForDecl()->isIncompleteType()) {
Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
- Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
+ Align = getDeclAlignIfRequired(ED, CGM.getContext());
}
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
uint32_t Align = 0;
if (!ED->getTypeForDecl()->isIncompleteType()) {
Size = CGM.getContext().getTypeSize(ED->getTypeForDecl());
- Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
+ Align = getDeclAlignIfRequired(ED, CGM.getContext());
}
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
return getOrCreateRecordFwdDecl(Ty, RDContext);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
- uint32_t Align = CGM.getContext().getTypeAlign(Ty);
+ auto Align = getDeclAlignIfRequired(D, CGM.getContext());
SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
StringRef Name, uint64_t *Offset) {
llvm::DIType *FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
uint64_t FieldSize = CGM.getContext().getTypeSize(FType);
- uint32_t FieldAlign = CGM.getContext().getTypeAlign(FType);
+ auto FieldAlign = getTypeAlignIfRequired(FType, CGM.getContext());
llvm::DIType *Ty =
DBuilder.createMemberType(Unit, Name, Unit, 0, FieldSize, FieldAlign,
*Offset, llvm::DINode::FlagZero, FieldTy);
unsigned Line = getLineNumber(Loc);
collectVarDeclProps(VD, Unit, Line, T, Name, LinkageName, DContext);
+ auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
auto *GV = DBuilder.createTempGlobalVariableFwdDecl(
DContext, Name, LinkageName, Unit, Line, getOrCreateType(T, Unit),
- !VD->isExternallyVisible(), nullptr, nullptr);
+ !VD->isExternallyVisible(), nullptr, nullptr, Align);
FwdDeclReplaceMap.emplace_back(
std::piecewise_construct,
std::make_tuple(cast<VarDecl>(VD->getCanonicalDecl())),
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
if (VD->isImplicit())
Flags |= llvm::DINode::FlagArtificial;
+
+ auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
+
// If this is the first argument and it is implicit then
// give it an object pointer flag.
// FIXME: There has to be a better way to do this, but for static
? DBuilder.createParameterVariable(Scope, VD->getName(),
*ArgNo, Unit, Line, Ty)
: DBuilder.createAutoVariable(Scope, VD->getName(), Unit,
- Line, Ty);
+ Line, Ty, Align);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
continue;
// Use VarDecl's Tag, Scope and Line number.
+ auto FieldAlign = getDeclAlignIfRequired(Field, CGM.getContext());
auto *D = DBuilder.createAutoVariable(
Scope, FieldName, Unit, Line, FieldTy, CGM.getLangOpts().Optimize,
- Flags | llvm::DINode::FlagArtificial);
+ Flags | llvm::DINode::FlagArtificial, FieldAlign);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
}
// Create the descriptor for the variable.
- auto *D =
- ArgNo
- ? DBuilder.createParameterVariable(Scope, Name, *ArgNo, Unit, Line,
- Ty, CGM.getLangOpts().Optimize,
- Flags)
- : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty,
- CGM.getLangOpts().Optimize, Flags);
+ auto *D = ArgNo
+ ? DBuilder.createParameterVariable(
+ Scope, Name, *ArgNo, Unit, Line, Ty,
+ CGM.getLangOpts().Optimize, Flags)
+ : DBuilder.createAutoVariable(Scope, Name, Unit, Line, Ty,
+ CGM.getLangOpts().Optimize, Flags,
+ Align);
// Insert an llvm.dbg.declare into the current block.
DBuilder.insertDeclare(Storage, D, DBuilder.createExpression(Expr),
}
// Create the descriptor for the variable.
+ auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
auto *D = DBuilder.createAutoVariable(
cast<llvm::DILocalScope>(LexicalBlockStack.back()), VD->getName(), Unit,
- Line, Ty);
+ Line, Ty, false, llvm::DINode::FlagZero, Align);
// Insert an llvm.dbg.declare into the current block.
auto DL = llvm::DebugLoc::get(Line, Column, LexicalBlockStack.back());
llvm::DIType *fieldType;
if (capture->isByRef()) {
TypeInfo PtrInfo = C.getTypeInfo(C.VoidPtrTy);
+ auto Align = PtrInfo.AlignIsRequired ? PtrInfo.Align : 0;
// FIXME: this creates a second copy of this type!
uint64_t xoffset;
fieldType = EmitTypeForVarWithBlocksAttr(variable, &xoffset);
fieldType = DBuilder.createPointerType(fieldType, PtrInfo.Width);
- fieldType = DBuilder.createMemberType(
- tunit, name, tunit, line, PtrInfo.Width, PtrInfo.Align, offsetInBits,
- llvm::DINode::FlagZero, fieldType);
+ fieldType = DBuilder.createMemberType(tunit, name, tunit, line,
+ PtrInfo.Width, Align, offsetInBits,
+ llvm::DINode::FlagZero, fieldType);
} else {
+ auto Align = getDeclAlignIfRequired(variable, CGM.getContext());
fieldType = createFieldType(name, variable->getType(), loc, AS_public,
- offsetInBits, tunit, tunit);
+ offsetInBits, Align, tunit, tunit);
}
fields.push_back(fieldType);
}
llvm::DIType *type =
DBuilder.createStructType(tunit, typeName.str(), tunit, line,
- CGM.getContext().toBits(block.BlockSize),
- CGM.getContext().toBits(block.BlockAlign),
+ CGM.getContext().toBits(block.BlockSize), 0,
llvm::DINode::FlagZero, nullptr, fieldsArray);
type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);
"unnamed non-anonymous struct or union?");
GV = CollectAnonRecordDecls(RD, Unit, LineNo, LinkageName, Var, DContext);
} else {
+ auto Align = getDeclAlignIfRequired(D, CGM.getContext());
GV = DBuilder.createGlobalVariable(
DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
Var->hasLocalLinkage(), /*Expr=*/nullptr,
- getOrCreateStaticDataMemberDeclarationOrNull(D));
+ getOrCreateStaticDataMemberDeclarationOrNull(D), Align);
Var->addDebugInfo(GV);
}
DeclCache[D->getCanonicalDecl()].reset(GV);
assert(DebugKind >= codegenoptions::LimitedDebugInfo);
if (VD->hasAttr<NoDebugAttr>())
return;
+ auto Align = getDeclAlignIfRequired(VD, CGM.getContext());
// Create the descriptor for the variable.
llvm::DIFile *Unit = getOrCreateFile(VD->getLocation());
StringRef Name = VD->getName();
DBuilder.createConstantValueExpression(Init.getInt().getExtValue());
GV.reset(DBuilder.createGlobalVariable(
DContext, Name, StringRef(), Unit, getLineNumber(VD->getLocation()), Ty,
- true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VarD)));
+ true, InitExpr, getOrCreateStaticDataMemberDeclarationOrNull(VarD),
+ Align));
}
llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {