[PATCH] D57476: [CodeGenObjC] Use an invoke instead of a call when calling `objc_alloc` or `objc_allocWithZone`

2019-01-30 Thread Pete Cooper via Phabricator via cfe-commits
pete accepted this revision.
pete added a comment.
This revision is now accepted and ready to land.

LGTM.  Thanks for fixing this!


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

https://reviews.llvm.org/D57476



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


[PATCH] D55349: Convert some ObjC alloc msgSends to runtime calls

2018-12-05 Thread Pete Cooper via Phabricator via cfe-commits
pete created this revision.
pete added reviewers: ahatanak, rjmccall, erik.pilkington.
Herald added a subscriber: cfe-commits.

It is faster to directly call the ObjC runtime for methods such as 
alloc/allocWithZone instead of sending a message to those functions.

This patch adds support for converting messages to alloc/allocWithZone to their 
equivalent runtime calls.

Tests included for the positive case of applying this transformation, negative 
tests that we ensure we only convert "alloc" to objc_alloc, not "alloc2", and 
also a driver test to ensure we enable this only for supported runtime versions.


Repository:
  rC Clang

https://reviews.llvm.org/D55349

Files:
  include/clang/Basic/ObjCRuntime.h
  include/clang/Driver/Options.td
  include/clang/Frontend/CodeGenOptions.def
  lib/CodeGen/CGObjC.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/CodeGen/CodeGenModule.h
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGenObjC/convert-messages-to-runtime-calls.m
  test/Driver/objc-convert-messages-to-runtime-calls.m

Index: test/Driver/objc-convert-messages-to-runtime-calls.m
===
--- /dev/null
+++ test/Driver/objc-convert-messages-to-runtime-calls.m
@@ -0,0 +1,7 @@
+// RUN: %clang %s -### -o %t.o 2>&1 -fsyntax-only -fobjc-convert-messages-to-runtime-calls -fno-objc-convert-messages-to-runtime-calls -target x86_64-apple-macosx10.10.0 | FileCheck  %s --check-prefix=DISABLE
+// RUN: %clang %s -### -o %t.o 2>&1 -fsyntax-only -fno-objc-convert-messages-to-runtime-calls -fobjc-convert-messages-to-runtime-calls -target x86_64-apple-macosx10.10.0 | FileCheck  %s --check-prefix=ENABLE
+
+// Check that we pass fobjc-convert-messages-to-runtime-calls only when supported, and not explicitly disabled.
+
+// DISABLE: "-fno-objc-convert-messages-to-runtime-calls"
+// ENABLE-NOT: "-fno-objc-convert-messages-to-runtime-calls"
Index: test/CodeGenObjC/convert-messages-to-runtime-calls.m
===
--- /dev/null
+++ test/CodeGenObjC/convert-messages-to-runtime-calls.m
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fno-objc-convert-messages-to-runtime-calls | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.9.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-fragile-10.10.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=ios-8.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=ios-7.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// Note: This line below is for tvos for which the driver passes through to use the ios9.0 runtime.
+// RUN: %clang_cc1 -fobjc-runtime=ios-9.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=watchos-2.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+
+#define nil (id)0
+
+@interface NSObject
++ (id)alloc;
++ (id)allocWithZone:(void*)zone;
++ (id)alloc2;
+@end
+
+// CHECK-LABEL: define {{.*}}void @test1
+void test1(id x) {
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_alloc}}
+  [NSObject alloc];
+  [NSObject allocWithZone:nil];
+}
+
+// CHECK-LABEL: define {{.*}}void @test2
+void test2(void* x) {
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  [NSObject alloc2];
+  [NSObject allocWithZone:(void*)-1];
+  [NSObject allocWithZone:x];
+}
+
+@class A;
+@interface B
++ (A*) alloc;
++ (A*)allocWithZone:(void*)zone;
+@end
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
+A* test_alloc_class_ptr() {
+  // CALLS: {{call.*@objc_alloc}}
+  // CALLS-NEXT: bitcast i8*
+  // CALLS-NEXT: ret
+  return [B alloc];
+}
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
+A* test_allocWithZone_class_ptr() {
+  // CALLS: {{call.*@objc_alloc}}
+  // CALLS-NEXT: bitcast i8*
+  // CALLS-NEXT: ret
+  return [B allocWithZone:nil];
+}
+
+
Index: lib/Frontend/CompilerInvocation.cpp
===
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1155,6 +1155,10 @@
 }
   }
 
+
+  if (Args.hasArg(OPT_fno_objc_convert_messages_to_runtime_calls))
+Opts.ObjCConvertMessagesToRuntimeCalls = 0;
+
   if (Args.getLastArg(OPT_femulated_tls) ||
   Args.getLastArg(OPT_fno_emulated_tls)) {
 Opts.ExplicitEmulatedTLS =

[PATCH] D55349: Convert some ObjC alloc msgSends to runtime calls

2018-12-07 Thread Pete Cooper via Phabricator via cfe-commits
pete updated this revision to Diff 177246.
pete added a comment.

Thanks for the review.  Have fixed the comments as suggested.


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

https://reviews.llvm.org/D55349

Files:
  include/clang/Basic/ObjCRuntime.h
  include/clang/Driver/Options.td
  include/clang/Frontend/CodeGenOptions.def
  lib/CodeGen/CGObjC.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/CodeGen/CodeGenModule.h
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGenObjC/convert-messages-to-runtime-calls.m
  test/Driver/objc-convert-messages-to-runtime-calls.m

Index: test/Driver/objc-convert-messages-to-runtime-calls.m
===
--- /dev/null
+++ test/Driver/objc-convert-messages-to-runtime-calls.m
@@ -0,0 +1,7 @@
+// RUN: %clang %s -### -o %t.o 2>&1 -fsyntax-only -fobjc-convert-messages-to-runtime-calls -fno-objc-convert-messages-to-runtime-calls -target x86_64-apple-macosx10.10.0 | FileCheck  %s --check-prefix=DISABLE
+// RUN: %clang %s -### -o %t.o 2>&1 -fsyntax-only -fno-objc-convert-messages-to-runtime-calls -fobjc-convert-messages-to-runtime-calls -target x86_64-apple-macosx10.10.0 | FileCheck  %s --check-prefix=ENABLE
+
+// Check that we pass fobjc-convert-messages-to-runtime-calls only when supported, and not explicitly disabled.
+
+// DISABLE: "-fno-objc-convert-messages-to-runtime-calls"
+// ENABLE-NOT: "-fno-objc-convert-messages-to-runtime-calls"
Index: test/CodeGenObjC/convert-messages-to-runtime-calls.m
===
--- /dev/null
+++ test/CodeGenObjC/convert-messages-to-runtime-calls.m
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fno-objc-convert-messages-to-runtime-calls | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.9.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-fragile-10.10.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=ios-8.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=ios-7.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// Note: This line below is for tvos for which the driver passes through to use the ios9.0 runtime.
+// RUN: %clang_cc1 -fobjc-runtime=ios-9.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=watchos-2.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+
+#define nil (id)0
+
+@interface NSObject
++ (id)alloc;
++ (id)allocWithZone:(void*)zone;
++ (id)alloc2;
+@end
+
+// CHECK-LABEL: define {{.*}}void @test1
+void test1(id x) {
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_alloc}}
+  [NSObject alloc];
+  [NSObject allocWithZone:nil];
+}
+
+// CHECK-LABEL: define {{.*}}void @test2
+void test2(void* x) {
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  [NSObject alloc2];
+  [NSObject allocWithZone:(void*)-1];
+  [NSObject allocWithZone:x];
+}
+
+@class A;
+@interface B
++ (A*) alloc;
++ (A*)allocWithZone:(void*)zone;
+@end
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
+A* test_alloc_class_ptr() {
+  // CALLS: {{call.*@objc_alloc}}
+  // CALLS-NEXT: bitcast i8*
+  // CALLS-NEXT: ret
+  return [B alloc];
+}
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
+A* test_allocWithZone_class_ptr() {
+  // CALLS: {{call.*@objc_alloc}}
+  // CALLS-NEXT: bitcast i8*
+  // CALLS-NEXT: ret
+  return [B allocWithZone:nil];
+}
+
+
Index: lib/Frontend/CompilerInvocation.cpp
===
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1155,6 +1155,10 @@
 }
   }
 
+
+  if (Args.hasArg(OPT_fno_objc_convert_messages_to_runtime_calls))
+Opts.ObjCConvertMessagesToRuntimeCalls = 0;
+
   if (Args.getLastArg(OPT_femulated_tls) ||
   Args.getLastArg(OPT_fno_emulated_tls)) {
 Opts.ExplicitEmulatedTLS = true;
Index: lib/Driver/ToolChains/Clang.cpp
===
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -2864,6 +2864,18 @@
 Args.ClaimAllArgs(options::OPT_fno_objc_arc_exceptions);
   }
 
+  // Allow the user to control whether messages can be converted to runtime
+  // functions.
+  if (types::isObjC(Input.getType())) {
+auto *Arg = Args.getLastAr

[PATCH] D55349: Convert some ObjC alloc msgSends to runtime calls

2018-12-07 Thread Pete Cooper via Phabricator via cfe-commits
pete marked 5 inline comments as done.
pete added inline comments.



Comment at: include/clang/Basic/ObjCRuntime.h:200
+case WatchOS:
+  return true;
+

rjmccall wrote:
> Did we really add this so long ago?  Wow.
Yeah!  I was thinking that too!


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

https://reviews.llvm.org/D55349



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


[PATCH] D55349: Convert some ObjC alloc msgSends to runtime calls

2018-12-07 Thread Pete Cooper via Phabricator via cfe-commits
pete updated this revision to Diff 177308.
pete marked an inline comment as done.
pete added a comment.

Added test for integer argument and updated code to only accept pointer types 
to allocWithZone.


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

https://reviews.llvm.org/D55349

Files:
  include/clang/Basic/ObjCRuntime.h
  include/clang/Driver/Options.td
  include/clang/Frontend/CodeGenOptions.def
  lib/CodeGen/CGObjC.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/CodeGen/CodeGenModule.h
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGenObjC/convert-messages-to-runtime-calls.m
  test/Driver/objc-convert-messages-to-runtime-calls.m

Index: test/Driver/objc-convert-messages-to-runtime-calls.m
===
--- /dev/null
+++ test/Driver/objc-convert-messages-to-runtime-calls.m
@@ -0,0 +1,7 @@
+// RUN: %clang %s -### -o %t.o 2>&1 -fsyntax-only -fobjc-convert-messages-to-runtime-calls -fno-objc-convert-messages-to-runtime-calls -target x86_64-apple-macosx10.10.0 | FileCheck  %s --check-prefix=DISABLE
+// RUN: %clang %s -### -o %t.o 2>&1 -fsyntax-only -fno-objc-convert-messages-to-runtime-calls -fobjc-convert-messages-to-runtime-calls -target x86_64-apple-macosx10.10.0 | FileCheck  %s --check-prefix=ENABLE
+
+// Check that we pass fobjc-convert-messages-to-runtime-calls only when supported, and not explicitly disabled.
+
+// DISABLE: "-fno-objc-convert-messages-to-runtime-calls"
+// ENABLE-NOT: "-fno-objc-convert-messages-to-runtime-calls"
Index: test/CodeGenObjC/convert-messages-to-runtime-calls.m
===
--- /dev/null
+++ test/CodeGenObjC/convert-messages-to-runtime-calls.m
@@ -0,0 +1,80 @@
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fno-objc-convert-messages-to-runtime-calls | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-10.9.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=macosx-fragile-10.10.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// RUN: %clang_cc1 -fobjc-runtime=ios-8.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=ios-7.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS
+// Note: This line below is for tvos for which the driver passes through to use the ios9.0 runtime.
+// RUN: %clang_cc1 -fobjc-runtime=ios-9.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+// RUN: %clang_cc1 -fobjc-runtime=watchos-2.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS
+
+#define nil (id)0
+
+@interface NSObject
++ (id)alloc;
++ (id)allocWithZone:(void*)zone;
++ (id)alloc2;
+@end
+
+// CHECK-LABEL: define {{.*}}void @test1
+void test1(id x) {
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_alloc}}
+  // CALLS: {{call.*@objc_allocWithZone}}
+  [NSObject alloc];
+  [NSObject allocWithZone:nil];
+}
+
+// CHECK-LABEL: define {{.*}}void @test2
+void test2(void* x) {
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  [NSObject alloc2];
+  [NSObject allocWithZone:(void*)-1];
+  [NSObject allocWithZone:x];
+}
+
+@class A;
+@interface B
++ (A*) alloc;
++ (A*)allocWithZone:(void*)zone;
+@end
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
+A* test_alloc_class_ptr() {
+  // CALLS: {{call.*@objc_alloc}}
+  // CALLS-NEXT: bitcast i8*
+  // CALLS-NEXT: ret
+  return [B alloc];
+}
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_alloc_class_ptr
+A* test_allocWithZone_class_ptr() {
+  // CALLS: {{call.*@objc_allocWithZone}}
+  // CALLS-NEXT: bitcast i8*
+  // CALLS-NEXT: ret
+  return [B allocWithZone:nil];
+}
+
+
+@interface C
++ (id)allocWithZone:(int)intArg;
+@end
+
+// Make sure we only accept pointer types
+// CHECK-LABEL: define {{.*}}void @test_allocWithZone_int
+C* test_allocWithZone_int() {
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  return [C allocWithZone:3];
+}
+
Index: lib/Frontend/CompilerInvocation.cpp
===
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1155,6 +1155,10 @@
 }
   }
 
+
+  if (Args.hasArg(OPT_fno_objc_convert_messages_to_runtime_calls))
+Opts.ObjCConvertMessagesToRuntimeCalls = 0;
+
   if (Args.getLastArg(OPT_femulated_tls) ||
   Args.getLastArg(OPT_fno_emulated_tls)) {
 Opts.Explic

[PATCH] D55349: Convert some ObjC alloc msgSends to runtime calls

2018-12-07 Thread Pete Cooper via Phabricator via cfe-commits
pete added a comment.

In D55349#1323926 , @rjmccall wrote:

> LGTM.


Thanks for the review!  Landed in r348687.


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

https://reviews.llvm.org/D55349



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


[PATCH] D55802: Change CGObjC to use objc intrinsics instead of runtime methods

2018-12-17 Thread Pete Cooper via Phabricator via cfe-commits
pete added a comment.

In D55802#1334008 , @rjmccall wrote:

> You're making intrinsics with `weak_external` linkage?  I feel like that's 
> going to be unnecessarily awkward in the future, but okay.


Yeah... i was a little surprised that was possible, but seems to work just fine.

Thanks for the quick review!  Will land it first thing tomorrow.


Repository:
  rC Clang

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

https://reviews.llvm.org/D55802



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


[PATCH] D55869: Convert some ObjC retain/release msgSends to runtime calls

2018-12-18 Thread Pete Cooper via Phabricator via cfe-commits
pete created this revision.
pete added reviewers: rjmccall, ahatanak, erik.pilkington.
Herald added a subscriber: cfe-commits.

It is faster to directly call the ObjC runtime for methods such as 
retain/release instead of sending a message to those functions.

This is an extension of the work we already do to convert alloc message sends 
to objc_alloc calls.


Repository:
  rC Clang

https://reviews.llvm.org/D55869

Files:
  include/clang/Basic/ObjCRuntime.h
  lib/CodeGen/CGObjC.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/CodeGen/CodeGenModule.h
  test/CodeGenObjC/convert-messages-to-runtime-calls.m

Index: test/CodeGenObjC/convert-messages-to-runtime-calls.m
===
--- test/CodeGenObjC/convert-messages-to-runtime-calls.m
+++ test/CodeGenObjC/convert-messages-to-runtime-calls.m
@@ -14,16 +14,28 @@
 + (id)alloc;
 + (id)allocWithZone:(void*)zone;
 + (id)alloc2;
+- (id)retain;
+- (void)release;
+- (id)autorelease;
 @end
 
 // CHECK-LABEL: define {{.*}}void @test1
 void test1(id x) {
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
   // MSGS: {{call.*@objc_msgSend}}
   // MSGS: {{call.*@objc_msgSend}}
   // CALLS: {{call.*@objc_alloc}}
   // CALLS: {{call.*@objc_allocWithZone}}
+  // CALLS: {{call.*@objc_retain}}
+  // CALLS: {{call.*@objc_release}}
+  // CALLS: {{call.*@objc_autorelease}}
   [NSObject alloc];
   [NSObject allocWithZone:nil];
+  [x retain];
+  [x release];
+  [x autorelease];
 }
 
 // CHECK-LABEL: define {{.*}}void @test2
@@ -43,6 +55,8 @@
 @interface B
 + (A*) alloc;
 + (A*)allocWithZone:(void*)zone;
+- (A*) retain;
+- (A*) autorelease;
 @end
 
 // Make sure we get a bitcast on the return type as the
@@ -65,9 +79,30 @@
   return [B allocWithZone:nil];
 }
 
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_retain_class_ptr
+A* test_retain_class_ptr(B *b) {
+  // CALLS: {{call.*@objc_retain}}
+  // CALLS-NEXT: bitcast i8*
+  // CALLS-NEXT: ret
+  return [b retain];
+}
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_autorelease_class_ptr
+A* test_autorelease_class_ptr(B *b) {
+  // CALLS: {{call.*@objc_autorelease}}
+  // CALLS-NEXT: bitcast i8*
+  // CALLS-NEXT: ret
+  return [b autorelease];
+}
+
 
 @interface C
 + (id)allocWithZone:(int)intArg;
+- (float) retain;
 @end
 
 // Make sure we only accept pointer types
@@ -78,3 +113,37 @@
   return [C allocWithZone:3];
 }
 
+// Make sure we use a message and not a call as the return type is
+// not a pointer type.
+// CHECK-LABEL: define {{.*}}void @test_cannot_message_return_float
+float test_cannot_message_return_float(C *c) {
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  return [c retain];
+}
+
+@interface NSString : NSObject
++ (void)retain_self;
+- (void)retain_super;
+@end
+
+@implementation NSString
+
+// Make sure we can convert a message to a dynamic receiver to a call
+// CHECK-LABEL: define {{.*}}void @retain_self
++ (void)retain_self {
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_retain}}
+  [self retain];
+}
+
+// Make sure we never convert a message to super to a call
+// CHECK-LABEL: define {{.*}}void @retain_super
+- (void)retain_super {
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  [super retain];
+}
+
+@end
+
Index: lib/CodeGen/CodeGenModule.h
===
--- lib/CodeGen/CodeGenModule.h
+++ lib/CodeGen/CodeGenModule.h
@@ -138,6 +138,10 @@
   /// id objc_autorelease(id);
   llvm::Constant *objc_autorelease;
 
+  /// id objc_autorelease(id);
+  /// Note this is the runtime method not the intrinsic
+  llvm::Constant *objc_autoreleaseRuntimeFunction;
+
   /// id objc_autoreleaseReturnValue(id);
   llvm::Constant *objc_autoreleaseReturnValue;
 
@@ -162,6 +166,10 @@
   /// id objc_retain(id);
   llvm::Constant *objc_retain;
 
+  /// id objc_retain(id);
+  /// Note this is the runtime method not the intrinsic
+  llvm::Constant *objc_retainRuntimeFunction;
+
   /// id objc_retainAutorelease(id);
   llvm::Constant *objc_retainAutorelease;
 
@@ -177,6 +185,10 @@
   /// void objc_release(id);
   llvm::Constant *objc_release;
 
+  /// void objc_release(id);
+  /// Note this is the runtime method not the intrinsic
+  llvm::Constant *objc_releaseRuntimeFunction;
+
   /// void objc_storeStrong(id*, id);
   llvm::Constant *objc_storeStrong;
 
Index: lib/CodeGen/CodeGenFunction.h
===
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -3798,6 +3798,11 @@
   llvm::Value *EmitARCRetainAutoreleasedReturnValue(llvm::Value *value);
   llvm::Value *EmitARCUnsafeClaimAutoreleasedReturnValue(llvm::Value *value);
 
+  llvm::

[PATCH] D55869: Convert some ObjC retain/release msgSends to runtime calls

2018-12-19 Thread Pete Cooper via Phabricator via cfe-commits
pete marked 3 inline comments as done.
pete added a comment.

In D55869#1335783 , @rjmccall wrote:

> So, once upon a time this was a problem because we were rewriting the method 
> calls in the runtime itself.  Can you explain how that's not a problem now?  
> Do we just expect the runtime to be compiled with the right switch?


Ah yeah, good point.

In the patch for rewriting objc_alloc messages (r348687) I added a new option 
(-fno-objc-convert-messages-to-runtime-calls) which the objc runtime will need 
to adopt.


Repository:
  rC Clang

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

https://reviews.llvm.org/D55869



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


[PATCH] D55869: Convert some ObjC retain/release msgSends to runtime calls

2018-12-19 Thread Pete Cooper via Phabricator via cfe-commits
pete updated this revision to Diff 179017.

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

https://reviews.llvm.org/D55869

Files:
  include/clang/Basic/ObjCRuntime.h
  lib/CodeGen/CGObjC.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/CodeGen/CodeGenModule.h
  test/CodeGenObjC/convert-messages-to-runtime-calls.m

Index: test/CodeGenObjC/convert-messages-to-runtime-calls.m
===
--- test/CodeGenObjC/convert-messages-to-runtime-calls.m
+++ test/CodeGenObjC/convert-messages-to-runtime-calls.m
@@ -14,16 +14,28 @@
 + (id)alloc;
 + (id)allocWithZone:(void*)zone;
 + (id)alloc2;
+- (id)retain;
+- (void)release;
+- (id)autorelease;
 @end
 
 // CHECK-LABEL: define {{.*}}void @test1
 void test1(id x) {
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
+  // MSGS: {{call.*@objc_msgSend}}
   // MSGS: {{call.*@objc_msgSend}}
   // MSGS: {{call.*@objc_msgSend}}
   // CALLS: {{call.*@objc_alloc}}
   // CALLS: {{call.*@objc_allocWithZone}}
+  // CALLS: {{call.*@objc_retain}}
+  // CALLS: {{call.*@objc_release}}
+  // CALLS: {{call.*@objc_autorelease}}
   [NSObject alloc];
   [NSObject allocWithZone:nil];
+  [x retain];
+  [x release];
+  [x autorelease];
 }
 
 // CHECK-LABEL: define {{.*}}void @test2
@@ -43,6 +55,8 @@
 @interface B
 + (A*) alloc;
 + (A*)allocWithZone:(void*)zone;
+- (A*) retain;
+- (A*) autorelease;
 @end
 
 // Make sure we get a bitcast on the return type as the
@@ -65,9 +79,30 @@
   return [B allocWithZone:nil];
 }
 
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_retain_class_ptr
+A* test_retain_class_ptr(B *b) {
+  // CALLS: {{call.*@objc_retain}}
+  // CALLS-NEXT: bitcast i8*
+  // CALLS-NEXT: ret
+  return [b retain];
+}
+
+// Make sure we get a bitcast on the return type as the
+// call will return i8* which we have to cast to A*
+// CHECK-LABEL: define {{.*}}void @test_autorelease_class_ptr
+A* test_autorelease_class_ptr(B *b) {
+  // CALLS: {{call.*@objc_autorelease}}
+  // CALLS-NEXT: bitcast i8*
+  // CALLS-NEXT: ret
+  return [b autorelease];
+}
+
 
 @interface C
 + (id)allocWithZone:(int)intArg;
+- (float) retain;
 @end
 
 // Make sure we only accept pointer types
@@ -78,3 +113,37 @@
   return [C allocWithZone:3];
 }
 
+// Make sure we use a message and not a call as the return type is
+// not a pointer type.
+// CHECK-LABEL: define {{.*}}void @test_cannot_message_return_float
+float test_cannot_message_return_float(C *c) {
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  return [c retain];
+}
+
+@interface NSString : NSObject
++ (void)retain_self;
+- (void)retain_super;
+@end
+
+@implementation NSString
+
+// Make sure we can convert a message to a dynamic receiver to a call
+// CHECK-LABEL: define {{.*}}void @retain_self
++ (void)retain_self {
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_retain}}
+  [self retain];
+}
+
+// Make sure we never convert a message to super to a call
+// CHECK-LABEL: define {{.*}}void @retain_super
+- (void)retain_super {
+  // MSGS: {{call.*@objc_msgSend}}
+  // CALLS: {{call.*@objc_msgSend}}
+  [super retain];
+}
+
+@end
+
Index: lib/CodeGen/CodeGenModule.h
===
--- lib/CodeGen/CodeGenModule.h
+++ lib/CodeGen/CodeGenModule.h
@@ -138,6 +138,10 @@
   /// id objc_autorelease(id);
   llvm::Constant *objc_autorelease;
 
+  /// id objc_autorelease(id);
+  /// Note this is the runtime method not the intrinsic.
+  llvm::Constant *objc_autoreleaseRuntimeFunction;
+
   /// id objc_autoreleaseReturnValue(id);
   llvm::Constant *objc_autoreleaseReturnValue;
 
@@ -162,6 +166,10 @@
   /// id objc_retain(id);
   llvm::Constant *objc_retain;
 
+  /// id objc_retain(id);
+  /// Note this is the runtime method not the intrinsic.
+  llvm::Constant *objc_retainRuntimeFunction;
+
   /// id objc_retainAutorelease(id);
   llvm::Constant *objc_retainAutorelease;
 
@@ -177,6 +185,10 @@
   /// void objc_release(id);
   llvm::Constant *objc_release;
 
+  /// void objc_release(id);
+  /// Note this is the runtime method not the intrinsic.
+  llvm::Constant *objc_releaseRuntimeFunction;
+
   /// void objc_storeStrong(id*, id);
   llvm::Constant *objc_storeStrong;
 
Index: lib/CodeGen/CodeGenFunction.h
===
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -3798,6 +3798,11 @@
   llvm::Value *EmitARCRetainAutoreleasedReturnValue(llvm::Value *value);
   llvm::Value *EmitARCUnsafeClaimAutoreleasedReturnValue(llvm::Value *value);
 
+  llvm::Value *EmitObjCAutorelease(llvm::Value *value, llvm::Type *returnType);
+  llvm::Value *EmitObjCRetainNonBlock(llvm::Value *value,
+  llvm::Type *returnType);
+  void EmitObjCRelease(llvm::Value *value, ARCPreciseLifetime_t precise);
+
  

[PATCH] D55869: Convert some ObjC retain/release msgSends to runtime calls

2018-12-20 Thread Pete Cooper via Phabricator via cfe-commits
pete added a comment.

In D55869#1337723 , @js wrote:

> In D55869#1337711 , @dexonsmith 
> wrote:
>
> > In D55869#1337706 , @js wrote:
> >
> > > The ObjFW runtime itself does not contain anything about release, retain 
> > > or autorelease - these are all part of ObjFW (as in the framework). As 
> > > ObjFW also supports the Apple runtime, as well as mixing with Foundation 
> > > code, it so far only provides objc_retain and objc_release when they are 
> > > missing, to make ARC work. They just call into the corresponding methods 
> > > on the object and do nothing else.
> > >
> > > How will this change work from the Apple runtime? Will 
> > > objc_retain/objc_release call the retain/release on the object if it 
> > > implements its own? Should I drop my own retain/release implementation 
> > > from my root object if I am compiling against the Apple runtime?
> >
> >
> > Yes, the idea is that the specialized runtime functions are fast paths for 
> > the common case, but they still fall back if the object has overridden them.
>
>
> I am guessing not just overridden, but also a root class providing one? IOW, 
> the fast path is used when the class does not have the retain or release 
> method at all? In that case, LGTM as is.


The Apple runtime is using a bit on each realized class to track the 
overriding.  The root class defaults to not having a custom RR, ie, it appears 
that its version of RR is considered equivalent to objc_retain.

Presumably that would apply to other root classes too, although i'm not 100% 
sure.  I did see some special handling of NSObject in there too so perhaps only 
its RR is equivalent to objc_retain/objc_release.


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

https://reviews.llvm.org/D55869



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


[PATCH] D55869: Convert some ObjC retain/release msgSends to runtime calls

2018-12-21 Thread Pete Cooper via Phabricator via cfe-commits
pete added a comment.

Thanks for all the feedback so far.  Is there anything else you'd like me to 
change before I can land this?


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

https://reviews.llvm.org/D55869



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


[PATCH] D55869: Convert some ObjC retain/release msgSends to runtime calls

2018-12-21 Thread Pete Cooper via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC349952: Convert some ObjC retain/release msgSends to runtime 
calls. (authored by pete, committed by ).

Repository:
  rC Clang

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

https://reviews.llvm.org/D55869

Files:
  include/clang/Basic/ObjCRuntime.h
  lib/CodeGen/CGObjC.cpp
  lib/CodeGen/CodeGenFunction.h
  lib/CodeGen/CodeGenModule.h
  test/CodeGenObjC/convert-messages-to-runtime-calls.m

Index: lib/CodeGen/CGObjC.cpp
===
--- lib/CodeGen/CGObjC.cpp
+++ lib/CodeGen/CGObjC.cpp
@@ -396,6 +396,29 @@
 }
 break;
 
+  case OMF_autorelease:
+if (ResultType->isObjCObjectPointerType() &&
+CGM.getLangOpts().getGC() == LangOptions::NonGC &&
+Runtime.shouldUseARCFunctionsForRetainRelease())
+  return CGF.EmitObjCAutorelease(Receiver, CGF.ConvertType(ResultType));
+break;
+
+  case OMF_retain:
+if (ResultType->isObjCObjectPointerType() &&
+CGM.getLangOpts().getGC() == LangOptions::NonGC &&
+Runtime.shouldUseARCFunctionsForRetainRelease())
+  return CGF.EmitObjCRetainNonBlock(Receiver, CGF.ConvertType(ResultType));
+break;
+
+  case OMF_release:
+if (ResultType->isVoidType() &&
+CGM.getLangOpts().getGC() == LangOptions::NonGC &&
+Runtime.shouldUseARCFunctionsForRetainRelease()) {
+  CGF.EmitObjCRelease(Receiver, ARCPreciseLifetime);
+  return nullptr;
+}
+break;
+
   default:
 break;
   }
@@ -2006,6 +2029,11 @@
 llvm::FunctionType *fnType =
   llvm::FunctionType::get(CGF.Int8PtrTy, CGF.Int8PtrTy, false);
 fn = CGF.CGM.CreateRuntimeFunction(fnType, fnName);
+
+// We have Native ARC, so set nonlazybind attribute for performance
+if (llvm::Function *f = dyn_cast(fn))
+  if (fnName == "objc_retain")
+f->addFnAttr(llvm::Attribute::NonLazyBind);
   }
 
   // Cast the argument to 'id'.
@@ -2510,6 +2538,55 @@
   CGF.EmitARCIntrinsicUse(value);
 }
 
+/// Autorelease the given object.
+///   call i8* \@objc_autorelease(i8* %value)
+llvm::Value *CodeGenFunction::EmitObjCAutorelease(llvm::Value *value,
+  llvm::Type *returnType) {
+  return emitObjCValueOperation(*this, value, returnType,
+  CGM.getObjCEntrypoints().objc_autoreleaseRuntimeFunction,
+"objc_autorelease");
+}
+
+/// Retain the given object, with normal retain semantics.
+///   call i8* \@objc_retain(i8* %value)
+llvm::Value *CodeGenFunction::EmitObjCRetainNonBlock(llvm::Value *value,
+ llvm::Type *returnType) {
+  return emitObjCValueOperation(*this, value, returnType,
+  CGM.getObjCEntrypoints().objc_retainRuntimeFunction,
+"objc_retain");
+}
+
+/// Release the given object.
+///   call void \@objc_release(i8* %value)
+void CodeGenFunction::EmitObjCRelease(llvm::Value *value,
+  ARCPreciseLifetime_t precise) {
+  if (isa(value)) return;
+
+  llvm::Constant *&fn = CGM.getObjCEntrypoints().objc_release;
+  if (!fn) {
+if (!fn) {
+  llvm::FunctionType *fnType =
+llvm::FunctionType::get(Builder.getVoidTy(), Int8PtrTy, false);
+  fn = CGM.CreateRuntimeFunction(fnType, "objc_release");
+  setARCRuntimeFunctionLinkage(CGM, fn);
+  // We have Native ARC, so set nonlazybind attribute for performance
+  if (llvm::Function *f = dyn_cast(fn))
+f->addFnAttr(llvm::Attribute::NonLazyBind);
+}
+  }
+
+  // Cast the argument to 'id'.
+  value = Builder.CreateBitCast(value, Int8PtrTy);
+
+  // Call objc_release.
+  llvm::CallInst *call = EmitNounwindRuntimeCall(fn, value);
+
+  if (precise == ARCImpreciseLifetime) {
+call->setMetadata("clang.imprecise_release",
+  llvm::MDNode::get(Builder.getContext(), None));
+  }
+}
+
 namespace {
   struct CallObjCAutoreleasePoolObject final : EHScopeStack::Cleanup {
 llvm::Value *Token;
Index: lib/CodeGen/CodeGenModule.h
===
--- lib/CodeGen/CodeGenModule.h
+++ lib/CodeGen/CodeGenModule.h
@@ -138,6 +138,10 @@
   /// id objc_autorelease(id);
   llvm::Constant *objc_autorelease;
 
+  /// id objc_autorelease(id);
+  /// Note this is the runtime method not the intrinsic.
+  llvm::Constant *objc_autoreleaseRuntimeFunction;
+
   /// id objc_autoreleaseReturnValue(id);
   llvm::Constant *objc_autoreleaseReturnValue;
 
@@ -162,6 +166,10 @@
   /// id objc_retain(id);
   llvm::Constant *objc_retain;
 
+  /// id objc_retain(id);
+  /// Note this is the runtime method not the intrinsic.
+  llvm::Constant *objc_retainRuntimeFunction;
+
   /// id objc_retainAutorelease(id);
   llvm::Constant *objc_retainAutorelease;
 
@@ -177,6 +185,10 @@
   /// void objc_release(id);
   llvm::Con

[PATCH] D55869: Convert some ObjC retain/release msgSends to runtime calls

2018-12-21 Thread Pete Cooper via Phabricator via cfe-commits
pete added a comment.

In D55869#1339537 , @rjmccall wrote:

> It sounds like it's fine.


Thanks for the review!  Just pushed it as r349952.


Repository:
  rC Clang

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

https://reviews.llvm.org/D55869



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


[PATCH] D30882: Add a callback for __has_include and use it for dependency scanning

2018-04-23 Thread Pete Cooper via Phabricator via cfe-commits
pete added a comment.

In https://reviews.llvm.org/D30882#1075461, @dexonsmith wrote:

> In https://reviews.llvm.org/D30882#1075407, @ddunbar wrote:
>
> > In https://reviews.llvm.org/D30882#1074822, @dexonsmith wrote:
> >
> > > I don't think this is quite right.  I know at least `make`-based 
> > > incremental builds wouldn't deal well with this.
> >
> >
> > This is actually not a novel problem w.r.t. this patch. The exact same 
> > situation comes up with Makefile-included .d files and when one of the 
> > referenced headers is removed.
> >
> > This is typically solved somewhere in the build system, for example Make 
> > has `-include`, and Ninja and llbuild have explicit support for this 
> > situation.
>
>
> Of course, yes, I was wrong.  Thanks for the correction.
>
> > I agree we might want to tread cautiously on how we change the .d output, 
> > but in this case I think it might be safe.
> > 
> > If we decide this isn't safe, then we may want to consider a new flag which 
> > tracks *all* anti-dependencies (file's for which Clang checked existence 
> > but did not exist), and include that here. The major concern with that 
> > approach is it is a much larger list, and while it would support being 
> > substantially more correct, it is also well beyond what people currently 
> > expect out of the build system + compiler generated deps approaches.
>
> Even though this is likely safe, it seems really noisy.  Consider the case 
> where someone has `__has_include()` -- we'll get an entry for every 
> `-I`, `-F`, `-isystem`, and `-iframework`.  If we're going to add that noise, 
> I prefer a separate flag that covers all anti-dependencies.


Oh, that actually wasn't my intention when I wrote it.

Honestly I didn't expect it to log anything for missing paths at all, as we 
don't currently log all the missing (but attempted) paths for regular 
#include's.

Would it be ok to turn this on by default, without a flag, only in the case of 
the path actually existing, and only the found path being the one we add to the 
.d?


https://reviews.llvm.org/D30882



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


[PATCH] D122085: Add clang DirectX target support

2022-03-19 Thread Pete Cooper via Phabricator via cfe-commits
pete accepted this revision.
pete added a comment.
This revision is now accepted and ready to land.

All seems very reasonable to me.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122085

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


[PATCH] D122087: Add HLSL Language Option and Preprocessor

2022-03-19 Thread Pete Cooper via Phabricator via cfe-commits
pete accepted this revision.
pete added a comment.
This revision is now accepted and ready to land.

LGTM


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122087

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


[PATCH] D146255: [clang] Unconditionally add autolink hints for frameworks.

2023-03-16 Thread Pete Cooper via Phabricator via cfe-commits
pete accepted this revision.
pete added a comment.
This revision is now accepted and ready to land.

LGTM


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146255

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


[PATCH] D30881: Track skipped files in dependency scanning

2017-03-13 Thread Pete Cooper via Phabricator via cfe-commits
pete created this revision.

Its possible for a header to be a symlink to another header.  In this case, 
both are actually the same underlying file, and will both have the same include 
guards.

Because of this, if we #include the header, then #include the symlink, or vice 
versa, then one will get a FileChanged callback, and the next FileSkipped.

So that we get an accurate dependency file, we therefore need to also implement 
the FileSkipped callback in dependency scanning.


https://reviews.llvm.org/D30881

Files:
  lib/Frontend/DependencyFile.cpp
  test/Frontend/dependency-gen-symlink.c


Index: test/Frontend/dependency-gen-symlink.c
===
--- /dev/null
+++ test/Frontend/dependency-gen-symlink.c
@@ -0,0 +1,20 @@
+// REQUIRES: shell
+
+// Basic test
+// RUN: rm -rf %t.dir
+// RUN: mkdir %t.dir
+// RUN: mkdir %t.dir/a
+// RUN: mkdir %t.dir/b
+// RUN: echo "#ifndef HEADER_A" > %t.dir/a/header.h
+// RUN: echo "#define HEADER_A" >> %t.dir/a/header.h
+// RUN: echo "#endif" >> %t.dir/a/header.h
+// RUN: ln %t.dir/a/header.h %t.dir/b/header.h
+
+// RUN: %clang -MD -MF %t.dir/file.deps %s -fsyntax-only -I %t.dir
+// RUN: FileCheck -input-file=%t.dir/file.deps %s
+// CHECK: dependency-gen-symlink.o
+// CHECK: dependency-gen-symlink.c
+// CHECK: a/header.h
+// CHECK: b/header.h
+#include "a/header.h"
+#include "b/header.h"
Index: lib/Frontend/DependencyFile.cpp
===
--- lib/Frontend/DependencyFile.cpp
+++ lib/Frontend/DependencyFile.cpp
@@ -185,6 +185,11 @@
   void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
FileID PrevFID) override;
+
+  void FileSkipped(const FileEntry &SkippedFile,
+   const Token &FilenameTok,
+   SrcMgr::CharacteristicKind FileType) override;
+
   void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
   StringRef FileName, bool IsAngled,
   CharSourceRange FilenameRange, const FileEntry *File,
@@ -291,6 +296,12 @@
   AddFilename(llvm::sys::path::remove_leading_dotslash(Filename));
 }
 
+void DFGImpl::FileSkipped(const FileEntry &SkippedFile,
+ const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) {
+  AddFilename(llvm::sys::path::remove_leading_dotslash(SkippedFile.getName()));
+}
+
 void DFGImpl::InclusionDirective(SourceLocation HashLoc,
  const Token &IncludeTok,
  StringRef FileName,


Index: test/Frontend/dependency-gen-symlink.c
===
--- /dev/null
+++ test/Frontend/dependency-gen-symlink.c
@@ -0,0 +1,20 @@
+// REQUIRES: shell
+
+// Basic test
+// RUN: rm -rf %t.dir
+// RUN: mkdir %t.dir
+// RUN: mkdir %t.dir/a
+// RUN: mkdir %t.dir/b
+// RUN: echo "#ifndef HEADER_A" > %t.dir/a/header.h
+// RUN: echo "#define HEADER_A" >> %t.dir/a/header.h
+// RUN: echo "#endif" >> %t.dir/a/header.h
+// RUN: ln %t.dir/a/header.h %t.dir/b/header.h
+
+// RUN: %clang -MD -MF %t.dir/file.deps %s -fsyntax-only -I %t.dir
+// RUN: FileCheck -input-file=%t.dir/file.deps %s
+// CHECK: dependency-gen-symlink.o
+// CHECK: dependency-gen-symlink.c
+// CHECK: a/header.h
+// CHECK: b/header.h
+#include "a/header.h"
+#include "b/header.h"
Index: lib/Frontend/DependencyFile.cpp
===
--- lib/Frontend/DependencyFile.cpp
+++ lib/Frontend/DependencyFile.cpp
@@ -185,6 +185,11 @@
   void FileChanged(SourceLocation Loc, FileChangeReason Reason,
SrcMgr::CharacteristicKind FileType,
FileID PrevFID) override;
+
+  void FileSkipped(const FileEntry &SkippedFile,
+   const Token &FilenameTok,
+   SrcMgr::CharacteristicKind FileType) override;
+
   void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
   StringRef FileName, bool IsAngled,
   CharSourceRange FilenameRange, const FileEntry *File,
@@ -291,6 +296,12 @@
   AddFilename(llvm::sys::path::remove_leading_dotslash(Filename));
 }
 
+void DFGImpl::FileSkipped(const FileEntry &SkippedFile,
+ const Token &FilenameTok,
+ SrcMgr::CharacteristicKind FileType) {
+  AddFilename(llvm::sys::path::remove_leading_dotslash(SkippedFile.getName()));
+}
+
 void DFGImpl::InclusionDirective(SourceLocation HashLoc,
  const Token &IncludeTok,
  StringRef FileName,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D30882: Add a callback for __has_include and use it for dependency scanning

2017-03-13 Thread Pete Cooper via Phabricator via cfe-commits
pete created this revision.
Herald added a subscriber: nemanjai.

This adds a PP callback for the __has_include and __has_include_next directives.

Checking for the presence of a header should add it to the list of header 
dependencies so this overrides the callback in the dependency scanner.

I kept the callback intentionally simple for now.  If we want to extend it to 
track things like missing headers, just as PP->FileNotFound() does today, then 
that wouldn't be hard to add later.


https://reviews.llvm.org/D30882

Files:
  include/clang/Lex/PPCallbacks.h
  lib/Frontend/DependencyFile.cpp
  lib/Lex/PPMacroExpansion.cpp
  test/Frontend/dependency-gen-has-include.c


Index: test/Frontend/dependency-gen-has-include.c
===
--- /dev/null
+++ test/Frontend/dependency-gen-has-include.c
@@ -0,0 +1,17 @@
+// REQUIRES: shell
+
+// Basic test
+// RUN: rm -rf %t.dir
+// RUN: mkdir %t.dir
+// RUN: mkdir %t.dir/a
+// RUN: echo "#ifndef HEADER_A" > %t.dir/a/header.h
+// RUN: echo "#define HEADER_A" >> %t.dir/a/header.h
+// RUN: echo "#endif" >> %t.dir/a/header.h
+
+// RUN: %clang -MD -MF %t.dir/file.deps %s -fsyntax-only -I %t.dir
+// RUN: FileCheck -input-file=%t.dir/file.deps %s
+// CHECK: dependency-gen-has-include.o
+// CHECK: dependency-gen-has-include.c
+// CHECK: a/header.h
+#if __has_include("a/header.h")
+#endif
Index: lib/Lex/PPMacroExpansion.cpp
===
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -1424,6 +1424,9 @@
   PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, 
LookupFromFile,
 CurDir, nullptr, nullptr, nullptr);
 
+  if (PPCallbacks *Callbacks = PP.getPPCallbacks())
+Callbacks->HasInclude(FilenameLoc, File);
+
   // Get the result value.  A result of true means the file exists.
   return File != nullptr;
 }
Index: lib/Frontend/DependencyFile.cpp
===
--- lib/Frontend/DependencyFile.cpp
+++ lib/Frontend/DependencyFile.cpp
@@ -196,6 +196,8 @@
   StringRef SearchPath, StringRef RelativePath,
   const Module *Imported) override;
 
+  void HasInclude(SourceLocation Loc, const FileEntry *File) override;
+
   void EndOfMainFile() override {
 OutputDependencyFile();
   }
@@ -319,6 +321,12 @@
   }
 }
 
+void DFGImpl::HasInclude(SourceLocation Loc, const FileEntry *File) {
+  if (!File)
+return;
+  AddFilename(llvm::sys::path::remove_leading_dotslash(File->getName()));
+}
+
 void DFGImpl::AddFilename(StringRef Filename) {
   if (FilesSet.insert(Filename).second)
 Files.push_back(Filename);
Index: include/clang/Lex/PPCallbacks.h
===
--- include/clang/Lex/PPCallbacks.h
+++ include/clang/Lex/PPCallbacks.h
@@ -258,6 +258,10 @@
   virtual void Defined(const Token &MacroNameTok, const MacroDefinition &MD,
SourceRange Range) {
   }
+
+  /// \brief Callback invoked when a has_include directive is read.
+  virtual void HasInclude(SourceLocation Loc, const FileEntry *File) {
+  }
   
   /// \brief Hook called when a source range is skipped.
   /// \param Range The SourceRange that was skipped. The range begins at the
@@ -411,6 +415,11 @@
 Second->PragmaDiagnostic(Loc, Namespace, mapping, Str);
   }
 
+  void HasInclude(SourceLocation Loc, const FileEntry *File) override {
+First->HasInclude(Loc, File);
+Second->HasInclude(Loc, File);
+  }
+
   void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo 
*Name,
  SourceLocation StateLoc, unsigned State) override 
{
 First->PragmaOpenCLExtension(NameLoc, Name, StateLoc, State);


Index: test/Frontend/dependency-gen-has-include.c
===
--- /dev/null
+++ test/Frontend/dependency-gen-has-include.c
@@ -0,0 +1,17 @@
+// REQUIRES: shell
+
+// Basic test
+// RUN: rm -rf %t.dir
+// RUN: mkdir %t.dir
+// RUN: mkdir %t.dir/a
+// RUN: echo "#ifndef HEADER_A" > %t.dir/a/header.h
+// RUN: echo "#define HEADER_A" >> %t.dir/a/header.h
+// RUN: echo "#endif" >> %t.dir/a/header.h
+
+// RUN: %clang -MD -MF %t.dir/file.deps %s -fsyntax-only -I %t.dir
+// RUN: FileCheck -input-file=%t.dir/file.deps %s
+// CHECK: dependency-gen-has-include.o
+// CHECK: dependency-gen-has-include.c
+// CHECK: a/header.h
+#if __has_include("a/header.h")
+#endif
Index: lib/Lex/PPMacroExpansion.cpp
===
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -1424,6 +1424,9 @@
   PP.LookupFile(FilenameLoc, Filename, isAngled, LookupFrom, LookupFromFile,
 CurDir, nullptr, nullptr, nullptr);
 
+  if (PPCallbacks *Callbacks = PP.getPPCallbacks())
+Callbacks->HasInclude(FilenameLoc, File);
+
   // Get the res