75
75
using namespace swift ;
76
76
using namespace irgen ;
77
77
78
+ llvm::cl::opt<bool > UseBasicDynamicReplacement (
79
+ " basic-dynamic-replacement" , llvm::cl::init(false ),
80
+ llvm::cl::desc(" Basic implementation of dynamic replacement" ));
81
+
78
82
namespace {
79
83
80
84
// / Add methods, properties, and protocol conformances from a JITed extension
@@ -2175,6 +2179,79 @@ static llvm::GlobalVariable *createGlobalForDynamicReplacementFunctionKey(
2175
2179
return key;
2176
2180
}
2177
2181
2182
+ // / Creates the prolog for a dynamically replaceable function.
2183
+ // / It checks if the replaced function or the original function should be called
2184
+ // / (by calling the swift_getFunctionReplacement runtime function). In case of
2185
+ // / the original function, it just jumps to the "real" code of the function,
2186
+ // / otherwise it tail calls the replacement.
2187
+ void IRGenModule::createReplaceableProlog (IRGenFunction &IGF, SILFunction *f) {
2188
+ LinkEntity varEntity =
2189
+ LinkEntity::forDynamicallyReplaceableFunctionVariable (f);
2190
+ LinkEntity keyEntity =
2191
+ LinkEntity::forDynamicallyReplaceableFunctionKey (f);
2192
+ Signature signature = getSignature (f->getLoweredFunctionType ());
2193
+
2194
+ // Create and initialize the first link entry for the chain of replacements.
2195
+ // The first implementation is initialized with 'implFn'.
2196
+ auto linkEntry = getChainEntryForDynamicReplacement (*this , varEntity, IGF.CurFn );
2197
+
2198
+ // Create the key data structure. This is used from other modules to refer to
2199
+ // the chain of replacements.
2200
+ createGlobalForDynamicReplacementFunctionKey (*this , keyEntity, linkEntry);
2201
+
2202
+ llvm::Constant *indices[] = {llvm::ConstantInt::get (Int32Ty, 0 ),
2203
+ llvm::ConstantInt::get (Int32Ty, 0 )};
2204
+
2205
+ auto *fnPtrAddr =
2206
+ llvm::ConstantExpr::getInBoundsGetElementPtr (nullptr , linkEntry, indices);
2207
+
2208
+ auto *ReplAddr =
2209
+ llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast (fnPtrAddr,
2210
+ FunctionPtrTy->getPointerTo ());
2211
+
2212
+ auto *FnAddr = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast (
2213
+ IGF.CurFn , FunctionPtrTy);
2214
+
2215
+ llvm::Value *ReplFn = nullptr , *rhs = nullptr ;
2216
+
2217
+ if (UseBasicDynamicReplacement) {
2218
+ ReplFn = IGF.Builder .CreateLoad (fnPtrAddr, getPointerAlignment ());
2219
+ rhs = FnAddr;
2220
+ } else {
2221
+ // Call swift_getFunctionReplacement to check which function to call.
2222
+ auto *callRTFunc = IGF.Builder .CreateCall (getGetReplacementFn (),
2223
+ { ReplAddr, FnAddr });
2224
+ callRTFunc->setDoesNotThrow ();
2225
+ ReplFn = callRTFunc;
2226
+ rhs = llvm::ConstantExpr::getNullValue (ReplFn->getType ());
2227
+ }
2228
+ auto *hasReplFn = IGF.Builder .CreateICmpEQ (ReplFn, rhs);
2229
+
2230
+ auto *replacedBB = IGF.createBasicBlock (" forward_to_replaced" );
2231
+ auto *origEntryBB = IGF.createBasicBlock (" original_entry" );
2232
+ IGF.Builder .CreateCondBr (hasReplFn, origEntryBB, replacedBB);
2233
+
2234
+ IGF.Builder .emitBlock (replacedBB);
2235
+
2236
+ // Call the replacement function.
2237
+ SmallVector<llvm::Value *, 16 > forwardedArgs;
2238
+ for (auto &arg : IGF.CurFn ->args ())
2239
+ forwardedArgs.push_back (&arg);
2240
+ auto *fnType = signature.getType ()->getPointerTo ();
2241
+ auto *realReplFn = IGF.Builder .CreateBitCast (ReplFn, fnType);
2242
+
2243
+ auto *Res = IGF.Builder .CreateCall (FunctionPointer (realReplFn, signature),
2244
+ forwardedArgs);
2245
+ Res->setTailCall ();
2246
+ if (IGF.CurFn ->getReturnType ()->isVoidTy ())
2247
+ IGF.Builder .CreateRetVoid ();
2248
+ else
2249
+ IGF.Builder .CreateRet (Res);
2250
+
2251
+ IGF.Builder .emitBlock (origEntryBB);
2252
+
2253
+ }
2254
+
2178
2255
// / Emit the thunk that dispatches to the dynamically replaceable function.
2179
2256
static void emitDynamicallyReplaceableThunk (IRGenModule &IGM,
2180
2257
LinkEntity varEntity,
@@ -2279,6 +2356,9 @@ void IRGenModule::emitOpaqueTypeDescriptorAccessor(OpaqueTypeDecl *opaque) {
2279
2356
void IRGenModule::emitDynamicReplacementOriginalFunctionThunk (SILFunction *f) {
2280
2357
assert (f->getDynamicallyReplacedFunction ());
2281
2358
2359
+ if (UseBasicDynamicReplacement)
2360
+ return ;
2361
+
2282
2362
auto entity = LinkEntity::forSILFunction (f, true );
2283
2363
2284
2364
Signature signature = getSignature (f->getLoweredFunctionType ());
@@ -2303,11 +2383,17 @@ void IRGenModule::emitDynamicReplacementOriginalFunctionThunk(SILFunction *f) {
2303
2383
llvm::Constant *indices[] = {llvm::ConstantInt::get (Int32Ty, 0 ),
2304
2384
llvm::ConstantInt::get (Int32Ty, 0 )};
2305
2385
2306
- auto *fnPtr = IGF.Builder .CreateLoad (
2386
+ auto *fnPtrAddr =
2387
+ llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast (
2307
2388
llvm::ConstantExpr::getInBoundsGetElementPtr (nullptr , linkEntry, indices),
2308
- getPointerAlignment ());
2389
+ FunctionPtrTy->getPointerTo ());
2390
+
2391
+ auto *OrigFn = IGF.Builder .CreateCall (getGetOrigOfReplaceableFn (),
2392
+ { fnPtrAddr });
2393
+ OrigFn->setDoesNotThrow ();
2394
+
2309
2395
auto *typeFnPtr =
2310
- IGF.Builder .CreateBitOrPointerCast (fnPtr , implFn->getType ());
2396
+ IGF.Builder .CreateBitOrPointerCast (OrigFn , implFn->getType ());
2311
2397
2312
2398
SmallVector<llvm::Value *, 16 > forwardedArgs;
2313
2399
for (auto &arg : implFn->args ())
@@ -2338,25 +2424,6 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
2338
2424
if (fn) {
2339
2425
if (forDefinition) {
2340
2426
updateLinkageForDefinition (*this , fn, entity);
2341
- if (isDynamicallyReplaceableImplementation) {
2342
- // Create the dynamically replacement thunk.
2343
- LinkEntity implEntity = LinkEntity::forSILFunction (f, true );
2344
- auto existingImpl = Module.getFunction (implEntity.mangleAsString ());
2345
- assert (!existingImpl);
2346
- (void ) existingImpl;
2347
- Signature signature = getSignature (f->getLoweredFunctionType ());
2348
- addLLVMFunctionAttributes (f, signature);
2349
- LinkInfo implLink = LinkInfo::get (*this , implEntity, forDefinition);
2350
- auto implFn = createFunction (*this , implLink, signature, fn,
2351
- f->getOptimizationMode ());
2352
- LinkEntity varEntity =
2353
- LinkEntity::forDynamicallyReplaceableFunctionVariable (f);
2354
- LinkEntity keyEntity =
2355
- LinkEntity::forDynamicallyReplaceableFunctionKey (f);
2356
- emitDynamicallyReplaceableThunk (*this , varEntity, keyEntity, fn, implFn,
2357
- signature);
2358
- return implFn;
2359
- }
2360
2427
}
2361
2428
return fn;
2362
2429
}
@@ -2431,20 +2498,6 @@ llvm::Function *IRGenModule::getAddrOfSILFunction(
2431
2498
if (hasOrderNumber) {
2432
2499
EmittedFunctionsByOrder.insert (orderNumber, fn);
2433
2500
}
2434
-
2435
- if (isDynamicallyReplaceableImplementation && forDefinition) {
2436
- LinkEntity implEntity = LinkEntity::forSILFunction (f, true );
2437
- LinkInfo implLink = LinkInfo::get (*this , implEntity, forDefinition);
2438
- auto implFn = createFunction (*this , implLink, signature, insertBefore,
2439
- f->getOptimizationMode ());
2440
-
2441
- LinkEntity varEntity =
2442
- LinkEntity::forDynamicallyReplaceableFunctionVariable (f);
2443
- LinkEntity keyEntity = LinkEntity::forDynamicallyReplaceableFunctionKey (f);
2444
- emitDynamicallyReplaceableThunk (*this , varEntity, keyEntity, fn, implFn,
2445
- signature);
2446
- return implFn;
2447
- }
2448
2501
return fn;
2449
2502
}
2450
2503
0 commit comments