mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-18 12:29:21 +00:00
the function type, instead they belong to functions and function calls. This is an updated and slightly corrected version of Reid Spencer's original patch. The only known problem is that auto-upgrading of bitcode files doesn't seem to work properly (see test/Bitcode/AutoUpgradeIntrinsics.ll). Hopefully a bitcode guru (who might that be? :) ) will fix it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44359 91177308-0d34-0410-b5e6-96231b3b80d8
146 lines
5.1 KiB
C++
146 lines
5.1 KiB
C++
//===-- ExtractFunction.cpp - Function extraction pass --------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file was developed by the LLVM research group and is distributed under
|
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This pass extracts
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Instructions.h"
|
|
#include "llvm/Module.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Transforms/IPO.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
/// @brief A pass to extract specific functions and their dependencies.
|
|
class VISIBILITY_HIDDEN FunctionExtractorPass : public ModulePass {
|
|
Function *Named;
|
|
bool deleteFunc;
|
|
bool reLink;
|
|
public:
|
|
static char ID; // Pass identification, replacement for typeid
|
|
|
|
/// FunctionExtractorPass - If deleteFn is true, this pass deletes as the
|
|
/// specified function. Otherwise, it deletes as much of the module as
|
|
/// possible, except for the function specified.
|
|
///
|
|
explicit FunctionExtractorPass(Function *F = 0, bool deleteFn = true,
|
|
bool relinkCallees = false)
|
|
: ModulePass((intptr_t)&ID), Named(F), deleteFunc(deleteFn),
|
|
reLink(relinkCallees) {}
|
|
|
|
bool runOnModule(Module &M) {
|
|
if (Named == 0) {
|
|
Named = M.getFunction("main");
|
|
if (Named == 0) return false; // No function to extract
|
|
}
|
|
|
|
if (deleteFunc)
|
|
return deleteFunction();
|
|
M.setModuleInlineAsm("");
|
|
return isolateFunction(M);
|
|
}
|
|
|
|
bool deleteFunction() {
|
|
// If we're in relinking mode, set linkage of all internal callees to
|
|
// external. This will allow us extract function, and then - link
|
|
// everything together
|
|
if (reLink) {
|
|
for (Function::iterator B = Named->begin(), BE = Named->end();
|
|
B != BE; ++B) {
|
|
for (BasicBlock::iterator I = B->begin(), E = B->end();
|
|
I != E; ++I) {
|
|
if (CallInst* callInst = dyn_cast<CallInst>(&*I)) {
|
|
Function* Callee = callInst->getCalledFunction();
|
|
if (Callee && Callee->hasInternalLinkage())
|
|
Callee->setLinkage(GlobalValue::ExternalLinkage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Named->setLinkage(GlobalValue::ExternalLinkage);
|
|
Named->deleteBody();
|
|
assert(Named->isDeclaration() && "This didn't make the function external!");
|
|
return true;
|
|
}
|
|
|
|
bool isolateFunction(Module &M) {
|
|
// Make sure our result is globally accessible...
|
|
Named->setLinkage(GlobalValue::ExternalLinkage);
|
|
|
|
// Mark all global variables internal
|
|
for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
|
|
if (!I->isDeclaration()) {
|
|
I->setInitializer(0); // Make all variables external
|
|
I->setLinkage(GlobalValue::ExternalLinkage);
|
|
}
|
|
|
|
// All of the functions may be used by global variables or the named
|
|
// function. Loop through them and create a new, external functions that
|
|
// can be "used", instead of ones with bodies.
|
|
std::vector<Function*> NewFunctions;
|
|
|
|
Function *Last = --M.end(); // Figure out where the last real fn is.
|
|
|
|
for (Module::iterator I = M.begin(); ; ++I) {
|
|
if (&*I != Named) {
|
|
Function *New = new Function(I->getFunctionType(),
|
|
GlobalValue::ExternalLinkage);
|
|
New->setCallingConv(I->getCallingConv());
|
|
New->setParamAttrs(I->getParamAttrs());
|
|
|
|
// If it's not the named function, delete the body of the function
|
|
I->dropAllReferences();
|
|
|
|
M.getFunctionList().push_back(New);
|
|
NewFunctions.push_back(New);
|
|
New->takeName(I);
|
|
}
|
|
|
|
if (&*I == Last) break; // Stop after processing the last function
|
|
}
|
|
|
|
// Now that we have replacements all set up, loop through the module,
|
|
// deleting the old functions, replacing them with the newly created
|
|
// functions.
|
|
if (!NewFunctions.empty()) {
|
|
unsigned FuncNum = 0;
|
|
Module::iterator I = M.begin();
|
|
do {
|
|
if (&*I != Named) {
|
|
// Make everything that uses the old function use the new dummy fn
|
|
I->replaceAllUsesWith(NewFunctions[FuncNum++]);
|
|
|
|
Function *Old = I;
|
|
++I; // Move the iterator to the new function
|
|
|
|
// Delete the old function!
|
|
M.getFunctionList().erase(Old);
|
|
|
|
} else {
|
|
++I; // Skip the function we are extracting
|
|
}
|
|
} while (&*I != NewFunctions[0]);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
};
|
|
|
|
char FunctionExtractorPass::ID = 0;
|
|
RegisterPass<FunctionExtractorPass> X("extract", "Function Extractor");
|
|
}
|
|
|
|
ModulePass *llvm::createFunctionExtractionPass(Function *F, bool deleteFn,
|
|
bool relinkCallees) {
|
|
return new FunctionExtractorPass(F, deleteFn, relinkCallees);
|
|
}
|