mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-13 03:13:13 +01:00
[svn r76] Fixed: TypeInfo for structs.
Fixed: PostExp was unable to allocate storage for parameters. Fixed: Many types of functions and delegates were broken. Misc cleanups.
This commit is contained in:
@@ -98,7 +98,7 @@ struct AggregateDeclaration : ScopeDsymbol
|
||||
|
||||
bool llvmInProgress;
|
||||
llvm::Type* llvmType;
|
||||
llvm::Value* llvmVtbl;
|
||||
llvm::Constant* llvmVtbl;
|
||||
llvm::ConstantStruct* llvmConstVtbl;
|
||||
llvm::Constant* llvmInitZ;
|
||||
virtual void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result); // converts a DMD field offsets to LLVM struct index vector
|
||||
|
||||
@@ -540,7 +540,7 @@ struct TypeStruct : Type
|
||||
|
||||
type *toCtype();
|
||||
|
||||
llvm::Value* llvmInit;
|
||||
llvm::Constant* llvmInit;
|
||||
};
|
||||
|
||||
struct TypeEnum : Type
|
||||
@@ -638,7 +638,7 @@ struct TypeClass : Type
|
||||
|
||||
Symbol *toSymbol();
|
||||
|
||||
llvm::Value* llvmInit;
|
||||
llvm::Constant* llvmInit;
|
||||
};
|
||||
|
||||
struct TypeTuple : Type
|
||||
|
||||
32
gen/toir.c
32
gen/toir.c
@@ -116,6 +116,7 @@ elem* VarExp::toElem(IRState* p)
|
||||
// _arguments
|
||||
if (vd->ident == Id::_arguments)
|
||||
{
|
||||
Logger::println("Id::_arguments");
|
||||
vd->llvmValue = p->func().decl->llvmArguments;
|
||||
assert(vd->llvmValue);
|
||||
e->mem = vd->llvmValue;
|
||||
@@ -124,6 +125,7 @@ elem* VarExp::toElem(IRState* p)
|
||||
// _argptr
|
||||
else if (vd->ident == Id::_argptr)
|
||||
{
|
||||
Logger::println("Id::_argptr");
|
||||
vd->llvmValue = p->func().decl->llvmArgPtr;
|
||||
assert(vd->llvmValue);
|
||||
e->mem = vd->llvmValue;
|
||||
@@ -132,6 +134,7 @@ elem* VarExp::toElem(IRState* p)
|
||||
// _dollar
|
||||
else if (vd->ident == Id::dollar)
|
||||
{
|
||||
Logger::println("Id::dollar");
|
||||
assert(!p->arrays.empty());
|
||||
llvm::Value* tmp = LLVM_DtoGEPi(p->arrays.back(),0,0,"tmp",p->scopebb());
|
||||
e->val = new llvm::LoadInst(tmp,"tmp",p->scopebb());
|
||||
@@ -152,6 +155,7 @@ elem* VarExp::toElem(IRState* p)
|
||||
}
|
||||
// nested variable
|
||||
else if (vd->nestedref) {
|
||||
Logger::println("nested variable");
|
||||
e->mem = LLVM_DtoNestedVariable(vd);
|
||||
e->type = elem::VAR;
|
||||
e->vardecl = vd;
|
||||
@@ -159,7 +163,11 @@ elem* VarExp::toElem(IRState* p)
|
||||
// function parameter
|
||||
else if (vd->isParameter()) {
|
||||
Logger::println("function param");
|
||||
assert(vd->llvmValue);
|
||||
if (!vd->llvmValue) {
|
||||
// TODO: determine this properly
|
||||
// this happens when the DMD frontend generates by pointer wrappers for struct opEquals(S) and opCmp(S)
|
||||
vd->llvmValue = &p->func().func->getArgumentList().back();
|
||||
}
|
||||
if (vd->isRef() || vd->isOut()) {
|
||||
e->mem = vd->llvmValue;
|
||||
e->type = elem::VAR;
|
||||
@@ -1432,18 +1440,27 @@ elem* SymOffExp::toElem(IRState* p)
|
||||
|
||||
assert(vd->llvmValue);
|
||||
Type* t = LLVM_DtoDType(type);
|
||||
Type* tnext = LLVM_DtoDType(t->next);
|
||||
Type* vdtype = LLVM_DtoDType(vd->type);
|
||||
|
||||
llvm::Value* llvalue = vd->nestedref ? LLVM_DtoNestedVariable(vd) : vd->llvmValue;
|
||||
|
||||
if (vdtype->ty == Tstruct && !(t->ty == Tpointer && t->next == vdtype)) {
|
||||
TypeStruct* vdt = (TypeStruct*)vdtype;
|
||||
assert(vdt->sym);
|
||||
e = new elem;
|
||||
std::vector<unsigned> dst(1,0);
|
||||
vdt->sym->offsetToIndex(t->next, offset, dst);
|
||||
llvm::Value* ptr = llvalue;
|
||||
assert(ptr);
|
||||
e->mem = LLVM_DtoGEP(ptr,dst,"tmp");
|
||||
bool donormally = true;
|
||||
if (offset == 0) {
|
||||
const llvm::Type* llt = LLVM_DtoType(t);
|
||||
e->mem = p->ir->CreateBitCast(llvalue, llt, "tmp");
|
||||
}
|
||||
else {
|
||||
std::vector<unsigned> dst(1,0);
|
||||
vdt->sym->offsetToIndex(tnext, offset, dst);
|
||||
llvm::Value* ptr = llvalue;
|
||||
assert(ptr);
|
||||
e->mem = LLVM_DtoGEP(ptr,dst,"tmp");
|
||||
}
|
||||
e->type = elem::VAL;
|
||||
e->field = true;
|
||||
}
|
||||
@@ -2118,7 +2135,8 @@ elem* PostExp::toElem(IRState* p)
|
||||
else
|
||||
assert(post);
|
||||
|
||||
//llvm::Value* tostore = l->storeVal ? l->storeVal : l->val;
|
||||
if (l->mem == 0)
|
||||
LLVM_DtoGiveArgumentStorage(l);
|
||||
new llvm::StoreInst(post,l->mem,p->scopebb());
|
||||
|
||||
delete l;
|
||||
|
||||
174
gen/tollvm.c
174
gen/tollvm.c
@@ -151,7 +151,7 @@ const llvm::Type* LLVM_DtoType(Type* t)
|
||||
case Tfunction:
|
||||
{
|
||||
if (t->llvmType == 0) {
|
||||
return LLVM_DtoFunctionType(t);
|
||||
return LLVM_DtoFunctionType(t,NULL);
|
||||
}
|
||||
else {
|
||||
return t->llvmType;
|
||||
@@ -188,94 +188,13 @@ const llvm::Type* LLVM_DtoType(Type* t)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam)
|
||||
const llvm::FunctionType* LLVM_DtoFunctionType(Type* type, const llvm::Type* thistype, bool ismain)
|
||||
{
|
||||
TypeFunction* f = (TypeFunction*)t;
|
||||
|
||||
// parameter types
|
||||
const llvm::Type* rettype;
|
||||
std::vector<const llvm::Type*> paramvec;
|
||||
|
||||
if (LLVM_DtoIsPassedByRef(f->next)) {
|
||||
rettype = llvm::PointerType::get(LLVM_DtoType(f->next));
|
||||
paramvec.push_back(rettype);
|
||||
rettype = llvm::Type::VoidTy;
|
||||
}
|
||||
else {
|
||||
Type* rt = f->next;
|
||||
if (rt)
|
||||
rettype = LLVM_DtoType(rt);
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (thisparam) {
|
||||
paramvec.push_back(thisparam);
|
||||
}
|
||||
|
||||
size_t n = Argument::dim(f->parameters);
|
||||
for (int i=0; i < n; ++i) {
|
||||
Argument* arg = Argument::getNth(f->parameters, i);
|
||||
// ensure scalar
|
||||
Type* argT = arg->type;
|
||||
assert(argT);
|
||||
paramvec.push_back(LLVM_DtoType(argT));
|
||||
}
|
||||
|
||||
Logger::cout() << "Return type: " << *rettype << '\n';
|
||||
|
||||
llvm::FunctionType* functype = llvm::FunctionType::get(rettype, paramvec, f->varargs);
|
||||
return functype;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const llvm::FunctionType* LLVM_DtoVaFunctionType(FuncDeclaration* fdecl)
|
||||
{
|
||||
TypeFunction* f = (TypeFunction*)fdecl->type;
|
||||
TypeFunction* f = (TypeFunction*)type;
|
||||
assert(f != 0);
|
||||
|
||||
const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
std::vector<const llvm::Type*> args;
|
||||
|
||||
if (fdecl->llvmInternal == LLVMva_start) {
|
||||
args.push_back(i8pty);
|
||||
}
|
||||
else if (fdecl->llvmInternal == LLVMva_intrinsic) {
|
||||
size_t n = Argument::dim(f->parameters);
|
||||
for (size_t i=0; i<n; ++i) {
|
||||
args.push_back(i8pty);
|
||||
}
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
|
||||
f->llvmType = fty;
|
||||
return fty;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
|
||||
{
|
||||
if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
|
||||
return LLVM_DtoVaFunctionType(fdecl);
|
||||
}
|
||||
|
||||
TypeFunction* f = (TypeFunction*)fdecl->type;
|
||||
assert(f != 0);
|
||||
|
||||
// type has already been resolved
|
||||
if (f->llvmType != 0) {
|
||||
return llvm::cast<llvm::FunctionType>(f->llvmType);
|
||||
}
|
||||
|
||||
bool typesafeVararg = false;
|
||||
if (f->linkage == LINKd && f->varargs == 1) {
|
||||
assert(fdecl->v_arguments);
|
||||
Logger::println("v_arguments = %s", fdecl->v_arguments->toChars());
|
||||
assert(fdecl->v_arguments->isParameter());
|
||||
typesafeVararg = true;
|
||||
}
|
||||
|
||||
@@ -286,11 +205,12 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
|
||||
bool retinptr = false;
|
||||
bool usesthis = false;
|
||||
|
||||
if (fdecl->isMain()) {
|
||||
if (ismain) {
|
||||
rettype = llvm::Type::Int32Ty;
|
||||
actualRettype = rettype;
|
||||
}
|
||||
else if (rt) {
|
||||
else {
|
||||
assert(rt);
|
||||
if (LLVM_DtoIsPassedByRef(rt)) {
|
||||
rettype = llvm::PointerType::get(LLVM_DtoType(rt));
|
||||
actualRettype = llvm::Type::VoidTy;
|
||||
@@ -301,9 +221,6 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
|
||||
actualRettype = rettype;
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// parameter types
|
||||
std::vector<const llvm::Type*> paramvec;
|
||||
@@ -313,21 +230,8 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
|
||||
paramvec.push_back(rettype);
|
||||
}
|
||||
|
||||
if (fdecl->needThis()) {
|
||||
if (AggregateDeclaration* ad = fdecl->isMember()) {
|
||||
Logger::print("isMember = this is: %s\n", ad->type->toChars());
|
||||
const llvm::Type* thisty = LLVM_DtoType(ad->type);
|
||||
Logger::cout() << "this llvm type: " << *thisty << '\n';
|
||||
if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get())
|
||||
thisty = llvm::PointerType::get(thisty);
|
||||
paramvec.push_back(thisty);
|
||||
usesthis = true;
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
else if (fdecl->isNested()) {
|
||||
paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
|
||||
if (thistype) {
|
||||
paramvec.push_back(thistype);
|
||||
usesthis = true;
|
||||
}
|
||||
|
||||
@@ -396,7 +300,6 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
|
||||
bool isvararg = !typesafeVararg && f->varargs;
|
||||
llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
|
||||
|
||||
f->llvmType = functype;
|
||||
f->llvmRetInPtr = retinptr;
|
||||
f->llvmUsesThis = usesthis;
|
||||
return functype;
|
||||
@@ -404,6 +307,67 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const llvm::FunctionType* LLVM_DtoVaFunctionType(FuncDeclaration* fdecl)
|
||||
{
|
||||
TypeFunction* f = (TypeFunction*)fdecl->type;
|
||||
assert(f != 0);
|
||||
|
||||
const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
std::vector<const llvm::Type*> args;
|
||||
|
||||
if (fdecl->llvmInternal == LLVMva_start) {
|
||||
args.push_back(i8pty);
|
||||
}
|
||||
else if (fdecl->llvmInternal == LLVMva_intrinsic) {
|
||||
size_t n = Argument::dim(f->parameters);
|
||||
for (size_t i=0; i<n; ++i) {
|
||||
args.push_back(i8pty);
|
||||
}
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
|
||||
const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false);
|
||||
f->llvmType = fty;
|
||||
return fty;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
|
||||
{
|
||||
if ((fdecl->llvmInternal == LLVMva_start) || (fdecl->llvmInternal == LLVMva_intrinsic)) {
|
||||
return LLVM_DtoVaFunctionType(fdecl);
|
||||
}
|
||||
|
||||
// type has already been resolved
|
||||
if (fdecl->type->llvmType != 0) {
|
||||
return llvm::cast<llvm::FunctionType>(fdecl->type->llvmType);
|
||||
}
|
||||
|
||||
const llvm::Type* thisty = NULL;
|
||||
if (fdecl->needThis()) {
|
||||
if (AggregateDeclaration* ad = fdecl->isMember()) {
|
||||
Logger::print("isMember = this is: %s\n", ad->type->toChars());
|
||||
thisty = LLVM_DtoType(ad->type);
|
||||
Logger::cout() << "this llvm type: " << *thisty << '\n';
|
||||
if (llvm::isa<llvm::StructType>(thisty) || thisty == gIR->topstruct().recty.get())
|
||||
thisty = llvm::PointerType::get(thisty);
|
||||
}
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
else if (fdecl->isNested()) {
|
||||
thisty = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
}
|
||||
|
||||
const llvm::FunctionType* functype = LLVM_DtoFunctionType(fdecl->type, thisty, fdecl->isMain());
|
||||
fdecl->type->llvmType = functype;
|
||||
return functype;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const llvm::StructType* LLVM_DtoDelegateType(Type* t)
|
||||
{
|
||||
const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
|
||||
@@ -11,7 +11,7 @@ llvm::Value* LLVM_DtoStructZeroInit(llvm::Value* v);
|
||||
llvm::Value* LLVM_DtoStructCopy(llvm::Value* dst, llvm::Value* src);
|
||||
llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si);
|
||||
|
||||
const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam = 0);
|
||||
const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thistype, bool ismain = false);
|
||||
const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl);
|
||||
llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl);
|
||||
|
||||
|
||||
@@ -296,7 +296,8 @@ void StructDeclaration::toObjFile()
|
||||
gIR->structs.pop_back();
|
||||
|
||||
// generate typeinfo
|
||||
//type->getTypeInfo(NULL);
|
||||
if (getModule() == gIR->dmodule)
|
||||
type->getTypeInfo(NULL);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
@@ -624,8 +625,7 @@ void TypedefDeclaration::toObjFile()
|
||||
LOG_SCOPE;
|
||||
|
||||
// generate typeinfo
|
||||
if (!type->builtinTypeInfo())
|
||||
type->getTypeInfo(NULL);
|
||||
type->getTypeInfo(NULL);
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
|
||||
244
gen/typinf.c
244
gen/typinf.c
@@ -263,12 +263,6 @@ void TypeInfoDeclaration::toObjFile()
|
||||
void TypeInfoDeclaration::toDt(dt_t **pdt)
|
||||
{
|
||||
assert(0 && "TypeInfoDeclaration");
|
||||
|
||||
/*
|
||||
//printf("TypeInfoDeclaration::toDt() %s\n", toChars());
|
||||
dtxoff(pdt, Type::typeinfo->toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo
|
||||
dtdword(pdt, 0); // monitor
|
||||
*/
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
@@ -316,7 +310,6 @@ void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
|
||||
if (tinfo->isZeroInit() || !sd->init) // 0 initializer, or the same as the base type
|
||||
{
|
||||
sinits.push_back(LLVM_DtoConstSlice(LLVM_DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
|
||||
//sinits.push_back(initZ->getOperand(3));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -334,43 +327,6 @@ void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
|
||||
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
|
||||
*/
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
@@ -418,7 +374,6 @@ void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
|
||||
if (tinfo->isZeroInit() || !sd->defaultval) // 0 initializer, or the same as the base type
|
||||
{
|
||||
sinits.push_back(LLVM_DtoConstSlice(LLVM_DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
|
||||
//sinits.push_back(initZ->getOperand(3));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -437,44 +392,6 @@ void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
|
||||
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::InternalLinkage,tiInit,toChars(),gIR->module);
|
||||
|
||||
llvmValue = gvar;
|
||||
|
||||
/*
|
||||
|
||||
//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
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
@@ -610,7 +527,166 @@ void TypeInfoDelegateDeclaration::toDt(dt_t **pdt)
|
||||
|
||||
void TypeInfoStructDeclaration::toDt(dt_t **pdt)
|
||||
{
|
||||
assert(0 && "TypeInfoStructDeclaration");
|
||||
Logger::println("TypeInfoStructDeclaration::toDt() %s", toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
assert(tinfo->ty == Tstruct);
|
||||
TypeStruct *tc = (TypeStruct *)tinfo;
|
||||
StructDeclaration *sd = tc->sym;
|
||||
|
||||
ClassDeclaration* base = Type::typeinfostruct;
|
||||
base->toObjFile();
|
||||
|
||||
const llvm::StructType* stype = llvm::cast<llvm::StructType>(base->llvmType);
|
||||
|
||||
std::vector<llvm::Constant*> sinits;
|
||||
sinits.push_back(base->llvmVtbl);
|
||||
|
||||
// char[] name
|
||||
char *name = sd->toPrettyChars();
|
||||
sinits.push_back(LLVM_DtoConstString(name));
|
||||
assert(sinits.back()->getType() == stype->getElementType(1));
|
||||
|
||||
// void[] init
|
||||
const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty);
|
||||
if (sd->zeroInit) // 0 initializer, or the same as the base type
|
||||
{
|
||||
sinits.push_back(LLVM_DtoConstSlice(LLVM_DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt)));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(sd->llvmInitZ);
|
||||
size_t cisize = gTargetData->getTypeSize(tc->llvmType);
|
||||
llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(tc->llvmInit, initpt);
|
||||
sinits.push_back(LLVM_DtoConstSlice(LLVM_DtoConstSize_t(cisize), cicast));
|
||||
}
|
||||
|
||||
// toX functions ground work
|
||||
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
|
||||
|
||||
const llvm::PointerType* ptty = llvm::cast<llvm::PointerType>(stype->getElementType(3));
|
||||
|
||||
s = search_function(sd, Id::tohash);
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
if (fdx)
|
||||
{
|
||||
fd = fdx->overloadExactMatch(tftohash);
|
||||
if (fd) {
|
||||
assert(fd->llvmValue != 0);
|
||||
llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
|
||||
assert(c);
|
||||
c = llvm::ConstantExpr::getBitCast(c, ptty);
|
||||
sinits.push_back(c);
|
||||
}
|
||||
else {
|
||||
//fdx->error("must be declared as extern (D) uint toHash()");
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
|
||||
}
|
||||
}
|
||||
else {
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
|
||||
}
|
||||
|
||||
s = search_function(sd, Id::eq);
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
ptty = llvm::cast<llvm::PointerType>(stype->getElementType(4+i));
|
||||
if (fdx)
|
||||
{
|
||||
fd = fdx->overloadExactMatch(tfeqptr);
|
||||
if (fd) {
|
||||
assert(fd->llvmValue != 0);
|
||||
llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
|
||||
assert(c);
|
||||
c = llvm::ConstantExpr::getBitCast(c, ptty);
|
||||
sinits.push_back(c);
|
||||
}
|
||||
else {
|
||||
//fdx->error("must be declared as extern (D) int %s(%s*)", fdx->toChars(), sd->toChars());
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
|
||||
}
|
||||
}
|
||||
else {
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
|
||||
}
|
||||
|
||||
s = search_function(sd, Id::cmp);
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
}
|
||||
|
||||
ptty = llvm::cast<llvm::PointerType>(stype->getElementType(6));
|
||||
s = search_function(sd, Id::tostring);
|
||||
fdx = s ? s->isFuncDeclaration() : NULL;
|
||||
if (fdx)
|
||||
{
|
||||
fd = fdx->overloadExactMatch(tftostring);
|
||||
if (fd) {
|
||||
assert(fd->llvmValue != 0);
|
||||
llvm::Constant* c = llvm::cast_or_null<llvm::Constant>(fd->llvmValue);
|
||||
assert(c);
|
||||
c = llvm::ConstantExpr::getBitCast(c, ptty);
|
||||
sinits.push_back(c);
|
||||
}
|
||||
else {
|
||||
//fdx->error("must be declared as extern (D) char[] toString()");
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
|
||||
}
|
||||
}
|
||||
else {
|
||||
sinits.push_back(llvm::ConstantPointerNull::get(ptty));
|
||||
}
|
||||
|
||||
// uint m_flags;
|
||||
sinits.push_back(LLVM_DtoConstUint(tc->hasPointers()));
|
||||
|
||||
// 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;
|
||||
|
||||
/*
|
||||
//printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars());
|
||||
|
||||
@@ -937,6 +937,8 @@ class TypeInfo_Interface : TypeInfo
|
||||
ClassInfo info;
|
||||
}
|
||||
|
||||
+/
|
||||
|
||||
class TypeInfo_Struct : TypeInfo
|
||||
{
|
||||
char[] toString() { return name; }
|
||||
@@ -987,7 +989,7 @@ class TypeInfo_Struct : TypeInfo
|
||||
return c;
|
||||
}
|
||||
|
||||
int compare(void *p2, void *p1)
|
||||
int compare(void *p1, void *p2)
|
||||
{
|
||||
int c = 0;
|
||||
|
||||
@@ -1029,6 +1031,8 @@ class TypeInfo_Struct : TypeInfo
|
||||
uint m_flags;
|
||||
}
|
||||
|
||||
/+
|
||||
|
||||
class TypeInfo_Tuple : TypeInfo
|
||||
{
|
||||
TypeInfo[] elements;
|
||||
|
||||
12
test/bug38.d
Normal file
12
test/bug38.d
Normal file
@@ -0,0 +1,12 @@
|
||||
module bug38;
|
||||
|
||||
void func(int* p)
|
||||
{
|
||||
p++;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
int i;
|
||||
func(&i);
|
||||
}
|
||||
13
test/bug39.d
Normal file
13
test/bug39.d
Normal file
@@ -0,0 +1,13 @@
|
||||
module bug39;
|
||||
|
||||
struct S
|
||||
{
|
||||
long l;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
S s;
|
||||
s.l = 23;
|
||||
void* p = &s;
|
||||
}
|
||||
12
test/bug40.d
Normal file
12
test/bug40.d
Normal file
@@ -0,0 +1,12 @@
|
||||
module bug40;
|
||||
|
||||
char[] func(void* p)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
char[] function(void*) fp = &func;
|
||||
assert(fp(null) is null);
|
||||
}
|
||||
64
test/typeinfo10.d
Normal file
64
test/typeinfo10.d
Normal file
@@ -0,0 +1,64 @@
|
||||
module typeinfo10;
|
||||
|
||||
struct S
|
||||
{
|
||||
long l;
|
||||
float f;
|
||||
void* vp;
|
||||
|
||||
hash_t toHash()
|
||||
{
|
||||
return l + cast(size_t)f;
|
||||
}
|
||||
|
||||
int opEquals(S s)
|
||||
{
|
||||
return (s.l == l) && (s.f == f);
|
||||
}
|
||||
|
||||
int opCmp(S a)
|
||||
{
|
||||
if (l == a.l) {
|
||||
return (f < a.f) ? -1 : (f > a.f) ? 1 : 0;
|
||||
}
|
||||
return (l < a.l) ? -1 : 1;
|
||||
}
|
||||
|
||||
char[] toString()
|
||||
{
|
||||
return "S instance";
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
S s=S(-1, 0);
|
||||
S t=S(-1, 1);
|
||||
S u=S(11,-1);
|
||||
S v=S(12,13);
|
||||
|
||||
{
|
||||
assert(s == s);
|
||||
assert(s != t);
|
||||
assert(s != v);
|
||||
assert(s < t);
|
||||
assert(u > s);
|
||||
assert(v > u);
|
||||
}
|
||||
|
||||
{
|
||||
auto ti = typeid(S);
|
||||
assert(ti.getHash(&s) == s.toHash());
|
||||
assert(ti.equals(&s,&s));
|
||||
assert(!ti.equals(&s,&t));
|
||||
assert(!ti.equals(&s,&v));
|
||||
assert(ti.compare(&s,&s) == 0);
|
||||
assert(ti.compare(&s,&t) < 0);
|
||||
assert(ti.compare(&u,&s) > 0);
|
||||
assert(ti.compare(&v,&u) > 0);
|
||||
{
|
||||
auto tis = cast(TypeInfo_Struct)ti;
|
||||
assert(tis.xtoString(&s) == s.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user