コード例 #1
0
ファイル: functions.cpp プロジェクト: gballet/ldc
llvm::FunctionType* DtoFunctionType(Type* type, IrFuncTy &irFty, Type* thistype, Type* nesttype,
                                    bool isMain, bool isCtor, bool isIntrinsic)
{
    IF_LOG Logger::println("DtoFunctionType(%s)", type->toChars());
    LOG_SCOPE

    // sanity check
    assert(type->ty == Tfunction);
    TypeFunction* f = static_cast<TypeFunction*>(type);
    assert(f->next && "Encountered function type with invalid return type; "
        "trying to codegen function ignored by the frontend?");

    // Return cached type if available
    if (irFty.funcType) return irFty.funcType;

    TargetABI* abi = (isIntrinsic ? TargetABI::getIntrinsic() : gABI);
    // Tell the ABI we're resolving a new function type
    abi->newFunctionType(f);

    // Do not modify irFty yet; this function may be called recursively if any
    // of the argument types refer to this type.
    IrFuncTy newIrFty;

    // llvm idx counter
    size_t lidx = 0;

    // main needs a little special handling
    if (isMain)
    {
        newIrFty.ret = new IrFuncTyArg(Type::tint32, false);
    }
    // sane return value
    else
    {
        Type* rt = f->next;
#if LDC_LLVM_VER >= 302
        llvm::AttrBuilder attrBuilder;
#else
        llvm::Attributes a = llvm::Attribute::None;
#endif

        // sret return
        if (abi->returnInArg(f))
        {
#if LDC_LLVM_VER >= 302
#if LDC_LLVM_VER >= 303
            newIrFty.arg_sret = new IrFuncTyArg(rt, true,
                llvm::AttrBuilder().addAttribute(llvm::Attribute::StructRet)
                .addAttribute(llvm::Attribute::NoAlias)
#else
            newIrFty.arg_sret = new IrFuncTyArg(rt, true, llvm::Attributes::get(gIR->context(),
                llvm::AttrBuilder().addAttribute(llvm::Attributes::StructRet)
                .addAttribute(llvm::Attributes::NoAlias)
#endif
#if LDC_LLVM_VER == 302
            )
#endif
            );
#else
            newIrFty.arg_sret = new IrFuncTyArg(rt, true,
                                                llvm::Attribute::StructRet | llvm::Attribute::NoAlias);
#endif
            rt = Type::tvoid;
            lidx++;
        }
        // sext/zext return
        else
        {
コード例 #2
0
ファイル: functions.cpp プロジェクト: WebDrake/ldc
llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nesttype, bool ismain)
{
    if (Logger::enabled())
        Logger::println("DtoFunctionType(%s)", type->toChars());
    LOG_SCOPE

    // sanity check
    assert(type->ty == Tfunction);
    TypeFunction* f = static_cast<TypeFunction*>(type);

    TargetABI* abi = (f->linkage == LINKintrinsic ? TargetABI::getIntrinsic() : gABI);
    // Tell the ABI we're resolving a new function type
    abi->newFunctionType(f);

    // Do not modify f->fty yet; this function may be called recursively if any
    // of the argument types refer to this type.
    IrFuncTy fty;

    // llvm idx counter
    size_t lidx = 0;

    // main needs a little special handling
    if (ismain)
    {
        fty.ret = new IrFuncTyArg(Type::tint32, false);
    }
    // sane return value
    else
    {
        Type* rt = f->next;
#if LDC_LLVM_VER >= 302
        llvm::AttrBuilder attrBuilder;
#else
        llvm::Attributes a = None;
#endif

        // sret return
        if (abi->returnInArg(f))
        {
#if LDC_LLVM_VER >= 302
#if LDC_LLVM_VER >= 303
            fty.arg_sret = new IrFuncTyArg(rt, true,
                llvm::AttrBuilder().addAttribute(llvm::Attribute::StructRet)
                .addAttribute(llvm::Attribute::NoAlias)
#else
            fty.arg_sret = new IrFuncTyArg(rt, true, llvm::Attributes::get(gIR->context(),
                llvm::AttrBuilder().addAttribute(llvm::Attributes::StructRet)
                .addAttribute(llvm::Attributes::NoAlias)
#endif
#if LDC_LLVM_VER == 302
            )
#endif
            );
#else
            fty.arg_sret = new IrFuncTyArg(rt, true, StructRet | NoAlias
            );
#endif
            rt = Type::tvoid;
            lidx++;
        }
        // sext/zext return
        else
        {
コード例 #3
0
llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nesttype, bool ismain)
{
    if (Logger::enabled())
        Logger::println("DtoFunctionType(%s)", type->toChars());
    LOG_SCOPE

    // sanity check
    assert(type->ty == Tfunction);
    TypeFunction* f = (TypeFunction*)type;

    TargetABI* abi = (f->linkage == LINKintrinsic ? TargetABI::getIntrinsic() : gABI);
    // Tell the ABI we're resolving a new function type
    abi->newFunctionType(f);

    // Do not modify f->fty yet; this function may be called recursively if any
    // of the argument types refer to this type.
    IrFuncTy fty;

    // llvm idx counter
    size_t lidx = 0;

    // main needs a little special handling
    if (ismain)
    {
        fty.ret = new IrFuncTyArg(Type::tint32, false);
    }
    // sane return value
    else
    {
        Type* rt = f->next;
        unsigned a = 0;
        // sret return
        if (abi->returnInArg(f))
        {
            fty.arg_sret = new IrFuncTyArg(rt, true, StructRet | NoAlias | NoCapture);
            rt = Type::tvoid;
            lidx++;
        }
        // sext/zext return
        else
        {
            Type *t = rt;
#if DMDV2
            if (f->isref)
                t = t->pointerTo();
#endif
            if (unsigned se = DtoShouldExtend(t))
                a = se;
        }
#if DMDV2
        fty.ret = new IrFuncTyArg(rt, f->isref, a);
#else
        fty.ret = new IrFuncTyArg(rt, false, a);
#endif
    }
    lidx++;

    // member functions
    if (thistype)
    {
        fty.arg_this = new IrFuncTyArg(thistype, thistype->toBasetype()->ty == Tstruct);
        lidx++;
    }

    // and nested functions
    else if (nesttype)
    {
        fty.arg_nest = new IrFuncTyArg(nesttype, false);
        lidx++;
    }

    // vararg functions are special too
    if (f->varargs)
    {
        if (f->linkage == LINKd)
        {
            // d style with hidden args
            // 2 (array) is handled by the frontend
            if (f->varargs == 1)
            {
                // _arguments
                fty.arg_arguments = new IrFuncTyArg(Type::typeinfo->type->arrayOf(), false);
                lidx++;
                // _argptr
                fty.arg_argptr = new IrFuncTyArg(Type::tvoid->pointerTo(), false, NoAlias | NoCapture);
                lidx++;
            }
        }
        else if (f->linkage == LINKc)
        {
            fty.c_vararg = true;
        }
        else
        {
            type->error(0, "invalid linkage for variadic function");
            fatal();
        }
    }

    // if this _Dmain() doesn't have an argument, we force it to have one
    int nargs = Parameter::dim(f->parameters);

    if (ismain && nargs == 0)
    {
        Type* mainargs = Type::tchar->arrayOf()->arrayOf();
        fty.args.push_back(new IrFuncTyArg(mainargs, false));
        lidx++;
    }
    // add explicit parameters
    else for (int i = 0; i < nargs; i++)
    {
        // get argument
        Parameter* arg = Parameter::getNth(f->parameters, i);

        // reference semantics? ref, out and d1 static arrays are
        bool byref = arg->storageClass & (STCref|STCout);
#if !SARRAYVALUE
        byref = byref || (arg->type->toBasetype()->ty == Tsarray);
#endif

        Type* argtype = arg->type;
        unsigned a = 0;

        // handle lazy args
        if (arg->storageClass & STClazy)
        {
            Logger::println("lazy param");
            TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
            TypeDelegate *ltd = new TypeDelegate(ltf);
            argtype = ltd;
        }
        // byval
        else if (abi->passByVal(byref ? argtype->pointerTo() : argtype))
        {
            if (!byref) a |= llvm::Attribute::ByVal;
            byref = true;
        }
        // sext/zext
        else if (!byref)
        {
            a |= DtoShouldExtend(argtype);
        }

        fty.args.push_back(new IrFuncTyArg(argtype, byref, a));
        lidx++;
    }

    // Now we can modify f->fty safely.
    f->fty = fty;

    // let the abi rewrite the types as necesary
    abi->rewriteFunctionType(f);

    // Tell the ABI we're done with this function type
    abi->doneWithFunctionType();

    // build the function type
    std::vector<LLType*> argtypes;
    argtypes.reserve(lidx);

    if (f->fty.arg_sret) argtypes.push_back(f->fty.arg_sret->ltype);
    if (f->fty.arg_this) argtypes.push_back(f->fty.arg_this->ltype);
    if (f->fty.arg_nest) argtypes.push_back(f->fty.arg_nest->ltype);
    if (f->fty.arg_arguments) argtypes.push_back(f->fty.arg_arguments->ltype);
    if (f->fty.arg_argptr) argtypes.push_back(f->fty.arg_argptr->ltype);

    size_t beg = argtypes.size();
    size_t nargs2 = f->fty.args.size();
    for (size_t i = 0; i < nargs2; i++)
    {
        argtypes.push_back(f->fty.args[i]->ltype);
    }

    // reverse params?
    if (f->fty.reverseParams && nargs2 > 1)
    {
        std::reverse(argtypes.begin() + beg, argtypes.end());
    }

    LLFunctionType* functype = LLFunctionType::get(f->fty.ret->ltype, argtypes, f->fty.c_vararg);

    Logger::cout() << "Final function type: " << *functype << "\n";

    return functype;
}
コード例 #4
0
ファイル: functions.cpp プロジェクト: Axure/ldc
llvm::FunctionType* DtoFunctionType(Type* type, IrFuncTy &irFty, Type* thistype, Type* nesttype,
                                    bool isMain, bool isCtor, bool isIntrinsic)
{
    IF_LOG Logger::println("DtoFunctionType(%s)", type->toChars());
    LOG_SCOPE

    // sanity check
    assert(type->ty == Tfunction);
    TypeFunction* f = static_cast<TypeFunction*>(type);
    assert(f->next && "Encountered function type with invalid return type; "
        "trying to codegen function ignored by the frontend?");

    // Return cached type if available
    if (irFty.funcType) return irFty.funcType;

    TargetABI* abi = (isIntrinsic ? TargetABI::getIntrinsic() : gABI);

    // Do not modify irFty yet; this function may be called recursively if any
    // of the argument types refer to this type.
    IrFuncTy newIrFty;

    // llvm idx counter
    size_t lidx = 0;

    // main needs a little special handling
    if (isMain)
    {
        newIrFty.ret = new IrFuncTyArg(Type::tint32, false);
    }
    // sane return value
    else
    {
        Type* rt = f->next;
        AttrBuilder attrBuilder;

        // sret return
        if (abi->returnInArg(f))
        {
            newIrFty.arg_sret = new IrFuncTyArg(rt, true,
                AttrBuilder().add(LDC_ATTRIBUTE(StructRet)).add(LDC_ATTRIBUTE(NoAlias)));
            rt = Type::tvoid;
            lidx++;
        }
        // sext/zext return
        else
        {
            Type *t = rt;
            if (f->isref)
                t = t->pointerTo();
            attrBuilder.add(DtoShouldExtend(t));
        }
        newIrFty.ret = new IrFuncTyArg(rt, f->isref, attrBuilder);
    }
    lidx++;

    // member functions
    if (thistype)
    {
        AttrBuilder attrBuilder;
#if LDC_LLVM_VER >= 303
        if (isCtor)
            attrBuilder.add(LDC_ATTRIBUTE(Returned));
#endif
        newIrFty.arg_this = new IrFuncTyArg(thistype, thistype->toBasetype()->ty == Tstruct, attrBuilder);
        lidx++;
    }

    // and nested functions
    else if (nesttype)
    {
        newIrFty.arg_nest = new IrFuncTyArg(nesttype, false);
        lidx++;
    }

    // vararg functions are special too
    if (f->varargs)
    {
        if (f->linkage == LINKd)
        {
            // d style with hidden args
            // 2 (array) is handled by the frontend
            if (f->varargs == 1)
            {
                // _arguments
                newIrFty.arg_arguments = new IrFuncTyArg(Type::dtypeinfo->type->arrayOf(), false);
                lidx++;
            }
        }

        newIrFty.c_vararg = true;
    }

    // if this _Dmain() doesn't have an argument, we force it to have one
    int nargs = Parameter::dim(f->parameters);

    if (isMain && nargs == 0)
    {
        Type* mainargs = Type::tchar->arrayOf()->arrayOf();
        newIrFty.args.push_back(new IrFuncTyArg(mainargs, false));
        lidx++;
    }
    // add explicit parameters
    else for (int i = 0; i < nargs; i++)
    {
        // get argument
        Parameter* arg = Parameter::getNth(f->parameters, i);

        // reference semantics? ref, out and d1 static arrays are
        bool byref = arg->storageClass & (STCref|STCout);

        Type* argtype = arg->type;
        AttrBuilder attrBuilder;

        // handle lazy args
        if (arg->storageClass & STClazy)
        {
            Logger::println("lazy param");
            TypeFunction *ltf = new TypeFunction(NULL, arg->type, 0, LINKd);
            TypeDelegate *ltd = new TypeDelegate(ltf);
            argtype = ltd;
        }
        else if (!byref)
        {
            // byval
            if (abi->passByVal(argtype))
            {
                attrBuilder.add(LDC_ATTRIBUTE(ByVal));
                // set byref, because byval requires a pointed LLVM type
                byref = true;
            }
            // sext/zext
            else
            {
                attrBuilder.add(DtoShouldExtend(argtype));
            }
        }
        newIrFty.args.push_back(new IrFuncTyArg(argtype, byref, attrBuilder));
        lidx++;
    }

    // let the abi rewrite the types as necesary
    abi->rewriteFunctionType(f, newIrFty);

    // Now we can modify irFty safely.
    irFty = llvm_move(newIrFty);

    // build the function type
    std::vector<LLType*> argtypes;
    argtypes.reserve(lidx);

    if (irFty.arg_sret) argtypes.push_back(irFty.arg_sret->ltype);
    if (irFty.arg_this) argtypes.push_back(irFty.arg_this->ltype);
    if (irFty.arg_nest) argtypes.push_back(irFty.arg_nest->ltype);
    if (irFty.arg_arguments) argtypes.push_back(irFty.arg_arguments->ltype);

    size_t beg = argtypes.size();
    size_t nargs2 = irFty.args.size();
    for (size_t i = 0; i < nargs2; i++)
    {
        argtypes.push_back(irFty.args[i]->ltype);
    }

    // reverse params?
    if (irFty.reverseParams && nargs2 > 1)
    {
        std::reverse(argtypes.begin() + beg, argtypes.end());
    }

    irFty.funcType = LLFunctionType::get(irFty.ret->ltype, argtypes, irFty.c_vararg);

    IF_LOG Logger::cout() << "Final function type: " << *irFty.funcType << "\n";

    return irFty.funcType;
}