Implemented first class delegates. closes #101

This commit is contained in:
Tomas Lindquist Olsen
2008-10-22 21:50:08 +02:00
parent 42ae090eaf
commit a52f0330d0
8 changed files with 151 additions and 125 deletions

View File

@@ -123,15 +123,24 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
const LLType* at = DtoType(argT);
// handle lazy args
if (arg->storageClass & STClazy)
{
Logger::println("lazy param");
TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
TypeDelegate *ltd = new TypeDelegate(ltf);
at = DtoType(ltd);
paramvec.push_back(at);
}
// opaque types need special handling
if (llvm::isa<llvm::OpaqueType>(at)) {
else if (llvm::isa<llvm::OpaqueType>(at)) {
Logger::println("opaque param");
assert(argT->ty == Tstruct || argT->ty == Tclass);
paramvec.push_back(getPtrToType(at));
}
// structs and delegates are passed as a reference, but by value
else if (argT->ty == Tstruct || argT->ty == Tdelegate) {
Logger::println("struct/sarray param");
// structs are passed as a reference, but by value
else if (argT->ty == Tstruct) {
Logger::println("struct param");
if (!refOrOut)
arg->llvmAttrs |= llvm::Attribute::ByVal;
paramvec.push_back(getPtrToType(at));
@@ -156,23 +165,6 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
arg->llvmAttrs |= ea;
paramvec.push_back(at);
}
// handle lazy args
if (arg->storageClass & STClazy)
{
if (Logger::enabled())
Logger::cout() << "for lazy got: " << *paramvec.back() << '\n';
TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
TypeDelegate *ltd = new TypeDelegate(ltf);
at = getPtrToType(DtoType(ltd));
if (Logger::enabled())
Logger::cout() << "lazy updated to: " << *at << '\n';
paramvec.back() = at;
// lazy doesn't need byval as the delegate is not visible to the user
}
}
// construct function type
@@ -652,13 +644,14 @@ void DtoDefineFunc(FuncDeclaration* fd)
IrLocal* irloc = vd->ir.irLocal;
assert(irloc);
bool refoutlazy = vd->storage_class & (STCref | STCout | STClazy);
bool refout = vd->storage_class & (STCref | STCout);
bool lazy = vd->storage_class & STClazy;
if (refoutlazy)
if (refout)
{
continue;
}
else if (DtoIsPassedByRef(vd->type))
else if (!lazy && DtoIsPassedByRef(vd->type))
{
LLValue* vdirval = irloc->value;
if (global.params.symdebug && !(isaArgument(vdirval) && !isaArgument(vdirval)->hasByValAttr()))
@@ -875,6 +868,13 @@ DValue* DtoArgument(Argument* fnarg, Expression* argexp)
else
arg = new DImValue(argexp->type, arg->getRVal());
}
// lazy arg
else if (fnarg && (fnarg->storageClass & STClazy))
{
assert(argexp->type->toBasetype()->ty == Tdelegate);
assert(!arg->isLVal());
return arg;
}
// byval arg, but expr has no storage yet
else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isNull()))
{