typeinference.cpp
No OneTemporary

File Metadata

Created
Thu, Jul 9, 6:28 AM

typeinference.cpp

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* typeinference.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on April 16, 2017, 10:13 AM
*/
/**
* \file typeinference.h
* \brief Type inference analysis
*/
#include "typeinference.h"
#include "llvmlayer.h"
#include "transcendlayer.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/DerivedTypes.h"
using namespace std;
namespace xreate{
namespace typeinference{
//TODO type conversion:
//a) automatically expand types int -> bigger int; int -> floating
//b) detect exact type of `num` based on max used numeral / function type
//c) warning if need to truncate (allow/dissallow based on annotations)
llvm::Value*
doAutomaticTypeConversion(llvm::Value* source, llvm::Type* tyTarget, llvm::IRBuilder<>& builder) {
if(tyTarget->isIntegerTy() && source->getType()->isIntegerTy()) {
llvm::IntegerType* tyTargetInt = llvm::dyn_cast<llvm::IntegerType>(tyTarget);
llvm::IntegerType* tySourceInt = llvm::dyn_cast<llvm::IntegerType>(source->getType());
if(tyTargetInt->getBitWidth() < tySourceInt->getBitWidth()) {
return builder.CreateCast(llvm::Instruction::Trunc, source, tyTarget);
}
if(tyTargetInt->getBitWidth() > tySourceInt->getBitWidth()) {
return builder.CreateCast(llvm::Instruction::SExt, source, tyTarget);
}
}
if(source->getType()->isIntegerTy() && tyTarget->isFloatingPointTy()) {
return builder.CreateCast(llvm::Instruction::SIToFP, source, tyTarget);
}
if (source->getType()->isStructTy() && tyTarget->isIntegerTy()){
llvm::StructType* sourceST = llvm::cast<llvm::StructType>(source->getType());
if(sourceST->getNumElements() == 1) {
llvm::Value* sourceElRaw = builder.CreateExtractValue(source, llvm::ArrayRef<unsigned>({0}));
return doAutomaticTypeConversion(sourceElRaw, tyTarget, builder);
}
}
return source;
}
ExpandedType
getType(const Expression& expression, const AST& ast) {
if(expression.type.isValid()) {
return ast.expandType(expression.type);
}
if(expression.__state == Expression::IDENT) {
Symbol s = Attachments::get<IdentifierSymbol>(expression);
return getType(CodeScope::getDefinition(s), ast);
}
if(Attachments::exists<TypeInferred>(expression)) {
return Attachments::get<TypeInferred>(expression);
}
if(expression.__state == Expression::NUMBER) {
return ExpandedType(TypeAnnotation(TypePrimitive::I32));
}
assert(false && "Type can't be determined for an expression");
}
}
} //end of namespace xreate::typeinference

Event Timeline