mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-05-03 00:41:29 +02:00
Fixed identity expression for dynamic arrays. Revamped the system to keep track of lvalues and rvalues and their relations. Typedef declaration now generate the custom typeinfo. Other bugfixes.
832 lines
23 KiB
C
832 lines
23 KiB
C
|
|
|
|
// Copyright (c) 1999-2004 by Digital Mars
|
|
// All Rights Reserved
|
|
// written by Walter Bright
|
|
// www.digitalmars.com
|
|
// License for redistribution is by either the Artistic License
|
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
|
// See the included readme.txt for details.
|
|
|
|
#include <cstdio>
|
|
#include <cassert>
|
|
|
|
#include "gen/llvm.h"
|
|
|
|
#include "mars.h"
|
|
#include "module.h"
|
|
#include "mtype.h"
|
|
#include "scope.h"
|
|
#include "init.h"
|
|
#include "expression.h"
|
|
#include "attrib.h"
|
|
#include "declaration.h"
|
|
#include "template.h"
|
|
#include "id.h"
|
|
#include "enum.h"
|
|
#include "import.h"
|
|
#include "aggregate.h"
|
|
|
|
#include "gen/irstate.h"
|
|
#include "gen/logger.h"
|
|
#include "gen/runtime.h"
|
|
#include "gen/tollvm.h"
|
|
#include "gen/arrays.h"
|
|
|
|
/*******************************************
|
|
* Get a canonicalized form of the TypeInfo for use with the internal
|
|
* runtime library routines. Canonicalized in that static arrays are
|
|
* represented as dynamic arrays, enums are represented by their
|
|
* underlying type, etc. This reduces the number of TypeInfo's needed,
|
|
* so we can use the custom internal ones more.
|
|
*/
|
|
|
|
Expression *Type::getInternalTypeInfo(Scope *sc)
|
|
{ TypeInfoDeclaration *tid;
|
|
Expression *e;
|
|
Type *t;
|
|
static TypeInfoDeclaration *internalTI[TMAX];
|
|
|
|
//printf("Type::getInternalTypeInfo() %s\n", toChars());
|
|
t = toBasetype();
|
|
switch (t->ty)
|
|
{
|
|
case Tsarray:
|
|
t = t->next->arrayOf(); // convert to corresponding dynamic array type
|
|
break;
|
|
|
|
case Tclass:
|
|
if (((TypeClass *)t)->sym->isInterfaceDeclaration())
|
|
break;
|
|
goto Linternal;
|
|
|
|
case Tarray:
|
|
if (t->next->ty != Tclass)
|
|
break;
|
|
goto Linternal;
|
|
|
|
case Tfunction:
|
|
case Tdelegate:
|
|
case Tpointer:
|
|
Linternal:
|
|
tid = internalTI[t->ty];
|
|
if (!tid)
|
|
{ tid = new TypeInfoDeclaration(t, 1);
|
|
internalTI[t->ty] = tid;
|
|
}
|
|
e = new VarExp(0, tid);
|
|
//e = e->addressOf(sc);
|
|
e->type = tid->type; // do this so we don't get redundant dereference
|
|
return e;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
//printf("\tcalling getTypeInfo() %s\n", t->toChars());
|
|
return t->getTypeInfo(sc);
|
|
}
|
|
|
|
|
|
/****************************************************
|
|
* Get the exact TypeInfo.
|
|
*/
|
|
|
|
Expression *Type::getTypeInfo(Scope *sc)
|
|
{
|
|
Expression *e;
|
|
Type *t;
|
|
|
|
//printf("Type::getTypeInfo() %p, %s\n", this, toChars());
|
|
t = merge(); // do this since not all Type's are merge'd
|
|
if (!t->vtinfo)
|
|
{ t->vtinfo = t->getTypeInfoDeclaration();
|
|
assert(t->vtinfo);
|
|
|
|
/* If this has a custom implementation in std/typeinfo, then
|
|
* do not generate a COMDAT for it.
|
|
*/
|
|
if (!t->builtinTypeInfo())
|
|
{ // Generate COMDAT
|
|
if (sc) // if in semantic() pass
|
|
{ // Find module that will go all the way to an object file
|
|
Module *m = sc->module->importedFrom;
|
|
m->members->push(t->vtinfo);
|
|
}
|
|
else // if in obj generation pass
|
|
{
|
|
t->vtinfo->toObjFile();
|
|
}
|
|
}
|
|
}
|
|
e = new VarExp(0, t->vtinfo);
|
|
//e = e->addressOf(sc);
|
|
e->type = t->vtinfo->type; // do this so we don't get redundant dereference
|
|
return e;
|
|
}
|
|
|
|
enum RET TypeFunction::retStyle()
|
|
{
|
|
return RETstack;
|
|
}
|
|
|
|
TypeInfoDeclaration *Type::getTypeInfoDeclaration()
|
|
{
|
|
//printf("Type::getTypeInfoDeclaration() %s\n", toChars());
|
|
return new TypeInfoDeclaration(this, 0);
|
|
}
|
|
|
|
TypeInfoDeclaration *TypeTypedef::getTypeInfoDeclaration()
|
|
{
|
|
return new TypeInfoTypedefDeclaration(this);
|
|
}
|
|
|
|
TypeInfoDeclaration *TypePointer::getTypeInfoDeclaration()
|
|
{
|
|
return new TypeInfoPointerDeclaration(this);
|
|
}
|
|
|
|
TypeInfoDeclaration *TypeDArray::getTypeInfoDeclaration()
|
|
{
|
|
return new TypeInfoArrayDeclaration(this);
|
|
}
|
|
|
|
TypeInfoDeclaration *TypeSArray::getTypeInfoDeclaration()
|
|
{
|
|
return new TypeInfoStaticArrayDeclaration(this);
|
|
}
|
|
|
|
TypeInfoDeclaration *TypeAArray::getTypeInfoDeclaration()
|
|
{
|
|
return new TypeInfoAssociativeArrayDeclaration(this);
|
|
}
|
|
|
|
TypeInfoDeclaration *TypeStruct::getTypeInfoDeclaration()
|
|
{
|
|
return new TypeInfoStructDeclaration(this);
|
|
}
|
|
|
|
TypeInfoDeclaration *TypeClass::getTypeInfoDeclaration()
|
|
{
|
|
if (sym->isInterfaceDeclaration())
|
|
return new TypeInfoInterfaceDeclaration(this);
|
|
else
|
|
return new TypeInfoClassDeclaration(this);
|
|
}
|
|
|
|
TypeInfoDeclaration *TypeEnum::getTypeInfoDeclaration()
|
|
{
|
|
return new TypeInfoEnumDeclaration(this);
|
|
}
|
|
|
|
TypeInfoDeclaration *TypeFunction::getTypeInfoDeclaration()
|
|
{
|
|
return new TypeInfoFunctionDeclaration(this);
|
|
}
|
|
|
|
TypeInfoDeclaration *TypeDelegate::getTypeInfoDeclaration()
|
|
{
|
|
return new TypeInfoDelegateDeclaration(this);
|
|
}
|
|
|
|
TypeInfoDeclaration *TypeTuple::getTypeInfoDeclaration()
|
|
{
|
|
return new TypeInfoTupleDeclaration(this);
|
|
}
|
|
|
|
|
|
/* ========================================================================= */
|
|
|
|
/* These decide if there's an instance for them already in std.typeinfo,
|
|
* because then the compiler doesn't need to build one.
|
|
*/
|
|
|
|
int Type::builtinTypeInfo()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int TypeBasic::builtinTypeInfo()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
int TypeDArray::builtinTypeInfo()
|
|
{
|
|
return next->isTypeBasic() != NULL;
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
|
|
/***************************************
|
|
* Create a static array of TypeInfo references
|
|
* corresponding to an array of Expression's.
|
|
* Used to supply hidden _arguments[] value for variadic D functions.
|
|
*/
|
|
|
|
Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim)
|
|
{
|
|
assert(0);
|
|
return 0;
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// MAGIC PLACE
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
void TypeInfoDeclaration::toObjFile()
|
|
{
|
|
Logger::println("TypeInfoDeclaration::toObjFile()");
|
|
LOG_SCOPE;
|
|
Logger::println("type = '%s'", tinfo->toChars());
|
|
|
|
if (llvmTouched) return;
|
|
else llvmTouched = true;
|
|
|
|
Logger::println("typeinfo mangle: %s", mangle());
|
|
|
|
if (tinfo->builtinTypeInfo()) {
|
|
// this is a declaration of a builtin __initZ var
|
|
llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangle());
|
|
assert(llvmValue);
|
|
Logger::cout() << "Got typeinfo var:" << '\n' << *llvmValue << '\n';
|
|
}
|
|
else {
|
|
toDt(NULL);
|
|
// this is a specialized typeinfo
|
|
//std::vector<const llvm::Type*> stypes;
|
|
//stypes.push_back(
|
|
}
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
|
|
void TypeInfoDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
assert(0 && "TypeInfoDeclaration");
|
|
}
|
|
|
|
void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
Logger::println("TypeInfoTypedefDeclaration::toDt() %s", toChars());
|
|
LOG_SCOPE;
|
|
|
|
ClassDeclaration* base = Type::typeinfotypedef;
|
|
base->toObjFile();
|
|
|
|
llvm::Constant* initZ = base->llvmInitZ;
|
|
assert(initZ);
|
|
const llvm::StructType* stype = llvm::cast<llvm::StructType>(initZ->getType());
|
|
|
|
std::vector<llvm::Constant*> sinits;
|
|
sinits.push_back(initZ->getOperand(0));
|
|
|
|
assert(tinfo->ty == Ttypedef);
|
|
TypeTypedef *tc = (TypeTypedef *)tinfo;
|
|
TypedefDeclaration *sd = tc->sym;
|
|
|
|
// TypeInfo base
|
|
//const llvm::PointerType* basept = llvm::cast<llvm::PointerType>(initZ->getOperand(1)->getType());
|
|
//sinits.push_back(llvm::ConstantPointerNull::get(basept));
|
|
Logger::println("generating base typeinfo");
|
|
//sd->basetype = sd->basetype->merge();
|
|
sd->basetype->getTypeInfo(NULL); // generate vtinfo
|
|
assert(sd->basetype->vtinfo);
|
|
if (!sd->basetype->vtinfo->llvmValue)
|
|
sd->basetype->vtinfo->toObjFile();
|
|
assert(llvm::isa<llvm::Constant>(sd->basetype->vtinfo->llvmValue));
|
|
llvm::Constant* castbase = llvm::cast<llvm::Constant>(sd->basetype->vtinfo->llvmValue);
|
|
castbase = llvm::ConstantExpr::getBitCast(castbase, initZ->getOperand(1)->getType());
|
|
sinits.push_back(castbase);
|
|
|
|
// char[] name
|
|
char *name = sd->toPrettyChars();
|
|
sinits.push_back(LLVM_DtoConstString(name));
|
|
assert(sinits.back()->getType() == initZ->getOperand(2)->getType());
|
|
|
|
// void[] init
|
|
//const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
|
|
//sinits.push_back(LLVM_DtoConstantSlice(LLVM_DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
|
|
sinits.push_back(initZ->getOperand(3));
|
|
|
|
// create the symbol
|
|
llvm::Constant* tiInit = llvm::ConstantStruct::get(stype, sinits);
|
|
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module);
|
|
|
|
llvmValue = gvar;
|
|
|
|
/*
|
|
dtxoff(pdt, Type::typeinfotypedef->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Typedef
|
|
dtdword(pdt, 0); // monitor
|
|
|
|
assert(tinfo->ty == Ttypedef);
|
|
|
|
TypeTypedef *tc = (TypeTypedef *)tinfo;
|
|
TypedefDeclaration *sd = tc->sym;
|
|
//printf("basetype = %s\n", sd->basetype->toChars());
|
|
|
|
// Put out:
|
|
// TypeInfo base;
|
|
// char[] name;
|
|
// void[] m_init;
|
|
|
|
sd->basetype = sd->basetype->merge();
|
|
sd->basetype->getTypeInfo(NULL); // generate vtinfo
|
|
assert(sd->basetype->vtinfo);
|
|
dtxoff(pdt, sd->basetype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for basetype
|
|
|
|
char *name = sd->toPrettyChars();
|
|
size_t namelen = strlen(name);
|
|
dtdword(pdt, namelen);
|
|
dtabytes(pdt, TYnptr, 0, namelen + 1, name);
|
|
|
|
// void[] init;
|
|
if (tinfo->isZeroInit() || !sd->init)
|
|
{ // 0 initializer, or the same as the base type
|
|
dtdword(pdt, 0); // init.length
|
|
dtdword(pdt, 0); // init.ptr
|
|
}
|
|
else
|
|
{
|
|
dtdword(pdt, sd->type->size()); // init.length
|
|
dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr
|
|
*/
|
|
}
|
|
|
|
void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
assert(0 && "TypeInfoEnumDeclaration");
|
|
}
|
|
|
|
void TypeInfoPointerDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
assert(0 && "TypeInfoPointerDeclaration");
|
|
}
|
|
|
|
void TypeInfoArrayDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
assert(0 && "TypeInfoArrayDeclaration");
|
|
}
|
|
|
|
void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
assert(0 && "TypeInfoStaticArrayDeclaration");
|
|
}
|
|
|
|
void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
assert(0 && "TypeInfoAssociativeArrayDeclaration");
|
|
}
|
|
|
|
void TypeInfoFunctionDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
assert(0 && "TypeInfoFunctionDeclaration");
|
|
}
|
|
|
|
void TypeInfoDelegateDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
assert(0 && "TypeInfoDelegateDeclaration");
|
|
}
|
|
|
|
void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
assert(0 && "TypeInfoStructDeclaration");
|
|
}
|
|
|
|
void TypeInfoClassDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
assert(0 && "TypeInfoClassDeclaration");
|
|
}
|
|
|
|
void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
assert(0 && "TypeInfoInterfaceDeclaration");
|
|
}
|
|
|
|
void TypeInfoTupleDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
assert(0 && "TypeInfoTupleDeclaration");
|
|
}
|
|
|
|
// original dmdfe toDt code for reference
|
|
|
|
#if 0
|
|
|
|
void TypeInfoDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
//printf("TypeInfoDeclaration::toDt() %s\n", toChars());
|
|
dtxoff(pdt, Type::typeinfo->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo
|
|
dtdword(pdt, 0); // monitor
|
|
}
|
|
|
|
void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
//printf("TypeInfoTypedefDeclaration::toDt() %s\n", toChars());
|
|
|
|
dtxoff(pdt, Type::typeinfotypedef->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Typedef
|
|
dtdword(pdt, 0); // monitor
|
|
|
|
assert(tinfo->ty == Ttypedef);
|
|
|
|
TypeTypedef *tc = (TypeTypedef *)tinfo;
|
|
TypedefDeclaration *sd = tc->sym;
|
|
//printf("basetype = %s\n", sd->basetype->toChars());
|
|
|
|
/* Put out:
|
|
* TypeInfo base;
|
|
* char[] name;
|
|
* void[] m_init;
|
|
*/
|
|
|
|
sd->basetype = sd->basetype->merge();
|
|
sd->basetype->getTypeInfo(NULL); // generate vtinfo
|
|
assert(sd->basetype->vtinfo);
|
|
dtxoff(pdt, sd->basetype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for basetype
|
|
|
|
char *name = sd->toPrettyChars();
|
|
size_t namelen = strlen(name);
|
|
dtdword(pdt, namelen);
|
|
dtabytes(pdt, TYnptr, 0, namelen + 1, name);
|
|
|
|
// void[] init;
|
|
if (tinfo->isZeroInit() || !sd->init)
|
|
{ // 0 initializer, or the same as the base type
|
|
dtdword(pdt, 0); // init.length
|
|
dtdword(pdt, 0); // init.ptr
|
|
}
|
|
else
|
|
{
|
|
dtdword(pdt, sd->type->size()); // init.length
|
|
dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr
|
|
}
|
|
}
|
|
|
|
void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
//printf("TypeInfoEnumDeclaration::toDt()\n");
|
|
dtxoff(pdt, Type::typeinfoenum->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Enum
|
|
dtdword(pdt, 0); // monitor
|
|
|
|
assert(tinfo->ty == Tenum);
|
|
|
|
TypeEnum *tc = (TypeEnum *)tinfo;
|
|
EnumDeclaration *sd = tc->sym;
|
|
|
|
/* Put out:
|
|
* TypeInfo base;
|
|
* char[] name;
|
|
* void[] m_init;
|
|
*/
|
|
|
|
sd->memtype->getTypeInfo(NULL);
|
|
dtxoff(pdt, sd->memtype->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for enum members
|
|
|
|
char *name = sd->toPrettyChars();
|
|
size_t namelen = strlen(name);
|
|
dtdword(pdt, namelen);
|
|
dtabytes(pdt, TYnptr, 0, namelen + 1, name);
|
|
|
|
// void[] init;
|
|
if (tinfo->isZeroInit() || !sd->defaultval)
|
|
{ // 0 initializer, or the same as the base type
|
|
dtdword(pdt, 0); // init.length
|
|
dtdword(pdt, 0); // init.ptr
|
|
}
|
|
else
|
|
{
|
|
dtdword(pdt, sd->type->size()); // init.length
|
|
dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr
|
|
}
|
|
}
|
|
|
|
void TypeInfoPointerDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
//printf("TypeInfoPointerDeclaration::toDt()\n");
|
|
dtxoff(pdt, Type::typeinfopointer->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Pointer
|
|
dtdword(pdt, 0); // monitor
|
|
|
|
assert(tinfo->ty == Tpointer);
|
|
|
|
TypePointer *tc = (TypePointer *)tinfo;
|
|
|
|
tc->next->getTypeInfo(NULL);
|
|
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for type being pointed to
|
|
}
|
|
|
|
void TypeInfoArrayDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
//printf("TypeInfoArrayDeclaration::toDt()\n");
|
|
dtxoff(pdt, Type::typeinfoarray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Array
|
|
dtdword(pdt, 0); // monitor
|
|
|
|
assert(tinfo->ty == Tarray);
|
|
|
|
TypeDArray *tc = (TypeDArray *)tinfo;
|
|
|
|
tc->next->getTypeInfo(NULL);
|
|
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type
|
|
}
|
|
|
|
void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
//printf("TypeInfoStaticArrayDeclaration::toDt()\n");
|
|
dtxoff(pdt, Type::typeinfostaticarray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_StaticArray
|
|
dtdword(pdt, 0); // monitor
|
|
|
|
assert(tinfo->ty == Tsarray);
|
|
|
|
TypeSArray *tc = (TypeSArray *)tinfo;
|
|
|
|
tc->next->getTypeInfo(NULL);
|
|
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type
|
|
|
|
dtdword(pdt, tc->dim->toInteger()); // length
|
|
}
|
|
|
|
void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
//printf("TypeInfoAssociativeArrayDeclaration::toDt()\n");
|
|
dtxoff(pdt, Type::typeinfoassociativearray->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_AssociativeArray
|
|
dtdword(pdt, 0); // monitor
|
|
|
|
assert(tinfo->ty == Taarray);
|
|
|
|
TypeAArray *tc = (TypeAArray *)tinfo;
|
|
|
|
tc->next->getTypeInfo(NULL);
|
|
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type
|
|
|
|
tc->index->getTypeInfo(NULL);
|
|
dtxoff(pdt, tc->index->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for array of type
|
|
}
|
|
|
|
void TypeInfoFunctionDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
//printf("TypeInfoFunctionDeclaration::toDt()\n");
|
|
dtxoff(pdt, Type::typeinfofunction->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Function
|
|
dtdword(pdt, 0); // monitor
|
|
|
|
assert(tinfo->ty == Tfunction);
|
|
|
|
TypeFunction *tc = (TypeFunction *)tinfo;
|
|
|
|
tc->next->getTypeInfo(NULL);
|
|
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for function return value
|
|
}
|
|
|
|
void TypeInfoDelegateDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
//printf("TypeInfoDelegateDeclaration::toDt()\n");
|
|
dtxoff(pdt, Type::typeinfodelegate->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Delegate
|
|
dtdword(pdt, 0); // monitor
|
|
|
|
assert(tinfo->ty == Tdelegate);
|
|
|
|
TypeDelegate *tc = (TypeDelegate *)tinfo;
|
|
|
|
tc->next->next->getTypeInfo(NULL);
|
|
dtxoff(pdt, tc->next->next->vtinfo->toSymbol(), 0, TYnptr); // TypeInfo for delegate return value
|
|
}
|
|
|
|
void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
//printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars());
|
|
|
|
unsigned offset = Type::typeinfostruct->structsize;
|
|
|
|
dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Struct
|
|
dtdword(pdt, 0); // monitor
|
|
|
|
assert(tinfo->ty == Tstruct);
|
|
|
|
TypeStruct *tc = (TypeStruct *)tinfo;
|
|
StructDeclaration *sd = tc->sym;
|
|
|
|
/* Put out:
|
|
* char[] name;
|
|
* void[] init;
|
|
* hash_t function(void*) xtoHash;
|
|
* int function(void*,void*) xopEquals;
|
|
* int function(void*,void*) xopCmp;
|
|
* char[] function(void*) xtoString;
|
|
* uint m_flags;
|
|
*
|
|
* name[]
|
|
*/
|
|
|
|
char *name = sd->toPrettyChars();
|
|
size_t namelen = strlen(name);
|
|
dtdword(pdt, namelen);
|
|
//dtabytes(pdt, TYnptr, 0, namelen + 1, name);
|
|
dtxoff(pdt, toSymbol(), offset, TYnptr);
|
|
offset += namelen + 1;
|
|
|
|
// void[] init;
|
|
dtdword(pdt, sd->structsize); // init.length
|
|
if (sd->zeroInit)
|
|
dtdword(pdt, 0); // NULL for 0 initialization
|
|
else
|
|
dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr
|
|
|
|
FuncDeclaration *fd;
|
|
FuncDeclaration *fdx;
|
|
TypeFunction *tf;
|
|
Type *ta;
|
|
Dsymbol *s;
|
|
|
|
static TypeFunction *tftohash;
|
|
static TypeFunction *tftostring;
|
|
|
|
if (!tftohash)
|
|
{
|
|
Scope sc;
|
|
|
|
tftohash = new TypeFunction(NULL, Type::thash_t, 0, LINKd);
|
|
tftohash = (TypeFunction *)tftohash->semantic(0, &sc);
|
|
|
|
tftostring = new TypeFunction(NULL, Type::tchar->arrayOf(), 0, LINKd);
|
|
tftostring = (TypeFunction *)tftostring->semantic(0, &sc);
|
|
}
|
|
|
|
TypeFunction *tfeqptr;
|
|
{
|
|
Scope sc;
|
|
Arguments *arguments = new Arguments;
|
|
Argument *arg = new Argument(STCin, tc->pointerTo(), NULL, NULL);
|
|
|
|
arguments->push(arg);
|
|
tfeqptr = new TypeFunction(arguments, Type::tint32, 0, LINKd);
|
|
tfeqptr = (TypeFunction *)tfeqptr->semantic(0, &sc);
|
|
}
|
|
|
|
#if 0
|
|
TypeFunction *tfeq;
|
|
{
|
|
Scope sc;
|
|
Array *arguments = new Array;
|
|
Argument *arg = new Argument(In, tc, NULL, NULL);
|
|
|
|
arguments->push(arg);
|
|
tfeq = new TypeFunction(arguments, Type::tint32, 0, LINKd);
|
|
tfeq = (TypeFunction *)tfeq->semantic(0, &sc);
|
|
}
|
|
#endif
|
|
|
|
s = search_function(sd, Id::tohash);
|
|
fdx = s ? s->isFuncDeclaration() : NULL;
|
|
if (fdx)
|
|
{ fd = fdx->overloadExactMatch(tftohash);
|
|
if (fd)
|
|
dtxoff(pdt, fd->toSymbol(), 0, TYnptr);
|
|
else
|
|
//fdx->error("must be declared as extern (D) uint toHash()");
|
|
dtdword(pdt, 0);
|
|
}
|
|
else
|
|
dtdword(pdt, 0);
|
|
|
|
s = search_function(sd, Id::eq);
|
|
fdx = s ? s->isFuncDeclaration() : NULL;
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
if (fdx)
|
|
{ fd = fdx->overloadExactMatch(tfeqptr);
|
|
if (fd)
|
|
dtxoff(pdt, fd->toSymbol(), 0, TYnptr);
|
|
else
|
|
//fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars());
|
|
dtdword(pdt, 0);
|
|
}
|
|
else
|
|
dtdword(pdt, 0);
|
|
|
|
s = search_function(sd, Id::cmp);
|
|
fdx = s ? s->isFuncDeclaration() : NULL;
|
|
}
|
|
|
|
s = search_function(sd, Id::tostring);
|
|
fdx = s ? s->isFuncDeclaration() : NULL;
|
|
if (fdx)
|
|
{ fd = fdx->overloadExactMatch(tftostring);
|
|
if (fd)
|
|
dtxoff(pdt, fd->toSymbol(), 0, TYnptr);
|
|
else
|
|
//fdx->error("must be declared as extern (D) char[] toString()");
|
|
dtdword(pdt, 0);
|
|
}
|
|
else
|
|
dtdword(pdt, 0);
|
|
|
|
// uint m_flags;
|
|
dtdword(pdt, tc->hasPointers());
|
|
|
|
// name[]
|
|
dtnbytes(pdt, namelen + 1, name);
|
|
}
|
|
|
|
void TypeInfoClassDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
//printf("TypeInfoClassDeclaration::toDt() %s\n", tinfo->toChars());
|
|
dtxoff(pdt, Type::typeinfoclass->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoClass
|
|
dtdword(pdt, 0); // monitor
|
|
|
|
assert(tinfo->ty == Tclass);
|
|
|
|
TypeClass *tc = (TypeClass *)tinfo;
|
|
Symbol *s;
|
|
|
|
if (!tc->sym->vclassinfo)
|
|
tc->sym->vclassinfo = new ClassInfoDeclaration(tc->sym);
|
|
s = tc->sym->vclassinfo->toSymbol();
|
|
dtxoff(pdt, s, 0, TYnptr); // ClassInfo for tinfo
|
|
}
|
|
|
|
void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
//printf("TypeInfoInterfaceDeclaration::toDt() %s\n", tinfo->toChars());
|
|
dtxoff(pdt, Type::typeinfointerface->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface
|
|
dtdword(pdt, 0); // monitor
|
|
|
|
assert(tinfo->ty == Tclass);
|
|
|
|
TypeClass *tc = (TypeClass *)tinfo;
|
|
Symbol *s;
|
|
|
|
if (!tc->sym->vclassinfo)
|
|
tc->sym->vclassinfo = new ClassInfoDeclaration(tc->sym);
|
|
s = tc->sym->vclassinfo->toSymbol();
|
|
dtxoff(pdt, s, 0, TYnptr); // ClassInfo for tinfo
|
|
}
|
|
|
|
void TypeInfoTupleDeclaration::toDt(dt_t **pdt)
|
|
{
|
|
//printf("TypeInfoTupleDeclaration::toDt() %s\n", tinfo->toChars());
|
|
dtxoff(pdt, Type::typeinfotypelist->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface
|
|
dtdword(pdt, 0); // monitor
|
|
|
|
assert(tinfo->ty == Ttuple);
|
|
|
|
TypeTuple *tu = (TypeTuple *)tinfo;
|
|
|
|
size_t dim = tu->arguments->dim;
|
|
dtdword(pdt, dim); // elements.length
|
|
|
|
dt_t *d = NULL;
|
|
for (size_t i = 0; i < dim; i++)
|
|
{ Argument *arg = (Argument *)tu->arguments->data[i];
|
|
Expression *e = arg->type->getTypeInfo(NULL);
|
|
e = e->optimize(WANTvalue);
|
|
e->toDt(&d);
|
|
}
|
|
|
|
Symbol *s;
|
|
s = static_sym();
|
|
s->Sdt = d;
|
|
outdata(s);
|
|
|
|
dtxoff(pdt, s, 0, TYnptr); // elements.ptr
|
|
}
|
|
|
|
void TypeInfoDeclaration::toObjFile()
|
|
{
|
|
Symbol *s;
|
|
unsigned sz;
|
|
Dsymbol *parent;
|
|
|
|
//printf("TypeInfoDeclaration::toObjFile(%p '%s') protection %d\n", this, toChars(), protection);
|
|
|
|
s = toSymbol();
|
|
sz = type->size();
|
|
|
|
parent = this->toParent();
|
|
s->Sclass = SCcomdat;
|
|
s->Sfl = FLdata;
|
|
|
|
toDt(&s->Sdt);
|
|
|
|
dt_optimize(s->Sdt);
|
|
|
|
// See if we can convert a comdat to a comdef,
|
|
// which saves on exe file space.
|
|
if (s->Sclass == SCcomdat &&
|
|
s->Sdt->dt == DT_azeros &&
|
|
s->Sdt->DTnext == NULL)
|
|
{
|
|
s->Sclass = SCglobal;
|
|
s->Sdt->dt = DT_common;
|
|
}
|
|
|
|
#if ELFOBJ // Burton
|
|
if (s->Sdt && s->Sdt->dt == DT_azeros && s->Sdt->DTnext == NULL)
|
|
s->Sseg = UDATA;
|
|
else
|
|
s->Sseg = DATA;
|
|
#endif /* ELFOBJ */
|
|
outdata(s);
|
|
if (isExport())
|
|
obj_export(s,0);
|
|
}
|
|
|
|
#endif
|