rustc: Translate literals in DPS style; no constification of strings yet.
This commit is contained in:
parent
6e114a367f
commit
0bd7b803f6
1 changed files with 174 additions and 7 deletions
|
|
@ -1,18 +1,28 @@
|
|||
// Translates individual functions in the completed AST to the LLVM IR, using
|
||||
// destination-passing style.
|
||||
|
||||
import syntax::ast;
|
||||
import back::abi;
|
||||
import lib::llvm::llvm;
|
||||
import llvm::TypeRef;
|
||||
import llvm::ValueRef;
|
||||
import middle::trans;
|
||||
import middle::ty;
|
||||
import syntax::ast;
|
||||
import trans::block_ctxt;
|
||||
import trans::crate_ctxt;
|
||||
import trans::fn_ctxt;
|
||||
import trans::local_ctxt;
|
||||
import lib::llvm::llvm::TypeRef;
|
||||
import lib::llvm::llvm::ValueRef;
|
||||
|
||||
import std::ivec;
|
||||
import std::option::none;
|
||||
import std::option::some;
|
||||
import std::str;
|
||||
|
||||
import LLFalse = lib::llvm::False;
|
||||
import LLTrue = lib::llvm::True;
|
||||
import lltype_of = trans::val_ty;
|
||||
import option = std::option::t;
|
||||
import tc = trans_common;
|
||||
import type_of_node = trans::node_id_type;
|
||||
|
||||
|
||||
|
|
@ -52,6 +62,13 @@ fn dest_tmp(&@block_ctxt bcx, ty::t t) -> tup(@block_ctxt, dest) {
|
|||
ret tup(r.bcx, dest_move(bcx_tcx(bcx), r.val, t));
|
||||
}
|
||||
|
||||
fn dest_ptr(&dest dest) -> ValueRef {
|
||||
alt (dest.slot) {
|
||||
dst_nil { tc::C_null(tc::T_ptr(tc::T_i8())) }
|
||||
dst_val(?llptr) { llptr }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Accessors
|
||||
// TODO: When we have overloading, simplify these names!
|
||||
|
|
@ -64,19 +81,94 @@ fn bcx_fcx(&@block_ctxt bcx) -> @fn_ctxt { ret bcx.fcx; }
|
|||
|
||||
// Common operations
|
||||
|
||||
fn store(&@block_ctxt bcx, &dest dest, ValueRef llsrc) -> @block_ctxt {
|
||||
// If "cast" is true, casts dest appropriately before the store.
|
||||
fn store(&@block_ctxt bcx, &dest dest, ValueRef llsrc, bool cast)
|
||||
-> @block_ctxt {
|
||||
alt (dest.slot) {
|
||||
dst_nil { /* no-op */ }
|
||||
dst_val(?lldest) { bcx.build.Store(llsrc, lldest); }
|
||||
dst_val(?lldestptr_orig) {
|
||||
auto lldestptr = lldestptr_orig;
|
||||
if (cast) {
|
||||
lldestptr = bcx.build.PointerCast(lldestptr,
|
||||
tc::T_ptr(lltype_of(llsrc)));
|
||||
}
|
||||
|
||||
bcx.build.Store(llsrc, lldestptr);
|
||||
}
|
||||
}
|
||||
ret bcx;
|
||||
}
|
||||
|
||||
tag heap { hp_task; hp_shared; }
|
||||
|
||||
// Allocates a value of the given LLVM size on either the task heap or the
|
||||
// shared heap.
|
||||
fn malloc(&@block_ctxt bcx, ValueRef lldest, heap heap,
|
||||
option[ValueRef] llcustom_size_opt) -> @block_ctxt {
|
||||
auto llptrty = llelement_type(lltype_of(lldest));
|
||||
auto llty = llelement_type(llptrty);
|
||||
|
||||
auto lltydescptr = tc::C_null(tc::T_ptr(bcx_ccx(bcx).tydesc_type));
|
||||
|
||||
auto llsize;
|
||||
alt (llcustom_size_opt) {
|
||||
none { llsize = trans::llsize_of(llty); }
|
||||
some(?llcustom_size) { llsize = llcustom_size; }
|
||||
}
|
||||
|
||||
auto llupcall;
|
||||
alt (heap) {
|
||||
hp_task { llupcall = bcx_ccx(bcx).upcalls.malloc; }
|
||||
hp_shared { llupcall = bcx_ccx(bcx).upcalls.shared_malloc; }
|
||||
}
|
||||
|
||||
auto llresult = bcx.build.Call(llupcall, ~[bcx_fcx(bcx).lltaskptr, llsize,
|
||||
lltydescptr]);
|
||||
llresult = bcx.build.PointerCast(llresult, llptrty);
|
||||
bcx.build.Store(llresult, lldest);
|
||||
ret bcx;
|
||||
}
|
||||
|
||||
|
||||
// AST substructure translation, with destinations
|
||||
|
||||
fn trans_lit(&@block_ctxt cx, &dest dest, &ast::lit lit) -> @block_ctxt {
|
||||
auto bcx = cx;
|
||||
alt (lit.node) {
|
||||
ast::lit_str(?s, ast::sk_unique) {
|
||||
auto r = trans_lit_str_common(bcx_ccx(bcx), s);
|
||||
auto llstackpart = r._0; auto llheappartopt = r._1;
|
||||
bcx = store(bcx, dest, llstackpart, true);
|
||||
alt (llheappartopt) {
|
||||
none { /* no-op */ }
|
||||
some(?llheappart) {
|
||||
auto lldestptrptr =
|
||||
bcx.build.InBoundsGEP(dest_ptr(dest),
|
||||
~[tc::C_int(0),
|
||||
tc::C_uint(abi::ivec_elt_elems)]);
|
||||
auto llheappartty = lltype_of(llheappart);
|
||||
lldestptrptr =
|
||||
bcx.build.PointerCast(lldestptrptr,
|
||||
tc::T_ptr(tc::T_ptr(llheappartty)));
|
||||
malloc(bcx, lldestptrptr, hp_shared, none);
|
||||
auto lldestptr = bcx.build.Load(lldestptrptr);
|
||||
bcx.build.Store(llheappart, lldestptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ {
|
||||
bcx = store(bcx, dest, trans_lit_common(bcx_ccx(bcx), lit), false);
|
||||
}
|
||||
}
|
||||
|
||||
ret bcx;
|
||||
}
|
||||
|
||||
fn trans_expr(&@block_ctxt bcx, &dest dest, &@ast::expr expr) -> @block_ctxt {
|
||||
ret bcx; // TODO
|
||||
alt (expr.node) {
|
||||
ast::expr_lit(?lit) { trans_lit(bcx, dest, *lit); ret bcx; }
|
||||
_ { fail "unhandled expr type in trans_expr"; }
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_recv(&@block_ctxt bcx, &dest dest, &@ast::expr expr) -> @block_ctxt {
|
||||
|
|
@ -105,8 +197,83 @@ fn trans_block(&@block_ctxt cx, &dest dest, &ast::block block)
|
|||
}
|
||||
|
||||
|
||||
|
||||
// AST substructure translation, without destinations
|
||||
|
||||
// Common setup code shared between the crate-constant literal string case and
|
||||
// the block-local literal string case. We don't use destination-passing style
|
||||
// since that doesn't work for crate constants.
|
||||
fn trans_lit_str_common(&@crate_ctxt ccx, &str s)
|
||||
-> tup(ValueRef, option[ValueRef]) {
|
||||
auto len = str::byte_len(s);
|
||||
|
||||
auto array = ~[];
|
||||
for (u8 ch in s) { array += ~[tc::C_u8(ch as uint)]; }
|
||||
array += ~[tc::C_u8(0u)];
|
||||
|
||||
if len < abi::ivec_default_length - 1u { // minus 1 because of the \0
|
||||
while (ivec::len(array) < abi::ivec_default_length) {
|
||||
array += ~[tc::C_u8(0u)];
|
||||
}
|
||||
|
||||
ret tup(tc::C_struct(~[tc::C_uint(len + 1u),
|
||||
tc::C_uint(abi::ivec_default_length),
|
||||
tc::C_array(tc::T_i8(), array)]),
|
||||
none);
|
||||
}
|
||||
|
||||
auto llarray = tc::C_array(tc::T_i8(), array);
|
||||
ret tup(tc::C_struct(~[tc::C_uint(0u),
|
||||
tc::C_uint(abi::ivec_default_length),
|
||||
tc::C_null(tc::T_ptr(lltype_of(llarray)))]),
|
||||
some(llarray));
|
||||
}
|
||||
|
||||
// As above, we don't use destination-passing style here.
|
||||
fn trans_lit_common(&@crate_ctxt ccx, &ast::lit lit) -> ValueRef {
|
||||
alt (lit.node) {
|
||||
ast::lit_int(?i) { ret tc::C_int(i); }
|
||||
ast::lit_uint(?u) { ret tc::C_int(u as int); }
|
||||
ast::lit_mach_int(?tm, ?i) {
|
||||
// FIXME: the entire handling of mach types falls apart
|
||||
// if target int width is larger than host, at the moment;
|
||||
// re-do the mach-int types using 'big' when that works.
|
||||
|
||||
auto t = tc::T_int();
|
||||
auto s = LLTrue;
|
||||
alt (tm) {
|
||||
ast::ty_u8 { t = tc::T_i8(); s = LLFalse; }
|
||||
ast::ty_u16 { t = tc::T_i16(); s = LLFalse; }
|
||||
ast::ty_u32 { t = tc::T_i32(); s = LLFalse; }
|
||||
ast::ty_u64 { t = tc::T_i64(); s = LLFalse; }
|
||||
ast::ty_i8 { t = tc::T_i8(); }
|
||||
ast::ty_i16 { t = tc::T_i16(); }
|
||||
ast::ty_i32 { t = tc::T_i32(); }
|
||||
ast::ty_i64 { t = tc::T_i64(); }
|
||||
}
|
||||
ret tc::C_integral(t, i as uint, s);
|
||||
}
|
||||
ast::lit_float(?fs) { ret tc::C_float(fs); }
|
||||
ast::lit_mach_float(?tm, ?s) {
|
||||
auto t = tc::T_float();
|
||||
alt (tm) {
|
||||
ast::ty_f32 { t = tc::T_f32(); }
|
||||
ast::ty_f64 { t = tc::T_f64(); }
|
||||
}
|
||||
ret tc::C_floating(s, t);
|
||||
}
|
||||
ast::lit_char(?c) {
|
||||
ret tc::C_integral(tc::T_char(), c as uint, LLFalse);
|
||||
}
|
||||
ast::lit_bool(?b) { ret tc::C_bool(b); }
|
||||
ast::lit_nil { ret tc::C_nil(); }
|
||||
ast::lit_str(?s, ast::sk_rc) { ret tc::C_str(ccx, s); }
|
||||
ast::lit_str(?s, ast::sk_unique) {
|
||||
fail "unique str in trans_lit_common";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn trans_init_local(&@block_ctxt bcx, &@ast::local local) -> @block_ctxt {
|
||||
auto llptr = bcx_fcx(bcx).lllocals.get(local.node.id);
|
||||
|
||||
|
|
@ -129,7 +296,7 @@ fn trans_init_local(&@block_ctxt bcx, &@ast::local local) -> @block_ctxt {
|
|||
}
|
||||
none {
|
||||
ret store(bcx, dest_copy(bcx_tcx(bcx), llptr, t),
|
||||
trans_common::C_null(llelement_type(trans::val_ty(llptr))));
|
||||
tc::C_null(llelement_type(trans::val_ty(llptr))), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue