comparison gen/functions.cpp @ 719:7261ff0f95ff

Implemented first class delegates. closes #101
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Wed, 22 Oct 2008 21:50:08 +0200
parents 30b42a283c8e
children e177ae483f8e
comparison
equal deleted inserted replaced
718:72ee105be27b 719:7261ff0f95ff
121 121
122 bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout)); 122 bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout));
123 123
124 const LLType* at = DtoType(argT); 124 const LLType* at = DtoType(argT);
125 125
126 // handle lazy args
127 if (arg->storageClass & STClazy)
128 {
129 Logger::println("lazy param");
130 TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
131 TypeDelegate *ltd = new TypeDelegate(ltf);
132 at = DtoType(ltd);
133 paramvec.push_back(at);
134 }
126 // opaque types need special handling 135 // opaque types need special handling
127 if (llvm::isa<llvm::OpaqueType>(at)) { 136 else if (llvm::isa<llvm::OpaqueType>(at)) {
128 Logger::println("opaque param"); 137 Logger::println("opaque param");
129 assert(argT->ty == Tstruct || argT->ty == Tclass); 138 assert(argT->ty == Tstruct || argT->ty == Tclass);
130 paramvec.push_back(getPtrToType(at)); 139 paramvec.push_back(getPtrToType(at));
131 } 140 }
132 // structs and delegates are passed as a reference, but by value 141 // structs are passed as a reference, but by value
133 else if (argT->ty == Tstruct || argT->ty == Tdelegate) { 142 else if (argT->ty == Tstruct) {
134 Logger::println("struct/sarray param"); 143 Logger::println("struct param");
135 if (!refOrOut) 144 if (!refOrOut)
136 arg->llvmAttrs |= llvm::Attribute::ByVal; 145 arg->llvmAttrs |= llvm::Attribute::ByVal;
137 paramvec.push_back(getPtrToType(at)); 146 paramvec.push_back(getPtrToType(at));
138 } 147 }
139 // static arrays are passed directly by reference 148 // static arrays are passed directly by reference
153 else { 162 else {
154 Logger::println("in param"); 163 Logger::println("in param");
155 if (unsigned ea = DtoShouldExtend(argT)) 164 if (unsigned ea = DtoShouldExtend(argT))
156 arg->llvmAttrs |= ea; 165 arg->llvmAttrs |= ea;
157 paramvec.push_back(at); 166 paramvec.push_back(at);
158 }
159
160 // handle lazy args
161 if (arg->storageClass & STClazy)
162 {
163 if (Logger::enabled())
164 Logger::cout() << "for lazy got: " << *paramvec.back() << '\n';
165
166 TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
167 TypeDelegate *ltd = new TypeDelegate(ltf);
168 at = getPtrToType(DtoType(ltd));
169
170 if (Logger::enabled())
171 Logger::cout() << "lazy updated to: " << *at << '\n';
172
173 paramvec.back() = at;
174 // lazy doesn't need byval as the delegate is not visible to the user
175 } 167 }
176 } 168 }
177 169
178 // construct function type 170 // construct function type
179 bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs; 171 bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs;
650 fd->nestedVars.insert(vd); 642 fd->nestedVars.insert(vd);
651 643
652 IrLocal* irloc = vd->ir.irLocal; 644 IrLocal* irloc = vd->ir.irLocal;
653 assert(irloc); 645 assert(irloc);
654 646
655 bool refoutlazy = vd->storage_class & (STCref | STCout | STClazy); 647 bool refout = vd->storage_class & (STCref | STCout);
656 648 bool lazy = vd->storage_class & STClazy;
657 if (refoutlazy) 649
650 if (refout)
658 { 651 {
659 continue; 652 continue;
660 } 653 }
661 else if (DtoIsPassedByRef(vd->type)) 654 else if (!lazy && DtoIsPassedByRef(vd->type))
662 { 655 {
663 LLValue* vdirval = irloc->value; 656 LLValue* vdirval = irloc->value;
664 if (global.params.symdebug && !(isaArgument(vdirval) && !isaArgument(vdirval)->hasByValAttr())) 657 if (global.params.symdebug && !(isaArgument(vdirval) && !isaArgument(vdirval)->hasByValAttr()))
665 DtoDwarfLocalVariable(vdirval, vd); 658 DtoDwarfLocalVariable(vdirval, vd);
666 continue; 659 continue;
873 if (arg->isVar() || arg->isLRValue()) 866 if (arg->isVar() || arg->isLRValue())
874 arg = new DImValue(argexp->type, arg->getLVal()); 867 arg = new DImValue(argexp->type, arg->getLVal());
875 else 868 else
876 arg = new DImValue(argexp->type, arg->getRVal()); 869 arg = new DImValue(argexp->type, arg->getRVal());
877 } 870 }
871 // lazy arg
872 else if (fnarg && (fnarg->storageClass & STClazy))
873 {
874 assert(argexp->type->toBasetype()->ty == Tdelegate);
875 assert(!arg->isLVal());
876 return arg;
877 }
878 // byval arg, but expr has no storage yet 878 // byval arg, but expr has no storage yet
879 else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isNull())) 879 else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isNull()))
880 { 880 {
881 LLValue* alloc = DtoAlloca(DtoType(argexp->type), ".tmp_arg"); 881 LLValue* alloc = DtoAlloca(DtoType(argexp->type), ".tmp_arg");
882 DVarValue* vv = new DVarValue(argexp->type, alloc); 882 DVarValue* vv = new DVarValue(argexp->type, alloc);