Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F3995474
llvmlayer.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Jul 7, 10:51 AM
Size
7 KB
Mime Type
text/x-c++
Expires
Thu, Jul 9, 10:51 AM (20 h, 28 m)
Engine
blob
Format
Raw Data
Handle
269130
Attached To
rXR Xreate
llvmlayer.cpp
View Options
/* 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/.
*
* llvmlayer.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
*/
/**
* \file llvmlayer.h
* \brief Bytecode generation
*/
#include "ast.h"
#include "llvmlayer.h"
#include "analysis/typehints.h"
#ifdef XREATE_ENABLE_EXTERN
#include "ExternLayer.h"
#endif
#include <compilation/containers.h>
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/Support/TargetSelect.h"
#include <iostream>
#include <cmath>
using namespace llvm;
using namespace xreate;
using namespace xreate::typehints;
using namespace std;
LLVMLayer::LLVMLayer(AST *root)
: llvmContext(),
irBuilder(llvmContext),
ast(root),
module(new llvm::Module(root->getModuleName(), llvmContext)){
llvm::InitializeNativeTarget();
llvm::InitializeNativeTargetAsmPrinter();
llvm::EngineBuilder builder;
TargetMachine *target = builder.selectTarget();
module->setDataLayout(target->createDataLayout());
#ifdef XREATE_ENABLE_EXTERN
layerExtern = new ExternLayer(this);
layerExtern->init(root);
#endif
}
void *
LLVMLayer::getFunctionPointer(llvm::Function *function){
uint64_t entryAddr = jit->getFunctionAddress(function->getName().str());
return (void *) entryAddr;
}
void
LLVMLayer::initJit(){
std::string ErrStr;
llvm::EngineBuilder builder(std::unique_ptr<llvm::Module>(module.release()));
jit.reset(builder
.setEngineKind(llvm::EngineKind::JIT)
.setTargetOptions(optsTarget)
.setOptLevel(optsLevel)
.setErrorStr(&ErrStr)
.setVerifyModules(true)
.create()
);
}
void
LLVMLayer::print(){
llvm::PassManager<llvm::Module> PM;
PM.addPass(llvm::PrintModulePass(llvm::outs(), "banner"));
llvm::AnalysisManager<llvm::Module> aman;
PM.run(*module.get(), aman);
}
void
LLVMLayer::moveToGarbage(void *o){
__garbage.push_back(o);
}
llvm::Type*
LLVMLayer::toLLVMType(const ExpandedType &ty, const Expression& expr){
TypeAnnotation t = ty.get();
switch(t.__operator){
case TypeOperator::ARRAY:{
if (expr.tags.size() == 0) return nullptr; //TODO shouldn't be invalid
return containers::IContainersIR::getRawType(expr, ty, this);
}
case TypeOperator::RECORD:{
std::vector<llvm::Type *> packVec;
packVec.reserve(t.__operands.size());
std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(packVec, packVec.end()),
[this](const TypeAnnotation &t){
return toLLVMType(ExpandedType(TypeAnnotation(t)));
});
llvm::ArrayRef<llvm::Type *> packArr(packVec);
return llvm::StructType::get(llvmContext, packArr, false);
};
case TypeOperator::REF:{
TypeAnnotation tyRef = t.__operands.at(0);
assert(tyRef.__operator == TypeOperator::ALIAS);
llvm::StructType *tyOpaqRaw = llvm::StructType::create(llvmContext, tyRef.__valueCustom);
llvm::PointerType *tyRefRaw = llvm::PointerType::get(tyOpaqRaw, 0);
return tyRefRaw;
};
case TypeOperator::ALIAS:{
#ifdef XREATE_ENABLE_EXTERN
//Look in extern types
clang::QualType qt = layerExtern->lookupType(t.__valueCustom);
return layerExtern->toLLVMType(qt);
#else
assert(false);
#endif
};
//DEBT omit ID field in case of single variant.
case TypeOperator::VARIANT:{
/* Variant Type Layout:
* {
* id :: i8, Holds stored variant id
* storage:: type of biggest variant
* }
*/
uint64_t sizeStorage = 0;
llvm::Type *typStorageRaw = llvm::Type::getVoidTy(llvmContext);
for(const TypeAnnotation &subtype : t.__operands){
llvm::Type *subtypeRaw = toLLVMType(ExpandedType(subtype));
if(subtypeRaw->isVoidTy()) continue;
uint64_t sizeSubtype = module->getDataLayout().getTypeStoreSize(subtypeRaw);
if(sizeSubtype > sizeStorage){
sizeStorage = sizeSubtype;
typStorageRaw = subtypeRaw;
}
}
std::vector<llvm::Type *> layout;
layout.push_back(llvm::Type::getInt8Ty(llvmContext)); //id
const bool flagHoldsData = sizeStorage > 0;
if(flagHoldsData){
layout.push_back(typStorageRaw); //storage
}
return llvm::StructType::get(llvmContext, llvm::ArrayRef<llvm::Type *>(layout));
}
case TypeOperator::NONE:{
switch(t.__value){
case TypePrimitive::Bool:
return llvm::Type::getInt1Ty(llvmContext);
case TypePrimitive::I8:
return llvm::Type::getInt8Ty(llvmContext);
case TypePrimitive::I32:
return llvm::Type::getInt32Ty(llvmContext);
case TypePrimitive::I64:
return llvm::Type::getInt64Ty(llvmContext);
case TypePrimitive::Int: {
// IntBits hintSize;
// if (existsSize(hintSize)){
// return llvm::IntegerType::getIntNTy(llvmContext, hintSize.n);
// }
TypesHelper helper(this);
return helper.getPreferredIntTy();
}
case TypePrimitive::Float:
return llvm::Type::getDoubleTy(llvmContext);
case TypePrimitive::String:
return llvm::Type::getInt8PtrTy(llvmContext);
case TypePrimitive::Invalid:
return llvm::Type::getVoidTy(llvmContext);
default:
assert(false);
}
}
default:
assert(false);
}
assert(false);
return nullptr;
}
bool
TypesHelper::isRecordT(const ExpandedType &ty){
const TypeAnnotation &t = ty.get();
if(t.__operator == TypeOperator::RECORD){
return true;
}
if(t.__operator != TypeOperator::ALIAS){
return false;
}
#ifdef XREATE_ENABLE_EXTERN
clang::QualType tqual = llvm->layerExtern->lookupType(t.__valueCustom);
const clang::Type * raw = tqual.getTypePtr();
// TODO skip ALL the pointers until non-pointer type found
if (raw->isStructureType()) return true;
if (!raw->isAnyPointerType()) return false;
clang::QualType pointee = raw->getPointeeType();
return pointee->isStructureType();
#else
assert(false);
return false;
#endif
}
bool
TypesHelper::isArrayT(const Expanded<TypeAnnotation>& ty){
const TypeAnnotation &t = ty.get();
if(t.__operator == TypeOperator::ARRAY){
return true;
}
return false;
}
bool
TypesHelper::isPointerT(const ExpandedType &ty){
if(ty.get().__operator != TypeOperator::ALIAS) return false;
#ifdef XREATE_ENABLE_EXTERN
clang::QualType qt = llvm->layerExtern->lookupType(ty.get().__valueCustom);
return llvm->layerExtern->isPointer(qt);
#else
assert(false);
return false;
#endif
}
bool
TypesHelper::isIntegerT(const Expanded<TypeAnnotation>& ty){
return
(ty->__operator == TypeOperator::NONE) &&
((ty->__value == TypePrimitive::Bool) ||
(ty->__value == TypePrimitive::I8) ||
(ty->__value == TypePrimitive::I32) ||
(ty->__value == TypePrimitive::I64) ||
(ty->__value == TypePrimitive::Int));
}
std::vector<std::string>
TypesHelper::getRecordFields(const ExpandedType &t){
#ifdef XREATE_ENABLE_EXTERN
return (t.get().__operator == TypeOperator::RECORD)
? t.get().fields
: llvm->layerExtern->getStructFields(
llvm->layerExtern->lookupType(t.get().__valueCustom));
#else
assert(t.get().__operator == TypeOperator::RECORD);
return t.get().fields;
#endif
}
llvm::IntegerType *
TypesHelper::getPreferredIntTy() const{
unsigned sizePreferred = llvm->module->getDataLayout().getLargestLegalIntTypeSizeInBits();
return llvm::IntegerType::getIntNTy(llvm->llvmContext, sizePreferred);
}
Event Timeline
Log In to Comment