How to debug passes

Iulia,

You need to check the contents of the hello.ll (or hello.bc) file rather
than the input *.c file - ultimately that's what opt consumes.

Try compiling without any optimisations:

clang -O0 -emit-llvm -S hello.c -c -o hello.ll

-Andrzej

Hi,

I checked the content of the hello.ll file and I have the bitcode disassembled in it. Compiling without optimizations gives the same result.

Regards,

Iulia

Iulia,

You need to check the contents of the hello.ll (or hello.bc) file rather

than the input *.c file - ultimately that’s what opt consumes.

Try compiling without any optimisations:

clang -O0 -emit-llvm -S hello.c -c -o hello.ll

-Andrzej

opt -load lib­dum­my­pass.so -dum­my­pass hel­lo.ll

``

Looks like you are loading a shared library different from "LLVMHello.so".

did you change the name of the compilation unit from "Hello.cpp" into
"dummypass.cpp"?

(As asked previously by Andrzej) did you register the dummy pass?

> RegisterPass<DummyPass> X("dummypass", "whatever");

Is any error/warning triggered when loading the library, executing "opt" or
during compilation?

Could you attach the fragment containing the "DummyPass"?

Lorenzo

Hi Lorenzo,

Sorry for the late answer.

I am loading LLVMHello.so in the command, but, as I was explaining to Andrzej in the previous mail, I copy pasted in the mail another command, from the source article, which uses dummypass. I also registered the Hello pass. There is no error or warning when executing the opt load command, but it seems like it is doing some processing (maybe in infinite loop) because the command does not finish execution. It is strange though that the command is not displaying nothing, even though there is a print at the very beginning of the runOnModule function.

This is the structure of my pass:

class Hello : public ModulePass {
public:
static char ID;

Hello() : ModulePass(ID) {
}

bool runOnModule(Module &M) override;

void getAnalysisUsage(AnalysisUsage &AU) const override {
getAnalysisUsage(AU);
}

static RegisterPass X(“hello”, “Hello World Pass”,
false /* Only looks at CFG /,
false /
Analysis Pass */);

static RegisterStandardPasses Y(
PassManagerBuilder::EP_EarlyAsPossible,
[](const PassManagerBuilder &Builder,
legacy::PassManagerBase &PM) { PM.add(new Hello()); });

bool Hello::runOnModule(Module &M) {
errs() << "Start pass: ";

Could you please help with any ideas?

Thank you.
Kind regards,
Iulia Stirb

opt -load lib­dum­my­pass.so -dum­my­pass hel­lo.ll

``

Looks like you are loading a shared library different from "LLVMHello.so".

did you change the name of the compilation unit from "Hello.cpp" into
"dummypass.cpp"?

(As asked previously by Andrzej) did you register the dummy pass?

> RegisterPass<DummyPass> X("dummypass", "whatever");

Is any error/warning triggered when loading the library, executing "opt" or
during compilation?

Could you attach the fragment containing the "DummyPass"?

Lorenzo

Hi Iulia,

This is really weird - the Hello pass from LLVM definitely works (I run
it occasionally for reference).

"Infinite loop" might mean that you're missing an argument - opt will
wait indefinitely until all positional argument are specified (i.e. the
*.ll file to process). I might be wrong here - that's just my experience
with opt.

Let's take a step back and focus on LLVMHello.so - could you send the
following:
1. Your input *.c (well, just copy and paste the contents here)
2. The command that you use to generate the *.ll file
3. The command that you use to run the Hello pass
4. The command that you used to build LLVM (in particular, LLVMHello.so)

Cheers,
Andrzej

Hi Andrzej,

Sorry. I will place the answer to the points inline. Could it be infinite loop in my pass? Shouldn’t the opt command display at least the first print at the very beginning, even if there is infinite loop in the pass?

Thank you.

Regards,
Iulia

Hi Iulia,

This is really weird - the Hello pass from LLVM definitely works (I run
it occasionally for reference).

“Infinite loop” might mean that you’re missing an argument - opt will
wait indefinitely until all positional argument are specified (i.e. the
*.ll file to process). I might be wrong here - that’s just my experience
with opt.

Let’s take a step back and focus on LLVMHello.so - could you send the
following:

  1. Your input *.c (well, just copy and paste the contents here)

#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#define NUM_THREADS 2
void * inc(void args) {
(
(int *)args)++;
return args;
}
void * dec(void args) {
(
(int *)args)–;
return args;
}
int main(int argc, char **argv) {
pthread_t *thr = (pthread_t )malloc(NUM_THREADSsizeof(pthread_t));
void * arg_thr0 = malloc(sizeof(void)), * arg_thr1 = malloc(sizeof(void));
*(int *)arg_thr0 = atoi(argv[1]);

if(pthread_create(&thr[0], NULL, inc, arg_thr0)) {
return EXIT_FAILURE;
}
else
{
cpu_set_t cpuset_thr0;
CPU_ZERO(&cpuset_thr0);
CPU_SET(0, &cpuset_thr0);

if(pthread_setaffinity_np(thr[0], sizeof(cpu_set_t), &cpuset_thr0)) {
return EXIT_FAILURE;
}
}
*(int *)arg_thr1 = atoi(argv[2]);

if(pthread_create(&thr[1], NULL, dec, arg_thr1)) {
return EXIT_FAILURE;
}
else
{
cpu_set_t cpuset_thr1;
CPU_ZERO(&cpuset_thr1);
CPU_SET(1, &cpuset_thr1);

if(pthread_setaffinity_np(thr[1], sizeof(cpu_set_t), &cpuset_thr1)) {
return EXIT_FAILURE;
}
}
void *status;
int i;
for (i = 0; i < NUM_THREADS; ++i) {
pthread_join(thr[i], &status);
printf("%d ", *(int *)status);

}
}

  1. The command that you use to generate the *.ll file
    llvm-dis test.bc

  2. The command that you use to run the Hello pass
    opt -load lib­/LLVMHello.so -hello test.ll

  3. The command that you used to build LLVM (in particular, LLVMHello.so)
    ninja
    (builds all LLVM)

Cheers,
Andrzej