refactor: Move the LLVM type and constant constructors into a new module.
This commit is contained in:
parent
e2fcd29bbd
commit
8afb1a7c63
5 changed files with 511 additions and 446 deletions
|
@ -1,22 +1,22 @@
|
||||||
|
|
||||||
import middle::trans;
|
import middle::trans;
|
||||||
import trans::decl_cdecl_fn;
|
import trans::decl_cdecl_fn;
|
||||||
import trans::T_f32;
|
import middle::trans_common::T_f32;
|
||||||
import trans::T_f64;
|
import middle::trans_common::T_f64;
|
||||||
import trans::T_fn;
|
import middle::trans_common::T_fn;
|
||||||
import trans::T_bool;
|
import middle::trans_common::T_bool;
|
||||||
import trans::T_i8;
|
import middle::trans_common::T_i8;
|
||||||
import trans::T_i32;
|
import middle::trans_common::T_i32;
|
||||||
import trans::T_int;
|
import middle::trans_common::T_int;
|
||||||
import trans::T_nil;
|
import middle::trans_common::T_nil;
|
||||||
import trans::T_opaque_chan_ptr;
|
import middle::trans_common::T_opaque_chan_ptr;
|
||||||
import trans::T_opaque_ivec;
|
import middle::trans_common::T_opaque_ivec;
|
||||||
import trans::T_opaque_port_ptr;
|
import middle::trans_common::T_opaque_port_ptr;
|
||||||
import trans::T_opaque_vec_ptr;
|
import middle::trans_common::T_opaque_vec_ptr;
|
||||||
import trans::T_ptr;
|
import middle::trans_common::T_ptr;
|
||||||
import trans::T_size_t;
|
import middle::trans_common::T_size_t;
|
||||||
import trans::T_str;
|
import middle::trans_common::T_str;
|
||||||
import trans::T_void;
|
import middle::trans_common::T_void;
|
||||||
import lib::llvm::type_names;
|
import lib::llvm::type_names;
|
||||||
import lib::llvm::llvm::ModuleRef;
|
import lib::llvm::llvm::ModuleRef;
|
||||||
import lib::llvm::llvm::ValueRef;
|
import lib::llvm::llvm::ValueRef;
|
||||||
|
|
|
@ -65,6 +65,8 @@ import util::ppaux::ty_to_short_str;
|
||||||
import syntax::print::pprust::expr_to_str;
|
import syntax::print::pprust::expr_to_str;
|
||||||
import syntax::print::pprust::path_to_str;
|
import syntax::print::pprust::path_to_str;
|
||||||
|
|
||||||
|
import trans_common::*;
|
||||||
|
|
||||||
obj namegen(mutable int i) {
|
obj namegen(mutable int i) {
|
||||||
fn next(str prefix) -> str { i += 1; ret prefix + int::str(i); }
|
fn next(str prefix) -> str { i += 1; ret prefix + int::str(i); }
|
||||||
}
|
}
|
||||||
|
@ -399,330 +401,6 @@ fn struct_elt(TypeRef llstructty, uint n) -> TypeRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// LLVM type constructors.
|
|
||||||
fn T_void() -> TypeRef {
|
|
||||||
// Note: For the time being llvm is kinda busted here, it has the notion
|
|
||||||
// of a 'void' type that can only occur as part of the signature of a
|
|
||||||
// function, but no general unit type of 0-sized value. This is, afaict,
|
|
||||||
// vestigial from its C heritage, and we'll be attempting to submit a
|
|
||||||
// patch upstream to fix it. In the mean time we only model function
|
|
||||||
// outputs (Rust functions and C functions) using T_void, and model the
|
|
||||||
// Rust general purpose nil type you can construct as 1-bit (always
|
|
||||||
// zero). This makes the result incorrect for now -- things like a tuple
|
|
||||||
// of 10 nil values will have 10-bit size -- but it doesn't seem like we
|
|
||||||
// have any other options until it's fixed upstream.
|
|
||||||
|
|
||||||
ret llvm::LLVMVoidType();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_nil() -> TypeRef {
|
|
||||||
// NB: See above in T_void().
|
|
||||||
|
|
||||||
ret llvm::LLVMInt1Type();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_i1() -> TypeRef { ret llvm::LLVMInt1Type(); }
|
|
||||||
|
|
||||||
fn T_i8() -> TypeRef { ret llvm::LLVMInt8Type(); }
|
|
||||||
|
|
||||||
fn T_i16() -> TypeRef { ret llvm::LLVMInt16Type(); }
|
|
||||||
|
|
||||||
fn T_i32() -> TypeRef { ret llvm::LLVMInt32Type(); }
|
|
||||||
|
|
||||||
fn T_i64() -> TypeRef { ret llvm::LLVMInt64Type(); }
|
|
||||||
|
|
||||||
fn T_f32() -> TypeRef { ret llvm::LLVMFloatType(); }
|
|
||||||
|
|
||||||
fn T_f64() -> TypeRef { ret llvm::LLVMDoubleType(); }
|
|
||||||
|
|
||||||
fn T_bool() -> TypeRef { ret T_i1(); }
|
|
||||||
|
|
||||||
fn T_int() -> TypeRef {
|
|
||||||
// FIXME: switch on target type.
|
|
||||||
|
|
||||||
ret T_i32();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_float() -> TypeRef {
|
|
||||||
// FIXME: switch on target type.
|
|
||||||
|
|
||||||
ret T_f64();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_char() -> TypeRef { ret T_i32(); }
|
|
||||||
|
|
||||||
fn T_size_t() -> TypeRef {
|
|
||||||
// FIXME: switch on target type.
|
|
||||||
|
|
||||||
ret T_i32();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_fn(&TypeRef[] inputs, TypeRef output) -> TypeRef {
|
|
||||||
ret llvm::LLVMFunctionType(output, std::ivec::to_ptr(inputs),
|
|
||||||
std::ivec::len[TypeRef](inputs), False);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_fn_pair(&crate_ctxt cx, TypeRef tfn) -> TypeRef {
|
|
||||||
ret T_struct(~[T_ptr(tfn), T_opaque_closure_ptr(cx)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_ptr(TypeRef t) -> TypeRef { ret llvm::LLVMPointerType(t, 0u); }
|
|
||||||
|
|
||||||
fn T_struct(&TypeRef[] elts) -> TypeRef {
|
|
||||||
ret llvm::LLVMStructType(std::ivec::to_ptr(elts), std::ivec::len(elts),
|
|
||||||
False);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_named_struct(&str name) -> TypeRef {
|
|
||||||
auto c = llvm::LLVMGetGlobalContext();
|
|
||||||
ret llvm::LLVMStructCreateNamed(c, str::buf(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_struct_body(TypeRef t, &TypeRef[] elts) {
|
|
||||||
llvm::LLVMStructSetBody(t, std::ivec::to_ptr(elts), std::ivec::len(elts),
|
|
||||||
False);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_empty_struct() -> TypeRef { ret T_struct(~[]); }
|
|
||||||
|
|
||||||
fn T_rust_object() -> TypeRef {
|
|
||||||
auto t = T_named_struct("rust_object");
|
|
||||||
auto e = T_ptr(T_empty_struct());
|
|
||||||
set_struct_body(t, ~[e,e]);
|
|
||||||
ret t;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_task() -> TypeRef {
|
|
||||||
auto t = T_named_struct("task");
|
|
||||||
|
|
||||||
auto elems = ~[T_int(), // Refcount
|
|
||||||
T_int(), // Delegate pointer
|
|
||||||
T_int(), // Stack segment pointer
|
|
||||||
T_int(), // Runtime SP
|
|
||||||
T_int(), // Rust SP
|
|
||||||
T_int(), // GC chain
|
|
||||||
|
|
||||||
T_int(), // Domain pointer
|
|
||||||
// Crate cache pointer
|
|
||||||
T_int()];
|
|
||||||
set_struct_body(t, elems);
|
|
||||||
ret t;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_tydesc_field(&crate_ctxt cx, int field) -> TypeRef {
|
|
||||||
// Bit of a kludge: pick the fn typeref out of the tydesc..
|
|
||||||
|
|
||||||
let TypeRef[] tydesc_elts =
|
|
||||||
std::ivec::init_elt[TypeRef](T_nil(), abi::n_tydesc_fields as uint);
|
|
||||||
llvm::LLVMGetStructElementTypes(cx.tydesc_type,
|
|
||||||
std::ivec::to_ptr[TypeRef](tydesc_elts));
|
|
||||||
auto t = llvm::LLVMGetElementType(tydesc_elts.(field));
|
|
||||||
ret t;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_glue_fn(&crate_ctxt cx) -> TypeRef {
|
|
||||||
auto s = "glue_fn";
|
|
||||||
if (cx.tn.name_has_type(s)) { ret cx.tn.get_type(s); }
|
|
||||||
auto t = T_tydesc_field(cx, abi::tydesc_field_drop_glue);
|
|
||||||
cx.tn.associate(s, t);
|
|
||||||
ret t;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_dtor(&@crate_ctxt ccx, &span sp) -> TypeRef {
|
|
||||||
ret type_of_fn_full(ccx, sp, ast::proto_fn, true,
|
|
||||||
~[], ty::mk_nil(ccx.tcx), 0u);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_cmp_glue_fn(&crate_ctxt cx) -> TypeRef {
|
|
||||||
auto s = "cmp_glue_fn";
|
|
||||||
if (cx.tn.name_has_type(s)) { ret cx.tn.get_type(s); }
|
|
||||||
auto t = T_tydesc_field(cx, abi::tydesc_field_cmp_glue);
|
|
||||||
cx.tn.associate(s, t);
|
|
||||||
ret t;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_tydesc(TypeRef taskptr_type) -> TypeRef {
|
|
||||||
auto tydesc = T_named_struct("tydesc");
|
|
||||||
auto tydescpp = T_ptr(T_ptr(tydesc));
|
|
||||||
auto pvoid = T_ptr(T_i8());
|
|
||||||
auto glue_fn_ty =
|
|
||||||
T_ptr(T_fn(~[T_ptr(T_nil()), taskptr_type, T_ptr(T_nil()), tydescpp,
|
|
||||||
pvoid], T_void()));
|
|
||||||
auto cmp_glue_fn_ty =
|
|
||||||
T_ptr(T_fn(~[T_ptr(T_i1()), taskptr_type, T_ptr(T_nil()), tydescpp,
|
|
||||||
pvoid, pvoid, T_i8()], T_void()));
|
|
||||||
|
|
||||||
auto elems = ~[tydescpp, // first_param
|
|
||||||
T_int(), // size
|
|
||||||
T_int(), // align
|
|
||||||
glue_fn_ty, // copy_glue
|
|
||||||
glue_fn_ty, // drop_glue
|
|
||||||
glue_fn_ty, // free_glue
|
|
||||||
glue_fn_ty, // sever_glue
|
|
||||||
glue_fn_ty, // mark_glue
|
|
||||||
glue_fn_ty, // obj_drop_glue
|
|
||||||
glue_fn_ty, // is_stateful
|
|
||||||
cmp_glue_fn_ty];
|
|
||||||
set_struct_body(tydesc, elems);
|
|
||||||
ret tydesc;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_array(TypeRef t, uint n) -> TypeRef { ret llvm::LLVMArrayType(t, n); }
|
|
||||||
|
|
||||||
fn T_vec(TypeRef t) -> TypeRef {
|
|
||||||
ret T_struct(~[T_int(), // Refcount
|
|
||||||
T_int(), // Alloc
|
|
||||||
T_int(), // Fill
|
|
||||||
|
|
||||||
T_int(), // Pad
|
|
||||||
// Body elements
|
|
||||||
T_array(t, 0u)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_opaque_vec_ptr() -> TypeRef { ret T_ptr(T_vec(T_int())); }
|
|
||||||
|
|
||||||
|
|
||||||
// Interior vector.
|
|
||||||
//
|
|
||||||
// TODO: Support user-defined vector sizes.
|
|
||||||
fn T_ivec(TypeRef t) -> TypeRef {
|
|
||||||
ret T_struct(~[T_int(), // Length ("fill"; if zero, heapified)
|
|
||||||
T_int(), // Alloc
|
|
||||||
T_array(t, abi::ivec_default_length)]); // Body elements
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Note that the size of this one is in bytes.
|
|
||||||
fn T_opaque_ivec() -> TypeRef {
|
|
||||||
ret T_struct(~[T_int(), // Length ("fill"; if zero, heapified)
|
|
||||||
T_int(), // Alloc
|
|
||||||
T_array(T_i8(), 0u)]); // Body elements
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_ivec_heap_part(TypeRef t) -> TypeRef {
|
|
||||||
ret T_struct(~[T_int(), // Real length
|
|
||||||
T_array(t, 0u)]); // Body elements
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Interior vector on the heap, also known as the "stub". Cast to this when
|
|
||||||
// the allocated length (second element of T_ivec above) is zero.
|
|
||||||
fn T_ivec_heap(TypeRef t) -> TypeRef {
|
|
||||||
ret T_struct(~[T_int(), // Length (zero)
|
|
||||||
T_int(), // Alloc
|
|
||||||
T_ptr(T_ivec_heap_part(t))]); // Pointer
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_opaque_ivec_heap_part() -> TypeRef {
|
|
||||||
ret T_struct(~[T_int(), // Real length
|
|
||||||
T_array(T_i8(), 0u)]); // Body elements
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_opaque_ivec_heap() -> TypeRef {
|
|
||||||
ret T_struct(~[T_int(), // Length (zero)
|
|
||||||
T_int(), // Alloc
|
|
||||||
T_ptr(T_opaque_ivec_heap_part())]); // Pointer
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_str() -> TypeRef { ret T_vec(T_i8()); }
|
|
||||||
|
|
||||||
fn T_box(TypeRef t) -> TypeRef { ret T_struct(~[T_int(), t]); }
|
|
||||||
|
|
||||||
fn T_port(TypeRef t) -> TypeRef {
|
|
||||||
ret T_struct(~[T_int()]); // Refcount
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_chan(TypeRef t) -> TypeRef {
|
|
||||||
ret T_struct(~[T_int()]); // Refcount
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_taskptr(&crate_ctxt cx) -> TypeRef { ret T_ptr(cx.task_type); }
|
|
||||||
|
|
||||||
|
|
||||||
// This type must never be used directly; it must always be cast away.
|
|
||||||
fn T_typaram(&type_names tn) -> TypeRef {
|
|
||||||
auto s = "typaram";
|
|
||||||
if (tn.name_has_type(s)) { ret tn.get_type(s); }
|
|
||||||
auto t = T_i8();
|
|
||||||
tn.associate(s, t);
|
|
||||||
ret t;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_typaram_ptr(&type_names tn) -> TypeRef { ret T_ptr(T_typaram(tn)); }
|
|
||||||
|
|
||||||
fn T_closure_ptr(&crate_ctxt cx, TypeRef lltarget_ty, TypeRef llbindings_ty,
|
|
||||||
uint n_ty_params) -> TypeRef {
|
|
||||||
// NB: keep this in sync with code in trans_bind; we're making
|
|
||||||
// an LLVM typeref structure that has the same "shape" as the ty::t
|
|
||||||
// it constructs.
|
|
||||||
|
|
||||||
ret T_ptr(T_box(T_struct(~[T_ptr(cx.tydesc_type), lltarget_ty,
|
|
||||||
llbindings_ty,
|
|
||||||
T_captured_tydescs(cx, n_ty_params)])));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_opaque_closure_ptr(&crate_ctxt cx) -> TypeRef {
|
|
||||||
auto s = "*closure";
|
|
||||||
if (cx.tn.name_has_type(s)) { ret cx.tn.get_type(s); }
|
|
||||||
auto t =
|
|
||||||
T_closure_ptr(cx,
|
|
||||||
T_struct(~[T_ptr(T_nil()), T_ptr(T_nil())]),
|
|
||||||
T_nil(),
|
|
||||||
0u);
|
|
||||||
cx.tn.associate(s, t);
|
|
||||||
ret t;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_tag(&type_names tn, uint size) -> TypeRef {
|
|
||||||
auto s = "tag_" + uint::to_str(size, 10u);
|
|
||||||
if (tn.name_has_type(s)) { ret tn.get_type(s); }
|
|
||||||
auto t = T_struct(~[T_int(), T_array(T_i8(), size)]);
|
|
||||||
tn.associate(s, t);
|
|
||||||
ret t;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_opaque_tag(&type_names tn) -> TypeRef {
|
|
||||||
auto s = "opaque_tag";
|
|
||||||
if (tn.name_has_type(s)) { ret tn.get_type(s); }
|
|
||||||
auto t = T_struct(~[T_int(), T_i8()]);
|
|
||||||
tn.associate(s, t);
|
|
||||||
ret t;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_opaque_tag_ptr(&type_names tn) -> TypeRef {
|
|
||||||
ret T_ptr(T_opaque_tag(tn));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_captured_tydescs(&crate_ctxt cx, uint n) -> TypeRef {
|
|
||||||
ret T_struct(std::ivec::init_elt[TypeRef](T_ptr(cx.tydesc_type), n));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_obj_ptr(&crate_ctxt cx, uint n_captured_tydescs) -> TypeRef {
|
|
||||||
// This function is not publicly exposed because it returns an incomplete
|
|
||||||
// type. The dynamically-sized fields follow the captured tydescs.
|
|
||||||
|
|
||||||
fn T_obj(&crate_ctxt cx, uint n_captured_tydescs) -> TypeRef {
|
|
||||||
ret T_struct(~[T_ptr(cx.tydesc_type),
|
|
||||||
T_captured_tydescs(cx, n_captured_tydescs)]);
|
|
||||||
}
|
|
||||||
ret T_ptr(T_box(T_obj(cx, n_captured_tydescs)));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn T_opaque_obj_ptr(&crate_ctxt cx) -> TypeRef { ret T_obj_ptr(cx, 0u); }
|
|
||||||
|
|
||||||
fn T_opaque_port_ptr() -> TypeRef { ret T_ptr(T_i8()); }
|
|
||||||
|
|
||||||
fn T_opaque_chan_ptr() -> TypeRef { ret T_ptr(T_i8()); }
|
|
||||||
|
|
||||||
|
|
||||||
// This function now fails if called on a type with dynamic size (as its
|
// This function now fails if called on a type with dynamic size (as its
|
||||||
// return value was always meaningless in that case anyhow). Beware!
|
// return value was always meaningless in that case anyhow). Beware!
|
||||||
//
|
//
|
||||||
|
@ -1009,106 +687,6 @@ fn sanitize(&str s) -> str {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// LLVM constant constructors.
|
|
||||||
fn C_null(TypeRef t) -> ValueRef { ret llvm::LLVMConstNull(t); }
|
|
||||||
|
|
||||||
fn C_integral(TypeRef t, uint u, Bool sign_extend) -> ValueRef {
|
|
||||||
// FIXME: We can't use LLVM::ULongLong with our existing minimal native
|
|
||||||
// API, which only knows word-sized args.
|
|
||||||
//
|
|
||||||
// ret llvm::LLVMConstInt(T_int(), t as LLVM::ULongLong, False);
|
|
||||||
//
|
|
||||||
|
|
||||||
ret llvm::LLVMRustConstSmallInt(t, u, sign_extend);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn C_float(&str s) -> ValueRef {
|
|
||||||
ret llvm::LLVMConstRealOfString(T_float(), str::buf(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn C_floating(&str s, TypeRef t) -> ValueRef {
|
|
||||||
ret llvm::LLVMConstRealOfString(t, str::buf(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn C_nil() -> ValueRef {
|
|
||||||
// NB: See comment above in T_void().
|
|
||||||
|
|
||||||
ret C_integral(T_i1(), 0u, False);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn C_bool(bool b) -> ValueRef {
|
|
||||||
if (b) {
|
|
||||||
ret C_integral(T_bool(), 1u, False);
|
|
||||||
} else { ret C_integral(T_bool(), 0u, False); }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn C_int(int i) -> ValueRef { ret C_integral(T_int(), i as uint, True); }
|
|
||||||
|
|
||||||
fn C_uint(uint i) -> ValueRef { ret C_integral(T_int(), i, False); }
|
|
||||||
|
|
||||||
fn C_u8(uint i) -> ValueRef { ret C_integral(T_i8(), i, False); }
|
|
||||||
|
|
||||||
|
|
||||||
// This is a 'c-like' raw string, which differs from
|
|
||||||
// our boxed-and-length-annotated strings.
|
|
||||||
fn C_cstr(&@crate_ctxt cx, &str s) -> ValueRef {
|
|
||||||
auto sc = llvm::LLVMConstString(str::buf(s), str::byte_len(s), False);
|
|
||||||
auto g =
|
|
||||||
llvm::LLVMAddGlobal(cx.llmod, val_ty(sc),
|
|
||||||
str::buf(cx.names.next("str")));
|
|
||||||
llvm::LLVMSetInitializer(g, sc);
|
|
||||||
llvm::LLVMSetGlobalConstant(g, True);
|
|
||||||
llvm::LLVMSetLinkage(g, lib::llvm::LLVMInternalLinkage as llvm::Linkage);
|
|
||||||
ret g;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// A rust boxed-and-length-annotated string.
|
|
||||||
fn C_str(&@crate_ctxt cx, &str s) -> ValueRef {
|
|
||||||
auto len = str::byte_len(s);
|
|
||||||
auto box =
|
|
||||||
C_struct(~[C_int(abi::const_refcount as int),
|
|
||||||
C_int(len + 1u as int), // 'alloc'
|
|
||||||
C_int(len + 1u as int), // 'fill'
|
|
||||||
C_int(0), // 'pad'
|
|
||||||
llvm::LLVMConstString(str::buf(s), len, False)]);
|
|
||||||
auto g =
|
|
||||||
llvm::LLVMAddGlobal(cx.llmod, val_ty(box),
|
|
||||||
str::buf(cx.names.next("str")));
|
|
||||||
llvm::LLVMSetInitializer(g, box);
|
|
||||||
llvm::LLVMSetGlobalConstant(g, True);
|
|
||||||
llvm::LLVMSetLinkage(g, lib::llvm::LLVMInternalLinkage as llvm::Linkage);
|
|
||||||
ret llvm::LLVMConstPointerCast(g, T_ptr(T_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a Plain Old LLVM String:
|
|
||||||
fn C_postr(&str s) -> ValueRef {
|
|
||||||
ret llvm::LLVMConstString(str::buf(s), str::byte_len(s), False);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn C_zero_byte_arr(uint size) -> ValueRef {
|
|
||||||
auto i = 0u;
|
|
||||||
let ValueRef[] elts = ~[];
|
|
||||||
while (i < size) { elts += ~[C_u8(0u)]; i += 1u; }
|
|
||||||
ret llvm::LLVMConstArray(T_i8(), std::ivec::to_ptr(elts),
|
|
||||||
std::ivec::len(elts));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn C_struct(&ValueRef[] elts) -> ValueRef {
|
|
||||||
ret llvm::LLVMConstStruct(std::ivec::to_ptr(elts), std::ivec::len(elts),
|
|
||||||
False);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn C_named_struct(TypeRef T, &ValueRef[] elts) -> ValueRef {
|
|
||||||
ret llvm::LLVMConstNamedStruct(T, std::ivec::to_ptr(elts),
|
|
||||||
std::ivec::len(elts));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn C_array(TypeRef ty, &ValueRef[] elts) -> ValueRef {
|
|
||||||
ret llvm::LLVMConstArray(ty, std::ivec::to_ptr(elts),
|
|
||||||
std::ivec::len(elts));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decl_fn(ModuleRef llmod, &str name, uint cc, TypeRef llty) -> ValueRef {
|
fn decl_fn(ModuleRef llmod, &str name, uint cc, TypeRef llty) -> ValueRef {
|
||||||
let ValueRef llfn = llvm::LLVMAddFunction(llmod, str::buf(name), llty);
|
let ValueRef llfn = llvm::LLVMAddFunction(llmod, str::buf(name), llty);
|
||||||
llvm::LLVMSetFunctionCallConv(llfn, cc);
|
llvm::LLVMSetFunctionCallConv(llfn, cc);
|
||||||
|
@ -9250,7 +8828,7 @@ fn create_crate_map(&@crate_ctxt ccx) -> ValueRef {
|
||||||
fn write_metadata(&@trans::crate_ctxt cx, &@ast::crate crate) {
|
fn write_metadata(&@trans::crate_ctxt cx, &@ast::crate crate) {
|
||||||
if (!cx.sess.get_opts().library) { ret; }
|
if (!cx.sess.get_opts().library) { ret; }
|
||||||
auto llmeta = C_postr(metadata::encoder::encode_metadata(cx, crate));
|
auto llmeta = C_postr(metadata::encoder::encode_metadata(cx, crate));
|
||||||
auto llconst = trans::C_struct(~[llmeta]);
|
auto llconst = trans_common::C_struct(~[llmeta]);
|
||||||
auto llglobal =
|
auto llglobal =
|
||||||
llvm::LLVMAddGlobal(cx.llmod, trans::val_ty(llconst),
|
llvm::LLVMAddGlobal(cx.llmod, trans::val_ty(llconst),
|
||||||
str::buf("rust_metadata"));
|
str::buf("rust_metadata"));
|
||||||
|
|
|
@ -16,9 +16,6 @@ import trans::block_ctxt;
|
||||||
import trans::new_sub_block_ctxt;
|
import trans::new_sub_block_ctxt;
|
||||||
import trans::new_scope_block_ctxt;
|
import trans::new_scope_block_ctxt;
|
||||||
import trans::load_if_immediate;
|
import trans::load_if_immediate;
|
||||||
import trans::C_int;
|
|
||||||
import trans::C_uint;
|
|
||||||
import trans::C_nil;
|
|
||||||
import trans::val_ty;
|
import trans::val_ty;
|
||||||
import ty::pat_ty;
|
import ty::pat_ty;
|
||||||
import syntax::ast;
|
import syntax::ast;
|
||||||
|
@ -26,6 +23,8 @@ import syntax::ast::def_id;
|
||||||
import syntax::codemap::span;
|
import syntax::codemap::span;
|
||||||
import util::common::lit_eq;
|
import util::common::lit_eq;
|
||||||
|
|
||||||
|
import trans_common::*;
|
||||||
|
|
||||||
// An option identifying a branch (either a literal or a tag variant)
|
// An option identifying a branch (either a literal or a tag variant)
|
||||||
tag opt {
|
tag opt {
|
||||||
lit(@ast::lit);
|
lit(@ast::lit);
|
||||||
|
@ -201,7 +200,7 @@ fn extract_variant_args(@block_ctxt bcx, ast::node_id pat_id,
|
||||||
(ccx.tcx, vdefs._0, vdefs._1).args);
|
(ccx.tcx, vdefs._0, vdefs._1).args);
|
||||||
if (size > 0u && ivec::len(variants) != 1u) {
|
if (size > 0u && ivec::len(variants) != 1u) {
|
||||||
auto tagptr = bcx.build.PointerCast
|
auto tagptr = bcx.build.PointerCast
|
||||||
(val, trans::T_opaque_tag_ptr(ccx.tn));
|
(val, trans_common::T_opaque_tag_ptr(ccx.tn));
|
||||||
blobptr = bcx.build.GEP(tagptr, ~[C_int(0), C_int(1)]);
|
blobptr = bcx.build.GEP(tagptr, ~[C_int(0), C_int(1)]);
|
||||||
}
|
}
|
||||||
auto i = 0u;
|
auto i = 0u;
|
||||||
|
@ -315,7 +314,7 @@ fn compile_submatch(@block_ctxt bcx, &match m, ValueRef[] vals, &mk_fail f,
|
||||||
kind = single;
|
kind = single;
|
||||||
} else {
|
} else {
|
||||||
auto tagptr = bcx.build.PointerCast
|
auto tagptr = bcx.build.PointerCast
|
||||||
(val, trans::T_opaque_tag_ptr(ccx.tn));
|
(val, trans_common::T_opaque_tag_ptr(ccx.tn));
|
||||||
auto discrimptr = bcx.build.GEP
|
auto discrimptr = bcx.build.GEP
|
||||||
(tagptr, ~[C_int(0), C_int(0)]);
|
(tagptr, ~[C_int(0), C_int(0)]);
|
||||||
test_val = bcx.build.Load(discrimptr);
|
test_val = bcx.build.Load(discrimptr);
|
||||||
|
|
487
src/comp/middle/trans_common.rs
Normal file
487
src/comp/middle/trans_common.rs
Normal file
|
@ -0,0 +1,487 @@
|
||||||
|
/**
|
||||||
|
Code that is useful in various trans modules.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
import std::int;
|
||||||
|
import std::str;
|
||||||
|
import std::uint;
|
||||||
|
import std::str::rustrt::sbuf;
|
||||||
|
import std::map;
|
||||||
|
import std::map::hashmap;
|
||||||
|
import std::option;
|
||||||
|
import std::option::some;
|
||||||
|
import std::option::none;
|
||||||
|
import std::fs;
|
||||||
|
import syntax::ast;
|
||||||
|
import syntax::walk;
|
||||||
|
import driver::session;
|
||||||
|
import middle::ty;
|
||||||
|
import back::link;
|
||||||
|
import back::x86;
|
||||||
|
import back::abi;
|
||||||
|
import back::upcall;
|
||||||
|
import syntax::visit;
|
||||||
|
import visit::vt;
|
||||||
|
import util::common;
|
||||||
|
import util::common::*;
|
||||||
|
import std::map::new_int_hash;
|
||||||
|
import std::map::new_str_hash;
|
||||||
|
import syntax::codemap::span;
|
||||||
|
import lib::llvm::llvm;
|
||||||
|
import lib::llvm::builder;
|
||||||
|
import lib::llvm::target_data;
|
||||||
|
import lib::llvm::type_names;
|
||||||
|
import lib::llvm::mk_target_data;
|
||||||
|
import lib::llvm::mk_type_names;
|
||||||
|
import lib::llvm::llvm::ModuleRef;
|
||||||
|
import lib::llvm::llvm::ValueRef;
|
||||||
|
import lib::llvm::llvm::TypeRef;
|
||||||
|
import lib::llvm::llvm::TypeHandleRef;
|
||||||
|
import lib::llvm::llvm::BuilderRef;
|
||||||
|
import lib::llvm::llvm::BasicBlockRef;
|
||||||
|
import lib::llvm::False;
|
||||||
|
import lib::llvm::True;
|
||||||
|
import lib::llvm::Bool;
|
||||||
|
import link::mangle_internal_name_by_type_only;
|
||||||
|
import link::mangle_internal_name_by_seq;
|
||||||
|
import link::mangle_internal_name_by_path;
|
||||||
|
import link::mangle_internal_name_by_path_and_seq;
|
||||||
|
import link::mangle_exported_name;
|
||||||
|
import metadata::creader;
|
||||||
|
import metadata::csearch;
|
||||||
|
import metadata::cstore;
|
||||||
|
import util::ppaux::ty_to_str;
|
||||||
|
import util::ppaux::ty_to_short_str;
|
||||||
|
import syntax::print::pprust::expr_to_str;
|
||||||
|
import syntax::print::pprust::path_to_str;
|
||||||
|
|
||||||
|
// FIXME: These should probably be pulled in here too.
|
||||||
|
import trans::crate_ctxt;
|
||||||
|
import trans::type_of_fn_full;
|
||||||
|
import trans::val_ty;
|
||||||
|
|
||||||
|
// LLVM type constructors.
|
||||||
|
fn T_void() -> TypeRef {
|
||||||
|
// Note: For the time being llvm is kinda busted here, it has the notion
|
||||||
|
// of a 'void' type that can only occur as part of the signature of a
|
||||||
|
// function, but no general unit type of 0-sized value. This is, afaict,
|
||||||
|
// vestigial from its C heritage, and we'll be attempting to submit a
|
||||||
|
// patch upstream to fix it. In the mean time we only model function
|
||||||
|
// outputs (Rust functions and C functions) using T_void, and model the
|
||||||
|
// Rust general purpose nil type you can construct as 1-bit (always
|
||||||
|
// zero). This makes the result incorrect for now -- things like a tuple
|
||||||
|
// of 10 nil values will have 10-bit size -- but it doesn't seem like we
|
||||||
|
// have any other options until it's fixed upstream.
|
||||||
|
|
||||||
|
ret llvm::LLVMVoidType();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_nil() -> TypeRef {
|
||||||
|
// NB: See above in T_void().
|
||||||
|
|
||||||
|
ret llvm::LLVMInt1Type();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_i1() -> TypeRef { ret llvm::LLVMInt1Type(); }
|
||||||
|
|
||||||
|
fn T_i8() -> TypeRef { ret llvm::LLVMInt8Type(); }
|
||||||
|
|
||||||
|
fn T_i16() -> TypeRef { ret llvm::LLVMInt16Type(); }
|
||||||
|
|
||||||
|
fn T_i32() -> TypeRef { ret llvm::LLVMInt32Type(); }
|
||||||
|
|
||||||
|
fn T_i64() -> TypeRef { ret llvm::LLVMInt64Type(); }
|
||||||
|
|
||||||
|
fn T_f32() -> TypeRef { ret llvm::LLVMFloatType(); }
|
||||||
|
|
||||||
|
fn T_f64() -> TypeRef { ret llvm::LLVMDoubleType(); }
|
||||||
|
|
||||||
|
fn T_bool() -> TypeRef { ret T_i1(); }
|
||||||
|
|
||||||
|
fn T_int() -> TypeRef {
|
||||||
|
// FIXME: switch on target type.
|
||||||
|
|
||||||
|
ret T_i32();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_float() -> TypeRef {
|
||||||
|
// FIXME: switch on target type.
|
||||||
|
|
||||||
|
ret T_f64();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_char() -> TypeRef { ret T_i32(); }
|
||||||
|
|
||||||
|
fn T_size_t() -> TypeRef {
|
||||||
|
// FIXME: switch on target type.
|
||||||
|
|
||||||
|
ret T_i32();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_fn(&TypeRef[] inputs, TypeRef output) -> TypeRef {
|
||||||
|
ret llvm::LLVMFunctionType(output, std::ivec::to_ptr(inputs),
|
||||||
|
std::ivec::len[TypeRef](inputs), False);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_fn_pair(&crate_ctxt cx, TypeRef tfn) -> TypeRef {
|
||||||
|
ret T_struct(~[T_ptr(tfn), T_opaque_closure_ptr(cx)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_ptr(TypeRef t) -> TypeRef { ret llvm::LLVMPointerType(t, 0u); }
|
||||||
|
|
||||||
|
fn T_struct(&TypeRef[] elts) -> TypeRef {
|
||||||
|
ret llvm::LLVMStructType(std::ivec::to_ptr(elts), std::ivec::len(elts),
|
||||||
|
False);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_named_struct(&str name) -> TypeRef {
|
||||||
|
auto c = llvm::LLVMGetGlobalContext();
|
||||||
|
ret llvm::LLVMStructCreateNamed(c, str::buf(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_struct_body(TypeRef t, &TypeRef[] elts) {
|
||||||
|
llvm::LLVMStructSetBody(t, std::ivec::to_ptr(elts), std::ivec::len(elts),
|
||||||
|
False);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_empty_struct() -> TypeRef { ret T_struct(~[]); }
|
||||||
|
|
||||||
|
fn T_rust_object() -> TypeRef {
|
||||||
|
auto t = T_named_struct("rust_object");
|
||||||
|
auto e = T_ptr(T_empty_struct());
|
||||||
|
set_struct_body(t, ~[e,e]);
|
||||||
|
ret t;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_task() -> TypeRef {
|
||||||
|
auto t = T_named_struct("task");
|
||||||
|
|
||||||
|
auto elems = ~[T_int(), // Refcount
|
||||||
|
T_int(), // Delegate pointer
|
||||||
|
T_int(), // Stack segment pointer
|
||||||
|
T_int(), // Runtime SP
|
||||||
|
T_int(), // Rust SP
|
||||||
|
T_int(), // GC chain
|
||||||
|
|
||||||
|
T_int(), // Domain pointer
|
||||||
|
// Crate cache pointer
|
||||||
|
T_int()];
|
||||||
|
set_struct_body(t, elems);
|
||||||
|
ret t;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_tydesc_field(&crate_ctxt cx, int field) -> TypeRef {
|
||||||
|
// Bit of a kludge: pick the fn typeref out of the tydesc..
|
||||||
|
|
||||||
|
let TypeRef[] tydesc_elts =
|
||||||
|
std::ivec::init_elt[TypeRef](T_nil(), abi::n_tydesc_fields as uint);
|
||||||
|
llvm::LLVMGetStructElementTypes(cx.tydesc_type,
|
||||||
|
std::ivec::to_ptr[TypeRef](tydesc_elts));
|
||||||
|
auto t = llvm::LLVMGetElementType(tydesc_elts.(field));
|
||||||
|
ret t;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_glue_fn(&crate_ctxt cx) -> TypeRef {
|
||||||
|
auto s = "glue_fn";
|
||||||
|
if (cx.tn.name_has_type(s)) { ret cx.tn.get_type(s); }
|
||||||
|
auto t = T_tydesc_field(cx, abi::tydesc_field_drop_glue);
|
||||||
|
cx.tn.associate(s, t);
|
||||||
|
ret t;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_dtor(&@crate_ctxt ccx, &span sp) -> TypeRef {
|
||||||
|
ret type_of_fn_full(ccx, sp, ast::proto_fn, true,
|
||||||
|
~[], ty::mk_nil(ccx.tcx), 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_cmp_glue_fn(&crate_ctxt cx) -> TypeRef {
|
||||||
|
auto s = "cmp_glue_fn";
|
||||||
|
if (cx.tn.name_has_type(s)) { ret cx.tn.get_type(s); }
|
||||||
|
auto t = T_tydesc_field(cx, abi::tydesc_field_cmp_glue);
|
||||||
|
cx.tn.associate(s, t);
|
||||||
|
ret t;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_tydesc(TypeRef taskptr_type) -> TypeRef {
|
||||||
|
auto tydesc = T_named_struct("tydesc");
|
||||||
|
auto tydescpp = T_ptr(T_ptr(tydesc));
|
||||||
|
auto pvoid = T_ptr(T_i8());
|
||||||
|
auto glue_fn_ty =
|
||||||
|
T_ptr(T_fn(~[T_ptr(T_nil()), taskptr_type, T_ptr(T_nil()), tydescpp,
|
||||||
|
pvoid], T_void()));
|
||||||
|
auto cmp_glue_fn_ty =
|
||||||
|
T_ptr(T_fn(~[T_ptr(T_i1()), taskptr_type, T_ptr(T_nil()), tydescpp,
|
||||||
|
pvoid, pvoid, T_i8()], T_void()));
|
||||||
|
|
||||||
|
auto elems = ~[tydescpp, // first_param
|
||||||
|
T_int(), // size
|
||||||
|
T_int(), // align
|
||||||
|
glue_fn_ty, // copy_glue
|
||||||
|
glue_fn_ty, // drop_glue
|
||||||
|
glue_fn_ty, // free_glue
|
||||||
|
glue_fn_ty, // sever_glue
|
||||||
|
glue_fn_ty, // mark_glue
|
||||||
|
glue_fn_ty, // obj_drop_glue
|
||||||
|
glue_fn_ty, // is_stateful
|
||||||
|
cmp_glue_fn_ty];
|
||||||
|
set_struct_body(tydesc, elems);
|
||||||
|
ret tydesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_array(TypeRef t, uint n) -> TypeRef { ret llvm::LLVMArrayType(t, n); }
|
||||||
|
|
||||||
|
fn T_vec(TypeRef t) -> TypeRef {
|
||||||
|
ret T_struct(~[T_int(), // Refcount
|
||||||
|
T_int(), // Alloc
|
||||||
|
T_int(), // Fill
|
||||||
|
|
||||||
|
T_int(), // Pad
|
||||||
|
// Body elements
|
||||||
|
T_array(t, 0u)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_opaque_vec_ptr() -> TypeRef { ret T_ptr(T_vec(T_int())); }
|
||||||
|
|
||||||
|
|
||||||
|
// Interior vector.
|
||||||
|
//
|
||||||
|
// TODO: Support user-defined vector sizes.
|
||||||
|
fn T_ivec(TypeRef t) -> TypeRef {
|
||||||
|
ret T_struct(~[T_int(), // Length ("fill"; if zero, heapified)
|
||||||
|
T_int(), // Alloc
|
||||||
|
T_array(t, abi::ivec_default_length)]); // Body elements
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Note that the size of this one is in bytes.
|
||||||
|
fn T_opaque_ivec() -> TypeRef {
|
||||||
|
ret T_struct(~[T_int(), // Length ("fill"; if zero, heapified)
|
||||||
|
T_int(), // Alloc
|
||||||
|
T_array(T_i8(), 0u)]); // Body elements
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_ivec_heap_part(TypeRef t) -> TypeRef {
|
||||||
|
ret T_struct(~[T_int(), // Real length
|
||||||
|
T_array(t, 0u)]); // Body elements
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Interior vector on the heap, also known as the "stub". Cast to this when
|
||||||
|
// the allocated length (second element of T_ivec above) is zero.
|
||||||
|
fn T_ivec_heap(TypeRef t) -> TypeRef {
|
||||||
|
ret T_struct(~[T_int(), // Length (zero)
|
||||||
|
T_int(), // Alloc
|
||||||
|
T_ptr(T_ivec_heap_part(t))]); // Pointer
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_opaque_ivec_heap_part() -> TypeRef {
|
||||||
|
ret T_struct(~[T_int(), // Real length
|
||||||
|
T_array(T_i8(), 0u)]); // Body elements
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_opaque_ivec_heap() -> TypeRef {
|
||||||
|
ret T_struct(~[T_int(), // Length (zero)
|
||||||
|
T_int(), // Alloc
|
||||||
|
T_ptr(T_opaque_ivec_heap_part())]); // Pointer
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_str() -> TypeRef { ret T_vec(T_i8()); }
|
||||||
|
|
||||||
|
fn T_box(TypeRef t) -> TypeRef { ret T_struct(~[T_int(), t]); }
|
||||||
|
|
||||||
|
fn T_port(TypeRef t) -> TypeRef {
|
||||||
|
ret T_struct(~[T_int()]); // Refcount
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_chan(TypeRef t) -> TypeRef {
|
||||||
|
ret T_struct(~[T_int()]); // Refcount
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_taskptr(&crate_ctxt cx) -> TypeRef { ret T_ptr(cx.task_type); }
|
||||||
|
|
||||||
|
|
||||||
|
// This type must never be used directly; it must always be cast away.
|
||||||
|
fn T_typaram(&type_names tn) -> TypeRef {
|
||||||
|
auto s = "typaram";
|
||||||
|
if (tn.name_has_type(s)) { ret tn.get_type(s); }
|
||||||
|
auto t = T_i8();
|
||||||
|
tn.associate(s, t);
|
||||||
|
ret t;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_typaram_ptr(&type_names tn) -> TypeRef { ret T_ptr(T_typaram(tn)); }
|
||||||
|
|
||||||
|
fn T_closure_ptr(&crate_ctxt cx, TypeRef lltarget_ty, TypeRef llbindings_ty,
|
||||||
|
uint n_ty_params) -> TypeRef {
|
||||||
|
// NB: keep this in sync with code in trans_bind; we're making
|
||||||
|
// an LLVM typeref structure that has the same "shape" as the ty::t
|
||||||
|
// it constructs.
|
||||||
|
|
||||||
|
ret T_ptr(T_box(T_struct(~[T_ptr(cx.tydesc_type), lltarget_ty,
|
||||||
|
llbindings_ty,
|
||||||
|
T_captured_tydescs(cx, n_ty_params)])));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_opaque_closure_ptr(&crate_ctxt cx) -> TypeRef {
|
||||||
|
auto s = "*closure";
|
||||||
|
if (cx.tn.name_has_type(s)) { ret cx.tn.get_type(s); }
|
||||||
|
auto t =
|
||||||
|
T_closure_ptr(cx,
|
||||||
|
T_struct(~[T_ptr(T_nil()), T_ptr(T_nil())]),
|
||||||
|
T_nil(),
|
||||||
|
0u);
|
||||||
|
cx.tn.associate(s, t);
|
||||||
|
ret t;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_tag(&type_names tn, uint size) -> TypeRef {
|
||||||
|
auto s = "tag_" + uint::to_str(size, 10u);
|
||||||
|
if (tn.name_has_type(s)) { ret tn.get_type(s); }
|
||||||
|
auto t = T_struct(~[T_int(), T_array(T_i8(), size)]);
|
||||||
|
tn.associate(s, t);
|
||||||
|
ret t;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_opaque_tag(&type_names tn) -> TypeRef {
|
||||||
|
auto s = "opaque_tag";
|
||||||
|
if (tn.name_has_type(s)) { ret tn.get_type(s); }
|
||||||
|
auto t = T_struct(~[T_int(), T_i8()]);
|
||||||
|
tn.associate(s, t);
|
||||||
|
ret t;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_opaque_tag_ptr(&type_names tn) -> TypeRef {
|
||||||
|
ret T_ptr(T_opaque_tag(tn));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_captured_tydescs(&crate_ctxt cx, uint n) -> TypeRef {
|
||||||
|
ret T_struct(std::ivec::init_elt[TypeRef](T_ptr(cx.tydesc_type), n));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_obj_ptr(&crate_ctxt cx, uint n_captured_tydescs) -> TypeRef {
|
||||||
|
// This function is not publicly exposed because it returns an incomplete
|
||||||
|
// type. The dynamically-sized fields follow the captured tydescs.
|
||||||
|
|
||||||
|
fn T_obj(&crate_ctxt cx, uint n_captured_tydescs) -> TypeRef {
|
||||||
|
ret T_struct(~[T_ptr(cx.tydesc_type),
|
||||||
|
T_captured_tydescs(cx, n_captured_tydescs)]);
|
||||||
|
}
|
||||||
|
ret T_ptr(T_box(T_obj(cx, n_captured_tydescs)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn T_opaque_obj_ptr(&crate_ctxt cx) -> TypeRef { ret T_obj_ptr(cx, 0u); }
|
||||||
|
|
||||||
|
fn T_opaque_port_ptr() -> TypeRef { ret T_ptr(T_i8()); }
|
||||||
|
|
||||||
|
fn T_opaque_chan_ptr() -> TypeRef { ret T_ptr(T_i8()); }
|
||||||
|
|
||||||
|
|
||||||
|
// LLVM constant constructors.
|
||||||
|
fn C_null(TypeRef t) -> ValueRef { ret llvm::LLVMConstNull(t); }
|
||||||
|
|
||||||
|
fn C_integral(TypeRef t, uint u, Bool sign_extend) -> ValueRef {
|
||||||
|
// FIXME: We can't use LLVM::ULongLong with our existing minimal native
|
||||||
|
// API, which only knows word-sized args.
|
||||||
|
//
|
||||||
|
// ret llvm::LLVMConstInt(T_int(), t as LLVM::ULongLong, False);
|
||||||
|
//
|
||||||
|
|
||||||
|
ret llvm::LLVMRustConstSmallInt(t, u, sign_extend);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn C_float(&str s) -> ValueRef {
|
||||||
|
ret llvm::LLVMConstRealOfString(T_float(), str::buf(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn C_floating(&str s, TypeRef t) -> ValueRef {
|
||||||
|
ret llvm::LLVMConstRealOfString(t, str::buf(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn C_nil() -> ValueRef {
|
||||||
|
// NB: See comment above in T_void().
|
||||||
|
|
||||||
|
ret C_integral(T_i1(), 0u, False);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn C_bool(bool b) -> ValueRef {
|
||||||
|
if (b) {
|
||||||
|
ret C_integral(T_bool(), 1u, False);
|
||||||
|
} else { ret C_integral(T_bool(), 0u, False); }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn C_int(int i) -> ValueRef { ret C_integral(T_int(), i as uint, True); }
|
||||||
|
|
||||||
|
fn C_uint(uint i) -> ValueRef { ret C_integral(T_int(), i, False); }
|
||||||
|
|
||||||
|
fn C_u8(uint i) -> ValueRef { ret C_integral(T_i8(), i, False); }
|
||||||
|
|
||||||
|
|
||||||
|
// This is a 'c-like' raw string, which differs from
|
||||||
|
// our boxed-and-length-annotated strings.
|
||||||
|
fn C_cstr(&@crate_ctxt cx, &str s) -> ValueRef {
|
||||||
|
auto sc = llvm::LLVMConstString(str::buf(s), str::byte_len(s), False);
|
||||||
|
auto g =
|
||||||
|
llvm::LLVMAddGlobal(cx.llmod, val_ty(sc),
|
||||||
|
str::buf(cx.names.next("str")));
|
||||||
|
llvm::LLVMSetInitializer(g, sc);
|
||||||
|
llvm::LLVMSetGlobalConstant(g, True);
|
||||||
|
llvm::LLVMSetLinkage(g, lib::llvm::LLVMInternalLinkage as llvm::Linkage);
|
||||||
|
ret g;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A rust boxed-and-length-annotated string.
|
||||||
|
fn C_str(&@crate_ctxt cx, &str s) -> ValueRef {
|
||||||
|
auto len = str::byte_len(s);
|
||||||
|
auto box =
|
||||||
|
C_struct(~[C_int(abi::const_refcount as int),
|
||||||
|
C_int(len + 1u as int), // 'alloc'
|
||||||
|
C_int(len + 1u as int), // 'fill'
|
||||||
|
C_int(0), // 'pad'
|
||||||
|
llvm::LLVMConstString(str::buf(s), len, False)]);
|
||||||
|
auto g =
|
||||||
|
llvm::LLVMAddGlobal(cx.llmod, val_ty(box),
|
||||||
|
str::buf(cx.names.next("str")));
|
||||||
|
llvm::LLVMSetInitializer(g, box);
|
||||||
|
llvm::LLVMSetGlobalConstant(g, True);
|
||||||
|
llvm::LLVMSetLinkage(g, lib::llvm::LLVMInternalLinkage as llvm::Linkage);
|
||||||
|
ret llvm::LLVMConstPointerCast(g, T_ptr(T_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a Plain Old LLVM String:
|
||||||
|
fn C_postr(&str s) -> ValueRef {
|
||||||
|
ret llvm::LLVMConstString(str::buf(s), str::byte_len(s), False);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn C_zero_byte_arr(uint size) -> ValueRef {
|
||||||
|
auto i = 0u;
|
||||||
|
let ValueRef[] elts = ~[];
|
||||||
|
while (i < size) { elts += ~[C_u8(0u)]; i += 1u; }
|
||||||
|
ret llvm::LLVMConstArray(T_i8(), std::ivec::to_ptr(elts),
|
||||||
|
std::ivec::len(elts));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn C_struct(&ValueRef[] elts) -> ValueRef {
|
||||||
|
ret llvm::LLVMConstStruct(std::ivec::to_ptr(elts), std::ivec::len(elts),
|
||||||
|
False);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn C_named_struct(TypeRef T, &ValueRef[] elts) -> ValueRef {
|
||||||
|
ret llvm::LLVMConstNamedStruct(T, std::ivec::to_ptr(elts),
|
||||||
|
std::ivec::len(elts));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn C_array(TypeRef ty, &ValueRef[] elts) -> ValueRef {
|
||||||
|
ret llvm::LLVMConstArray(ty, std::ivec::to_ptr(elts),
|
||||||
|
std::ivec::len(elts));
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ use std (name = "std",
|
||||||
url = "http://rust-lang.org/src/std");
|
url = "http://rust-lang.org/src/std");
|
||||||
|
|
||||||
mod middle {
|
mod middle {
|
||||||
|
mod trans_common;
|
||||||
mod trans;
|
mod trans;
|
||||||
mod trans_alt;
|
mod trans_alt;
|
||||||
mod ty;
|
mod ty;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue