brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.6 KiB · 9d44d86 Raw
194 lines · cpp
1//===- MultilibBuilder.cpp - MultilibBuilder Implementation -===//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 "clang/Driver/MultilibBuilder.h"10#include "clang/Driver/CommonArgs.h"11#include "llvm/ADT/StringMap.h"12#include "llvm/Support/Path.h"13#include "llvm/Support/Regex.h"14#include "llvm/Support/raw_ostream.h"15 16using namespace clang;17using namespace driver;18 19/// normalize Segment to "/foo/bar" or "".20static void normalizePathSegment(std::string &Segment) {21  StringRef seg = Segment;22 23  // Prune trailing "/" or "./"24  while (true) {25    StringRef last = llvm::sys::path::filename(seg);26    if (last != ".")27      break;28    seg = llvm::sys::path::parent_path(seg);29  }30 31  if (seg.empty() || seg == "/") {32    Segment.clear();33    return;34  }35 36  // Add leading '/'37  if (seg.front() != '/') {38    Segment = "/" + seg.str();39  } else {40    Segment = std::string(seg);41  }42}43 44MultilibBuilder::MultilibBuilder(StringRef GCC, StringRef OS, StringRef Include)45    : GCCSuffix(GCC), OSSuffix(OS), IncludeSuffix(Include) {46  normalizePathSegment(GCCSuffix);47  normalizePathSegment(OSSuffix);48  normalizePathSegment(IncludeSuffix);49}50 51MultilibBuilder::MultilibBuilder(StringRef Suffix)52    : MultilibBuilder(Suffix, Suffix, Suffix) {}53 54MultilibBuilder &MultilibBuilder::gccSuffix(StringRef S) {55  GCCSuffix = std::string(S);56  normalizePathSegment(GCCSuffix);57  return *this;58}59 60MultilibBuilder &MultilibBuilder::osSuffix(StringRef S) {61  OSSuffix = std::string(S);62  normalizePathSegment(OSSuffix);63  return *this;64}65 66MultilibBuilder &MultilibBuilder::includeSuffix(StringRef S) {67  IncludeSuffix = std::string(S);68  normalizePathSegment(IncludeSuffix);69  return *this;70}71 72bool MultilibBuilder::isValid() const {73  llvm::StringMap<int> FlagSet;74  for (unsigned I = 0, N = Flags.size(); I != N; ++I) {75    StringRef Flag(Flags[I]);76    auto [SI, Inserted] = FlagSet.try_emplace(Flag.substr(1), I);77 78    assert(StringRef(Flag).front() == '-' || StringRef(Flag).front() == '!');79 80    if (!Inserted && Flags[I] != Flags[SI->getValue()])81      return false;82  }83  return true;84}85 86MultilibBuilder &MultilibBuilder::flag(StringRef Flag, bool Disallow) {87  tools::addMultilibFlag(!Disallow, Flag, Flags);88  return *this;89}90 91Multilib MultilibBuilder::makeMultilib() const {92  return Multilib(GCCSuffix, OSSuffix, IncludeSuffix, Flags);93}94 95MultilibSetBuilder &MultilibSetBuilder::Maybe(const MultilibBuilder &M) {96  MultilibBuilder Opposite;97  // Negate positive flags98  for (StringRef Flag : M.flags()) {99    if (Flag.front() == '-')100      Opposite.flag(Flag, /*Disallow=*/true);101  }102  return Either(M, Opposite);103}104 105MultilibSetBuilder &MultilibSetBuilder::Either(const MultilibBuilder &M1,106                                               const MultilibBuilder &M2) {107  return Either({M1, M2});108}109 110MultilibSetBuilder &MultilibSetBuilder::Either(const MultilibBuilder &M1,111                                               const MultilibBuilder &M2,112                                               const MultilibBuilder &M3) {113  return Either({M1, M2, M3});114}115 116MultilibSetBuilder &MultilibSetBuilder::Either(const MultilibBuilder &M1,117                                               const MultilibBuilder &M2,118                                               const MultilibBuilder &M3,119                                               const MultilibBuilder &M4) {120  return Either({M1, M2, M3, M4});121}122 123MultilibSetBuilder &MultilibSetBuilder::Either(const MultilibBuilder &M1,124                                               const MultilibBuilder &M2,125                                               const MultilibBuilder &M3,126                                               const MultilibBuilder &M4,127                                               const MultilibBuilder &M5) {128  return Either({M1, M2, M3, M4, M5});129}130 131static MultilibBuilder compose(const MultilibBuilder &Base,132                               const MultilibBuilder &New) {133  SmallString<128> GCCSuffix;134  llvm::sys::path::append(GCCSuffix, "/", Base.gccSuffix(), New.gccSuffix());135  SmallString<128> OSSuffix;136  llvm::sys::path::append(OSSuffix, "/", Base.osSuffix(), New.osSuffix());137  SmallString<128> IncludeSuffix;138  llvm::sys::path::append(IncludeSuffix, "/", Base.includeSuffix(),139                          New.includeSuffix());140 141  MultilibBuilder Composed(GCCSuffix, OSSuffix, IncludeSuffix);142 143  MultilibBuilder::flags_list &Flags = Composed.flags();144 145  llvm::append_range(Flags, Base.flags());146  llvm::append_range(Flags, New.flags());147 148  return Composed;149}150 151MultilibSetBuilder &152MultilibSetBuilder::Either(ArrayRef<MultilibBuilder> MultilibSegments) {153  multilib_list Composed;154 155  if (Multilibs.empty())156    llvm::append_range(Multilibs, MultilibSegments);157  else {158    for (const auto &New : MultilibSegments) {159      for (const auto &Base : Multilibs) {160        MultilibBuilder MO = compose(Base, New);161        if (MO.isValid())162          Composed.push_back(MO);163      }164    }165 166    Multilibs = Composed;167  }168 169  return *this;170}171 172MultilibSetBuilder &MultilibSetBuilder::FilterOut(const char *Regex) {173  llvm::Regex R(Regex);174#ifndef NDEBUG175  std::string Error;176  if (!R.isValid(Error)) {177    llvm::errs() << Error;178    llvm_unreachable("Invalid regex!");179  }180#endif181  llvm::erase_if(Multilibs, [&R](const MultilibBuilder &M) {182    return R.match(M.gccSuffix());183  });184  return *this;185}186 187MultilibSet MultilibSetBuilder::makeMultilibSet() const {188  MultilibSet Result;189  for (const auto &M : Multilibs) {190    Result.push_back(M.makeMultilib());191  }192  return Result;193}194