Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unsafe post snapshot #1036

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
00bf461
expand purity to include unsafe
nikomatsakis Oct 6, 2011
60ce53c
Extend the unchecked block stuff to allow unsafe blocks as well.
nikomatsakis Oct 6, 2011
a2582b2
Add unsafe blocks, unsafe functions, and two rudimentary tests
nikomatsakis Oct 7, 2011
a0efd30
it is also legal to call unsafe functions from other unsafe functions
nikomatsakis Oct 7, 2011
91a039c
fix test to include a main() function
nikomatsakis Oct 7, 2011
6ec4b8b
add 'u' to decoder (kinda' important)
nikomatsakis Oct 7, 2011
f829894
add 'u' to one other place it was missing
nikomatsakis Oct 7, 2011
4450a82
make treatment of unchecked/unsafe blocks more uniform; also
nikomatsakis Oct 7, 2011
66c3bbd
enable unsafe checking but only with a flag --check-unsafe
nikomatsakis Oct 10, 2011
234263d
correct lines over 78 chars
nikomatsakis Oct 10, 2011
7a12d54
skip test, remove whitespace
nikomatsakis Oct 11, 2011
9886fc0
make native functions markable as unsafe and incorporate that
nikomatsakis Oct 11, 2011
26c2a6e
Add unsafe tags to usage of LLVM funcs
nikomatsakis Oct 7, 2011
9eff1a0
add unsafe tags into various points in the translation chains
nikomatsakis Oct 7, 2011
816548b
continue to annotate trans functions as unsafe where neccessary
nikomatsakis Oct 10, 2011
d961094
continue to annotate trans functions as unsafe where neccessary
nikomatsakis Oct 10, 2011
37a8c1b
continue to annotate functions as unsafe where neccessary
nikomatsakis Oct 10, 2011
e4bd3cc
all tests pass
nikomatsakis Oct 10, 2011
01490a4
all tests pass
nikomatsakis Oct 10, 2011
0746572
add pass to check that unsafe fns cannot be used as values
nikomatsakis Oct 12, 2011
7dbf2e9
improve the span used in test generation
nikomatsakis Oct 12, 2011
f273250
make a good error msg if you try to use an unsafe fn for a test
nikomatsakis Oct 12, 2011
76e25c0
convert a few tests from unsafe fns to fns with unsafe bodies
nikomatsakis Oct 12, 2011
6ebbe72
add some new tests
nikomatsakis Oct 12, 2011
140a467
fix error msg
nikomatsakis Oct 12, 2011
3866463
prohibit ptr deref unless in unsafe code
nikomatsakis Oct 12, 2011
991314c
make compiler emit more than 1 error in the case of unsafe
nikomatsakis Oct 12, 2011
b70e41c
new test
nikomatsakis Oct 12, 2011
8029ce8
remove unsafe tags
nikomatsakis Oct 12, 2011
f5f9e2d
reimplement some of the unsafe stuff which got lost:
nikomatsakis Oct 12, 2011
7f92f88
make treatment of unchecked/unsafe blocks more uniform; also
nikomatsakis Oct 7, 2011
d394bdc
Add unsafe tags to usage of LLVM funcs
nikomatsakis Oct 7, 2011
1e206cd
add unsafe tags into various points in the translation chains
nikomatsakis Oct 7, 2011
5f288f2
continue to annotate trans functions as unsafe where neccessary
nikomatsakis Oct 10, 2011
7a0d10f
continue to annotate trans functions as unsafe where neccessary
nikomatsakis Oct 10, 2011
cab76a5
continue to annotate functions as unsafe where neccessary
nikomatsakis Oct 10, 2011
777dd6a
all tests pass
nikomatsakis Oct 10, 2011
a6cd35e
all tests pass
nikomatsakis Oct 10, 2011
c5d671c
add pass to check that unsafe fns cannot be used as values
nikomatsakis Oct 12, 2011
4ad03cc
improve the span used in test generation
nikomatsakis Oct 12, 2011
2771e94
make a good error msg if you try to use an unsafe fn for a test
nikomatsakis Oct 12, 2011
8000ac3
convert a few tests from unsafe fns to fns with unsafe bodies
nikomatsakis Oct 12, 2011
98ee7ff
add some new tests
nikomatsakis Oct 12, 2011
d3ecc46
fix error msg
nikomatsakis Oct 12, 2011
63eee8f
prohibit ptr deref unless in unsafe code
nikomatsakis Oct 12, 2011
fece625
make compiler emit more than 1 error in the case of unsafe
nikomatsakis Oct 12, 2011
70c69f7
new test
nikomatsakis Oct 12, 2011
4173916
remove unsafe tags
nikomatsakis Oct 12, 2011
f804562
reimplement some of the unsafe stuff which got lost:
nikomatsakis Oct 12, 2011
fca04a9
Merge branch 'unsafe-post-snapshot' of github.com:nikomatsakis/rust i…
nikomatsakis Oct 12, 2011
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/comp/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ tag output_type {
output_type_exe;
}

fn llvm_err(sess: session::session, msg: str) {
fn llvm_err(sess: session::session, msg: str) unsafe {
let buf = llvm::LLVMRustGetLastError();
if buf == std::ptr::null() {
sess.fatal(msg);
Expand Down
10 changes: 5 additions & 5 deletions src/comp/driver/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import metadata::{creader, cstore};
import syntax::parse::{parser, token};
import syntax::{ast, codemap};
import front::attr;
import middle::{trans, resolve, freevars, kind, ty, typeck};
import middle::{trans, resolve, freevars, kind, ty, typeck, unsafeck};
import middle::tstate::ck;
import syntax::print::{pp, pprust};
import util::{ppaux, common, filesearch};
Expand Down Expand Up @@ -110,7 +110,7 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
if sess.get_opts().test {
crate =
time(time_passes, "building test harness",
bind front::test::modify_for_testing(crate));
bind front::test::modify_for_testing(sess, crate));
}
crate =
time(time_passes, "expansion",
Expand All @@ -129,6 +129,8 @@ fn compile_input(sess: session::session, cfg: ast::crate_cfg, input: str,
bind freevars::annotate_freevars(def_map, crate));
let ty_cx = ty::mk_ctxt(sess, def_map, ext_map, ast_map, freevars);
time(time_passes, "typechecking", bind typeck::check_crate(ty_cx, crate));
time(time_passes, "unsafechecking",
bind unsafeck::unsafeck_crate(ty_cx, crate));
time(time_passes, "alt checking",
bind middle::check_alt::check_crate(ty_cx, crate));
if sess.get_opts().run_typestate {
Expand Down Expand Up @@ -323,7 +325,6 @@ fn build_session_options(match: getopts::match)

let parse_only = opt_present(match, "parse-only");
let no_trans = opt_present(match, "no-trans");
let check_unsafe = opt_present(match, "check-unsafe");

let output_type =
if parse_only || no_trans {
Expand Down Expand Up @@ -395,8 +396,7 @@ fn build_session_options(match: getopts::match)
parse_only: parse_only,
no_trans: no_trans,
do_gc: do_gc,
stack_growth: stack_growth,
check_unsafe: check_unsafe};
stack_growth: stack_growth};
ret sopts;
}

Expand Down
3 changes: 1 addition & 2 deletions src/comp/driver/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ type options =
parse_only: bool,
no_trans: bool,
do_gc: bool,
stack_growth: bool,
check_unsafe: bool};
stack_growth: bool};

type crate_metadata = {name: str, data: [u8]};

Expand Down
39 changes: 27 additions & 12 deletions src/comp/front/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,26 @@ import syntax::ast_util::*;
//import syntax::ast_util::dummy_sp;
import syntax::fold;
import syntax::print::pprust;
import syntax::codemap::span;
import driver::session;
import front::attr;

export modify_for_testing;

type node_id_gen = fn() -> ast::node_id;

type test = {path: [ast::ident], ignore: bool};
type test = {span: span, path: [ast::ident], ignore: bool};

type test_ctxt =
@{next_node_id: node_id_gen,
@{sess: session::session,
next_node_id: node_id_gen,
mutable path: [ast::ident],
mutable testfns: [test]};

// Traverse the crate, collecting all the test functions, eliding any
// existing main functions, and synthesizing a main test harness
fn modify_for_testing(crate: @ast::crate) -> @ast::crate {
fn modify_for_testing(sess: session::session,
crate: @ast::crate) -> @ast::crate {

// FIXME: This hackasaurus assumes that 200000 is a safe number to start
// generating node_ids at (which is totally not the case). pauls is going
Expand All @@ -36,7 +40,8 @@ fn modify_for_testing(crate: @ast::crate) -> @ast::crate {
}(next_node_id);

let cx: test_ctxt =
@{next_node_id: next_node_id_fn,
@{sess: sess,
next_node_id: next_node_id_fn,
mutable path: [],
mutable testfns: []};

Expand Down Expand Up @@ -89,10 +94,19 @@ fn fold_item(cx: test_ctxt, &&i: @ast::item, fld: fold::ast_fold) ->
log #fmt["current path: %s", ast_util::path_name_i(cx.path)];

if is_test_fn(i) {
log "this is a test function";
let test = {path: cx.path, ignore: is_ignored(i)};
cx.testfns += [test];
log #fmt["have %u test functions", vec::len(cx.testfns)];
alt i.node {
ast::item_fn(f, _) when f.decl.purity == ast::unsafe_fn {
cx.sess.span_fatal(
i.span,
"unsafe functions cannot be used for tests");
}
_ {
log "this is a test function";
let test = {span: i.span, path: cx.path, ignore: is_ignored(i)};
cx.testfns += [test];
log #fmt["have %u test functions", vec::len(cx.testfns)];
}
}
}

let res = fold::noop_fold_item(i, fld);
Expand Down Expand Up @@ -237,6 +251,7 @@ fn mk_test_desc_vec(cx: test_ctxt) -> @ast::expr {
}

fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr {
let span = test.span;
let path = test.path;

log #fmt["encoding %s", ast_util::path_name_i(path)];
Expand All @@ -246,7 +261,7 @@ fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr {
let name_expr: ast::expr =
{id: cx.next_node_id(),
node: ast::expr_lit(@name_lit),
span: dummy_sp()};
span: span};

let name_field: ast::field =
nospan({mut: ast::imm, ident: "name", expr: @name_expr});
Expand All @@ -256,7 +271,7 @@ fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr {
let fn_expr: ast::expr =
{id: cx.next_node_id(),
node: ast::expr_path(fn_path),
span: dummy_sp()};
span: span};

let fn_field: ast::field =
nospan({mut: ast::imm, ident: "fn", expr: @fn_expr});
Expand All @@ -266,15 +281,15 @@ fn mk_test_desc_rec(cx: test_ctxt, test: test) -> @ast::expr {
let ignore_expr: ast::expr =
{id: cx.next_node_id(),
node: ast::expr_lit(@ignore_lit),
span: dummy_sp()};
span: span};

let ignore_field: ast::field =
nospan({mut: ast::imm, ident: "ignore", expr: @ignore_expr});

let desc_rec_: ast::expr_ =
ast::expr_rec([name_field, fn_field, ignore_field], option::none);
let desc_rec: ast::expr =
{id: cx.next_node_id(), node: desc_rec_, span: dummy_sp()};
{id: cx.next_node_id(), node: desc_rec_, span: span};
ret @desc_rec;
}

Expand Down
10 changes: 7 additions & 3 deletions src/comp/lib/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -961,7 +961,9 @@ fn type_to_str_inner(names: type_names, outer0: [TypeRef], ty: TypeRef) ->
let out_ty: TypeRef = llvm::LLVMGetReturnType(ty);
let n_args: uint = llvm::LLVMCountParamTypes(ty);
let args: [TypeRef] = vec::init_elt::<TypeRef>(0 as TypeRef, n_args);
llvm::LLVMGetParamTypes(ty, vec::to_ptr(args));
unsafe {
llvm::LLVMGetParamTypes(ty, vec::to_ptr(args));
}
s += tys_str(names, outer, args);
s += ") -> ";
s += type_to_str_inner(names, outer, out_ty);
Expand All @@ -971,7 +973,9 @@ fn type_to_str_inner(names: type_names, outer0: [TypeRef], ty: TypeRef) ->
let s: str = "{";
let n_elts: uint = llvm::LLVMCountStructElementTypes(ty);
let elts: [TypeRef] = vec::init_elt::<TypeRef>(0 as TypeRef, n_elts);
llvm::LLVMGetStructElementTypes(ty, vec::to_ptr(elts));
unsafe {
llvm::LLVMGetStructElementTypes(ty, vec::to_ptr(elts));
}
s += tys_str(names, outer, elts);
s += "}";
ret s;
Expand Down Expand Up @@ -1009,7 +1013,7 @@ fn float_width(llt: TypeRef) -> uint {
};
}

fn fn_ty_param_tys(fn_ty: TypeRef) -> [TypeRef] {
fn fn_ty_param_tys(fn_ty: TypeRef) -> [TypeRef] unsafe {
let args = vec::init_elt(0 as TypeRef, llvm::LLVMCountParamTypes(fn_ty));
llvm::LLVMGetParamTypes(fn_ty, vec::to_ptr(args));
ret args;
Expand Down
4 changes: 2 additions & 2 deletions src/comp/metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,10 @@ fn find_library_crate_aux(nn: {prefix: str, suffix: str}, crate_name: str,
});
}

fn get_metadata_section(filename: str) -> option::t<@[u8]> {
fn get_metadata_section(filename: str) -> option::t<@[u8]> unsafe {
let mb = str::as_buf(filename, {|buf|
llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
});
});
if mb as int == 0 { ret option::none::<@[u8]>; }
let of = mk_object_file(mb);
let si = mk_section_iter(of.llof);
Expand Down
4 changes: 4 additions & 0 deletions src/comp/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,8 @@ fn family_has_type_params(fam_ch: u8) -> bool {
'u' { true }
'p' { true }
'F' { true }
'U' { true }
'P' { true }
'y' { true }
't' { true }
'T' { false }
Expand Down Expand Up @@ -285,6 +287,8 @@ fn item_family_to_str(fam: u8) -> str {
'u' { ret "unsafe fn"; }
'p' { ret "pure fn"; }
'F' { ret "native fn"; }
'U' { ret "unsafe native fn"; }
'P' { ret "pure native fn"; }
'y' { ret "type"; }
'T' { ret "native type"; }
't' { ret "type"; }
Expand Down
71 changes: 46 additions & 25 deletions src/comp/middle/trans_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ fn AggregateRet(cx: @block_ctxt, RetVals: [ValueRef]) {
if cx.unreachable { ret; }
assert (!cx.terminated);
cx.terminated = true;
llvm::LLVMBuildAggregateRet(B(cx), vec::to_ptr(RetVals),
vec::len(RetVals));
unsafe {
llvm::LLVMBuildAggregateRet(B(cx), vec::to_ptr(RetVals),
vec::len(RetVals));
}
}

fn Br(cx: @block_ctxt, Dest: BasicBlockRef) {
Expand Down Expand Up @@ -88,18 +90,22 @@ fn Invoke(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef],
if cx.unreachable { ret; }
assert (!cx.terminated);
cx.terminated = true;
llvm::LLVMBuildInvoke(B(cx), Fn, vec::to_ptr(Args),
vec::len(Args), Then, Catch, noname());
unsafe {
llvm::LLVMBuildInvoke(B(cx), Fn, vec::to_ptr(Args),
vec::len(Args), Then, Catch, noname());
}
}

fn FastInvoke(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef],
Then: BasicBlockRef, Catch: BasicBlockRef) {
if cx.unreachable { ret; }
assert (!cx.terminated);
cx.terminated = true;
let v = llvm::LLVMBuildInvoke(B(cx), Fn, vec::to_ptr(Args),
vec::len(Args), Then, Catch, noname());
llvm::LLVMSetInstructionCallConv(v, lib::llvm::LLVMFastCallConv);
unsafe {
let v = llvm::LLVMBuildInvoke(B(cx), Fn, vec::to_ptr(Args),
vec::len(Args), Then, Catch, noname());
llvm::LLVMSetInstructionCallConv(v, lib::llvm::LLVMFastCallConv);
}
}

fn Unreachable(cx: @block_ctxt) {
Expand Down Expand Up @@ -311,15 +317,19 @@ fn Store(cx: @block_ctxt, Val: ValueRef, Ptr: ValueRef) {

fn GEP(cx: @block_ctxt, Pointer: ValueRef, Indices: [ValueRef]) -> ValueRef {
if cx.unreachable { ret llvm::LLVMGetUndef(T_ptr(T_nil())); }
ret llvm::LLVMBuildGEP(B(cx), Pointer, vec::to_ptr(Indices),
vec::len(Indices), noname());
unsafe {
ret llvm::LLVMBuildGEP(B(cx), Pointer, vec::to_ptr(Indices),
vec::len(Indices), noname());
}
}

fn InBoundsGEP(cx: @block_ctxt, Pointer: ValueRef, Indices: [ValueRef]) ->
ValueRef {
if cx.unreachable { ret llvm::LLVMGetUndef(T_ptr(T_nil())); }
ret llvm::LLVMBuildInBoundsGEP(B(cx), Pointer, vec::to_ptr(Indices),
vec::len(Indices), noname());
unsafe {
ret llvm::LLVMBuildInBoundsGEP(B(cx), Pointer, vec::to_ptr(Indices),
vec::len(Indices), noname());
}
}

fn StructGEP(cx: @block_ctxt, Pointer: ValueRef, Idx: uint) -> ValueRef {
Expand Down Expand Up @@ -460,9 +470,11 @@ fn Phi(cx: @block_ctxt, Ty: TypeRef, vals: [ValueRef], bbs: [BasicBlockRef])
if cx.unreachable { ret llvm::LLVMGetUndef(Ty); }
assert (vec::len::<ValueRef>(vals) == vec::len::<BasicBlockRef>(bbs));
let phi = EmptyPhi(cx, Ty);
llvm::LLVMAddIncoming(phi, vec::to_ptr(vals), vec::to_ptr(bbs),
vec::len(vals));
ret phi;
unsafe {
llvm::LLVMAddIncoming(phi, vec::to_ptr(vals), vec::to_ptr(bbs),
vec::len(vals));
ret phi;
}
}

fn AddIncomingToPhi(phi: ValueRef, val: ValueRef, bb: BasicBlockRef) {
Expand All @@ -481,25 +493,31 @@ fn _UndefReturn(Fn: ValueRef) -> ValueRef {

fn Call(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef]) -> ValueRef {
if cx.unreachable { ret _UndefReturn(Fn); }
ret llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
vec::len(Args), noname());
unsafe {
ret llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
vec::len(Args), noname());
}
}

fn FastCall(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef]) -> ValueRef {
if cx.unreachable { ret _UndefReturn(Fn); }
let v = llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
vec::len(Args), noname());
llvm::LLVMSetInstructionCallConv(v, lib::llvm::LLVMFastCallConv);
ret v;
unsafe {
let v = llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
vec::len(Args), noname());
llvm::LLVMSetInstructionCallConv(v, lib::llvm::LLVMFastCallConv);
ret v;
}
}

fn CallWithConv(cx: @block_ctxt, Fn: ValueRef, Args: [ValueRef], Conv: uint)
-> ValueRef {
if cx.unreachable { ret _UndefReturn(Fn); }
let v = llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
vec::len(Args), noname());
llvm::LLVMSetInstructionCallConv(v, Conv);
ret v;
unsafe {
let v = llvm::LLVMBuildCall(B(cx), Fn, vec::to_ptr(Args),
vec::len(Args), noname());
llvm::LLVMSetInstructionCallConv(v, Conv);
ret v;
}
}

fn Select(cx: @block_ctxt, If: ValueRef, Then: ValueRef, Else: ValueRef) ->
Expand Down Expand Up @@ -568,7 +586,10 @@ fn Trap(cx: @block_ctxt) {
});
assert (T as int != 0);
let Args: [ValueRef] = [];
llvm::LLVMBuildCall(b, T, vec::to_ptr(Args), vec::len(Args), noname());
unsafe {
llvm::LLVMBuildCall(b, T, vec::to_ptr(Args),
vec::len(Args), noname());
}
}

fn LandingPad(cx: @block_ctxt, Ty: TypeRef, PersFn: ValueRef,
Expand Down
Loading