Mercurial > projects > ldc
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); |