[svn r15] * Fixed a bunch problems with virtual calls. Seems I did some rather poor testing.

* Now 50/51 tests compile.
* Added a simple runalltests.d scripts that should be run with 'gdmd -run runalltests.d' - LLVMDC will not compile it yet.
This commit is contained in:
Tomas Lindquist Olsen
2007-10-02 05:10:18 +02:00
parent e1a8afb028
commit 4eab68b36c
19 changed files with 205 additions and 71 deletions

View File

@@ -509,6 +509,8 @@ struct FuncDeclaration : Declaration
int cvMember(unsigned char *p);
FuncDeclaration *isFuncDeclaration() { return this; }
bool llvmQueued;
};
struct FuncAliasDeclaration : FuncDeclaration

View File

@@ -73,6 +73,7 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC s
nrvo_can = 1;
nrvo_var = NULL;
shidden = NULL;
llvmQueued = false;
}
Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s)

View File

@@ -349,7 +349,7 @@ int main(int argc, char *argv[])
global.params.Dversion = 1;
else if (strcmp(p + 1, "w") == 0)
global.params.warnings = 1;
else if (strcmp(p + 1, "O") == 0)
else if (p[1] == 'O')
{
global.params.optimize = 1;
if (p[2] != 0) {

View File

@@ -114,7 +114,7 @@ Type::Type(TY ty, Type *next)
this->arrayof = NULL;
this->vtinfo = NULL;
this->ctype = NULL;
this->llvmType = 0;
this->llvmType = NULL;
}
Type *Type::syntaxCopy()

View File

@@ -250,7 +250,7 @@ struct Type : Object
virtual type *toCParamtype();
virtual Symbol *toSymbol();
llvm::Type* llvmType;
const llvm::Type* llvmType;
// For eliminating dynamic_cast
virtual TypeBasic *isTypeBasic();

View File

@@ -19,7 +19,7 @@
//////////////////////////////////////////////////////////////////////////////////////////
llvm::StructType* LLVM_DtoArrayType(Type* t)
const llvm::StructType* LLVM_DtoArrayType(Type* t)
{
assert(t->next);
const llvm::Type* at = LLVM_DtoType(t->next);
@@ -51,7 +51,7 @@ llvm::StructType* LLVM_DtoArrayType(Type* t)
//////////////////////////////////////////////////////////////////////////////////////////
llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t)
const llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t)
{
if (t->llvmType)
return llvm::cast<llvm::ArrayType>(t->llvmType);
@@ -63,7 +63,7 @@ llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t)
TypeSArray* tsa = (TypeSArray*)t;
assert(tsa->dim->type->isintegral());
llvm::ArrayType* arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger());
const llvm::ArrayType* arrty = llvm::ArrayType::get(at,tsa->dim->toUInteger());
tsa->llvmType = arrty;
return arrty;
@@ -298,7 +298,7 @@ llvm::Constant* LLVM_DtoArrayInitializer(ArrayInitializer* arrinit)
inits[i] = v;
}
llvm::ArrayType* arrty = LLVM_DtoStaticArrayType(t);
const llvm::ArrayType* arrty = LLVM_DtoStaticArrayType(t);
return llvm::ConstantArray::get(arrty, inits);
}

View File

@@ -1,9 +1,9 @@
#ifndef LLVMC_GEN_ARRAYS_H
#define LLVMC_GEN_ARRAYS_H
llvm::StructType* LLVM_DtoArrayType(Type* t);
const llvm::StructType* LLVM_DtoArrayType(Type* t);
llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t);
const llvm::ArrayType* LLVM_DtoStaticArrayType(Type* t);
llvm::Value* LLVM_DtoNullArray(llvm::Value* v);

View File

@@ -17,6 +17,7 @@ elem::elem()
type = NONE;
inplace = false;
field = false;
callconv = (unsigned)-1;
vardecl = 0;
funcdecl = 0;

View File

@@ -31,6 +31,7 @@ public:
int type;
bool inplace;
bool field;
unsigned callconv;
VarDeclaration* vardecl;
FuncDeclaration* funcdecl;

View File

@@ -954,6 +954,8 @@ elem* CallExp::toElem(IRState* p)
// set calling convention
if ((fn->funcdecl && (fn->funcdecl->llvmInternal != LLVMintrinsic)) || delegateCall)
call->setCallingConv(LLVM_DtoCallingConv(dlink));
else if (fn->callconv != (unsigned)-1)
call->setCallingConv(fn->callconv);
delete fn;
return e;
@@ -1253,7 +1255,7 @@ elem* DotVarExp::toElem(IRState* p)
funcval = LLVM_DtoGEP(funcval, zero, vtblidx, "tmp", p->scopebb());
funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb());
assert(funcval->getType() == fdecl->llvmValue->getType());
//funcval = new llvm::BitCastInst(funcval, fdecl->llvmValue->getType(), "tmp", p->scopebb());
e->callconv = LLVM_DtoCallingConv(fdecl->linkage);
}
e->val = funcval;
e->type = elem::VAL;

View File

@@ -159,7 +159,7 @@ const llvm::Type* LLVM_DtoType(Type* t)
//////////////////////////////////////////////////////////////////////////////////////////
llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam)
const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam)
{
TypeFunction* f = (TypeFunction*)t;
@@ -203,7 +203,7 @@ llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam)
//////////////////////////////////////////////////////////////////////////////////////////
llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
{
TypeFunction* f = (TypeFunction*)fdecl->type;
assert(f != 0);
@@ -309,7 +309,7 @@ llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl)
//////////////////////////////////////////////////////////////////////////////////////////
llvm::StructType* LLVM_DtoDelegateType(Type* t)
const llvm::StructType* LLVM_DtoDelegateType(Type* t)
{
const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty);
const llvm::Type* func = LLVM_DtoFunctionType(t->next, i8ptr);
@@ -323,7 +323,7 @@ llvm::StructType* LLVM_DtoDelegateType(Type* t)
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Type* LLVM_DtoStructType(Type* t)
const llvm::Type* LLVM_DtoStructType(Type* t)
{
assert(0);
std::vector<const llvm::Type*> types;
@@ -763,26 +763,40 @@ void LLVM_DtoCallClassDtors(TypeClass* tc, llvm::Value* instance)
void LLVM_DtoInitClass(TypeClass* tc, llvm::Value* dst)
{
assert(tc->llvmInit);
assert(dst->getType() == tc->llvmInit->getType());
assert(gIR);
assert(tc->llvmType);
uint64_t n = gTargetData->getTypeSize(tc->llvmType);
llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
uint64_t size_t_size = gTargetData->getTypeSize(LLVM_DtoSize_t());
uint64_t n = gTargetData->getTypeSize(tc->llvmType) - size_t_size;
llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
llvm::Value* srcarr = new llvm::BitCastInst(tc->llvmInit,arrty,"tmp",gIR->scopebb());
// set vtable field
llvm::Value* vtblvar = LLVM_DtoGEPi(dst,0,0,"tmp",gIR->scopebb());
assert(tc->sym->llvmVtbl);
new llvm::StoreInst(tc->sym->llvmVtbl, vtblvar, gIR->scopebb());
llvm::Function* fn = LLVM_DeclareMemCpy32();
std::vector<llvm::Value*> llargs;
llargs.resize(4);
llargs[0] = dstarr;
llargs[1] = srcarr;
llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
// copy the static initializer
if (n > 0) {
assert(tc->llvmInit);
assert(dst->getType() == tc->llvmInit->getType());
new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty);
llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
dstarr = LLVM_DtoGEPi(dstarr,size_t_size,"tmp",gIR->scopebb());
llvm::Value* srcarr = new llvm::BitCastInst(tc->llvmInit,arrty,"tmp",gIR->scopebb());
srcarr = LLVM_DtoGEPi(srcarr,size_t_size,"tmp",gIR->scopebb());
llvm::Function* fn = LLVM_DeclareMemCpy32();
std::vector<llvm::Value*> llargs;
llargs.resize(4);
llargs[0] = dstarr;
llargs[1] = srcarr;
llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
}
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -825,14 +839,19 @@ llvm::Constant* LLVM_DtoInitializer(Type* type, Initializer* init)
return _init;
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb)
{
std::vector<llvm::Value*> v(2);
v[0] = i0;
v[1] = i1;
Logger::cout() << "DtoGEP: " << *ptr << '\n';
return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb);
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb)
{
size_t n = src.size();
@@ -847,9 +866,32 @@ llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, const std::vector<unsigned>& src, con
return new llvm::GetElementPtrInst(ptr, dst.begin(), dst.end(), var, bb);
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* LLVM_DtoGEPi(llvm::Value* ptr, unsigned i, const std::string& var, llvm::BasicBlock* bb)
{
return new llvm::GetElementPtrInst(ptr, llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false), var, bb);
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Value* LLVM_DtoGEPi(llvm::Value* ptr, unsigned i0, unsigned i1, const std::string& var, llvm::BasicBlock* bb)
{
std::vector<llvm::Value*> v(2);
v[0] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i0, false);
v[1] = llvm::ConstantInt::get(llvm::Type::Int32Ty, i1, false);
return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb);
}
//////////////////////////////////////////////////////////////////////////////////////////
llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl)
{
TypeFunction* f = (TypeFunction*)fdecl->type;
assert(f != 0);
if (fdecl->llvmValue != 0) {
assert(llvm::isa<llvm::Function>(fdecl->llvmValue));
return llvm::cast<llvm::Function>(fdecl->llvmValue);
}
@@ -863,9 +905,7 @@ llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl)
}
// construct function
TypeFunction* f = (TypeFunction*)fdecl->type;
assert(f != 0);
llvm::FunctionType* functype = (f->llvmType == 0) ? LLVM_DtoFunctionType(fdecl) : llvm::cast<llvm::FunctionType>(f->llvmType);
const llvm::FunctionType* functype = (f->llvmType == 0) ? LLVM_DtoFunctionType(fdecl) : llvm::cast<llvm::FunctionType>(f->llvmType);
// mangled name
char* mangled_name = (fdecl->llvmInternal == LLVMintrinsic) ? fdecl->llvmInternal1 : fdecl->mangle();
@@ -881,6 +921,7 @@ llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl)
fdecl->llvmValue = func;
f->llvmType = functype;
assert(llvm::isa<llvm::FunctionType>(f->llvmType));
if (fdecl->isMain()) {
gIR->mainFunc = func;

View File

@@ -4,16 +4,16 @@ struct StructInitializer;
const llvm::Type* LLVM_DtoType(Type* t);
llvm::Type* LLVM_DtoStructType(Type* t);
const llvm::Type* LLVM_DtoStructType(Type* t);
llvm::Value* LLVM_DtoStructZeroInit(TypeStruct* t, llvm::Value* v);
llvm::Value* LLVM_DtoStructCopy(TypeStruct* t, llvm::Value* dst, llvm::Value* src);
llvm::Constant* LLVM_DtoStructInitializer(StructInitializer* si);
llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam = 0);
llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl);
const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam = 0);
const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl);
llvm::Function* LLVM_DtoDeclareFunction(FuncDeclaration* fdecl);
llvm::StructType* LLVM_DtoDelegateType(Type* t);
const llvm::StructType* LLVM_DtoDelegateType(Type* t);
llvm::Value* LLVM_DtoNullDelegate(llvm::Value* v);
llvm::Value* LLVM_DtoDelegateCopy(llvm::Value* dst, llvm::Value* src);
@@ -39,5 +39,7 @@ llvm::Function* LLVM_DeclareMemCpy64();
llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, llvm::Value* i0, llvm::Value* i1, const std::string& var, llvm::BasicBlock* bb);
llvm::Value* LLVM_DtoGEP(llvm::Value* ptr, const std::vector<unsigned>& src, const std::string& var, llvm::BasicBlock* bb);
llvm::Value* LLVM_DtoGEPi(llvm::Value* ptr, unsigned i0, const std::string& var, llvm::BasicBlock* bb);
llvm::Value* LLVM_DtoGEPi(llvm::Value* ptr, unsigned i0, unsigned i1, const std::string& var, llvm::BasicBlock* bb);
#include "enums.h"

View File

@@ -80,18 +80,21 @@ Module::genobjfile()
delete gTargetData;
gTargetData = 0;
// emit the llvm main function if necessary
if (ir.emitMain) {
LLVM_DtoMain();
}
// verify the llvm
std::string verifyErr;
Logger::println("Verifying module...");
if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr))
{
error("%s", verifyErr.c_str());
fatal();
}
// emit the llvm main function if necessary
if (ir.emitMain) {
LLVM_DtoMain();
}
else
Logger::println("Verification passed!");
// run passes
// TODO
@@ -386,6 +389,7 @@ void ClassDeclaration::toObjFile()
if (FuncDeclaration* fd = dsym->isFuncDeclaration()) {
fd->toObjFile();
assert(fd->llvmValue);
llvm::Constant* c = llvm::cast<llvm::Constant>(fd->llvmValue);
sinits.push_back(c);
sinits_ty.push_back(c->getType());
@@ -437,17 +441,11 @@ void ClassDeclaration::toObjFile()
assert(svtblVar != 0);
gIR->topstruct().inits[0] = svtblVar;
//assert(tk == gIR->topstruct().size());
#ifndef LLVMD_NO_LOGGER
Logger::cout() << *structtype << '\n';
//for (size_t k=0; k<gIR->topstruct().inits.size(); ++k)
// Logger::cout() << *gIR->topstruct().inits[k] << '\n';
#endif
_init = llvm::ConstantStruct::get(structtype,gIR->topstruct().inits);
assert(_init);
std::string initname(mangle());
initname.append("__initZ");
Logger::cout() << *_init << '\n';
//Logger::cout() << *_init << '\n';
llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, 0, initname, gIR->module);
ts->llvmInit = initvar;
if (define_vtable) {
@@ -616,27 +614,33 @@ void FuncDeclaration::toObjFile()
llvm::Function* func = LLVM_DtoDeclareFunction(this);
if (!gIR->queueClassMethods.empty() && gIR->queueClassMethods.back()) {
Logger::println("queueing %s", toChars());
assert(!gIR->classmethods.empty());
gIR->classmethods.back().push_back(this);
if (!llvmQueued) {
Logger::println("queueing %s", toChars());
assert(!gIR->classmethods.empty());
gIR->classmethods.back().push_back(this);
llvmQueued = true;
}
return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete
}
TypeFunction* f = (TypeFunction*)type;
llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(f->llvmType);
assert(f->llvmType);
const llvm::FunctionType* functype = llvm::cast<llvm::FunctionType>(llvmValue->getType()->getContainedType(0));
// only members of the current module maybe be defined
if (getModule() == gIR->dmodule)
{
llvmDModule = gIR->dmodule;
bool allow_fbody = true;
// handle static constructor / destructor
if (isStaticCtorDeclaration() || isStaticDtorDeclaration()) {
const llvm::ArrayType* sctor_type = llvm::ArrayType::get(llvm::PointerType::get(functype),1);
//Logger::cout() << "static ctor type: " << *sctor_type << '\n';
llvm::Constant* sctor_func = llvm::cast<llvm::Constant>(llvmValue);
//Logger::cout() << "static ctor func: " << *sctor_func << '\n';
llvm::Constant* sctor_init = 0;
if (llvmInternal == LLVMnull)
{
@@ -648,10 +652,9 @@ void FuncDeclaration::toObjFile()
{
sctor_init = llvm::ConstantArray::get(sctor_type,&sctor_func,1);
}
//Logger::cout() << "static ctor init: " << *sctor_init << '\n';
// output the llvm.global_ctors array
const char* varname = isStaticCtorDeclaration() ? "_d_module_ctor_array" : "_d_module_dtor_array";
llvm::GlobalVariable* sctor_arr = new llvm::GlobalVariable(sctor_type, false, llvm::GlobalValue::AppendingLinkage, sctor_init, varname, gIR->module);
@@ -660,6 +663,9 @@ void FuncDeclaration::toObjFile()
// function definition
if (allow_fbody && fbody != 0)
{
// first make absolutely sure the type is up to date
f->llvmType = llvmValue->getType()->getContainedType(0);
if (isMain())
gIR->emitMain = true;
@@ -672,10 +678,10 @@ void FuncDeclaration::toObjFile()
//assert(gIR->scopes.empty());
gIR->scopes.push_back(irs);
// create alloca point
f->llvmAllocaPoint = new llvm::BitCastInst(llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false),llvm::Type::Int32Ty,"alloca point",gIR->scopebb());
// output function body
fbody->toIR(gIR);
@@ -686,7 +692,7 @@ void FuncDeclaration::toObjFile()
//new llvm::BranchInst(irs.end, irs.begin);
new llvm::ReturnInst(gIR->scopebb());
}
// erase alloca point
f->llvmAllocaPoint->eraseFromParent();
f->llvmAllocaPoint = 0;
@@ -710,8 +716,4 @@ void FuncDeclaration::toObjFile()
}
}
}
llvmDModule = gIR->dmodule;
Logger::println("FuncDeclaration done\n");
}

Binary file not shown.

View File

@@ -29,10 +29,10 @@ pragma(LLVM_internal, "intrinsic", "llvm.pcmarker")
pragma(LLVM_internal, "intrinsic", "llvm.prefetch")
void llvm_prefetch(void* ptr, uint rw, uint locality);
*/
pragma(LLVM_internal, "intrinsic", "llvm.readcyclecounter")
ulong llvm_readcyclecounter();
*/
ulong readcyclecounter();
// standard C intrinsics
pragma(LLVM_internal, "intrinsic", "llvm.memcpy.i32")

33
runalltests.d Normal file
View File

@@ -0,0 +1,33 @@
module runalltests;
import std.file;
import std.path;
import std.process;
import std.stdio;
int main(string[] args) {
string[] good;
string[] bad;
auto contents = listdir("test", "*.d");
foreach(c; contents) {
if (system("./tester.sh "~getName(c)~" ll") != 0) {
bad ~= c;
}
else {
good ~= c;
}
}
int ret = 0;
if (bad.length > 0) {
writefln(bad.length, '/', contents.length, " tests failed:");
foreach(b; bad) {
writefln(" ",b);
}
ret = 1;
}
writefln(good.length, '/', contents.length, " tests passed");
return ret;
}

View File

@@ -4,12 +4,34 @@ class C
{
void f()
{
printf("hello world\n");
printf("world\n");
}
}
class D : C
{
void f()
{
printf("moon\n");
}
}
extern(C)
{
void srand(uint seed);
int rand();
}
import llvm.intrinsic;
void main()
{
scope c = new C;
C c;
srand(readcyclecounter());
if (rand() % 2)
c = new C;
else
c = new D;
c.f();
}

21
test/classes7.d Normal file
View File

@@ -0,0 +1,21 @@
module classes7;
class C
{
int i=0;
void f()
{
i=42;
}
void g()
{
f();
}
}
void main()
{
scope c = new C;
c.g();
assert(c.i == 43);
}

View File

@@ -6,24 +6,30 @@ if [ -z $1 ]; then
fi
if [ "$2" = "ll" ]; then
make &&
llvmdc $1 -Itest -odtest -c &&
llvm-dis -f $1.bc &&
cat $1.ll
exit $?
elif [ "$2" = "llopt" ]; then
llvmdc $1 -Itest -odtest -c &&
opt -f -o=$1.bc -std-compile-opts $1.bc &&
llvm-dis -f $1.bc &&
cat $1.ll
exit $?
elif [ "$2" = "run" ]; then
make &&
llvmdc $1 -Itest -odtest -of$1 &&
$1
exit $?
elif [ "$2" = "c" ]; then
make &&
llvmdc $1 -Itest -odtest -c
exit $?
elif [ "$2" = "gdb" ]; then
make &&
gdb --args llvmdc $1 -Itest -odtest '-c'
exit $?
elif [ "$2" = "gdbrun" ]; then
llvmdc $1 -Itest -odtest '-c' &&
gdb $1
exit $?
else
echo "bad command or filename"
fi