Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(368)

Side by Side Diff: lib/Transforms/NaCl/LowerEmAsyncify.cpp

Issue 1151093004: Changes from 3.7 merge to files not in upstream (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- LowerEmAsyncify - transform asynchronous functions for Emscripten/JS -- ---------===// 1 //===- LowerEmAsyncify - transform asynchronous functions for Emscripten/JS -- ---------===//
2 // 2 //
3 // The LLVM Compiler Infrastructure 3 // The LLVM Compiler Infrastructure
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // Lu Wang <coolwanglu@gmail.com> 10 // Lu Wang <coolwanglu@gmail.com>
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 Module *TheModule; 60 Module *TheModule;
61 61
62 public: 62 public:
63 static char ID; // Pass identification, replacement for typeid 63 static char ID; // Pass identification, replacement for typeid
64 explicit LowerEmAsyncify() : ModulePass(ID), TheModule(NULL) { 64 explicit LowerEmAsyncify() : ModulePass(ID), TheModule(NULL) {
65 initializeLowerEmAsyncifyPass(*PassRegistry::getPassRegistry()); 65 initializeLowerEmAsyncifyPass(*PassRegistry::getPassRegistry());
66 } 66 }
67 virtual ~LowerEmAsyncify() { } 67 virtual ~LowerEmAsyncify() { }
68 bool runOnModule(Module &M); 68 bool runOnModule(Module &M);
69 69
70 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
71 AU.addRequired<DataLayoutPass>();
72 ModulePass::getAnalysisUsage(AU);
73 }
74
75 private: 70 private:
76 const DataLayout *DL; 71 const DataLayout *DL;
77 72
78 Type *Void, *I1, *I32, *I32Ptr; 73 Type *Void, *I1, *I32, *I32Ptr;
79 FunctionType *VFunction, *I1Function, *I32PFunction; 74 FunctionType *VFunction, *I1Function, *I32PFunction;
80 FunctionType *VI32PFunction, *I32PI32Function; 75 FunctionType *VI32PFunction, *I32PI32Function;
81 FunctionType *CallbackFunctionType; 76 FunctionType *CallbackFunctionType;
82 77
83 Function *AllocAsyncCtxFunction, *ReallocAsyncCtxFunction, *FreeAsyncCtxFunc tion; 78 Function *AllocAsyncCtxFunction, *ReallocAsyncCtxFunction, *FreeAsyncCtxFunc tion;
84 Function *CheckAsyncFunction; 79 Function *CheckAsyncFunction;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 }; 112 };
118 } 113 }
119 114
120 char LowerEmAsyncify::ID = 0; 115 char LowerEmAsyncify::ID = 0;
121 INITIALIZE_PASS(LowerEmAsyncify, "loweremasyncify", 116 INITIALIZE_PASS(LowerEmAsyncify, "loweremasyncify",
122 "Lower async functions for js/emscripten", 117 "Lower async functions for js/emscripten",
123 false, false) 118 false, false)
124 119
125 bool LowerEmAsyncify::runOnModule(Module &M) { 120 bool LowerEmAsyncify::runOnModule(Module &M) {
126 TheModule = &M; 121 TheModule = &M;
122 DL = &M.getDataLayout();
127 123
128 std::set<std::string> WhiteList(AsyncifyWhiteList.begin(), AsyncifyWhiteList.e nd()); 124 std::set<std::string> WhiteList(AsyncifyWhiteList.begin(), AsyncifyWhiteList.e nd());
129 125
130 /* 126 /*
131 * collect all the functions that should be asyncified 127 * collect all the functions that should be asyncified
132 * any function that _might_ call an async function is also async 128 * any function that _might_ call an async function is also async
133 */ 129 */
134 std::vector<Function*> AsyncFunctionsPending; 130 std::vector<Function*> AsyncFunctionsPending;
135 for(unsigned i = 0; i < AsyncifyFunctions.size(); ++i) { 131 for(unsigned i = 0; i < AsyncifyFunctions.size(); ++i) {
136 std::string const& AFName = AsyncifyFunctions[i]; 132 std::string const& AFName = AsyncifyFunctions[i];
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 186
191 for (FunctionInstructionsMap::iterator I = AsyncFunctionCalls.begin(), E = Asy ncFunctionCalls.end(); 187 for (FunctionInstructionsMap::iterator I = AsyncFunctionCalls.begin(), E = Asy ncFunctionCalls.end();
192 I != E; ++I) { 188 I != E; ++I) {
193 transformAsyncFunction(*(I->first), I->second); 189 transformAsyncFunction(*(I->first), I->second);
194 } 190 }
195 191
196 return true; 192 return true;
197 } 193 }
198 194
199 void LowerEmAsyncify::initTypesAndFunctions(void) { 195 void LowerEmAsyncify::initTypesAndFunctions(void) {
200 DL = &getAnalysis<DataLayoutPass>().getDataLayout();
201
202 // Data types 196 // Data types
203 Void = Type::getVoidTy(TheModule->getContext()); 197 Void = Type::getVoidTy(TheModule->getContext());
204 I1 = Type::getInt1Ty(TheModule->getContext()); 198 I1 = Type::getInt1Ty(TheModule->getContext());
205 I32 = Type::getInt32Ty(TheModule->getContext()); 199 I32 = Type::getInt32Ty(TheModule->getContext());
206 I32Ptr = Type::getInt32PtrTy(TheModule->getContext()); 200 I32Ptr = Type::getInt32PtrTy(TheModule->getContext());
207 201
208 // Function types 202 // Function types
209 SmallVector<Type*, 2> ArgTypes; 203 SmallVector<Type*, 2> ArgTypes;
210 VFunction = FunctionType::get(Void, false); 204 VFunction = FunctionType::get(Void, false);
211 I1Function = FunctionType::get(I1, false); 205 I1Function = FunctionType::get(I1, false);
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 // - retrieve the async return value and free the async context if the called function turns out to be sync 424 // - retrieve the async return value and free the async context if the called function turns out to be sync
431 std::vector<AsyncCallEntry> AsyncCallEntries; 425 std::vector<AsyncCallEntry> AsyncCallEntries;
432 AsyncCallEntries.reserve(AsyncCalls.size()); 426 AsyncCallEntries.reserve(AsyncCalls.size());
433 for (Instructions::const_iterator I = AsyncCalls.begin(), E = AsyncCalls.end() ; I != E; ++I) { 427 for (Instructions::const_iterator I = AsyncCalls.begin(), E = AsyncCalls.end() ; I != E; ++I) {
434 // prepare blocks 428 // prepare blocks
435 Instruction *CurAsyncCall = *I; 429 Instruction *CurAsyncCall = *I;
436 430
437 // The block containing the async call 431 // The block containing the async call
438 BasicBlock *CurBlock = CurAsyncCall->getParent(); 432 BasicBlock *CurBlock = CurAsyncCall->getParent();
439 // The block should run after the async call 433 // The block should run after the async call
440 BasicBlock *AfterCallBlock = SplitBlock(CurBlock, CurAsyncCall->getNextNode( ), this); 434 BasicBlock *AfterCallBlock = SplitBlock(CurBlock, CurAsyncCall->getNextNode( ));
441 // The block where we store the context and return 435 // The block where we store the context and return
442 BasicBlock *SaveAsyncCtxBlock = BasicBlock::Create(TheModule->getContext(), "SaveAsyncCtx", &F, AfterCallBlock); 436 BasicBlock *SaveAsyncCtxBlock = BasicBlock::Create(TheModule->getContext(), "SaveAsyncCtx", &F, AfterCallBlock);
443 // return a dummy value at the end, to make the block valid 437 // return a dummy value at the end, to make the block valid
444 new UnreachableInst(TheModule->getContext(), SaveAsyncCtxBlock); 438 new UnreachableInst(TheModule->getContext(), SaveAsyncCtxBlock);
445 439
446 // allocate the context before making the call 440 // allocate the context before making the call
447 // we don't know the size yet, will fix it later 441 // we don't know the size yet, will fix it later
448 // we cannot insert the instruction later because, 442 // we cannot insert the instruction later because,
449 // we need to make sure that all the instructions and blocks are fixed befor e we can generate DT and find context variables 443 // we need to make sure that all the instructions and blocks are fixed befor e we can generate DT and find context variables
450 // In CallHandler.h `sp` will be put as the second parameter 444 // In CallHandler.h `sp` will be put as the second parameter
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 CurEntry.AllocAsyncCtxInst->setOperand(0, 493 CurEntry.AllocAsyncCtxInst->setOperand(0,
500 ConstantInt::get(I32, DL->getTypeStoreSize(CurEntry.ContextStructType))) ; 494 ConstantInt::get(I32, DL->getTypeStoreSize(CurEntry.ContextStructType))) ;
501 495
502 // construct SaveAsyncCtxBlock 496 // construct SaveAsyncCtxBlock
503 { 497 {
504 // fill in SaveAsyncCtxBlock 498 // fill in SaveAsyncCtxBlock
505 // temporarily remove the terminator for convenience 499 // temporarily remove the terminator for convenience
506 CurEntry.SaveAsyncCtxBlock->getTerminator()->eraseFromParent(); 500 CurEntry.SaveAsyncCtxBlock->getTerminator()->eraseFromParent();
507 assert(CurEntry.SaveAsyncCtxBlock->empty()); 501 assert(CurEntry.SaveAsyncCtxBlock->empty());
508 502
509 BitCastInst *AsyncCtxAddr = new BitCastInst(CurEntry.AllocAsyncCtxInst, Cu rEntry.ContextStructType->getPointerTo(), "AsyncCtxAddr", CurEntry.SaveAsyncCtxB lock); 503 Type *AsyncCtxAddrTy = CurEntry.ContextStructType->getPointerTo();
504 BitCastInst *AsyncCtxAddr = new BitCastInst(CurEntry.AllocAsyncCtxInst, As yncCtxAddrTy, "AsyncCtxAddr", CurEntry.SaveAsyncCtxBlock);
510 SmallVector<Value*, 2> Indices; 505 SmallVector<Value*, 2> Indices;
511 // store the callback 506 // store the callback
512 { 507 {
513 Indices.push_back(ConstantInt::get(I32, 0)); 508 Indices.push_back(ConstantInt::get(I32, 0));
514 Indices.push_back(ConstantInt::get(I32, 0)); 509 Indices.push_back(ConstantInt::get(I32, 0));
515 GetElementPtrInst *AsyncVarAddr = GetElementPtrInst::Create(AsyncCtxAddr , Indices, "", CurEntry.SaveAsyncCtxBlock); 510 GetElementPtrInst *AsyncVarAddr = GetElementPtrInst::Create(AsyncCtxAddr Ty, AsyncCtxAddr, Indices, "", CurEntry.SaveAsyncCtxBlock);
516 new StoreInst(CurEntry.CallbackFunc, AsyncVarAddr, CurEntry.SaveAsyncCtx Block); 511 new StoreInst(CurEntry.CallbackFunc, AsyncVarAddr, CurEntry.SaveAsyncCtx Block);
517 } 512 }
518 // store the context variables 513 // store the context variables
519 for (size_t i = 0; i < CurEntry.ContextVariables.size(); ++i) { 514 for (size_t i = 0; i < CurEntry.ContextVariables.size(); ++i) {
520 Indices.clear(); 515 Indices.clear();
521 Indices.push_back(ConstantInt::get(I32, 0)); 516 Indices.push_back(ConstantInt::get(I32, 0));
522 Indices.push_back(ConstantInt::get(I32, i + 1)); // the 0th element is t he callback function 517 Indices.push_back(ConstantInt::get(I32, i + 1)); // the 0th element is t he callback function
523 GetElementPtrInst *AsyncVarAddr = GetElementPtrInst::Create(AsyncCtxAddr , Indices, "", CurEntry.SaveAsyncCtxBlock); 518 GetElementPtrInst *AsyncVarAddr = GetElementPtrInst::Create(AsyncCtxAddr Ty, AsyncCtxAddr, Indices, "", CurEntry.SaveAsyncCtxBlock);
524 new StoreInst(CurEntry.ContextVariables[i], AsyncVarAddr, CurEntry.SaveA syncCtxBlock); 519 new StoreInst(CurEntry.ContextVariables[i], AsyncVarAddr, CurEntry.SaveA syncCtxBlock);
525 } 520 }
526 // to exit the block, we want to return without unwinding the stack frame 521 // to exit the block, we want to return without unwinding the stack frame
527 CallInst::Create(DoNotUnwindFunction, "", CurEntry.SaveAsyncCtxBlock); 522 CallInst::Create(DoNotUnwindFunction, "", CurEntry.SaveAsyncCtxBlock);
528 ReturnInst::Create(TheModule->getContext(), 523 ReturnInst::Create(TheModule->getContext(),
529 (F.getReturnType()->isVoidTy() ? 0 : Constant::getNullValue(F.getRetur nType())), 524 (F.getReturnType()->isVoidTy() ? 0 : Constant::getNullValue(F.getRetur nType())),
530 CurEntry.SaveAsyncCtxBlock); 525 CurEntry.SaveAsyncCtxBlock);
531 } 526 }
532 } 527 }
533 528
534 // Pass 3 529 // Pass 3
535 // now all the SaveAsyncCtxBlock's have been constructed 530 // now all the SaveAsyncCtxBlock's have been constructed
536 // we can clone F and construct callback functions 531 // we can clone F and construct callback functions
537 // we could not construct the callbacks in Pass 2 because we need _all_ those SaveAsyncCtxBlock's appear in _each_ callback 532 // we could not construct the callbacks in Pass 2 because we need _all_ those SaveAsyncCtxBlock's appear in _each_ callback
538 for (std::vector<AsyncCallEntry>::iterator EI = AsyncCallEntries.begin(), EE = AsyncCallEntries.end(); EI != EE; ++EI) { 533 for (std::vector<AsyncCallEntry>::iterator EI = AsyncCallEntries.begin(), EE = AsyncCallEntries.end(); EI != EE; ++EI) {
539 AsyncCallEntry & CurEntry = *EI; 534 AsyncCallEntry & CurEntry = *EI;
540 535
541 Function *CurCallbackFunc = CurEntry.CallbackFunc; 536 Function *CurCallbackFunc = CurEntry.CallbackFunc;
542 ValueToValueMapTy VMap; 537 ValueToValueMapTy VMap;
543 538
544 // Add the entry block 539 // Add the entry block
545 // load variables from the context 540 // load variables from the context
546 // also update VMap for CloneFunction 541 // also update VMap for CloneFunction
547 BasicBlock *EntryBlock = BasicBlock::Create(TheModule->getContext(), "AsyncC allbackEntry", CurCallbackFunc); 542 BasicBlock *EntryBlock = BasicBlock::Create(TheModule->getContext(), "AsyncC allbackEntry", CurCallbackFunc);
548 std::vector<LoadInst *> LoadedAsyncVars; 543 std::vector<LoadInst *> LoadedAsyncVars;
549 { 544 {
550 BitCastInst *AsyncCtxAddr = new BitCastInst(CurCallbackFunc->arg_begin(), CurEntry.ContextStructType->getPointerTo(), "AsyncCtx", EntryBlock); 545 Type *AsyncCtxAddrTy = CurEntry.ContextStructType->getPointerTo();
546 BitCastInst *AsyncCtxAddr = new BitCastInst(CurCallbackFunc->arg_begin(), AsyncCtxAddrTy, "AsyncCtx", EntryBlock);
551 SmallVector<Value*, 2> Indices; 547 SmallVector<Value*, 2> Indices;
552 for (size_t i = 0; i < CurEntry.ContextVariables.size(); ++i) { 548 for (size_t i = 0; i < CurEntry.ContextVariables.size(); ++i) {
553 Indices.clear(); 549 Indices.clear();
554 Indices.push_back(ConstantInt::get(I32, 0)); 550 Indices.push_back(ConstantInt::get(I32, 0));
555 Indices.push_back(ConstantInt::get(I32, i + 1)); // the 0th element of A syncCtx is the callback function 551 Indices.push_back(ConstantInt::get(I32, i + 1)); // the 0th element of A syncCtx is the callback function
556 GetElementPtrInst *AsyncVarAddr = GetElementPtrInst::Create(AsyncCtxAddr , Indices, "", EntryBlock); 552 GetElementPtrInst *AsyncVarAddr = GetElementPtrInst::Create(AsyncCtxAddr Ty, AsyncCtxAddr, Indices, "", EntryBlock);
557 LoadedAsyncVars.push_back(new LoadInst(AsyncVarAddr, "", EntryBlock)); 553 LoadedAsyncVars.push_back(new LoadInst(AsyncVarAddr, "", EntryBlock));
558 // we want the argument to be replaced by the loaded value 554 // we want the argument to be replaced by the loaded value
559 if (isa<Argument>(CurEntry.ContextVariables[i])) 555 if (isa<Argument>(CurEntry.ContextVariables[i]))
560 VMap[CurEntry.ContextVariables[i]] = LoadedAsyncVars.back(); 556 VMap[CurEntry.ContextVariables[i]] = LoadedAsyncVars.back();
561 } 557 }
562 } 558 }
563 559
564 // we don't need any argument, just leave dummy entries there to cheat Clone FunctionInto 560 // we don't need any argument, just leave dummy entries there to cheat Clone FunctionInto
565 for (Function::const_arg_iterator AI = F.arg_begin(), AE = F.arg_end(); AI ! = AE; ++AI) { 561 for (Function::const_arg_iterator AI = F.arg_begin(), AE = F.arg_end(); AI ! = AE; ++AI) {
566 if (VMap.count(AI) == 0) 562 if (VMap.count(AI) == 0)
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
720 // mostly from CallHandler.h 716 // mostly from CallHandler.h
721 ImmutableCallSite CS(I); 717 ImmutableCallSite CS(I);
722 if (!CS) return false; // not call nor invoke 718 if (!CS) return false; // not call nor invoke
723 const Value *CV = CS.getCalledValue()->stripPointerCasts(); 719 const Value *CV = CS.getCalledValue()->stripPointerCasts();
724 return !isa<const Function>(CV); 720 return !isa<const Function>(CV);
725 } 721 }
726 722
727 ModulePass *llvm::createLowerEmAsyncifyPass() { 723 ModulePass *llvm::createLowerEmAsyncifyPass() {
728 return new LowerEmAsyncify(); 724 return new LowerEmAsyncify();
729 } 725 }
730
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698