comparison gen/functions.cpp @ 1024:9167d492cbc2

Abstracted more (most) ABI details out of the normal codegen.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 03 Mar 2009 02:51:21 +0100
parents e8c6dbcd33d1
children 45af482e3832
comparison
equal deleted inserted replaced
1023:ca191c141cec 1024:9167d492cbc2
20 #include "gen/todebug.h" 20 #include "gen/todebug.h"
21 #include "gen/classes.h" 21 #include "gen/classes.h"
22 #include "gen/dvalue.h" 22 #include "gen/dvalue.h"
23 #include "gen/abi.h" 23 #include "gen/abi.h"
24 24
25 #include <algorithm> 25 const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nesttype, bool ismain)
26 26 {
27 const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, const LLType* nesttype, bool ismain) 27 // sanity check
28 {
29 assert(type->ty == Tfunction); 28 assert(type->ty == Tfunction);
30 TypeFunction* f = (TypeFunction*)type; 29 TypeFunction* f = (TypeFunction*)type;
31 30
31 // already built ?
32 if (type->ir.type != NULL) { 32 if (type->ir.type != NULL) {
33 assert(f->fty != NULL);
33 return llvm::cast<llvm::FunctionType>(type->ir.type->get()); 34 return llvm::cast<llvm::FunctionType>(type->ir.type->get());
34 } 35 }
35 36
36 bool dVararg = false; 37 // create new ir funcTy
37 bool arrayVararg = false; 38 assert(f->fty == NULL);
38 if (f->linkage == LINKd) 39 f->fty = new IrFuncTy();
39 { 40
40 if (f->varargs == 1) 41 // llvm idx counter
41 dVararg = true; 42 size_t lidx = 0;
42 else if (f->varargs == 2) 43
43 arrayVararg = true; 44 // main needs a little special handling
44 }
45
46 // return value type
47 const LLType* rettype;
48 const LLType* actualRettype;
49 Type* rt = f->next;
50 bool retinptr = false;
51 bool usesthis = false;
52 bool usesnest = false;
53
54 // parameter types
55 std::vector<const LLType*> paramvec;
56
57 // special case main
58 if (ismain) 45 if (ismain)
59 { 46 {
60 rettype = LLType::Int32Ty; 47 f->fty->ret = new IrFuncTyArg(Type::tint32, false);
61 actualRettype = rettype; 48 }
62 if (Argument::dim(f->parameters) == 0) 49 // sane return value
63 {
64 const LLType* arrTy = DtoArrayType(LLType::Int8Ty);
65 const LLType* arrArrTy = DtoArrayType(arrTy);
66 paramvec.push_back(arrArrTy);
67 }
68 }
69 // default handling
70 else 50 else
71 { 51 {
72 assert(rt); 52 Type* rt = f->next;
73 if (f->linkage == LINKintrinsic) 53 unsigned a = 0;
74 { 54 // sret return
75 // Intrinsics don't care about ABI 55 if (gABI->returnInArg(f))
76 Logger::cout() << "Intrinsic returning " << rt->toChars() << '\n'; 56 {
77 actualRettype = rettype = DtoType(rt); 57 f->fty->arg_sret = new IrFuncTyArg(rt, true, llvm::Attribute::StructRet);
78 Logger::cout() << " (LLVM type: " << *rettype << ")\n"; 58 rt = Type::tvoid;
59 lidx++;
60 }
61 // sext/zext return
62 else if (unsigned se = DtoShouldExtend(rt))
63 {
64 a = se;
65 }
66 f->fty->ret = new IrFuncTyArg(rt, false, a);
67 }
68 lidx++;
69
70 // member functions
71 if (thistype)
72 {
73 bool toref = (thistype->toBasetype()->ty == Tstruct);
74 f->fty->arg_this = new IrFuncTyArg(thistype, toref);
75 lidx++;
76 }
77
78 // and nested functions
79 else if (nesttype)
80 {
81 f->fty->arg_nest = new IrFuncTyArg(nesttype, false);
82 lidx++;
83 }
84
85 // vararg functions are special too
86 if (f->varargs)
87 {
88 if (f->linkage == LINKd)
89 {
90 // d style with hidden args
91 // 2 (array) is handled by the frontend
92 if (f->varargs == 1)
93 {
94 // _arguments
95 f->fty->arg_arguments = new IrFuncTyArg(Type::typeinfo->type->arrayOf(), false);
96 lidx++;
97 // _argptr
98 f->fty->arg_argptr = new IrFuncTyArg(Type::tvoid->pointerTo(), false);
99 lidx++;
100 }
101 }
102 else if (f->linkage == LINKc)
103 {
104 f->fty->c_vararg = true;
79 } 105 }
80 else 106 else
81 { 107 {
82 if (gABI->returnInArg(f)) 108 type->error(0, "invalid linkage for variadic function");
83 { 109 fatal();
84 rettype = getPtrToType(DtoType(rt)); 110 }
85 actualRettype = LLType::VoidTy; 111 }
86 f->retInPtr = retinptr = true; 112
87 } 113 // if this _Dmain() doesn't have an argument, we force it to have one
88 else 114 int nargs = Argument::dim(f->parameters);
89 { 115
90 rettype = DtoType(rt); 116 if (ismain && nargs == 0)
91 // do abi specific transformations 117 {
92 actualRettype = gABI->getRetType(f, rettype); 118 Type* mainargs = Type::tchar->arrayOf()->arrayOf();
93 } 119 f->fty->args.push_back(new IrFuncTyArg(mainargs, false));
94 120 lidx++;
95 // FIXME: should probably be part of the abi 121 }
96 if (unsigned ea = DtoShouldExtend(rt)) 122 // add explicit parameters
97 { 123 else for (int i = 0; i < nargs; i++)
98 f->retAttrs |= ea; 124 {
99 } 125 // get argument
100 }
101 }
102
103 // build up parameter list
104 if (retinptr) {
105 //Logger::cout() << "returning through pointer parameter: " << *rettype << '\n';
106 paramvec.push_back(rettype);
107 }
108
109 // this/context param
110 if (thistype) {
111 paramvec.push_back(thistype);
112 usesthis = true;
113 }
114 else if (nesttype) {
115 paramvec.push_back(nesttype);
116 usesnest = true;
117 }
118
119 // dstyle vararg
120 if (dVararg) {
121 paramvec.push_back(DtoType(Type::typeinfo->type->arrayOf())); // _arguments
122 paramvec.push_back(getVoidPtrType()); // _argptr
123 }
124
125 // now that all implicit args are done, store the start of the real args
126 f->firstRealArg = paramvec.size();
127
128 // number of formal params
129 size_t n = Argument::dim(f->parameters);
130
131 #if X86_REVERSE_PARAMS
132 // on x86 we need to reverse the formal params in some cases to match the ABI
133 if (global.params.cpu == ARCHx86)
134 {
135 // more than one formal arg,
136 // extern(D) linkage
137 // not a D-style vararg
138 if (n > 1 && f->linkage == LINKd && !dVararg)
139 {
140 f->reverseParams = true;
141 }
142 }
143 #endif // X86_REVERSE_PARAMS
144
145
146 for (int i=0; i < n; ++i) {
147 Argument* arg = Argument::getNth(f->parameters, i); 126 Argument* arg = Argument::getNth(f->parameters, i);
148 // ensure scalar 127
149 Type* argT = arg->type->toBasetype(); 128 // reference semantics? ref, out and static arrays are
150 assert(argT); 129 bool byref = (arg->storageClass & (STCref|STCout)) || (arg->type->toBasetype()->ty == Tsarray);
151 130
152 bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout)); 131 Type* argtype = arg->type;
153 132 unsigned a = 0;
154 const LLType* at = DtoType(argT);
155 133
156 // handle lazy args 134 // handle lazy args
157 if (arg->storageClass & STClazy) 135 if (arg->storageClass & STClazy)
158 { 136 {
159 Logger::println("lazy param"); 137 Logger::println("lazy param");
160 TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd); 138 TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
161 TypeDelegate *ltd = new TypeDelegate(ltf); 139 TypeDelegate *ltd = new TypeDelegate(ltf);
162 at = DtoType(ltd); 140 argtype = ltd;
163 paramvec.push_back(at); 141 }
164 } 142 // byval
165 // opaque types need special handling 143 else if (gABI->passByVal(argtype))
166 else if (llvm::isa<llvm::OpaqueType>(at)) { 144 {
167 Logger::println("opaque param"); 145 if (!byref) a |= llvm::Attribute::ByVal;
168 assert(argT->ty == Tstruct || argT->ty == Tclass); 146 byref = true;
169 paramvec.push_back(getPtrToType(at)); 147 }
170 } 148 // sext/zext
171 // structs are passed as a reference, but by value 149 else if (!byref)
172 else if (argT->ty == Tstruct) { 150 {
173 Logger::println("struct param"); 151 a |= DtoShouldExtend(argtype);
174 if (!refOrOut) 152 }
175 arg->llvmAttrs |= llvm::Attribute::ByVal; 153
176 paramvec.push_back(getPtrToType(at)); 154 f->fty->args.push_back(new IrFuncTyArg(argtype, byref, a));
177 } 155 lidx++;
178 // static arrays are passed directly by reference 156 }
179 else if (argT->ty == Tsarray) 157
180 { 158 // let the abi rewrite the types as necesary
181 Logger::println("static array param"); 159 gABI->rewriteFunctionType(f);
182 at = getPtrToType(at); 160
183 paramvec.push_back(at); 161 // build the function type
184 } 162 std::vector<const LLType*> argtypes;
185 // firstclass ' ref/out ' parameter 163 argtypes.reserve(lidx);
186 else if (refOrOut) { 164
187 Logger::println("ref/out param"); 165 if (f->fty->arg_sret) argtypes.push_back(f->fty->arg_sret->ltype);
188 at = getPtrToType(at); 166 if (f->fty->arg_this) argtypes.push_back(f->fty->arg_this->ltype);
189 paramvec.push_back(at); 167 if (f->fty->arg_nest) argtypes.push_back(f->fty->arg_nest->ltype);
190 } 168 if (f->fty->arg_arguments) argtypes.push_back(f->fty->arg_arguments->ltype);
191 // firstclass ' in ' parameter 169 if (f->fty->arg_argptr) argtypes.push_back(f->fty->arg_argptr->ltype);
192 else { 170
193 Logger::println("in param"); 171 size_t beg = argtypes.size();
194 if (unsigned ea = DtoShouldExtend(argT)) 172 size_t nargs2 = f->fty->args.size();
195 arg->llvmAttrs |= ea; 173 for (size_t i = 0; i < nargs2; i++)
196 paramvec.push_back(at); 174 {
197 } 175 argtypes.push_back(f->fty->args[i]->ltype);
198 } 176 }
199 177
200 // reverse params? 178 // reverse params?
201 if (f->reverseParams) 179 if (f->fty->reverseParams && f->parameters->dim > 1)
202 { 180 {
203 std::reverse(paramvec.begin() + f->firstRealArg, paramvec.end()); 181 std::reverse(argtypes.begin() + beg, argtypes.end());
204 } 182 }
205 183
206 #if X86_PASS_IN_EAX 184 llvm::FunctionType* functype = llvm::FunctionType::get(f->fty->ret->ltype, argtypes, f->fty->c_vararg);
207 // pass first param in EAX if it fits, is not floating point and is not a 3 byte struct.
208 // ONLY extern(D) functions !
209 if ((n > 0 || usesthis || usesnest) && f->linkage == LINKd)
210 {
211 // FIXME: Only x86 right now ...
212 if (global.params.cpu == ARCHx86)
213 {
214 int n_inreg = f->reverseParams ? n - 1 : 0;
215 Argument* arg = Argument::getNth(f->parameters, n_inreg);
216
217 // if there is a implicit context parameter, pass it in EAX
218 if (usesthis || usesnest)
219 {
220 f->thisAttrs |= llvm::Attribute::InReg;
221 assert((!arg || (arg->llvmAttrs & llvm::Attribute::InReg) == 0) && "can't have two inreg args!");
222 }
223 // otherwise check the first formal parameter
224 else
225 {
226 Type* t = arg->type->toBasetype();
227
228 // 32bit ints, pointers, classes, static arrays, AAs, ref and out params,
229 // and structs with size <= 4 and != 3
230 // are candidate for being passed in EAX
231 if (
232 (arg->storageClass & (STCref|STCout))
233 ||
234 ((arg->storageClass & STCin) &&
235 ((t->isscalar() && !t->isfloating()) ||
236 t->ty == Tclass || t->ty == Tsarray || t->ty == Taarray ||
237 (t->ty == Tstruct && t->size() != 3)
238 ) && (t->size() <= PTRSIZE))
239 )
240 {
241 arg->llvmAttrs |= llvm::Attribute::InReg;
242 assert((f->thisAttrs & llvm::Attribute::InReg) == 0 && "can't have two inreg args!");
243
244 // structs need to go from {...}* byval to i8/i16/i32 inreg
245 if ((arg->storageClass & STCin) && t->ty == Tstruct)
246 {
247 int n_param = f->reverseParams ? f->firstRealArg + n - 1 - n_inreg : f->firstRealArg + n_inreg;
248 assert(isaPointer(paramvec[n_param]) && (arg->llvmAttrs & llvm::Attribute::ByVal)
249 && "struct parameter expected to be {...}* byval before inreg is applied");
250 f->structInregArg = paramvec[n_param]->getContainedType(0);
251 paramvec[n_param] = LLIntegerType::get(8*t->size());
252 arg->llvmAttrs &= ~llvm::Attribute::ByVal;
253 }
254 }
255 }
256 }
257 }
258 #endif // X86_PASS_IN_EAX
259
260 // construct function type
261 bool isvararg = !(dVararg || arrayVararg) && f->varargs;
262 llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
263
264 // done
265 f->retInPtr = retinptr;
266 f->usesThis = usesthis;
267 f->usesNest = usesnest;
268
269 f->ir.type = new llvm::PATypeHolder(functype); 185 f->ir.type = new llvm::PATypeHolder(functype);
270 186
271 return functype; 187 return functype;
272 } 188 }
273 189
281 } 197 }
282 198
283 TypeFunction* f = (TypeFunction*)fdecl->type; 199 TypeFunction* f = (TypeFunction*)fdecl->type;
284 const llvm::FunctionType* fty = 0; 200 const llvm::FunctionType* fty = 0;
285 201
202 // create new ir funcTy
203 assert(f->fty == NULL);
204 f->fty = new IrFuncTy();
205 f->fty->ret = new IrFuncTyArg(Type::tvoid, false);
206
207 f->fty->args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false));
208
286 if (fdecl->llvmInternal == LLVMva_start) 209 if (fdecl->llvmInternal == LLVMva_start)
287 fty = GET_INTRINSIC_DECL(vastart)->getFunctionType(); 210 fty = GET_INTRINSIC_DECL(vastart)->getFunctionType();
288 else if (fdecl->llvmInternal == LLVMva_copy) 211 else if (fdecl->llvmInternal == LLVMva_copy) {
289 fty = GET_INTRINSIC_DECL(vacopy)->getFunctionType(); 212 fty = GET_INTRINSIC_DECL(vacopy)->getFunctionType();
213 f->fty->args.push_back(new IrFuncTyArg(Type::tvoid->pointerTo(), false));
214 }
290 else if (fdecl->llvmInternal == LLVMva_end) 215 else if (fdecl->llvmInternal == LLVMva_end)
291 fty = GET_INTRINSIC_DECL(vaend)->getFunctionType(); 216 fty = GET_INTRINSIC_DECL(vaend)->getFunctionType();
292 assert(fty); 217 assert(fty);
293 218
294 f->ir.type = new llvm::PATypeHolder(fty); 219 f->ir.type = new llvm::PATypeHolder(fty);
305 230
306 // type has already been resolved 231 // type has already been resolved
307 if (fdecl->type->ir.type != 0) 232 if (fdecl->type->ir.type != 0)
308 return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get()); 233 return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get());
309 234
310 const LLType* thisty = 0; 235 Type *dthis=0, *dnest=0;
311 const LLType* nestty = 0;
312 236
313 if (fdecl->needThis()) { 237 if (fdecl->needThis()) {
314 if (AggregateDeclaration* ad = fdecl->isMember2()) { 238 if (AggregateDeclaration* ad = fdecl->isMember2()) {
315 Logger::println("isMember = this is: %s", ad->type->toChars()); 239 Logger::println("isMember = this is: %s", ad->type->toChars());
316 thisty = DtoType(ad->type); 240 dthis = ad->type;
241 const LLType* thisty = DtoType(dthis);
317 //Logger::cout() << "this llvm type: " << *thisty << '\n'; 242 //Logger::cout() << "this llvm type: " << *thisty << '\n';
318 if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->type->ir.type->get())) 243 if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->type->ir.type->get()))
319 thisty = getPtrToType(thisty); 244 thisty = getPtrToType(thisty);
320 } 245 }
321 else { 246 else {
322 Logger::println("chars: %s type: %s kind: %s", fdecl->toChars(), fdecl->type->toChars(), fdecl->kind()); 247 Logger::println("chars: %s type: %s kind: %s", fdecl->toChars(), fdecl->type->toChars(), fdecl->kind());
323 assert(0); 248 assert(0);
324 } 249 }
325 } 250 }
326 else if (fdecl->isNested()) { 251 else if (fdecl->isNested()) {
327 nestty = getPtrToType(LLType::Int8Ty); 252 dnest = Type::tvoid->pointerTo();
328 } 253 }
329 254
330 const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, nestty, fdecl->isMain()); 255 const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, dthis, dnest, fdecl->isMain());
331 256
332 return functype; 257 return functype;
333 } 258 }
334 259
335 ////////////////////////////////////////////////////////////////////////////////////////// 260 //////////////////////////////////////////////////////////////////////////////////////////
412 337
413 ////////////////////////////////////////////////////////////////////////////////////////// 338 //////////////////////////////////////////////////////////////////////////////////////////
414 339
415 static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclaration* fdecl) 340 static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclaration* fdecl)
416 { 341 {
417 int llidx = 0;
418 if (f->retInPtr) ++llidx;
419 if (f->usesThis) ++llidx;
420 else if (f->usesNest) ++llidx;
421 if (f->linkage == LINKd && f->varargs == 1)
422 llidx += 2;
423
424 int funcNumArgs = func->getArgumentList().size(); 342 int funcNumArgs = func->getArgumentList().size();
425 343
426 LLSmallVector<llvm::AttributeWithIndex, 9> attrs; 344 LLSmallVector<llvm::AttributeWithIndex, 9> attrs;
427 llvm::AttributeWithIndex PAWI; 345 llvm::AttributeWithIndex PAWI;
428 346
429 // set return value attrs if any 347 int idx = 0;
430 if (f->retAttrs) 348
431 { 349 // handle implicit args
432 PAWI.Index = 0; 350 #define ADD_PA(X) \
433 PAWI.Attrs = f->retAttrs; 351 if (f->fty->X) { \
434 attrs.push_back(PAWI); 352 if (f->fty->X->attrs) { \
435 } 353 PAWI.Index = idx; \
436 354 PAWI.Attrs = f->fty->X->attrs; \
437 // set sret param 355 attrs.push_back(PAWI); \
438 if (f->retInPtr) 356 } \
439 { 357 idx++; \
440 PAWI.Index = 1; 358 }
441 PAWI.Attrs = llvm::Attribute::StructRet; 359
442 attrs.push_back(PAWI); 360 ADD_PA(ret)
443 } 361 ADD_PA(arg_sret)
444 362 ADD_PA(arg_this)
445 // set this/nest param attrs 363 ADD_PA(arg_nest)
446 if (f->thisAttrs) 364 ADD_PA(arg_arguments)
447 { 365 ADD_PA(arg_argptr)
448 PAWI.Index = f->retInPtr ? 2 : 1; 366
449 PAWI.Attrs = f->thisAttrs; 367 #undef ADD_PA
450 attrs.push_back(PAWI);
451 }
452 368
453 // set attrs on the rest of the arguments 369 // set attrs on the rest of the arguments
454 size_t n = Argument::dim(f->parameters); 370 size_t n = Argument::dim(f->parameters);
455 assert(funcNumArgs >= n); // main might mismatch, for the implicit char[][] arg
456
457 LLSmallVector<unsigned,8> attrptr(n, 0); 371 LLSmallVector<unsigned,8> attrptr(n, 0);
458 372
459 for (size_t k = 0; k < n; ++k) 373 for (size_t k = 0; k < n; ++k)
460 { 374 {
461 Argument* fnarg = Argument::getNth(f->parameters, k); 375 Argument* fnarg = Argument::getNth(f->parameters, k);
462 assert(fnarg); 376 assert(fnarg);
463 377
464 attrptr[k] = fnarg->llvmAttrs; 378 attrptr[k] = f->fty->args[k]->attrs;
465 } 379 }
466 380
467 // reverse params? 381 // reverse params?
468 if (f->reverseParams) 382 if (f->fty->reverseParams)
469 { 383 {
470 std::reverse(attrptr.begin(), attrptr.end()); 384 std::reverse(attrptr.begin(), attrptr.end());
471 } 385 }
472 386
473 // build rest of attrs list 387 // build rest of attrs list
474 for (int i = 0; i < n; i++) 388 for (int i = 0; i < n; i++)
475 { 389 {
476 if (attrptr[i]) 390 if (attrptr[i])
477 { 391 {
478 PAWI.Index = llidx+i+1; 392 PAWI.Index = idx+i;
479 PAWI.Attrs = attrptr[i]; 393 PAWI.Attrs = attrptr[i];
480 attrs.push_back(PAWI); 394 attrs.push_back(PAWI);
481 } 395 }
482 } 396 }
483 397
573 if (!declareOnly) 487 if (!declareOnly)
574 { 488 {
575 // name parameters 489 // name parameters
576 llvm::Function::arg_iterator iarg = func->arg_begin(); 490 llvm::Function::arg_iterator iarg = func->arg_begin();
577 491
578 if (f->retInPtr) { 492 if (f->fty->arg_sret) {
579 iarg->setName(".sret_arg"); 493 iarg->setName(".sret_arg");
580 fdecl->ir.irFunc->retArg = iarg; 494 fdecl->ir.irFunc->retArg = iarg;
581 ++iarg; 495 ++iarg;
582 } 496 }
583 497
584 if (f->usesThis) { 498 if (f->fty->arg_this) {
585 iarg->setName(".this_arg"); 499 iarg->setName(".this_arg");
586 fdecl->ir.irFunc->thisArg = iarg; 500 fdecl->ir.irFunc->thisArg = iarg;
587 assert(fdecl->ir.irFunc->thisArg); 501 assert(fdecl->ir.irFunc->thisArg);
588 ++iarg; 502 ++iarg;
589 } 503 }
590 else if (f->usesNest) { 504 else if (f->fty->arg_nest) {
591 iarg->setName(".nest_arg"); 505 iarg->setName(".nest_arg");
592 fdecl->ir.irFunc->nestArg = iarg; 506 fdecl->ir.irFunc->nestArg = iarg;
593 assert(fdecl->ir.irFunc->nestArg); 507 assert(fdecl->ir.irFunc->nestArg);
594 ++iarg; 508 ++iarg;
595 } 509 }
596 510
597 if (f->linkage == LINKd && f->varargs == 1) { 511 if (f->fty->arg_argptr) {
598 iarg->setName("._arguments"); 512 iarg->setName("._arguments");
599 fdecl->ir.irFunc->_arguments = iarg; 513 fdecl->ir.irFunc->_arguments = iarg;
600 ++iarg; 514 ++iarg;
601 iarg->setName("._argptr"); 515 iarg->setName("._argptr");
602 fdecl->ir.irFunc->_argptr = iarg; 516 fdecl->ir.irFunc->_argptr = iarg;
608 for (; iarg != func->arg_end(); ++iarg) 522 for (; iarg != func->arg_end(); ++iarg)
609 { 523 {
610 if (fdecl->parameters && fdecl->parameters->dim > k) 524 if (fdecl->parameters && fdecl->parameters->dim > k)
611 { 525 {
612 Dsymbol* argsym; 526 Dsymbol* argsym;
613 if (f->reverseParams) 527 if (f->fty->reverseParams)
614 argsym = (Dsymbol*)fdecl->parameters->data[fdecl->parameters->dim-k-1]; 528 argsym = (Dsymbol*)fdecl->parameters->data[fdecl->parameters->dim-k-1];
615 else 529 else
616 argsym = (Dsymbol*)fdecl->parameters->data[k]; 530 argsym = (Dsymbol*)fdecl->parameters->data[k];
617 531
618 VarDeclaration* argvd = argsym->isVarDeclaration(); 532 VarDeclaration* argvd = argsym->isVarDeclaration();
646 Logger::cout() << "func decl: " << *func << '\n'; 560 Logger::cout() << "func decl: " << *func << '\n';
647 } 561 }
648 562
649 ////////////////////////////////////////////////////////////////////////////////////////// 563 //////////////////////////////////////////////////////////////////////////////////////////
650 564
565 // FIXME: this isn't too pretty!
566
651 void DtoDefineFunction(FuncDeclaration* fd) 567 void DtoDefineFunction(FuncDeclaration* fd)
652 { 568 {
653 if (fd->ir.defined) return; 569 if (fd->ir.defined) return;
654 fd->ir.defined = true; 570 fd->ir.defined = true;
655 571
725 LLFunction* hack = GET_INTRINSIC_DECL(eh_unwind_init); 641 LLFunction* hack = GET_INTRINSIC_DECL(eh_unwind_init);
726 gIR->ir->CreateCall(hack, ""); 642 gIR->ir->CreateCall(hack, "");
727 } 643 }
728 644
729 // give the 'this' argument storage and debug info 645 // give the 'this' argument storage and debug info
730 if (f->usesThis) 646 if (f->fty->arg_this)
731 { 647 {
732 LLValue* thisvar = irfunction->thisArg; 648 LLValue* thisvar = irfunction->thisArg;
733 assert(thisvar); 649 assert(thisvar);
734 650
735 LLValue* thismem = DtoAlloca(thisvar->getType(), "this"); 651 LLValue* thismem = DtoAlloca(thisvar->getType(), "this");
755 671
756 // give arguments storage 672 // give arguments storage
757 // and debug info 673 // and debug info
758 if (fd->parameters) 674 if (fd->parameters)
759 { 675 {
760 size_t n = fd->parameters->dim; 676 size_t n = f->fty->args.size();
677 assert(n == fd->parameters->dim);
761 for (int i=0; i < n; ++i) 678 for (int i=0; i < n; ++i)
762 { 679 {
763 Dsymbol* argsym = (Dsymbol*)fd->parameters->data[i]; 680 Dsymbol* argsym = (Dsymbol*)fd->parameters->data[i];
764 VarDeclaration* vd = argsym->isVarDeclaration(); 681 VarDeclaration* vd = argsym->isVarDeclaration();
765 assert(vd); 682 assert(vd);
766 683
767 IrLocal* irloc = vd->ir.irLocal; 684 IrLocal* irloc = vd->ir.irLocal;
768 assert(irloc); 685 assert(irloc);
769 686
770 // if it's inreg struct arg, allocate storage 687 // let the abi transform the argument back first
771 if (f->structInregArg && i == (f->reverseParams ? n - 1 : 0)) 688 LLValue* argvalue = f->fty->getParam(vd->type, i, irloc->value);
772 {
773 int n_param = f->reverseParams ? f->firstRealArg + n - 1 - i : f->firstRealArg + i;
774 const LLType* paramty = functype->getParamType(n_param);
775 assert(!f->usesNest && !f->usesThis &&
776 llvm::isa<LLIntegerType>(paramty) && isaStruct(f->structInregArg)
777 && "Preconditions for inreg struct arg not met!");
778
779 LLValue* mem = DtoAlloca(f->structInregArg, "inregstructarg");
780
781 DtoStore(irloc->value, DtoBitCast(mem, getPtrToType(paramty)));
782 irloc->value = mem;
783 }
784 689
785 #if DMDV2 690 #if DMDV2
786 if (vd->nestedrefs.dim) 691 if (vd->nestedrefs.dim)
787 #else 692 #else
788 if (vd->nestedref) 693 if (vd->nestedref)
792 } 697 }
793 698
794 bool refout = vd->storage_class & (STCref | STCout); 699 bool refout = vd->storage_class & (STCref | STCout);
795 bool lazy = vd->storage_class & STClazy; 700 bool lazy = vd->storage_class & STClazy;
796 701
797 if (!refout && (!DtoIsPassedByRef(vd->type) || lazy)) 702 if (!refout && (!f->fty->args[i]->byref || lazy))
798 { 703 {
799 LLValue* a = irloc->value; 704 LLValue* a = argvalue;
800 LLValue* v = DtoAlloca(a->getType(), vd->ident->toChars()); 705 LLValue* v = DtoAlloca(a->getType(), vd->ident->toChars());
801 DtoStore(a,v); 706 DtoStore(a,v);
802 irloc->value = v; 707 irloc->value = v;
803 } 708 }
804 if (global.params.symdebug && !(isaArgument(irloc->value) && !isaArgument(irloc->value)->hasByValAttr()) && !refout) 709 if (global.params.symdebug && !(isaArgument(irloc->value) && !isaArgument(irloc->value)->hasByValAttr()) && !refout)