Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LLVM Cast Instructions

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.

like image 421
Blake Avatar asked Nov 18 '13 22:11

Blake


2 Answers

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.

like image 149
Eli Bendersky Avatar answered Nov 09 '22 23:11

Eli Bendersky


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());
like image 1
jv110 Avatar answered Nov 09 '22 21:11

jv110