<badref> when using CallInst::CreateMalloc for a struct type

Viewed 275

I am trying to generate LLVM IR for code (in a toy language) similar to the following C++ code:

struct test {
  int a;
  int b;
  int c;
};
int main() {
  tempVar *a;
  a = new test();
}

Unfortunately, when I run verifyModule, I receive the following error messages:

Instruction referencing instruction not embedded in a basic block!
  %malloccall = tail call i8* @malloc(i64 mul nuw (i64 ptrtoint (i32* getelementptr (i32, i32* null, i32 1) to i64), i64 3))
  <badref> = bitcast i8* %malloccall to %test*

The following MWE reproduces the issue:

#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <vector>
using namespace llvm;

std::map<std::string, StructType *> allocatedClasses;
std::map<std::string, std::vector<Type *>> classSizes;

static LLVMContext TheContext;
static IRBuilder<> Builder(TheContext);
static std::map<std::string, AllocaInst *> NamedValues;

int main() {
  static std::unique_ptr<Module> TheModule;

  TheModule = std::make_unique<Module>("inputFile", TheContext);

  allocatedClasses["test"] = StructType::create(TheContext, "test");
  classSizes["test"] = std::vector<Type *>(3, Type::getInt32Ty(TheContext));
  allocatedClasses["test"]->setBody(classSizes["test"]);

  FunctionType *mainType = FunctionType::get(Builder.getInt32Ty(), false);
  Function *main = Function::Create(mainType, Function::ExternalLinkage, "main",
                                    TheModule.get());
  BasicBlock *entry = BasicBlock::Create(TheContext, "entry", main);
  Builder.SetInsertPoint(entry);

  std::string tV = "tempVar";
  NamedValues[tV] = Builder.CreateAlloca(
      PointerType::get(allocatedClasses["test"], 0), nullptr, tV);
  auto typeSize = ConstantExpr::getSizeOf(allocatedClasses["test"]);
  typeSize =
      ConstantExpr::getTruncOrBitCast(typeSize, Type::getInt64Ty(TheContext));

  CallInst::CreateMalloc(Builder.GetInsertBlock(), Type::getInt64Ty(TheContext),
                         allocatedClasses["test"], typeSize, nullptr, nullptr,
                         "");
  Builder.CreateRet(ConstantInt::get(TheContext, APInt(32, 0)));

  TheModule->print(outs(), nullptr);
  Module *test = TheModule.get();
  verifyModule(*test, &errs());
}

I compile this with clang++ `llvm-config --cxxflags --ldflags --system-libs --libs all` -g ex.cpp, using clang version 10.0.0-4ubuntu1, on x86. When executed, the program outputs:

; ModuleID = 'inputFile'
source_filename = "inputFile"

%test = type { i32, i32, i32 }

define i32 @main() {
entry:
  %tempVar = alloca %test*
  %malloccall = tail call i8* @malloc(i64 mul nuw (i64 ptrtoint (i32* getelementptr (i32, i32* null, i32 1) to i64), i64 3))
  ret i32 0
}

declare noalias i8* @malloc(i64)

and the error message from above.

What am I doing wrong here?

1 Answers

The documentation for the function you call says "Note: This function does not add the bitcast to the basic block, that is the responsibility of the caller."

I have no idea why not, but the caller is you.

Related