structs support

This commit is contained in:
Ivan 2018-06-03 02:41:28 +03:00
parent 28abe2c975
commit f102c3d471
10 changed files with 121 additions and 31 deletions

View file

@ -24,7 +24,7 @@ enum {
};
llvm::FunctionType *getDstFuncType(llvm::FunctionType &srcType,
const llvm::ArrayRef<Slice> &params) {
const llvm::ArrayRef<ParamSlice> &params) {
assert(!srcType.isVarArg());
llvm::SmallVector<llvm::Type*, SmallParamsCount> newParams;
const auto srcParamsCount = srcType.params().size();
@ -41,7 +41,7 @@ llvm::FunctionType *getDstFuncType(llvm::FunctionType &srcType,
llvm::Function *createBindFunc(llvm::Module &module,
llvm::Function &srcFunc,
llvm::FunctionType &funcType,
const llvm::ArrayRef<Slice> &params) {
const llvm::ArrayRef<ParamSlice> &params) {
auto newFunc = llvm::Function::Create(
&funcType, llvm::GlobalValue::ExternalLinkage, "\1.jit_bind",
&module);
@ -65,8 +65,28 @@ llvm::Function *createBindFunc(llvm::Module &module,
return newFunc;
}
llvm::Value *allocParam(
llvm::IRBuilder<> &builder, llvm::Type &srcType, const
llvm::DataLayout &layout, const ParamSlice& param,
llvm::function_ref<void(const std::string &)> errHandler) {
if (param.type == ParamType::Aggregate && srcType.isPointerTy()) {
auto elemType = llvm::cast<llvm::PointerType>(&srcType)->getElementType();
auto stackArg = builder.CreateAlloca(elemType);
stackArg->setAlignment(layout.getABITypeAlignment(elemType));
auto init = parseInitializer(layout, *elemType, param.data, errHandler);
builder.CreateStore(init, stackArg);
return stackArg;
}
auto stackArg = builder.CreateAlloca(&srcType);
stackArg->setAlignment(layout.getABITypeAlignment(&srcType));
auto init = parseInitializer(layout, srcType, param.data, errHandler);
builder.CreateStore(init, stackArg);
return builder.CreateLoad(stackArg);
}
void doBind(llvm::Module &module, llvm::Function &dstFunc,
llvm::Function &srcFunc, const llvm::ArrayRef<Slice> &params,
llvm::Function &srcFunc, const llvm::ArrayRef<ParamSlice> &params,
llvm::function_ref<void(const std::string &)> errHandler) {
auto& context = dstFunc.getContext();
auto bb = llvm::BasicBlock::Create(context, "", &dstFunc);
@ -75,20 +95,17 @@ void doBind(llvm::Module &module, llvm::Function &dstFunc,
builder.SetInsertPoint(bb);
llvm::SmallVector<llvm::Value*, SmallParamsCount> args;
auto currentArg = dstFunc.arg_begin();
auto funcType = srcFunc.getFunctionType();
auto &layout = module.getDataLayout();
for (size_t i = 0; i < params.size(); ++i) {
auto type = srcFunc.getFunctionType()->getParamType(static_cast<unsigned>(i));
llvm::Value* arg = nullptr;
if (params[i].data == nullptr) {
const auto &param = params[i];
if (param.data == nullptr) {
arg = currentArg;
++currentArg;
} else {
auto &layout = module.getDataLayout();
auto stackArg = builder.CreateAlloca(type);
stackArg->setAlignment(layout.getABITypeAlignment(type));
const auto& param = params[i];
auto init = parseInitializer(layout, *type, param.data, errHandler);
builder.CreateStore(init, stackArg);
arg = builder.CreateLoad(stackArg);
auto type = funcType->getParamType(static_cast<unsigned>(i));
arg = allocParam(builder, *type, layout, param, errHandler);
}
assert(arg != nullptr);
args.push_back(arg);
@ -107,7 +124,7 @@ void doBind(llvm::Module &module, llvm::Function &dstFunc,
llvm::Function *bindParamsToFunc(
llvm::Module &module, llvm::Function &srcFunc,
const llvm::ArrayRef<Slice> &params,
const llvm::ArrayRef<ParamSlice> &params,
llvm::function_ref<void(const std::string &)> errHandler) {
auto srcType = srcFunc.getFunctionType();
auto dstType = getDstFuncType(*srcType, params);

View file

@ -15,7 +15,7 @@
#ifndef BIND_H
#define BIND_H
#include "context.h" // Slice
#include "param_slice.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
@ -27,7 +27,7 @@ class Function;
llvm::Function *bindParamsToFunc(
llvm::Module &module, llvm::Function &srcFunc,
const llvm::ArrayRef<Slice> &params,
const llvm::ArrayRef<ParamSlice> &params,
llvm::function_ref<void(const std::string &)> errHandler);
#endif // BIND_H

View file

@ -394,7 +394,7 @@ EXTERNAL void JIT_API_ENTRYPOINT(const void *modlist_head,
}
EXTERNAL void JIT_REG_BIND_PAYLOAD(void *handle, void *originalFunc,
const Slice *params, size_t paramsSize) {
const ParamSlice *params, size_t paramsSize) {
assert(handle != nullptr);
assert(originalFunc != nullptr);
JITContext &myJit = getJit();

View file

@ -15,6 +15,9 @@
#define CONTEXT_H
#include <cstddef> //size_t
#include <cstdint>
#include "param_slice.h"
enum class DumpStage : int {
OriginalModule = 0,
@ -25,11 +28,6 @@ enum class DumpStage : int {
enum { ApiVersion = LDC_DYNAMIC_COMPILE_API_VERSION };
struct Slice {
const void *data;
size_t size;
};
#ifdef _WIN32
#define EXTERNAL __declspec(dllexport)
#else

View file

@ -155,7 +155,7 @@ void JITContext::reset() {
}
void JITContext::registerBind(void *handle, void *originalFunc,
const llvm::ArrayRef<Slice> &params) {
const llvm::ArrayRef<ParamSlice> &params) {
assert(bindInstances.count(handle) == 0);
BindDesc::ParamsVec vec(params.begin(), params.end());
bindInstances.insert({handle, {originalFunc, std::move(vec)}});

View file

@ -91,7 +91,7 @@ private:
struct BindDesc final {
void *originalFunc;
using ParamsVec = llvm::SmallVector<Slice, 5>;
using ParamsVec = llvm::SmallVector<ParamSlice, 5>;
ParamsVec params;
};
llvm::MapVector<void*, BindDesc> bindInstances;
@ -123,7 +123,7 @@ public:
void reset();
void registerBind(void *handle, void *originalFunc,
const llvm::ArrayRef<Slice>& params);
const llvm::ArrayRef<ParamSlice>& params);
void unregisterBind(void *handle);

View file

@ -0,0 +1,32 @@
//===-- param_slice.h - jit support -----------------------------*- C++ -*-===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the Boost Software License. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
//
// ParamSlice declaration. Holds pointer into bind parameter and some metadata,
// will be null for placeholders.
//
//===----------------------------------------------------------------------===//
#ifndef PARAM_SLICE_H
#define PARAM_SLICE_H
#include <cstddef> //size_t
#include <cstdint>
enum ParamType : uint32_t {
Simple = 0,
Aggregate = 1
};
struct ParamSlice {
const void *data;
size_t size;
ParamType type;
};
#endif // PARAM_SLICE_H

View file

@ -15,7 +15,7 @@
#include <cstddef> // size_t
struct Context;
struct Slice;
struct ParamSlice;
#ifdef _WIN32
#define EXTERNAL __declspec(dllimport) extern
@ -46,7 +46,7 @@ EXTERNAL void JIT_API_ENTRYPOINT(const void *modlist_head,
std::size_t contextSize);
EXTERNAL void JIT_REG_BIND_PAYLOAD(void *handle, void *originalFunc,
const Slice *desc, size_t descSize);
const ParamSlice *desc, size_t descSize);
EXTERNAL void JIT_UNREG_BIND_PAYLOAD(void *handle);
@ -54,7 +54,7 @@ void rtCompileProcessImpl(const Context *context, std::size_t contextSize) {
JIT_API_ENTRYPOINT(dynamiccompile_modules_head, context, contextSize);
}
void registerBindPayload(void *handle, void *originalFunc, const Slice *desc,
void registerBindPayload(void *handle, void *originalFunc, const ParamSlice *desc,
size_t descSize) {
JIT_REG_BIND_PAYLOAD(handle, originalFunc, desc, descSize);
}

View file

@ -219,13 +219,14 @@ struct BindPayload(OF, F, int[] Index, Args...)
void register()
{
assert(!registered);
Slice[ParametersCount] desc;
ParamSlice[ParametersCount] desc;
static foreach(i, ind; Index)
{
static if (InvalidIndex != ind)
{
desc[i].data = &(argStore.args[ind]);
desc[i].size = (argStore.args[ind]).sizeof;
desc[i].type = (isAggregateType!(typeof(argStore.args[ind])) ? ParamType.Aggregate : ParamType.Simple);
}
}
@ -332,10 +333,15 @@ public:
extern(C)
{
struct Slice
enum ParamType : uint {
Simple = 0,
Aggregate = 1
}
struct ParamSlice
{
const(void)* data = null;
size_t size = 0;
ParamType type = ParamType.Simple;
}
void progressHandlerWrapper(void* context, const char* desc, const char* obj)
@ -369,7 +375,7 @@ struct Context
}
extern void rtCompileProcessImpl(const ref Context context, size_t contextSize);
void registerBindPayload(void* handle, void* originalFunc, const Slice* params, size_t paramsSize);
void registerBindPayload(void* handle, void* originalFunc, const ParamSlice* params, size_t paramsSize);
void unregisterBindPayload(void* handle);
}

View file

@ -4,7 +4,8 @@
import ldc.attributes;
import ldc.dynamic_compile;
@dynamicCompile int foo(int a, int b, int c)
@dynamicCompile
int foo(int a, int b, int c)
{
return a + b + c;
}
@ -14,6 +15,30 @@ int bar(int a, int b, int c)
return a + b + c;
}
struct Foo
{
int i;
int j;
}
struct Bar
{
Foo f;
int k;
}
@dynamicCompile
int baz1(Bar b)
{
return b.f.i + b.f.j + b.k;
}
@dynamicCompile
int baz2(Bar* b)
{
return b.f.i + b.f.j + b.k;
}
void main(string[] args)
{
foreach (i; 0..4)
@ -36,6 +61,12 @@ void main(string[] args)
auto b3 = ldc.dynamic_compile.bind(&bar, 1, 2, 3);
auto b4 = b3;
auto bz1 = ldc.dynamic_compile.bind(&baz1, Bar(Foo(1,2),3));
auto bz2 = ldc.dynamic_compile.bind(&baz2, Bar(Foo(1,2),3));
int delegate() bzd1 = bz1.toDelegate();
int delegate() bzd2 = bz2.toDelegate();
compileDynamicCode(settings);
assert(6 == f1(1,2,3));
assert(6 == f2(2));
@ -51,5 +82,11 @@ void main(string[] args)
assert(!b2.isCallable());
assert(!b3.isCallable());
assert(!b4.isCallable());
assert(6 == bz1());
assert(6 == bz2());
assert(6 == bzd1());
assert(6 == bzd2());
}
}