mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-04-28 14:10:42 +03:00
302 lines
8.9 KiB
C++
302 lines
8.9 KiB
C++
//===-- irtype.cpp --------------------------------------------------------===//
|
||
//
|
||
// LDC – the LLVM D compiler
|
||
//
|
||
// This file is distributed under the BSD-style LDC license. See the LICENSE
|
||
// file for details.
|
||
//
|
||
//===----------------------------------------------------------------------===//
|
||
|
||
#if LDC_LLVM_VER >= 303
|
||
#include "llvm/IR/DerivedTypes.h"
|
||
#include "llvm/IR/LLVMContext.h"
|
||
#else
|
||
#include "llvm/DerivedTypes.h"
|
||
#include "llvm/LLVMContext.h"
|
||
#endif
|
||
#include "mars.h"
|
||
#include "mtype.h"
|
||
#include "gen/irstate.h"
|
||
#include "gen/logger.h"
|
||
#include "gen/tollvm.h"
|
||
#include "ir/irtype.h"
|
||
|
||
// This code uses llvm::getGlobalContext() as these functions are invoked before gIR is set.
|
||
// ... thus it segfaults on gIR==NULL
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
IrType::IrType(Type* dt, LLType* lt)
|
||
: dtype(dt),
|
||
type(lt)
|
||
{
|
||
assert(dt && "null D Type");
|
||
assert(lt && "null LLVM Type");
|
||
assert(!dt->irtype && "already has IrType");
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
IrTypeBasic::IrTypeBasic(Type * dt)
|
||
: IrType(dt, basic2llvm(dt))
|
||
{
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
IrTypeBasic* IrTypeBasic::get(Type* dt)
|
||
{
|
||
IrTypeBasic* t = new IrTypeBasic(dt);
|
||
dt->irtype = t;
|
||
return t;
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
LLType* IrTypeBasic::getComplexType(llvm::LLVMContext& ctx, LLType* type)
|
||
{
|
||
llvm::Type *types[] = { type, type };
|
||
return llvm::StructType::get(ctx, types, false);
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
llvm::Type * IrTypeBasic::basic2llvm(Type* t)
|
||
{
|
||
LLType* t2;
|
||
|
||
llvm::LLVMContext& ctx = llvm::getGlobalContext();
|
||
|
||
switch(t->ty)
|
||
{
|
||
case Tvoid:
|
||
return llvm::Type::getVoidTy(ctx);
|
||
|
||
case Tint8:
|
||
case Tuns8:
|
||
case Tchar:
|
||
return llvm::Type::getInt8Ty(ctx);
|
||
|
||
case Tint16:
|
||
case Tuns16:
|
||
case Twchar:
|
||
return llvm::Type::getInt16Ty(ctx);
|
||
|
||
case Tint32:
|
||
case Tuns32:
|
||
case Tdchar:
|
||
return llvm::Type::getInt32Ty(ctx);
|
||
|
||
case Tint64:
|
||
case Tuns64:
|
||
return llvm::Type::getInt64Ty(ctx);
|
||
|
||
/*
|
||
case Tint128:
|
||
case Tuns128:
|
||
return llvm::IntegerType::get(llvm::getGlobalContext(), 128);
|
||
*/
|
||
|
||
case Tfloat32:
|
||
case Timaginary32:
|
||
return llvm::Type::getFloatTy(ctx);
|
||
|
||
case Tfloat64:
|
||
case Timaginary64:
|
||
return llvm::Type::getDoubleTy(ctx);
|
||
|
||
case Tfloat80:
|
||
case Timaginary80:
|
||
// only x86 has 80bit float
|
||
if (global.params.cpu == ARCHx86 || global.params.cpu == ARCHx86_64)
|
||
return llvm::Type::getX86_FP80Ty(ctx);
|
||
// PPC has a special 128bit float
|
||
else if (global.params.cpu == ARCHppc || global.params.cpu == ARCHppc_64)
|
||
return llvm::Type::getPPC_FP128Ty(ctx);
|
||
// other platforms use 64bit reals
|
||
else
|
||
return llvm::Type::getDoubleTy(ctx);
|
||
|
||
case Tcomplex32: {
|
||
t2 = llvm::Type::getFloatTy(ctx);
|
||
return getComplexType(ctx, t2);
|
||
}
|
||
|
||
case Tcomplex64:
|
||
t2 = llvm::Type::getDoubleTy(ctx);
|
||
return getComplexType(ctx, t2);
|
||
|
||
case Tcomplex80:
|
||
t2 = (global.params.cpu == ARCHx86 || global.params.cpu == ARCHx86_64)
|
||
? llvm::Type::getX86_FP80Ty(ctx)
|
||
: (global.params.cpu == ARCHppc || global.params.cpu == ARCHppc_64)
|
||
? llvm::Type::getPPC_FP128Ty(ctx)
|
||
: llvm::Type::getDoubleTy(ctx);
|
||
return getComplexType(ctx, t2);
|
||
|
||
case Tbool:
|
||
return llvm::Type::getInt1Ty(ctx);
|
||
default:
|
||
llvm_unreachable("Unknown basic type.");
|
||
}
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
IrTypePointer::IrTypePointer(Type* dt, LLType* lt)
|
||
: IrType(dt, lt)
|
||
{
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
IrTypePointer* IrTypePointer::get(Type* dt)
|
||
{
|
||
assert(!dt->irtype);
|
||
assert((dt->ty == Tpointer || dt->ty == Tnull) && "not pointer/null type");
|
||
|
||
LLType* elemType;
|
||
if (dt->ty == Tnull)
|
||
{
|
||
elemType = llvm::Type::getInt8Ty(llvm::getGlobalContext());
|
||
}
|
||
else
|
||
{
|
||
if (dt->nextOf()->ty == Tfunction)
|
||
{
|
||
TypeFunction* tf = static_cast<TypeFunction*>(dt->nextOf());
|
||
if (tf->funcdecl)
|
||
{
|
||
if (FuncLiteralDeclaration* fld =
|
||
tf->funcdecl->isFuncLiteralDeclaration())
|
||
{
|
||
if (fld->tok == TOKreserved)
|
||
{
|
||
// This is the type of a lambda that was inferred to be
|
||
// a function literal instead of a delegate, so set tok
|
||
// here in order to get correct types/mangling. Horrible
|
||
// hack, but DMD does the same thing in FuncExp::toElem
|
||
// and other random places.
|
||
fld->tok = TOKfunction;
|
||
fld->vthis = NULL;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
elemType = DtoTypeNotVoid(dt->nextOf());
|
||
|
||
// DtoTypeNotVoid could have already created the same type, e.g. for
|
||
// dt == Node* in struct Node { Node* n; }.
|
||
if (dt->irtype)
|
||
return dt->irtype->isPointer();
|
||
}
|
||
|
||
IrTypePointer* t = new IrTypePointer(dt, llvm::PointerType::get(elemType, 0));
|
||
dt->irtype = t;
|
||
return t;
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
IrTypeSArray::IrTypeSArray(Type * dt)
|
||
: IrType(dt, sarray2llvm(dt))
|
||
{
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
IrTypeSArray* IrTypeSArray::get(Type* dt)
|
||
{
|
||
IrTypeSArray* t = new IrTypeSArray(dt);
|
||
dt->irtype = t;
|
||
return t;
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
llvm::Type * IrTypeSArray::sarray2llvm(Type * t)
|
||
{
|
||
assert(t->ty == Tsarray && "not static array type");
|
||
TypeSArray* tsa = static_cast<TypeSArray*>(t);
|
||
uint64_t dim = static_cast<uint64_t>(tsa->dim->toUInteger());
|
||
LLType* elemType = DtoType(t->nextOf());
|
||
if (elemType == llvm::Type::getVoidTy(llvm::getGlobalContext()))
|
||
elemType = llvm::Type::getInt8Ty(llvm::getGlobalContext());
|
||
return llvm::ArrayType::get(elemType, dim);
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
IrTypeArray::IrTypeArray(Type* dt, LLType* lt)
|
||
: IrType(dt, lt)
|
||
{
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
IrTypeArray* IrTypeArray::get(Type* dt)
|
||
{
|
||
assert(!dt->irtype);
|
||
assert(dt->ty == Tarray && "not dynamic array type");
|
||
|
||
LLType* elemType = DtoTypeNotVoid(dt->nextOf());
|
||
|
||
// Could have already built the type as part of a struct forward reference,
|
||
// just as for pointers.
|
||
if (!dt->irtype)
|
||
{
|
||
llvm::Type *types[] = { DtoSize_t(), llvm::PointerType::get(elemType, 0) };
|
||
LLType* at = llvm::StructType::get(llvm::getGlobalContext(), types, false);
|
||
dt->irtype = new IrTypeArray(dt, at);
|
||
}
|
||
|
||
return dt->irtype->isArray();
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
#if DMDV2
|
||
|
||
IrTypeVector::IrTypeVector(Type* dt)
|
||
: IrType(dt, vector2llvm(dt))
|
||
{
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
IrTypeVector* IrTypeVector::get(Type* dt)
|
||
{
|
||
IrTypeVector* t = new IrTypeVector(dt);
|
||
dt->irtype = t;
|
||
return t;
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
llvm::Type* IrTypeVector::vector2llvm(Type* dt)
|
||
{
|
||
assert(dt->ty == Tvector && "not vector type");
|
||
TypeVector* tv = static_cast<TypeVector*>(dt);
|
||
assert(tv->basetype->ty == Tsarray);
|
||
TypeSArray* tsa = static_cast<TypeSArray*>(tv->basetype);
|
||
uint64_t dim = static_cast<uint64_t>(tsa->dim->toUInteger());
|
||
LLType* elemType = DtoType(tsa->next);
|
||
if (elemType == llvm::Type::getVoidTy(llvm::getGlobalContext()))
|
||
elemType = llvm::Type::getInt8Ty(llvm::getGlobalContext());
|
||
return llvm::VectorType::get(elemType, dim);
|
||
}
|
||
|
||
#endif
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|