Commit c5805662 authored by Victor Yacovlev's avatar Victor Yacovlev

Updated libLLVM usage to version 3.8

parent d3ba5dda
project(LLVMCodeGenerator)
cmake_minimum_required(VERSION 2.8.3)
cmake_minimum_required(VERSION 3.0.0)
if(NOT DEFINED USE_QT)
set(USE_QT 4)
......@@ -38,6 +38,9 @@ set(SOURCES
llvmcodegeneratorplugin.cpp
llvmgenerator.cpp
nametranslator.cpp
llvm_module_${Llvm_API_VERSION}.cpp
llvm_function_${Llvm_API_VERSION}.cpp
llvm_type_${Llvm_API_VERSION}.cpp
)
set(MOC_HEADERS
......@@ -123,9 +126,8 @@ if(WIN32)
)
else()
find_program(Clang_EXECUTABLE NAMES clang PATHS ${LLVM_ROOT} ${LLVM_ROOT}/bin)
add_custom_target(
stdlib.llvm
ALL
add_custom_command(
OUTPUT ${SHARE_PATH}/llvmcodegenerator/stdlib.bc
DEPENDS stdlib_c.h stdlib_c.cpp
COMMAND ${Clang_EXECUTABLE} -c -std=c++0x -emit-llvm
-I${CMAKE_SOURCE_DIR}/src/shared
......@@ -133,9 +135,8 @@ else()
${CMAKE_CURRENT_SOURCE_DIR}/stdlib_c.cpp
)
if(CMAKE_BUILD_TYPE MATCHES Debug)
add_custom_target(
stdlib.llvm-debug
ALL
add_custom_command(
OUTPUT ${SHARE_PATH}/llvmcodegenerator/stdlib_debug.o
DEPENDS stdlib_c.h stdlib_c.cpp
COMMAND ${Clang_EXECUTABLE} -c -g -std=c++0x -DSTDLIB_DEBUG
-I${CMAKE_SOURCE_DIR}/src/shared
......
#ifndef LLVM_FUNCTION_H
#define LLVM_FUNCTION_H
#include "llvm_module.h"
#include "llvm_type.h"
#include <memory>
#include <QVector>
namespace llvm {
class LLVMContext;
class Function;
class Value;
class CallInst;
}
namespace LLVM {
struct FunctionRefPrivate;
class FunctionRef {
friend class ModuleRef;
public:
enum Visibility { VS_Extern, VS_Static };
llvm::Function* rawPtr() const;
QByteArray name() const;
bool hasExternalLinkage() const;
static FunctionRef create(
TypeRef returnType,
Visibility visibility,
const QByteArray &name,
const QVector<TypeRef> &argTypes,
const QVector<QByteArray> &argNames,
bool firstArgIsReturnValuePointer,
class ModuleRef & parent,
llvm::LLVMContext* context
);
void copyToModule(ModuleRef & target);
operator bool() const;
bool operator == (const FunctionRef & other) const;
llvm::CallInst* createCallInstruction(void *builder, const QVector<llvm::Value*> &values);
inline llvm::CallInst* createCallInstruction(void *builder) {
return createCallInstruction(builder, QVector<llvm::Value*>());
}
inline llvm::CallInst* createCallInstruction(void *builder, llvm::Value* arg1) {
QVector<llvm::Value*> args(1);
args[0] = arg1;
return createCallInstruction(builder, args);
}
inline llvm::CallInst* createCallInstruction(void *builder, llvm::Value* arg1, llvm::Value* arg2) {
QVector<llvm::Value*> args(2);
args[0] = arg1;
args[1] = arg2;
return createCallInstruction(builder, args);
}
inline llvm::CallInst* createCallInstruction(void *builder, llvm::Value* arg1, llvm::Value* arg2, llvm::Value* arg3) {
QVector<llvm::Value*> args(3);
args[0] = arg1;
args[1] = arg2;
args[2] = arg3;
return createCallInstruction(builder, args);
}
inline llvm::CallInst* createCallInstruction(void *builder, llvm::Value* arg1, llvm::Value* arg2, llvm::Value* arg3, llvm::Value* arg4) {
QVector<llvm::Value*> args(4);
args[0] = arg1;
args[1] = arg2;
args[2] = arg3;
args[3] = arg4;
return createCallInstruction(builder, args);
}
private:
llvm::Function * d = 0;
};
}
#endif
#include "llvm_function.h"
#include "llvm_type.h"
#include "llvm_module.h"
#include <llvm/IR/IRBuilder.h>
namespace LLVM {
llvm::Function* FunctionRef::rawPtr() const
{
return d;
}
QByteArray FunctionRef::name() const
{
llvm::StringRef ls = rawPtr()->getName();
return QByteArray(ls.begin(), ls.size());
}
bool FunctionRef::hasExternalLinkage() const
{
return rawPtr()->hasExternalLinkage();
}
FunctionRef FunctionRef::create(
TypeRef returnType,
Visibility visibility,
const QByteArray &name,
const QVector<TypeRef> &argTypes,
const QVector<QByteArray> &argNames,
bool firstArgIsReturnValuePointer,
ModuleRef & parent,
llvm::LLVMContext* ctx
)
{
llvm::Type *lt = returnType.rawPtr();
std::vector<llvm::Type*> largTypes(argTypes.size());
for (int i=0; i<argTypes.size(); ++i) {
llvm::Type *at = (llvm::Type*) argTypes[i].rawPtr();
largTypes[i] = at;
}
llvm::FunctionType * lft = largTypes.empty()
? llvm::FunctionType::get(lt, false)
: llvm::FunctionType::get(lt, largTypes, false)
;
llvm::GlobalValue::LinkageTypes link =
VS_Extern==visibility
? llvm::GlobalValue::ExternalLinkage
: llvm::GlobalValue::PrivateLinkage
;
std::string lname(name.constData(), name.size());
llvm::Module *lm = (llvm::Module*) parent.rawPtr();
llvm::Function *lf = llvm::Function::Create(
lft, link, lname, lm
);
lf->addFnAttr(llvm::Attribute::NoUnwind);
lf->addFnAttr(llvm::Attribute::UWTable);
typedef llvm::Function::ArgumentListType::iterator AIt;
int argNumber = 0;
for (AIt it=lf->getArgumentList().begin();
argNumber<argNames.size() ; ++argNumber, ++it)
{
const std::string argName(argNames[argNumber].constData());
it->setName(argName);
}
if (firstArgIsReturnValuePointer) {
llvm::Argument & firstArg = lf->getArgumentList().front();
llvm::AttrBuilder abuilder;
abuilder.addAttribute(llvm::Attribute::StructRet);
abuilder.addAttribute(llvm::Attribute::NoAlias);
firstArg.addAttr(llvm::AttributeSet::get(*ctx, 0, abuilder));
firstArg.addAttr(llvm::AttributeSet::get(*ctx, 1, abuilder));
}
FunctionRef result;
result.d = (lf);
return result;
}
void FunctionRef::copyToModule(ModuleRef & target)
{
llvm::FunctionType * ft = d->getFunctionType();
llvm::StringRef fn = d->getName();
llvm::GlobalValue::LinkageTypes fl = d->getLinkage();
llvm::Module* tm = target.rawPtr();
llvm::Function::Create(ft,fl,fn,tm);
}
LLVM::FunctionRef::operator bool() const
{
return 0 != rawPtr();
}
bool FunctionRef::operator ==(const FunctionRef &other) const
{
return rawPtr() == other.rawPtr();
}
llvm::CallInst *FunctionRef::createCallInstruction(void *b, const QVector<llvm::Value *> &values)
{
llvm::IRBuilder<> * builder =
reinterpret_cast<llvm::IRBuilder<>*>(b);
std::vector<llvm::Value*> callArgs(values.size());
std::copy(values.begin(), values.end(), callArgs.begin());
return builder->CreateCall(d, callArgs);
}
}
#ifndef LLVM_MODULE_H
#define LLVM_MODULE_H
#include "llvm_function.h"
#include "llvm_type.h"
#include <memory>
#include <QByteArray>
#include <QString>
namespace llvm {
class Module;
class LLVMContext;
}
namespace LLVM {
class FunctionRef;
struct ModuleRefPrivate;
class ModuleRef {
public:
llvm::Module * rawPtr() const;
static ModuleRef create(llvm::LLVMContext * context);
static ModuleRef fromTextRepresentation(const QByteArray &text, llvm::LLVMContext * context);
static ModuleRef fromBinaryRepresentation(const QByteArray &data,
const QString &fileName,
llvm::LLVMContext * context
);
LLVM::FunctionRef getFunction(const QByteArray & name) const;
LLVM::TypeRef getType(const QByteArray &name) const;
QList<LLVM::FunctionRef> functions() const;
// Waring!!!: this DESTROYS source module, so it must be recreated
// after calling this method (thanks to f**king LLVM API)
void linkInto(ModuleRef & dest);
QByteArray textRepresentation() const;
QByteArray binaryRepresentation() const;
operator bool() const;
bool operator == (const ModuleRef other) const;
ModuleRef();
ModuleRef(ModuleRef && src);
ModuleRef& operator=(ModuleRef && src);
~ModuleRef();
private:
std::unique_ptr<llvm::Module> d;
};
}
#endif
#include "llvm_module.h"
#include <memory>
#include <string>
#include <QByteArray>
#include <QCoreApplication>
#include <QVariant>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/Linker/Linker.h>
#include <llvm/Support/ErrorOr.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/AsmParser/Parser.h>
namespace LLVM {
void ModuleRef::linkInto(ModuleRef & dest)
{
llvm::Module & ldest = *(dest.rawPtr());
llvm::Linker::linkModules(ldest, std::move(d));
}
QByteArray ModuleRef::textRepresentation() const
{
std::string buf;
llvm::raw_string_ostream ostream(buf);
d->print(ostream, 0);
ostream.flush();
buf = ostream.str();
return QByteArray(buf.c_str(), buf.size());
}
QByteArray ModuleRef::binaryRepresentation() const
{
std::string buf;
llvm::raw_string_ostream ostream(buf);
llvm::WriteBitcodeToFile(d.get(), ostream);
ostream.flush();
buf = ostream.str();
return QByteArray(buf.c_str(), buf.size());
}
LLVM::ModuleRef::operator bool() const
{
if (!d) return false;
return 0 != rawPtr();
}
bool ModuleRef::operator ==(const ModuleRef other) const
{
if (!d) {
return !other.d;
}
else {
return d.get() == other.d.get();
}
}
ModuleRef::ModuleRef()
{
}
ModuleRef::ModuleRef(ModuleRef && src)
{
d = std::move(src.d);
}
ModuleRef &ModuleRef::operator=(ModuleRef && src)
{
d = std::move(src.d);
return *this;
}
ModuleRef::~ModuleRef()
{
}
llvm::Module * ModuleRef::rawPtr() const
{
if (d) {
return d.get();
}
else {
return 0;
}
}
ModuleRef ModuleRef::create(llvm::LLVMContext *ctx)
{
ModuleRef result;
result.d =
std::unique_ptr<llvm::Module> (
new llvm::Module("", *ctx)
);
return result;
}
ModuleRef ModuleRef::fromTextRepresentation(const QByteArray &text, llvm::LLVMContext * ctx)
{
llvm::SMDiagnostic lerr;
ModuleRef result;
result.d =
llvm::parseAssemblyString(text.constData(), lerr, *ctx);
if (! result.d ) {
lerr.print("kumir2-llvmc", llvm::errs());
qApp->setProperty("returnCode", QVariant(5));
qApp->quit();
}
return result;
}
ModuleRef ModuleRef::fromBinaryRepresentation(const QByteArray &data,
const QString &fileName,
llvm::LLVMContext * ctx)
{
std::string lFileName(fileName.toUtf8().constData());
std::string lContents(data.constData(), data.size());
std::unique_ptr<llvm::MemoryBuffer> unitBuffer =
llvm::MemoryBuffer::getMemBufferCopy(
lContents, lFileName
);
llvm::MemoryBufferRef unitBufferRef = llvm::MemoryBufferRef(*unitBuffer);
llvm::ErrorOr<std::unique_ptr<llvm::Module>> errorOrUnit =
llvm::parseBitcodeFile(unitBufferRef, *ctx);
ModuleRef result;
if (errorOrUnit) {
result.d = std::move(errorOrUnit.get());
}
return result;
}
TypeRef ModuleRef::getType(const QByteArray &name) const
{
llvm::StructType * t = d->getTypeByName(std::string(name.constData(), name.size()));
TypeRef result;
result.d = (t);
return result;
}
QList<FunctionRef> ModuleRef::functions() const
{
typedef llvm::Module::iterator Fit;
QList<FunctionRef> result;
llvm::Module* lm = rawPtr();
for (Fit it=lm->begin(); it!=lm->end(); ++it) {
llvm::Function & func = *it;
FunctionRef ref;
ref.d = (&func);
result.push_back(ref);
}
return result;
}
FunctionRef ModuleRef::getFunction(const QByteArray &name) const
{
FunctionRef result;
if (d) {
llvm::Module * l = d.get();
llvm::Function *lf = l->getFunction(std::string(name.constData(), name.size()));
result.d = lf;
}
return result;
}
}
#ifndef LLVM_TYPE_H
#define LLVM_TYPE_H
namespace llvm {
class Type;
class LLVMContext;
}
namespace LLVM {
class TypeRef {
friend class ModuleRef;
public:
llvm::Type * rawPtr() const;
enum GenericType { TY_Void = 0, TY_Int = 1, TY_Real = 2, TY_Byte = 3, TY_CStr = 4 };
static TypeRef getGeneric(GenericType t, llvm::LLVMContext* context);
operator bool() const;
bool operator ==(const TypeRef &other) const;
TypeRef pointerTo() const;
private:
llvm::Type * d = 0;
};
}
#endif
#include "llvm_type.h"
#include <llvm/IR/Type.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/LLVMContext.h>
namespace LLVM {
llvm::Type * TypeRef::rawPtr() const
{
return d;
}
TypeRef TypeRef::getGeneric(GenericType type, llvm::LLVMContext * ctx)
{
llvm::Type * t = 0;
switch (type) {
case TY_Void:
t = llvm::Type::getVoidTy(*ctx);
break;
case TY_Int:
t = llvm::Type::getInt32Ty(*ctx);
break;
case TY_Real:
t = llvm::Type::getDoubleTy(*ctx);
break;
case TY_Byte:
t = llvm::Type::getInt8Ty(*ctx);
break;
case TY_CStr:
t = llvm::Type::getInt8PtrTy(*ctx);
break;
default:
t = 0;
break;
}
TypeRef result;
result.d = (t);
return result;
}
LLVM::TypeRef::operator bool() const
{
return bool(d);
}
bool TypeRef::operator ==(const TypeRef &other) const
{
return rawPtr()==other.rawPtr();
}
TypeRef TypeRef::pointerTo() const
{
llvm::Type * me = d;
TypeRef result;
result.d = (me->getPointerTo());
return result;
}
}
......@@ -8,35 +8,24 @@
#endif
#include <llvm/Config/llvm-config.h>
#if LLVM_VERSION_MINOR >= 3
#include <llvm/IR/Module.h>
#include <llvm/IR/LLVMContext.h>
#else
#include <llvm/Module.h>
#include <llvm/LLVMContext.h>
#endif
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Support/raw_os_ostream.h>
#include <llvm/Support/FormattedStream.h>
#if LLVM_VERSION_MINOR >= 5
#include <llvm/Linker/Linker.h>
#include <llvm/AsmParser/Parser.h>