[PATCH] D55121: Make several Python scripts portable across Python2 and Python 3

2018-11-30 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

In general LGTM, as someone who's done a 2-3 conversion of similar scale before.

The only suggestion I'd make is to consider changing the `__future__` imports 
to `from __future__ import absolute_import, division, print_function`
I found this gave the best consistency between 2 & 3. Probably you don't need 
it at this point, but once the conversion is done there's less to go wrong in 
future.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55121/new/

https://reviews.llvm.org/D55121



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D55121: Make several Python scripts portable across Python2 and Python 3

2018-12-03 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings accepted this revision.
michaelplatings added a comment.
This revision is now accepted and ready to land.

LGTM


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55121/new/

https://reviews.llvm.org/D55121



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57337: [Targets] Adjust ARM data layout

2019-01-28 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 183893.
michaelplatings added a comment.

Diff with -U9


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57337/new/

https://reviews.llvm.org/D57337

Files:
  clang/lib/Basic/Targets/ARM.cpp
  clang/test/CodeGen/armv7k-abi.c
  clang/test/CodeGen/target-data.c

Index: clang/test/CodeGen/target-data.c
===
--- clang/test/CodeGen/target-data.c
+++ clang/test/CodeGen/target-data.c
@@ -96,7 +96,7 @@
 
 // RUN: %clang_cc1 -triple arm-nacl -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=ARM-NACL
-// ARM-NACL: target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128"
+// ARM-NACL: target datalayout = "e-m:e-p:32:32-F8-i64:64-v128:64:128-a:0:32-n32-S128"
 
 // RUN: %clang_cc1 -triple mipsel-nacl -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=MIPS-NACL
@@ -165,19 +165,19 @@
 
 // RUN: %clang_cc1 -triple thumb-unknown-gnueabi -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=THUMB
-// THUMB: target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+// THUMB: target datalayout = "e-m:e-p:32:32-F8-i64:64-v128:64:128-a:0:32-n32-S64"
 
 // RUN: %clang_cc1 -triple arm-unknown-gnueabi -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=ARM
-// ARM: target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
+// ARM: target datalayout = "e-m:e-p:32:32-F8-i64:64-v128:64:128-a:0:32-n32-S64"
 
 // RUN: %clang_cc1 -triple thumb-unknown -o - -emit-llvm -target-abi apcs-gnu \
 // RUN: %s | FileCheck %s -check-prefix=THUMB-GNU
-// THUMB-GNU: target datalayout = "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+// THUMB-GNU: target datalayout = "e-m:e-p:32:32-F8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
 
 // RUN: %clang_cc1 -triple arm-unknown -o - -emit-llvm -target-abi apcs-gnu \
 // RUN: %s | FileCheck %s -check-prefix=ARM-GNU
-// ARM-GNU: target datalayout = "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+// ARM-GNU: target datalayout = "e-m:e-p:32:32-F8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
 
 // RUN: %clang_cc1 -triple arc-unknown-unknown -o - -emit-llvm %s | \
 // RUN: FileCheck %s -check-prefix=ARC
Index: clang/test/CodeGen/armv7k-abi.c
===
--- clang/test/CodeGen/armv7k-abi.c
+++ clang/test/CodeGen/armv7k-abi.c
@@ -4,7 +4,7 @@
 
 // Make sure 64 and 128 bit types are naturally aligned by the v7k ABI:
 
-// CHECK: target datalayout = "e-m:o-p:32:32-i64:64-a:0:32-n32-S128"
+// CHECK: target datalayout = "e-m:o-p:32:32-F8-i64:64-a:0:32-n32-S128"
 
 typedef struct {
   float arr[4];
Index: clang/lib/Basic/Targets/ARM.cpp
===
--- clang/lib/Basic/Targets/ARM.cpp
+++ clang/lib/Basic/Targets/ARM.cpp
@@ -40,13 +40,14 @@
   // so set preferred for small types to 32.
   if (T.isOSBinFormatMachO()) {
 resetDataLayout(BigEndian
-? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
-: "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
+? "E-m:o-p:32:32-F8-i64:64-v128:64:128-a:0:32-n32-S64"
+: "e-m:o-p:32:32-F8-i64:64-v128:64:128-a:0:32-n32-S64");
   } else if (T.isOSWindows()) {
 assert(!BigEndian && "Windows on ARM does not support big endian");
 resetDataLayout("e"
 "-m:w"
 "-p:32:32"
+"-F8"
 "-i64:64"
 "-v128:64:128"
 "-a:0:32"
@@ -54,11 +55,11 @@
 "-S64");
   } else if (T.isOSNaCl()) {
 assert(!BigEndian && "NaCl on ARM does not support big endian");
-resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128");
+resetDataLayout("e-m:e-p:32:32-F8-i64:64-v128:64:128-a:0:32-n32-S128");
   } else {
 resetDataLayout(BigEndian
-? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
-: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
+? "E-m:e-p:32:32-F8-i64:64-v128:64:128-a:0:32-n32-S64"
+: "e-m:e-p:32:32-F8-i64:64-v128:64:128-a:0:32-n32-S64");
   }
 
   // FIXME: Enumerated types are variable width in straight AAPCS.
@@ -87,17 +88,17 @@
 
   if (T.isOSBinFormatMachO() && IsAAPCS16) {
 assert(!BigEndian && "AAPCS16 does not support big-endian");
-resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128");
+resetDataLayout("e-m:o-p:32:32-F8-i64:64-a:0:32-n32-S128");
   } else if (T.isOSBinFormatMachO())
 resetDataLayout(
 BigEndian
-? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
-: "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
+? "E-m:o-p:32:32-F8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
+ 

[PATCH] D57335: [IR] Don't assume all functions are 4 byte aligned

2019-02-25 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings marked 4 inline comments as done.
michaelplatings added inline comments.



Comment at: llvm/lib/IR/ConstantFold.cpp:1087
+  if (GVAlign == 0U && isa(GV))
+GVAlign = 4U;
 

efriedma wrote:
> Using "4" as a default is dangerous; on x86, the alignment of the pointer 
> corresponds to the alignment of the function, but might be less than 4 if it 
> isn't explicitly specified.
I've put in a comment to say as much. Sadly I'm not in a position to change 
this behaviour without causing a code size regression.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57335/new/

https://reviews.llvm.org/D57335



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57335: [IR] Don't assume all functions are 4 byte aligned

2019-02-26 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 188325.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57335/new/

https://reviews.llvm.org/D57335

Files:
  clang/lib/Basic/Targets/ARM.cpp
  clang/test/CodeGen/armv7k-abi.c
  clang/test/CodeGen/target-data.c
  llvm/docs/LangRef.rst
  llvm/include/llvm/IR/DataLayout.h
  llvm/lib/IR/ConstantFold.cpp
  llvm/lib/IR/DataLayout.cpp
  llvm/lib/IR/Value.cpp
  llvm/lib/Target/ARM/ARMTargetMachine.cpp
  llvm/unittests/IR/CMakeLists.txt
  llvm/unittests/IR/ConstantsTest.cpp
  llvm/unittests/IR/DataLayoutTest.cpp
  llvm/unittests/IR/FunctionTest.cpp

Index: llvm/unittests/IR/FunctionTest.cpp
===
--- llvm/unittests/IR/FunctionTest.cpp
+++ llvm/unittests/IR/FunctionTest.cpp
@@ -129,4 +129,29 @@
   EXPECT_TRUE(F->hasSection());
 }
 
+TEST(FunctionTest, GetPointerAlignment) {
+  LLVMContext Context;
+  Type *VoidType(Type::getVoidTy(Context));
+  FunctionType *FuncType(FunctionType::get(VoidType, false));
+  Function *Func = Function::Create(
+  FuncType, GlobalValue::ExternalLinkage);
+  EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout("")));
+  EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8")));
+  EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fn8")));
+  EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16")));
+  EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fn16")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32")));
+
+  Func->setAlignment(4U);
+
+  EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout("")));
+  EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn8")));
+  EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn16")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32")));
+}
+
 } // end namespace
Index: llvm/unittests/IR/DataLayoutTest.cpp
===
--- /dev/null
+++ llvm/unittests/IR/DataLayoutTest.cpp
@@ -0,0 +1,47 @@
+//===- ConstantRangeTest.cpp - ConstantRange tests ===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "llvm/IR/DataLayout.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(DataLayoutTest, FunctionPtrAlign) {
+  EXPECT_EQ(0U, DataLayout("").getFunctionPtrAlign());
+  EXPECT_EQ(1U, DataLayout("Fi8").getFunctionPtrAlign());
+  EXPECT_EQ(2U, DataLayout("Fi16").getFunctionPtrAlign());
+  EXPECT_EQ(4U, DataLayout("Fi32").getFunctionPtrAlign());
+  EXPECT_EQ(8U, DataLayout("Fi64").getFunctionPtrAlign());
+  EXPECT_EQ(1U, DataLayout("Fn8").getFunctionPtrAlign());
+  EXPECT_EQ(2U, DataLayout("Fn16").getFunctionPtrAlign());
+  EXPECT_EQ(4U, DataLayout("Fn32").getFunctionPtrAlign());
+  EXPECT_EQ(8U, DataLayout("Fn64").getFunctionPtrAlign());
+  EXPECT_EQ(DataLayout::FunctionPtrAlignType::Independent, \
+  DataLayout("").getFunctionPtrAlignType());
+  EXPECT_EQ(DataLayout::FunctionPtrAlignType::Independent, \
+  DataLayout("Fi8").getFunctionPtrAlignType());
+  EXPECT_EQ(DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign, \
+  DataLayout("Fn8").getFunctionPtrAlignType());
+  EXPECT_EQ(DataLayout("Fi8"), DataLayout("Fi8"));
+  EXPECT_NE(DataLayout("Fi8"), DataLayout("Fi16"));
+  EXPECT_NE(DataLayout("Fi8"), DataLayout("Fn8"));
+
+  DataLayout a(""), b("Fi8"), c("Fn8");
+  EXPECT_NE(a, b);
+  EXPECT_NE(a, c);
+  EXPECT_NE(b, c);
+
+  a = b;
+  EXPECT_EQ(a, b);
+  a = c;
+  EXPECT_EQ(a, c);
+}
+
+}  // anonymous namespace
Index: llvm/unittests/IR/ConstantsTest.cpp
===
--- llvm/unittests/IR/ConstantsTest.cpp
+++ llvm/unittests/IR/ConstantsTest.cpp
@@ -475,5 +475,105 @@
   ASSERT_EQ(cast(C)->getOpcode(), Instruction::BitCast);
 }
 
+bool foldFuncPtrAndConstToNull(LLVMContext , Module *TheModule,
+   uint64_t AndValue, unsigned FunctionAlign = 0) {
+  Type *VoidType(Type::getVoidTy(Context));
+  FunctionType *FuncType(FunctionType::get(VoidType, false));
+  Function *Func(Function::Create(
+  FuncType, GlobalValue::ExternalLinkage, "", TheModule));
+
+  if (FunctionAlign) Func->setAlignment(FunctionAlign);
+
+  IntegerType *ConstantIntType(Type::getInt32Ty(Context));
+  ConstantInt *TheConstant(ConstantInt::get(ConstantIntType, AndValue));
+
+  Constant *TheConstantExpr(
+  ConstantExpr::getPtrToInt(Func, ConstantIntType));
+
+  return 

[PATCH] D57335: [IR] Don't assume all functions are 4 byte aligned

2019-02-26 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 188324.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57335/new/

https://reviews.llvm.org/D57335

Files:
  clang/lib/Basic/Targets/ARM.cpp
  clang/test/CodeGen/armv7k-abi.c
  clang/test/CodeGen/target-data.c
  llvm/docs/LangRef.rst
  llvm/include/llvm/IR/DataLayout.h
  llvm/lib/IR/ConstantFold.cpp
  llvm/lib/IR/DataLayout.cpp
  llvm/lib/IR/Value.cpp
  llvm/lib/Target/ARM/ARMTargetMachine.cpp
  llvm/unittests/IR/CMakeLists.txt
  llvm/unittests/IR/ConstantsTest.cpp
  llvm/unittests/IR/DataLayoutTest.cpp
  llvm/unittests/IR/FunctionTest.cpp

Index: llvm/unittests/IR/FunctionTest.cpp
===
--- llvm/unittests/IR/FunctionTest.cpp
+++ llvm/unittests/IR/FunctionTest.cpp
@@ -129,4 +129,29 @@
   EXPECT_TRUE(F->hasSection());
 }
 
+TEST(FunctionTest, GetPointerAlignment) {
+  LLVMContext Context;
+  Type *VoidType(Type::getVoidTy(Context));
+  FunctionType *FuncType(FunctionType::get(VoidType, false));
+  Function *Func = Function::Create(
+  FuncType, GlobalValue::ExternalLinkage);
+  EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout("")));
+  EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8")));
+  EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fn8")));
+  EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16")));
+  EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fn16")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32")));
+
+  Func->setAlignment(4U);
+
+  EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout("")));
+  EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn8")));
+  EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn16")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32")));
+}
+
 } // end namespace
Index: llvm/unittests/IR/DataLayoutTest.cpp
===
--- /dev/null
+++ llvm/unittests/IR/DataLayoutTest.cpp
@@ -0,0 +1,47 @@
+//===- ConstantRangeTest.cpp - ConstantRange tests ===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "llvm/IR/DataLayout.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(DataLayoutTest, FunctionPtrAlign) {
+  EXPECT_EQ(0U, DataLayout("").getFunctionPtrAlign());
+  EXPECT_EQ(1U, DataLayout("Fi8").getFunctionPtrAlign());
+  EXPECT_EQ(2U, DataLayout("Fi16").getFunctionPtrAlign());
+  EXPECT_EQ(4U, DataLayout("Fi32").getFunctionPtrAlign());
+  EXPECT_EQ(8U, DataLayout("Fi64").getFunctionPtrAlign());
+  EXPECT_EQ(1U, DataLayout("Fn8").getFunctionPtrAlign());
+  EXPECT_EQ(2U, DataLayout("Fn16").getFunctionPtrAlign());
+  EXPECT_EQ(4U, DataLayout("Fn32").getFunctionPtrAlign());
+  EXPECT_EQ(8U, DataLayout("Fn64").getFunctionPtrAlign());
+  EXPECT_EQ(DataLayout::FunctionPtrAlignType::Independent, \
+  DataLayout("").getFunctionPtrAlignType());
+  EXPECT_EQ(DataLayout::FunctionPtrAlignType::Independent, \
+  DataLayout("Fi8").getFunctionPtrAlignType());
+  EXPECT_EQ(DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign, \
+  DataLayout("Fn8").getFunctionPtrAlignType());
+  EXPECT_EQ(DataLayout("Fi8"), DataLayout("Fi8"));
+  EXPECT_NE(DataLayout("Fi8"), DataLayout("Fi16"));
+  EXPECT_NE(DataLayout("Fi8"), DataLayout("Fn8"));
+
+  DataLayout a(""), b("Fi8"), c("Fn8");
+  EXPECT_NE(a, b);
+  EXPECT_NE(a, c);
+  EXPECT_NE(b, c);
+
+  a = b;
+  EXPECT_EQ(a, b);
+  a = c;
+  EXPECT_EQ(a, c);
+}
+
+}  // anonymous namespace
Index: llvm/unittests/IR/ConstantsTest.cpp
===
--- llvm/unittests/IR/ConstantsTest.cpp
+++ llvm/unittests/IR/ConstantsTest.cpp
@@ -475,5 +475,105 @@
   ASSERT_EQ(cast(C)->getOpcode(), Instruction::BitCast);
 }
 
+bool foldFuncPtrAndConstToNull(LLVMContext , Module *TheModule,
+   uint64_t AndValue, unsigned FunctionAlign = 0) {
+  Type *VoidType(Type::getVoidTy(Context));
+  FunctionType *FuncType(FunctionType::get(VoidType, false));
+  Function *Func(Function::Create(
+  FuncType, GlobalValue::ExternalLinkage, "", TheModule));
+
+  if (FunctionAlign) Func->setAlignment(FunctionAlign);
+
+  IntegerType *ConstantIntType(Type::getInt32Ty(Context));
+  ConstantInt *TheConstant(ConstantInt::get(ConstantIntType, AndValue));
+
+  Constant *TheConstantExpr(
+  ConstantExpr::getPtrToInt(Func, ConstantIntType));
+
+  return 

[PATCH] D57896: Variable names rule

2019-02-19 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 187339.
michaelplatings added a comment.

Changed recommendation for acronyms from lower case to upper case, as suggested 
by several responses to the RFC.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57896/new/

https://reviews.llvm.org/D57896

Files:
  .clang-tidy
  clang/.clang-tidy
  llvm/.clang-tidy
  llvm/docs/CodingStandards.rst

Index: llvm/docs/CodingStandards.rst
===
--- llvm/docs/CodingStandards.rst
+++ llvm/docs/CodingStandards.rst
@@ -311,13 +311,13 @@
 
.. code-block:: c++
 
- Object.emitName(nullptr);
+ object.emitName(nullptr);
 
An in-line C-style comment makes the intent obvious:
 
.. code-block:: c++
 
- Object.emitName(/*Prefix=*/nullptr);
+ object.emitName(/*prefix=*/nullptr);
 
 Commenting out large blocks of code is discouraged, but if you really have to do
 this (for documentation purposes or as a suggestion for debug printing), use
@@ -355,8 +355,8 @@
 
 .. code-block:: c++
 
-  /// Sets the xyzzy property to \p Baz.
-  void setXyzzy(bool Baz);
+  /// Sets the xyzzy property to \p baz.
+  void setXyzzy(bool baz);
 
 A documentation comment that uses all Doxygen features in a preferred way:
 
@@ -364,18 +364,18 @@
 
   /// Does foo and bar.
   ///
-  /// Does not do foo the usual way if \p Baz is true.
+  /// Does not do foo the usual way if \p baz is true.
   ///
   /// Typical usage:
   /// \code
-  ///   fooBar(false, "quux", Res);
+  ///   fooBar(false, "quux", res);
   /// \endcode
   ///
-  /// \param Quux kind of foo to do.
+  /// \param quux kind of foo to do.
   /// \param [out] Result filled with bar sequence on foo success.
   ///
   /// \returns true on success.
-  bool fooBar(bool Baz, StringRef Quux, std::vector );
+  bool fooBar(bool baz, StringRef quux, std::vector );
 
 Don't duplicate the documentation comment in the header file and in the
 implementation file.  Put the documentation comments for public APIs into the
@@ -603,7 +603,7 @@
 
   foo({a, b, c}, {1, 2, 3});
 
-  llvm::Constant *Mask[] = {
+  llvm::Constant *mask[] = {
   llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 0),
   llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 1),
   llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 2)};
@@ -633,7 +633,7 @@
 
 .. code-block:: c++
 
-  if (V = getValue()) {
+  if (v = getValue()) {
 ...
   }
 
@@ -644,7 +644,7 @@
 
 .. code-block:: c++
 
-  if ((V = getValue())) {
+  if ((v = getValue())) {
 ...
   }
 
@@ -736,7 +736,7 @@
   class Foo;
 
   // Breaks mangling in MSVC.
-  struct Foo { int Data; };
+  struct Foo { int data; };
 
 * As a rule of thumb, ``struct`` should be kept to structures where *all*
   members are declared public.
@@ -746,17 +746,17 @@
   // Foo feels like a class... this is strange.
   struct Foo {
   private:
-int Data;
+int data;
   public:
-Foo() : Data(0) { }
-int getData() const { return Data; }
-void setData(int D) { Data = D; }
+Foo() : data(0) { }
+int getData() const { return data; }
+void setData(int d) { data = d; }
   };
 
   // Bar isn't POD, but it does look like a struct.
   struct Bar {
-int Data;
-Bar() : Data(0) { }
+int data;
+Bar() : data(0) { }
   };
 
 Do not use Braced Initializer Lists to Call a Constructor
@@ -780,7 +780,7 @@
 Foo(std::string filename);
 
 // Construct a Foo by looking up the Nth element of some global data ...
-Foo(int N);
+Foo(int n);
 
 // ...
   };
@@ -789,7 +789,7 @@
   std::fill(foo.begin(), foo.end(), Foo("name"));
 
   // The pair is just being constructed like an aggregate, use braces.
-  bar_map.insert({my_key, my_value});
+  bar_map.insert({myKey, myValue});
 
 If you use a braced initializer list when initializing a variable, use an equals before the open curly brace:
 
@@ -821,15 +821,15 @@
 .. code-block:: c++
 
   // Typically there's no reason to copy.
-  for (const auto  : Container) { observe(Val); }
-  for (auto  : Container) { Val.change(); }
+  for (const auto  : container) { observe(val); }
+  for (auto  : container) { val.change(); }
 
   // Remove the reference if you really want a new copy.
-  for (auto Val : Container) { Val.change(); saveSomewhere(Val); }
+  for (auto val : container) { val.change(); saveSomewhere(val); }
 
   // Copy pointers, but make it clear that they're pointers.
-  for (const auto *Ptr : Container) { observe(*Ptr); }
-  for (auto *Ptr : Container) { Ptr->change(); }
+  for (const auto *ptr : container) { observe(*ptr); }
+  for (auto *ptr : container) { ptr->change(); }
 
 Beware of non-determinism due to ordering of pointers
 ^
@@ -968,9 +968,9 @@
 
 .. code-block:: c++
 
-  Value *doSomething(Instruction *I) {
-if (!I->isTerminator() &&
-I->hasOneUse() && 

[PATCH] D57896: Variable names rule

2019-02-19 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

In D57896#1402194 , @lattner wrote:

> > Changed recommendation for acronyms from lower case to upper case, as 
> > suggested by several responses to the RFC.
>
> I haven't been following the discussion closely - why is this the preferred 
> direction?  I don't think that things like "Basicblock *bb" or "MachineInstr 
> *mi" will be confusing, and going towards a consistently leading lower case 
> letter seems simple and preferable.


Maybe I misunderstood you 
(http://lists.llvm.org/pipermail/llvm-dev/2019-February/130223.html):

>> Maybe there should be an exception that variable names that start with an 
>> acronym still should start with an upper case letter?
>  That would also be fine with me - it could push such a debate down the road, 
> and is definitely important for a transition period anyway.

Also Chandler 
(http://lists.llvm.org/pipermail/llvm-dev/2019-February/130313.html):

> FWIW, I suspect separating the transition of our acronyms from the transition 
> of identifiers with non-acronym words may be an effective way to chip away at 
> the transition cost... Definitely an area that people who really care about 
> this should look at carefully.

And Sanjoy (kind of) 
(http://lists.llvm.org/pipermail/llvm-dev/2019-February/130304.html):

> maybe a gradual transition plan could be to allow these upper case acronyms 
> for specific classes?

I agree that lower case acronyms would ultimately be more consistent, but given 
where we are it seems more achievable to only change the rule for non-acronyms.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57896/new/

https://reviews.llvm.org/D57896



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57896: Variable names rule

2019-02-19 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 187344.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57896/new/

https://reviews.llvm.org/D57896

Files:
  .clang-tidy
  clang/.clang-tidy
  llvm/.clang-tidy
  llvm/docs/CodingStandards.rst

Index: llvm/docs/CodingStandards.rst
===
--- llvm/docs/CodingStandards.rst
+++ llvm/docs/CodingStandards.rst
@@ -311,13 +311,13 @@
 
.. code-block:: c++
 
- Object.emitName(nullptr);
+ object.emitName(nullptr);
 
An in-line C-style comment makes the intent obvious:
 
.. code-block:: c++
 
- Object.emitName(/*Prefix=*/nullptr);
+ object.emitName(/*prefix=*/nullptr);
 
 Commenting out large blocks of code is discouraged, but if you really have to do
 this (for documentation purposes or as a suggestion for debug printing), use
@@ -355,8 +355,8 @@
 
 .. code-block:: c++
 
-  /// Sets the xyzzy property to \p Baz.
-  void setXyzzy(bool Baz);
+  /// Sets the xyzzy property to \p baz.
+  void setXyzzy(bool baz);
 
 A documentation comment that uses all Doxygen features in a preferred way:
 
@@ -364,18 +364,18 @@
 
   /// Does foo and bar.
   ///
-  /// Does not do foo the usual way if \p Baz is true.
+  /// Does not do foo the usual way if \p baz is true.
   ///
   /// Typical usage:
   /// \code
-  ///   fooBar(false, "quux", Res);
+  ///   fooBar(false, "quux", res);
   /// \endcode
   ///
-  /// \param Quux kind of foo to do.
+  /// \param quux kind of foo to do.
   /// \param [out] Result filled with bar sequence on foo success.
   ///
   /// \returns true on success.
-  bool fooBar(bool Baz, StringRef Quux, std::vector );
+  bool fooBar(bool baz, StringRef quux, std::vector );
 
 Don't duplicate the documentation comment in the header file and in the
 implementation file.  Put the documentation comments for public APIs into the
@@ -603,7 +603,7 @@
 
   foo({a, b, c}, {1, 2, 3});
 
-  llvm::Constant *Mask[] = {
+  llvm::Constant *mask[] = {
   llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 0),
   llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 1),
   llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 2)};
@@ -633,7 +633,7 @@
 
 .. code-block:: c++
 
-  if (V = getValue()) {
+  if (v = getValue()) {
 ...
   }
 
@@ -644,7 +644,7 @@
 
 .. code-block:: c++
 
-  if ((V = getValue())) {
+  if ((v = getValue())) {
 ...
   }
 
@@ -736,7 +736,7 @@
   class Foo;
 
   // Breaks mangling in MSVC.
-  struct Foo { int Data; };
+  struct Foo { int data; };
 
 * As a rule of thumb, ``struct`` should be kept to structures where *all*
   members are declared public.
@@ -746,17 +746,17 @@
   // Foo feels like a class... this is strange.
   struct Foo {
   private:
-int Data;
+int data;
   public:
-Foo() : Data(0) { }
-int getData() const { return Data; }
-void setData(int D) { Data = D; }
+Foo() : data(0) { }
+int getData() const { return data; }
+void setData(int d) { data = d; }
   };
 
   // Bar isn't POD, but it does look like a struct.
   struct Bar {
-int Data;
-Bar() : Data(0) { }
+int data;
+Bar() : data(0) { }
   };
 
 Do not use Braced Initializer Lists to Call a Constructor
@@ -780,7 +780,7 @@
 Foo(std::string filename);
 
 // Construct a Foo by looking up the Nth element of some global data ...
-Foo(int N);
+Foo(int n);
 
 // ...
   };
@@ -789,7 +789,7 @@
   std::fill(foo.begin(), foo.end(), Foo("name"));
 
   // The pair is just being constructed like an aggregate, use braces.
-  bar_map.insert({my_key, my_value});
+  bar_map.insert({myKey, myValue});
 
 If you use a braced initializer list when initializing a variable, use an equals before the open curly brace:
 
@@ -821,15 +821,15 @@
 .. code-block:: c++
 
   // Typically there's no reason to copy.
-  for (const auto  : Container) { observe(Val); }
-  for (auto  : Container) { Val.change(); }
+  for (const auto  : container) { observe(val); }
+  for (auto  : container) { val.change(); }
 
   // Remove the reference if you really want a new copy.
-  for (auto Val : Container) { Val.change(); saveSomewhere(Val); }
+  for (auto val : container) { val.change(); saveSomewhere(val); }
 
   // Copy pointers, but make it clear that they're pointers.
-  for (const auto *Ptr : Container) { observe(*Ptr); }
-  for (auto *Ptr : Container) { Ptr->change(); }
+  for (const auto *ptr : container) { observe(*ptr); }
+  for (auto *ptr : container) { ptr->change(); }
 
 Beware of non-determinism due to ordering of pointers
 ^
@@ -968,9 +968,9 @@
 
 .. code-block:: c++
 
-  Value *doSomething(Instruction *I) {
-if (!I->isTerminator() &&
-I->hasOneUse() && doOtherThing(I)) {
+  Value *doSomething(Instruction *instruction) {
+if (!instruction->isTerminator() &&
+instruction->hasOneUse() && 

[PATCH] D57335: [IR] Don't assume all functions are 4 byte aligned

2019-03-06 Thread Michael Platings via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL355522: [IR][ARM] Add function pointer alignment to 
datalayout (authored by michaelplatings, committed by ).

Changed prior to commit:
  https://reviews.llvm.org/D57335?vs=188325=189524#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57335/new/

https://reviews.llvm.org/D57335

Files:
  cfe/trunk/lib/Basic/Targets/ARM.cpp
  cfe/trunk/test/CodeGen/armv7k-abi.c
  cfe/trunk/test/CodeGen/target-data.c
  llvm/trunk/docs/LangRef.rst
  llvm/trunk/include/llvm/IR/DataLayout.h
  llvm/trunk/lib/IR/ConstantFold.cpp
  llvm/trunk/lib/IR/DataLayout.cpp
  llvm/trunk/lib/IR/Value.cpp
  llvm/trunk/lib/Target/ARM/ARMTargetMachine.cpp
  llvm/trunk/unittests/IR/CMakeLists.txt
  llvm/trunk/unittests/IR/ConstantsTest.cpp
  llvm/trunk/unittests/IR/DataLayoutTest.cpp
  llvm/trunk/unittests/IR/FunctionTest.cpp

Index: llvm/trunk/lib/Target/ARM/ARMTargetMachine.cpp
===
--- llvm/trunk/lib/Target/ARM/ARMTargetMachine.cpp
+++ llvm/trunk/lib/Target/ARM/ARMTargetMachine.cpp
@@ -141,6 +141,10 @@
   // Pointers are 32 bits and aligned to 32 bits.
   Ret += "-p:32:32";
 
+  // Function pointers are aligned to 8 bits (because the LSB stores the
+  // ARM/Thumb state).
+  Ret += "-Fi8";
+
   // ABIs other than APCS have 64 bit integers with natural alignment.
   if (ABI != ARMBaseTargetMachine::ARM_ABI_APCS)
 Ret += "-i64:64";
Index: llvm/trunk/lib/IR/DataLayout.cpp
===
--- llvm/trunk/lib/IR/DataLayout.cpp
+++ llvm/trunk/lib/IR/DataLayout.cpp
@@ -184,6 +184,8 @@
   AllocaAddrSpace = 0;
   StackNaturalAlign = 0;
   ProgramAddrSpace = 0;
+  FunctionPtrAlign = 0;
+  TheFunctionPtrAlignType = FunctionPtrAlignType::Independent;
   ManglingMode = MM_None;
   NonIntegralAddressSpaces.clear();
 
@@ -379,6 +381,22 @@
   StackNaturalAlign = inBytes(getInt(Tok));
   break;
 }
+case 'F': {
+  switch (Tok.front()) {
+  case 'i':
+TheFunctionPtrAlignType = FunctionPtrAlignType::Independent;
+break;
+  case 'n':
+TheFunctionPtrAlignType = FunctionPtrAlignType::MultipleOfFunctionAlign;
+break;
+  default:
+report_fatal_error("Unknown function pointer alignment type in "
+   "datalayout string");
+  }
+  Tok = Tok.substr(1);
+  FunctionPtrAlign = inBytes(getInt(Tok));
+  break;
+}
 case 'P': { // Function address space.
   ProgramAddrSpace = getAddrSpace(Tok);
   break;
@@ -432,6 +450,8 @@
  AllocaAddrSpace == Other.AllocaAddrSpace &&
  StackNaturalAlign == Other.StackNaturalAlign &&
  ProgramAddrSpace == Other.ProgramAddrSpace &&
+ FunctionPtrAlign == Other.FunctionPtrAlign &&
+ TheFunctionPtrAlignType == Other.TheFunctionPtrAlignType &&
  ManglingMode == Other.ManglingMode &&
  LegalIntWidths == Other.LegalIntWidths &&
  Alignments == Other.Alignments && Pointers == Other.Pointers;
Index: llvm/trunk/lib/IR/ConstantFold.cpp
===
--- llvm/trunk/lib/IR/ConstantFold.cpp
+++ llvm/trunk/lib/IR/ConstantFold.cpp
@@ -26,6 +26,7 @@
 #include "llvm/IR/GlobalAlias.h"
 #include "llvm/IR/GlobalVariable.h"
 #include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
 #include "llvm/IR/Operator.h"
 #include "llvm/IR/PatternMatch.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -1076,10 +1077,29 @@
 isa(CE1->getOperand(0))) {
   GlobalValue *GV = cast(CE1->getOperand(0));
 
-  // Functions are at least 4-byte aligned.
-  unsigned GVAlign = GV->getAlignment();
-  if (isa(GV))
-GVAlign = std::max(GVAlign, 4U);
+  unsigned GVAlign;
+
+  if (Module *TheModule = GV->getParent()) {
+GVAlign = GV->getPointerAlignment(TheModule->getDataLayout());
+
+// If the function alignment is not specified then assume that it
+// is 4.
+// This is dangerous; on x86, the alignment of the pointer
+// corresponds to the alignment of the function, but might be less
+// than 4 if it isn't explicitly specified.
+// However, a fix for this behaviour was reverted because it
+// increased code size (see https://reviews.llvm.org/D55115)
+// FIXME: This code should be deleted once existing targets have
+// appropriate defaults
+if (GVAlign == 0U && isa(GV))
+  GVAlign = 4U;
+  } else if (isa(GV)) {
+// Without a datalayout we have to assume the worst case: that the
+// function pointer isn't aligned at all.
+GVAlign = 0U;
+  } else {
+GVAlign = GV->getAlignment();
+  }
 
   

[PATCH] D57335: [IR] Don't assume all functions are 4 byte aligned

2019-02-25 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 188184.
michaelplatings added a comment.
Herald added subscribers: cfe-commits, jdoerfert, mgorny, dschuff.
Herald added projects: clang, LLVM.

Hi @efriedma, sorry for the delayed response.
I've added the features you asked for to DataLayout.
It is intended that this patch preserves the existing behaviour if no function 
pointer alignment is specified.* Therefore I hope you'll agree that it isn't 
necessary for me to provide code to use the new feature on all platforms.
I did also look into using a target hook but doing so would require modifying a 
//lot// of functions to take a TargetTransformInfo argument. Given that we're 
in agreement that the DataLayout is an appropriate choice, it seemed like the 
best option.

- The exception to this is the case where the Function object doesn't have a 
parent - no alignment is assumed whereas previously 4-byte alignment was 
assumed. Hopefully this case is rare enough that code size won't be 
significantly impacted.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57335/new/

https://reviews.llvm.org/D57335

Files:
  clang/lib/Basic/Targets/ARM.cpp
  clang/test/CodeGen/armv7k-abi.c
  clang/test/CodeGen/target-data.c
  llvm/docs/LangRef.rst
  llvm/include/llvm/IR/ConstantFold.h
  llvm/include/llvm/IR/DataLayout.h
  llvm/lib/IR/ConstantFold.cpp
  llvm/lib/IR/ConstantFold.h
  llvm/lib/IR/Constants.cpp
  llvm/lib/IR/DataLayout.cpp
  llvm/lib/IR/Value.cpp
  llvm/lib/Target/ARM/ARMTargetMachine.cpp
  llvm/unittests/IR/CMakeLists.txt
  llvm/unittests/IR/ConstantFoldTest.cpp
  llvm/unittests/IR/DataLayoutTest.cpp
  llvm/unittests/IR/FunctionTest.cpp

Index: llvm/unittests/IR/FunctionTest.cpp
===
--- llvm/unittests/IR/FunctionTest.cpp
+++ llvm/unittests/IR/FunctionTest.cpp
@@ -129,4 +129,29 @@
   EXPECT_TRUE(F->hasSection());
 }
 
+TEST(FunctionTest, GetPointerAlignment) {
+  LLVMContext Context;
+  Type *VoidType(Type::getVoidTy(Context));
+  FunctionType *FuncType(FunctionType::get(VoidType, false));
+  Function *Func = Function::Create(
+  FuncType, GlobalValue::ExternalLinkage);
+  EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout("")));
+  EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8")));
+  EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fn8")));
+  EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16")));
+  EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fn16")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32")));
+
+  Func->setAlignment(4U);
+
+  EXPECT_EQ(0U, Func->getPointerAlignment(DataLayout("")));
+  EXPECT_EQ(1U, Func->getPointerAlignment(DataLayout("Fi8")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn8")));
+  EXPECT_EQ(2U, Func->getPointerAlignment(DataLayout("Fi16")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn16")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fi32")));
+  EXPECT_EQ(4U, Func->getPointerAlignment(DataLayout("Fn32")));
+}
+
 } // end namespace
Index: llvm/unittests/IR/DataLayoutTest.cpp
===
--- /dev/null
+++ llvm/unittests/IR/DataLayoutTest.cpp
@@ -0,0 +1,47 @@
+//===- ConstantRangeTest.cpp - ConstantRange tests ===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "llvm/IR/DataLayout.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(DataLayoutTest, FunctionPtrAlign) {
+  EXPECT_EQ(0U, DataLayout("").getFunctionPtrAlign());
+  EXPECT_EQ(1U, DataLayout("Fi8").getFunctionPtrAlign());
+  EXPECT_EQ(2U, DataLayout("Fi16").getFunctionPtrAlign());
+  EXPECT_EQ(4U, DataLayout("Fi32").getFunctionPtrAlign());
+  EXPECT_EQ(8U, DataLayout("Fi64").getFunctionPtrAlign());
+  EXPECT_EQ(1U, DataLayout("Fn8").getFunctionPtrAlign());
+  EXPECT_EQ(2U, DataLayout("Fn16").getFunctionPtrAlign());
+  EXPECT_EQ(4U, DataLayout("Fn32").getFunctionPtrAlign());
+  EXPECT_EQ(8U, DataLayout("Fn64").getFunctionPtrAlign());
+  EXPECT_EQ(DataLayout::FunctionPtrAlignType::Independent, \
+  DataLayout("").getFunctionPtrAlignType());
+  EXPECT_EQ(DataLayout::FunctionPtrAlignType::Independent, \
+  DataLayout("Fi8").getFunctionPtrAlignType());
+  EXPECT_EQ(DataLayout::FunctionPtrAlignType::MultipleOfFunctionAlign, \
+  DataLayout("Fn8").getFunctionPtrAlignType());
+  EXPECT_EQ(DataLayout("Fi8"), DataLayout("Fi8"));
+  EXPECT_NE(DataLayout("Fi8"), DataLayout("Fi16"));
+  EXPECT_NE(DataLayout("Fi8"), DataLayout("Fn8"));
+
+  DataLayout a(""), b("Fi8"), c("Fn8");
+  EXPECT_NE(a, b);
+  EXPECT_NE(a, 

[PATCH] D57896: Variable names rule

2019-02-07 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Following discussion 
 and 
general agreement that the current naming rule for variables is not ideal, this 
patch switches the naming rule to make `lowerCamelCase` the standard, 
consistent with a prior RFC 
.

Given that over 450,000 variables are currently named in `UpperCamelCase`, the 
rule also permits using that form for consistency with existing code. I can't 
see a way to express that in .clang-tidy files.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D57896

Files:
  .clang-tidy
  clang/.clang-tidy
  llvm/.clang-tidy
  llvm/docs/CodingStandards.rst

Index: llvm/docs/CodingStandards.rst
===
--- llvm/docs/CodingStandards.rst
+++ llvm/docs/CodingStandards.rst
@@ -1191,8 +1191,9 @@
   nouns and start with an upper-case letter (e.g. ``TextFileReader``).
 
 * **Variable names** should be nouns (as they represent state).  The name should
-  be camel case, and start with an upper case letter (e.g. ``Leader`` or
-  ``Boats``).
+  be camel case, and start with a lower case letter (e.g. ``leader`` or
+  ``boats``). It is also acceptable to use ``UpperCamelCase`` for consistency
+  with existing code.
   
 * **Function names** should be verb phrases (as they represent actions), and
   command-like function should be imperative.  The name should be camel case,
@@ -1232,16 +1233,22 @@
 
   class VehicleMaker {
 ...
-Factory F;// Bad -- abbreviation and non-descriptive.
-Factory Factory;  // Better.
-Factory TireFactory;  // Even better -- if VehicleMaker has more than one
-// kind of factories.
+Factory f;// Bad -- abbreviation and non-descriptive.
+Factory factory;  // Better.
+Factory tireFactory;  // Even better -- if VehicleMaker has more than
+// one kind of factory.
   };
 
-  Vehicle makeVehicle(VehicleType Type) {
-VehicleMaker M; // Might be OK if having a short life-span.
-Tire Tmp1 = M.makeTire();   // Bad -- 'Tmp1' provides no information.
-Light Headlight = M.makeLight("head");  // Good -- descriptive.
+  Vehicle makeVehicle(VehicleType type) {
+// Reusing the type name in lowerCamelCase form is often a good way to get
+// a suitable variable name.
+VehicleMaker vehicleMaker;
+
+// Bad -- 'tmp1' provides no information.
+Tire tmp1 = vehicleMaker.makeTire();
+
+// Good -- descriptive.
+Light headlight = vehicleMaker.makeLight("head");
 ...
   }
 
Index: llvm/.clang-tidy
===
--- llvm/.clang-tidy
+++ llvm/.clang-tidy
@@ -7,11 +7,11 @@
   - key: readability-identifier-naming.FunctionCase
 value:   camelBack
   - key: readability-identifier-naming.MemberCase
-value:   CamelCase
+value:   camelBack
   - key: readability-identifier-naming.ParameterCase
-value:   CamelCase
+value:   camelBack
   - key: readability-identifier-naming.UnionCase
 value:   CamelCase
   - key: readability-identifier-naming.VariableCase
-value:   CamelCase
+value:   camelBack
 
Index: clang/.clang-tidy
===
--- clang/.clang-tidy
+++ clang/.clang-tidy
@@ -12,11 +12,11 @@
   - key: readability-identifier-naming.FunctionCase
 value:   camelBack
   - key: readability-identifier-naming.MemberCase
-value:   CamelCase
+value:   camelBack
   - key: readability-identifier-naming.ParameterCase
-value:   CamelCase
+value:   camelBack
   - key: readability-identifier-naming.UnionCase
 value:   CamelCase
   - key: readability-identifier-naming.VariableCase
-value:   CamelCase
+value:   camelBack
 
Index: .clang-tidy
===
--- .clang-tidy
+++ .clang-tidy
@@ -7,11 +7,11 @@
   - key: readability-identifier-naming.FunctionCase
 value:   camelBack
   - key: readability-identifier-naming.MemberCase
-value:   CamelCase
+value:   camelBack
   - key: readability-identifier-naming.ParameterCase
-value:   CamelCase
+value:   camelBack
   - key: readability-identifier-naming.UnionCase
 value:   CamelCase
   - key: readability-identifier-naming.VariableCase
-value:   CamelCase
+value:  

[PATCH] D57896: Variable names rule

2019-02-07 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

In D57896#1389042 , @lebedev.ri wrote:

> Pretty sure this patch should have gone to llvm-commits, not cfe-commits.


I just set the repository, Phabricator did the rest - apparently the magic 
isn't working so well.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57896/new/

https://reviews.llvm.org/D57896



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57896: Variable names rule

2019-02-08 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

In D57896#1389067 , @lebedev.ri wrote:

> 1. Does clang-tidy warn on every single existing variable now?
> 2. It might be best to give this more visibility, by submitting a mail to 
> llvm-dev, with a **noticeable** subject, like "RFC: changing variable naming 
> rules in LLVM codebase"




1. Pretty much. Previously clang-tidy gave 56,787 unique warnings. After this 
patch it gives 361,382 unique warnings. I personally would be happy to change 
the settings from `camelBack` to `aNy_CasE`.

2. Done: http://lists.llvm.org/pipermail/llvm-dev/2019-February/130083.html


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57896/new/

https://reviews.llvm.org/D57896



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57896: Variable names rule

2019-02-18 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 187252.
michaelplatings added a comment.

Update .clang-tidy files to use aNy_CasE until camelBackOrCase is available.
Add more guidance around acronyms.
Add more guidance around consistency with existing CamelCase variable names.
Change other code examples to camelBack.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57896/new/

https://reviews.llvm.org/D57896

Files:
  .clang-tidy
  clang/.clang-tidy
  llvm/.clang-tidy
  llvm/docs/CodingStandards.rst

Index: llvm/docs/CodingStandards.rst
===
--- llvm/docs/CodingStandards.rst
+++ llvm/docs/CodingStandards.rst
@@ -311,13 +311,13 @@
 
.. code-block:: c++
 
- Object.emitName(nullptr);
+ object.emitName(nullptr);
 
An in-line C-style comment makes the intent obvious:
 
.. code-block:: c++
 
- Object.emitName(/*Prefix=*/nullptr);
+ object.emitName(/*prefix=*/nullptr);
 
 Commenting out large blocks of code is discouraged, but if you really have to do
 this (for documentation purposes or as a suggestion for debug printing), use
@@ -355,8 +355,8 @@
 
 .. code-block:: c++
 
-  /// Sets the xyzzy property to \p Baz.
-  void setXyzzy(bool Baz);
+  /// Sets the xyzzy property to \p baz.
+  void setXyzzy(bool baz);
 
 A documentation comment that uses all Doxygen features in a preferred way:
 
@@ -364,18 +364,18 @@
 
   /// Does foo and bar.
   ///
-  /// Does not do foo the usual way if \p Baz is true.
+  /// Does not do foo the usual way if \p baz is true.
   ///
   /// Typical usage:
   /// \code
-  ///   fooBar(false, "quux", Res);
+  ///   fooBar(false, "quux", res);
   /// \endcode
   ///
-  /// \param Quux kind of foo to do.
+  /// \param quux kind of foo to do.
   /// \param [out] Result filled with bar sequence on foo success.
   ///
   /// \returns true on success.
-  bool fooBar(bool Baz, StringRef Quux, std::vector );
+  bool fooBar(bool baz, StringRef quux, std::vector );
 
 Don't duplicate the documentation comment in the header file and in the
 implementation file.  Put the documentation comments for public APIs into the
@@ -568,16 +568,16 @@
 .. code-block:: c++
 
   dyn_switch(V->stripPointerCasts(),
- [] (PHINode *PN) {
+ [] (PHINode *phiNode) {
// process phis...
  },
- [] (SelectInst *SI) {
+ [] (SelectInst *selectInst) {
// process selects...
  },
- [] (LoadInst *LI) {
+ [] (LoadInst *loadInst) {
// process loads...
  },
- [] (AllocaInst *AI) {
+ [] (AllocaInst *allocaInst) {
// process allocas...
  });
 
@@ -603,7 +603,7 @@
 
   foo({a, b, c}, {1, 2, 3});
 
-  llvm::Constant *Mask[] = {
+  llvm::Constant *mask[] = {
   llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 0),
   llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 1),
   llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 2)};
@@ -633,7 +633,7 @@
 
 .. code-block:: c++
 
-  if (V = getValue()) {
+  if (v = getValue()) {
 ...
   }
 
@@ -644,7 +644,7 @@
 
 .. code-block:: c++
 
-  if ((V = getValue())) {
+  if ((v = getValue())) {
 ...
   }
 
@@ -736,7 +736,7 @@
   class Foo;
 
   // Breaks mangling in MSVC.
-  struct Foo { int Data; };
+  struct Foo { int data; };
 
 * As a rule of thumb, ``struct`` should be kept to structures where *all*
   members are declared public.
@@ -746,17 +746,17 @@
   // Foo feels like a class... this is strange.
   struct Foo {
   private:
-int Data;
+int data;
   public:
-Foo() : Data(0) { }
-int getData() const { return Data; }
-void setData(int D) { Data = D; }
+Foo() : data(0) { }
+int getData() const { return data; }
+void setData(int d) { data = d; }
   };
 
   // Bar isn't POD, but it does look like a struct.
   struct Bar {
-int Data;
-Bar() : Data(0) { }
+int data;
+Bar() : data(0) { }
   };
 
 Do not use Braced Initializer Lists to Call a Constructor
@@ -780,7 +780,7 @@
 Foo(std::string filename);
 
 // Construct a Foo by looking up the Nth element of some global data ...
-Foo(int N);
+Foo(int n);
 
 // ...
   };
@@ -789,7 +789,7 @@
   std::fill(foo.begin(), foo.end(), Foo("name"));
 
   // The pair is just being constructed like an aggregate, use braces.
-  bar_map.insert({my_key, my_value});
+  bar_map.insert({myKey, myValue});
 
 If you use a braced initializer list when initializing a variable, use an equals before the open curly brace:
 
@@ -821,15 +821,15 @@
 .. code-block:: c++
 
   // Typically there's no reason to copy.
-  for (const auto  : Container) { observe(Val); }
-  for (auto  : Container) { Val.change(); }
+  for (const auto  : container) { observe(val); }
+  for (auto  : container) { val.change(); }
 
   // Remove 

[PATCH] D57896: Variable names rule

2019-02-18 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings marked an inline comment as done.
michaelplatings added inline comments.



Comment at: llvm/docs/CodingStandards.rst:1195
+  be camel case, and start with a lower case letter (e.g. ``leader`` or
+  ``boats``). It is also acceptable to use ``UpperCamelCase`` for consistency
+  with existing code.

rupprecht wrote:
> It would be nice for this section to be expanded a bit, just to avoid 
> inevitable code review churn, e.g. if I'm adding 50 lines to a 200 line file, 
> am I allowed to change the existing var names elsewhere in the file or 
> method, or is that outside the scope of my change? If I'm reviewing that 
> patch, do I tell the author they have to be consistent and revert other 
> changes? etc.
> 
> Is there any plan to use clang-tidy to do a global cleanup, or is this going 
> to be a totally ad-hoc migration -- variables use the new scheme only when 
> the code is updated?
I've had a go at expanding it. Please let me know if you have other suggestions.

> Is there any plan to use clang-tidy to do a global cleanup, or is this going 
> to be a totally ad-hoc migration -- variables use the new scheme only when 
> the code is updated?

The latter. Given that the code doesn't keep to the existing .clang-tidy rules 
I'm not optimistic that we could persuade code owners to start now. That's not 
to say it couldn't happen eventually, but my aim at this point in time is to 
make it easier to use good variable names and I don't want perfect to be the 
enemy of better.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57896/new/

https://reviews.llvm.org/D57896



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57896: Variable names rule

2019-02-11 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

In D57896#1390517 , @MyDeveloperDay 
wrote:

> Should we come up with a new style?  say `UpperOrLowerCamelCase`,   I don't 
> mind going and doing that in the readability-identifier-naming check, given 
> that I just wrote up all the Options for that check 
> https://clang.llvm.org/extra/clang-tidy/checks/readability-identifier-naming.html
>  in D56563: [clang-tidy]  add options documentation to 
> readability-identifier-naming checker 


Sounds good to me. I see that you've made D57966 
 a child of this issue, but we could swap the 
dependency around so that once your patch is applied I can update this patch to 
use `camelBackOrCase`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57896/new/

https://reviews.llvm.org/D57896



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D64123: Add clang-llvm-rename tool.

2019-07-05 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

Hi @ruiu,
Can you comment on how this compares to clang-tidy? I had assumed that the 
readability-identifier-naming clang-tidy rule would largely do the trick.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D64123/new/

https://reviews.llvm.org/D64123



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D71991: Fix external-names.c test when separator is \\

2019-12-31 Thread Michael Platings via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG0c7ca82161b5: Fix external-names.c test when separator is \\ 
(authored by michaelplatings).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71991/new/

https://reviews.llvm.org/D71991

Files:
  clang/test/VFS/external-names.c


Index: clang/test/VFS/external-names.c
===
--- clang/test/VFS/external-names.c
+++ clang/test/VFS/external-names.c
@@ -21,7 +21,7 @@
 // Diagnostics:
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.external.yaml -fsyntax-only %s 2>&1 | 
FileCheck -check-prefix=CHECK-DIAG-EXTERNAL %s
-// CHECK-DIAG-EXTERNAL: {{.*}}Inputs{{.}}external-names.h:{{[0-9]*:[0-9]*}}: 
warning: incompatible pointer
+// CHECK-DIAG-EXTERNAL: {{.*}}Inputs{{..?}}external-names.h:{{[0-9]*:[0-9]*}}: 
warning: incompatible pointer
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.yaml -fsyntax-only %s 2>&1 | 
FileCheck -check-prefix=CHECK-DIAG %s
 // CHECK-DIAG-NOT: Inputs
@@ -31,7 +31,7 @@
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.external.yaml -triple 
%itanium_abi_triple -debug-info-kind=limited -emit-llvm %s -o - | FileCheck 
-check-prefix=CHECK-DEBUG-EXTERNAL %s
 // CHECK-DEBUG-EXTERNAL: !DISubprogram({{.*}}file: ![[Num:[0-9]+]]
-// CHECK-DEBUG-EXTERNAL: ![[Num]] = !DIFile(filename: 
"{{[^"]*}}Inputs{{.}}external-names.h"
+// CHECK-DEBUG-EXTERNAL: ![[Num]] = !DIFile(filename: 
"{{[^"]*}}Inputs{{..?}}external-names.h"
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.yaml -triple %itanium_abi_triple 
-debug-info-kind=limited -emit-llvm %s -o - | FileCheck 
-check-prefix=CHECK-DEBUG %s
 // CHECK-DEBUG-NOT: Inputs
@@ -42,7 +42,7 @@
 // RUN: %clang_cc1 -D REINCLUDE -I %t -ivfsoverlay %t.external.yaml -Eonly %s 
-MTfoo -dependency-file %t.external.dep
 // RUN: echo "EOF" >> %t.external.dep
 // RUN: cat %t.external.dep | FileCheck --check-prefix=CHECK-DEP-EXTERNAL %s
-// CHECK-DEP-EXTERNAL: Inputs{{.}}external-names.h
+// CHECK-DEP-EXTERNAL: Inputs{{..?}}external-names.h
 // CHECK-DEP-EXTERNAL-NEXT: EOF
 
 // RUN: %clang_cc1 -D REINCLUDE -I %t -ivfsoverlay %t.yaml -Eonly %s -MTfoo 
-dependency-file %t.dep


Index: clang/test/VFS/external-names.c
===
--- clang/test/VFS/external-names.c
+++ clang/test/VFS/external-names.c
@@ -21,7 +21,7 @@
 // Diagnostics:
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.external.yaml -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-DIAG-EXTERNAL %s
-// CHECK-DIAG-EXTERNAL: {{.*}}Inputs{{.}}external-names.h:{{[0-9]*:[0-9]*}}: warning: incompatible pointer
+// CHECK-DIAG-EXTERNAL: {{.*}}Inputs{{..?}}external-names.h:{{[0-9]*:[0-9]*}}: warning: incompatible pointer
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.yaml -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-DIAG %s
 // CHECK-DIAG-NOT: Inputs
@@ -31,7 +31,7 @@
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.external.yaml -triple %itanium_abi_triple -debug-info-kind=limited -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-DEBUG-EXTERNAL %s
 // CHECK-DEBUG-EXTERNAL: !DISubprogram({{.*}}file: ![[Num:[0-9]+]]
-// CHECK-DEBUG-EXTERNAL: ![[Num]] = !DIFile(filename: "{{[^"]*}}Inputs{{.}}external-names.h"
+// CHECK-DEBUG-EXTERNAL: ![[Num]] = !DIFile(filename: "{{[^"]*}}Inputs{{..?}}external-names.h"
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.yaml -triple %itanium_abi_triple -debug-info-kind=limited -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-DEBUG %s
 // CHECK-DEBUG-NOT: Inputs
@@ -42,7 +42,7 @@
 // RUN: %clang_cc1 -D REINCLUDE -I %t -ivfsoverlay %t.external.yaml -Eonly %s -MTfoo -dependency-file %t.external.dep
 // RUN: echo "EOF" >> %t.external.dep
 // RUN: cat %t.external.dep | FileCheck --check-prefix=CHECK-DEP-EXTERNAL %s
-// CHECK-DEP-EXTERNAL: Inputs{{.}}external-names.h
+// CHECK-DEP-EXTERNAL: Inputs{{..?}}external-names.h
 // CHECK-DEP-EXTERNAL-NEXT: EOF
 
 // RUN: %clang_cc1 -D REINCLUDE -I %t -ivfsoverlay %t.yaml -Eonly %s -MTfoo -dependency-file %t.dep
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D71991: Fix external-names.c test when separator is \\

2019-12-31 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

Thanks for accepting.
The repo is up to date. I guess the reason the failure hasn't happened with the 
build bots is that our downstream test setup differs somewhat from the norm - 
our test runner imports lit.discovery & lit.LitConfig directly rather than 
using the command line interface. I've had a hunt for what the exact difference 
might be but haven't been able to find it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71991/new/

https://reviews.llvm.org/D71991



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D71991: Fix external-names.c test when separator is \\

2019-12-30 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added reviewers: rnk, amccarth, dsanders, miyuki.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
michaelplatings edited the summary of this revision.

This fixes the following failure:

  C:\[...]\llvm\tools\clang\test\VFS\external-names.c:34:26: error: 
CHECK-DEBUG-EXTERNAL: expected string not found in input
  // CHECK-DEBUG-EXTERNAL: ![[Num]] = !DIFile(filename: 
"{{[^"]*}}Inputs{{.}}external-names.h"
   ^
  [...]
  :42:54: note: possible intended match here
  !10 = !DIFile(filename: 
"C:/[...]\\llvm\\tools\\clang\\test\\VFS\\Inputs\\external-names.h", directory: 
"")


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D71991

Files:
  clang/test/VFS/external-names.c


Index: clang/test/VFS/external-names.c
===
--- clang/test/VFS/external-names.c
+++ clang/test/VFS/external-names.c
@@ -21,7 +21,7 @@
 // Diagnostics:
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.external.yaml -fsyntax-only %s 2>&1 | 
FileCheck -check-prefix=CHECK-DIAG-EXTERNAL %s
-// CHECK-DIAG-EXTERNAL: {{.*}}Inputs{{.}}external-names.h:{{[0-9]*:[0-9]*}}: 
warning: incompatible pointer
+// CHECK-DIAG-EXTERNAL: {{.*}}Inputs{{..?}}external-names.h:{{[0-9]*:[0-9]*}}: 
warning: incompatible pointer
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.yaml -fsyntax-only %s 2>&1 | 
FileCheck -check-prefix=CHECK-DIAG %s
 // CHECK-DIAG-NOT: Inputs
@@ -31,7 +31,7 @@
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.external.yaml -triple 
%itanium_abi_triple -debug-info-kind=limited -emit-llvm %s -o - | FileCheck 
-check-prefix=CHECK-DEBUG-EXTERNAL %s
 // CHECK-DEBUG-EXTERNAL: !DISubprogram({{.*}}file: ![[Num:[0-9]+]]
-// CHECK-DEBUG-EXTERNAL: ![[Num]] = !DIFile(filename: 
"{{[^"]*}}Inputs{{.}}external-names.h"
+// CHECK-DEBUG-EXTERNAL: ![[Num]] = !DIFile(filename: 
"{{[^"]*}}Inputs{{..?}}external-names.h"
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.yaml -triple %itanium_abi_triple 
-debug-info-kind=limited -emit-llvm %s -o - | FileCheck 
-check-prefix=CHECK-DEBUG %s
 // CHECK-DEBUG-NOT: Inputs
@@ -42,7 +42,7 @@
 // RUN: %clang_cc1 -D REINCLUDE -I %t -ivfsoverlay %t.external.yaml -Eonly %s 
-MTfoo -dependency-file %t.external.dep
 // RUN: echo "EOF" >> %t.external.dep
 // RUN: cat %t.external.dep | FileCheck --check-prefix=CHECK-DEP-EXTERNAL %s
-// CHECK-DEP-EXTERNAL: Inputs{{.}}external-names.h
+// CHECK-DEP-EXTERNAL: Inputs{{..?}}external-names.h
 // CHECK-DEP-EXTERNAL-NEXT: EOF
 
 // RUN: %clang_cc1 -D REINCLUDE -I %t -ivfsoverlay %t.yaml -Eonly %s -MTfoo 
-dependency-file %t.dep


Index: clang/test/VFS/external-names.c
===
--- clang/test/VFS/external-names.c
+++ clang/test/VFS/external-names.c
@@ -21,7 +21,7 @@
 // Diagnostics:
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.external.yaml -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-DIAG-EXTERNAL %s
-// CHECK-DIAG-EXTERNAL: {{.*}}Inputs{{.}}external-names.h:{{[0-9]*:[0-9]*}}: warning: incompatible pointer
+// CHECK-DIAG-EXTERNAL: {{.*}}Inputs{{..?}}external-names.h:{{[0-9]*:[0-9]*}}: warning: incompatible pointer
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.yaml -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-DIAG %s
 // CHECK-DIAG-NOT: Inputs
@@ -31,7 +31,7 @@
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.external.yaml -triple %itanium_abi_triple -debug-info-kind=limited -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-DEBUG-EXTERNAL %s
 // CHECK-DEBUG-EXTERNAL: !DISubprogram({{.*}}file: ![[Num:[0-9]+]]
-// CHECK-DEBUG-EXTERNAL: ![[Num]] = !DIFile(filename: "{{[^"]*}}Inputs{{.}}external-names.h"
+// CHECK-DEBUG-EXTERNAL: ![[Num]] = !DIFile(filename: "{{[^"]*}}Inputs{{..?}}external-names.h"
 
 // RUN: %clang_cc1 -I %t -ivfsoverlay %t.yaml -triple %itanium_abi_triple -debug-info-kind=limited -emit-llvm %s -o - | FileCheck -check-prefix=CHECK-DEBUG %s
 // CHECK-DEBUG-NOT: Inputs
@@ -42,7 +42,7 @@
 // RUN: %clang_cc1 -D REINCLUDE -I %t -ivfsoverlay %t.external.yaml -Eonly %s -MTfoo -dependency-file %t.external.dep
 // RUN: echo "EOF" >> %t.external.dep
 // RUN: cat %t.external.dep | FileCheck --check-prefix=CHECK-DEP-EXTERNAL %s
-// CHECK-DEP-EXTERNAL: Inputs{{.}}external-names.h
+// CHECK-DEP-EXTERNAL: Inputs{{..?}}external-names.h
 // CHECK-DEP-EXTERNAL-NEXT: EOF
 
 // RUN: %clang_cc1 -D REINCLUDE -I %t -ivfsoverlay %t.yaml -Eonly %s -MTfoo -dependency-file %t.dep
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D134824: Fix frint ACLE intrinsic names

2022-09-28 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added a reviewer: jaykang10.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Although the instruction names begin "frint", the ACLE spec states that the 
intrinsic names begin "__rint", without the "f".


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134824

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/arm_acle.h
  clang/test/CodeGen/aarch64-v8.5a-scalar-frint3264-intrinsic.c

Index: clang/test/CodeGen/aarch64-v8.5a-scalar-frint3264-intrinsic.c
===
--- clang/test/CodeGen/aarch64-v8.5a-scalar-frint3264-intrinsic.c
+++ clang/test/CodeGen/aarch64-v8.5a-scalar-frint3264-intrinsic.c
@@ -7,58 +7,58 @@
 
 #include 
 
-// CHECK-LABEL: test_frint32zf
+// CHECK-LABEL: test_rint32zf
 // CHECK:  [[RND:%.*]] =  call float @llvm.aarch64.frint32z.f32(float %a)
 // CHECK:  ret float [[RND]]
-float test_frint32zf(float a) {
-  return __frint32zf(a);
+float test_rint32zf(float a) {
+  return __rint32zf(a);
 }
 
-// CHECK-LABEL: test_frint32z
+// CHECK-LABEL: test_rint32z
 // CHECK:  [[RND:%.*]] =  call double @llvm.aarch64.frint32z.f64(double %a)
 // CHECK:  ret double [[RND]]
-double test_frint32z(double a) {
-  return __frint32z(a);
+double test_rint32z(double a) {
+  return __rint32z(a);
 }
 
-// CHECK-LABEL: test_frint64zf
+// CHECK-LABEL: test_rint64zf
 // CHECK:  [[RND:%.*]] =  call float @llvm.aarch64.frint64z.f32(float %a)
 // CHECK:  ret float [[RND]]
-float test_frint64zf(float a) {
-  return __frint64zf(a);
+float test_rint64zf(float a) {
+  return __rint64zf(a);
 }
 
-// CHECK-LABEL: test_frint64z
+// CHECK-LABEL: test_rint64z
 // CHECK:  [[RND:%.*]] =  call double @llvm.aarch64.frint64z.f64(double %a)
 // CHECK:  ret double [[RND]]
-double test_frint64z(double a) {
-  return __frint64z(a);
+double test_rint64z(double a) {
+  return __rint64z(a);
 }
 
-// CHECK-LABEL: test_frint32xf
+// CHECK-LABEL: test_rint32xf
 // CHECK:  [[RND:%.*]] =  call float @llvm.aarch64.frint32x.f32(float %a)
 // CHECK:  ret float [[RND]]
-float test_frint32xf(float a) {
-  return __frint32xf(a);
+float test_rint32xf(float a) {
+  return __rint32xf(a);
 }
 
-// CHECK-LABEL: test_frint32x
+// CHECK-LABEL: test_rint32x
 // CHECK:  [[RND:%.*]] =  call double @llvm.aarch64.frint32x.f64(double %a)
 // CHECK:  ret double [[RND]]
-double test_frint32x(double a) {
-  return __frint32x(a);
+double test_rint32x(double a) {
+  return __rint32x(a);
 }
 
-// CHECK-LABEL: test_frint64xf
+// CHECK-LABEL: test_rint64xf
 // CHECK:  [[RND:%.*]] =  call float @llvm.aarch64.frint64x.f32(float %a)
 // CHECK:  ret float [[RND]]
-float test_frint64xf(float a) {
-  return __frint64xf(a);
+float test_rint64xf(float a) {
+  return __rint64xf(a);
 }
 
-// CHECK-LABEL: test_frint64x
+// CHECK-LABEL: test_rint64x
 // CHECK:  [[RND:%.*]] =  call double @llvm.aarch64.frint64x.f64(double %a)
 // CHECK:  ret double [[RND]]
-double test_frint64x(double a) {
-  return __frint64x(a);
+double test_rint64x(double a) {
+  return __rint64x(a);
 }
Index: clang/lib/Headers/arm_acle.h
===
--- clang/lib/Headers/arm_acle.h
+++ clang/lib/Headers/arm_acle.h
@@ -642,43 +642,43 @@
 /* Armv8.5-A FP rounding intrinsics */
 #if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE && defined(__ARM_FEATURE_FRINT)
 static __inline__ float __attribute__((__always_inline__, __nodebug__))
-__frint32zf(float __a) {
-  return __builtin_arm_frint32zf(__a);
+__rint32zf(float __a) {
+  return __builtin_arm_rint32zf(__a);
 }
 
 static __inline__ double __attribute__((__always_inline__, __nodebug__))
-__frint32z(double __a) {
-  return __builtin_arm_frint32z(__a);
+__rint32z(double __a) {
+  return __builtin_arm_rint32z(__a);
 }
 
 static __inline__ float __attribute__((__always_inline__, __nodebug__))
-__frint64zf(float __a) {
-  return __builtin_arm_frint64zf(__a);
+__rint64zf(float __a) {
+  return __builtin_arm_rint64zf(__a);
 }
 
 static __inline__ double __attribute__((__always_inline__, __nodebug__))
-__frint64z(double __a) {
-  return __builtin_arm_frint64z(__a);
+__rint64z(double __a) {
+  return __builtin_arm_rint64z(__a);
 }
 
 static __inline__ float __attribute__((__always_inline__, __nodebug__))
-__frint32xf(float __a) {
-  return __builtin_arm_frint32xf(__a);
+__rint32xf(float __a) {
+  return __builtin_arm_rint32xf(__a);
 }
 
 static __inline__ double __attribute__((__always_inline__, __nodebug__))
-__frint32x(double __a) {
-  return __builtin_arm_frint32x(__a);
+__rint32x(double __a) {
+  return __builtin_arm_rint32x(__a);
 }
 
 static __inline__ float __attribute__((__always_inline__, __nodebug__))
-__frint64xf(float __a) {
-  return __builtin_arm_frint64xf(__a);
+__rint64xf(float __a) {
+  return 

[PATCH] D134824: Fix frint ACLE intrinsic names

2022-09-29 Thread Michael Platings via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGdba8fced969e: Fix frint ACLE intrinsic names (authored by 
michaelplatings).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D134824/new/

https://reviews.llvm.org/D134824

Files:
  clang/include/clang/Basic/BuiltinsAArch64.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Headers/arm_acle.h
  clang/test/CodeGen/aarch64-v8.5a-scalar-frint3264-intrinsic.c

Index: clang/test/CodeGen/aarch64-v8.5a-scalar-frint3264-intrinsic.c
===
--- clang/test/CodeGen/aarch64-v8.5a-scalar-frint3264-intrinsic.c
+++ clang/test/CodeGen/aarch64-v8.5a-scalar-frint3264-intrinsic.c
@@ -7,58 +7,58 @@
 
 #include 
 
-// CHECK-LABEL: test_frint32zf
+// CHECK-LABEL: test_rint32zf
 // CHECK:  [[RND:%.*]] =  call float @llvm.aarch64.frint32z.f32(float %a)
 // CHECK:  ret float [[RND]]
-float test_frint32zf(float a) {
-  return __frint32zf(a);
+float test_rint32zf(float a) {
+  return __rint32zf(a);
 }
 
-// CHECK-LABEL: test_frint32z
+// CHECK-LABEL: test_rint32z
 // CHECK:  [[RND:%.*]] =  call double @llvm.aarch64.frint32z.f64(double %a)
 // CHECK:  ret double [[RND]]
-double test_frint32z(double a) {
-  return __frint32z(a);
+double test_rint32z(double a) {
+  return __rint32z(a);
 }
 
-// CHECK-LABEL: test_frint64zf
+// CHECK-LABEL: test_rint64zf
 // CHECK:  [[RND:%.*]] =  call float @llvm.aarch64.frint64z.f32(float %a)
 // CHECK:  ret float [[RND]]
-float test_frint64zf(float a) {
-  return __frint64zf(a);
+float test_rint64zf(float a) {
+  return __rint64zf(a);
 }
 
-// CHECK-LABEL: test_frint64z
+// CHECK-LABEL: test_rint64z
 // CHECK:  [[RND:%.*]] =  call double @llvm.aarch64.frint64z.f64(double %a)
 // CHECK:  ret double [[RND]]
-double test_frint64z(double a) {
-  return __frint64z(a);
+double test_rint64z(double a) {
+  return __rint64z(a);
 }
 
-// CHECK-LABEL: test_frint32xf
+// CHECK-LABEL: test_rint32xf
 // CHECK:  [[RND:%.*]] =  call float @llvm.aarch64.frint32x.f32(float %a)
 // CHECK:  ret float [[RND]]
-float test_frint32xf(float a) {
-  return __frint32xf(a);
+float test_rint32xf(float a) {
+  return __rint32xf(a);
 }
 
-// CHECK-LABEL: test_frint32x
+// CHECK-LABEL: test_rint32x
 // CHECK:  [[RND:%.*]] =  call double @llvm.aarch64.frint32x.f64(double %a)
 // CHECK:  ret double [[RND]]
-double test_frint32x(double a) {
-  return __frint32x(a);
+double test_rint32x(double a) {
+  return __rint32x(a);
 }
 
-// CHECK-LABEL: test_frint64xf
+// CHECK-LABEL: test_rint64xf
 // CHECK:  [[RND:%.*]] =  call float @llvm.aarch64.frint64x.f32(float %a)
 // CHECK:  ret float [[RND]]
-float test_frint64xf(float a) {
-  return __frint64xf(a);
+float test_rint64xf(float a) {
+  return __rint64xf(a);
 }
 
-// CHECK-LABEL: test_frint64x
+// CHECK-LABEL: test_rint64x
 // CHECK:  [[RND:%.*]] =  call double @llvm.aarch64.frint64x.f64(double %a)
 // CHECK:  ret double [[RND]]
-double test_frint64x(double a) {
-  return __frint64x(a);
+double test_rint64x(double a) {
+  return __rint64x(a);
 }
Index: clang/lib/Headers/arm_acle.h
===
--- clang/lib/Headers/arm_acle.h
+++ clang/lib/Headers/arm_acle.h
@@ -642,43 +642,43 @@
 /* Armv8.5-A FP rounding intrinsics */
 #if defined(__ARM_64BIT_STATE) && __ARM_64BIT_STATE && defined(__ARM_FEATURE_FRINT)
 static __inline__ float __attribute__((__always_inline__, __nodebug__))
-__frint32zf(float __a) {
-  return __builtin_arm_frint32zf(__a);
+__rint32zf(float __a) {
+  return __builtin_arm_rint32zf(__a);
 }
 
 static __inline__ double __attribute__((__always_inline__, __nodebug__))
-__frint32z(double __a) {
-  return __builtin_arm_frint32z(__a);
+__rint32z(double __a) {
+  return __builtin_arm_rint32z(__a);
 }
 
 static __inline__ float __attribute__((__always_inline__, __nodebug__))
-__frint64zf(float __a) {
-  return __builtin_arm_frint64zf(__a);
+__rint64zf(float __a) {
+  return __builtin_arm_rint64zf(__a);
 }
 
 static __inline__ double __attribute__((__always_inline__, __nodebug__))
-__frint64z(double __a) {
-  return __builtin_arm_frint64z(__a);
+__rint64z(double __a) {
+  return __builtin_arm_rint64z(__a);
 }
 
 static __inline__ float __attribute__((__always_inline__, __nodebug__))
-__frint32xf(float __a) {
-  return __builtin_arm_frint32xf(__a);
+__rint32xf(float __a) {
+  return __builtin_arm_rint32xf(__a);
 }
 
 static __inline__ double __attribute__((__always_inline__, __nodebug__))
-__frint32x(double __a) {
-  return __builtin_arm_frint32x(__a);
+__rint32x(double __a) {
+  return __builtin_arm_rint32x(__a);
 }
 
 static __inline__ float __attribute__((__always_inline__, __nodebug__))
-__frint64xf(float __a) {
-  return __builtin_arm_frint64xf(__a);
+__rint64xf(float __a) {
+  return __builtin_arm_rint64xf(__a);
 }
 
 static __inline__ double __attribute__((__always_inline__, 

[PATCH] D140959: RFC: Multilib prototype

2023-01-04 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added a project: clang.
Herald added subscribers: s.egerton, ormris, abidh, mgrang, simoncook, 
kristof.beyls.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.

This is a prototype of a new approach to multilib.

The `multilib.yaml` file is a new interface that allows customising (a) which 
system library variants are available; and (b) how a library variant is 
identified as compatible with the clang arguments provided by the user.

The file 
clang/test/Driver/Inputs/baremetal_multilib/arm-none-eabi/multilib.yaml is an 
example that contains comments explaining how it is used.

The project I'm working on is LLVM Embedded Toolchain for Arm 
 so the design 
is made with that in mind, but it's intended to be flexible enough to work with 
other toolchains with many system library variants.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D140959

Files:
  clang/include/clang/Driver/Multilib2.h
  clang/lib/Driver/CMakeLists.txt
  clang/lib/Driver/Multilib2.cpp
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/test/Driver/Inputs/baremetal_multilib/arm-none-eabi/multilib.yaml
  clang/test/Driver/arm-compiler-rt.c
  clang/test/Driver/baremetal-multilib.cpp
  clang/test/Driver/baremetal.cpp
  clang/test/Driver/print-libgcc-file-name-clangrt.c
  clang/unittests/Driver/CMakeLists.txt
  clang/unittests/Driver/Multilib2Test.cpp

Index: clang/unittests/Driver/Multilib2Test.cpp
===
--- /dev/null
+++ clang/unittests/Driver/Multilib2Test.cpp
@@ -0,0 +1,281 @@
+//===- unittests/Driver/Multilib2Test.cpp --- Multilib2 tests ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "clang/Driver/Multilib2.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "gtest/gtest.h"
+
+using namespace clang::driver;
+using namespace clang;
+
+TEST(Multilib2Test, Parse) {
+  std::string O;
+  llvm::raw_string_ostream OS(O);
+
+  Multilib2 M;
+  EXPECT_FALSE(M.parse(R"(
+variants:
+- path: /abc
+)", OS));
+  EXPECT_TRUE(StringRef(O).contains("paths must be relative")) << O;
+
+  EXPECT_TRUE(M.parse(R"(
+variants:
+- path: .
+)", OS));
+  EXPECT_EQ(1U, M.size());
+  EXPECT_EQ("", std::get<0>(*M.begin()));
+
+  EXPECT_TRUE(M.parse(R"(
+variants:
+- path: abc
+)", OS));
+  EXPECT_EQ(1U, M.size());
+  EXPECT_EQ("/abc", std::get<0>(*M.begin()));
+
+  EXPECT_TRUE(M.parse(R"(
+variants:
+- path: pqr
+  args: [-mfloat-abi=soft]
+)", OS));
+  EXPECT_EQ(1U, M.size());
+  EXPECT_EQ("/pqr", std::get<0>(*M.begin()));
+  EXPECT_EQ(std::vector({"-mfloat-abi=soft"}), std::get<1>(*M.begin()));
+
+  EXPECT_TRUE(M.parse(R"(
+variants:
+- path: pqr
+  args: [-mfloat-abi=soft, -fno-exceptions]
+)", OS));
+  EXPECT_EQ(1U, M.size());
+  EXPECT_EQ(std::vector({"-mfloat-abi=soft", "-fno-exceptions"}), std::get<1>(*M.begin()));
+
+  EXPECT_TRUE(M.parse(R"(
+variants:
+- path: a
+- path: b
+)", OS));
+  EXPECT_EQ(2U, M.size());
+}
+
+TEST(Multilib2Test, SelectSoft) {
+  std::string O;
+  llvm::raw_string_ostream OS(O);
+  Multilib2 M;
+  ASSERT_TRUE(M.parse(R"(
+variants:
+- path: s
+  attrs: [softabi]
+arguments:
+- regex: -mfloat-abi soft
+  matchAttrs: [softabi]
+- regex: -mfloat-abi hard
+  matchAttrs: [hardabi]
+- regex: -msoft-float
+  noMatchAttrs: [hasfp]
+)", OS));
+  EXPECT_TRUE(M.select({"--target=arm-none-eabi"}).first);
+  EXPECT_TRUE(M.select({"--target=arm-none-eabi", "-mfloat-abi=soft"}).first);
+  EXPECT_TRUE(M.select({"--target=arm-none-eabi", "-mfloat-abi=softfp"}).first);
+  EXPECT_FALSE(M.select({"--target=arm-none-eabi", "-mfloat-abi=hard"}).first);
+  EXPECT_FALSE(M.select({"--target=arm-none-eabihf"}).first);
+}
+
+TEST(Multilib2Test, SelectSoftFP) {
+  std::string O;
+  llvm::raw_string_ostream OS(O);
+  Multilib2 M;
+  ASSERT_TRUE(M.parse(R"(
+variants:
+- path: f
+  attrs: [softabi, hasfp]
+arguments:
+- regex: -mfloat-abi soft
+  matchAttrs: [softabi]
+- regex: -mfloat-abi hard
+  matchAttrs: [hardabi]
+- regex: -msoft-float
+  noMatchAttrs: [hasfp]
+)", OS));
+  EXPECT_FALSE(M.select({"--target=arm-none-eabi", "-mfloat-abi=soft"}).first);
+  EXPECT_TRUE(M.select({"--target=arm-none-eabi", "-mfloat-abi=softfp"}).first);
+  EXPECT_FALSE(M.select({"--target=arm-none-eabi", "-mfloat-abi=hard"}).first);
+  EXPECT_FALSE(M.select({"--target=arm-none-eabihf"}).first);
+}
+
+TEST(Multilib2Test, SelectHard) {
+  // If hard float is all that's available then select that only if compiling with hard float.
+  std::string O;
+  llvm::raw_string_ostream OS(O);
+  Multilib2 M;
+  ASSERT_TRUE(M.parse(R"(
+variants:
+- 

[PATCH] D139822: Allow using BareMetal toolchain with LLVM_ENABLE_PER_TARGET_RUNTIME_DIR compiler-rt

2022-12-12 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added reviewers: abidh, jroelofs.
michaelplatings added a project: clang.
Herald added subscribers: dberris, ki.stfu.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.

If you build compiler-rt with LLVM_ENABLE_PER_TARGET_RUNTIME_DIR then the 
library filename will be "libclang_rt.builtins.a" instead of 
"libclang_rt.builtins-.a"

The ToolChain::getCompilerRT method uses the "libclang_rt.builtins.a" name if 
it can find the file in the library directories. If it can't then it falls back 
to using "libclang_rt.builtins-.a". This change adds the library 
directory such that "libclang_rt.builtins.a" can be found.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D139822

Files:
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/test/Driver/baremetal.cpp


Index: clang/test/Driver/baremetal.cpp
===
--- clang/test/Driver/baremetal.cpp
+++ clang/test/Driver/baremetal.cpp
@@ -340,3 +340,27 @@
 // CHECK-RV32IMAFC-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic"
 // CHECK-RV32IMAFC-SAME: 
"-L[[SYSROOT:[^"]+]]{{[/\\]+}}rv32imafc{{[/\\]+}}ilp32f{{[/\\]+}}lib"
 // CHECK-RV32IMAFC-SAME: 
"-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}baremetal{{[/\\]+}}rv32imafc{{[/\\]+}}ilp32f"
+
+// Check that compiler-rt library without the arch filename suffix will
+// be used if present.
+// RUN: rm -rf %T/baremetal_clang_rt_noarch
+// RUN: mkdir -p %T/baremetal_clang_rt_noarch/lib
+// RUN: touch %T/baremetal_clang_rt_noarch/lib/libclang_rt.builtins.a
+// RUN: %clang %s -### 2>&1 \
+// RUN: --target=armv6m-none-eabi \
+// RUN: --sysroot=%T/baremetal_clang_rt_noarch \
+// RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-NOARCH %s
+// CHECK-CLANGRT-NOARCH: "-lclang_rt.builtins"
+// CHECK-CLANGRT-NOARCH-NOT: "-lclang_rt.builtins-armv6m"
+
+// Check that compiler-rt library with the arch filename suffix will be
+// used if present.
+// RUN: rm -rf %T/baremetal_clang_rt_arch
+// RUN: mkdir -p %T/baremetal_clang_rt_arch/lib
+// RUN: touch %T/baremetal_clang_rt_arch/lib/libclang_rt.builtins-armv6m.a
+// RUN: %clang %s -### 2>&1 \
+// RUN: --target=armv6m-none-eabi \
+// RUN: --sysroot=%T/baremetal_clang_rt_arch \
+// RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARCH %s
+// CHECK-CLANGRT-ARCH: "-lclang_rt.builtins-armv6m"
+// CHECK-CLANGRT-ARCH-NOT: "-lclang_rt.builtins"
Index: clang/lib/Driver/ToolChains/BareMetal.cpp
===
--- clang/lib/Driver/ToolChains/BareMetal.cpp
+++ clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -103,6 +103,7 @@
   if (!SysRoot.empty()) {
 llvm::sys::path::append(SysRoot, "lib");
 getFilePaths().push_back(std::string(SysRoot));
+getLibraryPaths().push_back(std::string(SysRoot));
   }
 }
 


Index: clang/test/Driver/baremetal.cpp
===
--- clang/test/Driver/baremetal.cpp
+++ clang/test/Driver/baremetal.cpp
@@ -340,3 +340,27 @@
 // CHECK-RV32IMAFC-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic"
 // CHECK-RV32IMAFC-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}rv32imafc{{[/\\]+}}ilp32f{{[/\\]+}}lib"
 // CHECK-RV32IMAFC-SAME: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}baremetal{{[/\\]+}}rv32imafc{{[/\\]+}}ilp32f"
+
+// Check that compiler-rt library without the arch filename suffix will
+// be used if present.
+// RUN: rm -rf %T/baremetal_clang_rt_noarch
+// RUN: mkdir -p %T/baremetal_clang_rt_noarch/lib
+// RUN: touch %T/baremetal_clang_rt_noarch/lib/libclang_rt.builtins.a
+// RUN: %clang %s -### 2>&1 \
+// RUN: --target=armv6m-none-eabi \
+// RUN: --sysroot=%T/baremetal_clang_rt_noarch \
+// RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-NOARCH %s
+// CHECK-CLANGRT-NOARCH: "-lclang_rt.builtins"
+// CHECK-CLANGRT-NOARCH-NOT: "-lclang_rt.builtins-armv6m"
+
+// Check that compiler-rt library with the arch filename suffix will be
+// used if present.
+// RUN: rm -rf %T/baremetal_clang_rt_arch
+// RUN: mkdir -p %T/baremetal_clang_rt_arch/lib
+// RUN: touch %T/baremetal_clang_rt_arch/lib/libclang_rt.builtins-armv6m.a
+// RUN: %clang %s -### 2>&1 \
+// RUN: --target=armv6m-none-eabi \
+// RUN: --sysroot=%T/baremetal_clang_rt_arch \
+// RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARCH %s
+// CHECK-CLANGRT-ARCH: "-lclang_rt.builtins-armv6m"
+// CHECK-CLANGRT-ARCH-NOT: "-lclang_rt.builtins"
Index: clang/lib/Driver/ToolChains/BareMetal.cpp
===
--- clang/lib/Driver/ToolChains/BareMetal.cpp
+++ clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -103,6 +103,7 @@
   if (!SysRoot.empty()) {
 llvm::sys::path::append(SysRoot, "lib");
 getFilePaths().push_back(std::string(SysRoot));
+getLibraryPaths().push_back(std::string(SysRoot));
   }
 }
 
___

[PATCH] D139822: Allow using BareMetal toolchain with LLVM_ENABLE_PER_TARGET_RUNTIME_DIR compiler-rt

2022-12-12 Thread Michael Platings via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG620d2bfdadeb: [clang] Allow using BareMetal toolchain with 
LLVM_ENABLE_PER_TARGET_RUNTIME_DIR… (authored by michaelplatings).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139822/new/

https://reviews.llvm.org/D139822

Files:
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/test/Driver/baremetal.cpp


Index: clang/test/Driver/baremetal.cpp
===
--- clang/test/Driver/baremetal.cpp
+++ clang/test/Driver/baremetal.cpp
@@ -340,3 +340,27 @@
 // CHECK-RV32IMAFC-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic"
 // CHECK-RV32IMAFC-SAME: 
"-L[[SYSROOT:[^"]+]]{{[/\\]+}}rv32imafc{{[/\\]+}}ilp32f{{[/\\]+}}lib"
 // CHECK-RV32IMAFC-SAME: 
"-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}baremetal{{[/\\]+}}rv32imafc{{[/\\]+}}ilp32f"
+
+// Check that compiler-rt library without the arch filename suffix will
+// be used if present.
+// RUN: rm -rf %T/baremetal_clang_rt_noarch
+// RUN: mkdir -p %T/baremetal_clang_rt_noarch/lib
+// RUN: touch %T/baremetal_clang_rt_noarch/lib/libclang_rt.builtins.a
+// RUN: %clang %s -### 2>&1 \
+// RUN: --target=armv6m-none-eabi \
+// RUN: --sysroot=%T/baremetal_clang_rt_noarch \
+// RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-NOARCH %s
+// CHECK-CLANGRT-NOARCH: "-lclang_rt.builtins"
+// CHECK-CLANGRT-NOARCH-NOT: "-lclang_rt.builtins-armv6m"
+
+// Check that compiler-rt library with the arch filename suffix will be
+// used if present.
+// RUN: rm -rf %T/baremetal_clang_rt_arch
+// RUN: mkdir -p %T/baremetal_clang_rt_arch/lib
+// RUN: touch %T/baremetal_clang_rt_arch/lib/libclang_rt.builtins-armv6m.a
+// RUN: %clang %s -### 2>&1 \
+// RUN: --target=armv6m-none-eabi \
+// RUN: --sysroot=%T/baremetal_clang_rt_arch \
+// RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARCH %s
+// CHECK-CLANGRT-ARCH: "-lclang_rt.builtins-armv6m"
+// CHECK-CLANGRT-ARCH-NOT: "-lclang_rt.builtins"
Index: clang/lib/Driver/ToolChains/BareMetal.cpp
===
--- clang/lib/Driver/ToolChains/BareMetal.cpp
+++ clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -103,6 +103,7 @@
   if (!SysRoot.empty()) {
 llvm::sys::path::append(SysRoot, "lib");
 getFilePaths().push_back(std::string(SysRoot));
+getLibraryPaths().push_back(std::string(SysRoot));
   }
 }
 


Index: clang/test/Driver/baremetal.cpp
===
--- clang/test/Driver/baremetal.cpp
+++ clang/test/Driver/baremetal.cpp
@@ -340,3 +340,27 @@
 // CHECK-RV32IMAFC-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic"
 // CHECK-RV32IMAFC-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}rv32imafc{{[/\\]+}}ilp32f{{[/\\]+}}lib"
 // CHECK-RV32IMAFC-SAME: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}baremetal{{[/\\]+}}rv32imafc{{[/\\]+}}ilp32f"
+
+// Check that compiler-rt library without the arch filename suffix will
+// be used if present.
+// RUN: rm -rf %T/baremetal_clang_rt_noarch
+// RUN: mkdir -p %T/baremetal_clang_rt_noarch/lib
+// RUN: touch %T/baremetal_clang_rt_noarch/lib/libclang_rt.builtins.a
+// RUN: %clang %s -### 2>&1 \
+// RUN: --target=armv6m-none-eabi \
+// RUN: --sysroot=%T/baremetal_clang_rt_noarch \
+// RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-NOARCH %s
+// CHECK-CLANGRT-NOARCH: "-lclang_rt.builtins"
+// CHECK-CLANGRT-NOARCH-NOT: "-lclang_rt.builtins-armv6m"
+
+// Check that compiler-rt library with the arch filename suffix will be
+// used if present.
+// RUN: rm -rf %T/baremetal_clang_rt_arch
+// RUN: mkdir -p %T/baremetal_clang_rt_arch/lib
+// RUN: touch %T/baremetal_clang_rt_arch/lib/libclang_rt.builtins-armv6m.a
+// RUN: %clang %s -### 2>&1 \
+// RUN: --target=armv6m-none-eabi \
+// RUN: --sysroot=%T/baremetal_clang_rt_arch \
+// RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARCH %s
+// CHECK-CLANGRT-ARCH: "-lclang_rt.builtins-armv6m"
+// CHECK-CLANGRT-ARCH-NOT: "-lclang_rt.builtins"
Index: clang/lib/Driver/ToolChains/BareMetal.cpp
===
--- clang/lib/Driver/ToolChains/BareMetal.cpp
+++ clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -103,6 +103,7 @@
   if (!SysRoot.empty()) {
 llvm::sys::path::append(SysRoot, "lib");
 getFilePaths().push_back(std::string(SysRoot));
+getLibraryPaths().push_back(std::string(SysRoot));
   }
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D140959: RFC: Multilib prototype

2023-01-20 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

A constraint is that the user should be able to choose the library with a 
single list of arguments, as displayed with `-print-multi-lib`. Therefore I'm 
sceptical about making the selection mechanism too expressive, because 
`-print-multi-lib` can't explain that to the user. Already the presence of 
negation is stretching that.

Nevertheless let's pick an example of something that can't be directly 
expressed in the prototype: `NOT (a AND b)`. (I don't know why you'd want to do 
that, if you have a motivating example of something genuinely useful then that 
would be better)

The expression can be rearranged to `(a AND NOT b) OR (b AND NOT a) OR ((NOT a) 
AND NOT b)` which can be represented in an ugly way:

  variants:
  - path: p
args: [-a]
attrs: [a, not-b]
  - path: p
args: [-b]
attrs: [not-a, b]
  - path: p
args: []
attrs: [not-a, not-b]
  arguments:
  - regex: -a
matchAttrs: [a]
noMatchAttrs: [not-a]
  - regex: -b
matchAttrs: [b]
noMatchAttrs: [not-b]

I think this fits with the spirit of "Make the easy things easy, and the hard 
things possible."

> perhaps it's enough to just make sure there's extension room in the syntax so 
> that this can be added later

One of the many nice things about JSON & YAML is it gives you loads of room for 
extension, so yes. For example, currently `attrs` must be an array, but the 
option could be added later that it could be an object like `attrs: {not: [a, 
b]}`. But I hope it doesn't prove necessary ;)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D140959/new/

https://reviews.llvm.org/D140959

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D140959: RFC: Multilib prototype

2023-01-25 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

How the multilib system matches user arguments is the main problem I've been 
struggling with.

These are the options I see:

1. Grant the multilib system full access to all cc1 arguments, as demonstrated 
by the current code. However declare the multilib system unstable - if you 
write a multilib specification, you are responsible for making sure it's 
updated when clang is updated. Clang plugins set the precedent for such an 
approach.

  Advantage: It's powerful.

  Disadvantages:
  - Experience with clang plugins suggests instability will be a source of 
frequent pain.
  - @lenary points out that the order of arguments can be significant.
  - Requires some major refactoring of how arguments are processed before this 
can be done in a robust way (how I implemented it in the prototype is far from 
robust).

2. Pass to the multilib system only the arguments as provided by the user.

  Advantage: Greatly reduced API surface.

  Disadvantage: whoever writes a multilib specification will have to reinvent a 
lot of logic to infer attributes from --target, -march, -mcpu etc. but with 
inadequate tools to do so.

3. Normalise user arguments before passing them to the multilib system.

  Advantages:
  - Uses the existing arguments API.
  - Powerful, if it can be done correctly.

Disadvantage:
  - The normalisation process effectively becomes a new API.
  - Normalisation appears hard to do correctly = likelihood of bugs.
  - Identifying attributes from arguments is fiddly e.g. extracting Arm 
architecture extensions from the march argument.
  - It's too easy to write a regex that could unintentionally match a newly 
introduced argument so the instability problem remains somewhat.

4. Hard-code the attributes and how they are detected in the same way they 
already are right now. For Arm this could be extended with Function Multi 
Versioning as @lenary pointed to, with namespacing to avoid potential clashes 
with other names. So you could have attributes like `[fsanitize=address, 
fno-exceptions, mfloat-abi=softfp, march=thumbv8.1m.main, arm:mve]`.

  Advantages:
  - This is similar to what we already do for multilib so it's well understood.
  - Limited yet extensible API.

Disadvantages:
  - Greatly limits the expressiveness of the multilib system.
  - Any time someone wants to base their multilib on a new attribute it 
requires a change to Clang.
  - Some regular expressions still required for forward compatibility e.g. with 
future versions of Armv8-M.

5. A combination of (1) and (4) as proposed by @lenary.

  Advantages:
  - Stability where predefined attributes are available.
  - The power to access unstable arguments if necessary.

Disadvantages:
  - Same as for (1) - requires some major refactoring of how arguments are 
processed before this can be done in a robust way (how I implemented it in the 
prototype is far from robust).
  - Greater maintenance burden.

None of these options are great but (4) is low risk and extensible so I'm 
currently investigating that.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D140959/new/

https://reviews.llvm.org/D140959

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D142878: Add testing for Fuchsia multilib

2023-01-30 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added a reviewer: phosek.
Herald added a subscriber: abrachet.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

The plan is to change how multilib works under the hood and this test gives 
confidence that the changes won't break user-visible behaviour.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142878

Files:
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/Fuchsia.h
  clang/unittests/Driver/CMakeLists.txt
  clang/unittests/Driver/FuchsiaTest.cpp

Index: clang/unittests/Driver/FuchsiaTest.cpp
===
--- /dev/null
+++ clang/unittests/Driver/FuchsiaTest.cpp
@@ -0,0 +1,80 @@
+//===- unittests/Driver/FuchsiaTest.cpp --- Fuchsia tests ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// Unit tests for Fuchsia
+//
+//===--===//
+
+#include "../../lib/Driver/ToolChains/Fuchsia.h"
+#include "gtest/gtest.h"
+
+using namespace clang::driver;
+
+/*
+This test was added prior to changing the behaviour of Multilib.
+The way that Fuchsia used Multilib made it very likely that the change
+would cause it to break so by adding this exhaustive test we avoid that
+possibility.
+*/
+TEST(FuchsiaTest, MultilibVariant) {
+  MultilibSet Multilibs;
+  toolchains::Fuchsia::configureMultilibs(Multilibs);
+
+  std::string Actual;
+
+  for (bool Itanium : {false, true}) {
+for (bool RelativeVtables : {false, true}) {
+  for (bool Hwasan : {false, true}) {
+for (bool Asan : {false, true}) {
+  for (bool Exceptions : {false, true}) {
+Multilib::flags_list Flags;
+toolchains::Fuchsia::configureMultilibFlags(
+Flags, Exceptions, Asan, Hwasan, RelativeVtables, Itanium);
+Multilib Selected;
+EXPECT_TRUE(Multilibs.select(Flags, Selected));
+Actual += Selected.gccSuffix() + "\n";
+  }
+}
+  }
+}
+  }
+  std::string Expected = R"(/noexcept
+
+/asan+noexcept
+/asan
+/hwasan+noexcept
+/hwasan
+/hwasan+noexcept
+/hwasan
+/relative-vtables+noexcept
+/relative-vtables
+/relative-vtables+asan+noexcept
+/relative-vtables+asan
+/relative-vtables+hwasan+noexcept
+/relative-vtables+hwasan
+/relative-vtables+hwasan+noexcept
+/relative-vtables+hwasan
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+)";
+  EXPECT_EQ(Expected, Actual);
+}
Index: clang/unittests/Driver/CMakeLists.txt
===
--- clang/unittests/Driver/CMakeLists.txt
+++ clang/unittests/Driver/CMakeLists.txt
@@ -9,6 +9,7 @@
 add_clang_unittest(ClangDriverTests
   DistroTest.cpp
   DXCModeTest.cpp
+  FuchsiaTest.cpp
   ToolChainTest.cpp
   ModuleCacheTest.cpp
   MultilibTest.cpp
Index: clang/lib/Driver/ToolChains/Fuchsia.h
===
--- clang/lib/Driver/ToolChains/Fuchsia.h
+++ clang/lib/Driver/ToolChains/Fuchsia.h
@@ -98,6 +98,11 @@
 
   const char *getDefaultLinker() const override { return "ld.lld"; }
 
+  static void configureMultilibs(MultilibSet &);
+  static void configureMultilibFlags(Multilib::flags_list &, bool Exceptions,
+ bool Asan, bool Hwasan,
+ bool RelativeVtables, bool Itanium);
+
 protected:
   Tool *buildLinker() const override;
 };
Index: clang/lib/Driver/ToolChains/Fuchsia.cpp
===
--- clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -215,6 +215,35 @@
 return FP;
   };
 
+  configureMultilibs(Multilibs);
+
+  Multilibs.FilterOut([&](const Multilib ) {
+std::vector RD = FilePaths(M);
+return llvm::all_of(RD, [&](std::string P) { return !getVFS().exists(P); });
+  });
+
+  Multilib::flags_list Flags;
+  configureMultilibFlags(
+  Flags,
+  Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true),
+  getSanitizerArgs(Args).needsAsanRt(),
+  getSanitizerArgs(Args).needsHwasanRt(),
+  Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables,
+   options::OPT_fno_experimental_relative_cxx_abi_vtables,
+   false),
+  Args.getLastArgValue(options::OPT_fcxx_abi_EQ) == "itanium");
+
+  Multilibs.setFilePathsCallback(FilePaths);
+
+  if (Multilibs.select(Flags, SelectedMultilib))
+if 

[PATCH] D142893: Class for building MultilibSet

2023-01-30 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added a reviewer: phosek.
Herald added a subscriber: abrachet.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

The functionality in MultilibSet for creating it is tied to its current
implementation. Putting that code in a separate class is an enabler for
changing the MultilibSet implementation.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142893

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/MultilibBuilder.h
  clang/lib/Driver/CMakeLists.txt
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/MultilibBuilder.cpp
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/unittests/Driver/CMakeLists.txt
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -11,34 +11,17 @@
 //===--===//
 
 #include "clang/Driver/Multilib.h"
+#include "../../lib/Driver/ToolChains/CommonArgs.h"
 #include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
 
 using namespace clang::driver;
 using namespace clang;
 
-TEST(MultilibTest, MultilibValidity) {
-
-  ASSERT_TRUE(Multilib().isValid()) << "Empty multilib is not valid";
-
-  ASSERT_TRUE(Multilib().flag("+foo").isValid())
-  << "Single indicative flag is not valid";
-
-  ASSERT_TRUE(Multilib().flag("-foo").isValid())
-  << "Single contraindicative flag is not valid";
-
-  ASSERT_FALSE(Multilib().flag("+foo").flag("-foo").isValid())
-  << "Conflicting flags should invalidate the Multilib";
-
-  ASSERT_TRUE(Multilib().flag("+foo").flag("+foo").isValid())
-  << "Multilib should be valid even if it has the same flag twice";
-
-  ASSERT_TRUE(Multilib().flag("+foo").flag("-foobar").isValid())
-  << "Seemingly conflicting prefixes shouldn't actually conflict";
-}
-
 TEST(MultilibTest, OpEqReflexivity1) {
   Multilib M;
   ASSERT_TRUE(M == M) << "Multilib::operator==() is not reflexive";
@@ -50,40 +33,28 @@
 }
 
 TEST(MultilibTest, OpEqReflexivity3) {
-  Multilib M1, M2;
-  M1.flag("+foo");
-  M2.flag("+foo");
+  Multilib M1({}, {}, {}, 0, {"+foo"});
+  Multilib M2({}, {}, {}, 0, {"+foo"});
   ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same";
 }
 
 TEST(MultilibTest, OpEqInequivalence1) {
-  Multilib M1, M2;
-  M1.flag("+foo");
-  M2.flag("-foo");
+  Multilib M1({}, {}, {}, 0, {"+foo"});
+  Multilib M2({}, {}, {}, 0, {"-foo"});
   ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same";
   ASSERT_FALSE(M2 == M1)
   << "Multilibs with conflicting flags are not the same (commuted)";
 }
 
 TEST(MultilibTest, OpEqInequivalence2) {
-  Multilib M1, M2;
-  M2.flag("+foo");
+  Multilib M1;
+  Multilib M2({}, {}, {}, 0, {"+foo"});
   ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different";
 }
 
-TEST(MultilibTest, OpEqEquivalence1) {
-  Multilib M1, M2;
-  M1.flag("+foo");
-  M2.flag("+foo").flag("+foo");
-  ASSERT_TRUE(M1 == M2) << "Flag duplication shouldn't affect equivalence";
-  ASSERT_TRUE(M2 == M1)
-  << "Flag duplication shouldn't affect equivalence (commuted)";
-}
-
 TEST(MultilibTest, OpEqEquivalence2) {
-  Multilib M1("64");
-  Multilib M2;
-  M2.gccSuffix("/64");
+  Multilib M1("/64");
+  Multilib M2("/64");
   ASSERT_TRUE(M1 == M2)
   << "Constructor argument must match Multilib::gccSuffix()";
   ASSERT_TRUE(M2 == M1)
@@ -91,9 +62,8 @@
 }
 
 TEST(MultilibTest, OpEqEquivalence3) {
-  Multilib M1("", "32");
-  Multilib M2;
-  M2.osSuffix("/32");
+  Multilib M1("", "/32");
+  Multilib M2("", "/32");
   ASSERT_TRUE(M1 == M2)
   << "Constructor argument must match Multilib::osSuffix()";
   ASSERT_TRUE(M2 == M1)
@@ -101,9 +71,8 @@
 }
 
 TEST(MultilibTest, OpEqEquivalence4) {
-  Multilib M1("", "", "16");
-  Multilib M2;
-  M2.includeSuffix("/16");
+  Multilib M1("", "", "/16");
+  Multilib M2("", "", "/16");
   ASSERT_TRUE(M1 == M2)
   << "Constructor argument must match Multilib::includeSuffix()";
   ASSERT_TRUE(M2 == M1)
@@ -111,31 +80,31 @@
 }
 
 TEST(MultilibTest, OpEqInequivalence3) {
-  Multilib M1("foo");
-  Multilib M2("bar");
+  Multilib M1("/foo");
+  Multilib M2("/bar");
   ASSERT_FALSE(M1 == M2) << "Differing gccSuffixes should be different";
   ASSERT_FALSE(M2 == M1)
   << "Differing gccSuffixes should be different (commuted)";
 }
 
 TEST(MultilibTest, OpEqInequivalence4) {
-  Multilib M1("", "foo");
-  Multilib M2("", "bar");
+  Multilib M1("", 

[PATCH] D142878: Add testing for Fuchsia multilib

2023-01-30 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 493244.
michaelplatings added a comment.

Update commit message and run arc with clang-format on the PATH


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142878/new/

https://reviews.llvm.org/D142878

Files:
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/Fuchsia.h
  clang/unittests/Driver/CMakeLists.txt
  clang/unittests/Driver/FuchsiaTest.cpp

Index: clang/unittests/Driver/FuchsiaTest.cpp
===
--- /dev/null
+++ clang/unittests/Driver/FuchsiaTest.cpp
@@ -0,0 +1,80 @@
+//===- unittests/Driver/FuchsiaTest.cpp --- Fuchsia tests ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+// Unit tests for Fuchsia
+//
+//===--===//
+
+#include "../../lib/Driver/ToolChains/Fuchsia.h"
+#include "gtest/gtest.h"
+
+using namespace clang::driver;
+
+/*
+This test was added prior to changing the behaviour of Multilib.
+The way that Fuchsia used Multilib made it very likely that the change
+would cause it to break so by adding this exhaustive test we avoid that
+possibility.
+*/
+TEST(FuchsiaTest, MultilibVariant) {
+  MultilibSet Multilibs;
+  toolchains::Fuchsia::configureMultilibs(Multilibs);
+
+  std::string Actual;
+
+  for (bool Itanium : {false, true}) {
+for (bool RelativeVtables : {false, true}) {
+  for (bool Hwasan : {false, true}) {
+for (bool Asan : {false, true}) {
+  for (bool Exceptions : {false, true}) {
+Multilib::flags_list Flags;
+toolchains::Fuchsia::configureMultilibFlags(
+Flags, Exceptions, Asan, Hwasan, RelativeVtables, Itanium);
+Multilib Selected;
+EXPECT_TRUE(Multilibs.select(Flags, Selected));
+Actual += Selected.gccSuffix() + "\n";
+  }
+}
+  }
+}
+  }
+  std::string Expected = R"(/noexcept
+
+/asan+noexcept
+/asan
+/hwasan+noexcept
+/hwasan
+/hwasan+noexcept
+/hwasan
+/relative-vtables+noexcept
+/relative-vtables
+/relative-vtables+asan+noexcept
+/relative-vtables+asan
+/relative-vtables+hwasan+noexcept
+/relative-vtables+hwasan
+/relative-vtables+hwasan+noexcept
+/relative-vtables+hwasan
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+/compat
+)";
+  EXPECT_EQ(Expected, Actual);
+}
Index: clang/unittests/Driver/CMakeLists.txt
===
--- clang/unittests/Driver/CMakeLists.txt
+++ clang/unittests/Driver/CMakeLists.txt
@@ -9,6 +9,7 @@
 add_clang_unittest(ClangDriverTests
   DistroTest.cpp
   DXCModeTest.cpp
+  FuchsiaTest.cpp
   ToolChainTest.cpp
   ModuleCacheTest.cpp
   MultilibTest.cpp
Index: clang/lib/Driver/ToolChains/Fuchsia.h
===
--- clang/lib/Driver/ToolChains/Fuchsia.h
+++ clang/lib/Driver/ToolChains/Fuchsia.h
@@ -98,6 +98,11 @@
 
   const char *getDefaultLinker() const override { return "ld.lld"; }
 
+  static void configureMultilibs(MultilibSet &);
+  static void configureMultilibFlags(Multilib::flags_list &, bool Exceptions,
+ bool Asan, bool Hwasan,
+ bool RelativeVtables, bool Itanium);
+
 protected:
   Tool *buildLinker() const override;
 };
Index: clang/lib/Driver/ToolChains/Fuchsia.cpp
===
--- clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -215,6 +215,35 @@
 return FP;
   };
 
+  configureMultilibs(Multilibs);
+
+  Multilibs.FilterOut([&](const Multilib ) {
+std::vector RD = FilePaths(M);
+return llvm::all_of(RD, [&](std::string P) { return !getVFS().exists(P); });
+  });
+
+  Multilib::flags_list Flags;
+  configureMultilibFlags(
+  Flags,
+  Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, true),
+  getSanitizerArgs(Args).needsAsanRt(),
+  getSanitizerArgs(Args).needsHwasanRt(),
+  Args.hasFlag(options::OPT_fexperimental_relative_cxx_abi_vtables,
+   options::OPT_fno_experimental_relative_cxx_abi_vtables,
+   false),
+  Args.getLastArgValue(options::OPT_fcxx_abi_EQ) == "itanium");
+
+  Multilibs.setFilePathsCallback(FilePaths);
+
+  if (Multilibs.select(Flags, SelectedMultilib))
+if (!SelectedMultilib.isDefault())
+  if (const auto  = Multilibs.filePathsCallback())
+for (const auto  : PathsCallback(SelectedMultilib))
+  // Prepend the multilib path to ensure 

[PATCH] D142905: Change multilib selection algorithm

2023-01-30 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added a reviewer: phosek.
Herald added subscribers: abrachet, mgrang.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

The new algorithm is:

1. Find all multilibs with flags that are a subset of the requested flags.
2. If more than one multilib matches, choose the last.

In addition a new selection mechanism is permitted, for which multiple
multilibs are returned. This allows layering multilibs on top of each
other.

Since multilibs are now ordered within a list, they no longer need a
Priority field.

The new algorithm is different to the old algorithm, but in practise
the old algorithm was always used in such a way that the effect is the
same.
The old algorithm was to find the set intersection of the requested
flags (with the first character of each removed) with each multilib's
flags (ditto), and for that intersection check whether the first
character matched. However, ignoring the first characters, the
requested flags were always a superset of all the multilibs flags.
Therefore the new algorithm can be used as a drop-in replacement.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142905

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/MultilibBuilder.h
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/MultilibBuilder.cpp
  clang/lib/Driver/ToolChains/CommonArgs.cpp
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -33,14 +33,14 @@
 }
 
 TEST(MultilibTest, OpEqReflexivity3) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same";
 }
 
 TEST(MultilibTest, OpEqInequivalence1) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"-foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"-foo"});
   ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same";
   ASSERT_FALSE(M2 == M1)
   << "Multilibs with conflicting flags are not the same (commuted)";
@@ -48,7 +48,7 @@
 
 TEST(MultilibTest, OpEqInequivalence2) {
   Multilib M1;
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different";
 }
 
@@ -124,7 +124,7 @@
 }
 
 TEST(MultilibTest, Construction3) {
-  Multilib M({}, {}, {}, 0, {"+f1", "+f2", "-f3"});
+  Multilib M({}, {}, {}, {"+f1", "+f2", "-f3"});
   for (Multilib::flags_list::const_iterator I = M.flags().begin(),
 E = M.flags().end();
I != E; ++I) {
@@ -149,8 +149,8 @@
 
 TEST(MultilibTest, SetPriority) {
   MultilibSet MS({
-  Multilib("/foo", {}, {}, 1, {"+foo"}),
-  Multilib("/bar", {}, {}, 2, {"+bar"}),
+  Multilib("/foo", {}, {}, {"+foo"}),
+  Multilib("/bar", {}, {}, {"+bar"}),
   });
   Multilib::flags_list Flags1 = {"+foo", "-bar"};
   Multilib Selection1;
@@ -166,3 +166,24 @@
   ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
   << "Selection picked " << Selection2 << " which was not expected";
 }
+
+TEST(MultilibTest, SelectMultiple) {
+  MultilibSet MS({
+  Multilib("/a", {}, {}, {"x"}),
+  Multilib("/b", {}, {}, {"y"}),
+  });
+  std::vector Selection;
+
+  Selection = MS.select({"x"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/b", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y", "x"});
+  ASSERT_EQ(2u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+  EXPECT_EQ("/b", Selection[1].gccSuffix());
+}
Index: clang/unittests/Driver/MultilibBuilderTest.cpp
===
--- clang/unittests/Driver/MultilibBuilderTest.cpp
+++ clang/unittests/Driver/MultilibBuilderTest.cpp
@@ -7,7 +7,7 @@
 //
 //===--===//
 //
-// Unit tests for Multilib and MultilibBuilder
+// Unit tests for MultilibBuilderVariant and MultilibBuilder
 //
 //===--===//
 
@@ -185,14 +185,14 @@
 bool IsSF = I & 0x2;
 Multilib::flags_list Flags;
 if (IsEL)
-  Flags.push_back("+EL");
+  Flags.insert("+EL");
 else
-  Flags.push_back("-EL");
+  Flags.insert("-EL");
 
 if (IsSF)
-  Flags.push_back("+SF");
+  Flags.insert("+SF");
 else
-  

[PATCH] D142933: Add -print-multi-selection-flags argument

2023-01-30 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added reviewers: phosek, lenary, simon_tatham.
Herald added subscribers: abrachet, mgrang.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142933

Files:
  clang/include/clang/Driver/Options.td
  clang/include/clang/Driver/ToolChain.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/test/Driver/print-multi-selection-flags.c

Index: clang/test/Driver/print-multi-selection-flags.c
===
--- /dev/null
+++ clang/test/Driver/print-multi-selection-flags.c
@@ -0,0 +1,41 @@
+// RUN: %clang -print-multi-selection-flags --target=aarch64-linux -fc++-abi=itanium -fsanitize=address | FileCheck --check-prefix=CHECK-LINUX %s
+// CHECK-LINUX: fc++-abi=itanium
+// CHECK-LINUX-NEXT: fexceptions
+// CHECK-LINUX-NEXT: fno-experimental-relative-c++-abi-vtables
+// CHECK-LINUX-NEXT: frtti
+// CHECK-LINUX-NEXT: fsanitize=address
+// CHECK-LINUX-NEXT: target=aarch64-unknown-linux
+
+// RUN: %clang -print-multi-selection-flags --target=aarch64-fuchsia -fsanitize=hwaddress | FileCheck --check-prefix=CHECK-FUCHSIA %s
+// CHECK-FUCHSIA: fexperimental-relative-c++-abi-vtables
+// CHECK-FUCHSIA: fsanitize=hwaddress
+// CHECK-FUCHSIA: target=aarch64-unknown-fuchsia
+
+// RUN: %clang -print-multi-selection-flags --target=arm-none-eabi -mfloat-abi=soft -fno-exceptions -fno-rtti | FileCheck --check-prefix=CHECK-ARMV4T %s
+// CHECK-ARMV4T: fno-exceptions
+// CHECK-ARMV4T: fno-rtti
+// CHECK-ARMV4T: mfloat-abi=soft
+// CHECK-ARMV4T: mfpu=none
+// CHECK-ARMV4T: target=armv4t-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags --target=armv7em-none-eabi -mfloat-abi=softfp | FileCheck --check-prefix=CHECK-SOFTFP %s
+// CHECK-SOFTFP: mfloat-abi=softfp
+// CHECK-SOFTFP: mfpu=fpv4-sp-d16
+// CHECK-SOFTFP: target=thumbv7em-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags --target=arm-none-eabihf -march=armv7em -mfpu=fpv5-d16 | FileCheck --check-prefix=CHECK-HARD %s
+// CHECK-HARD: mfloat-abi=hard
+// CHECK-HARD: mfpu=fpv5-d16
+// CHECK-HARD: target=thumbv7em-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-flags --target=arm-none-eabi -mfloat-abi=hard -march=armv8.1m.main+mve.fp | FileCheck --check-prefix=CHECK-MVE %s
+// CHECK-MVE: march=+mve
+// CHECK-MVE: march=+mve.fp
+// CHECK-MVE: mfloat-abi=hard
+// CHECK-MVE: mfpu=fp-armv8-fullfp16-sp-d16
+// CHECK-MVE: target=thumbv8.1m.main-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-flags --target=arm-none-eabi -march=armv8.1m.main+mve+nofp | FileCheck --check-prefix=CHECK-MVENOFP %s
+// CHECK-MVENOFP: march=+mve
+// CHECK-MVENOFP-NOT: march=+mve.fp
+// CHECK-MVENOFP: mfpu=none
Index: clang/lib/Driver/ToolChains/Arch/ARM.h
===
--- clang/lib/Driver/ToolChains/Arch/ARM.h
+++ clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -64,9 +64,11 @@
 void getARMArchCPUFromArgs(const llvm::opt::ArgList ,
llvm::StringRef , llvm::StringRef ,
bool FromAs = false);
+// Optionally returns the FPUKind
 void getARMTargetFeatures(const Driver , const llvm::Triple ,
   const llvm::opt::ArgList ,
-  std::vector , bool ForAS);
+  std::vector , bool ForAS,
+  unsigned *OutFPUKind = nullptr);
 int getARMSubArchVersionNumber(const llvm::Triple );
 bool isARMMProfile(const llvm::Triple );
 bool isARMAProfile(const llvm::Triple );
Index: clang/lib/Driver/ToolChains/Arch/ARM.cpp
===
--- clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -438,7 +438,8 @@
 
 void arm::getARMTargetFeatures(const Driver , const llvm::Triple ,
const ArgList ,
-   std::vector , bool ForAS) {
+   std::vector , bool ForAS,
+   unsigned *OutFPUKind) {
   bool KernelOrKext =
   Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext);
   arm::FloatABI ABI = arm::getARMFloatABI(D, Triple, Args);
@@ -643,6 +644,7 @@
 {"-dotprod", "-fp16fml", "-bf16", "-mve.fp"});
 if (!hasIntegerMVE(Features))
   Features.emplace_back("-fpregs");
+FPUID = llvm::ARM::FK_NONE;
   }
 
   // En/disable crc code generation.
@@ -899,6 +901,10 @@
 
   if (Args.getLastArg(options::OPT_mno_bti_at_return_twice))
 Features.push_back("+no-bti-at-return-twice");
+
+  if (OutFPUKind) {
+*OutFPUKind = FPUID;
+  }
 }
 
 std::string arm::getARMArch(StringRef Arch, const 

[PATCH] D142932: Multilib YAML parsing

2023-01-30 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added a reviewer: phosek.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142932

Files:
  clang/include/clang/Driver/Multilib.h
  clang/lib/Driver/Multilib.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -187,3 +187,347 @@
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
 }
+
+static void diagnosticCallback(const llvm::SMDiagnostic , void *Out) {
+  *reinterpret_cast(Out) = D.getMessage();
+}
+
+static bool parse(MultilibSet , MultilibFlagMap ,
+  std::string , const char *Data) {
+  return MS.parse(llvm::MemoryBufferRef(Data, "TEST"), MFM, diagnosticCallback,
+  );
+}
+
+static bool parse(MultilibSet , MultilibFlagMap , const char *Data) {
+  return MS.parse(llvm::MemoryBufferRef(Data, "TEST"), MFM);
+}
+
+TEST(MultilibTest, ParseInvalid) {
+  std::string Diagnostic;
+
+  MultilibSet MS;
+  MultilibFlagMap MFM;
+  EXPECT_FALSE(parse(MS, MFM, Diagnostic, R"(
+variants:
+- dir: /abc
+  flags: []
+  printArgs: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("paths must be relative"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, MFM, Diagnostic, R"(
+variants:
+- flags: []
+  printArgs: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'dir'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, MFM, Diagnostic, R"(
+variants:
+- dir: .
+  printArgs: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'flags'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, MFM, Diagnostic, R"(
+variants:
+- dir: .
+  flags: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("missing required key 'printArgs'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, MFM, Diagnostic, R"(
+flagMap:
+- regex: abc
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic)
+  .contains("value required for 'matchFlags' or 'noMatchFlags'"))
+  << Diagnostic;
+}
+
+TEST(MultilibTest, Parse) {
+  MultilibSet MS;
+  MultilibFlagMap MFM;
+  EXPECT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: .
+  flags: []
+  printArgs: []
+)"));
+  EXPECT_EQ(1U, MS.size());
+  EXPECT_EQ("", MS.begin()->gccSuffix());
+
+  EXPECT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: abc
+  flags: []
+  printArgs: []
+)"));
+  EXPECT_EQ(1U, MS.size());
+  EXPECT_EQ("/abc", MS.begin()->gccSuffix());
+
+  EXPECT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: pqr
+  flags: []
+  printArgs: [-mfloat-abi=soft]
+)"));
+  EXPECT_EQ(1U, MS.size());
+  EXPECT_EQ("/pqr", MS.begin()->gccSuffix());
+  EXPECT_EQ(std::vector({"-mfloat-abi=soft"}),
+MS.begin()->getPrintArgs());
+
+  EXPECT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: pqr
+  flags: []
+  printArgs: [-mfloat-abi=soft, -fno-exceptions]
+)"));
+  EXPECT_EQ(1U, MS.size());
+  EXPECT_EQ(std::vector({"-mfloat-abi=soft", "-fno-exceptions"}),
+MS.begin()->getPrintArgs());
+
+  EXPECT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: a
+  flags: []
+  printArgs: []
+- dir: b
+  flags: []
+  printArgs: []
+)"));
+  EXPECT_EQ(2U, MS.size());
+}
+
+static bool select(const std::vector ,
+   const MultilibSet , const MultilibFlagMap ,
+   Multilib ) {
+  Multilib::flags_list Flags(MFM.getFlags(InFlags));
+  Flags.insert(InFlags.begin(), InFlags.end());
+  return MS.select(Flags, Selected);
+}
+
+TEST(MultilibTest, SelectSoft) {
+  MultilibSet MS;
+  MultilibFlagMap MFM;
+  Multilib Selected;
+  ASSERT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: s
+  flags: [softabi]
+  printArgs: []
+flagMap:
+- regex: mfloat-abi=soft
+  matchFlags: [softabi]
+- regex: mfloat-abi=softfp
+  matchFlags: [softabi]
+)"));
+  EXPECT_TRUE(select({"mfloat-abi=soft"}, MS, MFM, Selected));
+  EXPECT_TRUE(select({"mfloat-abi=softfp"}, MS, MFM, Selected));
+  EXPECT_FALSE(select({"mfloat-abi=hard"}, MS, MFM, Selected));
+}
+
+TEST(MultilibTest, SelectSoftFP) {
+  MultilibSet MS;
+  MultilibFlagMap MFM;
+  Multilib Selected;
+  ASSERT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: f
+  flags: [mfloat-abi=softfp]
+  printArgs: []
+)"));
+  EXPECT_FALSE(select({"mfloat-abi=soft"}, MS, MFM, Selected));
+  EXPECT_TRUE(select({"mfloat-abi=softfp"}, MS, MFM, Selected));
+  EXPECT_FALSE(select({"mfloat-abi=hard"}, MS, MFM, Selected));
+}
+
+TEST(MultilibTest, SelectHard) {
+  // If hard float is all that's available then select that only if compiling
+  // with hard float.
+  MultilibSet MS;
+  MultilibFlagMap MFM;
+  Multilib Selected;
+  ASSERT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: h
+  flags: [mfloat-abi=hard]
+  printArgs: []
+)"));
+  

[PATCH] D140959: RFC: Multilib prototype

2023-01-05 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added inline comments.



Comment at: clang/include/clang/Driver/Multilib2.h:33-34
+private:
+  std::vector, 
std::vector>> Multilibs;
+  std::vector, 
std::vector>> RegexAttributes;
+};

phosek wrote:
> I think it'd really help readability and comprehension if this was modeled 
> using types (that is `struct`s and `class`es). It's not at all clear what 
> these strings are supposed to represent, and seeing expressions like 
> `std::get<0>` doesn't help either.
I fully agree. Sorry if I wasn't clear in the RFC but this is the kind of thing 
I meant when I said the code is not intended to be production quality.



Comment at: 
clang/test/Driver/Inputs/baremetal_multilib/arm-none-eabi/multilib.yaml:24
+- path: thumb/v6-m/nofp
+  args: [--target=arm-none-eabi, -mfloat-abi=soft, -march=armv6m]
+  attrs: [thumb, soft, v6m]

phosek wrote:
> I understand how the second section is used to match arguments passed to 
> `clang -cc1` and turn those into attributes which are then used to find the 
> right variant, but I don't understand what this list of arguments is used for?
Having these here permits `clang -print-multi-lib` to work, which would print 
out something like this:
```
thumb/nofp;@mthumb@mfloat-abi=soft
thumb/v7/nofp;@mthumb@march=armv7@mfloat-abi=soft
...
```


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D140959/new/

https://reviews.llvm.org/D140959

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D142986: Enable multilib.yaml in the BareMetal ToolChain

2023-01-31 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added a reviewer: phosek.
Herald added subscribers: abidh, kristof.beyls.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

The default location for multilib.yaml is lib/clang-runtimes, without
any target-specific suffix. This will allow multilibs for different
architectures to share a common include directory.

To avoid breaking the arm-execute-only.c CHECK-NO-EXECUTE-ONLY-ASM
test, add a GetExecuteOnly argument to getARMTargetFeatures.

Since the presence of multilib.yaml can change the exact location of a
library, relax the baremetal.cpp test.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142986

Files:
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/test/Driver/Inputs/baremetal_multilib/multilib.yaml
  clang/test/Driver/baremetal-multilib.cpp
  clang/test/Driver/baremetal.cpp

Index: clang/test/Driver/baremetal.cpp
===
--- clang/test/Driver/baremetal.cpp
+++ clang/test/Driver/baremetal.cpp
@@ -118,9 +118,9 @@
 // Verify that the bare metal driver does not include any host system paths:
 // CHECK-AARCH64-NO-HOST-INC: InstalledDir: [[INSTALLEDDIR:.+]]
 // CHECK-AARCH64-NO-HOST-INC: "-resource-dir" "[[RESOURCE:[^"]+]]"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include{{[/\\]+}}c++{{[/\\]+}}v1"
 // CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[RESOURCE]]{{[/\\]+}}include"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include"
 
 // RUN: %clang %s -### --target=riscv64-unknown-elf -o %t.out -L some/directory/user/asked/for \
 // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf 2>&1 \
Index: clang/test/Driver/baremetal-multilib.cpp
===
--- /dev/null
+++ clang/test/Driver/baremetal-multilib.cpp
@@ -0,0 +1,45 @@
+// REQUIRES: shell
+// UNSUPPORTED: system-windows
+
+// RUN: rm -rf %T/baremetal_multilib
+// RUN: mkdir -p %T/baremetal_multilib/bin
+// RUN: mkdir -p %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib
+// RUN: touch %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib/libclang_rt.builtins.a
+// RUN: ln -s %clang %T/baremetal_multilib/bin/clang
+// RUN: ln -s %S/Inputs/baremetal_multilib/multilib.yaml %T/baremetal_multilib/lib/clang-runtimes/multilib.yaml
+
+// RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+// RUN:   | FileCheck %s
+// CHECK: "{{.*}}clang{{.*}}" "-cc1" "-triple" "thumbv8m.main-none-unknown-eabihf"
+// CHECK-SAME: "-internal-isystem" "{{.*}}/baremetal_multilib/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include/c++/v1"
+// CHECK-SAME: "-internal-isystem" "{{.*}}/baremetal_multilib/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include"
+// CHECK-SAME: "-x" "c++" "{{.*}}/baremetal-multilib.cpp"
+// CHECK-NEXT: "{{[^"]*}}ld{{(\.(lld|bfd|gold))?}}{{(\.exe)?}}" "{{.*}}.o" "-Bstatic"
+// CHECK-SAME: "-L{{.*}}/baremetal_multilib/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib"
+// CHECK-SAME: "-lc" "-lm" "-lclang_rt.builtins"
+// CHECK-SAME: "-o" "{{.*}}.o"
+
+// RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+// RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+// RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY %s
+// CHECK-PRINT-MULTI-DIRECTORY: arm-none-eabi/thumb/v8-m.main/fp
+
+// RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
+// RUN: --target=arm-none-eabi --sysroot= \
+// RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
+// CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v6-m/nofp;@-target=thumbv6m-none-eabi@mfloat-abi=soft
+// CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7-m/nofp;@-target=thumbv7m-none-eabi@mfloat-abi=soft
+// CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7e-m/nofp;@-target=thumbv7em-none-eabi@mfloat-abi=soft@mfpu=none
+// CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/nofp;@-target=arm-none-eabi@mfloat-abi=soft@march=armv8m.main+nofp
+// CHECK-PRINT-MULTI-LIB: 

[PATCH] D142933: Add -print-multi-selection-flags argument

2023-02-01 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

> The main trouble I had was at that point we don't have a reference to the 
> ToolChain, so calling `getMultiSelectionFlags` was not possible. [...] I'm 
> not sure what the solution here is.

I see two options:

1. Split getMultiSelectionFlags into needs-ToolChain and doesn't-need-ToolChain 
parts, with the former calling the latter. From Gnu.cpp, call the latter, with 
the limitation that it can use fewer flags.
2. Pass a ToolChain to the Gnu.cpp functions.

> I added the arch extensions and abi to the Result in `getMultiSelectionFlags`

What was the syntax you used for that?
I'm not super keen on the `march=+ext` syntax I came up with so I'm open to 
alternatives.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142933/new/

https://reviews.llvm.org/D142933

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D142932: Multilib YAML parsing

2023-02-01 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 493968.
michaelplatings added a comment.

Incorporated changes requested by @miyuki


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142932/new/

https://reviews.llvm.org/D142932

Files:
  clang/include/clang/Driver/Multilib.h
  clang/lib/Driver/Multilib.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -187,3 +187,357 @@
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
 }
+
+static void diagnosticCallback(const llvm::SMDiagnostic , void *Out) {
+  *reinterpret_cast(Out) = D.getMessage();
+}
+
+static bool parse(MultilibSet , MultilibFlagMap ,
+  std::string , const char *Data) {
+  return MS.parse(llvm::MemoryBufferRef(Data, "TEST"), MFM, diagnosticCallback,
+  );
+}
+
+static bool parse(MultilibSet , MultilibFlagMap , const char *Data) {
+  return MS.parse(llvm::MemoryBufferRef(Data, "TEST"), MFM);
+}
+
+TEST(MultilibTest, ParseInvalid) {
+  std::string Diagnostic;
+
+  MultilibSet MS;
+  MultilibFlagMap MFM;
+  EXPECT_FALSE(parse(MS, MFM, Diagnostic, R"(
+variants:
+- dir: /abc
+  flags: []
+  printArgs: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("paths must be relative"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, MFM, Diagnostic, R"(
+variants:
+- flags: []
+  printArgs: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'dir'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, MFM, Diagnostic, R"(
+variants:
+- dir: .
+  printArgs: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'flags'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, MFM, Diagnostic, R"(
+variants:
+- dir: .
+  flags: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("missing required key 'printArgs'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, MFM, Diagnostic, R"(
+flagMap:
+- regex: abc
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic)
+  .contains("value required for 'matchFlags' or 'noMatchFlags'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, MFM, Diagnostic, R"(
+flagMap:
+- dir: .
+  regex: '('
+  printArgs: []
+
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("parentheses not balanced"))
+  << Diagnostic;
+}
+
+TEST(MultilibTest, Parse) {
+  MultilibSet MS;
+  MultilibFlagMap MFM;
+  EXPECT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: .
+  flags: []
+  printArgs: []
+)"));
+  EXPECT_EQ(1U, MS.size());
+  EXPECT_EQ("", MS.begin()->gccSuffix());
+
+  EXPECT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: abc
+  flags: []
+  printArgs: []
+)"));
+  EXPECT_EQ(1U, MS.size());
+  EXPECT_EQ("/abc", MS.begin()->gccSuffix());
+
+  EXPECT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: pqr
+  flags: []
+  printArgs: [-mfloat-abi=soft]
+)"));
+  EXPECT_EQ(1U, MS.size());
+  EXPECT_EQ("/pqr", MS.begin()->gccSuffix());
+  EXPECT_EQ(std::vector({"-mfloat-abi=soft"}),
+MS.begin()->getPrintArgs());
+
+  EXPECT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: pqr
+  flags: []
+  printArgs: [-mfloat-abi=soft, -fno-exceptions]
+)"));
+  EXPECT_EQ(1U, MS.size());
+  EXPECT_EQ(std::vector({"-mfloat-abi=soft", "-fno-exceptions"}),
+MS.begin()->getPrintArgs());
+
+  EXPECT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: a
+  flags: []
+  printArgs: []
+- dir: b
+  flags: []
+  printArgs: []
+)"));
+  EXPECT_EQ(2U, MS.size());
+}
+
+static bool select(const std::vector ,
+   const MultilibSet , const MultilibFlagMap ,
+   Multilib ) {
+  Multilib::flags_list Flags(MFM.getFlags(InFlags));
+  Flags.insert(InFlags.begin(), InFlags.end());
+  return MS.select(Flags, Selected);
+}
+
+TEST(MultilibTest, SelectSoft) {
+  MultilibSet MS;
+  MultilibFlagMap MFM;
+  Multilib Selected;
+  ASSERT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: s
+  flags: [softabi]
+  printArgs: []
+flagMap:
+- regex: mfloat-abi=soft
+  matchFlags: [softabi]
+- regex: mfloat-abi=softfp
+  matchFlags: [softabi]
+)"));
+  EXPECT_TRUE(select({"mfloat-abi=soft"}, MS, MFM, Selected));
+  EXPECT_TRUE(select({"mfloat-abi=softfp"}, MS, MFM, Selected));
+  EXPECT_FALSE(select({"mfloat-abi=hard"}, MS, MFM, Selected));
+}
+
+TEST(MultilibTest, SelectSoftFP) {
+  MultilibSet MS;
+  MultilibFlagMap MFM;
+  Multilib Selected;
+  ASSERT_TRUE(parse(MS, MFM, R"(
+variants:
+- dir: f
+  flags: [mfloat-abi=softfp]
+  printArgs: []
+)"));
+  EXPECT_FALSE(select({"mfloat-abi=soft"}, MS, MFM, Selected));
+  EXPECT_TRUE(select({"mfloat-abi=softfp"}, MS, MFM, Selected));
+  EXPECT_FALSE(select({"mfloat-abi=hard"}, MS, MFM, Selected));
+}
+
+TEST(MultilibTest, SelectHard) {
+  // If hard float is all that's available then select that only if compiling
+  // with hard float.
+  

[PATCH] D145567: [Driver] Rename multilib flags to tags

2023-03-08 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added a reviewer: phosek.
Herald added a subscriber: abrachet.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

The name "flag" implies a type of command line option which is no longer
how these variables are used in multilib. Although tags often look
similar to command line options this is not a requirement - tags may be
arbitrary strings.

MultilibBuilder still uses the name "flag" since it is designed to be
used only with valid command line options, even though these are
subsequently used as multilib tags. Similarly addMultilibFlag() keeps
its existing name because of how it is used, even though it now takes a
tag_set argument.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D145567

Files:
  clang/docs/Multilib.rst
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/Options.td
  clang/include/clang/Driver/ToolChain.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/MultilibBuilder.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/CommonArgs.cpp
  clang/lib/Driver/ToolChains/CommonArgs.h
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/test/Driver/baremetal-multilib.yaml
  clang/test/Driver/print-multi-selection-flags.c
  clang/test/Driver/print-multi-selection-tags.c
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -36,21 +36,21 @@
 TEST(MultilibTest, OpEqReflexivity3) {
   Multilib M1({}, {}, {}, {"+foo"});
   Multilib M2({}, {}, {}, {"+foo"});
-  ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same";
+  ASSERT_TRUE(M1 == M2) << "Multilibs with the same tag should be the same";
 }
 
 TEST(MultilibTest, OpEqInequivalence1) {
   Multilib M1({}, {}, {}, {"+foo"});
   Multilib M2({}, {}, {}, {"-foo"});
-  ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same";
+  ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting tags are not the same";
   ASSERT_FALSE(M2 == M1)
-  << "Multilibs with conflicting flags are not the same (commuted)";
+  << "Multilibs with conflicting tags are not the same (commuted)";
 }
 
 TEST(MultilibTest, OpEqInequivalence2) {
   Multilib M1;
   Multilib M2({}, {}, {}, {"+foo"});
-  ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different";
+  ASSERT_FALSE(M1 == M2) << "Tags make Multilibs different";
 }
 
 TEST(MultilibTest, OpEqEquivalence2) {
@@ -126,8 +126,8 @@
 
 TEST(MultilibTest, Construction3) {
   Multilib M({}, {}, {}, {"+f1", "+f2", "-f3"});
-  for (Multilib::flag_set::const_iterator I = M.flags().begin(),
-  E = M.flags().end();
+  for (Multilib::tag_set::const_iterator I = M.tags().begin(),
+  E = M.tags().end();
I != E; ++I) {
 ASSERT_TRUE(llvm::StringSwitch(*I)
 .Cases("+f1", "+f2", "-f3", true)
@@ -153,17 +153,17 @@
   Multilib("/foo", {}, {}, {"+foo"}),
   Multilib("/bar", {}, {}, {"+bar"}),
   });
-  Multilib::flag_set Flags1 = {"+foo", "-bar"};
+  Multilib::tag_set Tags1 = {"+foo", "-bar"};
   llvm::SmallVector Selection1;
-  ASSERT_TRUE(MS.select(Flags1, Selection1))
-  << "Flag set was {\"+foo\"}, but selection not found";
+  ASSERT_TRUE(MS.select(Tags1, Selection1))
+  << "Tag set was {\"+foo\"}, but selection not found";
   ASSERT_TRUE(Selection1.back().gccSuffix() == "/foo")
   << "Selection picked " << Selection1.back() << " which was not expected";
 
-  Multilib::flag_set Flags2 = {"+foo", "+bar"};
+  Multilib::tag_set Tags2 = {"+foo", "+bar"};
   llvm::SmallVector Selection2;
-  ASSERT_TRUE(MS.select(Flags2, Selection2))
-  << "Flag set was {\"+bar\"}, but selection not found";
+  ASSERT_TRUE(MS.select(Tags2, Selection2))
+  << "Tag set was {\"+bar\"}, but selection not found";
   ASSERT_TRUE(Selection2.back().gccSuffix() == "/bar")
   << "Selection picked " << Selection2.back() << " which was not expected";
 }
@@ -276,7 +276,7 @@
   EXPECT_FALSE(parse(MS, Diagnostic, YAML_PREAMBLE R"(
 Variants:
 - Dir: /abc
-  Flags: []
+  Tags: []
   PrintOptions: []
 )"));
   EXPECT_TRUE(StringRef(Diagnostic).contains("paths must be relative"))
@@ -284,7 +284,7 @@
 
   EXPECT_FALSE(parse(MS, Diagnostic, YAML_PREAMBLE R"(
 Variants:
-- Flags: []
+- Tags: []
   PrintOptions: []
 )"));
   EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Dir'"))
@@ -295,13 +295,13 @@
 - Dir: .
   PrintOptions: []
 )"));
-  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Flags'"))
+  

[PATCH] D143059: [Driver] Enable selecting multiple multilibs

2023-03-09 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 503904.
michaelplatings added a comment.

flags -> tags


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143059/new/

https://reviews.llvm.org/D143059

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/ToolChain.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/CSKYToolChain.cpp
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/lib/Driver/ToolChains/Gnu.h
  clang/lib/Driver/ToolChains/Hexagon.cpp
  clang/lib/Driver/ToolChains/Hurd.cpp
  clang/lib/Driver/ToolChains/Linux.cpp
  clang/lib/Driver/ToolChains/MipsLinux.cpp
  clang/lib/Driver/ToolChains/RISCVToolchain.cpp
  clang/test/Driver/fuchsia.cpp
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -154,18 +154,18 @@
   Multilib("/bar", {}, {}, {"+bar"}),
   });
   Multilib::tag_set Tags1 = {"+foo", "-bar"};
-  Multilib Selection1;
+  llvm::SmallVector Selection1;
   ASSERT_TRUE(MS.select(Tags1, Selection1))
   << "Tag set was {\"+foo\"}, but selection not found";
-  ASSERT_TRUE(Selection1.gccSuffix() == "/foo")
-  << "Selection picked " << Selection1 << " which was not expected";
+  ASSERT_TRUE(Selection1.back().gccSuffix() == "/foo")
+  << "Selection picked " << Selection1.back() << " which was not expected";
 
   Multilib::tag_set Tags2 = {"+foo", "+bar"};
-  Multilib Selection2;
+  llvm::SmallVector Selection2;
   ASSERT_TRUE(MS.select(Tags2, Selection2))
   << "Tag set was {\"+bar\"}, but selection not found";
-  ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
-  << "Selection picked " << Selection2 << " which was not expected";
+  ASSERT_TRUE(Selection2.back().gccSuffix() == "/bar")
+  << "Selection picked " << Selection2.back() << " which was not expected";
 }
 
 TEST(MultilibTest, SelectMultiple) {
@@ -173,17 +173,17 @@
   Multilib("/a", {}, {}, {"x"}),
   Multilib("/b", {}, {}, {"y"}),
   });
-  std::vector Selection;
+  llvm::SmallVector Selection;
 
-  Selection = MS.select({"x"});
+  ASSERT_TRUE(MS.select({"x"}, Selection));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
 
-  Selection = MS.select({"y"});
+  ASSERT_TRUE(MS.select({"y"}, Selection));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/b", Selection[0].gccSuffix());
 
-  Selection = MS.select({"y", "x"});
+  ASSERT_TRUE(MS.select({"y", "x"}, Selection));
   ASSERT_EQ(2u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
@@ -382,7 +382,7 @@
 
 TEST(MultilibTest, SelectSoft) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parse(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: s
@@ -401,7 +401,7 @@
 
 TEST(MultilibTest, SelectSoftFP) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parse(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: f
@@ -417,7 +417,7 @@
   // If hard float is all that's available then select that only if compiling
   // with hard float.
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parse(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: h
@@ -431,7 +431,7 @@
 
 TEST(MultilibTest, SelectFloatABI) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parse(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: s
@@ -452,18 +452,18 @@
   NoMatchTags: [hasfp]
 )"));
   MS.select({"mfloat-abi=soft"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=softfp"}, Selected);
-  EXPECT_EQ("/f", Selected.gccSuffix());
+  EXPECT_EQ("/f", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=hard"}, Selected);
-  EXPECT_EQ("/h", Selected.gccSuffix());
+  EXPECT_EQ("/h", Selected.back().gccSuffix());
 }
 
 TEST(MultilibTest, SelectFloatABIReversed) {
   // If soft is specified after softfp then softfp will never be
   // selected because soft is compatible with softfp and last wins.
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parse(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: h
@@ -484,11 +484,11 @@
   NoMatchTags: [hasfp]
 )"));
   MS.select({"mfloat-abi=soft"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=softfp"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=hard"}, Selected);
-  EXPECT_EQ("/h", Selected.gccSuffix());
+  EXPECT_EQ("/h", 

[PATCH] D142986: Enable multilib.yaml in the BareMetal ToolChain

2023-03-09 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 503903.
michaelplatings added a comment.

flags -> tags


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142986/new/

https://reviews.llvm.org/D142986

Files:
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/test/Driver/baremetal-multilib.yaml
  clang/test/Driver/baremetal.cpp
  clang/test/Driver/lit.local.cfg

Index: clang/test/Driver/lit.local.cfg
===
--- clang/test/Driver/lit.local.cfg
+++ clang/test/Driver/lit.local.cfg
@@ -1,7 +1,7 @@
 from lit.llvm import llvm_config
 
 config.suffixes = ['.c', '.cpp', '.cppm', '.h', '.m', '.mm', '.S', '.s', '.f90', '.F90', '.f95',
-   '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hipi', '.hlsl']
+   '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hipi', '.hlsl', '.yaml']
 config.substitutions = list(config.substitutions)
 config.substitutions.insert(0,
 ('%clang_cc1',
Index: clang/test/Driver/baremetal.cpp
===
--- clang/test/Driver/baremetal.cpp
+++ clang/test/Driver/baremetal.cpp
@@ -118,9 +118,9 @@
 // Verify that the bare metal driver does not include any host system paths:
 // CHECK-AARCH64-NO-HOST-INC: InstalledDir: [[INSTALLEDDIR:.+]]
 // CHECK-AARCH64-NO-HOST-INC: "-resource-dir" "[[RESOURCE:[^"]+]]"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include{{[/\\]+}}c++{{[/\\]+}}v1"
 // CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[RESOURCE]]{{[/\\]+}}include"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include"
 
 // RUN: %clang %s -### --target=riscv64-unknown-elf -o %t.out -L some/directory/user/asked/for \
 // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf 2>&1 \
Index: clang/test/Driver/baremetal-multilib.yaml
===
--- /dev/null
+++ clang/test/Driver/baremetal-multilib.yaml
@@ -0,0 +1,143 @@
+# REQUIRES: shell
+# UNSUPPORTED: system-windows
+
+# RUN: rm -rf %T/baremetal_multilib
+# RUN: mkdir -p %T/baremetal_multilib/bin
+# RUN: mkdir -p %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib
+# RUN: touch %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib/libclang_rt.builtins.a
+# RUN: ln -s %clang %T/baremetal_multilib/bin/clang
+# RUN: ln -s %s %T/baremetal_multilib/lib/clang-runtimes/multilib.yaml
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c++ %s -### -o %t.out 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib %s
+# CHECK:  "-cc1" "-triple" "thumbv8m.main-none-unknown-eabihf"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include/c++/v1"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include"
+# CHECK-SAME: "-x" "c++" "{{.*}}baremetal-multilib.yaml"
+# CHECK-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic"
+# CHECK-SAME: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib"
+# CHECK-SAME: "-lc" "-lm" "-lclang_rt.builtins"
+# CHECK-SAME: "-o" "{{.*}}.tmp.out"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY %s
+# CHECK-PRINT-MULTI-DIRECTORY: arm-none-eabi/thumb/v8-m.main/fp
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
+# RUN: --target=arm-none-eabi --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v6-m/nofp;@-target=thumbv6m-none-eabi@mfloat-abi=soft
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7-m/nofp;@-target=thumbv7m-none-eabi@mfloat-abi=soft
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7e-m/nofp;@-target=thumbv7em-none-eabi@mfloat-abi=soft@mfpu=none
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/nofp;@-target=arm-none-eabi@mfloat-abi=soft@march=armv8m.main+nofp
+# CHECK-PRINT-MULTI-LIB: 

[PATCH] D142932: Multilib YAML parsing

2023-03-09 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 503900.
michaelplatings added a comment.

flags -> tags


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142932/new/

https://reviews.llvm.org/D142932

Files:
  clang/include/clang/Driver/Multilib.h
  clang/lib/Driver/Multilib.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -13,6 +13,7 @@
 #include "clang/Driver/Multilib.h"
 #include "../../lib/Driver/ToolChains/CommonArgs.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/Version.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -187,3 +188,407 @@
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
 }
+
+static void diagnosticCallback(const llvm::SMDiagnostic , void *Out) {
+  *reinterpret_cast(Out) = D.getMessage();
+}
+
+static bool parse(MultilibSet , std::string , const char *Data) {
+  return MS.parse(llvm::MemoryBufferRef(Data, "TEST"), diagnosticCallback,
+  );
+}
+
+static bool parse(MultilibSet , std::string ,
+  const std::string ) {
+  return MS.parse(llvm::MemoryBufferRef(Data, "TEST"), diagnosticCallback,
+  );
+}
+
+static bool parse(MultilibSet , const char *Data) {
+  return MS.parse(llvm::MemoryBufferRef(Data, "TEST"));
+}
+
+#define _STRINGIFY(x) #x
+#define STRINGIFY(x) _STRINGIFY(x)
+// Avoid using MULTILIB_CLANG_VERSION in case it has extra non-numeric parts.
+#define MULTILIB_CLANG_VERSION \
+  STRINGIFY(CLANG_VERSION_MAJOR)   \
+  "." STRINGIFY(CLANG_VERSION_MINOR) "." STRINGIFY(CLANG_VERSION_PATCHLEVEL)
+#define YAML_PREAMBLE "ClangMinimumVersion: " MULTILIB_CLANG_VERSION "\n"
+
+TEST(MultilibTest, ParseInvalid) {
+  std::string Diagnostic;
+
+  MultilibSet MS;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, R"(
+Variants: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic)
+  .contains("missing required key 'ClangMinimumVersion'"))
+  << Diagnostic;
+
+  // Require all 3 major.minor.patch version components
+  EXPECT_FALSE(parse(MS, Diagnostic, R"(
+ClangMinimumVersion: )" STRINGIFY(CLANG_VERSION_MAJOR) R"(.0
+Variants: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic)
+  .contains("not a valid version string. Expected "
+"MAJOR.MINOR.PATCHLEVEL but got \"" STRINGIFY(
+CLANG_VERSION_MAJOR) ".0\""))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, R"(
+ClangMinimumVersion: )" MULTILIB_CLANG_VERSION R"(a
+Variants: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic)
+  .contains("not a valid version string. Expected "
+"MAJOR.MINOR.PATCHLEVEL where all components are decimal "
+"integers but got \"" MULTILIB_CLANG_VERSION "a\""))
+  << Diagnostic;
+
+  // Reject configurations that require a later clang version
+  EXPECT_FALSE(parse(MS, Diagnostic,
+ R"(
+ClangMinimumVersion: )" + std::to_string(CLANG_VERSION_MAJOR + 1) +
+ R"(.0.0
+Variants: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic)
+  .contains("clang version " MULTILIB_CLANG_VERSION
+" is less than ClangMinimumVersion: " +
+std::to_string(CLANG_VERSION_MAJOR + 1) + ".0.0"))
+  << Diagnostic;
+
+  // but accept configurations that only need an earlier clang version
+  EXPECT_TRUE(parse(MS, Diagnostic, R"(
+ClangMinimumVersion: 16.0.0
+Variants: []
+)")) << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, YAML_PREAMBLE));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Variants'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: /abc
+  Tags: []
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("paths must be relative"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Tags: []
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Dir'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: .
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Tags'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: .
+  Tags: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("missing required key 'PrintOptions'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants: []
+TagMap:
+- Regex: abc
+)"));
+  

[PATCH] D142933: Add -print-multi-selection-flags-experimental option

2023-03-09 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 503902.
michaelplatings added a comment.

flags -> tags


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142933/new/

https://reviews.llvm.org/D142933

Files:
  clang/include/clang/Driver/Options.td
  clang/include/clang/Driver/ToolChain.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/test/Driver/print-multi-selection-tags.c

Index: clang/test/Driver/print-multi-selection-tags.c
===
--- /dev/null
+++ clang/test/Driver/print-multi-selection-tags.c
@@ -0,0 +1,54 @@
+// RUN: %clang -print-multi-selection-tags-experimental --target=aarch64-linux -fc++-abi=itanium -fsanitize=address | FileCheck --check-prefix=CHECK-LINUX %s
+// CHECK-LINUX: fc++-abi=itanium
+// CHECK-LINUX: fexceptions
+// CHECK-LINUX: frtti
+// CHECK-LINUX: fsanitize=address
+// CHECK-LINUX: target=aarch64-unknown-linux
+
+// RUN: %clang -print-multi-selection-tags-experimental --target=aarch64-fuchsia -fsanitize=hwaddress | FileCheck --check-prefix=CHECK-FUCHSIA %s
+// CHECK-FUCHSIA: fsanitize=hwaddress
+// CHECK-FUCHSIA: target=aarch64-unknown-fuchsia
+
+// RUN: %clang -print-multi-selection-tags-experimental --target=arm-none-eabi -mfloat-abi=soft -fno-exceptions -fno-rtti | FileCheck --check-prefix=CHECK-ARMV4T %s
+// CHECK-ARMV4T: fno-exceptions
+// CHECK-ARMV4T: fno-rtti
+// CHECK-ARMV4T: mfloat-abi=soft
+// CHECK-ARMV4T: mfpu=none
+// CHECK-ARMV4T: target=armv4t-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-tags-experimental --target=armv7em-none-eabi -mfloat-abi=softfp | FileCheck --check-prefix=CHECK-SOFTFP %s
+// CHECK-SOFTFP: mfloat-abi=softfp
+// CHECK-SOFTFP: mfpu=fpv4-sp-d16
+// CHECK-SOFTFP: target=thumbv7em-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-tags-experimental --target=arm-none-eabihf -march=armv7em -mfpu=fpv5-d16 | FileCheck --check-prefix=CHECK-HARD %s
+// CHECK-HARD: mfloat-abi=hard
+// CHECK-HARD: mfpu=fpv5-d16
+// CHECK-HARD: target=thumbv7em-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-tags-experimental --target=arm-none-eabi -mfloat-abi=soft -march=armv8-m.main+nofp | FileCheck --check-prefix=CHECK-V8MMAIN-NOFP %s
+// CHECK-V8MMAIN-NOFP: mfloat-abi=soft
+// CHECK-V8MMAIN-NOFP: mfpu=none
+// CHECK-V8MMAIN-NOFP: target=thumbv8m.main-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-tags-experimental --target=arm-none-eabi -mfloat-abi=hard -march=armv8.1m.main+mve.fp | FileCheck --check-prefix=CHECK-MVE %s
+// CHECK-MVE: march=+mve
+// CHECK-MVE: march=+mve.fp
+// CHECK-MVE: mfloat-abi=hard
+// CHECK-MVE: mfpu=fp-armv8-fullfp16-sp-d16
+// CHECK-MVE: target=thumbv8.1m.main-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-tags-experimental --target=arm-none-eabi -march=armv8.1m.main+mve+nofp | FileCheck --check-prefix=CHECK-MVENOFP %s
+// CHECK-MVENOFP: march=+mve
+// CHECK-MVENOFP-NOT: march=+mve.fp
+// CHECK-MVENOFP: mfpu=none
+
+// RUN: %clang -print-multi-selection-tags-experimental --target=aarch64-none-elf -march=armv8-a+lse | FileCheck --check-prefix=CHECK-LSE %s
+// CHECK-LSE: march=+lse
+
+// RUN: %clang -print-multi-selection-tags-experimental --target=aarch64-none-elf -march=armv8.5-a+sve+sve2 | FileCheck --check-prefix=CHECK-SVE2 %s
+// RUN: %clang -print-multi-selection-tags-experimental --target=aarch64-none-elf -march=armv9-a| FileCheck --check-prefix=CHECK-SVE2 %s
+// CHECK-SVE2: march=+simd
+// CHECK-SVE2: march=+sve
+// CHECK-SVE2: march=+sve2
+// CHECK-SVE2: target=aarch64-none-unknown-elf
Index: clang/lib/Driver/ToolChains/Arch/ARM.h
===
--- clang/lib/Driver/ToolChains/Arch/ARM.h
+++ clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -63,9 +63,11 @@
 void getARMArchCPUFromArgs(const llvm::opt::ArgList ,
llvm::StringRef , llvm::StringRef ,
bool FromAs = false);
+// Optionally returns the FPUKind
 void getARMTargetFeatures(const Driver , const llvm::Triple ,
   const llvm::opt::ArgList ,
-  std::vector , bool ForAS);
+  std::vector , bool ForAS,
+  unsigned *OutFPUKind = nullptr);
 int getARMSubArchVersionNumber(const llvm::Triple );
 bool isARMMProfile(const llvm::Triple );
 bool isARMAProfile(const llvm::Triple );
Index: clang/lib/Driver/ToolChains/Arch/ARM.cpp
===
--- clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -437,7 +437,8 @@
 
 void arm::getARMTargetFeatures(const Driver , const llvm::Triple ,
const ArgList ,
-   std::vector , bool ForAS) {
+   std::vector , 

[PATCH] D143587: [Docs] Multilib design

2023-03-09 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 503906.
michaelplatings added a comment.

flags -> tags


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143587/new/

https://reviews.llvm.org/D143587

Files:
  clang/docs/Multilib.rst
  clang/docs/index.rst

Index: clang/docs/index.rst
===
--- clang/docs/index.rst
+++ clang/docs/index.rst
@@ -100,6 +100,7 @@
CodeOwners
InternalsManual
DriverInternals
+   Multilib
OffloadingDesign
PCHInternals
ItaniumMangleAbiTags
Index: clang/docs/Multilib.rst
===
--- /dev/null
+++ clang/docs/Multilib.rst
@@ -0,0 +1,327 @@
+
+Multilib
+
+
+Introduction
+
+
+This document describes how multilib is implemented in Clang.
+
+What is multilib and why might you care?
+If you're :doc:`cross compiling` then you can't use native
+system headers and libraries. To address this, you can use a combination of
+``--sysroot``, ``-isystem`` and ``-L`` options to point Clang at suitable
+directories for your target.
+However, when there are many possible directories to choose from, it's not
+necessarily obvious which one to pick.
+Multilib allows a toolchain designer to imbue the toolchain with the ability to
+pick a suitable directory automatically, based on the options the user provides
+to Clang. For example, if the user specifies
+``--target=arm-none-eabi -mcpu=cortex-m4`` the toolchain can choose a directory
+containing headers and libraries suitable for Armv7E-M, because it knows that's
+a suitable architecture for Arm Cortex-M4.
+Multilib can also choose between libraries for the same architecture based on
+other options. For example if the user specifies ``-fno-exceptions`` then a
+toolchain could select libraries built without exception support, thereby
+reducing the size of the resulting binary.
+
+Design
+==
+
+Clang supports GCC's ``-print-multi-lib`` and ``-print-multi-directory``
+options. These are described in
+`GCC Developer Options `_.
+
+There are two ways to configure multilib in Clang: hard-coded or via a
+configuration file.
+
+Hard-coded Multilib
+===
+
+The available libraries can be hard-coded in Clang. Typically this is done
+using the ``MultilibBuilder`` interface in
+``clang/include/clang/Driver/MultilibBuilder.h``.
+There are many examples of this in ``lib/Driver/ToolChains/Gnu.cpp``.
+The remainder of this document will not focus on this type of multilib.
+
+EXPERIMENTAL Multilib via configuration file
+
+
+Some Clang toolchains support loading multilib configuration from a
+``multilib.yaml`` configuration file.
+
+A ``multilib.yaml`` configuration file specifies which multilib variants are
+available, their relative location, what compilation options were used to build
+them, and the criteria by which they are selected.
+
+Multilib processing
+===
+
+Clang goes through the following steps to use multilib from a configuration
+file:
+#. Convert command line options to tags. Clang can accept the same
+   information via different options - for example,
+   ``--target=arm-none-eabi -march=armv7-m`` and
+   ``--target=armv7m-none-eabi`` are equivalent. Clang can also accept many
+   independent pieces of information within a single option - for example
+   ``-march=armv8.1m.main+fp+mve`` specifies the architecture and two
+   extensions in a single command line option.
+   To make it easier for the multilib system, Clang converts the command line
+   options into a standard set of simpler "tags". In many cases these tags
+   will look like a command line option with the leading ``-`` stripped off,
+   but where a suitable form for the tag doesn't exist in command line
+   options then its form will be different. For example, an Arm architecture
+   extension is represented like ``march=+mve`` since there's no way to specify
+   it in isolation in a command line option.
+   To see what tags are emitted for a given set of command line options, use
+   the ``-print-multi-selection-tags-experimental`` command line option
+   along with the rest of the options you want to use.
+#. Load ``multilib.yaml`` from sysroot.
+#. Generate additional tags. ``multilib.yaml`` contains a ``TagMap`` section,
+   which specifies how to generate additional tags based on the tags derived
+   from command line options. Tags are matched using regular expressions.
+   These regular expressions shall use the POSIX extended regular expression
+   syntax.
+#. Match tags against multilib variants. If the generated tags are a superset
+   of the tags specified for a multilib variant then the variant is considered
+   a match.
+   If more than one variant matches then a toolchain may opt to either use only
+   the *last* 

[PATCH] D143075: BareMetal ToolChain multilib layering

2023-03-09 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 503905.
michaelplatings added a comment.

flags -> tags


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143075/new/

https://reviews.llvm.org/D143075

Files:
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/BareMetal.h
  clang/test/Driver/baremetal-multilib.yaml

Index: clang/test/Driver/baremetal-multilib.yaml
===
--- clang/test/Driver/baremetal-multilib.yaml
+++ clang/test/Driver/baremetal-multilib.yaml
@@ -25,6 +25,23 @@
 # RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY %s
 # CHECK-PRINT-MULTI-DIRECTORY: arm-none-eabi/thumb/v8-m.main/fp
 
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c++ %s -### -o %t.out 2>&1 \
+# RUN: --target=thumbv8.1m.main-none-eabihf -fno-exceptions --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib --check-prefix=CHECK-LAYERED-MULTILIB %s
+# CHECK-LAYERED-MULTILIB:  "-cc1" "-triple" "thumbv8.1m.main-none-unknown-eabihf"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/include/c++/v1"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/include/c++/v1"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/include"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/include"
+# CHECK-LAYERED-MULTILIB-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/lib"
+# CHECK-LAYERED-MULTILIB-SAME: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/lib"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: --target=thumbv8.1m.main-none-eabihf -fno-exceptions --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-LAYERED-PRINT-MULTI-DIRECTORY %s
+# CHECK-LAYERED-PRINT-MULTI-DIRECTORY:  arm-none-eabi/thumb/v8.1-m.main/fp
+# CHECK-LAYERED-PRINT-MULTI-DIRECTORY-NEXT: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept
+
 # RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
 # RUN: --target=arm-none-eabi --sysroot= \
 # RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
@@ -38,6 +55,7 @@
 # CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/fp;@-target=thumbv8m.main-none-eabihf
 # CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/fp;@-target=thumbv8.1m.main-none-eabihf
 # CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/nofp/mve;@-target=arm-none-eabihf@march=armv8.1m.main+nofp+mve
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept;@-target=thumbv8.1m.main-none-eabihf@fno-exceptions
 
 # RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x assembler -mexecute-only \
 # RUN: --target=arm-none-eabi --sysroot= %s -c -### 2>&1 \
@@ -118,6 +136,14 @@
   Tags: [target=thumbv8.1m.main-none-unknown-eabihf, march=+mve]
   PrintOptions: [--target=arm-none-eabihf, -march=armv8.1m.main+nofp+mve]
 
+# A specialisation of v8.1-m.main/fp without exceptions.
+# This layers over the top of the regular v8.1-m.main/fp so it doesn't
+# need to have its own include directory or C library, thereby saving
+# disk space.
+- Dir: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept
+  Tags: [target=thumbv8.1m.main-none-unknown-eabihf, hasfpu, fno-exceptions]
+  PrintOptions: [--target=thumbv8.1m.main-none-eabihf, -fno-exceptions]
+
 
 # The second section of the file is a map from auto-detected tags
 # to custom tags. The auto-detected tags can be printed out
Index: clang/lib/Driver/ToolChains/BareMetal.h
===
--- clang/lib/Driver/ToolChains/BareMetal.h
+++ clang/lib/Driver/ToolChains/BareMetal.h
@@ -71,6 +71,9 @@
   void AddLinkRuntimeLib(const llvm::opt::ArgList ,
  llvm::opt::ArgStringList ) const;
   std::string computeSysRoot() const override;
+
+private:
+  llvm::SmallVector getOrderedMultilibs() const;
 };
 
 } // namespace toolchains
Index: clang/lib/Driver/ToolChains/BareMetal.cpp
===
--- clang/lib/Driver/ToolChains/BareMetal.cpp
+++ clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -103,9 +103,12 @@
   findMultilibs(D, Triple, Args);
   SmallString<128> SysRoot(computeSysRoot());
   if (!SysRoot.empty()) {
-llvm::sys::path::append(SysRoot, "lib");
-getFilePaths().push_back(std::string(SysRoot));
-getLibraryPaths().push_back(std::string(SysRoot));
+for (const Multilib  : getOrderedMultilibs()) {
+  SmallString<128> Dir(SysRoot);
+  llvm::sys::path::append(Dir, M.osSuffix(), "lib");
+  

[PATCH] D145567: [Driver] Rename multilib flags to tags

2023-03-09 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 503899.
michaelplatings added a comment.

Rebase on top of D142905 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D145567/new/

https://reviews.llvm.org/D145567

Files:
  clang/include/clang/Driver/Multilib.h
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/MultilibBuilder.cpp
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/CommonArgs.cpp
  clang/lib/Driver/ToolChains/CommonArgs.h
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -35,21 +35,21 @@
 TEST(MultilibTest, OpEqReflexivity3) {
   Multilib M1({}, {}, {}, {"+foo"});
   Multilib M2({}, {}, {}, {"+foo"});
-  ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same";
+  ASSERT_TRUE(M1 == M2) << "Multilibs with the same tag should be the same";
 }
 
 TEST(MultilibTest, OpEqInequivalence1) {
   Multilib M1({}, {}, {}, {"+foo"});
   Multilib M2({}, {}, {}, {"-foo"});
-  ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same";
+  ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting tags are not the same";
   ASSERT_FALSE(M2 == M1)
-  << "Multilibs with conflicting flags are not the same (commuted)";
+  << "Multilibs with conflicting tags are not the same (commuted)";
 }
 
 TEST(MultilibTest, OpEqInequivalence2) {
   Multilib M1;
   Multilib M2({}, {}, {}, {"+foo"});
-  ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different";
+  ASSERT_FALSE(M1 == M2) << "Tags make Multilibs different";
 }
 
 TEST(MultilibTest, OpEqEquivalence2) {
@@ -125,8 +125,8 @@
 
 TEST(MultilibTest, Construction3) {
   Multilib M({}, {}, {}, {"+f1", "+f2", "-f3"});
-  for (Multilib::flag_set::const_iterator I = M.flags().begin(),
-  E = M.flags().end();
+  for (Multilib::tag_set::const_iterator I = M.tags().begin(),
+ E = M.tags().end();
I != E; ++I) {
 ASSERT_TRUE(llvm::StringSwitch(*I)
 .Cases("+f1", "+f2", "-f3", true)
@@ -152,17 +152,17 @@
   Multilib("/foo", {}, {}, {"+foo"}),
   Multilib("/bar", {}, {}, {"+bar"}),
   });
-  Multilib::flag_set Flags1 = {"+foo", "-bar"};
+  Multilib::tag_set Tags1 = {"+foo", "-bar"};
   Multilib Selection1;
-  ASSERT_TRUE(MS.select(Flags1, Selection1))
-  << "Flag set was {\"+foo\"}, but selection not found";
+  ASSERT_TRUE(MS.select(Tags1, Selection1))
+  << "Tag set was {\"+foo\"}, but selection not found";
   ASSERT_TRUE(Selection1.gccSuffix() == "/foo")
   << "Selection picked " << Selection1 << " which was not expected";
 
-  Multilib::flag_set Flags2 = {"+foo", "+bar"};
+  Multilib::tag_set Tags2 = {"+foo", "+bar"};
   Multilib Selection2;
-  ASSERT_TRUE(MS.select(Flags2, Selection2))
-  << "Flag set was {\"+bar\"}, but selection not found";
+  ASSERT_TRUE(MS.select(Tags2, Selection2))
+  << "Tag set was {\"+bar\"}, but selection not found";
   ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
   << "Selection picked " << Selection2 << " which was not expected";
 }
Index: clang/unittests/Driver/MultilibBuilderTest.cpp
===
--- clang/unittests/Driver/MultilibBuilderTest.cpp
+++ clang/unittests/Driver/MultilibBuilderTest.cpp
@@ -34,7 +34,7 @@
   << "Single contraindicative flag is not valid";
 
   ASSERT_FALSE(MultilibBuilder().flag("+foo").flag("-foo").isValid())
-  << "Conflicting flags should invalidate the Multilib";
+  << "Conflicting tags should invalidate the Multilib";
 
   ASSERT_TRUE(MultilibBuilder().flag("+foo").flag("+foo").isValid())
   << "Multilib should be valid even if it has the same flag "
@@ -68,9 +68,9 @@
   ASSERT_TRUE(MS.size() == 2);
   for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) {
 if (I->gccSuffix() == "/64")
-  ASSERT_TRUE(*I->flags().begin() == "+m64");
+  ASSERT_TRUE(*I->tags().begin() == "+m64");
 else if (I->gccSuffix() == "")
-  ASSERT_TRUE(*I->flags().begin() == "-m64");
+  ASSERT_TRUE(*I->tags().begin() == "-m64");
 else
   FAIL() << "Unrecognized gccSufix: " << I->gccSuffix();
   }
@@ -89,17 +89,17 @@
 .Default(false))
 << "Multilib " << *I << " wasn't expected";
 ASSERT_TRUE(llvm::StringSwitch(I->gccSuffix())
-.Case("", is_contained(I->flags(), "-sof"))
-.Case("/sof", is_contained(I->flags(), "+sof"))
-.Case("/el", is_contained(I->flags(), "-sof"))
-.Case("/sof/el", is_contained(I->flags(), 

[PATCH] D145567: [Driver] Rename multilib flags to tags

2023-03-09 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 503913.
michaelplatings added a comment.

Tiny tweak: undo an unnecessary change to a test


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D145567/new/

https://reviews.llvm.org/D145567

Files:
  clang/include/clang/Driver/Multilib.h
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/MultilibBuilder.cpp
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/CommonArgs.cpp
  clang/lib/Driver/ToolChains/CommonArgs.h
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -35,21 +35,21 @@
 TEST(MultilibTest, OpEqReflexivity3) {
   Multilib M1({}, {}, {}, {"+foo"});
   Multilib M2({}, {}, {}, {"+foo"});
-  ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same";
+  ASSERT_TRUE(M1 == M2) << "Multilibs with the same tag should be the same";
 }
 
 TEST(MultilibTest, OpEqInequivalence1) {
   Multilib M1({}, {}, {}, {"+foo"});
   Multilib M2({}, {}, {}, {"-foo"});
-  ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same";
+  ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting tags are not the same";
   ASSERT_FALSE(M2 == M1)
-  << "Multilibs with conflicting flags are not the same (commuted)";
+  << "Multilibs with conflicting tags are not the same (commuted)";
 }
 
 TEST(MultilibTest, OpEqInequivalence2) {
   Multilib M1;
   Multilib M2({}, {}, {}, {"+foo"});
-  ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different";
+  ASSERT_FALSE(M1 == M2) << "Tags make Multilibs different";
 }
 
 TEST(MultilibTest, OpEqEquivalence2) {
@@ -125,8 +125,8 @@
 
 TEST(MultilibTest, Construction3) {
   Multilib M({}, {}, {}, {"+f1", "+f2", "-f3"});
-  for (Multilib::flag_set::const_iterator I = M.flags().begin(),
-  E = M.flags().end();
+  for (Multilib::tag_set::const_iterator I = M.tags().begin(),
+ E = M.tags().end();
I != E; ++I) {
 ASSERT_TRUE(llvm::StringSwitch(*I)
 .Cases("+f1", "+f2", "-f3", true)
@@ -152,17 +152,17 @@
   Multilib("/foo", {}, {}, {"+foo"}),
   Multilib("/bar", {}, {}, {"+bar"}),
   });
-  Multilib::flag_set Flags1 = {"+foo", "-bar"};
+  Multilib::tag_set Tags1 = {"+foo", "-bar"};
   Multilib Selection1;
-  ASSERT_TRUE(MS.select(Flags1, Selection1))
-  << "Flag set was {\"+foo\"}, but selection not found";
+  ASSERT_TRUE(MS.select(Tags1, Selection1))
+  << "Tag set was {\"+foo\"}, but selection not found";
   ASSERT_TRUE(Selection1.gccSuffix() == "/foo")
   << "Selection picked " << Selection1 << " which was not expected";
 
-  Multilib::flag_set Flags2 = {"+foo", "+bar"};
+  Multilib::tag_set Tags2 = {"+foo", "+bar"};
   Multilib Selection2;
-  ASSERT_TRUE(MS.select(Flags2, Selection2))
-  << "Flag set was {\"+bar\"}, but selection not found";
+  ASSERT_TRUE(MS.select(Tags2, Selection2))
+  << "Tag set was {\"+bar\"}, but selection not found";
   ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
   << "Selection picked " << Selection2 << " which was not expected";
 }
Index: clang/unittests/Driver/MultilibBuilderTest.cpp
===
--- clang/unittests/Driver/MultilibBuilderTest.cpp
+++ clang/unittests/Driver/MultilibBuilderTest.cpp
@@ -68,9 +68,9 @@
   ASSERT_TRUE(MS.size() == 2);
   for (MultilibSet::const_iterator I = MS.begin(), E = MS.end(); I != E; ++I) {
 if (I->gccSuffix() == "/64")
-  ASSERT_TRUE(*I->flags().begin() == "+m64");
+  ASSERT_TRUE(*I->tags().begin() == "+m64");
 else if (I->gccSuffix() == "")
-  ASSERT_TRUE(*I->flags().begin() == "-m64");
+  ASSERT_TRUE(*I->tags().begin() == "-m64");
 else
   FAIL() << "Unrecognized gccSufix: " << I->gccSuffix();
   }
@@ -89,17 +89,17 @@
 .Default(false))
 << "Multilib " << *I << " wasn't expected";
 ASSERT_TRUE(llvm::StringSwitch(I->gccSuffix())
-.Case("", is_contained(I->flags(), "-sof"))
-.Case("/sof", is_contained(I->flags(), "+sof"))
-.Case("/el", is_contained(I->flags(), "-sof"))
-.Case("/sof/el", is_contained(I->flags(), "+sof"))
+.Case("", is_contained(I->tags(), "-sof"))
+.Case("/sof", is_contained(I->tags(), "+sof"))
+.Case("/el", is_contained(I->tags(), "-sof"))
+.Case("/sof/el", is_contained(I->tags(), "+sof"))
 .Default(false))
 << "Multilib " << *I << " didn't have the appropriate {+,-}sof flag";
 

[PATCH] D142905: [Driver] Change multilib selection algorithm

2023-03-17 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 506044.
michaelplatings added a comment.

fix typo in comment


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142905/new/

https://reviews.llvm.org/D142905

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/MultilibBuilder.h
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/MultilibBuilder.cpp
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -33,14 +33,14 @@
 }
 
 TEST(MultilibTest, OpEqReflexivity3) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same";
 }
 
 TEST(MultilibTest, OpEqInequivalence1) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"-foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"-foo"});
   ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same";
   ASSERT_FALSE(M2 == M1)
   << "Multilibs with conflicting flags are not the same (commuted)";
@@ -48,7 +48,7 @@
 
 TEST(MultilibTest, OpEqInequivalence2) {
   Multilib M1;
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different";
 }
 
@@ -124,7 +124,7 @@
 }
 
 TEST(MultilibTest, Construction3) {
-  Multilib M({}, {}, {}, 0, {"+f1", "+f2", "-f3"});
+  Multilib M({}, {}, {}, {"+f1", "+f2", "-f3"});
   for (Multilib::flags_list::const_iterator I = M.flags().begin(),
 E = M.flags().end();
I != E; ++I) {
@@ -149,8 +149,8 @@
 
 TEST(MultilibTest, SetPriority) {
   MultilibSet MS({
-  Multilib("/foo", {}, {}, 1, {"+foo"}),
-  Multilib("/bar", {}, {}, 2, {"+bar"}),
+  Multilib("/foo", {}, {}, {"+foo"}),
+  Multilib("/bar", {}, {}, {"+bar"}),
   });
   Multilib::flags_list Flags1 = {"+foo", "-bar"};
   Multilib Selection1;
@@ -166,3 +166,24 @@
   ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
   << "Selection picked " << Selection2 << " which was not expected";
 }
+
+TEST(MultilibTest, SelectMultiple) {
+  MultilibSet MS({
+  Multilib("/a", {}, {}, {"x"}),
+  Multilib("/b", {}, {}, {"y"}),
+  });
+  std::vector Selection;
+
+  Selection = MS.select({"x"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/b", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y", "x"});
+  ASSERT_EQ(2u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+  EXPECT_EQ("/b", Selection[1].gccSuffix());
+}
Index: clang/unittests/Driver/MultilibBuilderTest.cpp
===
--- clang/unittests/Driver/MultilibBuilderTest.cpp
+++ clang/unittests/Driver/MultilibBuilderTest.cpp
@@ -207,3 +207,14 @@
 << "Selection picked " << Selection << " which was not expected ";
   }
 }
+
+TEST(MultilibBuilderTest, PrintOptions) {
+  Multilib M = MultilibBuilder()
+   .flag("+x")
+   .flag("-y")
+   .flag("+a")
+   .flag("-b")
+   .flag("+c")
+   .makeMultilib();
+  ASSERT_EQ(Multilib::flags_list({"-x", "-a", "-c"}), M.getPrintOptions());
+}
Index: clang/lib/Driver/ToolChains/Fuchsia.cpp
===
--- clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -263,33 +263,33 @@
 
   Multilibs.push_back(Multilib());
   // Use the noexcept variant with -fno-exceptions to avoid the extra overhead.
-  Multilibs.push_back(MultilibBuilder("noexcept", {}, {}, 1)
+  Multilibs.push_back(MultilibBuilder("noexcept", {}, {})
   .flag("-fexceptions")
   .flag("+fno-exceptions")
   .makeMultilib());
   // ASan has higher priority because we always want the instrumentated version.
-  Multilibs.push_back(MultilibBuilder("asan", {}, {}, 2)
+  Multilibs.push_back(MultilibBuilder("asan", {}, {})
   .flag("+fsanitize=address")
   .makeMultilib());
   // Use the asan+noexcept variant with ASan and -fno-exceptions.
-  Multilibs.push_back(MultilibBuilder("asan+noexcept", {}, {}, 3)
+  Multilibs.push_back(MultilibBuilder("asan+noexcept", {}, {})
   .flag("+fsanitize=address")
   .flag("-fexceptions")
   .flag("+fno-exceptions")

[PATCH] D146141: [ARM] Use FPUKind enum instead of unsigned

2023-03-15 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added reviewers: simon_tatham, dcandler.
Herald added subscribers: hiraditya, kristof.beyls.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added subscribers: llvm-commits, cfe-commits, MaskRay.
Herald added projects: clang, LLVM.

Also rename some FPUID variables to FPUKind now it's clear that's what
they are.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146141

Files:
  clang/lib/Basic/Targets/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  llvm/include/llvm/MC/MCStreamer.h
  llvm/include/llvm/TargetParser/ARMTargetParser.h
  llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
  llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
  llvm/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp
  llvm/lib/TargetParser/ARMTargetParser.cpp
  llvm/unittests/TargetParser/TargetParserTest.cpp

Index: llvm/unittests/TargetParser/TargetParserTest.cpp
===
--- llvm/unittests/TargetParser/TargetParserTest.cpp
+++ llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -120,7 +120,7 @@
   ARM::ArchKind AK = ARM::parseCPUArch(params.CPUName);
   EXPECT_EQ(params.ExpectedArch, ARM::getArchName(AK));
 
-  unsigned FPUKind = ARM::getDefaultFPU(params.CPUName, AK);
+  ARM::FPUKind FPUKind = ARM::getDefaultFPU(params.CPUName, AK);
   EXPECT_EQ(params.ExpectedFPU, ARM::getFPUName(FPUKind));
 
   uint64_t default_extensions = ARM::getDefaultExtensions(params.CPUName, AK);
@@ -765,10 +765,10 @@
 testArchExtDependency(const char *ArchExt,
   const std::initializer_list ) {
   std::vector Features;
-  unsigned FPUID;
+  ARM::FPUKind FPUKind;
 
   if (!ARM::appendArchExtFeatures("", ARM::ArchKind::ARMV8_1MMainline, ArchExt,
-  Features, FPUID))
+  Features, FPUKind))
 return false;
 
   return llvm::all_of(Expected, [&](StringRef Ext) {
Index: llvm/lib/TargetParser/ARMTargetParser.cpp
===
--- llvm/lib/TargetParser/ARMTargetParser.cpp
+++ llvm/lib/TargetParser/ARMTargetParser.cpp
@@ -147,7 +147,8 @@
   return getProfileKind(parseArch(Arch));
 }
 
-bool ARM::getFPUFeatures(unsigned FPUKind, std::vector ) {
+bool ARM::getFPUFeatures(ARM::FPUKind FPUKind,
+ std::vector ) {
 
   if (FPUKind >= FK_LAST || FPUKind == FK_INVALID)
 return false;
@@ -211,7 +212,7 @@
   return true;
 }
 
-unsigned ARM::parseFPU(StringRef FPU) {
+ARM::FPUKind ARM::parseFPU(StringRef FPU) {
   StringRef Syn = getFPUSynonym(FPU);
   for (const auto  : FPUNames) {
 if (Syn == F.Name)
@@ -220,7 +221,7 @@
   return FK_INVALID;
 }
 
-ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
+ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(ARM::FPUKind FPUKind) {
   if (FPUKind >= FK_LAST)
 return NeonSupportLevel::None;
   return FPUNames[FPUKind].NeonSupport;
@@ -243,33 +244,33 @@
   .Default(FPU);
 }
 
-StringRef ARM::getFPUName(unsigned FPUKind) {
+StringRef ARM::getFPUName(ARM::FPUKind FPUKind) {
   if (FPUKind >= FK_LAST)
 return StringRef();
   return FPUNames[FPUKind].Name;
 }
 
-ARM::FPUVersion ARM::getFPUVersion(unsigned FPUKind) {
+ARM::FPUVersion ARM::getFPUVersion(ARM::FPUKind FPUKind) {
   if (FPUKind >= FK_LAST)
 return FPUVersion::NONE;
   return FPUNames[FPUKind].FPUVer;
 }
 
-ARM::FPURestriction ARM::getFPURestriction(unsigned FPUKind) {
+ARM::FPURestriction ARM::getFPURestriction(ARM::FPUKind FPUKind) {
   if (FPUKind >= FK_LAST)
 return FPURestriction::None;
   return FPUNames[FPUKind].Restriction;
 }
 
-unsigned ARM::getDefaultFPU(StringRef CPU, ARM::ArchKind AK) {
+ARM::FPUKind ARM::getDefaultFPU(StringRef CPU, ARM::ArchKind AK) {
   if (CPU == "generic")
 return ARM::ARMArchNames[static_cast(AK)].DefaultFPU;
 
-  return StringSwitch(CPU)
+  return StringSwitch(CPU)
 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)   \
   .Case(NAME, DEFAULT_FPU)
 #include "llvm/TargetParser/ARMTargetParser.def"
-   .Default(ARM::FK_INVALID);
+  .Default(ARM::FK_INVALID);
 }
 
 uint64_t ARM::getDefaultExtensions(StringRef CPU, ARM::ArchKind AK) {
@@ -362,7 +363,7 @@
   return StringRef();
 }
 
-static unsigned findDoublePrecisionFPU(unsigned InputFPUKind) {
+static ARM::FPUKind findDoublePrecisionFPU(ARM::FPUKind InputFPUKind) {
   const ARM::FPUName  = ARM::FPUNames[InputFPUKind];
 
   // If the input FPU already supports double-precision, then there
@@ -394,7 +395,7 @@
 bool ARM::appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK,
 StringRef ArchExt,
 std::vector ,
-unsigned ) {
+ARM::FPUKind ) {
 
   size_t StartingNumFeatures = Features.size();
   const bool Negated = stripNegationPrefix(ArchExt);
@@ -417,7 

[PATCH] D145567: [Driver] Rename multilib flags to tags

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings abandoned this revision.
michaelplatings marked an inline comment as done.
michaelplatings added a comment.

We're going back to "flags": https://discourse.llvm.org/t/rfc-multilib/67494/14


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D145567/new/

https://reviews.llvm.org/D145567

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D142933: Add -print-multi-selection-tags-experimental option

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505048.
michaelplatings added a comment.

tags->flags


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142933/new/

https://reviews.llvm.org/D142933

Files:
  clang/include/clang/Driver/Options.td
  clang/include/clang/Driver/ToolChain.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/test/Driver/print-multi-selection-flags.c

Index: clang/test/Driver/print-multi-selection-flags.c
===
--- /dev/null
+++ clang/test/Driver/print-multi-selection-flags.c
@@ -0,0 +1,54 @@
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-linux -fc++-abi=itanium -fsanitize=address | FileCheck --check-prefix=CHECK-LINUX %s
+// CHECK-LINUX: fc++-abi=itanium
+// CHECK-LINUX: fexceptions
+// CHECK-LINUX: frtti
+// CHECK-LINUX: fsanitize=address
+// CHECK-LINUX: target=aarch64-unknown-linux
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-fuchsia -fsanitize=hwaddress | FileCheck --check-prefix=CHECK-FUCHSIA %s
+// CHECK-FUCHSIA: fsanitize=hwaddress
+// CHECK-FUCHSIA: target=aarch64-unknown-fuchsia
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=soft -fno-exceptions -fno-rtti | FileCheck --check-prefix=CHECK-ARMV4T %s
+// CHECK-ARMV4T: fno-exceptions
+// CHECK-ARMV4T: fno-rtti
+// CHECK-ARMV4T: mfloat-abi=soft
+// CHECK-ARMV4T: mfpu=none
+// CHECK-ARMV4T: target=armv4t-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=armv7em-none-eabi -mfloat-abi=softfp | FileCheck --check-prefix=CHECK-SOFTFP %s
+// CHECK-SOFTFP: mfloat-abi=softfp
+// CHECK-SOFTFP: mfpu=fpv4-sp-d16
+// CHECK-SOFTFP: target=thumbv7em-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabihf -march=armv7em -mfpu=fpv5-d16 | FileCheck --check-prefix=CHECK-HARD %s
+// CHECK-HARD: mfloat-abi=hard
+// CHECK-HARD: mfpu=fpv5-d16
+// CHECK-HARD: target=thumbv7em-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=soft -march=armv8-m.main+nofp | FileCheck --check-prefix=CHECK-V8MMAIN-NOFP %s
+// CHECK-V8MMAIN-NOFP: mfloat-abi=soft
+// CHECK-V8MMAIN-NOFP: mfpu=none
+// CHECK-V8MMAIN-NOFP: target=thumbv8m.main-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=hard -march=armv8.1m.main+mve.fp | FileCheck --check-prefix=CHECK-MVE %s
+// CHECK-MVE: march=+mve
+// CHECK-MVE: march=+mve.fp
+// CHECK-MVE: mfloat-abi=hard
+// CHECK-MVE: mfpu=fp-armv8-fullfp16-sp-d16
+// CHECK-MVE: target=thumbv8.1m.main-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -march=armv8.1m.main+mve+nofp | FileCheck --check-prefix=CHECK-MVENOFP %s
+// CHECK-MVENOFP: march=+mve
+// CHECK-MVENOFP-NOT: march=+mve.fp
+// CHECK-MVENOFP: mfpu=none
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-none-elf -march=armv8-a+lse | FileCheck --check-prefix=CHECK-LSE %s
+// CHECK-LSE: march=+lse
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-none-elf -march=armv8.5-a+sve+sve2 | FileCheck --check-prefix=CHECK-SVE2 %s
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-none-elf -march=armv9-a| FileCheck --check-prefix=CHECK-SVE2 %s
+// CHECK-SVE2: march=+simd
+// CHECK-SVE2: march=+sve
+// CHECK-SVE2: march=+sve2
+// CHECK-SVE2: target=aarch64-none-unknown-elf
Index: clang/lib/Driver/ToolChains/Arch/ARM.h
===
--- clang/lib/Driver/ToolChains/Arch/ARM.h
+++ clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -63,9 +63,11 @@
 void getARMArchCPUFromArgs(const llvm::opt::ArgList ,
llvm::StringRef , llvm::StringRef ,
bool FromAs = false);
+// Optionally returns the FPUKind
 void getARMTargetFeatures(const Driver , const llvm::Triple ,
   const llvm::opt::ArgList ,
-  std::vector , bool ForAS);
+  std::vector , bool ForAS,
+  unsigned *OutFPUKind = nullptr);
 int getARMSubArchVersionNumber(const llvm::Triple );
 bool isARMMProfile(const llvm::Triple );
 bool isARMAProfile(const llvm::Triple );
Index: clang/lib/Driver/ToolChains/Arch/ARM.cpp
===
--- clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -437,7 +437,8 @@
 
 void arm::getARMTargetFeatures(const Driver , const llvm::Triple ,
const ArgList ,
-   std::vector , bool ForAS) {
+   

[PATCH] D142986: Enable multilib.yaml in the BareMetal ToolChain

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505050.
michaelplatings added a comment.

tags->flags


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142986/new/

https://reviews.llvm.org/D142986

Files:
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/test/Driver/baremetal-multilib.yaml
  clang/test/Driver/baremetal.cpp
  clang/test/Driver/lit.local.cfg

Index: clang/test/Driver/lit.local.cfg
===
--- clang/test/Driver/lit.local.cfg
+++ clang/test/Driver/lit.local.cfg
@@ -1,7 +1,7 @@
 from lit.llvm import llvm_config
 
 config.suffixes = ['.c', '.cpp', '.cppm', '.h', '.m', '.mm', '.S', '.s', '.f90', '.F90', '.f95',
-   '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hipi', '.hlsl']
+   '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hipi', '.hlsl', '.yaml']
 config.substitutions = list(config.substitutions)
 config.substitutions.insert(0,
 ('%clang_cc1',
Index: clang/test/Driver/baremetal.cpp
===
--- clang/test/Driver/baremetal.cpp
+++ clang/test/Driver/baremetal.cpp
@@ -118,9 +118,9 @@
 // Verify that the bare metal driver does not include any host system paths:
 // CHECK-AARCH64-NO-HOST-INC: InstalledDir: [[INSTALLEDDIR:.+]]
 // CHECK-AARCH64-NO-HOST-INC: "-resource-dir" "[[RESOURCE:[^"]+]]"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include{{[/\\]+}}c++{{[/\\]+}}v1"
 // CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[RESOURCE]]{{[/\\]+}}include"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include"
 
 // RUN: %clang %s -### --target=riscv64-unknown-elf -o %t.out -L some/directory/user/asked/for \
 // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf 2>&1 \
Index: clang/test/Driver/baremetal-multilib.yaml
===
--- /dev/null
+++ clang/test/Driver/baremetal-multilib.yaml
@@ -0,0 +1,143 @@
+# REQUIRES: shell
+# UNSUPPORTED: system-windows
+
+# RUN: rm -rf %T/baremetal_multilib
+# RUN: mkdir -p %T/baremetal_multilib/bin
+# RUN: mkdir -p %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib
+# RUN: touch %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib/libclang_rt.builtins.a
+# RUN: ln -s %clang %T/baremetal_multilib/bin/clang
+# RUN: ln -s %s %T/baremetal_multilib/lib/clang-runtimes/multilib.yaml
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c++ %s -### -o %t.out 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib %s
+# CHECK:  "-cc1" "-triple" "thumbv8m.main-none-unknown-eabihf"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include/c++/v1"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include"
+# CHECK-SAME: "-x" "c++" "{{.*}}baremetal-multilib.yaml"
+# CHECK-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic"
+# CHECK-SAME: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib"
+# CHECK-SAME: "-lc" "-lm" "-lclang_rt.builtins"
+# CHECK-SAME: "-o" "{{.*}}.tmp.out"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY %s
+# CHECK-PRINT-MULTI-DIRECTORY: arm-none-eabi/thumb/v8-m.main/fp
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
+# RUN: --target=arm-none-eabi --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v6-m/nofp;@-target=thumbv6m-none-eabi@mfloat-abi=soft
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7-m/nofp;@-target=thumbv7m-none-eabi@mfloat-abi=soft
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7e-m/nofp;@-target=thumbv7em-none-eabi@mfloat-abi=soft@mfpu=none
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/nofp;@-target=arm-none-eabi@mfloat-abi=soft@march=armv8m.main+nofp
+# CHECK-PRINT-MULTI-LIB: 

[PATCH] D142932: Multilib YAML parsing

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505047.
michaelplatings added a comment.

tags->flags


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142932/new/

https://reviews.llvm.org/D142932

Files:
  clang/include/clang/Driver/Multilib.h
  clang/lib/Driver/Multilib.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -13,6 +13,7 @@
 #include "clang/Driver/Multilib.h"
 #include "../../lib/Driver/ToolChains/CommonArgs.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/Version.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -187,3 +188,409 @@
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
 }
+
+static void diagnosticCallback(const llvm::SMDiagnostic , void *Out) {
+  *reinterpret_cast(Out) = D.getMessage();
+}
+
+static bool parseYaml(MultilibSet , std::string ,
+  const char *Data) {
+  return MS.parseYaml(llvm::MemoryBufferRef(Data, "TEST"), diagnosticCallback,
+  );
+}
+
+static bool parseYaml(MultilibSet , std::string ,
+  const std::string ) {
+  return MS.parseYaml(llvm::MemoryBufferRef(Data, "TEST"), diagnosticCallback,
+  );
+}
+
+static bool parseYaml(MultilibSet , const char *Data) {
+  return MS.parseYaml(llvm::MemoryBufferRef(Data, "TEST"));
+}
+
+#define _STRINGIFY(x) #x
+#define STRINGIFY(x) _STRINGIFY(x)
+// Avoid using MULTILIB_CLANG_VERSION in case it has extra non-numeric parts.
+#define MULTILIB_CLANG_VERSION \
+  STRINGIFY(CLANG_VERSION_MAJOR)   \
+  "." STRINGIFY(CLANG_VERSION_MINOR) "." STRINGIFY(CLANG_VERSION_PATCHLEVEL)
+#define YAML_PREAMBLE "ClangMinimumVersion: " MULTILIB_CLANG_VERSION "\n"
+
+TEST(MultilibTest, ParseInvalid) {
+  std::string Diagnostic;
+
+  MultilibSet MS;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, R"(
+Variants: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic)
+  .contains("missing required key 'ClangMinimumVersion'"))
+  << Diagnostic;
+
+  // Require all 3 major.minor.patch version components
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, R"(
+ClangMinimumVersion: )" STRINGIFY(CLANG_VERSION_MAJOR) R"(.0
+Variants: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic)
+  .contains("not a valid version string. Expected "
+"MAJOR.MINOR.PATCHLEVEL but got \"" STRINGIFY(
+CLANG_VERSION_MAJOR) ".0\""))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, R"(
+ClangMinimumVersion: )" MULTILIB_CLANG_VERSION R"(a
+Variants: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic)
+  .contains("not a valid version string. Expected "
+"MAJOR.MINOR.PATCHLEVEL where all components are decimal "
+"integers but got \"" MULTILIB_CLANG_VERSION "a\""))
+  << Diagnostic;
+
+  // Reject configurations that require a later clang version
+  EXPECT_FALSE(parseYaml(MS, Diagnostic,
+ R"(
+ClangMinimumVersion: )" + std::to_string(CLANG_VERSION_MAJOR + 1) +
+ R"(.0.0
+Variants: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic)
+  .contains("clang version " MULTILIB_CLANG_VERSION
+" is less than ClangMinimumVersion: " +
+std::to_string(CLANG_VERSION_MAJOR + 1) + ".0.0"))
+  << Diagnostic;
+
+  // but accept configurations that only need an earlier clang version
+  EXPECT_TRUE(parseYaml(MS, Diagnostic, R"(
+ClangMinimumVersion: 16.0.0
+Variants: []
+)")) << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Variants'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: /abc
+  Flags: []
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("paths must be relative"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Flags: []
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Dir'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: .
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Flags'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: .
+  Flags: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("missing required key 'PrintOptions'"))
+  << Diagnostic;
+
+  

[PATCH] D143059: [Driver] Enable selecting multiple multilibs

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505051.
michaelplatings added a comment.

tags->flags


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143059/new/

https://reviews.llvm.org/D143059

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/ToolChain.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/CSKYToolChain.cpp
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/lib/Driver/ToolChains/Gnu.h
  clang/lib/Driver/ToolChains/Hexagon.cpp
  clang/lib/Driver/ToolChains/Hurd.cpp
  clang/lib/Driver/ToolChains/Linux.cpp
  clang/lib/Driver/ToolChains/MipsLinux.cpp
  clang/lib/Driver/ToolChains/RISCVToolchain.cpp
  clang/test/Driver/fuchsia.cpp
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -154,18 +154,18 @@
   Multilib("/bar", {}, {}, {"+bar"}),
   });
   Multilib::flag_set Flags1 = {"+foo", "-bar"};
-  Multilib Selection1;
+  llvm::SmallVector Selection1;
   ASSERT_TRUE(MS.select(Flags1, Selection1))
   << "Flag set was {\"+foo\"}, but selection not found";
-  ASSERT_TRUE(Selection1.gccSuffix() == "/foo")
-  << "Selection picked " << Selection1 << " which was not expected";
+  ASSERT_TRUE(Selection1.back().gccSuffix() == "/foo")
+  << "Selection picked " << Selection1.back() << " which was not expected";
 
   Multilib::flag_set Flags2 = {"+foo", "+bar"};
-  Multilib Selection2;
+  llvm::SmallVector Selection2;
   ASSERT_TRUE(MS.select(Flags2, Selection2))
   << "Flag set was {\"+bar\"}, but selection not found";
-  ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
-  << "Selection picked " << Selection2 << " which was not expected";
+  ASSERT_TRUE(Selection2.back().gccSuffix() == "/bar")
+  << "Selection picked " << Selection2.back() << " which was not expected";
 }
 
 TEST(MultilibTest, SelectMultiple) {
@@ -173,17 +173,17 @@
   Multilib("/a", {}, {}, {"x"}),
   Multilib("/b", {}, {}, {"y"}),
   });
-  std::vector Selection;
+  llvm::SmallVector Selection;
 
-  Selection = MS.select({"x"});
+  ASSERT_TRUE(MS.select({"x"}, Selection));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
 
-  Selection = MS.select({"y"});
+  ASSERT_TRUE(MS.select({"y"}, Selection));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/b", Selection[0].gccSuffix());
 
-  Selection = MS.select({"y", "x"});
+  ASSERT_TRUE(MS.select({"y", "x"}, Selection));
   ASSERT_EQ(2u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
@@ -384,7 +384,7 @@
 
 TEST(MultilibTest, SelectSoft) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: s
@@ -403,7 +403,7 @@
 
 TEST(MultilibTest, SelectSoftFP) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: f
@@ -419,7 +419,7 @@
   // If hard float is all that's available then select that only if compiling
   // with hard float.
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: h
@@ -433,7 +433,7 @@
 
 TEST(MultilibTest, SelectFloatABI) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: s
@@ -454,18 +454,18 @@
   NoMatchFlags: [hasfp]
 )"));
   MS.select({"mfloat-abi=soft"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=softfp"}, Selected);
-  EXPECT_EQ("/f", Selected.gccSuffix());
+  EXPECT_EQ("/f", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=hard"}, Selected);
-  EXPECT_EQ("/h", Selected.gccSuffix());
+  EXPECT_EQ("/h", Selected.back().gccSuffix());
 }
 
 TEST(MultilibTest, SelectFloatABIReversed) {
   // If soft is specified after softfp then softfp will never be
   // selected because soft is compatible with softfp and last wins.
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: h
@@ -486,11 +486,11 @@
   NoMatchFlags: [hasfp]
 )"));
   MS.select({"mfloat-abi=soft"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=softfp"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=hard"}, Selected);
-  EXPECT_EQ("/h", 

[PATCH] D143075: BareMetal ToolChain multilib layering

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505052.
michaelplatings added a comment.

tags->flags


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143075/new/

https://reviews.llvm.org/D143075

Files:
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/BareMetal.h
  clang/test/Driver/baremetal-multilib.yaml

Index: clang/test/Driver/baremetal-multilib.yaml
===
--- clang/test/Driver/baremetal-multilib.yaml
+++ clang/test/Driver/baremetal-multilib.yaml
@@ -25,6 +25,23 @@
 # RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY %s
 # CHECK-PRINT-MULTI-DIRECTORY: arm-none-eabi/thumb/v8-m.main/fp
 
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c++ %s -### -o %t.out 2>&1 \
+# RUN: --target=thumbv8.1m.main-none-eabihf -fno-exceptions --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib --check-prefix=CHECK-LAYERED-MULTILIB %s
+# CHECK-LAYERED-MULTILIB:  "-cc1" "-triple" "thumbv8.1m.main-none-unknown-eabihf"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/include/c++/v1"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/include/c++/v1"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/include"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/include"
+# CHECK-LAYERED-MULTILIB-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/lib"
+# CHECK-LAYERED-MULTILIB-SAME: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/lib"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: --target=thumbv8.1m.main-none-eabihf -fno-exceptions --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-LAYERED-PRINT-MULTI-DIRECTORY %s
+# CHECK-LAYERED-PRINT-MULTI-DIRECTORY:  arm-none-eabi/thumb/v8.1-m.main/fp
+# CHECK-LAYERED-PRINT-MULTI-DIRECTORY-NEXT: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept
+
 # RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
 # RUN: --target=arm-none-eabi --sysroot= \
 # RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
@@ -38,6 +55,7 @@
 # CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/fp;@-target=thumbv8m.main-none-eabihf
 # CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/fp;@-target=thumbv8.1m.main-none-eabihf
 # CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/nofp/mve;@-target=arm-none-eabihf@march=armv8.1m.main+nofp+mve
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept;@-target=thumbv8.1m.main-none-eabihf@fno-exceptions
 
 # RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x assembler -mexecute-only \
 # RUN: --target=arm-none-eabi --sysroot= %s -c -### 2>&1 \
@@ -118,6 +136,14 @@
   Flags: [target=thumbv8.1m.main-none-unknown-eabihf, march=+mve]
   PrintOptions: [--target=arm-none-eabihf, -march=armv8.1m.main+nofp+mve]
 
+# A specialisation of v8.1-m.main/fp without exceptions.
+# This layers over the top of the regular v8.1-m.main/fp so it doesn't
+# need to have its own include directory or C library, thereby saving
+# disk space.
+- Dir: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept
+  Flags: [target=thumbv8.1m.main-none-unknown-eabihf, hasfpu, fno-exceptions]
+  PrintOptions: [--target=thumbv8.1m.main-none-eabihf, -fno-exceptions]
+
 
 # The second section of the file is a map from auto-detected flags
 # to custom flags. The auto-detected flags can be printed out
Index: clang/lib/Driver/ToolChains/BareMetal.h
===
--- clang/lib/Driver/ToolChains/BareMetal.h
+++ clang/lib/Driver/ToolChains/BareMetal.h
@@ -71,6 +71,9 @@
   void AddLinkRuntimeLib(const llvm::opt::ArgList ,
  llvm::opt::ArgStringList ) const;
   std::string computeSysRoot() const override;
+
+private:
+  llvm::SmallVector getOrderedMultilibs() const;
 };
 
 } // namespace toolchains
Index: clang/lib/Driver/ToolChains/BareMetal.cpp
===
--- clang/lib/Driver/ToolChains/BareMetal.cpp
+++ clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -103,9 +103,12 @@
   findMultilibs(D, Triple, Args);
   SmallString<128> SysRoot(computeSysRoot());
   if (!SysRoot.empty()) {
-llvm::sys::path::append(SysRoot, "lib");
-getFilePaths().push_back(std::string(SysRoot));
-getLibraryPaths().push_back(std::string(SysRoot));
+for (const Multilib  : getOrderedMultilibs()) {
+  SmallString<128> Dir(SysRoot);
+  llvm::sys::path::append(Dir, M.osSuffix(), "lib");
+  

[PATCH] D143587: [Docs] Multilib design

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505053.
michaelplatings added a comment.

tags->flags


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143587/new/

https://reviews.llvm.org/D143587

Files:
  clang/docs/Multilib.rst
  clang/docs/index.rst
  clang/include/clang/Driver/Multilib.h

Index: clang/include/clang/Driver/Multilib.h
===
--- clang/include/clang/Driver/Multilib.h
+++ clang/include/clang/Driver/Multilib.h
@@ -66,6 +66,8 @@
   /// options and look similar to them, and others can be defined by a
   /// particular multilib.yaml. A multilib is considered compatible if its flags
   /// are a subset of the flags derived from the Clang command line options.
+  /// See clang/docs/Multilib.rst for further explanation of how flags may be
+  /// generated and used.
   const flag_set () const { return Flags; }
 
   /// Returns the options that should be used for clang -print-multi-lib
Index: clang/docs/index.rst
===
--- clang/docs/index.rst
+++ clang/docs/index.rst
@@ -100,6 +100,7 @@
CodeOwners
InternalsManual
DriverInternals
+   Multilib
OffloadingDesign
PCHInternals
ItaniumMangleAbiTags
Index: clang/docs/Multilib.rst
===
--- /dev/null
+++ clang/docs/Multilib.rst
@@ -0,0 +1,327 @@
+
+Multilib
+
+
+Introduction
+
+
+This document describes how multilib is implemented in Clang.
+
+What is multilib and why might you care?
+If you're :doc:`cross compiling` then you can't use native
+system headers and libraries. To address this, you can use a combination of
+``--sysroot``, ``-isystem`` and ``-L`` options to point Clang at suitable
+directories for your target.
+However, when there are many possible directories to choose from, it's not
+necessarily obvious which one to pick.
+Multilib allows a toolchain designer to imbue the toolchain with the ability to
+pick a suitable directory automatically, based on the options the user provides
+to Clang. For example, if the user specifies
+``--target=arm-none-eabi -mcpu=cortex-m4`` the toolchain can choose a directory
+containing headers and libraries suitable for Armv7E-M, because it knows that's
+a suitable architecture for Arm Cortex-M4.
+Multilib can also choose between libraries for the same architecture based on
+other options. For example if the user specifies ``-fno-exceptions`` then a
+toolchain could select libraries built without exception support, thereby
+reducing the size of the resulting binary.
+
+Design
+==
+
+Clang supports GCC's ``-print-multi-lib`` and ``-print-multi-directory``
+options. These are described in
+`GCC Developer Options `_.
+
+There are two ways to configure multilib in Clang: hard-coded or via a
+configuration file.
+
+Hard-coded Multilib
+===
+
+The available libraries can be hard-coded in Clang. Typically this is done
+using the ``MultilibBuilder`` interface in
+``clang/include/clang/Driver/MultilibBuilder.h``.
+There are many examples of this in ``lib/Driver/ToolChains/Gnu.cpp``.
+The remainder of this document will not focus on this type of multilib.
+
+EXPERIMENTAL Multilib via configuration file
+
+
+Some Clang toolchains support loading multilib configuration from a
+``multilib.yaml`` configuration file.
+
+A ``multilib.yaml`` configuration file specifies which multilib variants are
+available, their relative location, what compilation options were used to build
+them, and the criteria by which they are selected.
+
+Multilib processing
+===
+
+Clang goes through the following steps to use multilib from a configuration
+file:
+#. Convert command line options to flags. Clang can accept the same
+   information via different options - for example,
+   ``--target=arm-none-eabi -march=armv7-m`` and
+   ``--target=armv7m-none-eabi`` are equivalent. Clang can also accept many
+   independent pieces of information within a single option - for example
+   ``-march=armv8.1m.main+fp+mve`` specifies the architecture and two
+   extensions in a single command line option.
+   To make it easier for the multilib system, Clang converts the command line
+   options into a standard set of simpler "flags". In many cases these flags
+   will look like a command line option with the leading ``-`` stripped off,
+   but where a suitable form for the flag doesn't exist in command line
+   options then its form will be different. For example, an Arm architecture
+   extension is represented like ``march=+mve`` since there's no way to specify
+   it in isolation in a command line option.
+   To see what flags are emitted for a given set of command line options, use
+   the 

[PATCH] D142933: Add -print-multi-selection-flags-experimental option

2023-03-15 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505643.
michaelplatings marked 2 inline comments as done.
michaelplatings added a comment.

Rebase on D146141 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142933/new/

https://reviews.llvm.org/D142933

Files:
  clang/include/clang/Driver/Options.td
  clang/include/clang/Driver/ToolChain.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/test/Driver/print-multi-selection-flags.c

Index: clang/test/Driver/print-multi-selection-flags.c
===
--- /dev/null
+++ clang/test/Driver/print-multi-selection-flags.c
@@ -0,0 +1,54 @@
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-linux -fc++-abi=itanium -fsanitize=address | FileCheck --check-prefix=CHECK-LINUX %s
+// CHECK-LINUX: fc++-abi=itanium
+// CHECK-LINUX: fexceptions
+// CHECK-LINUX: frtti
+// CHECK-LINUX: fsanitize=address
+// CHECK-LINUX: target=aarch64-unknown-linux
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-fuchsia -fsanitize=hwaddress | FileCheck --check-prefix=CHECK-FUCHSIA %s
+// CHECK-FUCHSIA: fsanitize=hwaddress
+// CHECK-FUCHSIA: target=aarch64-unknown-fuchsia
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=soft -fno-exceptions -fno-rtti | FileCheck --check-prefix=CHECK-ARMV4T %s
+// CHECK-ARMV4T: fno-exceptions
+// CHECK-ARMV4T: fno-rtti
+// CHECK-ARMV4T: mfloat-abi=soft
+// CHECK-ARMV4T: mfpu=none
+// CHECK-ARMV4T: target=armv4t-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=armv7em-none-eabi -mfloat-abi=softfp | FileCheck --check-prefix=CHECK-SOFTFP %s
+// CHECK-SOFTFP: mfloat-abi=softfp
+// CHECK-SOFTFP: mfpu=fpv4-sp-d16
+// CHECK-SOFTFP: target=thumbv7em-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabihf -march=armv7em -mfpu=fpv5-d16 | FileCheck --check-prefix=CHECK-HARD %s
+// CHECK-HARD: mfloat-abi=hard
+// CHECK-HARD: mfpu=fpv5-d16
+// CHECK-HARD: target=thumbv7em-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=soft -march=armv8-m.main+nofp | FileCheck --check-prefix=CHECK-V8MMAIN-NOFP %s
+// CHECK-V8MMAIN-NOFP: mfloat-abi=soft
+// CHECK-V8MMAIN-NOFP: mfpu=none
+// CHECK-V8MMAIN-NOFP: target=thumbv8m.main-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=hard -march=armv8.1m.main+mve.fp | FileCheck --check-prefix=CHECK-MVE %s
+// CHECK-MVE: march=+mve
+// CHECK-MVE: march=+mve.fp
+// CHECK-MVE: mfloat-abi=hard
+// CHECK-MVE: mfpu=fp-armv8-fullfp16-sp-d16
+// CHECK-MVE: target=thumbv8.1m.main-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -march=armv8.1m.main+mve+nofp | FileCheck --check-prefix=CHECK-MVENOFP %s
+// CHECK-MVENOFP: march=+mve
+// CHECK-MVENOFP-NOT: march=+mve.fp
+// CHECK-MVENOFP: mfpu=none
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-none-elf -march=armv8-a+lse | FileCheck --check-prefix=CHECK-LSE %s
+// CHECK-LSE: march=+lse
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-none-elf -march=armv8.5-a+sve+sve2 | FileCheck --check-prefix=CHECK-SVE2 %s
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-none-elf -march=armv9-a| FileCheck --check-prefix=CHECK-SVE2 %s
+// CHECK-SVE2: march=+simd
+// CHECK-SVE2: march=+sve
+// CHECK-SVE2: march=+sve2
+// CHECK-SVE2: target=aarch64-none-unknown-elf
Index: clang/lib/Driver/ToolChains/Arch/ARM.h
===
--- clang/lib/Driver/ToolChains/Arch/ARM.h
+++ clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -63,9 +63,11 @@
 void getARMArchCPUFromArgs(const llvm::opt::ArgList ,
llvm::StringRef , llvm::StringRef ,
bool FromAs = false);
-void getARMTargetFeatures(const Driver , const llvm::Triple ,
-  const llvm::opt::ArgList ,
-  std::vector , bool ForAS);
+llvm::ARM::FPUKind getARMTargetFeatures(const Driver ,
+const llvm::Triple ,
+const llvm::opt::ArgList ,
+std::vector ,
+bool ForAS);
 int getARMSubArchVersionNumber(const llvm::Triple );
 bool isARMMProfile(const llvm::Triple );
 bool isARMAProfile(const llvm::Triple );
Index: clang/lib/Driver/ToolChains/Arch/ARM.cpp
===
--- clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ 

[PATCH] D142986: Enable multilib.yaml in the BareMetal ToolChain

2023-03-15 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505644.
michaelplatings added a comment.

Rebase on D146141 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142986/new/

https://reviews.llvm.org/D142986

Files:
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/test/Driver/baremetal-multilib.yaml
  clang/test/Driver/baremetal.cpp
  clang/test/Driver/lit.local.cfg

Index: clang/test/Driver/lit.local.cfg
===
--- clang/test/Driver/lit.local.cfg
+++ clang/test/Driver/lit.local.cfg
@@ -1,7 +1,7 @@
 from lit.llvm import llvm_config
 
 config.suffixes = ['.c', '.cpp', '.cppm', '.h', '.m', '.mm', '.S', '.s', '.f90', '.F90', '.f95',
-   '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hipi', '.hlsl']
+   '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hipi', '.hlsl', '.yaml']
 config.substitutions = list(config.substitutions)
 config.substitutions.insert(0,
 ('%clang_cc1',
Index: clang/test/Driver/baremetal.cpp
===
--- clang/test/Driver/baremetal.cpp
+++ clang/test/Driver/baremetal.cpp
@@ -118,9 +118,9 @@
 // Verify that the bare metal driver does not include any host system paths:
 // CHECK-AARCH64-NO-HOST-INC: InstalledDir: [[INSTALLEDDIR:.+]]
 // CHECK-AARCH64-NO-HOST-INC: "-resource-dir" "[[RESOURCE:[^"]+]]"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include{{[/\\]+}}c++{{[/\\]+}}v1"
 // CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[RESOURCE]]{{[/\\]+}}include"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include"
 
 // RUN: %clang %s -### --target=riscv64-unknown-elf -o %t.out -L some/directory/user/asked/for \
 // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf 2>&1 \
Index: clang/test/Driver/baremetal-multilib.yaml
===
--- /dev/null
+++ clang/test/Driver/baremetal-multilib.yaml
@@ -0,0 +1,142 @@
+# REQUIRES: shell
+# UNSUPPORTED: system-windows
+
+# RUN: rm -rf %T/baremetal_multilib
+# RUN: mkdir -p %T/baremetal_multilib/bin
+# RUN: mkdir -p %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib
+# RUN: touch %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib/libclang_rt.builtins.a
+# RUN: ln -s %clang %T/baremetal_multilib/bin/clang
+# RUN: ln -s %s %T/baremetal_multilib/lib/clang-runtimes/multilib.yaml
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c++ %s -### -o %t.out 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib %s
+# CHECK:  "-cc1" "-triple" "thumbv8m.main-none-unknown-eabihf"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include/c++/v1"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include"
+# CHECK-SAME: "-x" "c++" "{{.*}}baremetal-multilib.yaml"
+# CHECK-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic"
+# CHECK-SAME: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib"
+# CHECK-SAME: "-lc" "-lm" "-lclang_rt.builtins"
+# CHECK-SAME: "-o" "{{.*}}.tmp.out"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY %s
+# CHECK-PRINT-MULTI-DIRECTORY: arm-none-eabi/thumb/v8-m.main/fp
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
+# RUN: --target=arm-none-eabi --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v6-m/nofp;@-target=thumbv6m-none-eabi@mfloat-abi=soft
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7-m/nofp;@-target=thumbv7m-none-eabi@mfloat-abi=soft
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7e-m/nofp;@-target=thumbv7em-none-eabi@mfloat-abi=soft@mfpu=none
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/nofp;@-target=arm-none-eabi@mfloat-abi=soft@march=armv8m.main+nofp
+# CHECK-PRINT-MULTI-LIB: 

[PATCH] D142933: Add -print-multi-selection-flags-experimental option

2023-03-15 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added inline comments.



Comment at: clang/lib/Driver/ToolChain.cpp:237-245
+  // Enumerate boolean flags we care about for the purposes of multilib here.
+  // There must be a smarter way to do it but this gets us started.
+  const struct HasFlag {
+ID Pos, Neg;
+bool Default;
+  } HasFlagList[] = {
+  {OPT_fexceptions, OPT_fno_exceptions, true},

phosek wrote:
> Would it be possible to add this information to 
> https://github.com/llvm/llvm-project/blob/main/clang/include/clang/Driver/Options.td?
>  I think that would be more maintainable.
I thought about that, and it would be nice - it's a shame that this information 
gets copy-pasted across the Clang sources - there are already 5 or so places 
that do this. However for this change I think that would be too much scope 
creep so I've stuck with the status quo.



Comment at: clang/lib/Driver/ToolChains/Arch/ARM.cpp:441
+   std::vector , bool ForAS,
+   unsigned *OutFPUKind) {
   bool KernelOrKext =

phosek wrote:
> Can we use `ARM::FPUKind` as a type here?
I made a new change, D146141, that makes this possible. I've rebased this patch 
on that change now so this is done.



Comment at: clang/lib/Driver/ToolChains/Arch/ARM.cpp:556
   // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=.
   unsigned FPUID = llvm::ARM::FK_INVALID;
   const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ);

phosek wrote:
> Is this variable used anywhere in this function?
Yes, although previously in this scope only for `FPUID == llvm::ARM::FK_NONE`. 
Now we're using it more since we're returning it.



Comment at: clang/lib/Driver/ToolChains/Arch/ARM.h:70
+  std::vector , bool ForAS,
+  unsigned *OutFPUKind = nullptr);
 int getARMSubArchVersionNumber(const llvm::Triple );

phosek wrote:
> Using output argument isn't very common in LLVM and even in this particular 
> case seems a bit ad-hoc. I'm wondering if we could instead extract this logic 
> into a new function, for example `getARMFPUFeatures`?
It's not unusual in this area of the code. Usually the name is `ArgFPUKind` 
which I don't find descriptive so I went with `OutFPUKind` to make it clearer 
that it's an output of the function. However since the function had return type 
`void` I've now simply changed it to return `FPUKind` directly.

I spent a chunk of time looking into whether I could get a separate 
FPU-specific function. Finding the FPU is tightly coupled across a lot of code 
with finding the architecture and CPU. Although I'm sure the code could be 
better structured, the problem is also inherent because the floating point 
support is dependent on `-mfpu`, `-march`, `-mcpu`, `--target`, `-mfloat-abi` 
and possibly others so figuring everything out requires parsing many options. 
In short, I think returning FPUKind is the lesser evil here, even if it does 
seem a bit ad-hoc.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142933/new/

https://reviews.llvm.org/D142933

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D142986: Enable multilib.yaml in the BareMetal ToolChain

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505286.
michaelplatings added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142986/new/

https://reviews.llvm.org/D142986

Files:
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/test/Driver/baremetal-multilib.yaml
  clang/test/Driver/baremetal.cpp
  clang/test/Driver/lit.local.cfg

Index: clang/test/Driver/lit.local.cfg
===
--- clang/test/Driver/lit.local.cfg
+++ clang/test/Driver/lit.local.cfg
@@ -1,7 +1,7 @@
 from lit.llvm import llvm_config
 
 config.suffixes = ['.c', '.cpp', '.cppm', '.h', '.m', '.mm', '.S', '.s', '.f90', '.F90', '.f95',
-   '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hipi', '.hlsl']
+   '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hipi', '.hlsl', '.yaml']
 config.substitutions = list(config.substitutions)
 config.substitutions.insert(0,
 ('%clang_cc1',
Index: clang/test/Driver/baremetal.cpp
===
--- clang/test/Driver/baremetal.cpp
+++ clang/test/Driver/baremetal.cpp
@@ -118,9 +118,9 @@
 // Verify that the bare metal driver does not include any host system paths:
 // CHECK-AARCH64-NO-HOST-INC: InstalledDir: [[INSTALLEDDIR:.+]]
 // CHECK-AARCH64-NO-HOST-INC: "-resource-dir" "[[RESOURCE:[^"]+]]"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include{{[/\\]+}}c++{{[/\\]+}}v1"
 // CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[RESOURCE]]{{[/\\]+}}include"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include"
 
 // RUN: %clang %s -### --target=riscv64-unknown-elf -o %t.out -L some/directory/user/asked/for \
 // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf 2>&1 \
Index: clang/test/Driver/baremetal-multilib.yaml
===
--- /dev/null
+++ clang/test/Driver/baremetal-multilib.yaml
@@ -0,0 +1,142 @@
+# REQUIRES: shell
+# UNSUPPORTED: system-windows
+
+# RUN: rm -rf %T/baremetal_multilib
+# RUN: mkdir -p %T/baremetal_multilib/bin
+# RUN: mkdir -p %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib
+# RUN: touch %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib/libclang_rt.builtins.a
+# RUN: ln -s %clang %T/baremetal_multilib/bin/clang
+# RUN: ln -s %s %T/baremetal_multilib/lib/clang-runtimes/multilib.yaml
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c++ %s -### -o %t.out 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib %s
+# CHECK:  "-cc1" "-triple" "thumbv8m.main-none-unknown-eabihf"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include/c++/v1"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include"
+# CHECK-SAME: "-x" "c++" "{{.*}}baremetal-multilib.yaml"
+# CHECK-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic"
+# CHECK-SAME: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib"
+# CHECK-SAME: "-lc" "-lm" "-lclang_rt.builtins"
+# CHECK-SAME: "-o" "{{.*}}.tmp.out"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY %s
+# CHECK-PRINT-MULTI-DIRECTORY: arm-none-eabi/thumb/v8-m.main/fp
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
+# RUN: --target=arm-none-eabi --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v6-m/nofp;@-target=thumbv6m-none-eabi@mfloat-abi=soft
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7-m/nofp;@-target=thumbv7m-none-eabi@mfloat-abi=soft
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7e-m/nofp;@-target=thumbv7em-none-eabi@mfloat-abi=soft@mfpu=none
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/nofp;@-target=arm-none-eabi@mfloat-abi=soft@march=armv8m.main+nofp
+# CHECK-PRINT-MULTI-LIB: 

[PATCH] D142986: Enable multilib.yaml in the BareMetal ToolChain

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added inline comments.



Comment at: clang/lib/Driver/ToolChains/BareMetal.cpp:184
+  SmallString<128> MultilibPath(SysRootDir);
+  llvm::sys::path::append(MultilibPath, MULTILIB_YAML_FILENAME);
+

phosek wrote:
> Rather than hardcoding the filename and the location, which is inflexible, 
> could we instead provide a command line option to specify the file to use?
I'm not opposed to that in principle but I'd rather leave that as an option for 
a future change. At this point, for LLVM Embedded Toolchain for Arm our intent 
is that users will specify `--sysroot` if they want to use a separate set of 
multilibs.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142986/new/

https://reviews.llvm.org/D142986

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143587: [Docs] Multilib design

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505293.
michaelplatings added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143587/new/

https://reviews.llvm.org/D143587

Files:
  clang/docs/Multilib.rst
  clang/docs/index.rst
  clang/include/clang/Driver/Multilib.h

Index: clang/include/clang/Driver/Multilib.h
===
--- clang/include/clang/Driver/Multilib.h
+++ clang/include/clang/Driver/Multilib.h
@@ -72,6 +72,8 @@
   /// options and look similar to them, and others can be defined by a
   /// particular multilib.yaml. A multilib is considered compatible if its flags
   /// are a subset of the flags derived from the Clang command line options.
+  /// See clang/docs/Multilib.rst for further explanation of how flags may be
+  /// generated and used.
   const flags_list () const { return Flags; }
 
   /// Returns the options that should be used for clang -print-multi-lib
Index: clang/docs/index.rst
===
--- clang/docs/index.rst
+++ clang/docs/index.rst
@@ -100,6 +100,7 @@
CodeOwners
InternalsManual
DriverInternals
+   Multilib
OffloadingDesign
PCHInternals
ItaniumMangleAbiTags
Index: clang/docs/Multilib.rst
===
--- /dev/null
+++ clang/docs/Multilib.rst
@@ -0,0 +1,327 @@
+
+Multilib
+
+
+Introduction
+
+
+This document describes how multilib is implemented in Clang.
+
+What is multilib and why might you care?
+If you're :doc:`cross compiling` then you can't use native
+system headers and libraries. To address this, you can use a combination of
+``--sysroot``, ``-isystem`` and ``-L`` options to point Clang at suitable
+directories for your target.
+However, when there are many possible directories to choose from, it's not
+necessarily obvious which one to pick.
+Multilib allows a toolchain designer to imbue the toolchain with the ability to
+pick a suitable directory automatically, based on the options the user provides
+to Clang. For example, if the user specifies
+``--target=arm-none-eabi -mcpu=cortex-m4`` the toolchain can choose a directory
+containing headers and libraries suitable for Armv7E-M, because it knows that's
+a suitable architecture for Arm Cortex-M4.
+Multilib can also choose between libraries for the same architecture based on
+other options. For example if the user specifies ``-fno-exceptions`` then a
+toolchain could select libraries built without exception support, thereby
+reducing the size of the resulting binary.
+
+Design
+==
+
+Clang supports GCC's ``-print-multi-lib`` and ``-print-multi-directory``
+options. These are described in
+`GCC Developer Options `_.
+
+There are two ways to configure multilib in Clang: hard-coded or via a
+configuration file.
+
+Hard-coded Multilib
+===
+
+The available libraries can be hard-coded in Clang. Typically this is done
+using the ``MultilibBuilder`` interface in
+``clang/include/clang/Driver/MultilibBuilder.h``.
+There are many examples of this in ``lib/Driver/ToolChains/Gnu.cpp``.
+The remainder of this document will not focus on this type of multilib.
+
+EXPERIMENTAL Multilib via configuration file
+
+
+Some Clang toolchains support loading multilib configuration from a
+``multilib.yaml`` configuration file.
+
+A ``multilib.yaml`` configuration file specifies which multilib variants are
+available, their relative location, what compilation options were used to build
+them, and the criteria by which they are selected.
+
+Multilib processing
+===
+
+Clang goes through the following steps to use multilib from a configuration
+file:
+#. Convert command line options to flags. Clang can accept the same
+   information via different options - for example,
+   ``--target=arm-none-eabi -march=armv7-m`` and
+   ``--target=armv7m-none-eabi`` are equivalent. Clang can also accept many
+   independent pieces of information within a single option - for example
+   ``-march=armv8.1m.main+fp+mve`` specifies the architecture and two
+   extensions in a single command line option.
+   To make it easier for the multilib system, Clang converts the command line
+   options into a standard set of simpler "flags". In many cases these flags
+   will look like a command line option with the leading ``-`` stripped off,
+   but where a suitable form for the flag doesn't exist in command line
+   options then its form will be different. For example, an Arm architecture
+   extension is represented like ``march=+mve`` since there's no way to specify
+   it in isolation in a command line option.
+   To see what flags are emitted for a given set of command line options, use
+   the ``-print-multi-selection-flags-experimental`` 

[PATCH] D142933: Add -print-multi-selection-flags-experimental option

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505284.
michaelplatings added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142933/new/

https://reviews.llvm.org/D142933

Files:
  clang/include/clang/Driver/Options.td
  clang/include/clang/Driver/ToolChain.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/test/Driver/print-multi-selection-flags.c

Index: clang/test/Driver/print-multi-selection-flags.c
===
--- /dev/null
+++ clang/test/Driver/print-multi-selection-flags.c
@@ -0,0 +1,54 @@
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-linux -fc++-abi=itanium -fsanitize=address | FileCheck --check-prefix=CHECK-LINUX %s
+// CHECK-LINUX: fc++-abi=itanium
+// CHECK-LINUX: fexceptions
+// CHECK-LINUX: frtti
+// CHECK-LINUX: fsanitize=address
+// CHECK-LINUX: target=aarch64-unknown-linux
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-fuchsia -fsanitize=hwaddress | FileCheck --check-prefix=CHECK-FUCHSIA %s
+// CHECK-FUCHSIA: fsanitize=hwaddress
+// CHECK-FUCHSIA: target=aarch64-unknown-fuchsia
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=soft -fno-exceptions -fno-rtti | FileCheck --check-prefix=CHECK-ARMV4T %s
+// CHECK-ARMV4T: fno-exceptions
+// CHECK-ARMV4T: fno-rtti
+// CHECK-ARMV4T: mfloat-abi=soft
+// CHECK-ARMV4T: mfpu=none
+// CHECK-ARMV4T: target=armv4t-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=armv7em-none-eabi -mfloat-abi=softfp | FileCheck --check-prefix=CHECK-SOFTFP %s
+// CHECK-SOFTFP: mfloat-abi=softfp
+// CHECK-SOFTFP: mfpu=fpv4-sp-d16
+// CHECK-SOFTFP: target=thumbv7em-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabihf -march=armv7em -mfpu=fpv5-d16 | FileCheck --check-prefix=CHECK-HARD %s
+// CHECK-HARD: mfloat-abi=hard
+// CHECK-HARD: mfpu=fpv5-d16
+// CHECK-HARD: target=thumbv7em-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=soft -march=armv8-m.main+nofp | FileCheck --check-prefix=CHECK-V8MMAIN-NOFP %s
+// CHECK-V8MMAIN-NOFP: mfloat-abi=soft
+// CHECK-V8MMAIN-NOFP: mfpu=none
+// CHECK-V8MMAIN-NOFP: target=thumbv8m.main-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=hard -march=armv8.1m.main+mve.fp | FileCheck --check-prefix=CHECK-MVE %s
+// CHECK-MVE: march=+mve
+// CHECK-MVE: march=+mve.fp
+// CHECK-MVE: mfloat-abi=hard
+// CHECK-MVE: mfpu=fp-armv8-fullfp16-sp-d16
+// CHECK-MVE: target=thumbv8.1m.main-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -march=armv8.1m.main+mve+nofp | FileCheck --check-prefix=CHECK-MVENOFP %s
+// CHECK-MVENOFP: march=+mve
+// CHECK-MVENOFP-NOT: march=+mve.fp
+// CHECK-MVENOFP: mfpu=none
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-none-elf -march=armv8-a+lse | FileCheck --check-prefix=CHECK-LSE %s
+// CHECK-LSE: march=+lse
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-none-elf -march=armv8.5-a+sve+sve2 | FileCheck --check-prefix=CHECK-SVE2 %s
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-none-elf -march=armv9-a| FileCheck --check-prefix=CHECK-SVE2 %s
+// CHECK-SVE2: march=+simd
+// CHECK-SVE2: march=+sve
+// CHECK-SVE2: march=+sve2
+// CHECK-SVE2: target=aarch64-none-unknown-elf
Index: clang/lib/Driver/ToolChains/Arch/ARM.h
===
--- clang/lib/Driver/ToolChains/Arch/ARM.h
+++ clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -63,9 +63,11 @@
 void getARMArchCPUFromArgs(const llvm::opt::ArgList ,
llvm::StringRef , llvm::StringRef ,
bool FromAs = false);
+// Optionally returns the FPUKind
 void getARMTargetFeatures(const Driver , const llvm::Triple ,
   const llvm::opt::ArgList ,
-  std::vector , bool ForAS);
+  std::vector , bool ForAS,
+  unsigned *OutFPUKind = nullptr);
 int getARMSubArchVersionNumber(const llvm::Triple );
 bool isARMMProfile(const llvm::Triple );
 bool isARMAProfile(const llvm::Triple );
Index: clang/lib/Driver/ToolChains/Arch/ARM.cpp
===
--- clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -437,7 +437,8 @@
 
 void arm::getARMTargetFeatures(const Driver , const llvm::Triple ,
const ArgList ,
-   std::vector , bool ForAS) {
+   

[PATCH] D142905: [Driver] Change multilib selection algorithm

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505279.
michaelplatings marked an inline comment as done.
michaelplatings added a comment.

Calculate the output for -print-multi-lib lazily.
This necessitated returning to using std::vector to store flags to avoid 
reordering them.
In theory the big-O time to select a multilib is larger now but in practise the 
number of flags is small enough that in practice this is about 2 microseconds 
faster per clang invocation.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142905/new/

https://reviews.llvm.org/D142905

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/MultilibBuilder.h
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/MultilibBuilder.cpp
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -33,14 +33,14 @@
 }
 
 TEST(MultilibTest, OpEqReflexivity3) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same";
 }
 
 TEST(MultilibTest, OpEqInequivalence1) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"-foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"-foo"});
   ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same";
   ASSERT_FALSE(M2 == M1)
   << "Multilibs with conflicting flags are not the same (commuted)";
@@ -48,7 +48,7 @@
 
 TEST(MultilibTest, OpEqInequivalence2) {
   Multilib M1;
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different";
 }
 
@@ -124,7 +124,7 @@
 }
 
 TEST(MultilibTest, Construction3) {
-  Multilib M({}, {}, {}, 0, {"+f1", "+f2", "-f3"});
+  Multilib M({}, {}, {}, {"+f1", "+f2", "-f3"});
   for (Multilib::flags_list::const_iterator I = M.flags().begin(),
 E = M.flags().end();
I != E; ++I) {
@@ -149,8 +149,8 @@
 
 TEST(MultilibTest, SetPriority) {
   MultilibSet MS({
-  Multilib("/foo", {}, {}, 1, {"+foo"}),
-  Multilib("/bar", {}, {}, 2, {"+bar"}),
+  Multilib("/foo", {}, {}, {"+foo"}),
+  Multilib("/bar", {}, {}, {"+bar"}),
   });
   Multilib::flags_list Flags1 = {"+foo", "-bar"};
   Multilib Selection1;
@@ -166,3 +166,24 @@
   ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
   << "Selection picked " << Selection2 << " which was not expected";
 }
+
+TEST(MultilibTest, SelectMultiple) {
+  MultilibSet MS({
+  Multilib("/a", {}, {}, {"x"}),
+  Multilib("/b", {}, {}, {"y"}),
+  });
+  std::vector Selection;
+
+  Selection = MS.select({"x"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/b", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y", "x"});
+  ASSERT_EQ(2u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+  EXPECT_EQ("/b", Selection[1].gccSuffix());
+}
Index: clang/unittests/Driver/MultilibBuilderTest.cpp
===
--- clang/unittests/Driver/MultilibBuilderTest.cpp
+++ clang/unittests/Driver/MultilibBuilderTest.cpp
@@ -207,3 +207,14 @@
 << "Selection picked " << Selection << " which was not expected ";
   }
 }
+
+TEST(MultilibBuilderTest, PrintOptions) {
+  Multilib M = MultilibBuilder()
+   .flag("+x")
+   .flag("-y")
+   .flag("+a")
+   .flag("-b")
+   .flag("+c")
+   .makeMultilib();
+  ASSERT_EQ(Multilib::flags_list({"-x", "-a", "-c"}), M.getPrintOptions());
+}
Index: clang/lib/Driver/ToolChains/Fuchsia.cpp
===
--- clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -263,33 +263,33 @@
 
   Multilibs.push_back(Multilib());
   // Use the noexcept variant with -fno-exceptions to avoid the extra overhead.
-  Multilibs.push_back(MultilibBuilder("noexcept", {}, {}, 1)
+  Multilibs.push_back(MultilibBuilder("noexcept", {}, {})
   .flag("-fexceptions")
   .flag("+fno-exceptions")
   .makeMultilib());
   // ASan has higher priority because we always want the instrumentated version.
-  Multilibs.push_back(MultilibBuilder("asan", {}, {}, 2)
+  Multilibs.push_back(MultilibBuilder("asan", {}, {})
   .flag("+fsanitize=address")
   .makeMultilib());
  

[PATCH] D142932: Multilib YAML parsing

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505283.
michaelplatings marked 2 inline comments as done.
michaelplatings added a comment.

Decouple multilib versioning scheme from the Clang version


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142932/new/

https://reviews.llvm.org/D142932

Files:
  clang/include/clang/Driver/Multilib.h
  clang/lib/Driver/Multilib.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -13,6 +13,7 @@
 #include "clang/Driver/Multilib.h"
 #include "../../lib/Driver/ToolChains/CommonArgs.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/Version.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -187,3 +188,392 @@
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
 }
+
+static void diagnosticCallback(const llvm::SMDiagnostic , void *Out) {
+  *reinterpret_cast(Out) = D.getMessage();
+}
+
+static bool parseYaml(MultilibSet , std::string ,
+  const char *Data) {
+  return MS.parseYaml(llvm::MemoryBufferRef(Data, "TEST"), diagnosticCallback,
+  );
+}
+
+static bool parseYaml(MultilibSet , const char *Data) {
+  return MS.parseYaml(llvm::MemoryBufferRef(Data, "TEST"));
+}
+
+// When updating this version also update MultilibVersionCurrent in Multilib.cpp
+#define YAML_PREAMBLE "MultilibVersion: 1.0\n"
+
+TEST(MultilibTest, ParseInvalid) {
+  std::string Diagnostic;
+
+  MultilibSet MS;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, R"(
+Variants: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("missing required key 'MultilibVersion'"))
+  << Diagnostic;
+
+  // Reject files with a different major version
+  EXPECT_FALSE(parseYaml(MS, Diagnostic,
+ R"(
+MultilibVersion: 2.0
+Variants: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("Multilib version 2.0 is unsupported"))
+  << Diagnostic;
+  EXPECT_FALSE(parseYaml(MS, Diagnostic,
+ R"(
+MultilibVersion: 0.1
+Variants: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("Multilib version 0.1 is unsupported"))
+  << Diagnostic;
+
+  // Reject files with a later minor version
+  EXPECT_FALSE(parseYaml(MS, Diagnostic,
+ R"(
+MultilibVersion: 1.9
+Variants: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("Multilib version 1.9 is unsupported"))
+  << Diagnostic;
+
+  // Accept files with the same major version and the same or earlier minor
+  // version
+  EXPECT_TRUE(parseYaml(MS, Diagnostic, R"(
+MultilibVersion: 1.0
+Variants: []
+)")) << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Variants'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: /abc
+  Flags: []
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("paths must be relative"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Flags: []
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Dir'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: .
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Flags'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: .
+  Flags: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("missing required key 'PrintOptions'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants: []
+FlagMap:
+- Regex: abc
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic)
+  .contains("value required for 'MatchFlags' or 'NoMatchFlags'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants: []
+FlagMap:
+- Dir: .
+  Regex: '('
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("parentheses not balanced"))
+  << Diagnostic;
+}
+
+TEST(MultilibTest, Parse) {
+  MultilibSet MS;
+  EXPECT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
+Variants:
+- Dir: .
+  Flags: []
+  PrintOptions: []
+)"));
+  EXPECT_EQ(1U, MS.size());
+  EXPECT_EQ("", MS.begin()->gccSuffix());
+
+  EXPECT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
+Variants:
+- Dir: abc
+  Flags: []
+  PrintOptions: []
+)"));
+  EXPECT_EQ(1U, MS.size());
+  EXPECT_EQ("/abc", MS.begin()->gccSuffix());
+
+  EXPECT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
+Variants:
+- Dir: pqr
+  Flags: []
+  PrintOptions: [-mfloat-abi=soft]
+)"));
+  EXPECT_EQ(1U, MS.size());
+  

[PATCH] D143059: [Driver] Enable selecting multiple multilibs

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505288.
michaelplatings added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143059/new/

https://reviews.llvm.org/D143059

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/ToolChain.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/CSKYToolChain.cpp
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/lib/Driver/ToolChains/Gnu.h
  clang/lib/Driver/ToolChains/Hexagon.cpp
  clang/lib/Driver/ToolChains/Hurd.cpp
  clang/lib/Driver/ToolChains/Linux.cpp
  clang/lib/Driver/ToolChains/MipsLinux.cpp
  clang/lib/Driver/ToolChains/RISCVToolchain.cpp
  clang/test/Driver/fuchsia.cpp
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -154,18 +154,18 @@
   Multilib("/bar", {}, {}, {"+bar"}),
   });
   Multilib::flags_list Flags1 = {"+foo", "-bar"};
-  Multilib Selection1;
+  llvm::SmallVector Selection1;
   ASSERT_TRUE(MS.select(Flags1, Selection1))
   << "Flag set was {\"+foo\"}, but selection not found";
-  ASSERT_TRUE(Selection1.gccSuffix() == "/foo")
-  << "Selection picked " << Selection1 << " which was not expected";
+  ASSERT_TRUE(Selection1.back().gccSuffix() == "/foo")
+  << "Selection picked " << Selection1.back() << " which was not expected";
 
   Multilib::flags_list Flags2 = {"+foo", "+bar"};
-  Multilib Selection2;
+  llvm::SmallVector Selection2;
   ASSERT_TRUE(MS.select(Flags2, Selection2))
   << "Flag set was {\"+bar\"}, but selection not found";
-  ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
-  << "Selection picked " << Selection2 << " which was not expected";
+  ASSERT_TRUE(Selection2.back().gccSuffix() == "/bar")
+  << "Selection picked " << Selection2.back() << " which was not expected";
 }
 
 TEST(MultilibTest, SelectMultiple) {
@@ -173,17 +173,17 @@
   Multilib("/a", {}, {}, {"x"}),
   Multilib("/b", {}, {}, {"y"}),
   });
-  std::vector Selection;
+  llvm::SmallVector Selection;
 
-  Selection = MS.select({"x"});
+  ASSERT_TRUE(MS.select({"x"}, Selection));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
 
-  Selection = MS.select({"y"});
+  ASSERT_TRUE(MS.select({"y"}, Selection));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/b", Selection[0].gccSuffix());
 
-  Selection = MS.select({"y", "x"});
+  ASSERT_TRUE(MS.select({"y", "x"}, Selection));
   ASSERT_EQ(2u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
@@ -367,7 +367,7 @@
 
 TEST(MultilibTest, SelectSoft) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: s
@@ -386,7 +386,7 @@
 
 TEST(MultilibTest, SelectSoftFP) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: f
@@ -402,7 +402,7 @@
   // If hard float is all that's available then select that only if compiling
   // with hard float.
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: h
@@ -416,7 +416,7 @@
 
 TEST(MultilibTest, SelectFloatABI) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: s
@@ -437,18 +437,18 @@
   NoMatchFlags: [hasfp]
 )"));
   MS.select({"mfloat-abi=soft"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=softfp"}, Selected);
-  EXPECT_EQ("/f", Selected.gccSuffix());
+  EXPECT_EQ("/f", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=hard"}, Selected);
-  EXPECT_EQ("/h", Selected.gccSuffix());
+  EXPECT_EQ("/h", Selected.back().gccSuffix());
 }
 
 TEST(MultilibTest, SelectFloatABIReversed) {
   // If soft is specified after softfp then softfp will never be
   // selected because soft is compatible with softfp and last wins.
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: h
@@ -469,11 +469,11 @@
   NoMatchFlags: [hasfp]
 )"));
   MS.select({"mfloat-abi=soft"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=softfp"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=hard"}, Selected);
-  EXPECT_EQ("/h", 

[PATCH] D143075: BareMetal ToolChain multilib layering

2023-03-14 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505290.
michaelplatings added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143075/new/

https://reviews.llvm.org/D143075

Files:
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/BareMetal.h
  clang/test/Driver/baremetal-multilib.yaml

Index: clang/test/Driver/baremetal-multilib.yaml
===
--- clang/test/Driver/baremetal-multilib.yaml
+++ clang/test/Driver/baremetal-multilib.yaml
@@ -25,6 +25,23 @@
 # RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY %s
 # CHECK-PRINT-MULTI-DIRECTORY: arm-none-eabi/thumb/v8-m.main/fp
 
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c++ %s -### -o %t.out 2>&1 \
+# RUN: --target=thumbv8.1m.main-none-eabihf -fno-exceptions --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib --check-prefix=CHECK-LAYERED-MULTILIB %s
+# CHECK-LAYERED-MULTILIB:  "-cc1" "-triple" "thumbv8.1m.main-none-unknown-eabihf"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/include/c++/v1"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/include/c++/v1"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/include"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/include"
+# CHECK-LAYERED-MULTILIB-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/lib"
+# CHECK-LAYERED-MULTILIB-SAME: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/lib"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: --target=thumbv8.1m.main-none-eabihf -fno-exceptions --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-LAYERED-PRINT-MULTI-DIRECTORY %s
+# CHECK-LAYERED-PRINT-MULTI-DIRECTORY:  arm-none-eabi/thumb/v8.1-m.main/fp
+# CHECK-LAYERED-PRINT-MULTI-DIRECTORY-NEXT: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept
+
 # RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
 # RUN: --target=arm-none-eabi --sysroot= \
 # RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
@@ -38,6 +55,7 @@
 # CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/fp;@-target=thumbv8m.main-none-eabihf
 # CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/fp;@-target=thumbv8.1m.main-none-eabihf
 # CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/nofp/mve;@-target=arm-none-eabihf@march=armv8.1m.main+nofp+mve
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept;@-target=thumbv8.1m.main-none-eabihf@fno-exceptions
 
 # RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x assembler -mexecute-only \
 # RUN: --target=arm-none-eabi --sysroot= %s -c -### 2>&1 \
@@ -117,6 +135,14 @@
   Flags: [target=thumbv8.1m.main-none-unknown-eabihf, march=+mve]
   PrintOptions: [--target=arm-none-eabihf, -march=armv8.1m.main+nofp+mve]
 
+# A specialisation of v8.1-m.main/fp without exceptions.
+# This layers over the top of the regular v8.1-m.main/fp so it doesn't
+# need to have its own include directory or C library, thereby saving
+# disk space.
+- Dir: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept
+  Flags: [target=thumbv8.1m.main-none-unknown-eabihf, hasfpu, fno-exceptions]
+  PrintOptions: [--target=thumbv8.1m.main-none-eabihf, -fno-exceptions]
+
 
 # The second section of the file is a map from auto-detected flags
 # to custom flags. The auto-detected flags can be printed out
Index: clang/lib/Driver/ToolChains/BareMetal.h
===
--- clang/lib/Driver/ToolChains/BareMetal.h
+++ clang/lib/Driver/ToolChains/BareMetal.h
@@ -71,6 +71,9 @@
   void AddLinkRuntimeLib(const llvm::opt::ArgList ,
  llvm::opt::ArgStringList ) const;
   std::string computeSysRoot() const override;
+
+private:
+  llvm::SmallVector getOrderedMultilibs() const;
 };
 
 } // namespace toolchains
Index: clang/lib/Driver/ToolChains/BareMetal.cpp
===
--- clang/lib/Driver/ToolChains/BareMetal.cpp
+++ clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -103,9 +103,12 @@
   findMultilibs(D, Triple, Args);
   SmallString<128> SysRoot(computeSysRoot());
   if (!SysRoot.empty()) {
-llvm::sys::path::append(SysRoot, "lib");
-getFilePaths().push_back(std::string(SysRoot));
-getLibraryPaths().push_back(std::string(SysRoot));
+for (const Multilib  : getOrderedMultilibs()) {
+  SmallString<128> Dir(SysRoot);
+  llvm::sys::path::append(Dir, M.osSuffix(), "lib");
+  

[PATCH] D142905: [Driver] Change multilib selection algorithm

2023-03-22 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 507527.
michaelplatings marked an inline comment as done.
michaelplatings added a comment.

Add enum to Multilib class for how print options should be calculated.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142905/new/

https://reviews.llvm.org/D142905

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/MultilibBuilder.h
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/MultilibBuilder.cpp
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/OHOS.cpp
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -33,14 +33,14 @@
 }
 
 TEST(MultilibTest, OpEqReflexivity3) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same";
 }
 
 TEST(MultilibTest, OpEqInequivalence1) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"-foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"-foo"});
   ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same";
   ASSERT_FALSE(M2 == M1)
   << "Multilibs with conflicting flags are not the same (commuted)";
@@ -48,7 +48,7 @@
 
 TEST(MultilibTest, OpEqInequivalence2) {
   Multilib M1;
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different";
 }
 
@@ -124,7 +124,7 @@
 }
 
 TEST(MultilibTest, Construction3) {
-  Multilib M({}, {}, {}, 0, {"+f1", "+f2", "-f3"});
+  Multilib M({}, {}, {}, {"+f1", "+f2", "-f3"});
   for (Multilib::flags_list::const_iterator I = M.flags().begin(),
 E = M.flags().end();
I != E; ++I) {
@@ -149,8 +149,8 @@
 
 TEST(MultilibTest, SetPriority) {
   MultilibSet MS({
-  Multilib("/foo", {}, {}, 1, {"+foo"}),
-  Multilib("/bar", {}, {}, 2, {"+bar"}),
+  Multilib("/foo", {}, {}, {"+foo"}),
+  Multilib("/bar", {}, {}, {"+bar"}),
   });
   Multilib::flags_list Flags1 = {"+foo", "-bar"};
   Multilib Selection1;
@@ -166,3 +166,24 @@
   ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
   << "Selection picked " << Selection2 << " which was not expected";
 }
+
+TEST(MultilibTest, SelectMultiple) {
+  MultilibSet MS({
+  Multilib("/a", {}, {}, {"x"}),
+  Multilib("/b", {}, {}, {"y"}),
+  });
+  std::vector Selection;
+
+  Selection = MS.select({"x"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/b", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y", "x"});
+  ASSERT_EQ(2u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+  EXPECT_EQ("/b", Selection[1].gccSuffix());
+}
Index: clang/unittests/Driver/MultilibBuilderTest.cpp
===
--- clang/unittests/Driver/MultilibBuilderTest.cpp
+++ clang/unittests/Driver/MultilibBuilderTest.cpp
@@ -207,3 +207,14 @@
 << "Selection picked " << Selection << " which was not expected ";
   }
 }
+
+TEST(MultilibBuilderTest, PrintOptions) {
+  Multilib M = MultilibBuilder()
+   .flag("+x")
+   .flag("-y")
+   .flag("+a")
+   .flag("-b")
+   .flag("+c")
+   .makeMultilib();
+  ASSERT_EQ(Multilib::flags_list({"-x", "-a", "-c"}), M.getPrintOptions());
+}
Index: clang/lib/Driver/ToolChains/OHOS.cpp
===
--- clang/lib/Driver/ToolChains/OHOS.cpp
+++ clang/lib/Driver/ToolChains/OHOS.cpp
@@ -39,13 +39,13 @@
   // -mcpu=cortex-a7
   // -mfloat-abi=soft -mfloat-abi=softfp -mfloat-abi=hard
   // -mfpu=neon-vfpv4
-  Multilibs.push_back(Multilib("/a7_soft", {}, {}, 1,
+  Multilibs.push_back(Multilib("/a7_soft", {}, {},
   {"+mcpu=cortex-a7", "+mfloat-abi=soft"}));
 
-  Multilibs.push_back(Multilib("/a7_softfp_neon-vfpv4", {}, {}, 1,
+  Multilibs.push_back(Multilib("/a7_softfp_neon-vfpv4", {}, {},
   {"+mcpu=cortex-a7", "+mfloat-abi=softfp", "+mfpu=neon-vfpv4"}));
 
-  Multilibs.push_back(Multilib("/a7_hard_neon-vfpv4", {}, {}, 1,
+  Multilibs.push_back(Multilib("/a7_hard_neon-vfpv4", {}, {},
   {"+mcpu=cortex-a7", "+mfloat-abi=hard", "+mfpu=neon-vfpv4"}));
 
   if (Multilibs.select(Flags, Result.SelectedMultilib)) {
Index: clang/lib/Driver/ToolChains/Fuchsia.cpp
===
--- 

[PATCH] D142905: [Driver] Change multilib selection algorithm

2023-03-23 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 507864.
michaelplatings added a comment.

Move change to print options into D146757 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142905/new/

https://reviews.llvm.org/D142905

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/MultilibBuilder.h
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/MultilibBuilder.cpp
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/OHOS.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -33,14 +33,14 @@
 }
 
 TEST(MultilibTest, OpEqReflexivity3) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same";
 }
 
 TEST(MultilibTest, OpEqInequivalence1) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"-foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"-foo"});
   ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same";
   ASSERT_FALSE(M2 == M1)
   << "Multilibs with conflicting flags are not the same (commuted)";
@@ -48,7 +48,7 @@
 
 TEST(MultilibTest, OpEqInequivalence2) {
   Multilib M1;
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different";
 }
 
@@ -124,7 +124,7 @@
 }
 
 TEST(MultilibTest, Construction3) {
-  Multilib M({}, {}, {}, 0, {"+f1", "+f2", "-f3"});
+  Multilib M({}, {}, {}, {"+f1", "+f2", "-f3"});
   for (Multilib::flags_list::const_iterator I = M.flags().begin(),
 E = M.flags().end();
I != E; ++I) {
@@ -149,8 +149,8 @@
 
 TEST(MultilibTest, SetPriority) {
   MultilibSet MS({
-  Multilib("/foo", {}, {}, 1, {"+foo"}),
-  Multilib("/bar", {}, {}, 2, {"+bar"}),
+  Multilib("/foo", {}, {}, {"+foo"}),
+  Multilib("/bar", {}, {}, {"+bar"}),
   });
   Multilib::flags_list Flags1 = {"+foo", "-bar"};
   Multilib Selection1;
@@ -166,3 +166,24 @@
   ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
   << "Selection picked " << Selection2 << " which was not expected";
 }
+
+TEST(MultilibTest, SelectMultiple) {
+  MultilibSet MS({
+  Multilib("/a", {}, {}, {"x"}),
+  Multilib("/b", {}, {}, {"y"}),
+  });
+  std::vector Selection;
+
+  Selection = MS.select({"x"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/b", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y", "x"});
+  ASSERT_EQ(2u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+  EXPECT_EQ("/b", Selection[1].gccSuffix());
+}
Index: clang/lib/Driver/ToolChains/OHOS.cpp
===
--- clang/lib/Driver/ToolChains/OHOS.cpp
+++ clang/lib/Driver/ToolChains/OHOS.cpp
@@ -39,14 +39,16 @@
   // -mcpu=cortex-a7
   // -mfloat-abi=soft -mfloat-abi=softfp -mfloat-abi=hard
   // -mfpu=neon-vfpv4
-  Multilibs.push_back(Multilib("/a7_soft", {}, {}, 1,
-  {"+mcpu=cortex-a7", "+mfloat-abi=soft"}));
+  Multilibs.push_back(
+  Multilib("/a7_soft", {}, {}, {"+mcpu=cortex-a7", "+mfloat-abi=soft"}));
 
-  Multilibs.push_back(Multilib("/a7_softfp_neon-vfpv4", {}, {}, 1,
-  {"+mcpu=cortex-a7", "+mfloat-abi=softfp", "+mfpu=neon-vfpv4"}));
+  Multilibs.push_back(
+  Multilib("/a7_softfp_neon-vfpv4", {}, {},
+   {"+mcpu=cortex-a7", "+mfloat-abi=softfp", "+mfpu=neon-vfpv4"}));
 
-  Multilibs.push_back(Multilib("/a7_hard_neon-vfpv4", {}, {}, 1,
-  {"+mcpu=cortex-a7", "+mfloat-abi=hard", "+mfpu=neon-vfpv4"}));
+  Multilibs.push_back(
+  Multilib("/a7_hard_neon-vfpv4", {}, {},
+   {"+mcpu=cortex-a7", "+mfloat-abi=hard", "+mfpu=neon-vfpv4"}));
 
   if (Multilibs.select(Flags, Result.SelectedMultilib)) {
 Result.Multilibs = Multilibs;
Index: clang/lib/Driver/ToolChains/Fuchsia.cpp
===
--- clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -263,33 +263,33 @@
 
   Multilibs.push_back(Multilib());
   // Use the noexcept variant with -fno-exceptions to avoid the extra overhead.
-  Multilibs.push_back(MultilibBuilder("noexcept", {}, {}, 1)
+  Multilibs.push_back(MultilibBuilder("noexcept", {}, {})
   .flag("-fexceptions")
   .flag("+fno-exceptions")
   .makeMultilib());
   // ASan has higher 

[PATCH] D146757: [Driver] Enable defining multilib print options independently of flags

2023-03-23 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added a reviewer: phosek.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

Sometimes it's necessary to define a multilib in terms of attributes
that don't correspond directly to a valid command line option.
However to support -print-multi-lib we still need to specify a
representative set of command line options for the multilib.
Decoupling flags from print options enables this.

The default of deriving print options from flags beginning '+' remains.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146757

Files:
  clang/include/clang/Driver/Multilib.h
  clang/lib/Driver/Multilib.cpp
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -187,3 +187,19 @@
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
 }
+
+TEST(MultilibBuilder, PrintOptions) {
+  ASSERT_EQ(Multilib::flags_list(), Multilib().getPrintOptions());
+  ASSERT_EQ(Multilib::flags_list({"-x"}),
+Multilib({}, {}, {}, {"+x"}).getPrintOptions());
+  ASSERT_EQ(Multilib::flags_list({"-x"}),
+Multilib({}, {}, {}, {"+x"}, Multilib::PrintOptionsType::PlusFlags)
+.getPrintOptions());
+  ASSERT_EQ(
+  Multilib::flags_list({"-x", "-a", "-c"}),
+  Multilib({}, {}, {}, {"+x", "-y", "+a", "-b", "+c"}).getPrintOptions());
+  ASSERT_EQ(
+  Multilib::flags_list({"-y"}),
+  Multilib({}, {}, {}, {"+x"}, Multilib::PrintOptionsType::List, {"-y"})
+  .getPrintOptions());
+}
Index: clang/unittests/Driver/MultilibBuilderTest.cpp
===
--- clang/unittests/Driver/MultilibBuilderTest.cpp
+++ clang/unittests/Driver/MultilibBuilderTest.cpp
@@ -207,3 +207,14 @@
 << "Selection picked " << Selection << " which was not expected ";
   }
 }
+
+TEST(MultilibBuilderTest, PrintOptions) {
+  Multilib M = MultilibBuilder()
+   .flag("+x")
+   .flag("-y")
+   .flag("+a")
+   .flag("-b")
+   .flag("+c")
+   .makeMultilib();
+  ASSERT_EQ(Multilib::flags_list({"-x", "-a", "-c"}), M.getPrintOptions());
+}
Index: clang/lib/Driver/Multilib.cpp
===
--- clang/lib/Driver/Multilib.cpp
+++ clang/lib/Driver/Multilib.cpp
@@ -26,15 +26,43 @@
 using namespace llvm::sys;
 
 Multilib::Multilib(StringRef GCCSuffix, StringRef OSSuffix,
-   StringRef IncludeSuffix, const flags_list )
+   StringRef IncludeSuffix, const flags_list ,
+   PrintOptionsType PrintOptions,
+   const flags_list )
 : GCCSuffix(GCCSuffix), OSSuffix(OSSuffix), IncludeSuffix(IncludeSuffix),
-  Flags(Flags) {
+  Flags(Flags), PrintOptionsList(PrintOptionsList),
+  PrintOptions(PrintOptions) {
   assert(GCCSuffix.empty() ||
  (StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1));
   assert(OSSuffix.empty() ||
  (StringRef(OSSuffix).front() == '/' && OSSuffix.size() > 1));
   assert(IncludeSuffix.empty() ||
  (StringRef(IncludeSuffix).front() == '/' && IncludeSuffix.size() > 1));
+  // If PrintOptions is something other than List then PrintOptionsList must be
+  // empty.
+  assert(PrintOptions == PrintOptionsType::List || PrintOptionsList.empty());
+}
+
+static Multilib::flags_list
+getPrintOptionsFromPlusFlags(const Multilib::flags_list ) {
+  // Derive print options from flags beginning '+', replacing the first
+  // character with '-'.
+  Multilib::flags_list PrintOptions;
+  for (StringRef Flag : Flags) {
+if (Flag.front() == '+')
+  PrintOptions.push_back(("-" + Flag.substr(1)).str());
+  }
+  return PrintOptions;
+}
+
+Multilib::flags_list Multilib::getPrintOptions() const {
+  switch (PrintOptions) {
+  case PrintOptionsType::List:
+return PrintOptionsList;
+  case PrintOptionsType::PlusFlags:
+return getPrintOptionsFromPlusFlags(Flags);
+  }
+  llvm_unreachable("Unknown Multilib::PrintOptionsType");
 }
 
 LLVM_DUMP_METHOD void Multilib::dump() const {
@@ -44,14 +72,11 @@
 void Multilib::print(raw_ostream ) const {
   if (GCCSuffix.empty())
 OS << ".";
-  else {
+  else
 OS << StringRef(GCCSuffix).drop_front();
-  }
   OS << ";";
-  for (StringRef Flag : Flags) {
-if (Flag.front() == '+')
-  OS << "@" << Flag.substr(1);
-  }
+  for (StringRef Option : getPrintOptions())
+OS << "@" << Option.substr(1);
 }
 
 bool Multilib::operator==(const Multilib ) const {
Index: clang/include/clang/Driver/Multilib.h

[PATCH] D142905: [Driver] Change multilib selection algorithm

2023-03-24 Thread Michael Platings via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGd30bc9e91241: [Driver] Change multilib selection algorithm 
(authored by michaelplatings).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142905/new/

https://reviews.llvm.org/D142905

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/MultilibBuilder.h
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/MultilibBuilder.cpp
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/OHOS.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -33,14 +33,14 @@
 }
 
 TEST(MultilibTest, OpEqReflexivity3) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same";
 }
 
 TEST(MultilibTest, OpEqInequivalence1) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"-foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"-foo"});
   ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same";
   ASSERT_FALSE(M2 == M1)
   << "Multilibs with conflicting flags are not the same (commuted)";
@@ -48,7 +48,7 @@
 
 TEST(MultilibTest, OpEqInequivalence2) {
   Multilib M1;
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different";
 }
 
@@ -124,7 +124,7 @@
 }
 
 TEST(MultilibTest, Construction3) {
-  Multilib M({}, {}, {}, 0, {"+f1", "+f2", "-f3"});
+  Multilib M({}, {}, {}, {"+f1", "+f2", "-f3"});
   for (Multilib::flags_list::const_iterator I = M.flags().begin(),
 E = M.flags().end();
I != E; ++I) {
@@ -149,8 +149,8 @@
 
 TEST(MultilibTest, SetPriority) {
   MultilibSet MS({
-  Multilib("/foo", {}, {}, 1, {"+foo"}),
-  Multilib("/bar", {}, {}, 2, {"+bar"}),
+  Multilib("/foo", {}, {}, {"+foo"}),
+  Multilib("/bar", {}, {}, {"+bar"}),
   });
   Multilib::flags_list Flags1 = {"+foo", "-bar"};
   Multilib Selection1;
@@ -166,3 +166,24 @@
   ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
   << "Selection picked " << Selection2 << " which was not expected";
 }
+
+TEST(MultilibTest, SelectMultiple) {
+  MultilibSet MS({
+  Multilib("/a", {}, {}, {"x"}),
+  Multilib("/b", {}, {}, {"y"}),
+  });
+  std::vector Selection;
+
+  Selection = MS.select({"x"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/b", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y", "x"});
+  ASSERT_EQ(2u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+  EXPECT_EQ("/b", Selection[1].gccSuffix());
+}
Index: clang/lib/Driver/ToolChains/OHOS.cpp
===
--- clang/lib/Driver/ToolChains/OHOS.cpp
+++ clang/lib/Driver/ToolChains/OHOS.cpp
@@ -39,14 +39,16 @@
   // -mcpu=cortex-a7
   // -mfloat-abi=soft -mfloat-abi=softfp -mfloat-abi=hard
   // -mfpu=neon-vfpv4
-  Multilibs.push_back(Multilib("/a7_soft", {}, {}, 1,
-  {"+mcpu=cortex-a7", "+mfloat-abi=soft"}));
+  Multilibs.push_back(
+  Multilib("/a7_soft", {}, {}, {"+mcpu=cortex-a7", "+mfloat-abi=soft"}));
 
-  Multilibs.push_back(Multilib("/a7_softfp_neon-vfpv4", {}, {}, 1,
-  {"+mcpu=cortex-a7", "+mfloat-abi=softfp", "+mfpu=neon-vfpv4"}));
+  Multilibs.push_back(
+  Multilib("/a7_softfp_neon-vfpv4", {}, {},
+   {"+mcpu=cortex-a7", "+mfloat-abi=softfp", "+mfpu=neon-vfpv4"}));
 
-  Multilibs.push_back(Multilib("/a7_hard_neon-vfpv4", {}, {}, 1,
-  {"+mcpu=cortex-a7", "+mfloat-abi=hard", "+mfpu=neon-vfpv4"}));
+  Multilibs.push_back(
+  Multilib("/a7_hard_neon-vfpv4", {}, {},
+   {"+mcpu=cortex-a7", "+mfloat-abi=hard", "+mfpu=neon-vfpv4"}));
 
   if (Multilibs.select(Flags, Result.SelectedMultilib)) {
 Result.Multilibs = Multilibs;
Index: clang/lib/Driver/ToolChains/Fuchsia.cpp
===
--- clang/lib/Driver/ToolChains/Fuchsia.cpp
+++ clang/lib/Driver/ToolChains/Fuchsia.cpp
@@ -263,33 +263,33 @@
 
   Multilibs.push_back(Multilib());
   // Use the noexcept variant with -fno-exceptions to avoid the extra overhead.
-  Multilibs.push_back(MultilibBuilder("noexcept", {}, {}, 1)
+  Multilibs.push_back(MultilibBuilder("noexcept", {}, {})
   .flag("-fexceptions")
   .flag("+fno-exceptions")

[PATCH] D142932: Multilib YAML parsing

2023-03-24 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 508036.
michaelplatings added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142932/new/

https://reviews.llvm.org/D142932

Files:
  clang/include/clang/Driver/Multilib.h
  clang/lib/Driver/Multilib.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -13,6 +13,7 @@
 #include "clang/Driver/Multilib.h"
 #include "../../lib/Driver/ToolChains/CommonArgs.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/Version.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -203,3 +204,392 @@
   Multilib({}, {}, {}, {"+x"}, Multilib::PrintOptionsType::List, {"-y"})
   .getPrintOptions());
 }
+
+static void diagnosticCallback(const llvm::SMDiagnostic , void *Out) {
+  *reinterpret_cast(Out) = D.getMessage();
+}
+
+static bool parseYaml(MultilibSet , std::string ,
+  const char *Data) {
+  return MS.parseYaml(llvm::MemoryBufferRef(Data, "TEST"), diagnosticCallback,
+  );
+}
+
+static bool parseYaml(MultilibSet , const char *Data) {
+  return MS.parseYaml(llvm::MemoryBufferRef(Data, "TEST"));
+}
+
+// When updating this version also update MultilibVersionCurrent in Multilib.cpp
+#define YAML_PREAMBLE "MultilibVersion: 1.0\n"
+
+TEST(MultilibTest, ParseInvalid) {
+  std::string Diagnostic;
+
+  MultilibSet MS;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, R"(
+Variants: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("missing required key 'MultilibVersion'"))
+  << Diagnostic;
+
+  // Reject files with a different major version
+  EXPECT_FALSE(parseYaml(MS, Diagnostic,
+ R"(
+MultilibVersion: 2.0
+Variants: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("Multilib version 2.0 is unsupported"))
+  << Diagnostic;
+  EXPECT_FALSE(parseYaml(MS, Diagnostic,
+ R"(
+MultilibVersion: 0.1
+Variants: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("Multilib version 0.1 is unsupported"))
+  << Diagnostic;
+
+  // Reject files with a later minor version
+  EXPECT_FALSE(parseYaml(MS, Diagnostic,
+ R"(
+MultilibVersion: 1.9
+Variants: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("Multilib version 1.9 is unsupported"))
+  << Diagnostic;
+
+  // Accept files with the same major version and the same or earlier minor
+  // version
+  EXPECT_TRUE(parseYaml(MS, Diagnostic, R"(
+MultilibVersion: 1.0
+Variants: []
+)")) << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Variants'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: /abc
+  Flags: []
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("paths must be relative"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Flags: []
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Dir'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: .
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Flags'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: .
+  Flags: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("missing required key 'PrintOptions'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants: []
+FlagMap:
+- Regex: abc
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic)
+  .contains("value required for 'MatchFlags' or 'NoMatchFlags'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants: []
+FlagMap:
+- Dir: .
+  Regex: '('
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("parentheses not balanced"))
+  << Diagnostic;
+}
+
+TEST(MultilibTest, Parse) {
+  MultilibSet MS;
+  EXPECT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
+Variants:
+- Dir: .
+  Flags: []
+  PrintOptions: []
+)"));
+  EXPECT_EQ(1U, MS.size());
+  EXPECT_EQ("", MS.begin()->gccSuffix());
+
+  EXPECT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
+Variants:
+- Dir: abc
+  Flags: []
+  PrintOptions: []
+)"));
+  EXPECT_EQ(1U, MS.size());
+  EXPECT_EQ("/abc", MS.begin()->gccSuffix());
+
+  EXPECT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
+Variants:
+- Dir: pqr
+  Flags: []
+  PrintOptions: [-mfloat-abi=soft]
+)"));
+  EXPECT_EQ(1U, MS.size());
+  EXPECT_EQ("/pqr", MS.begin()->gccSuffix());
+  EXPECT_EQ(std::vector({"-mfloat-abi=soft"}),
+ 

[PATCH] D142933: Add -print-multi-selection-flags-experimental option

2023-03-24 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 508037.
michaelplatings added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142933/new/

https://reviews.llvm.org/D142933

Files:
  clang/include/clang/Driver/Options.td
  clang/include/clang/Driver/ToolChain.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/test/Driver/print-multi-selection-flags.c

Index: clang/test/Driver/print-multi-selection-flags.c
===
--- /dev/null
+++ clang/test/Driver/print-multi-selection-flags.c
@@ -0,0 +1,54 @@
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-linux -fc++-abi=itanium -fsanitize=address | FileCheck --check-prefix=CHECK-LINUX %s
+// CHECK-LINUX: fc++-abi=itanium
+// CHECK-LINUX: fexceptions
+// CHECK-LINUX: frtti
+// CHECK-LINUX: fsanitize=address
+// CHECK-LINUX: target=aarch64-unknown-linux
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-fuchsia -fsanitize=hwaddress | FileCheck --check-prefix=CHECK-FUCHSIA %s
+// CHECK-FUCHSIA: fsanitize=hwaddress
+// CHECK-FUCHSIA: target=aarch64-unknown-fuchsia
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=soft -fno-exceptions -fno-rtti | FileCheck --check-prefix=CHECK-ARMV4T %s
+// CHECK-ARMV4T: fno-exceptions
+// CHECK-ARMV4T: fno-rtti
+// CHECK-ARMV4T: mfloat-abi=soft
+// CHECK-ARMV4T: mfpu=none
+// CHECK-ARMV4T: target=armv4t-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=armv7em-none-eabi -mfloat-abi=softfp | FileCheck --check-prefix=CHECK-SOFTFP %s
+// CHECK-SOFTFP: mfloat-abi=softfp
+// CHECK-SOFTFP: mfpu=fpv4-sp-d16
+// CHECK-SOFTFP: target=thumbv7em-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabihf -march=armv7em -mfpu=fpv5-d16 | FileCheck --check-prefix=CHECK-HARD %s
+// CHECK-HARD: mfloat-abi=hard
+// CHECK-HARD: mfpu=fpv5-d16
+// CHECK-HARD: target=thumbv7em-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=soft -march=armv8-m.main+nofp | FileCheck --check-prefix=CHECK-V8MMAIN-NOFP %s
+// CHECK-V8MMAIN-NOFP: mfloat-abi=soft
+// CHECK-V8MMAIN-NOFP: mfpu=none
+// CHECK-V8MMAIN-NOFP: target=thumbv8m.main-none-unknown-eabi
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -mfloat-abi=hard -march=armv8.1m.main+mve.fp | FileCheck --check-prefix=CHECK-MVE %s
+// CHECK-MVE: march=+mve
+// CHECK-MVE: march=+mve.fp
+// CHECK-MVE: mfloat-abi=hard
+// CHECK-MVE: mfpu=fp-armv8-fullfp16-sp-d16
+// CHECK-MVE: target=thumbv8.1m.main-none-unknown-eabihf
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=arm-none-eabi -march=armv8.1m.main+mve+nofp | FileCheck --check-prefix=CHECK-MVENOFP %s
+// CHECK-MVENOFP: march=+mve
+// CHECK-MVENOFP-NOT: march=+mve.fp
+// CHECK-MVENOFP: mfpu=none
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-none-elf -march=armv8-a+lse | FileCheck --check-prefix=CHECK-LSE %s
+// CHECK-LSE: march=+lse
+
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-none-elf -march=armv8.5-a+sve+sve2 | FileCheck --check-prefix=CHECK-SVE2 %s
+// RUN: %clang -print-multi-selection-flags-experimental --target=aarch64-none-elf -march=armv9-a| FileCheck --check-prefix=CHECK-SVE2 %s
+// CHECK-SVE2: march=+simd
+// CHECK-SVE2: march=+sve
+// CHECK-SVE2: march=+sve2
+// CHECK-SVE2: target=aarch64-none-unknown-elf
Index: clang/lib/Driver/ToolChains/Arch/ARM.h
===
--- clang/lib/Driver/ToolChains/Arch/ARM.h
+++ clang/lib/Driver/ToolChains/Arch/ARM.h
@@ -63,9 +63,11 @@
 void getARMArchCPUFromArgs(const llvm::opt::ArgList ,
llvm::StringRef , llvm::StringRef ,
bool FromAs = false);
-void getARMTargetFeatures(const Driver , const llvm::Triple ,
-  const llvm::opt::ArgList ,
-  std::vector , bool ForAS);
+llvm::ARM::FPUKind getARMTargetFeatures(const Driver ,
+const llvm::Triple ,
+const llvm::opt::ArgList ,
+std::vector ,
+bool ForAS);
 int getARMSubArchVersionNumber(const llvm::Triple );
 bool isARMMProfile(const llvm::Triple );
 bool isARMAProfile(const llvm::Triple );
Index: clang/lib/Driver/ToolChains/Arch/ARM.cpp
===
--- clang/lib/Driver/ToolChains/Arch/ARM.cpp
+++ clang/lib/Driver/ToolChains/Arch/ARM.cpp
@@ -447,9 +447,11 @@
  (NoMVE == F.rend() || std::distance(MVE, NoMVE) > 0);
 }
 

[PATCH] D143059: [Driver] Enable selecting multiple multilibs

2023-03-24 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 508039.
michaelplatings added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143059/new/

https://reviews.llvm.org/D143059

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/ToolChain.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/CSKYToolChain.cpp
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/lib/Driver/ToolChains/Gnu.h
  clang/lib/Driver/ToolChains/Hexagon.cpp
  clang/lib/Driver/ToolChains/Hurd.cpp
  clang/lib/Driver/ToolChains/Linux.cpp
  clang/lib/Driver/ToolChains/MipsLinux.cpp
  clang/lib/Driver/ToolChains/OHOS.cpp
  clang/lib/Driver/ToolChains/RISCVToolchain.cpp
  clang/test/Driver/fuchsia.cpp
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -154,18 +154,18 @@
   Multilib("/bar", {}, {}, {"+bar"}),
   });
   Multilib::flags_list Flags1 = {"+foo", "-bar"};
-  Multilib Selection1;
+  llvm::SmallVector Selection1;
   ASSERT_TRUE(MS.select(Flags1, Selection1))
   << "Flag set was {\"+foo\"}, but selection not found";
-  ASSERT_TRUE(Selection1.gccSuffix() == "/foo")
-  << "Selection picked " << Selection1 << " which was not expected";
+  ASSERT_TRUE(Selection1.back().gccSuffix() == "/foo")
+  << "Selection picked " << Selection1.back() << " which was not expected";
 
   Multilib::flags_list Flags2 = {"+foo", "+bar"};
-  Multilib Selection2;
+  llvm::SmallVector Selection2;
   ASSERT_TRUE(MS.select(Flags2, Selection2))
   << "Flag set was {\"+bar\"}, but selection not found";
-  ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
-  << "Selection picked " << Selection2 << " which was not expected";
+  ASSERT_TRUE(Selection2.back().gccSuffix() == "/bar")
+  << "Selection picked " << Selection2.back() << " which was not expected";
 }
 
 TEST(MultilibTest, SelectMultiple) {
@@ -173,17 +173,17 @@
   Multilib("/a", {}, {}, {"x"}),
   Multilib("/b", {}, {}, {"y"}),
   });
-  std::vector Selection;
+  llvm::SmallVector Selection;
 
-  Selection = MS.select({"x"});
+  ASSERT_TRUE(MS.select({"x"}, Selection));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
 
-  Selection = MS.select({"y"});
+  ASSERT_TRUE(MS.select({"y"}, Selection));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/b", Selection[0].gccSuffix());
 
-  Selection = MS.select({"y", "x"});
+  ASSERT_TRUE(MS.select({"y", "x"}, Selection));
   ASSERT_EQ(2u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
@@ -383,7 +383,7 @@
 
 TEST(MultilibTest, SelectSoft) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: s
@@ -402,7 +402,7 @@
 
 TEST(MultilibTest, SelectSoftFP) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: f
@@ -418,7 +418,7 @@
   // If hard float is all that's available then select that only if compiling
   // with hard float.
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: h
@@ -432,7 +432,7 @@
 
 TEST(MultilibTest, SelectFloatABI) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: s
@@ -453,18 +453,18 @@
   NoMatchFlags: [hasfp]
 )"));
   MS.select({"mfloat-abi=soft"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=softfp"}, Selected);
-  EXPECT_EQ("/f", Selected.gccSuffix());
+  EXPECT_EQ("/f", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=hard"}, Selected);
-  EXPECT_EQ("/h", Selected.gccSuffix());
+  EXPECT_EQ("/h", Selected.back().gccSuffix());
 }
 
 TEST(MultilibTest, SelectFloatABIReversed) {
   // If soft is specified after softfp then softfp will never be
   // selected because soft is compatible with softfp and last wins.
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: h
@@ -485,11 +485,11 @@
   NoMatchFlags: [hasfp]
 )"));
   MS.select({"mfloat-abi=soft"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=softfp"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=hard"}, 

[PATCH] D143587: [Docs] Multilib design

2023-03-24 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 508041.
michaelplatings added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143587/new/

https://reviews.llvm.org/D143587

Files:
  clang/docs/Multilib.rst
  clang/docs/index.rst
  clang/include/clang/Driver/Multilib.h

Index: clang/include/clang/Driver/Multilib.h
===
--- clang/include/clang/Driver/Multilib.h
+++ clang/include/clang/Driver/Multilib.h
@@ -77,6 +77,8 @@
   /// options and look similar to them, and others can be defined by a
   /// particular multilib.yaml. A multilib is considered compatible if its flags
   /// are a subset of the flags derived from the Clang command line options.
+  /// See clang/docs/Multilib.rst for further explanation of how flags may be
+  /// generated and used.
   const flags_list () const { return Flags; }
 
   /// Returns the options that should be used for clang -print-multi-lib
Index: clang/docs/index.rst
===
--- clang/docs/index.rst
+++ clang/docs/index.rst
@@ -100,6 +100,7 @@
CodeOwners
InternalsManual
DriverInternals
+   Multilib
OffloadingDesign
PCHInternals
ItaniumMangleAbiTags
Index: clang/docs/Multilib.rst
===
--- /dev/null
+++ clang/docs/Multilib.rst
@@ -0,0 +1,327 @@
+
+Multilib
+
+
+Introduction
+
+
+This document describes how multilib is implemented in Clang.
+
+What is multilib and why might you care?
+If you're :doc:`cross compiling` then you can't use native
+system headers and libraries. To address this, you can use a combination of
+``--sysroot``, ``-isystem`` and ``-L`` options to point Clang at suitable
+directories for your target.
+However, when there are many possible directories to choose from, it's not
+necessarily obvious which one to pick.
+Multilib allows a toolchain designer to imbue the toolchain with the ability to
+pick a suitable directory automatically, based on the options the user provides
+to Clang. For example, if the user specifies
+``--target=arm-none-eabi -mcpu=cortex-m4`` the toolchain can choose a directory
+containing headers and libraries suitable for Armv7E-M, because it knows that's
+a suitable architecture for Arm Cortex-M4.
+Multilib can also choose between libraries for the same architecture based on
+other options. For example if the user specifies ``-fno-exceptions`` then a
+toolchain could select libraries built without exception support, thereby
+reducing the size of the resulting binary.
+
+Design
+==
+
+Clang supports GCC's ``-print-multi-lib`` and ``-print-multi-directory``
+options. These are described in
+`GCC Developer Options `_.
+
+There are two ways to configure multilib in Clang: hard-coded or via a
+configuration file.
+
+Hard-coded Multilib
+===
+
+The available libraries can be hard-coded in Clang. Typically this is done
+using the ``MultilibBuilder`` interface in
+``clang/include/clang/Driver/MultilibBuilder.h``.
+There are many examples of this in ``lib/Driver/ToolChains/Gnu.cpp``.
+The remainder of this document will not focus on this type of multilib.
+
+EXPERIMENTAL Multilib via configuration file
+
+
+Some Clang toolchains support loading multilib configuration from a
+``multilib.yaml`` configuration file.
+
+A ``multilib.yaml`` configuration file specifies which multilib variants are
+available, their relative location, what compilation options were used to build
+them, and the criteria by which they are selected.
+
+Multilib processing
+===
+
+Clang goes through the following steps to use multilib from a configuration
+file:
+#. Convert command line options to flags. Clang can accept the same
+   information via different options - for example,
+   ``--target=arm-none-eabi -march=armv7-m`` and
+   ``--target=armv7m-none-eabi`` are equivalent. Clang can also accept many
+   independent pieces of information within a single option - for example
+   ``-march=armv8.1m.main+fp+mve`` specifies the architecture and two
+   extensions in a single command line option.
+   To make it easier for the multilib system, Clang converts the command line
+   options into a standard set of simpler "flags". In many cases these flags
+   will look like a command line option with the leading ``-`` stripped off,
+   but where a suitable form for the flag doesn't exist in command line
+   options then its form will be different. For example, an Arm architecture
+   extension is represented like ``march=+mve`` since there's no way to specify
+   it in isolation in a command line option.
+   To see what flags are emitted for a given set of command line options, use
+   the ``-print-multi-selection-flags-experimental`` 

[PATCH] D142986: Enable multilib.yaml in the BareMetal ToolChain

2023-03-24 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 508038.
michaelplatings added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142986/new/

https://reviews.llvm.org/D142986

Files:
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/test/Driver/baremetal-multilib.yaml
  clang/test/Driver/baremetal.cpp
  clang/test/Driver/lit.local.cfg

Index: clang/test/Driver/lit.local.cfg
===
--- clang/test/Driver/lit.local.cfg
+++ clang/test/Driver/lit.local.cfg
@@ -1,7 +1,7 @@
 from lit.llvm import llvm_config
 
 config.suffixes = ['.c', '.cpp', '.cppm', '.h', '.m', '.mm', '.S', '.s', '.f90', '.F90', '.f95',
-   '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hipi', '.hlsl']
+   '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hipi', '.hlsl', '.yaml']
 config.substitutions = list(config.substitutions)
 config.substitutions.insert(0,
 ('%clang_cc1',
Index: clang/test/Driver/baremetal.cpp
===
--- clang/test/Driver/baremetal.cpp
+++ clang/test/Driver/baremetal.cpp
@@ -118,9 +118,9 @@
 // Verify that the bare metal driver does not include any host system paths:
 // CHECK-AARCH64-NO-HOST-INC: InstalledDir: [[INSTALLEDDIR:.+]]
 // CHECK-AARCH64-NO-HOST-INC: "-resource-dir" "[[RESOURCE:[^"]+]]"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include{{[/\\]+}}c++{{[/\\]+}}v1"
 // CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[RESOURCE]]{{[/\\]+}}include"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include"
 
 // RUN: %clang %s -### --target=riscv64-unknown-elf -o %t.out -L some/directory/user/asked/for \
 // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf 2>&1 \
Index: clang/test/Driver/baremetal-multilib.yaml
===
--- /dev/null
+++ clang/test/Driver/baremetal-multilib.yaml
@@ -0,0 +1,142 @@
+# REQUIRES: shell
+# UNSUPPORTED: system-windows
+
+# RUN: rm -rf %T/baremetal_multilib
+# RUN: mkdir -p %T/baremetal_multilib/bin
+# RUN: mkdir -p %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib
+# RUN: touch %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib/libclang_rt.builtins.a
+# RUN: ln -s %clang %T/baremetal_multilib/bin/clang
+# RUN: ln -s %s %T/baremetal_multilib/lib/clang-runtimes/multilib.yaml
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c++ %s -### -o %t.out 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib %s
+# CHECK:  "-cc1" "-triple" "thumbv8m.main-none-unknown-eabihf"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include/c++/v1"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include"
+# CHECK-SAME: "-x" "c++" "{{.*}}baremetal-multilib.yaml"
+# CHECK-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic"
+# CHECK-SAME: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib"
+# CHECK-SAME: "-lc" "-lm" "-lclang_rt.builtins"
+# CHECK-SAME: "-o" "{{.*}}.tmp.out"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY %s
+# CHECK-PRINT-MULTI-DIRECTORY: arm-none-eabi/thumb/v8-m.main/fp
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
+# RUN: --target=arm-none-eabi --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v6-m/nofp;@-target=thumbv6m-none-eabi@mfloat-abi=soft
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7-m/nofp;@-target=thumbv7m-none-eabi@mfloat-abi=soft
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7e-m/nofp;@-target=thumbv7em-none-eabi@mfloat-abi=soft@mfpu=none
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/nofp;@-target=arm-none-eabi@mfloat-abi=soft@march=armv8m.main+nofp
+# CHECK-PRINT-MULTI-LIB: 

[PATCH] D143075: BareMetal ToolChain multilib layering

2023-03-24 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 508040.
michaelplatings added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143075/new/

https://reviews.llvm.org/D143075

Files:
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/BareMetal.h
  clang/test/Driver/baremetal-multilib.yaml

Index: clang/test/Driver/baremetal-multilib.yaml
===
--- clang/test/Driver/baremetal-multilib.yaml
+++ clang/test/Driver/baremetal-multilib.yaml
@@ -25,6 +25,23 @@
 # RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY %s
 # CHECK-PRINT-MULTI-DIRECTORY: arm-none-eabi/thumb/v8-m.main/fp
 
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c++ %s -### -o %t.out 2>&1 \
+# RUN: --target=thumbv8.1m.main-none-eabihf -fno-exceptions --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib --check-prefix=CHECK-LAYERED-MULTILIB %s
+# CHECK-LAYERED-MULTILIB:  "-cc1" "-triple" "thumbv8.1m.main-none-unknown-eabihf"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/include/c++/v1"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/include/c++/v1"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/include"
+# CHECK-LAYERED-MULTILIB-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/include"
+# CHECK-LAYERED-MULTILIB-NEXT: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/noexcept/lib"
+# CHECK-LAYERED-MULTILIB-SAME: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8.1-m.main/fp/lib"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: --target=thumbv8.1m.main-none-eabihf -fno-exceptions --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-LAYERED-PRINT-MULTI-DIRECTORY %s
+# CHECK-LAYERED-PRINT-MULTI-DIRECTORY:  arm-none-eabi/thumb/v8.1-m.main/fp
+# CHECK-LAYERED-PRINT-MULTI-DIRECTORY-NEXT: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept
+
 # RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
 # RUN: --target=arm-none-eabi --sysroot= \
 # RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
@@ -38,6 +55,7 @@
 # CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/fp;@-target=thumbv8m.main-none-eabihf
 # CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/fp;@-target=thumbv8.1m.main-none-eabihf
 # CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/nofp/mve;@-target=arm-none-eabihf@march=armv8.1m.main+nofp+mve
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept;@-target=thumbv8.1m.main-none-eabihf@fno-exceptions
 
 # RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x assembler -mexecute-only \
 # RUN: --target=arm-none-eabi --sysroot= %s -c -### 2>&1 \
@@ -117,6 +135,14 @@
   Flags: [target=thumbv8.1m.main-none-unknown-eabihf, march=+mve]
   PrintOptions: [--target=arm-none-eabihf, -march=armv8.1m.main+nofp+mve]
 
+# A specialisation of v8.1-m.main/fp without exceptions.
+# This layers over the top of the regular v8.1-m.main/fp so it doesn't
+# need to have its own include directory or C library, thereby saving
+# disk space.
+- Dir: arm-none-eabi/thumb/v8.1-m.main/fp/noexcept
+  Flags: [target=thumbv8.1m.main-none-unknown-eabihf, hasfpu, fno-exceptions]
+  PrintOptions: [--target=thumbv8.1m.main-none-eabihf, -fno-exceptions]
+
 
 # The second section of the file is a map from auto-detected flags
 # to custom flags. The auto-detected flags can be printed out
Index: clang/lib/Driver/ToolChains/BareMetal.h
===
--- clang/lib/Driver/ToolChains/BareMetal.h
+++ clang/lib/Driver/ToolChains/BareMetal.h
@@ -71,6 +71,9 @@
   void AddLinkRuntimeLib(const llvm::opt::ArgList ,
  llvm::opt::ArgStringList ) const;
   std::string computeSysRoot() const override;
+
+private:
+  llvm::SmallVector getOrderedMultilibs() const;
 };
 
 } // namespace toolchains
Index: clang/lib/Driver/ToolChains/BareMetal.cpp
===
--- clang/lib/Driver/ToolChains/BareMetal.cpp
+++ clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -103,9 +103,12 @@
   findMultilibs(D, Triple, Args);
   SmallString<128> SysRoot(computeSysRoot());
   if (!SysRoot.empty()) {
-llvm::sys::path::append(SysRoot, "lib");
-getFilePaths().push_back(std::string(SysRoot));
-getLibraryPaths().push_back(std::string(SysRoot));
+for (const Multilib  : getOrderedMultilibs()) {
+  SmallString<128> Dir(SysRoot);
+  llvm::sys::path::append(Dir, M.osSuffix(), "lib");
+  

[PATCH] D143587: [Docs] Multilib design

2023-03-07 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 503046.
michaelplatings added a comment.

- Make "experimental" more obvious.
- Demonstrate using a Clang-generated flag directly in Flags


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143587/new/

https://reviews.llvm.org/D143587

Files:
  clang/docs/Multilib.rst
  clang/docs/index.rst

Index: clang/docs/index.rst
===
--- clang/docs/index.rst
+++ clang/docs/index.rst
@@ -100,6 +100,7 @@
CodeOwners
InternalsManual
DriverInternals
+   Multilib
OffloadingDesign
PCHInternals
ItaniumMangleAbiTags
Index: clang/docs/Multilib.rst
===
--- /dev/null
+++ clang/docs/Multilib.rst
@@ -0,0 +1,324 @@
+
+Multilib
+
+
+Introduction
+
+
+This document describes how multilib is implemented in Clang.
+
+What is multilib and why might you care?
+If you're :doc:`cross compiling` then you can't use native
+system headers and libraries. To address this, you can use a combination of
+``--sysroot``, ``-isystem`` and ``-L`` options to point Clang at suitable
+directories for your target.
+However, when there are many possible directories to choose from, it's not
+necessarily obvious which one to pick.
+Multilib allows a toolchain designer to imbue the toolchain with the ability to
+pick a suitable directory automatically, based on the options the user provides
+to Clang. For example, if the user specifies
+``--target=arm-none-eabi -mcpu=cortex-m4`` the toolchain can choose a directory
+containing headers and libraries suitable for Armv7E-M, because it knows that's
+a suitable architecture for Arm Cortex-M4.
+Multilib can also choose between libraries for the same architecture based on
+other options. For example if the user specifies ``-fno-exceptions`` then a
+toolchain could select libraries built without exception support, thereby
+reducing the size of the resulting binary.
+
+Design
+==
+
+Clang supports GCC's ``-print-multi-lib`` and ``-print-multi-directory``
+options. These are described in
+`GCC Developer Options `_.
+
+There are two ways to configure multilib in Clang: hard-coded or via a
+configuration file.
+
+Hard-coded Multilib
+===
+
+The available libraries can be hard-coded in Clang. Typically this is done
+using the ``MultilibBuilder`` interface in
+``clang/include/clang/Driver/MultilibBuilder.h``.
+There are many examples of this in ``lib/Driver/ToolChains/Gnu.cpp``.
+The remainder of this document will not focus on this type of multilib.
+
+EXPERIMENTAL Multilib via configuration file
+
+
+Some Clang toolchains support loading multilib configuration from a
+``multilib.yaml`` configuration file.
+
+A ``multilib.yaml`` configuration file specifies which multilib variants are
+available, their relative location, what compilation options were used to build
+them, and the criteria by which they are selected.
+
+Multilib processing
+===
+
+Clang goes through the following steps to use multilib from a configuration
+file:
+#. Convert command line arguments to flags. Clang can accept the same
+   information via different arguments - for example,
+   ``--target=arm-none-eabi -march=armv7-m`` and
+   ``--target=armv7m-none-eabi`` are equivalent. Clang can also accept many
+   independent pieces of information within a single flag - for example
+   ``-march=armv8.1m.main+fp+mve`` specifies the architecture and two
+   extensions in a single command line argument.
+   To make it easier for the multilib system, Clang converts the command line
+   arguments into a standard set of simpler "flags". In many cases these flags
+   will look like a command line argument with the leading ``-`` stripped off,
+   but where a suitable form for the flag doesn't exist in command line
+   arguments then its form will be different. For example, an Arm architecture
+   extension is represented like ``march=+mve`` since there's no way to specify
+   it in isolation in a command line argument.
+   To see what flags are emitted for a given set of command line arguments, use
+   the ``-print-multi-selection-flags-experimental`` command line argument
+   along with the rest of the arguments you want to use.
+#. Load ``multilib.yaml`` from sysroot.
+#. Generate additional flags. ``multilib.yaml`` contains a ``FlagMap`` section,
+   which specifies how to generate additional flags based on the flags derived
+   from command line arguments. Flags are matched using regular expressions.
+   These regular expressions shall use the POSIX extended regular expression
+   syntax.
+#. Match flags against multilib variants. If the generated flags are a superset
+   of the flags specified for a multilib variant then the variant is considered

[PATCH] D142986: Enable multilib.yaml in the BareMetal ToolChain

2023-03-13 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 504772.
michaelplatings added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142986/new/

https://reviews.llvm.org/D142986

Files:
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.h
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/test/Driver/baremetal-multilib.yaml
  clang/test/Driver/baremetal.cpp
  clang/test/Driver/lit.local.cfg

Index: clang/test/Driver/lit.local.cfg
===
--- clang/test/Driver/lit.local.cfg
+++ clang/test/Driver/lit.local.cfg
@@ -1,7 +1,7 @@
 from lit.llvm import llvm_config
 
 config.suffixes = ['.c', '.cpp', '.cppm', '.h', '.m', '.mm', '.S', '.s', '.f90', '.F90', '.f95',
-   '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hipi', '.hlsl']
+   '.cu', '.rs', '.cl', '.clcpp', '.hip', '.hipi', '.hlsl', '.yaml']
 config.substitutions = list(config.substitutions)
 config.substitutions.insert(0,
 ('%clang_cc1',
Index: clang/test/Driver/baremetal.cpp
===
--- clang/test/Driver/baremetal.cpp
+++ clang/test/Driver/baremetal.cpp
@@ -118,9 +118,9 @@
 // Verify that the bare metal driver does not include any host system paths:
 // CHECK-AARCH64-NO-HOST-INC: InstalledDir: [[INSTALLEDDIR:.+]]
 // CHECK-AARCH64-NO-HOST-INC: "-resource-dir" "[[RESOURCE:[^"]+]]"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include{{[/\\]+}}c++{{[/\\]+}}v1"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include{{[/\\]+}}c++{{[/\\]+}}v1"
 // CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[RESOURCE]]{{[/\\]+}}include"
-// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+}}aarch64-none-elf{{[/\\]+}}include"
+// CHECK-AARCH64-NO-HOST-INC-SAME: "-internal-isystem" "[[INSTALLEDDIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}clang-runtimes{{[/\\]+[^"]*}}include"
 
 // RUN: %clang %s -### --target=riscv64-unknown-elf -o %t.out -L some/directory/user/asked/for \
 // RUN: --sysroot=%S/Inputs/basic_riscv64_tree/riscv64-unknown-elf 2>&1 \
Index: clang/test/Driver/baremetal-multilib.yaml
===
--- /dev/null
+++ clang/test/Driver/baremetal-multilib.yaml
@@ -0,0 +1,143 @@
+# REQUIRES: shell
+# UNSUPPORTED: system-windows
+
+# RUN: rm -rf %T/baremetal_multilib
+# RUN: mkdir -p %T/baremetal_multilib/bin
+# RUN: mkdir -p %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib
+# RUN: touch %T/baremetal_multilib/lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib/libclang_rt.builtins.a
+# RUN: ln -s %clang %T/baremetal_multilib/bin/clang
+# RUN: ln -s %s %T/baremetal_multilib/lib/clang-runtimes/multilib.yaml
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -x c++ %s -### -o %t.out 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck -DSYSROOT=%T/baremetal_multilib %s
+# CHECK:  "-cc1" "-triple" "thumbv8m.main-none-unknown-eabihf"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include/c++/v1"
+# CHECK-SAME: "-internal-isystem" "[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/include"
+# CHECK-SAME: "-x" "c++" "{{.*}}baremetal-multilib.yaml"
+# CHECK-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic"
+# CHECK-SAME: "-L[[SYSROOT]]/bin/../lib/clang-runtimes/arm-none-eabi/thumb/v8-m.main/fp/lib"
+# CHECK-SAME: "-lc" "-lm" "-lclang_rt.builtins"
+# CHECK-SAME: "-o" "{{.*}}.tmp.out"
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-directory 2>&1 \
+# RUN: --target=thumbv8m.main-none-eabihf --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-DIRECTORY %s
+# CHECK-PRINT-MULTI-DIRECTORY: arm-none-eabi/thumb/v8-m.main/fp
+
+# RUN: %T/baremetal_multilib/bin/clang -no-canonical-prefixes -print-multi-lib 2>&1 \
+# RUN: --target=arm-none-eabi --sysroot= \
+# RUN:   | FileCheck --check-prefix=CHECK-PRINT-MULTI-LIB %s
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v6-m/nofp;@-target=thumbv6m-none-eabi@mfloat-abi=soft
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7-m/nofp;@-target=thumbv7m-none-eabi@mfloat-abi=soft
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v7e-m/nofp;@-target=thumbv7em-none-eabi@mfloat-abi=soft@mfpu=none
+# CHECK-PRINT-MULTI-LIB: arm-none-eabi/thumb/v8-m.main/nofp;@-target=arm-none-eabi@mfloat-abi=soft@march=armv8m.main+nofp
+# CHECK-PRINT-MULTI-LIB: 

[PATCH] D143059: [Driver] Enable selecting multiple multilibs

2023-03-13 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 504774.
michaelplatings added a comment.

Rebase


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143059/new/

https://reviews.llvm.org/D143059

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/ToolChain.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/ToolChain.cpp
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/CSKYToolChain.cpp
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/lib/Driver/ToolChains/Gnu.h
  clang/lib/Driver/ToolChains/Hexagon.cpp
  clang/lib/Driver/ToolChains/Hurd.cpp
  clang/lib/Driver/ToolChains/Linux.cpp
  clang/lib/Driver/ToolChains/MipsLinux.cpp
  clang/lib/Driver/ToolChains/RISCVToolchain.cpp
  clang/test/Driver/fuchsia.cpp
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -154,18 +154,18 @@
   Multilib("/bar", {}, {}, {"+bar"}),
   });
   Multilib::tag_set Tags1 = {"+foo", "-bar"};
-  Multilib Selection1;
+  llvm::SmallVector Selection1;
   ASSERT_TRUE(MS.select(Tags1, Selection1))
   << "Tag set was {\"+foo\"}, but selection not found";
-  ASSERT_TRUE(Selection1.gccSuffix() == "/foo")
-  << "Selection picked " << Selection1 << " which was not expected";
+  ASSERT_TRUE(Selection1.back().gccSuffix() == "/foo")
+  << "Selection picked " << Selection1.back() << " which was not expected";
 
   Multilib::tag_set Tags2 = {"+foo", "+bar"};
-  Multilib Selection2;
+  llvm::SmallVector Selection2;
   ASSERT_TRUE(MS.select(Tags2, Selection2))
   << "Tag set was {\"+bar\"}, but selection not found";
-  ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
-  << "Selection picked " << Selection2 << " which was not expected";
+  ASSERT_TRUE(Selection2.back().gccSuffix() == "/bar")
+  << "Selection picked " << Selection2.back() << " which was not expected";
 }
 
 TEST(MultilibTest, SelectMultiple) {
@@ -173,17 +173,17 @@
   Multilib("/a", {}, {}, {"x"}),
   Multilib("/b", {}, {}, {"y"}),
   });
-  std::vector Selection;
+  llvm::SmallVector Selection;
 
-  Selection = MS.select({"x"});
+  ASSERT_TRUE(MS.select({"x"}, Selection));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
 
-  Selection = MS.select({"y"});
+  ASSERT_TRUE(MS.select({"y"}, Selection));
   ASSERT_EQ(1u, Selection.size());
   EXPECT_EQ("/b", Selection[0].gccSuffix());
 
-  Selection = MS.select({"y", "x"});
+  ASSERT_TRUE(MS.select({"y", "x"}, Selection));
   ASSERT_EQ(2u, Selection.size());
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
@@ -383,7 +383,7 @@
 
 TEST(MultilibTest, SelectSoft) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: s
@@ -402,7 +402,7 @@
 
 TEST(MultilibTest, SelectSoftFP) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: f
@@ -418,7 +418,7 @@
   // If hard float is all that's available then select that only if compiling
   // with hard float.
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: h
@@ -432,7 +432,7 @@
 
 TEST(MultilibTest, SelectFloatABI) {
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: s
@@ -453,18 +453,18 @@
   NoMatchTags: [hasfp]
 )"));
   MS.select({"mfloat-abi=soft"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=softfp"}, Selected);
-  EXPECT_EQ("/f", Selected.gccSuffix());
+  EXPECT_EQ("/f", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=hard"}, Selected);
-  EXPECT_EQ("/h", Selected.gccSuffix());
+  EXPECT_EQ("/h", Selected.back().gccSuffix());
 }
 
 TEST(MultilibTest, SelectFloatABIReversed) {
   // If soft is specified after softfp then softfp will never be
   // selected because soft is compatible with softfp and last wins.
   MultilibSet MS;
-  Multilib Selected;
+  llvm::SmallVector Selected;
   ASSERT_TRUE(parseYaml(MS, YAML_PREAMBLE R"(
 Variants:
 - Dir: h
@@ -485,11 +485,11 @@
   NoMatchTags: [hasfp]
 )"));
   MS.select({"mfloat-abi=soft"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=softfp"}, Selected);
-  EXPECT_EQ("/s", Selected.gccSuffix());
+  EXPECT_EQ("/s", Selected.back().gccSuffix());
   MS.select({"mfloat-abi=hard"}, Selected);
-  EXPECT_EQ("/h", Selected.gccSuffix());
+  

[PATCH] D142905: [Driver] Change multilib selection algorithm

2023-03-13 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings marked an inline comment as done.
michaelplatings added inline comments.



Comment at: clang/include/clang/Driver/Multilib.h:67
+  /// a subset of the flags derived from the Clang command line options.
+  const flag_set () const { return Flags; }
 

peter.smith wrote:
> Would be good to reference the Multilib Design document's definition and 
> examples of (what will be renamed in D145567 to tags).
> 
> This may require moving the design doc down the stack, probably not necessary 
> if everything is committed at once.
I've changed D143587 to update the comment to reference the docs.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142905/new/

https://reviews.llvm.org/D142905

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D142932: Multilib YAML parsing

2023-03-13 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 504771.
michaelplatings marked 2 inline comments as done.
michaelplatings added a comment.

parse -> parseYaml


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142932/new/

https://reviews.llvm.org/D142932

Files:
  clang/include/clang/Driver/Multilib.h
  clang/lib/Driver/Multilib.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -13,6 +13,7 @@
 #include "clang/Driver/Multilib.h"
 #include "../../lib/Driver/ToolChains/CommonArgs.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/Version.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -187,3 +188,408 @@
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
 }
+
+static void diagnosticCallback(const llvm::SMDiagnostic , void *Out) {
+  *reinterpret_cast(Out) = D.getMessage();
+}
+
+static bool parseYaml(MultilibSet , std::string ,
+  const char *Data) {
+  return MS.parseYaml(llvm::MemoryBufferRef(Data, "TEST"), diagnosticCallback,
+  );
+}
+
+static bool parseYaml(MultilibSet , std::string ,
+  const std::string ) {
+  return MS.parseYaml(llvm::MemoryBufferRef(Data, "TEST"), diagnosticCallback,
+  );
+}
+
+static bool parseYaml(MultilibSet , const char *Data) {
+  return MS.parseYaml(llvm::MemoryBufferRef(Data, "TEST"));
+}
+
+#define _STRINGIFY(x) #x
+#define STRINGIFY(x) _STRINGIFY(x)
+// Avoid using MULTILIB_CLANG_VERSION in case it has extra non-numeric parts.
+#define MULTILIB_CLANG_VERSION \
+  STRINGIFY(CLANG_VERSION_MAJOR)   \
+  "." STRINGIFY(CLANG_VERSION_MINOR) "." STRINGIFY(CLANG_VERSION_PATCHLEVEL)
+#define YAML_PREAMBLE "ClangMinimumVersion: " MULTILIB_CLANG_VERSION "\n"
+
+TEST(MultilibTest, ParseInvalid) {
+  std::string Diagnostic;
+
+  MultilibSet MS;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, R"(
+Variants: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic)
+  .contains("missing required key 'ClangMinimumVersion'"))
+  << Diagnostic;
+
+  // Require all 3 major.minor.patch version components
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, R"(
+ClangMinimumVersion: )" STRINGIFY(CLANG_VERSION_MAJOR) R"(.0
+Variants: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic)
+  .contains("not a valid version string. Expected "
+"MAJOR.MINOR.PATCHLEVEL but got \"" STRINGIFY(
+CLANG_VERSION_MAJOR) ".0\""))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, R"(
+ClangMinimumVersion: )" MULTILIB_CLANG_VERSION R"(a
+Variants: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic)
+  .contains("not a valid version string. Expected "
+"MAJOR.MINOR.PATCHLEVEL where all components are decimal "
+"integers but got \"" MULTILIB_CLANG_VERSION "a\""))
+  << Diagnostic;
+
+  // Reject configurations that require a later clang version
+  EXPECT_FALSE(parseYaml(MS, Diagnostic,
+ R"(
+ClangMinimumVersion: )" + std::to_string(CLANG_VERSION_MAJOR + 1) +
+ R"(.0.0
+Variants: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic)
+  .contains("clang version " MULTILIB_CLANG_VERSION
+" is less than ClangMinimumVersion: " +
+std::to_string(CLANG_VERSION_MAJOR + 1) + ".0.0"))
+  << Diagnostic;
+
+  // but accept configurations that only need an earlier clang version
+  EXPECT_TRUE(parseYaml(MS, Diagnostic, R"(
+ClangMinimumVersion: 16.0.0
+Variants: []
+)")) << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Variants'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: /abc
+  Tags: []
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("paths must be relative"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Tags: []
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Dir'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: .
+  PrintOptions: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Tags'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parseYaml(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: .
+  Tags: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic).contains("missing required key 

[PATCH] D142932: Multilib YAML parsing

2023-03-13 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added inline comments.



Comment at: clang/include/clang/Driver/Multilib.h:66
+  /// options and look similar to them, and others can be defined by a
+  /// particular multilib.yaml. A multilib is considered compatible if its tags
+  /// are a subset of the tags derived from the Clang command line options.

peter.smith wrote:
> With the context of https://discourse.llvm.org/t/rfc-multilib/67494 and 
> potential other formats. I think it will be worth making this comment not 
> specific to multilib.yaml. For example if there is another non-YAML DSL that 
> has tags.
> 
> For example `multilib DSL` rather than `multilib.yaml`  
If I were a newcomer to this code I think I'd find it easier to grep for 
multilib.yaml so on that basis I'd prefer to stick with the current wording. 
Should another file format be adopted then the comment could be updated at that 
point.



Comment at: clang/include/clang/Driver/Multilib.h:140
+
+  bool parse(llvm::MemoryBufferRef, llvm::SourceMgr::DiagHandlerTy = nullptr,
+ void *DiagHandlerCtxt = nullptr);

peter.smith wrote:
> With reference to https://discourse.llvm.org/t/rfc-multilib/67494 perhaps 
> rename this to `parseMultilibYaml` as parse is generic, yet there is no 
> indication it is working on a yaml file here.
Agreed. Renamed to `parseYaml`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142932/new/

https://reviews.llvm.org/D142932

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143587: [Docs] Multilib design

2023-03-13 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 504775.
michaelplatings added a comment.

Reference Multilib.rst from comment in Multilib.h


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143587/new/

https://reviews.llvm.org/D143587

Files:
  clang/docs/Multilib.rst
  clang/docs/index.rst
  clang/include/clang/Driver/Multilib.h

Index: clang/include/clang/Driver/Multilib.h
===
--- clang/include/clang/Driver/Multilib.h
+++ clang/include/clang/Driver/Multilib.h
@@ -65,6 +65,8 @@
   /// options and look similar to them, and others can be defined by a
   /// particular multilib.yaml. A multilib is considered compatible if its tags
   /// are a subset of the tags derived from the Clang command line options.
+  /// See clang/docs/Multilib.rst for further explanation of how tags may be
+  /// generated and used.
   const tag_set () const { return Tags; }
 
   /// Returns the options that should be used for clang -print-multi-lib
Index: clang/docs/index.rst
===
--- clang/docs/index.rst
+++ clang/docs/index.rst
@@ -100,6 +100,7 @@
CodeOwners
InternalsManual
DriverInternals
+   Multilib
OffloadingDesign
PCHInternals
ItaniumMangleAbiTags
Index: clang/docs/Multilib.rst
===
--- /dev/null
+++ clang/docs/Multilib.rst
@@ -0,0 +1,327 @@
+
+Multilib
+
+
+Introduction
+
+
+This document describes how multilib is implemented in Clang.
+
+What is multilib and why might you care?
+If you're :doc:`cross compiling` then you can't use native
+system headers and libraries. To address this, you can use a combination of
+``--sysroot``, ``-isystem`` and ``-L`` options to point Clang at suitable
+directories for your target.
+However, when there are many possible directories to choose from, it's not
+necessarily obvious which one to pick.
+Multilib allows a toolchain designer to imbue the toolchain with the ability to
+pick a suitable directory automatically, based on the options the user provides
+to Clang. For example, if the user specifies
+``--target=arm-none-eabi -mcpu=cortex-m4`` the toolchain can choose a directory
+containing headers and libraries suitable for Armv7E-M, because it knows that's
+a suitable architecture for Arm Cortex-M4.
+Multilib can also choose between libraries for the same architecture based on
+other options. For example if the user specifies ``-fno-exceptions`` then a
+toolchain could select libraries built without exception support, thereby
+reducing the size of the resulting binary.
+
+Design
+==
+
+Clang supports GCC's ``-print-multi-lib`` and ``-print-multi-directory``
+options. These are described in
+`GCC Developer Options `_.
+
+There are two ways to configure multilib in Clang: hard-coded or via a
+configuration file.
+
+Hard-coded Multilib
+===
+
+The available libraries can be hard-coded in Clang. Typically this is done
+using the ``MultilibBuilder`` interface in
+``clang/include/clang/Driver/MultilibBuilder.h``.
+There are many examples of this in ``lib/Driver/ToolChains/Gnu.cpp``.
+The remainder of this document will not focus on this type of multilib.
+
+EXPERIMENTAL Multilib via configuration file
+
+
+Some Clang toolchains support loading multilib configuration from a
+``multilib.yaml`` configuration file.
+
+A ``multilib.yaml`` configuration file specifies which multilib variants are
+available, their relative location, what compilation options were used to build
+them, and the criteria by which they are selected.
+
+Multilib processing
+===
+
+Clang goes through the following steps to use multilib from a configuration
+file:
+#. Convert command line options to tags. Clang can accept the same
+   information via different options - for example,
+   ``--target=arm-none-eabi -march=armv7-m`` and
+   ``--target=armv7m-none-eabi`` are equivalent. Clang can also accept many
+   independent pieces of information within a single option - for example
+   ``-march=armv8.1m.main+fp+mve`` specifies the architecture and two
+   extensions in a single command line option.
+   To make it easier for the multilib system, Clang converts the command line
+   options into a standard set of simpler "tags". In many cases these tags
+   will look like a command line option with the leading ``-`` stripped off,
+   but where a suitable form for the tag doesn't exist in command line
+   options then its form will be different. For example, an Arm architecture
+   extension is represented like ``march=+mve`` since there's no way to specify
+   it in isolation in a command line option.
+   To see what tags are emitted for a given set of command line options, use
+   the 

[PATCH] D142905: [Driver] Change multilib selection algorithm

2023-03-22 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

@phosek ping.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142905/new/

https://reviews.llvm.org/D142905

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D146141: [ARM] Use FPUKind enum instead of unsigned

2023-03-16 Thread Michael Platings via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG60bbf271b568: [ARM][NFC] Use FPUKind enum instead of 
unsigned (authored by michaelplatings).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D146141/new/

https://reviews.llvm.org/D146141

Files:
  clang/lib/Basic/Targets/ARM.cpp
  clang/lib/Driver/ToolChains/Arch/ARM.cpp
  llvm/include/llvm/MC/MCStreamer.h
  llvm/include/llvm/TargetParser/ARMTargetParser.h
  llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
  llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
  llvm/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp
  llvm/lib/TargetParser/ARMTargetParser.cpp
  llvm/unittests/TargetParser/TargetParserTest.cpp

Index: llvm/unittests/TargetParser/TargetParserTest.cpp
===
--- llvm/unittests/TargetParser/TargetParserTest.cpp
+++ llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -120,7 +120,7 @@
   ARM::ArchKind AK = ARM::parseCPUArch(params.CPUName);
   EXPECT_EQ(params.ExpectedArch, ARM::getArchName(AK));
 
-  unsigned FPUKind = ARM::getDefaultFPU(params.CPUName, AK);
+  ARM::FPUKind FPUKind = ARM::getDefaultFPU(params.CPUName, AK);
   EXPECT_EQ(params.ExpectedFPU, ARM::getFPUName(FPUKind));
 
   uint64_t default_extensions = ARM::getDefaultExtensions(params.CPUName, AK);
@@ -765,10 +765,10 @@
 testArchExtDependency(const char *ArchExt,
   const std::initializer_list ) {
   std::vector Features;
-  unsigned FPUID;
+  ARM::FPUKind FPUKind;
 
   if (!ARM::appendArchExtFeatures("", ARM::ArchKind::ARMV8_1MMainline, ArchExt,
-  Features, FPUID))
+  Features, FPUKind))
 return false;
 
   return llvm::all_of(Expected, [&](StringRef Ext) {
Index: llvm/lib/TargetParser/ARMTargetParser.cpp
===
--- llvm/lib/TargetParser/ARMTargetParser.cpp
+++ llvm/lib/TargetParser/ARMTargetParser.cpp
@@ -147,7 +147,8 @@
   return getProfileKind(parseArch(Arch));
 }
 
-bool ARM::getFPUFeatures(unsigned FPUKind, std::vector ) {
+bool ARM::getFPUFeatures(ARM::FPUKind FPUKind,
+ std::vector ) {
 
   if (FPUKind >= FK_LAST || FPUKind == FK_INVALID)
 return false;
@@ -211,7 +212,7 @@
   return true;
 }
 
-unsigned ARM::parseFPU(StringRef FPU) {
+ARM::FPUKind ARM::parseFPU(StringRef FPU) {
   StringRef Syn = getFPUSynonym(FPU);
   for (const auto  : FPUNames) {
 if (Syn == F.Name)
@@ -220,7 +221,7 @@
   return FK_INVALID;
 }
 
-ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(unsigned FPUKind) {
+ARM::NeonSupportLevel ARM::getFPUNeonSupportLevel(ARM::FPUKind FPUKind) {
   if (FPUKind >= FK_LAST)
 return NeonSupportLevel::None;
   return FPUNames[FPUKind].NeonSupport;
@@ -243,33 +244,33 @@
   .Default(FPU);
 }
 
-StringRef ARM::getFPUName(unsigned FPUKind) {
+StringRef ARM::getFPUName(ARM::FPUKind FPUKind) {
   if (FPUKind >= FK_LAST)
 return StringRef();
   return FPUNames[FPUKind].Name;
 }
 
-ARM::FPUVersion ARM::getFPUVersion(unsigned FPUKind) {
+ARM::FPUVersion ARM::getFPUVersion(ARM::FPUKind FPUKind) {
   if (FPUKind >= FK_LAST)
 return FPUVersion::NONE;
   return FPUNames[FPUKind].FPUVer;
 }
 
-ARM::FPURestriction ARM::getFPURestriction(unsigned FPUKind) {
+ARM::FPURestriction ARM::getFPURestriction(ARM::FPUKind FPUKind) {
   if (FPUKind >= FK_LAST)
 return FPURestriction::None;
   return FPUNames[FPUKind].Restriction;
 }
 
-unsigned ARM::getDefaultFPU(StringRef CPU, ARM::ArchKind AK) {
+ARM::FPUKind ARM::getDefaultFPU(StringRef CPU, ARM::ArchKind AK) {
   if (CPU == "generic")
 return ARM::ARMArchNames[static_cast(AK)].DefaultFPU;
 
-  return StringSwitch(CPU)
+  return StringSwitch(CPU)
 #define ARM_CPU_NAME(NAME, ID, DEFAULT_FPU, IS_DEFAULT, DEFAULT_EXT)   \
   .Case(NAME, DEFAULT_FPU)
 #include "llvm/TargetParser/ARMTargetParser.def"
-   .Default(ARM::FK_INVALID);
+  .Default(ARM::FK_INVALID);
 }
 
 uint64_t ARM::getDefaultExtensions(StringRef CPU, ARM::ArchKind AK) {
@@ -362,7 +363,7 @@
   return StringRef();
 }
 
-static unsigned findDoublePrecisionFPU(unsigned InputFPUKind) {
+static ARM::FPUKind findDoublePrecisionFPU(ARM::FPUKind InputFPUKind) {
   const ARM::FPUName  = ARM::FPUNames[InputFPUKind];
 
   // If the input FPU already supports double-precision, then there
@@ -394,7 +395,7 @@
 bool ARM::appendArchExtFeatures(StringRef CPU, ARM::ArchKind AK,
 StringRef ArchExt,
 std::vector ,
-unsigned ) {
+ARM::FPUKind ) {
 
   size_t StartingNumFeatures = Features.size();
   const bool Negated = stripNegationPrefix(ArchExt);
@@ -417,7 +418,7 @@
 CPU = "generic";
 
   if (ArchExt == "fp" || ArchExt == "fp.dp") {
-unsigned 

[PATCH] D145567: [Driver] Rename multilib flags to tags

2023-03-09 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

Thanks @MaskRay for taking a look and thanks @simon_tatham for the review of 
the change. This change affects existing code so I think it deserves its own 
commit, but I'll move it down the stack to before D142932 
 so that later changes use the new names 
immediately, and I'll incorporate Simon's suggestions into those.




Comment at: clang/docs/Multilib.rst:66
``--target=armv7m-none-eabi`` are equivalent. Clang can also accept many
-   independent pieces of information within a single flag - for example
+   independent pieces of information within a single option - for example
``-march=armv8.1m.main+fp+mve`` specifies the architecture and two

simon_tatham wrote:
> An "option" here seems to be the same thing as an "argument" elsewhere in 
> this paragraph. Since the terminology is already confusing, perhaps simplify 
> by using the same word consistently throughout? I think "option" is more 
> precise, because //positional// clang arguments like input files definitely 
> //don't// play a part in this mechanism.
I'll incorporate this into D143587.



Comment at: clang/docs/Multilib.rst:71
+   arguments into a standard set of simpler "tags". In many cases these tags
will look like a command line argument with the leading ``-`` stripped off,
+   but where a suitable form for the tag doesn't exist in command line

simon_tatham wrote:
> This is a particular case where "option" seems like a better word. Not every 
> //argument// has a leading `-` in the first place. But every //option// does.
> 
> (Or, at least, in the default Unix / gcc style of clang options. I suppose in 
> `clang-cl` even that is not true, because options can have a leading `/` in 
> Windows style. I assume that in that situation the options are normalised to 
> their GNU representation before converting into multilib selection tags?)
I'll incorporate this into D143587.



Comment at: clang/docs/Multilib.rst:182
   # List of multilib variants. Required.
   # The ordering of Variants is important if more than one variant can match
+  # the same set of tags. See the docs on multilib layering for more info.

simon_tatham wrote:
> That capital V looks unintentional to me, and is potentially confusing – 
> someone might go looking for a formal definition of it somewhere.
I'll incorporate this into D143587.



Comment at: clang/include/clang/Driver/Multilib.h:64-65
+  /// Get the set of tags that indicate this multilib's use.
+  /// Tags are arbitrary strings although typically they will look similar to
+  /// command line options. A multilib is considered compatible if its tags are
+  /// a subset of the tags derived from the Clang command line options.

simon_tatham wrote:
> Tags are arbitrary strings, some of which are derived from command-line 
> options and look similar to them, and others can be defined by a particular 
> multilib.yaml
I'll move this change to earlier in the stack before multilib.yaml is a thing, 
but then I'll update the comment with your suggestion in D142932.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D145567/new/

https://reviews.llvm.org/D145567

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145567: [Driver] Rename multilib flags to tags

2023-03-13 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings marked an inline comment as done.
michaelplatings added a comment.

Thanks @peter.smith. I've opted to leave the comment as-is. If we can expect a 
tag_set to actually contain flags then I've continued to use that terminology.




Comment at: clang/lib/Driver/ToolChains/CommonArgs.h:202
+ Multilib::tag_set );
 
 void addX86AlignBranchArgs(const Driver , const llvm::opt::ArgList ,

peter.smith wrote:
> I can see the reason to keep the name `addMultilibFlag`. At this point is the 
> tag_set expected to be simplified tags or full command line flags. If it is 
> the former I think it would be good to change Flags to Tags here.
> 
> May also be useul to add a \p for Flags (or Tags) if there are any 
> requirements, or just useful information on what it is expected to be.
> 
> Parameter name also applies to CommonArgs.cpp below.
For the way this function is used I would expect `Flags` to be command line 
flags prefixed with `+` or `-`, the same as for the `Flag` parameter. Therefore 
I think it best to leave it as-is.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D145567/new/

https://reviews.llvm.org/D145567

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143587: [Docs] Multilib design

2023-03-15 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 505451.
michaelplatings marked an inline comment as done.
michaelplatings added a comment.

Add quotes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143587/new/

https://reviews.llvm.org/D143587

Files:
  clang/docs/Multilib.rst
  clang/docs/index.rst
  clang/include/clang/Driver/Multilib.h

Index: clang/include/clang/Driver/Multilib.h
===
--- clang/include/clang/Driver/Multilib.h
+++ clang/include/clang/Driver/Multilib.h
@@ -72,6 +72,8 @@
   /// options and look similar to them, and others can be defined by a
   /// particular multilib.yaml. A multilib is considered compatible if its flags
   /// are a subset of the flags derived from the Clang command line options.
+  /// See clang/docs/Multilib.rst for further explanation of how flags may be
+  /// generated and used.
   const flags_list () const { return Flags; }
 
   /// Returns the options that should be used for clang -print-multi-lib
Index: clang/docs/index.rst
===
--- clang/docs/index.rst
+++ clang/docs/index.rst
@@ -100,6 +100,7 @@
CodeOwners
InternalsManual
DriverInternals
+   Multilib
OffloadingDesign
PCHInternals
ItaniumMangleAbiTags
Index: clang/docs/Multilib.rst
===
--- /dev/null
+++ clang/docs/Multilib.rst
@@ -0,0 +1,327 @@
+
+Multilib
+
+
+Introduction
+
+
+This document describes how multilib is implemented in Clang.
+
+What is multilib and why might you care?
+If you're :doc:`cross compiling` then you can't use native
+system headers and libraries. To address this, you can use a combination of
+``--sysroot``, ``-isystem`` and ``-L`` options to point Clang at suitable
+directories for your target.
+However, when there are many possible directories to choose from, it's not
+necessarily obvious which one to pick.
+Multilib allows a toolchain designer to imbue the toolchain with the ability to
+pick a suitable directory automatically, based on the options the user provides
+to Clang. For example, if the user specifies
+``--target=arm-none-eabi -mcpu=cortex-m4`` the toolchain can choose a directory
+containing headers and libraries suitable for Armv7E-M, because it knows that's
+a suitable architecture for Arm Cortex-M4.
+Multilib can also choose between libraries for the same architecture based on
+other options. For example if the user specifies ``-fno-exceptions`` then a
+toolchain could select libraries built without exception support, thereby
+reducing the size of the resulting binary.
+
+Design
+==
+
+Clang supports GCC's ``-print-multi-lib`` and ``-print-multi-directory``
+options. These are described in
+`GCC Developer Options `_.
+
+There are two ways to configure multilib in Clang: hard-coded or via a
+configuration file.
+
+Hard-coded Multilib
+===
+
+The available libraries can be hard-coded in Clang. Typically this is done
+using the ``MultilibBuilder`` interface in
+``clang/include/clang/Driver/MultilibBuilder.h``.
+There are many examples of this in ``lib/Driver/ToolChains/Gnu.cpp``.
+The remainder of this document will not focus on this type of multilib.
+
+EXPERIMENTAL Multilib via configuration file
+
+
+Some Clang toolchains support loading multilib configuration from a
+``multilib.yaml`` configuration file.
+
+A ``multilib.yaml`` configuration file specifies which multilib variants are
+available, their relative location, what compilation options were used to build
+them, and the criteria by which they are selected.
+
+Multilib processing
+===
+
+Clang goes through the following steps to use multilib from a configuration
+file:
+#. Convert command line options to flags. Clang can accept the same
+   information via different options - for example,
+   ``--target=arm-none-eabi -march=armv7-m`` and
+   ``--target=armv7m-none-eabi`` are equivalent. Clang can also accept many
+   independent pieces of information within a single option - for example
+   ``-march=armv8.1m.main+fp+mve`` specifies the architecture and two
+   extensions in a single command line option.
+   To make it easier for the multilib system, Clang converts the command line
+   options into a standard set of simpler "flags". In many cases these flags
+   will look like a command line option with the leading ``-`` stripped off,
+   but where a suitable form for the flag doesn't exist in command line
+   options then its form will be different. For example, an Arm architecture
+   extension is represented like ``march=+mve`` since there's no way to specify
+   it in isolation in a command line option.
+   To see what flags are emitted for a given set of command line options, use

[PATCH] D143763: [Clang] Add clangMinimumVersion to multilib.yaml

2023-02-22 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings abandoned this revision.
michaelplatings marked 3 inline comments as done.
michaelplatings added a comment.

Squashed into D142932 


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143763/new/

https://reviews.llvm.org/D143763

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143666: [Clang] Fix clang_rt tests when LLVM_ENABLE_PER_TARGET_RUNTIME_DIR is ON

2023-02-22 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

Hi Petr,
In LLVM Embedded Toolchain for Arm we put libclang_rt in the regular library 
directory, not the resource dir. Therefore `-resource-dir` has no effect for us.
Instead of this change, I could have added a `--sysroot` argument to each test, 
but this change seemed to fit well with the discussion in 
https://discourse.llvm.org/t/rfc-time-to-drop-legacy-runtime-paths/64628.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143666/new/

https://reviews.llvm.org/D143666

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D144542: [Clang] Improve hermeticity of clang_rt tests

2023-02-22 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings created this revision.
michaelplatings added a reviewer: phosek.
Herald added a project: All.
michaelplatings requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Specifying --sysroot prevents libclang_rt from being located in standard
library directories.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D144542

Files:
  clang/test/Driver/arm-compiler-rt.c
  clang/test/Driver/print-libgcc-file-name-clangrt.c

Index: clang/test/Driver/print-libgcc-file-name-clangrt.c
===
--- clang/test/Driver/print-libgcc-file-name-clangrt.c
+++ clang/test/Driver/print-libgcc-file-name-clangrt.c
@@ -2,55 +2,64 @@
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=x86_64-pc-linux \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-X8664 %s
-// CHECK-CLANGRT-X8664: libclang_rt.builtins{{(-x86_64)?}}.a
+// CHECK-CLANGRT-X8664: libclang_rt.builtins-x86_64.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=i386-pc-linux \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-I386 %s
-// CHECK-CLANGRT-I386: libclang_rt.builtins{{(-i386)?}}.a
+// CHECK-CLANGRT-I386: libclang_rt.builtins-i386.a
 
 // Check whether alternate arch values map to the correct library.
 //
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=i686-pc-linux \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-I386 %s
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=arm-linux-gnueabi \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARM %s
-// CHECK-CLANGRT-ARM: libclang_rt.builtins{{(-arm)?}}.a
+// CHECK-CLANGRT-ARM: libclang_rt.builtins-arm.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=arm-linux-androideabi \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARM-ANDROID %s
 // CHECK-CLANGRT-ARM-ANDROID: libclang_rt.builtins-arm-android.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=arm-linux-gnueabihf \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARMHF %s
-// CHECK-CLANGRT-ARMHF: libclang_rt.builtins{{(-armhf)?}}.a
+// CHECK-CLANGRT-ARMHF: libclang_rt.builtins-armhf.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=arm-linux-gnueabi -mfloat-abi=hard \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARM-ABI %s
-// CHECK-CLANGRT-ARM-ABI: libclang_rt.builtins{{(-armhf)?}}.a
+// CHECK-CLANGRT-ARM-ABI: libclang_rt.builtins-armhf.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=armv7m-none-eabi \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARM-BAREMETAL %s
-// CHECK-CLANGRT-ARM-BAREMETAL: libclang_rt.builtins{{(-armv7m)?}}.a
+// CHECK-CLANGRT-ARM-BAREMETAL: libclang_rt.builtins-armv7m.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=armv7m-vendor-none-eabi \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARM-BAREMETAL-PER-TARGET %s
 // CHECK-CLANGRT-ARM-BAREMETAL-PER-TARGET: libclang_rt.builtins.a
Index: clang/test/Driver/arm-compiler-rt.c
===
--- clang/test/Driver/arm-compiler-rt.c
+++ clang/test/Driver/arm-compiler-rt.c
@@ -1,48 +1,56 @@
 // RUN: %clang -target arm-none-eabi \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -rtlib=compiler-rt -### %s 2>&1 \
 // RUN:   | FileCheck %s -check-prefix ARM-EABI
-// ARM-EABI: "-lclang_rt.builtins{{(-arm)?}}"
+// 

[PATCH] D144542: [Clang] Improve hermeticity of clang_rt tests

2023-02-22 Thread Michael Platings via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG67e28a3010e1: [Clang] Improve hermeticity of clang_rt tests 
(authored by michaelplatings).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D144542/new/

https://reviews.llvm.org/D144542

Files:
  clang/test/Driver/arm-compiler-rt.c
  clang/test/Driver/print-libgcc-file-name-clangrt.c

Index: clang/test/Driver/print-libgcc-file-name-clangrt.c
===
--- clang/test/Driver/print-libgcc-file-name-clangrt.c
+++ clang/test/Driver/print-libgcc-file-name-clangrt.c
@@ -2,55 +2,64 @@
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=x86_64-pc-linux \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-X8664 %s
-// CHECK-CLANGRT-X8664: libclang_rt.builtins{{(-x86_64)?}}.a
+// CHECK-CLANGRT-X8664: libclang_rt.builtins-x86_64.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=i386-pc-linux \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-I386 %s
-// CHECK-CLANGRT-I386: libclang_rt.builtins{{(-i386)?}}.a
+// CHECK-CLANGRT-I386: libclang_rt.builtins-i386.a
 
 // Check whether alternate arch values map to the correct library.
 //
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=i686-pc-linux \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-I386 %s
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=arm-linux-gnueabi \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARM %s
-// CHECK-CLANGRT-ARM: libclang_rt.builtins{{(-arm)?}}.a
+// CHECK-CLANGRT-ARM: libclang_rt.builtins-arm.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=arm-linux-androideabi \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARM-ANDROID %s
 // CHECK-CLANGRT-ARM-ANDROID: libclang_rt.builtins-arm-android.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=arm-linux-gnueabihf \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARMHF %s
-// CHECK-CLANGRT-ARMHF: libclang_rt.builtins{{(-armhf)?}}.a
+// CHECK-CLANGRT-ARMHF: libclang_rt.builtins-armhf.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=arm-linux-gnueabi -mfloat-abi=hard \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARM-ABI %s
-// CHECK-CLANGRT-ARM-ABI: libclang_rt.builtins{{(-armhf)?}}.a
+// CHECK-CLANGRT-ARM-ABI: libclang_rt.builtins-armhf.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=armv7m-none-eabi \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARM-BAREMETAL %s
-// CHECK-CLANGRT-ARM-BAREMETAL: libclang_rt.builtins{{(-armv7m)?}}.a
+// CHECK-CLANGRT-ARM-BAREMETAL: libclang_rt.builtins-armv7m.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=armv7m-vendor-none-eabi \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARM-BAREMETAL-PER-TARGET %s
 // CHECK-CLANGRT-ARM-BAREMETAL-PER-TARGET: libclang_rt.builtins.a
Index: clang/test/Driver/arm-compiler-rt.c
===
--- clang/test/Driver/arm-compiler-rt.c
+++ clang/test/Driver/arm-compiler-rt.c
@@ -1,48 +1,56 @@
 // RUN: %clang -target arm-none-eabi \
+// RUN: --sysroot=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -rtlib=compiler-rt -### %s 2>&1 \
 // RUN:   | FileCheck %s -check-prefix ARM-EABI
-// ARM-EABI: "-lclang_rt.builtins{{(-arm)?}}"
+// ARM-EABI: 

[PATCH] D143666: [Clang] Fix clang_rt tests when LLVM_ENABLE_PER_TARGET_RUNTIME_DIR is ON

2023-02-22 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

https://reviews.llvm.org/D144542


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143666/new/

https://reviews.llvm.org/D143666

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D143666: [Clang] Fix clang_rt tests when LLVM_ENABLE_PER_TARGET_RUNTIME_DIR is ON

2023-02-21 Thread Michael Platings via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGd61a863050bb: [Clang] Fix clang_rt tests when 
LLVM_ENABLE_PER_TARGET_RUNTIME_DIR is ON (authored by michaelplatings).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143666/new/

https://reviews.llvm.org/D143666

Files:
  clang/test/Driver/arm-compiler-rt.c
  clang/test/Driver/print-libgcc-file-name-clangrt.c

Index: clang/test/Driver/print-libgcc-file-name-clangrt.c
===
--- clang/test/Driver/print-libgcc-file-name-clangrt.c
+++ clang/test/Driver/print-libgcc-file-name-clangrt.c
@@ -4,13 +4,13 @@
 // RUN: --target=x86_64-pc-linux \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-X8664 %s
-// CHECK-CLANGRT-X8664: libclang_rt.builtins-x86_64.a
+// CHECK-CLANGRT-X8664: libclang_rt.builtins{{(-x86_64)?}}.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=i386-pc-linux \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-I386 %s
-// CHECK-CLANGRT-I386: libclang_rt.builtins-i386.a
+// CHECK-CLANGRT-I386: libclang_rt.builtins{{(-i386)?}}.a
 
 // Check whether alternate arch values map to the correct library.
 //
@@ -23,7 +23,7 @@
 // RUN: --target=arm-linux-gnueabi \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARM %s
-// CHECK-CLANGRT-ARM: libclang_rt.builtins-arm.a
+// CHECK-CLANGRT-ARM: libclang_rt.builtins{{(-arm)?}}.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=arm-linux-androideabi \
@@ -35,19 +35,19 @@
 // RUN: --target=arm-linux-gnueabihf \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARMHF %s
-// CHECK-CLANGRT-ARMHF: libclang_rt.builtins-armhf.a
+// CHECK-CLANGRT-ARMHF: libclang_rt.builtins{{(-armhf)?}}.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=arm-linux-gnueabi -mfloat-abi=hard \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARM-ABI %s
-// CHECK-CLANGRT-ARM-ABI: libclang_rt.builtins-armhf.a
+// CHECK-CLANGRT-ARM-ABI: libclang_rt.builtins{{(-armhf)?}}.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=armv7m-none-eabi \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN:   | FileCheck --check-prefix=CHECK-CLANGRT-ARM-BAREMETAL %s
-// CHECK-CLANGRT-ARM-BAREMETAL: libclang_rt.builtins-armv7m.a
+// CHECK-CLANGRT-ARM-BAREMETAL: libclang_rt.builtins{{(-armv7m)?}}.a
 
 // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \
 // RUN: --target=armv7m-vendor-none-eabi \
Index: clang/test/Driver/arm-compiler-rt.c
===
--- clang/test/Driver/arm-compiler-rt.c
+++ clang/test/Driver/arm-compiler-rt.c
@@ -2,47 +2,47 @@
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -rtlib=compiler-rt -### %s 2>&1 \
 // RUN:   | FileCheck %s -check-prefix ARM-EABI
-// ARM-EABI: "-lclang_rt.builtins-arm"
+// ARM-EABI: "-lclang_rt.builtins{{(-arm)?}}"
 
 // RUN: %clang -target arm-linux-gnueabi \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -rtlib=compiler-rt -### %s 2>&1 \
 // RUN:   | FileCheck %s -check-prefix ARM-GNUEABI
-// ARM-GNUEABI: "{{.*[/\\]}}libclang_rt.builtins-arm.a"
+// ARM-GNUEABI: "{{.*[/\\]}}libclang_rt.builtins{{(-arm)?}}.a"
 
 // RUN: %clang -target arm-linux-gnueabi \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -rtlib=compiler-rt -mfloat-abi=hard -### %s 2>&1 \
 // RUN:   | FileCheck %s -check-prefix ARM-GNUEABI-ABI
-// ARM-GNUEABI-ABI: "{{.*[/\\]}}libclang_rt.builtins-armhf.a"
+// ARM-GNUEABI-ABI: "{{.*[/\\]}}libclang_rt.builtins{{(-armhf)?}}.a"
 
 // RUN: %clang -target arm-linux-gnueabihf \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -rtlib=compiler-rt -### %s 2>&1 \
 // RUN:   | FileCheck %s -check-prefix ARM-GNUEABIHF
-// ARM-GNUEABIHF: "{{.*[/\\]}}libclang_rt.builtins-armhf.a"
+// ARM-GNUEABIHF: "{{.*[/\\]}}libclang_rt.builtins{{(-armhf)?}}.a"
 
 // RUN: %clang -target arm-linux-gnueabihf \
 // RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
 // RUN: -rtlib=compiler-rt -mfloat-abi=soft -### %s 2>&1 \
 // RUN:   | FileCheck %s -check-prefix ARM-GNUEABIHF-ABI
-// ARM-GNUEABIHF-ABI: "{{.*[/\\]}}libclang_rt.builtins-arm.a"
+// ARM-GNUEABIHF-ABI: "{{.*[/\\]}}libclang_rt.builtins{{(-arm)?}}.a"
 
 // RUN: %clang -target arm-windows-itanium \
 // RUN: 

[PATCH] D143666: [Clang] Fix clang_rt tests when LLVM_ENABLE_PER_TARGET_RUNTIME_DIR is ON

2023-02-22 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings added a comment.

I'm happy to revert this and add `--sysroot` if you prefer. That would fit with 
keeping the tests hermetic.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143666/new/

https://reviews.llvm.org/D143666

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D142893: [NFC] Class for building MultilibSet

2023-02-22 Thread Michael Platings via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
michaelplatings marked 4 inline comments as done.
Closed by commit rG850dab0f2537: [NFC] Class for building MultilibSet (authored 
by michaelplatings).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142893/new/

https://reviews.llvm.org/D142893

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/MultilibBuilder.h
  clang/lib/Driver/CMakeLists.txt
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/MultilibBuilder.cpp
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/unittests/Driver/CMakeLists.txt
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -11,34 +11,17 @@
 //===--===//
 
 #include "clang/Driver/Multilib.h"
+#include "../../lib/Driver/ToolChains/CommonArgs.h"
 #include "clang/Basic/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/SourceMgr.h"
 #include "gtest/gtest.h"
 
 using namespace clang::driver;
 using namespace clang;
 
-TEST(MultilibTest, MultilibValidity) {
-
-  ASSERT_TRUE(Multilib().isValid()) << "Empty multilib is not valid";
-
-  ASSERT_TRUE(Multilib().flag("+foo").isValid())
-  << "Single indicative flag is not valid";
-
-  ASSERT_TRUE(Multilib().flag("-foo").isValid())
-  << "Single contraindicative flag is not valid";
-
-  ASSERT_FALSE(Multilib().flag("+foo").flag("-foo").isValid())
-  << "Conflicting flags should invalidate the Multilib";
-
-  ASSERT_TRUE(Multilib().flag("+foo").flag("+foo").isValid())
-  << "Multilib should be valid even if it has the same flag twice";
-
-  ASSERT_TRUE(Multilib().flag("+foo").flag("-foobar").isValid())
-  << "Seemingly conflicting prefixes shouldn't actually conflict";
-}
-
 TEST(MultilibTest, OpEqReflexivity1) {
   Multilib M;
   ASSERT_TRUE(M == M) << "Multilib::operator==() is not reflexive";
@@ -50,40 +33,28 @@
 }
 
 TEST(MultilibTest, OpEqReflexivity3) {
-  Multilib M1, M2;
-  M1.flag("+foo");
-  M2.flag("+foo");
+  Multilib M1({}, {}, {}, 0, {"+foo"});
+  Multilib M2({}, {}, {}, 0, {"+foo"});
   ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same";
 }
 
 TEST(MultilibTest, OpEqInequivalence1) {
-  Multilib M1, M2;
-  M1.flag("+foo");
-  M2.flag("-foo");
+  Multilib M1({}, {}, {}, 0, {"+foo"});
+  Multilib M2({}, {}, {}, 0, {"-foo"});
   ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same";
   ASSERT_FALSE(M2 == M1)
   << "Multilibs with conflicting flags are not the same (commuted)";
 }
 
 TEST(MultilibTest, OpEqInequivalence2) {
-  Multilib M1, M2;
-  M2.flag("+foo");
+  Multilib M1;
+  Multilib M2({}, {}, {}, 0, {"+foo"});
   ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different";
 }
 
-TEST(MultilibTest, OpEqEquivalence1) {
-  Multilib M1, M2;
-  M1.flag("+foo");
-  M2.flag("+foo").flag("+foo");
-  ASSERT_TRUE(M1 == M2) << "Flag duplication shouldn't affect equivalence";
-  ASSERT_TRUE(M2 == M1)
-  << "Flag duplication shouldn't affect equivalence (commuted)";
-}
-
 TEST(MultilibTest, OpEqEquivalence2) {
-  Multilib M1("64");
-  Multilib M2;
-  M2.gccSuffix("/64");
+  Multilib M1("/64");
+  Multilib M2("/64");
   ASSERT_TRUE(M1 == M2)
   << "Constructor argument must match Multilib::gccSuffix()";
   ASSERT_TRUE(M2 == M1)
@@ -91,9 +62,8 @@
 }
 
 TEST(MultilibTest, OpEqEquivalence3) {
-  Multilib M1("", "32");
-  Multilib M2;
-  M2.osSuffix("/32");
+  Multilib M1("", "/32");
+  Multilib M2("", "/32");
   ASSERT_TRUE(M1 == M2)
   << "Constructor argument must match Multilib::osSuffix()";
   ASSERT_TRUE(M2 == M1)
@@ -101,9 +71,8 @@
 }
 
 TEST(MultilibTest, OpEqEquivalence4) {
-  Multilib M1("", "", "16");
-  Multilib M2;
-  M2.includeSuffix("/16");
+  Multilib M1("", "", "/16");
+  Multilib M2("", "", "/16");
   ASSERT_TRUE(M1 == M2)
   << "Constructor argument must match Multilib::includeSuffix()";
   ASSERT_TRUE(M2 == M1)
@@ -111,31 +80,31 @@
 }
 
 TEST(MultilibTest, OpEqInequivalence3) {
-  Multilib M1("foo");
-  Multilib M2("bar");
+  Multilib M1("/foo");
+  Multilib M2("/bar");
   ASSERT_FALSE(M1 == M2) << "Differing gccSuffixes should be different";
   ASSERT_FALSE(M2 == M1)
   << "Differing gccSuffixes should be different (commuted)";
 }
 
 TEST(MultilibTest, OpEqInequivalence4) {
-  Multilib M1("", "foo");
-  Multilib M2("", "bar");
+  Multilib M1("", "/foo");
+  Multilib M2("", "/bar");
   ASSERT_FALSE(M1 == M2) << "Differing osSuffixes should be different";
   ASSERT_FALSE(M2 == M1)
   << "Differing osSuffixes should be 

[PATCH] D142905: Change multilib selection algorithm

2023-02-22 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 499416.
michaelplatings marked 2 inline comments as done.
michaelplatings added a comment.

Remove braces as requested by @MaskRay


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142905/new/

https://reviews.llvm.org/D142905

Files:
  clang/include/clang/Driver/Multilib.h
  clang/include/clang/Driver/MultilibBuilder.h
  clang/lib/Driver/Multilib.cpp
  clang/lib/Driver/MultilibBuilder.cpp
  clang/lib/Driver/ToolChains/BareMetal.cpp
  clang/lib/Driver/ToolChains/CommonArgs.cpp
  clang/lib/Driver/ToolChains/CommonArgs.h
  clang/lib/Driver/ToolChains/Fuchsia.cpp
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/unittests/Driver/MultilibBuilderTest.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -33,14 +33,14 @@
 }
 
 TEST(MultilibTest, OpEqReflexivity3) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_TRUE(M1 == M2) << "Multilibs with the same flag should be the same";
 }
 
 TEST(MultilibTest, OpEqInequivalence1) {
-  Multilib M1({}, {}, {}, 0, {"+foo"});
-  Multilib M2({}, {}, {}, 0, {"-foo"});
+  Multilib M1({}, {}, {}, {"+foo"});
+  Multilib M2({}, {}, {}, {"-foo"});
   ASSERT_FALSE(M1 == M2) << "Multilibs with conflicting flags are not the same";
   ASSERT_FALSE(M2 == M1)
   << "Multilibs with conflicting flags are not the same (commuted)";
@@ -48,7 +48,7 @@
 
 TEST(MultilibTest, OpEqInequivalence2) {
   Multilib M1;
-  Multilib M2({}, {}, {}, 0, {"+foo"});
+  Multilib M2({}, {}, {}, {"+foo"});
   ASSERT_FALSE(M1 == M2) << "Flags make Multilibs different";
 }
 
@@ -124,9 +124,9 @@
 }
 
 TEST(MultilibTest, Construction3) {
-  Multilib M({}, {}, {}, 0, {"+f1", "+f2", "-f3"});
-  for (Multilib::flags_list::const_iterator I = M.flags().begin(),
-E = M.flags().end();
+  Multilib M({}, {}, {}, {"+f1", "+f2", "-f3"});
+  for (Multilib::flag_set::const_iterator I = M.flags().begin(),
+  E = M.flags().end();
I != E; ++I) {
 ASSERT_TRUE(llvm::StringSwitch(*I)
 .Cases("+f1", "+f2", "-f3", true)
@@ -149,20 +149,41 @@
 
 TEST(MultilibTest, SetPriority) {
   MultilibSet MS({
-  Multilib("/foo", {}, {}, 1, {"+foo"}),
-  Multilib("/bar", {}, {}, 2, {"+bar"}),
+  Multilib("/foo", {}, {}, {"+foo"}),
+  Multilib("/bar", {}, {}, {"+bar"}),
   });
-  Multilib::flags_list Flags1 = {"+foo", "-bar"};
+  Multilib::flag_set Flags1 = {"+foo", "-bar"};
   Multilib Selection1;
   ASSERT_TRUE(MS.select(Flags1, Selection1))
   << "Flag set was {\"+foo\"}, but selection not found";
   ASSERT_TRUE(Selection1.gccSuffix() == "/foo")
   << "Selection picked " << Selection1 << " which was not expected";
 
-  Multilib::flags_list Flags2 = {"+foo", "+bar"};
+  Multilib::flag_set Flags2 = {"+foo", "+bar"};
   Multilib Selection2;
   ASSERT_TRUE(MS.select(Flags2, Selection2))
   << "Flag set was {\"+bar\"}, but selection not found";
   ASSERT_TRUE(Selection2.gccSuffix() == "/bar")
   << "Selection picked " << Selection2 << " which was not expected";
 }
+
+TEST(MultilibTest, SelectMultiple) {
+  MultilibSet MS({
+  Multilib("/a", {}, {}, {"x"}),
+  Multilib("/b", {}, {}, {"y"}),
+  });
+  std::vector Selection;
+
+  Selection = MS.select({"x"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y"});
+  ASSERT_EQ(1u, Selection.size());
+  EXPECT_EQ("/b", Selection[0].gccSuffix());
+
+  Selection = MS.select({"y", "x"});
+  ASSERT_EQ(2u, Selection.size());
+  EXPECT_EQ("/a", Selection[0].gccSuffix());
+  EXPECT_EQ("/b", Selection[1].gccSuffix());
+}
Index: clang/unittests/Driver/MultilibBuilderTest.cpp
===
--- clang/unittests/Driver/MultilibBuilderTest.cpp
+++ clang/unittests/Driver/MultilibBuilderTest.cpp
@@ -157,14 +157,14 @@
 .Maybe(MultilibBuilder("64").flag("+m64"))
 .makeMultilibSet();
 
-  Multilib::flags_list FlagM64 = {"+m64"};
+  Multilib::flag_set FlagM64 = {"+m64"};
   Multilib SelectionM64;
   ASSERT_TRUE(MS1.select(FlagM64, SelectionM64))
   << "Flag set was {\"+m64\"}, but selection not found";
   ASSERT_TRUE(SelectionM64.gccSuffix() == "/64")
   << "Selection picked " << SelectionM64 << " which was not expected";
 
-  Multilib::flags_list FlagNoM64 = {"-m64"};
+  Multilib::flag_set FlagNoM64 = {"-m64"};
   Multilib SelectionNoM64;
   ASSERT_TRUE(MS1.select(FlagNoM64, SelectionNoM64))
   << "Flag set was {\"-m64\"}, but selection not found";
@@ -181,16 +181,16 @@
   for (unsigned I = 0; 

[PATCH] D142932: [NFC] Multilib YAML parsing

2023-02-22 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 499443.
michaelplatings added a subscriber: peter.smith.
michaelplatings added a comment.

- Squash D143763  into this change as 
suggested by @MaskRay
- Use PascalCase field names as requested by @phosek
- Applied improvements to error messages suggested by @peter.smith
- Removed some braces as requested by @MaskRay
- Moved serialization structs to anonymous namespace as requested by @MaskRay


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142932/new/

https://reviews.llvm.org/D142932

Files:
  clang/include/clang/Driver/Multilib.h
  clang/lib/Driver/Multilib.cpp
  clang/unittests/Driver/MultilibTest.cpp

Index: clang/unittests/Driver/MultilibTest.cpp
===
--- clang/unittests/Driver/MultilibTest.cpp
+++ clang/unittests/Driver/MultilibTest.cpp
@@ -13,6 +13,7 @@
 #include "clang/Driver/Multilib.h"
 #include "../../lib/Driver/ToolChains/CommonArgs.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/Version.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -187,3 +188,408 @@
   EXPECT_EQ("/a", Selection[0].gccSuffix());
   EXPECT_EQ("/b", Selection[1].gccSuffix());
 }
+
+static void diagnosticCallback(const llvm::SMDiagnostic , void *Out) {
+  *reinterpret_cast(Out) = D.getMessage();
+}
+
+static bool parse(MultilibSet , std::string , const char *Data) {
+  return MS.parse(llvm::MemoryBufferRef(Data, "TEST"), diagnosticCallback,
+  );
+}
+
+static bool parse(MultilibSet , std::string ,
+  const std::string ) {
+  return MS.parse(llvm::MemoryBufferRef(Data, "TEST"), diagnosticCallback,
+  );
+}
+
+static bool parse(MultilibSet , const char *Data) {
+  return MS.parse(llvm::MemoryBufferRef(Data, "TEST"));
+}
+
+#define _STRINGIFY(x) #x
+#define STRINGIFY(x) _STRINGIFY(x)
+// Avoid using MULTILIB_CLANG_VERSION in case it has extra non-numeric parts.
+#define MULTILIB_CLANG_VERSION \
+  STRINGIFY(CLANG_VERSION_MAJOR)   \
+  "." STRINGIFY(CLANG_VERSION_MINOR) "." STRINGIFY(CLANG_VERSION_PATCHLEVEL)
+#define YAML_PREAMBLE "ClangMinimumVersion: " MULTILIB_CLANG_VERSION "\n"
+
+TEST(MultilibTest, ParseInvalid) {
+  std::string Diagnostic;
+
+  MultilibSet MS;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, R"(
+Variants: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic)
+  .contains("missing required key 'ClangMinimumVersion'"))
+  << Diagnostic;
+
+  // Require all 3 major.minor.patch version components
+  EXPECT_FALSE(parse(MS, Diagnostic, R"(
+ClangMinimumVersion: )" STRINGIFY(CLANG_VERSION_MAJOR) R"(.0
+Variants: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic)
+  .contains("not a valid version string. Expected "
+"MAJOR.MINOR.PATCHLEVEL but got \"" STRINGIFY(
+CLANG_VERSION_MAJOR) ".0\""))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, R"(
+ClangMinimumVersion: )" MULTILIB_CLANG_VERSION R"(a
+Variants: []
+)"));
+  EXPECT_TRUE(
+  StringRef(Diagnostic)
+  .contains("not a valid version string. Expected "
+"MAJOR.MINOR.PATCHLEVEL where all components are decimal "
+"integers but got \"" MULTILIB_CLANG_VERSION "a\""))
+  << Diagnostic;
+
+  // Reject configurations that require a later clang version
+  EXPECT_FALSE(parse(MS, Diagnostic,
+ R"(
+ClangMinimumVersion: )" + std::to_string(CLANG_VERSION_MAJOR + 1) +
+ R"(.0.0
+Variants: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic)
+  .contains("clang version " MULTILIB_CLANG_VERSION
+" is less than ClangMinimumVersion: " +
+std::to_string(CLANG_VERSION_MAJOR + 1) + ".0.0"))
+  << Diagnostic;
+
+  // but accept configurations that only need an earlier clang version
+  EXPECT_TRUE(parse(MS, Diagnostic, R"(
+ClangMinimumVersion: 16.0.0
+Variants: []
+)")) << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, YAML_PREAMBLE));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Variants'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: /abc
+  Flags: []
+  PrintArgs: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("paths must be relative"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Flags: []
+  PrintArgs: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Dir'"))
+  << Diagnostic;
+
+  EXPECT_FALSE(parse(MS, Diagnostic, YAML_PREAMBLE R"(
+Variants:
+- Dir: .
+  PrintArgs: []
+)"));
+  EXPECT_TRUE(StringRef(Diagnostic).contains("missing required key 'Flags'"))

[PATCH] D143587: [Docs] Multilib design

2023-02-23 Thread Michael Platings via Phabricator via cfe-commits
michaelplatings updated this revision to Diff 499963.
michaelplatings added a comment.

PrintArgs -> PrintOptions


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D143587/new/

https://reviews.llvm.org/D143587

Files:
  clang/docs/Multilib.rst
  clang/docs/index.rst

Index: clang/docs/index.rst
===
--- clang/docs/index.rst
+++ clang/docs/index.rst
@@ -100,6 +100,7 @@
CodeOwners
InternalsManual
DriverInternals
+   Multilib
OffloadingDesign
PCHInternals
ItaniumMangleAbiTags
Index: clang/docs/Multilib.rst
===
--- /dev/null
+++ clang/docs/Multilib.rst
@@ -0,0 +1,327 @@
+
+Multilib
+
+
+Introduction
+
+
+This document describes how multilib is implemented in Clang.
+
+What is multilib and why might you care?
+If you're :doc:`cross compiling` then you can't use native
+system headers and libraries. To address this, you can use a combination of
+``--sysroot``, ``-isystem`` and ``-L`` options to point Clang at suitable
+directories for your target.
+However, when there are many possible directories to choose from, it's not
+necessarily obvious which one to pick.
+Multilib allows a toolchain designer to imbue the toolchain with the ability to
+pick a suitable directory automatically, based on the options the user provides
+to Clang. For example, if the user specifies
+``--target=arm-none-eabi -mcpu=cortex-m4`` the toolchain can choose a directory
+containing headers and libraries suitable for Armv7E-M, because it knows that's
+a suitable architecture for Arm Cortex-M4.
+Multilib can also choose between libraries for the same architecture based on
+other options. For example if the user specifies ``-fno-exceptions`` then a
+toolchain could select libraries built without exception support, thereby
+reducing the size of the resulting binary.
+
+Design
+==
+
+Clang supports GCC's ``-print-multi-lib`` and ``-print-multi-directory``
+options. These are described in
+`GCC Developer Options `_.
+
+There are two ways to configure multilib in Clang: hard-coded or via a
+configuration file.
+
+Hard-coded Multilib
+===
+
+The available libraries can be hard-coded in Clang. Typically this is done
+using the ``MultilibBuilder`` interface in
+``clang/include/clang/Driver/MultilibBuilder.h``.
+There are many examples of this in ``lib/Driver/ToolChains/Gnu.cpp``.
+The remainder of this document will not focus on this type of multilib.
+
+Multilib via configuration file
+===
+
+Some Clang toolchains support loading multilib configuration from a
+``multilib.yaml`` configuration file.
+
+A ``multilib.yaml`` configuration file specifies which multilib variants are
+available, their relative location, what compilation options were used to build
+them, and the criteria by which they are selected.
+
+Multilib processing
+===
+
+Clang goes through the following steps to use multilib from a configuration
+file:
+#. Convert command line arguments to flags. Clang can accept the same
+   information via different arguments - for example,
+   ``--target=arm-none-eabi -march=armv7-m`` and
+   ``--target=armv7m-none-eabi`` are equivalent. Clang can also accept many
+   independent pieces of information within a single flag - for example
+   ``-march=armv8.1m.main+fp+mve`` specifies the architecture and two
+   extensions in a single command line argument.
+   To make it easier for the multilib system, Clang converts the command line
+   arguments into a standard set of simpler "flags". In many cases these flags
+   will look like a command line argument with the leading ``-`` stripped off,
+   but where a suitable form for the flag doesn't exist in command line
+   arguments then its form will be different. For example, an Arm architecture
+   extension is represented like ``march=+mve`` since there's no way to specify
+   it in isolation in a command line argument.
+   To see what flags are emitted for a given set of command line arguments, use
+   the ``-print-multi-selection-flags-experimental`` command line argument
+   along with the rest of the arguments you want to use.
+#. Load ``multilib.yaml`` from sysroot.
+#. Generate additional flags. ``multilib.yaml`` contains a ``flagMap`` section,
+   which specifies how to generate additional flags based on the flags derived
+   from command line arguments. Flags are matched using regular expressions.
+   These regular expressions shall use the POSIX extended regular expression
+   syntax.
+#. Match flags against multilib variants. If the generated flags are a superset
+   of the flags specified for a multilib variant then the variant is considered
+   a match.
+   If more than one variant matches then a toolchain may opt to either use only
+  

  1   2   3   >