aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/comp/middle/trans.rs138
-rw-r--r--src/rt/rust.cpp2
-rw-r--r--src/rt/rust_crate.cpp86
-rw-r--r--src/rt/rust_internal.h5
-rw-r--r--src/rt/rust_log.cpp4
5 files changed, 206 insertions, 29 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 1643ba64..ac2ceff5 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -108,12 +108,14 @@ state type crate_ctxt = rec(session.session sess,
hashmap[ast.def_id, ValueRef] consts,
hashmap[ast.def_id,()] obj_methods,
hashmap[@ty.t, @tydesc_info] tydescs,
+ hashmap[str, ValueRef] module_data,
@glue_fns glues,
namegen names,
vec[str] path,
std.sha1.sha1 sha);
type local_ctxt = rec(vec[str] path,
+ vec[str] module_path,
vec[ast.ty_param] obj_typarams,
vec[ast.obj_field] obj_fields,
@crate_ctxt ccx);
@@ -426,7 +428,8 @@ fn T_crate(type_names tn) -> TypeRef {
T_int(), // int n_rust_syms
T_int(), // int n_c_syms
T_int(), // int n_libs
- T_int() // uintptr_t abi_tag
+ T_int(), // uintptr_t abi_tag
+ T_int() // void* crate_map
));
tn.associate(s, t);
ret t;
@@ -909,6 +912,11 @@ fn C_struct(vec[ValueRef] elts) -> ValueRef {
False);
}
+fn C_array(TypeRef ty, vec[ValueRef] elts) -> ValueRef {
+ ret llvm.LLVMConstArray(ty, _vec.buf[ValueRef](elts),
+ _vec.len[ValueRef](elts));
+}
+
fn decl_fn(ModuleRef llmod, str name, uint cc, TypeRef llty) -> ValueRef {
let ValueRef llfn =
llvm.LLVMAddFunction(llmod, _str.buf(name), llty);
@@ -4925,8 +4933,28 @@ fn load_if_immediate(@block_ctxt cx, ValueRef v, @ty.t t) -> ValueRef {
}
fn trans_log(@block_ctxt cx, @ast.expr e) -> result {
-
- auto sub = trans_expr(cx, e);
+ auto lcx = cx.fcx.lcx;
+ auto modname = _str.connect(lcx.module_path, ".");
+ auto global;
+ if (lcx.ccx.module_data.contains_key(modname)) {
+ global = lcx.ccx.module_data.get(modname);
+ } else {
+ global = llvm.LLVMAddGlobal(lcx.ccx.llmod, T_int(),
+ _str.buf("_rust_mod_log_" + modname));
+ llvm.LLVMSetGlobalConstant(global, False);
+ llvm.LLVMSetInitializer(global, C_null(T_int()));
+ llvm.LLVMSetLinkage(global, lib.llvm.LLVMInternalLinkage
+ as llvm.Linkage);
+ lcx.ccx.module_data.insert(modname, global);
+ }
+
+ auto log_cx = new_sub_block_ctxt(cx, "log");
+ auto after_cx = new_sub_block_ctxt(cx, "after");
+ auto load = cx.build.Load(global);
+ auto test = cx.build.ICmp(lib.llvm.LLVMIntSGE, load, C_int(1));
+ cx.build.CondBr(test, log_cx.llbb, after_cx.llbb);
+
+ auto sub = trans_expr(log_cx, e);
auto e_ty = ty.expr_ty(e);
if (ty.type_is_fp(e_ty)) {
@@ -4945,33 +4973,34 @@ fn trans_log(@block_ctxt cx, @ast.expr e) -> result {
}
}
if (is32bit) {
- ret trans_upcall(sub.bcx,
- "upcall_log_float",
- vec(sub.val));
+ trans_upcall(sub.bcx,
+ "upcall_log_float",
+ vec(sub.val)).bcx.build.Br(after_cx.llbb);
} else {
auto tmp = alloca(sub.bcx, tr);
sub.bcx.build.Store(sub.val, tmp);
auto v = vp2i(sub.bcx, tmp);
- ret trans_upcall(sub.bcx,
- "upcall_log_double",
- vec(v));
+ trans_upcall(sub.bcx,
+ "upcall_log_double",
+ vec(v)).bcx.build.Br(after_cx.llbb);
}
- }
-
- alt (e_ty.struct) {
- case (ty.ty_str) {
- auto v = vp2i(sub.bcx, sub.val);
- ret trans_upcall(sub.bcx,
+ } else {
+ alt (e_ty.struct) {
+ case (ty.ty_str) {
+ auto v = vp2i(sub.bcx, sub.val);
+ trans_upcall(sub.bcx,
"upcall_log_str",
- vec(v));
- }
- case (_) {
- ret trans_upcall(sub.bcx,
+ vec(v)).bcx.build.Br(after_cx.llbb);
+ }
+ case (_) {
+ trans_upcall(sub.bcx,
"upcall_log_int",
- vec(sub.val));
+ vec(sub.val)).bcx.build.Br(after_cx.llbb);
+ }
}
}
- fail;
+
+ ret res(after_cx, C_nil());
}
fn trans_check_expr(@block_ctxt cx, @ast.expr e) -> result {
@@ -6114,7 +6143,9 @@ fn trans_item(@local_ctxt cx, &ast.item item) {
trans_obj(sub_cx, ob, oid.ctor, tps, ann);
}
case (ast.item_mod(?name, ?m, _)) {
- auto sub_cx = extend_path(cx, name);
+ auto sub_cx = @rec(path = cx.path + vec(name),
+ module_path = cx.module_path + vec(name)
+ with *cx);
trans_mod(sub_cx, m);
}
case (ast.item_tag(?name, ?variants, ?tps, ?tag_id, _)) {
@@ -6593,7 +6624,8 @@ fn create_typedefs(@crate_ctxt cx) {
llvm.LLVMAddTypeName(cx.llmod, _str.buf("tydesc"), T_tydesc(cx.tn));
}
-fn create_crate_constant(ValueRef crate_ptr, @glue_fns glues) {
+fn create_crate_constant(ValueRef crate_ptr, @glue_fns glues,
+ ValueRef crate_map) {
let ValueRef crate_addr = p2i(crate_ptr);
@@ -6608,7 +6640,7 @@ fn create_crate_constant(ValueRef crate_ptr, @glue_fns glues) {
let ValueRef crate_val =
C_struct(vec(C_null(T_int()), // ptrdiff_t image_base_off
- p2i(crate_ptr), // uintptr_t self_addr
+ p2i(crate_ptr), // uintptr_t self_addr
C_null(T_int()), // ptrdiff_t debug_abbrev_off
C_null(T_int()), // size_t debug_abbrev_sz
C_null(T_int()), // ptrdiff_t debug_info_off
@@ -6621,7 +6653,8 @@ fn create_crate_constant(ValueRef crate_ptr, @glue_fns glues) {
C_null(T_int()), // int n_rust_syms
C_null(T_int()), // int n_c_syms
C_null(T_int()), // int n_libs
- C_int(abi.abi_x86_rustc_fastcall) // uintptr_t abi_tag
+ C_int(abi.abi_x86_rustc_fastcall), // uintptr_t abi_tag
+ p2i(crate_map) // void* crate_map
));
llvm.LLVMSetInitializer(crate_ptr, crate_val);
@@ -7159,6 +7192,54 @@ fn make_common_glue(str output, bool optimize,
run_passes(llmod, optimize, output, ot);
}
+fn create_module_map(@crate_ctxt ccx) -> ValueRef {
+ auto elttype = T_struct(vec(T_int(), T_int()));
+ auto maptype = T_array(elttype, ccx.module_data.size() + 1u);
+ auto map = llvm.LLVMAddGlobal(ccx.llmod, maptype,
+ _str.buf("_rust_mod_map"));
+ llvm.LLVMSetLinkage(map, lib.llvm.LLVMInternalLinkage as llvm.Linkage);
+ let vec[ValueRef] elts = vec();
+ for each (@tup(str, ValueRef) item in ccx.module_data.items()) {
+ auto elt = C_struct(vec(p2i(C_cstr(ccx, item._0)), p2i(item._1)));
+ _vec.push[ValueRef](elts, elt);
+ }
+ auto term = C_struct(vec(C_int(0), C_int(0)));
+ _vec.push[ValueRef](elts, term);
+ llvm.LLVMSetInitializer(map, C_array(elttype, elts));
+ ret map;
+}
+
+fn crate_name(@crate_ctxt ccx, str deflt) -> str {
+ for (@ast.meta_item item in ccx.sess.get_metadata()) {
+ if (_str.eq(item.node.name, "name")) {
+ ret item.node.value;
+ }
+ }
+ ret deflt;
+}
+
+// FIXME use hashed metadata instead of crate names once we have that
+fn create_crate_map(@crate_ctxt ccx) -> ValueRef {
+ let vec[ValueRef] subcrates = vec();
+ auto i = 1;
+ while (ccx.sess.has_external_crate(i)) {
+ auto name = ccx.sess.get_external_crate(i).name;
+ auto cr = llvm.LLVMAddGlobal(ccx.llmod, T_int(),
+ _str.buf("_rust_crate_map_" + name));
+ _vec.push[ValueRef](subcrates, p2i(cr));
+ i += 1;
+ }
+ _vec.push[ValueRef](subcrates, C_int(0));
+ auto sym_name = "_rust_crate_map_" + crate_name(ccx, "__none__");
+ auto arrtype = T_array(T_int(), _vec.len[ValueRef](subcrates));
+ auto maptype = T_struct(vec(T_int(), arrtype));
+ auto map = llvm.LLVMAddGlobal(ccx.llmod, maptype, _str.buf(sym_name));
+ llvm.LLVMSetLinkage(map, lib.llvm.LLVMExternalLinkage as llvm.Linkage);
+ llvm.LLVMSetInitializer(map, C_struct(vec(p2i(create_module_map(ccx)),
+ C_array(T_int(), subcrates))));
+ ret map;
+}
+
fn trans_crate(session.session sess, @ast.crate crate,
&ty.type_cache type_cache, str output, bool shared,
bool optimize, output_type ot) {
@@ -7203,25 +7284,28 @@ fn trans_crate(session.session sess, @ast.crate crate,
consts = new_def_hash[ValueRef](),
obj_methods = new_def_hash[()](),
tydescs = tydescs,
+ module_data = new_str_hash[ValueRef](),
glues = glues,
names = namegen(0),
path = pth,
sha = std.sha1.mk_sha1());
auto cx = @rec(path=pth,
+ module_path=vec(crate_name(ccx, "main")),
obj_typarams = obj_typarams,
obj_fields = obj_fields,
ccx = ccx);
- create_typedefs(cx.ccx);
+ create_typedefs(ccx);
collect_items(cx, crate);
collect_tag_ctors(cx, crate);
trans_constants(cx, crate);
trans_mod(cx, crate.node.module);
trans_vec_append_glue(cx);
+ auto crate_map = create_crate_map(ccx);
if (!shared) {
trans_main_fn(cx, crate_ptr);
- create_crate_constant(crate_ptr, ccx.glues);
+ create_crate_constant(crate_ptr, ccx.glues, crate_map);
}
// Translate the metadata.
diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp
index 9600b4d5..013705f2 100644
--- a/src/rt/rust.cpp
+++ b/src/rt/rust.cpp
@@ -80,6 +80,7 @@ extern "C" CDECL int
rust_start(uintptr_t main_fn, rust_crate const *crate, int argc,
char **argv) {
+ crate->update_log_settings(getenv("RUST_LOG"));
rust_srv *srv = new rust_srv();
rust_kernel *kernel = new rust_kernel(srv);
kernel->start();
@@ -102,6 +103,7 @@ rust_start(uintptr_t main_fn, rust_crate const *crate, int argc,
dom->root_task->start(crate->get_exit_task_glue(),
crate->abi_tag, main_fn,
(uintptr_t)&main_args, sizeof(main_args));
+
int ret = dom->start_main_loop();
delete args;
kernel->destroy_domain(dom);
diff --git a/src/rt/rust_crate.cpp b/src/rt/rust_crate.cpp
index 23f01c07..e7ee0350 100644
--- a/src/rt/rust_crate.cpp
+++ b/src/rt/rust_crate.cpp
@@ -65,6 +65,92 @@ rust_crate::get_debug_abbrev(rust_dom *dom) const {
return mem_area(dom, 0, 0);
}
+struct mod_entry {
+ const char* name;
+ int* state;
+};
+
+struct cratemap {
+ mod_entry* entries;
+ cratemap* children[1];
+};
+
+struct log_directive {
+ char* name;
+ size_t level;
+};
+
+const size_t max_log_directives = 255;
+
+size_t parse_logging_spec(char* spec, log_directive* dirs) {
+ size_t dir = 0;
+ while (dir < max_log_directives && *spec) {
+ char* start = spec;
+ char cur;
+ while (true) {
+ cur = *spec;
+ if (cur == ',' || cur == '=' || cur == '\0') {
+ if (start == spec) {spec++; break;}
+ *spec = '\0';
+ spec++;
+ size_t level = 3;
+ if (cur == '=') {
+ level = *spec - '0';
+ if (level > 3) level = 1;
+ if (*spec) ++spec;
+ }
+ dirs[dir].name = start;
+ dirs[dir++].level = level;
+ break;
+ }
+ spec++;
+ }
+ }
+ return dir;
+}
+
+void update_crate_map(cratemap* map, log_directive* dirs, size_t n_dirs) {
+ // First update log levels for this crate
+ for (mod_entry* cur = map->entries; cur->name; cur++) {
+ size_t level = 1, longest_match = 0;
+ for (size_t d = 0; d < n_dirs; d++) {
+ if (strstr(cur->name, dirs[d].name) == cur->name &&
+ strlen(dirs[d].name) > longest_match) {
+ longest_match = strlen(dirs[d].name);
+ level = dirs[d].level;
+ }
+ }
+ *cur->state = level;
+ }
+
+ // Then recurse on linked crates
+ for (size_t i = 0; map->children[i]; i++) {
+ update_crate_map(map->children[i], dirs, n_dirs);
+ }
+}
+
+void rust_crate::update_log_settings(char* settings) const {
+ // Only try this if the crate was generated by Rustc, not rustboot
+ if (image_base_off) return;
+
+ // This is a rather ugly parser for strings in the form
+ // "crate1,crate2.mod3,crate3.x=2". Log levels range 0=err, 1=warn,
+ // 2=info, 3=debug. Default is 1. Words without an '=X' part set the log
+ // level for that module (and submodules) to 3.
+ char* buffer = NULL;
+ log_directive dirs[256];
+ size_t dir = 0;
+ if (settings) {
+ buffer = (char*)malloc(strlen(settings));
+ strcpy(buffer, settings);
+ dir = parse_logging_spec(buffer, &dirs[0]);
+ }
+
+ update_crate_map((cratemap*)crate_map, &dirs[0], dir);
+
+ free(buffer);
+}
+
//
// Local Variables:
// mode: C++
diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h
index 4a1f3e45..695fc21d 100644
--- a/src/rt/rust_internal.h
+++ b/src/rt/rust_internal.h
@@ -248,6 +248,9 @@ public:
size_t n_libs;
uintptr_t abi_tag;
+ // FIXME: not generated by rustboot, should only be accessed in crates
+ // generated by rustc.
+ void* crate_map;
// Crates are immutable, constructed by the compiler.
@@ -259,6 +262,8 @@ public:
uintptr_t get_gc_glue() const;
uintptr_t get_exit_task_glue() const;
+ void update_log_settings(char* settings) const;
+
struct mem_area
{
rust_dom *dom;
diff --git a/src/rt/rust_log.cpp b/src/rt/rust_log.cpp
index 3017b549..076c4b0a 100644
--- a/src/rt/rust_log.cpp
+++ b/src/rt/rust_log.cpp
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <string.h>
+// FIXME somehow unify this with the parsing happening in rust_crate.cpp
static uint32_t
read_type_bit_mask() {
uint32_t bits = rust_log::ULOG | rust_log::ERR;
@@ -18,14 +19,13 @@ read_type_bit_mask() {
str[0] = ',';
strcpy(str + 1, env_str);
- bits = 0;
+ bits = rust_log::ULOG;
bits |= strstr(str, ",err") ? rust_log::ERR : 0;
bits |= strstr(str, ",mem") ? rust_log::MEM : 0;
bits |= strstr(str, ",comm") ? rust_log::COMM : 0;
bits |= strstr(str, ",task") ? rust_log::TASK : 0;
bits |= strstr(str, ",up") ? rust_log::UPCALL : 0;
bits |= strstr(str, ",dom") ? rust_log::DOM : 0;
- bits |= strstr(str, ",ulog") ? rust_log::ULOG : 0;
bits |= strstr(str, ",trace") ? rust_log::TRACE : 0;
bits |= strstr(str, ",dwarf") ? rust_log::DWARF : 0;
bits |= strstr(str, ",cache") ? rust_log::CACHE : 0;