diff --git a/clang/include/clang/Driver/CommonArgs.h b/clang/include/clang/Driver/CommonArgs.h index 49c7149380fba..42590fbd89e9a 100644 --- a/clang/include/clang/Driver/CommonArgs.h +++ b/clang/include/clang/Driver/CommonArgs.h @@ -85,8 +85,8 @@ const char *RelocationModelName(llvm::Reloc::Model Model); std::tuple ParsePICArgs(const ToolChain &ToolChain, const llvm::opt::ArgList &Args); -unsigned ParseFunctionAlignment(const ToolChain &TC, - const llvm::opt::ArgList &Args); +llvm::MaybeAlign ParseFunctionAlignment(const ToolChain &TC, + const llvm::opt::ArgList &Args); void addDebugInfoKind(llvm::opt::ArgStringList &CmdArgs, llvm::codegenoptions::DebugInfoKind DebugInfoKind); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 236cc3d9e8907..905f0c70750a1 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2760,9 +2760,11 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, if (alignment) F->setAlignment(llvm::Align(alignment)); - if (!D->hasAttr()) - if (LangOpts.FunctionAlignment) - F->setAlignment(llvm::Align(1ull << LangOpts.FunctionAlignment)); + if (!D->hasAttr()) { + llvm::MaybeAlign Align = llvm::decodeMaybeAlign(LangOpts.FunctionAlignment); + if (Align) + F->setAlignment(*Align); + } // Some C++ ABIs require 2-byte alignment for member functions, in order to // reserve a bit for differentiating between virtual and non-virtual member diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 8880c9375143f..43bfabe0f5d57 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -40,6 +40,7 @@ #include "llvm/Frontend/Debug/Options.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Option/ArgList.h" +#include "llvm/Support/Alignment.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Compression.h" @@ -5516,11 +5517,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CheckCodeGenerationOptions(D, Args); - unsigned FunctionAlignment = ParseFunctionAlignment(TC, Args); - assert(FunctionAlignment <= 31 && "function alignment will be truncated!"); + llvm::MaybeAlign FunctionAlignment = ParseFunctionAlignment(TC, Args); if (FunctionAlignment) { CmdArgs.push_back("-function-alignment"); - CmdArgs.push_back(Args.MakeArgString(std::to_string(FunctionAlignment))); + CmdArgs.push_back( + Args.MakeArgString(std::to_string(llvm::encode(FunctionAlignment)))); } // We support -falign-loops=N where N is a power of 2. GCC supports more diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 651a39c03bb54..672b154d1855f 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -2120,29 +2120,33 @@ tools::ParsePICArgs(const ToolChain &ToolChain, const ArgList &Args) { // [0, 65536]. If the value is not a power-of-two, it will be rounded up to // the nearest power-of-two. // -// If we return `0`, the frontend will default to the backend's preferred -// alignment. +// If we return `MaybeAlign()`, the frontend will default to the backend's +// preferred alignment. // // NOTE: icc only allows values between [0, 4096]. icc uses `-falign-functions` // to mean `-falign-functions=16`. GCC defaults to the backend's preferred // alignment. For unaligned functions, we default to the backend's preferred // alignment. -unsigned tools::ParseFunctionAlignment(const ToolChain &TC, - const ArgList &Args) { +llvm::MaybeAlign tools::ParseFunctionAlignment(const ToolChain &TC, + const ArgList &Args) { const Arg *A = Args.getLastArg(options::OPT_falign_functions, options::OPT_falign_functions_EQ, options::OPT_fno_align_functions); - if (!A || A->getOption().matches(options::OPT_fno_align_functions)) - return 0; + if (!A) + return llvm::MaybeAlign(); + + if (A->getOption().matches(options::OPT_fno_align_functions)) + return llvm::Align(1); if (A->getOption().matches(options::OPT_falign_functions)) - return 0; + return llvm::MaybeAlign(); unsigned Value = 0; if (StringRef(A->getValue()).getAsInteger(10, Value) || Value > 65536) TC.getDriver().Diag(diag::err_drv_invalid_int_value) << A->getAsString(Args) << A->getValue(); - return Value ? llvm::Log2_32_Ceil(std::min(Value, 65536u)) : Value; + return Value ? llvm::Align(1 << llvm::Log2_32_Ceil(std::min(Value, 65536u))) + : llvm::MaybeAlign(); } void tools::addDebugInfoKind( diff --git a/clang/test/CodeGen/function-alignment.c b/clang/test/CodeGen/function-alignment.c index 8564ceb02354b..c3e06e1c571d5 100644 --- a/clang/test/CodeGen/function-alignment.c +++ b/clang/test/CodeGen/function-alignment.c @@ -1,6 +1,7 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NONE -// RUN: %clang_cc1 -emit-llvm -function-alignment 4 %s -o - | FileCheck %s -check-prefix CHECK-16 -// RUN: %clang_cc1 -emit-llvm -function-alignment 5 %s -o - | FileCheck %s -check-prefix CHECK-32 +// RUN: %clang_cc1 -emit-llvm -function-alignment 0 %s -o - | FileCheck %s -check-prefix CHECK-NONE +// RUN: %clang_cc1 -emit-llvm -function-alignment 1 %s -o - | FileCheck %s -check-prefix CHECK-1 +// RUN: %clang_cc1 -emit-llvm -function-alignment 5 %s -o - | FileCheck %s -check-prefix CHECK-16 +// RUN: %clang_cc1 -emit-llvm -function-alignment 6 %s -o - | FileCheck %s -check-prefix CHECK-32 void f(void) {} void __attribute__((__aligned__(64))) g(void) {} @@ -8,6 +9,9 @@ void __attribute__((__aligned__(64))) g(void) {} // CHECK-NONE-NOT: define {{(dso_local )?}}void @f() #0 align // CHECK-NONE: define {{(dso_local )?}}void @g() #0 align 64 +// CHECK-1: define {{(dso_local )?}}void @f() #0 align 1 +// CHECK-1: define {{(dso_local )?}}void @g() #0 align 64 + // CHECK-16: define {{(dso_local )?}}void @f() #0 align 16 // CHECK-16: define {{(dso_local )?}}void @g() #0 align 64 diff --git a/clang/test/Driver/function-alignment.c b/clang/test/Driver/function-alignment.c index ed4cc80f7ed4f..0321b0587f2bb 100644 --- a/clang/test/Driver/function-alignment.c +++ b/clang/test/Driver/function-alignment.c @@ -1,17 +1,17 @@ // RUN: %clang -### %s 2>&1 | FileCheck %s -check-prefix CHECK-0 -// RUN: %clang -### -falign-functions %s 2>&1 | FileCheck %s -check-prefix CHECK-1 +// RUN: %clang -### -falign-functions %s 2>&1 | FileCheck %s -check-prefix CHECK-0 +// RUN: %clang -### -fno-align-functions %s 2>&1 | FileCheck %s -check-prefix CHECK-1 // RUN: %clang -### -falign-functions=1 %s 2>&1 | FileCheck %s -check-prefix CHECK-1 // RUN: %clang -### -falign-functions=2 %s 2>&1 | FileCheck %s -check-prefix CHECK-2 // RUN: %clang -### -falign-functions=3 %s 2>&1 | FileCheck %s -check-prefix CHECK-3 -// RUN: %clang -### -falign-functions=4 %s 2>&1 | FileCheck %s -check-prefix CHECK-4 +// RUN: %clang -### -falign-functions=4 %s 2>&1 | FileCheck %s -check-prefix CHECK-3 // RUN: not %clang -### -falign-functions=65537 %s 2>&1 | FileCheck %s -check-prefix CHECK-ERR-65537 // RUN: not %clang -### -falign-functions=a %s 2>&1 | FileCheck %s -check-prefix CHECK-ERR-A // CHECK-0-NOT: "-function-alignment" -// CHECK-1-NOT: "-function-alignment" -// CHECK-2: "-function-alignment" "1" -// CHECK-3: "-function-alignment" "2" -// CHECK-4: "-function-alignment" "2" +// CHECK-1: "-function-alignment" "1" +// CHECK-2: "-function-alignment" "2" +// CHECK-3: "-function-alignment" "3" // CHECK-ERR-65537: error: invalid integral value '65537' in '-falign-functions=65537' // CHECK-ERR-A: error: invalid integral value 'a' in '-falign-functions=a'