mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-08 20:06:03 +03:00
structs support
This commit is contained in:
parent
28abe2c975
commit
f102c3d471
10 changed files with 121 additions and 31 deletions
|
@ -24,7 +24,7 @@ enum {
|
|||
};
|
||||
|
||||
llvm::FunctionType *getDstFuncType(llvm::FunctionType &srcType,
|
||||
const llvm::ArrayRef<Slice> ¶ms) {
|
||||
const llvm::ArrayRef<ParamSlice> ¶ms) {
|
||||
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> ¶ms) {
|
||||
const llvm::ArrayRef<ParamSlice> ¶ms) {
|
||||
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> ¶ms,
|
||||
llvm::Function &srcFunc, const llvm::ArrayRef<ParamSlice> ¶ms,
|
||||
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 ¶m = 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> ¶ms,
|
||||
const llvm::ArrayRef<ParamSlice> ¶ms,
|
||||
llvm::function_ref<void(const std::string &)> errHandler) {
|
||||
auto srcType = srcFunc.getFunctionType();
|
||||
auto dstType = getDstFuncType(*srcType, params);
|
||||
|
|
|
@ -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> ¶ms,
|
||||
const llvm::ArrayRef<ParamSlice> ¶ms,
|
||||
llvm::function_ref<void(const std::string &)> errHandler);
|
||||
|
||||
#endif // BIND_H
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -155,7 +155,7 @@ void JITContext::reset() {
|
|||
}
|
||||
|
||||
void JITContext::registerBind(void *handle, void *originalFunc,
|
||||
const llvm::ArrayRef<Slice> ¶ms) {
|
||||
const llvm::ArrayRef<ParamSlice> ¶ms) {
|
||||
assert(bindInstances.count(handle) == 0);
|
||||
BindDesc::ParamsVec vec(params.begin(), params.end());
|
||||
bindInstances.insert({handle, {originalFunc, std::move(vec)}});
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
32
runtime/jit-rt/cpp-so/param_slice.h
Normal file
32
runtime/jit-rt/cpp-so/param_slice.h
Normal 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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue