mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-06 23:32:27 +00:00
Split the External and Intrinsic handling into seperate functions. This
improves readability of the call handling code significantly, as well as makes it clear which parts are hacky (externals) and which parts are good (call handling). No functionality change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31415 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e6e97e66a3
commit
118c094176
@ -131,6 +131,8 @@ namespace {
|
||||
void visitCastInst(CastInst &CI);
|
||||
void visitInstruction(Instruction &I);
|
||||
|
||||
bool visitIntrinsic(CallSite CS, Function* F);
|
||||
bool visitExternal(CallSite CS, Function* F);
|
||||
void visitCallSite(CallSite CS);
|
||||
void visitVAArgInst(VAArgInst &I);
|
||||
|
||||
@ -406,8 +408,9 @@ void GraphBuilder::visitGetElementPtrInst(User &GEP) {
|
||||
for (gep_type_iterator I = gep_type_begin(GEP), E = gep_type_end(GEP);
|
||||
I != E; ++I)
|
||||
if (const StructType *STy = dyn_cast<StructType>(*I)) {
|
||||
const ConstantInt* CUI = cast<ConstantInt>(I.getOperand());
|
||||
unsigned FieldNo =
|
||||
(unsigned)cast<ConstantInt>(I.getOperand())->getZExtValue();
|
||||
CUI->getType()->isSigned() ? CUI->getSExtValue() : CUI->getZExtValue();
|
||||
Offset += (unsigned)TD.getStructLayout(STy)->MemberOffsets[FieldNo];
|
||||
} else if (isa<PointerType>(*I)) {
|
||||
if (!isa<Constant>(I.getOperand()) ||
|
||||
@ -420,7 +423,9 @@ void GraphBuilder::visitGetElementPtrInst(User &GEP) {
|
||||
if (const SequentialType *STy = cast<SequentialType>(*I)) {
|
||||
CurTy = STy->getElementType();
|
||||
if (ConstantInt *CS = dyn_cast<ConstantInt>(GEP.getOperand(i))) {
|
||||
Offset += CS->getValue()*TD.getTypeSize(CurTy);
|
||||
Offset +=
|
||||
(CS->getType()->isSigned() ? CS->getSExtValue() : CS->getZExtValue())
|
||||
* TD.getTypeSize(CurTy);
|
||||
} else {
|
||||
// Variable index into a node. We must merge all of the elements of the
|
||||
// sequential type here.
|
||||
@ -529,25 +534,21 @@ void GraphBuilder::visitInvokeInst(InvokeInst &II) {
|
||||
visitCallSite(&II);
|
||||
}
|
||||
|
||||
void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
Value *Callee = CS.getCalledValue();
|
||||
|
||||
// Special case handling of certain libc allocation functions here.
|
||||
if (Function *F = dyn_cast<Function>(Callee))
|
||||
if (F->isExternal())
|
||||
/// returns true if the intrinsic is handled
|
||||
bool GraphBuilder::visitIntrinsic(CallSite CS, Function *F) {
|
||||
switch (F->getIntrinsicID()) {
|
||||
case Intrinsic::vastart:
|
||||
getValueDest(*CS.getInstruction()).getNode()->setAllocaNodeMarker();
|
||||
return;
|
||||
return true;
|
||||
case Intrinsic::vacopy:
|
||||
getValueDest(*CS.getInstruction()).
|
||||
mergeWith(getValueDest(**(CS.arg_begin())));
|
||||
return;
|
||||
return true;
|
||||
case Intrinsic::vaend:
|
||||
case Intrinsic::dbg_func_start:
|
||||
case Intrinsic::dbg_region_end:
|
||||
case Intrinsic::dbg_stoppoint:
|
||||
return; // noop
|
||||
return true; // noop
|
||||
case Intrinsic::memcpy_i32:
|
||||
case Intrinsic::memcpy_i64:
|
||||
case Intrinsic::memmove_i32:
|
||||
@ -558,57 +559,36 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
RetNH.mergeWith(getValueDest(**(CS.arg_begin()+1)));
|
||||
if (DSNode *N = RetNH.getNode())
|
||||
N->setModifiedMarker()->setReadMarker();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
case Intrinsic::memset_i32:
|
||||
case Intrinsic::memset_i64:
|
||||
// Mark the memory modified.
|
||||
if (DSNode *N = getValueDest(**CS.arg_begin()).getNode())
|
||||
N->setModifiedMarker();
|
||||
return;
|
||||
return true;
|
||||
default:
|
||||
// Determine if the called function is one of the specified heap
|
||||
// allocation functions
|
||||
for (cl::list<std::string>::iterator AllocFunc = AllocList.begin(),
|
||||
LastAllocFunc = AllocList.end();
|
||||
AllocFunc != LastAllocFunc;
|
||||
++AllocFunc) {
|
||||
if (F->getName() == *(AllocFunc)) {
|
||||
setDestTo(*CS.getInstruction(),
|
||||
createNode()->setHeapNodeMarker()->setModifiedMarker());
|
||||
return;
|
||||
DEBUG(std::cerr << "[dsa:local] Unhandled intrinsic: " << F->getName() << "\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if the called function is one of the specified heap
|
||||
// free functions
|
||||
for (cl::list<std::string>::iterator FreeFunc = FreeList.begin(),
|
||||
LastFreeFunc = FreeList.end();
|
||||
FreeFunc != LastFreeFunc;
|
||||
++FreeFunc) {
|
||||
if (F->getName() == *(FreeFunc)) {
|
||||
// Mark that the node is written to...
|
||||
if (DSNode *N = getValueDest(*(CS.getArgument(0))).getNode())
|
||||
N->setModifiedMarker()->setHeapNodeMarker();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//gets select localtime ioctl
|
||||
|
||||
if ((F->isExternal() && F->getName() == "calloc")
|
||||
/// returns true if the external is a recognized libc function with a
|
||||
/// known (and generated) graph
|
||||
bool GraphBuilder::visitExternal(CallSite CS, Function *F) {
|
||||
if (F->getName() == "calloc"
|
||||
|| F->getName() == "posix_memalign"
|
||||
|| F->getName() == "memalign" || F->getName() == "valloc") {
|
||||
setDestTo(*CS.getInstruction(),
|
||||
createNode()->setHeapNodeMarker()->setModifiedMarker());
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "realloc") {
|
||||
DSNodeHandle RetNH = getValueDest(*CS.getInstruction());
|
||||
if (CS.arg_begin() != CS.arg_end())
|
||||
RetNH.mergeWith(getValueDest(**CS.arg_begin()));
|
||||
if (DSNode *N = RetNH.getNode())
|
||||
N->setHeapNodeMarker()->setModifiedMarker()->setReadMarker();
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "memmove") {
|
||||
// Merge the first & second arguments, and mark the memory read and
|
||||
// modified.
|
||||
@ -616,7 +596,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
RetNH.mergeWith(getValueDest(**(CS.arg_begin()+1)));
|
||||
if (DSNode *N = RetNH.getNode())
|
||||
N->setModifiedMarker()->setReadMarker();
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "free") {
|
||||
// Mark that the node is written to...
|
||||
if (DSNode *N = getValueDest(**CS.arg_begin()).getNode())
|
||||
@ -641,14 +621,14 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setReadMarker();
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "memchr") {
|
||||
DSNodeHandle RetNH = getValueDest(**CS.arg_begin());
|
||||
DSNodeHandle Result = getValueDest(*CS.getInstruction());
|
||||
RetNH.mergeWith(Result);
|
||||
if (DSNode *N = RetNH.getNode())
|
||||
N->setReadMarker();
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "read" || F->getName() == "pipe" ||
|
||||
F->getName() == "wait" || F->getName() == "time" ||
|
||||
F->getName() == "getrusage") {
|
||||
@ -659,7 +639,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setModifiedMarker();
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "stat" || F->getName() == "fstat" ||
|
||||
F->getName() == "lstat") {
|
||||
// These functions read their first operand if its a pointer.
|
||||
@ -677,7 +657,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
if (const PointerType *PTy = dyn_cast<PointerType>(StatTy))
|
||||
N->mergeTypeInfo(PTy->getElementType(), StatBuf.getOffset());
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "strtod" || F->getName() == "strtof" ||
|
||||
F->getName() == "strtold") {
|
||||
// These functions read the first pointer
|
||||
@ -694,7 +674,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
Link.mergeWith(getValueDest(**CS.arg_begin()));
|
||||
}
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "fopen" || F->getName() == "fdopen" ||
|
||||
F->getName() == "freopen") {
|
||||
// These functions read all of their pointer operands.
|
||||
@ -722,7 +702,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
CallSite::arg_iterator compit = CS.arg_end();
|
||||
Result.mergeWith(getValueDest(**--compit));
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "fclose" && CS.arg_end()-CS.arg_begin() ==1){
|
||||
// fclose reads and deallocates the memory in an unknown way for the
|
||||
// file descriptor. It merges the FILE type into the descriptor.
|
||||
@ -733,7 +713,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
|
||||
N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} else if (CS.arg_end()-CS.arg_begin() == 1 &&
|
||||
(F->getName() == "fflush" || F->getName() == "feof" ||
|
||||
F->getName() == "fileno" || F->getName() == "clearerr" ||
|
||||
@ -750,7 +730,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
|
||||
N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} else if (CS.arg_end()-CS.arg_begin() == 4 &&
|
||||
(F->getName() == "fwrite" || F->getName() == "fread")) {
|
||||
// fread writes the first operand, fwrite reads it. They both
|
||||
@ -770,7 +750,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
N->setReadMarker();
|
||||
else
|
||||
N->setModifiedMarker();
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "fgets" && CS.arg_end()-CS.arg_begin() == 3){
|
||||
// fgets reads and writes the memory for the file descriptor. It
|
||||
// merges the FILE type into the descriptor, and writes to the
|
||||
@ -790,7 +770,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
|
||||
N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "ungetc" || F->getName() == "fputc" ||
|
||||
F->getName() == "fputs" || F->getName() == "putc" ||
|
||||
F->getName() == "ftell" || F->getName() == "rewind" ||
|
||||
@ -813,7 +793,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
if (isPointerType((*AI)->getType()))
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setReadMarker();
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "fseek" || F->getName() == "fgetpos" ||
|
||||
F->getName() == "fsetpos") {
|
||||
// These functions read and write the memory for the file descriptor,
|
||||
@ -832,7 +812,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
if (isPointerType((*AI)->getType()))
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setReadMarker()->setModifiedMarker();
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "printf" || F->getName() == "fprintf" ||
|
||||
F->getName() == "sprintf") {
|
||||
CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
|
||||
@ -864,7 +844,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setReadMarker();
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "vprintf" || F->getName() == "vfprintf" ||
|
||||
F->getName() == "vsprintf") {
|
||||
CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
|
||||
@ -912,7 +892,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "scanf" || F->getName() == "fscanf" ||
|
||||
F->getName() == "sscanf") {
|
||||
CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
|
||||
@ -944,7 +924,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setModifiedMarker();
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "strtok") {
|
||||
// strtok reads and writes the first argument, returning it. It reads
|
||||
// its second arg. FIXME: strtok also modifies some hidden static
|
||||
@ -966,7 +946,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
|
||||
N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "strchr" || F->getName() == "strrchr" ||
|
||||
F->getName() == "strstr") {
|
||||
// These read their arguments, and return the first one
|
||||
@ -981,14 +961,14 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
|
||||
if (DSNode *N = H.getNode())
|
||||
N->setReadMarker();
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "__assert_fail") {
|
||||
for (CallSite::arg_iterator AI = CS.arg_begin(), E = CS.arg_end();
|
||||
AI != E; ++AI)
|
||||
if (isPointerType((*AI)->getType()))
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setReadMarker();
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "modf" && CS.arg_end()-CS.arg_begin() == 2) {
|
||||
// This writes its second argument, and forces it to double.
|
||||
CallSite::arg_iterator compit = CS.arg_end();
|
||||
@ -997,7 +977,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
N->setModifiedMarker();
|
||||
N->mergeTypeInfo(Type::DoubleTy, H.getOffset());
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "strcat" || F->getName() == "strncat") {
|
||||
//This might be making unsafe assumptions about usage
|
||||
//Merge return and first arg
|
||||
@ -1008,7 +988,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
//and read second pointer
|
||||
if (DSNode *N = getValueDest(**(CS.arg_begin() + 1)).getNode())
|
||||
N->setReadMarker();
|
||||
return;
|
||||
return true;
|
||||
} else if (F->getName() == "strcpy" || F->getName() == "strncpy") {
|
||||
//This might be making unsafe assumptions about usage
|
||||
//Merge return and first arg
|
||||
@ -1019,8 +999,38 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
//and read second pointer
|
||||
if (DSNode *N = getValueDest(**(CS.arg_begin() + 1)).getNode())
|
||||
N->setReadMarker();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
Value *Callee = CS.getCalledValue();
|
||||
|
||||
// Special case handling of certain libc allocation functions here.
|
||||
if (Function *F = dyn_cast<Function>(Callee))
|
||||
if (F->isExternal())
|
||||
if (F->isIntrinsic() && visitIntrinsic(CS, F))
|
||||
return;
|
||||
else {
|
||||
// Determine if the called function is one of the specified heap
|
||||
// allocation functions
|
||||
if (AllocList.end() != std::find(AllocList.begin(), AllocList.end(), F->getName())) {
|
||||
setDestTo(*CS.getInstruction(),
|
||||
createNode()->setHeapNodeMarker()->setModifiedMarker());
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine if the called function is one of the specified heap
|
||||
// free functions
|
||||
if (FreeList.end() != std::find(FreeList.begin(), FreeList.end(), F->getName())) {
|
||||
// Mark that the node is written to...
|
||||
if (DSNode *N = getValueDest(*(CS.getArgument(0))).getNode())
|
||||
N->setModifiedMarker()->setHeapNodeMarker();
|
||||
return;
|
||||
}
|
||||
if (visitExternal(CS,F))
|
||||
return;
|
||||
} else {
|
||||
// Unknown function, warn if it returns a pointer type or takes a
|
||||
// pointer argument.
|
||||
bool Warn = isPointerType(CS.getInstruction()->getType());
|
||||
@ -1036,8 +1046,6 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
||||
<< F->getName() << "' will cause pessimistic results!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set up the return value...
|
||||
DSNodeHandle RetVal;
|
||||
|
Loading…
x
Reference in New Issue
Block a user