mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-21 06:30:16 +00:00
Add support for alloca, implementing ctor-list-opt.ll:CTOR6
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@23452 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
33c36f399f
commit
a22fdb0a37
@ -1380,21 +1380,28 @@ static bool EvaluateStaticConstructor(Function *F) {
|
|||||||
/// we can only evaluate any one basic block at most once. This set keeps
|
/// we can only evaluate any one basic block at most once. This set keeps
|
||||||
/// track of what we have executed so we can detect recursive cases etc.
|
/// track of what we have executed so we can detect recursive cases etc.
|
||||||
std::set<BasicBlock*> ExecutedBlocks;
|
std::set<BasicBlock*> ExecutedBlocks;
|
||||||
|
|
||||||
|
/// AllocaTmps - To 'execute' an alloca, we create a temporary global variable
|
||||||
|
/// to represent its body. This allows us to delete the temporary globals
|
||||||
|
/// when we are done.
|
||||||
|
std::vector<GlobalVariable*> AllocaTmps;
|
||||||
|
|
||||||
// CurInst - The current instruction we're evaluating.
|
// CurInst - The current instruction we're evaluating.
|
||||||
BasicBlock::iterator CurInst = F->begin()->begin();
|
BasicBlock::iterator CurInst = F->begin()->begin();
|
||||||
ExecutedBlocks.insert(F->begin());
|
ExecutedBlocks.insert(F->begin());
|
||||||
|
|
||||||
|
bool EvaluationSuccessful = false;
|
||||||
|
|
||||||
// This is the main evaluation loop.
|
// This is the main evaluation loop.
|
||||||
while (1) {
|
while (1) {
|
||||||
Constant *InstResult = 0;
|
Constant *InstResult = 0;
|
||||||
|
|
||||||
if (StoreInst *SI = dyn_cast<StoreInst>(CurInst)) {
|
if (StoreInst *SI = dyn_cast<StoreInst>(CurInst)) {
|
||||||
if (SI->isVolatile()) return false; // no volatile accesses.
|
if (SI->isVolatile()) break; // no volatile accesses.
|
||||||
Constant *Ptr = getVal(Values, SI->getOperand(1));
|
Constant *Ptr = getVal(Values, SI->getOperand(1));
|
||||||
if (!isSimpleEnoughPointerToCommit(Ptr))
|
if (!isSimpleEnoughPointerToCommit(Ptr))
|
||||||
// If this is too complex for us to commit, reject it.
|
// If this is too complex for us to commit, reject it.
|
||||||
return false;
|
break;
|
||||||
Constant *Val = getVal(Values, SI->getOperand(0));
|
Constant *Val = getVal(Values, SI->getOperand(0));
|
||||||
MutatedMemory[Ptr] = Val;
|
MutatedMemory[Ptr] = Val;
|
||||||
} else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CurInst)) {
|
} else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(CurInst)) {
|
||||||
@ -1419,10 +1426,18 @@ static bool EvaluateStaticConstructor(Function *F) {
|
|||||||
GEPOps.push_back(getVal(Values, GEP->getOperand(i)));
|
GEPOps.push_back(getVal(Values, GEP->getOperand(i)));
|
||||||
InstResult = ConstantExpr::getGetElementPtr(P, GEPOps);
|
InstResult = ConstantExpr::getGetElementPtr(P, GEPOps);
|
||||||
} else if (LoadInst *LI = dyn_cast<LoadInst>(CurInst)) {
|
} else if (LoadInst *LI = dyn_cast<LoadInst>(CurInst)) {
|
||||||
if (LI->isVolatile()) return false; // no volatile accesses.
|
if (LI->isVolatile()) break; // no volatile accesses.
|
||||||
InstResult = ComputeLoadResult(getVal(Values, LI->getOperand(0)),
|
InstResult = ComputeLoadResult(getVal(Values, LI->getOperand(0)),
|
||||||
MutatedMemory);
|
MutatedMemory);
|
||||||
if (InstResult == 0) return false; // Could not evaluate load.
|
if (InstResult == 0) break; // Could not evaluate load.
|
||||||
|
} else if (AllocaInst *AI = dyn_cast<AllocaInst>(CurInst)) {
|
||||||
|
if (AI->isArrayAllocation()) break; // Cannot handle array allocs.
|
||||||
|
const Type *Ty = AI->getType()->getElementType();
|
||||||
|
AllocaTmps.push_back(new GlobalVariable(Ty, false,
|
||||||
|
GlobalValue::InternalLinkage,
|
||||||
|
UndefValue::get(Ty),
|
||||||
|
AI->getName()));
|
||||||
|
InstResult = AllocaTmps.back();
|
||||||
} else if (TerminatorInst *TI = dyn_cast<TerminatorInst>(CurInst)) {
|
} else if (TerminatorInst *TI = dyn_cast<TerminatorInst>(CurInst)) {
|
||||||
BasicBlock *NewBB = 0;
|
BasicBlock *NewBB = 0;
|
||||||
if (BranchInst *BI = dyn_cast<BranchInst>(CurInst)) {
|
if (BranchInst *BI = dyn_cast<BranchInst>(CurInst)) {
|
||||||
@ -1431,27 +1446,28 @@ static bool EvaluateStaticConstructor(Function *F) {
|
|||||||
} else {
|
} else {
|
||||||
ConstantBool *Cond =
|
ConstantBool *Cond =
|
||||||
dyn_cast<ConstantBool>(getVal(Values, BI->getCondition()));
|
dyn_cast<ConstantBool>(getVal(Values, BI->getCondition()));
|
||||||
if (!Cond) return false; // Cannot determine.
|
if (!Cond) break; // Cannot determine.
|
||||||
NewBB = BI->getSuccessor(!Cond->getValue());
|
NewBB = BI->getSuccessor(!Cond->getValue());
|
||||||
}
|
}
|
||||||
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(CurInst)) {
|
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(CurInst)) {
|
||||||
ConstantInt *Val =
|
ConstantInt *Val =
|
||||||
dyn_cast<ConstantInt>(getVal(Values, SI->getCondition()));
|
dyn_cast<ConstantInt>(getVal(Values, SI->getCondition()));
|
||||||
if (!Val) return false; // Cannot determine.
|
if (!Val) break; // Cannot determine.
|
||||||
NewBB = SI->getSuccessor(SI->findCaseValue(Val));
|
NewBB = SI->getSuccessor(SI->findCaseValue(Val));
|
||||||
} else if (ReturnInst *RI = dyn_cast<ReturnInst>(CurInst)) {
|
} else if (ReturnInst *RI = dyn_cast<ReturnInst>(CurInst)) {
|
||||||
assert(RI->getNumOperands() == 0);
|
assert(RI->getNumOperands() == 0);
|
||||||
|
EvaluationSuccessful = true;
|
||||||
break; // We succeeded at evaluating this ctor!
|
break; // We succeeded at evaluating this ctor!
|
||||||
} else {
|
} else {
|
||||||
// unwind, unreachable.
|
// unwind, unreachable.
|
||||||
return false; // Cannot handle this terminator.
|
break; // Cannot handle this terminator.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Okay, we succeeded in evaluating this control flow. See if we have
|
// Okay, we succeeded in evaluating this control flow. See if we have
|
||||||
// executed the new block before. If so, we have a looping or recursive
|
// executed the new block before. If so, we have a looping or recursive
|
||||||
// function, which we cannot evaluate in reasonable time.
|
// function, which we cannot evaluate in reasonable time.
|
||||||
if (!ExecutedBlocks.insert(NewBB).second)
|
if (!ExecutedBlocks.insert(NewBB).second)
|
||||||
return false; // Recursed!
|
break; // Recursed/looped!
|
||||||
|
|
||||||
// Okay, we have never been in this block before. Check to see if there
|
// Okay, we have never been in this block before. Check to see if there
|
||||||
// are any PHI nodes. If so, evaluate them with information about where
|
// are any PHI nodes. If so, evaluate them with information about where
|
||||||
@ -1468,7 +1484,7 @@ static bool EvaluateStaticConstructor(Function *F) {
|
|||||||
// TODO: use ConstantFoldCall for function calls.
|
// TODO: use ConstantFoldCall for function calls.
|
||||||
|
|
||||||
// Did not know how to evaluate this!
|
// Did not know how to evaluate this!
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CurInst->use_empty())
|
if (!CurInst->use_empty())
|
||||||
@ -1477,16 +1493,31 @@ static bool EvaluateStaticConstructor(Function *F) {
|
|||||||
// Advance program counter.
|
// Advance program counter.
|
||||||
++CurInst;
|
++CurInst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (EvaluationSuccessful) {
|
||||||
|
// We succeeded at evaluation: commit the result.
|
||||||
|
DEBUG(std::cerr << "FULLY EVALUATED GLOBAL CTOR FUNCTION '" <<
|
||||||
|
F->getName() << "'\n");
|
||||||
|
for (std::map<Constant*, Constant*>::iterator I = MutatedMemory.begin(),
|
||||||
|
E = MutatedMemory.end(); I != E; ++I)
|
||||||
|
CommitValueTo(I->second, I->first);
|
||||||
|
}
|
||||||
|
|
||||||
// If we get here, we know that we succeeded at evaluation: commit the result.
|
// At this point, we are done interpreting. If we created any 'alloca'
|
||||||
//
|
// temporaries, release them now.
|
||||||
for (std::map<Constant*, Constant*>::iterator I = MutatedMemory.begin(),
|
while (!AllocaTmps.empty()) {
|
||||||
E = MutatedMemory.end(); I != E; ++I)
|
GlobalVariable *Tmp = AllocaTmps.back();
|
||||||
CommitValueTo(I->second, I->first);
|
AllocaTmps.pop_back();
|
||||||
|
|
||||||
|
// If there are still users of the alloca, the program is doing something
|
||||||
|
// silly, e.g. storing the address of the alloca somewhere and using it
|
||||||
|
// later. Since this is undefined, we'll just make it be null.
|
||||||
|
if (!Tmp->use_empty())
|
||||||
|
Tmp->replaceAllUsesWith(Constant::getNullValue(Tmp->getType()));
|
||||||
|
delete Tmp;
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG(std::cerr << "FULLY EVALUATED GLOBAL CTOR FUNCTION '" <<
|
return EvaluationSuccessful;
|
||||||
F->getName() << "'\n");
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user