aboutsummaryrefslogtreecommitdiff
path: root/src/comp
diff options
context:
space:
mode:
authorGraydon Hoare <[email protected]>2010-09-24 14:56:04 -0700
committerGraydon Hoare <[email protected]>2010-09-24 14:56:04 -0700
commit4cfc4250bf721d5946b4f91c7b561dd57a00cc96 (patch)
tree74ddce35ffc08f66def2dccba16515414b01868d /src/comp
parentWrap long line. (diff)
downloadrust-4cfc4250bf721d5946b4f91c7b561dd57a00cc96.tar.xz
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 1a349a7b..ad4c066e 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 bfe50200..b3edcae6 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 704c6092..ac8dd76f 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 30d72104..e2dfc7c1 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 cf2c25ae..76b8fd62 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 {