[PATCH] D65249: [NFC] use C++11 in AlignOf.h, remove AlignedCharArray

2021-02-08 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.
Herald added a subscriber: JDevlieghere.

Hi @jfb This patch results in a compiler crash when building a simple C program 
on a Windows X86 Debug build. I have filed this 
 issue to track it.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D65249

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


[PATCH] D78853: [Analysis] Fix null pointer dereference warnings [1/n]

2020-04-27 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 260517.
mgrang retitled this revision from "[Sema] Fix null pointer dereference 
warnings [1/n]" to "[Analysis] Fix null pointer dereference warnings [1/n]".

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

https://reviews.llvm.org/D78853

Files:
  clang/lib/Analysis/ThreadSafety.cpp


Index: clang/lib/Analysis/ThreadSafety.cpp
===
--- clang/lib/Analysis/ThreadSafety.cpp
+++ clang/lib/Analysis/ThreadSafety.cpp
@@ -1935,6 +1935,10 @@
   CapDiagKind);
 
   if (isScopedVar) {
+// The default value for the argument VD to the current function is
+// nullptr. So we assert that VD is non null because we deref VD here.
+assert(VD && "!VD");
+
 // Add the managing object as a dummy mutex, mapped to the underlying 
mutex.
 SourceLocation MLoc = VD->getLocation();
 DeclRefExpr DRE(VD->getASTContext(), VD, false, VD->getType(), VK_LValue,


Index: clang/lib/Analysis/ThreadSafety.cpp
===
--- clang/lib/Analysis/ThreadSafety.cpp
+++ clang/lib/Analysis/ThreadSafety.cpp
@@ -1935,6 +1935,10 @@
   CapDiagKind);
 
   if (isScopedVar) {
+// The default value for the argument VD to the current function is
+// nullptr. So we assert that VD is non null because we deref VD here.
+assert(VD && "!VD");
+
 // Add the managing object as a dummy mutex, mapped to the underlying mutex.
 SourceLocation MLoc = VD->getLocation();
 DeclRefExpr DRE(VD->getASTContext(), VD, false, VD->getType(), VK_LValue,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D78853: [Sema] Fix null pointer dereference warnings [1/n]

2020-04-27 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D78853#2003866 , @efriedma wrote:

> Please don't add null checks for pointers that can't be null.  It makes the 
> code slower and harder to understand.  And least one of the checks you added 
> is actively breaking the code.
>
> In some cases, the analysis is pointing to cases where the code could be made 
> more clear for both humans and machines with some refactoring or assertions.  
> Patches welcome, but please make sure any assertions properly explain the 
> invariant. And please split the patches up a bit more; adding assertions for 
> complex invariants in ten different unrelated places is more than I really 
> want to review at once.
>
> (Also, a reminder, please post patches with full context.)


Thanks @efriedma. Will split up the patches into smaller chunks and also post 
with full context.


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

https://reviews.llvm.org/D78853



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


[PATCH] D78853: [Sema] Fix null pointer dereference warnings [1/n]

2020-04-24 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang created this revision.
mgrang added reviewers: rsmith, efriedma, rnk, dblaikie.

Running the PREfast static analysis tool on clang resulted in several null
pointer dereference warnings. This is the first of several patches to fix
these.

The full list of warnings reported is here: 
https://docs.google.com/spreadsheets/d/1h_3tHxsgBampxb7PXoB5lgwiBSpTty9RLe5maIQxnTk/edit#gid=2014408543


https://reviews.llvm.org/D78853

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaExprObjC.cpp
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/lib/Sema/SemaTemplateVariadic.cpp
  clang/lib/Sema/SemaType.cpp
  clang/lib/Sema/TreeTransform.h

Index: clang/lib/Sema/TreeTransform.h
===
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -13921,7 +13921,7 @@
   }
 
   // Determine whether this should be a builtin operation.
-  if (Op == OO_Subscript) {
+  if (Op == OO_Subscript && Second) {
 if (!First->getType()->isOverloadableType() &&
 !Second->getType()->isOverloadableType())
   return getSema().CreateBuiltinArraySubscriptExpr(
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -8289,7 +8289,7 @@
   // unless it's actually needed.
   if (Tag || IFace) {
 // Avoid diagnosing invalid decls as incomplete.
-if (Def->isInvalidDecl())
+if (Def && Def->isInvalidDecl())
   return true;
 
 // Give the external AST source a chance to complete the type.
Index: clang/lib/Sema/SemaTemplateVariadic.cpp
===
--- clang/lib/Sema/SemaTemplateVariadic.cpp
+++ clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -765,6 +765,8 @@
   // retain an expansion.
   if (NumPartialExpansions) {
 if (NumExpansions && *NumExpansions < *NumPartialExpansions) {
+  assert(CurrentInstantiationScope && "!CurrentInstantiationScope");
+
   NamedDecl *PartialPack =
   CurrentInstantiationScope->getPartiallySubstitutedPack();
   Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_partial)
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5186,7 +5186,7 @@
   LocalEagerInstantiationScope LocalInstantiations(*this);
 
   VarDecl *OldVar = Var;
-  if (Def->isStaticDataMember() && !Def->isOutOfLine()) {
+  if (Def && Def->isStaticDataMember() && !Def->isOutOfLine()) {
 // We're instantiating an inline static data member whose definition was
 // provided inside the class.
 InstantiateVariableInitializer(Var, Def, TemplateArgs);
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -10413,7 +10413,8 @@
 !ToRefTy->getPointeeType()->isIncompleteType() &&
 S.IsDerivedFrom(SourceLocation(), ToRefTy->getPointeeType(), FromTy)) {
   BaseToDerivedConversion = 3;
-} else if (ToTy->isLValueReferenceType() && !FromExpr->isLValue() &&
+} else if (ToTy->isLValueReferenceType() && FromExpr &&
+   !FromExpr->isLValue() &&
ToTy.getNonReferenceType().getCanonicalType() ==
FromTy.getNonReferenceType().getCanonicalType()) {
   S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_lvalue)
Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -5912,11 +5912,11 @@
 DeclAccessPair dap;
 if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) {
   AddZeroInitializationStep(Entity.getType());
-} else if (Initializer->getType() == Context.OverloadTy &&
+} else if (Initializer && Initializer->getType() == Context.OverloadTy &&
!S.ResolveAddressOfOverloadedFunction(Initializer, DestType,
  false, dap))
   SetFailed(InitializationSequence::FK_AddressOfOverloadFailed);
-else if (Initializer->getType()->isFunctionType() &&
+else if (Initializer && Initializer->getType()->isFunctionType() &&
  isExprAnUnaddressableFunction(S, Initializer))
   SetFailed(InitializationSequence::FK_AddressOfUnaddressableFunction);
 else
Index: clang/lib/Sema/SemaExprObjC.cpp
===
--- clang/lib/Sema/SemaExprObjC.cpp
+++ clang/lib/Sema/SemaExprObjC.cpp
@@ -589,6 +589,8 @@
   }
 
   BoxingMethod = StringWithUTF8StringMethod;
+   

[PATCH] D66122: [CodeGen] Emit dynamic initializers for static TLS vars in outlined scopes

2019-08-16 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added inline comments.



Comment at: clang/lib/CodeGen/CodeGenFunction.cpp:472
+
+  llvm::sort(OrderedVarInits.begin(), OrderedVarInits.end(),
+  [](const VarDecl *a, const VarDecl *b) {

You can use the range-based version of llvm::sort here:

`llvm::sort(OrderedVarInits);`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D66122



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


[PATCH] D59279: [Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers

2019-05-24 Thread Mandeep Singh Grang via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL361664: [Analyzer] Checker for non-determinism caused by 
iteration of unordered… (authored by mgrang, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D59279?vs=190472=201310#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D59279

Files:
  cfe/trunk/docs/analyzer/checkers.rst
  cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
  cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt
  cfe/trunk/lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp
  cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
  cfe/trunk/test/Analysis/ptr-iter.cpp
  cfe/trunk/www/analyzer/alpha_checks.html

Index: cfe/trunk/www/analyzer/alpha_checks.html
===
--- cfe/trunk/www/analyzer/alpha_checks.html
+++ cfe/trunk/www/analyzer/alpha_checks.html
@@ -1068,6 +1068,24 @@
 Name, DescriptionExample
 
 
+
+alpha.nondeterminism.PointerIteration
+(C++)
+Check for non-determinism caused by iterating unordered containers of pointers.
+
+
+// C++
+void test() {
+ int a = 1, b = 2;
+ std::unordered_set UnorderedPtrSet = {, };
+
+ for (auto i : UnorderedPtrSet) // warn
+   f(i);
+}
+
+
+
+
 
 alpha.nondeterminism.PointerSorting
 (C++)
Index: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
===
--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -1340,6 +1340,10 @@
 
 let ParentPackage = NonDeterminismAlpha in {
 
+def PointerIterationChecker : Checker<"PointerIteration">,
+  HelpText<"Checks for non-determinism caused by iteration of unordered containers of pointers">,
+  Documentation;
+
 def PointerSortingChecker : Checker<"PointerSorting">,
   HelpText<"Check for non-determinism caused by sorting of pointers">,
   Documentation;
Index: cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -846,3 +846,64 @@
   template
   BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPredicate p);
 }
+
+namespace std {
+
+template< class T = void >
+struct less;
+
+template< class T >
+struct allocator;
+
+template< class Key >
+struct hash;
+
+template<
+  class Key,
+  class Compare = std::less,
+  class Alloc = std::allocator
+> class set {
+  public:
+set(initializer_list __list) {}
+
+class iterator {
+public:
+  iterator(Key *key): ptr(key) {}
+  iterator operator++() { ++ptr; return *this; }
+  bool operator!=(const iterator ) const { return ptr != other.ptr; }
+  const Key *() const { return *ptr; }
+private:
+  Key *ptr;
+};
+
+  public:
+Key *val;
+iterator begin() const { return iterator(val); }
+iterator end() const { return iterator(val + 1); }
+};
+
+template<
+  class Key,
+  class Hash = std::hash,
+  class Compare = std::less,
+  class Alloc = std::allocator
+> class unordered_set {
+  public:
+unordered_set(initializer_list __list) {}
+
+class iterator {
+public:
+  iterator(Key *key): ptr(key) {}
+  iterator operator++() { ++ptr; return *this; }
+  bool operator!=(const iterator ) const { return ptr != other.ptr; }
+  const Key *() const { return *ptr; }
+private:
+  Key *ptr;
+};
+
+  public:
+Key *val;
+iterator begin() const { return iterator(val); }
+iterator end() const { return iterator(val + 1); }
+};
+}
Index: cfe/trunk/test/Analysis/ptr-iter.cpp
===
--- cfe/trunk/test/Analysis/ptr-iter.cpp
+++ cfe/trunk/test/Analysis/ptr-iter.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_analyze_cc1 %s -analyzer-output=text -verify \
+// RUN: -analyzer-checker=core,alpha.nondeterminism.PointerIteration
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+template
+void f(T x);
+
+void PointerIteration() {
+  int a = 1, b = 2;
+  std::set OrderedIntSet = {a, b};
+  std::set OrderedPtrSet = {, };
+  std::unordered_set UnorderedIntSet = {a, b};
+  std::unordered_set UnorderedPtrSet = {, };
+
+  for (auto i : OrderedIntSet) // no-warning
+f(i);
+
+  for (auto i : OrderedPtrSet) // no-warning
+f(i);
+
+  for (auto i : UnorderedIntSet) // no-warning
+f(i);
+
+  for (auto i : UnorderedPtrSet) // expected-warning {{Iteration of pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerIteration]
+// expected-note@-1 {{Iteration of pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerIteration]
+f(i);
+}

[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-05-03 Thread Mandeep Singh Grang via Phabricator via cfe-commits
This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rC359932: [COFF, ARM64] Fix ABI implementation of struct 
returns (authored by mgrang, committed by ).

Repository:
  rC Clang

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

https://reviews.llvm.org/D60349

Files:
  include/clang/AST/DeclCXX.h
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeGen/arm64-microsoft-arguments.cpp
  test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp

Index: test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
===
--- test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -69,6 +69,11 @@
   int bb;
 };
 
+struct SmallWithPrivate {
+private:
+ int i;
+};
+
 // WIN32: declare dso_local void @"{{.*take_bools_and_chars.*}}"
 // WIN32:   (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
 // WIN32:   i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
@@ -165,7 +170,7 @@
 // WIN64:   call void @"??1SmallWithDtor@@QEAA@XZ"
 // WIN64: }
 // WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
-// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"
+// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA64: }
 
 // FIXME: MSVC incompatible!
@@ -173,6 +178,12 @@
 // WOA:   call arm_aapcs_vfpcc void @"??1SmallWithDtor@@QAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA: }
 
+
+// Test that the eligible non-aggregate is passed directly, but returned
+// indirectly on ARM64 Windows.
+// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(%struct.SmallWithPrivate* inreg noalias sret %agg.result, i64 %s.coerce) {{.*}} {
+SmallWithPrivate small_arg_with_private_member(SmallWithPrivate s) { return s; }
+
 void call_small_arg_with_dtor() {
   small_arg_with_dtor(SmallWithDtor());
 }
Index: test/CodeGen/arm64-microsoft-arguments.cpp
===
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -1,25 +1,203 @@
 // RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
 // RUN: -x c++ -o - %s | FileCheck %s
 
-struct pod { int a, b, c, d, e; };
+// Pass and return for type size <= 8 bytes.
+// CHECK: define {{.*}} i64 @{{.*}}f1{{.*}}()
+// CHECK: call i64 {{.*}}func1{{.*}}(i64 %3)
+struct S1 {
+  int a[2];
+};
+
+S1 func1(S1 x);
+S1 f1() {
+  S1 x;
+  return func1(x);
+}
+
+// Pass and return type size <= 16 bytes.
+// CHECK: define {{.*}} [2 x i64] @{{.*}}f2{{.*}}()
+// CHECK: call [2 x i64] {{.*}}func2{{.*}}([2 x i64] %3)
+struct S2 {
+  int a[4];
+};
+
+S2 func2(S2 x);
+S2 f2() {
+  S2 x;
+  return func2(x);
+}
+
+// Pass and return for type size > 16 bytes.
+// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(%struct.S3* noalias sret %agg.result)
+// CHECK: call void {{.*}}func3{{.*}}(%struct.S3* sret %agg.result, %struct.S3* %agg.tmp)
+struct S3 {
+  int a[5];
+};
+
+S3 func3(S3 x);
+S3 f3() {
+  S3 x;
+  return func3(x);
+}
+
+// Pass and return aggregate (of size < 16 bytes) with non-trivial destructor.
+// Passed directly but returned indirectly.
+// CHECK: define {{.*}} void {{.*}}f4{{.*}}(%struct.S4* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}func4{{.*}}(%struct.S4* inreg sret %agg.result, [2 x i64] %4)
+struct S4 {
+  int a[3];
+  ~S4();
+};
+
+S4 func4(S4 x);
+S4 f4() {
+  S4 x;
+  return func4(x);
+}
+
+// Pass and return from instance method called from instance method.
+// CHECK: define {{.*}} void @{{.*}}bar@Q1{{.*}}(%class.Q1* %this, %class.P1* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}foo@P1{{.*}}(%class.P1* %ref.tmp, %class.P1* inreg sret %agg.result, i8 %0)
+
+class P1 {
+public:
+  P1 foo(P1 x);
+};
+
+class Q1 {
+public:
+  P1 bar();
+};
+
+P1 Q1::bar() {
+  P1 p1;
+  return P1().foo(p1);
+}
+
+// Pass and return from instance method called from free function.
+// CHECK: define {{.*}} void {{.*}}bar{{.*}}()
+// CHECK: call void {{.*}}foo@P2{{.*}}(%class.P2* %ref.tmp, %class.P2* inreg sret %retval, i8 %0)
+class P2 {
+public:
+  P2 foo(P2 x);
+};
+
+P2 bar() {
+  P2 p2;
+  return P2().foo(p2);
+}
+
+// Pass and return an object with a user-provided constructor (passed directly,
+// returned indirectly)
+// CHECK: define {{.*}} void @{{.*}}f5{{.*}}(%struct.S5* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}func5{{.*}}(%struct.S5* inreg sret %agg.result, i64 {{.*}})
+struct S5 {
+  S5();
+  int x;
+};
+
+S5 func5(S5 x);
+S5 f5() {
+  S5 x;
+  return func5(x);
+}
+
+// Pass and return an object with a non-trivial explicitly defaulted constructor
+// (passed directly, returned directly)
+// CHECK: define {{.*}} i64 

[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-05-02 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D60349#1488411 , @efriedma wrote:

> LGTM, assuming it passes testing on electron


Thanks Eli. @richard.townsend.arm Can you please confirm whether Electron works 
with this patch and D60348 ?


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

https://reviews.llvm.org/D60349



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


[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-05-02 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 197831.
mgrang edited the summary of this revision.

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

https://reviews.llvm.org/D60349

Files:
  include/clang/AST/DeclCXX.h
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeGen/arm64-microsoft-arguments.cpp
  test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp

Index: test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
===
--- test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -69,6 +69,11 @@
   int bb;
 };
 
+struct SmallWithPrivate {
+private:
+ int i;
+};
+
 // WIN32: declare dso_local void @"{{.*take_bools_and_chars.*}}"
 // WIN32:   (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
 // WIN32:   i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
@@ -165,7 +170,7 @@
 // WIN64:   call void @"??1SmallWithDtor@@QEAA@XZ"
 // WIN64: }
 // WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
-// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"
+// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA64: }
 
 // FIXME: MSVC incompatible!
@@ -173,6 +178,12 @@
 // WOA:   call arm_aapcs_vfpcc void @"??1SmallWithDtor@@QAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA: }
 
+
+// Test that the eligible non-aggregate is passed directly, but returned
+// indirectly on ARM64 Windows.
+// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(%struct.SmallWithPrivate* inreg noalias sret %agg.result, i64 %s.coerce) {{.*}} {
+SmallWithPrivate small_arg_with_private_member(SmallWithPrivate s) { return s; }
+
 void call_small_arg_with_dtor() {
   small_arg_with_dtor(SmallWithDtor());
 }
Index: test/CodeGen/arm64-microsoft-arguments.cpp
===
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -1,25 +1,203 @@
 // RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
 // RUN: -x c++ -o - %s | FileCheck %s
 
-struct pod { int a, b, c, d, e; };
+// Pass and return for type size <= 8 bytes.
+// CHECK: define {{.*}} i64 @{{.*}}f1{{.*}}()
+// CHECK: call i64 {{.*}}func1{{.*}}(i64 %3)
+struct S1 {
+  int a[2];
+};
+
+S1 func1(S1 x);
+S1 f1() {
+  S1 x;
+  return func1(x);
+}
+
+// Pass and return type size <= 16 bytes.
+// CHECK: define {{.*}} [2 x i64] @{{.*}}f2{{.*}}()
+// CHECK: call [2 x i64] {{.*}}func2{{.*}}([2 x i64] %3)
+struct S2 {
+  int a[4];
+};
+
+S2 func2(S2 x);
+S2 f2() {
+  S2 x;
+  return func2(x);
+}
+
+// Pass and return for type size > 16 bytes.
+// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(%struct.S3* noalias sret %agg.result)
+// CHECK: call void {{.*}}func3{{.*}}(%struct.S3* sret %agg.result, %struct.S3* %agg.tmp)
+struct S3 {
+  int a[5];
+};
+
+S3 func3(S3 x);
+S3 f3() {
+  S3 x;
+  return func3(x);
+}
+
+// Pass and return aggregate (of size < 16 bytes) with non-trivial destructor.
+// Passed directly but returned indirectly.
+// CHECK: define {{.*}} void {{.*}}f4{{.*}}(%struct.S4* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}func4{{.*}}(%struct.S4* inreg sret %agg.result, [2 x i64] %4)
+struct S4 {
+  int a[3];
+  ~S4();
+};
+
+S4 func4(S4 x);
+S4 f4() {
+  S4 x;
+  return func4(x);
+}
+
+// Pass and return from instance method called from instance method.
+// CHECK: define {{.*}} void @{{.*}}bar@Q1{{.*}}(%class.Q1* %this, %class.P1* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}foo@P1{{.*}}(%class.P1* %ref.tmp, %class.P1* inreg sret %agg.result, i8 %0)
+
+class P1 {
+public:
+  P1 foo(P1 x);
+};
+
+class Q1 {
+public:
+  P1 bar();
+};
+
+P1 Q1::bar() {
+  P1 p1;
+  return P1().foo(p1);
+}
+
+// Pass and return from instance method called from free function.
+// CHECK: define {{.*}} void {{.*}}bar{{.*}}()
+// CHECK: call void {{.*}}foo@P2{{.*}}(%class.P2* %ref.tmp, %class.P2* inreg sret %retval, i8 %0)
+class P2 {
+public:
+  P2 foo(P2 x);
+};
+
+P2 bar() {
+  P2 p2;
+  return P2().foo(p2);
+}
 
-struct non_pod {
-  int a;
-  non_pod() {}
+// Pass and return an object with a user-provided constructor (passed directly,
+// returned indirectly)
+// CHECK: define {{.*}} void @{{.*}}f5{{.*}}(%struct.S5* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}func5{{.*}}(%struct.S5* inreg sret %agg.result, i64 {{.*}})
+struct S5 {
+  S5();
+  int x;
 };
 
-struct pod s;
-struct non_pod t;
+S5 func5(S5 x);
+S5 f5() {
+  S5 x;
+  return func5(x);
+}
 
-struct pod bar() { return s; }
-struct non_pod foo() { return t; }
-// CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result)
-// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result)
+// Pass and return an object with a 

[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-30 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 197436.

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

https://reviews.llvm.org/D60349

Files:
  include/clang/AST/DeclCXX.h
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeGen/arm64-microsoft-arguments.cpp
  test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp

Index: test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
===
--- test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -69,6 +69,11 @@
   int bb;
 };
 
+struct SmallWithPrivate {
+private:
+ int i;
+};
+
 // WIN32: declare dso_local void @"{{.*take_bools_and_chars.*}}"
 // WIN32:   (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
 // WIN32:   i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
@@ -165,7 +170,7 @@
 // WIN64:   call void @"??1SmallWithDtor@@QEAA@XZ"
 // WIN64: }
 // WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
-// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"
+// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA64: }
 
 // FIXME: MSVC incompatible!
@@ -173,6 +178,12 @@
 // WOA:   call arm_aapcs_vfpcc void @"??1SmallWithDtor@@QAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA: }
 
+
+// Test that the eligible non-aggregate is passed directly, but returned
+// indirectly on ARM64 Windows.
+// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(%struct.SmallWithPrivate* inreg noalias sret %agg.result, i64 %s.coerce) {{.*}} {
+SmallWithPrivate small_arg_with_private_member(SmallWithPrivate s) { return s; }
+
 void call_small_arg_with_dtor() {
   small_arg_with_dtor(SmallWithDtor());
 }
Index: test/CodeGen/arm64-microsoft-arguments.cpp
===
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -1,25 +1,187 @@
 // RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
 // RUN: -x c++ -o - %s | FileCheck %s
 
-struct pod { int a, b, c, d, e; };
+// Pass and return for type size <= 8 bytes.
+// CHECK: define {{.*}} i64 @{{.*}}f1{{.*}}()
+// CHECK: call i64 {{.*}}func1{{.*}}(i64 %3)
+struct S1 {
+  int a[2];
+};
+
+S1 func1(S1 x);
+S1 f1() {
+  S1 x;
+  return func1(x);
+}
+
+// Pass and return type size <= 16 bytes.
+// CHECK: define {{.*}} [2 x i64] @{{.*}}f2{{.*}}()
+// CHECK: call [2 x i64] {{.*}}func2{{.*}}([2 x i64] %3)
+struct S2 {
+  int a[4];
+};
+
+S2 func2(S2 x);
+S2 f2() {
+  S2 x;
+  return func2(x);
+}
+
+// Pass and return for type size > 16 bytes.
+// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(%struct.S3* noalias sret %agg.result)
+// CHECK: call void {{.*}}func3{{.*}}(%struct.S3* sret %agg.result, %struct.S3* %agg.tmp)
+struct S3 {
+  int a[5];
+};
+
+S3 func3(S3 x);
+S3 f3() {
+  S3 x;
+  return func3(x);
+}
+
+// Pass and return aggregate (of size < 16 bytes) with non-trivial destructor.
+// Passed directly but returned indirectly.
+// CHECK: define {{.*}} void {{.*}}f4{{.*}}(%struct.S4* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}func4{{.*}}(%struct.S4* inreg sret %agg.result, [2 x i64] %4)
+struct S4 {
+  int a[3];
+  ~S4();
+};
+
+S4 func4(S4 x);
+S4 f4() {
+  S4 x;
+  return func4(x);
+}
+
+// Pass and return from instance method called from instance method.
+// CHECK: define {{.*}} void @{{.*}}bar@Q1{{.*}}(%class.Q1* %this, %class.P1* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}foo@P1{{.*}}(%class.P1* %ref.tmp, %class.P1* inreg sret %agg.result, i8 %0)
+
+class P1 {
+public:
+  P1 foo(P1 x);
+};
+
+class Q1 {
+public:
+  P1 bar();
+};
+
+P1 Q1::bar() {
+  P1 p1;
+  return P1().foo(p1);
+}
+
+// Pass and return from instance method called from free function.
+// CHECK: define {{.*}} void {{.*}}bar{{.*}}()
+// CHECK: call void {{.*}}foo@P2{{.*}}(%class.P2* %ref.tmp, %class.P2* inreg sret %retval, i8 %0)
+class P2 {
+public:
+  P2 foo(P2 x);
+};
+
+P2 bar() {
+  P2 p2;
+  return P2().foo(p2);
+}
+
+// Pass and return an object with a user-provided constructor (passed directly,
+// returned indirectly)
+// CHECK: define {{.*}} void @{{.*}}f5{{.*}}(%struct.S5* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}func5{{.*}}(%struct.S5* inreg sret %agg.result, i64 {{.*}})
+struct S5 {
+  S5();
+  int x;
+};
+
+S5 func5(S5 x);
+S5 f5() {
+  S5 x;
+  return func5(x);
+}
+
+// Pass and return an object with a non-trivial explicitly defaulted constructor
+// (passed directly, returned directly)
+// CHECK: define {{.*}} i64 @"?f6@@YA?AUS6@@XZ"()
+// CHECK: call i64 {{.*}}func6{{.*}}(i64 {{.*}})
+struct S6a {
+  S6a();
+};
+
+struct S6 {
+  S6() = default;
+  S6a x;
+};
 
-struct non_pod {
-  int a;
-  non_pod() {}
+S6 func6(S6 x);
+S6 f6() {
+  S6 x;
+  return func6(x);
+}
+

[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-29 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

Thanks @richard.townsend.arm . I have updated the patch.


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

https://reviews.llvm.org/D60349



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


[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-29 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 197158.

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

https://reviews.llvm.org/D60349

Files:
  include/clang/AST/DeclCXX.h
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeGen/arm64-microsoft-arguments.cpp
  test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp

Index: test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
===
--- test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -69,6 +69,11 @@
   int bb;
 };
 
+struct SmallWithPrivate {
+private:
+ int i;
+};
+
 // WIN32: declare dso_local void @"{{.*take_bools_and_chars.*}}"
 // WIN32:   (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
 // WIN32:   i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
@@ -165,7 +170,7 @@
 // WIN64:   call void @"??1SmallWithDtor@@QEAA@XZ"
 // WIN64: }
 // WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
-// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"
+// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA64: }
 
 // FIXME: MSVC incompatible!
@@ -173,6 +178,12 @@
 // WOA:   call arm_aapcs_vfpcc void @"??1SmallWithDtor@@QAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA: }
 
+
+// Test that the eligible non-aggregate is passed directly, but returned
+// indirectly on ARM64 Windows.
+// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(%struct.SmallWithPrivate* inreg noalias sret %agg.result, i64 %s.coerce) {{.*}} {
+SmallWithPrivate small_arg_with_private_member(SmallWithPrivate s) { return s; }
+
 void call_small_arg_with_dtor() {
   small_arg_with_dtor(SmallWithDtor());
 }
Index: test/CodeGen/arm64-microsoft-arguments.cpp
===
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -1,25 +1,88 @@
 // RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
 // RUN: -x c++ -o - %s | FileCheck %s
 
-struct pod { int a, b, c, d, e; };
+// Pass and return for type size <= 8 bytes.
+// CHECK: define {{.*}} i64 @{{.*}}f1{{.*}}()
+// CHECK: call i64 {{.*}}func1{{.*}}(i64 %3)
+struct S1 {
+  int a[2];
+};
+
+S1 func1(S1 x);
+S1 f1() {
+  S1 x;
+  return func1(x);
+}
 
-struct non_pod {
-  int a;
-  non_pod() {}
+// Pass and return type size <= 16 bytes.
+// CHECK: define {{.*}} [2 x i64] @{{.*}}f2{{.*}}()
+// CHECK: call [2 x i64] {{.*}}func2{{.*}}([2 x i64] %3)
+struct S2 {
+  int a[4];
 };
 
-struct pod s;
-struct non_pod t;
+S2 func2(S2 x);
+S2 f2() {
+  S2 x;
+  return func2(x);
+}
+
+// Pass and return for type size > 16 bytes.
+// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(%struct.S3* noalias sret %agg.result)
+// CHECK: call void {{.*}}func3{{.*}}(%struct.S3* sret %agg.result, %struct.S3* %agg.tmp)
+struct S3 {
+  int a[5];
+};
+
+S3 func3(S3 x);
+S3 f3() {
+  S3 x;
+  return func3(x);
+}
+
+// Pass and return aggregate (of size < 16 bytes) with non-trivial destructor.
+// Passed directly but returned indirectly.
+// CHECK: define {{.*}} void {{.*}}f4{{.*}}(%struct.S4* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}func4{{.*}}(%struct.S4* inreg sret %agg.result, [2 x i64] %4)
+struct S4 {
+  int a[3];
+  ~S4();
+};
 
-struct pod bar() { return s; }
-struct non_pod foo() { return t; }
-// CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result)
-// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result)
+S4 func4(S4 x);
+S4 f4() {
+  S4 x;
+  return func4(x);
+}
 
+// Pass and return from instance method called from instance method.
+// CHECK: define {{.*}} void @{{.*}}bar@Q1{{.*}}(%class.Q1* %this, %class.P1* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}foo@P1{{.*}}(%class.P1* %ref.tmp, %class.P1* inreg sret %agg.result, i8 %0)
 
-// Check instance methods.
-struct pod2 { int x; };
-struct Baz { pod2 baz(); };
+class P1 {
+public:
+  P1 foo(P1 x);
+};
+
+class Q1 {
+public:
+  P1 bar();
+};
+
+P1 Q1::bar() {
+  P1 p1;
+  return P1().foo(p1);
+}
+
+// Pass and return from instance method called from free function.
+// CHECK: define {{.*}} void {{.*}}bar{{.*}}()
+// CHECK: call void {{.*}}foo@P2{{.*}}(%class.P2* %ref.tmp, %class.P2* inreg sret %retval, i8 %0)
+class P2 {
+public:
+  P2 foo(P2 x);
+};
 
-int qux() { return Baz().baz().x; }
-// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2*)
+P2 bar() {
+  P2 p2;
+  return P2().foo(p2);
+}
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -5952,8 +5952,11 @@
 
 // Note: This permits small classes with nontrivial destructors to be
 // passed in 

[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-26 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 196894.

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

https://reviews.llvm.org/D60349

Files:
  include/clang/AST/DeclCXX.h
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeGen/arm64-microsoft-arguments.cpp
  test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp

Index: test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
===
--- test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -69,6 +69,11 @@
   int bb;
 };
 
+struct SmallWithPrivate {
+private:
+ int i;
+};
+
 // WIN32: declare dso_local void @"{{.*take_bools_and_chars.*}}"
 // WIN32:   (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
 // WIN32:   i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
@@ -165,7 +170,7 @@
 // WIN64:   call void @"??1SmallWithDtor@@QEAA@XZ"
 // WIN64: }
 // WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
-// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"
+// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA64: }
 
 // FIXME: MSVC incompatible!
@@ -173,6 +178,12 @@
 // WOA:   call arm_aapcs_vfpcc void @"??1SmallWithDtor@@QAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA: }
 
+
+// Test that the eligible non-aggregate is passed directly, but returned
+// indirectly on ARM64 Windows.
+// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(%struct.SmallWithPrivate* inreg noalias sret %agg.result, i64 %s.coerce) {{.*}} {
+SmallWithPrivate small_arg_with_private_member(SmallWithPrivate s) { return s; }
+
 void call_small_arg_with_dtor() {
   small_arg_with_dtor(SmallWithDtor());
 }
Index: test/CodeGen/arm64-microsoft-arguments.cpp
===
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -1,25 +1,88 @@
 // RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
 // RUN: -x c++ -o - %s | FileCheck %s
 
-struct pod { int a, b, c, d, e; };
+// Pass and return for type size <= 8 bytes.
+// CHECK: define {{.*}} i64 @{{.*}}f1{{.*}}()
+// CHECK: call i64 {{.*}}func1{{.*}}(i64 %3)
+struct S1 {
+  int a[2];
+};
+
+S1 func1(S1 x);
+S1 f1() {
+  S1 x;
+  return func1(x);
+}
 
-struct non_pod {
-  int a;
-  non_pod() {}
+// Pass and return type size <= 16 bytes.
+// CHECK: define {{.*}} [2 x i64] @{{.*}}f2{{.*}}()
+// CHECK: call [2 x i64] {{.*}}func2{{.*}}([2 x i64] %3)
+struct S2 {
+  int a[4];
 };
 
-struct pod s;
-struct non_pod t;
+S2 func2(S2 x);
+S2 f2() {
+  S2 x;
+  return func2(x);
+}
+
+// Pass and return for type size > 16 bytes.
+// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(%struct.S3* noalias sret %agg.result)
+// CHECK: call void {{.*}}func3{{.*}}(%struct.S3* sret %agg.result, %struct.S3* %agg.tmp)
+struct S3 {
+  int a[5];
+};
+
+S3 func3(S3 x);
+S3 f3() {
+  S3 x;
+  return func3(x);
+}
+
+// Pass and return aggregate (of size < 16 bytes) with non-trivial destructor.
+// Passed directly but returned indirectly.
+// CHECK: define {{.*}} void {{.*}}f4{{.*}}(%struct.S4* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}func4{{.*}}(%struct.S4* inreg sret %agg.result, [2 x i64] %4)
+struct S4 {
+  int a[3];
+  ~S4();
+};
 
-struct pod bar() { return s; }
-struct non_pod foo() { return t; }
-// CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result)
-// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result)
+S4 func4(S4 x);
+S4 f4() {
+  S4 x;
+  return func4(x);
+}
 
+// Pass and return from instance method called from instance method.
+// CHECK: define {{.*}} void @{{.*}}bar@Q1{{.*}}(%class.Q1* %this, %class.P1* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}foo@P1{{.*}}(%class.P1* %ref.tmp, %class.P1* inreg sret %agg.result, i8 %0)
 
-// Check instance methods.
-struct pod2 { int x; };
-struct Baz { pod2 baz(); };
+class P1 {
+public:
+  P1 foo(P1 x);
+};
+
+class Q1 {
+public:
+  P1 bar();
+};
+
+P1 Q1::bar() {
+  P1 p1;
+  return P1().foo(p1);
+}
+
+// Pass and return from instance method called from free function.
+// CHECK: define {{.*}} void {{.*}}bar{{.*}}()
+// CHECK: call void {{.*}}foo@P2{{.*}}(%class.P2* %ref.tmp, %class.P2* inreg sret %retval, i8 %0)
+class P2 {
+public:
+  P2 foo(P2 x);
+};
 
-int qux() { return Baz().baz().x; }
-// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2*)
+P2 bar() {
+  P2 p2;
+  return P2().foo(p2);
+}
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -5952,8 +5952,11 @@
 
 // Note: This permits small classes with nontrivial destructors to be
 // passed in 

[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-25 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 196774.

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

https://reviews.llvm.org/D60349

Files:
  include/clang/AST/DeclCXX.h
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeGen/arm64-microsoft-arguments.cpp
  test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp

Index: test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
===
--- test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -69,6 +69,11 @@
   int bb;
 };
 
+struct SmallWithPrivate {
+private:
+ int i;
+};
+
 // WIN32: declare dso_local void @"{{.*take_bools_and_chars.*}}"
 // WIN32:   (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
 // WIN32:   i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
@@ -164,8 +169,8 @@
 // WIN64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
 // WIN64:   call void @"??1SmallWithDtor@@QEAA@XZ"
 // WIN64: }
-// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
-// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"
+// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
+// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA64: }
 
 // FIXME: MSVC incompatible!
@@ -173,6 +178,12 @@
 // WOA:   call arm_aapcs_vfpcc void @"??1SmallWithDtor@@QAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA: }
 
+
+// Test that the eligible non-aggregate is passed directly, but returned
+// indirectly on ARM64 Windows.
+// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(%struct.SmallWithPrivate* inreg noalias sret %agg.result, i64 %s.coerce) {{.*}} {
+SmallWithPrivate small_arg_with_private_member(SmallWithPrivate s) { return s; }
+
 void call_small_arg_with_dtor() {
   small_arg_with_dtor(SmallWithDtor());
 }
Index: test/CodeGen/arm64-microsoft-arguments.cpp
===
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -1,25 +1,88 @@
 // RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
 // RUN: -x c++ -o - %s | FileCheck %s
 
-struct pod { int a, b, c, d, e; };
+// Pass and return for type size <= 8 bytes.
+// CHECK: define {{.*}} i64 @{{.*}}f1{{.*}}()
+// CHECK: call i64 {{.*}}func1{{.*}}(i64 %3)
+struct S1 {
+  int a[2];
+};
+
+S1 func1(S1 x);
+S1 f1() {
+  S1 x;
+  return func1(x);
+}
 
-struct non_pod {
-  int a;
-  non_pod() {}
+// Pass and return type size <= 16 bytes.
+// CHECK: define {{.*}} [2 x i64] @{{.*}}f2{{.*}}()
+// CHECK: call [2 x i64] {{.*}}func2{{.*}}([2 x i64] %3)
+struct S2 {
+  int a[4];
 };
 
-struct pod s;
-struct non_pod t;
+S2 func2(S2 x);
+S2 f2() {
+  S2 x;
+  return func2(x);
+}
+
+// Pass and return for type size > 16 bytes.
+// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(%struct.S3* noalias sret %agg.result)
+// CHECK: call void {{.*}}func3{{.*}}(%struct.S3* sret %agg.result, %struct.S3* %agg.tmp)
+struct S3 {
+  int a[5];
+};
+
+S3 func3(S3 x);
+S3 f3() {
+  S3 x;
+  return func3(x);
+}
+
+// Pass and return aggregate (of size < 16 bytes) with non-trivial destructor.
+// Passed directly but returned indirectly.
+// CHECK: define {{.*}} void {{.*}}f4{{.*}}(%struct.S4* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}func4{{.*}}(%struct.S4* inreg sret %agg.result, [2 x i64] %4)
+struct S4 {
+  int a[3];
+  ~S4();
+};
 
-struct pod bar() { return s; }
-struct non_pod foo() { return t; }
-// CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result)
-// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result)
+S4 func4(S4 x);
+S4 f4() {
+  S4 x;
+  return func4(x);
+}
 
+// Pass and return from instance method called from instance method.
+// CHECK: define {{.*}} void @{{.*}}bar@Q1{{.*}}(%class.Q1* %this, %class.P1* inreg noalias sret %agg.result)
+// CHECK: call void {{.*}}foo@P1{{.*}}(%class.P1* %ref.tmp, %class.P1* inreg sret %agg.result, i8 %0)
 
-// Check instance methods.
-struct pod2 { int x; };
-struct Baz { pod2 baz(); };
+class P1 {
+public:
+  P1 foo(P1 x);
+};
+
+class Q1 {
+public:
+  P1 bar();
+};
+
+P1 Q1::bar() {
+  P1 p1;
+  return P1().foo(p1);
+}
+
+// Pass and return from instance method called from free function.
+// CHECK: define {{.*}} void {{.*}}bar{{.*}}()
+// CHECK: call void {{.*}}foo@P2{{.*}}(%class.P2* %ref.tmp, %class.P2* inreg sret %retval, i8 %0)
+class P2 {
+public:
+  P2 foo(P2 x);
+};
 
-int qux() { return Baz().baz().x; }
-// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2*)
+P2 bar() {
+  P2 p2;
+  return P2().foo(p2);
+}
Index: lib/Sema/SemaDeclCXX.cpp

[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-23 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 196342.

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

https://reviews.llvm.org/D60349

Files:
  include/clang/AST/DeclCXX.h
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeGen/arm64-microsoft-arguments.cpp
  test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp

Index: test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
===
--- test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -69,6 +69,11 @@
   int bb;
 };
 
+struct SmallWithPrivate {
+private:
+ int i;
+};
+
 // WIN32: declare dso_local void @"{{.*take_bools_and_chars.*}}"
 // WIN32:   (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
 // WIN32:   i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
@@ -164,8 +169,8 @@
 // WIN64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
 // WIN64:   call void @"??1SmallWithDtor@@QEAA@XZ"
 // WIN64: }
-// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
-// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"
+// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
+// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA64: }
 
 // FIXME: MSVC incompatible!
@@ -173,6 +178,12 @@
 // WOA:   call arm_aapcs_vfpcc void @"??1SmallWithDtor@@QAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA: }
 
+
+// Test that the eligible non-aggregate is passed directly, but returned
+// indirectly on ARM64 Windows.
+// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(%struct.SmallWithPrivate* inreg noalias sret %agg.result, i64 %s.coerce) {{.*}} {
+SmallWithPrivate small_arg_with_private_member(SmallWithPrivate s) { return s; }
+
 void call_small_arg_with_dtor() {
   small_arg_with_dtor(SmallWithDtor());
 }
Index: test/CodeGen/arm64-microsoft-arguments.cpp
===
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -1,25 +1,31 @@
 // RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
 // RUN: -x c++ -o - %s | FileCheck %s
 
-struct pod { int a, b, c, d, e; };
+// Return type size <= 8 bytes.
+// CHECK: define {{.*}} i64 @{{.*}}f1{{.*}}()
+struct S1 { int a, b; };
+S1 f1() { return S1{}; }
 
-struct non_pod {
-  int a;
-  non_pod() {}
-};
+// Return type size <= 16 bytes.
+// CHECK: define {{.*}} [2 x i64] @{{.*}}f2{{.*}}()
+struct S2 { int a, b, c, d; };
+S2 f2() { return S2{}; }
 
-struct pod s;
-struct non_pod t;
+// Return type size > 16 bytes.
+// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(%struct.S3* noalias sret %agg.result)
+struct S3 { int a, b, c, d, e; };
+S3 f3() { return S3{}; }
 
-struct pod bar() { return s; }
-struct non_pod foo() { return t; }
-// CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result)
-// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result)
+// Instance methods.
+// CHECK: define {{.*}} void @{{.*}}inst@C{{.*}}(%class.C* %this, %class.A* inreg noalias sret %agg.result)
 
+class A {};
 
-// Check instance methods.
-struct pod2 { int x; };
-struct Baz { pod2 baz(); };
+class C {
+public:
+  A inst();
+};
 
-int qux() { return Baz().baz().x; }
-// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2*)
+A C::inst() {
+  return A();
+}
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -5952,7 +5952,8 @@
 
 // Note: This permits small classes with nontrivial destructors to be
 // passed in registers, which is non-conforming.
-if (CopyCtorIsTrivial &&
+bool isAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
+if (!isAArch64 && CopyCtorIsTrivial &&
 S.getASTContext().getTypeSize(D->getTypeForDecl()) <= 64)
   return true;
 return false;
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -52,6 +52,10 @@
 
   bool classifyReturnType(CGFunctionInfo ) const override;
 
+  bool passClassIndirect(const CXXRecordDecl *RD) const {
+return !canCopyArgument(RD);
+  }
+
   RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override;
 
   bool isSRetParameterAfterThis() const override { return true; }
@@ -1051,33 +1055,44 @@
   return isDeletingDtor(GD);
 }
 
+static bool hasMicrosoftABIRestrictions(const CXXRecordDecl *RD) {
+  // The checks below ensure that thare no user provided constructors.
+  // For AArch64, we use the C++14 

[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-23 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 196341.

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

https://reviews.llvm.org/D60349

Files:
  include/clang/AST/DeclCXX.h
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeGen/arm64-microsoft-arguments.cpp
  test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp

Index: test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
===
--- test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -3,7 +3,6 @@
 // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=thumb-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA %s
 // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 %s
 // RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=aarch64-windows-msvc -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA64 %s
-
 struct Empty {};
 
 struct EmptyWithCtor {
@@ -69,6 +68,11 @@
   int bb;
 };
 
+struct SmallWithPrivate {
+private:
+ int i;
+};
+
 // WIN32: declare dso_local void @"{{.*take_bools_and_chars.*}}"
 // WIN32:   (<{ i8, [3 x i8], i8, [3 x i8], %struct.SmallWithDtor,
 // WIN32:   i8, [3 x i8], i8, [3 x i8], i32, i8, [3 x i8] }>* inalloca)
@@ -164,8 +168,8 @@
 // WIN64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
 // WIN64:   call void @"??1SmallWithDtor@@QEAA@XZ"
 // WIN64: }
-// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
-// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"
+// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
+// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA64: }
 
 // FIXME: MSVC incompatible!
@@ -173,6 +177,12 @@
 // WOA:   call arm_aapcs_vfpcc void @"??1SmallWithDtor@@QAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA: }
 
+
+// Test that the eligible non-aggregate is passed directly, but returned
+// indirectly on ARM64 Windows.
+// WOA64: define dso_local void @"?small_arg_with_private_member@@YA?AUSmallWithPrivate@@U1@@Z"(%struct.SmallWithPrivate* inreg noalias sret %agg.result, i64 %s.coerce) {{.*}} {
+SmallWithPrivate small_arg_with_private_member(SmallWithPrivate s) { return s; }
+
 void call_small_arg_with_dtor() {
   small_arg_with_dtor(SmallWithDtor());
 }
Index: test/CodeGen/arm64-microsoft-arguments.cpp
===
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -1,25 +1,31 @@
 // RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
 // RUN: -x c++ -o - %s | FileCheck %s
 
-struct pod { int a, b, c, d, e; };
+// Return type size <= 8 bytes.
+// CHECK: define {{.*}} i64 @{{.*}}f1{{.*}}()
+struct S1 { int a, b; };
+S1 f1() { return S1{}; }
 
-struct non_pod {
-  int a;
-  non_pod() {}
-};
+// Return type size <= 16 bytes.
+// CHECK: define {{.*}} [2 x i64] @{{.*}}f2{{.*}}()
+struct S2 { int a, b, c, d; };
+S2 f2() { return S2{}; }
 
-struct pod s;
-struct non_pod t;
+// Return type size > 16 bytes.
+// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(%struct.S3* noalias sret %agg.result)
+struct S3 { int a, b, c, d, e; };
+S3 f3() { return S3{}; }
 
-struct pod bar() { return s; }
-struct non_pod foo() { return t; }
-// CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result)
-// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result)
+// Instance methods.
+// CHECK: define {{.*}} void @{{.*}}inst@C{{.*}}(%class.C* %this, %class.A* inreg noalias sret %agg.result)
 
+class A {};
 
-// Check instance methods.
-struct pod2 { int x; };
-struct Baz { pod2 baz(); };
+class C {
+public:
+  A inst();
+};
 
-int qux() { return Baz().baz().x; }
-// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2*)
+A C::inst() {
+  return A();
+}
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -5952,7 +5952,8 @@
 
 // Note: This permits small classes with nontrivial destructors to be
 // passed in registers, which is non-conforming.
-if (CopyCtorIsTrivial &&
+bool isAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
+if (!isAArch64 && CopyCtorIsTrivial &&
 S.getASTContext().getTypeSize(D->getTypeForDecl()) <= 64)
   return true;
 return false;
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -52,6 +52,10 @@
 
   bool classifyReturnType(CGFunctionInfo ) const 

[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-22 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 196144.

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

https://reviews.llvm.org/D60349

Files:
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeGen/arm64-microsoft-arguments.cpp
  test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp

Index: test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
===
--- test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -164,8 +164,8 @@
 // WIN64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
 // WIN64:   call void @"??1SmallWithDtor@@QEAA@XZ"
 // WIN64: }
-// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
-// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"
+// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
+// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA64: }
 
 // FIXME: MSVC incompatible!
Index: test/CodeGen/arm64-microsoft-arguments.cpp
===
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -1,25 +1,31 @@
 // RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
 // RUN: -x c++ -o - %s | FileCheck %s
 
-struct pod { int a, b, c, d, e; };
+// Return type size <= 8 bytes.
+// CHECK: define {{.*}} i64 @{{.*}}f1{{.*}}()
+struct S1 { int a, b; };
+S1 f1() { return S1{}; }
 
-struct non_pod {
-  int a;
-  non_pod() {}
-};
+// Return type size <= 16 bytes.
+// CHECK: define {{.*}} [2 x i64] @{{.*}}f2{{.*}}()
+struct S2 { int a, b, c, d; };
+S2 f2() { return S2{}; }
 
-struct pod s;
-struct non_pod t;
+// Return type size > 16 bytes.
+// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(%struct.S3* noalias sret %agg.result)
+struct S3 { int a, b, c, d, e; };
+S3 f3() { return S3{}; }
 
-struct pod bar() { return s; }
-struct non_pod foo() { return t; }
-// CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result)
-// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result)
+// Instance methods.
+// CHECK: define {{.*}} void @{{.*}}inst@C{{.*}}(%class.C* %this, %class.A* inreg noalias sret %agg.result)
 
+class A {};
 
-// Check instance methods.
-struct pod2 { int x; };
-struct Baz { pod2 baz(); };
+class C {
+public:
+  A inst();
+};
 
-int qux() { return Baz().baz().x; }
-// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2*)
+A C::inst() {
+  return A();
+}
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -5902,6 +5902,27 @@
!D->hasNonTrivialCopyConstructorForCall();
 
   if (CCK == TargetInfo::CCK_MicrosoftWin64) {
+bool isAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
+
+// The checks below ensure that thare no user provided constructors.
+// For AArch64, we use the C++14 definition of an aggregate, so we also
+// check for:
+//   No private or protected non static data members.
+//   No base classes
+//   No virtual functions
+// Additionally, we need to ensure that there is a trivial copy assignment
+// operator.
+if (isAArch64) {
+  if (D->getAccess() == AS_private || D->getAccess() == AS_protected)
+return false;
+  if (D->getNumBases() > 0)
+return false;
+  if (D->isPolymorphic())
+return false;
+  if (D->needsImplicitCopyAssignment() && !D->hasTrivialCopyAssignment())
+return false;
+}
+
 bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;
 bool DtorIsTrivialForCall = false;
 
@@ -5952,7 +5973,7 @@
 
 // Note: This permits small classes with nontrivial destructors to be
 // passed in registers, which is non-conforming.
-if (CopyCtorIsTrivial &&
+if (!isAArch64 && CopyCtorIsTrivial &&
 S.getASTContext().getTypeSize(D->getTypeForDecl()) <= 64)
   return true;
 return false;
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -52,6 +52,10 @@
 
   bool classifyReturnType(CGFunctionInfo ) const override;
 
+  bool passClassIndirect(const CXXRecordDecl *RD) const {
+return !canCopyArgument(RD);
+  }
+
   RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override;
 
   bool isSRetParameterAfterThis() const override { return true; }
@@ -1056,28 +1060,17 @@
   if (!RD)
 return false;
 
-  CharUnits Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
-  if (FI.isInstanceMethod()) {
-// If it's an 

[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-22 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 196109.

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

https://reviews.llvm.org/D60349

Files:
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeGen/arm64-microsoft-arguments.cpp
  test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp

Index: test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
===
--- test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -164,8 +164,8 @@
 // WIN64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i32 %s.coerce) {{.*}} {
 // WIN64:   call void @"??1SmallWithDtor@@QEAA@XZ"
 // WIN64: }
-// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(i64 %s.coerce) {{.*}} {
-// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"
+// WOA64: define dso_local void @"?small_arg_with_dtor@@YAXUSmallWithDtor@@@Z"(%struct.SmallWithDtor* %s) {{.*}} {
+// WOA64:   call void @"??1SmallWithDtor@@QEAA@XZ"(%struct.SmallWithDtor* %s)
 // WOA64: }
 
 // FIXME: MSVC incompatible!
Index: test/CodeGen/arm64-microsoft-arguments.cpp
===
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -1,25 +1,31 @@
 // RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
 // RUN: -x c++ -o - %s | FileCheck %s
 
-struct pod { int a, b, c, d, e; };
+// Return type size <= 8 bytes.
+// CHECK: define {{.*}} i64 @{{.*}}f1{{.*}}()
+struct S1 { int a, b; };
+S1 f1() { return S1{}; }
 
-struct non_pod {
-  int a;
-  non_pod() {}
-};
+// Return type size <= 16 bytes.
+// CHECK: define {{.*}} [2 x i64] @{{.*}}f2{{.*}}()
+struct S2 { int a, b, c, d; };
+S2 f2() { return S2{}; }
 
-struct pod s;
-struct non_pod t;
+// Return type size > 16 bytes.
+// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(%struct.S3* noalias sret %agg.result)
+struct S3 { int a, b, c, d, e; };
+S3 f3() { return S3{}; }
 
-struct pod bar() { return s; }
-struct non_pod foo() { return t; }
-// CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result)
-// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result)
+// Instance methods.
+// CHECK: define {{.*}} void @{{.*}}inst@C{{.*}}(%class.C* %this, %class.A* inreg noalias sret %agg.result)
 
+class A {};
 
-// Check instance methods.
-struct pod2 { int x; };
-struct Baz { pod2 baz(); };
+class C {
+public:
+  A inst();
+};
 
-int qux() { return Baz().baz().x; }
-// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2*)
+A C::inst() {
+  return A();
+}
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -5902,8 +5902,13 @@
!D->hasNonTrivialCopyConstructorForCall();
 
   if (CCK == TargetInfo::CCK_MicrosoftWin64) {
+bool isAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
+if (isAArch64 && !D->isAggregate())
+  return false;
+
 bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;
 bool DtorIsTrivialForCall = false;
+bool CopyAssignmentIsTrivial = !isAArch64;
 
 // If a class has at least one non-deleted, trivial copy constructor, it
 // is passed according to the C ABI. Otherwise, it is passed indirectly.
@@ -5929,6 +5934,9 @@
   }
 }
 
+if (isAArch64 && D->needsImplicitCopyAssignment())
+  CopyAssignmentIsTrivial = D->hasTrivialCopyAssignment();
+
 if (D->needsImplicitDestructor()) {
   if (!D->defaultedDestructorIsDeleted() &&
   D->hasTrivialDestructorForCall())
@@ -5939,7 +5947,8 @@
 }
 
 // If the copy ctor and dtor are both trivial-for-calls, pass direct.
-if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall)
+if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall &&
+CopyAssignmentIsTrivial)
   return true;
 
 // If a class has a destructor, we'd really like to pass it indirectly
@@ -5952,7 +5961,7 @@
 
 // Note: This permits small classes with nontrivial destructors to be
 // passed in registers, which is non-conforming.
-if (CopyCtorIsTrivial &&
+if (!isAArch64 && CopyCtorIsTrivial &&
 S.getASTContext().getTypeSize(D->getTypeForDecl()) <= 64)
   return true;
 return false;
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -52,6 +52,10 @@
 
   bool classifyReturnType(CGFunctionInfo ) const override;
 
+  bool passClassIndirect(const CXXRecordDecl *RD) const {
+return !canCopyArgument(RD);
+  }
+
   RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override;
 
   bool isSRetParameterAfterThis() const override { 

[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-19 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 195932.

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

https://reviews.llvm.org/D60349

Files:
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  lib/Sema/SemaDeclCXX.cpp
  test/CodeGen/arm64-microsoft-arguments.cpp

Index: test/CodeGen/arm64-microsoft-arguments.cpp
===
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -1,25 +1,31 @@
 // RUN: %clang_cc1 -triple aarch64-windows -ffreestanding -emit-llvm -O0 \
 // RUN: -x c++ -o - %s | FileCheck %s
 
-struct pod { int a, b, c, d, e; };
+// Return type size <= 8 bytes.
+// CHECK: define {{.*}} i64 @{{.*}}f1{{.*}}()
+struct S1 { int a, b; };
+S1 f1() { return S1{}; }
 
-struct non_pod {
-  int a;
-  non_pod() {}
-};
+// Return type size <= 16 bytes.
+// CHECK: define {{.*}} [2 x i64] @{{.*}}f2{{.*}}()
+struct S2 { int a, b, c, d; };
+S2 f2() { return S2{}; }
 
-struct pod s;
-struct non_pod t;
+// Return type size > 16 bytes.
+// CHECK: define {{.*}} void @{{.*}}f3{{.*}}(%struct.S3* noalias sret %agg.result)
+struct S3 { int a, b, c, d, e; };
+S3 f3() { return S3{}; }
 
-struct pod bar() { return s; }
-struct non_pod foo() { return t; }
-// CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result)
-// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result)
+// Instance methods.
+// CHECK: define {{.*}} void @{{.*}}inst@C{{.*}}(%class.C* %this, %class.A* inreg noalias sret %agg.result)
 
+class A {};
 
-// Check instance methods.
-struct pod2 { int x; };
-struct Baz { pod2 baz(); };
+class C {
+public:
+  A inst();
+};
 
-int qux() { return Baz().baz().x; }
-// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2*)
+A C::inst() {
+  return A();
+}
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -5902,8 +5902,13 @@
!D->hasNonTrivialCopyConstructorForCall();
 
   if (CCK == TargetInfo::CCK_MicrosoftWin64) {
+bool isAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
+if (isAArch64 && !D->isAggregate())
+  return false;
+
 bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;
 bool DtorIsTrivialForCall = false;
+bool CopyAssignmentIsTrivial = !isAArch64;
 
 // If a class has at least one non-deleted, trivial copy constructor, it
 // is passed according to the C ABI. Otherwise, it is passed indirectly.
@@ -5929,6 +5934,9 @@
   }
 }
 
+if (isAArch64 && D->needsImplicitCopyAssignment())
+  CopyAssignmentIsTrivial = D->hasTrivialCopyAssignment();
+
 if (D->needsImplicitDestructor()) {
   if (!D->defaultedDestructorIsDeleted() &&
   D->hasTrivialDestructorForCall())
@@ -5939,7 +5947,8 @@
 }
 
 // If the copy ctor and dtor are both trivial-for-calls, pass direct.
-if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall)
+if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall &&
+CopyAssignmentIsTrivial)
   return true;
 
 // If a class has a destructor, we'd really like to pass it indirectly
@@ -5952,7 +5961,7 @@
 
 // Note: This permits small classes with nontrivial destructors to be
 // passed in registers, which is non-conforming.
-if (CopyCtorIsTrivial &&
+if (!isAArch64 && CopyCtorIsTrivial &&
 S.getASTContext().getTypeSize(D->getTypeForDecl()) <= 64)
   return true;
 return false;
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -52,6 +52,10 @@
 
   bool classifyReturnType(CGFunctionInfo ) const override;
 
+  bool passClassIndirect(const CXXRecordDecl *RD) const {
+return !canCopyArgument(RD);
+  }
+
   RecordArgABI getRecordArgABI(const CXXRecordDecl *RD) const override;
 
   bool isSRetParameterAfterThis() const override { return true; }
@@ -1056,28 +1060,17 @@
   if (!RD)
 return false;
 
-  CharUnits Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
-  if (FI.isInstanceMethod()) {
-// If it's an instance method, aggregates are always returned indirectly via
-// the second parameter.
-FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
-FI.getReturnInfo().setSRetAfterThis(FI.isInstanceMethod());
+  bool isIndirectReturn = passClassIndirect(RD);
+  bool isInstanceMethod = FI.isInstanceMethod();
 
-// aarch64-windows requires that instance methods use X1 for the return
-// address. So for aarch64-windows we do not mark the
-// return as SRet.
-FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() ==
-   llvm::Triple::aarch64);
-return true;
-  } else 

[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-12 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang marked an inline comment as done.
mgrang added a comment.

In D60349#1462638 , @ostannard wrote:

> The document you linked in the LLVM change 
> (https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=vs-2019#return-values)
>  says that small POD types are returned directly in X0 or X0 and X1, but this 
> looks like it will always return them indirectly. I think we also need to 
> check the size of the type, and fall back the the plain C ABI for small types.





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

https://reviews.llvm.org/D60349



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


[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-12 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 194954.

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

https://reviews.llvm.org/D60349

Files:
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  test/CodeGen/arm64-microsoft-arguments.cpp

Index: test/CodeGen/arm64-microsoft-arguments.cpp
===
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -14,7 +14,7 @@
 struct pod bar() { return s; }
 struct non_pod foo() { return t; }
 // CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result)
-// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result)
+// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* inreg noalias sret %agg.result)
 
 
 // Check instance methods.
@@ -22,4 +22,4 @@
 struct Baz { pod2 baz(); };
 
 int qux() { return Baz().baz().x; }
-// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2*)
+// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2* sret)
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -1052,32 +1052,43 @@
 }
 
 bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo ) const {
+  // For AArch64 see:
+  // https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=vs-2019#return-values
+
+  // 1. For return types <= 16 bytes, use the C return semantics.
+
+  // 2. For instance methods, "this" is passed to the callee in X0 and the
+  // struct address in X1. So the callee needs to copy X1 to X0 before
+  // returning.
+
+  // 3. For non-instance methods which return a non-POD struct, the address of
+  // the struct is passed to the callee in X0. We use the "inreg" attribute on
+  // a parameter to indicate a non-POD struct.
+
+  // 4. Example of POD struct: struct pod { int x; }
+  //Example of non-POD struct: struct nonpod { int x; nonpod() {} }
+
+  bool isAArch64 = CGM.getTarget().getTriple().isAArch64();
+
+  if (isAArch64) {
+uint64_t RetTySize = getContext().getTypeSize(FI.getReturnType());
+if (RetTySize <= 16)
+  return false;
+  }
+
   const CXXRecordDecl *RD = FI.getReturnType()->getAsCXXRecordDecl();
   if (!RD)
 return false;
 
-  CharUnits Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
-  if (FI.isInstanceMethod()) {
-// If it's an instance method, aggregates are always returned indirectly via
-// the second parameter.
-FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
-FI.getReturnInfo().setSRetAfterThis(FI.isInstanceMethod());
+  bool isIndirectReturn = !RD->isPOD();
+  bool isInstanceMethod = FI.isInstanceMethod();
 
-// aarch64-windows requires that instance methods use X1 for the return
-// address. So for aarch64-windows we do not mark the
-// return as SRet.
-FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() ==
-   llvm::Triple::aarch64);
-return true;
-  } else if (!RD->isPOD()) {
-// If it's a free function, non-POD types are returned indirectly.
+  CharUnits Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
+  if (isIndirectReturn || isInstanceMethod) {
 FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
+FI.getReturnInfo().setSRetAfterThis(isInstanceMethod);
+FI.getReturnInfo().setInReg(isAArch64 && isIndirectReturn);
 
-// aarch64-windows requires that non-POD, non-instance returns use X0 for
-// the return address. So for aarch64-windows we do not mark the return as
-// SRet.
-FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() ==
-   llvm::Triple::aarch64);
 return true;
   }
 
Index: lib/CodeGen/CGCall.cpp
===
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -1999,8 +1999,7 @@
   // Attach attributes to sret.
   if (IRFunctionArgs.hasSRetArg()) {
 llvm::AttrBuilder SRETAttrs;
-if (!RetAI.getSuppressSRet())
-  SRETAttrs.addAttribute(llvm::Attribute::StructRet);
+SRETAttrs.addAttribute(llvm::Attribute::StructRet);
 hasUsedSRet = true;
 if (RetAI.getInReg())
   SRETAttrs.addAttribute(llvm::Attribute::InReg);
Index: include/clang/CodeGen/CGFunctionInfo.h
===
--- include/clang/CodeGen/CGFunctionInfo.h
+++ include/clang/CodeGen/CGFunctionInfo.h
@@ -95,7 +95,6 @@
   bool InReg : 1;   // isDirect() || isExtend() || isIndirect()
   bool CanBeFlattened: 1;   // isDirect()
   bool SignExt : 1; // isExtend()
-  bool SuppressSRet : 1;// isIndirect()
 
   bool canHavePaddingType() const {
 

[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-05 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

Got rid of the confusing SuppressSRet logic. The "inreg" attribute is now used 
to indicate sret returns in X0.


Repository:
  rC Clang

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

https://reviews.llvm.org/D60349



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


[PATCH] D60349: [COFF, ARM64] Fix ABI implementation of struct returns

2019-04-05 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang created this revision.
mgrang added reviewers: rnk, efriedma, TomTan, ssijaric.
Herald added subscribers: kristof.beyls, javed.absar.
Herald added a project: clang.

Related llvm patch: D60348 .


Repository:
  rC Clang

https://reviews.llvm.org/D60349

Files:
  include/clang/CodeGen/CGFunctionInfo.h
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/MicrosoftCXXABI.cpp
  test/CodeGen/arm64-microsoft-arguments.cpp

Index: test/CodeGen/arm64-microsoft-arguments.cpp
===
--- test/CodeGen/arm64-microsoft-arguments.cpp
+++ test/CodeGen/arm64-microsoft-arguments.cpp
@@ -14,7 +14,7 @@
 struct pod bar() { return s; }
 struct non_pod foo() { return t; }
 // CHECK: define {{.*}} void @{{.*}}bar{{.*}}(%struct.pod* noalias sret %agg.result)
-// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* noalias %agg.result)
+// CHECK: define {{.*}} void @{{.*}}foo{{.*}}(%struct.non_pod* inreg noalias sret %agg.result)
 
 
 // Check instance methods.
@@ -22,4 +22,4 @@
 struct Baz { pod2 baz(); };
 
 int qux() { return Baz().baz().x; }
-// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2*)
+// CHECK: declare {{.*}} void @{{.*}}baz@Baz{{.*}}(%struct.Baz*, %struct.pod2* sret)
Index: lib/CodeGen/MicrosoftCXXABI.cpp
===
--- lib/CodeGen/MicrosoftCXXABI.cpp
+++ lib/CodeGen/MicrosoftCXXABI.cpp
@@ -1056,28 +1056,25 @@
   if (!RD)
 return false;
 
+  // Note: The "inreg" attribute is used to signal that the struct return
+  // should be in X0.
+  bool sretInX0 = (CGM.getTarget().getTriple().getArch() ==
+   llvm::Triple::aarch64) && !RD->isPOD();
+
   CharUnits Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType());
   if (FI.isInstanceMethod()) {
 // If it's an instance method, aggregates are always returned indirectly via
 // the second parameter.
 FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
 FI.getReturnInfo().setSRetAfterThis(FI.isInstanceMethod());
+FI.getReturnInfo().setInReg(sretInX0);
 
-// aarch64-windows requires that instance methods use X1 for the return
-// address. So for aarch64-windows we do not mark the
-// return as SRet.
-FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() ==
-   llvm::Triple::aarch64);
 return true;
   } else if (!RD->isPOD()) {
 // If it's a free function, non-POD types are returned indirectly.
 FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false);
+FI.getReturnInfo().setInReg(sretInX0);
 
-// aarch64-windows requires that non-POD, non-instance returns use X0 for
-// the return address. So for aarch64-windows we do not mark the return as
-// SRet.
-FI.getReturnInfo().setSuppressSRet(CGM.getTarget().getTriple().getArch() ==
-   llvm::Triple::aarch64);
 return true;
   }
 
Index: lib/CodeGen/CGCall.cpp
===
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -1999,8 +1999,7 @@
   // Attach attributes to sret.
   if (IRFunctionArgs.hasSRetArg()) {
 llvm::AttrBuilder SRETAttrs;
-if (!RetAI.getSuppressSRet())
-  SRETAttrs.addAttribute(llvm::Attribute::StructRet);
+SRETAttrs.addAttribute(llvm::Attribute::StructRet);
 hasUsedSRet = true;
 if (RetAI.getInReg())
   SRETAttrs.addAttribute(llvm::Attribute::InReg);
Index: include/clang/CodeGen/CGFunctionInfo.h
===
--- include/clang/CodeGen/CGFunctionInfo.h
+++ include/clang/CodeGen/CGFunctionInfo.h
@@ -95,7 +95,6 @@
   bool InReg : 1;   // isDirect() || isExtend() || isIndirect()
   bool CanBeFlattened: 1;   // isDirect()
   bool SignExt : 1; // isExtend()
-  bool SuppressSRet : 1;// isIndirect()
 
   bool canHavePaddingType() const {
 return isDirect() || isExtend() || isIndirect() || isExpand();
@@ -111,14 +110,13 @@
   }
 
   ABIArgInfo(Kind K)
-  : TheKind(K), PaddingInReg(false), InReg(false), SuppressSRet(false) {
+  : TheKind(K), PaddingInReg(false), InReg(false) {
   }
 
 public:
   ABIArgInfo()
   : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0),
-TheKind(Direct), PaddingInReg(false), InReg(false),
-SuppressSRet(false) {}
+TheKind(Direct), PaddingInReg(false), InReg(false) {}
 
   static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
   llvm::Type *Padding = nullptr,
@@ -407,16 +405,6 @@
 CanBeFlattened = Flatten;
   }
 
-  bool getSuppressSRet() const {
-assert(isIndirect() && "Invalid kind!");
-return SuppressSRet;
-  }
-
-  void setSuppressSRet(bool Suppress) {
-assert(isIndirect() && "Invalid kind!");
-SuppressSRet = Suppress;
-  }
-
   

[PATCH] D59279: [Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers

2019-03-22 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D59279#1439014 , @Szelethus wrote:

> In D59279#1438514 , @mgrang wrote:
>
> > Although, as you rightly pointed out that //ordered// sets of pointers are 
> > as non-deterministic as //unordered// ones.
>
>
> What if you store pointers to the elements of an array? In that case, it 
> should be deterministic.
>
>   ---
>   |1|2|3|5|6|
>   ---
>^ ^ 
>p q
>
>
> In the above example, pointer `p`'s memory address will always be less then 
> `q`'s, so in an ordered set, iterating over them would be deterministic. When 
> hashing algorithms come into the picture, than it wouldn't be :^)


Yes, by //containers// here I mean //hashing containers//.


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

https://reviews.llvm.org/D59279



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


[PATCH] D59279: [Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers

2019-03-21 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D59279#1438500 , @rnkovacs wrote:

> In D59279#1427017 , @mgrang wrote:
>
> > Following are the assumptions/limitations of this patch:
> >
> >   1. The assumption is that iteration of ordered containers of pointers is 
> > not non-deterministic.
> >
>
>
> Could you please explain which type of non-determinism we are addressing 
> here? If our issue is that iteration order is not consistent across runs, 
> then an unordered set of //integers// seems just as non-deterministic as an 
> unordered set of //pointers//. On the other hand, if our issue is that 
> pointer values vary between runs, then an //ordered// set of pointers seems 
> just as non-deterministic as an //unordered// set of pointers. Are 
> //unordered// sets of //pointers// distinguished because they lie in the 
> intersection of these categories and thus avoid the most false positive 
> cases? If so, for someone debugging non-deterministic behavior in their code, 
> would it be useful to add a strict option that shows other cases too? If not, 
> maybe we could document our reasons somewhere.


Yes, the reason we limit the checks only to //unordered// containers is to 
reduce the false positive rate. Although, as you rightly pointed out that 
//ordered// sets of pointers are as non-deterministic as //unordered// ones. 
Once our checks have the capability to detect what happens inside the loop 
maybe we can add //ordered// sets too. I will add this to the TODO. Thanks.


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

https://reviews.llvm.org/D59279



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


[PATCH] D59279: [Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers

2019-03-20 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

Ping for reviews please.


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

https://reviews.llvm.org/D59279



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


[PATCH] D59279: [Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers

2019-03-14 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

I was trying to write another checker for hashing of pointers. Basically, I 
wanted to match all instances where the keys of std::map are pointers. Writing 
an AST matcher for std::map is straightforward. However, I am not sure how to 
check for pointer keys after matching std::map.

The following matches std::map. But I need to match std::map. 
So I was thinking something on the lines of 
templateArgument(hasType(pointerType())).

  auto ContainersM = anyOf(
   hasName("std::map"),
   hasName("std::unordered_map")
 );
  
  auto HashContainerM = varDecl(hasType(cxxRecordDecl(ContainersM)))


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

https://reviews.llvm.org/D59279



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


[PATCH] D59279: [Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers

2019-03-13 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 190472.

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

https://reviews.llvm.org/D59279

Files:
  docs/analyzer/checkers.rst
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp
  test/Analysis/Inputs/system-header-simulator-cxx.h
  test/Analysis/ptr-iter.cpp
  www/analyzer/alpha_checks.html

Index: www/analyzer/alpha_checks.html
===
--- www/analyzer/alpha_checks.html
+++ www/analyzer/alpha_checks.html
@@ -1182,6 +1182,24 @@
 Name, DescriptionExample
 
 
+
+alpha.nondeterminism.PointerIteration
+(C++)
+Check for non-determinism caused by iterating unordered containers of pointers.
+
+
+// C++
+void test() {
+ int a = 1, b = 2;
+ std::unordered_set UnorderedPtrSet = {, };
+
+ for (auto i : UnorderedPtrSet) // warn
+   f(i);
+}
+
+
+
+
 
 alpha.nondeterminism.PointerSorting
 (C++)
Index: test/Analysis/ptr-iter.cpp
===
--- /dev/null
+++ test/Analysis/ptr-iter.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_analyze_cc1 %s -analyzer-output=text -verify \
+// RUN: -analyzer-checker=core,alpha.nondeterminism.PointerIteration
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+template
+void f(T x);
+
+void PointerIteration() {
+  int a = 1, b = 2;
+  std::set OrderedIntSet = {a, b};
+  std::set OrderedPtrSet = {, };
+  std::unordered_set UnorderedIntSet = {a, b};
+  std::unordered_set UnorderedPtrSet = {, };
+
+  for (auto i : OrderedIntSet) // no-warning
+f(i);
+
+  for (auto i : OrderedPtrSet) // no-warning
+f(i);
+
+  for (auto i : UnorderedIntSet) // no-warning
+f(i);
+
+  for (auto i : UnorderedPtrSet) // expected-warning {{Iteration of pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerIteration]
+// expected-note@-1 {{Iteration of pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerIteration]
+f(i);
+}
Index: test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- test/Analysis/Inputs/system-header-simulator-cxx.h
+++ test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -845,3 +845,64 @@
   template
   BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPredicate p);
 }
+
+namespace std {
+
+template< class T = void >
+struct less;
+
+template< class T >
+struct allocator;
+
+template< class Key >
+struct hash;
+
+template<
+  class Key,
+  class Compare = std::less,
+  class Alloc = std::allocator
+> class set {
+  public:
+set(initializer_list __list) {}
+
+class iterator {
+public:
+  iterator(Key *key): ptr(key) {}
+  iterator operator++() { ++ptr; return *this; }
+  bool operator!=(const iterator ) const { return ptr != other.ptr; }
+  const Key *() const { return *ptr; }
+private:
+  Key *ptr;
+};
+
+  public:
+Key *val;
+iterator begin() const { return iterator(val); }
+iterator end() const { return iterator(val + 1); }
+};
+
+template<
+  class Key,
+  class Hash = std::hash,
+  class Compare = std::less,
+  class Alloc = std::allocator
+> class unordered_set {
+  public:
+unordered_set(initializer_list __list) {}
+
+class iterator {
+public:
+  iterator(Key *key): ptr(key) {}
+  iterator operator++() { ++ptr; return *this; }
+  bool operator!=(const iterator ) const { return ptr != other.ptr; }
+  const Key *() const { return *ptr; }
+private:
+  Key *ptr;
+};
+
+  public:
+Key *val;
+iterator begin() const { return iterator(val); }
+iterator end() const { return iterator(val + 1); }
+};
+}
Index: lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp
@@ -0,0 +1,100 @@
+//== PointerIterationChecker.cpp --- -*- C++ -*--=//
+//
+// 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
+//
+//===--===//
+//
+// This file defines PointerIterationChecker which checks for non-determinism
+// caused due to iteration of unordered containers of pointer elements.
+//
+//===--===//
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+using namespace ast_matchers;
+
+namespace {
+
+// ID 

[PATCH] D59279: [Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers

2019-03-13 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

> Could you please add a commit that changes the top of the file on your 
> previous commit? Feel free to do that without review (I can't commit it 
> myself atm).

Done in https://reviews.llvm.org/rC356086.


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

https://reviews.llvm.org/D59279



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


[PATCH] D59279: [Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers

2019-03-13 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

> The obvious question, why not implement this in clang-tidy?

Going forward I would like to make these non-determinism checks more precise by 
reasoning about what happens inside the loop, for example. I am not sure if 
clang-tidy has support for such deeper reasoning. I thought clang-tidy is more 
of a pattern matcher?


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

https://reviews.llvm.org/D59279



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


[PATCH] D59279: [Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers

2019-03-13 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

Also, what is the difference between these two: 
https://clang.llvm.org/docs/analyzer/checkers.html, 
https://clang-analyzer.llvm.org/available_checks.html. It seems they document 
similar stuff. Should we add the doc for each new checker in both of these?


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

https://reviews.llvm.org/D59279



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


[PATCH] D59279: [Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers

2019-03-13 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 190453.

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

https://reviews.llvm.org/D59279

Files:
  docs/analyzer/checkers.rst
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp
  test/Analysis/Inputs/system-header-simulator-cxx.h
  test/Analysis/ptr-iter.cpp
  www/analyzer/alpha_checks.html

Index: www/analyzer/alpha_checks.html
===
--- www/analyzer/alpha_checks.html
+++ www/analyzer/alpha_checks.html
@@ -1182,6 +1182,24 @@
 Name, DescriptionExample
 
 
+
+alpha.nondeterminism.PointerIteration
+(C++)
+Check for non-determinism caused by iterating unordered containers of pointers.
+
+
+// C++
+void test() {
+ int a = 1, b = 2;
+ std::unordered_set UnorderedPointerSet = {, };
+
+ for (auto i : UnorderedPointerSet) // warn
+   f(i);
+}
+
+
+
+
 
 alpha.nondeterminism.PointerSorting
 (C++)
Index: test/Analysis/ptr-iter.cpp
===
--- /dev/null
+++ test/Analysis/ptr-iter.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_analyze_cc1 %s -analyzer-output=text -verify \
+// RUN: -analyzer-checker=core,alpha.nondeterminism.PointerIteration
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+template
+void f(T x);
+
+void PointerIteration() {
+  int a = 1, b = 2;
+  std::set OrderedIntSet = {a, b};
+  std::set OrderedPointerSet = {, };
+  std::unordered_set UnorderedIntSet = {a, b};
+  std::unordered_set UnorderedPointerSet = {, };
+
+  for (auto i : OrderedIntSet) // no-warning
+f(i);
+
+  for (auto i : OrderedPointerSet) // no-warning
+f(i);
+
+  for (auto i : UnorderedIntSet) // no-warning
+f(i);
+
+  for (auto i : UnorderedPointerSet) // expected-warning {{Iteration of pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerIteration]
+// expected-note@-1 {{Iteration of pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerIteration]
+f(i);
+}
Index: test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- test/Analysis/Inputs/system-header-simulator-cxx.h
+++ test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -845,3 +845,64 @@
   template
   BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPredicate p);
 }
+
+namespace std {
+
+template< class T = void >
+struct less;
+
+template< class T >
+struct allocator;
+
+template< class Key >
+struct hash;
+
+template<
+  class Key,
+  class Compare = std::less,
+  class Alloc = std::allocator
+> class set {
+  public:
+set(initializer_list __list) {}
+
+class iterator {
+public:
+  iterator(Key *key): ptr(key) {}
+  iterator operator++() { ++ptr; return *this; }
+  bool operator!=(const iterator ) const { return ptr != other.ptr; }
+  const Key *() const { return *ptr; }
+private:
+  Key *ptr;
+};
+
+  public:
+Key *val;
+iterator begin() const { return iterator(val); }
+iterator end() const { return iterator(val + 1); }
+};
+
+template<
+  class Key,
+  class Hash = std::hash,
+  class Compare = std::less,
+  class Alloc = std::allocator
+> class unordered_set {
+  public:
+unordered_set(initializer_list __list) {}
+
+class iterator {
+public:
+  iterator(Key *key): ptr(key) {}
+  iterator operator++() { ++ptr; return *this; }
+  bool operator!=(const iterator ) const { return ptr != other.ptr; }
+  const Key *() const { return *ptr; }
+private:
+  Key *ptr;
+};
+
+  public:
+Key *val;
+iterator begin() const { return iterator(val); }
+iterator end() const { return iterator(val + 1); }
+};
+}
Index: lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp
@@ -0,0 +1,100 @@
+//== PointerIterationChecker.cpp --- -*- C++ -*--=//
+//
+// 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
+//
+//===--===//
+//
+// This file defines PointerIterationChecker which checks for non-determinism
+// caused due to iteration of unordered containers of pointer elements.
+//
+//===--===//
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+using namespace ast_matchers;

[PATCH] D59279: [Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers

2019-03-12 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

Following are the assumptions/limitations of this patch:

  1. The assumption is that iteration of ordered containers of pointers is not 
non-deterministic.
  
  2. Currently we only detect std::unordered_set. Detection of unordered_map 
can be added later.
  
  3. Currently, we also do not check for what happens inside the for loop. Not 
all iterations may causes non-determinism. For example, counting or summing up 
the elements should not be non-deterministic.


Repository:
  rC Clang

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

https://reviews.llvm.org/D59279



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


[PATCH] D59279: [Analyzer] Checker for non-determinism caused by iteration of unordered container of pointers

2019-03-12 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang created this revision.
mgrang added reviewers: NoQ, george.karpenkov, whisperity, Szelethus.
mgrang added a project: clang.
Herald added subscribers: Charusso, jdoerfert, dkrupp, donat.nagy, 
mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware, xazax.hun, 
mgorny.

Added a checker for non-determinism caused by iterating unordered containers 
like std::unordered_set containing pointer elements.


Repository:
  rC Clang

https://reviews.llvm.org/D59279

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp
  test/Analysis/Inputs/system-header-simulator-cxx.h
  test/Analysis/ptr-iter.cpp

Index: test/Analysis/ptr-iter.cpp
===
--- /dev/null
+++ test/Analysis/ptr-iter.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.nondeterminism.PointerIteration %s -analyzer-output=text -verify
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+template
+void f(T x);
+
+void PointerIteration() {
+  int a = 1, b = 2;
+  std::set OrderedIntSet = {a, b};
+  std::set OrderedPointerSet = {, };
+  std::unordered_set UnorderedIntSet = {a, b};
+  std::unordered_set UnorderedPointerSet = {, };
+
+  for (auto i : OrderedIntSet) // no-warning
+f(i);
+
+  for (auto i : OrderedPointerSet) // no-warning
+f(i);
+
+  for (auto i : UnorderedIntSet) // no-warning
+f(i);
+
+  for (auto i : UnorderedPointerSet) // expected-warning {{Iteration of pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerIteration]
+// expected-note@-1 {{Iteration of pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerIteration]
+f(i);
+}
Index: test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- test/Analysis/Inputs/system-header-simulator-cxx.h
+++ test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -845,3 +845,64 @@
   template
   BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPredicate p);
 }
+
+namespace std {
+
+template< class T = void >
+struct less;
+
+template< class T >
+struct allocator;
+
+template< class Key >
+struct hash;
+
+template<
+  class Key,
+  class Compare = std::less,
+  class Alloc = std::allocator
+> class set {
+  public:
+set(initializer_list __list) {}
+
+class iterator {
+public:
+  iterator(Key *key): ptr(key) {}
+  iterator operator++() { ++ptr; return *this; }
+  bool operator!=(const iterator ) const { return ptr != other.ptr; }
+  const Key *() const { return *ptr; }
+private:
+  Key *ptr;
+};
+
+  public:
+Key *val;
+iterator begin() const { return iterator(val); }
+iterator end() const { return iterator(val + 1); }
+};
+
+template<
+  class Key,
+  class Hash = std::hash,
+  class Compare = std::less,
+  class Alloc = std::allocator
+> class unordered_set {
+  public:
+unordered_set(initializer_list __list) {}
+
+class iterator {
+public:
+  iterator(Key *key): ptr(key) {}
+  iterator operator++() { ++ptr; return *this; }
+  bool operator!=(const iterator ) const { return ptr != other.ptr; }
+  const Key *() const { return *ptr; }
+private:
+  Key *ptr;
+};
+
+  public:
+Key *val;
+iterator begin() const { return iterator(val); }
+iterator end() const { return iterator(val + 1); }
+};
+}
Index: lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/PointerIterationChecker.cpp
@@ -0,0 +1,92 @@
+//=== PointerIterationChecker.cpp - Pointer Iteration Checker -*- C++ -*---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// This file defines PointerIterationChecker which checks for non-determinism
+// caused due to iteration of unordered containers of pointer elements.
+//
+//===--===//
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+
+using namespace clang;
+using namespace ento;
+using namespace ast_matchers;
+
+namespace {
+
+// ID of a node at which the diagnostic would be emitted.
+constexpr llvm::StringLiteral WarnAtNode = "iter";
+
+class PointerIterationChecker : public Checker {
+public:
+  void checkASTCodeBody(const Decl *D,
+AnalysisManager ,
+BugReporter ) const;
+};
+
+static void 

[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-03-08 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 189905.

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

https://reviews.llvm.org/D50488

Files:
  docs/analyzer/checkers.rst
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp
  test/Analysis/Inputs/system-header-simulator-cxx.h
  test/Analysis/ptr-sort.cpp
  www/analyzer/alpha_checks.html

Index: www/analyzer/alpha_checks.html
===
--- www/analyzer/alpha_checks.html
+++ www/analyzer/alpha_checks.html
@@ -33,6 +33,7 @@
 OS X Alpha Checkers
 Security Alpha Checkers
 Unix Alpha Checkers
+Non-determinism Alpha Checkers
 
 
 
@@ -1174,6 +1175,28 @@
 
 
 
+
+Non-determinism Alpha Checkers
+
+
+Name, DescriptionExample
+
+
+
+alpha.nondeterminism.PointerSorting
+(C++)
+Check for non-determinism caused by sorting of pointers.
+
+
+// C++
+void test() {
+ int a = 1, b = 2;
+ std::vector V = {, };
+ std::sort(V.begin(), V.end()); // warn
+}
+
+
+
  
  
 
Index: test/Analysis/ptr-sort.cpp
===
--- /dev/null
+++ test/Analysis/ptr-sort.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.nondeterminism.PointerSorting %s -analyzer-output=text -verify
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+bool f (int x) { return true; }
+bool g (int *x) { return true; }
+
+void PointerSorting() {
+  int a = 1, b = 2, c = 3;
+  std::vector V1 = {a, b};
+  std::vector V2 = {, };
+
+  std::is_sorted(V1.begin(), V1.end());// no-warning
+  std::nth_element(V1.begin(), V1.begin() + 1, V1.end());  // no-warning
+  std::partial_sort(V1.begin(), V1.begin() + 1, V1.end()); // no-warning
+  std::sort(V1.begin(), V1.end()); // no-warning
+  std::stable_sort(V1.begin(), V1.end());  // no-warning
+  std::partition(V1.begin(), V1.end(), f); // no-warning
+  std::stable_partition(V1.begin(), V1.end(), g);  // no-warning
+
+  std::is_sorted(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::nth_element(V2.begin(), V2.begin() + 1, V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::partial_sort(V2.begin(), V2.begin() + 1, V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::sort(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::stable_sort(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::partition(V2.begin(), V2.end(), f); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::stable_partition(V2.begin(), V2.end(), g); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+}
Index: test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- test/Analysis/Inputs/system-header-simulator-cxx.h
+++ test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -822,3 +822,26 @@
 int *status);
 }}
 namespace abi = __cxxabiv1;
+
+namespace std {
+  template
+  bool is_sorted(ForwardIt first, ForwardIt last);
+
+  template 
+  void nth_element(RandomIt first, RandomIt nth, RandomIt last);
+
+  template
+  void partial_sort(RandomIt first, RandomIt middle, RandomIt last);
+
+  template
+  void sort (RandomIt first, RandomIt last);
+
+  template
+  void 

[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-03-08 Thread Mandeep Singh Grang via Phabricator via cfe-commits
This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was automatically updated to reflect the committed changes.
Closed by commit rL355720: [Analyzer] Checker for non-determinism caused by 
sorting of pointer-like… (authored by mgrang, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D50488?vs=189905=189906#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D50488

Files:
  cfe/trunk/docs/analyzer/checkers.rst
  cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
  cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt
  cfe/trunk/lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp
  cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
  cfe/trunk/test/Analysis/ptr-sort.cpp
  cfe/trunk/www/analyzer/alpha_checks.html

Index: cfe/trunk/docs/analyzer/checkers.rst
===
--- cfe/trunk/docs/analyzer/checkers.rst
+++ cfe/trunk/docs/analyzer/checkers.rst
@@ -1943,6 +1943,18 @@
int y = strlen((char *)); // warn
  }
 
+alpha.nondeterminism.PointerSorting (C++)
+"
+Check for non-determinism caused by sorting of pointers.
+
+.. code-block:: c
+
+ void test() {
+  int a = 1, b = 2;
+  std::vector V = {, };
+  std::sort(V.begin(), V.end()); // warn
+ }
+
 
 Debug Checkers
 ---
Index: cfe/trunk/www/analyzer/alpha_checks.html
===
--- cfe/trunk/www/analyzer/alpha_checks.html
+++ cfe/trunk/www/analyzer/alpha_checks.html
@@ -33,6 +33,7 @@
 OS X Alpha Checkers
 Security Alpha Checkers
 Unix Alpha Checkers
+Non-determinism Alpha Checkers
 
 
 
@@ -1174,6 +1175,28 @@
 
 
 
+
+Non-determinism Alpha Checkers
+
+
+Name, DescriptionExample
+
+
+
+alpha.nondeterminism.PointerSorting
+(C++)
+Check for non-determinism caused by sorting of pointers.
+
+
+// C++
+void test() {
+ int a = 1, b = 2;
+ std::vector V = {, };
+ std::sort(V.begin(), V.end()); // warn
+}
+
+
+
  
  
 
Index: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
===
--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -94,6 +94,8 @@
 
 def CloneDetectionAlpha : Package<"clone">, ParentPackage;
 
+def NonDeterminismAlpha : Package<"nondeterminism">, ParentPackage;
+
 //===--===//
 // Core Checkers.
 //===--===//
@@ -1043,3 +1045,15 @@
   Documentation;
 
 } // end optin.portability
+
+//===--===//
+// NonDeterminism checkers.
+//===--===//
+
+let ParentPackage = NonDeterminismAlpha in {
+
+def PointerSortingChecker : Checker<"PointerSorting">,
+  HelpText<"Check for non-determinism caused by sorting of pointers">,
+  Documentation;
+
+} // end alpha.nondeterminism
Index: cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
===
--- cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ cfe/trunk/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -822,3 +822,26 @@
 int *status);
 }}
 namespace abi = __cxxabiv1;
+
+namespace std {
+  template
+  bool is_sorted(ForwardIt first, ForwardIt last);
+
+  template 
+  void nth_element(RandomIt first, RandomIt nth, RandomIt last);
+
+  template
+  void partial_sort(RandomIt first, RandomIt middle, RandomIt last);
+
+  template
+  void sort (RandomIt first, RandomIt last);
+
+  template
+  void stable_sort(RandomIt first, RandomIt last);
+
+  template
+  BidirIt partition(BidirIt first, BidirIt last, UnaryPredicate p);
+
+  template
+  BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPredicate p);
+}
Index: cfe/trunk/test/Analysis/ptr-sort.cpp
===
--- cfe/trunk/test/Analysis/ptr-sort.cpp
+++ cfe/trunk/test/Analysis/ptr-sort.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.nondeterminism.PointerSorting %s -analyzer-output=text -verify
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+bool f (int x) { return true; }
+bool g (int *x) { return true; }
+
+void PointerSorting() {
+  int a = 1, b = 2, c = 3;
+  std::vector V1 = {a, b};
+  std::vector V2 = {, };
+
+  std::is_sorted(V1.begin(), V1.end());// no-warning
+  std::nth_element(V1.begin(), V1.begin() + 1, V1.end());  // no-warning
+  std::partial_sort(V1.begin(), V1.begin() + 1, V1.end()); // no-warning
+  std::sort(V1.begin(), V1.end());   

[PATCH] D39050: Add index-while-building support to Clang

2019-03-06 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added inline comments.



Comment at: lib/Index/FileIndexData.cpp:31
+  std::vector Sorted(Decls);
+  std::sort(Sorted.begin(), Sorted.end());
+  return Sorted;

Please use range-based llvm::sort instead of std::sort:

```
llvm::sort(Sorted);
```
See 
https://llvm.org/docs/CodingStandards.html#beware-of-non-deterministic-sorting-order-of-equal-elements


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

https://reviews.llvm.org/D39050



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-03-04 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

@NoQ Ping 2 for reviews please.


Repository:
  rC Clang

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

https://reviews.llvm.org/D50488



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


[PATCH] D57986: [ProfileData] Sort FuncData before iteration to remove non-determinism

2019-03-01 Thread Mandeep Singh Grang via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL355252: [ProfileData] Sort FuncData before iteration to 
remove non-determinism (authored by mgrang, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D57986?vs=189002=189009#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D57986

Files:
  llvm/trunk/lib/ProfileData/InstrProfWriter.cpp


Index: llvm/trunk/lib/ProfileData/InstrProfWriter.cpp
===
--- llvm/trunk/lib/ProfileData/InstrProfWriter.cpp
+++ llvm/trunk/lib/ProfileData/InstrProfWriter.cpp
@@ -408,14 +408,30 @@
   else if (ProfileKind == PF_IRLevelWithCS)
 OS << "# CSIR level Instrumentation Flag\n:csir\n";
   InstrProfSymtab Symtab;
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
+
+  using FuncPair = detail::DenseMapPair;
+  using RecordType = std::pair;
+  SmallVector OrderedFuncData;
+
+  for (const auto  : FunctionData) {
+if (shouldEncodeData(I.getValue())) {
   if (Error E = Symtab.addFuncName(I.getKey()))
 return E;
-
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
   for (const auto  : I.getValue())
-writeRecordInText(I.getKey(), Func.first, Func.second, Symtab, OS);
+OrderedFuncData.push_back(std::make_pair(I.getKey(), Func));
+}
+  }
+
+  llvm::sort(OrderedFuncData, [](const RecordType , const RecordType ) {
+return std::tie(A.first, A.second.first) <
+   std::tie(B.first, B.second.first);
+  });
+
+  for (const auto  : OrderedFuncData) {
+const StringRef  = record.first;
+const FuncPair  = record.second;
+writeRecordInText(Name, Func.first, Func.second, Symtab, OS);
+  }
+
   return Error::success();
 }


Index: llvm/trunk/lib/ProfileData/InstrProfWriter.cpp
===
--- llvm/trunk/lib/ProfileData/InstrProfWriter.cpp
+++ llvm/trunk/lib/ProfileData/InstrProfWriter.cpp
@@ -408,14 +408,30 @@
   else if (ProfileKind == PF_IRLevelWithCS)
 OS << "# CSIR level Instrumentation Flag\n:csir\n";
   InstrProfSymtab Symtab;
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
+
+  using FuncPair = detail::DenseMapPair;
+  using RecordType = std::pair;
+  SmallVector OrderedFuncData;
+
+  for (const auto  : FunctionData) {
+if (shouldEncodeData(I.getValue())) {
   if (Error E = Symtab.addFuncName(I.getKey()))
 return E;
-
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
   for (const auto  : I.getValue())
-writeRecordInText(I.getKey(), Func.first, Func.second, Symtab, OS);
+OrderedFuncData.push_back(std::make_pair(I.getKey(), Func));
+}
+  }
+
+  llvm::sort(OrderedFuncData, [](const RecordType , const RecordType ) {
+return std::tie(A.first, A.second.first) <
+   std::tie(B.first, B.second.first);
+  });
+
+  for (const auto  : OrderedFuncData) {
+const StringRef  = record.first;
+const FuncPair  = record.second;
+writeRecordInText(Name, Func.first, Func.second, Symtab, OS);
+  }
+
   return Error::success();
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57986: [ProfileData] Sort FuncData before iteration to remove non-determinism

2019-03-01 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 189002.
mgrang added a comment.

Addressed comments.


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

https://reviews.llvm.org/D57986

Files:
  lib/ProfileData/InstrProfWriter.cpp


Index: lib/ProfileData/InstrProfWriter.cpp
===
--- lib/ProfileData/InstrProfWriter.cpp
+++ lib/ProfileData/InstrProfWriter.cpp
@@ -408,14 +408,30 @@
   else if (ProfileKind == PF_IRLevelWithCS)
 OS << "# CSIR level Instrumentation Flag\n:csir\n";
   InstrProfSymtab Symtab;
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
+
+  using FuncPair = detail::DenseMapPair;
+  using RecordType = std::pair;
+  SmallVector OrderedFuncData;
+
+  for (const auto  : FunctionData) {
+if (shouldEncodeData(I.getValue())) {
   if (Error E = Symtab.addFuncName(I.getKey()))
 return E;
-
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
   for (const auto  : I.getValue())
-writeRecordInText(I.getKey(), Func.first, Func.second, Symtab, OS);
+OrderedFuncData.push_back(std::make_pair(I.getKey(), Func));
+}
+  }
+
+  llvm::sort(OrderedFuncData, [](const RecordType , const RecordType ) {
+return std::tie(A.first, A.second.first) <
+   std::tie(B.first, B.second.first);
+  });
+
+  for (const auto  : OrderedFuncData) {
+const StringRef  = record.first;
+const FuncPair  = record.second;
+writeRecordInText(Name, Func.first, Func.second, Symtab, OS);
+  }
+
   return Error::success();
 }


Index: lib/ProfileData/InstrProfWriter.cpp
===
--- lib/ProfileData/InstrProfWriter.cpp
+++ lib/ProfileData/InstrProfWriter.cpp
@@ -408,14 +408,30 @@
   else if (ProfileKind == PF_IRLevelWithCS)
 OS << "# CSIR level Instrumentation Flag\n:csir\n";
   InstrProfSymtab Symtab;
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
+
+  using FuncPair = detail::DenseMapPair;
+  using RecordType = std::pair;
+  SmallVector OrderedFuncData;
+
+  for (const auto  : FunctionData) {
+if (shouldEncodeData(I.getValue())) {
   if (Error E = Symtab.addFuncName(I.getKey()))
 return E;
-
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
   for (const auto  : I.getValue())
-writeRecordInText(I.getKey(), Func.first, Func.second, Symtab, OS);
+OrderedFuncData.push_back(std::make_pair(I.getKey(), Func));
+}
+  }
+
+  llvm::sort(OrderedFuncData, [](const RecordType , const RecordType ) {
+return std::tie(A.first, A.second.first) <
+   std::tie(B.first, B.second.first);
+  });
+
+  for (const auto  : OrderedFuncData) {
+const StringRef  = record.first;
+const FuncPair  = record.second;
+writeRecordInText(Name, Func.first, Func.second, Symtab, OS);
+  }
+
   return Error::success();
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57986: [ProfileData] Sort FuncData before iteration to remove non-determinism

2019-03-01 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 188951.

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

https://reviews.llvm.org/D57986

Files:
  lib/ProfileData/InstrProfWriter.cpp


Index: lib/ProfileData/InstrProfWriter.cpp
===
--- lib/ProfileData/InstrProfWriter.cpp
+++ lib/ProfileData/InstrProfWriter.cpp
@@ -408,14 +408,30 @@
   else if (ProfileKind == PF_IRLevelWithCS)
 OS << "# CSIR level Instrumentation Flag\n:csir\n";
   InstrProfSymtab Symtab;
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
+
+  using FuncPair = detail::DenseMapPair;
+  using RecordType = std::pair;
+  SmallVector OrderedFuncData;
+
+  for (const auto  : FunctionData) {
+if (shouldEncodeData(I.getValue())) {
   if (Error E = Symtab.addFuncName(I.getKey()))
 return E;
-
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
   for (const auto  : I.getValue())
-writeRecordInText(I.getKey(), Func.first, Func.second, Symtab, OS);
+OrderedFuncData.push_back(std::make_pair(I.getKey(), Func));
+}
+  }
+
+  llvm::sort(OrderedFuncData, [](const RecordType , const RecordType ) {
+return std::tie(A.first, A.second.first) <
+   std::tie(B.first, B.second.first);
+  });
+
+  for (const auto  : OrderedFuncData) {
+const auto  = record.first;
+const auto  = record.second;
+writeRecordInText(name, Func.first, Func.second, Symtab, OS);
+  }
+
   return Error::success();
 }


Index: lib/ProfileData/InstrProfWriter.cpp
===
--- lib/ProfileData/InstrProfWriter.cpp
+++ lib/ProfileData/InstrProfWriter.cpp
@@ -408,14 +408,30 @@
   else if (ProfileKind == PF_IRLevelWithCS)
 OS << "# CSIR level Instrumentation Flag\n:csir\n";
   InstrProfSymtab Symtab;
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
+
+  using FuncPair = detail::DenseMapPair;
+  using RecordType = std::pair;
+  SmallVector OrderedFuncData;
+
+  for (const auto  : FunctionData) {
+if (shouldEncodeData(I.getValue())) {
   if (Error E = Symtab.addFuncName(I.getKey()))
 return E;
-
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
   for (const auto  : I.getValue())
-writeRecordInText(I.getKey(), Func.first, Func.second, Symtab, OS);
+OrderedFuncData.push_back(std::make_pair(I.getKey(), Func));
+}
+  }
+
+  llvm::sort(OrderedFuncData, [](const RecordType , const RecordType ) {
+return std::tie(A.first, A.second.first) <
+   std::tie(B.first, B.second.first);
+  });
+
+  for (const auto  : OrderedFuncData) {
+const auto  = record.first;
+const auto  = record.second;
+writeRecordInText(name, Func.first, Func.second, Symtab, OS);
+  }
+
   return Error::success();
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-03-01 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D50488#1409565 , @mgrang wrote:

> In D50488#1407975 , @Szelethus wrote:
>
> > But, as a work-in-progress alpha checker, the direction is set and looks 
> > great. Please let @NoQ have the final say.
>
>
> Thanks a lot @Szelethus! I will wait for @NoQ 's comments.


@NoQ Could you please review this patch?


Repository:
  rC Clang

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

https://reviews.llvm.org/D50488



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


[PATCH] D57986: [ProfileData] Sort FuncData before iteration to remove non-determinism

2019-02-28 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 188843.

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

https://reviews.llvm.org/D57986

Files:
  lib/ProfileData/InstrProfWriter.cpp


Index: lib/ProfileData/InstrProfWriter.cpp
===
--- lib/ProfileData/InstrProfWriter.cpp
+++ lib/ProfileData/InstrProfWriter.cpp
@@ -376,14 +376,37 @@
   if (ProfileKind == PF_IRLevel)
 OS << "# IR level Instrumentation Flag\n:ir\n";
   InstrProfSymtab Symtab;
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
+
+  using FuncPair = detail::DenseMapPair;
+  using RecordType = std::pair;
+
+  SmallVector OrderedFuncData;
+  for (const auto  : FunctionData) {
+if (shouldEncodeData(I.getValue())) {
   if (Error E = Symtab.addFuncName(I.getKey()))
 return E;
-
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
   for (const auto  : I.getValue())
-writeRecordInText(I.getKey(), Func.first, Func.second, Symtab, OS);
+OrderedFuncData.push_back(std::make_pair(I.getKey(), Func));
+}
+  }
+
+  llvm::sort(OrderedFuncData, [](const RecordType , const RecordType ) {
+ auto nameA = A.first;
+ auto nameB = B.first;
+ int comp = nameA.compare(nameB);
+ if (comp)
+   return comp < 0;
+
+ auto hashA = A.second.first;
+ auto hashB = B.second.first;
+ return hashA < hashB;
+  });
+
+  for (const auto  : OrderedFuncData) {
+const auto  = record.first;
+const auto  = record.second;
+writeRecordInText(name, Func.first, Func.second, Symtab, OS);
+  }
+
   return Error::success();
 }


Index: lib/ProfileData/InstrProfWriter.cpp
===
--- lib/ProfileData/InstrProfWriter.cpp
+++ lib/ProfileData/InstrProfWriter.cpp
@@ -376,14 +376,37 @@
   if (ProfileKind == PF_IRLevel)
 OS << "# IR level Instrumentation Flag\n:ir\n";
   InstrProfSymtab Symtab;
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
+
+  using FuncPair = detail::DenseMapPair;
+  using RecordType = std::pair;
+
+  SmallVector OrderedFuncData;
+  for (const auto  : FunctionData) {
+if (shouldEncodeData(I.getValue())) {
   if (Error E = Symtab.addFuncName(I.getKey()))
 return E;
-
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
   for (const auto  : I.getValue())
-writeRecordInText(I.getKey(), Func.first, Func.second, Symtab, OS);
+OrderedFuncData.push_back(std::make_pair(I.getKey(), Func));
+}
+  }
+
+  llvm::sort(OrderedFuncData, [](const RecordType , const RecordType ) {
+ auto nameA = A.first;
+ auto nameB = B.first;
+ int comp = nameA.compare(nameB);
+ if (comp)
+   return comp < 0;
+
+ auto hashA = A.second.first;
+ auto hashB = B.second.first;
+ return hashA < hashB;
+  });
+
+  for (const auto  : OrderedFuncData) {
+const auto  = record.first;
+const auto  = record.second;
+writeRecordInText(name, Func.first, Func.second, Symtab, OS);
+  }
+
   return Error::success();
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D57986: [ProfileData] Sort FuncData before iteration to remove non-determinism

2019-02-28 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 188824.
mgrang retitled this revision from "[ProfileData] Remove non-determinism: 
Change DenseMap to MapVector" to "[ProfileData] Sort FuncData before iteration 
to remove non-determinism".
mgrang added a reviewer: dblaikie.
Herald added a subscriber: jdoerfert.

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

https://reviews.llvm.org/D57986

Files:
  lib/ProfileData/InstrProfWriter.cpp


Index: lib/ProfileData/InstrProfWriter.cpp
===
--- lib/ProfileData/InstrProfWriter.cpp
+++ lib/ProfileData/InstrProfWriter.cpp
@@ -376,14 +376,41 @@
   if (ProfileKind == PF_IRLevel)
 OS << "# IR level Instrumentation Flag\n:ir\n";
   InstrProfSymtab Symtab;
+
+  using FuncPair = detail::DenseMapPair;
+  using RecordType = std::pair;
+
+  SmallVector OrderedFuncData;
   for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
-  if (Error E = Symtab.addFuncName(I.getKey()))
+for (const auto  : I.getValue())
+  OrderedFuncData.push_back(std::make_pair(I.getKey(), Func));
+
+  llvm::sort(OrderedFuncData, [](const RecordType , const RecordType ) {
+ auto nameA = A.first;
+ auto nameB = B.first;
+ int comp = nameA.compare(nameB);
+ if (comp)
+   return comp < 0;
+
+ auto hashA = A.second.first;
+ auto hashB = B.second.first;
+ return hashA < hashB;
+  });
+
+  for (const auto  : OrderedFuncData) {
+const auto  = pair.first;
+if (shouldEncodeData(FunctionData[key]))
+  if (Error E = Symtab.addFuncName(key))
 return E;
+  }
+
+  for (const auto  : OrderedFuncData) {
+const auto  = pair.first;
+if (shouldEncodeData(FunctionData[key])) {
+  const auto  = pair.second;
+  writeRecordInText(pair.first, Func.first, Func.second, Symtab, OS);
+}
+  }
 
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
-  for (const auto  : I.getValue())
-writeRecordInText(I.getKey(), Func.first, Func.second, Symtab, OS);
   return Error::success();
 }


Index: lib/ProfileData/InstrProfWriter.cpp
===
--- lib/ProfileData/InstrProfWriter.cpp
+++ lib/ProfileData/InstrProfWriter.cpp
@@ -376,14 +376,41 @@
   if (ProfileKind == PF_IRLevel)
 OS << "# IR level Instrumentation Flag\n:ir\n";
   InstrProfSymtab Symtab;
+
+  using FuncPair = detail::DenseMapPair;
+  using RecordType = std::pair;
+
+  SmallVector OrderedFuncData;
   for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
-  if (Error E = Symtab.addFuncName(I.getKey()))
+for (const auto  : I.getValue())
+  OrderedFuncData.push_back(std::make_pair(I.getKey(), Func));
+
+  llvm::sort(OrderedFuncData, [](const RecordType , const RecordType ) {
+ auto nameA = A.first;
+ auto nameB = B.first;
+ int comp = nameA.compare(nameB);
+ if (comp)
+   return comp < 0;
+
+ auto hashA = A.second.first;
+ auto hashB = B.second.first;
+ return hashA < hashB;
+  });
+
+  for (const auto  : OrderedFuncData) {
+const auto  = pair.first;
+if (shouldEncodeData(FunctionData[key]))
+  if (Error E = Symtab.addFuncName(key))
 return E;
+  }
+
+  for (const auto  : OrderedFuncData) {
+const auto  = pair.first;
+if (shouldEncodeData(FunctionData[key])) {
+  const auto  = pair.second;
+  writeRecordInText(pair.first, Func.first, Func.second, Symtab, OS);
+}
+  }
 
-  for (const auto  : FunctionData)
-if (shouldEncodeData(I.getValue()))
-  for (const auto  : I.getValue())
-writeRecordInText(I.getKey(), Func.first, Func.second, Symtab, OS);
   return Error::success();
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-25 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D50488#1407975 , @Szelethus wrote:

> But, as a work-in-progress alpha checker, the direction is set and looks 
> great. Please let @NoQ have the final say.


Thanks a lot @Szelethus! I will wait for @NoQ 's comments.


Repository:
  rC Clang

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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-25 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D50488#1407884 , @Szelethus wrote:

> In D50488#1405094 , @mgrang wrote:
>
> > So I was able compile a couple of C++ code bases through csa-testbench. I 
> > built cppcheck and tinyxml2 without any problems. cppcheck has one 
> > invocation std::sort but the keys are not pointers whereas tinyxml2 does 
> > not use std::sort. I tried bitcoin, rtags, xerces but run into a lot of 
> > configure/build errors.
>
>
> Thats great. How about LLVM+Clang? That'll be a pain in the butt to analyze, 
> but is pretty great for testing. Also, did you clone rtags with the git 
> option `--recursive`?


LLVM does not directly use std::sort. It calls llvm::sort which in-turn call 
std::sort (but it does have std::stable_sort, etc). However, I run into a host 
of errors while building LLVM inside csa-testbench. Maybe, once this patch 
lands, I could use llvm as a bootstrap stage1 compiler with this checker 
enabled.

>>   Also, did you clone rtags with the git option `--recursive`?

Yes, I followed the build instructions from 
https://github.com/Andersbakken/rtags. But run into these errors:

  ./configure //this invokes "cmake" "." -DCMAKE_EXPORT_COMPILE_COMMANDS=1)
The compiler uses a libstdc++ without c++11 regex support.
  
  ./configure --clang-cxxflags '-std=c++11' //this invokes "cmake" "." 
-DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DLIBCLANG_CXXFLAGS="-std=c++11"
It's likely that the include file  could not be found!

I tried installing libclang-dev, libclang-3.8-dev, libclang-6.0-dev as well as 
adding -I include paths for clang-c to configure but I am not able to go past 
the above error.


Repository:
  rC Clang

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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-25 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang marked an inline comment as done.
mgrang added inline comments.



Comment at: include/clang/StaticAnalyzer/Checkers/Checkers.td:97
 
+def NonDeterminismAlpha : Package<"nondeterminism">, ParentPackage;
+

Szelethus wrote:
> Hmmm, okay, so your checker ks C++ exclusive I belive? How about making this 
> checker reside in `alpha.cplusplus`? Rgard this one as more of a question.
This particular checker is C++ exclusive. The reason behind creating a new 
non-determinism category was so that we could add more language-agnostic 
checkers for non-determinism in future.


Repository:
  rC Clang

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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-25 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 188232.
mgrang set the repository for this revision to rC Clang.

Repository:
  rC Clang

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

https://reviews.llvm.org/D50488

Files:
  docs/analyzer/checkers.rst
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp
  test/Analysis/ptr-sort.cpp
  www/analyzer/alpha_checks.html

Index: www/analyzer/alpha_checks.html
===
--- www/analyzer/alpha_checks.html
+++ www/analyzer/alpha_checks.html
@@ -33,6 +33,7 @@
 OS X Alpha Checkers
 Security Alpha Checkers
 Unix Alpha Checkers
+Non-determinism Alpha Checkers
 
 
 
@@ -1174,6 +1175,28 @@
 
 
 
+
+Non-determinism Alpha Checkers
+
+
+Name, DescriptionExample
+
+
+
+alpha.nondeterminism.PointerSorting
+(C++)
+Check for non-determinism caused by sorting of pointers.
+
+
+// C++
+void test() {
+ int a = 1, b = 2;
+ std::vector V = {, };
+ std::sort(V.begin(), V.end()); // warn
+}
+
+
+
  
  
 
Index: test/Analysis/ptr-sort.cpp
===
--- /dev/null
+++ test/Analysis/ptr-sort.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.nondeterminism.PointerSorting %s -analyzer-output=text -verify
+
+#include "Inputs/system-header-simulator-cxx.h"
+namespace std {
+  template
+  bool is_sorted(ForwardIt first, ForwardIt last);
+
+  template 
+  void nth_element(RandomIt first, RandomIt nth, RandomIt last);
+
+  template
+  void partial_sort(RandomIt first, RandomIt middle, RandomIt last);
+
+  template
+  void sort (RandomIt first, RandomIt last);
+
+  template
+  void stable_sort(RandomIt first, RandomIt last);
+
+  template
+  BidirIt partition(BidirIt first, BidirIt last, UnaryPredicate p);
+
+  template
+  BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPredicate p);
+}
+
+bool f (int x) { return true; }
+bool g (int *x) { return true; }
+
+void PointerSorting() {
+  int a = 1, b = 2, c = 3;
+  std::vector V1 = {a, b};
+  std::vector V2 = {, };
+
+  std::is_sorted(V1.begin(), V1.end());// no-warning
+  std::nth_element(V1.begin(), V1.begin() + 1, V1.end());  // no-warning
+  std::partial_sort(V1.begin(), V1.begin() + 1, V1.end()); // no-warning
+  std::sort(V1.begin(), V1.end()); // no-warning
+  std::stable_sort(V1.begin(), V1.end());  // no-warning
+  std::partition(V1.begin(), V1.end(), f); // no-warning
+  std::stable_partition(V1.begin(), V1.end(), g);  // no-warning
+
+  std::is_sorted(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::nth_element(V2.begin(), V2.begin() + 1, V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::partial_sort(V2.begin(), V2.begin() + 1, V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::sort(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::stable_sort(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::partition(V2.begin(), V2.end(), f); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::stable_partition(V2.begin(), V2.end(), g); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+}
Index: lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp

[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-22 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D50488#1407695 , @Charusso wrote:

> bitcoin:
>
>   sudo apt-get install build-essential libtool autotools-dev automake 
> pkg-config libssl-dev libevent-dev bsdmainutils python3 libboost-all-dev 
> software-properties-common libminiupnpc-dev libzmq3-dev libqt5gui5 
> libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev 
> protobuf-compiler
>   sudo add-apt-repository ppa:bitcoin/bitcoin
>   sudo apt-get update
>   sudo apt-get install libdb4.8-dev libdb4.8++-dev
>  
>   git clone https://github.com/bitcoin/bitcoin.git
>   cd bitcoin
>  
>   ./autogen.sh
>   ./configure
>   CodeChecker log -b "make -j13" -o compile_commands.json
>
>
> xerces:
>
>   wget http://www-eu.apache.org/dist//xerces/c/3/sources/xerces-c-3.2.2.tar.gz
>   tar xf xerces-c-3.2.2.tar.gz
>   mv xerces-c-3.2.2 xerces
>   rm xerces-c-3.2.2.tar.gz
>   cd xerces
>  
>   ./configure
>   CodeChecker log -b "make -j13" -o compile_commands.json
>
>
> where `-j13` means 13 threads.


Thanks @Charusso . I have already tried these steps.

By running just ./configure I get this error:

  configure: error: cannot figure out how to use std::atomic

Instead, this is the configure command I use for bitcoin:

  ./configure --disable-wallet CFLAGS='-target x86_64-linux-gnu -L 
/usr/lib/x86_64-linux-gnu -B /usr/lib/x86_64-linux-gnu -B 
/usr/lib/gcc/x86_64-linux-gnu/5 -L /usr/lib/gcc/x86_64-linux-gnu/5 -I 
/usr/include/c++/5 -I /usr/include/x86_64-linux-gnu/c++/5' CXXFLAGS='-target 
x86_64-linux-gnu -L /usr/lib/x86_64-linux-gnu -B /usr/lib/x86_64-linux-gnu -B 
/usr/lib/gcc/x86_64-linux-gnu/5 -L /usr/lib/gcc/x86_64-linux-gnu/5 -I 
/usr/include/c++/5 -I /usr/include/x86_64-linux-gnu/c++/5'

And then I hit this:

  configure: error: Could not link against boost_filesystem !


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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-22 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D50488#1405094 , @mgrang wrote:

> So I was able compile a couple of C++ code bases through csa-testbench. I 
> built cppcheck and tinyxml2 without any problems. cppcheck has one invocation 
> std::sort but the keys are not pointers whereas tinyxml2 does not use 
> std::sort. I tried bitcoin, rtags, xerces but run into a lot of 
> configure/build errors.


@Szelethus Are you able to build bitcoin, xerces, etc? I seem to hit "Could not 
link against boost_filesystem" errors with bitcoin. I have installed 
dependencies mentioned in 
https://stackoverflow.com/questions/9132335/configure-error-could-not-link-against-boost-system/47773206
 and https://github.com/bitcoin/bitcoin/issues/8749.


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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-20 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

So I was able compile a couple of C++ code bases through csa-testbench. I built 
cppcheck and tinyxml2 without any problems. cppcheck has one invocation 
std::sort but the keys are not pointers whereas tinyxml2 does not use 
std::sort. I tried bitcoin, rtags, xerces but run into a lot of configure/build 
errors.


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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-20 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D50488#1403653 , @Szelethus wrote:

> In D50488#1403197 , @mgrang wrote:
>
> > > It's because it invokes CodeChecker, which by default enables 
> > > valist.Uninitialized, but not ValistBase. Do you have assert failures 
> > > after my hotfix?
> >
> > @Szelethus Thanks. I run into this assert when run through CodeChecker:
> >
> >   Assertion `CheckerTags.count(tag) != 0 && "Requested checker is not 
> > registered! Maybe you should add it as a " "dependency in Checkers.td?"'
> >
> >
> > Is there a workaround?
>
>
> Uhh, I'm afraid the only way out is to actually fix the problem :) couple 
> questions:
>
> 1. Are you *sure* that you rebased to rC354235 
>  (which is the hotfix I mentioned), 
> CodeChecker runs *that* clang when the assert failure happens?


I guess, I totally missed your hotfix. After sync'ing to the latest sources I 
no longer hit the assert. Thanks!

> 2. Can you provide a stacktrace? Luckily, that would for sure point me to the 
> problematic checker.
> 
> In D50488#1403199 , @mgrang wrote:
> 
>> Also I don't see the helptext for PointerSorting when I run:
>>
>>   clang -cc1 -analyzer-checker-help | grep Pointer
>>  
>> alpha.core.PointerArithmCheck for pointer arithmetic on 
>> locations other than array elements
>> alpha.core.PointerSub   Check for pointer subtractions on two 
>> pointers pointing to different memory chunks
>> alpha.nondeterminism.PointerSorting
>> cplusplus.InnerPointer  Check for inner pointers of C++ 
>> containers used after re/deallocation
>>
> 
> 
> How about `clang -cc1 -analyzer-checker-help | grep Pointer -A3`? There could 
> be a linebreak after the ckecker's name (raises the question though whether 
> it should be there).

Yep, line break it was. I see the help text with -A1.

> In D50488#1403212 , @mgrang wrote:
> 
>> > There is a revision to solve this problem here: D58065 
>> > . I guess your input, as someone who 
>> > didn't participate in the checker dependency related patch reviews would 
>> > be invaluable, in terms of whether my description is understandable enough.
>>
>> Thanks. I took a look at the documentation and it looks fine to me (modulo 
>> the comments from other reviewers and a couple of minor typos). I feel the 
>> csa-testbench documentation (https://github.com/Xazax-hun/csa-testbench) is 
>> very minimal and does not document a lot of intricacies which I had to 
>> figure out by trial-and-error.
> 
> 
> Due to an upcoming conference, I didn't bother with it much, i just used 
> CodeChecker on its own, which is fairly well documented.
>  I'm trying to move my checker out of alpha, and my testing goes as follows:
> 
> 1. Clone LLVM+Clang, cppcheck, rtags, bitcoin, xerces (~~you could throw in 
> vim, tmux, as your checker isnt C++ exclusive~~ (see edit), or whatever else)
> 2. Create compile_commands.json either with CMake 
> (-DCANE_GENERATE_COMPILE_COMMANDS, or smt similar), or `CodeChecker log`
> 3. `CodeChecker analyze` projects, paying attention to not forgetting the 
> CodeChecker flag `--verbose debug_analyzer` (and enabling your checker ofc), 
> and piping the output to a file
> 4. Create a `CodeChecker server`, `CodeChecker store` the results, and stare 
> at the web gui for hours. Its very pretty btw ;)
> 
>   Csa-testbench is a work in progress, so I guess you can expect more in the 
> future :)
> 
>   Thanks for your work, even through a few annoyances, very much appreciated!
> 
>   Edit: Since your checker **is** C++ exclusive, please return true only if 
> `LangOpts.CPlusPlus` is true in the `shouldRegister` function. Didn't catch 
> my eye at first.

Done.


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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-20 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 187695.

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

https://reviews.llvm.org/D50488

Files:
  docs/analyzer/checkers.rst
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp
  test/Analysis/ptr-sort.cpp
  www/analyzer/alpha_checks.html

Index: www/analyzer/alpha_checks.html
===
--- www/analyzer/alpha_checks.html
+++ www/analyzer/alpha_checks.html
@@ -33,6 +33,7 @@
 OS X Alpha Checkers
 Security Alpha Checkers
 Unix Alpha Checkers
+Non-determinism Alpha Checkers
 
 
 
@@ -1174,6 +1175,28 @@
 
 
 
+
+Non-determinism Alpha Checkers
+
+
+Name, DescriptionExample
+
+
+
+alpha.nondeterminism.PointerSorting
+(C++)
+Check for non-determinism caused by sorting of pointers.
+
+
+// C++
+void test() {
+ int a = 1, b = 2;
+ std::vector V = {, };
+ std::sort(V.begin(), V.end()); // warn
+}
+
+
+
  
  
 
Index: test/Analysis/ptr-sort.cpp
===
--- /dev/null
+++ test/Analysis/ptr-sort.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.nondeterminism.PointerSorting %s -analyzer-output=text -verify
+
+#include "Inputs/system-header-simulator-cxx.h"
+namespace std {
+  template
+  bool is_sorted(ForwardIt first, ForwardIt last);
+
+  template 
+  void nth_element(RandomIt first, RandomIt nth, RandomIt last);
+
+  template
+  void partial_sort(RandomIt first, RandomIt middle, RandomIt last);
+
+  template
+  void sort (RandomIt first, RandomIt last);
+
+  template
+  void stable_sort(RandomIt first, RandomIt last);
+
+  template
+  BidirIt partition(BidirIt first, BidirIt last, UnaryPredicate p);
+
+  template
+  BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPredicate p);
+}
+
+bool f (int x) { return true; }
+bool g (int *x) { return true; }
+
+void PointerSorting() {
+  int a = 1, b = 2, c = 3;
+  std::vector V1 = {a, b};
+  std::vector V2 = {, };
+
+  std::is_sorted(V1.begin(), V1.end());// no-warning
+  std::nth_element(V1.begin(), V1.begin() + 1, V1.end());  // no-warning
+  std::partial_sort(V1.begin(), V1.begin() + 1, V1.end()); // no-warning
+  std::sort(V1.begin(), V1.end()); // no-warning
+  std::stable_sort(V1.begin(), V1.end());  // no-warning
+  std::partition(V1.begin(), V1.end(), f); // no-warning
+  std::stable_partition(V1.begin(), V1.end(), g);  // no-warning
+
+  std::is_sorted(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::nth_element(V2.begin(), V2.begin() + 1, V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::partial_sort(V2.begin(), V2.begin() + 1, V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::sort(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::stable_sort(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::partition(V2.begin(), V2.end(), f); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::stable_partition(V2.begin(), V2.end(), g); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+}
Index: lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp
===
--- /dev/null
+++ 

[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-19 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

> There is a revision to solve this problem here: D58065 
> . I guess your input, as someone who didn't 
> participate in the checker dependency related patch reviews would be 
> invaluable, in terms of whether my description is understandable enough.

Thanks. I took a look at the documentation and it looks fine to me (modulo the 
comments from other reviewers and a couple of minor typos). I feel the 
csa-testbench documentation (https://github.com/Xazax-hun/csa-testbench) is 
very minimal and does not document a lot of intricacies which I had to figure 
out by trial-and-error.


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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-19 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

Also I don't see the helptext for PointerSorting when I run:

  clang -cc1 -analyzer-checker-help | grep Pointer
  
alpha.core.PointerArithmCheck for pointer arithmetic on locations 
other than array elements
alpha.core.PointerSub   Check for pointer subtractions on two 
pointers pointing to different memory chunks
alpha.nondeterminism.PointerSorting
cplusplus.InnerPointer  Check for inner pointers of C++ containers 
used after re/deallocation


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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-19 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

> It's because it invokes CodeChecker, which by default enables 
> valist.Uninitialized, but not ValistBase. Do you have assert failures after 
> my hotfix?

@Szelethus Thanks. I run into this assert when run through CodeChecker:

  Assertion `CheckerTags.count(tag) != 0 && "Requested checker is not 
registered! Maybe you should add it as a " "dependency in Checkers.td?"'

Is there a workaround?


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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-19 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 187466.

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

https://reviews.llvm.org/D50488

Files:
  docs/analyzer/checkers.rst
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp
  test/Analysis/ptr-sort.cpp
  www/analyzer/alpha_checks.html

Index: www/analyzer/alpha_checks.html
===
--- www/analyzer/alpha_checks.html
+++ www/analyzer/alpha_checks.html
@@ -33,6 +33,7 @@
 OS X Alpha Checkers
 Security Alpha Checkers
 Unix Alpha Checkers
+Non-determinism Alpha Checkers
 
 
 
@@ -1174,6 +1175,28 @@
 
 
 
+
+Non-determinism Alpha Checkers
+
+
+Name, DescriptionExample
+
+
+
+alpha.nondeterminism.PointerSorting
+(C++)
+Check for non-determinism caused by sorting of pointers.
+
+
+// C++
+void test() {
+ int a = 1, b = 2;
+ std::vector V = {, };
+ std::sort(V.begin(), V.end()); // warn
+}
+
+
+
  
  
 
Index: test/Analysis/ptr-sort.cpp
===
--- /dev/null
+++ test/Analysis/ptr-sort.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.nondeterminism.PointerSorting %s -analyzer-output=text -verify
+
+#include "Inputs/system-header-simulator-cxx.h"
+namespace std {
+  template
+  bool is_sorted(ForwardIt first, ForwardIt last);
+
+  template 
+  void nth_element(RandomIt first, RandomIt nth, RandomIt last);
+
+  template
+  void partial_sort(RandomIt first, RandomIt middle, RandomIt last);
+
+  template
+  void sort (RandomIt first, RandomIt last);
+
+  template
+  void stable_sort(RandomIt first, RandomIt last);
+
+  template
+  BidirIt partition(BidirIt first, BidirIt last, UnaryPredicate p);
+
+  template
+  BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPredicate p);
+}
+
+bool f (int x) { return true; }
+bool g (int *x) { return true; }
+
+void PointerSorting() {
+  int a = 1, b = 2, c = 3;
+  std::vector V1 = {a, b};
+  std::vector V2 = {, };
+
+  std::is_sorted(V1.begin(), V1.end());// no-warning
+  std::nth_element(V1.begin(), V1.begin() + 1, V1.end());  // no-warning
+  std::partial_sort(V1.begin(), V1.begin() + 1, V1.end()); // no-warning
+  std::sort(V1.begin(), V1.end()); // no-warning
+  std::stable_sort(V1.begin(), V1.end());  // no-warning
+  std::partition(V1.begin(), V1.end(), f); // no-warning
+  std::stable_partition(V1.begin(), V1.end(), g);  // no-warning
+
+  std::is_sorted(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::nth_element(V2.begin(), V2.begin() + 1, V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::partial_sort(V2.begin(), V2.begin() + 1, V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::sort(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::stable_sort(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::partition(V2.begin(), V2.end(), f); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::stable_partition(V2.begin(), V2.end(), g); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+}
Index: lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp
===
--- /dev/null
+++ 

[PATCH] D58065: [analyzer] Document the frontend library

2019-02-19 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added inline comments.



Comment at: docs/analyzer/developer-docs/FrontendLibrary.rst:12
+This document will describe the frontend of the Static Analyzer, basically
+everything from compiling the analyzer from source, through it's invocation up
+to the beginning of the analysis. It will touch on topics such as

typo: it's --> its



Comment at: docs/analyzer/developer-docs/FrontendLibrary.rst:42
+
+The following section is sort of a summary, and severeral items will be later
+revisited in greater detail.

typo: severeral --> several


Repository:
  rC Clang

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

https://reviews.llvm.org/D58065



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-19 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D50488#1400823 , @whisperity wrote:

> Yeah, it seems upstream has moved away due to @Szelethus' implementation of a 
> much more manageable "checker dependency" system. You most likely will have 
> to rebase your patch first, then check what you missed which got added to 
> other merged, existing checkers.


Yes, I see that D55429 , D54438 
 added a new dependency field for checkers. 
However, I see that not all checkers need/have that field. In this case, 
shouldn't providing a ento::shouldRegisterPointerSortingChecker function which 
returns true be enough to register the checker?
Moreover, as I said I hit this assert only when invoking the checker via 
csa-testbench. Outside that it seems to work fine. For example, my unit test 
Analysis/ptr-sort.cpp passes.


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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-19 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 187418.

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

https://reviews.llvm.org/D50488

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp
  test/Analysis/ptr-sort.cpp

Index: test/Analysis/ptr-sort.cpp
===
--- /dev/null
+++ test/Analysis/ptr-sort.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.nondeterminism.PointerSorting %s -analyzer-output=text -verify
+
+#include "Inputs/system-header-simulator-cxx.h"
+namespace std {
+  template
+  bool is_sorted(ForwardIt first, ForwardIt last);
+
+  template 
+  void nth_element(RandomIt first, RandomIt nth, RandomIt last);
+
+  template
+  void partial_sort(RandomIt first, RandomIt middle, RandomIt last);
+
+  template
+  void sort (RandomIt first, RandomIt last);
+
+  template
+  void stable_sort(RandomIt first, RandomIt last);
+
+  template
+  BidirIt partition(BidirIt first, BidirIt last, UnaryPredicate p);
+
+  template
+  BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPredicate p);
+}
+
+bool f (int x) { return true; }
+bool g (int *x) { return true; }
+
+void PointerSorting() {
+  int a = 1, b = 2, c = 3;
+  std::vector V1 = {a, b};
+  std::vector V2 = {, };
+
+  std::is_sorted(V1.begin(), V1.end());// no-warning
+  std::nth_element(V1.begin(), V1.begin() + 1, V1.end());  // no-warning
+  std::partial_sort(V1.begin(), V1.begin() + 1, V1.end()); // no-warning
+  std::sort(V1.begin(), V1.end()); // no-warning
+  std::stable_sort(V1.begin(), V1.end());  // no-warning
+  std::partition(V1.begin(), V1.end(), f); // no-warning
+  std::stable_partition(V1.begin(), V1.end(), g);  // no-warning
+
+  std::is_sorted(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::nth_element(V2.begin(), V2.begin() + 1, V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::partial_sort(V2.begin(), V2.begin() + 1, V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::sort(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::stable_sort(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::partition(V2.begin(), V2.end(), f); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::stable_partition(V2.begin(), V2.end(), g); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+}
Index: lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp
@@ -0,0 +1,117 @@
+//===-- PointerSortingChecker.cpp -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// This file defines PointerSortingChecker which checks for non-determinism
+// caused due to sorting containers with pointer-like elements.
+//
+//===--===//
+
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include 

[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-15 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

I hacked around the run_experiments.py to set CMAKE_C_FLAGS and now I see the 
following error in stats.html. Note: I see the same error with an existing 
checker like PointerArithmChecker. And I do not hit this assert when I run the 
checker outside of csa-testbench.

  Assertion `CheckerTags.count(tag) != 0 && "Requested checker is not 
registered! Maybe you should add it as a " "dependency in Checkers.td?"'

Here's my config file:

  {
"projects": [
  {
"name": "TinyXML2",
"url": "https://github.com/leethomason/tinyxml2.git;,
"clang_sa_args": "-target x86_64-linux-gnu -L /usr/lib/x86_64-linux-gnu 
-B /usr/lib/x86_64-linux-gnu -B /usr/lib/gcc/x86_64-linux-gnu/5 -L 
/usr/lib/gcc/x86_64-linux-gnu/5 --analyze -Xanalyzer -analyzer-checker=core 
-Xanalyzer -analyzer-checker=alpha.core.PointerArithm -Xclang -analyzer-stats",
"clang_path": "path/install/bin",
"binary_dir": "build"
  }
],
  
"CodeChecker": {
  "url": "http://localhost:8001/Default;,
  "analyze_args": "",
  "store_args": ""
}
  }


Repository:
  rC Clang

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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-15 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

The error I now get is:

  clang is not able to compile a simple test program.
  /usr/bin/ld: unrecognised emulation mode: armelf_linux_eabi
Supported emulations: elf_x86_64 elf32_x86_64 elf_i386 elf_iamcu i386linux
elf_l1om elf_k1om i386pep i386pe

This is because I need to pass the correct -target and -L options to config. I 
see that there is a configure_command option that can be set. However, 
different projects use different build systems (make, cmake, bake, etc). How do 
we then pass flags to their respective configures?


Repository:
  rC Clang

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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-14 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

I guess I hadn't sourced the CodeChecker venv correctly. Now that I did source 
it and started the CodeChecker server I seem to be progressing. The error I get 
now is compiler related (which I will dig into).

  12:51:35 [bitcoin] Checking out project... 
  [ERROR] Unknown option: json
  
  [ERROR] configure: error: in `csa-testbench/projects/bitcoin':
  configure: error: C++ compiler cannot create executables
  See `config.log' for more details

Should I be worried about the "[ERROR] Unknown option: json" message?


Repository:
  rC Clang

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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-14 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D50488#1397721 , @xazax.hun wrote:

> In D50488#1395483 , @mgrang wrote:
>
> > Reviving this now that I have some cycles to work on this.
> >
> > So I tried running this on csa-testbench projects but I didn't have much 
> > success. I always run into a bunch of build/env related errors:
> >
> >   python run_experiments.py --config myconfig.json
> >  
> >   15:05:20 [libcxx] Checking out project... 
> >   [ERROR] Unknown option: json
> >  
> >   15:05:22 [libcxx] LOC: ?.
> >   15:05:22 [libcxx] Generating build log... 
> >   15:05:22 [libcxx_master] Analyzing project... 
> >   [ERROR] Traceback (most recent call last):
> > File 
> > "/local/mnt/workspace/mgrang/comm_analyzer/CodeChecker/cc_bin/CodeChecker.py",
> >  line 20, in 
> >   from shared.ttypes import RequestFailed
> >   ImportError: No module named shared.ttypes
> >
> >
> >
>
>
> Hi!
>
> Sorry for the late response. Does CodeChecker work for you (when not using 
> the testbench)?
>  I think one of the most common reason for such errors is when we do not 
> source the virtualenv of CodeChecker so the dependencies are not available.


I followed the instructions at https://github.com/Ericsson/codechecker and 
sourced the venv and here's what I see now:

  12:46:30 [libcxx] Checking out project... 
  [ERROR] Unknown option: json
  
  
  12:46:32 [libcxx] LOC: ?.
  12:46:32 [libcxx] Generating build log... 
  12:46:32 [libcxx_master] Analyzing project... 
  [ERROR] [ERROR 2019-02-14 12:46] - Connection failed.
  [ERROR 2019-02-14 12:46] - Connection refused
  [ERROR 2019-02-14 12:46] - [Errno 111] Connection refused
  [ERROR 2019-02-14 12:46] - Check if your CodeChecker server is running.
  
  12:46:34 [libcxx_master] Done. Storing results...
  12:46:35 [libcxx_master] Results stored.
  Traceback (most recent call last):
File "run_experiments.py", line 482, in 
  main()
File "run_experiments.py", line 470, in main
  post_process_project(project, source_dir, config, printer)
File "run_experiments.py", line 355, in post_process_project
  runs = json.loads(stdout)
File "/usr/lib/python2.7/json/__init__.py", line 339, in loads
  return _default_decoder.decode(s)
File "/usr/lib/python2.7/json/decoder.py", line 364, in decode
  obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
  raise ValueError("No JSON object could be decoded")
  ValueError: No JSON object could be decoded


Repository:
  rC Clang

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

https://reviews.llvm.org/D50488



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


[PATCH] D57986: [ProfileData] Remove non-determinism: Change DenseMap to MapVector

2019-02-14 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

Ping for reviews please.


Repository:
  rC Clang

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

https://reviews.llvm.org/D57986



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-12 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

Reviving this now that I have some cycles to work on this.

So I tried running this on csa-testbench projects but I didn't have much 
success. I always run into a bunch of build/env related errors:

  15:05:20 [libcxx] Checking out project... 
  [ERROR] Unknown option: json
  
  15:05:22 [libcxx] LOC: ?.
  15:05:22 [libcxx] Generating build log... 
  15:05:22 [libcxx_master] Analyzing project... 
  [ERROR] Traceback (most recent call last):
File 
"/local/mnt/workspace/mgrang/comm_analyzer/CodeChecker/cc_bin/CodeChecker.py", 
line 20, in 
  from shared.ttypes import RequestFailed
  ImportError: No module named shared.ttypes

I installed CodeChecker and various other dependencies mentioned in the README. 
Here's what my input json looks like:

  {
"projects": [
  {
"url": "git://github.com/chapuni/libcxx.git",
"name": "libcxx",
"clang_sa_args": "--analyze -Xanalyzer 
-analyzer-checker=alpha.nondeterminism.PointerSorting",
"clang_path": "path/to/llvm/install/bin",
"binary_dir": "build"
  },
  {
"name": "bitcoin",
"url": "https://github.com/bitcoin/bitcoin.git;,
"tag": "v0.15.1",
"clang_sa_args": "--analyze -Xanalyzer 
-analyzer-checker=alpha.nondeterminism.PointerSorting",
"clang_path": "path/to/llvm/install/bin",
"binary_dir": "build"
  },
  {
"name": "xerces-c",
"url": "https://github.com/apache/xerces-c.git;,
"prepared": true,
"clang_sa_args": "--analyze -Xanalyzer 
-analyzer-checker=alpha.nondeterminism.PointerSorting",
"clang_path": "path/to/llvm/install/bin",
"binary_dir": "build"
  }
],
  
"CodeChecker": {
  "url": "http://localhost:8001/Default;,
  "analyze_args": "",
  "store_args": ""
}
  }


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

https://reviews.llvm.org/D50488



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


[PATCH] D50488: [Analyzer] Checker for non-determinism caused by sorting of pointer-like elements

2019-02-12 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 186549.
Herald added subscribers: jdoerfert, baloghadamsoftware.

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

https://reviews.llvm.org/D50488

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp
  test/Analysis/ptr-sort.cpp

Index: test/Analysis/ptr-sort.cpp
===
--- /dev/null
+++ test/Analysis/ptr-sort.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.nondeterminism.PointerSorting %s -analyzer-output=text -verify
+
+#include "Inputs/system-header-simulator-cxx.h"
+namespace std {
+  template
+  bool is_sorted(ForwardIt first, ForwardIt last);
+
+  template 
+  void nth_element(RandomIt first, RandomIt nth, RandomIt last);
+
+  template
+  void partial_sort(RandomIt first, RandomIt middle, RandomIt last);
+
+  template
+  void sort (RandomIt first, RandomIt last);
+
+  template
+  void stable_sort(RandomIt first, RandomIt last);
+
+  template
+  BidirIt partition(BidirIt first, BidirIt last, UnaryPredicate p);
+
+  template
+  BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPredicate p);
+}
+
+bool f (int x) { return true; }
+bool g (int *x) { return true; }
+
+void PointerSorting() {
+  int a = 1, b = 2, c = 3;
+  std::vector V1 = {a, b};
+  std::vector V2 = {, };
+
+  std::is_sorted(V1.begin(), V1.end());// no-warning
+  std::nth_element(V1.begin(), V1.begin() + 1, V1.end());  // no-warning
+  std::partial_sort(V1.begin(), V1.begin() + 1, V1.end()); // no-warning
+  std::sort(V1.begin(), V1.end()); // no-warning
+  std::stable_sort(V1.begin(), V1.end());  // no-warning
+  std::partition(V1.begin(), V1.end(), f); // no-warning
+  std::stable_partition(V1.begin(), V1.end(), g);  // no-warning
+
+  std::is_sorted(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::nth_element(V2.begin(), V2.begin() + 1, V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::partial_sort(V2.begin(), V2.begin() + 1, V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::sort(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::stable_sort(V2.begin(), V2.end()); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::partition(V2.begin(), V2.end(), f); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  std::stable_partition(V2.begin(), V2.end(), g); // expected-warning {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+  // expected-note@-1 {{Sorting pointer-like elements can result in non-deterministic ordering}} [alpha.nondeterminism.PointerSorting]
+}
Index: lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp
===
--- /dev/null
+++ lib/StaticAnalyzer/Checkers/PointerSortingChecker.cpp
@@ -0,0 +1,119 @@
+//===-- PointerSortingChecker.cpp -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+//
+// This file defines PointerSortingChecker which checks for non-determinism
+// caused due to sorting containers with pointer-like elements.
+//
+//===--===//
+

[PATCH] D57986: [ProfileData] Remove non-determinism: Change DenseMap to MapVector

2019-02-08 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

tools/llvm-profdata/instr-remap.test is failing in the reverse iteration bot. 
See 
http://lab.llvm.org:8011/builders/reverse-iteration/builds/10546/steps/check_all/logs/stdio.

This is because FunctionData is iterated in InstrProfWriter to output function 
counts, etc. But for two functions with the same name the iteration order is 
not defined if we use a DenseMap. Changing this to MapVector resolves this.

Note: We can also sort FunctionData before iteration to fix this issue. But 
that would mean we would need to sort every time we iterate in order to print. 
Using a MapVector instead is a better option IMO.


Repository:
  rC Clang

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

https://reviews.llvm.org/D57986



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


[PATCH] D57986: [ProfileData] Remove non-determinism: Change DenseMap to MapVector

2019-02-08 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang created this revision.
mgrang added reviewers: rsmith, bogner.
Herald added a project: clang.

Repository:
  rC Clang

https://reviews.llvm.org/D57986

Files:
  include/llvm/ProfileData/InstrProfWriter.h


Index: include/llvm/ProfileData/InstrProfWriter.h
===
--- include/llvm/ProfileData/InstrProfWriter.h
+++ include/llvm/ProfileData/InstrProfWriter.h
@@ -14,7 +14,7 @@
 #ifndef LLVM_PROFILEDATA_INSTRPROFWRITER_H
 #define LLVM_PROFILEDATA_INSTRPROFWRITER_H
 
-#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ProfileData/InstrProf.h"
 #include "llvm/Support/Endian.h"
@@ -32,7 +32,7 @@
 
 class InstrProfWriter {
 public:
-  using ProfilingData = SmallDenseMap;
+  using ProfilingData = MapVector;
   enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel };
 
 private:


Index: include/llvm/ProfileData/InstrProfWriter.h
===
--- include/llvm/ProfileData/InstrProfWriter.h
+++ include/llvm/ProfileData/InstrProfWriter.h
@@ -14,7 +14,7 @@
 #ifndef LLVM_PROFILEDATA_INSTRPROFWRITER_H
 #define LLVM_PROFILEDATA_INSTRPROFWRITER_H
 
-#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ProfileData/InstrProf.h"
 #include "llvm/Support/Endian.h"
@@ -32,7 +32,7 @@
 
 class InstrProfWriter {
 public:
-  using ProfilingData = SmallDenseMap;
+  using ProfilingData = MapVector;
   enum ProfKind { PF_Unknown = 0, PF_FE, PF_IRLevel };
 
 private:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53541: [COFF, ARM64] Do not emit x86_seh_recoverfp intrinsic

2019-01-16 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang abandoned this revision.
mgrang added a comment.

I have added a default lowering for llvm.eh.recoverfp in D53540 
. So this patch is no longer needed.


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

https://reviews.llvm.org/D53541



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


[PATCH] D53541: [COFF, ARM64] Do not emit x86_seh_recoverfp intrinsic

2019-01-15 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

I have renamed llvm.x86.seh.recoverfp intrinsic to llvm.eh.recoverfp in D56747 
 and D56748 .


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

https://reviews.llvm.org/D53541



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


[PATCH] D56748: [EH] Rename llvm.x86.seh.recoverfp intrinsic to llvm.eh.recoverfp

2019-01-15 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang created this revision.
mgrang added reviewers: rnk, efriedma.

This is the clang counterpart to D56747 .


Repository:
  rC Clang

https://reviews.llvm.org/D56748

Files:
  lib/CodeGen/CGException.cpp
  test/CodeGen/exceptions-seh.c
  test/CodeGenCXX/exceptions-seh-filter-captures.cpp


Index: test/CodeGenCXX/exceptions-seh-filter-captures.cpp
===
--- test/CodeGenCXX/exceptions-seh-filter-captures.cpp
+++ test/CodeGenCXX/exceptions-seh-filter-captures.cpp
@@ -21,7 +21,7 @@
 // CHECK: invoke void @might_crash()
 
 // CHECK-LABEL: define internal i32 @"?filt$0@0@test_freefunc@@"(i8* 
%exception_pointers, i8* %frame_pointer)
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void 
(i32)* @test_freefunc to i8*), i8* %frame_pointer)
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (i32)* 
@test_freefunc to i8*), i8* %frame_pointer)
 // CHECK: %[[p1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void 
(i32)* @test_freefunc to i8*), i8* %[[fp]], i32 0)
 // CHECK: %[[p1_ptr:[^ ]*]] = bitcast i8* %[[p1_i8]] to i32*
 // CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void 
(i32)* @test_freefunc to i8*), i8* %[[fp]], i32 1)
@@ -51,7 +51,7 @@
 // CHECK: invoke void @might_crash()
 
 // CHECK-LABEL: define internal i32 @"?filt$0@0@test_method@S@@"(i8* 
%exception_pointers, i8* %frame_pointer)
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void 
(%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer)
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void 
(%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %frame_pointer)
 // CHECK: %[[l1_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void 
(%struct.S*)* @"?test_method@S@@QEAAXXZ" to i8*), i8* %[[fp]], i32 0)
 // CHECK: %[[l1_ptr:[^ ]*]] = bitcast i8* %[[l1_i8]] to i32*
 // CHECK: %[[l1:[^ ]*]] = load i32, i32* %[[l1_ptr]]
@@ -76,7 +76,7 @@
 // CHECK: invoke void @might_crash()
 
 // CHECK-LABEL: define internal i32 
@"?filt$0@0@?R@?0??test_lambda@@YAXXZ@"(i8* %exception_pointers, i8* 
%frame_pointer)
-// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void 
(%class.anon*)* @"??R@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* 
%frame_pointer)
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void 
(%class.anon*)* @"??R@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* 
%frame_pointer)
 // CHECK: %[[l2_i8:[^ ]*]] = call i8* @llvm.localrecover(i8* bitcast (void 
(%class.anon*)* @"??R@?0??test_lambda@@YAXXZ@QEBA@XZ" to i8*), i8* 
%[[fp]], i32 0)
 // CHECK: %[[l2_ptr:[^ ]*]] = bitcast i8* %[[l2_i8]] to i32*
 // CHECK: %[[l2:[^ ]*]] = load i32, i32* %[[l2_ptr]]
Index: test/CodeGen/exceptions-seh.c
===
--- test/CodeGen/exceptions-seh.c
+++ test/CodeGen/exceptions-seh.c
@@ -52,7 +52,7 @@
 //
 // X86-LABEL: define internal i32 @"?filt$0@0@safe_div@@"()
 // X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
-// X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 
(i32, i32, i32*)* @safe_div to i8*), i8* %[[ebp]])
+// X86: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (i32 (i32, 
i32, i32*)* @safe_div to i8*), i8* %[[ebp]])
 // X86: call i8* @llvm.localrecover(i8* bitcast (i32 (i32, i32, i32*)* 
@safe_div to i8*), i8* %[[fp]], i32 0)
 // X86: load i8*, i8**
 // X86: load i32*, i32**
@@ -95,16 +95,16 @@
 // CHECK: ret i32 %[[rv]]
 
 // X64-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"(i8* 
%exception_pointers, i8* %frame_pointer)
-// X64: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* 
@filter_expr_capture to i8*), i8* %frame_pointer)
+// X64: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (i32 ()* 
@filter_expr_capture to i8*), i8* %frame_pointer)
 // X64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture 
to i8*), i8* %[[fp]], i32 0)
 //
 // ARM64-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"(i8* 
%exception_pointers, i8* %frame_pointer)
-// ARM64: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 
()* @filter_expr_capture to i8*), i8* %frame_pointer)
+// ARM64: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (i32 ()* 
@filter_expr_capture to i8*), i8* %frame_pointer)
 // ARM64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* 
@filter_expr_capture to i8*), i8* %[[fp]], i32 0)
 //
 // X86-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"()
 // X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
-// X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* 
@filter_expr_capture to i8*), i8* %[[ebp]])
+// X86: %[[fp:[^ ]*]] = call i8* @llvm.eh.recoverfp(i8* bitcast (i32 ()* 
@filter_expr_capture to i8*), i8* %[[ebp]])
 // X86: call i8* @llvm.localrecover(i8* bitcast (i32 

[PATCH] D53541: [COFF, ARM64] Do not emit x86_seh_recoverfp intrinsic

2019-01-15 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D53541#1358210 , @rnk wrote:

> I can't compile the example you gave yet because I haven't applied your 
> patches locally, but this is the "three stack pointer" case that I have in 
> mind:
>
>   struct Foo {
> void (*ptr)();
> int x, y, z;
>   };
>  
>   void escape(void *);
>   void large_align(int a0, int a1, int a2, int a3, int a4, int a5, int a6, 
> int a7,
>int stackarg) {
> struct Foo __declspec(align(32)) alignedlocal;
> alignedlocal.x = 42;
> int vla[a0];
> escape();
> vla[0] = stackarg;
> escape([0]);
>   }
>
>
> This is LLVM's generated code:
>
>   "?large_align@@YAXH@Z": ; @"?large_align@@YAXH@Z"
>   .seh_proc "?large_align@@YAXH@Z"
>   ; %bb.0:; %entry
>   stp x21, x22, [sp, #-48]!   ; 16-byte Folded Spill
>   stp x19, x20, [sp, #16] ; 16-byte Folded Spill
>   stp x29, x30, [sp, #32] ; 16-byte Folded Spill
>   add x29, sp, #32; =32
>   sub x9, sp, #48 ; =48
>   and sp, x9, #0xffe0
>   mov x19, sp
>   mov w8, #42
>   str w8, [x19, #8]
>   mov w8, w0
>   ldr w22, [x29, #16]
>   lsl x8, x8, #2
>   add x8, x8, #15 ; =15
>   lsr x15, x8, #4
>   mov x21, sp
>   bl  __chkstk
>   mov x8, sp
>   sub x20, x8, x15, lsl #4
>   mov sp, x20
>   add x0, x19, #0 ; =0
>   bl  "?escape@@YAXPEAX@Z"
>   mov x0, x20
>   str w22, [x20]
>   bl  "?escape@@YAXPEAX@Z"
>   mov sp, x21
>   sub sp, x29, #32; =32
>   ldp x29, x30, [sp, #32] ; 16-byte Folded Reload
>   ldp x19, x20, [sp, #16] ; 16-byte Folded Reload
>   ldp x21, x22, [sp], #48 ; 16-byte Folded Reload
>   ret
>
>
> I see three pointers used to address the stack:
>
> - sp: to address vla
> - x19: to address locals, the so-called "base" pointer
> - x29: to address parameters on the stack, looks like the traditional FP, 
> points to FP+LR pair as well
>
>   At least for x86, the unwind info doesn't describe X19, it just describes 
> X29, since that's what you need to restore CSRs and find the parent stack 
> frame. We saw that the Windows EH runtime passes in some value based on the 
> unwind info. For x86, it was just whatever EBP held, so recoverfp simply 
> aligns that value forward to recover the base pointer (ESI) and then uses 
> that to recover locals. For x64, the runtime passes in the value of RSP after 
> the prologue ends, so we adjust it by the "parent frame offset" to get back 
> the value we put in RBP. It looks like for x64 we never handled the case I'm 
> asking you about, because this program doesn't print the right value: ``` 
> #include  struct Foo { void (*ptr)(); int x, y, z; }; int filter(int 
> n) { printf("o.x: %d\n", n); return 1; } void may_throw() { __builtin_trap(); 
> } int main() { struct Foo __declspec(align(32)) o; o.x = 42; __try { 
> may_throw(); } __except(filter(o.x)) { } } ```
>
>   I get "o.x: 0" instead of 42. I bet we can find something about that in 
> bugzilla somewhere. =/
>
>   So, hopefully that explains the intended purpose of 
> `llvm.x86.seh.recoverfp`, and why we might need to generalize it into 
> something non-x86 specific. Maybe `llvm.eh.recoverfp`. Let me know if I can 
> clarify anything else.


@rnk Thanks a lot for the clarification. Yes, I see o.x: 0 instead of 42. 
Supporting this case would mean implementing recoverfp as well as support 
generating the correct parent frame offset for arm64 windows. Do you think this 
can be done in a follow-up patch? So this patch and D53540 
 would add the basic support for SEH and we 
can go fix corner/more complex cases in follow-up patches. There are also 
several more comprehensive test cases in 
https://github.com/Microsoft/windows_seh_tests which we plan to address next.


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

https://reviews.llvm.org/D53541



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


[PATCH] D53541: [COFF, ARM64] Do not emit x86_seh_recoverfp intrinsic

2019-01-15 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D53541#1356904 , @rnk wrote:

> In D53541#1353251 , @mgrang wrote:
>
> > > What about the three stack pointer case of stack realignment plus a 
> > > dynamic alloca? Typically this is the case where recoverfp is necessary.
> >
> > @rnk Sorry, I missed your comment earlier. I am not sure what scenario the 
> > three stack pointer case is. Could you please give me a test case for it?
>
>
> I think you just need a local variable with an alignment greater than the ABI 
> provides, something like:
>
>   struct Foo {
> Foo();
> int x, y, z;
>   };
>   int filter(int);
>   void may_throw();
>   void seh_byval(int n) {
> Foo __declspec(align(32)) o;
> __try {
>   may_throw();
> } __except(filter(o.x)) {
> }
>   }
>


We seem to be generating the same code as MSVC. Here's my test case:

  struct Foo {
void (*ptr)();
int x, y, z;
  };
  
  int filter(int);
  void may_throw();
  void seh_byval(int n) {
struct Foo __declspec(align(32)) o;
__try {
  may_throw();
} __except(filter(o.x)) {
}
  }

MSVC:

  |seh_byval$filt$0| PROC
  stp fp,lr,[sp,#-0x10]!
  mov fp,x1
  |$LN5@seh_byval$|
  ldr x8,[fp,#0x10]
  ldr w0,[x8,#8]
  bl  filter
  nop
  |$LN7@seh_byval$|
  ldp fp,lr,[sp],#0x10
  ret

LLVM:

  .seh_proc "?filt$0@0@seh_byval@@"
  ; %bb.0:; %entry
  movzx8, #:abs_g1_s:.Lseh_byval$frame_escape_0
  movkx8, #:abs_g0_nc:.Lseh_byval$frame_escape_0
  add x8, x1, x8
  ldr w0, [x8, #8]
  b   filter


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

https://reviews.llvm.org/D53541



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


[PATCH] D56685: [COFF, ARM64] Add __byteswap intrinsics

2019-01-14 Thread Mandeep Singh Grang via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC351147: [COFF, ARM64] Add __byteswap intrinsics (authored by 
mgrang, committed by ).

Repository:
  rC Clang

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

https://reviews.llvm.org/D56685

Files:
  lib/Headers/intrin.h
  test/Headers/ms-arm64-intrin.cpp


Index: test/Headers/ms-arm64-intrin.cpp
===
--- test/Headers/ms-arm64-intrin.cpp
+++ test/Headers/ms-arm64-intrin.cpp
@@ -1,13 +1,29 @@
-// RUN: %clang_cc1 -triple arm64-windows \
+// REQUIRES: aarch64-registered-target
+
+// RUN: %clang_cc1 -triple arm64-windows -O1 \
 // RUN: -fms-compatibility -fms-compatibility-version=17.00 \
 // RUN: -ffreestanding -fsyntax-only -Werror \
-// RUN: -isystem %S/Inputs/include %s -S -o - 2>&1 | FileCheck %s
-
-// REQUIRES: aarch64-registered-target
+// RUN: -isystem %S/Inputs/include %s -S -o - -emit-llvm 2>&1 \
+// RUN: | FileCheck %s
 
 #include 
 
-void f() {
-// CHECK: nop
+void check_nop() {
+// CHECK: "nop"
   __nop();
 }
+
+unsigned short check_byteswap_ushort(unsigned short val) {
+// CHECK: call i16 @llvm.bswap.i16(i16 %val)
+  return _byteswap_ushort(val);
+}
+
+unsigned long check_byteswap_ulong(unsigned long val) {
+// CHECK: call i32 @llvm.bswap.i32(i32 %val)
+  return _byteswap_ulong(val);
+}
+
+unsigned __int64 check_byteswap_uint64(unsigned __int64 val) {
+// CHECK: call i64 @llvm.bswap.i64(i64 %val)
+  return _byteswap_uint64(val);
+}
Index: lib/Headers/intrin.h
===
--- lib/Headers/intrin.h
+++ lib/Headers/intrin.h
@@ -566,6 +566,16 @@
 long _InterlockedAdd(long volatile *Addend, long Value);
 int _ReadStatusReg(int);
 void _WriteStatusReg(int, int);
+
+static inline unsigned short _byteswap_ushort (unsigned short val) {
+  return __builtin_bswap16(val);
+}
+static inline unsigned long _byteswap_ulong (unsigned long val) {
+  return __builtin_bswap32(val);
+}
+static inline unsigned __int64 _byteswap_uint64 (unsigned __int64 val) {
+  return __builtin_bswap64(val);
+}
 #endif
 
 
/**\


Index: test/Headers/ms-arm64-intrin.cpp
===
--- test/Headers/ms-arm64-intrin.cpp
+++ test/Headers/ms-arm64-intrin.cpp
@@ -1,13 +1,29 @@
-// RUN: %clang_cc1 -triple arm64-windows \
+// REQUIRES: aarch64-registered-target
+
+// RUN: %clang_cc1 -triple arm64-windows -O1 \
 // RUN: -fms-compatibility -fms-compatibility-version=17.00 \
 // RUN: -ffreestanding -fsyntax-only -Werror \
-// RUN: -isystem %S/Inputs/include %s -S -o - 2>&1 | FileCheck %s
-
-// REQUIRES: aarch64-registered-target
+// RUN: -isystem %S/Inputs/include %s -S -o - -emit-llvm 2>&1 \
+// RUN: | FileCheck %s
 
 #include 
 
-void f() {
-// CHECK: nop
+void check_nop() {
+// CHECK: "nop"
   __nop();
 }
+
+unsigned short check_byteswap_ushort(unsigned short val) {
+// CHECK: call i16 @llvm.bswap.i16(i16 %val)
+  return _byteswap_ushort(val);
+}
+
+unsigned long check_byteswap_ulong(unsigned long val) {
+// CHECK: call i32 @llvm.bswap.i32(i32 %val)
+  return _byteswap_ulong(val);
+}
+
+unsigned __int64 check_byteswap_uint64(unsigned __int64 val) {
+// CHECK: call i64 @llvm.bswap.i64(i64 %val)
+  return _byteswap_uint64(val);
+}
Index: lib/Headers/intrin.h
===
--- lib/Headers/intrin.h
+++ lib/Headers/intrin.h
@@ -566,6 +566,16 @@
 long _InterlockedAdd(long volatile *Addend, long Value);
 int _ReadStatusReg(int);
 void _WriteStatusReg(int, int);
+
+static inline unsigned short _byteswap_ushort (unsigned short val) {
+  return __builtin_bswap16(val);
+}
+static inline unsigned long _byteswap_ulong (unsigned long val) {
+  return __builtin_bswap32(val);
+}
+static inline unsigned __int64 _byteswap_uint64 (unsigned __int64 val) {
+  return __builtin_bswap64(val);
+}
 #endif
 
 /**\
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56685: [COFF, ARM64] Add __byteswap intrinsics

2019-01-14 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 181679.

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

https://reviews.llvm.org/D56685

Files:
  lib/Headers/intrin.h
  test/Headers/ms-arm64-intrin.cpp


Index: test/Headers/ms-arm64-intrin.cpp
===
--- test/Headers/ms-arm64-intrin.cpp
+++ test/Headers/ms-arm64-intrin.cpp
@@ -1,13 +1,29 @@
-// RUN: %clang_cc1 -triple arm64-windows \
+// REQUIRES: aarch64-registered-target
+
+// RUN: %clang_cc1 -triple arm64-windows -O1 \
 // RUN: -fms-compatibility -fms-compatibility-version=17.00 \
 // RUN: -ffreestanding -fsyntax-only -Werror \
-// RUN: -isystem %S/Inputs/include %s -S -o - 2>&1 | FileCheck %s
-
-// REQUIRES: aarch64-registered-target
+// RUN: -isystem %S/Inputs/include %s -S -o - -emit-llvm 2>&1 \
+// RUN: | FileCheck %s
 
 #include 
 
-void f() {
-// CHECK: nop
+void check_nop() {
+// CHECK: "nop"
   __nop();
 }
+
+unsigned short check_byteswap_ushort(unsigned short val) {
+// CHECK: call i16 @llvm.bswap.i16(i16 %val)
+  return _byteswap_ushort(val);
+}
+
+unsigned long check_byteswap_ulong(unsigned long val) {
+// CHECK: call i32 @llvm.bswap.i32(i32 %val)
+  return _byteswap_ulong(val);
+}
+
+unsigned __int64 check_byteswap_uint64(unsigned __int64 val) {
+// CHECK: call i64 @llvm.bswap.i64(i64 %val)
+  return _byteswap_uint64(val);
+}
Index: lib/Headers/intrin.h
===
--- lib/Headers/intrin.h
+++ lib/Headers/intrin.h
@@ -566,6 +566,16 @@
 long _InterlockedAdd(long volatile *Addend, long Value);
 int _ReadStatusReg(int);
 void _WriteStatusReg(int, int);
+
+static inline unsigned short _byteswap_ushort (unsigned short val) {
+  return __builtin_bswap16(val);
+}
+static inline unsigned long _byteswap_ulong (unsigned long val) {
+  return __builtin_bswap32(val);
+}
+static inline unsigned __int64 _byteswap_uint64 (unsigned __int64 val) {
+  return __builtin_bswap64(val);
+}
 #endif
 
 
/**\


Index: test/Headers/ms-arm64-intrin.cpp
===
--- test/Headers/ms-arm64-intrin.cpp
+++ test/Headers/ms-arm64-intrin.cpp
@@ -1,13 +1,29 @@
-// RUN: %clang_cc1 -triple arm64-windows \
+// REQUIRES: aarch64-registered-target
+
+// RUN: %clang_cc1 -triple arm64-windows -O1 \
 // RUN: -fms-compatibility -fms-compatibility-version=17.00 \
 // RUN: -ffreestanding -fsyntax-only -Werror \
-// RUN: -isystem %S/Inputs/include %s -S -o - 2>&1 | FileCheck %s
-
-// REQUIRES: aarch64-registered-target
+// RUN: -isystem %S/Inputs/include %s -S -o - -emit-llvm 2>&1 \
+// RUN: | FileCheck %s
 
 #include 
 
-void f() {
-// CHECK: nop
+void check_nop() {
+// CHECK: "nop"
   __nop();
 }
+
+unsigned short check_byteswap_ushort(unsigned short val) {
+// CHECK: call i16 @llvm.bswap.i16(i16 %val)
+  return _byteswap_ushort(val);
+}
+
+unsigned long check_byteswap_ulong(unsigned long val) {
+// CHECK: call i32 @llvm.bswap.i32(i32 %val)
+  return _byteswap_ulong(val);
+}
+
+unsigned __int64 check_byteswap_uint64(unsigned __int64 val) {
+// CHECK: call i64 @llvm.bswap.i64(i64 %val)
+  return _byteswap_uint64(val);
+}
Index: lib/Headers/intrin.h
===
--- lib/Headers/intrin.h
+++ lib/Headers/intrin.h
@@ -566,6 +566,16 @@
 long _InterlockedAdd(long volatile *Addend, long Value);
 int _ReadStatusReg(int);
 void _WriteStatusReg(int, int);
+
+static inline unsigned short _byteswap_ushort (unsigned short val) {
+  return __builtin_bswap16(val);
+}
+static inline unsigned long _byteswap_ulong (unsigned long val) {
+  return __builtin_bswap32(val);
+}
+static inline unsigned __int64 _byteswap_uint64 (unsigned __int64 val) {
+  return __builtin_bswap64(val);
+}
 #endif
 
 /**\
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56685: [COFF, ARM64] Add __byteswap intrinsics

2019-01-14 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang marked an inline comment as done.
mgrang added a comment.

Verified that this compiles when both intrin.h and stdlib.h from the Microsoft 
SDK are included, in either order.


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

https://reviews.llvm.org/D56685



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


[PATCH] D56685: [COFF, ARM64] Add __byteswap intrinsics

2019-01-14 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 181671.
mgrang retitled this revision from "[COFF, ARM64] Declare __byteswap 
intrinsics" to "[COFF, ARM64] Add __byteswap intrinsics".

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

https://reviews.llvm.org/D56685

Files:
  lib/Headers/intrin.h
  test/Headers/ms-arm64-intrin.cpp


Index: test/Headers/ms-arm64-intrin.cpp
===
--- test/Headers/ms-arm64-intrin.cpp
+++ test/Headers/ms-arm64-intrin.cpp
@@ -1,9 +1,15 @@
+// REQUIRES: aarch64-registered-target
+
 // RUN: %clang_cc1 -triple arm64-windows \
 // RUN: -fms-compatibility -fms-compatibility-version=17.00 \
 // RUN: -ffreestanding -fsyntax-only -Werror \
 // RUN: -isystem %S/Inputs/include %s -S -o - 2>&1 | FileCheck %s
 
-// REQUIRES: aarch64-registered-target
+// RUN: %clang_cc1 -triple arm64-windows -O1 \
+// RUN: -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -ffreestanding -fsyntax-only -Werror \
+// RUN: -isystem %S/Inputs/include %s -S -o - -emit-llvm 2>&1 \
+// RUN: | FileCheck %s --check-prefix CHECK-IR
 
 #include 
 
@@ -11,3 +17,18 @@
 // CHECK: nop
   __nop();
 }
+
+unsigned short check_byteswap_ushort(unsigned short val) {
+// CHECK-IR: call i16 @llvm.bswap.i16(i16 %val)
+  return _byteswap_ushort(val);
+}
+
+unsigned long check_byteswap_ulong(unsigned long val) {
+// CHECK-IR: call i32 @llvm.bswap.i32(i32 %val)
+  return _byteswap_ulong(val);
+}
+
+unsigned __int64 check_byteswap_uint64(unsigned __int64 val) {
+// CHECK-IR: call i64 @llvm.bswap.i64(i64 %val)
+  return _byteswap_uint64(val);
+}
Index: lib/Headers/intrin.h
===
--- lib/Headers/intrin.h
+++ lib/Headers/intrin.h
@@ -566,6 +566,16 @@
 long _InterlockedAdd(long volatile *Addend, long Value);
 int _ReadStatusReg(int);
 void _WriteStatusReg(int, int);
+
+static inline unsigned short _byteswap_ushort (unsigned short val) {
+  return __builtin_bswap16(val);
+}
+static inline unsigned long _byteswap_ulong (unsigned long val) {
+  return __builtin_bswap32(val);
+}
+static inline unsigned __int64 _byteswap_uint64 (unsigned __int64 val) {
+  return __builtin_bswap64(val);
+}
 #endif
 
 
/**\


Index: test/Headers/ms-arm64-intrin.cpp
===
--- test/Headers/ms-arm64-intrin.cpp
+++ test/Headers/ms-arm64-intrin.cpp
@@ -1,9 +1,15 @@
+// REQUIRES: aarch64-registered-target
+
 // RUN: %clang_cc1 -triple arm64-windows \
 // RUN: -fms-compatibility -fms-compatibility-version=17.00 \
 // RUN: -ffreestanding -fsyntax-only -Werror \
 // RUN: -isystem %S/Inputs/include %s -S -o - 2>&1 | FileCheck %s
 
-// REQUIRES: aarch64-registered-target
+// RUN: %clang_cc1 -triple arm64-windows -O1 \
+// RUN: -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -ffreestanding -fsyntax-only -Werror \
+// RUN: -isystem %S/Inputs/include %s -S -o - -emit-llvm 2>&1 \
+// RUN: | FileCheck %s --check-prefix CHECK-IR
 
 #include 
 
@@ -11,3 +17,18 @@
 // CHECK: nop
   __nop();
 }
+
+unsigned short check_byteswap_ushort(unsigned short val) {
+// CHECK-IR: call i16 @llvm.bswap.i16(i16 %val)
+  return _byteswap_ushort(val);
+}
+
+unsigned long check_byteswap_ulong(unsigned long val) {
+// CHECK-IR: call i32 @llvm.bswap.i32(i32 %val)
+  return _byteswap_ulong(val);
+}
+
+unsigned __int64 check_byteswap_uint64(unsigned __int64 val) {
+// CHECK-IR: call i64 @llvm.bswap.i64(i64 %val)
+  return _byteswap_uint64(val);
+}
Index: lib/Headers/intrin.h
===
--- lib/Headers/intrin.h
+++ lib/Headers/intrin.h
@@ -566,6 +566,16 @@
 long _InterlockedAdd(long volatile *Addend, long Value);
 int _ReadStatusReg(int);
 void _WriteStatusReg(int, int);
+
+static inline unsigned short _byteswap_ushort (unsigned short val) {
+  return __builtin_bswap16(val);
+}
+static inline unsigned long _byteswap_ulong (unsigned long val) {
+  return __builtin_bswap32(val);
+}
+static inline unsigned __int64 _byteswap_uint64 (unsigned __int64 val) {
+  return __builtin_bswap64(val);
+}
 #endif
 
 /**\
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56671: [COFF, ARM64] Add __nop intrinsic

2019-01-14 Thread Mandeep Singh Grang via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL351135: [COFF, ARM64] Add __nop intrinsic (authored by 
mgrang, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D56671?vs=181578=181659#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D56671

Files:
  cfe/trunk/lib/Headers/intrin.h
  cfe/trunk/test/Headers/ms-arm64-intrin.cpp


Index: cfe/trunk/lib/Headers/intrin.h
===
--- cfe/trunk/lib/Headers/intrin.h
+++ cfe/trunk/lib/Headers/intrin.h
@@ -549,6 +549,9 @@
 __halt(void) {
   __asm__ volatile ("hlt");
 }
+#endif
+
+#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
 static __inline__ void __DEFAULT_FN_ATTRS
 __nop(void) {
   __asm__ volatile ("nop");
Index: cfe/trunk/test/Headers/ms-arm64-intrin.cpp
===
--- cfe/trunk/test/Headers/ms-arm64-intrin.cpp
+++ cfe/trunk/test/Headers/ms-arm64-intrin.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple arm64-windows \
+// RUN: -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -ffreestanding -fsyntax-only -Werror \
+// RUN: -isystem %S/Inputs/include %s -S -o - 2>&1 | FileCheck %s
+
+// REQUIRES: aarch64-registered-target
+
+#include 
+
+void f() {
+// CHECK: nop
+  __nop();
+}


Index: cfe/trunk/lib/Headers/intrin.h
===
--- cfe/trunk/lib/Headers/intrin.h
+++ cfe/trunk/lib/Headers/intrin.h
@@ -549,6 +549,9 @@
 __halt(void) {
   __asm__ volatile ("hlt");
 }
+#endif
+
+#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
 static __inline__ void __DEFAULT_FN_ATTRS
 __nop(void) {
   __asm__ volatile ("nop");
Index: cfe/trunk/test/Headers/ms-arm64-intrin.cpp
===
--- cfe/trunk/test/Headers/ms-arm64-intrin.cpp
+++ cfe/trunk/test/Headers/ms-arm64-intrin.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple arm64-windows \
+// RUN: -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -ffreestanding -fsyntax-only -Werror \
+// RUN: -isystem %S/Inputs/include %s -S -o - 2>&1 | FileCheck %s
+
+// REQUIRES: aarch64-registered-target
+
+#include 
+
+void f() {
+// CHECK: nop
+  __nop();
+}
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56620: [COFF, ARM64] Declare intrinsics: __nop, _byteswap_[ushort/ulong/uint64]

2019-01-14 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang abandoned this revision.
mgrang added a comment.

_bytswap intrinsics are added in D56685 . 
Abandoning this patch.


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

https://reviews.llvm.org/D56620



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


[PATCH] D56685: [COFF, ARM64] Declare __byteswap intrinsics

2019-01-14 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang created this revision.
mgrang added reviewers: rnk, efriedma, ssijaric, TomTan, haripul.
Herald added subscribers: kristof.beyls, javed.absar.

Repository:
  rC Clang

https://reviews.llvm.org/D56685

Files:
  lib/Headers/arm64intr.h
  test/Headers/ms-arm64-intrin.cpp


Index: test/Headers/ms-arm64-intrin.cpp
===
--- test/Headers/ms-arm64-intrin.cpp
+++ test/Headers/ms-arm64-intrin.cpp
@@ -3,6 +3,11 @@
 // RUN: -ffreestanding -fsyntax-only -Werror \
 // RUN: -isystem %S/Inputs/include %s -S -o - 2>&1 | FileCheck %s
 
+// RUN: %clang_cc1 -triple arm64-windows \
+// RUN: -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -ffreestanding -fsyntax-only -Werror \
+// RUN: -isystem %S/Inputs/include %s -S -o - -emit-llvm 2>&1 | FileCheck %s 
--check-prefix CHECK-IR
+
 // REQUIRES: aarch64-registered-target
 
 #include 
@@ -11,3 +16,66 @@
 // CHECK: nop
   __nop();
 }
+
+unsigned short check_byteswap_ushort_1() {
+// CHECK-IR: ret i16 256
+  return _byteswap_ushort(1);
+}
+unsigned short check_byteswap_ushort_2() {
+// CHECK-IR: ret i16 512
+  return _byteswap_ushort(2);
+}
+unsigned short check_byteswap_ushort_3() {
+// CHECK-IR: ret i16 768
+  return _byteswap_ushort(3);
+}
+unsigned short check_byteswap_ushort_4() {
+// CHECK-IR: ret i16 1024
+  return _byteswap_ushort(4);
+}
+unsigned short check_byteswap_ushort_5() {
+// CHECK-IR: ret i16 1280
+  return _byteswap_ushort(5);
+}
+
+unsigned long check_byteswap_ulong_1() {
+// CHECK-IR: ret i32 16777216
+  return _byteswap_ulong(1);
+}
+unsigned long check_byteswap_ulong_2() {
+// CHECK-IR: ret i32 33554432
+  return _byteswap_ulong(2);
+}
+unsigned long check_byteswap_ulong_3() {
+// CHECK-IR: ret i32 50331648
+  return _byteswap_ulong(3);
+}
+unsigned long check_byteswap_ulong_4() {
+// CHECK-IR: ret i32 67108864
+  return _byteswap_ulong(4);
+}
+unsigned long check_byteswap_ulong_5() {
+// CHECK-IR: ret i32 83886080
+  return _byteswap_ulong(5);
+}
+
+unsigned __int64 check_byteswap_uint64_1() {
+// CHECK-IR: ret i64 72057594037927936
+  return _byteswap_uint64(1);
+}
+unsigned __int64 check_byteswap_uint64_2() {
+// CHECK-IR: ret i64 144115188075855872
+  return _byteswap_uint64(2);
+}
+unsigned __int64 check_byteswap_uint64_3() {
+// CHECK-IR: ret i64 216172782113783808
+  return _byteswap_uint64(3);
+}
+unsigned __int64 check_byteswap_uint64_4() {
+// CHECK-IR: ret i64 288230376151711744
+  return _byteswap_uint64(4);
+}
+unsigned __int64 check_byteswap_uint64_5() {
+// CHECK-IR: ret i64 360287970189639680
+  return _byteswap_uint64(5);
+}
Index: lib/Headers/arm64intr.h
===
--- lib/Headers/arm64intr.h
+++ lib/Headers/arm64intr.h
@@ -45,5 +45,9 @@
   _ARM64_BARRIER_OSHLD = 0x1
 } _ARM64INTR_BARRIER_TYPE;
 
+#define _byteswap_ushort __builtin_bswap16
+#define _byteswap_ulong  __builtin_bswap32
+#define _byteswap_uint64 __builtin_bswap64
+
 #endif /* __ARM64INTR_H */
 #endif /* _MSC_VER */


Index: test/Headers/ms-arm64-intrin.cpp
===
--- test/Headers/ms-arm64-intrin.cpp
+++ test/Headers/ms-arm64-intrin.cpp
@@ -3,6 +3,11 @@
 // RUN: -ffreestanding -fsyntax-only -Werror \
 // RUN: -isystem %S/Inputs/include %s -S -o - 2>&1 | FileCheck %s
 
+// RUN: %clang_cc1 -triple arm64-windows \
+// RUN: -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -ffreestanding -fsyntax-only -Werror \
+// RUN: -isystem %S/Inputs/include %s -S -o - -emit-llvm 2>&1 | FileCheck %s --check-prefix CHECK-IR
+
 // REQUIRES: aarch64-registered-target
 
 #include 
@@ -11,3 +16,66 @@
 // CHECK: nop
   __nop();
 }
+
+unsigned short check_byteswap_ushort_1() {
+// CHECK-IR: ret i16 256
+  return _byteswap_ushort(1);
+}
+unsigned short check_byteswap_ushort_2() {
+// CHECK-IR: ret i16 512
+  return _byteswap_ushort(2);
+}
+unsigned short check_byteswap_ushort_3() {
+// CHECK-IR: ret i16 768
+  return _byteswap_ushort(3);
+}
+unsigned short check_byteswap_ushort_4() {
+// CHECK-IR: ret i16 1024
+  return _byteswap_ushort(4);
+}
+unsigned short check_byteswap_ushort_5() {
+// CHECK-IR: ret i16 1280
+  return _byteswap_ushort(5);
+}
+
+unsigned long check_byteswap_ulong_1() {
+// CHECK-IR: ret i32 16777216
+  return _byteswap_ulong(1);
+}
+unsigned long check_byteswap_ulong_2() {
+// CHECK-IR: ret i32 33554432
+  return _byteswap_ulong(2);
+}
+unsigned long check_byteswap_ulong_3() {
+// CHECK-IR: ret i32 50331648
+  return _byteswap_ulong(3);
+}
+unsigned long check_byteswap_ulong_4() {
+// CHECK-IR: ret i32 67108864
+  return _byteswap_ulong(4);
+}
+unsigned long check_byteswap_ulong_5() {
+// CHECK-IR: ret i32 83886080
+  return _byteswap_ulong(5);
+}
+
+unsigned __int64 check_byteswap_uint64_1() {
+// CHECK-IR: ret i64 72057594037927936
+  return _byteswap_uint64(1);
+}
+unsigned __int64 check_byteswap_uint64_2() {
+// CHECK-IR: ret i64 144115188075855872
+  return 

[PATCH] D56671: [COFF, ARM64] Add __nop intrinsic

2019-01-14 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang created this revision.
mgrang added reviewers: rnk, efriedma, TomTan, haripul, ssijaric.
Herald added subscribers: kristof.beyls, javed.absar.

Repository:
  rC Clang

https://reviews.llvm.org/D56671

Files:
  lib/Headers/intrin.h
  test/Headers/ms-arm64-intrin.cpp


Index: test/Headers/ms-arm64-intrin.cpp
===
--- /dev/null
+++ test/Headers/ms-arm64-intrin.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple arm64-windows \
+// RUN: -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -ffreestanding -fsyntax-only -Werror \
+// RUN: -isystem %S/Inputs/include %s -S -o - 2>&1 | FileCheck %s
+
+// REQUIRES: aarch64-registered-target
+
+#include 
+
+void f() {
+// CHECK: nop
+  __nop();
+}
Index: lib/Headers/intrin.h
===
--- lib/Headers/intrin.h
+++ lib/Headers/intrin.h
@@ -549,6 +549,9 @@
 __halt(void) {
   __asm__ volatile ("hlt");
 }
+#endif
+
+#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
 static __inline__ void __DEFAULT_FN_ATTRS
 __nop(void) {
   __asm__ volatile ("nop");


Index: test/Headers/ms-arm64-intrin.cpp
===
--- /dev/null
+++ test/Headers/ms-arm64-intrin.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple arm64-windows \
+// RUN: -fms-compatibility -fms-compatibility-version=17.00 \
+// RUN: -ffreestanding -fsyntax-only -Werror \
+// RUN: -isystem %S/Inputs/include %s -S -o - 2>&1 | FileCheck %s
+
+// REQUIRES: aarch64-registered-target
+
+#include 
+
+void f() {
+// CHECK: nop
+  __nop();
+}
Index: lib/Headers/intrin.h
===
--- lib/Headers/intrin.h
+++ lib/Headers/intrin.h
@@ -549,6 +549,9 @@
 __halt(void) {
   __asm__ volatile ("hlt");
 }
+#endif
+
+#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
 static __inline__ void __DEFAULT_FN_ATTRS
 __nop(void) {
   __asm__ volatile ("nop");
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56620: [COFF, ARM64] Declare intrinsics: __nop, _byteswap_[ushort/ulong/uint64]

2019-01-14 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

I have implemented __nop intrinsics in https://reviews.llvm.org/D56620


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

https://reviews.llvm.org/D56620



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


[PATCH] D56620: [COFF, ARM64] Declare intrinsics: __nop, _byteswap_[short/long/uint64]

2019-01-11 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 181390.
mgrang retitled this revision from "[COFF, ARM64] Include stdlib.h in 
arm64intr.h" to "[COFF, ARM64] Declare intrinsics: __nop, 
_byteswap_[short/long/uint64]".
mgrang edited the summary of this revision.

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

https://reviews.llvm.org/D56620

Files:
  lib/Headers/intrin.h


Index: lib/Headers/intrin.h
===
--- lib/Headers/intrin.h
+++ lib/Headers/intrin.h
@@ -563,6 +563,10 @@
 long _InterlockedAdd(long volatile *Addend, long Value);
 int _ReadStatusReg(int);
 void _WriteStatusReg(int, int);
+unsigned short _byteswap_ushort (unsigned short val);
+unsigned long _byteswap_ulong (unsigned long val);
+unsigned __int64 _byteswap_uint64 (unsigned __int64 val);
+void __nop();
 #endif
 
 
/**\


Index: lib/Headers/intrin.h
===
--- lib/Headers/intrin.h
+++ lib/Headers/intrin.h
@@ -563,6 +563,10 @@
 long _InterlockedAdd(long volatile *Addend, long Value);
 int _ReadStatusReg(int);
 void _WriteStatusReg(int, int);
+unsigned short _byteswap_ushort (unsigned short val);
+unsigned long _byteswap_ulong (unsigned long val);
+unsigned __int64 _byteswap_uint64 (unsigned __int64 val);
+void __nop();
 #endif
 
 /**\
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56620: [COFF, ARM64] Include stdlib.h in arm64intr.h

2019-01-11 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D56620#1354979 , @efriedma wrote:

> Have you verified this matches MSVC?  (IIRC the only reason we include 
> stdlib.h on x86 is so we can define _mm_malloc.)


I don't see MSVC intrin.h including stdlib.h. So I guess I will just declare 
the required intrinsics.


Repository:
  rC Clang

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

https://reviews.llvm.org/D56620



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


[PATCH] D56620: [COFF, ARM64] Include stdlib.h in arm64intr.h

2019-01-11 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang created this revision.
mgrang added reviewers: rnk, efriedma, ssijaric, TomTan, haripul.
Herald added subscribers: kristof.beyls, javed.absar.

We mimic x86 behavior which includes stdlib.h in x86intr.h.


Repository:
  rC Clang

https://reviews.llvm.org/D56620

Files:
  lib/Headers/arm64intr.h


Index: lib/Headers/arm64intr.h
===
--- lib/Headers/arm64intr.h
+++ lib/Headers/arm64intr.h
@@ -26,6 +26,10 @@
 #include_next 
 #else
 
+#if __STDC_HOSTED__
+#include 
+#endif
+
 #ifndef __ARM64INTR_H
 #define __ARM64INTR_H
 


Index: lib/Headers/arm64intr.h
===
--- lib/Headers/arm64intr.h
+++ lib/Headers/arm64intr.h
@@ -26,6 +26,10 @@
 #include_next 
 #else
 
+#if __STDC_HOSTED__
+#include 
+#endif
+
 #ifndef __ARM64INTR_H
 #define __ARM64INTR_H
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53541: [COFF, ARM64] Do not emit x86_seh_recoverfp intrinsic

2019-01-11 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 181333.

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

https://reviews.llvm.org/D53541

Files:
  lib/CodeGen/CGException.cpp
  test/CodeGen/exceptions-seh.c


Index: test/CodeGen/exceptions-seh.c
===
--- test/CodeGen/exceptions-seh.c
+++ test/CodeGen/exceptions-seh.c
@@ -99,8 +99,7 @@
 // X64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture 
to i8*), i8* %[[fp]], i32 0)
 //
 // ARM64-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"(i8* 
%exception_pointers, i8* %frame_pointer)
-// ARM64: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 
()* @filter_expr_capture to i8*), i8* %frame_pointer)
-// ARM64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* 
@filter_expr_capture to i8*), i8* %[[fp]], i32 0)
+// ARM64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* 
@filter_expr_capture to i8*), i8* %frame_pointer, i32 0)
 //
 // X86-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"()
 // X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
Index: lib/CodeGen/CGException.cpp
===
--- lib/CodeGen/CGException.cpp
+++ lib/CodeGen/CGException.cpp
@@ -1783,7 +1783,8 @@
   }
 
   llvm::Value *ParentFP = EntryFP;
-  if (IsFilter) {
+  if (IsFilter &&
+  CGM.getTarget().getTriple().getArch() != llvm::Triple::aarch64) {
 // Given whatever FP the runtime provided us in EntryFP, recover the true
 // frame pointer of the parent function. We only need to do this in 
filters,
 // since finally funclets recover the parent FP for us.


Index: test/CodeGen/exceptions-seh.c
===
--- test/CodeGen/exceptions-seh.c
+++ test/CodeGen/exceptions-seh.c
@@ -99,8 +99,7 @@
 // X64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0)
 //
 // ARM64-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer)
-// ARM64: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer)
-// ARM64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0)
+// ARM64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer, i32 0)
 //
 // X86-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"()
 // X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
Index: lib/CodeGen/CGException.cpp
===
--- lib/CodeGen/CGException.cpp
+++ lib/CodeGen/CGException.cpp
@@ -1783,7 +1783,8 @@
   }
 
   llvm::Value *ParentFP = EntryFP;
-  if (IsFilter) {
+  if (IsFilter &&
+  CGM.getTarget().getTriple().getArch() != llvm::Triple::aarch64) {
 // Given whatever FP the runtime provided us in EntryFP, recover the true
 // frame pointer of the parent function. We only need to do this in filters,
 // since finally funclets recover the parent FP for us.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56463: [SEH] Pass the frame pointer from SEH finally to finally functions

2019-01-11 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added inline comments.



Comment at: lib/CodeGen/CGException.cpp:1635
+else {
+  llvm::Value *LocalAddrFn = 
CGM.getIntrinsic(llvm::Intrinsic::localaddress);
+  FP = CGF.Builder.CreateCall(LocalAddrFn);

80 char limit.


Repository:
  rC Clang

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

https://reviews.llvm.org/D56463



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


[PATCH] D53541: [COFF, ARM64] Do not emit x86_seh_recoverfp intrinsic

2019-01-10 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D53541#1282900 , @rnk wrote:

> In D53541#1282764 , @mgrang wrote:
>
> > Updated the patch with the following changes:
> >
> > 1. Emit llvm.x86.seh.recoverfp only for non-aarch64 targets. For aarch64 
> > windows, the parent fp is always passed in x1. So we don't need a separate 
> > instrinsic to recover the fp.
>
>
> What about the three stack pointer case of stack realignment plus a dynamic 
> alloca? Typically this is the case where recoverfp is necessary.


@rnk Sorry, I missed your comment earlier. I am not sure what scenario the 
three stack pointer case is. Could you please give me a test case for it?


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

https://reviews.llvm.org/D53541



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


[PATCH] D53541: [COFF, ARM64] Do not emit x86_seh_recoverfp intrinsic

2019-01-10 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 181106.
mgrang retitled this revision from "[COFF, ARM64] Support SEH for ARM64 
Windows" to "[COFF, ARM64] Do not emit x86_seh_recoverfp intrinsic".

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

https://reviews.llvm.org/D53541

Files:
  lib/CodeGen/CGException.cpp
  test/CodeGen/exceptions-seh.c


Index: test/CodeGen/exceptions-seh.c
===
--- test/CodeGen/exceptions-seh.c
+++ test/CodeGen/exceptions-seh.c
@@ -2,8 +2,6 @@
 // RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X64
 // RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - \
 // RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X86
-// RUN: %clang_cc1 %s -triple aarch64-windows -fms-extensions -emit-llvm -o - \
-// RUN: | FileCheck %s --check-prefixes=CHECK,ARM64
 // RUN: %clang_cc1 %s -triple i686-pc-windows-gnu -fms-extensions -emit-llvm 
-o - \
 // RUN: | FileCheck %s --check-prefix=X86-GNU
 // RUN: %clang_cc1 %s -triple x86_64-pc-windows-gnu -fms-extensions -emit-llvm 
-o - \
@@ -31,14 +29,12 @@
 
 // CHECK-LABEL: define dso_local i32 @safe_div(i32 %numerator, i32 
%denominator, i32* %res)
 // X64-SAME:  personality i8* bitcast (i32 (...)* @__C_specific_handler to 
i8*)
-// ARM64-SAME:personality i8* bitcast (i32 (...)* @__C_specific_handler to 
i8*)
 // X86-SAME:  personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
 // CHECK: invoke void @try_body(i32 %{{.*}}, i32 %{{.*}}, i32* %{{.*}}) 
#[[NOINLINE:[0-9]+]]
 // CHECK:   to label %{{.*}} unwind label %[[catchpad:[^ ]*]]
 //
 // CHECK: [[catchpad]]
 // X64: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* null]
-// ARM64: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* null]
 // X86: %[[padtoken:[^ ]*]] = catchpad within %{{[^ ]*}} [i8* bitcast (i32 ()* 
@"?filt$0@0@safe_div@@" to i8*)]
 // CHECK-NEXT: catchret from %[[padtoken]] to label %[[except:[^ ]*]]
 //
@@ -80,10 +76,8 @@
 
 // CHECK-LABEL: define dso_local i32 @filter_expr_capture()
 // X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
-// ARM64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to 
i8*)
 // X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
 // X64: call void (...) @llvm.localescape(i32* %[[r:[^ ,]*]])
-// ARM64: call void (...) @llvm.localescape(i32* %[[r:[^ ,]*]])
 // X86: call void (...) @llvm.localescape(i32* %[[r:[^ ,]*]], i32* %[[code:[^ 
,]*]])
 // CHECK: store i32 42, i32* %[[r]]
 // CHECK: invoke void @j() #[[NOINLINE]]
@@ -98,10 +92,6 @@
 // X64: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* 
@filter_expr_capture to i8*), i8* %frame_pointer)
 // X64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* @filter_expr_capture 
to i8*), i8* %[[fp]], i32 0)
 //
-// ARM64-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"(i8* 
%exception_pointers, i8* %frame_pointer)
-// ARM64: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 
()* @filter_expr_capture to i8*), i8* %frame_pointer)
-// ARM64: call i8* @llvm.localrecover(i8* bitcast (i32 ()* 
@filter_expr_capture to i8*), i8* %[[fp]], i32 0)
-//
 // X86-LABEL: define internal i32 @"?filt$0@0@filter_expr_capture@@"()
 // X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
 // X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* 
@filter_expr_capture to i8*), i8* %[[ebp]])
@@ -126,7 +116,6 @@
 }
 // CHECK-LABEL: define dso_local i32 @nested_try()
 // X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
-// ARM64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to 
i8*)
 // X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
 // CHECK: store i32 42, i32* %[[r:[^ ,]*]]
 // CHECK: invoke void @j() #[[NOINLINE]]
@@ -187,7 +176,6 @@
 }
 // CHECK-LABEL: define dso_local i32 @basic_finally(i32 %g)
 // X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
-// ARM64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to 
i8*)
 // X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
 // CHECK: %[[g_addr:[^ ]*]] = alloca i32, align 4
 // CHECK: call void (...) @llvm.localescape(i32* %[[g_addr]])
@@ -287,8 +275,6 @@
 // CHECK: catchret from %[[pad]]
 // X64: %[[code:[^ ]*]] = call i32 @llvm.eh.exceptioncode(token %[[pad]])
 // X64: store i32 %[[code]], i32* %[[code_slot]]
-// ARM64: %[[code:[^ ]*]] = call i32 @llvm.eh.exceptioncode(token %[[pad]])
-// ARM64: store i32 %[[code]], i32* %[[code_slot]]
 // CHECK: %[[ret1:[^ ]*]] = load i32, i32* %[[code_slot]]
 // CHECK: store i32 %[[ret1]], i32* %[[ret_slot]]
 // CHECK: %[[ret2:[^ ]*]] = load i32, i32* %[[ret_slot]]
Index: lib/CodeGen/CGException.cpp
===
--- lib/CodeGen/CGException.cpp
+++ 

[PATCH] D55229: [COFF] Statically link certain runtime library functions

2018-12-10 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

Ping for reviews please.


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

https://reviews.llvm.org/D55229



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


[PATCH] D55229: [COFF] Statically link certain runtime library functions

2018-12-04 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang marked an inline comment as done.
mgrang added inline comments.



Comment at: CodeGenObjC/gnu-init.m:103
+// Make sure we do not have dllimport on the load function
+// CHECK-WIN: declare dso_local void @__objc_load
 

I had to remove dllimport in this and the next unit test. I am not sure of the 
wider implications of this change. Maybe controlling this via a flag (like 
-flto-visibility-public-std) is a better/more localized option?


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

https://reviews.llvm.org/D55229



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


[PATCH] D55229: [COFF] Statically link certain runtime library functions

2018-12-04 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang updated this revision to Diff 176693.
mgrang retitled this revision from "[COFF, ARM64] Make 
-flto-visibility-public-std a driver and cc1 flag" to "[COFF] Statically link 
certain runtime library functions".
mgrang edited the summary of this revision.

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

https://reviews.llvm.org/D55229

Files:
  CodeGen/CodeGenModule.cpp
  CodeGen/ms-symbol-linkage.cpp
  CodeGenCXX/runtime-dllstorage.cpp
  CodeGenObjC/gnu-init.m
  CodeGenObjCXX/msabi-stret.mm


Index: CodeGenObjCXX/msabi-stret.mm
===
--- CodeGenObjCXX/msabi-stret.mm
+++ CodeGenObjCXX/msabi-stret.mm
@@ -13,6 +13,5 @@
   return [I m:S()];
 }
 
-// CHECK: declare dllimport void @objc_msgSend_stret(i8*, i8*, ...)
+// CHECK: declare dso_local void @objc_msgSend_stret(i8*, i8*, ...)
 // CHECK-NOT: declare dllimport void @objc_msgSend(i8*, i8*, ...)
-
Index: CodeGenObjC/gnu-init.m
===
--- CodeGenObjC/gnu-init.m
+++ CodeGenObjC/gnu-init.m
@@ -99,6 +99,6 @@
 // Check our load function is in a comdat.
 // CHECK-WIN: define linkonce_odr hidden void @.objcv2_load_function() comdat {
 
-// Make sure we have dllimport on the load function
-// CHECK-WIN: declare dllimport void @__objc_load
+// Make sure we do not have dllimport on the load function
+// CHECK-WIN: declare dso_local void @__objc_load
 
Index: CodeGenCXX/runtime-dllstorage.cpp
===
--- CodeGenCXX/runtime-dllstorage.cpp
+++ CodeGenCXX/runtime-dllstorage.cpp
@@ -108,7 +108,7 @@
 // CHECK-MS-DAG: @_Init_thread_epoch = external thread_local global i32
 // CHECK-MS-DAG: declare dso_local i32 @__tlregdtor(void ()*)
 // CHECK-MS-DAG: declare dso_local i32 @atexit(void ()*)
-// CHECK-MS-DYNAMIC-DAG: declare dllimport {{.*}} void @_CxxThrowException
+// CHECK-MS-DYNAMIC-DAG: declare {{.*}} void @_CxxThrowException
 // CHECK-MS-STATIC-DAG: declare {{.*}} void @_CxxThrowException
 // CHECK-MS-DAG: declare dso_local noalias i8* @"??2@YAPAXI@Z"
 // CHECK-MS-DAG: declare dso_local void @_Init_thread_header(i32*)
Index: CodeGen/ms-symbol-linkage.cpp
===
--- /dev/null
+++ CodeGen/ms-symbol-linkage.cpp
@@ -0,0 +1,20 @@
+// RUN: %clangxx -target aarch64-windows \
+// RUN: -fcxx-exceptions -c -o - %s \
+// RUN: | llvm-objdump -syms - 2>&1 | FileCheck %s
+
+void foo1() { throw 1; }
+// CHECK-LABEL: foo1
+// CHECK-NOT: __imp__CxxThrowException
+
+void bar();
+void foo2() noexcept(true) { bar(); }
+// CHECK-LABEL: foo2
+// CHECK-NOT: __imp___std_terminate
+
+struct A {};
+struct B { virtual void f(); };
+struct C : A, virtual B {};
+struct T {};
+T *foo3() { return dynamic_cast((C *)0); }
+// CHECK-LABEL: foo3
+// CHECK-NOT: __imp___RTDynamicCast
Index: CodeGen/CodeGenModule.cpp
===
--- CodeGen/CodeGenModule.cpp
+++ CodeGen/CodeGenModule.cpp
@@ -2954,7 +2954,8 @@
 
   if (!Local && getTriple().isOSBinFormatCOFF() &&
   !getCodeGenOpts().LTOVisibilityPublicStd &&
-  !getTriple().isWindowsGNUEnvironment()) {
+  !getTriple().isWindowsGNUEnvironment() &&
+  !getTriple().isWindowsMSVCEnvironment()) {
 const FunctionDecl *FD = GetRuntimeFunctionDecl(Context, Name);
 if (!FD || FD->hasAttr()) {
   F->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);


Index: CodeGenObjCXX/msabi-stret.mm
===
--- CodeGenObjCXX/msabi-stret.mm
+++ CodeGenObjCXX/msabi-stret.mm
@@ -13,6 +13,5 @@
   return [I m:S()];
 }
 
-// CHECK: declare dllimport void @objc_msgSend_stret(i8*, i8*, ...)
+// CHECK: declare dso_local void @objc_msgSend_stret(i8*, i8*, ...)
 // CHECK-NOT: declare dllimport void @objc_msgSend(i8*, i8*, ...)
-
Index: CodeGenObjC/gnu-init.m
===
--- CodeGenObjC/gnu-init.m
+++ CodeGenObjC/gnu-init.m
@@ -99,6 +99,6 @@
 // Check our load function is in a comdat.
 // CHECK-WIN: define linkonce_odr hidden void @.objcv2_load_function() comdat {
 
-// Make sure we have dllimport on the load function
-// CHECK-WIN: declare dllimport void @__objc_load
+// Make sure we do not have dllimport on the load function
+// CHECK-WIN: declare dso_local void @__objc_load
 
Index: CodeGenCXX/runtime-dllstorage.cpp
===
--- CodeGenCXX/runtime-dllstorage.cpp
+++ CodeGenCXX/runtime-dllstorage.cpp
@@ -108,7 +108,7 @@
 // CHECK-MS-DAG: @_Init_thread_epoch = external thread_local global i32
 // CHECK-MS-DAG: declare dso_local i32 @__tlregdtor(void ()*)
 // CHECK-MS-DAG: declare dso_local i32 @atexit(void ()*)
-// CHECK-MS-DYNAMIC-DAG: declare dllimport {{.*}} void @_CxxThrowException
+// CHECK-MS-DYNAMIC-DAG: declare {{.*}} void 

[PATCH] D55229: [COFF, ARM64] Make -flto-visibility-public-std a driver and cc1 flag

2018-12-03 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D55229#1317333 , @rnk wrote:

> I think @compnerd arranged things this way. I don't know why 
> -flto-visibility-public-std is involved, I have no idea what that does. I 
> think we should do what MSVC does here, which is to leave _CxxThrowException 
> unannotated and let the linker synthesize import thunks.
>
> Here is the code in question that applies dllimport: 
> https://github.com/llvm-git-prototype/llvm/blob/master/clang/lib/CodeGen/CodeGenModule.cpp#L2955
>
> My suggestion would be to make it check `isWindowsItaniumEnvironment` so we 
> can avoid this behavior which isn't desired under either mingw or MSVC.


Even with the isWindowsItaniumEnvironment check I see it generate 
__imp__CxxThrowException and break the unit test 
CodeGenCXX/runtime-dllstorage.cpp. However, with the isOSWindows check it 
generates __CxxThrowException but ends up breaking a few more unit tests.


Repository:
  rC Clang

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

https://reviews.llvm.org/D55229



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


[PATCH] D55229: [COFF, ARM64] Make -flto-visibility-public-std a driver and cc1 flag

2018-12-03 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

In D55229#1317232 , @pcc wrote:

> The reason why it has that name is that it was originally added to support 
> the logic here: 
> http://llvm-cs.pcc.me.uk/tools/clang/lib/CodeGen/CGVTables.cpp#991
>
> It looks like it was later repurposed as a "was /MT passed to the driver" 
> flag when the logic was added to mark runtime functions as dllimport 
> depending on the value of the flag.
>
> It certainly seems to make sense to rename it since the name makes no sense 
> as a driver flag and is now being used for other purposes.


How about calling it -fmsvc-static-link?


Repository:
  rC Clang

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

https://reviews.llvm.org/D55229



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


[PATCH] D55229: [COFF, ARM64] Make -flto-visibility-public-std a driver and cc1 flag

2018-12-03 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

I wonder why this flag is called -flto-visibility-public-std. It has nothing to 
do with -flto. While we are at it, does it make sense to rename this flag?


Repository:
  rC Clang

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

https://reviews.llvm.org/D55229



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


[PATCH] D55229: [COFF, ARM64] Make -flto-visibility-public-std a driver and cc1 flag

2018-12-03 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang created this revision.
mgrang added reviewers: rnk, mstorsjo, efriedma, TomTan.
Herald added subscribers: dexonsmith, kristof.beyls, inglorion, javed.absar, 
mehdi_amini.

Clang currently imports certain functions (like __imp__CxxThrowException) even 
when statically linking.
Whereas MSVC statically links them (like __CxxThrowException). In clang, 
function linkage is controlled via /MT 
flag which is a clang-cl flag. This flag gets expanded to 
-flto-visibility-public-std which is a -cc1 option.
So from clang driver there is no way to statically link these functions. This 
patch makes -flto-visibility-public-std a
 driver flag which can be used to control function linkage.


Repository:
  rC Clang

https://reviews.llvm.org/D55229

Files:
  CodeGen/arm64-microsoft-symbol-linkage.cpp
  Driver/ToolChains/Clang.cpp
  clang/Driver/CC1Options.td
  clang/Driver/Options.td


Index: CodeGen/arm64-microsoft-symbol-linkage.cpp
===
--- /dev/null
+++ CodeGen/arm64-microsoft-symbol-linkage.cpp
@@ -0,0 +1,29 @@
+// REQUIRES: aarch64-registered-target
+
+// RUN: %clangxx -target aarch64-windows \
+// RUN: -fcxx-exceptions -emit-obj -c -o - %s \
+// RUN: | llvm-objdump -syms - 2>&1 | FileCheck %s --check-prefix LINK-DYN
+
+// RUN: %clangxx -target aarch64-windows -flto-visibility-public-std \
+// RUN: -fcxx-exceptions -emit-obj -c -o - %s \
+// RUN: | llvm-objdump -syms - 2>&1 | FileCheck %s --check-prefix LINK-STAT
+
+void foo1() { throw 1; }
+// CHECK-LABEL: foo1
+// LINK-DYN: __imp__CxxThrowException
+// LINK-STAT-NOT: __imp__CxxThrowException
+
+void bar();
+void foo2() noexcept(true) { bar(); }
+// CHECK-LABEL: foo2
+// LINK-DYN: __imp___std_terminate
+// LINK-STAT-NOT: __imp___std_terminate
+
+struct A {};
+struct B { virtual void f(); };
+struct C : A, virtual B {};
+struct T {};
+T *foo3() { return dynamic_cast((C *)0); }
+// CHECK-LABEL: foo3
+// LINK-DYN: __imp___RTDynamicCast
+// LINK-STAT-NOT: __imp___RTDynamicCast
Index: Driver/ToolChains/Clang.cpp
===
--- Driver/ToolChains/Clang.cpp
+++ Driver/ToolChains/Clang.cpp
@@ -5210,6 +5210,9 @@
TC.useIntegratedAs()))
 CmdArgs.push_back("-faddrsig");
 
+  if (Args.hasArg(options::OPT_flto_visibility_public_std))
+CmdArgs.push_back("-flto-visibility-public-std");
+
   // Finally add the compile command to the compilation.
   if (Args.hasArg(options::OPT__SLASH_fallback) &&
   Output.getType() == types::TY_Object &&
Index: clang/Driver/Options.td
===
--- clang/Driver/Options.td
+++ clang/Driver/Options.td
@@ -825,6 +825,9 @@
 def fcreate_profile : Flag<["-"], "fcreate-profile">, Group;
 def fcxx_exceptions: Flag<["-"], "fcxx-exceptions">, Group,
   HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>;
+def flto_visibility_public_std:
+Flag<["-"], "flto-visibility-public-std">, Group, 
Flags<[CC1Option]>,
+HelpText<"Use public LTO visibility for classes in std and stdext 
namespaces">;
 def fcxx_modules : Flag <["-"], "fcxx-modules">, Group,
   Flags<[DriverOption]>;
 def fdebug_pass_arguments : Flag<["-"], "fdebug-pass-arguments">, 
Group;
Index: clang/Driver/CC1Options.td
===
--- clang/Driver/CC1Options.td
+++ clang/Driver/CC1Options.td
@@ -345,9 +345,6 @@
 def fprofile_instrument_use_path_EQ :
 Joined<["-"], "fprofile-instrument-use-path=">,
 HelpText<"Specify the profile path in PGO use compilation">;
-def flto_visibility_public_std:
-Flag<["-"], "flto-visibility-public-std">,
-HelpText<"Use public LTO visibility for classes in std and stdext 
namespaces">;
 def flto_unit: Flag<["-"], "flto-unit">,
 HelpText<"Emit IR to support LTO unit features (CFI, whole program vtable 
opt)">;
 def fno_lto_unit: Flag<["-"], "fno-lto-unit">;


Index: CodeGen/arm64-microsoft-symbol-linkage.cpp
===
--- /dev/null
+++ CodeGen/arm64-microsoft-symbol-linkage.cpp
@@ -0,0 +1,29 @@
+// REQUIRES: aarch64-registered-target
+
+// RUN: %clangxx -target aarch64-windows \
+// RUN: -fcxx-exceptions -emit-obj -c -o - %s \
+// RUN: | llvm-objdump -syms - 2>&1 | FileCheck %s --check-prefix LINK-DYN
+
+// RUN: %clangxx -target aarch64-windows -flto-visibility-public-std \
+// RUN: -fcxx-exceptions -emit-obj -c -o - %s \
+// RUN: | llvm-objdump -syms - 2>&1 | FileCheck %s --check-prefix LINK-STAT
+
+void foo1() { throw 1; }
+// CHECK-LABEL: foo1
+// LINK-DYN: __imp__CxxThrowException
+// LINK-STAT-NOT: __imp__CxxThrowException
+
+void bar();
+void foo2() noexcept(true) { bar(); }
+// CHECK-LABEL: foo2
+// LINK-DYN: __imp___std_terminate
+// LINK-STAT-NOT: __imp___std_terminate
+
+struct A {};
+struct B { virtual void f(); };
+struct C : A, virtual B {};
+struct T {};
+T *foo3() { return dynamic_cast((C *)0); }
+// 

[PATCH] D54816: [RISCV] Mark unit tests as "requires: riscv-registered-target"

2018-11-27 Thread Mandeep Singh Grang via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL347688: [RISCV] Mark unit tests as requires: 
riscv-registered-target (authored by mgrang, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D54816?vs=174988=175541#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D54816

Files:
  cfe/trunk/Driver/riscv-abi.c
  cfe/trunk/Driver/riscv-arch.c
  cfe/trunk/Driver/riscv-features.c
  cfe/trunk/Driver/riscv-gnutools.c
  cfe/trunk/Driver/riscv32-toolchain.c
  cfe/trunk/Driver/riscv64-toolchain.c
  cfe/trunk/test/Driver/riscv-abi.c
  cfe/trunk/test/Driver/riscv-arch.c
  cfe/trunk/test/Driver/riscv-features.c
  cfe/trunk/test/Driver/riscv-gnutools.c
  cfe/trunk/test/Driver/riscv32-toolchain.c
  cfe/trunk/test/Driver/riscv64-toolchain.c

Index: cfe/trunk/Driver/riscv-features.c
===
--- cfe/trunk/Driver/riscv-features.c
+++ cfe/trunk/Driver/riscv-features.c
@@ -0,0 +1,15 @@
+// REQUIRES: riscv-registered-target
+
+// RUN: %clang -target riscv32-unknown-elf -### %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -### %s -fsyntax-only 2>&1 | FileCheck %s
+
+// CHECK: fno-signed-char
+
+// RUN: %clang -target riscv32-unknown-elf -### %s -mrelax 2>&1 | FileCheck %s -check-prefix=RELAX
+// RUN: %clang -target riscv32-unknown-elf -### %s -mno-relax 2>&1 | FileCheck %s -check-prefix=NO-RELAX
+// RUN: %clang -target riscv32-unknown-elf -### %s 2>&1 | FileCheck %s -check-prefix=DEFAULT
+
+// RELAX: "-target-feature" "+relax"
+// NO-RELAX: "-target-feature" "-relax"
+// DEFAULT-NOT: "-target-feature" "+relax"
+// DEFAULT-NOT: "-target-feature" "-relax"
Index: cfe/trunk/Driver/riscv-arch.c
===
--- cfe/trunk/Driver/riscv-arch.c
+++ cfe/trunk/Driver/riscv-arch.c
@@ -0,0 +1,319 @@
+// REQUIRES: riscv-registered-target
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32i -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32im -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ima -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imaf -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imafd -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ic -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imac -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imafc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32imafdc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ia -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iaf -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iafd -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iac -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iafc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32iafdc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32g -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv32-unknown-elf -march=rv32gc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64i -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64im -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64ima -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imaf -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imafd -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+
+// RUN: %clang -target riscv64-unknown-elf -march=rv64ic -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imc -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang -target riscv64-unknown-elf -march=rv64imac -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang 

[PATCH] D54816: [RISCV] Mark unit tests as "requires: riscv-registered-target"

2018-11-27 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang added a comment.

Ping for reviews please.


Repository:
  rC Clang

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

https://reviews.llvm.org/D54816



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


[PATCH] D54816: [RISCV] Mark unit tests as "requires: riscv-registered-target"

2018-11-21 Thread Mandeep Singh Grang via Phabricator via cfe-commits
mgrang created this revision.
mgrang added reviewers: asb, apazos.
Herald added subscribers: jocewei, PkmX, rkruppe, the_o, brucehoult, 
MartinMosbeck, rogfer01, edward-jones, zzheng, jrtc27, shiva0217, kito-cheng, 
niosHD, sabuasal, simoncook, johnrusso, rbar.

Some of these tests break if the RISCV backend has not been built.


Repository:
  rC Clang

https://reviews.llvm.org/D54816

Files:
  Driver/riscv-abi.c
  Driver/riscv-arch.c
  Driver/riscv-features.c
  Driver/riscv-gnutools.c
  Driver/riscv32-toolchain.c
  Driver/riscv64-toolchain.c


Index: Driver/riscv64-toolchain.c
===
--- Driver/riscv64-toolchain.c
+++ Driver/riscv64-toolchain.c
@@ -1,3 +1,5 @@
+// REQUIRES: riscv-registered-target
+
 // A basic clang -cc1 command-line, and simple environment check.
 
 // RUN: %clang %s -### -no-canonical-prefixes -target riscv64 2>&1 | FileCheck 
-check-prefix=CC1 %s
Index: Driver/riscv32-toolchain.c
===
--- Driver/riscv32-toolchain.c
+++ Driver/riscv32-toolchain.c
@@ -1,3 +1,5 @@
+// REQUIRES: riscv-registered-target
+
 // A basic clang -cc1 command-line, and simple environment check.
 
 // RUN: %clang %s -### -no-canonical-prefixes -target riscv32 2>&1 | FileCheck 
-check-prefix=CC1 %s
Index: Driver/riscv-gnutools.c
===
--- Driver/riscv-gnutools.c
+++ Driver/riscv-gnutools.c
@@ -1,3 +1,5 @@
+// REQUIRES: riscv-registered-target
+
 // Check gnutools are invoked with propagated values for -mabi and -march.
 
 // RUN: %clang -target riscv32 -fno-integrated-as %s -###  -c \
Index: Driver/riscv-features.c
===
--- Driver/riscv-features.c
+++ Driver/riscv-features.c
@@ -1,3 +1,5 @@
+// REQUIRES: riscv-registered-target
+
 // RUN: %clang -target riscv32-unknown-elf -### %s -fsyntax-only 2>&1 | 
FileCheck %s
 // RUN: %clang -target riscv64-unknown-elf -### %s -fsyntax-only 2>&1 | 
FileCheck %s
 
Index: Driver/riscv-arch.c
===
--- Driver/riscv-arch.c
+++ Driver/riscv-arch.c
@@ -1,3 +1,5 @@
+// REQUIRES: riscv-registered-target
+
 // RUN: %clang -target riscv32-unknown-elf -march=rv32i -### %s \
 // RUN: -fsyntax-only 2>&1 | FileCheck %s
 // RUN: %clang -target riscv32-unknown-elf -march=rv32im -### %s \
Index: Driver/riscv-abi.c
===
--- Driver/riscv-abi.c
+++ Driver/riscv-abi.c
@@ -1,3 +1,5 @@
+// REQUIRES: riscv-registered-target
+
 // RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-ILP32 %s
 // RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o -mabi=ilp32 2>&1 \


Index: Driver/riscv64-toolchain.c
===
--- Driver/riscv64-toolchain.c
+++ Driver/riscv64-toolchain.c
@@ -1,3 +1,5 @@
+// REQUIRES: riscv-registered-target
+
 // A basic clang -cc1 command-line, and simple environment check.
 
 // RUN: %clang %s -### -no-canonical-prefixes -target riscv64 2>&1 | FileCheck -check-prefix=CC1 %s
Index: Driver/riscv32-toolchain.c
===
--- Driver/riscv32-toolchain.c
+++ Driver/riscv32-toolchain.c
@@ -1,3 +1,5 @@
+// REQUIRES: riscv-registered-target
+
 // A basic clang -cc1 command-line, and simple environment check.
 
 // RUN: %clang %s -### -no-canonical-prefixes -target riscv32 2>&1 | FileCheck -check-prefix=CC1 %s
Index: Driver/riscv-gnutools.c
===
--- Driver/riscv-gnutools.c
+++ Driver/riscv-gnutools.c
@@ -1,3 +1,5 @@
+// REQUIRES: riscv-registered-target
+
 // Check gnutools are invoked with propagated values for -mabi and -march.
 
 // RUN: %clang -target riscv32 -fno-integrated-as %s -###  -c \
Index: Driver/riscv-features.c
===
--- Driver/riscv-features.c
+++ Driver/riscv-features.c
@@ -1,3 +1,5 @@
+// REQUIRES: riscv-registered-target
+
 // RUN: %clang -target riscv32-unknown-elf -### %s -fsyntax-only 2>&1 | FileCheck %s
 // RUN: %clang -target riscv64-unknown-elf -### %s -fsyntax-only 2>&1 | FileCheck %s
 
Index: Driver/riscv-arch.c
===
--- Driver/riscv-arch.c
+++ Driver/riscv-arch.c
@@ -1,3 +1,5 @@
+// REQUIRES: riscv-registered-target
+
 // RUN: %clang -target riscv32-unknown-elf -march=rv32i -### %s \
 // RUN: -fsyntax-only 2>&1 | FileCheck %s
 // RUN: %clang -target riscv32-unknown-elf -march=rv32im -### %s \
Index: Driver/riscv-abi.c
===
--- Driver/riscv-abi.c
+++ Driver/riscv-abi.c
@@ -1,3 +1,5 @@
+// REQUIRES: riscv-registered-target
+
 // RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o 

  1   2   3   4   >