about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2010-09-24 14:56:04 -0700
committerGraydon Hoare <graydon@mozilla.com>2010-09-24 14:56:04 -0700
commit4cfc4250bf721d5946b4f91c7b561dd57a00cc96 (patch)
tree74ddce35ffc08f66def2dccba16515414b01868d /src/comp
parent6b412be619279aa89bf30fe31f69e9bfa3d550ee (diff)
downloadrust-4cfc4250bf721d5946b4f91c7b561dd57a00cc96.tar.gz
rust-4cfc4250bf721d5946b4f91c7b561dd57a00cc96.zip
More work on trans, almost getting to the point of emitting an upcall.
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/back/abi.rs12
-rw-r--r--src/comp/back/x86.rs6
-rw-r--r--src/comp/lib/llvm.rs89
-rw-r--r--src/comp/middle/trans.rs133
-rw-r--r--src/comp/rustc.rc1
5 files changed, 204 insertions, 37 deletions
diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs
index 1a349a7b8db..ad4c066e361 100644
--- a/src/comp/back/abi.rs
+++ b/src/comp/back/abi.rs
@@ -36,6 +36,18 @@ const int worst_case_glue_call_args = 7;
 
 const int n_upcall_glues = 7;
 
+fn upcall_glue_name(int n) -> str {
+    ret "rust_upcall_" + util.common.istr(n);
+}
+
+fn activate_glue_name() -> str {
+    ret "rust_activate_glue";
+}
+
+fn yield_glue_name() -> str {
+    ret "rust_yield_glue";
+}
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/comp/back/x86.rs b/src/comp/back/x86.rs
index bfe502009c7..b3edcae6f0a 100644
--- a/src/comp/back/x86.rs
+++ b/src/comp/back/x86.rs
@@ -121,7 +121,7 @@ fn decl_glue(int align, str prefix, str name, vec[str] insns) -> str {
 fn decl_upcall_glue(int align, str prefix, uint n) -> str {
     let int i = n as int;
     ret decl_glue(align, prefix,
-                  "rust_upcall_" + istr(i),
+                  abi.upcall_glue_name(i),
                   upcall_glue(i));
 }
 
@@ -131,11 +131,11 @@ fn get_module_asm() -> str {
 
     auto glues =
         vec(decl_glue(align, prefix,
-                      "rust_activate_glue",
+                      abi.activate_glue_name(),
                       rust_activate_glue()),
 
             decl_glue(align, prefix,
-                      "rust_yield_glue",
+                      abi.yield_glue_name(),
                       rust_yield_glue()))
 
         + _vec.init_fn[str](bind decl_upcall_glue(align, prefix, _),
diff --git a/src/comp/lib/llvm.rs b/src/comp/lib/llvm.rs
index 704c6092db5..ac8dd76f3d9 100644
--- a/src/comp/lib/llvm.rs
+++ b/src/comp/lib/llvm.rs
@@ -41,7 +41,6 @@ const uint LLVMColdCallConv = 9u;
 const uint LLVMX86StdcallCallConv = 64u;
 const uint LLVMX86FastcallCallConv = 65u;
 
-
 native mod llvm = llvm_lib {
 
     type ModuleRef;
@@ -96,6 +95,14 @@ native mod llvm = llvm_lib {
     /** See Module::setModuleInlineAsm. */
     fn LLVMSetModuleInlineAsm(ModuleRef M, sbuf Asm);
 
+    /** See llvm::LLVMTypeKind::getTypeID. */
+
+    // FIXME: returning int rather than TypeKind because
+    // we directly inspect the values, and casting from
+    // a native doesn't work yet (only *to* a native).
+
+    fn LLVMGetTypeKind(TypeRef Ty) -> int;
+
     /** See llvm::LLVMType::getContext. */
     fn LLVMGetTypeContext(TypeRef Ty) -> ContextRef;
 
@@ -213,7 +220,9 @@ native mod llvm = llvm_lib {
 
     /* Operations on scalar constants */
     fn LLVMConstInt(TypeRef IntTy, ULongLong N, Bool SignExtend) -> ValueRef;
-    fn LLVMConstIntOfString(TypeRef IntTy, sbuf Text, u8 Radix) -> ValueRef;
+    // FIXME: radix is actually u8, but our native layer can't handle this
+    // yet.  lucky for us we're little-endian. Small miracles.
+    fn LLVMConstIntOfString(TypeRef IntTy, sbuf Text, int Radix) -> ValueRef;
     fn LLVMConstIntOfStringAndSize(TypeRef IntTy, sbuf Text,
                                    uint SLen, u8 Radix) -> ValueRef;
     fn LLVMConstReal(TypeRef RealTy, f64 N) -> ValueRef;
@@ -1041,6 +1050,82 @@ obj builder(BuilderRef B) {
     }
 }
 
+fn type_to_str(TypeRef ty) -> str {
+    let int kind = llvm.LLVMGetTypeKind(ty);
+
+    fn tys_str(vec[TypeRef] tys) -> str {
+        let str s = "";
+        let bool first = true;
+        for (TypeRef t in tys) {
+            if (first) {
+                first = false;
+            } else {
+                s += ", ";
+            }
+            s += type_to_str(t);
+        }
+        ret s;
+    }
+
+    alt (kind) {
+
+        // FIXME: more enum-as-int constants determined from Core.h;
+        // horrible, horrible. Complete as needed.
+
+        case (0) { ret "Void"; }
+        case (1) { ret "Float"; }
+        case (2) { ret "Double"; }
+        case (3) { ret "X86_FP80"; }
+        case (4) { ret "FP128"; }
+        case (5) { ret "PPC_FP128"; }
+        case (6) { ret "Label"; }
+
+        case (7) {
+            ret "i" + util.common.istr(llvm.LLVMGetIntTypeWidth(ty) as int);
+        }
+
+        case (8) {
+            auto s = "fn(";
+            let TypeRef out_ty = llvm.LLVMGetReturnType(ty);
+            let uint n_args = llvm.LLVMCountParamTypes(ty);
+            let vec[TypeRef] args =
+                _vec.init_elt[TypeRef](0 as TypeRef, n_args);
+            llvm.LLVMGetParamTypes(ty, _vec.buf[TypeRef](args));
+            s += tys_str(args);
+            s += ") -> ";
+            s += type_to_str(out_ty);
+            ret s;
+        }
+
+        case (9) {
+            let str s = "{";
+            let uint n_elts = llvm.LLVMCountStructElementTypes(ty);
+            let vec[TypeRef] elts =
+                _vec.init_elt[TypeRef](0 as TypeRef, n_elts);
+            llvm.LLVMGetStructElementTypes(ty, _vec.buf[TypeRef](elts));
+            s += tys_str(elts);
+            s += "}";
+            ret s;
+        }
+
+        case (10) { ret "Array"; }
+
+        case (11) {
+            ret "*" + type_to_str(llvm.LLVMGetElementType(ty));
+        }
+
+        case (12) { ret "Opaque"; }
+        case (13) { ret "Vector"; }
+        case (14) { ret "Metadata"; }
+        case (15) { ret "Union"; }
+        case (_) {
+            log "unknown TypeKind" + util.common.istr(kind as int);
+            fail;
+        }
+    }
+}
+
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 30d721044a6..e2dfc7c1b29 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -33,6 +33,21 @@ type trans_ctxt = rec(session.session sess,
                       @glue_fns glues,
                       str path);
 
+type fn_ctxt = rec(ValueRef llfn,
+                   ValueRef lloutptr,
+                   ValueRef lltaskptr,
+                   @trans_ctxt tcx);
+
+type terminator = fn(@fn_ctxt cx, builder build);
+
+type block_ctxt = rec(BasicBlockRef llbb,
+                      builder build,
+                      terminator term,
+                      @fn_ctxt fcx);
+
+
+// LLVM type constructors.
+
 fn T_nil() -> TypeRef {
     ret llvm.LLVMVoidType();
 }
@@ -67,9 +82,38 @@ fn T_task() -> TypeRef {
                      T_opaque())); // Rest is opaque for now
 }
 
+
+// LLVM constant constructors.
+
+fn C_null(TypeRef t) -> ValueRef {
+    ret llvm.LLVMConstNull(t);
+}
+
+fn C_int(int i) -> 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);
+}
+
+fn C_str(str s) -> ValueRef {
+    ret llvm.LLVMConstString(_str.buf(s), _str.byte_len(s), False);
+}
+
+fn C_struct(vec[ValueRef] elts) -> ValueRef {
+    ret llvm.LLVMConstStruct(_vec.buf[ValueRef](elts),
+                             _vec.len[ValueRef](elts),
+                             False);
+}
+
 fn decl_cdecl_fn(ModuleRef llmod, str name,
                  vec[TypeRef] inputs, TypeRef output) -> ValueRef {
     let TypeRef llty = T_fn(inputs, output);
+    log "declaring " + name + " with type " + lib.llvm.type_to_str(llty);
     let ValueRef llfn =
         llvm.LLVMAddFunction(llmod, _str.buf(name), llty);
     llvm.LLVMSetFunctionCallConv(llfn, lib.llvm.LLVMCCallConv);
@@ -82,7 +126,7 @@ fn decl_glue(ModuleRef llmod, str s) -> ValueRef {
 
 fn decl_upcall(ModuleRef llmod, uint _n) -> ValueRef {
     let int n = _n as int;
-    let str s = "rust_upcall_" + istr(n);
+    let str s = abi.upcall_glue_name(n);
     let vec[TypeRef] args =
         vec(T_ptr(T_task()), // taskptr
             T_int())         // callee
@@ -91,9 +135,7 @@ fn decl_upcall(ModuleRef llmod, uint _n) -> ValueRef {
     ret decl_cdecl_fn(llmod, s, args, T_int());
 }
 
-type terminator = fn(&trans_ctxt cx, builder b);
-
-fn get_upcall(&trans_ctxt cx, str name, int n_args) -> ValueRef {
+fn get_upcall(@trans_ctxt cx, str name, int n_args) -> ValueRef {
     if (cx.upcalls.contains_key(name)) {
         ret cx.upcalls.get(name);
     }
@@ -105,61 +147,87 @@ fn get_upcall(&trans_ctxt cx, str name, int n_args) -> ValueRef {
     ret f;
 }
 
-fn trans_log(&trans_ctxt cx, builder b, &ast.atom a) {
+fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> ValueRef {
+    let int n = _vec.len[ValueRef](args) as int;
+    let ValueRef llupcall = get_upcall(cx.fcx.tcx, name, n);
+    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;
+    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));
+    }
+    log "emitting call to callee of type: " +
+        lib.llvm.type_to_str(llvm.LLVMTypeOf(llglue));
+    ret cx.build.Call(llglue, call_args);
+}
+
+fn trans_log(@block_ctxt cx, &ast.atom a) {
     alt (a) {
         case (ast.atom_lit(?lit)) {
             alt (*lit) {
                 case (ast.lit_int(?i)) {
-                    cx.sess.unimpl("log int");
+                    trans_upcall(cx, "upcall_log_int", vec(C_int(i)));
                 }
                 case (_) {
-                    cx.sess.unimpl("literal variant in trans_log");
+                    cx.fcx.tcx.sess.unimpl("literal variant in trans_log");
                 }
             }
         }
         case (_) {
-            cx.sess.unimpl("atom variant in trans_log");
+            cx.fcx.tcx.sess.unimpl("atom variant in trans_log");
         }
     }
 }
 
-fn trans_stmt(&trans_ctxt cx, builder b, &ast.stmt s, terminator t) {
+fn trans_stmt(@block_ctxt cx, &ast.stmt s) {
     alt (s) {
         case (ast.stmt_log(?a)) {
-            trans_log(cx, b, *a);
+            trans_log(cx, *a);
         }
         case (_) {
-            cx.sess.unimpl("stmt variant");
+            cx.fcx.tcx.sess.unimpl("stmt variant");
         }
     }
 }
 
-fn default_terminate(&trans_ctxt cx, builder b) {
-    b.RetVoid();
+fn default_terminate(@fn_ctxt cx, builder build) {
+    build.RetVoid();
 }
 
-fn trans_block(&trans_ctxt cx, ValueRef llfn, &ast.block b, terminator t) {
+fn trans_block(@fn_ctxt cx, &ast.block b, terminator term) {
     let BasicBlockRef llbb =
-        llvm.LLVMAppendBasicBlock(llfn, _str.buf(""));
+        llvm.LLVMAppendBasicBlock(cx.llfn, _str.buf(""));
     let BuilderRef llbuild = llvm.LLVMCreateBuilder();
     llvm.LLVMPositionBuilderAtEnd(llbuild, llbb);
-    auto bld = builder(llbuild);
+    auto bcx = @rec(llbb=llbb,
+                    build=builder(llbuild),
+                    term=term,
+                    fcx=cx);
     for (@ast.stmt s in b) {
-        trans_stmt(cx, bld, *s, t);
+        trans_stmt(bcx, *s);
     }
-    t(cx, bld);
+    bcx.term(cx, bcx.build);
 }
 
-fn trans_fn(&trans_ctxt cx, &ast._fn f) {
-    let vec[TypeRef] args = vec();
+fn trans_fn(@trans_ctxt cx, &ast._fn f) {
+    let vec[TypeRef] args = vec(T_ptr(T_int()), // outptr.
+                                T_ptr(T_task()) // taskptr
+                                );
     let ValueRef llfn = decl_cdecl_fn(cx.llmod, cx.path, args, T_nil());
+    let ValueRef lloutptr = llvm.LLVMGetParam(llfn, 0u);
+    let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 1u);
+    auto fcx = @rec(llfn=llfn,
+                    lloutptr=lloutptr,
+                    lltaskptr=lltaskptr,
+                    tcx=cx);
     auto term = default_terminate;
-
-    trans_block(cx, llfn, f.body, term);
+    trans_block(fcx, f.body, term);
 }
 
-fn trans_item(&trans_ctxt cx, &str name, &ast.item item) {
-    auto sub_cx = rec(path=cx.path + "." + name with cx);
+fn trans_item(@trans_ctxt cx, &str name, &ast.item item) {
+    auto sub_cx = @rec(path=cx.path + "." + name with *cx);
     alt (item) {
         case (ast.item_fn(?f)) {
             trans_fn(sub_cx, *f);
@@ -170,7 +238,7 @@ fn trans_item(&trans_ctxt cx, &str name, &ast.item item) {
     }
 }
 
-fn trans_mod(&trans_ctxt cx, &ast._mod m) {
+fn trans_mod(@trans_ctxt cx, &ast._mod m) {
     for each (tup(str, ast.item) pair in m.items()) {
         trans_item(cx, pair._0, pair._1);
     }
@@ -183,17 +251,18 @@ fn trans_crate(session.session sess, ast.crate crate) {
 
     llvm.LLVMSetModuleInlineAsm(llmod, _str.buf(x86.get_module_asm()));
 
-    auto glues = @rec(activate_glue = decl_glue(llmod, "rust_activate_glue"),
-                      yield_glue = decl_glue(llmod, "rust_yield_glue"),
+    auto glues = @rec(activate_glue = decl_glue(llmod,
+                                                abi.activate_glue_name()),
+                      yield_glue = decl_glue(llmod, abi.yield_glue_name()),
                       upcall_glues =
                       _vec.init_fn[ValueRef](bind decl_upcall(llmod, _),
                                              abi.n_upcall_glues as uint));
 
-    auto cx = rec(sess = sess,
-                  llmod = llmod,
-                  upcalls = new_str_hash[ValueRef](),
-                  glues = glues,
-                  path = "");
+    auto cx = @rec(sess = sess,
+                   llmod = llmod,
+                   upcalls = new_str_hash[ValueRef](),
+                   glues = glues,
+                   path = "");
 
     trans_mod(cx, crate.module);
 
diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc
index cf2c25ae8c2..76b8fd624bc 100644
--- a/src/comp/rustc.rc
+++ b/src/comp/rustc.rc
@@ -30,6 +30,7 @@ mod util {
 
 auth driver.rustc.main = state;
 auth middle.trans = unsafe;
+auth lib.llvm = unsafe;
 
 
 mod lib {