Skip to content

Commit

Permalink
[Clang][AArch64][ARM] Unaligned Access Warning Added
Browse files Browse the repository at this point in the history
Added warning for potential cases of
unaligned access when option
-mno-unaligned-access has been specified

Differential Revision: https://reviews.llvm.org/D116221
  • Loading branch information
mub-at-arm committed Jan 20, 2022
1 parent 60147c6 commit 35737df
Show file tree
Hide file tree
Showing 9 changed files with 846 additions and 10 deletions.
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/DiagnosticASTKinds.td
Expand Up @@ -590,4 +590,9 @@ def warn_padded_struct_size : Warning<
InGroup<Padded>, DefaultIgnore;
def warn_unnecessary_packed : Warning<
"packed attribute is unnecessary for %0">, InGroup<Packed>, DefaultIgnore;

// -Wunaligned-access
def warn_unaligned_access : Warning<
"field %1 within %0 is less aligned than %2 and is usually due to %0 being "
"packed, which can lead to unaligned accesses">, InGroup<UnalignedAccess>, DefaultIgnore;
}
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Expand Up @@ -543,6 +543,7 @@ def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
def OrderedCompareFunctionPointers : DiagGroup<"ordered-compare-function-pointers">;
def Packed : DiagGroup<"packed">;
def Padded : DiagGroup<"padded">;
def UnalignedAccess : DiagGroup<"unaligned-access">;

def PessimizingMove : DiagGroup<"pessimizing-move">;
def ReturnStdMove : DiagGroup<"return-std-move">;
Expand Down
17 changes: 17 additions & 0 deletions clang/lib/AST/RecordLayoutBuilder.cpp
Expand Up @@ -2021,6 +2021,7 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
CharUnits UnpackedFieldAlign =
!DefaultsToAIXPowerAlignment ? FieldAlign : PreferredAlign;
CharUnits UnpackedFieldOffset = FieldOffset;
CharUnits OriginalFieldAlign = UnpackedFieldAlign;

if (FieldPacked) {
FieldAlign = CharUnits::One();
Expand Down Expand Up @@ -2105,6 +2106,22 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
// Remember max struct/class ABI-specified alignment.
UnadjustedAlignment = std::max(UnadjustedAlignment, FieldAlign);
UpdateAlignment(FieldAlign, UnpackedFieldAlign, PreferredAlign);

// For checking the alignment of inner fields against
// the alignment of its parent record.
if (const RecordDecl *RD = D->getParent()) {
// Check if packed attribute or pragma pack is present.
if (RD->hasAttr<PackedAttr>() || !MaxFieldAlignment.isZero())
if (FieldAlign < OriginalFieldAlign)
if (D->getType()->isRecordType()) {
// If the offset is a multiple of the alignment of
// the type, raise the warning.
// TODO: Takes no account the alignment of the outer struct
if (FieldOffset % OriginalFieldAlign != 0)
Diag(D->getLocation(), diag::warn_unaligned_access)
<< Context.getTypeDeclType(RD) << D->getName() << D->getType();
}
}
}

void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
Expand Down
11 changes: 9 additions & 2 deletions clang/lib/Driver/ToolChains/Arch/AArch64.cpp
Expand Up @@ -221,6 +221,7 @@ getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
void aarch64::getAArch64TargetFeatures(const Driver &D,
const llvm::Triple &Triple,
const ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
std::vector<StringRef> &Features,
bool ForAS) {
Arg *A;
Expand Down Expand Up @@ -464,10 +465,16 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,

if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
options::OPT_munaligned_access)) {
if (A->getOption().matches(options::OPT_mno_unaligned_access))
if (A->getOption().matches(options::OPT_mno_unaligned_access)) {
Features.push_back("+strict-align");
} else if (Triple.isOSOpenBSD())
if (!ForAS)
CmdArgs.push_back("-Wunaligned-access");
}
} else if (Triple.isOSOpenBSD()) {
Features.push_back("+strict-align");
if (!ForAS)
CmdArgs.push_back("-Wunaligned-access");
}

if (Args.hasArg(options::OPT_ffixed_x1))
Features.push_back("+reserve-x1");
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/Arch/AArch64.h
Expand Up @@ -22,6 +22,7 @@ namespace aarch64 {

void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs,
std::vector<llvm::StringRef> &Features,
bool ForAS);

Expand Down
28 changes: 21 additions & 7 deletions clang/lib/Driver/ToolChains/Arch/ARM.cpp
Expand Up @@ -769,10 +769,12 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
}

// Kernel code has more strict alignment requirements.
if (KernelOrKext)
if (KernelOrKext) {
Features.push_back("+strict-align");
else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
options::OPT_munaligned_access)) {
if (!ForAS)
CmdArgs.push_back("-Wunaligned-access");
} else if (Arg *A = Args.getLastArg(options::OPT_mno_unaligned_access,
options::OPT_munaligned_access)) {
if (A->getOption().matches(options::OPT_munaligned_access)) {
// No v6M core supports unaligned memory access (v6M ARM ARM A3.2).
if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
Expand All @@ -781,8 +783,11 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
// access either.
else if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline)
D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base";
} else
} else {
Features.push_back("+strict-align");
if (!ForAS)
CmdArgs.push_back("-Wunaligned-access");
}
} else {
// Assume pre-ARMv6 doesn't support unaligned accesses.
//
Expand All @@ -801,14 +806,23 @@ void arm::getARMTargetFeatures(const Driver &D, const llvm::Triple &Triple,
int VersionNum = getARMSubArchVersionNumber(Triple);
if (Triple.isOSDarwin() || Triple.isOSNetBSD()) {
if (VersionNum < 6 ||
Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m)
Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) {
Features.push_back("+strict-align");
if (!ForAS)
CmdArgs.push_back("-Wunaligned-access");
}
} else if (Triple.isOSLinux() || Triple.isOSNaCl() ||
Triple.isOSWindows()) {
if (VersionNum < 7)
if (VersionNum < 7) {
Features.push_back("+strict-align");
} else
if (!ForAS)
CmdArgs.push_back("-Wunaligned-access");
}
} else {
Features.push_back("+strict-align");
if (!ForAS)
CmdArgs.push_back("-Wunaligned-access");
}
}

// llvm does not support reserving registers in general. There is support
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Driver/ToolChains/Clang.cpp
Expand Up @@ -346,7 +346,8 @@ static void getTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_32:
case llvm::Triple::aarch64_be:
aarch64::getAArch64TargetFeatures(D, Triple, Args, Features, ForAS);
aarch64::getAArch64TargetFeatures(D, Triple, Args, CmdArgs, Features,
ForAS);
break;
case llvm::Triple::x86:
case llvm::Triple::x86_64:
Expand Down

0 comments on commit 35737df

Please sign in to comment.