提交 4cfc4250 编写于 作者: G Graydon Hoare

More work on trans, almost getting to the point of emitting an upcall.

上级 6b412be6
......@@ -36,6 +36,18 @@
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
......
......@@ -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, _),
......
......@@ -41,7 +41,6 @@
const uint LLVMX86StdcallCallConv = 64u;
const uint LLVMX86FastcallCallConv = 65u;
native mod llvm = llvm_lib {
type ModuleRef;
......@@ -96,6 +95,14 @@ fn LLVMModuleCreateWithNameInContext(sbuf ModuleID,
/** 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 @@ fn LLVMUnionTypeInContext(ContextRef C, vbuf ElementTypes,
/* 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 @@ fn PtrDiff(ValueRef LHS, ValueRef RHS) -> ValueRef {
}
}
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
......
......@@ -33,6 +33,21 @@
@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);
......
......@@ -30,6 +30,7 @@ mod util {
auth driver.rustc.main = state;
auth middle.trans = unsafe;
auth lib.llvm = unsafe;
mod lib {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册