Example #1
0
// run time version of bitcast intrinsic
JL_DLLEXPORT jl_value_t *jl_bitcast(jl_value_t *ty, jl_value_t *v)
{
    JL_TYPECHK(bitcast, datatype, ty);
    if (!jl_is_concrete_type(ty) || !jl_is_primitivetype(ty))
        jl_error("bitcast: target type not a leaf primitive type");
    if (!jl_is_primitivetype(jl_typeof(v)))
        jl_error("bitcast: value not a primitive type");
    if (jl_datatype_size(jl_typeof(v)) != jl_datatype_size(ty))
        jl_error("bitcast: argument size does not match size of target type");
    if (ty == jl_typeof(v))
        return v;
    if (ty == (jl_value_t*)jl_bool_type)
        return *(uint8_t*)jl_data_ptr(v) & 1 ? jl_true : jl_false;
    return jl_new_bits(ty, jl_data_ptr(v));
}
Example #2
0
// Determine if homogeneous tuple with fields of type t will have
// a special alignment beyond normal Julia rules.
// Return special alignment if one exists, 0 if normal alignment rules hold.
// A non-zero result *must* match the LLVM rules for a vector type <nfields x t>.
// For sake of Ahead-Of-Time (AOT) compilation, this routine has to work
// without LLVM being available.
unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *t)
{
    if (!jl_is_vecelement_type(t))
        return 0;
    // LLVM 3.7 and 3.8 either crash or generate wrong code for many
    // SIMD vector sizes N. It seems the rule is that N can have at
    // most 2 non-zero bits. (This is true at least for N<=100.) See
    // also <https://llvm.org/bugs/show_bug.cgi?id=27708>.
    size_t mask = nfields;
    // See e.g.
    // <https://graphics.stanford.edu/%7Eseander/bithacks.html> for an
    // explanation of this bit-counting algorithm.
    mask &= mask-1;             // clear least-significant 1 if present
    mask &= mask-1;             // clear another 1
    if (mask)
        return 0;               // nfields has more than two 1s
    assert(jl_datatype_nfields(t)==1);
    jl_value_t *ty = jl_field_type(t, 0);
    if (!jl_is_primitivetype(ty))
        // LLVM requires that a vector element be a primitive type.
        // LLVM allows pointer types as vector elements, but until a
        // motivating use case comes up for Julia, we reject pointers.
        return 0;
    size_t elsz = jl_datatype_size(ty);
    if (elsz>8 || (1<<elsz & 0x116) == 0)
        // Element size is not 1, 2, 4, or 8.
        return 0;
    size_t size = nfields*elsz;
    // LLVM's alignment rule for vectors seems to be to round up to
    // a power of two, even if that's overkill for the target hardware.
    size_t alignment=1;
    for( ; size>alignment; alignment*=2 )
        continue;
    return alignment;
}
Example #3
0
bool needPassByRef(jl_datatype_t *dt, AttrBuilder &ab) override
{
    size_t size = jl_datatype_size(dt);
    if (is_complex64(dt) || is_complex128(dt) || (jl_is_primitivetype(dt) && size <= 8))
        return false;
    ab.addAttribute(Attribute::ByVal);
    return true;
}
Example #4
0
bool use_sret(jl_datatype_t *dt) override
{
    size_t size = jl_datatype_size(dt);
    if (size == 0)
        return false;
    if (is_complex64(dt) || (jl_is_primitivetype(dt) && size <= 8))
        return false;
    return true;
}
Example #5
0
// count the homogeneous floating agregate size (saturating at max count of 8)
unsigned isHFA(jl_datatype_t *ty, jl_datatype_t **ty0, bool *hva) const
{
    size_t i, l = ty->layout->nfields;
    // handle homogeneous float aggregates
    if (l == 0) {
        if (ty != jl_float64_type && ty != jl_float32_type)
            return 9;
        *hva = false;
        if (*ty0 == NULL)
            *ty0 = ty;
        else if (*hva || ty->size != (*ty0)->size)
            return 9;
        return 1;
    }

    // handle homogeneous vector aggregates
    jl_datatype_t *fld0 = (jl_datatype_t*)jl_field_type(ty, 0);
    if (!jl_is_datatype(fld0) || ty->name == jl_vecelement_typename)
        return 9;
    if (fld0->name == jl_vecelement_typename) {
        if (!jl_is_primitivetype(jl_tparam0(fld0)) || jl_datatype_size(ty) > 16)
            return 9;
        if (l != 1 && l != 2 && l != 4 && l != 8 && l != 16)
            return 9;
        *hva = true;
        if (*ty0 == NULL)
            *ty0 = ty;
        else if (!*hva || ty->size != (*ty0)->size)
            return 9;
        for (i = 1; i < l; i++) {
            jl_datatype_t *fld = (jl_datatype_t*)jl_field_type(ty, i);
            if (fld != fld0)
                return 9;
        }
        return 1;
    }

    // recurse through other struct types
    int n = 0;
    for (i = 0; i < l; i++) {
        jl_datatype_t *fld = (jl_datatype_t*)jl_field_type(ty, i);
        if (!jl_is_datatype(fld) || ((jl_datatype_t*)fld)->layout == NULL)
            return 9;
        n += isHFA((jl_datatype_t*)fld, ty0, hva);
        if (n > 8)
            return 9;
    }
    return n;
}
Example #6
0
Type *preferred_llvm_type(jl_datatype_t *dt, bool isret) const override
{
    // Arguments are either scalar or passed by value
    size_t size = jl_datatype_size(dt);
    // don't need to change bitstypes
    if (!jl_datatype_nfields(dt))
        return NULL;
    // legalize this into [n x f32/f64]
    jl_datatype_t *ty0 = NULL;
    bool hva = false;
    int hfa = isHFA(dt, &ty0, &hva);
    if (hfa <= 8) {
        if (ty0 == jl_float32_type) {
            return ArrayType::get(T_float32, hfa);
        }
        else if (ty0 == jl_float64_type) {
            return ArrayType::get(T_float64, hfa);
        }
        else {
            jl_datatype_t *vecty = (jl_datatype_t*)jl_field_type(ty0, 0);
            assert(jl_is_datatype(vecty) && vecty->name == jl_vecelement_typename);
            jl_value_t *elemty = jl_tparam0(vecty);
            assert(jl_is_primitivetype(elemty));

            Type *ety = julia_type_to_llvm(elemty);
            Type *vty = VectorType::get(ety, jl_datatype_nfields(ty0));
            return ArrayType::get(vty, hfa);
        }
    }
    // rewrite integer-sized (non-HFA) struct to an array
    // the bitsize of the integer gives the desired alignment
    if (size > 8) {
        if (jl_datatype_align(dt) <= 8) {
            return ArrayType::get(T_int64, (size + 7) / 8);
        }
        else {
            Type *T_int128 = Type::getIntNTy(jl_LLVMContext, 128);
            return ArrayType::get(T_int128, (size + 15) / 16);
        }
    }
    return Type::getIntNTy(jl_LLVMContext, size * 8);
}