Skip to content

Commit 4cfc425

Browse files
committed
More work on trans, almost getting to the point of emitting an upcall.
1 parent 6b412be commit 4cfc425

File tree

5 files changed

+204
-37
lines changed

5 files changed

+204
-37
lines changed

src/comp/back/abi.rs

+12
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@ const int worst_case_glue_call_args = 7;
3636

3737
const int n_upcall_glues = 7;
3838

39+
fn upcall_glue_name(int n) -> str {
40+
ret "rust_upcall_" + util.common.istr(n);
41+
}
42+
43+
fn activate_glue_name() -> str {
44+
ret "rust_activate_glue";
45+
}
46+
47+
fn yield_glue_name() -> str {
48+
ret "rust_yield_glue";
49+
}
50+
3951
//
4052
// Local Variables:
4153
// mode: rust

src/comp/back/x86.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ fn decl_glue(int align, str prefix, str name, vec[str] insns) -> str {
121121
fn decl_upcall_glue(int align, str prefix, uint n) -> str {
122122
let int i = n as int;
123123
ret decl_glue(align, prefix,
124-
"rust_upcall_" + istr(i),
124+
abi.upcall_glue_name(i),
125125
upcall_glue(i));
126126
}
127127

@@ -131,11 +131,11 @@ fn get_module_asm() -> str {
131131

132132
auto glues =
133133
vec(decl_glue(align, prefix,
134-
"rust_activate_glue",
134+
abi.activate_glue_name(),
135135
rust_activate_glue()),
136136

137137
decl_glue(align, prefix,
138-
"rust_yield_glue",
138+
abi.yield_glue_name(),
139139
rust_yield_glue()))
140140

141141
+ _vec.init_fn[str](bind decl_upcall_glue(align, prefix, _),

src/comp/lib/llvm.rs

+87-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ const uint LLVMColdCallConv = 9u;
4141
const uint LLVMX86StdcallCallConv = 64u;
4242
const uint LLVMX86FastcallCallConv = 65u;
4343

44-
4544
native mod llvm = llvm_lib {
4645

4746
type ModuleRef;
@@ -96,6 +95,14 @@ native mod llvm = llvm_lib {
9695
/** See Module::setModuleInlineAsm. */
9796
fn LLVMSetModuleInlineAsm(ModuleRef M, sbuf Asm);
9897

98+
/** See llvm::LLVMTypeKind::getTypeID. */
99+
100+
// FIXME: returning int rather than TypeKind because
101+
// we directly inspect the values, and casting from
102+
// a native doesn't work yet (only *to* a native).
103+
104+
fn LLVMGetTypeKind(TypeRef Ty) -> int;
105+
99106
/** See llvm::LLVMType::getContext. */
100107
fn LLVMGetTypeContext(TypeRef Ty) -> ContextRef;
101108

@@ -213,7 +220,9 @@ native mod llvm = llvm_lib {
213220

214221
/* Operations on scalar constants */
215222
fn LLVMConstInt(TypeRef IntTy, ULongLong N, Bool SignExtend) -> ValueRef;
216-
fn LLVMConstIntOfString(TypeRef IntTy, sbuf Text, u8 Radix) -> ValueRef;
223+
// FIXME: radix is actually u8, but our native layer can't handle this
224+
// yet. lucky for us we're little-endian. Small miracles.
225+
fn LLVMConstIntOfString(TypeRef IntTy, sbuf Text, int Radix) -> ValueRef;
217226
fn LLVMConstIntOfStringAndSize(TypeRef IntTy, sbuf Text,
218227
uint SLen, u8 Radix) -> ValueRef;
219228
fn LLVMConstReal(TypeRef RealTy, f64 N) -> ValueRef;
@@ -1041,6 +1050,82 @@ obj builder(BuilderRef B) {
10411050
}
10421051
}
10431052

1053+
fn type_to_str(TypeRef ty) -> str {
1054+
let int kind = llvm.LLVMGetTypeKind(ty);
1055+
1056+
fn tys_str(vec[TypeRef] tys) -> str {
1057+
let str s = "";
1058+
let bool first = true;
1059+
for (TypeRef t in tys) {
1060+
if (first) {
1061+
first = false;
1062+
} else {
1063+
s += ", ";
1064+
}
1065+
s += type_to_str(t);
1066+
}
1067+
ret s;
1068+
}
1069+
1070+
alt (kind) {
1071+
1072+
// FIXME: more enum-as-int constants determined from Core.h;
1073+
// horrible, horrible. Complete as needed.
1074+
1075+
case (0) { ret "Void"; }
1076+
case (1) { ret "Float"; }
1077+
case (2) { ret "Double"; }
1078+
case (3) { ret "X86_FP80"; }
1079+
case (4) { ret "FP128"; }
1080+
case (5) { ret "PPC_FP128"; }
1081+
case (6) { ret "Label"; }
1082+
1083+
case (7) {
1084+
ret "i" + util.common.istr(llvm.LLVMGetIntTypeWidth(ty) as int);
1085+
}
1086+
1087+
case (8) {
1088+
auto s = "fn(";
1089+
let TypeRef out_ty = llvm.LLVMGetReturnType(ty);
1090+
let uint n_args = llvm.LLVMCountParamTypes(ty);
1091+
let vec[TypeRef] args =
1092+
_vec.init_elt[TypeRef](0 as TypeRef, n_args);
1093+
llvm.LLVMGetParamTypes(ty, _vec.buf[TypeRef](args));
1094+
s += tys_str(args);
1095+
s += ") -> ";
1096+
s += type_to_str(out_ty);
1097+
ret s;
1098+
}
1099+
1100+
case (9) {
1101+
let str s = "{";
1102+
let uint n_elts = llvm.LLVMCountStructElementTypes(ty);
1103+
let vec[TypeRef] elts =
1104+
_vec.init_elt[TypeRef](0 as TypeRef, n_elts);
1105+
llvm.LLVMGetStructElementTypes(ty, _vec.buf[TypeRef](elts));
1106+
s += tys_str(elts);
1107+
s += "}";
1108+
ret s;
1109+
}
1110+
1111+
case (10) { ret "Array"; }
1112+
1113+
case (11) {
1114+
ret "*" + type_to_str(llvm.LLVMGetElementType(ty));
1115+
}
1116+
1117+
case (12) { ret "Opaque"; }
1118+
case (13) { ret "Vector"; }
1119+
case (14) { ret "Metadata"; }
1120+
case (15) { ret "Union"; }
1121+
case (_) {
1122+
log "unknown TypeKind" + util.common.istr(kind as int);
1123+
fail;
1124+
}
1125+
}
1126+
}
1127+
1128+
10441129
//
10451130
// Local Variables:
10461131
// mode: rust

src/comp/middle/trans.rs

+101-32
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@ type trans_ctxt = rec(session.session sess,
3333
@glue_fns glues,
3434
str path);
3535

36+
type fn_ctxt = rec(ValueRef llfn,
37+
ValueRef lloutptr,
38+
ValueRef lltaskptr,
39+
@trans_ctxt tcx);
40+
41+
type terminator = fn(@fn_ctxt cx, builder build);
42+
43+
type block_ctxt = rec(BasicBlockRef llbb,
44+
builder build,
45+
terminator term,
46+
@fn_ctxt fcx);
47+
48+
49+
// LLVM type constructors.
50+
3651
fn T_nil() -> TypeRef {
3752
ret llvm.LLVMVoidType();
3853
}
@@ -67,9 +82,38 @@ fn T_task() -> TypeRef {
6782
T_opaque())); // Rest is opaque for now
6883
}
6984

85+
86+
// LLVM constant constructors.
87+
88+
fn C_null(TypeRef t) -> ValueRef {
89+
ret llvm.LLVMConstNull(t);
90+
}
91+
92+
fn C_int(int i) -> ValueRef {
93+
// FIXME. We can't use LLVM.ULongLong with our existing minimal native
94+
// API, which only knows word-sized args. Lucky for us LLVM has a "take a
95+
// string encoding" version. Hilarious. Please fix to handle:
96+
//
97+
// ret llvm.LLVMConstInt(T_int(), t as LLVM.ULongLong, False);
98+
//
99+
ret llvm.LLVMConstIntOfString(T_int(),
100+
_str.buf(istr(i)), 10);
101+
}
102+
103+
fn C_str(str s) -> ValueRef {
104+
ret llvm.LLVMConstString(_str.buf(s), _str.byte_len(s), False);
105+
}
106+
107+
fn C_struct(vec[ValueRef] elts) -> ValueRef {
108+
ret llvm.LLVMConstStruct(_vec.buf[ValueRef](elts),
109+
_vec.len[ValueRef](elts),
110+
False);
111+
}
112+
70113
fn decl_cdecl_fn(ModuleRef llmod, str name,
71114
vec[TypeRef] inputs, TypeRef output) -> ValueRef {
72115
let TypeRef llty = T_fn(inputs, output);
116+
log "declaring " + name + " with type " + lib.llvm.type_to_str(llty);
73117
let ValueRef llfn =
74118
llvm.LLVMAddFunction(llmod, _str.buf(name), llty);
75119
llvm.LLVMSetFunctionCallConv(llfn, lib.llvm.LLVMCCallConv);
@@ -82,7 +126,7 @@ fn decl_glue(ModuleRef llmod, str s) -> ValueRef {
82126

83127
fn decl_upcall(ModuleRef llmod, uint _n) -> ValueRef {
84128
let int n = _n as int;
85-
let str s = "rust_upcall_" + istr(n);
129+
let str s = abi.upcall_glue_name(n);
86130
let vec[TypeRef] args =
87131
vec(T_ptr(T_task()), // taskptr
88132
T_int()) // callee
@@ -91,9 +135,7 @@ fn decl_upcall(ModuleRef llmod, uint _n) -> ValueRef {
91135
ret decl_cdecl_fn(llmod, s, args, T_int());
92136
}
93137

94-
type terminator = fn(&trans_ctxt cx, builder b);
95-
96-
fn get_upcall(&trans_ctxt cx, str name, int n_args) -> ValueRef {
138+
fn get_upcall(@trans_ctxt cx, str name, int n_args) -> ValueRef {
97139
if (cx.upcalls.contains_key(name)) {
98140
ret cx.upcalls.get(name);
99141
}
@@ -105,61 +147,87 @@ fn get_upcall(&trans_ctxt cx, str name, int n_args) -> ValueRef {
105147
ret f;
106148
}
107149

108-
fn trans_log(&trans_ctxt cx, builder b, &ast.atom a) {
150+
fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> ValueRef {
151+
let int n = _vec.len[ValueRef](args) as int;
152+
let ValueRef llupcall = get_upcall(cx.fcx.tcx, name, n);
153+
llupcall = llvm.LLVMConstPointerCast(llupcall, T_int());
154+
155+
let ValueRef llglue = cx.fcx.tcx.glues.upcall_glues.(n);
156+
let vec[ValueRef] call_args = vec(cx.fcx.lltaskptr, llupcall) + args;
157+
log "emitting indirect-upcall via " + abi.upcall_glue_name(n);
158+
for (ValueRef v in call_args) {
159+
log "arg: " + lib.llvm.type_to_str(llvm.LLVMTypeOf(v));
160+
}
161+
log "emitting call to callee of type: " +
162+
lib.llvm.type_to_str(llvm.LLVMTypeOf(llglue));
163+
ret cx.build.Call(llglue, call_args);
164+
}
165+
166+
fn trans_log(@block_ctxt cx, &ast.atom a) {
109167
alt (a) {
110168
case (ast.atom_lit(?lit)) {
111169
alt (*lit) {
112170
case (ast.lit_int(?i)) {
113-
cx.sess.unimpl("log int");
171+
trans_upcall(cx, "upcall_log_int", vec(C_int(i)));
114172
}
115173
case (_) {
116-
cx.sess.unimpl("literal variant in trans_log");
174+
cx.fcx.tcx.sess.unimpl("literal variant in trans_log");
117175
}
118176
}
119177
}
120178
case (_) {
121-
cx.sess.unimpl("atom variant in trans_log");
179+
cx.fcx.tcx.sess.unimpl("atom variant in trans_log");
122180
}
123181
}
124182
}
125183

126-
fn trans_stmt(&trans_ctxt cx, builder b, &ast.stmt s, terminator t) {
184+
fn trans_stmt(@block_ctxt cx, &ast.stmt s) {
127185
alt (s) {
128186
case (ast.stmt_log(?a)) {
129-
trans_log(cx, b, *a);
187+
trans_log(cx, *a);
130188
}
131189
case (_) {
132-
cx.sess.unimpl("stmt variant");
190+
cx.fcx.tcx.sess.unimpl("stmt variant");
133191
}
134192
}
135193
}
136194

137-
fn default_terminate(&trans_ctxt cx, builder b) {
138-
b.RetVoid();
195+
fn default_terminate(@fn_ctxt cx, builder build) {
196+
build.RetVoid();
139197
}
140198

141-
fn trans_block(&trans_ctxt cx, ValueRef llfn, &ast.block b, terminator t) {
199+
fn trans_block(@fn_ctxt cx, &ast.block b, terminator term) {
142200
let BasicBlockRef llbb =
143-
llvm.LLVMAppendBasicBlock(llfn, _str.buf(""));
201+
llvm.LLVMAppendBasicBlock(cx.llfn, _str.buf(""));
144202
let BuilderRef llbuild = llvm.LLVMCreateBuilder();
145203
llvm.LLVMPositionBuilderAtEnd(llbuild, llbb);
146-
auto bld = builder(llbuild);
204+
auto bcx = @rec(llbb=llbb,
205+
build=builder(llbuild),
206+
term=term,
207+
fcx=cx);
147208
for (@ast.stmt s in b) {
148-
trans_stmt(cx, bld, *s, t);
209+
trans_stmt(bcx, *s);
149210
}
150-
t(cx, bld);
211+
bcx.term(cx, bcx.build);
151212
}
152213

153-
fn trans_fn(&trans_ctxt cx, &ast._fn f) {
154-
let vec[TypeRef] args = vec();
214+
fn trans_fn(@trans_ctxt cx, &ast._fn f) {
215+
let vec[TypeRef] args = vec(T_ptr(T_int()), // outptr.
216+
T_ptr(T_task()) // taskptr
217+
);
155218
let ValueRef llfn = decl_cdecl_fn(cx.llmod, cx.path, args, T_nil());
219+
let ValueRef lloutptr = llvm.LLVMGetParam(llfn, 0u);
220+
let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 1u);
221+
auto fcx = @rec(llfn=llfn,
222+
lloutptr=lloutptr,
223+
lltaskptr=lltaskptr,
224+
tcx=cx);
156225
auto term = default_terminate;
157-
158-
trans_block(cx, llfn, f.body, term);
226+
trans_block(fcx, f.body, term);
159227
}
160228

161-
fn trans_item(&trans_ctxt cx, &str name, &ast.item item) {
162-
auto sub_cx = rec(path=cx.path + "." + name with cx);
229+
fn trans_item(@trans_ctxt cx, &str name, &ast.item item) {
230+
auto sub_cx = @rec(path=cx.path + "." + name with *cx);
163231
alt (item) {
164232
case (ast.item_fn(?f)) {
165233
trans_fn(sub_cx, *f);
@@ -170,7 +238,7 @@ fn trans_item(&trans_ctxt cx, &str name, &ast.item item) {
170238
}
171239
}
172240

173-
fn trans_mod(&trans_ctxt cx, &ast._mod m) {
241+
fn trans_mod(@trans_ctxt cx, &ast._mod m) {
174242
for each (tup(str, ast.item) pair in m.items()) {
175243
trans_item(cx, pair._0, pair._1);
176244
}
@@ -183,17 +251,18 @@ fn trans_crate(session.session sess, ast.crate crate) {
183251

184252
llvm.LLVMSetModuleInlineAsm(llmod, _str.buf(x86.get_module_asm()));
185253

186-
auto glues = @rec(activate_glue = decl_glue(llmod, "rust_activate_glue"),
187-
yield_glue = decl_glue(llmod, "rust_yield_glue"),
254+
auto glues = @rec(activate_glue = decl_glue(llmod,
255+
abi.activate_glue_name()),
256+
yield_glue = decl_glue(llmod, abi.yield_glue_name()),
188257
upcall_glues =
189258
_vec.init_fn[ValueRef](bind decl_upcall(llmod, _),
190259
abi.n_upcall_glues as uint));
191260

192-
auto cx = rec(sess = sess,
193-
llmod = llmod,
194-
upcalls = new_str_hash[ValueRef](),
195-
glues = glues,
196-
path = "");
261+
auto cx = @rec(sess = sess,
262+
llmod = llmod,
263+
upcalls = new_str_hash[ValueRef](),
264+
glues = glues,
265+
path = "");
197266

198267
trans_mod(cx, crate.module);
199268

src/comp/rustc.rc

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ mod util {
3030

3131
auth driver.rustc.main = state;
3232
auth middle.trans = unsafe;
33+
auth lib.llvm = unsafe;
3334

3435

3536
mod lib {

0 commit comments

Comments
 (0)