Question

I have ConstantInt and ConstantFP values that I want to add using fadd. However, I'm having trouble casting the ConstantInt into a floating point number that fadd will accept.

Here is an excerpt of the code:

Value* left = ConstantInt::get(Type::getInt64Ty(getGlobalContext()), 12, true);
Value* right = ConstantFP::get(Type::getFloatTy(getGlobalContext()), 11.6);

Instruction* cast = CastInst::Create(Instruction::SIToFP, left, left->getType(), "", currentBlock());
left = cast->getOperand(0);

BinaryOperator::Create(Instruction::FAdd, left, right, "", currentBlock());

where currentBlock() returns a BasicBlock. After trying to generate the opcode for this, LLVM complains that it can't add the two values because they are not the same.

I'm rather new to LLVM, so I'll take any advice if this code makes no sense.

Was it helpful?

Solution

My usual approach with these things is see what Clang generates - both the LLVM IR and the C++ API calls (C++ backend). You can use the online instance for simplicity. So, compiling this C code:

float foo(int a, float b) {
  return a + b;
}

Gives me this LLVM IR:

define float @foo(i32 %a, float %b) #0 {
entry:
  %conv = sitofp i32 %a to float
  %add = fadd float %conv, %b
  ret float %add
}

And this is the C++ API calls required to recreate that:

 // Function: foo (func_foo)
 {
  Function::arg_iterator args = func_foo->arg_begin();
  Value* int32_a = args++;
  int32_a->setName("a");
  Value* float_b = args++;
  float_b->setName("b");

  BasicBlock* label_entry = BasicBlock::Create(mod->getContext(), "entry",func_foo,0);

  // Block entry (label_entry)
  CastInst* float_conv = new SIToFPInst(int32_a, Type::getFloatTy(mod->getContext()), "conv", label_entry);
  BinaryOperator* float_add = BinaryOperator::Create(Instruction::FAdd, float_conv, float_b, "add", label_entry);
  ReturnInst::Create(mod->getContext(), float_add, label_entry);   
 }

You're free to tweak the input C code (i.e. replacing vars with constants, etc) and seeing what Clang/LLVM emit. This is the best/quickest way to find your way around the IR and API when you're not too familiar with it.

OTHER TIPS

The problem is here:

Instruction* cast = CastInst::Create(Instruction::SIToFP, left, left->getType(), "", currentBlock());

You casted left to left->getType(), i.e., you did nothing. Cast to right->getType() instead:

Instruction* cast = CastInst::Create(Instruction::SIToFP, left, right->getType(), "", currentBlock());

LLVM 12

    Value *cg_binary(BinaryAst *ast)
    {
      auto l = codegen(ast->left);
      auto r = codegen(ast->right);
      switch (ast->op)
      {
      case parser::token::PLUS:
      {
        if (l->getType()->getTypeID() == Type::TypeID::DoubleTyID || r->getType()->getTypeID() == Type::TypeID::DoubleTyID)
          return b->CreateFAdd(b->CreateSIToFP(l, b->getDoubleTy()), b->CreateSIToFP(r, b->getDoubleTy()));
        else
          return b->CreateAdd(l, r);
      }
      }
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top