Bram,
I looked over your patch and it looks good. I applied a patch based on
yours. The llvm-ld tool now uses the PluginLoader just like the opt
tool. It will also run some cleanup passes after the loaded plugins run
to ensure cruft is removed.
See this patch for details:
http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20060814/036882.html
Thanks for the patch! And, yes, you are on the bleeding edge of llvm-ld
usage. I don't think anyone else was using RunOptimizations. You're the
first to comment on it.
Reid.
On Fri, 2006-08-18 at 17:49 +0200, Bram Adams wrote:> Hi,
>
> Reid Spencer wrote:
> > > That's interesting! So, one only needs to add a 2-arg
function called
> > > RunOptimizations to the module (can't check it right now)?
> > >
> >
> > That is correct. That function and only that function will be called.
> > What happens in that function is up to you :)
> >
> So, I tried this the last two days, but to no avail. I first wrote the
> following three files to introduce the RunOptimizations-symbol
> (adapted from http://www.parashift.com/c
> ++-faq-lite/mixing-c-and-cpp.html#faq-32.8):
>
> a) Loader.h
>
> #ifndef LOADER_H
> #define LOADER_H
>
> #ifdef __cplusplus
> #include "llvm/PassManager.h"
> using namespace llvm;
> #else
> typedef struct PassManager PassManager;
> #endif
>
> #ifdef __cplusplus
> extern "C" {
> extern void RunOptimizations(PassManager*,...); /* ANSI C
> prototypes */
> extern PassManager* load_weaver_passes(PassManager*);
> }
> #endif
>
> #endif
>
>
> b) c-Loader.c
>
> #include "loader/Loader.h"
>
> void RunOptimizations(PassManager* mgr,...){
> load_weaver_passes(mgr);
> }
>
>
> c) Loader.cpp
>
> #include "loader/Loader.h"
> #include "matcher/Matcher.h"
> #include "reifier/Reifier.h"
>
> PassManager* load_weaver_passes(PassManager* mgr){
> mgr->add(createFirstPass());
> mgr->add(createSecondPass());
>
> return mgr;
> }
>
> In short, the C part (RunOptimizations) hands its first argument over
> to a global C++ method to add my passes.
>
> When using this machinery with llvm-ld (Slackware 10.2, GCC 3.3.6 and
> LLVM 1.8a), my passes are indeed loaded in and the PassManager
> attempts to run on the processed module. Then, I get the following:
>
> Program received signal SIGSEGV, Segmentation fault.
> 0xb7f16abf in __dynamic_cast () from /usr/lib/libstdc++.so.5
>
> #0 0xb7ea9abf in __dynamic_cast () from /usr/lib/libstdc++.so.5
> #1 0x0843f19d in llvm::PMDebug::PrintArgumentInformation
> (P=0x85e3b00) at /.../llvm/lib/VMCore/Pass.cpp:132
> #2 0x0843f1fc in llvm::PMDebug::PrintArgumentInformation
> (P=0x85ca030) at /.../llvm/lib/VMCore/Pass.cpp:134
> #3 0x0844e3b8 in llvm::PMDebug::PerformPassStartupStuff (P=0x85ca030)
> at PassManagerT.h:66
> #4 0x08444146 in llvm::PassManagerT<llvm::MTraits>::runOnUnit
> (this=0x85ca048, M=0x85bf330) at PassManagerT.h:280
> #5 0x0843eb26 in llvm::ModulePassManager::runOnModule
> (this=0x85ca030, M=@0x85bf330) at PassManagerT.h:905
> #6 0x0843eebf in llvm::PassManager::run (this=0xbfe36400,
> M=@0x85bf330) at /.../llvm/lib/VMCore/Pass.cpp:85
> #7 0x082a0361 in llvm::Optimize (M=0x85bf330)
> at /.../llvm/tools/llvm-ld/Optimize.cpp:189
> #8 0x082a7161 in main (argc=14, argv=0xbfe365e4, envp=0xbfe36620)
> at /.../llvm/tools/llvm-ld/llvm-ld.cpp:467
>
> The backtrace led me to this code snippet (lib/VMCore/Pass.cpp near
> line 132):
>
> void PMDebug::PrintArgumentInformation(const Pass *P) {
> // Print out passes in pass manager...
> if (const AnalysisResolver *PM = dynamic_cast<const
> AnalysisResolver*>(P)) { //<-- !!!!!!! ERROR !!!!!!!
> for (unsigned i = 0, e = PM->getNumContainedPasses(); i != e; ++i)
> PrintArgumentInformation(PM->getContainedPass(i));
>
> } else { // Normal pass. Print argument information...
> // Print out arguments for registered passes that are
> _optimizations_
> if (const PassInfo *PI = P->getPassInfo())
> if (PI->getPassType() & PassInfo::Optimization)
> std::cerr << " -" <<
PI->getPassArgument();
> }
> }
>
> While I could verify (using GDB/DDD) that my passes were loaded
> perfectly in load_weaver_pass, once they got on the line marked with
> ERROR the pointer to their vtable suddenly was inaccessible. This made
> dynamic_cast crash. The hardcoded passes, loaded in before mine by
> llvm-ld, had no problems whatsoever. For some reason, some memory
> allocated in my C/C++ bridge is just not accessible anymore by
> llvm-ld, but I don't know why ...
>
> At long last, I decided to port opt's pass loading mechanism to
> llvm-ld to see if this would solve things in my case (despite its
> limitations). And it did! I attached my hack (with uncommented
> existing loading mechanism) in case someone else encounters the same
> problems. Maybe some extra argument switch for llvm-ld could allow
> user-switchable coexistence of both loading mechanisms?
>
> Has anyone else experimented with llvm-ld yet? Did the same problem
> arise?
>
> Kind regards,
>
> Bram Adams
> GH-SEL, INTEC, Ghent University
> plain text document attachment (patch.llvm-ld-1.8)
> diff -u'rF^function' tools/llvm-ld/Optimize.cpp
tools/llvm-ld/Optimize.cpp
> --- tools/llvm-ld/Optimize.cpp 2006-06-16 20:23:48.000000000 +0200
> +++ tools/llvm-ld/Optimize.cpp 2006-08-18 16:36:39.000000000 +0200
> @@ -21,8 +21,16 @@
> #include "llvm/Target/TargetData.h"
> #include "llvm/Transforms/IPO.h"
> #include "llvm/Transforms/Scalar.h"
> +#include "llvm/Support/PassNameParser.h"
> +#include "llvm/Support/PluginLoader.h"
> using namespace llvm;
>
> +// Pass Name Options (cf. opt)
> +
> +static cl::list<const PassInfo*, bool,
> + FilteredPassNameParser<PassInfo::Optimization> >
> +OptimizationList(cl::desc("Optimizations available:"));
> +
> // Optimization Options
>
> enum OptimizationLevels {
> @@ -72,9 +80,10 @@
> cl::aliasopt(DisableInternalize),
> cl::desc("Alias for -disable-internalize"));
>
> -static cl::list<std::string> LoadableModules("load",
> +//disambiguate with -load option from llvm/Support/PluginLoader.h
> +/*static cl::list<std::string> LoadableModules("load",
> cl::value_desc("path"),
> - cl::desc("Load an optimization module and run it"));
> + cl::desc("Load an optimization module and run it"));*/
>
> // A utility function that adds a pass to the pass manager but will also
add
> // a verifier pass after if we're supposed to verify.
> @@ -168,7 +177,8 @@
> addPass(Passes, createGlobalDCEPass());
> }
>
> - std::vector<std::string> plugins = LoadableModules;
> + // Get rid of low-level library loading: inaccessible memory for vtable?
> + /* std::vector<std::string> plugins = LoadableModules;
> for (std::vector<std::string>::iterator I = plugins.begin(),
> E = plugins.end(); I != E; ++I) {
> sys::DynamicLibrary dll(I->c_str());
> @@ -180,6 +190,29 @@
> "' is missing the RunOptimizations symbol";
> }
> (*OF)(Passes,OptLevel);
> + }*/
> +
> + // Create a new optimization pass for each one specified on the command
line
> + std::auto_ptr<TargetMachine> target;
> + for (unsigned i = 0; i < OptimizationList.size(); ++i) {
> + const PassInfo *Opt = OptimizationList[i];
> +
> + if (Opt->getNormalCtor())
> + Passes.add(Opt->getNormalCtor()());
> + else if (Opt->getTargetCtor()) {
> +#if 0
> + if (target.get() == NULL)
> + target.reset(allocateSparcTargetMachine()); // FIXME: target option
> +#endif
> + assert(target.get() && "Could not allocate target
machine!");
> + Passes.add(Opt->getTargetCtor()(*target.get()));
> + } else
> + std::cerr << "llvm-ld" << ": cannot
create pass: " << Opt->getPassName()
> + << "\n";
> +
> + // what's this?
> + // if (PrintEachXForm)
> + // Passes.add(new PrintModulePass(&std::cerr));
> }
>
> // Make sure everything is still good.
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev