Handle "known" external calls context sensitively, add support for realloc

and a couple of other functions that are important.

Handle aggregate undef values for gv initializers

llvm-svn: 20914
This commit is contained in:
Chris Lattner 2005-03-29 06:09:07 +00:00
parent 60956dd52f
commit 7617e886c1
1 changed files with 29 additions and 17 deletions

View File

@ -306,8 +306,8 @@ namespace {
void AddGlobalInitializerConstraints(Node *N, Constant *C); void AddGlobalInitializerConstraints(Node *N, Constant *C);
void AddConstraintsForNonInternalLinkage(Function *F); void AddConstraintsForNonInternalLinkage(Function *F);
bool AddConstraintsForExternalFunction(Function *F);
void AddConstraintsForCall(CallSite CS, Function *F); void AddConstraintsForCall(CallSite CS, Function *F);
bool AddConstraintsForExternalCall(CallSite CS, Function *F);
void PrintNode(Node *N); void PrintNode(Node *N);
@ -581,7 +581,7 @@ void Andersens::AddGlobalInitializerConstraints(Node *N, Constant *C) {
} else if (C->isNullValue()) { } else if (C->isNullValue()) {
N->addPointerTo(&GraphNodes[NullObject]); N->addPointerTo(&GraphNodes[NullObject]);
return; return;
} else { } else if (!isa<UndefValue>(C)) {
// If this is an array or struct, include constraints for each element. // If this is an array or struct, include constraints for each element.
assert(isa<ConstantArray>(C) || isa<ConstantStruct>(C)); assert(isa<ConstantArray>(C) || isa<ConstantStruct>(C));
for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)
@ -601,32 +601,41 @@ void Andersens::AddConstraintsForNonInternalLinkage(Function *F) {
&GraphNodes[UniversalSet])); &GraphNodes[UniversalSet]));
} }
/// AddConstraintsForExternalFunction - If this is a call to a "known" function, /// AddConstraintsForCall - If this is a call to a "known" function, add the
/// add the constraints and return false. If this is a call to an unknown /// constraints and return true. If this is a call to an unknown function,
/// function, return true. /// return false.
bool Andersens::AddConstraintsForExternalFunction(Function *F) { bool Andersens::AddConstraintsForExternalCall(CallSite CS, Function *F) {
assert(F->isExternal() && "Not an external function!"); assert(F->isExternal() && "Not an external function!");
// These functions don't induce any points-to constraints. // These functions don't induce any points-to constraints.
if (F->getName() == "printf" || F->getName() == "fprintf" || if (F->getName() == "printf" || F->getName() == "fprintf" ||
F->getName() == "fgets" ||
F->getName() == "open" || F->getName() == "fopen" || F->getName() == "open" || F->getName() == "fopen" ||
F->getName() == "atoi" || F->getName() == "fclose" || F->getName() == "fflush" ||
F->getName() == "atoi" || F->getName() == "sscanf" ||
F->getName() == "llvm.memset" || F->getName() == "memcmp" || F->getName() == "llvm.memset" || F->getName() == "memcmp" ||
F->getName() == "read" || F->getName() == "write") F->getName() == "read" || F->getName() == "write")
return false; return true;
// These functions do induce points-to edges. // These functions do induce points-to edges.
if (F->getName() == "llvm.memcpy" || F->getName() == "llvm.memmove") { if (F->getName() == "llvm.memcpy" || F->getName() == "llvm.memmove") {
Function::arg_iterator Dst = F->arg_begin(), Src = Dst;
// Note: this is a poor approximation, this says Dest = Src, instead of // Note: this is a poor approximation, this says Dest = Src, instead of
// *Dest = *Src. // *Dest = *Src.
++Src; Constraints.push_back(Constraint(Constraint::Copy,
Constraints.push_back(Constraint(Constraint::Copy, getNode(Dst), getNode(CS.getArgument(0)),
getNode(Src))); getNode(CS.getArgument(1))));
return false; return true;
} }
return true; if (F->getName() == "realloc") {
// Result = Arg
Constraints.push_back(Constraint(Constraint::Copy,
getNode(CS.getInstruction()),
getNode(CS.getArgument(0))));
return true;
}
return false;
} }
@ -689,9 +698,7 @@ void Andersens::CollectConstraints(Module &M) {
// allocation in the body of the function and a node to represent all // allocation in the body of the function and a node to represent all
// pointer values defined by instructions and used as operands. // pointer values defined by instructions and used as operands.
visit(F); visit(F);
} else if (AddConstraintsForExternalFunction(F)) { } else {
// If we don't "know" about this function, assume the worst.
// External functions that return pointers return the universal set. // External functions that return pointers return the universal set.
if (isa<PointerType>(F->getFunctionType()->getReturnType())) if (isa<PointerType>(F->getFunctionType()->getReturnType()))
Constraints.push_back(Constraint(Constraint::Copy, Constraints.push_back(Constraint(Constraint::Copy,
@ -836,6 +843,11 @@ void Andersens::visitVAArg(VAArgInst &I) {
/// the function pointer has been casted. If this is the case, do something /// the function pointer has been casted. If this is the case, do something
/// reasonable. /// reasonable.
void Andersens::AddConstraintsForCall(CallSite CS, Function *F) { void Andersens::AddConstraintsForCall(CallSite CS, Function *F) {
// If this is a call to an external function, handle it directly to get some
// taste of context sensitivity.
if (F->isExternal() && AddConstraintsForExternalCall(CS, F))
return;
if (isa<PointerType>(CS.getType())) { if (isa<PointerType>(CS.getType())) {
Node *CSN = getNode(CS.getInstruction()); Node *CSN = getNode(CS.getInstruction());
if (isa<PointerType>(F->getFunctionType()->getReturnType())) { if (isa<PointerType>(F->getFunctionType()->getReturnType())) {