Ejemplo n.º 1
0
static Constant *julia_const_to_llvm(const void *ptr, jl_datatype_t *bt)
{
    // assumes `jl_isbits(bt)`.
    // `ptr` can point to a inline field, do not read the tag from it.
    // make sure to return exactly the type specified by
    // julia_type_to_llvm as this will be assumed by the callee.
    if (bt == jl_bool_type)
        return ConstantInt::get(T_int8, (*(const uint8_t*)ptr) ? 1 : 0);

    if (jl_is_vecelement_type((jl_value_t*)bt))
        bt = (jl_datatype_t*)jl_tparam0(bt);

    Type *lt = julia_struct_to_llvm((jl_value_t*)bt, NULL, NULL);

    if (type_is_ghost(lt))
        return UndefValue::get(NoopType);

    if (jl_is_primitivetype(bt)) {
        if (lt->isFloatTy()) {
            uint32_t data32 = *(const uint32_t*)ptr;
            return ConstantFP::get(jl_LLVMContext,
                    APFloat(lt->getFltSemantics(), APInt(32, data32)));
        }
        if (lt->isDoubleTy()) {
            uint64_t data64 = *(const uint64_t*)ptr;
            return ConstantFP::get(jl_LLVMContext,
                    APFloat(lt->getFltSemantics(), APInt(64, data64)));
        }
        int nb = jl_datatype_size(bt);
        APInt val(8 * nb, 0);
        void *bits = const_cast<uint64_t*>(val.getRawData());
        assert(sys::IsLittleEndianHost);
        memcpy(bits, ptr, nb);
        if (lt->isFloatingPointTy()) {
            return ConstantFP::get(jl_LLVMContext,
                    APFloat(lt->getFltSemantics(), val));
        }
        assert(cast<IntegerType>(lt)->getBitWidth() == 8u * nb);
        return ConstantInt::get(lt, val);
    }

    CompositeType *lct = cast<CompositeType>(lt);
    size_t nf = jl_datatype_nfields(bt);
    std::vector<Constant*> fields(nf);
    for (size_t i = 0; i < nf; i++) {
        size_t offs = jl_field_offset(bt, i);
        assert(!jl_field_isptr(bt, i));
        jl_value_t *ft = jl_field_type(bt, i);
        Type *lft = lct->getTypeAtIndex(i);
        const uint8_t *ov = (const uint8_t*)ptr + offs;
        Constant *val;
        if (jl_is_uniontype(ft)) {
            // compute the same type layout as julia_struct_to_llvm
            size_t fsz = jl_field_size(bt, i);
            size_t al = jl_field_align(bt, i);
            uint8_t sel = ((const uint8_t*)ptr)[offs + fsz - 1];
            jl_value_t *active_ty = jl_nth_union_component(ft, sel);
            size_t active_sz = jl_datatype_size(active_ty);
            ArrayType *aty = cast<ArrayType>(cast<StructType>(lft)->getTypeAtIndex(0u));
            assert(aty->getElementType() == IntegerType::get(jl_LLVMContext, 8 * al) &&
                   aty->getNumElements() == (fsz - 1) / al);
            std::vector<Constant*> ArrayElements(0);
            for (unsigned j = 0; j < aty->getNumElements(); j++) {
                APInt Elem(8 * al, 0);
                void *bits = const_cast<uint64_t*>(Elem.getRawData());
                if (active_sz > al) {
                    memcpy(bits, ov, al);
                    active_sz -= al;
                }
                else if (active_sz > 0) {
                    memcpy(bits, ov, active_sz);
                    active_sz = 0;
                }
                ov += al;
                ArrayElements.push_back(ConstantInt::get(aty->getElementType(), Elem));
            }
            std::vector<Constant*> Elements(0);
            Elements.push_back(ConstantArray::get(aty, ArrayElements));
            unsigned remainder = (fsz - 1) % al;
            while (remainder--) {
                uint8_t byte;
                if (active_sz > 0) {
                    byte = *ov;
                    active_sz -= 1;
                }
                else {
                    byte = 0;
                }
                ov += 1;
                APInt Elem(8, byte);
                Elements.push_back(ConstantInt::get(T_int8, Elem));
            }
            Elements.push_back(ConstantInt::get(T_int8, sel));
            val = ConstantStruct::get(cast<StructType>(lft), Elements);
        }
        else {
            val = julia_const_to_llvm(ov, (jl_datatype_t*)ft);
        }
        fields[i] = val;
    }

    if (lct->isVectorTy())
        return ConstantVector::get(fields);
    if (StructType *st = dyn_cast<StructType>(lct))
        return ConstantStruct::get(st, fields);
    ArrayType *at = cast<ArrayType>(lct);
    return ConstantArray::get(at, fields);
}