Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

root/gen/abi-x86-64.cpp

Revision 1571:8d086d552909, 26.0 kB (checked in by Benjamin Kramer <benny.kra@gmail.com>, 3 years ago)

IntegerType? is now contextifed.

Requires llvm >= 78969. resistor says this will be the last context API change :)

Line 
1 /* TargetABI implementation for x86-64.
2  * Written for LDC by Frits van Bommel in 2009.
3  *
4  * extern(D) follows no particular external ABI, but tries to be smart about
5  * passing structs and returning them. It should probably be reviewed if the
6  * way LLVM implements fastcc on this platform ever changes.
7  * (Specifically, the number of return registers of various types is hardcoded)
8  *
9  *
10  * extern(C) implements the C calling convention for x86-64, as found in
11  * http://www.x86-64.org/documentation/abi-0.99.pdf
12  *
13  * Note:
14  *   Where a discrepancy was found between llvm-gcc and the ABI documentation,
15  *   llvm-gcc behavior was used for compatibility (after it was verified that
16  *   regular gcc has the same behavior).
17  *
18  * LLVM gets it right for most types, but complex numbers and structs need some
19  * help. To make sure it gets those right we essentially bitcast small structs
20  * to a type to which LLVM assigns the appropriate registers, and pass that
21  * instead. Structs that are required to be passed in memory are explicitly
22  * marked with the ByVal attribute to ensure no part of them ends up in
23  * registers when only a subset of the desired registers are available.
24  *
25  * We don't perform the same transformation for D-specific types that contain
26  * multiple parts, such as dynamic arrays and delegates. They're passed as if
27  * the parts were passed as separate parameters. This helps make things like
28  * printf("%.*s", o.toString()) work as expected; if we didn't do this that
29  * wouldn't work if there were 4 other integer/pointer arguments before the
30  * toString() call because the string got bumped to memory with one integer
31  * register still free. Keeping it untransformed puts the length in a register
32  * and the pointer in memory, as printf expects it.
33  */
34
35 #include "mtype.h"
36 #include "declaration.h"
37 #include "aggregate.h"
38
39 #include "gen/irstate.h"
40 #include "gen/llvm.h"
41 #include "gen/tollvm.h"
42 #include "gen/logger.h"
43 #include "gen/dvalue.h"
44 #include "gen/llvmhelpers.h"
45 #include "gen/abi.h"
46 #include "gen/abi-x86-64.h"
47 #include "gen/abi-generic.h"
48 #include "ir/irfunction.h"
49
50 #include <cassert>
51 #include <map>
52 #include <string>
53 #include <utility>
54
55 // Implementation details for extern(C)
56 namespace {
57     /**
58      * This function helps filter out things that look like structs to C,
59      * but should be passed to C in separate arguments anyway.
60      *
61      * (e.g. dynamic arrays are passed as separate length and ptr. This
62      * is both less work and makes printf("%.*s", o.toString()) work)
63      */
64     inline bool keepUnchanged(Type* t) {
65         switch (t->ty) {
66             case Tarray:    // dynamic array
67             case Taarray:   // assoc array
68             case Tdelegate:
69                 return true;
70            
71             default:
72                 return false;
73         }
74     }
75    
76     enum ArgClass {
77         Integer, Sse, SseUp, X87, X87Up, ComplexX87, NoClass, Memory
78     };
79    
80     struct Classification {
81         bool isMemory;
82         ArgClass classes[2];
83        
84         Classification() : isMemory(false) {
85             classes[0] = NoClass;
86             classes[1] = NoClass;
87         }
88        
89         void addField(unsigned offset, ArgClass cl) {
90             if (isMemory)
91                 return;
92            
93             // Note that we don't need to bother checking if it crosses 8 bytes.
94             // We don't get here with unaligned fields, and anything that can be
95             // big enough to cross 8 bytes (cdoubles, reals, structs and arrays)
96             // is special-cased in classifyType()
97             int idx = (offset < 8 ? 0 : 1);
98            
99             ArgClass nw = merge(classes[idx], cl);
100             if (nw != classes[idx]) {
101                 classes[idx] = nw;
102                
103                 if (nw == Memory) {
104                     classes[1-idx] = Memory;
105                     isMemory = true;
106                 }
107             }
108         }
109        
110     private:
111         ArgClass merge(ArgClass accum, ArgClass cl) {
112             if (accum == cl)
113                 return accum;
114             if (accum == NoClass)
115                 return cl;
116             if (cl == NoClass)
117                 return accum;
118             if (accum == Memory || cl == Memory)
119                 return Memory;
120             if (accum == Integer || cl == Integer)
121                 return Integer;
122             if (accum == X87 || accum == X87Up || accum == ComplexX87 ||
123                 cl == X87 || cl == X87Up || cl == ComplexX87)
124                 return Memory;
125             return Sse;
126         }
127     };
128    
129     void classifyType(Classification& accum, Type* ty, d_uns64 offset) {
130         if (Logger::enabled())
131             Logger::cout() << "Classifying " << ty->toChars() << " @ " << offset << '\n';
132        
133         ty = ty->toBasetype();
134        
135         if (ty->isintegral() || ty->ty == Tpointer) {
136             accum.addField(offset, Integer);
137         } else if (ty->ty == Tfloat80 || ty->ty == Timaginary80) {
138             accum.addField(offset, X87);
139             accum.addField(offset+8, X87Up);
140         } else if (ty->ty == Tcomplex80) {
141             accum.addField(offset, ComplexX87);
142             // make sure other half knows about it too:
143             accum.addField(offset+16, ComplexX87);
144         } else if (ty->ty == Tcomplex64) {
145             accum.addField(offset, Sse);
146             accum.addField(offset+8, Sse);
147         } else if (ty->ty == Tcomplex32) {
148             accum.addField(offset, Sse);
149             accum.addField(offset+4, Sse);
150         } else if (ty->isfloating()) {
151             accum.addField(offset, Sse);
152         } else if (ty->size() > 16 || hasUnalignedFields(ty)) {
153             // This isn't creal, yet is > 16 bytes, so pass in memory.
154             // Must be after creal case but before arrays and structs,
155             // the other types that can get bigger than 16 bytes
156             accum.addField(offset, Memory);
157         } else if (ty->ty == Tsarray) {
158             Type* eltType = ty->nextOf();
159             d_uns64 eltsize = eltType->size();
160             if (eltsize > 0) {
161                 d_uns64 dim = ty->size() / eltsize;
162                 assert(dim <= 16
163                         && "Array of non-empty type <= 16 bytes but > 16 elements?");
164                 for (d_uns64 i = 0; i < dim; i++) {
165                     classifyType(accum, eltType, offset);
166                     offset += eltsize;
167                 }
168             }
169         } else if (ty->ty == Tstruct) {
170             Array* fields = &((TypeStruct*) ty)->sym->fields;
171             for (size_t i = 0; i < fields->dim; i++) {
172                 VarDeclaration* field = (VarDeclaration*) fields->data[i];
173                 classifyType(accum, field->type, offset + field->offset);
174             }
175         } else {
176             if (Logger::enabled())
177                 Logger::cout() << "x86-64 ABI: Implicitly handled type: "
178                                << ty->toChars() << '\n';
179             // arrays, delegates, etc. (pointer-sized fields, <= 16 bytes)
180             assert(offset == 0 || offset == 8
181                     && "must be aligned and doesn't fit otherwise");
182             assert(ty->size() % 8 == 0 && "Not a multiple of pointer size?");
183            
184             accum.addField(offset, Integer);
185             if (ty->size() > 8)
186                 accum.addField(offset+8, Integer);
187         }
188     }
189    
190     Classification classify(Type* ty) {
191         typedef std::map<Type*, Classification> ClassMap;
192         static ClassMap cache;
193        
194         ClassMap::iterator it = cache.find(ty);
195         if (it != cache.end()) {
196             return it->second;
197         } else {
198             Classification cl;
199             classifyType(cl, ty, 0);
200             cache[ty] = cl;
201             return cl;
202         }
203     }
204    
205     /// Returns the type to pass as, or null if no transformation is needed.
206     LLType* getAbiType(Type* ty) {
207         ty = ty->toBasetype();
208        
209         // First, check if there's any need of a transformation:
210        
211         if (keepUnchanged(ty))
212             return 0;
213        
214         if (ty->ty != Tcomplex32 && ty->ty != Tstruct)
215             return 0; // Nothing to do,
216        
217         Classification cl = classify(ty);
218         assert(!cl.isMemory);
219        
220         if (cl.classes[0] == NoClass) {
221             assert(cl.classes[1] == NoClass && "Non-empty struct with empty first half?");
222             return 0; // Empty structs should also be handled correctly by LLVM
223         }
224        
225         // Okay, we may need to transform. Figure out a canonical type:
226        
227         std::vector<const LLType*> parts;
228        
229         unsigned size = ty->size();
230        
231         switch (cl.classes[0]) {
232             case Integer: {
233                 unsigned bits = (size >= 8 ? 64 : (size * 8));
234                 parts.push_back(LLIntegerType::get(gIR->context(), bits));
235                 break;
236             }
237            
238             case Sse:
239                 parts.push_back(size <= 4 ? LLType::getFloatTy(gIR->context()) : LLType::getDoubleTy(gIR->context()));
240                 break;
241            
242             case X87:
243                 assert(cl.classes[1] == X87Up && "Upper half of real not X87Up?");
244                 /// The type only contains a single real/ireal field,
245                 /// so just use that type.
246                 return const_cast<LLType*>(LLType::getX86_FP80Ty(gIR->context()));
247            
248             default:
249                 assert(0 && "Unanticipated argument class");
250         }
251        
252         switch(cl.classes[1]) {
253             case NoClass:
254                 assert(parts.size() == 1);
255                 // No need to use a single-element struct type.
256                 // Just use the element type instead.
257                 return const_cast<LLType*>(parts[0]);
258                 break;
259            
260             case Integer: {
261                 assert(size > 8);
262                 unsigned bits = (size - 8) * 8;
263                 parts.push_back(LLIntegerType::get(gIR->context(), bits));
264                 break;
265             }
266             case Sse:
267                 parts.push_back(size <= 12 ? LLType::getFloatTy(gIR->context()) : LLType::getDoubleTy(gIR->context()));
268                 break;
269            
270             case X87Up:
271                 if(cl.classes[0] == X87) {
272                     // This won't happen: it was short-circuited while
273                     // processing the first half.
274                 } else {                   
275                     // I can't find this anywhere in the ABI documentation,
276                     // but this is what gcc does (both regular and llvm-gcc).
277                     // (This triggers for types like union { real r; byte b; })
278                     parts.push_back(LLType::getDoubleTy(gIR->context()));
279                 }
280                 break;
281            
282             default:
283                 assert(0 && "Unanticipated argument class for second half");
284         }
285         return LLStructType::get(gIR->context(), parts);
286     }
287 }
288
289
290 // Implementation details for extern(D)
291 namespace x86_64_D_cc {
292     struct DRegCount {
293         unsigned ints;
294         unsigned sse;
295         unsigned x87;
296        
297         DRegCount(unsigned ints_, unsigned sse_, unsigned x87_)
298         : ints(ints_), sse(sse_), x87(x87_) {}
299     };
300    
301     // Count the number of registers needed for a simple type.
302     // (Not a struct or static array)
303     DRegCount regsNeededForSimpleType(Type* t) {
304         DRegCount r(0, 0, 0);
305         switch(t->ty) {
306             case Tstruct:
307             case Tsarray:
308                 assert(0 && "Not a simple type!");
309                 // Return huge numbers if assertions are disabled, so it'll always get
310                 // bumped to memory.
311                 r.ints = r.sse = r.x87 = (unsigned)-1;
312                 break;
313            
314             // Floats, doubles and such are passed in SSE registers
315             case Tfloat32:
316             case Tfloat64:
317             case Timaginary32:
318             case Timaginary64:
319                 r.sse = 1;
320                 break;
321            
322             case Tcomplex32:
323             case Tcomplex64:
324                 r.sse = 2;
325                 break;
326            
327             // Reals, ireals and creals are passed in x87 registers
328             case Tfloat80:
329             case Timaginary80:
330                 r.x87 = 1;
331                 break;
332            
333             case Tcomplex80:
334                 r.x87 = 2;
335                 break;
336            
337             // Anything else is passed in one or two integer registers,
338             // depending on its size.
339             default: {
340                 int needed = (t->size() + 7) / 8;
341                 assert(needed <= 2);
342                 r.ints = needed;
343                 break;
344             }
345         }
346         return r;
347     }
348    
349     // Returns true if it's possible (and a good idea) to pass the struct in the
350     // specified number of registers.
351     // (May return false if it's a bad idea to pass the type in registers for
352     // reasons other than it not fitting)
353     // Note that if true is returned, 'left' is also modified to contain the
354     // number of registers left. This property is used in the recursive case.
355     // If false is returned, 'left' is garbage.
356     bool shouldPassStructInRegs(TypeStruct* t, DRegCount& left) {
357         // If it has unaligned fields, there's probably a reason for it,
358         // so keep it in memory.
359         if (hasUnalignedFields(t))
360             return false;
361        
362         Array* fields = &t->sym->fields;
363         d_uns64 nextbyte = 0;
364         for (d_uns64 i = 0; i < fields->dim; i++) {
365             VarDeclaration* field = (VarDeclaration*) fields->data[i];
366            
367             // This depends on ascending order of field offsets in structs
368             // without overlapping fields.
369             if (field->offset < nextbyte) {
370                 // Don't return unions (or structs containing them) in registers.
371                 return false;
372             }
373             nextbyte = field->offset + field->type->size();
374            
375             switch (field->type->ty) {
376                 case Tstruct:
377                     if (!shouldPassStructInRegs((TypeStruct*) field->type, left))
378                         return false;
379                     break;
380                
381                 case Tsarray:
382                     // Don't return static arrays in registers
383                     // (indexing registers doesn't work well)
384                     return false;
385                
386                 default: {
387                     DRegCount needed = regsNeededForSimpleType(field->type);
388                     if (needed.ints > left.ints || needed.sse > left.sse || needed.x87 > left.x87)
389                         return false;
390                     left.ints -= needed.ints;
391                     left.sse -= needed.sse;
392                     left.x87 -= needed.x87;
393                     break;
394                 }
395             }
396         }
397         return true;
398     }
399    
400     // Returns true if the struct fits in return registers in the x86-64 fastcc
401     // calling convention.
402     bool retStructInRegs(TypeStruct* st) {
403         // 'fastcc' allows returns in up to two registers of each kind:
404         DRegCount state(2, 2, 2);
405         return shouldPassStructInRegs(st, state);
406     }
407    
408     // Heuristic for determining whether to pass a struct type directly or
409     // bump it to memory.
410     bool passStructTypeDirectly(TypeStruct* st) {
411         // If the type fits in a reasonable number of registers,
412         // pass it directly.
413         // This does not necessarily mean it will actually be passed in
414         // registers. For example, x87 registers are never actually used for
415         // parameters.
416         DRegCount state(2, 2, 2);
417         return shouldPassStructInRegs(st, state);
418        
419         // This doesn't work well: Since the register count can differ depending
420         // on backend options, there's no way to be exact anyway.
421         /*
422         // Regular fastcc:      6 int, 8 sse, 0 x87
423         // fastcc + tailcall:   5 int, 8 sse, 0 x87
424         RegCount state(5, 8, 0);
425         */
426     }
427 }
428
429 ////////////////////////////////////////////////////////////////////////////////
430 ////////////////////////////////////////////////////////////////////////////////
431 ////////////////////////////////////////////////////////////////////////////////
432 ////////////////////////////////////////////////////////////////////////////////
433
434
435 /// Just store to memory and it's readable as the other type.
436 struct X86_64_C_struct_rewrite : ABIRewrite {
437     // Get struct from ABI-mangled representation
438     LLValue* get(Type* dty, DValue* v)
439     {
440         LLValue* lval;
441         if (v->isLVal()) {
442             lval = v->getLVal();
443         } else {
444             // No memory location, create one.
445             LLValue* rval = v->getRVal();
446             lval = DtoRawAlloca(rval->getType(), 0);
447             DtoStore(rval, lval);
448         }
449        
450         const LLType* pTy = getPtrToType(DtoType(dty));
451         return DtoLoad(DtoBitCast(lval, pTy), "get-result");
452     }
453    
454     // Get struct from ABI-mangled representation, and store in the provided location.
455     void getL(Type* dty, DValue* v, llvm::Value* lval) {
456         LLValue* rval = v->getRVal();
457         const LLType* pTy = getPtrToType(rval->getType());
458         DtoStore(rval, DtoBitCast(lval, pTy));
459     }
460    
461     // Turn a struct into an ABI-mangled representation
462     LLValue* put(Type* dty, DValue* v)
463     {
464         LLValue* lval;
465         if (v->isLVal()) {
466             lval = v->getLVal();
467         } else {
468             // No memory location, create one.
469             LLValue* rval = v->getRVal();
470             lval = DtoRawAlloca(rval->getType(), 0);
471             DtoStore(rval, lval);
472         }
473        
474         LLType* abiTy = getAbiType(dty);
475         assert(abiTy && "Why are we rewriting a non-rewritten type?");
476        
477         const LLType* pTy = getPtrToType(abiTy);
478         return DtoLoad(DtoBitCast(lval, pTy), "put-result");
479     }
480    
481     /// should return the transformed type for this rewrite
482     const LLType* type(Type* dty, const LLType* t)
483     {
484         return getAbiType(dty);
485     }
486 };
487
488
489 struct RegCount {
490     unsigned char int_regs, sse_regs;
491 };
492
493
494 struct X86_64TargetABI : TargetABI {
495     X86_64_C_struct_rewrite struct_rewrite;
496     RemoveStructPadding remove_padding;
497    
498     void newFunctionType(TypeFunction* tf) {
499         funcTypeStack.push_back(FuncTypeData(tf->linkage));
500     }
501    
502     bool returnInArg(TypeFunction* tf);
503    
504     bool passByVal(Type* t);
505    
506     void rewriteFunctionType(TypeFunction* tf);
507    
508     void doneWithFunctionType() {
509         funcTypeStack.pop_back();
510     }
511    
512 private:
513     struct FuncTypeData {
514         LINK linkage;       // Linkage of the function type currently under construction
515         RegCount state;     // bookkeeping for extern(C) parameter registers
516        
517         FuncTypeData(LINK linkage_)
518         : linkage(linkage_)
519         {
520             state.int_regs = 6;
521             state.sse_regs = 8;
522         }
523     };
524     std::vector<FuncTypeData> funcTypeStack;
525    
526     LINK linkage() {
527         assert(funcTypeStack.size() != 0);
528         return funcTypeStack.back().linkage;
529     }
530    
531     RegCount& state() {
532         assert(funcTypeStack.size() != 0);
533         return funcTypeStack.back().state;
534     }
535    
536     void fixup_D(IrFuncTyArg& arg);
537     void fixup(IrFuncTyArg& arg);
538 };
539
540
541 // The public getter for abi.cpp
542 TargetABI* getX86_64TargetABI() {
543     return new X86_64TargetABI;
544 }
545
546
547 bool X86_64TargetABI::returnInArg(TypeFunction* tf) {
548     assert(linkage() == tf->linkage);
549     Type* rt = tf->next->toBasetype();
550    
551     if (tf->linkage == LINKd) {
552         assert(rt->ty != Tsarray && "Update calling convention for static array returns");
553        
554         // All non-structs can be returned in registers.
555         if (rt->ty != Tstruct)
556             return false;
557        
558         // Try to figure out whether the struct fits in return registers
559         // and whether it's a good idea to put it there.
560         return !x86_64_D_cc::retStructInRegs((TypeStruct*) rt);
561     } else {
562         if (rt == Type::tvoid || keepUnchanged(rt))
563             return false;
564        
565         Classification cl = classify(rt);
566         if (cl.isMemory) {
567             assert(state().int_regs > 0
568                 && "No int registers available when determining sret-ness?");
569             // An sret parameter takes an integer register.
570             state().int_regs--;
571             return true;
572         }
573         return false;
574     }
575 }
576
577 bool X86_64TargetABI::passByVal(Type* t) {
578     t = t->toBasetype();
579     if (linkage() == LINKd) {
580         if (t->ty != Tstruct)
581             return false;
582        
583         // Try to be smart about which structs are passed in memory.
584         return !x86_64_D_cc::passStructTypeDirectly((TypeStruct*) t);
585     } else {
586         // This implements the C calling convention for x86-64.
587         // It might not be correct for other calling conventions.
588         Classification cl = classify(t);
589         if (cl.isMemory)
590             return true;
591        
592         // Figure out how many registers we want for this arg:
593         RegCount wanted = { 0, 0 };
594         for (int i = 0 ; i < 2; i++) {
595             if (cl.classes[i] == Integer)
596                 wanted.int_regs++;
597             else if (cl.classes[i] == Sse)
598                 wanted.sse_regs++;
599         }
600        
601         // See if they're available:
602         RegCount& state = this->state();
603         if (wanted.int_regs <= state.int_regs && wanted.sse_regs <= state.sse_regs) {
604             state.int_regs -= wanted.int_regs;
605             state.sse_regs -= wanted.sse_regs;
606         } else {
607             if (keepUnchanged(t)) {
608                 // Not enough registers available, but this is passed as if it's
609                 // multiple arguments. Just use the registers there are,
610                 // automatically spilling the rest to memory.
611                 if (wanted.int_regs > state.int_regs)
612                     state.int_regs = 0;
613                 else
614                     state.int_regs -= wanted.int_regs;
615                
616                 if (wanted.sse_regs > state.sse_regs)
617                     state.sse_regs = 0;
618                 else
619                     state.sse_regs -= wanted.sse_regs;
620             } else if (t->iscomplex() || t->ty == Tstruct) {
621                 // Spill entirely to memory, even if some of the registers are
622                 // available.
623                
624                 // FIXME: Don't do this if *none* of the wanted registers are available,
625                 //        (i.e. only when absolutely necessary for abi-compliance)
626                 //        so it gets alloca'd by the callee and -scalarrepl can
627                 //        more easily break it up?
628                 // Note: this won't be necessary if the following LLVM bug gets fixed:
629                 //       http://llvm.org/bugs/show_bug.cgi?id=3741
630                 return true;
631             } else {
632                 assert(t == Type::tfloat80 || t == Type::timaginary80 || t->size() <= 8
633                     && "What other big types are there?"); // other than static arrays...
634                 // In any case, they shouldn't be represented as structs in LLVM:
635                 assert(!isaStruct(DtoType(t)));
636             }
637         }
638         // Everything else that's passed in memory is handled by LLVM.
639         return false;
640     }
641 }
642
643 // Helper function for rewriteFunctionType.
644 // Structs passed or returned in registers are passed here
645 // to get their padding removed (if necessary).
646 void X86_64TargetABI::fixup_D(IrFuncTyArg& arg) {
647     assert(arg.type->ty == Tstruct);
648     LLType* abiTy = DtoUnpaddedStructType(arg.type);
649    
650     if (abiTy && abiTy != arg.ltype) {
651         arg.ltype = abiTy;
652         arg.rewrite = &remove_padding;
653     }
654 }
655
656 // Helper function for rewriteFunctionType.
657 // Return type and parameters are passed here (unless they're already in memory)
658 // to get the rewrite applied (if necessary).
659 void X86_64TargetABI::fixup(IrFuncTyArg& arg) {
660     LLType* abiTy = getAbiType(arg.type);
661    
662     if (abiTy && abiTy != arg.ltype) {
663         assert(arg.type == Type::tcomplex32 || arg.type->ty == Tstruct);
664         arg.ltype = abiTy;
665         arg.rewrite = &struct_rewrite;
666     }
667 }
668
669 void X86_64TargetABI::rewriteFunctionType(TypeFunction* tf) {
670     IrFuncTy& fty = tf->fty;
671    
672     if (tf->linkage == LINKd) {
673         if (!fty.arg_sret) {
674             Type* rt = fty.ret->type->toBasetype();
675             if (rt->ty == Tstruct)  {
676                 Logger::println("x86-64 D ABI: Transforming return type");
677                 fixup_D(*fty.ret);
678             }
679         }
680        
681         if (fty.arg_this) {
682             fty.arg_this->attrs |= llvm::Attribute::Nest;
683         }
684         if (fty.arg_nest) {
685             fty.arg_nest->attrs |= llvm::Attribute::Nest;
686         }
687        
688         Logger::println("x86-64 D ABI: Transforming arguments");
689         LOG_SCOPE;
690        
691         for (IrFuncTy::ArgIter I = fty.args.begin(), E = fty.args.end(); I != E; ++I) {
692             IrFuncTyArg& arg = **I;
693            
694             if (Logger::enabled())
695                 Logger::cout() << "Arg: " << arg.type->toChars() << '\n';
696            
697             // Arguments that are in memory are of no interest to us.
698             if (arg.byref)
699                 continue;
700            
701             Type* ty = arg.type->toBasetype();
702             if (ty->ty == Tstruct)
703                 fixup_D(arg);
704            
705             if (Logger::enabled())
706                 Logger::cout() << "New arg type: " << *arg.ltype << '\n';
707         }
708        
709     } else {
710         // TODO: See if this is correct for more than just extern(C).
711        
712         if (!fty.arg_sret) {
713             Logger::println("x86-64 ABI: Transforming return type");
714             Type* rt = fty.ret->type->toBasetype();
715             if (rt != Type::tvoid)
716                 fixup(*fty.ret);
717         }
718        
719        
720         Logger::println("x86-64 ABI: Transforming arguments");
721         LOG_SCOPE;
722        
723         for (IrFuncTy::ArgIter I = fty.args.begin(), E = fty.args.end(); I != E; ++I) {
724             IrFuncTyArg& arg = **I;
725            
726             if (Logger::enabled())
727                 Logger::cout() << "Arg: " << arg.type->toChars() << '\n';
728            
729             // Arguments that are in memory are of no interest to us.
730             if (arg.byref)
731                 continue;
732            
733             Type* ty = arg.type->toBasetype();
734            
735             fixup(arg);
736             if (Logger::enabled())
737                 Logger::cout() << "New arg type: " << *arg.ltype << '\n';
738         }
739     }
740 }
Note: See TracBrowser for help on using the browser.
Copyright © 2008, LDC Development Team.