diff options
Diffstat (limited to 'src/comp')
| -rw-r--r-- | src/comp/driver/rustc.rs | 2 | ||||
| -rw-r--r-- | src/comp/front/lexer.rs | 18 | ||||
| -rw-r--r-- | src/comp/front/parser.rs | 78 | ||||
| -rw-r--r-- | src/comp/middle/trans.rs | 88 |
4 files changed, 118 insertions, 68 deletions
diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs index e3eb10cf..b9e4aef1 100644 --- a/src/comp/driver/rustc.rs +++ b/src/comp/driver/rustc.rs @@ -4,7 +4,7 @@ import front.parser; import front.token; import middle.trans; -fn main(vec[str] args) { +io fn main(vec[str] args) { log "This is the rust 'self-hosted' compiler."; log "The one written in rust."; diff --git a/src/comp/front/lexer.rs b/src/comp/front/lexer.rs index d058db4a..f38f5024 100644 --- a/src/comp/front/lexer.rs +++ b/src/comp/front/lexer.rs @@ -9,8 +9,8 @@ state type reader = state obj { fn is_eof() -> bool; fn curr() -> char; fn next() -> char; - state fn bump(); - state fn mark(); + io fn bump(); + fn mark(); fn get_filename() -> str; fn get_mark_pos() -> common.pos; fn get_curr_pos() -> common.pos; @@ -55,7 +55,7 @@ fn new_reader(stdio_reader rdr, str filename) -> reader ret n; } - state fn bump() { + io fn bump() { c = n; if (c == (-1) as char) { @@ -72,7 +72,7 @@ fn new_reader(stdio_reader rdr, str filename) -> reader n = rdr.getc() as char; } - state fn mark() { + fn mark() { mark_line = line; mark_col = col; } @@ -243,14 +243,14 @@ fn is_whitespace(char c) -> bool { ret c == ' ' || c == '\t' || c == '\r' || c == '\n'; } -state fn consume_any_whitespace(reader rdr) { +io fn consume_any_whitespace(reader rdr) { while (is_whitespace(rdr.curr())) { rdr.bump(); } be consume_any_line_comment(rdr); } -state fn consume_any_line_comment(reader rdr) { +io fn consume_any_line_comment(reader rdr) { if (rdr.curr() == '/') { alt (rdr.next()) { case ('/') { @@ -273,7 +273,7 @@ state fn consume_any_line_comment(reader rdr) { } -state fn consume_block_comment(reader rdr) { +io fn consume_block_comment(reader rdr) { let int level = 1; while (level > 0) { if (rdr.curr() == '/' && rdr.next() == '*') { @@ -294,7 +294,7 @@ state fn consume_block_comment(reader rdr) { be consume_any_whitespace(rdr); } -state fn next_token(reader rdr) -> token.token { +io fn next_token(reader rdr) -> token.token { auto accum_str = ""; auto accum_int = 0; @@ -355,7 +355,7 @@ state fn next_token(reader rdr) -> token.token { ret token.LIT_INT(accum_int); } - state fn binop(reader rdr, token.binop op) -> token.token { + io fn binop(reader rdr, token.binop op) -> token.token { rdr.bump(); if (rdr.next() == '=') { rdr.bump(); diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs index 98cb7e1e..44bddf08 100644 --- a/src/comp/front/parser.rs +++ b/src/comp/front/parser.rs @@ -14,26 +14,26 @@ tag option[T] { state type parser = state obj { - state fn peek() -> token.token; - state fn bump(); + fn peek() -> token.token; + io fn bump(); io fn err(str s); fn get_session() -> session.session; fn get_span() -> common.span; }; -state fn new_parser(session.session sess, str path) -> parser { +io fn new_parser(session.session sess, str path) -> parser { state obj stdio_parser(session.session sess, mutable token.token tok, mutable common.pos lo, mutable common.pos hi, lexer.reader rdr) { - state fn peek() -> token.token { + fn peek() -> token.token { log token.to_str(tok); ret tok; } - state fn bump() { + io fn bump() { tok = lexer.next_token(rdr); lo = rdr.get_mark_pos(); hi = rdr.get_curr_pos(); @@ -60,7 +60,7 @@ state fn new_parser(session.session sess, str path) -> parser { ret stdio_parser(sess, lexer.next_token(rdr), npos, npos, rdr); } -state fn expect(parser p, token.token t) { +io fn expect(parser p, token.token t) { if (p.peek() == t) { p.bump(); } else { @@ -72,7 +72,7 @@ state fn expect(parser p, token.token t) { } } -state fn parse_ident(parser p) -> ast.ident { +io fn parse_ident(parser p) -> ast.ident { alt (p.peek()) { case (token.IDENT(?i)) { p.bump(); ret i; } case (_) { @@ -82,7 +82,7 @@ state fn parse_ident(parser p) -> ast.ident { } } -state fn parse_ty(parser p) -> ast.ty { +io fn parse_ty(parser p) -> ast.ty { alt (p.peek()) { case (token.INT) { p.bump(); ret ast.ty_int; } case (token.UINT) { p.bump(); ret ast.ty_int; } @@ -94,7 +94,7 @@ state fn parse_ty(parser p) -> ast.ty { fail; } -state fn parse_slot(parser p) -> ast.slot { +io fn parse_slot(parser p) -> ast.slot { let ast.mode m = ast.val; if (p.peek() == token.BINOP(token.AND)) { m = ast.alias; @@ -104,10 +104,10 @@ state fn parse_slot(parser p) -> ast.slot { ret rec(ty=t, mode=m); } -state fn parse_seq[T](token.token bra, +io fn parse_seq[T](token.token bra, token.token ket, option[token.token] sep, - (state fn(parser) -> T) f, + (io fn(parser) -> T) f, parser p) -> vec[T] { let bool first = true; expect(p, bra); @@ -132,7 +132,7 @@ state fn parse_seq[T](token.token bra, ret v; } -state fn parse_lit(parser p) -> @ast.lit { +io fn parse_lit(parser p) -> @ast.lit { alt (p.peek()) { case (token.LIT_INT(?i)) { p.bump(); @@ -161,7 +161,7 @@ state fn parse_lit(parser p) -> @ast.lit { -state fn parse_bottom_expr(parser p) -> @ast.expr { +io fn parse_bottom_expr(parser p) -> @ast.expr { alt (p.peek()) { case (token.LPAREN) { p.bump(); @@ -192,7 +192,7 @@ state fn parse_bottom_expr(parser p) -> @ast.expr { case (token.REC) { p.bump(); - state fn parse_entry(parser p) -> + io fn parse_entry(parser p) -> tup(ast.ident, @ast.expr) { auto i = parse_ident(p); expect(p, token.EQ); @@ -219,7 +219,7 @@ state fn parse_bottom_expr(parser p) -> @ast.expr { } } -state fn parse_path_expr(parser p) -> @ast.expr { +io fn parse_path_expr(parser p) -> @ast.expr { auto e = parse_bottom_expr(p); while (true) { alt (p.peek()) { @@ -246,7 +246,7 @@ state fn parse_path_expr(parser p) -> @ast.expr { ret e; } -state fn parse_prefix_expr(parser p) -> @ast.expr { +io fn parse_prefix_expr(parser p) -> @ast.expr { alt (p.peek()) { case (token.NOT) { @@ -294,8 +294,8 @@ state fn parse_prefix_expr(parser p) -> @ast.expr { } } -state fn parse_binops(parser p, - (state fn(parser) -> @ast.expr) sub, +io fn parse_binops(parser p, + (io fn(parser) -> @ast.expr) sub, vec[tup(token.binop, ast.binop)] ops) -> @ast.expr { auto e = sub(p); @@ -317,8 +317,8 @@ state fn parse_binops(parser p, ret e; } -state fn parse_binary_exprs(parser p, - (state fn(parser) -> @ast.expr) sub, +io fn parse_binary_exprs(parser p, + (io fn(parser) -> @ast.expr) sub, vec[tup(token.token, ast.binop)] ops) -> @ast.expr { auto e = sub(p); @@ -336,42 +336,42 @@ state fn parse_binary_exprs(parser p, ret e; } -state fn parse_factor_expr(parser p) -> @ast.expr { +io fn parse_factor_expr(parser p) -> @ast.expr { auto sub = parse_prefix_expr; ret parse_binops(p, sub, vec(tup(token.STAR, ast.mul), tup(token.SLASH, ast.div), tup(token.PERCENT, ast.rem))); } -state fn parse_term_expr(parser p) -> @ast.expr { +io fn parse_term_expr(parser p) -> @ast.expr { auto sub = parse_factor_expr; ret parse_binops(p, sub, vec(tup(token.PLUS, ast.add), tup(token.MINUS, ast.sub))); } -state fn parse_shift_expr(parser p) -> @ast.expr { +io fn parse_shift_expr(parser p) -> @ast.expr { auto sub = parse_term_expr; ret parse_binops(p, sub, vec(tup(token.LSL, ast.lsl), tup(token.LSR, ast.lsr), tup(token.ASR, ast.asr))); } -state fn parse_bitand_expr(parser p) -> @ast.expr { +io fn parse_bitand_expr(parser p) -> @ast.expr { auto sub = parse_shift_expr; ret parse_binops(p, sub, vec(tup(token.AND, ast.bitand))); } -state fn parse_bitxor_expr(parser p) -> @ast.expr { +io fn parse_bitxor_expr(parser p) -> @ast.expr { auto sub = parse_bitand_expr; ret parse_binops(p, sub, vec(tup(token.CARET, ast.bitxor))); } -state fn parse_bitor_expr(parser p) -> @ast.expr { +io fn parse_bitor_expr(parser p) -> @ast.expr { auto sub = parse_bitxor_expr; ret parse_binops(p, sub, vec(tup(token.OR, ast.bitor))); } -state fn parse_cast_expr(parser p) -> @ast.expr { +io fn parse_cast_expr(parser p) -> @ast.expr { auto e = parse_bitor_expr(p); while (true) { alt (p.peek()) { @@ -389,7 +389,7 @@ state fn parse_cast_expr(parser p) -> @ast.expr { ret e; } -state fn parse_relational_expr(parser p) -> @ast.expr { +io fn parse_relational_expr(parser p) -> @ast.expr { auto sub = parse_cast_expr; ret parse_binary_exprs(p, sub, vec(tup(token.LT, ast.lt), tup(token.LE, ast.le), @@ -398,27 +398,27 @@ state fn parse_relational_expr(parser p) -> @ast.expr { } -state fn parse_equality_expr(parser p) -> @ast.expr { +io fn parse_equality_expr(parser p) -> @ast.expr { auto sub = parse_relational_expr; ret parse_binary_exprs(p, sub, vec(tup(token.EQEQ, ast.eq), tup(token.NE, ast.ne))); } -state fn parse_and_expr(parser p) -> @ast.expr { +io fn parse_and_expr(parser p) -> @ast.expr { auto sub = parse_equality_expr; ret parse_binary_exprs(p, sub, vec(tup(token.ANDAND, ast.and))); } -state fn parse_or_expr(parser p) -> @ast.expr { +io fn parse_or_expr(parser p) -> @ast.expr { auto sub = parse_and_expr; ret parse_binary_exprs(p, sub, vec(tup(token.OROR, ast.or))); } -state fn parse_expr(parser p) -> @ast.expr { +io fn parse_expr(parser p) -> @ast.expr { ret parse_or_expr(p); } -state fn parse_stmt(parser p) -> @ast.stmt { +io fn parse_stmt(parser p) -> @ast.stmt { alt (p.peek()) { case (token.LOG) { p.bump(); @@ -431,7 +431,7 @@ state fn parse_stmt(parser p) -> @ast.stmt { fail; } -state fn parse_block(parser p) -> ast.block { +io fn parse_block(parser p) -> ast.block { auto f = parse_stmt; // FIXME: passing parse_stmt as an lval doesn't work at the moment. ret parse_seq[@ast.stmt](token.LBRACE, @@ -440,14 +440,14 @@ state fn parse_block(parser p) -> ast.block { f, p); } -state fn parse_slot_ident_pair(parser p) -> +io fn parse_slot_ident_pair(parser p) -> rec(ast.slot slot, ast.ident ident) { auto s = parse_slot(p); auto i = parse_ident(p); ret rec(slot=s, ident=i); } -state fn parse_fn(parser p) -> tup(ast.ident, ast.item) { +io fn parse_fn(parser p) -> tup(ast.ident, ast.item) { expect(p, token.FN); auto id = parse_ident(p); auto pf = parse_slot_ident_pair; @@ -477,7 +477,7 @@ state fn parse_fn(parser p) -> tup(ast.ident, ast.item) { ret tup(id, ast.item_fn(@f)); } -state fn parse_mod(parser p) -> tup(ast.ident, ast.item) { +io fn parse_mod(parser p) -> tup(ast.ident, ast.item) { expect(p, token.MOD); auto id = parse_ident(p); expect(p, token.LBRACE); @@ -490,7 +490,7 @@ state fn parse_mod(parser p) -> tup(ast.ident, ast.item) { ret tup(id, ast.item_mod(@m)); } -state fn parse_item(parser p) -> tup(ast.ident, ast.item) { +io fn parse_item(parser p) -> tup(ast.ident, ast.item) { alt (p.peek()) { case (token.FN) { ret parse_fn(p); @@ -503,7 +503,7 @@ state fn parse_item(parser p) -> tup(ast.ident, ast.item) { fail; } -state fn parse_crate(parser p) -> ast.crate { +io fn parse_crate(parser p) -> ast.crate { let ast._mod m = new_str_hash[ast.item](); while (p.peek() != token.EOF) { auto i = parse_item(p); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index eb396976..1828271f 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -50,10 +50,28 @@ state type fn_ctxt = rec(ValueRef llfn, type terminator = fn(@fn_ctxt cx, builder build); -type block_ctxt = rec(BasicBlockRef llbb, - builder build, - terminator term, - @fn_ctxt fcx); +tag cleanup { + clean(fn(@block_ctxt cx, ValueRef v), ValueRef); +} + +state type block_ctxt = rec(BasicBlockRef llbb, + builder build, + terminator term, + mutable vec[cleanup] cleanups, + @fn_ctxt fcx); + + +fn ty_str(TypeRef t) -> str { + ret lib.llvm.type_to_str(t); +} + +fn val_ty(ValueRef v) -> TypeRef { + ret llvm.LLVMTypeOf(v); +} + +fn val_str(ValueRef v) -> str { + ret ty_str(val_ty(v)); +} // LLVM type constructors. @@ -120,6 +138,12 @@ fn T_task() -> TypeRef { )); } +fn T_str() -> TypeRef { + ret T_struct(vec(T_int(), // Refcount + T_int() // Lie about the remainder + )); +} + fn T_crate() -> TypeRef { ret T_struct(vec(T_int(), // ptrdiff_t image_base_off T_int(), // uintptr_t self_addr @@ -134,7 +158,7 @@ fn T_crate() -> TypeRef { T_int(), // size_t main_exit_task_glue_off T_int(), // int n_rust_syms T_int(), // int n_c_syms - T_int() //int n_libs + T_int() // int n_libs )); } @@ -146,7 +170,6 @@ fn T_taskptr() -> TypeRef { ret T_ptr(T_task()); } - // LLVM constant constructors. fn C_null(TypeRef t) -> ValueRef { @@ -177,7 +200,7 @@ fn C_int(int i) -> ValueRef { fn C_str(@trans_ctxt cx, str s) -> ValueRef { auto sc = llvm.LLVMConstString(_str.buf(s), _str.byte_len(s), False); - auto g = llvm.LLVMAddGlobal(cx.llmod, llvm.LLVMTypeOf(sc), + auto g = llvm.LLVMAddGlobal(cx.llmod, val_ty(sc), _str.buf(cx.names.next("str"))); llvm.LLVMSetInitializer(g, sc); ret g; @@ -192,7 +215,7 @@ fn C_struct(vec[ValueRef] elts) -> ValueRef { 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); + log "declaring " + name + " with type " + ty_str(llty); let ValueRef llfn = llvm.LLVMAddFunction(llmod, _str.buf(name), llty); llvm.LLVMSetFunctionCallConv(llfn, lib.llvm.LLVMCCallConv); @@ -224,7 +247,7 @@ fn get_upcall(@trans_ctxt cx, str name, int n_args) -> ValueRef { } auto inputs = vec(T_taskptr()); inputs += _vec.init_elt[TypeRef](T_int(), n_args as uint); - auto output = T_nil(); + auto output = T_int(); auto f = decl_cdecl_fn(cx.llmod, name, inputs, output); cx.upcalls.insert(name, f); ret f; @@ -240,15 +263,26 @@ fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> ValueRef { for (ValueRef a in args) { call_args += cx.build.ZExtOrBitCast(a, T_int()); } - 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)); + /* + log "emitting indirect-upcall via " + abi.upcall_glue_name(n); + for (ValueRef v in call_args) { + log "arg: " + val_str(v); + } + log "emitting call to llglue of type: " + val_str(llglue); + */ + ret cx.build.Call(llglue, call_args); } +fn build_non_gc_free(@block_ctxt cx, ValueRef v) { + trans_upcall(cx, "upcall_free", vec(cx.build.PtrToInt(v, T_int()), + C_int(0))); +} + +fn drop_str(@block_ctxt cx, ValueRef v) { + build_non_gc_free(cx, v); +} + fn trans_lit(@block_ctxt cx, &ast.lit lit) -> ValueRef { alt (lit) { case (ast.lit_int(?i)) { @@ -265,9 +299,13 @@ fn trans_lit(@block_ctxt cx, &ast.lit lit) -> ValueRef { } case (ast.lit_str(?s)) { auto len = (_str.byte_len(s) as int) + 1; - ret trans_upcall(cx, "upcall_new_str", - vec(p2i(C_str(cx.fcx.tcx, s)), - C_int(len))); + auto v = trans_upcall(cx, "upcall_new_str", + vec(p2i(C_str(cx.fcx.tcx, s)), + C_int(len))); + v = cx.build.IntToPtr(v, T_ptr(T_str())); + auto f = drop_str; + cx.cleanups += vec(clean(f, v)); + ret v; } } } @@ -402,7 +440,8 @@ fn trans_log(@block_ctxt cx, &ast.expr e) { alt (*lit) { case (ast.lit_str(_)) { auto v = trans_expr(cx, e); - trans_upcall(cx, "upcall_log_str", vec(v)); + trans_upcall(cx, "upcall_log_str", + vec(cx.build.PtrToInt(v, T_int()))); } case (_) { auto v = trans_expr(cx, e); @@ -441,9 +480,11 @@ fn new_builder(BasicBlockRef llbb) -> builder { fn new_block_ctxt(@fn_ctxt cx, terminator term) -> @block_ctxt { let BasicBlockRef llbb = llvm.LLVMAppendBasicBlock(cx.llfn, _str.buf("")); + let vec[cleanup] cleanups = vec(); ret @rec(llbb=llbb, build=new_builder(llbb), term=term, + mutable cleanups=cleanups, fcx=cx); } @@ -452,6 +493,15 @@ fn trans_block(@fn_ctxt cx, &ast.block b, terminator term) { for (@ast.stmt s in b) { trans_stmt(bcx, *s); } + + for (cleanup c in bcx.cleanups) { + alt (c) { + case (clean(?cfn, ?v)) { + cfn(bcx, v); + } + } + } + bcx.term(cx, bcx.build); } |