Esempio n. 1
0
int FuncCallStack::push(ITypeInfo* argType, IHqlExpression* curParam)
{
    unsigned len = 0;
    char* str;
    int incsize;
    int inclen;

    IValue * paramValue = curParam->queryValue();
    Owned<IValue> castParam;
    if (paramValue) // Not all constants have a paramValue - null, all, constant records etc
    {
        castParam.setown(paramValue->castTo(argType));
        if(!castParam)
        {
            PrintLog("Failed to cast paramValue to argType in FuncCallStack::push");
            return -1;
        }
    }

    switch (argType->getTypeCode()) 
    {
    case type_string:
    case type_data:
        getStringFromIValue(len, str, castParam);
        // For STRINGn, len doesn't need to be passed in.
        if(argType->getSize() == UNKNOWN_LENGTH) {
            push(sizeof(unsigned), &len);
        }
        push(sizeof(char *), &str);
        if(numToFree < MAXARGS) {
            toFree[numToFree++] = str;
        }
        break;
    case type_varstring:
        getStringFromIValue(len, str, castParam);
        push(sizeof(char *), &str);
        if(numToFree < MAXARGS) {
            toFree[numToFree++] = str;
        }
        break;
    case type_qstring:
    case type_unicode:
    case type_utf8:
        {
            unsigned argSize = castParam->getSize();
            const void * text = castParam->queryValue();
            str = (char *)malloc(argSize);
            memcpy(str, text, argSize);

            // For STRINGn, len doens't need to be passed in.
            if(argType->getSize() == UNKNOWN_LENGTH)
            {
                len = castParam->queryType()->getStringLen();
                push(sizeof(unsigned), &len);
            }
            push(sizeof(char *), &str);
            if(numToFree < MAXARGS) {
                toFree[numToFree++] = str;
            }
        }
        break;
    case type_varunicode:
        UNIMPLEMENTED;
    case type_real:
#ifdef MAXFPREGS
        if (numFpRegs==MAXFPREGS) {
            PrintLog("Too many floating point registers needed in FuncCallStack::push");
            return -1;
        }
        char tempbuf[sizeof(double)];
        castParam->toMem(tempbuf);
#ifdef FPREG_FIXEDSIZE
        if (argType->getSize()<=4)
            fpRegs[numFpRegs++] = *(float *)&tempbuf;
        else
            fpRegs[numFpRegs++] = *(double *)&tempbuf;
#else
        // Variable size FP registers as on arm/x64
        if (argType->getSize()<=4)
            fpRegs[numFpRegs].f = *(float *)&tempbuf;
        else
            fpRegs[numFpRegs].d = *(double *)&tempbuf;
        fpSizes[numFpRegs++] = argType->getSize();
#endif
        break;
#else
    // fall through if no hw regs used for params
#endif
    case type_boolean:
    case type_int:
    case type_decimal:
    case type_date:
    case type_char:
    case type_enumerated:
    case type_swapint:
    case type_packedint:
        incsize = argType->getSize();
        inclen = align(incsize);
        assure(inclen);
        castParam->toMem(stackbuf+sp);
        memset(stackbuf+sp+incsize, 0, inclen - incsize);
        sp += inclen;
        break;
    case type_row:
    {
        if (hasMeta)
        {
            try
            {
                pushMeta(curParam->queryRecordType());
            }
            catch (IException *E)
            {
                ::Release(E);
                return -1;
            }
        }
        if (curParam->getOperator()==no_null)
        {
            // MORE - check type matches
            MemoryBuffer out;
            createConstantNullRow(out, curParam->queryRecord());
            str = (char *) out.detach();
            push(sizeof(char *), &str);
            if(numToFree < MAXARGS)
                toFree[numToFree++] = str;
        }
        else
            return -1;
        break;
    }
    case type_record:
    {
        try
        {
            pushMeta(curParam->queryRecordType());
        }
        catch (IException *E)
        {
            ::Release(E);
            return -1;
        }
        break;
    }
    default:
        EclIR::dump_ir(curParam);
        //code isn't here to pass sets/datasets to external functions....
        return -1;
    }

    return sp;
}