More work on trans, almost getting to the point of emitting an upcall.
This commit is contained in:
parent
6b412be619
commit
4cfc4250bf
5 changed files with 204 additions and 37 deletions
|
@ -36,6 +36,18 @@ const int worst_case_glue_call_args = 7;
|
||||||
|
|
||||||
const int n_upcall_glues = 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:
|
// Local Variables:
|
||||||
// mode: rust
|
// 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 {
|
fn decl_upcall_glue(int align, str prefix, uint n) -> str {
|
||||||
let int i = n as int;
|
let int i = n as int;
|
||||||
ret decl_glue(align, prefix,
|
ret decl_glue(align, prefix,
|
||||||
"rust_upcall_" + istr(i),
|
abi.upcall_glue_name(i),
|
||||||
upcall_glue(i));
|
upcall_glue(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,11 +131,11 @@ fn get_module_asm() -> str {
|
||||||
|
|
||||||
auto glues =
|
auto glues =
|
||||||
vec(decl_glue(align, prefix,
|
vec(decl_glue(align, prefix,
|
||||||
"rust_activate_glue",
|
abi.activate_glue_name(),
|
||||||
rust_activate_glue()),
|
rust_activate_glue()),
|
||||||
|
|
||||||
decl_glue(align, prefix,
|
decl_glue(align, prefix,
|
||||||
"rust_yield_glue",
|
abi.yield_glue_name(),
|
||||||
rust_yield_glue()))
|
rust_yield_glue()))
|
||||||
|
|
||||||
+ _vec.init_fn[str](bind decl_upcall_glue(align, prefix, _),
|
+ _vec.init_fn[str](bind decl_upcall_glue(align, prefix, _),
|
||||||
|
|
|
@ -41,7 +41,6 @@ const uint LLVMColdCallConv = 9u;
|
||||||
const uint LLVMX86StdcallCallConv = 64u;
|
const uint LLVMX86StdcallCallConv = 64u;
|
||||||
const uint LLVMX86FastcallCallConv = 65u;
|
const uint LLVMX86FastcallCallConv = 65u;
|
||||||
|
|
||||||
|
|
||||||
native mod llvm = llvm_lib {
|
native mod llvm = llvm_lib {
|
||||||
|
|
||||||
type ModuleRef;
|
type ModuleRef;
|
||||||
|
@ -96,6 +95,14 @@ native mod llvm = llvm_lib {
|
||||||
/** See Module::setModuleInlineAsm. */
|
/** See Module::setModuleInlineAsm. */
|
||||||
fn LLVMSetModuleInlineAsm(ModuleRef M, sbuf Asm);
|
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. */
|
/** See llvm::LLVMType::getContext. */
|
||||||
fn LLVMGetTypeContext(TypeRef Ty) -> ContextRef;
|
fn LLVMGetTypeContext(TypeRef Ty) -> ContextRef;
|
||||||
|
|
||||||
|
@ -213,7 +220,9 @@ native mod llvm = llvm_lib {
|
||||||
|
|
||||||
/* Operations on scalar constants */
|
/* Operations on scalar constants */
|
||||||
fn LLVMConstInt(TypeRef IntTy, ULongLong N, Bool SignExtend) -> ValueRef;
|
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,
|
fn LLVMConstIntOfStringAndSize(TypeRef IntTy, sbuf Text,
|
||||||
uint SLen, u8 Radix) -> ValueRef;
|
uint SLen, u8 Radix) -> ValueRef;
|
||||||
fn LLVMConstReal(TypeRef RealTy, f64 N) -> 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:
|
// Local Variables:
|
||||||
// mode: rust
|
// mode: rust
|
||||||
|
|
|
@ -33,6 +33,21 @@ type trans_ctxt = rec(session.session sess,
|
||||||
@glue_fns glues,
|
@glue_fns glues,
|
||||||
str path);
|
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 {
|
fn T_nil() -> TypeRef {
|
||||||
ret llvm.LLVMVoidType();
|
ret llvm.LLVMVoidType();
|
||||||
}
|
}
|
||||||
|
@ -67,9 +82,38 @@ fn T_task() -> TypeRef {
|
||||||
T_opaque())); // Rest is opaque for now
|
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,
|
fn decl_cdecl_fn(ModuleRef llmod, str name,
|
||||||
vec[TypeRef] inputs, TypeRef output) -> ValueRef {
|
vec[TypeRef] inputs, TypeRef output) -> ValueRef {
|
||||||
let TypeRef llty = T_fn(inputs, output);
|
let TypeRef llty = T_fn(inputs, output);
|
||||||
|
log "declaring " + name + " with type " + lib.llvm.type_to_str(llty);
|
||||||
let ValueRef llfn =
|
let ValueRef llfn =
|
||||||
llvm.LLVMAddFunction(llmod, _str.buf(name), llty);
|
llvm.LLVMAddFunction(llmod, _str.buf(name), llty);
|
||||||
llvm.LLVMSetFunctionCallConv(llfn, lib.llvm.LLVMCCallConv);
|
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 {
|
fn decl_upcall(ModuleRef llmod, uint _n) -> ValueRef {
|
||||||
let int n = _n as int;
|
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 =
|
let vec[TypeRef] args =
|
||||||
vec(T_ptr(T_task()), // taskptr
|
vec(T_ptr(T_task()), // taskptr
|
||||||
T_int()) // callee
|
T_int()) // callee
|
||||||
|
@ -91,9 +135,7 @@ fn decl_upcall(ModuleRef llmod, uint _n) -> ValueRef {
|
||||||
ret decl_cdecl_fn(llmod, s, args, T_int());
|
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)) {
|
if (cx.upcalls.contains_key(name)) {
|
||||||
ret cx.upcalls.get(name);
|
ret cx.upcalls.get(name);
|
||||||
}
|
}
|
||||||
|
@ -105,61 +147,87 @@ fn get_upcall(&trans_ctxt cx, str name, int n_args) -> ValueRef {
|
||||||
ret f;
|
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) {
|
alt (a) {
|
||||||
case (ast.atom_lit(?lit)) {
|
case (ast.atom_lit(?lit)) {
|
||||||
alt (*lit) {
|
alt (*lit) {
|
||||||
case (ast.lit_int(?i)) {
|
case (ast.lit_int(?i)) {
|
||||||
cx.sess.unimpl("log int");
|
trans_upcall(cx, "upcall_log_int", vec(C_int(i)));
|
||||||
}
|
}
|
||||||
case (_) {
|
case (_) {
|
||||||
cx.sess.unimpl("literal variant in trans_log");
|
cx.fcx.tcx.sess.unimpl("literal variant in trans_log");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case (_) {
|
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) {
|
alt (s) {
|
||||||
case (ast.stmt_log(?a)) {
|
case (ast.stmt_log(?a)) {
|
||||||
trans_log(cx, b, *a);
|
trans_log(cx, *a);
|
||||||
}
|
}
|
||||||
case (_) {
|
case (_) {
|
||||||
cx.sess.unimpl("stmt variant");
|
cx.fcx.tcx.sess.unimpl("stmt variant");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_terminate(&trans_ctxt cx, builder b) {
|
fn default_terminate(@fn_ctxt cx, builder build) {
|
||||||
b.RetVoid();
|
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 =
|
let BasicBlockRef llbb =
|
||||||
llvm.LLVMAppendBasicBlock(llfn, _str.buf(""));
|
llvm.LLVMAppendBasicBlock(cx.llfn, _str.buf(""));
|
||||||
let BuilderRef llbuild = llvm.LLVMCreateBuilder();
|
let BuilderRef llbuild = llvm.LLVMCreateBuilder();
|
||||||
llvm.LLVMPositionBuilderAtEnd(llbuild, llbb);
|
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) {
|
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) {
|
fn trans_fn(@trans_ctxt cx, &ast._fn f) {
|
||||||
let vec[TypeRef] args = vec();
|
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 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;
|
auto term = default_terminate;
|
||||||
|
trans_block(fcx, f.body, term);
|
||||||
trans_block(cx, llfn, f.body, term);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_item(&trans_ctxt cx, &str name, &ast.item item) {
|
fn trans_item(@trans_ctxt cx, &str name, &ast.item item) {
|
||||||
auto sub_cx = rec(path=cx.path + "." + name with cx);
|
auto sub_cx = @rec(path=cx.path + "." + name with *cx);
|
||||||
alt (item) {
|
alt (item) {
|
||||||
case (ast.item_fn(?f)) {
|
case (ast.item_fn(?f)) {
|
||||||
trans_fn(sub_cx, *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()) {
|
for each (tup(str, ast.item) pair in m.items()) {
|
||||||
trans_item(cx, pair._0, pair._1);
|
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()));
|
llvm.LLVMSetModuleInlineAsm(llmod, _str.buf(x86.get_module_asm()));
|
||||||
|
|
||||||
auto glues = @rec(activate_glue = decl_glue(llmod, "rust_activate_glue"),
|
auto glues = @rec(activate_glue = decl_glue(llmod,
|
||||||
yield_glue = decl_glue(llmod, "rust_yield_glue"),
|
abi.activate_glue_name()),
|
||||||
|
yield_glue = decl_glue(llmod, abi.yield_glue_name()),
|
||||||
upcall_glues =
|
upcall_glues =
|
||||||
_vec.init_fn[ValueRef](bind decl_upcall(llmod, _),
|
_vec.init_fn[ValueRef](bind decl_upcall(llmod, _),
|
||||||
abi.n_upcall_glues as uint));
|
abi.n_upcall_glues as uint));
|
||||||
|
|
||||||
auto cx = rec(sess = sess,
|
auto cx = @rec(sess = sess,
|
||||||
llmod = llmod,
|
llmod = llmod,
|
||||||
upcalls = new_str_hash[ValueRef](),
|
upcalls = new_str_hash[ValueRef](),
|
||||||
glues = glues,
|
glues = glues,
|
||||||
path = "");
|
path = "");
|
||||||
|
|
||||||
trans_mod(cx, crate.module);
|
trans_mod(cx, crate.module);
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ mod util {
|
||||||
|
|
||||||
auth driver.rustc.main = state;
|
auth driver.rustc.main = state;
|
||||||
auth middle.trans = unsafe;
|
auth middle.trans = unsafe;
|
||||||
|
auth lib.llvm = unsafe;
|
||||||
|
|
||||||
|
|
||||||
mod lib {
|
mod lib {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue