mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-07 12:28:24 +00:00
Implemented cleanups as suggested by Chris:
* Use Module::getNamedFunction() to delete "main" instead of using a loop * Compare function pointers instead of function names to determine equivalence * Simplified creation of a 2-element vector containing zeroes * Manually performed LICM on code * Added an abort() in case a function we're considering occurs in something that is not an instruction * Use DEBUG() around code sections instead of just in a statement in a loop, because GCC's DCE may not be good enough to completely remove it in a release build * Print out a command that can be directly copied-and-pasted to re-execute * Instead of just checking if a symbol begins with a dot and fixing it accordingly, use Mangler and fix all the problems (invalid chars in C symbol names) entirely * The new `main' function has external linkage git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@7371 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
#include "llvm/Module.h"
|
#include "llvm/Module.h"
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
#include "llvm/Analysis/Verifier.h"
|
#include "llvm/Analysis/Verifier.h"
|
||||||
|
#include "llvm/Support/Mangler.h"
|
||||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||||
#include "llvm/Transforms/Utils/Cloning.h"
|
#include "llvm/Transforms/Utils/Cloning.h"
|
||||||
#include "llvm/Transforms/Utils/Linker.h"
|
#include "llvm/Transforms/Utils/Linker.h"
|
||||||
@@ -94,8 +95,8 @@ bool ReduceMisCodegenFunctions::TestFuncs(const std::vector<Function*> &Funcs,
|
|||||||
// (called or taken address of), and make them call the JIT wrapper instead
|
// (called or taken address of), and make them call the JIT wrapper instead
|
||||||
if (BD.isExecutingJIT()) {
|
if (BD.isExecutingJIT()) {
|
||||||
// Must delete `main' from Safe module if it has it
|
// Must delete `main' from Safe module if it has it
|
||||||
for (Module::iterator I=SafeModule->begin(), E=SafeModule->end();I!=E;++I)
|
Function *safeMain = SafeModule->getNamedFunction("main");
|
||||||
if (I->getName() == "main") DeleteFunctionBody(I);
|
DeleteFunctionBody(safeMain);
|
||||||
|
|
||||||
// Add an external function "getPointerToNamedFunction" that JIT provides
|
// Add an external function "getPointerToNamedFunction" that JIT provides
|
||||||
// Prototype: void *getPointerToNamedFunction(const char* Name)
|
// Prototype: void *getPointerToNamedFunction(const char* Name)
|
||||||
@@ -103,17 +104,15 @@ bool ReduceMisCodegenFunctions::TestFuncs(const std::vector<Function*> &Funcs,
|
|||||||
Params.push_back(PointerType::get(Type::SByteTy)); // std::string&
|
Params.push_back(PointerType::get(Type::SByteTy)); // std::string&
|
||||||
FunctionType *resolverTy = FunctionType::get(PointerType::get(Type::VoidTy),
|
FunctionType *resolverTy = FunctionType::get(PointerType::get(Type::VoidTy),
|
||||||
Params, false /* isVarArg */);
|
Params, false /* isVarArg */);
|
||||||
const std::string ResolverFunctionName = "getPointerToNamedFunction";
|
|
||||||
Function *resolverFunc = new Function(resolverTy,
|
Function *resolverFunc = new Function(resolverTy,
|
||||||
GlobalValue::ExternalLinkage,
|
GlobalValue::ExternalLinkage,
|
||||||
ResolverFunctionName,
|
"getPointerToNamedFunction",
|
||||||
SafeModule);
|
SafeModule);
|
||||||
|
|
||||||
// Use the function we just added to get addresses of functions we need
|
// Use the function we just added to get addresses of functions we need
|
||||||
// Iterate over the global declarations in the Safe module
|
// Iterate over the global declarations in the Safe module
|
||||||
for (Module::iterator F=SafeModule->begin(),E=SafeModule->end(); F!=E; ++F){
|
for (Module::iterator F=SafeModule->begin(),E=SafeModule->end(); F!=E; ++F){
|
||||||
if (F->isExternal() && F->use_begin() != F->use_end() &&
|
if (F->isExternal() && !F->use_empty() && &(*F) != resolverFunc) {
|
||||||
F->getName() != ResolverFunctionName) {
|
|
||||||
// If it has a non-zero use list,
|
// If it has a non-zero use list,
|
||||||
// 1. Add a string constant with its name to the global file
|
// 1. Add a string constant with its name to the global file
|
||||||
// The correct type is `const [ NUM x sbyte ]' where NUM is length of
|
// The correct type is `const [ NUM x sbyte ]' where NUM is length of
|
||||||
@@ -129,26 +128,23 @@ bool ReduceMisCodegenFunctions::TestFuncs(const std::vector<Function*> &Funcs,
|
|||||||
|
|
||||||
// 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an
|
// 2. Use `GetElementPtr *funcName, 0, 0' to convert the string to an
|
||||||
// sbyte* so it matches the signature of the resolver function.
|
// sbyte* so it matches the signature of the resolver function.
|
||||||
Constant *Zero = Constant::getNullValue(Type::LongTy);
|
std::vector<Constant*> GEPargs(2, Constant::getNullValue(Type::LongTy));
|
||||||
std::vector<Constant*> GEPargs;
|
|
||||||
GEPargs.push_back(Zero);
|
|
||||||
GEPargs.push_back(Zero);
|
|
||||||
|
|
||||||
// 3. Replace all uses of `func' with calls to resolver by:
|
// 3. Replace all uses of `func' with calls to resolver by:
|
||||||
// (a) Iterating through the list of uses of this function
|
// (a) Iterating through the list of uses of this function
|
||||||
// (b) Insert a cast instruction in front of each use
|
// (b) Insert a cast instruction in front of each use
|
||||||
// (c) Replace use of old call with new call
|
// (c) Replace use of old call with new call
|
||||||
|
|
||||||
// Insert code at the beginning of the function
|
|
||||||
|
|
||||||
for (Value::use_iterator i=F->use_begin(), e=F->use_end(); i!=e; ++i) {
|
|
||||||
if (Instruction* Inst = dyn_cast<Instruction>(*i)) {
|
|
||||||
// GetElementPtr *funcName, ulong 0, ulong 0
|
// GetElementPtr *funcName, ulong 0, ulong 0
|
||||||
Value *GEP =
|
Value *GEP =
|
||||||
ConstantExpr::getGetElementPtr(ConstantPointerRef::get(funcName),
|
ConstantExpr::getGetElementPtr(ConstantPointerRef::get(funcName),
|
||||||
GEPargs);
|
GEPargs);
|
||||||
std::vector<Value*> ResolverArgs;
|
std::vector<Value*> ResolverArgs;
|
||||||
ResolverArgs.push_back(GEP);
|
ResolverArgs.push_back(GEP);
|
||||||
|
|
||||||
|
// Insert code at the beginning of the function
|
||||||
|
for (Value::use_iterator i=F->use_begin(), e=F->use_end(); i!=e; ++i) {
|
||||||
|
if (Instruction* Inst = dyn_cast<Instruction>(*i)) {
|
||||||
// call resolver(GetElementPtr...)
|
// call resolver(GetElementPtr...)
|
||||||
CallInst *resolve = new CallInst(resolverFunc, ResolverArgs,
|
CallInst *resolve = new CallInst(resolverFunc, ResolverArgs,
|
||||||
"resolver", Inst);
|
"resolver", Inst);
|
||||||
@@ -158,27 +154,32 @@ bool ReduceMisCodegenFunctions::TestFuncs(const std::vector<Function*> &Funcs,
|
|||||||
"", Inst);
|
"", Inst);
|
||||||
// actually use the resolved function
|
// actually use the resolved function
|
||||||
Inst->replaceUsesOfWith(F, castResolver);
|
Inst->replaceUsesOfWith(F, castResolver);
|
||||||
|
} else {
|
||||||
//BasicBlock::iterator ii(Inst);
|
// FIXME: need to take care of cases where a function is used that
|
||||||
//ReplaceInstWithValue(Inst->getParent()->getInstList(),
|
// is not an instruction, e.g. global variable initializer...
|
||||||
// ii, ResolverResult);
|
std::cerr << "Non-instruction is using an external function!\n";
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(std::cerr << "Safe module:\n");
|
DEBUG(std::cerr << "Safe module:\n";
|
||||||
for (Module::iterator I = SafeModule->begin(), E = SafeModule->end();I!=E;++I)
|
typedef Module::iterator MI;
|
||||||
if (!I->isExternal()) DEBUG(std::cerr << "\t" << I->getName() << "\n");
|
typedef Module::giterator MGI;
|
||||||
for (Module::giterator I=SafeModule->gbegin(),E = SafeModule->gend();I!=E;++I)
|
|
||||||
if (!I->isExternal()) DEBUG(std::cerr << "\t" << I->getName() << "\n");
|
|
||||||
|
|
||||||
DEBUG(std::cerr << "Test module:\n");
|
for (MI I = SafeModule->begin(), E = SafeModule->end(); I != E; ++I)
|
||||||
for (Module::iterator I =TestModule->begin(),E = TestModule->end(); I!=E;++I)
|
if (!I->isExternal()) std::cerr << "\t" << I->getName() << "\n";
|
||||||
if (!I->isExternal()) DEBUG(std::cerr << "\t" << I->getName() << "\n");
|
for (MGI I = SafeModule->gbegin(), E = SafeModule->gend(); I!=E; ++I)
|
||||||
for (Module::giterator I=TestModule->gbegin(),E = TestModule->gend();I!=E;++I)
|
if (!I->isExternal()) std::cerr << "\t" << I->getName() << "\n";
|
||||||
if (!I->isExternal()) DEBUG(std::cerr << "\t" << I->getName() << "\n");
|
|
||||||
|
std::cerr << "Test module:\n";
|
||||||
|
for (MI I = TestModule->begin(), E = TestModule->end(); I != E; ++I)
|
||||||
|
if (!I->isExternal()) std::cerr << "\t" << I->getName() << "\n";
|
||||||
|
for (MGI I=TestModule->gbegin(),E = TestModule->gend(); I!= E; ++I)
|
||||||
|
if (!I->isExternal()) std::cerr << "\t" << I->getName() << "\n";
|
||||||
|
);
|
||||||
|
|
||||||
// Write out the bytecode to be sent to CBE
|
// Write out the bytecode to be sent to CBE
|
||||||
std::string SafeModuleBC = getUniqueFilename("bugpoint.safe.bc");
|
std::string SafeModuleBC = getUniqueFilename("bugpoint.safe.bc");
|
||||||
@@ -226,7 +227,8 @@ bool ReduceMisCodegenFunctions::TestFuncs(const std::vector<Function*> &Funcs,
|
|||||||
int Result = BD.diffProgram(TestModuleBC, SharedObject, false);
|
int Result = BD.diffProgram(TestModuleBC, SharedObject, false);
|
||||||
if (KeepFiles) {
|
if (KeepFiles) {
|
||||||
std::cout << "You can reproduce the problem with the command line: \n"
|
std::cout << "You can reproduce the problem with the command line: \n"
|
||||||
<< "lli (or llc) -load " << SharedObject << " " << TestModuleBC
|
<< (BD.isExecutingJIT() ? "lli" : "llc")
|
||||||
|
<< " -load " << SharedObject << " " << TestModuleBC
|
||||||
<< "\n";
|
<< "\n";
|
||||||
} else {
|
} else {
|
||||||
removeFile(TestModuleBC);
|
removeFile(TestModuleBC);
|
||||||
@@ -253,13 +255,10 @@ namespace {
|
|||||||
|
|
||||||
std::string SymName = V.getName();
|
std::string SymName = V.getName();
|
||||||
|
|
||||||
// If the symbol starts with a '.', replace it with 'x'
|
// Use the Mangler facility to make symbol names that will be valid in
|
||||||
// This solves the problem of not being able to find symbols in an .so
|
// shared objects.
|
||||||
// file when those symbol names start with '.'
|
SymName = Mangler::makeNameProper(SymName);
|
||||||
if (SymName[0] == '.') {
|
|
||||||
SymName[0] = 'x';
|
|
||||||
V.setName(SymName);
|
V.setName(SymName);
|
||||||
}
|
|
||||||
|
|
||||||
if (SymbolNames.count(SymName) == 0) {
|
if (SymbolNames.count(SymName) == 0) {
|
||||||
DEBUG(std::cerr << "Disambiguator: adding " << SymName
|
DEBUG(std::cerr << "Disambiguator: adding " << SymName
|
||||||
@@ -322,7 +321,7 @@ bool BugDriver::debugCodeGenerator() {
|
|||||||
oldMain->setName("old_main");
|
oldMain->setName("old_main");
|
||||||
// Create a NEW `main' function with same type
|
// Create a NEW `main' function with same type
|
||||||
Function *newMain = new Function(oldMain->getFunctionType(),
|
Function *newMain = new Function(oldMain->getFunctionType(),
|
||||||
GlobalValue::InternalLinkage,
|
GlobalValue::ExternalLinkage,
|
||||||
"main", Program);
|
"main", Program);
|
||||||
// Call the old main function and return its result
|
// Call the old main function and return its result
|
||||||
BasicBlock *BB = new BasicBlock("entry", newMain);
|
BasicBlock *BB = new BasicBlock("entry", newMain);
|
||||||
@@ -344,7 +343,6 @@ bool BugDriver::debugCodeGenerator() {
|
|||||||
BB->getInstList().push_back(ret);
|
BB->getInstList().push_back(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Do the reduction...
|
// Do the reduction...
|
||||||
ReduceMisCodegenFunctions(*this).reduceList(MisCodegenFunctions);
|
ReduceMisCodegenFunctions(*this).reduceList(MisCodegenFunctions);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user