Opt can't find 'hello' pass

I’m just trying to run the hello world example from the LLVM Writing a Pass Tutorial (https://llvm.org/docs/WritingAnLLVMPass.html), but whenever I run:

$BUILD_DIR/bin/clang -c -emit-llvm hello.c

$BUILD_DIR/bin/opt -load $BUILD_DIR/lib/LLVMHello.so -hello < hello.bc > /dev/null

I get the following error:

bin/opt: unknown pass name ‘hello’

Which seems odd because if I run:

$BUILD_DIR/bin/opt -load $BUILD_DIR/lib/LLVMHello.so --help | grep hello

I get:

–hello - Hello World Pass

To build LLVM I’m running the following commands from my build directory:

cmake -G Ninja -DLLVM_ENABLE_PROJECTS=‘clang’ …/llvm

cmake --build .

Just to clarify, I’m not writing my own pass. Just trying to run the ‘hello’ pass that comes default when building LLVM

That’s due to the recent transition to the new pass manager. Adding -enable-new-pm=0 to the opt command should work.

I’ll update the documentation to explicitly say that the legacy pass manager is no longer the default in big red letters.

https://llvm.org/docs/WritingAnLLVMPass.html is mostly about the
legacy pass manager.
A big revamp is needed to make it new PM ready:)

Got it. Thank you. I tried using the new pass manager from the new tutorial as well but was having an issue where the ‘helloworld’ pass would only work if I manually removed all the metadata from my hello.ll file to where the only thing in it was the function. Otherwise, it would run silently and not print out any function names. Any solution to that?

Can you post the .ll file that doesn’t work and the command you ran?

cat hello.ll

; ModuleID = ‘hello.c’
source_filename = “hello.c”
target datalayout = “e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128”
target triple = “x86_64-unknown-linux-gnu”

; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @foo() #0 {
%a = alloca i32, align 4
store i32 1, i32* %a, align 4
%0 = load i32, i32* %a, align 4
ret i32 %0

attributes #0 = { noinline nounwind optnone uwtable “disable-tail-calls”=“false” “frame-pointer”=“all” “less-precise-fpmad”=“false” “min-legal-vector-width”=“0” “no-infs-fp-math”=“false” “no-jump-tables”=“false” “no-nans-fp-math”=“false” “no-signed-zeros-fp-math”=“false” “no-trapping-math”=“true” “stack-protector-buffer-size”=“8” “target-cpu”=“x86-64” “target-features”=“+cx8,+fxsr,+mmx,+sse,+sse2,+x87” “tune-cpu”=“generic” “unsafe-fp-math”=“false” “use-soft-float”=“false” }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !“wchar_size”, i32 4}
!1 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 16e7973c5d8fb543ea9e91735be8610a8b1c262a)”}

$BUILD_DIR/bin/opt -disable-output hello.ll -passes=helloworld

nothing gets printed

Adding the -debug-pass-manager flag to the opt commands shows what’s going on:

Starting llvm::Module pass manager run.
Running pass: VerifierPass on C:/src/tmp/a.ll
Running analysis: VerifierAnalysis on C:/src/tmp/a.ll
Running analysis: InnerAnalysisManagerProxy<llvm::FunctionAnalysisManager, llvm::Module> on C:/src/tmp/a.ll
Starting llvm::Function pass manager run.
Skipping pass HelloWorldPass on foo due to optnone attribute
Skipping pass: HelloWorldPass on foo
Finished llvm::Function pass manager run.
Running pass: VerifierPass on C:/src/tmp/a.ll
Finished llvm::Module pass manager run.

The optnone attribute on a function makes most function passes skip running on the function. You got the IR from the output of clang -O0 which adds that attribute. This is actually briefly mentioned at the end of https://llvm.org/docs/WritingAnLLVMNewPMPass.html.
Perhaps we can make HelloWorldPass required for demonstration purposes and to avoid this specific problem in the future.