2 Code that is useful in various trans modules.
6 import core::{int, vec, str, uint, option, unsafe};
8 import std::map::hashmap;
11 import driver::session;
12 import middle::{resolve, ty};
13 import back::{link, abi, upcall};
14 import util::common::*;
15 import syntax::codemap::span;
16 import lib::llvm::{llvm, target_data, type_names};
17 import lib::llvm::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef};
18 import lib::llvm::{True, False, Bool};
19 import metadata::{csearch};
21 // FIXME: These should probably be pulled in here too.
22 import trans::{type_of_fn, drop_ty};
24 obj namegen(mutable i: int) {
25 fn next(prefix: str) -> str { i += 1; ret prefix + int::str(i); }
28 type derived_tydesc_info = {lltydesc: ValueRef, escapes: bool};
31 tk_static; // Static (monomorphic) type descriptor.
32 tk_param; // Type parameter.
33 tk_derived; // Derived from a typaram or another derived tydesc.
41 mutable take_glue: option::t<ValueRef>,
42 mutable drop_glue: option::t<ValueRef>,
43 mutable free_glue: option::t<ValueRef>,
44 mutable cmp_glue: option::t<ValueRef>,
49 * A note on nomenclature of linking: "upcall", "extern" and "native".
51 * An "extern" is an LLVM symbol we wind up emitting an undefined external
52 * reference to. This means "we don't have the thing in this compilation unit,
53 * please make sure you link it in at runtime". This could be a reference to
54 * C code found in a C library, or rust code found in a rust crate.
56 * A "native" is an extern that references C code. Called with cdecl.
58 * An upcall is a native call generated by the compiler (not corresponding to
59 * any user-written call in the code) into librustrt, to perform some helper
60 * task such as bringing a task to life, allocating memory, etc.
64 {mutable n_static_tydescs: uint,
65 mutable n_derived_tydescs: uint,
66 mutable n_glues_created: uint,
67 mutable n_null_glues: uint,
68 mutable n_real_glues: uint,
69 fn_times: @mutable [{ident: str, time: int}]};
71 resource BuilderRef_res(B: llvm::BuilderRef) { llvm::LLVMDisposeBuilder(B); }
73 // Crate context. Every crate we compile has one of these.
75 // A mapping from the def_id of each item in this crate to the address
76 // of the first instruction of the item's definition in the executable
78 // TODO: hashmap<tup(tag_id,subtys), @tag_info>
79 {sess: session::session,
83 externs: hashmap<str, ValueRef>,
84 intrinsics: hashmap<str, ValueRef>,
85 item_ids: hashmap<ast::node_id, ValueRef>,
86 ast_map: ast_map::map,
87 exp_map: resolve::exp_map,
88 item_symbols: hashmap<ast::node_id, str>,
89 mutable main_fn: option::t<ValueRef>,
90 link_meta: link::link_meta,
91 tag_sizes: hashmap<ty::t, uint>,
92 discrims: hashmap<ast::def_id, ValueRef>,
93 discrim_symbols: hashmap<ast::node_id, str>,
94 consts: hashmap<ast::node_id, ValueRef>,
95 tydescs: hashmap<ty::t, @tydesc_info>,
96 dicts: hashmap<dict_id, ValueRef>,
97 module_data: hashmap<str, ValueRef>,
98 lltypes: hashmap<ty::t, TypeRef>,
100 sha: std::sha1::sha1,
101 type_sha1s: hashmap<ty::t, str>,
102 type_short_names: hashmap<ty::t, str>,
104 mut_map: mut::mut_map,
105 copy_map: alias::copy_map,
106 last_uses: last_use::last_uses,
107 method_map: typeck::method_map,
108 dict_map: typeck::dict_map,
110 upcalls: @upcall::upcalls,
111 rust_object_type: TypeRef,
112 tydesc_type: TypeRef,
116 opaque_vec_type: TypeRef,
117 builder: BuilderRef_res,
118 shape_cx: shape::ctxt,
121 dbg_cx: option::t<@debuginfo::debug_ctxt>};
126 obj_typarams: [ast::ty_param],
127 obj_fields: [ast::obj_field],
130 // Types used for llself.
131 type val_self_pair = {v: ValueRef, t: ty::t};
133 tag local_val { local_mem(ValueRef); local_imm(ValueRef); }
135 type fn_ty_param = {desc: ValueRef, dicts: option::t<[ValueRef]>};
137 // Function context. Every LLVM function we create will have one of
140 // The ValueRef returned from a call to llvm::LLVMAddFunction; the
141 // address of the first instruction in the sequence of
142 // instructions for this function that will go in the .text
143 // section of the executable we're generating.
145 // The three implicit arguments that arrive in the function we're
146 // creating. For instance, foo(int, int) is really foo(ret*,
147 // task*, env*, int, int). These are also available via
148 // llvm::LLVMGetParam(llfn, uint) where uint = 1, 2, 0
149 // respectively, but we unpack them into these fields for
152 // Points to the current task.
154 // Points to the current environment (bindings of variables to
155 // values), if this is a regular function; points to the current
156 // object, if this is a method.
158 // Points to where the return value of this function should end
161 // The next three elements: "hoisted basic blocks" containing
162 // administrative activities that have to happen in only one place in
163 // the function, due to LLVM's quirks.
165 // A block for all the function's static allocas, so that LLVM
166 // will coalesce them into a single alloca call.
168 // A block containing code that copies incoming arguments to space
169 // already allocated by code in one of the llallocas blocks.
170 // (LLVM requires that arguments be copied to local allocas before
171 // allowing most any operation to be performed on them.)
173 // The first block containing derived tydescs received from the
174 // runtime. See description of derived_tydescs, below.
176 // The last block of the llderivedtydescs group.
178 // A block for all of the dynamically sized allocas. This must be
179 // after llderivedtydescs, because these sometimes depend on
180 // information computed from derived tydescs.
182 // The token used to clear the dynamic allocas at the end of this frame.
184 // The 'self' object currently in use in this function, if there
187 // If this function is actually a iter, a block containing the
188 // code called whenever the iter calls 'put'.
190 // The next four items: hash tables mapping from AST def_ids to
191 // LLVM-stuff-in-the-frame.
193 // Maps arguments to allocas created for them in llallocas.
195 // Maps fields in objects to pointers into the interior of
198 // Maps the def_ids for local variables to the allocas created for
199 // them in llallocas.
201 // The same as above, but for variables accessed via the frame
202 // pointer we pass into an iter, for access to the static
203 // environment of the iter-calling frame.
205 // For convenience, a vector of the incoming tydescs for each of
206 // this functions type parameters, fetched via llvm::LLVMGetParam.
207 // For example, for a function foo::<A, B, C>(), lltydescs contains
208 // the ValueRefs for the tydescs for A, B, and C.
210 // Derived tydescs are tydescs created at runtime, for types that
211 // involve type parameters inside type constructors. For example,
212 // suppose a function parameterized by T creates a vector of type
213 // [T]. The function doesn't know what T is until runtime, and
214 // the function's caller knows T but doesn't know that a vector is
215 // involved. So a tydesc for [T] can't be created until runtime,
216 // when information about both "[T]" and "T" are available. When
217 // such a tydesc is created, we cache it in the derived_tydescs
218 // table for the next time that such a tydesc is needed.
220 // The node_id of the function, or -1 if it doesn't correspond to
221 // a user-defined function.
223 // The source span where this function comes from, for error
226 // This function's enclosing local context.
230 mutable llstaticallocas: BasicBlockRef,
231 mutable llloadenv: BasicBlockRef,
232 mutable llderivedtydescs_first: BasicBlockRef,
233 mutable llderivedtydescs: BasicBlockRef,
234 mutable lldynamicallocas: BasicBlockRef,
235 mutable llreturn: BasicBlockRef,
236 mutable llobstacktoken: option::t<ValueRef>,
237 mutable llself: option::t<val_self_pair>,
238 llargs: hashmap<ast::node_id, local_val>,
239 llobjfields: hashmap<ast::node_id, ValueRef>,
240 lllocals: hashmap<ast::node_id, local_val>,
241 llupvars: hashmap<ast::node_id, ValueRef>,
242 mutable lltyparams: [fn_ty_param],
243 derived_tydescs: hashmap<ty::t, derived_tydesc_info>,
245 ret_style: ast::ret_style,
250 clean(fn@(@block_ctxt) -> @block_ctxt);
251 clean_temp(ValueRef, fn@(@block_ctxt) -> @block_ctxt);
254 fn add_clean(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
255 if !ty::type_needs_drop(bcx_tcx(cx), ty) { ret; }
256 let scope_cx = find_scope_cx(cx);
257 scope_cx.cleanups += [clean(bind drop_ty(_, val, ty))];
258 scope_cx.lpad_dirty = true;
260 fn add_clean_temp(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
261 if !ty::type_needs_drop(bcx_tcx(cx), ty) { ret; }
262 fn do_drop(bcx: @block_ctxt, val: ValueRef, ty: ty::t) ->
264 if ty::type_is_immediate(bcx_tcx(bcx), ty) {
265 ret trans::drop_ty_immediate(bcx, val, ty);
267 ret drop_ty(bcx, val, ty);
270 let scope_cx = find_scope_cx(cx);
272 [clean_temp(val, bind do_drop(_, val, ty))];
273 scope_cx.lpad_dirty = true;
275 fn add_clean_temp_mem(cx: @block_ctxt, val: ValueRef, ty: ty::t) {
276 if !ty::type_needs_drop(bcx_tcx(cx), ty) { ret; }
277 let scope_cx = find_scope_cx(cx);
278 scope_cx.cleanups += [clean_temp(val, bind drop_ty(_, val, ty))];
279 scope_cx.lpad_dirty = true;
281 fn add_clean_free(cx: @block_ctxt, ptr: ValueRef, shared: bool) {
282 let scope_cx = find_scope_cx(cx);
283 let free_fn = if shared { bind trans::trans_shared_free(_, ptr) }
284 else { bind trans::trans_free_if_not_gc(_, ptr) };
285 scope_cx.cleanups += [clean_temp(ptr, free_fn)];
286 scope_cx.lpad_dirty = true;
289 // Note that this only works for temporaries. We should, at some point, move
290 // to a system where we can also cancel the cleanup on local variables, but
291 // this will be more involved. For now, we simply zero out the local, and the
292 // drop glue checks whether it is zero.
293 fn revoke_clean(cx: @block_ctxt, val: ValueRef) {
294 let sc_cx = find_scope_cx(cx);
297 for c: cleanup in sc_cx.cleanups {
300 if v as uint == val as uint { found = i; break; }
306 // The value does not have a cleanup associated with it.
307 if found == -1 { ret; }
308 // We found the cleanup and remove it
310 vec::slice(sc_cx.cleanups, 0u, found as uint) +
311 vec::slice(sc_cx.cleanups, (found as uint) + 1u,
312 vec::len(sc_cx.cleanups));
313 sc_cx.lpad_dirty = true;
317 fn get_res_dtor(ccx: @crate_ctxt, sp: span, did: ast::def_id, inner_t: ty::t)
319 if did.crate == ast::local_crate {
320 alt ccx.item_ids.find(did.node) {
322 _ { ccx.tcx.sess.bug("get_res_dtor: can't find resource dtor!"); }
326 let param_bounds = ty::lookup_item_type(ccx.tcx, did).bounds;
327 let nil_res = ty::mk_nil(ccx.tcx);
328 // FIXME: Silly check -- mk_nil should have a postcondition
329 check non_ty_var(ccx, nil_res);
330 let f_t = type_of_fn(ccx, sp, false,
331 [{mode: ast::by_ref, ty: inner_t}],
332 nil_res, *param_bounds);
333 ret trans::get_extern_const(ccx.externs, ccx.llmod,
334 csearch::get_symbol(ccx.sess.get_cstore(),
341 // A scope block is a basic block created by translating a block { ... }
342 // the the source language. Since these blocks create variable scope, any
343 // variables created in them that are still live at the end of the block
344 // must be dropped and cleaned up when the block ends.
348 // A basic block created from the body of a loop. Contains pointers to
349 // which block to jump to in the case of "continue" or "break", with the
350 // "continue" block optional, because "while" and "do while" don't support
351 // "continue" (TODO: is this intentional?)
352 LOOP_SCOPE_BLOCK(option::t<@block_ctxt>, @block_ctxt);
355 // A non-scope block is a basic block created as a translation artifact
356 // from translating code that expresses conditional logic rather than by
357 // explicit { ... } block structure in the source language. It's called a
358 // non-scope block because it doesn't introduce a new variable scope.
363 // Basic block context. We create a block context for each basic block
364 // (single-entry, single-exit sequence of instructions) we generate from Rust
365 // code. Each basic block we generate is attached to a function, typically
366 // with many basic blocks per function. All the basic blocks attached to a
367 // function are organized as a directed graph.
369 // The BasicBlockRef returned from a call to
370 // llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
371 // block to the function pointed to by llfn. We insert
372 // instructions into that block by way of this block context.
373 // The block pointing to this one in the function's digraph.
374 // The 'kind' of basic block this is.
375 // A list of functions that run at the end of translating this
376 // block, cleaning up any variables that were introduced in the
377 // block and need to go out of scope at the end of it.
378 // The source span where this block comes from, for error
379 // reporting. FIXME this is not currently reliable
380 // The function context for the function to which this block is
382 {llbb: BasicBlockRef,
383 mutable terminated: bool,
384 mutable unreachable: bool,
385 parent: block_parent,
387 mutable cleanups: [cleanup],
388 mutable lpad_dirty: bool,
389 mutable lpad: option::t<BasicBlockRef>,
393 // FIXME: we should be able to use option::t<@block_parent> here but
394 // the infinite-tag check in rustboot gets upset.
395 tag block_parent { parent_none; parent_some(@block_ctxt); }
397 type result = {bcx: @block_ctxt, val: ValueRef};
398 type result_t = {bcx: @block_ctxt, val: ValueRef, ty: ty::t};
400 fn extend_path(cx: @local_ctxt, name: str) -> @local_ctxt {
401 ret @{path: cx.path + [name] with *cx};
404 fn rslt(bcx: @block_ctxt, val: ValueRef) -> result {
408 fn ty_str(tn: type_names, t: TypeRef) -> str {
409 ret lib::llvm::type_to_str(tn, t);
412 fn val_ty(&&v: ValueRef) -> TypeRef { ret llvm::LLVMTypeOf(v); }
414 fn val_str(tn: type_names, v: ValueRef) -> str { ret ty_str(tn, val_ty(v)); }
416 // Returns the nth element of the given LLVM structure type.
417 fn struct_elt(llstructty: TypeRef, n: uint) -> TypeRef unsafe {
418 let elt_count = llvm::LLVMCountStructElementTypes(llstructty);
419 assert (n < elt_count);
420 let elt_tys = vec::init_elt(T_nil(), elt_count);
421 llvm::LLVMGetStructElementTypes(llstructty, to_ptr(elt_tys));
422 ret llvm::LLVMGetElementType(elt_tys[n]);
425 fn find_scope_cx(cx: @block_ctxt) -> @block_ctxt {
426 if cx.kind != NON_SCOPE_BLOCK { ret cx; }
428 parent_some(b) { ret find_scope_cx(b); }
430 cx.fcx.lcx.ccx.sess.bug("trans::find_scope_cx() " +
431 "called on parentless block_ctxt");
437 // TODO: When we have overloading, simplify these names!
439 pure fn bcx_tcx(bcx: @block_ctxt) -> ty::ctxt { ret bcx.fcx.lcx.ccx.tcx; }
440 pure fn bcx_ccx(bcx: @block_ctxt) -> @crate_ctxt { ret bcx.fcx.lcx.ccx; }
441 pure fn bcx_lcx(bcx: @block_ctxt) -> @local_ctxt { ret bcx.fcx.lcx; }
442 pure fn bcx_fcx(bcx: @block_ctxt) -> @fn_ctxt { ret bcx.fcx; }
443 pure fn fcx_ccx(fcx: @fn_ctxt) -> @crate_ctxt { ret fcx.lcx.ccx; }
444 pure fn fcx_tcx(fcx: @fn_ctxt) -> ty::ctxt { ret fcx.lcx.ccx.tcx; }
445 pure fn lcx_ccx(lcx: @local_ctxt) -> @crate_ctxt { ret lcx.ccx; }
446 pure fn ccx_tcx(ccx: @crate_ctxt) -> ty::ctxt { ret ccx.tcx; }
448 // LLVM type constructors.
449 fn T_void() -> TypeRef {
450 // Note: For the time being llvm is kinda busted here, it has the notion
451 // of a 'void' type that can only occur as part of the signature of a
452 // function, but no general unit type of 0-sized value. This is, afaict,
453 // vestigial from its C heritage, and we'll be attempting to submit a
454 // patch upstream to fix it. In the mean time we only model function
455 // outputs (Rust functions and C functions) using T_void, and model the
456 // Rust general purpose nil type you can construct as 1-bit (always
457 // zero). This makes the result incorrect for now -- things like a tuple
458 // of 10 nil values will have 10-bit size -- but it doesn't seem like we
459 // have any other options until it's fixed upstream.
461 ret llvm::LLVMVoidType();
464 fn T_nil() -> TypeRef {
465 // NB: See above in T_void().
467 ret llvm::LLVMInt1Type();
470 fn T_metadata() -> TypeRef { ret llvm::LLVMMetadataType(); }
472 fn T_i1() -> TypeRef { ret llvm::LLVMInt1Type(); }
474 fn T_i8() -> TypeRef { ret llvm::LLVMInt8Type(); }
476 fn T_i16() -> TypeRef { ret llvm::LLVMInt16Type(); }
478 fn T_i32() -> TypeRef { ret llvm::LLVMInt32Type(); }
480 fn T_i64() -> TypeRef { ret llvm::LLVMInt64Type(); }
482 fn T_f32() -> TypeRef { ret llvm::LLVMFloatType(); }
484 fn T_f64() -> TypeRef { ret llvm::LLVMDoubleType(); }
486 fn T_bool() -> TypeRef { ret T_i1(); }
488 fn T_int(targ_cfg: @session::config) -> TypeRef {
489 ret alt targ_cfg.arch {
490 session::arch_x86. { T_i32() }
491 session::arch_x86_64. { T_i64() }
492 session::arch_arm. { T_i32() }
496 fn T_int_ty(cx: @crate_ctxt, t: ast::int_ty) -> TypeRef {
498 ast::ty_i. { cx.int_type }
499 ast::ty_char. { T_char() }
500 ast::ty_i8. { T_i8() }
501 ast::ty_i16. { T_i16() }
502 ast::ty_i32. { T_i32() }
503 ast::ty_i64. { T_i64() }
507 fn T_uint_ty(cx: @crate_ctxt, t: ast::uint_ty) -> TypeRef {
509 ast::ty_u. { cx.int_type }
510 ast::ty_u8. { T_i8() }
511 ast::ty_u16. { T_i16() }
512 ast::ty_u32. { T_i32() }
513 ast::ty_u64. { T_i64() }
517 fn T_float_ty(cx: @crate_ctxt, t: ast::float_ty) -> TypeRef {
519 ast::ty_f. { cx.float_type }
520 ast::ty_f32. { T_f32() }
521 ast::ty_f64. { T_f64() }
525 fn T_float(targ_cfg: @session::config) -> TypeRef {
526 ret alt targ_cfg.arch {
527 session::arch_x86. { T_f64() }
528 session::arch_x86_64. { T_f64() }
529 session::arch_arm. { T_f64() }
533 fn T_char() -> TypeRef { ret T_i32(); }
535 fn T_size_t(targ_cfg: @session::config) -> TypeRef {
539 fn T_fn(inputs: [TypeRef], output: TypeRef) -> TypeRef unsafe {
540 ret llvm::LLVMFunctionType(output, to_ptr(inputs),
541 vec::len::<TypeRef>(inputs), False);
544 fn T_fn_pair(cx: @crate_ctxt, tfn: TypeRef) -> TypeRef {
545 ret T_struct([T_ptr(tfn), T_opaque_boxed_closure_ptr(cx)]);
548 fn T_ptr(t: TypeRef) -> TypeRef { ret llvm::LLVMPointerType(t, 0u); }
550 fn T_struct(elts: [TypeRef]) -> TypeRef unsafe {
551 ret llvm::LLVMStructType(to_ptr(elts), vec::len(elts), False);
554 fn T_named_struct(name: str) -> TypeRef {
555 let c = llvm::LLVMGetGlobalContext();
556 ret str::as_buf(name, {|buf| llvm::LLVMStructCreateNamed(c, buf) });
559 fn set_struct_body(t: TypeRef, elts: [TypeRef]) unsafe {
560 llvm::LLVMStructSetBody(t, to_ptr(elts), vec::len(elts), False);
563 fn T_empty_struct() -> TypeRef { ret T_struct([]); }
565 // NB: This will return something different every time it's called. If
566 // you need a generic object type that matches the type of your
567 // existing objects, use ccx.rust_object_type. Calling
568 // T_rust_object() again will return a different one.
569 fn T_rust_object() -> TypeRef {
570 let t = T_named_struct("rust_object");
571 let e = T_ptr(T_empty_struct());
572 set_struct_body(t, [e, e]);
576 // A dict is, in reality, a vtable pointer followed by zero or more pointers
577 // to tydescs and other dicts that it closes over. But the types and number of
578 // those are rarely known to the code that needs to manipulate them, so they
579 // are described by this opaque type.
580 fn T_dict() -> TypeRef { T_array(T_ptr(T_i8()), 1u) }
582 fn T_task(targ_cfg: @session::config) -> TypeRef {
583 let t = T_named_struct("task");
587 // Stack segment pointer
594 // Crate cache pointer
596 let t_int = T_int(targ_cfg);
598 [t_int, t_int, t_int, t_int,
599 t_int, t_int, t_int, t_int];
600 set_struct_body(t, elems);
604 fn T_tydesc_field(cx: @crate_ctxt, field: int) -> TypeRef unsafe {
605 // Bit of a kludge: pick the fn typeref out of the tydesc..
607 let tydesc_elts: [TypeRef] =
608 vec::init_elt::<TypeRef>(T_nil(),
609 abi::n_tydesc_fields as uint);
610 llvm::LLVMGetStructElementTypes(cx.tydesc_type,
611 to_ptr::<TypeRef>(tydesc_elts));
612 let t = llvm::LLVMGetElementType(tydesc_elts[field]);
616 fn T_glue_fn(cx: @crate_ctxt) -> TypeRef {
618 if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
619 let t = T_tydesc_field(cx, abi::tydesc_field_drop_glue);
620 cx.tn.associate(s, t);
624 fn T_cmp_glue_fn(cx: @crate_ctxt) -> TypeRef {
625 let s = "cmp_glue_fn";
626 if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
627 let t = T_tydesc_field(cx, abi::tydesc_field_cmp_glue);
628 cx.tn.associate(s, t);
632 fn T_tydesc(targ_cfg: @session::config) -> TypeRef {
633 let tydesc = T_named_struct("tydesc");
634 let tydescpp = T_ptr(T_ptr(tydesc));
635 let pvoid = T_ptr(T_i8());
637 T_ptr(T_fn([T_ptr(T_nil()), T_ptr(T_nil()), tydescpp,
640 T_ptr(T_fn([T_ptr(T_i1()), T_ptr(tydesc), tydescpp,
641 pvoid, pvoid, T_i8()], T_void()));
643 let int_type = T_int(targ_cfg);
645 [tydescpp, int_type, int_type,
646 glue_fn_ty, glue_fn_ty, glue_fn_ty,
647 T_ptr(T_i8()), glue_fn_ty, glue_fn_ty, glue_fn_ty, cmp_glue_fn_ty,
648 T_ptr(T_i8()), T_ptr(T_i8()), int_type, int_type];
649 set_struct_body(tydesc, elems);
653 fn T_array(t: TypeRef, n: uint) -> TypeRef { ret llvm::LLVMArrayType(t, n); }
657 // TODO: Support user-defined vector sizes.
658 fn T_vec2(targ_cfg: @session::config, t: TypeRef) -> TypeRef {
659 ret T_struct([T_int(targ_cfg), // fill
660 T_int(targ_cfg), // alloc
661 T_array(t, 0u)]); // elements
664 fn T_vec(ccx: @crate_ctxt, t: TypeRef) -> TypeRef {
665 ret T_vec2(ccx.sess.get_targ_cfg(), t);
668 // Note that the size of this one is in bytes.
669 fn T_opaque_vec(targ_cfg: @session::config) -> TypeRef {
670 ret T_vec2(targ_cfg, T_i8());
673 fn T_box(cx: @crate_ctxt, t: TypeRef) -> TypeRef {
674 ret T_struct([cx.int_type, t]);
677 fn T_port(cx: @crate_ctxt, _t: TypeRef) -> TypeRef {
678 ret T_struct([cx.int_type]); // Refcount
682 fn T_chan(cx: @crate_ctxt, _t: TypeRef) -> TypeRef {
683 ret T_struct([cx.int_type]); // Refcount
687 fn T_taskptr(cx: @crate_ctxt) -> TypeRef { ret T_ptr(cx.task_type); }
690 // This type must never be used directly; it must always be cast away.
691 fn T_typaram(tn: type_names) -> TypeRef {
693 if tn.name_has_type(s) { ret tn.get_type(s); }
699 fn T_typaram_ptr(tn: type_names) -> TypeRef { ret T_ptr(T_typaram(tn)); }
701 fn T_closure(cx: @crate_ctxt,
702 llbindings_ty: TypeRef,
703 n_ty_params: uint) -> TypeRef {
704 ret T_struct([T_ptr(cx.tydesc_type),
705 T_captured_tydescs(cx, n_ty_params),
709 fn T_opaque_closure(cx: @crate_ctxt) -> TypeRef {
711 if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
712 let t = T_closure(cx, T_nil(), 0u);
713 cx.tn.associate(s, t);
717 fn T_boxed_closure_ptr(cx: @crate_ctxt, llbindings_ty: TypeRef,
718 n_ty_params: uint) -> TypeRef {
719 // NB: keep this in sync with code in trans_bind; we're making
720 // an LLVM typeref structure that has the same "shape" as the ty::t
722 ret T_ptr(T_box(cx, T_closure(cx, llbindings_ty, n_ty_params)));
725 fn T_opaque_boxed_closure_ptr(cx: @crate_ctxt) -> TypeRef {
727 if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
728 let t = T_boxed_closure_ptr(cx, T_nil(), 0u);
729 cx.tn.associate(s, t);
733 fn T_tag_variant(cx: @crate_ctxt) -> TypeRef {
737 fn T_tag(cx: @crate_ctxt, size: uint) -> TypeRef {
738 let s = "tag_" + uint::to_str(size, 10u);
739 if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
742 T_struct([T_tag_variant(cx)])
743 } else { T_struct([T_tag_variant(cx), T_array(T_i8(), size)]) };
744 cx.tn.associate(s, t);
748 fn T_opaque_tag(cx: @crate_ctxt) -> TypeRef {
749 let s = "opaque_tag";
750 if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
751 let t = T_struct([T_tag_variant(cx), T_i8()]);
752 cx.tn.associate(s, t);
756 fn T_opaque_tag_ptr(cx: @crate_ctxt) -> TypeRef {
757 ret T_ptr(T_opaque_tag(cx));
760 fn T_captured_tydescs(cx: @crate_ctxt, n: uint) -> TypeRef {
761 ret T_struct(vec::init_elt::<TypeRef>(T_ptr(cx.tydesc_type), n));
764 fn T_obj_ptr(cx: @crate_ctxt, n_captured_tydescs: uint) -> TypeRef {
765 // This function is not publicly exposed because it returns an incomplete
766 // type. The dynamically-sized fields follow the captured tydescs.
768 fn T_obj(cx: @crate_ctxt, n_captured_tydescs: uint) -> TypeRef {
769 ret T_struct([T_ptr(cx.tydesc_type),
770 T_captured_tydescs(cx, n_captured_tydescs)]);
772 ret T_ptr(T_box(cx, T_obj(cx, n_captured_tydescs)));
775 fn T_opaque_obj_ptr(cx: @crate_ctxt) -> TypeRef { ret T_obj_ptr(cx, 0u); }
777 fn T_opaque_port_ptr() -> TypeRef { ret T_ptr(T_i8()); }
779 fn T_opaque_chan_ptr() -> TypeRef { ret T_ptr(T_i8()); }
782 // LLVM constant constructors.
783 fn C_null(t: TypeRef) -> ValueRef { ret llvm::LLVMConstNull(t); }
785 fn C_integral(t: TypeRef, u: u64, sign_extend: Bool) -> ValueRef {
786 let u_hi = (u >> 32u64) as uint;
787 let u_lo = u as uint;
788 ret llvm::LLVMRustConstInt(t, u_hi, u_lo, sign_extend);
791 fn C_floating(s: str, t: TypeRef) -> ValueRef {
792 ret str::as_buf(s, {|buf| llvm::LLVMConstRealOfString(t, buf) });
795 fn C_nil() -> ValueRef {
796 // NB: See comment above in T_void().
798 ret C_integral(T_i1(), 0u64, False);
801 fn C_bool(b: bool) -> ValueRef {
803 ret C_integral(T_bool(), 1u64, False);
804 } else { ret C_integral(T_bool(), 0u64, False); }
807 fn C_i32(i: i32) -> ValueRef {
808 ret C_integral(T_i32(), i as u64, True);
811 fn C_i64(i: i64) -> ValueRef {
812 ret C_integral(T_i64(), i as u64, True);
815 fn C_int(cx: @crate_ctxt, i: int) -> ValueRef {
816 ret C_integral(cx.int_type, i as u64, True);
819 fn C_uint(cx: @crate_ctxt, i: uint) -> ValueRef {
820 ret C_integral(cx.int_type, i as u64, False);
823 fn C_u8(i: uint) -> ValueRef { ret C_integral(T_i8(), i as u64, False); }
826 // This is a 'c-like' raw string, which differs from
827 // our boxed-and-length-annotated strings.
828 fn C_cstr(cx: @crate_ctxt, s: str) -> ValueRef {
832 llvm::LLVMConstString(buf, str::byte_len(s), False)
835 str::as_buf(cx.names.next("str"),
836 {|buf| llvm::LLVMAddGlobal(cx.llmod, val_ty(sc), buf) });
837 llvm::LLVMSetInitializer(g, sc);
838 llvm::LLVMSetGlobalConstant(g, True);
839 llvm::LLVMSetLinkage(g, lib::llvm::LLVMInternalLinkage as llvm::Linkage);
843 // Returns a Plain Old LLVM String:
844 fn C_postr(s: str) -> ValueRef {
847 llvm::LLVMConstString(buf, str::byte_len(s), False)
851 fn C_zero_byte_arr(size: uint) -> ValueRef unsafe {
853 let elts: [ValueRef] = [];
854 while i < size { elts += [C_u8(0u)]; i += 1u; }
855 ret llvm::LLVMConstArray(T_i8(), vec::to_ptr(elts),
859 fn C_struct(elts: [ValueRef]) -> ValueRef unsafe {
860 ret llvm::LLVMConstStruct(vec::to_ptr(elts), vec::len(elts),
864 fn C_named_struct(T: TypeRef, elts: [ValueRef]) -> ValueRef unsafe {
865 ret llvm::LLVMConstNamedStruct(T, vec::to_ptr(elts),
869 fn C_array(ty: TypeRef, elts: [ValueRef]) -> ValueRef unsafe {
870 ret llvm::LLVMConstArray(ty, vec::to_ptr(elts),
874 fn C_bytes(bytes: [u8]) -> ValueRef unsafe {
875 ret llvm::LLVMConstString(
876 unsafe::reinterpret_cast(vec::to_ptr(bytes)),
877 vec::len(bytes), False);
880 fn C_shape(ccx: @crate_ctxt, bytes: [u8]) -> ValueRef {
881 let llshape = C_bytes(bytes);
883 str::as_buf(ccx.names.next("shape"),
885 llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape), buf)
887 llvm::LLVMSetInitializer(llglobal, llshape);
888 llvm::LLVMSetGlobalConstant(llglobal, True);
889 llvm::LLVMSetLinkage(llglobal,
890 lib::llvm::LLVMInternalLinkage as llvm::Linkage);
891 ret llvm::LLVMConstPointerCast(llglobal, T_ptr(T_i8()));
895 pure fn valid_variant_index(ix: uint, cx: @block_ctxt, tag_id: ast::def_id,
896 variant_id: ast::def_id) -> bool {
898 // Handwaving: it's ok to pretend this code is referentially
899 // transparent, because the relevant parts of the type context don't
900 // change. (We're not adding new variants during trans.)
903 ty::tag_variant_with_id(bcx_tcx(cx), tag_id, variant_id);
904 ix < vec::len(variant.args)
908 pure fn type_has_static_size(cx: @crate_ctxt, t: ty::t) -> bool {
909 !ty::type_has_dynamic_size(cx.tcx, t)
912 pure fn non_ty_var(cx: @crate_ctxt, t: ty::t) -> bool {
913 let st = ty::struct(cx.tcx, t);
915 ty::ty_var(_) { false }
920 pure fn returns_non_ty_var(cx: @crate_ctxt, t: ty::t) -> bool {
921 non_ty_var(cx, ty::ty_fn_ret(cx.tcx, t))
924 pure fn type_is_tup_like(cx: @block_ctxt, t: ty::t) -> bool {
925 let tcx = bcx_tcx(cx);
926 ty::type_is_tup_like(tcx, t)
929 // Used to identify cached dictionaries
931 dict_param_dict(dict_id);
932 dict_param_ty(ty::t);
934 type dict_id = @{impl_def: ast::def_id, params: [dict_param]};
935 fn hash_dict_id(&&dp: dict_id) -> uint {
936 let h = syntax::ast_util::hash_def_id(dp.impl_def);
937 for param in dp.params {
940 dict_param_dict(d) { h += hash_dict_id(d); }
941 dict_param_ty(t) { h += t; }
951 // indent-tabs-mode: nil
953 // buffer-file-coding-system: utf-8-unix