mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 00:20:40 +03:00
935 lines
38 KiB
C++
935 lines
38 KiB
C++
//===-- runtime.cpp -------------------------------------------------------===//
|
||
//
|
||
// LDC – the LLVM D compiler
|
||
//
|
||
// This file is distributed under the BSD-style LDC license. See the LICENSE
|
||
// file for details.
|
||
//
|
||
//===----------------------------------------------------------------------===//
|
||
|
||
#include "gen/runtime.h"
|
||
#include "aggregate.h"
|
||
#include "dsymbol.h"
|
||
#include "lexer.h"
|
||
#include "mars.h"
|
||
#include "module.h"
|
||
#include "mtype.h"
|
||
#include "root.h"
|
||
#include "gen/abi.h"
|
||
#include "gen/irstate.h"
|
||
#include "gen/llvm.h"
|
||
#include "gen/llvmhelpers.h"
|
||
#include "gen/logger.h"
|
||
#include "gen/tollvm.h"
|
||
#include "ir/irtype.h"
|
||
#include "ir/irtypefunction.h"
|
||
#include "llvm/Bitcode/ReaderWriter.h"
|
||
#include "llvm/Support/CommandLine.h"
|
||
#include "llvm/Support/MemoryBuffer.h"
|
||
#include "llvm/IR/Module.h"
|
||
#include "llvm/IR/Attributes.h"
|
||
|
||
#include <algorithm>
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
static llvm::cl::opt<bool> nogc(
|
||
"nogc",
|
||
llvm::cl::desc(
|
||
"Do not allow code that generates implicit garbage collector calls"),
|
||
llvm::cl::ZeroOrMore);
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
static llvm::Module *M = nullptr;
|
||
|
||
static void LLVM_D_BuildRuntimeModule();
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
static void checkForImplicitGCCall(const Loc &loc, const char *name) {
|
||
if (nogc) {
|
||
static const std::string GCNAMES[] = {
|
||
"_aaDelX",
|
||
"_aaGetY",
|
||
"_aaKeys",
|
||
"_aaRehash",
|
||
"_aaValues",
|
||
"_d_allocmemory",
|
||
"_d_allocmemoryT",
|
||
"_d_array_cast_len",
|
||
"_d_array_slice_copy",
|
||
"_d_arrayappendT",
|
||
"_d_arrayappendcTX",
|
||
"_d_arrayappendcd",
|
||
"_d_arrayappendwd",
|
||
"_d_arraycatT",
|
||
"_d_arraycatnTX",
|
||
"_d_arraysetlengthT",
|
||
"_d_arraysetlengthiT",
|
||
"_d_assocarrayliteralTX",
|
||
"_d_callfinalizer",
|
||
"_d_delarray_t",
|
||
"_d_delclass",
|
||
"_d_delstruct",
|
||
"_d_delinterface",
|
||
"_d_delmemory",
|
||
"_d_newarrayT",
|
||
"_d_newarrayiT",
|
||
"_d_newarraymTX",
|
||
"_d_newarraymiTX",
|
||
"_d_newarrayU",
|
||
"_d_newclass",
|
||
"_d_newitemT",
|
||
"_d_newitemiT",
|
||
};
|
||
|
||
if (binary_search(&GCNAMES[0],
|
||
&GCNAMES[sizeof(GCNAMES) / sizeof(std::string)], name)) {
|
||
error(loc, "No implicit garbage collector calls allowed with -nogc "
|
||
"option enabled: %s",
|
||
name);
|
||
fatal();
|
||
}
|
||
}
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
bool LLVM_D_InitRuntime() {
|
||
Logger::println("*** Initializing D runtime declarations ***");
|
||
LOG_SCOPE;
|
||
|
||
if (!M) {
|
||
LLVM_D_BuildRuntimeModule();
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
void LLVM_D_FreeRuntime() {
|
||
if (M) {
|
||
Logger::println("*** Freeing D runtime declarations ***");
|
||
delete M;
|
||
M = nullptr;
|
||
}
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
llvm::Function *LLVM_D_GetRuntimeFunction(const Loc &loc, llvm::Module &target,
|
||
const char *name) {
|
||
checkForImplicitGCCall(loc, name);
|
||
|
||
if (!M) {
|
||
LLVM_D_InitRuntime();
|
||
}
|
||
|
||
LLFunction *fn = target.getFunction(name);
|
||
if (fn) {
|
||
return fn;
|
||
}
|
||
|
||
fn = M->getFunction(name);
|
||
assert(fn && "Runtime function not found.");
|
||
|
||
LLFunctionType *fnty = fn->getFunctionType();
|
||
LLFunction *resfn =
|
||
llvm::cast<llvm::Function>(target.getOrInsertFunction(name, fnty));
|
||
resfn->setAttributes(fn->getAttributes());
|
||
resfn->setCallingConv(fn->getCallingConv());
|
||
return resfn;
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
llvm::GlobalVariable *LLVM_D_GetRuntimeGlobal(Loc &loc, llvm::Module &target,
|
||
const char *name) {
|
||
LLGlobalVariable *gv = target.getNamedGlobal(name);
|
||
if (gv) {
|
||
return gv;
|
||
}
|
||
|
||
checkForImplicitGCCall(loc, name);
|
||
|
||
if (!M) {
|
||
LLVM_D_InitRuntime();
|
||
}
|
||
|
||
LLGlobalVariable *g = M->getNamedGlobal(name);
|
||
if (!g) {
|
||
error(loc, "Runtime global '%s' was not found", name);
|
||
fatal();
|
||
// return NULL;
|
||
}
|
||
|
||
LLPointerType *t = g->getType();
|
||
return getOrCreateGlobal(loc, target, t->getElementType(), g->isConstant(),
|
||
g->getLinkage(), nullptr, g->getName());
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
static LLType *rt_ptr(LLType *t) { return getPtrToType(t); }
|
||
|
||
static LLType *rt_array(LLType *elemty) {
|
||
LLType *types[] = {DtoSize_t(), rt_ptr(elemty)};
|
||
return LLStructType::get(gIR->context(), types, false);
|
||
}
|
||
|
||
static LLType *rt_dg1() {
|
||
LLType *types1[] = {rt_ptr(LLType::getInt8Ty(gIR->context())),
|
||
rt_ptr(LLType::getInt8Ty(gIR->context()))};
|
||
LLFunctionType *fty =
|
||
LLFunctionType::get(LLType::getInt32Ty(gIR->context()), types1, false);
|
||
|
||
LLType *types[] = {rt_ptr(LLType::getInt8Ty(gIR->context())), rt_ptr(fty)};
|
||
return LLStructType::get(gIR->context(), types, false);
|
||
}
|
||
|
||
static LLType *rt_dg2() {
|
||
LLType *Int8PtrTy = rt_ptr(LLType::getInt8Ty(gIR->context()));
|
||
LLType *types1[] = {Int8PtrTy, Int8PtrTy, Int8PtrTy};
|
||
LLFunctionType *fty =
|
||
LLFunctionType::get(LLType::getInt32Ty(gIR->context()), types1, false);
|
||
|
||
LLType *types[] = {rt_ptr(LLType::getInt8Ty(gIR->context())), rt_ptr(fty)};
|
||
return LLStructType::get(gIR->context(), types, false);
|
||
}
|
||
|
||
template <typename DECL> static void ensureDecl(DECL *decl, const char *msg) {
|
||
if (!decl || !decl->type) {
|
||
Logger::println("Missing class declaration: %s\n", msg);
|
||
error(Loc(), "Missing class declaration: %s", msg);
|
||
errorSupplemental(Loc(),
|
||
"Please check that object.di is included and valid");
|
||
fatal();
|
||
}
|
||
}
|
||
|
||
static void LLVM_D_BuildRuntimeModule() {
|
||
Logger::println("building runtime module");
|
||
M = new llvm::Module("ldc internal runtime", gIR->context());
|
||
|
||
LLType *voidTy = LLType::getVoidTy(gIR->context());
|
||
LLType *boolTy = LLType::getInt1Ty(gIR->context());
|
||
LLType *byteTy = LLType::getInt8Ty(gIR->context());
|
||
LLType *intTy = LLType::getInt32Ty(gIR->context());
|
||
LLType *longTy = LLType::getInt64Ty(gIR->context());
|
||
LLType *sizeTy = DtoSize_t();
|
||
|
||
LLType *voidPtrTy = rt_ptr(byteTy);
|
||
LLType *voidArrayTy = rt_array(byteTy);
|
||
LLType *voidArrayPtrTy = rt_ptr(voidArrayTy);
|
||
LLType *stringTy = DtoType(Type::tchar->arrayOf());
|
||
LLType *wstringTy = DtoType(Type::twchar->arrayOf());
|
||
LLType *dstringTy = DtoType(Type::tdchar->arrayOf());
|
||
|
||
// Ensure that the declarations exist before creating llvm types for them.
|
||
ensureDecl(ClassDeclaration::object, "Object");
|
||
ensureDecl(Type::typeinfoclass, "TypeInfo_Class");
|
||
ensureDecl(Type::dtypeinfo, "DTypeInfo");
|
||
ensureDecl(Type::typeinfoassociativearray, "TypeInfo_AssociativeArray");
|
||
ensureDecl(Module::moduleinfo, "ModuleInfo");
|
||
|
||
LLType *objectTy = DtoType(ClassDeclaration::object->type);
|
||
LLType *classInfoTy = DtoType(Type::typeinfoclass->type);
|
||
LLType *typeInfoTy = DtoType(Type::dtypeinfo->type);
|
||
LLType *aaTypeInfoTy = DtoType(Type::typeinfoassociativearray->type);
|
||
LLType *moduleInfoPtrTy = rt_ptr(DtoType(Module::moduleinfo->type));
|
||
LLType *aaTy = voidPtrTy;
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// Construct some attribute lists used below (possibly multiple times)
|
||
AttrSet NoAttrs, Attr_NoAlias(NoAttrs, 0, llvm::Attribute::NoAlias),
|
||
Attr_NoUnwind(NoAttrs, ~0U, llvm::Attribute::NoUnwind),
|
||
Attr_ReadOnly(NoAttrs, ~0U, llvm::Attribute::ReadOnly),
|
||
Attr_ReadOnly_NoUnwind(Attr_ReadOnly, ~0U, llvm::Attribute::NoUnwind),
|
||
Attr_ReadOnly_1_NoCapture(Attr_ReadOnly, 1, llvm::Attribute::NoCapture),
|
||
Attr_ReadOnly_1_3_NoCapture(Attr_ReadOnly_1_NoCapture, 3,
|
||
llvm::Attribute::NoCapture),
|
||
Attr_ReadOnly_NoUnwind_1_NoCapture(Attr_ReadOnly_1_NoCapture, ~0U,
|
||
llvm::Attribute::NoUnwind),
|
||
Attr_ReadNone(NoAttrs, ~0U, llvm::Attribute::ReadNone),
|
||
Attr_1_NoCapture(NoAttrs, 1, llvm::Attribute::NoCapture),
|
||
Attr_NoAlias_1_NoCapture(Attr_1_NoCapture, 0, llvm::Attribute::NoAlias),
|
||
Attr_1_2_NoCapture(Attr_1_NoCapture, 2, llvm::Attribute::NoCapture),
|
||
Attr_1_3_NoCapture(Attr_1_NoCapture, 3, llvm::Attribute::NoCapture),
|
||
Attr_1_4_NoCapture(Attr_1_NoCapture, 4, llvm::Attribute::NoCapture);
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// void _d_assert(string file, uint line)
|
||
// void _d_arraybounds(string file, uint line)
|
||
{
|
||
llvm::StringRef fname("_d_assert");
|
||
llvm::StringRef fname2("_d_arraybounds");
|
||
LLType *types[] = {stringTy, intTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
|
||
}
|
||
|
||
// void _d_assert_msg(string msg, string file, uint line)
|
||
{
|
||
llvm::StringRef fname("_d_assert_msg");
|
||
LLType *types[] = {stringTy, stringTy, intTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
// void _d_assertm(immutable(ModuleInfo)* m, uint line)
|
||
// void _d_array_bounds(immutable(ModuleInfo)* m, uint line)
|
||
{
|
||
llvm::StringRef fname("_d_assertm");
|
||
llvm::StringRef fname2("_d_array_bounds");
|
||
LLType *types[] = {moduleInfoPtrTy, intTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
|
||
}
|
||
|
||
// void _d_switch_error(immutable(ModuleInfo)* m, uint line)
|
||
{
|
||
llvm::StringRef fname("_d_switch_error");
|
||
LLType *types[] = {moduleInfoPtrTy, intTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// void* _d_allocmemory(size_t sz)
|
||
{
|
||
llvm::StringRef fname("_d_allocmemory");
|
||
LLType *types[] = {sizeTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidPtrTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_NoAlias);
|
||
}
|
||
|
||
// void* _d_allocmemoryT(TypeInfo ti)
|
||
{
|
||
llvm::StringRef fname("_d_allocmemoryT");
|
||
LLType *types[] = {typeInfoTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidPtrTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_NoAlias);
|
||
}
|
||
// void[] _d_newarrayT (const TypeInfo ti, size_t length)
|
||
// void[] _d_newarrayiT(const TypeInfo ti, size_t length)
|
||
// void[] _d_newarrayU (const TypeInfo ti, size_t length)
|
||
{
|
||
llvm::StringRef fname("_d_newarrayT");
|
||
llvm::StringRef fname2("_d_newarrayiT");
|
||
llvm::StringRef fname3("_d_newarrayU");
|
||
LLType *types[] = {typeInfoTy, sizeTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname3, M);
|
||
}
|
||
// void[] _d_newarraymTX (const TypeInfo ti, size_t[] dims)
|
||
// void[] _d_newarraymiTX(const TypeInfo ti, size_t[] dims)
|
||
{
|
||
llvm::StringRef fname("_d_newarraymTX");
|
||
llvm::StringRef fname2("_d_newarraymiTX");
|
||
LLType *types[] = {typeInfoTy, rt_array(sizeTy)};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
|
||
}
|
||
|
||
// void[] _d_arraysetlengthT (const TypeInfo ti, size_t newlength, void[]* p)
|
||
// void[] _d_arraysetlengthiT(const TypeInfo ti, size_t newlength, void[]* p)
|
||
{
|
||
llvm::StringRef fname("_d_arraysetlengthT");
|
||
llvm::StringRef fname2("_d_arraysetlengthiT");
|
||
LLType *types[] = {typeInfoTy, sizeTy, voidArrayPtrTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
|
||
}
|
||
|
||
// byte[] _d_arrayappendcTX(const TypeInfo ti, ref byte[] px, size_t n)
|
||
{
|
||
llvm::StringRef fname("_d_arrayappendcTX");
|
||
LLType *types[] = {typeInfoTy, voidArrayPtrTy, sizeTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
// void[] _d_arrayappendT(const TypeInfo ti, ref byte[] x, byte[] y)
|
||
{
|
||
llvm::StringRef fname("_d_arrayappendT");
|
||
LLType *types[] = {typeInfoTy, voidArrayPtrTy, voidArrayTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
// void[] _d_arrayappendcd(ref byte[] x, dchar c)
|
||
{
|
||
llvm::StringRef fname("_d_arrayappendcd");
|
||
LLType *types[] = {voidArrayPtrTy, intTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
// void[] _d_arrayappendwd(ref byte[] x, dchar c)
|
||
{
|
||
llvm::StringRef fname("_d_arrayappendwd");
|
||
LLType *types[] = {voidArrayPtrTy, intTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
// byte[] _d_arraycatT(const TypeInfo ti, byte[] x, byte[] y)
|
||
{
|
||
llvm::StringRef fname("_d_arraycatT");
|
||
LLType *types[] = {typeInfoTy, voidArrayTy, voidArrayTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
// void[] _d_arraycatnTX(const TypeInfo ti, byte[][] arrs)
|
||
{
|
||
llvm::StringRef fname("_d_arraycatnTX");
|
||
LLType *types[] = {typeInfoTy, rt_array(voidArrayTy)};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
// Object _d_newclass(const ClassInfo ci)
|
||
{
|
||
llvm::StringRef fname("_d_newclass");
|
||
LLType *types[] = {classInfoTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(objectTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_NoAlias);
|
||
}
|
||
|
||
// void* _d_newitemT (TypeInfo ti)
|
||
// void* _d_newitemiT(TypeInfo ti)
|
||
{
|
||
llvm::StringRef fname("_d_newitemT");
|
||
llvm::StringRef fname2("_d_newitemiT");
|
||
LLType *types[] = {typeInfoTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidPtrTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_NoAlias);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M)
|
||
->setAttributes(Attr_NoAlias);
|
||
}
|
||
|
||
// void _d_delarray_t(void[]* p, const TypeInfo_Struct ti)
|
||
{
|
||
llvm::StringRef fname("_d_delarray_t");
|
||
LLType *types[] = {voidArrayPtrTy, DtoType(Type::typeinfostruct->type)};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
// void _d_delmemory(void** p)
|
||
// void _d_delinterface(void** p)
|
||
{
|
||
llvm::StringRef fname("_d_delmemory");
|
||
llvm::StringRef fname2("_d_delinterface");
|
||
LLType *types[] = {rt_ptr(voidPtrTy)};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
|
||
}
|
||
|
||
// void _d_callfinalizer(void* p)
|
||
{
|
||
llvm::StringRef fname("_d_callfinalizer");
|
||
LLType *types[] = {voidPtrTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
// D2: void _d_delclass(Object* p)
|
||
{
|
||
llvm::StringRef fname("_d_delclass");
|
||
LLType *types[] = {rt_ptr(objectTy)};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
// void _d_delstruct(void** p, TypeInfo_Struct inf)
|
||
{
|
||
llvm::StringRef fname("_d_delstruct");
|
||
LLType *types[] = {rt_ptr(voidPtrTy), DtoType(Type::typeinfostruct->type)};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// array slice copy when assertions are on!
|
||
// void _d_array_slice_copy(void* dst, size_t dstlen, void* src, size_t
|
||
// srclen)
|
||
{
|
||
llvm::StringRef fname("_d_array_slice_copy");
|
||
LLType *types[] = {voidPtrTy, sizeTy, voidPtrTy, sizeTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_1_3_NoCapture);
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
// int _aApplycd1(in char[] aa, dg_t dg)
|
||
// int _aApplyRcd1(in char[] aa, dg_t dg)
|
||
#define STR_APPLY1(TY, a, b) \
|
||
{ \
|
||
const std::string prefix = "_aApply"; \
|
||
std::string fname1 = prefix + (a) + '1', fname2 = prefix + (b) + '1', \
|
||
fname3 = prefix + 'R' + (a) + '1', \
|
||
fname4 = prefix + 'R' + (b) + '1'; \
|
||
LLType *types[] = {TY, rt_dg1()}; \
|
||
LLFunctionType *fty = llvm::FunctionType::get(intTy, types, false); \
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname1, \
|
||
M); \
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, \
|
||
M); \
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname3, \
|
||
M); \
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname4, \
|
||
M); \
|
||
}
|
||
STR_APPLY1(stringTy, "cw", "cd")
|
||
STR_APPLY1(wstringTy, "wc", "wd")
|
||
STR_APPLY1(dstringTy, "dc", "dw")
|
||
#undef STR_APPLY1
|
||
|
||
// int _aApplycd2(in char[] aa, dg2_t dg)
|
||
// int _aApplyRcd2(in char[] aa, dg2_t dg)
|
||
#define STR_APPLY2(TY, a, b) \
|
||
{ \
|
||
const std::string prefix = "_aApply"; \
|
||
std::string fname1 = prefix + (a) + '2', fname2 = prefix + (b) + '2', \
|
||
fname3 = prefix + 'R' + (a) + '2', \
|
||
fname4 = prefix + 'R' + (b) + '2'; \
|
||
LLType *types[] = {TY, rt_dg2()}; \
|
||
LLFunctionType *fty = llvm::FunctionType::get(intTy, types, false); \
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname1, \
|
||
M); \
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, \
|
||
M); \
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname3, \
|
||
M); \
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname4, \
|
||
M); \
|
||
}
|
||
STR_APPLY2(stringTy, "cw", "cd")
|
||
STR_APPLY2(wstringTy, "wc", "wd")
|
||
STR_APPLY2(dstringTy, "dc", "dw")
|
||
#undef STR_APPLY2
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// fixes the length for dynamic array casts
|
||
// size_t _d_array_cast_len(size_t len, size_t elemsz, size_t newelemsz)
|
||
{
|
||
llvm::StringRef fname("_d_array_cast_len");
|
||
LLType *types[] = {sizeTy, sizeTy, sizeTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(sizeTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_ReadNone);
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// void[] _d_arrayassign_l(TypeInfo ti, void[] src, void[] dst, void* ptmp)
|
||
// void[] _d_arrayassign_r(TypeInfo ti, void[] src, void[] dst, void* ptmp)
|
||
{
|
||
llvm::StringRef fname("_d_arrayassign_l");
|
||
llvm::StringRef fname2("_d_arrayassign_r");
|
||
LLType *types[] = {typeInfoTy, voidArrayTy, voidArrayTy, voidPtrTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
|
||
}
|
||
|
||
// void[] _d_arrayctor(TypeInfo ti, void[] from, void[] to)
|
||
{
|
||
llvm::StringRef fname("_d_arrayctor");
|
||
LLType *types[] = {typeInfoTy, voidArrayTy, voidArrayTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
// void* _d_arraysetassign(void* p, void* value, int count, TypeInfo ti)
|
||
// void* _d_arraysetctor(void* p, void* value, int count, TypeInfo ti)
|
||
{
|
||
llvm::StringRef fname("_d_arraysetassign");
|
||
llvm::StringRef fname2("_d_arraysetctor");
|
||
LLType *types[] = {voidPtrTy, voidPtrTy, intTy, typeInfoTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidPtrTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_NoAlias);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M)
|
||
->setAttributes(Attr_NoAlias);
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// cast interface
|
||
// void* _d_interface_cast(void* p, ClassInfo c)
|
||
{
|
||
llvm::StringRef fname("_d_interface_cast");
|
||
LLType *types[] = {voidPtrTy, classInfoTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidPtrTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_ReadOnly_NoUnwind);
|
||
}
|
||
|
||
// dynamic cast
|
||
// void* _d_dynamic_cast(Object o, ClassInfo c)
|
||
{
|
||
llvm::StringRef fname("_d_dynamic_cast");
|
||
LLType *types[] = {objectTy, classInfoTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidPtrTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_ReadOnly_NoUnwind);
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// char[] _adReverseChar(char[] a)
|
||
// char[] _adSortChar(char[] a)
|
||
{
|
||
llvm::StringRef fname("_adReverseChar");
|
||
llvm::StringRef fname2("_adSortChar");
|
||
LLType *types[] = {stringTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(stringTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
|
||
}
|
||
|
||
// wchar[] _adReverseWchar(wchar[] a)
|
||
// wchar[] _adSortWchar(wchar[] a)
|
||
{
|
||
llvm::StringRef fname("_adReverseWchar");
|
||
llvm::StringRef fname2("_adSortWchar");
|
||
LLType *types[] = {wstringTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(wstringTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
|
||
}
|
||
|
||
// void[] _adReverse(void[] a, size_t szelem)
|
||
{
|
||
llvm::StringRef fname("_adReverse");
|
||
LLType *types[] = {voidArrayTy, sizeTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_NoUnwind);
|
||
}
|
||
|
||
// int _adEq(void[] a1, void[] a2, TypeInfo ti)
|
||
// int _adCmp(void[] a1, void[] a2, TypeInfo ti)
|
||
{
|
||
llvm::StringRef fname("_adEq2");
|
||
llvm::StringRef fname2("_adCmp2");
|
||
LLType *types[] = {voidArrayTy, voidArrayTy, typeInfoTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(intTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_ReadOnly);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M)
|
||
->setAttributes(Attr_ReadOnly);
|
||
}
|
||
|
||
// int _adCmpChar(void[] a1, void[] a2)
|
||
{
|
||
llvm::StringRef fname("_adCmpChar");
|
||
LLType *types[] = {voidArrayTy, voidArrayTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(intTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_ReadOnly_NoUnwind);
|
||
}
|
||
|
||
// void[] _adSort(void[] a, TypeInfo ti)
|
||
{
|
||
llvm::StringRef fname("_adSort");
|
||
LLType *types[] = {voidArrayTy, typeInfoTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// size_t _aaLen(in AA aa)
|
||
{
|
||
llvm::StringRef fname("_aaLen");
|
||
LLType *types[] = {aaTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(sizeTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_ReadOnly_NoUnwind_1_NoCapture);
|
||
}
|
||
|
||
// void* _aaGetY(AA* aa, const TypeInfo aati, in size_t valuesize, in void*
|
||
// pkey)
|
||
{
|
||
llvm::StringRef fname("_aaGetY");
|
||
LLType *types[] = {rt_ptr(aaTy), aaTypeInfoTy, sizeTy, voidPtrTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidPtrTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_1_4_NoCapture);
|
||
}
|
||
|
||
// inout(void)* _aaInX(inout AA aa, in TypeInfo keyti, in void* pkey)
|
||
{
|
||
llvm::StringRef fname("_aaInX");
|
||
LLType *types[] = {aaTy, typeInfoTy, voidPtrTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidPtrTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_ReadOnly_1_3_NoCapture);
|
||
}
|
||
|
||
// bool _aaDelX(AA aa, in TypeInfo keyti, in void* pkey)
|
||
{
|
||
llvm::StringRef fname("_aaDelX");
|
||
LLType *types[] = {aaTy, typeInfoTy, voidPtrTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(boolTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_1_3_NoCapture);
|
||
}
|
||
|
||
// inout(void[]) _aaValues(inout AA aa, in size_t keysize, in size_t
|
||
// valuesize, const TypeInfo tiValueArray)
|
||
{
|
||
llvm::StringRef fname("_aaValues");
|
||
LLType *types[] = {aaTy, sizeTy, sizeTy, typeInfoTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_NoAlias_1_NoCapture);
|
||
}
|
||
|
||
// void* _aaRehash(AA* paa, in TypeInfo keyti)
|
||
{
|
||
llvm::StringRef fname("_aaRehash");
|
||
LLType *types[] = {rt_ptr(aaTy), typeInfoTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidPtrTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
// inout(void[]) _aaKeys(inout AA aa, in size_t keysize, const TypeInfo
|
||
// tiKeyArray)
|
||
{
|
||
llvm::StringRef fname("_aaKeys");
|
||
LLType *types[] = {aaTy, sizeTy, typeInfoTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidArrayTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_NoAlias_1_NoCapture);
|
||
}
|
||
|
||
// int _aaApply(AA aa, in size_t keysize, dg_t dg)
|
||
{
|
||
llvm::StringRef fname("_aaApply");
|
||
LLType *types[] = {aaTy, sizeTy, rt_dg1()};
|
||
LLFunctionType *fty = llvm::FunctionType::get(intTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_1_NoCapture);
|
||
}
|
||
|
||
// int _aaApply2(AA aa, in size_t keysize, dg2_t dg)
|
||
{
|
||
llvm::StringRef fname("_aaApply2");
|
||
LLType *types[] = {aaTy, sizeTy, rt_dg2()};
|
||
LLFunctionType *fty = llvm::FunctionType::get(intTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_1_NoCapture);
|
||
}
|
||
|
||
// int _aaEqual(in TypeInfo tiRaw, in AA e1, in AA e2)
|
||
{
|
||
llvm::StringRef fname("_aaEqual");
|
||
LLType *types[] = {typeInfoTy, aaTy, aaTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(intTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_1_2_NoCapture);
|
||
}
|
||
// AA _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, void[] keys,
|
||
// void[] values)
|
||
{
|
||
llvm::StringRef fname("_d_assocarrayliteralTX");
|
||
LLType *types[] = {aaTypeInfoTy, voidArrayTy, voidArrayTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(aaTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// void _moduleCtor()
|
||
// void _moduleDtor()
|
||
{
|
||
llvm::StringRef fname("_moduleCtor");
|
||
llvm::StringRef fname2("_moduleDtor");
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidTy, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// void _d_throw_exception(Object e)
|
||
{
|
||
llvm::StringRef fname("_d_throw_exception");
|
||
LLType *types[] = {objectTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// int _d_switch_string(char[][] table, char[] ca)
|
||
{
|
||
llvm::StringRef fname("_d_switch_string");
|
||
LLType *types[] = {rt_array(stringTy), stringTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(intTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_ReadOnly);
|
||
}
|
||
|
||
// int _d_switch_ustring(wchar[][] table, wchar[] ca)
|
||
{
|
||
llvm::StringRef fname("_d_switch_ustring");
|
||
LLType *types[] = {rt_array(wstringTy), wstringTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(intTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_ReadOnly);
|
||
}
|
||
|
||
// int _d_switch_dstring(dchar[][] table, dchar[] ca)
|
||
{
|
||
llvm::StringRef fname("_d_switch_dstring");
|
||
LLType *types[] = {rt_array(dstringTy), dstringTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(intTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_ReadOnly);
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// int _d_eh_personality(...)
|
||
{
|
||
LLFunctionType *fty = nullptr;
|
||
if (global.params.targetTriple.isWindowsMSVCEnvironment()) {
|
||
// (ptr ExceptionRecord, ptr EstablisherFrame, ptr ContextRecord,
|
||
// ptr DispatcherContext)
|
||
LLType *types[] = {voidPtrTy, voidPtrTy, voidPtrTy, voidPtrTy};
|
||
fty = llvm::FunctionType::get(intTy, types, false);
|
||
} else if (global.params.targetTriple.getArch() == llvm::Triple::arm) {
|
||
// (int state, ptr ucb, ptr context)
|
||
LLType *types[] = {intTy, voidPtrTy, voidPtrTy};
|
||
fty = llvm::FunctionType::get(intTy, types, false);
|
||
} else {
|
||
// (int ver, int actions, ulong eh_class, ptr eh_info, ptr context)
|
||
LLType *types[] = {intTy, intTy, longTy, voidPtrTy, voidPtrTy};
|
||
fty = llvm::FunctionType::get(intTy, types, false);
|
||
}
|
||
|
||
llvm::StringRef fname("_d_eh_personality");
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
// void _d_eh_resume_unwind(ptr exc_struct)
|
||
{
|
||
llvm::StringRef fname("_d_eh_resume_unwind");
|
||
LLType *types[] = {voidPtrTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
// Object _d_eh_enter_catch(ptr exc_struct)
|
||
{
|
||
llvm::StringRef fname("_d_eh_enter_catch");
|
||
LLType *types[] = {voidPtrTy};
|
||
LLFunctionType *fty = llvm::FunctionType::get(voidPtrTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
|
||
->setAttributes(Attr_NoUnwind);
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// void invariant._d_invariant(Object o)
|
||
{
|
||
// KLUDGE: _d_invariant is actually extern(D) in the upstream runtime,
|
||
// possibly
|
||
// for more efficient parameter passing on x86. This complicates our code
|
||
// here
|
||
// quite a bit, though.
|
||
auto params = new Parameters();
|
||
params->push(
|
||
new Parameter(STCin, ClassDeclaration::object->type, nullptr, nullptr));
|
||
auto dty = new TypeFunction(params, Type::tvoid, 0, LINKd);
|
||
llvm::Function *fn = llvm::Function::Create(
|
||
llvm::cast<llvm::FunctionType>(DtoType(dty)),
|
||
llvm::GlobalValue::ExternalLinkage,
|
||
gABI->mangleForLLVM("_D9invariant12_d_invariantFC6ObjectZv", LINKd), M);
|
||
assert(dty->ctype);
|
||
IrFuncTy &irFty = dty->ctype->getIrFuncTy();
|
||
gABI->rewriteFunctionType(dty, irFty);
|
||
fn->addAttributes(
|
||
1, llvm::AttributeSet::get(gIR->context(), 1, irFty.args[0]->attrs));
|
||
fn->setCallingConv(gABI->callingConv(fn->getFunctionType(), LINKd));
|
||
}
|
||
|
||
// void _d_dso_registry(CompilerDSOData* data)
|
||
if (global.params.isLinux) {
|
||
llvm::StringRef fname("_d_dso_registry");
|
||
|
||
llvm::StructType *dsoDataTy =
|
||
llvm::StructType::get(sizeTy, // version
|
||
rt_ptr(voidPtrTy), // slot
|
||
rt_ptr(moduleInfoPtrTy), // _minfo_beg
|
||
rt_ptr(moduleInfoPtrTy), // _minfo_end
|
||
NULL);
|
||
|
||
llvm::Type *types[] = {rt_ptr(dsoDataTy)};
|
||
llvm::FunctionType *fty = llvm::FunctionType::get(voidTy, types, false);
|
||
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
|
||
}
|
||
|
||
// extern (C) void _d_cover_register2(string filename, size_t[] valid, uint[]
|
||
// data, ubyte minPercent)
|
||
// as defined in druntime/rt/cover.d.
|
||
if (global.params.cov) {
|
||
llvm::StringRef fname("_d_cover_register2");
|
||
|
||
LLType *params[] = {stringTy, rt_array(sizeTy), rt_array(intTy), byteTy};
|
||
|
||
LLFunctionType *fty = LLFunctionType::get(voidTy, params, false);
|
||
llvm::Function *fn =
|
||
LLFunction::Create(fty, LLGlobalValue::ExternalLinkage, fname, M);
|
||
fn->setCallingConv(gABI->callingConv(fn->getFunctionType(), LINKc));
|
||
}
|
||
}
|