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

Changeset 930:7985bb036db4

Show
Ignore:
Timestamp:
02/03/09 15:46:46 (3 years ago)
Author:
Christian Kamm <kamm incasoftware de>
branch:
default
Message:

Follow the D ABI and pass the last arg in a register if it is a struct that fits.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • dmd/mtype.c

    r913 r930  
    26922692    this->usesThis = false; 
    26932693    this->usesNest = false; 
     2694    this->structInregArg = false; 
    26942695    this->retAttrs = 0; 
    26952696    this->thisAttrs = 0; 
    26962697    this->reverseParams = false; 
    2697     this->reverseIndex = 0; 
     2698    this->firstRealArg = 0; 
    26982699} 
    26992700 
     
    27092710    t->thisAttrs = thisAttrs; 
    27102711    t->reverseParams = reverseParams; 
    2711     t->reverseIndex = reverseIndex
     2712    t->firstRealArg = firstRealArg
    27122713    return t; 
    27132714} 
  • dmd/mtype.h

    r875 r930  
    439439    bool usesThis; 
    440440    bool usesNest; 
     441    bool structInregArg; 
    441442    unsigned retAttrs; 
    442443    unsigned thisAttrs; // also used for nest 
     444    // parameter index in the llvm function that contains the first not-implicit arg 
     445    size_t firstRealArg; 
    443446 
    444447    bool reverseParams; 
    445     size_t reverseIndex; 
    446448}; 
    447449 
  • gen/functions.cpp

    r920 r930  
    102102    } 
    103103 
     104    // now that all implicit args are done, store the start of the real args 
     105    f->firstRealArg = paramvec.size(); 
     106 
    104107    // number of formal params 
    105108    size_t n = Argument::dim(f->parameters); 
     
    115118        { 
    116119            f->reverseParams = true; 
    117             f->reverseIndex = paramvec.size(); 
    118120        } 
    119121    } 
     
    178180    if (f->reverseParams) 
    179181    { 
    180         std::reverse(paramvec.begin() + f->reverseIndex, paramvec.end()); 
    181     } 
    182  
    183     // construct function type 
    184     bool isvararg = !(dVararg || arrayVararg) && f->varargs; 
    185     llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); 
     182        std::reverse(paramvec.begin() + f->firstRealArg, paramvec.end()); 
     183    } 
    186184 
    187185#if X86_PASS_IN_EAX 
    188     // tell first param to be passed in a register if we can 
     186    // pass first param in EAX if it fits, is not floating point and is not a 3 byte struct. 
    189187    // ONLY extern(D) functions ! 
    190188    if ((n > 0 || usesthis || usesnest) && f->linkage == LINKd) 
     
    193191        if (global.params.cpu == ARCHx86) 
    194192        { 
    195             // pass first param in EAX if it fits, is not floating point and is not a 3 byte struct. 
    196             // FIXME: struct are not passed in EAX yet 
    197  
    198193            int n_inreg = f->reverseParams ? n - 1 : 0; 
    199194            Argument* arg = Argument::getNth(f->parameters, n_inreg); 
     
    210205                Type* t = arg->type->toBasetype(); 
    211206 
    212                 // 32bit ints, pointers, classes, static arrays, AAs, ref and out params 
     207                // 32bit ints, pointers, classes, static arrays, AAs, ref and out params, 
     208                // and structs with size <= 4 and != 3 
    213209                // are candidate for being passed in EAX 
    214210                if ( 
     
    217213                    ((arg->storageClass & STCin) && 
    218214                     ((t->isscalar() && !t->isfloating()) || 
    219                      t->ty == Tclass || t->ty == Tsarray || t->ty == Taarray) && 
    220                      (t->size() <= PTRSIZE)) 
     215                      t->ty == Tclass || t->ty == Tsarray || t->ty == Taarray || 
     216                      (t->ty == Tstruct && t->size() != 3) 
     217                     ) && (t->size() <= PTRSIZE)) 
    221218                   ) 
    222219                { 
    223220                    arg->llvmAttrs |= llvm::Attribute::InReg; 
    224221                    assert((f->thisAttrs & llvm::Attribute::InReg) == 0 && "can't have two inreg args!"); 
     222 
     223                    // structs need to go from {...}* byval to {...} inreg 
     224                    if ((arg->storageClass & STCin) && t->ty == Tstruct) 
     225                    { 
     226                        int n_param = f->reverseParams ? f->firstRealArg + n - 1 - n_inreg : f->firstRealArg + n_inreg; 
     227                        assert(isaPointer(paramvec[n_param]) && (arg->llvmAttrs & llvm::Attribute::ByVal) 
     228                            && "struct parameter expected to be {...}* byval before inreg is applied"); 
     229                        paramvec[n_param] = paramvec[n_param]->getContainedType(0); 
     230                        arg->llvmAttrs &= ~llvm::Attribute::ByVal; 
     231                        f->structInregArg = true; 
     232                    } 
    225233                } 
    226234            } 
     
    228236    } 
    229237#endif // X86_PASS_IN_EAX 
     238 
     239    // construct function type 
     240    bool isvararg = !(dVararg || arrayVararg) && f->varargs; 
     241    llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); 
    230242 
    231243    // done 
     
    740752            VarDeclaration* vd = argsym->isVarDeclaration(); 
    741753            assert(vd); 
     754 
     755            IrLocal* irloc = vd->ir.irLocal; 
     756            assert(irloc); 
     757 
     758            // if it's inreg struct arg, allocate storage 
     759            if (f->structInregArg && i == (f->reverseParams ? n - 1 : 0)) 
     760            { 
     761                int n_param = f->reverseParams ? f->firstRealArg + n - 1 - i : f->firstRealArg + i; 
     762                assert(!f->usesNest && !f->usesThis && isaStruct(functype->getParamType(n_param)) 
     763                    && "Preconditions for inreg struct arg not met!"); 
     764 
     765                LLValue* mem = DtoAlloca(functype->getParamType(n_param), "inregstructarg"); 
     766                DtoStore(irloc->value, mem); 
     767                irloc->value = mem; 
     768            } 
    742769 
    743770        #if DMDV2 
     
    749776                fd->nestedVars.insert(vd); 
    750777            } 
    751  
    752             IrLocal* irloc = vd->ir.irLocal; 
    753             assert(irloc); 
    754778 
    755779            bool refout = vd->storage_class & (STCref | STCout); 
  • gen/tocall.cpp

    r839 r930  
    371371            LLValue* arg = argval->getRVal(); 
    372372 
     373            // if it's a struct inreg arg, load first to pass as first-class value 
     374            if (tf->structInregArg && i == (tf->reverseParams ? n - 1 : 0)) 
     375            { 
     376                assert(fnarg->llvmAttrs & llvm::Attribute::InReg); 
     377                arg = DtoLoad(arg); 
     378            } 
     379 
    373380            int j = tf->reverseParams ? beg + n - i - 1 : beg + i; 
    374381 
     
    396403        if (tf->reverseParams) 
    397404        { 
    398             std::reverse(args.begin() + tf->reverseIndex, args.end()); 
     405            std::reverse(args.begin() + tf->firstRealArg, args.end()); 
    399406            std::reverse(attrptr.begin(), attrptr.end()); 
    400407        } 
Copyright © 2008, LDC Development Team.