aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/comp/front/parser.rs4
-rw-r--r--src/comp/middle/trans.rs111
2 files changed, 95 insertions, 20 deletions
diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs
index ea983968..9596f714 100644
--- a/src/comp/front/parser.rs
+++ b/src/comp/front/parser.rs
@@ -150,6 +150,10 @@ state fn parse_lit(parser p) -> @ast.lit {
p.bump();
ret @ast.lit_bool(b);
}
+ case (token.LIT_STR(?s)) {
+ p.bump();
+ ret @ast.lit_str(s);
+ }
}
p.err("expected literal");
fail;
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index b9b3f4d2..9da370d7 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -23,22 +23,30 @@ import lib.llvm.llvm.BasicBlockRef;
import lib.llvm.False;
import lib.llvm.True;
+state obj namegen(mutable int i) {
+ fn next(str prefix) -> str {
+ i += 1;
+ ret prefix + istr(i);
+ }
+}
+
type glue_fns = rec(ValueRef activate_glue,
ValueRef yield_glue,
ValueRef exit_task_glue,
vec[ValueRef] upcall_glues);
-type trans_ctxt = rec(session.session sess,
- ModuleRef llmod,
- hashmap[str,ValueRef] upcalls,
- hashmap[str,ValueRef] fns,
- @glue_fns glues,
- str path);
+state type trans_ctxt = rec(session.session sess,
+ ModuleRef llmod,
+ hashmap[str,ValueRef] upcalls,
+ hashmap[str,ValueRef] fns,
+ @glue_fns glues,
+ namegen names,
+ str path);
-type fn_ctxt = rec(ValueRef llfn,
- ValueRef lloutptr,
- ValueRef lltaskptr,
- @trans_ctxt tcx);
+state type fn_ctxt = rec(ValueRef llfn,
+ ValueRef lloutptr,
+ ValueRef lltaskptr,
+ @trans_ctxt tcx);
type terminator = fn(@fn_ctxt cx, builder build);
@@ -54,10 +62,27 @@ fn T_nil() -> TypeRef {
ret llvm.LLVMVoidType();
}
-fn T_int() -> TypeRef {
+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_int() -> TypeRef {
+ // FIXME: switch on target type.
+ ret T_i32();
+}
+
fn T_fn(vec[TypeRef] inputs, TypeRef output) -> TypeRef {
ret llvm.LLVMFunctionType(output,
_vec.buf[TypeRef](inputs),
@@ -124,19 +149,26 @@ fn C_null(TypeRef t) -> ValueRef {
ret llvm.LLVMConstNull(t);
}
-fn C_int(int i) -> ValueRef {
+fn C_integral(int i, TypeRef t) -> ValueRef {
// FIXME. We can't use LLVM.ULongLong with our existing minimal native
// API, which only knows word-sized args. Lucky for us LLVM has a "take a
// string encoding" version. Hilarious. Please fix to handle:
//
// ret llvm.LLVMConstInt(T_int(), t as LLVM.ULongLong, False);
//
- ret llvm.LLVMConstIntOfString(T_int(),
- _str.buf(istr(i)), 10);
+ ret llvm.LLVMConstIntOfString(t, _str.buf(istr(i)), 10);
+}
+
+fn C_int(int i) -> ValueRef {
+ ret C_integral(i, T_int());
}
-fn C_str(str s) -> ValueRef {
- ret llvm.LLVMConstString(_str.buf(s), _str.byte_len(s), False);
+fn C_str(@trans_ctxt cx, str s) -> ValueRef {
+ auto sc = llvm.LLVMConstString(_str.buf(s), _str.byte_len(s), False);
+ auto g = llvm.LLVMAddGlobal(cx.llmod, llvm.LLVMTypeOf(sc),
+ _str.buf(cx.names.next("str")));
+ llvm.LLVMSetInitializer(g, sc);
+ ret g;
}
fn C_struct(vec[ValueRef] elts) -> ValueRef {
@@ -192,7 +224,10 @@ fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> ValueRef {
llupcall = llvm.LLVMConstPointerCast(llupcall, T_int());
let ValueRef llglue = cx.fcx.tcx.glues.upcall_glues.(n);
- let vec[ValueRef] call_args = vec(cx.fcx.lltaskptr, llupcall) + args;
+ let vec[ValueRef] call_args = vec(cx.fcx.lltaskptr, llupcall);
+ for (ValueRef a in args) {
+ call_args += cx.build.ZExtOrBitCast(a, T_int());
+ }
log "emitting indirect-upcall via " + abi.upcall_glue_name(n);
for (ValueRef v in call_args) {
log "arg: " + lib.llvm.type_to_str(llvm.LLVMTypeOf(v));
@@ -202,15 +237,50 @@ fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> ValueRef {
ret cx.build.Call(llglue, call_args);
}
-fn trans_log(@block_ctxt cx, &ast.expr e) {
+fn trans_expr(@block_ctxt cx, &ast.expr e) -> ValueRef {
alt (e) {
case (ast.expr_lit(?lit)) {
alt (*lit) {
case (ast.lit_int(?i)) {
- trans_upcall(cx, "upcall_log_int", vec(C_int(i)));
+ ret C_int(i);
+ }
+ case (ast.lit_uint(?u)) {
+ ret C_int(u as int);
+ }
+ case (ast.lit_char(?c)) {
+ ret C_integral(c as int, T_i32());
+ }
+ case (ast.lit_bool(?b)) {
+ if (b) {
+ ret C_integral(1, T_i8());
+ } else {
+ ret C_integral(0, T_i8());
+ }
+ }
+ case (ast.lit_str(?s)) {
+ auto len = (_str.byte_len(s) as int) + 1;
+ ret trans_upcall(cx, "upcall_new_str",
+ vec(p2i(C_str(cx.fcx.tcx, s)),
+ C_int(len)));
+ }
+ }
+ }
+ }
+ cx.fcx.tcx.sess.unimpl("expr variant in trans_expr");
+ fail;
+}
+
+fn trans_log(@block_ctxt cx, &ast.expr e) {
+ alt (e) {
+ case (ast.expr_lit(?lit)) {
+ alt (*lit) {
+ case (ast.lit_str(_)) {
+ auto v = trans_expr(cx, e);
+ trans_upcall(cx, "upcall_log_str", vec(v));
}
case (_) {
- cx.fcx.tcx.sess.unimpl("literal variant in trans_log");
+ auto v = trans_expr(cx, e);
+ trans_upcall(cx, "upcall_log_int", vec(v));
}
}
}
@@ -432,6 +502,7 @@ fn trans_crate(session.session sess, ast.crate crate) {
upcalls = new_str_hash[ValueRef](),
fns = new_str_hash[ValueRef](),
glues = glues,
+ names = namegen(0),
path = "_rust");
trans_mod(cx, crate.module);