Skip to content

Commit 322c9b1

Browse files
author
git apple-llvm automerger
committed
Merge commit '87fb89b63b3a' from apple/stable/20210107 into swift/main
2 parents f2ba792 + 87fb89b commit 322c9b1

File tree

28 files changed

+853
-232
lines changed

28 files changed

+853
-232
lines changed

clang/lib/AST/ExprCXX.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,7 @@ CXXMethodDecl *CXXMemberCallExpr::getMethodDecl() const {
670670
return cast<CXXMethodDecl>(MemExpr->getMemberDecl());
671671

672672
// FIXME: Will eventually need to cope with member pointers.
673+
// NOTE: Update makeTailCallIfSwiftAsync on fixing this.
673674
return nullptr;
674675
}
675676

clang/lib/CodeGen/CGStmt.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,10 +1149,25 @@ struct SaveRetExprRAII {
11491149
/// codegen it as 'tail call ...; ret void;'.
11501150
static void makeTailCallIfSwiftAsync(const CallExpr *CE, CGBuilderTy &Builder,
11511151
const CGFunctionInfo *CurFnInfo) {
1152-
auto callee = CE->getDirectCallee();
1153-
if (!callee)
1152+
auto calleeQualType = CE->getCallee()->getType();
1153+
const FunctionType *calleeType = nullptr;
1154+
if (calleeQualType->isFunctionPointerType() ||
1155+
calleeQualType->isFunctionReferenceType() ||
1156+
calleeQualType->isBlockPointerType() ||
1157+
calleeQualType->isMemberFunctionPointerType()) {
1158+
calleeType = calleeQualType->getPointeeType()->castAs<FunctionType>();
1159+
} else if (auto *ty = dyn_cast<FunctionType>(calleeQualType)) {
1160+
calleeType = ty;
1161+
} else if (auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
1162+
if (auto methodDecl = CMCE->getMethodDecl()) {
1163+
// getMethodDecl() doesn't handle member pointers at the moment.
1164+
calleeType = methodDecl->getType()->castAs<FunctionType>();
1165+
} else {
1166+
return;
1167+
}
1168+
} else {
11541169
return;
1155-
auto calleeType = callee->getFunctionType();
1170+
}
11561171
if (calleeType->getCallConv() == CallingConv::CC_SwiftAsync
11571172
&& (CurFnInfo->getASTCallingConvention() ==
11581173
CallingConv::CC_SwiftAsync)) {

clang/test/CodeGen/swift-async-call-conv.c

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
// RUN: %clang_cc1 -triple armv7s-apple-ios9 -emit-llvm -o - %s | FileCheck %s
55
// RUN: %clang_cc1 -triple armv7k-apple-ios9 -emit-llvm -o - %s | FileCheck %s
66

7-
// RUN: %clang_cc1 -x c++ -triple x86_64-apple-darwin10 -target-cpu core2 -emit-llvm -o - %s | FileCheck %s
8-
// RUN: %clang_cc1 -x c++ -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s
9-
// RUN: %clang_cc1 -x c++ -triple armv7-apple-darwin9 -emit-llvm -o - %s | FileCheck %s
10-
// RUN: %clang_cc1 -x c++ -triple armv7s-apple-ios9 -emit-llvm -o - %s | FileCheck %s
11-
// RUN: %clang_cc1 -x c++ -triple armv7k-apple-ios9 -emit-llvm -o - %s | FileCheck %s
7+
// RUN: %clang_cc1 -x c++ -triple x86_64-apple-darwin10 -target-cpu core2 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY
8+
// RUN: %clang_cc1 -x c++ -triple arm64-apple-ios9 -target-cpu cyclone -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY
9+
// RUN: %clang_cc1 -x c++ -triple armv7-apple-darwin9 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY
10+
// RUN: %clang_cc1 -x c++ -triple armv7s-apple-ios9 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY
11+
// RUN: %clang_cc1 -x c++ -triple armv7k-apple-ios9 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CPPONLY
1212

1313
// Test tail call behavior when a swiftasynccall function is called
1414
// from another swiftasynccall function.
@@ -136,3 +136,49 @@ char c_calling_async(MYBOOL b, unsigned u) {
136136
return x;
137137
}
138138

139+
#if __cplusplus
140+
struct S {
141+
SWIFTASYNCCALL void (*fptr)(char * ASYNC_CONTEXT);
142+
143+
SWIFTASYNCCALL void async_leaf_method(char * ASYNC_CONTEXT ctx) {
144+
*ctx += 1;
145+
}
146+
SWIFTASYNCCALL void async_nonleaf_method1(char * ASYNC_CONTEXT ctx) {
147+
return async_leaf_method(ctx);
148+
}
149+
SWIFTASYNCCALL void async_nonleaf_method2(char * ASYNC_CONTEXT ctx) {
150+
return this->async_leaf_method(ctx);
151+
}
152+
};
153+
154+
SWIFTASYNCCALL void (S::*async_leaf_method_ptr)(char * ASYNC_CONTEXT) = &S::async_leaf_method;
155+
156+
// CPPONLY-LABEL: swifttailcc void {{.*}}async_struct_field_and_methods
157+
// CPPONLY: musttail call swifttailcc void %{{[0-9]+}}
158+
// CPPONLY: musttail call swifttailcc void @{{.*}}async_nonleaf_method1
159+
// CPPONLY: musttail call swifttailcc void %{{[0-9]+}}
160+
// CPPONLY: musttail call swifttailcc void @{{.*}}async_nonleaf_method2
161+
// CPPONLY-NOT: musttail call swifttailcc void @{{.*}}async_leaf_method
162+
// ^ TODO: Member pointers should also work.
163+
SWIFTASYNCCALL void async_struct_field_and_methods(int i, S &sref, S *sptr) {
164+
char x = 'a';
165+
if (i == 0) {
166+
return (*sref.fptr)(&x);
167+
} else if (i == 1) {
168+
return sref.async_nonleaf_method1(&x);
169+
} else if (i == 2) {
170+
return (*(sptr->fptr))(&x);
171+
} else if (i == 3) {
172+
return sptr->async_nonleaf_method2(&x);
173+
} else if (i == 4) {
174+
return (sref.*async_leaf_method_ptr)(&x);
175+
}
176+
return (sptr->*async_leaf_method_ptr)(&x);
177+
}
178+
179+
// CPPONLY-LABEL: define{{.*}} swifttailcc void @{{.*}}async_nonleaf_method1
180+
// CPPONLY: musttail call swifttailcc void @{{.*}}async_leaf_method
181+
182+
// CPPONLY-LABEL: define{{.*}} swifttailcc void @{{.*}}async_nonleaf_method2
183+
// CPPONLY: musttail call swifttailcc void @{{.*}}async_leaf_method
184+
#endif

compiler-rt/include/sanitizer/tsan_interface.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ void __tsan_external_write(void *addr, void *caller_pc, void *tag);
141141
// and freed by __tsan_destroy_fiber.
142142
// - TSAN context of current fiber or thread can be obtained
143143
// by calling __tsan_get_current_fiber.
144-
// - __tsan_switch_to_fiber should be called immediatly before switch
144+
// - __tsan_switch_to_fiber should be called immediately before switch
145145
// to fiber, such as call of swapcontext.
146146
// - Fiber name can be set by __tsan_set_fiber_name.
147147
void *__tsan_get_current_fiber(void);
@@ -154,6 +154,15 @@ void __tsan_set_fiber_name(void *fiber, const char *name);
154154
// Do not establish a happens-before relation between fibers
155155
static const unsigned __tsan_switch_to_fiber_no_sync = 1 << 0;
156156

157+
// User-provided callback invoked on TSan initialization.
158+
void __tsan_on_initialize();
159+
160+
// User-provided callback invoked on TSan shutdown.
161+
// `failed` - Nonzero if TSan did detect issues, zero otherwise.
162+
// Return `0` if TSan should exit as if no issues were detected. Return nonzero
163+
// if TSan should exit as if issues were detected.
164+
int __tsan_on_finalize(int failed);
165+
157166
#ifdef __cplusplus
158167
} // extern "C"
159168
#endif

compiler-rt/lib/tsan/rtl/tsan_interface.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,13 @@ void __tsan_go_atomic32_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
415415
SANITIZER_INTERFACE_ATTRIBUTE
416416
void __tsan_go_atomic64_compare_exchange(ThreadState *thr, uptr cpc, uptr pc,
417417
u8 *a);
418+
419+
SANITIZER_INTERFACE_ATTRIBUTE
420+
void __tsan_on_initialize();
421+
422+
SANITIZER_INTERFACE_ATTRIBUTE
423+
int __tsan_on_finalize(int failed);
424+
418425
} // extern "C"
419426

420427
} // namespace __tsan

compiler-rt/lib/tsan/rtl/tsan_rtl.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "sanitizer_common/sanitizer_placement_new.h"
2020
#include "sanitizer_common/sanitizer_symbolizer.h"
2121
#include "tsan_defs.h"
22+
#include "tsan_interface.h"
2223
#include "tsan_platform.h"
2324
#include "tsan_rtl.h"
2425
#include "tsan_mman.h"
@@ -56,12 +57,23 @@ Context *ctx;
5657
bool OnFinalize(bool failed);
5758
void OnInitialize();
5859
#else
60+
#include <dlfcn.h>
5961
SANITIZER_WEAK_CXX_DEFAULT_IMPL
6062
bool OnFinalize(bool failed) {
63+
#if !SANITIZER_GO
64+
if (auto *ptr = dlsym(RTLD_DEFAULT, "__tsan_on_finalize"))
65+
return reinterpret_cast<decltype(&__tsan_on_finalize)>(ptr)(failed);
66+
#endif
6167
return failed;
6268
}
6369
SANITIZER_WEAK_CXX_DEFAULT_IMPL
64-
void OnInitialize() {}
70+
void OnInitialize() {
71+
#if !SANITIZER_GO
72+
if (auto *ptr = dlsym(RTLD_DEFAULT, "__tsan_on_initialize")) {
73+
return reinterpret_cast<decltype(&__tsan_on_initialize)>(ptr)();
74+
}
75+
#endif
76+
}
6577
#endif
6678

6779
static char thread_registry_placeholder[sizeof(ThreadRegistry)];
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: %clang_tsan -O1 %s -o %t.lib -fno-sanitize=thread -shared -fPIC -DBUILD_LIB=1
2+
// RUN: %clang_tsan -O1 %s %t.lib -o %t
3+
// RUN: %run %t | FileCheck %s
4+
5+
// Test that initialization/finalization hooks are called, even when they are
6+
// not defined in the main executable, but by another another library that
7+
// doesn't directly link against the TSan runtime.
8+
9+
#include <stdio.h>
10+
11+
#if BUILD_LIB
12+
13+
extern "C" void __tsan_on_initialize() {
14+
printf("__tsan_on_initialize()\n");
15+
}
16+
17+
extern "C" int __tsan_on_finalize(int failed) {
18+
printf("__tsan_on_finalize()\n");
19+
return failed;
20+
}
21+
22+
#else // BUILD_LIB
23+
24+
int main() {
25+
printf("main()\n");
26+
return 0;
27+
}
28+
29+
#endif // BUILD_LIB
30+
31+
// CHECK: __tsan_on_initialize()
32+
// CHECK: main()
33+
// CHECK: __tsan_on_finalize()

lldb/include/lldb/Breakpoint/BreakpointLocation.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,12 @@ class BreakpointLocation
230230
/// \b true if the target should stop at this breakpoint and \b
231231
/// false not.
232232
bool InvokeCallback(StoppointCallbackContext *context);
233+
234+
/// Report whether the callback for this location is synchronous or not.
235+
///
236+
/// \return
237+
/// \b true if the callback is synchronous and \b false if not.
238+
bool IsCallbackSynchronous();
233239

234240
/// Returns whether we should resolve Indirect functions in setting the
235241
/// breakpoint site for this location.

lldb/include/lldb/Target/DynamicLoader.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,14 @@ class DynamicLoader : public PluginInterface {
251251
return false;
252252
}
253253

254+
/// Return whether the dynamic loader is fully initialized and it's safe to
255+
/// call its APIs.
256+
///
257+
/// On some systems (e.g. Darwin based systems), lldb will get notified by
258+
/// the dynamic loader before it itself finished initializing and it's not
259+
/// safe to call certain APIs or SPIs.
260+
virtual bool IsFullyInitialized() { return true; }
261+
254262
protected:
255263
// Utility methods for derived classes
256264

@@ -294,7 +302,7 @@ class DynamicLoader : public PluginInterface {
294302
// Read a pointer from memory at the given addr. Return LLDB_INVALID_ADDRESS
295303
// if the read fails.
296304
lldb::addr_t ReadPointer(lldb::addr_t addr);
297-
305+
298306
// Calls into the Process protected method LoadOperatingSystemPlugin:
299307
void LoadOperatingSystemPlugin(bool flush);
300308

lldb/source/Breakpoint/BreakpointLocation.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,13 @@ bool BreakpointLocation::InvokeCallback(StoppointCallbackContext *context) {
195195
return m_owner.InvokeCallback(context, GetID());
196196
}
197197

198+
bool BreakpointLocation::IsCallbackSynchronous() {
199+
if (m_options_up != nullptr && m_options_up->HasCallback())
200+
return m_options_up->IsCallbackSynchronous();
201+
else
202+
return m_owner.GetOptions()->IsCallbackSynchronous();
203+
}
204+
198205
void BreakpointLocation::SetCallback(BreakpointHitCallback callback,
199206
void *baton, bool is_synchronous) {
200207
// The default "Baton" class will keep a copy of "baton" and won't free or

lldb/source/Breakpoint/BreakpointOptions.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,8 +453,6 @@ bool BreakpointOptions::InvokeCallback(StoppointCallbackContext *context,
453453
: nullptr,
454454
context, break_id, break_loc_id);
455455
} else if (IsCallbackSynchronous()) {
456-
// If a synchronous callback is called at async time, it should not say
457-
// to stop.
458456
return false;
459457
}
460458
}

lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,12 @@ bool DynamicLoaderMacOSXDYLD::GetSharedCacheInformation(
11191119
return false;
11201120
}
11211121

1122+
bool DynamicLoaderMacOSXDYLD::IsFullyInitialized() {
1123+
if (ReadAllImageInfosStructure())
1124+
return m_dyld_all_image_infos.libSystemInitialized;
1125+
return false;
1126+
}
1127+
11221128
void DynamicLoaderMacOSXDYLD::Initialize() {
11231129
PluginManager::RegisterPlugin(GetPluginNameStatic(),
11241130
GetPluginDescriptionStatic(), CreateInstance);

lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoaderDarwin {
6868

6969
uint32_t GetPluginVersion() override;
7070

71+
bool IsFullyInitialized() override;
72+
7173
protected:
7274
void PutToLog(lldb_private::Log *log) const;
7375

0 commit comments

Comments
 (0)