Add support for the Invoke instruction!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@6934 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner
2003-06-28 17:53:05 +00:00
parent 4097b2a963
commit 9bda5f52bd
2 changed files with 96 additions and 18 deletions

View File

@ -17,6 +17,7 @@
#include "llvm/Analysis/ConstantsScanner.h" #include "llvm/Analysis/ConstantsScanner.h"
#include "llvm/Support/InstVisitor.h" #include "llvm/Support/InstVisitor.h"
#include "llvm/Support/InstIterator.h" #include "llvm/Support/InstIterator.h"
#include "llvm/Support/CallSite.h"
#include "Support/StringExtras.h" #include "Support/StringExtras.h"
#include "Support/STLExtras.h" #include "Support/STLExtras.h"
#include <algorithm> #include <algorithm>
@ -30,7 +31,7 @@ namespace {
const Module *TheModule; const Module *TheModule;
std::map<const Type *, std::string> TypeNames; std::map<const Type *, std::string> TypeNames;
std::set<const Value*> MangledGlobals; std::set<const Value*> MangledGlobals;
bool needsMalloc; bool needsMalloc, emittedInvoke;
std::map<const ConstantFP *, unsigned> FPConstantMap; std::map<const ConstantFP *, unsigned> FPConstantMap;
public: public:
@ -117,12 +118,14 @@ namespace {
void visitReturnInst(ReturnInst &I); void visitReturnInst(ReturnInst &I);
void visitBranchInst(BranchInst &I); void visitBranchInst(BranchInst &I);
void visitSwitchInst(SwitchInst &I); void visitSwitchInst(SwitchInst &I);
void visitInvokeInst(InvokeInst &I);
void visitPHINode(PHINode &I); void visitPHINode(PHINode &I);
void visitBinaryOperator(Instruction &I); void visitBinaryOperator(Instruction &I);
void visitCastInst (CastInst &I); void visitCastInst (CastInst &I);
void visitCallInst (CallInst &I); void visitCallInst (CallInst &I);
void visitCallSite (CallSite CS);
void visitShiftInst(ShiftInst &I) { visitBinaryOperator(I); } void visitShiftInst(ShiftInst &I) { visitBinaryOperator(I); }
void visitMallocInst(MallocInst &I); void visitMallocInst(MallocInst &I);
@ -589,7 +592,7 @@ static void generateCompilerSpecificCode(std::ostream& Out) {
// We output GCC specific attributes to preserve 'linkonce'ness on globals. // We output GCC specific attributes to preserve 'linkonce'ness on globals.
// If we aren't being compiled with GCC, just drop these attributes. // If we aren't being compiled with GCC, just drop these attributes.
Out << "#ifndef __GNUC__\n" Out << "#ifndef __GNUC__ /* Can only support \"linkonce\" vars with GCC */\n"
<< "#define __attribute__(X)\n" << "#define __attribute__(X)\n"
<< "#endif\n"; << "#endif\n";
} }
@ -628,6 +631,11 @@ void CWriter::printModule(Module *M) {
<< "typedef unsigned long long ConstantDoubleTy;\n" << "typedef unsigned long long ConstantDoubleTy;\n"
<< "typedef unsigned int ConstantFloatTy;\n" << "typedef unsigned int ConstantFloatTy;\n"
<< "\n\n/* Support for the invoke instruction */\n"
<< "extern struct __llvm_jmpbuf_list_t {\n"
<< " jmp_buf buf; struct __llvm_jmpbuf_list_t *next;\n"
<< "} *__llvm_jmpbuf_list;\n"
<< "\n\n/* Global Declarations */\n"; << "\n\n/* Global Declarations */\n";
// First output all the declarations for the program, because C requires // First output all the declarations for the program, because C requires
@ -703,11 +711,20 @@ void CWriter::printModule(Module *M) {
} }
// Output all of the functions... // Output all of the functions...
emittedInvoke = false;
if (!M->empty()) { if (!M->empty()) {
Out << "\n\n/* Function Bodies */\n"; Out << "\n\n/* Function Bodies */\n";
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
printFunction(I); printFunction(I);
} }
// If the program included an invoke instruction, we need to output the
// support code for it here!
if (emittedInvoke) {
Out << "\n/* More support for the invoke instruction */\n"
<< "struct __llvm_jmpbuf_list_t *__llvm_jmpbuf_list "
<< "__attribute__((common)) = 0;\n";
}
} }
@ -982,6 +999,24 @@ void CWriter::visitSwitchInst(SwitchInst &SI) {
Out << " }\n"; Out << " }\n";
} }
void CWriter::visitInvokeInst(InvokeInst &II) {
Out << " {\n"
<< " struct __llvm_jmpbuf_list_t Entry;\n"
<< " Entry.next = __llvm_jmpbuf_list;\n"
<< " if (setjmp(Entry.buf)) {\n"
<< " __llvm_jmpbuf_list = Entry.next;\n";
printBranchToBlock(II.getParent(), II.getExceptionalDest(), 4);
Out << " }\n"
<< " __llvm_jmpbuf_list = &Entry;\n"
<< " ";
visitCallSite(&II);
Out << ";\n"
<< " __llvm_jmpbuf_list = Entry.next;\n"
<< " }\n";
printBranchToBlock(II.getParent(), II.getNormalDest(), 0);
emittedInvoke = true;
}
static bool isGotoCodeNeccessary(BasicBlock *From, BasicBlock *To) { static bool isGotoCodeNeccessary(BasicBlock *From, BasicBlock *To) {
// If PHI nodes need copies, we need the copy code... // If PHI nodes need copies, we need the copy code...
@ -994,7 +1029,7 @@ static bool isGotoCodeNeccessary(BasicBlock *From, BasicBlock *To) {
} }
void CWriter::printBranchToBlock(BasicBlock *CurBB, BasicBlock *Succ, void CWriter::printBranchToBlock(BasicBlock *CurBB, BasicBlock *Succ,
unsigned Indent) { unsigned Indent) {
for (BasicBlock::iterator I = Succ->begin(); for (BasicBlock::iterator I = Succ->begin();
PHINode *PN = dyn_cast<PHINode>(I); ++I) { PHINode *PN = dyn_cast<PHINode>(I); ++I) {
// now we have to do the printing // now we have to do the printing
@ -1156,20 +1191,24 @@ void CWriter::visitCallInst(CallInst &I) {
return; return;
} }
} }
visitCallSite(&I);
}
const PointerType *PTy = cast<PointerType>(I.getCalledValue()->getType()); void CWriter::visitCallSite(CallSite CS) {
const PointerType *PTy = cast<PointerType>(CS.getCalledValue()->getType());
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
const Type *RetTy = FTy->getReturnType(); const Type *RetTy = FTy->getReturnType();
writeOperand(I.getOperand(0)); writeOperand(CS.getCalledValue());
Out << "("; Out << "(";
if (I.getNumOperands() > 1) { if (CS.arg_begin() != CS.arg_end()) {
writeOperand(I.getOperand(1)); CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
writeOperand(*AI);
for (unsigned op = 2, Eop = I.getNumOperands(); op != Eop; ++op) { for (++AI; AI != AE; ++AI) {
Out << ", "; Out << ", ";
writeOperand(I.getOperand(op)); writeOperand(*AI);
} }
} }
Out << ")"; Out << ")";

View File

@ -17,6 +17,7 @@
#include "llvm/Analysis/ConstantsScanner.h" #include "llvm/Analysis/ConstantsScanner.h"
#include "llvm/Support/InstVisitor.h" #include "llvm/Support/InstVisitor.h"
#include "llvm/Support/InstIterator.h" #include "llvm/Support/InstIterator.h"
#include "llvm/Support/CallSite.h"
#include "Support/StringExtras.h" #include "Support/StringExtras.h"
#include "Support/STLExtras.h" #include "Support/STLExtras.h"
#include <algorithm> #include <algorithm>
@ -30,7 +31,7 @@ namespace {
const Module *TheModule; const Module *TheModule;
std::map<const Type *, std::string> TypeNames; std::map<const Type *, std::string> TypeNames;
std::set<const Value*> MangledGlobals; std::set<const Value*> MangledGlobals;
bool needsMalloc; bool needsMalloc, emittedInvoke;
std::map<const ConstantFP *, unsigned> FPConstantMap; std::map<const ConstantFP *, unsigned> FPConstantMap;
public: public:
@ -117,12 +118,14 @@ namespace {
void visitReturnInst(ReturnInst &I); void visitReturnInst(ReturnInst &I);
void visitBranchInst(BranchInst &I); void visitBranchInst(BranchInst &I);
void visitSwitchInst(SwitchInst &I); void visitSwitchInst(SwitchInst &I);
void visitInvokeInst(InvokeInst &I);
void visitPHINode(PHINode &I); void visitPHINode(PHINode &I);
void visitBinaryOperator(Instruction &I); void visitBinaryOperator(Instruction &I);
void visitCastInst (CastInst &I); void visitCastInst (CastInst &I);
void visitCallInst (CallInst &I); void visitCallInst (CallInst &I);
void visitCallSite (CallSite CS);
void visitShiftInst(ShiftInst &I) { visitBinaryOperator(I); } void visitShiftInst(ShiftInst &I) { visitBinaryOperator(I); }
void visitMallocInst(MallocInst &I); void visitMallocInst(MallocInst &I);
@ -589,7 +592,7 @@ static void generateCompilerSpecificCode(std::ostream& Out) {
// We output GCC specific attributes to preserve 'linkonce'ness on globals. // We output GCC specific attributes to preserve 'linkonce'ness on globals.
// If we aren't being compiled with GCC, just drop these attributes. // If we aren't being compiled with GCC, just drop these attributes.
Out << "#ifndef __GNUC__\n" Out << "#ifndef __GNUC__ /* Can only support \"linkonce\" vars with GCC */\n"
<< "#define __attribute__(X)\n" << "#define __attribute__(X)\n"
<< "#endif\n"; << "#endif\n";
} }
@ -628,6 +631,11 @@ void CWriter::printModule(Module *M) {
<< "typedef unsigned long long ConstantDoubleTy;\n" << "typedef unsigned long long ConstantDoubleTy;\n"
<< "typedef unsigned int ConstantFloatTy;\n" << "typedef unsigned int ConstantFloatTy;\n"
<< "\n\n/* Support for the invoke instruction */\n"
<< "extern struct __llvm_jmpbuf_list_t {\n"
<< " jmp_buf buf; struct __llvm_jmpbuf_list_t *next;\n"
<< "} *__llvm_jmpbuf_list;\n"
<< "\n\n/* Global Declarations */\n"; << "\n\n/* Global Declarations */\n";
// First output all the declarations for the program, because C requires // First output all the declarations for the program, because C requires
@ -703,11 +711,20 @@ void CWriter::printModule(Module *M) {
} }
// Output all of the functions... // Output all of the functions...
emittedInvoke = false;
if (!M->empty()) { if (!M->empty()) {
Out << "\n\n/* Function Bodies */\n"; Out << "\n\n/* Function Bodies */\n";
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
printFunction(I); printFunction(I);
} }
// If the program included an invoke instruction, we need to output the
// support code for it here!
if (emittedInvoke) {
Out << "\n/* More support for the invoke instruction */\n"
<< "struct __llvm_jmpbuf_list_t *__llvm_jmpbuf_list "
<< "__attribute__((common)) = 0;\n";
}
} }
@ -982,6 +999,24 @@ void CWriter::visitSwitchInst(SwitchInst &SI) {
Out << " }\n"; Out << " }\n";
} }
void CWriter::visitInvokeInst(InvokeInst &II) {
Out << " {\n"
<< " struct __llvm_jmpbuf_list_t Entry;\n"
<< " Entry.next = __llvm_jmpbuf_list;\n"
<< " if (setjmp(Entry.buf)) {\n"
<< " __llvm_jmpbuf_list = Entry.next;\n";
printBranchToBlock(II.getParent(), II.getExceptionalDest(), 4);
Out << " }\n"
<< " __llvm_jmpbuf_list = &Entry;\n"
<< " ";
visitCallSite(&II);
Out << ";\n"
<< " __llvm_jmpbuf_list = Entry.next;\n"
<< " }\n";
printBranchToBlock(II.getParent(), II.getNormalDest(), 0);
emittedInvoke = true;
}
static bool isGotoCodeNeccessary(BasicBlock *From, BasicBlock *To) { static bool isGotoCodeNeccessary(BasicBlock *From, BasicBlock *To) {
// If PHI nodes need copies, we need the copy code... // If PHI nodes need copies, we need the copy code...
@ -994,7 +1029,7 @@ static bool isGotoCodeNeccessary(BasicBlock *From, BasicBlock *To) {
} }
void CWriter::printBranchToBlock(BasicBlock *CurBB, BasicBlock *Succ, void CWriter::printBranchToBlock(BasicBlock *CurBB, BasicBlock *Succ,
unsigned Indent) { unsigned Indent) {
for (BasicBlock::iterator I = Succ->begin(); for (BasicBlock::iterator I = Succ->begin();
PHINode *PN = dyn_cast<PHINode>(I); ++I) { PHINode *PN = dyn_cast<PHINode>(I); ++I) {
// now we have to do the printing // now we have to do the printing
@ -1156,20 +1191,24 @@ void CWriter::visitCallInst(CallInst &I) {
return; return;
} }
} }
visitCallSite(&I);
}
const PointerType *PTy = cast<PointerType>(I.getCalledValue()->getType()); void CWriter::visitCallSite(CallSite CS) {
const PointerType *PTy = cast<PointerType>(CS.getCalledValue()->getType());
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
const Type *RetTy = FTy->getReturnType(); const Type *RetTy = FTy->getReturnType();
writeOperand(I.getOperand(0)); writeOperand(CS.getCalledValue());
Out << "("; Out << "(";
if (I.getNumOperands() > 1) { if (CS.arg_begin() != CS.arg_end()) {
writeOperand(I.getOperand(1)); CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
writeOperand(*AI);
for (unsigned op = 2, Eop = I.getNumOperands(); op != Eop; ++op) { for (++AI; AI != AE; ++AI) {
Out << ", "; Out << ", ";
writeOperand(I.getOperand(op)); writeOperand(*AI);
} }
} }
Out << ")"; Out << ")";