]> granicus.if.org Git - clang/commitdiff
Add low level support for generating invoke instead of calls.
authorDaniel Dunbar <daniel@zuster.org>
Mon, 23 Feb 2009 17:26:39 +0000 (17:26 +0000)
committerDaniel Dunbar <daniel@zuster.org>
Mon, 23 Feb 2009 17:26:39 +0000 (17:26 +0000)
 - No functionality change.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65325 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCall.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h

index db5085aaab81654bdf959db2c2c737c667d0b024..8f4367c8586bd7fd587d4f89e24481d61a3234b0 100644 (file)
@@ -1517,7 +1517,6 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
   }
   if (FuncAttrs)
     PAL.push_back(llvm::AttributeWithIndex::get(~0, FuncAttrs));
-
 }
 
 void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
@@ -1763,26 +1762,46 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
       break;
     }
   }
-  
-  llvm::CallInst *CI = Builder.CreateCall(Callee,&Args[0],&Args[0]+Args.size());
 
+  llvm::BasicBlock *InvokeDest = getInvokeDest();
   CodeGen::AttributeListType AttributeList;
   CGM.ConstructAttributeList(CallInfo, TargetDecl, AttributeList);
-  CI->setAttributes(llvm::AttrListPtr::get(AttributeList.begin(), 
-                                           AttributeList.size()));  
+  llvm::AttrListPtr Attrs = llvm::AttrListPtr::get(AttributeList.begin(),
+                                                   AttributeList.end());
   
-  if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee))
-    CI->setCallingConv(F->getCallingConv());
+  llvm::Instruction *CI;
+  if (!InvokeDest || Attrs.getFnAttributes() & (llvm::Attribute::NoUnwind ||
+                                                llvm::Attribute::NoReturn)) {
+    llvm::CallInst *CallInstr = 
+      Builder.CreateCall(Callee, &Args[0], &Args[0]+Args.size());
+    CI = CallInstr;
+
+    CallInstr->setAttributes(Attrs);
+    if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee))
+      CallInstr->setCallingConv(F->getCallingConv());
+
+    // If the call doesn't return, finish the basic block and clear the
+    // insertion point; this allows the rest of IRgen to discard
+    // unreachable code.
+    if (CallInstr->doesNotReturn()) {
+      Builder.CreateUnreachable();
+      Builder.ClearInsertionPoint();
+      
+      // Return a reasonable RValue.
+      return GetUndefRValue(RetTy);
+    }    
+  } else {
+    llvm::BasicBlock *Cont = createBasicBlock("invoke.cont");
+    llvm::InvokeInst *InvokeInstr = 
+      Builder.CreateInvoke(Callee, Cont, InvokeDest, 
+                           &Args[0], &Args[0]+Args.size());
+    CI = InvokeInstr;
 
-  // If the call doesn't return, finish the basic block and clear the
-  // insertion point; this allows the rest of IRgen to discard
-  // unreachable code.
-  if (CI->doesNotReturn()) {
-    Builder.CreateUnreachable();
-    Builder.ClearInsertionPoint();
+    InvokeInstr->setAttributes(Attrs);
+    if (const llvm::Function *F = dyn_cast<llvm::Function>(Callee))
+      InvokeInstr->setCallingConv(F->getCallingConv());
 
-    // Return a reasonable RValue.
-    return GetUndefRValue(RetTy);
+    EmitBlock(Cont);
   }
 
   if (CI->getType() != llvm::Type::VoidTy)
index 9175d16063c24f40ba9ef6922cc45303d39e645f..ccd961ac28335dfc6a750ce3243934dc4d6de8ff 100644 (file)
@@ -25,7 +25,7 @@ using namespace CodeGen;
 
 CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) 
   : CGM(cgm), Target(CGM.getContext().Target), DebugInfo(0), SwitchInsn(0), 
-    CaseRangeBlock(0) {
+    CaseRangeBlock(0), InvokeDest(0) {
   LLVMIntTy = ConvertType(getContext().IntTy);
   LLVMPointerWidth = Target.getPointerWidth(0);
 
index 8bda453ee72863e3471fd39de91fa7b13a5fb85d..b3d6a327ebeac97d01908c8f9cbe4965b2b53c2f 100644 (file)
@@ -190,6 +190,10 @@ private:
   /// statement range in current switch instruction.
   llvm::BasicBlock *CaseRangeBlock;
 
+  /// InvokeDest - This is the nearest exception target for calls
+  /// which can unwind, when exceptions are being used.
+  llvm::BasicBlock *InvokeDest;
+
   // VLASizeMap - This keeps track of the associated size for each VLA type.
   // FIXME: Maybe this could be a stack of maps that is pushed/popped as we
   // enter/leave scopes.
@@ -233,6 +237,13 @@ public:
   ASTContext &getContext() const;
   CGDebugInfo *getDebugInfo() { return DebugInfo; }
 
+  llvm::BasicBlock *getInvokeDest() { return InvokeDest; }
+  void setInvokeDest(llvm::BasicBlock *B) { InvokeDest = B; }
+
+  //===--------------------------------------------------------------------===//
+  //                                  Objective-C
+  //===--------------------------------------------------------------------===//
+
   void GenerateObjCMethod(const ObjCMethodDecl *OMD);
 
   void StartObjCMethod(const ObjCMethodDecl *MD,