brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.0 KiB · da084bd Raw
316 lines · cpp
1//===--- LoongArch.cpp - LoongArch Helpers for Tools ------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "LoongArch.h"10#include "../Clang.h"11#include "clang/Basic/DiagnosticDriver.h"12#include "clang/Driver/CommonArgs.h"13#include "clang/Driver/Driver.h"14#include "clang/Options/Options.h"15#include "llvm/TargetParser/Host.h"16#include "llvm/TargetParser/LoongArchTargetParser.h"17 18using namespace clang::driver;19using namespace clang::driver::tools;20using namespace clang;21using namespace llvm::opt;22 23StringRef loongarch::getLoongArchABI(const Driver &D, const ArgList &Args,24                                     const llvm::Triple &Triple) {25  assert((Triple.getArch() == llvm::Triple::loongarch32 ||26          Triple.getArch() == llvm::Triple::loongarch64) &&27         "Unexpected triple");28  bool IsLA32 = Triple.getArch() == llvm::Triple::loongarch32;29 30  // Record -mabi value for later use.31  const Arg *MABIArg = Args.getLastArg(options::OPT_mabi_EQ);32  StringRef MABIValue;33  if (MABIArg) {34    MABIValue = MABIArg->getValue();35  }36 37  // Parse -mfpu value for later use.38  const Arg *MFPUArg = Args.getLastArg(options::OPT_mfpu_EQ);39  int FPU = -1;40  if (MFPUArg) {41    StringRef V = MFPUArg->getValue();42    if (V == "64")43      FPU = 64;44    else if (V == "32")45      FPU = 32;46    else if (V == "0" || V == "none")47      FPU = 0;48    else49      D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << V;50  }51 52  // Check -m*-float firstly since they have highest priority.53  if (const Arg *A = Args.getLastArg(options::OPT_mdouble_float,54                                     options::OPT_msingle_float,55                                     options::OPT_msoft_float)) {56    StringRef ImpliedABI;57    int ImpliedFPU = -1;58    if (A->getOption().matches(options::OPT_mdouble_float)) {59      ImpliedABI = IsLA32 ? "ilp32d" : "lp64d";60      ImpliedFPU = 64;61    }62    if (A->getOption().matches(options::OPT_msingle_float)) {63      ImpliedABI = IsLA32 ? "ilp32f" : "lp64f";64      ImpliedFPU = 32;65    }66    if (A->getOption().matches(options::OPT_msoft_float)) {67      ImpliedABI = IsLA32 ? "ilp32s" : "lp64s";68      ImpliedFPU = 0;69    }70 71    // Check `-mabi=` and `-mfpu=` settings and report if they conflict with72    // the higher-priority settings implied by -m*-float.73    //74    // ImpliedABI and ImpliedFPU are guaranteed to have valid values because75    // one of the match arms must match if execution can arrive here at all.76    if (!MABIValue.empty() && ImpliedABI != MABIValue)77      D.Diag(diag::warn_drv_loongarch_conflicting_implied_val)78          << MABIArg->getAsString(Args) << A->getAsString(Args) << ImpliedABI;79 80    if (FPU != -1 && ImpliedFPU != FPU)81      D.Diag(diag::warn_drv_loongarch_conflicting_implied_val)82          << MFPUArg->getAsString(Args) << A->getAsString(Args) << ImpliedFPU;83 84    return ImpliedABI;85  }86 87  // If `-mabi=` is specified, use it.88  if (!MABIValue.empty())89    return MABIValue;90 91  // Select abi based on -mfpu=xx.92  switch (FPU) {93  case 64:94    return IsLA32 ? "ilp32d" : "lp64d";95  case 32:96    return IsLA32 ? "ilp32f" : "lp64f";97  case 0:98    return IsLA32 ? "ilp32s" : "lp64s";99  }100 101  // Choose a default based on the triple.102  // Honor the explicit ABI modifier suffix in triple's environment part if103  // present, falling back to {ILP32,LP64}D otherwise.104  switch (Triple.getEnvironment()) {105  case llvm::Triple::GNUSF:106  case llvm::Triple::MuslSF:107    return IsLA32 ? "ilp32s" : "lp64s";108  case llvm::Triple::GNUF32:109  case llvm::Triple::MuslF32:110    return IsLA32 ? "ilp32f" : "lp64f";111  case llvm::Triple::GNUF64:112    // This was originally permitted (and indeed the canonical way) to113    // represent the {ILP32,LP64}D ABIs, but in Feb 2023 Loongson decided to114    // drop the explicit suffix in favor of unmarked `-gnu` for the115    // "general-purpose" ABIs, among other non-technical reasons.116    //117    // The spec change did not mention whether existing usages of "gnuf64"118    // shall remain valid or not, so we are going to continue recognizing it119    // for some time, until it is clear that everyone else has migrated away120    // from it.121    [[fallthrough]];122  case llvm::Triple::GNU:123  default:124    return IsLA32 ? "ilp32d" : "lp64d";125  }126}127 128void loongarch::getLoongArchTargetFeatures(const Driver &D,129                                           const llvm::Triple &Triple,130                                           const ArgList &Args,131                                           std::vector<StringRef> &Features) {132  // Enable the `lsx` feature on 64-bit LoongArch by default.133  if (Triple.isLoongArch64() && (!Args.hasArgNoClaim(options::OPT_march_EQ)))134    Features.push_back("+lsx");135 136  // -mrelax is default, unless -mno-relax is specified.137  // FIXME: Only for loongarch64, loongarch32 has not been fully verified.138  if (Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax,139                   Triple.isLoongArch64() ? true : false)) {140    Features.push_back("+relax");141    // -gsplit-dwarf -mrelax requires DW_AT_high_pc/DW_AT_ranges/... indexing142    // into .debug_addr, which is currently not implemented.143    Arg *A;144    if (getDebugFissionKind(D, Args, A) != DwarfFissionKind::None)145      D.Diag(clang::diag::err_drv_loongarch_unsupported_with_linker_relaxation)146          << A->getAsString(Args);147  } else if (Args.getLastArg(options::OPT_mno_relax)) {148    Features.push_back("-relax");149  }150 151  std::string ArchName;152  const Arg *MArch = Args.getLastArg(options::OPT_march_EQ);153  if (MArch)154    ArchName = MArch->getValue();155  ArchName = postProcessTargetCPUString(ArchName, Triple);156  llvm::LoongArch::getArchFeatures(ArchName, Features);157  if (MArch && StringRef(MArch->getValue()) == "native")158    for (auto &F : llvm::sys::getHostCPUFeatures())159      Features.push_back(160          Args.MakeArgString((F.second ? "+" : "-") + F.first()));161 162  // Select floating-point features determined by -mdouble-float,163  // -msingle-float, -msoft-float and -mfpu.164  // Note: -m*-float wins any other options.165  if (const Arg *A = Args.getLastArg(options::OPT_mdouble_float,166                                     options::OPT_msingle_float,167                                     options::OPT_msoft_float)) {168    if (A->getOption().matches(options::OPT_mdouble_float)) {169      Features.push_back("+f");170      Features.push_back("+d");171    } else if (A->getOption().matches(options::OPT_msingle_float)) {172      Features.push_back("+f");173      Features.push_back("-d");174      Features.push_back("-lsx");175    } else /*Soft-float*/ {176      Features.push_back("-f");177      Features.push_back("-d");178      Features.push_back("-lsx");179    }180  } else if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) {181    StringRef FPU = A->getValue();182    if (FPU == "64") {183      Features.push_back("+f");184      Features.push_back("+d");185    } else if (FPU == "32") {186      Features.push_back("+f");187      Features.push_back("-d");188      Features.push_back("-lsx");189    } else if (FPU == "0" || FPU == "none") {190      Features.push_back("-f");191      Features.push_back("-d");192      Features.push_back("-lsx");193    } else {194      D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << FPU;195    }196  }197 198  // Accept but warn about these TargetSpecific options.199  if (Arg *A = Args.getLastArgNoClaim(options::OPT_mabi_EQ))200    A->ignoreTargetSpecific();201  if (Arg *A = Args.getLastArgNoClaim(options::OPT_mfpu_EQ))202    A->ignoreTargetSpecific();203  if (Arg *A = Args.getLastArgNoClaim(options::OPT_msimd_EQ))204    A->ignoreTargetSpecific();205 206  // Select lsx/lasx feature determined by -msimd=.207  // Option -msimd= precedes -m[no-]lsx and -m[no-]lasx.208  if (const Arg *A = Args.getLastArg(options::OPT_msimd_EQ)) {209    StringRef MSIMD = A->getValue();210    if (MSIMD == "lsx") {211      // Option -msimd=lsx depends on 64-bit FPU.212      // -m*-float and -mfpu=none/0/32 conflict with -msimd=lsx.213      if (llvm::is_contained(Features, "-d"))214        D.Diag(diag::err_drv_loongarch_wrong_fpu_width) << /*LSX*/ 0;215      else216        Features.push_back("+lsx");217    } else if (MSIMD == "lasx") {218      // Option -msimd=lasx depends on 64-bit FPU and LSX.219      // -m*-float, -mfpu=none/0/32 and -mno-lsx conflict with -msimd=lasx.220      if (llvm::is_contained(Features, "-d"))221        D.Diag(diag::err_drv_loongarch_wrong_fpu_width) << /*LASX*/ 1;222      else if (llvm::is_contained(Features, "-lsx"))223        D.Diag(diag::err_drv_loongarch_invalid_simd_option_combination);224 225      // The command options do not contain -mno-lasx.226      if (!Args.getLastArg(options::OPT_mno_lasx)) {227        Features.push_back("+lsx");228        Features.push_back("+lasx");229      }230    } else if (MSIMD == "none") {231      if (llvm::is_contained(Features, "+lsx"))232        Features.push_back("-lsx");233      if (llvm::is_contained(Features, "+lasx"))234        Features.push_back("-lasx");235    } else {236      D.Diag(diag::err_drv_loongarch_invalid_msimd_EQ) << MSIMD;237    }238  }239 240  // Select lsx feature determined by -m[no-]lsx.241  if (const Arg *A = Args.getLastArg(options::OPT_mlsx, options::OPT_mno_lsx)) {242    // LSX depends on 64-bit FPU.243    // -m*-float and -mfpu=none/0/32 conflict with -mlsx.244    if (A->getOption().matches(options::OPT_mlsx)) {245      if (llvm::find(Features, "-d") != Features.end())246        D.Diag(diag::err_drv_loongarch_wrong_fpu_width) << /*LSX*/ 0;247      else /*-mlsx*/248        Features.push_back("+lsx");249    } else /*-mno-lsx*/ {250      Features.push_back("-lsx");251      Features.push_back("-lasx");252    }253  }254 255  // Select lasx feature determined by -m[no-]lasx.256  if (const Arg *A =257          Args.getLastArg(options::OPT_mlasx, options::OPT_mno_lasx)) {258    // LASX depends on 64-bit FPU and LSX.259    // -mno-lsx conflicts with -mlasx.260    if (A->getOption().matches(options::OPT_mlasx)) {261      if (llvm::find(Features, "-d") != Features.end())262        D.Diag(diag::err_drv_loongarch_wrong_fpu_width) << /*LASX*/ 1;263      else { /*-mlasx*/264        Features.push_back("+lsx");265        Features.push_back("+lasx");266      }267    } else /*-mno-lasx*/268      Features.push_back("-lasx");269  }270 271  AddTargetFeature(Args, Features, options::OPT_mno_strict_align,272                   options::OPT_mstrict_align, "ual");273  AddTargetFeature(Args, Features, options::OPT_mno_strict_align,274                   options::OPT_mstrict_align, "ual");275  AddTargetFeature(Args, Features, options::OPT_mfrecipe,276                   options::OPT_mno_frecipe, "frecipe");277  AddTargetFeature(Args, Features, options::OPT_mlam_bh,278                   options::OPT_mno_lam_bh, "lam-bh");279  AddTargetFeature(Args, Features, options::OPT_mlamcas,280                   options::OPT_mno_lamcas, "lamcas");281  AddTargetFeature(Args, Features, options::OPT_mld_seq_sa,282                   options::OPT_mno_ld_seq_sa, "ld-seq-sa");283  AddTargetFeature(Args, Features, options::OPT_mdiv32,284                   options::OPT_mno_div32, "div32");285  AddTargetFeature(Args, Features, options::OPT_mscq, options::OPT_mno_scq,286                   "scq");287}288 289std::string loongarch::postProcessTargetCPUString(const std::string &CPU,290                                                  const llvm::Triple &Triple) {291  std::string CPUString = CPU;292  if (CPUString == "native") {293    CPUString = llvm::sys::getHostCPUName();294    if (CPUString == "generic")295      CPUString = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64());296  }297  if (CPUString.empty())298    CPUString = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64());299  return CPUString;300}301 302std::string loongarch::getLoongArchTargetCPU(const llvm::opt::ArgList &Args,303                                             const llvm::Triple &Triple) {304  std::string CPU;305  std::string Arch;306  // If we have -march, use that.307  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {308    Arch = A->getValue();309    if (Arch == "la64v1.0" || Arch == "la64v1.1")310      CPU = llvm::LoongArch::getDefaultArch(Triple.isLoongArch64());311    else312      CPU = Arch;313  }314  return postProcessTargetCPUString(CPU, Triple);315}316