0
votes

I'm trying to write a compiler for a c-like language using llvm for educational purposes.

So far, it's going quite well but I often have issues with the lack of documentation on actual usage. The examples I find are rather thin and clang is a bit too complex since it includes all the possible features in c++.

When generating code for a variable declaration and the initialization of it, I use AllocaInst with a known type since the language is strongly typed. On the other hand, I also have the code generation for the initialization of the right-hand expression where I'm currently not aware of the desired type.

The allocation looks like this: llvm::AllocaInst *alloc = new llvm::AllocaInst(generateType(varDecl->getType()), varDecl->identifier().c_str(), block);

I then generate the expression the right hand side and for a simple integer I end up calling this: llvm::ConstantInt::get(llvm::Type::getInt32Ty(m_context), decExpr->value(), block);

My problem is that when I call the store instruction, I might have issues if the variable is declared on 8 bits and the value for the expression uses a 32 bit type (even though it may fit on 8 bits): llvm::StoreInst(val, alloc, false, block);

My first idea would be to check the types and convert but that seems redundant for a value that is going to fit anyway. Another idea would be to pass a type hint when generating the right-hand expression and generate my constant integer using that type but that seems like a hack and I'm trying to avoid those.

My question here is: what would be the best reasonable approch to handle this issue? I'm currently not aware of any forums/ IRC channels that could help people in similar situations so any kind of help would be appreciated.

1
Why don't you know the types? If your language is statically typed, you should know the types of every expression before starting code generation. - Ismail Badawi
Honestly, it seems you didn't read the question. I know the type of every expression before starting code generation. I don't know the type of the left-hand value. - Sanctus2099

1 Answers

-1
votes

LLVM will require your L-value and R-value types to match so you need to be explicit about whether it's e.g. i8 or i32 in each assignment case.

Assuming you don't want the compiler to generate code that may silently truncate the value (risk losing data without emitting a warning), you'll need to ensure the L-value is at least as wide as the R-value requires.

If on the other hand the L-value is wider than the R-value, you'll need to extend the R-value before storing it.

One tip is to use LLVM's casting op-codes for scalars, e.g:

Instruction::CastOps cop = CastInst::getCastOpcode( srcValue, srcSigned, dstLlvmType, dstSigned );
Value* newSrcVal = builder->CreateCast( cop, srcValue, dstLlvmType, "" );