[svn r56] Initial support for TypeInfo.

Enums not work.
Several other bugfixes.
This commit is contained in:
Tomas Lindquist Olsen
2007-10-23 05:55:12 +02:00
parent 2c99df8deb
commit 5fee3fc8b7
75 changed files with 1091 additions and 2923 deletions

View File

@@ -480,3 +480,74 @@ llvm::Value* LLVM_DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r)
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* LLVM_DtoDynArrayCompare(TOK op, llvm::Value* l, llvm::Value* r)
{
const char* fname;
if (op == TOKequal)
fname = "_d_dyn_array_eq";
else if (op == TOKnotequal)
fname = "_d_dyn_array_neq";
else
assert(0);
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname);
assert(fn);
Logger::cout() << "lhsType:" << *l->getType() << "\nrhsType:" << *r->getType() << '\n';
assert(l->getType() == r->getType());
assert(llvm::isa<llvm::PointerType>(l->getType()));
const llvm::Type* arrty = l->getType()->getContainedType(0);
assert(llvm::isa<llvm::StructType>(arrty));
const llvm::StructType* structType = llvm::cast<llvm::StructType>(arrty);
const llvm::Type* elemType = structType->getElementType(1)->getContainedType(0);
std::vector<const llvm::Type*> arrTypes;
arrTypes.push_back(LLVM_DtoSize_t());
arrTypes.push_back(llvm::PointerType::get(llvm::Type::Int8Ty));
const llvm::StructType* arrType = llvm::StructType::get(arrTypes);
llvm::Value* llmem = l;
llvm::Value* rrmem = r;
if (arrty != arrType) {
llmem= new llvm::AllocaInst(arrType,"tmparr",gIR->topallocapoint());
llvm::Value* ll = gIR->ir->CreateLoad(LLVM_DtoGEPi(l, 0,0, "tmp"),"tmp");
ll = LLVM_DtoArrayCastLength(ll, elemType, llvm::Type::Int8Ty);
llvm::Value* lllen = LLVM_DtoGEPi(llmem, 0,0, "tmp");
gIR->ir->CreateStore(ll,lllen);
ll = gIR->ir->CreateLoad(LLVM_DtoGEPi(l, 0,1, "tmp"),"tmp");
ll = new llvm::BitCastInst(ll, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
llvm::Value* llptr = LLVM_DtoGEPi(llmem, 0,1, "tmp");
gIR->ir->CreateStore(ll,llptr);
rrmem = new llvm::AllocaInst(arrType,"tmparr",gIR->topallocapoint());
llvm::Value* rr = gIR->ir->CreateLoad(LLVM_DtoGEPi(r, 0,0, "tmp"),"tmp");
rr = LLVM_DtoArrayCastLength(rr, elemType, llvm::Type::Int8Ty);
llvm::Value* rrlen = LLVM_DtoGEPi(rrmem, 0,0, "tmp");
gIR->ir->CreateStore(rr,rrlen);
rr = gIR->ir->CreateLoad(LLVM_DtoGEPi(r, 0,1, "tmp"),"tmp");
rr = new llvm::BitCastInst(rr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb());
llvm::Value* rrptr = LLVM_DtoGEPi(rrmem, 0,1, "tmp");
gIR->ir->CreateStore(rr,rrptr);
}
std::vector<llvm::Value*> args;
args.push_back(llmem);
args.push_back(rrmem);
return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* LLVM_DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty)
{
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_array_cast_len");
assert(fn);
std::vector<llvm::Value*> args;
args.push_back(len);
args.push_back(llvm::ConstantInt::get(LLVM_DtoSize_t(), gTargetData->getTypeSize(elemty), false));
args.push_back(llvm::ConstantInt::get(LLVM_DtoSize_t(), gTargetData->getTypeSize(newelemty), false));
return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb());
}

View File

@@ -20,6 +20,10 @@ void LLVM_DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz);
void LLVM_DtoCatArrayElement(llvm::Value* arr, Expression* exp);
void LLVM_DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src);
llvm::Value* LLVM_DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r);
llvm::Value* LLVM_DtoDynArrayCompare(TOK op, llvm::Value* l, llvm::Value* r);
llvm::Value* LLVM_DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty);
#endif // LLVMC_GEN_ARRAYS_H

View File

@@ -19,6 +19,7 @@ elem::elem()
field = false;
callconv = (unsigned)-1;
isthis = false;
istypeinfo = false;
vardecl = 0;
funcdecl = 0;

View File

@@ -32,6 +32,7 @@ public:
bool field;
unsigned callconv;
bool isthis;
bool istypeinfo;
VarDeclaration* vardecl;
FuncDeclaration* funcdecl;

View File

@@ -1,5 +1,6 @@
#include <cassert>
#include "gen/llvm.h"
#include "llvm/Module.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -13,6 +14,8 @@
static llvm::Module* M = NULL;
static bool runtime_failed = false;
//////////////////////////////////////////////////////////////////////////////////////////////////
bool LLVM_D_InitRuntime()
{
Logger::println("*** Loading D runtime ***");
@@ -41,7 +44,7 @@ bool LLVM_D_InitRuntime()
Logger::println("Failed to load runtime: %s", errstr.c_str());
runtime_failed = true;
}
delete buffer;
return retval;
}
@@ -54,6 +57,8 @@ void LLVM_D_FreeRuntime()
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name)
{
// TODO maybe check the target module first, to allow overriding the runtime on a pre module basis?
@@ -63,20 +68,47 @@ llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name
error("No implicit runtime calls allowed with -noruntime option enabled");
fatal();
}
if (!M) {
assert(!runtime_failed);
LLVM_D_InitRuntime();
}
llvm::Function* fn = M->getFunction(name);
if (!fn) {
error("Runtime function '%s' was not found", name);
fatal();
//return NULL;
}
const llvm::FunctionType* fnty = fn->getFunctionType();
return llvm::cast<llvm::Function>(target->getOrInsertFunction(name, fnty));
}
//////////////////////////////////////////////////////////////////////////////////////////////////
llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char* name)
{
// TODO maybe check the target module first, to allow overriding the runtime on a pre module basis?
// could be done and seems like it could be neat too :)
if (global.params.noruntime) {
error("No implicit runtime calls allowed with -noruntime option enabled");
fatal();
}
if (!M) {
assert(!runtime_failed);
LLVM_D_InitRuntime();
}
llvm::GlobalVariable* g = M->getNamedGlobal(name);
if (!g) {
error("Runtime global '%s' was not found", name);
fatal();
//return NULL;
}
const llvm::PointerType* t = g->getType();
return new llvm::GlobalVariable(t->getElementType(),g->isConstant(),g->getLinkage(),NULL,g->getName(),target);
}

View File

@@ -4,3 +4,5 @@ bool LLVM_D_InitRuntime();
void LLVM_D_FreeRuntime();
llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name);
llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char* name);

View File

@@ -116,36 +116,6 @@ void StructDeclaration::toDt(dt_t **pdt)
{
}
void TypeInfoPointerDeclaration::toDt(dt_t **pdt)
{
}
void TypeInfoArrayDeclaration::toDt(dt_t **pdt)
{
}
void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt)
{
}
void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt)
{
}
void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
{
}
void TypeInfoFunctionDeclaration::toDt(dt_t **pdt)
{
}
void TypeInfoDelegateDeclaration::toDt(dt_t **pdt)
{
}
void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt)
{
}
void TypeInfoTupleDeclaration::toDt(dt_t **pdt)
{
}
dt_t **Type::toDt(dt_t **pdt)
{
return 0;

View File

@@ -83,12 +83,17 @@ elem* DeclarationExp::toElem(IRState* p)
else if (AliasDeclaration* a = declaration->isAliasDeclaration())
{
Logger::println("AliasDeclaration");
assert(0);
}
else if (EnumDeclaration* e = declaration->isEnumDeclaration())
{
// do nothing
}
// unsupported declaration
else
{
error("Only Var/Struct-Declaration is supported for DeclarationExp");
fatal();
assert(0);
}
return e;
}
@@ -138,9 +143,7 @@ elem* VarExp::toElem(IRState* p)
// typeinfo
else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
{
tid->toObjFile();
e->mem = tid->llvmValue;
e->type = elem::VAR;
assert(0);
}
// global forward ref
else {
@@ -181,28 +184,24 @@ elem* VarExp::toElem(IRState* p)
else {
// nested variable
if (vd->nestedref) {
/*
FuncDeclaration* fd = vd->toParent()->isFuncDeclaration();
assert(fd != NULL);
llvm::Value* ptr = NULL;
// inside nested function
if (fd != p->func().decl) {
ptr = p->func().decl->llvmThisVar;
Logger::cout() << "nested var reference:" << '\n' << *ptr << *vd->llvmValue->getType() << '\n';
ptr = p->ir->CreateBitCast(ptr, vd->llvmValue->getType(), "tmp");
}
// inside the actual parent function
else {
ptr = vd->llvmValue;
}
assert(ptr);
e->mem = LLVM_DtoGEPi(ptr,0,unsigned(vd->llvmNestedIndex),"tmp",p->scopebb());
*/
e->mem = LLVM_DtoNestedVariable(vd);
}
// normal local variable
else {
e->mem = vd->llvmValue;
if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration()) {
Logger::println("typeinfo varexp");
const llvm::Type* vartype = LLVM_DtoType(type);
if (tid->llvmValue->getType() != llvm::PointerType::get(vartype)) {
e->mem = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp");
}
else {
e->mem = tid->llvmValue;
}
Logger::cout() << "got:" << '\n' << *tid->llvmValue << "returned:" << '\n' << *e->mem << '\n';
}
else {
e->mem = vd->llvmValue;
}
}
e->vardecl = vd;
e->type = elem::VAR;
@@ -350,7 +349,7 @@ llvm::Constant* NullExp::toConstElem(IRState* p)
elem* StringExp::toElem(IRState* p)
{
Logger::print("StringExp::toElem: %s | \n", toChars(), type->toChars());
Logger::print("StringExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
Type* dtype = LLVM_DtoDType(type);
@@ -379,10 +378,9 @@ elem* StringExp::toElem(IRState* p)
if (dtype->ty == Tarray) {
llvm::Constant* clen = llvm::ConstantInt::get(LLVM_DtoSize_t(),len,false);
if (p->lvals.empty() || !p->toplval()) {
e->type = elem::SLICE;
e->arg = clen;
e->mem = arrptr;
return e;
llvm::Value* tmpmem = new llvm::AllocaInst(LLVM_DtoType(dtype),"tmp",p->topallocapoint());
LLVM_DtoSetArray(tmpmem, clen, arrptr);
e->mem = tmpmem;
}
else if (llvm::Value* arr = p->toplval()) {
if (llvm::isa<llvm::GlobalVariable>(arr)) {
@@ -1247,15 +1245,21 @@ elem* CastExp::toElem(IRState* p)
}
else if (totype->ty == Tarray) {
Logger::cout() << "to array" << '\n';
assert(fromtype->next->size() == totype->next->size());
const llvm::Type* ptrty = LLVM_DtoType(totype->next);
if (ptrty == llvm::Type::VoidTy)
ptrty = llvm::Type::Int8Ty;
ptrty = llvm::PointerType::get(ptrty);
const llvm::Type* ety = LLVM_DtoType(fromtype->next);
if (ety == llvm::Type::VoidTy)
ety = llvm::Type::Int8Ty;
if (u->type == elem::SLICE) {
e->mem = new llvm::BitCastInst(u->mem, ptrty, "tmp", p->scopebb());
e->arg = u->arg;
if (fromtype->next->size() == totype->next->size())
e->arg = u->arg;
else
e->arg = LLVM_DtoArrayCastLength(u->arg, ety, ptrty->getContainedType(0));
}
else {
llvm::Value* uval = u->getValue();
@@ -1264,6 +1268,7 @@ elem* CastExp::toElem(IRState* p)
assert(llvm::isa<llvm::PointerType>(uval->getType()));
const llvm::ArrayType* arrty = llvm::cast<llvm::ArrayType>(uval->getType()->getContainedType(0));
e->arg = llvm::ConstantInt::get(LLVM_DtoSize_t(), arrty->getNumElements(), false);
e->arg = LLVM_DtoArrayCastLength(e->arg, ety, ptrty->getContainedType(0));
e->mem = new llvm::BitCastInst(uval, ptrty, "tmp", p->scopebb());
}
else {
@@ -1271,6 +1276,7 @@ elem* CastExp::toElem(IRState* p)
llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false);
e->arg = LLVM_DtoGEP(uval,zero,zero,"tmp",p->scopebb());
e->arg = new llvm::LoadInst(e->arg, "tmp", p->scopebb());
e->arg = LLVM_DtoArrayCastLength(e->arg, ety, ptrty->getContainedType(0));
e->mem = LLVM_DtoGEP(uval,zero,one,"tmp",p->scopebb());
e->mem = new llvm::LoadInst(e->mem, "tmp", p->scopebb());
@@ -1318,6 +1324,13 @@ elem* SymOffExp::toElem(IRState* p)
if (VarDeclaration* vd = var->isVarDeclaration())
{
Logger::println("VarDeclaration");
if (!vd->llvmTouched && vd->isDataseg())
vd->toObjFile();
if (vd->isTypedefDeclaration()) {
e->istypeinfo = true;
}
assert(vd->llvmValue);
Type* t = LLVM_DtoDType(type);
Type* vdtype = LLVM_DtoDType(vd->type);
@@ -1634,6 +1647,9 @@ elem* SliceExp::toElem(IRState* p)
Logger::print("SliceExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
Type* t = LLVM_DtoDType(type);
assert(t->ty == Tarray);
elem* v = e1->toElem(p);
Type* e1type = LLVM_DtoDType(e1->type);
@@ -1722,6 +1738,16 @@ elem* SliceExp::toElem(IRState* p)
delete lo;
delete up;
/*
llvm::Value* tmpmem = new llvm::AllocaInst(LLVM_DtoType(t),"tmp",p->topallocapoint());
llvm::Value* ptr = LLVM_DtoGEPi(tmpmem,0,0,"tmp");
p->ir->CreateStore(e->arg, ptr);
ptr = LLVM_DtoGEPi(tmpmem,0,1,"tmp");
p->ir->CreateStore(e->mem, ptr);
e->arg = NULL;
e->mem = tmpmem;
*/
}
// full slice
else
@@ -1897,7 +1923,7 @@ elem* EqualExp::toElem(IRState* p)
}
else if (t->ty == Tarray)
{
assert(0 && "array comparison invokes the typeinfo runtime");
e->val = LLVM_DtoDynArrayCompare(op,l->mem,r->mem);
}
else
{

View File

@@ -161,7 +161,9 @@ const llvm::Type* LLVM_DtoType(Type* t)
}
// typedefs
// enum
case Ttypedef:
case Tenum:
{
Type* bt = t->toBasetype();
assert(bt);

View File

@@ -98,19 +98,19 @@ Module::genobjfile()
// run passes
// TODO
/*if (global.params.llvmLL) {
//assert(0);
std::ofstream os(llfile->name->toChars());
//llvm::WriteAssemblyToFile(ir.module, os);
ir.module->print(os);
}*/
// write bytecode
//if (global.params.llvmBC) {
{
Logger::println("Writing LLVM bitcode\n");
std::ofstream os(bcfile->name->toChars(), std::ios::binary);
llvm::WriteBitcodeToFile(ir.module, os);
//}
std::ofstream bos(bcfile->name->toChars(), std::ios::binary);
llvm::WriteBitcodeToFile(ir.module, bos);
}
// disassemble ?
if (global.params.disassemble) {
Logger::println("Writing LLVM asm to: %s\n", llfile->name->toChars());
std::ofstream aos(llfile->name->toChars());
ir.module->print(aos);
}
delete ir.module;
gIR = NULL;
@@ -295,7 +295,7 @@ void StructDeclaration::toObjFile()
gIR->structs.pop_back();
// generate typeinfo
type->getTypeInfo(NULL); // generate TypeInfo
//type->getTypeInfo(NULL);
}
/* ================================================================== */
@@ -407,8 +407,10 @@ void ClassDeclaration::toObjFile()
{
llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
std::string varname(mangle());
varname.append("__vtblZ");
std::string varname("_D");
varname.append(mangle());
varname.append("6__vtblZ");
std::string styname(mangle());
styname.append("__vtblTy");
@@ -441,8 +443,10 @@ void ClassDeclaration::toObjFile()
_init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
assert(_init);
std::string initname(mangle());
initname.append("__initZ");
std::string initname("_D");
initname.append(mangle());
initname.append("6__initZ");
//Logger::cout() << *_init << '\n';
llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, 0, initname, gIR->module);
ts->llvmInit = initvar;
@@ -499,7 +503,7 @@ void VarDeclaration::toObjFile()
bool _isconst = isConst();
llvm::GlobalValue::LinkageTypes _linkage;
if (parent->isFuncDeclaration())
if (parent && parent->isFuncDeclaration())
_linkage = llvm::GlobalValue::InternalLinkage;
else
_linkage = LLVM_DtoLinkage(protection, storage_class);
@@ -514,46 +518,51 @@ void VarDeclaration::toObjFile()
Logger::println("Creating global variable");
std::string _name(mangle());
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M);
llvmValue = gvar;
gIR->lvals.push_back(gvar);
_init = LLVM_DtoConstInitializer(t, init);
gIR->lvals.pop_back();
// if extern don't emit initializer
if (!(storage_class & STCextern))
{
gIR->lvals.push_back(gvar);
_init = LLVM_DtoConstInitializer(t, init);
gIR->lvals.pop_back();
//Logger::cout() << "initializer: " << *_init << '\n';
if (_type != _init->getType()) {
Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n";
// zero initalizer
if (_init->isNullValue())
_init = llvm::Constant::getNullValue(_type);
// pointer to global constant (struct.init)
else if (llvm::isa<llvm::GlobalVariable>(_init))
{
assert(_init->getType()->getContainedType(0) == _type);
llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init);
assert(t->ty == Tstruct);
TypeStruct* ts = (TypeStruct*)t;
assert(ts->sym->llvmInitZ);
_init = ts->sym->llvmInitZ;
}
// array single value init
else if (llvm::isa<llvm::ArrayType>(_type))
{
const llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(_type);
assert(_type->getContainedType(0) == _init->getType());
std::vector<llvm::Constant*> initvals;
initvals.resize(at->getNumElements(), _init);
_init = llvm::ConstantArray::get(at, initvals);
}
else {
Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
//assert(0);
//Logger::cout() << "initializer: " << *_init << '\n';
if (_type != _init->getType()) {
Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n";
// zero initalizer
if (_init->isNullValue())
_init = llvm::Constant::getNullValue(_type);
// pointer to global constant (struct.init)
else if (llvm::isa<llvm::GlobalVariable>(_init))
{
assert(_init->getType()->getContainedType(0) == _type);
llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init);
assert(t->ty == Tstruct);
TypeStruct* ts = (TypeStruct*)t;
assert(ts->sym->llvmInitZ);
_init = ts->sym->llvmInitZ;
}
// array single value init
else if (llvm::isa<llvm::ArrayType>(_type))
{
const llvm::ArrayType* at = llvm::cast<llvm::ArrayType>(_type);
assert(_type->getContainedType(0) == _init->getType());
std::vector<llvm::Constant*> initvals;
initvals.resize(at->getNumElements(), _init);
_init = llvm::ConstantArray::get(at, initvals);
}
else {
Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
//assert(0);
}
}
gvar->setInitializer(_init);
}
gvar->setInitializer(_init);
llvmDModule = gIR->dmodule;
//if (storage_class & STCprivate)
@@ -618,7 +627,8 @@ void TypedefDeclaration::toObjFile()
Logger::print("TypedefDeclaration::toObjFile(%d): %s\n", tdi++, toChars());
LOG_SCOPE;
// TODO
// generate typeinfo
type->getTypeInfo(NULL);
}
/* ================================================================== */
@@ -695,7 +705,7 @@ void FuncDeclaration::toObjFile()
// first make absolutely sure the type is up to date
f->llvmType = llvmValue->getType()->getContainedType(0);
Logger::cout() << "func type: " << *f->llvmType << '\n';
//Logger::cout() << "func type: " << *f->llvmType << '\n';
// this handling
if (f->llvmUsesThis) {
@@ -754,12 +764,15 @@ void FuncDeclaration::toObjFile()
// llvm requires all basic blocks to end with a TerminatorInst but DMD does not put a return statement
// in automatically, so we do it here.
if (!isMain()) {
if (gIR->scopebb()->empty() || !llvm::isa<llvm::TerminatorInst>(gIR->scopebb()->back())) {
if (!gIR->scopereturned()) {
// pass the previous block into this block
//new llvm::BranchInst(irs.end, irs.begin);
if (func->getReturnType() == llvm::Type::VoidTy) {
new llvm::ReturnInst(gIR->scopebb());
}
else {
new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), gIR->scopebb());
}
}
}
@@ -778,7 +791,17 @@ void FuncDeclaration::toObjFile()
// would be nice to figure out how to assert that this is correct
llvm::BasicBlock* lastbb = &func->getBasicBlockList().back();
if (lastbb->empty()) {
lastbb->eraseFromParent();
if (lastbb->getNumUses() == 0)
lastbb->eraseFromParent();
else {
new llvm::UnreachableInst(lastbb);
/*if (func->getReturnType() == llvm::Type::VoidTy) {
new llvm::ReturnInst(lastbb);
}
else {
new llvm::ReturnInst(llvm::UndefValue::get(func->getReturnType()), lastbb);
}*/
}
}
gIR->functions.pop_back();

View File

@@ -11,6 +11,8 @@
#include <cstdio>
#include <cassert>
#include "gen/llvm.h"
#include "mars.h"
#include "module.h"
#include "mtype.h"
@@ -25,347 +27,171 @@
#include "import.h"
#include "aggregate.h"
#include "gen/irstate.h"
#include "gen/logger.h"
#include "gen/runtime.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 = 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);
}
enum RET TypeFunction::retStyle()
{
return RETstack;
}
TypeInfoDeclaration *TypeDelegate::getTypeInfoDeclaration()
{
return new TypeInfoDelegateDeclaration(this);
}
TypeInfoDeclaration *TypeTuple::getTypeInfoDeclaration()
{
return new TypeInfoTupleDeclaration(this);
}
void TypeInfoDeclaration::toDt(dt_t **pdt)
{
}
void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
{
}
void TypeInfoStructDeclaration::toDt(dt_t **pdt)
{
}
void TypeInfoClassDeclaration::toDt(dt_t **pdt)
{
}
void TypeInfoDeclaration::toObjFile()
{
Logger::println("TypeInfoDeclaration::toObjFile()");
LOG_SCOPE;
Logger::println("type = '%s'", tinfo->toChars());
}
/* ========================================================================= */
/* These decide if there's an instance for them already in std.typeinfo,
@@ -384,7 +210,7 @@ int TypeBasic::builtinTypeInfo()
int TypeDArray::builtinTypeInfo()
{
return 0;
return next->isTypeBasic() != NULL;
}
/* ========================================================================= */
@@ -401,3 +227,511 @@ Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim)
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("Getting typeinfo var: %s", mangle());
llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangle());
assert(llvmValue);
Logger::cout() << "Got:" << '\n' << *llvmValue << '\n';
}
/* ========================================================================= */
void TypeInfoDeclaration::toDt(dt_t **pdt)
{
assert(0 && "TypeInfoDeclaration");
}
void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
{
assert(0 && "TypeInfoTypedefDeclaration");
}
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