Commit 5ca24d09 authored by Fangrui Song's avatar Fangrui Song
Browse files

[Driver][X86] Add -malign-branch* and -mbranches-within-32B-boundaries

These driver options perform some checking and delegate to MC options -x86-align-branch* and -x86-branches-within-32B-boundaries.

Reviewed By: skan

Differential Revision: https://reviews.llvm.org/D72463
parent a60e8927
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -250,6 +250,9 @@ def err_drv_unsupported_embed_bitcode
def err_drv_bitcode_unsupported_on_toolchain : Error<
  "-fembed-bitcode is not supported on versions of iOS prior to 6.0">;

def err_drv_invalid_malign_branch_EQ : Error<
  "invalid argument '%0' to -malign-branch=; each element must be one of: %1">;

def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>;
def warn_drv_optimization_value : Warning<"optimization level '%0' is not supported; using '%1%2' instead">,
  InGroup<InvalidCommandLineArgument>;
+4 −0
Original line number Diff line number Diff line
@@ -2146,6 +2146,10 @@ def mno_iamcu : Flag<["-"], "mno-iamcu">, Group<m_Group>, Flags<[DriverOption, C
def malign_functions_EQ : Joined<["-"], "malign-functions=">, Group<clang_ignored_m_Group>;
def malign_loops_EQ : Joined<["-"], "malign-loops=">, Group<clang_ignored_m_Group>;
def malign_jumps_EQ : Joined<["-"], "malign-jumps=">, Group<clang_ignored_m_Group>;
def malign_branch_EQ : CommaJoined<["-"], "malign-branch=">, Group<m_Group>;
def malign_branch_boundary_EQ : Joined<["-"], "malign-branch-boundary=">, Group<m_Group>;
def malign_branch_prefix_size_EQ : Joined<["-"], "malign-branch-prefix-size=">, Group<m_Group>;
def mbranches_within_32B_boundaries : Flag<["-"], "mbranches-within-32B-boundaries">, Flags<[DriverOption]>, Group<m_Group>;
def mfancy_math_387 : Flag<["-"], "mfancy-math-387">, Group<clang_ignored_m_Group>;
def mlong_calls : Flag<["-"], "mlong-calls">, Group<m_Group>,
  HelpText<"Generate branches with extended addressability, usually via indirect jumps.">;
+55 −2
Original line number Diff line number Diff line
@@ -2015,8 +2015,59 @@ void Clang::AddSystemZTargetArgs(const ArgList &Args,
    CmdArgs.push_back("-mpacked-stack");
}

static void addX86AlignBranchArgs(const Driver &D, const ArgList &Args,
                                  ArgStringList &CmdArgs) {
  if (Args.hasArg(options::OPT_mbranches_within_32B_boundaries)) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-x86-branches-within-32B-boundaries");
  }
  if (const Arg *A = Args.getLastArg(options::OPT_malign_branch_boundary_EQ)) {
    StringRef Value = A->getValue();
    unsigned Boundary;
    if (Value.getAsInteger(10, Boundary) || Boundary < 16 ||
        !llvm::isPowerOf2_64(Boundary)) {
      D.Diag(diag::err_drv_invalid_argument_to_option)
          << Value << A->getOption().getName();
    } else {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back(
          Args.MakeArgString("-x86-align-branch-boundary=" + Twine(Boundary)));
    }
  }
  if (const Arg *A = Args.getLastArg(options::OPT_malign_branch_EQ)) {
    std::string AlignBranch;
    for (StringRef T : A->getValues()) {
      if (T != "fused" && T != "jcc" && T != "jmp" && T != "call" &&
          T != "ret" && T != "indirect")
        D.Diag(diag::err_drv_invalid_malign_branch_EQ)
            << T << "fused, jcc, jmp, call, ret, indirect";
      if (!AlignBranch.empty())
        AlignBranch += '+';
      AlignBranch += T;
    }
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back(Args.MakeArgString("-x86-align-branch=" + AlignBranch));
  }
  if (const Arg *A =
          Args.getLastArg(options::OPT_malign_branch_prefix_size_EQ)) {
    StringRef Value = A->getValue();
    unsigned PrefixSize;
    if (Value.getAsInteger(10, PrefixSize) || PrefixSize > 5) {
      D.Diag(diag::err_drv_invalid_argument_to_option)
          << Value << A->getOption().getName();
    } else {
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back(Args.MakeArgString("-x86-align-branch-prefix-size=" +
                                           Twine(PrefixSize)));
    }
  }
}

void Clang::AddX86TargetArgs(const ArgList &Args,
                             ArgStringList &CmdArgs) const {
  const Driver &D = getToolChain().getDriver();
  addX86AlignBranchArgs(D, Args, CmdArgs);

  if (!Args.hasFlag(options::OPT_mred_zone, options::OPT_mno_red_zone, true) ||
      Args.hasArg(options::OPT_mkernel) ||
      Args.hasArg(options::OPT_fapple_kext))
@@ -2046,10 +2097,10 @@ void Clang::AddX86TargetArgs(const ArgList &Args,
      CmdArgs.push_back("-mllvm");
      CmdArgs.push_back(Args.MakeArgString("-x86-asm-syntax=" + Value));
    } else {
      getToolChain().getDriver().Diag(diag::err_drv_unsupported_option_argument)
      D.Diag(diag::err_drv_unsupported_option_argument)
          << A->getOption().getName() << Value;
    }
  } else if (getToolChain().getDriver().IsCLMode()) {
  } else if (D.IsCLMode()) {
    CmdArgs.push_back("-mllvm");
    CmdArgs.push_back("-x86-asm-syntax=intel");
  }
@@ -6480,6 +6531,8 @@ void ClangAs::AddMIPSTargetArgs(const ArgList &Args,

void ClangAs::AddX86TargetArgs(const ArgList &Args,
                               ArgStringList &CmdArgs) const {
  addX86AlignBranchArgs(getToolChain().getDriver(), Args, CmdArgs);

  if (Arg *A = Args.getLastArg(options::OPT_masm_EQ)) {
    StringRef Value = A->getValue();
    if (Value == "intel" || Value == "att") {
+39 −0
Original line number Diff line number Diff line
/// Test that -malign-branch* and -mbranches-within-32B-boundaries are parsed and converted to -mllvm options.

/// Test -malign-branch-boundary=
// RUN: %clang -target x86_64 -malign-branch-boundary=16 %s -c -### 2>&1 | FileCheck %s --check-prefix=BOUNDARY
// BOUNDARY: "-mllvm" "-x86-align-branch-boundary=16"

// RUN: %clang -target x86_64 -malign-branch-boundary=8 %s -c -### 2>&1 | FileCheck %s --check-prefix=BOUNDARY-ERR
// RUN: %clang -target x86_64 -malign-branch-boundary=15 %s -c -### 2>&1 | FileCheck %s --check-prefix=BOUNDARY-ERR
// BOUNDARY-ERR: invalid argument {{.*}} to -malign-branch-boundary=

/// Test -malign-branch=
// RUN: %clang -target x86_64 -malign-branch=fused,jcc,jmp %s -c -### %s 2>&1 | FileCheck %s --check-prefix=TYPE0
// TYPE0: "-mllvm" "-x86-align-branch=fused+jcc+jmp"
// RUN: %clang -target x86_64 -malign-branch=fused,jcc,jmp,ret,call,indirect %s -c -### %s 2>&1 | FileCheck %s --check-prefix=TYPE1
// TYPE1: "-mllvm" "-x86-align-branch=fused+jcc+jmp+ret+call+indirect"

// RUN: %clang -target x86_64 -malign-branch=fused,foo,bar %s -c -### %s 2>&1 | FileCheck %s --check-prefix=TYPE-ERR
// TYPE-ERR: invalid argument 'foo' to -malign-branch=; each element must be one of: fused, jcc, jmp, call, ret, indirect
// TYPE-ERR: invalid argument 'bar' to -malign-branch=; each element must be one of: fused, jcc, jmp, call, ret, indirect

/// Test -malign-branch-prefix-size=
// RUN: %clang -target x86_64 -malign-branch-prefix-size=0 %s -c -### 2>&1 | FileCheck %s --check-prefix=PREFIX-0
// PREFIX-0: "-mllvm" "-x86-align-branch-prefix-size=0"
// RUN: %clang -target x86_64 -malign-branch-prefix-size=5 %s -c -### 2>&1 | FileCheck %s --check-prefix=PREFIX-5
// PREFIX-5: "-mllvm" "-x86-align-branch-prefix-size=5"

// RUN: %clang -target x86_64 -malign-branch-prefix-size=6 %s -c -### 2>&1 | FileCheck %s --check-prefix=PREFIX-6
// PREFIX-6: invalid argument

/// Test -mbranches-within-32B-boundaries
// RUN: %clang -target x86_64 -mbranches-within-32B-boundaries %s -c -### 2>&1 | FileCheck %s --check-prefix=32B
// 32B: "-mllvm" "-x86-branches-within-32B-boundaries"

/// Unsupported on other targets.
// RUN: %clang -target aarch64 -malign-branch=jmp %s -c -### 2>&1 | FileCheck --check-prefix=UNUSED %s
// RUN: %clang -target aarch64 -malign-branch-boundary=7 %s -c -### 2>&1 | FileCheck --check-prefix=UNUSED %s
// RUN: %clang -target aarch64 -malign-branch-prefix-size=15 %s -c -### 2>&1 | FileCheck --check-prefix=UNUSED %s
// RUN: %clang -target aarch64 -mbranches-within-32B-boundaries %s -c -### 2>&1 | FileCheck --check-prefix=UNUSED %s
// UNUSED: warning: argument unused
+13 −0
Original line number Diff line number Diff line
/// Test that -malign-branch* and -mbranches-within-32B-boundaries are handled for assembly files.

// RUN: %clang -target x86_64 -malign-branch-boundary=16 %s -c -### 2>&1 | FileCheck %s --check-prefix=BOUNDARY
// BOUNDARY: "-mllvm" "-x86-align-branch-boundary=16"

// RUN: %clang -target x86_64 -malign-branch=fused,jcc,jmp %s -c -### %s 2>&1 | FileCheck %s --check-prefix=TYPE
// TYPE: "-mllvm" "-x86-align-branch=fused+jcc+jmp"

// RUN: %clang -target x86_64 -malign-branch-prefix-size=5 %s -c -### 2>&1 | FileCheck %s --check-prefix=PREFIX
// PREFIX: "-mllvm" "-x86-align-branch-prefix-size=5"

// RUN: %clang -target x86_64 -mbranches-within-32B-boundaries %s -c -### 2>&1 | FileCheck %s --check-prefix=32B
// 32B: "-mllvm" "-x86-branches-within-32B-boundaries"