3

I have been trying to write an LLVM Pass Following a mixture of this and this part of the documentation.

I am assuming that since Mac comes with Clang and LLVM I should be able to use their installation to create plugins. So I made a directory layout as follows:

optimizations
    CMakeLists.txt  (--> outer)
    Hello
        CMakeLists.txt (--> inner)
        Hello.cpp

The contents of "outer" is:

find_package(LLVM REQUIRED CONFIG)
list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
include(AddLLVM)

add_definitions(${LLVM_DEFINITONS})
include_directories(${LLVM_INCLUDE_DIRS})

add_subdirectory(Hello)

The contents of "inner" are:

add_llvm_loadable_module(LLVMHello
     Hello.cpp
     )

In Hello.cpp I have what is made in the other set of instructions:

#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

namespace {
  struct Hello : public FunctionPass {
    static char ID;
    Hello() : FunctionPass(ID) {}

    bool runOnFunction(Function &F) override {
      errs() << "Hello: ";
      errs().write_escaped(F.getName()) << '\n';
      return false;
    }
  };
}

char Hello::ID = 0;
static RegisterPass<Hello> X("hello", "Hello World Pass", false, false);

So then I went to the optimizations directory and ran cmake CMakeLists.txt. This created a Makefile in each directory as well as a bunch of other cmake related files. This worked fine but then I tried running make and at first I got errors similar to here. To fix that, at the top of Hello.cpp I added:

#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS

But now I get these errors:

/usr/local/include/llvm/Support/AlignOf.h:53:10: error: unknown type name 'constexpr'
  static constexpr unsigned Alignment =
         ^
/usr/local/include/llvm/Support/AlignOf.h:53:20: error: expected member name or ';' after declaration specifiers
  static constexpr unsigned Alignment =
  ~~~~~~~~~~~~~~~~ ^
/usr/local/include/llvm/Support/AlignOf.h:59:42: error: use of undeclared identifier 'Alignment'
  enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 };
                                         ^
/usr/local/include/llvm/Support/AlignOf.h:60:42: error: use of undeclared identifier 'Alignment'
  enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 };
                                         ^
/usr/local/include/llvm/Support/AlignOf.h:61:42: error: use of undeclared identifier 'Alignment'
  enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 };
                                         ^
/usr/local/include/llvm/Support/AlignOf.h:62:43: error: use of undeclared identifier 'Alignment'
  enum { Alignment_GreaterEqual_16Bytes = Alignment >= 16 ? 1 : 0 };
                                          ^
/usr/local/include/llvm/Support/AlignOf.h:64:39: error: use of undeclared identifier 'Alignment'
  enum { Alignment_LessEqual_2Bytes = Alignment <= 2 ? 1 : 0 };
                                      ^
/usr/local/include/llvm/Support/AlignOf.h:65:39: error: use of undeclared identifier 'Alignment'
  enum { Alignment_LessEqual_4Bytes = Alignment <= 4 ? 1 : 0 };
                                      ^
/usr/local/include/llvm/Support/AlignOf.h:66:39: error: use of undeclared identifier 'Alignment'
  enum { Alignment_LessEqual_8Bytes = Alignment <= 8 ? 1 : 0 };
                                      ^
/usr/local/include/llvm/Support/AlignOf.h:67:40: error: use of undeclared identifier 'Alignment'
  enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 };
                                       ^
/usr/local/include/llvm/Support/AlignOf.h:71:23: error: unknown type name 'constexpr'
template <typename T> constexpr unsigned AlignOf<T>::Alignment;
                      ^
/usr/local/include/llvm/Support/AlignOf.h:71:33: error: expected unqualified-id
template <typename T> constexpr unsigned AlignOf<T>::Alignment;

I'm not exactly sure what to do about these errors. Any help would be appreciated.

Adding set(CMAKE_CXX_STANDARD 11) to my CMakeLists.txt gives:

Hello[ 50%] Linking CXX shared module LLVMHello.dylib
Undefined symbols for architecture x86_64:
  "llvm::FunctionPass::assignPassManager(llvm::PMStack&, llvm::PassManagerType)", referenced from:
      vtable for (anonymous namespace)::Hello in Hello.o
  "llvm::FunctionPass::createPrinterPass(llvm::raw_ostream&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const", referenced from:
      vtable for (anonymous namespace)::Hello in Hello.o
  "llvm::Pass::getAnalysisUsage(llvm::AnalysisUsage&) const", referenced from:
      vtable for (anonymous namespace)::Hello in Hello.o
  "llvm::Pass::getAdjustedAnalysisPointer(void const*)", referenced from:
      vtable for (anonymous namespace)::Hello in Hello.o
  "llvm::Pass::getPassName() const", referenced from:
      vtable for (anonymous namespace)::Hello in Hello.o
  "llvm::Pass::verifyAnalysis() const", referenced from:
      vtable for (anonymous namespace)::Hello in Hello.o
  "llvm::Value::getName() const", referenced from:
      (anonymous namespace)::Hello::runOnFunction(llvm::Function&) in Hello.o
  "llvm::errs()", referenced from:
      (anonymous namespace)::Hello::runOnFunction(llvm::Function&) in Hello.o
  "llvm::raw_ostream::write(char const*, unsigned long)", referenced from:
      llvm::raw_ostream::operator<<(llvm::StringRef) in Hello.o
  "llvm::Pass::dumpPassStructure(unsigned int)", referenced from:
      vtable for (anonymous namespace)::Hello in Hello.o
  "llvm::Pass::getAsPMDataManager()", referenced from:
      vtable for (anonymous namespace)::Hello in Hello.o
  "llvm::Pass::~Pass()", referenced from:
      llvm::FunctionPass::~FunctionPass() in Hello.o
  "llvm::Pass::print(llvm::raw_ostream&, llvm::Module const*) const", referenced from:
      vtable for (anonymous namespace)::Hello in Hello.o
  "llvm::raw_ostream::write(unsigned char)", referenced from:
      llvm::raw_ostream::operator<<(char) in Hello.o
  "llvm::FunctionPass::getPotentialPassManagerType() const", referenced from:
      vtable for (anonymous namespace)::Hello in Hello.o
  "vtable for llvm::FunctionPass", referenced from:
      llvm::FunctionPass::FunctionPass(char&) in Hello.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "llvm::Pass::preparePassManager(llvm::PMStack&)", referenced from:
      vtable for (anonymous namespace)::Hello in Hello.o
  "llvm::Pass::getAsImmutablePass()", referenced from:
      vtable for (anonymous namespace)::Hello in Hello.o
  "vtable for llvm::Pass", referenced from:
      llvm::Pass::Pass(llvm::PassKind, char&) in Hello.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "llvm::raw_ostream::write_escaped(llvm::StringRef, bool)", referenced from:
      (anonymous namespace)::Hello::runOnFunction(llvm::Function&) in Hello.o
  "llvm::Pass::releaseMemory()", referenced from:
      vtable for (anonymous namespace)::Hello in Hello.o
  "llvm::PassRegistry::getPassRegistry()", referenced from:
      llvm::RegisterPass<(anonymous namespace)::Hello>::RegisterPass(char const*, char const*, bool, bool) in Hello.o
  "llvm::PassRegistry::registerPass(llvm::PassInfo const&, bool)", referenced from:
      llvm::RegisterPass<(anonymous namespace)::Hello>::RegisterPass(char const*, char const*, bool, bool) in Hello.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [Hello/LLVMHello.dylib] Error 1
make[1]: *** [Hello/CMakeFiles/LLVMHello.dir/all] Error 2
make: *** [all] Error 2
Community
  • 1
  • 1
Dair
  • 15,910
  • 9
  • 62
  • 107

2 Answers2

1

The compiler is complaining about constexpr which is a C++11 feature. Make sure that C++11 is enabled by passing the -std=c++11 switch to gcc (or Clang, same switch for both compilers). This will fix all the errors you're seeing. Since you're using a makefile, you should add this switch to the CXXFLAGS variable as shown here.

Community
  • 1
  • 1
Hadi Brais
  • 22,259
  • 3
  • 54
  • 95
  • Do you know if saying `set(CMAKE_CXX_STANDARD 11)` in my `CMakeLists.txt` is equivalent to `-std=c++11` Doing so fixes those errors, but there are others that are created. – Dair Oct 18 '15 at 05:18
  • @Dair Regarding the new set of errors. It looks like you are not referencing all the required LLVM static libraries . There is a file called `Makefile.common` in the `build` directory in LLVM. This file has to be included in your makefile. – Hadi Brais Oct 18 '15 at 05:37
  • I have a `Makefile.common`, `Makefile.rules`, and `Makefile.config.in` inside my llvm root directory where I checked out LLVM to. In build, I have none of those... – Dair Oct 18 '15 at 06:23
  • @Dair You should not use a `CMakeLists.txt` file to compile your pass. You have to create a makefile as shown [here](http://llvm.org/docs/WritingAnLLVMPass.html#setting-up-the-build-environment). In this example, the `LEVEL` variable defines the root directory of LLVM. Notice at the end `include $(LEVEL)/Makefile.common`. There must be such file. – Hadi Brais Oct 19 '15 at 11:35
  • Ok, so I had a build of LLVM from source. I thought it was possible to do this with the Clang and LLVM that Apple provided by default (still not 100% sure but I guess I was wrong?) Adjusting the level fixed things, still wish I could do it with Apple's LLVM and Clang, it would make it easier for me to help people I know set this up. – Dair Oct 20 '15 at 21:57
-2

UPDATE: Disregard this answer. The answer about C++11 is correct.

It can't find a definition for constexpr. This is either a typedef as in typedef something constexpr, but much more likely a macro as in #define constexpr const

It should be defined in a .h file somewhere (or within the makefile as -Dconstexpr=const).

NOTE: On the page you cited, they suggested adding -D's to the makefile. Also, see the second answer that used llvm-config --cppflags. Just type it in and see what it outputs.

But, it you have to troubleshoot further ...

First, find the file that has the definition via something like:

egrep -r '#define.*constexpr' .
You may get a few extras. Sift through them and find the file that has the definition. Then, look for an #ifdef BLAH wrapper around it. BLAH is not being defined properly.

If BLAH turns out to be one of the __STDC_* you mentioned, you may need to define it indirectly as sometimes certain .h files will undef these and redef them, based on a more "global" symbol (e.g. STDC_* or _STDC_SOURCE)

For example, with GNU, to get the sub features, you don't define them directly, you use _GNU_SOURCE which turns on a whole bunch

Craig Estey
  • 30,627
  • 4
  • 24
  • 48