code-altering Passes for llc

Greetinigs,

I am extending llc to include runtime checks for calls (in X86). So a call
'call target' is altered to look like this:

  [some check]
  jne error_function
  call target

I've done this by implementing a MachineFunctionPass that is instantiated
and added to the PassManager in X86TargetMachine::addPreRegAlloc.

In order to create the jne-instruction I need some BasicBlock that contains
the error routine. So I tried to create a ModulePass to insert some basic
block e. g. in the beginning of the program, to use it for the
jne-instruction. Unfortunately, llc then produces the error

  llc: PassManager.cpp:1597:
    virtual void llvm::ModulePass::assignPassManager(llvm::PMStack&,
llvm::PassManagerType):
    Assertion `!PMS.empty() && "Unable to find appropriate Pass Manager"'
failed.

Adding a MachineFunctionPass the same way works fine. I've read here on the
mailing list that some Pass dependencies cause this error, but I have no
dependencies specified.

How do I get the ModulePass to run? Is a ModulePass the right way to
accomplish my aim, altogether?

One more question concerning passes:
Clearly, inserting a jne-instruction changes control flow, so the CFG is not
up to date after the pass. Do I set AnalysisUsage in getAnalysisUsage to
preserve nothing? In that case, is the CFG updated automatically by LLVM or
do I need to apply the changes during the Pass not only the the
MachineFunction, but also the the CFG?

-Artjom

Greetinigs,

I am extending llc to include runtime checks for calls (in X86). So a call
'call target' is altered to look like this:

[some check]
jne error_function
call target

I've done this by implementing a MachineFunctionPass that is instantiated
and added to the PassManager in X86TargetMachine::addPreRegAlloc.

In order to create the jne-instruction I need some BasicBlock that contains
the error routine. So I tried to create a ModulePass to insert some basic
block e. g. in the beginning of the program, to use it for the
jne-instruction. Unfortunately, llc then produces the error

llc: PassManager.cpp:1597:
   virtual void llvm::ModulePass::assignPassManager(llvm::PMStack&,
llvm::PassManagerType):
   Assertion `!PMS.empty() && "Unable to find appropriate Pass Manager"'
failed.

Adding a MachineFunctionPass the same way works fine. I've read here on the
mailing list that some Pass dependencies cause this error, but I have no
dependencies specified.

How do I get the ModulePass to run? Is a ModulePass the right way to
accomplish my aim, altogether?

You don't need a ModulePass to modify a CFG. A MachineFunctionPass
is fine for this.

The actual problem may be that your pass doesn't preserve some
Analysis that CodeGen is using. Since CodeGen is function-oriented,
ModulePasses cannot be freely scheduled.

One more question concerning passes:
Clearly, inserting a jne-instruction changes control flow, so the CFG is not
up to date after the pass. Do I set AnalysisUsage in getAnalysisUsage to
preserve nothing? In that case, is the CFG updated automatically by LLVM or
do I need to apply the changes during the Pass not only the the
MachineFunction, but also the the CFG?

The default if you don't override getAnalysisUsage is that everything is
considered clobbered. With a MachineFunctionPass, you can modify
the MachineFunction (including the MachineBasicBlock CFG), but
you shouldn't modify the LLVM IR Function.

Dan

Dan Gohman-2 wrote:

You don't need a ModulePass to modify a CFG. A MachineFunctionPass
is fine for this.

Well, okay. But I need to insert some BasicBlock that contains the error
handling (that the runtime check jumpts to on failure). Just putting another
MachineBasicBlock at the beginning of some arbitrary MachineFunction doesn't
seem to be the right way to go, does it?

Does the error function *have* to be auto-generated in your pass?
Perhaps the original code should use invokes, and your pass insert the
error check with a jne to the "unwind" block.

Kenneth Uildriks wrote:

Does the error function *have* to be auto-generated in your pass?
Perhaps the original code should use invokes, and your pass insert the
error check with a jne to the "unwind" block.

If I understand correctly, unwind is some kind of exception handling in LLVM
IR? I'm not sure if this is the right thing.

First, I include runtime checks inst programs that are already written
during their compilation (with my modified version of LLVM). Second, the
error handling is a (context independent) program termination, so it is of
no use to replicate it at every call.

So I was searching for a possibility to include an additional
(Machine)BasicBlock (or rather a MachineFunction?) somewhere in the program
that contains the program termination and that I can jump to on check
failure. Can't I do that during a Pass in llc?

-Artjom

If you just have a magic block of instructions you want to stick
somewhere, a module-level inline asm may be the easiest way. If
you have higher-level language code you want to stick somewhere,
you should probably create a new Function (and/or MachineFunction)
that can be "called", so that it plays nicely with the rest of
the compiler.

Dan

I tried to insert a new MachineBasicBlock at the beginning of functions, but when I do that like

  MachineBasicBlock *entry = MF.begin();
  const BasicBlock *block = entry->getBasicBlock();

  MachineBasicBlock *newMBB = MF.CreateMachineBasicBlock(block);			
  MachineInstrBuilder instr = BuildMI(labelBlock, TII->get(X86::NOOP));
  newMBB->addSuccessor(entry);
  MF.push_front(newMBB);

llc fails with the following error message. Can someone tell me what I am doing wrong?