aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Anderson <[email protected]>2011-03-13 19:40:25 -0400
committerBrian Anderson <[email protected]>2011-03-13 19:40:25 -0400
commitbbb6836da003be71744b6e6ea7af1fd4674f8291 (patch)
treefc7780f767666cced8406818806216bee3863c91
parentRemove extra blocks from the translation of expr_block (diff)
parentAdd llvmext/include to the list of include directories to hopefully put out t... (diff)
downloadrust-bbb6836da003be71744b6e6ea7af1fd4674f8291.tar.xz
rust-bbb6836da003be71744b6e6ea7af1fd4674f8291.zip
Merge branch 'master' into recursive-elseif
Conflicts: src/comp/middle/typeck.rs
-rw-r--r--src/Makefile90
-rw-r--r--src/boot/be/abi.ml2
-rw-r--r--src/boot/driver/main.ml5
-rw-r--r--src/boot/me/semant.ml4
-rw-r--r--src/boot/me/trans.ml172
-rw-r--r--src/comp/back/x86.rs69
-rw-r--r--src/comp/driver/rustc.rs24
-rw-r--r--src/comp/front/ast.rs53
-rw-r--r--src/comp/front/eval.rs9
-rw-r--r--src/comp/front/parser.rs56
-rw-r--r--src/comp/front/pretty.rs87
-rw-r--r--src/comp/middle/fold.rs40
-rw-r--r--src/comp/middle/metadata.rs29
-rw-r--r--src/comp/middle/resolve.rs51
-rw-r--r--src/comp/middle/trans.rs989
-rw-r--r--src/comp/middle/ty.rs95
-rw-r--r--src/comp/middle/typeck.rs569
-rw-r--r--src/comp/pretty/pp.rs43
-rw-r--r--src/comp/pretty/pprust.rs75
-rw-r--r--src/comp/rustc.rc4
-rw-r--r--src/comp/util/common.rs10
-rw-r--r--src/lib/_int.rs1
-rw-r--r--src/lib/_str.rs2
-rw-r--r--src/lib/_uint.rs1
-rw-r--r--src/lib/_vec.rs1
-rw-r--r--src/lib/bitv.rs4
-rw-r--r--src/lib/dbg.rs2
-rw-r--r--src/lib/deque.rs4
-rw-r--r--src/lib/io.rs105
-rw-r--r--src/lib/list.rs2
-rw-r--r--src/lib/map.rs6
-rw-r--r--src/lib/sha1.rs3
-rw-r--r--src/llvmext/Object.cpp55
-rw-r--r--src/llvmext/README3
-rw-r--r--src/llvmext/include/llvm-c/Object.h75
-rw-r--r--src/test/run-pass/box-compare.rs5
-rw-r--r--src/test/run-pass/generic-bind-2.rs10
-rw-r--r--src/test/run-pass/generic-bind.rs6
-rw-r--r--src/test/run-pass/generic-tag-alt.rs2
-rw-r--r--src/test/run-pass/generic-tag-local.rs8
-rw-r--r--src/test/run-pass/leak-tag-copy.rs9
-rw-r--r--src/test/run-pass/seq-compare.rs15
-rw-r--r--src/test/run-pass/simple-generic-alt.rs11
-rw-r--r--src/test/run-pass/simple-generic-tag.rs7
44 files changed, 1854 insertions, 959 deletions
diff --git a/src/Makefile b/src/Makefile
index 8855a2d1..43b66193 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -34,6 +34,7 @@ DSYMUTIL := true
ifeq ($(CFG_OSTYPE), FreeBSD)
CFG_RUNTIME := librustrt.so
+ CFG_SUPPORT := librustllvm.so
CFG_STDLIB := libstd.so
CFG_GCC_CFLAGS += -fPIC -march=i686 -I/usr/local/include
CFG_GCC_LINK_FLAGS += -shared -fPIC -lpthread -lrt
@@ -47,6 +48,7 @@ endif
ifeq ($(CFG_OSTYPE), Linux)
CFG_RUNTIME := librustrt.so
+ CFG_SUPPORT := librustllvm.so
CFG_STDLIB := libstd.so
CFG_GCC_CFLAGS += -fPIC -march=i686
CFG_GCC_LINK_FLAGS += -shared -fPIC -ldl -lpthread -lrt
@@ -60,6 +62,7 @@ endif
ifeq ($(CFG_OSTYPE), Darwin)
CFG_RUNTIME := librustrt.dylib
+ CFG_SUPPORT := librustllvm.dylib
CFG_STDLIB := libstd.dylib
CFG_UNIXY := 1
CFG_GCC_LINK_FLAGS += -dynamiclib -lpthread
@@ -85,8 +88,8 @@ ifdef CFG_WINDOWSY
CFG_NATIVE := 1
endif
CFG_RUNTIME := rustrt.dll
+ CFG_SUPPORT := rustllvm.dll
CFG_STDLIB := std.dll
- CFG_OBJ_SUFFIX := .o
CFG_EXE_SUFFIX := .exe
CFG_BOOT := ./rustboot.exe
CFG_RUSTC := ./rustc.exe
@@ -101,7 +104,6 @@ ifdef CFG_UNIXY
CFG_INFO := $(info cfg: unix-y environment)
CFG_BOOT := ./rustboot
CFG_RUSTC := ./rustc
- CFG_OBJ_SUFFIX := .o
CFG_RUN_TARG = LD_LIBRARY_PATH=. $(CFG_VALGRIND) $(1)
CFG_GCC := 1
ifdef MINGW_CROSS
@@ -109,12 +111,12 @@ ifdef CFG_UNIXY
CFG_GCC_CROSS := i586-mingw32msvc-
CFG_BOOT_FLAGS += -t win32-x86-pe
CFG_RUNTIME := rustrt.dll
+ CFG_SUPPORT := rustllvm.dll
CFG_STDLIB := std.dll
CFG_RUSTC := ./rustc.exe
ifdef CFG_VALGRIND
CFG_VALGRIND += wine
endif
- CFG_OBJ_SUFFIX := .o
CFG_EXE_SUFFIX := .exe
CFG_GCC_CFLAGS := -march=i686
CFG_GCC_LINK_FLAGS := -shared
@@ -182,7 +184,7 @@ endif
ifneq ($(CFG_LLVM_CONFIG),)
CFG_LLVM_VERSION := $(shell $(CFG_LLVM_CONFIG) --version)
$(info cfg: found llvm-config at $(CFG_LLVM_CONFIG))
- CFG_LLVM_ALLOWED_VERSIONS := 2.8svn 2.8 2.9svn
+ CFG_LLVM_ALLOWED_VERSIONS := 2.8svn 2.8 2.9svn 3.0svn
ifneq ($(findstring $(CFG_LLVM_VERSION),$(CFG_LLVM_ALLOWED_VERSIONS)),)
$(info cfg: using LLVM version $(CFG_LLVM_VERSION))
else
@@ -196,6 +198,10 @@ ifdef CFG_LLVM_CONFIG
LLC := "$(shell $(CFG_LLVM_CONFIG) --bindir)/llc"
CFG_LLC_CFLAGS := -march=x86
LLVM-DIS := "$(shell $(CFG_LLVM_CONFIG) --bindir)/llvm-dis"
+ CFG_LLVM_INCDIR := $(shell $(CFG_LLVM_CONFIG) --includedir)
+ CFG_LLVM_CXXFLAGS := $(shell $(CFG_LLVM_CONFIG) --cxxflags)
+ CFG_LLVM_LDFLAGS := $(shell $(CFG_LLVM_CONFIG) --ldflags)
+ CFG_LLVM_LIBS := $(shell $(CFG_LLVM_CONFIG) --libs)
endif
MKFILES := Makefile
@@ -302,15 +308,22 @@ RUNTIME_HDR := rt/globals.h \
rt/test/rust_test_util.h
RUNTIME_INCS := -Irt/isaac -Irt/uthash
-RUNTIME_OBJS := $(RUNTIME_CS:.cpp=$(CFG_OBJ_SUFFIX))
-RUNTIME_LIBS := $(CFG_RUNTIME_LIBS)
+RUNTIME_OBJS := $(RUNTIME_CS:.cpp=.o)
+
+SUPPORT_CS := llvmext/Object.cpp
+
+SUPPORT_HDR := llvmext/include/llvm-c/Object.h
+
+SUPPORT_INCS := -iquote $(CFG_LLVM_INCDIR) -iquote llvmext/include
+SUPPORT_OBJS := $(SUPPORT_CS:.cpp=.o)
+SUPPORT_LIBS := $(CFG_LLVM_LDFLAGS) $(CFG_LLVM_LIBS)
STDLIB_CRATE := lib/std.rc
STDLIB_INPUTS := $(wildcard lib/*.rc lib/*.rs lib/*/*.rs)
COMPILER_CRATE := comp/rustc.rc
-COMPILER_INPUTS := $(wildcard comp/*.rc comp/*.rs comp/*/*.rs)
+COMPILER_INPUTS := $(wildcard comp/rustc.rc comp/*.rs comp/*/*.rs)
-GENERATED := boot/fe/lexer.ml boot/util/version.ml
+GENERATED := boot/fe/lexer.ml boot/util/version.ml glue.o
all: $(CFG_RUSTC) $(MKFILES) $(GENERATED)
@@ -325,14 +338,24 @@ $(CFG_RUNTIME): $(RUNTIME_OBJS) $(MKFILES) $(RUNTIME_HDR)
@$(call CFG_ECHO, compile: $<)
$(CFG_QUIET)$(call CFG_LINK_C, $@) $(RUNTIME_OBJS)
+$(CFG_SUPPORT): $(SUPPORT_OBJS) $(MKFILES) $(SUPPORT_HDR)
+ @$(call CFG_ECHO, compile: $<)
+ $(CFG_QUIET)$(call CFG_LINK_C, $@ $(CFG_LLVM_LDFLAGS) $(CFG_LLVM_LIBS)) \
+ $(SUPPORT_OBJS)
+
$(CFG_STDLIB): $(STDLIB_CRATE) $(CFG_BOOT) $(MKFILES)
@$(call CFG_ECHO, compile: $<)
$(BOOT) -shared -o $@ $(STDLIB_CRATE)
-%$(CFG_OBJ_SUFFIX): %.cpp $(MKFILES)
+rt/%.o: rt/%.cpp $(MKFILES)
@$(call CFG_ECHO, compile: $<)
$(CFG_QUIET)$(call CFG_COMPILE_C, $@, $(RUNTIME_INCS)) $<
+llvmext/%.o: llvmext/%.cpp $(MKFILES)
+ @$(call CFG_ECHO, compile: $<)
+ $(CFG_QUIET)$(call CFG_COMPILE_C, $@, $(CFG_LLVM_CXXFLAGS) \
+ $(SUPPORT_INCS)) $<
+
ifdef CFG_NATIVE
$(CFG_BOOT): $(BOOT_CMXS) $(MKFILES)
@$(call CFG_ECHO, compile: $<)
@@ -363,13 +386,18 @@ endif
# Main compiler targets and rules
######################################################################
-$(CFG_RUSTC): $(COMPILER_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB)
+$(CFG_RUSTC): $(COMPILER_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB) \
+ $(CFG_SUPPORT)
@$(call CFG_ECHO, compile: $<)
$(BOOT) -minimal -o $@ $<
$(CFG_QUIET)chmod 0755 $@
+glue.bc: $(CFG_RUSTC) $(CFG_RUNTIME) $(CFG_STDLIB)
+ @$(call CFG_ECHO, generate: $@)
+ $(RUSTC) -o $@ -glue
+
self: $(CFG_RUSTC)
- @$(call CFG_ECHO, compile: $<)
+ @$(call CFG_ECHO, compile: $(COMPILER_CRATE))
$(RUSTC) $(COMPILER_CRATE)
@@ -402,6 +430,7 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \
$(NOMINAL_TAG_XFAILS) \
$(CONST_TAG_XFAILS) \
test/run-pass/arith-unsigned.rs \
+ test/run-pass/box-compare.rs \
test/run-pass/child-outlives-parent.rs \
test/run-pass/clone-with-exterior.rs \
test/run-pass/constrained-type.rs \
@@ -409,12 +438,15 @@ TEST_XFAILS_BOOT := $(TASK_XFAILS) \
test/run-pass/obj-as.rs \
test/run-pass/vec-slice.rs \
test/run-pass/fn-lval.rs \
+ test/run-pass/generic-bind-2.rs \
test/run-pass/generic-fn-box.rs \
test/run-pass/generic-tup.rs \
test/run-pass/iter-ret.rs \
+ test/run-pass/leak-tag-copy.rs \
test/run-pass/lib-io.rs \
test/run-pass/mlist-cycle.rs \
test/run-pass/obj-as.rs \
+ test/run-pass/seq-compare.rs \
test/run-pass/task-comm.rs \
test/run-pass/task-comm-3.rs \
test/run-pass/vec-slice.rs \
@@ -439,24 +471,11 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \
basic-1.rs \
basic-2.rs \
basic.rs \
- bind-obj-ctor.rs \
child-outlives-parent.rs \
clone-with-exterior.rs \
comm.rs \
constrained-type.rs \
destructor-ordering.rs \
- drop-parametric-closure-with-bound-box.rs \
- export-non-interference.rs \
- foreach-nested-2.rs \
- foreach-nested.rs \
- foreach-put-structured.rs \
- foreach-simple-outer-slot.rs \
- generic-fn-twice.rs \
- generic-iter-frame.rs \
- generic-recursive-tag.rs \
- generic-tag-alt.rs \
- generic-tag-values.rs \
- iter-range.rs \
iter-ret.rs \
lazychan.rs \
lib-bitv.rs \
@@ -478,7 +497,6 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \
mutable-alias-vec.rs \
obj-as.rs \
obj-dtor.rs \
- obj-return-polytypes.rs \
pred.rs \
preempt.rs \
rt-circular-buffer.rs \
@@ -511,13 +529,11 @@ TEST_XFAILS_RUSTC := $(addprefix test/run-pass/, \
threads.rs \
type-sizes.rs \
typestate-cfg-nesting.rs \
- use-import-export.rs \
user.rs \
utf8.rs \
vec-alloc-append.rs \
vec-append.rs \
vec-slice.rs \
- while-prelude-drop.rs \
while-with-break.rs \
yield.rs \
yield2.rs \
@@ -764,9 +780,9 @@ test/bench/shootout/%.boot$(CFG_EXE_SUFFIX): \
@$(call CFG_ECHO, assemble [llvm]: $<)
$(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) -o $@ -c $<
-%.rustc$(CFG_EXE_SUFFIX): %.o $(CFG_RUNTIME)
+%.rustc$(CFG_EXE_SUFFIX): %.o $(CFG_RUNTIME) glue.o
@$(call CFG_ECHO, link [llvm]: $<)
- $(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) -o $@ $< -L. -lrustrt
+ $(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) glue.o -o $@ $< -L. -lrustrt
@# dsymutil sometimes fails or prints a warning, but the
@# program still runs. Since it simplifies debugging other
@# programs, I\'ll live with the noise.
@@ -803,7 +819,7 @@ C_DEPFILES := $(RUNTIME_CS:%.cpp=%.d)
%.d: %.cpp $(MKFILES)
@$(call CFG_ECHO, dep: $<)
$(CFG_QUIET)$(call CFG_DEPEND_C, $@ \
- $(patsubst %.cpp, %$(CFG_OBJ_SUFFIX), $<), \
+ $(patsubst %.cpp, %.o, $<), \
$(RUNTIME_INCS)) $< $(CFG_PATH_MUNGE) >[email protected] \
@@ -826,9 +842,15 @@ RUSTBOOT_PROBE := $(wildcard $(CFG_BOOT))
ifneq ($(RUSTBOOT_PROBE),)
CFG_INFO := $(info cfg: using built $(CFG_BOOT) for rust deps)
STDLIB_DEPFILE := $(CFG_STDLIB).d
+RUSTC_DEPFILE := $(CFG_RUSTC).d
CRATE_DEPFILES := $(ALL_TEST_CRATES:%.rc=%.d) $(STDLIB_DEPFILE)
-$(STDLIB_DEPFILE): $(STDLIB_CRATE) $(MKFILES) $(CFG_BOOT)
+$(STDLIB_DEPFILE): $(STDLIB_CRATE) $(MKFILES) $(CFG_BOOT) $(STDLIB_INPUTS)
+ @$(call CFG_ECHO, dep: $<)
+ $(BOOT) -shared -rdeps $< $(CFG_PATH_MUNGE) >[email protected] \
+
+$(RUSTC_DEPFILE): $(STDLIB_CRATE) $(MKFILES) $(CFG_BOOT) $(COMPILER_INPUTS)
@$(call CFG_ECHO, dep: $<)
$(BOOT) -shared -rdeps $< $(CFG_PATH_MUNGE) >[email protected] \
@@ -920,12 +942,12 @@ clean:
$(CFG_QUIET)rm -f $(ML_DEPFILES:%.d=%.d.tmp)
$(CFG_QUIET)rm -f $(C_DEPFILES:%.d=%.d.tmp)
$(CFG_QUIET)rm -f $(CRATE_DEPFILES:%.d=%.d.tmp)
- $(CFG_QUIET)rm -f $(GENERATED)
+ $(CFG_QUIET)rm -f $(GENERATED) glue.bc glue.s
$(CFG_QUIET)rm -f $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB)
$(CFG_QUIET)rm -Rf $(PKG_NAME)-*.tar.gz dist
- $(CFG_QUIET)rm -f $(foreach ext,cmx cmi cmo cma o a d exe,\
+ $(CFG_QUIET)rm -f $(foreach ext,cmx cmi cmo cma bc o a d exe,\
$(wildcard boot/*/*.$(ext) boot/*/*/*.$(ext)))
- $(CFG_QUIET)rm -Rf $(foreach ext,out llvm x86 boot rustc o s exe dSYM,\
+ $(CFG_QUIET)rm -Rf $(foreach ext,out llvm x86 boot rustc bc o s exe dSYM,\
$(wildcard test/*/*.$(ext)))
diff --git a/src/boot/be/abi.ml b/src/boot/be/abi.ml
index 89e308bf..023e1e1d 100644
--- a/src/boot/be/abi.ml
+++ b/src/boot/be/abi.ml
@@ -80,7 +80,7 @@ let general_code_alignment = 16;;
let tydesc_field_first_param = 0;;
let tydesc_field_size = 1;;
let tydesc_field_align = 2;;
-let tydesc_field_copy_glue = 3;;
+let tydesc_field_take_glue = 3;;
let tydesc_field_drop_glue = 4;;
let tydesc_field_free_glue = 5;;
let tydesc_field_sever_glue = 6;;
diff --git a/src/boot/driver/main.ml b/src/boot/driver/main.ml
index 9705f1ee..ddcbc9af 100644
--- a/src/boot/driver/main.ml
+++ b/src/boot/driver/main.ml
@@ -1,11 +1,6 @@
open Common;;
-let _ =
- Gc.set { (Gc.get()) with
- Gc.space_overhead = 400; }
-;;
-
let (targ:Common.target) =
match Sys.os_type with
diff --git a/src/boot/me/semant.ml b/src/boot/me/semant.ml
index 3ce5eba2..3419bb34 100644
--- a/src/boot/me/semant.ml
+++ b/src/boot/me/semant.ml
@@ -20,7 +20,7 @@ type glue =
| GLUE_yield
| GLUE_exit_main_task
| GLUE_exit_task
- | GLUE_copy of Ast.ty (* One-level copy. *)
+ | GLUE_take of Ast.ty (* One-level refcounts++. *)
| GLUE_drop of Ast.ty (* De-initialize local memory. *)
| GLUE_free of Ast.ty (* Drop body + free() box ptr. *)
| GLUE_sever of Ast.ty (* Null all box state slots. *)
@@ -2776,7 +2776,7 @@ let glue_str (cx:ctxt) (g:glue) : string =
| GLUE_yield -> "glue$yield"
| GLUE_exit_main_task -> "glue$exit_main_task"
| GLUE_exit_task -> "glue$exit_task"
- | GLUE_copy ty -> "glue$copy$" ^ (ty_str cx ty)
+ | GLUE_take ty -> "glue$take$" ^ (ty_str cx ty)
| GLUE_drop ty -> "glue$drop$" ^ (ty_str cx ty)
| GLUE_free ty -> "glue$free$" ^ (ty_str cx ty)
| GLUE_sever ty -> "glue$sever$" ^ (ty_str cx ty)
diff --git a/src/boot/me/trans.ml b/src/boot/me/trans.ml
index bbf49e83..17dbe3ea 100644
--- a/src/boot/me/trans.ml
+++ b/src/boot/me/trans.ml
@@ -1355,7 +1355,7 @@ let trans_visitor
Asm.WORD (word_ty_mach, Asm.IMM 0L);
Asm.WORD (word_ty_mach, Asm.IMM sz);
Asm.WORD (word_ty_mach, Asm.IMM align);
- fix (get_copy_glue t);
+ fix (get_take_glue t);
fix (get_drop_glue t);
begin
match ty_mem_ctrl cx t with
@@ -2022,34 +2022,18 @@ let trans_visitor
get_typed_mem_glue g fty inner
- and get_copy_glue
+ and get_take_glue
(ty:Ast.ty)
: fixup =
let ty = get_genericized_ty ty in
let arg_ty_params_alias = 0 in
let arg_src_alias = 1 in
- let arg_initflag = 2 in
- let g = GLUE_copy ty in
- let inner (out_ptr:Il.cell) (args:Il.cell) =
- let dst = deref out_ptr in
+ let g = GLUE_take ty in
+ let inner (_:Il.cell) (args:Il.cell) =
let ty_params = deref (get_element_ptr args arg_ty_params_alias) in
let src = deref (get_element_ptr args arg_src_alias) in
-
- (* Translate copy code for the dst-initializing and
- * dst-non-initializing cases and branch accordingly. *)
- let initflag = get_element_ptr args arg_initflag in
- let jmps = trans_compare_simple Il.JNE (Il.Cell initflag) one in
-
- trans_copy_ty_full true ty_params true dst ty src ty;
-
- let skip_noninit_jmp = mark() in
- emit (Il.jmp Il.JMP Il.CodeNone);
- List.iter patch jmps;
-
- trans_copy_ty_full true ty_params false dst ty src ty;
-
- patch skip_noninit_jmp;
+ trans_take_ty true ty_params src ty;
in
let ty_params_ptr = ty_params_covering ty in
let fty =
@@ -2186,17 +2170,23 @@ let trans_visitor
get_tydesc_params ty_params_cell elt_td_ptr_cell
in
- let initflag = Il.Reg (force_to_reg one) in
-
+ (* Take all *)
copy_loop dst_buf src_buf (Il.Cell fill) (Il.Cell elt_sz)
begin
- fun dptr sptr ->
+ fun _ sptr ->
trans_call_dynamic_glue
elt_td_ptr_cell
- Abi.tydesc_field_copy_glue
- (Some (deref dptr))
- [| ty_params_ptr; sptr; initflag |]
+ Abi.tydesc_field_take_glue
None
+ [| ty_params_ptr; sptr |]
+ None;
+ end;
+
+ (* Memcpy all *)
+ copy_loop dst_buf src_buf (Il.Cell fill) one
+ begin
+ fun dptr sptr ->
+ mov (deref dptr) (Il.Cell (deref sptr))
end;
(* Set the new vec's fill to the original vec's fill *)
@@ -3734,17 +3724,58 @@ let trans_visitor
end
tys
- and trans_copy_ty
+ and trans_take_ty
+ (force_inline:bool)
(ty_params:Il.cell)
- (initializing:bool)
- (dst:Il.cell) (dst_ty:Ast.ty)
- (src:Il.cell) (src_ty:Ast.ty)
+ (v:Il.cell)
+ (ty:Ast.ty)
: unit =
- trans_copy_ty_full
- false ty_params initializing dst dst_ty src src_ty
+ let ty = strip_mutable_or_constrained_ty ty in
+ match ty_mem_ctrl cx ty with
+ MEM_rc_opaque | MEM_gc | MEM_rc_struct -> incr_refcount v
+ | _ ->
+ begin
+ match ty with
+ Ast.TY_fn _
+ | Ast.TY_obj _ ->
+ let binding =
+ get_element_ptr v Abi.binding_field_bound_data
+ in
+ let null_jmp = null_check binding in
+ incr_refcount binding;
+ patch null_jmp
- and trans_copy_ty_full
- (force_inline:bool)
+ | Ast.TY_param (i, _) ->
+ aliasing false v
+ begin
+ fun v ->
+ let td = get_ty_param ty_params i in
+ let ty_params_ptr = get_tydesc_params ty_params td in
+ trans_call_dynamic_glue
+ td Abi.tydesc_field_take_glue
+ None
+ [| ty_params_ptr; v; |]
+ None
+ end
+
+ | Ast.TY_rec _
+ | Ast.TY_tag _
+ | Ast.TY_tup _ ->
+ if force_inline
+ then
+ iter_ty_parts ty_params v ty
+ (trans_take_ty force_inline ty_params)
+ else
+ trans_call_static_glue
+ (code_fixup_to_ptr_operand (get_take_glue ty))
+ None
+ [| alias ty_params; alias v; |]
+ None
+
+ | _ -> ()
+ end
+
+ and trans_copy_ty
(ty_params:Il.cell)
(initializing:bool)
(dst:Il.cell) (dst_ty:Ast.ty)
@@ -3789,7 +3820,7 @@ let trans_visitor
| _ ->
(* Heavyweight copy: duplicate 1 level of the referent. *)
anno "heavy";
- trans_copy_ty_heavy force_inline ty_params initializing
+ trans_copy_ty_heavy ty_params initializing
dst dst_ty src src_ty
end
@@ -3821,7 +3852,6 @@ let trans_visitor
*)
and trans_copy_ty_heavy
- (force_inline:bool)
(ty_params:Il.cell)
(initializing:bool)
(dst:Il.cell) (dst_ty:Ast.ty)
@@ -3863,68 +3893,14 @@ let trans_visitor
(ty_sz cx ty)));
mov dst (Il.Cell src)
- | Ast.TY_param (i, _) ->
- iflog
- (fun _ -> annotate
- (Printf.sprintf "copy_ty: parametric copy %#d" i));
- let initflag = Il.Reg (force_to_reg one) in
- aliasing false src
- begin
- fun src ->
- let td = get_ty_param ty_params i in
- let ty_params_ptr = get_tydesc_params ty_params td in
- trans_call_dynamic_glue
- td Abi.tydesc_field_copy_glue
- (Some dst)
- [| ty_params_ptr; src; initflag |]
- None
- end
-
- | Ast.TY_fn _
- | Ast.TY_obj _ ->
- begin
- let src_item =
- get_element_ptr src Abi.binding_field_dispatch
- in
- let dst_item =
- get_element_ptr dst Abi.binding_field_dispatch
- in
- let src_binding =
- get_element_ptr src Abi.binding_field_bound_data
- in
- let dst_binding =
- get_element_ptr dst Abi.binding_field_bound_data
- in
- mov dst_item (Il.Cell src_item);
- mov dst_binding zero;
- let null_jmp = null_check src_binding in
- (* Copy if we have a src binding. *)
- (* FIXME (issue #58): this is completely wrong, call
- * through to the binding's self-copy fptr. For now
- * this only works by accident.
- *)
- trans_copy_ty ty_params true
- dst_binding (Ast.TY_box Ast.TY_int)
- src_binding (Ast.TY_box Ast.TY_int);
- patch null_jmp
- end
-
| _ ->
- if force_inline || should_inline_structure_helpers ty
- then
- iter_ty_parts_full ty_params dst src ty
- (fun dst src ty ->
- trans_copy_ty ty_params true
- dst ty src ty)
- else
- let initflag = Il.Reg (force_to_reg one) in
- trans_call_static_glue
- (code_fixup_to_ptr_operand (get_copy_glue ty))
- (Some dst)
- [| alias ty_params;
- alias src;
- initflag |]
- None
+ trans_take_ty false ty_params src ty;
+ if not initializing
+ then drop_ty ty_params dst ty;
+ let sz = ty_sz_with_ty_params ty_params ty in
+ copy_loop dst src sz (imm 1L)
+ (fun dptr sptr ->
+ mov (deref dptr) (Il.Cell (deref sptr)))
and trans_copy
diff --git a/src/comp/back/x86.rs b/src/comp/back/x86.rs
index 10227df7..0ed79db4 100644
--- a/src/comp/back/x86.rs
+++ b/src/comp/back/x86.rs
@@ -25,22 +25,39 @@ fn restore_callee_saves() -> vec[str] {
"popl %ebp");
}
-fn load_esp_from_rust_sp() -> vec[str] {
+fn load_esp_from_rust_sp_first_arg() -> vec[str] {
ret vec("movl " + wstr(abi.task_field_rust_sp) + "(%ecx), %esp");
}
-fn load_esp_from_runtime_sp() -> vec[str] {
+fn load_esp_from_runtime_sp_first_arg() -> vec[str] {
ret vec("movl " + wstr(abi.task_field_runtime_sp) + "(%ecx), %esp");
}
-fn store_esp_to_rust_sp() -> vec[str] {
+fn store_esp_to_rust_sp_first_arg() -> vec[str] {
ret vec("movl %esp, " + wstr(abi.task_field_rust_sp) + "(%ecx)");
}
-fn store_esp_to_runtime_sp() -> vec[str] {
+fn store_esp_to_runtime_sp_first_arg() -> vec[str] {
ret vec("movl %esp, " + wstr(abi.task_field_runtime_sp) + "(%ecx)");
}
+fn load_esp_from_rust_sp_second_arg() -> vec[str] {
+ ret vec("movl " + wstr(abi.task_field_rust_sp) + "(%edx), %esp");
+}
+
+fn load_esp_from_runtime_sp_second_arg() -> vec[str] {
+ ret vec("movl " + wstr(abi.task_field_runtime_sp) + "(%edx), %esp");
+}
+
+fn store_esp_to_rust_sp_second_arg() -> vec[str] {
+ ret vec("movl %esp, " + wstr(abi.task_field_rust_sp) + "(%edx)");
+}
+
+fn store_esp_to_runtime_sp_second_arg() -> vec[str] {
+ ret vec("movl %esp, " + wstr(abi.task_field_runtime_sp) + "(%edx)");
+}
+
+
/*
* This is a bit of glue-code. It should be emitted once per
* compilation unit.
@@ -61,8 +78,8 @@ fn store_esp_to_runtime_sp() -> vec[str] {
fn rust_activate_glue() -> vec[str] {
ret vec("movl 4(%esp), %ecx # ecx = rust_task")
+ save_callee_saves()
- + store_esp_to_runtime_sp()
- + load_esp_from_rust_sp()
+ + store_esp_to_runtime_sp_first_arg()
+ + load_esp_from_rust_sp_first_arg()
/*
* There are two paths we can arrive at this code from:
@@ -154,10 +171,10 @@ fn rust_activate_glue() -> vec[str] {
fn rust_yield_glue() -> vec[str] {
ret vec("movl 0(%esp), %ecx # ecx = rust_task")
- + load_esp_from_rust_sp()
+ + load_esp_from_rust_sp_first_arg()
+ save_callee_saves()
- + store_esp_to_rust_sp()
- + load_esp_from_runtime_sp()
+ + store_esp_to_rust_sp_first_arg()
+ + load_esp_from_runtime_sp_first_arg()
+ restore_callee_saves()
+ vec("ret");
}
@@ -175,8 +192,11 @@ fn upcall_glue(int n_args) -> vec[str] {
*/
fn copy_arg(uint i) -> str {
- auto src_off = wstr(5 + (i as int));
- auto dst_off = wstr(1 + (i as int));
+ if (i == 0u) {
+ ret "movl %edx, (%esp)";
+ }
+ auto src_off = wstr(4 + (i as int));
+ auto dst_off = wstr(0 + (i as int));
auto m = vec("movl " + src_off + "(%ebp),%eax",
"movl %eax," + dst_off + "(%esp)");
ret _str.connect(m, "\n\t");
@@ -189,20 +209,19 @@ fn upcall_glue(int n_args) -> vec[str] {
+ vec("movl %esp, %ebp # ebp = rust_sp")
- + store_esp_to_rust_sp()
- + load_esp_from_runtime_sp()
+ + store_esp_to_rust_sp_second_arg()
+ + load_esp_from_runtime_sp_second_arg()
+ vec("subl $" + wstr(n_args + 1) + ", %esp # esp -= args",
- "andl $~0xf, %esp # align esp down",
- "movl %ecx, (%esp) # arg[0] = rust_task ")
+ "andl $~0xf, %esp # align esp down")
- + _vec.init_fn[str](carg, n_args as uint)
+ + _vec.init_fn[str](carg, (n_args + 1) as uint)
- + vec("movl %ecx, %edi # save task from ecx to edi",
- "call *%edx # call *%edx",
- "movl %edi, %ecx # restore edi-saved task to ecx")
+ + vec("movl %edx, %edi # save task from edx to edi",
+ "call *%ecx # call *%ecx",
+ "movl %edi, %edx # restore edi-saved task to edx")
- + load_esp_from_rust_sp()
+ + load_esp_from_rust_sp_second_arg()
+ restore_callee_saves()
+ vec("ret");
@@ -254,6 +273,16 @@ fn get_module_asm() -> str {
ret _str.connect(glues, "\n\n");
}
+fn get_meta_sect_name() -> str {
+ if (_str.eq(target_os(), "macos")) {
+ ret "__DATA,__note.rustc";
+ }
+ if (_str.eq(target_os(), "win32")) {
+ ret ".note.rustc";
+ }
+ ret ".note.rustc";
+}
+
fn get_data_layout() -> str {
if (_str.eq(target_os(), "macos")) {
ret "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-n8:16:32";
diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs
index 7ad0cdc7..00d41fff 100644
--- a/src/comp/driver/rustc.rs
+++ b/src/comp/driver/rustc.rs
@@ -54,7 +54,8 @@ impure fn compile_input(session.session sess,
eval.env env,
str input, str output,
bool shared) {
- auto p = parser.new_parser(sess, env, 0, input);
+ auto def = tup(0, 0);
+ auto p = parser.new_parser(sess, env, def, input);
auto crate = parse_input(sess, p, input);
crate = resolve.resolve_crate(sess, crate);
crate = typeck.check_crate(sess, crate);
@@ -64,9 +65,10 @@ impure fn compile_input(session.session sess,
impure fn pretty_print_input(session.session sess,
eval.env env,
str input) {
- auto p = front.parser.new_parser(sess, env, 0, input);
+ auto def = tup(0, 0);
+ auto p = front.parser.new_parser(sess, env, def, input);
auto crate = front.parser.parse_crate_from_source_file(p);
- pretty.pprust.print_ast(crate.node.module);
+ pretty.pprust.print_ast(crate.node.module, std.io.stdout_writer());
}
fn warn_wrong_compiler() {
@@ -82,6 +84,7 @@ fn usage(session.session sess, str argv0) {
log "";
log " -o <filename> write output to <filename>";
log " -nowarn suppress wrong-compiler warning";
+ log " -glue generate glue.bc file";
log " -shared compile a shared-library crate";
log " -pp pretty-print the input instead of compiling";
log " -h display this message";
@@ -111,6 +114,7 @@ impure fn main(vec[str] args) {
let bool do_warn = true;
let bool shared = false;
let bool pretty = false;
+ let bool glue = false;
auto i = 1u;
auto len = _vec.len[str](args);
@@ -121,6 +125,8 @@ impure fn main(vec[str] args) {
if (_str.byte_len(arg) > 0u && arg.(0) == '-' as u8) {
if (_str.eq(arg, "-nowarn")) {
do_warn = false;
+ } else if (_str.eq(arg, "-glue")) {
+ glue = true;
} else if (_str.eq(arg, "-shared")) {
shared = true;
} else if (_str.eq(arg, "-pp")) {
@@ -157,6 +163,18 @@ impure fn main(vec[str] args) {
warn_wrong_compiler();
}
+ if (glue) {
+ alt (output_file) {
+ case (none[str]) {
+ middle.trans.make_common_glue("glue.bc");
+ }
+ case (some[str](?s)) {
+ middle.trans.make_common_glue(s);
+ }
+ }
+ ret;
+ }
+
alt (input_file) {
case (none[str]) {
usage(sess, args.(0));
diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs
index f9d609d1..59a928be 100644
--- a/src/comp/front/ast.rs
+++ b/src/comp/front/ast.rs
@@ -21,7 +21,7 @@ type ty_param = rec(ident ident, def_id id);
// Annotations added during successive passes.
tag ann {
ann_none;
- ann_type(@middle.ty.t);
+ ann_type(@middle.ty.t, option.t[vec[@middle.ty.t]] /* ty param substs */);
}
tag def {
@@ -29,9 +29,11 @@ tag def {
def_obj(def_id);
def_obj_field(def_id);
def_mod(def_id);
+ def_native_mod(def_id);
def_const(def_id);
def_arg(def_id);
def_local(def_id);
+ def_upvar(def_id);
def_variant(def_id /* tag */, def_id /* variant */);
def_ty(def_id);
def_ty_arg(def_id);
@@ -42,7 +44,8 @@ tag def {
}
type crate = spanned[crate_];
-type crate_ = rec(_mod module);
+type crate_ = rec(vec[@crate_directive] directives,
+ _mod module);
tag crate_directive_ {
cdir_expr(@expr);
@@ -64,9 +67,15 @@ type meta_item = spanned[meta_item_];
type meta_item_ = rec(ident name, str value);
type block = spanned[block_];
+type block_index = hashmap[ident, block_index_entry];
+tag block_index_entry {
+ bie_item(@item);
+ bie_local(@local);
+ bie_tag_variant(@item /* tag item */, uint /* variant index */);
+}
type block_ = rec(vec[@stmt] stmts,
option.t[@expr] expr,
- hashmap[ident,uint] index);
+ hashmap[ident,block_index_entry] index);
type variant_def = tup(def_id /* tag */, def_id /* variant */);
@@ -427,6 +436,44 @@ fn index_native_view_item(native_mod_index index, @view_item it) {
}
}
+fn index_stmt(block_index index, @stmt s) {
+ alt (s.node) {
+ case (ast.stmt_decl(?d)) {
+ alt (d.node) {
+ case (ast.decl_local(?loc)) {
+ index.insert(loc.ident, ast.bie_local(loc));
+ }
+ case (ast.decl_item(?it)) {
+ alt (it.node) {
+ case (ast.item_fn(?i, _, _, _, _)) {
+ index.insert(i, ast.bie_item(it));
+ }
+ case (ast.item_mod(?i, _, _)) {
+ index.insert(i, ast.bie_item(it));
+ }
+ case (ast.item_ty(?i, _, _, _, _)) {
+ index.insert(i, ast.bie_item(it));
+ }
+ case (ast.item_tag(?i, ?variants, _, _)) {
+ index.insert(i, ast.bie_item(it));
+ let uint vid = 0u;
+ for (ast.variant v in variants) {
+ auto t = ast.bie_tag_variant(it, vid);
+ index.insert(v.name, t);
+ vid += 1u;
+ }
+ }
+ case (ast.item_obj(?i, _, _, _, _)) {
+ index.insert(i, ast.bie_item(it));
+ }
+ }
+ }
+ }
+ }
+ case (_) { /* fall through */ }
+ }
+}
+
fn is_call_expr(@expr e) -> bool {
alt (e.node) {
case (expr_call(_, _, _)) {
diff --git a/src/comp/front/eval.rs b/src/comp/front/eval.rs
index 881797c9..21a764df 100644
--- a/src/comp/front/eval.rs
+++ b/src/comp/front/eval.rs
@@ -42,7 +42,7 @@ fn val_is_bool(val v) -> bool {
fn val_is_int(val v) -> bool {
alt (v) {
- case (val_bool(_)) { ret true; }
+ case (val_int(_)) { ret true; }
case (_) { }
}
ret false;
@@ -386,9 +386,12 @@ impure fn eval_crate_directive(parser p,
auto full_path = prefix + std.os.path_sep() + file_path;
- auto p0 = new_parser(p.get_session(), e, 0, full_path);
+ auto start_id = p.next_def_id();
+ auto p0 = new_parser(p.get_session(), e, start_id, full_path);
auto m0 = parse_mod_items(p0, token.EOF);
- auto im = ast.item_mod(id, m0, p.next_def_id());
+ auto next_id = p0.next_def_id();
+ p.set_def(next_id._1);
+ auto im = ast.item_mod(id, m0, next_id);
auto i = @spanned(cdir.span, cdir.span, im);
ast.index_item(index, i);
append[@ast.item](items, i);
diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs
index bb7b8558..653e45a1 100644
--- a/src/comp/front/parser.rs
+++ b/src/comp/front/parser.rs
@@ -35,12 +35,13 @@ state type parser =
fn get_session() -> session.session;
fn get_span() -> common.span;
fn next_def_id() -> ast.def_id;
+ fn set_def(ast.def_num);
fn get_prec_table() -> vec[op_spec];
};
impure fn new_parser(session.session sess,
eval.env env,
- ast.crate_num crate,
+ ast.def_id initial_def,
str path) -> parser {
state obj stdio_parser(session.session sess,
eval.env env,
@@ -94,6 +95,10 @@ impure fn new_parser(session.session sess,
ret tup(crate, def);
}
+ fn set_def(ast.def_num d) {
+ def = d;
+ }
+
fn get_file_type() -> file_type {
ret ftype;
}
@@ -114,8 +119,8 @@ impure fn new_parser(session.session sess,
auto rdr = lexer.new_reader(srdr, path);
auto npos = rdr.get_curr_pos();
ret stdio_parser(sess, env, ftype, lexer.next_token(rdr),
- npos, npos, 0, UNRESTRICTED, crate, rdr,
- prec_table());
+ npos, npos, initial_def._1, UNRESTRICTED, initial_def._0,
+ rdr, prec_table());
}
impure fn unexpected(parser p, token.token t) {
@@ -1465,39 +1470,9 @@ impure fn parse_source_stmt(parser p) -> @ast.stmt {
}
fn index_block(vec[@ast.stmt] stmts, option.t[@ast.expr] expr) -> ast.block_ {
- auto index = new_str_hash[uint]();
- auto u = 0u;
+ auto index = new_str_hash[ast.block_index_entry]();
for (@ast.stmt s in stmts) {
- alt (s.node) {
- case (ast.stmt_decl(?d)) {
- alt (d.node) {
- case (ast.decl_local(?loc)) {
- index.insert(loc.ident, u);
- }
- case (ast.decl_item(?it)) {
- alt (it.node) {
- case (ast.item_fn(?i, _, _, _, _)) {
- index.insert(i, u);
- }
- case (ast.item_mod(?i, _, _)) {
- index.insert(i, u);
- }
- case (ast.item_ty(?i, _, _, _, _)) {
- index.insert(i, u);
- }
- case (ast.item_tag(?i, _, _, _)) {
- index.insert(i, u);
- }
- case (ast.item_obj(?i, _, _, _, _)) {
- index.insert(i, u);
- }
- }
- }
- }
- }
- case (_) { /* fall through */ }
- }
- u += 1u;
+ ast.index_stmt(index, s);
}
ret rec(stmts=stmts, expr=expr, index=index);
}
@@ -2261,7 +2236,9 @@ impure fn parse_crate_from_source_file(parser p) -> @ast.crate {
auto lo = p.get_span();
auto hi = lo;
auto m = parse_mod_items(p, token.EOF);
- ret @spanned(lo, hi, rec(module=m));
+ let vec[@ast.crate_directive] cdirs = vec();
+ ret @spanned(lo, hi, rec(directives=cdirs,
+ module=m));
}
// Logic for parsing crate files (.rc)
@@ -2276,8 +2253,6 @@ impure fn parse_crate_directive(parser p) -> ast.crate_directive
auto hi = lo;
alt (p.peek()) {
case (token.AUTH) {
- // FIXME: currently dropping auth clauses on the floor,
- // as there is no effect-checking pass.
p.bump();
auto n = parse_path(p, GREEDY);
expect(p, token.EQ);
@@ -2288,8 +2263,6 @@ impure fn parse_crate_directive(parser p) -> ast.crate_directive
}
case (token.META) {
- // FIXME: currently dropping meta clauses on the floor,
- // as there is no crate metadata system
p.bump();
auto mis = parse_meta(p);
hi = p.get_span();
@@ -2398,7 +2371,8 @@ impure fn parse_crate_from_crate_file(parser p) -> @ast.crate {
cdirs, prefix);
hi = p.get_span();
expect(p, token.EOF);
- ret @spanned(lo, hi, rec(module=m));
+ ret @spanned(lo, hi, rec(directives=cdirs,
+ module=m));
}
diff --git a/src/comp/front/pretty.rs b/src/comp/front/pretty.rs
deleted file mode 100644
index 2fd58126..00000000
--- a/src/comp/front/pretty.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-import std._int;
-import std._str;
-import std._uint;
-import std._vec;
-
-export print_expr;
-
-// FIXME this is superseded by ../pretty/pprust.rs. can it be dropped?
-
-fn unknown() -> str {
- ret "<unknown ast node>";
-}
-
-fn print_expr(@ast.expr expr) -> str {
- alt (expr.node) {
- case (ast.expr_lit(?lit, _)) {
- ret print_lit(lit);
- }
- case (ast.expr_binary(?op, ?lhs, ?rhs, _)) {
- ret print_expr_binary(op, lhs, rhs);
- }
- case (ast.expr_call(?path, ?args, _)) {
- ret print_expr_call(path, args);
- }
- case (ast.expr_path(?path, _, _)) {
- ret print_path(path);
- }
- case (_) {
- ret unknown();
- }
- }
-}
-
-fn print_lit(@ast.lit lit) -> str {
- alt (lit.node) {
- case (ast.lit_str(?s)) {
- ret "\"" + s + "\"";
- }
- case (ast.lit_int(?i)) {
- ret _int.to_str(i, 10u);
- }
- case (ast.lit_uint(?u)) {
- ret _uint.to_str(u, 10u);
- }
- case (_) {
- ret unknown();
- }
- }
-}
-
-fn print_expr_binary(ast.binop op, @ast.expr lhs, @ast.expr rhs) -> str {
- alt (op) {
- case (ast.add) {
- auto l = print_expr(lhs);
- auto r = print_expr(rhs);
- ret l + " + " + r;
- }
- }
-}
-
-fn print_expr_call(@ast.expr path_expr, vec[@ast.expr] args) -> str {
- auto s = print_expr(path_expr);
-
- s += "(";
- fn print_expr_ref(&@ast.expr e) -> str { ret print_expr(e); }
- auto mapfn = print_expr_ref;
- auto argstrs = _vec.map[@ast.expr, str](mapfn, args);
- s += _str.connect(argstrs, ", ");
- s += ")";
-
- ret s;
-}
-
-fn print_path(ast.path path) -> str {
- ret _str.connect(path.node.idents, ".");
-}
-
-//
-// Local Variables:
-// mode: rust
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
-// End:
-//
diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs
index d7660460..bbe6f841 100644
--- a/src/comp/middle/fold.rs
+++ b/src/comp/middle/fold.rs
@@ -253,6 +253,8 @@ type ast_fold[ENV] =
(fn(&ENV e, &span sp, ident i, vec[ident] idents,
def_id id, option.t[def]) -> @view_item) fold_view_item_import,
+ (fn(&ENV e, &span sp, ident i) -> @view_item) fold_view_item_export,
+
// Additional nodes.
(fn(&ENV e, &span sp,
&ast.block_) -> block) fold_block,
@@ -270,6 +272,7 @@ type ast_fold[ENV] =
(fn(&ENV e, &ast.native_mod m) -> ast.native_mod) fold_native_mod,
(fn(&ENV e, &span sp,
+ vec[@ast.crate_directive] cdirs,
&ast._mod m) -> @ast.crate) fold_crate,
(fn(&ENV e,
@@ -451,11 +454,14 @@ fn fold_pat[ENV](&ENV env, ast_fold[ENV] fld, @ast.pat p) -> @ast.pat {
ret fld.fold_pat_bind(env_, p.span, id, did, t);
}
case (ast.pat_tag(?path, ?pats, ?d, ?t)) {
+ auto ppath = fold_path(env, fld, path);
+
let vec[@ast.pat] ppats = vec();
for (@ast.pat pat in pats) {
ppats += vec(fold_pat(env_, fld, pat));
}
- ret fld.fold_pat_tag(env_, p.span, path, ppats, d, t);
+
+ ret fld.fold_pat_tag(env_, p.span, ppath, ppats, d, t);
}
}
}
@@ -718,6 +724,7 @@ fn fold_stmt[ENV](&ENV env, ast_fold[ENV] fld, &@stmt s) -> @stmt {
fn fold_block[ENV](&ENV env, ast_fold[ENV] fld, &block blk) -> block {
+ auto index = new_str_hash[ast.block_index_entry]();
let ENV env_ = fld.update_env_for_block(env, blk);
if (!fld.keep_going(env_)) {
@@ -726,7 +733,9 @@ fn fold_block[ENV](&ENV env, ast_fold[ENV] fld, &block blk) -> block {
let vec[@ast.stmt] stmts = vec();
for (@ast.stmt s in blk.node.stmts) {
- append[@ast.stmt](stmts, fold_stmt[ENV](env_, fld, s));
+ auto new_stmt = fold_stmt[ENV](env_, fld, s);
+ append[@ast.stmt](stmts, new_stmt);
+ ast.index_stmt(index, new_stmt);
}
auto expr = none[@ast.expr];
@@ -739,8 +748,7 @@ fn fold_block[ENV](&ENV env, ast_fold[ENV] fld, &block blk) -> block {
}
}
- // FIXME: should we reindex?
- ret respan(blk.span, rec(stmts=stmts, expr=expr, index=blk.node.index));
+ ret respan(blk.span, rec(stmts=stmts, expr=expr, index=index));
}
fn fold_arm[ENV](&ENV env, ast_fold[ENV] fld, &arm a) -> arm {
@@ -838,6 +846,10 @@ fn fold_view_item[ENV](&ENV env, ast_fold[ENV] fld, @view_item vi)
ret fld.fold_view_item_import(env_, vi.span, def_ident, idents,
def_id, target_def);
}
+
+ case (ast.view_item_export(?def_ident)) {
+ ret fld.fold_view_item_export(env_, vi.span, def_ident);
+ }
}
fail;
@@ -969,9 +981,12 @@ fn fold_native_mod[ENV](&ENV e, ast_fold[ENV] fld,
}
fn fold_crate[ENV](&ENV env, ast_fold[ENV] fld, @ast.crate c) -> @ast.crate {
+ // FIXME: possibly fold the directives so you process any expressions
+ // within them? Not clear. After front/eval.rs, nothing else should look
+ // at crate directives.
let ENV env_ = fld.update_env_for_crate(env, c);
let ast._mod m = fold_mod[ENV](env_, fld, c.node.module);
- ret fld.fold_crate(env_, c.span, m);
+ ret fld.fold_crate(env_, c.span, c.node.directives, m);
}
//// Identity folds.
@@ -1324,6 +1339,11 @@ fn identity_fold_view_item_import[ENV](&ENV e, &span sp, ident i,
ret @respan(sp, ast.view_item_import(i, is, id, target_def));
}
+fn identity_fold_view_item_export[ENV](&ENV e, &span sp, ident i)
+ -> @view_item {
+ ret @respan(sp, ast.view_item_export(i));
+}
+
// Additional identities.
fn identity_fold_block[ENV](&ENV e, &span sp, &ast.block_ blk) -> block {
@@ -1353,8 +1373,10 @@ fn identity_fold_native_mod[ENV](&ENV e,
ret m;
}
-fn identity_fold_crate[ENV](&ENV e, &span sp, &ast._mod m) -> @ast.crate {
- ret @respan(sp, rec(module=m));
+fn identity_fold_crate[ENV](&ENV e, &span sp,
+ vec[@ast.crate_directive] cdirs,
+ &ast._mod m) -> @ast.crate {
+ ret @respan(sp, rec(directives=cdirs, module=m));
}
fn identity_fold_obj[ENV](&ENV e,
@@ -1501,13 +1523,15 @@ fn new_identity_fold[ENV]() -> ast_fold[ENV] {
bind identity_fold_view_item_use[ENV](_,_,_,_,_),
fold_view_item_import =
bind identity_fold_view_item_import[ENV](_,_,_,_,_,_),
+ fold_view_item_export =
+ bind identity_fold_view_item_export[ENV](_,_,_),
fold_block = bind identity_fold_block[ENV](_,_,_),
fold_fn = bind identity_fold_fn[ENV](_,_,_,_),
fold_fn_decl = bind identity_fold_fn_decl[ENV](_,_,_,_),
fold_mod = bind identity_fold_mod[ENV](_,_),
fold_native_mod = bind identity_fold_native_mod[ENV](_,_),
- fold_crate = bind identity_fold_crate[ENV](_,_,_),
+ fold_crate = bind identity_fold_crate[ENV](_,_,_,_),
fold_obj = bind identity_fold_obj[ENV](_,_,_,_),
update_env_for_crate = bind identity_update_env_for_crate[ENV](_,_),
diff --git a/src/comp/middle/metadata.rs b/src/comp/middle/metadata.rs
new file mode 100644
index 00000000..433d7147
--- /dev/null
+++ b/src/comp/middle/metadata.rs
@@ -0,0 +1,29 @@
+import std._str;
+import front.ast;
+import middle.trans;
+import back.x86;
+
+import lib.llvm.llvm;
+import lib.llvm.llvm.ValueRef;
+import lib.llvm.False;
+
+// Returns a Plain Old LLVM String.
+fn C_postr(str s) -> ValueRef {
+ ret llvm.LLVMConstString(_str.buf(s), _str.byte_len(s), False);
+}
+
+fn collect_meta_directives(@trans.crate_ctxt cx, @ast.crate crate)
+ -> ValueRef {
+ ret C_postr("Hello world!"); // TODO
+}
+
+fn write_metadata(@trans.crate_ctxt cx, @ast.crate crate) {
+ auto llmeta = collect_meta_directives(cx, crate);
+
+ auto llconst = trans.C_struct(vec(llmeta));
+ auto llglobal = llvm.LLVMAddGlobal(cx.llmod, trans.val_ty(llconst),
+ _str.buf("rust_metadata"));
+ llvm.LLVMSetInitializer(llglobal, llconst);
+ llvm.LLVMSetSection(llglobal, _str.buf(x86.get_meta_sect_name()));
+}
+
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index 5b6db631..1079489e 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -71,6 +71,13 @@ fn unwrap_def(def_wrap d) -> def {
}
}
}
+ case (def_wrap_native_mod(?m)) {
+ alt (m.node) {
+ case (ast.item_native_mod(_, _, ?id)) {
+ ret ast.def_native_mod(id);
+ }
+ }
+ }
case (def_wrap_other(?d)) {
ret d;
}
@@ -335,6 +342,40 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
ret none[def_wrap];
}
+ fn found_tag(@ast.item item, uint variant_idx) -> def_wrap {
+ alt (item.node) {
+ case (ast.item_tag(_, ?variants, _, ?tid)) {
+ auto vid = variants.(variant_idx).id;
+ auto t = ast.def_variant(tid, vid);
+ ret def_wrap_other(t);
+ }
+ case (_) {
+ log "tag item not actually a tag";
+ fail;
+ }
+ }
+ }
+
+ fn check_block(ast.ident i, &ast.block_ b) -> option.t[def_wrap] {
+ alt (b.index.find(i)) {
+ case (some[ast.block_index_entry](?ix)) {
+ alt(ix) {
+ case (ast.bie_item(?it)) {
+ ret some(found_def_item(it));
+ }
+ case (ast.bie_local(?l)) {
+ auto t = ast.def_local(l.id);
+ ret some(def_wrap_other(t));
+ }
+ case (ast.bie_tag_variant(?item, ?variant_idx)) {
+ ret some(found_tag(item, variant_idx));
+ }
+ }
+ }
+ case (_) { ret none[def_wrap]; }
+ }
+ }
+
fn in_scope(ast.ident i, &scope s) -> option.t[def_wrap] {
alt (s) {
@@ -361,7 +402,7 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
}
}
}
- case (ast.item_tag(_, _, ?ty_params, _)) {
+ case (ast.item_tag(_, ?variants, ?ty_params, ?tag_id)) {
for (ast.ty_param tp in ty_params) {
if (_str.eq(tp.ident, i)) {
auto t = ast.def_ty_arg(tp.id);
@@ -407,13 +448,7 @@ fn lookup_name_wrapped(&env e, ast.ident i) -> option.t[tup(@env, def_wrap)] {
}
case (scope_block(?b)) {
- alt (b.node.index.find(i)) {
- case (some[uint](?ix)) {
- auto x = found_decl_stmt(b.node.stmts.(ix));
- ret some(x);
- }
- case (_) { /* fall through */ }
- }
+ ret check_block(i, b.node);
}
case (scope_arm(?a)) {
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 87f01609..6dcfb5c0 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -98,6 +98,7 @@ state type fn_ctxt = rec(ValueRef llfn,
hashmap[ast.def_id, ValueRef] llargs,
hashmap[ast.def_id, ValueRef] llobjfields,
hashmap[ast.def_id, ValueRef] lllocals,
+ hashmap[ast.def_id, ValueRef] llupvars,
hashmap[ast.def_id, ValueRef] lltydescs,
@crate_ctxt ccx);
@@ -387,6 +388,10 @@ fn T_closure_ptr(type_names tn,
TypeRef lltarget_ty,
TypeRef llbindings_ty,
uint n_ty_params) -> TypeRef {
+
+ // NB: keep this in sync with code in trans_bind; we're making
+ // an LLVM typeref structure that has the same "shape" as the ty.t
+ // it constructs.
ret T_ptr(T_box(T_struct(vec(T_ptr(T_tydesc(tn)),
lltarget_ty,
llbindings_ty,
@@ -499,7 +504,8 @@ fn type_of_fn_full(@crate_ctxt cx,
ast.proto proto,
option.t[TypeRef] obj_self,
vec[ty.arg] inputs,
- @ty.t output) -> TypeRef {
+ @ty.t output,
+ uint ty_param_count) -> TypeRef {
let vec[TypeRef] atys = vec();
// Arg 0: Output pointer.
@@ -525,10 +531,6 @@ fn type_of_fn_full(@crate_ctxt cx,
// Args >3: ty params, if not acquired via capture...
if (obj_self == none[TypeRef]) {
- auto ty_param_count =
- ty.count_ty_params(plain_ty(ty.ty_fn(proto,
- inputs,
- output)));
auto i = 0u;
while (i < ty_param_count) {
atys += T_ptr(T_tydesc(cx.tn));
@@ -543,7 +545,7 @@ fn type_of_fn_full(@crate_ctxt cx,
atys += T_fn_pair(cx.tn,
type_of_fn_full(cx, ast.proto_fn, none[TypeRef],
vec(rec(mode=ast.val, ty=output)),
- plain_ty(ty.ty_nil)));
+ plain_ty(ty.ty_nil), 0u));
}
// ... then explicit args.
@@ -554,8 +556,11 @@ fn type_of_fn_full(@crate_ctxt cx,
fn type_of_fn(@crate_ctxt cx,
ast.proto proto,
- vec[ty.arg] inputs, @ty.t output) -> TypeRef {
- ret type_of_fn_full(cx, proto, none[TypeRef], inputs, output);
+ vec[ty.arg] inputs,
+ @ty.t output,
+ uint ty_param_count) -> TypeRef {
+ ret type_of_fn_full(cx, proto, none[TypeRef], inputs, output,
+ ty_param_count);
}
fn type_of_native_fn(@crate_ctxt cx, ast.native_abi abi,
@@ -630,7 +635,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t, bool boxed) -> TypeRef {
llty = T_struct(tys);
}
case (ty.ty_fn(?proto, ?args, ?out)) {
- llty = T_fn_pair(cx.tn, type_of_fn(cx, proto, args, out));
+ llty = T_fn_pair(cx.tn, type_of_fn(cx, proto, args, out, 0u));
}
case (ty.ty_native_fn(?abi, ?args, ?out)) {
llty = T_fn_pair(cx.tn, type_of_native_fn(cx, abi, args, out));
@@ -644,7 +649,7 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t, bool boxed) -> TypeRef {
let TypeRef mty =
type_of_fn_full(cx, m.proto,
some[TypeRef](self_ty),
- m.inputs, m.output);
+ m.inputs, m.output, 0u);
mtys += T_ptr(mty);
}
let TypeRef vtbl = T_struct(mtys);
@@ -827,38 +832,51 @@ fn decl_upcall_glue(ModuleRef llmod, type_names tn, uint _n) -> ValueRef {
let int n = _n as int;
let str s = abi.upcall_glue_name(n);
let vec[TypeRef] args =
- vec(T_taskptr(tn), // taskptr
- T_int()) // callee
+ vec(T_int(), // callee
+ T_int()) // taskptr
+ _vec.init_elt[TypeRef](T_int(), n as uint);
ret decl_fastcall_fn(llmod, s, T_fn(args, T_int()));
}
-fn get_upcall(@crate_ctxt cx, str name, int n_args) -> ValueRef {
- if (cx.upcalls.contains_key(name)) {
- ret cx.upcalls.get(name);
+fn get_upcall(&hashmap[str, ValueRef] upcalls,
+ type_names tn, ModuleRef llmod,
+ str name, int n_args) -> ValueRef {
+ if (upcalls.contains_key(name)) {
+ ret upcalls.get(name);
}
- auto inputs = vec(T_taskptr(cx.tn));
+ auto inputs = vec(T_taskptr(tn));
inputs += _vec.init_elt[TypeRef](T_int(), n_args as uint);
auto output = T_int();
- auto f = decl_cdecl_fn(cx.llmod, name, T_fn(inputs, output));
- cx.upcalls.insert(name, f);
+ auto f = decl_cdecl_fn(llmod, name, T_fn(inputs, output));
+ upcalls.insert(name, f);
ret f;
}
fn trans_upcall(@block_ctxt cx, str name, vec[ValueRef] args) -> result {
+ auto cxx = cx.fcx.ccx;
+ auto t = trans_upcall2(cx.build, cxx.glues, cx.fcx.lltaskptr,
+ cxx.upcalls, cxx.tn, cxx.llmod, name, args);
+ ret res(cx, t);
+}
+
+fn trans_upcall2(builder b, @glue_fns glues, ValueRef lltaskptr,
+ &hashmap[str, ValueRef] upcalls,
+ type_names tn, ModuleRef llmod, str name,
+ vec[ValueRef] args) -> ValueRef {
let int n = _vec.len[ValueRef](args) as int;
- let ValueRef llupcall = get_upcall(cx.fcx.ccx, name, n);
+ let ValueRef llupcall = get_upcall(upcalls, tn, llmod, name, n);
llupcall = llvm.LLVMConstPointerCast(llupcall, T_int());
- let ValueRef llglue = cx.fcx.ccx.glues.upcall_glues.(n);
- let vec[ValueRef] call_args = vec(cx.fcx.lltaskptr, llupcall);
+ let ValueRef llglue = glues.upcall_glues.(n);
+ let vec[ValueRef] call_args = vec(llupcall);
+ call_args += b.PtrToInt(lltaskptr, T_int());
for (ValueRef a in args) {
- call_args += cx.build.ZExtOrBitCast(a, T_int());
+ call_args += b.ZExtOrBitCast(a, T_int());
}
- ret res(cx, cx.build.FastCall(llglue, call_args));
+ ret b.FastCall(llglue, call_args);
}
fn trans_non_gc_free(@block_ctxt cx, ValueRef v) -> result {
@@ -885,6 +903,11 @@ fn umax(@block_ctxt cx, ValueRef a, ValueRef b) -> ValueRef {
ret cx.build.Select(cond, b, a);
}
+fn umin(@block_ctxt cx, ValueRef a, ValueRef b) -> ValueRef {
+ auto cond = cx.build.ICmp(lib.llvm.LLVMIntULT, a, b);
+ ret cx.build.Select(cond, a, b);
+}
+
fn align_to(@block_ctxt cx, ValueRef off, ValueRef align) -> ValueRef {
auto mask = cx.build.Sub(align, C_int(1));
auto bumped = cx.build.Add(off, mask);
@@ -942,6 +965,9 @@ fn static_size_of_tag(@crate_ctxt cx, @ty.t t) -> uint {
}
}
+ // Pull the type parameters out of the corresponding tag item.
+ let vec[ast.ty_param] ty_params = tag_ty_params(cx, tid);
+
// Compute max(variant sizes).
auto max_size = 0u;
auto variants = tag_variants(cx, tid);
@@ -949,6 +975,9 @@ fn static_size_of_tag(@crate_ctxt cx, @ty.t t) -> uint {
let vec[@ty.t] tys = variant_types(cx, variant);
auto tup_ty = ty.plain_ty(ty.ty_tup(tys));
+ // Perform any type parameter substitutions.
+ tup_ty = ty.substitute_ty_params(ty_params, subtys, tup_ty);
+
// Here we possibly do a recursive call.
auto this_size = llsize_of_real(cx, type_of(cx, tup_ty));
@@ -1009,9 +1038,17 @@ fn dynamic_size_of(@block_ctxt cx, @ty.t t) -> result {
let ValueRef max_size = bcx.build.Alloca(T_int());
bcx.build.Store(C_int(0), max_size);
+ auto ty_params = tag_ty_params(bcx.fcx.ccx, tid);
auto variants = tag_variants(bcx.fcx.ccx, tid);
for (ast.variant variant in variants) {
- let vec[@ty.t] tys = variant_types(bcx.fcx.ccx, variant);
+ // Perform type substitution on the raw variant types.
+ let vec[@ty.t] raw_tys = variant_types(bcx.fcx.ccx, variant);
+ let vec[@ty.t] tys = vec();
+ for (@ty.t raw_ty in raw_tys) {
+ auto t = ty.substitute_ty_params(ty_params, tps, raw_ty);
+ tys += vec(t);
+ }
+
auto rslt = align_elements(bcx, tys);
bcx = rslt.bcx;
@@ -1053,6 +1090,9 @@ fn dynamic_align_of(@block_ctxt cx, @ty.t t) -> result {
}
ret res(bcx, a);
}
+ case (ty.ty_tag(_, _)) {
+ ret res(cx, C_int(1)); // FIXME: stub
+ }
}
}
@@ -1163,8 +1203,16 @@ fn GEP_tup_like(@block_ctxt cx, @ty.t t,
// This function uses GEP_tup_like() above and automatically performs casts as
// appropriate. @llblobptr is the data part of a tag value; its actual type is
// meaningless, as it will be cast away.
-fn GEP_tag(@block_ctxt cx, ValueRef llblobptr, &ast.variant variant, int ix)
+fn GEP_tag(@block_ctxt cx,
+ ValueRef llblobptr,
+ &ast.def_id tag_id,
+ &ast.def_id variant_id,
+ vec[@ty.t] ty_substs,
+ int ix)
-> result {
+ auto ty_params = tag_ty_params(cx.fcx.ccx, tag_id);
+ auto variant = tag_variant_with_id(cx.fcx.ccx, tag_id, variant_id);
+
// Synthesize a tuple type so that GEP_tup_like() can work its magic.
// Separately, store the type of the element we're interested in.
auto arg_tys = arg_tys_of_fn(variant.ann);
@@ -1172,9 +1220,10 @@ fn GEP_tag(@block_ctxt cx, ValueRef llblobptr, &ast.variant variant, int ix)
auto i = 0;
let vec[@ty.t] true_arg_tys = vec();
for (ty.arg a in arg_tys) {
- true_arg_tys += vec(a.ty);
+ auto arg_ty = ty.substitute_ty_params(ty_params, ty_substs, a.ty);
+ true_arg_tys += vec(arg_ty);
if (i == ix) {
- elem_ty = a.ty;
+ elem_ty = arg_ty;
}
i += 1;
@@ -1685,11 +1734,15 @@ fn variant_types(@crate_ctxt cx, &ast.variant v) -> vec[@ty.t] {
ret tys;
}
-fn type_of_variant(@crate_ctxt cx, &ast.variant v) -> TypeRef {
+fn type_of_variant(@crate_ctxt cx,
+ &ast.variant v,
+ vec[ast.ty_param] ty_params,
+ vec[@ty.t] ty_param_substs) -> TypeRef {
let vec[TypeRef] lltys = vec();
auto tys = variant_types(cx, v);
for (@ty.t typ in tys) {
- lltys += vec(type_of(cx, typ));
+ auto typ2 = ty.substitute_ty_params(ty_params, ty_param_substs, typ);
+ lltys += vec(type_of(cx, typ2));
}
ret T_struct(lltys);
}
@@ -1712,6 +1765,25 @@ fn tag_variants(@crate_ctxt cx, ast.def_id id) -> vec[ast.variant] {
fail; // not reached
}
+// Returns the tag variant with the given ID.
+fn tag_variant_with_id(@crate_ctxt cx,
+ &ast.def_id tag_id,
+ &ast.def_id variant_id) -> ast.variant {
+ auto variants = tag_variants(cx, tag_id);
+
+ auto i = 0u;
+ while (i < _vec.len[ast.variant](variants)) {
+ auto variant = variants.(i);
+ if (common.def_eq(variant.id, variant_id)) {
+ ret variant;
+ }
+ i += 1u;
+ }
+
+ log "tag_variant_with_id(): no variant exists with that ID";
+ fail;
+}
+
// Returns a new plain tag type of the given ID with no type parameters. Don't
// use this function in new code; it's a hack to keep things working for now.
fn mk_plain_tag(ast.def_id tid) -> @ty.t {
@@ -1720,7 +1792,7 @@ fn mk_plain_tag(ast.def_id tid) -> @ty.t {
}
-type val_fn = fn(@block_ctxt cx, ValueRef v) -> result;
+type val_pair_fn = fn(@block_ctxt cx, ValueRef dst, ValueRef src) -> result;
type val_and_ty_fn = fn(@block_ctxt cx, ValueRef v, @ty.t t) -> result;
@@ -1805,12 +1877,21 @@ fn iter_structural_ty_full(@block_ctxt cx,
auto variants = tag_variants(cx.fcx.ccx, tid);
auto n_variants = _vec.len[ast.variant](variants);
- auto lldiscrim_a_ptr = cx.build.GEP(av, vec(C_int(0), C_int(0)));
- auto llunion_a_ptr = cx.build.GEP(av, vec(C_int(0), C_int(1)));
+ // Cast the tags to types we can GEP into.
+ auto lltagty = T_opaque_tag_ptr(cx.fcx.ccx.tn);
+ auto av_tag = cx.build.PointerCast(av, lltagty);
+ auto bv_tag = cx.build.PointerCast(bv, lltagty);
+
+ auto lldiscrim_a_ptr = cx.build.GEP(av_tag,
+ vec(C_int(0), C_int(0)));
+ auto llunion_a_ptr = cx.build.GEP(av_tag,
+ vec(C_int(0), C_int(1)));
auto lldiscrim_a = cx.build.Load(lldiscrim_a_ptr);
- auto lldiscrim_b_ptr = cx.build.GEP(bv, vec(C_int(0), C_int(0)));
- auto llunion_b_ptr = cx.build.GEP(bv, vec(C_int(0), C_int(1)));
+ auto lldiscrim_b_ptr = cx.build.GEP(bv_tag,
+ vec(C_int(0), C_int(0)));
+ auto llunion_b_ptr = cx.build.GEP(bv_tag,
+ vec(C_int(0), C_int(1)));
auto lldiscrim_b = cx.build.Load(lldiscrim_b_ptr);
// NB: we must hit the discriminant first so that structural
@@ -1827,6 +1908,8 @@ fn iter_structural_ty_full(@block_ctxt cx,
auto next_cx = new_sub_block_ctxt(bcx, "tag-iter-next");
+ auto ty_params = tag_ty_params(bcx.fcx.ccx, tid);
+
auto i = 0u;
for (ast.variant variant in variants) {
auto variant_cx = new_sub_block_ctxt(bcx,
@@ -1836,7 +1919,8 @@ fn iter_structural_ty_full(@block_ctxt cx,
if (_vec.len[ast.variant_arg](variant.args) > 0u) {
// N-ary variant.
- auto llvarty = type_of_variant(bcx.fcx.ccx, variants.(i));
+ auto llvarty = type_of_variant(bcx.fcx.ccx, variants.(i),
+ ty_params, tps);
auto fn_ty = ty.ann_to_type(variants.(i).ann);
alt (fn_ty.struct) {
@@ -1847,8 +1931,6 @@ fn iter_structural_ty_full(@block_ctxt cx,
auto llvarp_b = variant_cx.build.
TruncOrBitCast(llunion_b_ptr, T_ptr(llvarty));
- auto ty_params = tag_ty_params(bcx.fcx.ccx, tid);
-
auto j = 0u;
for (ty.arg a in args) {
auto v = vec(C_int(0), C_int(j as int));
@@ -1923,13 +2005,15 @@ fn iter_structural_ty_full(@block_ctxt cx,
// Iterates through a pointer range, until the src* hits the src_lim*.
fn iter_sequence_raw(@block_ctxt cx,
+ ValueRef dst, // elt*
ValueRef src, // elt*
ValueRef src_lim, // elt*
ValueRef elt_sz,
- val_fn f) -> result {
+ val_pair_fn f) -> result {
auto bcx = cx;
+ let ValueRef dst_int = vp2i(bcx, dst);
let ValueRef src_int = vp2i(bcx, src);
let ValueRef src_lim_int = vp2i(bcx, src_lim);
@@ -1939,6 +2023,8 @@ fn iter_sequence_raw(@block_ctxt cx,
bcx.build.Br(cond_cx.llbb);
+ let ValueRef dst_curr = cond_cx.build.Phi(T_int(),
+ vec(dst_int), vec(bcx.llbb));
let ValueRef src_curr = cond_cx.build.Phi(T_int(),
vec(src_int), vec(bcx.llbb));
@@ -1947,14 +2033,18 @@ fn iter_sequence_raw(@block_ctxt cx,
cond_cx.build.CondBr(end_test, body_cx.llbb, next_cx.llbb);
+ auto dst_curr_ptr = vi2p(body_cx, dst_curr, T_ptr(T_i8()));
auto src_curr_ptr = vi2p(body_cx, src_curr, T_ptr(T_i8()));
- auto body_res = f(body_cx, src_curr_ptr);
+ auto body_res = f(body_cx, dst_curr_ptr, src_curr_ptr);
body_cx = body_res.bcx;
+ auto dst_next = body_cx.build.Add(dst_curr, elt_sz);
auto src_next = body_cx.build.Add(src_curr, elt_sz);
body_cx.build.Br(cond_cx.llbb);
+ cond_cx.build.AddIncomingToPhi(dst_curr, vec(dst_next),
+ vec(body_cx.llbb));
cond_cx.build.AddIncomingToPhi(src_curr, vec(src_next),
vec(body_cx.llbb));
@@ -1970,15 +2060,16 @@ fn iter_sequence_inner(@block_ctxt cx,
fn adaptor_fn(val_and_ty_fn f,
@ty.t elt_ty,
@block_ctxt cx,
- ValueRef v) -> result {
+ ValueRef dst,
+ ValueRef src) -> result {
auto llty = type_of(cx.fcx.ccx, elt_ty);
- auto p = cx.build.PointerCast(v, T_ptr(llty));
+ auto p = cx.build.PointerCast(src, T_ptr(llty));
ret f(cx, load_scalar_or_boxed(cx, p, elt_ty), elt_ty);
}
auto elt_sz = size_of(cx, elt_ty);
- be iter_sequence_raw(elt_sz.bcx, src, src_lim, elt_sz.val,
- bind adaptor_fn(f, elt_ty, _, _));
+ be iter_sequence_raw(elt_sz.bcx, src, src, src_lim, elt_sz.val,
+ bind adaptor_fn(f, elt_ty, _, _, _));
}
@@ -2222,12 +2313,30 @@ fn node_ann_type(@crate_ctxt cx, &ast.ann a) -> @ty.t {
case (ast.ann_none) {
cx.sess.bug("missing type annotation");
}
- case (ast.ann_type(?t)) {
+ case (ast.ann_type(?t, _)) {
ret target_type(cx, t);
}
}
}
+fn node_ann_ty_params(&ast.ann a) -> vec[@ty.t] {
+ alt (a) {
+ case (ast.ann_none) {
+ log "missing type annotation";
+ fail;
+ }
+ case (ast.ann_type(_, ?tps_opt)) {
+ alt (tps_opt) {
+ case (none[vec[@ty.t]]) {
+ log "type annotation has no ty params";
+ fail;
+ }
+ case (some[vec[@ty.t]](?tps)) { ret tps; }
+ }
+ }
+ }
+}
+
fn node_type(@crate_ctxt cx, &ast.ann a) -> TypeRef {
ret type_of(cx, node_ann_type(cx, a));
}
@@ -2296,13 +2405,27 @@ fn trans_unary(@block_ctxt cx, ast.unop op,
fail;
}
-fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t,
- ValueRef lhs, ValueRef rhs) -> result {
+fn trans_compare(@block_ctxt cx0, ast.binop op, @ty.t t0,
+ ValueRef lhs0, ValueRef rhs0) -> result {
+
+ auto cx = cx0;
+
+ auto lhs_r = autoderef(cx, lhs0, t0);
+ auto lhs = lhs_r.val;
+ cx = lhs_r.bcx;
+
+ auto rhs_r = autoderef(cx, rhs0, t0);
+ auto rhs = rhs_r.val;
+ cx = rhs_r.bcx;
+
+ auto t = autoderefed_ty(t0);
if (ty.type_is_scalar(t)) {
ret res(cx, trans_scalar_compare(cx, op, t, lhs, rhs));
- } else if (ty.type_is_structural(t)) {
+ } else if (ty.type_is_structural(t)
+ || ty.type_is_sequence(t)) {
+
auto scx = new_sub_block_ctxt(cx, "structural compare start");
auto next = new_sub_block_ctxt(cx, "structural compare end");
cx.build.Br(scx.llbb);
@@ -2333,28 +2456,52 @@ fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t,
auto flag = scx.build.Alloca(T_i1());
- alt (op) {
- // ==, <= and >= default to true if they find == all the way.
- case (ast.eq) { scx.build.Store(C_integral(1, T_i1()), flag); }
- case (ast.le) { scx.build.Store(C_integral(1, T_i1()), flag); }
- case (ast.ge) { scx.build.Store(C_integral(1, T_i1()), flag); }
- case (_) {
- // ==, <= and >= default to false if they find == all the way.
- scx.build.Store(C_integral(0, T_i1()), flag);
+ if (ty.type_is_sequence(t)) {
+
+ // If we hit == all the way through the minimum-shared-length
+ // section, default to judging the relative sequence lengths.
+ auto len_cmp =
+ trans_integral_compare(scx, op, plain_ty(ty.ty_uint),
+ vec_fill(scx, lhs),
+ vec_fill(scx, rhs));
+ scx.build.Store(len_cmp, flag);
+
+ } else {
+ auto T = C_integral(1, T_i1());
+ auto F = C_integral(0, T_i1());
+
+ alt (op) {
+ // ==, <= and >= default to true if they find == all the way.
+ case (ast.eq) { scx.build.Store(T, flag); }
+ case (ast.le) { scx.build.Store(T, flag); }
+ case (ast.ge) { scx.build.Store(T, flag); }
+ case (_) {
+ // < > default to false if they find == all the way.
+ scx.build.Store(F, flag);
+ }
+
}
}
fn inner(@block_ctxt last_cx,
+ bool load_inner,
ValueRef flag,
ast.binop op,
@block_ctxt cx,
- ValueRef av,
- ValueRef bv,
+ ValueRef av0,
+ ValueRef bv0,
@ty.t t) -> result {
auto cnt_cx = new_sub_block_ctxt(cx, "continue comparison");
auto stop_cx = new_sub_block_ctxt(cx, "stop comparison");
+ auto av = av0;
+ auto bv = bv0;
+ if (load_inner) {
+ av = load_scalar_or_boxed(cx, av, t);
+ bv = load_scalar_or_boxed(cx, bv, t);
+ }
+
// First 'eq' comparison: if so, continue to next elts.
auto eq_r = trans_compare(cx, ast.eq, t, av, bv);
eq_r.bcx.build.CondBr(eq_r.val, cnt_cx.llbb, stop_cx.llbb);
@@ -2366,16 +2513,32 @@ fn trans_compare(@block_ctxt cx, ast.binop op, @ty.t t,
ret res(cnt_cx, C_nil());
}
- auto r = iter_structural_ty_full(scx, lhs, rhs, t,
- bind inner(next, flag, op,
- _, _, _, _));
+ auto r;
+ if (ty.type_is_structural(t)) {
+ r = iter_structural_ty_full(scx, lhs, rhs, t,
+ bind inner(next, false, flag, op,
+ _, _, _, _));
+ } else {
+ auto lhs_p0 = vec_p0(scx, lhs);
+ auto rhs_p0 = vec_p0(scx, rhs);
+ auto min_len = umin(scx, vec_fill(scx, lhs), vec_fill(scx, rhs));
+ auto rhs_lim = scx.build.GEP(rhs_p0, vec(min_len));
+ auto elt_ty = ty.sequence_element_type(t);
+ auto elt_llsz_r = size_of(scx, elt_ty);
+ scx = elt_llsz_r.bcx;
+ r = iter_sequence_raw(scx, lhs, rhs, rhs_lim,
+ elt_llsz_r.val,
+ bind inner(next, true, flag, op,
+ _, _, _, elt_ty));
+ }
r.bcx.build.Br(next.llbb);
auto v = next.build.Load(flag);
ret res(next, v);
+
} else {
- // FIXME: compare vec, str, box?
+ // FIXME: compare obj, fn by pointer?
cx.fcx.ccx.sess.unimpl("type in trans_compare");
ret res(cx, C_bool(false));
}
@@ -2732,6 +2895,62 @@ fn trans_for(@block_ctxt cx,
bind inner(_, local, _, _, body));
}
+
+// Iterator translation
+
+// Searches through a block for all references to locals or upvars in this
+// frame and returns the list of definition IDs thus found.
+fn collect_upvars(@block_ctxt cx, &ast.block bloc, &ast.def_id initial_decl)
+ -> vec[ast.def_id] {
+ type env = @rec(
+ mutable vec[ast.def_id] refs,
+ hashmap[ast.def_id,()] decls
+ );
+
+ fn fold_expr_path(&env e, &common.span sp, &ast.path p,
+ &option.t[ast.def] d, ast.ann a) -> @ast.expr {
+ alt (option.get[ast.def](d)) {
+ case (ast.def_arg(?did)) { e.refs += vec(did); }
+ case (ast.def_local(?did)) { e.refs += vec(did); }
+ case (ast.def_upvar(?did)) { e.refs += vec(did); }
+ case (_) { /* ignore */ }
+ }
+
+ ret @fold.respan[ast.expr_](sp, ast.expr_path(p, d, a));
+ }
+
+ fn fold_decl_local(&env e, &common.span sp, @ast.local local)
+ -> @ast.decl {
+ e.decls.insert(local.id, ());
+ ret @fold.respan[ast.decl_](sp, ast.decl_local(local));
+ }
+
+ auto fep = fold_expr_path;
+ auto fdl = fold_decl_local;
+ auto fld = @rec(
+ fold_expr_path=fep,
+ fold_decl_local=fdl
+ with *fold.new_identity_fold[env]()
+ );
+
+ let vec[ast.def_id] refs = vec();
+ let hashmap[ast.def_id,()] decls = new_def_hash[()]();
+ decls.insert(initial_decl, ());
+ let env e = @rec(mutable refs=refs, decls=decls);
+
+ fold.fold_block[env](e, fld, bloc);
+
+ // Calculate (refs - decls). This is the set of captured upvars.
+ let vec[ast.def_id] result = vec();
+ for (ast.def_id ref_id in e.refs) {
+ if (!decls.contains_key(ref_id)) {
+ result += vec(ref_id);
+ }
+ }
+
+ ret result;
+}
+
fn trans_for_each(@block_ctxt cx,
@ast.decl decl,
@ast.expr seq,
@@ -2763,19 +2982,63 @@ fn trans_for_each(@block_ctxt cx,
// escape. This could be determined upstream, and probably ought
// to be so, eventualy. For first cut, skip this. Null env.
- auto env_ty = T_opaque_closure_ptr(cx.fcx.ccx.tn);
-
-
- // Step 2: Declare foreach body function.
-
// FIXME: possibly support alias-mode here?
auto decl_ty = plain_ty(ty.ty_nil);
+ auto decl_id;
alt (decl.node) {
case (ast.decl_local(?local)) {
decl_ty = node_ann_type(cx.fcx.ccx, local.ann);
+ decl_id = local.id;
}
}
+ auto upvars = collect_upvars(cx, body, decl_id);
+ auto upvar_count = _vec.len[ast.def_id](upvars);
+
+ auto llbindingsptr;
+ if (upvar_count > 0u) {
+ // Gather up the upvars.
+ let vec[ValueRef] llbindings = vec();
+ let vec[TypeRef] llbindingtys = vec();
+ for (ast.def_id did in upvars) {
+ auto llbinding;
+ alt (cx.fcx.lllocals.find(did)) {
+ case (none[ValueRef]) {
+ llbinding = cx.fcx.llupvars.get(did);
+ }
+ case (some[ValueRef](?llval)) { llbinding = llval; }
+ }
+ llbindings += vec(llbinding);
+ llbindingtys += vec(val_ty(llbinding));
+ }
+
+ // Create an array of bindings and copy in aliases to the upvars.
+ llbindingsptr = cx.build.Alloca(T_struct(llbindingtys));
+ auto i = 0u;
+ while (i < upvar_count) {
+ auto llbindingptr = cx.build.GEP(llbindingsptr,
+ vec(C_int(0), C_int(i as int)));
+ cx.build.Store(llbindings.(i), llbindingptr);
+ i += 1u;
+ }
+ } else {
+ // Null bindings.
+ llbindingsptr = C_null(T_ptr(T_i8()));
+ }
+
+ // Create an environment and populate it with the bindings.
+ auto llenvptrty = T_closure_ptr(cx.fcx.ccx.tn, T_ptr(T_nil()),
+ val_ty(llbindingsptr), 0u);
+ auto llenvptr = cx.build.Alloca(llvm.LLVMGetElementType(llenvptrty));
+
+ auto llbindingsptrptr = cx.build.GEP(llenvptr,
+ vec(C_int(0),
+ C_int(abi.box_rc_field_body),
+ C_int(2)));
+ cx.build.Store(llbindingsptr, llbindingsptrptr);
+
+ // Step 2: Declare foreach body function.
+
let str s =
cx.fcx.ccx.names.next("_rust_foreach")
+ sep() + cx.fcx.ccx.path;
@@ -2789,7 +3052,7 @@ fn trans_for_each(@block_ctxt cx,
auto iter_body_llty = type_of_fn_full(cx.fcx.ccx, ast.proto_fn,
none[TypeRef],
vec(rec(mode=ast.val, ty=decl_ty)),
- plain_ty(ty.ty_nil));
+ plain_ty(ty.ty_nil), 0u);
let ValueRef lliterbody = decl_fastcall_fn(cx.fcx.ccx.llmod,
s, iter_body_llty);
@@ -2800,7 +3063,30 @@ fn trans_for_each(@block_ctxt cx,
auto fcx = new_fn_ctxt(cx.fcx.ccx, lliterbody);
auto bcx = new_top_block_ctxt(fcx);
- // FIXME: populate lllocals from llenv here.
+ // Populate the upvars from the environment.
+ auto llremoteenvptr = bcx.build.PointerCast(fcx.llenv, llenvptrty);
+ auto llremotebindingsptrptr = bcx.build.GEP(llremoteenvptr,
+ vec(C_int(0), C_int(abi.box_rc_field_body), C_int(2)));
+ auto llremotebindingsptr = bcx.build.Load(llremotebindingsptrptr);
+
+ auto i = 0u;
+ while (i < upvar_count) {
+ auto upvar_id = upvars.(i);
+ auto llupvarptrptr = bcx.build.GEP(llremotebindingsptr,
+ vec(C_int(0), C_int(i as int)));
+ auto llupvarptr = bcx.build.Load(llupvarptrptr);
+ fcx.llupvars.insert(upvar_id, llupvarptr);
+
+ i += 1u;
+ }
+
+ // Treat the loop variable as an upvar as well. We copy it to an alloca
+ // as usual.
+ auto lllvar = llvm.LLVMGetParam(fcx.llfn, 3u);
+ auto lllvarptr = bcx.build.Alloca(val_ty(lllvar));
+ bcx.build.Store(lllvar, lllvarptr);
+ fcx.llupvars.insert(decl_id, lllvarptr);
+
auto res = trans_block(bcx, body);
res.bcx.build.RetVoid();
@@ -2818,6 +3104,12 @@ fn trans_for_each(@block_ctxt cx,
C_int(abi.fn_field_code)));
cx.build.Store(lliterbody, code_cell);
+ auto env_cell = cx.build.GEP(pair, vec(C_int(0),
+ C_int(abi.fn_field_box)));
+ auto llenvblobptr = cx.build.PointerCast(llenvptr,
+ T_opaque_closure_ptr(cx.fcx.ccx.tn));
+ cx.build.Store(llenvblobptr, env_cell);
+
// log "lliterbody: " + val_str(cx.fcx.ccx.tn, lliterbody);
ret trans_call(cx, f,
some[ValueRef](cx.build.Load(pair)),
@@ -2840,9 +3132,9 @@ fn trans_while(@block_ctxt cx, @ast.expr cond,
auto cond_res = trans_expr(cond_cx, cond);
body_res.bcx.build.Br(cond_cx.llbb);
- cond_res.bcx.build.CondBr(cond_res.val,
- body_cx.llbb,
- next_cx.llbb);
+
+ auto cond_bcx = trans_block_cleanups(cond_res.bcx, cond_cx);
+ cond_bcx.build.CondBr(cond_res.val, body_cx.llbb, next_cx.llbb);
cx.build.Br(cond_cx.llbb);
ret res(next_cx, C_nil());
@@ -2866,23 +3158,6 @@ fn trans_do_while(@block_ctxt cx, &ast.block body,
// Pattern matching translation
-// Returns a pointer to the union part of the LLVM representation of a tag
-// type, cast to the appropriate type.
-fn get_pat_union_ptr(@block_ctxt cx, vec[@ast.pat] subpats, ValueRef llval)
- -> ValueRef {
- auto llblobptr = cx.build.GEP(llval, vec(C_int(0), C_int(1)));
-
- // Generate the union type.
- let vec[TypeRef] llsubpattys = vec();
- for (@ast.pat subpat in subpats) {
- llsubpattys += vec(type_of(cx.fcx.ccx, pat_ty(subpat)));
- }
-
- // Recursively check subpatterns.
- auto llunionty = T_struct(llsubpattys);
- ret cx.build.TruncOrBitCast(llblobptr, T_ptr(llunionty));
-}
-
fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval,
@block_ctxt next_cx) -> result {
alt (pat.node) {
@@ -2900,8 +3175,12 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval,
}
case (ast.pat_tag(?id, ?subpats, ?vdef_opt, ?ann)) {
- auto lltagptr = cx.build.GEP(llval, vec(C_int(0), C_int(0)));
- auto lltag = cx.build.Load(lltagptr);
+ auto lltagptr = cx.build.PointerCast(llval,
+ T_opaque_tag_ptr(cx.fcx.ccx.tn));
+
+ auto lldiscrimptr = cx.build.GEP(lltagptr,
+ vec(C_int(0), C_int(0)));
+ auto lldiscrim = cx.build.Load(lldiscrimptr);
auto vdef = option.get[ast.variant_def](vdef_opt);
auto variant_id = vdef._1;
@@ -2920,18 +3199,22 @@ fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval,
auto matched_cx = new_sub_block_ctxt(cx, "matched_cx");
- auto lleq = cx.build.ICmp(lib.llvm.LLVMIntEQ, lltag,
+ auto lleq = cx.build.ICmp(lib.llvm.LLVMIntEQ, lldiscrim,
C_int(variant_tag));
cx.build.CondBr(lleq, matched_cx.llbb, next_cx.llbb);
+ auto ty_params = node_ann_ty_params(ann);
+
if (_vec.len[@ast.pat](subpats) > 0u) {
- auto llunionptr = get_pat_union_ptr(matched_cx, subpats,
- llval);
+ auto llblobptr = matched_cx.build.GEP(lltagptr,
+ vec(C_int(0), C_int(1)));
auto i = 0;
for (@ast.pat subpat in subpats) {
- auto llsubvalptr = matched_cx.build.GEP(llunionptr,
- vec(C_int(0),
- C_int(i)));
+ auto rslt = GEP_tag(matched_cx, llblobptr, vdef._0,
+ vdef._1, ty_params, i);
+ auto llsubvalptr = rslt.val;
+ matched_cx = rslt.bcx;
+
auto llsubval = load_scalar_or_boxed(matched_cx,
llsubvalptr,
pat_ty(subpat));
@@ -2955,25 +3238,38 @@ fn trans_pat_binding(@block_ctxt cx, @ast.pat pat, ValueRef llval)
case (ast.pat_lit(_, _)) { ret res(cx, llval); }
case (ast.pat_bind(?id, ?def_id, ?ann)) {
auto ty = node_ann_type(cx.fcx.ccx, ann);
- auto llty = type_of(cx.fcx.ccx, ty);
- auto dst = cx.build.Alloca(llty);
+ auto rslt = alloc_ty(cx, ty);
+ auto dst = rslt.val;
+ auto bcx = rslt.bcx;
+
llvm.LLVMSetValueName(dst, _str.buf(id));
- cx.fcx.lllocals.insert(def_id, dst);
- cx.cleanups += clean(bind drop_slot(_, dst, ty));
+ bcx.fcx.lllocals.insert(def_id, dst);
+ bcx.cleanups += clean(bind drop_slot(_, dst, ty));
- ret copy_ty(cx, INIT, dst, llval, ty);
+ ret copy_ty(bcx, INIT, dst, llval, ty);
}
- case (ast.pat_tag(_, ?subpats, _, _)) {
+ case (ast.pat_tag(_, ?subpats, ?vdef_opt, ?ann)) {
if (_vec.len[@ast.pat](subpats) == 0u) { ret res(cx, llval); }
- auto llunionptr = get_pat_union_ptr(cx, subpats, llval);
+ // Get the appropriate variant for this tag.
+ auto vdef = option.get[ast.variant_def](vdef_opt);
+ auto variant = tag_variant_with_id(cx.fcx.ccx, vdef._0, vdef._1);
+
+ auto lltagptr = cx.build.PointerCast(llval,
+ T_opaque_tag_ptr(cx.fcx.ccx.tn));
+ auto llblobptr = cx.build.GEP(lltagptr, vec(C_int(0), C_int(1)));
+
+ auto ty_param_substs = node_ann_ty_params(ann);
auto this_cx = cx;
auto i = 0;
for (@ast.pat subpat in subpats) {
- auto llsubvalptr = this_cx.build.GEP(llunionptr,
- vec(C_int(0), C_int(i)));
+ auto rslt = GEP_tag(this_cx, llblobptr, vdef._0, vdef._1,
+ ty_param_substs, i);
+ this_cx = rslt.bcx;
+ auto llsubvalptr = rslt.val;
+
auto llsubval = load_scalar_or_boxed(this_cx, llsubvalptr,
pat_ty(subpat));
auto subpat_res = trans_pat_binding(this_cx, subpat,
@@ -3052,8 +3348,19 @@ fn lval_generic_fn(@block_ctxt cx,
check (cx.fcx.ccx.fn_pairs.contains_key(fn_id));
auto lv = lval_val(cx, cx.fcx.ccx.fn_pairs.get(fn_id));
- auto monoty = node_ann_type(cx.fcx.ccx, ann);
- auto tys = ty.resolve_ty_params(tpt, monoty);
+
+ auto monoty;
+ auto tys;
+ alt (ann) {
+ case (ast.ann_none) {
+ cx.fcx.ccx.sess.bug("no type annotation for path!");
+ fail;
+ }
+ case (ast.ann_type(?monoty_, ?tps)) {
+ monoty = monoty_;
+ tys = option.get[vec[@ty.t]](tps);
+ }
+ }
if (_vec.len[@ty.t](tys) != 0u) {
auto bcx = cx;
@@ -3082,8 +3389,15 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt,
ret lval_mem(cx, cx.fcx.llargs.get(did));
}
case (ast.def_local(?did)) {
- check (cx.fcx.lllocals.contains_key(did));
- ret lval_mem(cx, cx.fcx.lllocals.get(did));
+ alt (cx.fcx.lllocals.find(did)) {
+ case (none[ValueRef]) {
+ check (cx.fcx.llupvars.contains_key(did));
+ ret lval_mem(cx, cx.fcx.llupvars.get(did));
+ }
+ case (some[ValueRef](?llval)) {
+ ret lval_mem(cx, llval);
+ }
+ }
}
case (ast.def_binding(?did)) {
check (cx.fcx.lllocals.contains_key(did));
@@ -3215,7 +3529,6 @@ fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base,
ix_val = ix.val;
}
- auto llunit_ty = node_type(cx.fcx.ccx, ann);
auto unit_sz = size_of(bcx, node_ann_type(cx.fcx.ccx, ann));
bcx = unit_sz.bcx;
@@ -3295,7 +3608,7 @@ fn trans_bind_thunk(@crate_ctxt cx,
@ty.t incoming_fty,
@ty.t outgoing_fty,
vec[option.t[@ast.expr]] args,
- TypeRef llclosure_ty,
+ @ty.t closure_ty,
vec[@ty.t] bound_tys,
uint ty_param_count) -> ValueRef {
// Construct a thunk-call with signature incoming_fty, and that copies
@@ -3308,27 +3621,21 @@ fn trans_bind_thunk(@crate_ctxt cx,
auto fcx = new_fn_ctxt(cx, llthunk);
auto bcx = new_top_block_ctxt(fcx);
- auto llclosure = bcx.build.PointerCast(fcx.llenv, llclosure_ty);
-
- auto llbody = bcx.build.GEP(llclosure,
- vec(C_int(0),
- C_int(abi.box_rc_field_body)));
-
- auto lltarget = bcx.build.GEP(llbody,
- vec(C_int(0),
- C_int(abi.closure_elt_target)));
-
- auto llbound = bcx.build.GEP(llbody,
- vec(C_int(0),
- C_int(abi.closure_elt_bindings)));
+ auto llclosure_ptr_ty = type_of(cx, plain_ty(ty.ty_box(closure_ty)));
+ auto llclosure = bcx.build.PointerCast(fcx.llenv, llclosure_ptr_ty);
- auto lltargetclosure = bcx.build.GEP(lltarget,
+ auto lltarget = GEP_tup_like(bcx, closure_ty, llclosure,
+ vec(0,
+ abi.box_rc_field_body,
+ abi.closure_elt_target));
+ bcx = lltarget.bcx;
+ auto lltargetclosure = bcx.build.GEP(lltarget.val,
vec(C_int(0),
C_int(abi.fn_field_box)));
lltargetclosure = bcx.build.Load(lltargetclosure);
auto outgoing_ret_ty = ty.ty_fn_ret(outgoing_fty);
- auto outgoing_arg_tys = ty.ty_fn_args(outgoing_fty);
+ auto outgoing_args = ty.ty_fn_args(outgoing_fty);
auto llretptr = fcx.llretptr;
if (ty.type_has_dynamic_size(outgoing_ret_ty)) {
@@ -3343,51 +3650,84 @@ fn trans_bind_thunk(@crate_ctxt cx,
let uint i = 0u;
while (i < ty_param_count) {
auto lltyparam_ptr =
- bcx.build.GEP(llbody, vec(C_int(0),
- C_int(abi.closure_elt_ty_params),
- C_int(i as int)));
- llargs += vec(bcx.build.Load(lltyparam_ptr));
+ GEP_tup_like(bcx, closure_ty, llclosure,
+ vec(0,
+ abi.box_rc_field_body,
+ abi.closure_elt_ty_params,
+ (i as int)));
+ bcx = lltyparam_ptr.bcx;
+ llargs += vec(bcx.build.Load(lltyparam_ptr.val));
i += 1u;
}
- let uint a = 2u + i; // retptr, task ptr, env come first
+ let uint a = 3u; // retptr, task ptr, env come first
let int b = 0;
let uint outgoing_arg_index = 0u;
+ let vec[TypeRef] llout_arg_tys =
+ type_of_explicit_args(cx, outgoing_args);
+
for (option.t[@ast.expr] arg in args) {
+
+ auto out_arg = outgoing_args.(outgoing_arg_index);
+ auto llout_arg_ty = llout_arg_tys.(outgoing_arg_index);
+
alt (arg) {
// Arg provided at binding time; thunk copies it from closure.
case (some[@ast.expr](_)) {
- let ValueRef bound_arg = bcx.build.GEP(llbound,
- vec(C_int(0),
- C_int(b)));
- // FIXME: possibly support passing aliases someday.
- llargs += bcx.build.Load(bound_arg);
+ auto bound_arg =
+ GEP_tup_like(bcx, closure_ty, llclosure,
+ vec(0,
+ abi.box_rc_field_body,
+ abi.closure_elt_bindings,
+ b));
+
+ bcx = bound_arg.bcx;
+ auto val = bound_arg.val;
+
+ if (out_arg.mode == ast.val) {
+ val = bcx.build.Load(val);
+ } else if (ty.count_ty_params(out_arg.ty) > 0u) {
+ check (out_arg.mode == ast.alias);
+ val = bcx.build.PointerCast(val, llout_arg_ty);
+ }
+
+ llargs += val;
b += 1;
}
// Arg will be provided when the thunk is invoked.
case (none[@ast.expr]) {
let ValueRef passed_arg = llvm.LLVMGetParam(llthunk, a);
- if (ty.type_has_dynamic_size(outgoing_arg_tys.
- (outgoing_arg_index).ty)) {
- // Cast to a generic typaram pointer in order to make a
- // type-compatible call.
+
+ if (ty.count_ty_params(out_arg.ty) > 0u) {
+ check (out_arg.mode == ast.alias);
passed_arg = bcx.build.PointerCast(passed_arg,
- T_typaram_ptr(cx.tn));
+ llout_arg_ty);
}
+
llargs += passed_arg;
a += 1u;
}
}
- outgoing_arg_index += 0u;
+ outgoing_arg_index += 1u;
}
// FIXME: turn this call + ret into a tail call.
- auto lltargetfn = bcx.build.GEP(lltarget,
+ auto lltargetfn = bcx.build.GEP(lltarget.val,
vec(C_int(0),
C_int(abi.fn_field_code)));
+
+ // Cast the outgoing function to the appropriate type (see the comments in
+ // trans_bind below for why this is necessary).
+ auto lltargetty = type_of_fn(bcx.fcx.ccx,
+ ty.ty_fn_proto(outgoing_fty),
+ outgoing_args,
+ outgoing_ret_ty,
+ ty_param_count);
+ lltargetfn = bcx.build.PointerCast(lltargetfn, T_ptr(T_ptr(lltargetty)));
+
lltargetfn = bcx.build.Load(lltargetfn);
auto r = bcx.build.FastCall(lltargetfn, llargs);
@@ -3452,21 +3792,26 @@ fn trans_bind(@block_ctxt cx, @ast.expr f,
i += 1u;
}
- // Get the type of the bound function.
- let TypeRef lltarget_ty = type_of(bcx.fcx.ccx, outgoing_fty);
-
// Synthesize a closure type.
let @ty.t bindings_ty = plain_ty(ty.ty_tup(bound_tys));
- let TypeRef llbindings_ty = type_of(bcx.fcx.ccx, bindings_ty);
- let TypeRef llclosure_ty = T_closure_ptr(cx.fcx.ccx.tn,
- lltarget_ty,
- llbindings_ty,
- ty_param_count);
-
- // Malloc a box for the body.
- // FIXME: this isn't generic-safe
- auto r = trans_raw_malloc(bcx, llclosure_ty,
- llsize_of(llvm.LLVMGetElementType(llclosure_ty)));
+
+ // NB: keep this in sync with T_closure_ptr; we're making
+ // a ty.t structure that has the same "shape" as the LLVM type
+ // it constructs.
+ let @ty.t tydesc_ty = plain_ty(ty.ty_type);
+
+ let vec[@ty.t] captured_tys =
+ _vec.init_elt[@ty.t](tydesc_ty, ty_param_count);
+
+ let vec[@ty.t] closure_tys =
+ vec(tydesc_ty,
+ outgoing_fty,
+ bindings_ty,
+ plain_ty(ty.ty_tup(captured_tys)));
+
+ let @ty.t closure_ty = plain_ty(ty.ty_tup(closure_tys));
+
+ auto r = trans_malloc_boxed(bcx, closure_ty);
auto box = r.val;
bcx = r.bcx;
auto rc = bcx.build.GEP(box,
@@ -3487,12 +3832,26 @@ fn trans_bind(@block_ctxt cx, @ast.expr f,
bcx = bindings_tydesc.bcx;
bcx.build.Store(bindings_tydesc.val, bound_tydesc);
+ // Determine the LLVM type for the outgoing function type. This
+ // may be different from the type returned by trans_malloc_boxed()
+ // since we have more information than that function does;
+ // specifically, we know how many type descriptors the outgoing
+ // function has, which type_of() doesn't, as only we know which
+ // item the function refers to.
+ auto llfnty = type_of_fn(bcx.fcx.ccx,
+ ty.ty_fn_proto(outgoing_fty),
+ ty.ty_fn_args(outgoing_fty),
+ ty.ty_fn_ret(outgoing_fty),
+ ty_param_count);
+ auto llclosurety = T_ptr(T_fn_pair(bcx.fcx.ccx.tn, llfnty));
+
// Store thunk-target.
auto bound_target =
bcx.build.GEP(closure,
vec(C_int(0),
C_int(abi.closure_elt_target)));
auto src = bcx.build.Load(f_res.res.val);
+ bound_target = bcx.build.PointerCast(bound_target, llclosurety);
bcx.build.Store(src, bound_target);
// Copy expr values into boxed bindings.
@@ -3525,6 +3884,8 @@ fn trans_bind(@block_ctxt cx, @ast.expr f,
bcx.build.Store(td, ty_param_slot);
i += 1;
}
+
+ outgoing_fty = ginfo.item_type;
}
}
@@ -3534,9 +3895,10 @@ fn trans_bind(@block_ctxt cx, @ast.expr f,
C_int(abi.fn_field_code)));
let @ty.t pair_ty = node_ann_type(cx.fcx.ccx, ann);
+
let ValueRef llthunk =
trans_bind_thunk(cx.fcx.ccx, pair_ty, outgoing_fty,
- args, llclosure_ty, bound_tys,
+ args, closure_ty, bound_tys,
ty_param_count);
bcx.build.Store(llthunk, pair_code);
@@ -3824,7 +4186,27 @@ fn trans_vec(@block_ctxt cx, vec[@ast.expr] args,
bcx = src_res.bcx;
auto dst_res = GEP_tup_like(bcx, pseudo_tup_ty, body, vec(0, i));
bcx = dst_res.bcx;
- bcx = copy_ty(bcx, INIT, dst_res.val, src_res.val, unit_ty).bcx;
+
+ // Cast the destination type to the source type. This is needed to
+ // make tags work, for a subtle combination of reasons:
+ //
+ // (1) "dst_res" above is derived from "body", which is in turn
+ // derived from "vec_val".
+ // (2) "vec_val" has the LLVM type "llty".
+ // (3) "llty" is the result of calling type_of() on a vector type.
+ // (4) For tags, type_of() returns a different type depending on
+ // on whether the tag is behind a box or not. Vector types are
+ // considered boxes.
+ // (5) "src_res" is derived from "unit_ty", which is not behind a box.
+
+ auto dst_val;
+ if (!ty.type_has_dynamic_size(unit_ty)) {
+ dst_val = bcx.build.PointerCast(dst_res.val, T_ptr(llunit_ty));
+ } else {
+ dst_val = dst_res.val;
+ }
+
+ bcx = copy_ty(bcx, INIT, dst_val, src_res.val, unit_ty).bcx;
i += 1;
}
auto fill = bcx.build.GEP(vec_val,
@@ -4108,10 +4490,19 @@ fn trans_put(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
case (none[@ast.expr]) { }
case (some[@ast.expr](?x)) {
auto r = trans_expr(bcx, x);
- llargs += r.val;
+
+ auto llarg = r.val;
bcx = r.bcx;
+ if (ty.type_is_structural(ty.expr_ty(x))) {
+ // Until here we've been treating structures by pointer; we
+ // are now passing it as an arg, so need to load it.
+ llarg = bcx.build.Load(llarg);
+ }
+
+ llargs += llarg;
}
}
+
ret res(bcx, bcx.build.FastCall(llcallee, llargs));
}
@@ -4369,6 +4760,7 @@ fn new_fn_ctxt(@crate_ctxt cx,
let hashmap[ast.def_id, ValueRef] llargs = new_def_hash[ValueRef]();
let hashmap[ast.def_id, ValueRef] llobjfields = new_def_hash[ValueRef]();
let hashmap[ast.def_id, ValueRef] lllocals = new_def_hash[ValueRef]();
+ let hashmap[ast.def_id, ValueRef] llupvars = new_def_hash[ValueRef]();
let hashmap[ast.def_id, ValueRef] lltydescs = new_def_hash[ValueRef]();
ret @rec(llfn=llfndecl,
@@ -4380,6 +4772,7 @@ fn new_fn_ctxt(@crate_ctxt cx,
llargs=llargs,
llobjfields=llobjfields,
lllocals=lllocals,
+ llupvars=llupvars,
lltydescs=lltydescs,
ccx=cx);
}
@@ -4619,7 +5012,8 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty,
case (ty.ty_fn(?proto, ?inputs, ?output)) {
llfnty = type_of_fn_full(cx, proto,
some[TypeRef](self_ty),
- inputs, output);
+ inputs, output,
+ _vec.len[ast.ty_param](ty_params));
}
}
@@ -4792,6 +5186,11 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id,
none[TypeRef], ret_ty_of_fn(variant.ann),
fn_args, ty_params);
+ let vec[@ty.t] ty_param_substs = vec();
+ for (ast.ty_param tp in ty_params) {
+ ty_param_substs += vec(plain_ty(ty.ty_param(tp.id)));
+ }
+
auto bcx = new_top_block_ctxt(fcx);
auto arg_tys = arg_tys_of_fn(variant.ann);
@@ -4810,7 +5209,8 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id,
i = 0u;
for (ast.variant_arg va in variant.args) {
- auto rslt = GEP_tag(bcx, llblobptr, variant, i as int);
+ auto rslt = GEP_tag(bcx, llblobptr, tag_id, variant.id,
+ ty_param_substs, i as int);
bcx = rslt.bcx;
auto lldestptr = rslt.val;
@@ -4822,7 +5222,8 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id,
auto arg_ty = arg_tys.(i).ty;
auto llargval;
- if (ty.type_is_structural(arg_ty)) {
+ if (ty.type_is_structural(arg_ty) ||
+ ty.type_has_dynamic_size(arg_ty)) {
llargval = llargptr;
} else {
llargval = bcx.build.Load(llargptr);
@@ -4918,11 +5319,23 @@ fn get_pair_fn_ty(TypeRef llpairty) -> TypeRef {
fn decl_fn_and_pair(@crate_ctxt cx,
str kind,
str name,
+ vec[ast.ty_param] ty_params,
&ast.ann ann,
ast.def_id id) {
- auto llpairty = node_type(cx, ann);
- auto llfty = get_pair_fn_ty(llpairty);
+ auto llfty;
+ auto llpairty;
+ alt (node_ann_type(cx, ann).struct) {
+ case (ty.ty_fn(?proto, ?inputs, ?output)) {
+ llfty = type_of_fn(cx, proto, inputs, output,
+ _vec.len[ast.ty_param](ty_params));
+ llpairty = T_fn_pair(cx.tn, llfty);
+ }
+ case (_) {
+ cx.sess.bug("decl_fn_and_pair(): fn item doesn't have fn type?!");
+ fail;
+ }
+ }
// Declare the function itself.
let str s = cx.names.next("_rust_" + kind) + sep() + name;
@@ -4951,11 +5364,29 @@ fn register_fn_pair(@crate_ctxt cx, str ps, TypeRef llpairty, ValueRef llfn,
cx.fn_pairs.insert(id, gvar);
}
-fn native_fn_wrapper_type(@crate_ctxt cx, &ast.ann ann) -> TypeRef {
+// Returns the number of type parameters that the given native function has.
+fn native_fn_ty_param_count(@crate_ctxt cx, &ast.def_id id) -> uint {
+ auto count;
+ auto native_item = cx.native_items.get(id);
+ alt (native_item.node) {
+ case (ast.native_item_ty(_,_)) {
+ cx.sess.bug("decl_native_fn_and_pair(): native fn isn't " +
+ "actually a fn?!");
+ fail;
+ }
+ case (ast.native_item_fn(_, _, ?tps, _, _)) {
+ count = _vec.len[ast.ty_param](tps);
+ }
+ }
+ ret count;
+}
+
+fn native_fn_wrapper_type(@crate_ctxt cx, uint ty_param_count, &ast.ann ann)
+ -> TypeRef {
auto x = node_ann_type(cx, ann);
alt (x.struct) {
case (ty.ty_native_fn(?abi, ?args, ?out)) {
- ret type_of_fn(cx, ast.proto_fn, args, out);
+ ret type_of_fn(cx, ast.proto_fn, args, out, ty_param_count);
}
}
fail;
@@ -4965,8 +5396,10 @@ fn decl_native_fn_and_pair(@crate_ctxt cx,
str name,
&ast.ann ann,
ast.def_id id) {
+ auto num_ty_param = native_fn_ty_param_count(cx, id);
+
// Declare the wrapper.
- auto wrapper_type = native_fn_wrapper_type(cx, ann);
+ auto wrapper_type = native_fn_wrapper_type(cx, num_ty_param, ann);
let str s = cx.names.next("_rust_wrapper") + sep() + name;
let ValueRef wrapper_fn = decl_fastcall_fn(cx.llmod, s, wrapper_type);
@@ -4991,7 +5424,6 @@ fn decl_native_fn_and_pair(@crate_ctxt cx,
alt (abi) {
case (ast.native_abi_rust) {
call_args += vec(fcx.lltaskptr);
- auto num_ty_param = ty.count_ty_params(plain_ty(fn_type.struct));
for each (uint i in _uint.range(0u, num_ty_param)) {
auto llarg = llvm.LLVMGetParam(fcx.llfn, arg_n);
check (llarg as int != 0);
@@ -5009,6 +5441,7 @@ fn decl_native_fn_and_pair(@crate_ctxt cx,
call_args += vec(llarg);
arg_n += 1u;
}
+
auto r = bcx.build.Call(function, call_args);
bcx.build.Store(r, fcx.llretptr);
bcx.build.RetVoid();
@@ -5030,16 +5463,16 @@ fn collect_native_item(&@crate_ctxt cx, @ast.native_item i) -> @crate_ctxt {
fn collect_item(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
alt (i.node) {
- case (ast.item_fn(?name, ?f, _, ?fid, ?ann)) {
+ case (ast.item_fn(?name, ?f, ?tps, ?fid, ?ann)) {
cx.items.insert(fid, i);
if (! cx.obj_methods.contains_key(fid)) {
- decl_fn_and_pair(cx, "fn", name, ann, fid);
+ decl_fn_and_pair(cx, "fn", name, tps, ann, fid);
}
}
- case (ast.item_obj(?name, ?ob, _, ?oid, ?ann)) {
+ case (ast.item_obj(?name, ?ob, ?tps, ?oid, ?ann)) {
cx.items.insert(oid, i);
- decl_fn_and_pair(cx, "obj_ctor", name, ann, oid);
+ decl_fn_and_pair(cx, "obj_ctor", name, tps, ann, oid);
for (@ast.method m in ob.methods) {
cx.obj_methods.insert(m.node.id, ());
}
@@ -5079,11 +5512,11 @@ fn collect_tag_ctor(&@crate_ctxt cx, @ast.item i) -> @crate_ctxt {
alt (i.node) {
- case (ast.item_tag(_, ?variants, _, _)) {
+ case (ast.item_tag(_, ?variants, ?tps, _)) {
for (ast.variant variant in variants) {
if (_vec.len[ast.variant_arg](variant.args) != 0u) {
decl_fn_and_pair(cx, "tag", variant.name,
- variant.ann, variant.id);
+ tps, variant.ann, variant.id);
}
}
}
@@ -5176,27 +5609,21 @@ fn i2p(ValueRef v, TypeRef t) -> ValueRef {
ret llvm.LLVMConstIntToPtr(v, t);
}
-fn trans_exit_task_glue(@crate_ctxt cx) {
+fn trans_exit_task_glue(@glue_fns glues,
+ &hashmap[str, ValueRef] upcalls,
+ type_names tn, ModuleRef llmod) {
let vec[TypeRef] T_args = vec();
let vec[ValueRef] V_args = vec();
- auto llfn = cx.glues.exit_task_glue;
+ auto llfn = glues.exit_task_glue;
let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 3u);
- auto fcx = @rec(llfn=llfn,
- lltaskptr=lltaskptr,
- llenv=C_null(T_opaque_closure_ptr(cx.tn)),
- llretptr=C_null(T_ptr(T_nil())),
- mutable llself=none[ValueRef],
- mutable lliterbody=none[ValueRef],
- llargs=new_def_hash[ValueRef](),
- llobjfields=new_def_hash[ValueRef](),
- lllocals=new_def_hash[ValueRef](),
- lltydescs=new_def_hash[ValueRef](),
- ccx=cx);
- auto bcx = new_top_block_ctxt(fcx);
- trans_upcall(bcx, "upcall_exit", V_args);
- bcx.build.RetVoid();
+ auto entrybb = llvm.LLVMAppendBasicBlock(llfn, _str.buf("entry"));
+ auto build = new_builder(entrybb);
+
+ trans_upcall2(build, glues, lltaskptr,
+ upcalls, tn, llmod, "upcall_exit", V_args);
+ build.RetVoid();
}
fn create_typedefs(@crate_ctxt cx) {
@@ -5205,22 +5632,22 @@ fn create_typedefs(@crate_ctxt cx) {
llvm.LLVMAddTypeName(cx.llmod, _str.buf("tydesc"), T_tydesc(cx.tn));
}
-fn create_crate_constant(@crate_ctxt cx) {
+fn create_crate_constant(ValueRef crate_ptr, @glue_fns glues) {
- let ValueRef crate_addr = p2i(cx.crate_ptr);
+ let ValueRef crate_addr = p2i(crate_ptr);
let ValueRef activate_glue_off =
- llvm.LLVMConstSub(p2i(cx.glues.activate_glue), crate_addr);
+ llvm.LLVMConstSub(p2i(glues.activate_glue), crate_addr);
let ValueRef yield_glue_off =
- llvm.LLVMConstSub(p2i(cx.glues.yield_glue), crate_addr);
+ llvm.LLVMConstSub(p2i(glues.yield_glue), crate_addr);
let ValueRef exit_task_glue_off =
- llvm.LLVMConstSub(p2i(cx.glues.exit_task_glue), crate_addr);
+ llvm.LLVMConstSub(p2i(glues.exit_task_glue), crate_addr);
let ValueRef crate_val =
C_struct(vec(C_null(T_int()), // ptrdiff_t image_base_off
- p2i(cx.crate_ptr), // uintptr_t self_addr
+ p2i(crate_ptr), // uintptr_t self_addr
C_null(T_int()), // ptrdiff_t debug_abbrev_off
C_null(T_int()), // size_t debug_abbrev_sz
C_null(T_int()), // ptrdiff_t debug_info_off
@@ -5236,7 +5663,7 @@ fn create_crate_constant(@crate_ctxt cx) {
C_int(abi.abi_x86_rustc_fastcall) // uintptr_t abi_tag
));
- llvm.LLVMSetInitializer(cx.crate_ptr, crate_val);
+ llvm.LLVMSetInitializer(crate_ptr, crate_val);
}
fn find_main_fn(@crate_ctxt cx) -> ValueRef {
@@ -5338,26 +5765,28 @@ fn check_module(ModuleRef llmod) {
// TODO: run the linter here also, once there are llvm-c bindings for it.
}
-fn make_no_op_type_glue(ModuleRef llmod, type_names tn) -> ValueRef {
+fn decl_no_op_type_glue(ModuleRef llmod, type_names tn) -> ValueRef {
auto ty = T_fn(vec(T_taskptr(tn), T_ptr(T_i8())), T_void());
- auto fun = decl_fastcall_fn(llmod, abi.no_op_type_glue_name(), ty);
+ ret decl_fastcall_fn(llmod, abi.no_op_type_glue_name(), ty);
+}
+
+fn make_no_op_type_glue(ValueRef fun) {
auto bb_name = _str.buf("_rust_no_op_type_glue_bb");
auto llbb = llvm.LLVMAppendBasicBlock(fun, bb_name);
new_builder(llbb).RetVoid();
- ret fun;
}
-fn make_memcpy_glue(ModuleRef llmod) -> ValueRef {
-
- // We're not using the LLVM memcpy intrinsic. It appears to call through
- // to the platform memcpy in some cases, which is not terribly safe to run
- // on a rust stack.
-
+fn decl_memcpy_glue(ModuleRef llmod) -> ValueRef {
auto p8 = T_ptr(T_i8());
auto ty = T_fn(vec(p8, p8, T_int()), T_void());
- auto fun = decl_fastcall_fn(llmod, abi.memcpy_glue_name(), ty);
+ ret decl_fastcall_fn(llmod, abi.memcpy_glue_name(), ty);
+}
+fn make_memcpy_glue(ValueRef fun) {
+ // We're not using the LLVM memcpy intrinsic. It appears to call through
+ // to the platform memcpy in some cases, which is not terribly safe to run
+ // on a rust stack.
auto initbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("init"));
auto hdrbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("hdr"));
auto loopbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("loop"));
@@ -5389,18 +5818,18 @@ fn make_memcpy_glue(ModuleRef llmod) -> ValueRef {
// End block
auto eb = new_builder(endbb);
eb.RetVoid();
- ret fun;
}
-fn make_bzero_glue(ModuleRef llmod) -> ValueRef {
-
- // We're not using the LLVM memset intrinsic. Same as with memcpy.
-
+fn decl_bzero_glue(ModuleRef llmod) -> ValueRef {
auto p8 = T_ptr(T_i8());
auto ty = T_fn(vec(p8, T_int()), T_void());
- auto fun = decl_fastcall_fn(llmod, abi.bzero_glue_name(), ty);
+ ret decl_fastcall_fn(llmod, abi.bzero_glue_name(), ty);
+}
+fn make_bzero_glue(ModuleRef llmod) -> ValueRef {
+ // We're not using the LLVM memset intrinsic. Same as with memcpy.
+ auto fun = decl_bzero_glue(llmod);
auto initbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("init"));
auto hdrbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("hdr"));
auto loopbb = llvm.LLVMAppendBasicBlock(fun, _str.buf("loop"));
@@ -5465,6 +5894,45 @@ fn make_vec_append_glue(ModuleRef llmod, type_names tn) -> ValueRef {
ret llfn;
}
+
+fn vec_fill(@block_ctxt bcx, ValueRef v) -> ValueRef {
+ ret bcx.build.Load(bcx.build.GEP(v, vec(C_int(0),
+ C_int(abi.vec_elt_fill))));
+}
+
+fn put_vec_fill(@block_ctxt bcx, ValueRef v, ValueRef fill) -> ValueRef {
+ ret bcx.build.Store(fill,
+ bcx.build.GEP(v,
+ vec(C_int(0),
+ C_int(abi.vec_elt_fill))));
+}
+
+fn vec_fill_adjusted(@block_ctxt bcx, ValueRef v,
+ ValueRef skipnull) -> ValueRef {
+ auto f = bcx.build.Load(bcx.build.GEP(v,
+ vec(C_int(0),
+ C_int(abi.vec_elt_fill))));
+ ret bcx.build.Select(skipnull, bcx.build.Sub(f, C_int(1)), f);
+}
+
+fn vec_p0(@block_ctxt bcx, ValueRef v) -> ValueRef {
+ auto p = bcx.build.GEP(v, vec(C_int(0),
+ C_int(abi.vec_elt_data)));
+ ret bcx.build.PointerCast(p, T_ptr(T_i8()));
+}
+
+
+fn vec_p1(@block_ctxt bcx, ValueRef v) -> ValueRef {
+ auto len = vec_fill(bcx, v);
+ ret bcx.build.GEP(vec_p0(bcx, v), vec(len));
+}
+
+fn vec_p1_adjusted(@block_ctxt bcx, ValueRef v,
+ ValueRef skipnull) -> ValueRef {
+ auto len = vec_fill_adjusted(bcx, v, skipnull);
+ ret bcx.build.GEP(vec_p0(bcx, v), vec(len));
+}
+
fn trans_vec_append_glue(@crate_ctxt cx) {
auto llfn = cx.glues.vec_append_glue;
@@ -5485,6 +5953,7 @@ fn trans_vec_append_glue(@crate_ctxt cx) {
llargs=new_def_hash[ValueRef](),
llobjfields=new_def_hash[ValueRef](),
lllocals=new_def_hash[ValueRef](),
+ llupvars=new_def_hash[ValueRef](),
lltydescs=new_def_hash[ValueRef](),
ccx=cx);
@@ -5495,45 +5964,6 @@ fn trans_vec_append_glue(@crate_ctxt cx) {
// First the dst vec needs to grow to accommodate the src vec.
// To do this we have to figure out how many bytes to add.
- fn vec_fill(@block_ctxt bcx, ValueRef v) -> ValueRef {
- ret bcx.build.Load(bcx.build.GEP(v, vec(C_int(0),
- C_int(abi.vec_elt_fill))));
- }
-
- fn put_vec_fill(@block_ctxt bcx, ValueRef v, ValueRef fill) -> ValueRef {
- ret bcx.build.Store(fill,
- bcx.build.GEP(v,
- vec(C_int(0),
- C_int(abi.vec_elt_fill))));
- }
-
- fn vec_fill_adjusted(@block_ctxt bcx, ValueRef v,
- ValueRef skipnull) -> ValueRef {
- auto f = bcx.build.Load(bcx.build.GEP(v,
- vec(C_int(0),
- C_int(abi.vec_elt_fill))));
- ret bcx.build.Select(skipnull, bcx.build.Sub(f, C_int(1)), f);
- }
-
- fn vec_p0(@block_ctxt bcx, ValueRef v) -> ValueRef {
- auto p = bcx.build.GEP(v, vec(C_int(0),
- C_int(abi.vec_elt_data)));
- ret bcx.build.PointerCast(p, T_ptr(T_i8()));
- }
-
-
- fn vec_p1(@block_ctxt bcx, ValueRef v) -> ValueRef {
- auto len = vec_fill(bcx, v);
- ret bcx.build.GEP(vec_p0(bcx, v), vec(len));
- }
-
- fn vec_p1_adjusted(@block_ctxt bcx, ValueRef v,
- ValueRef skipnull) -> ValueRef {
- auto len = vec_fill_adjusted(bcx, v, skipnull);
- ret bcx.build.GEP(vec_p0(bcx, v), vec(len));
- }
-
-
auto llcopy_dst_ptr = bcx.build.Alloca(T_int());
auto llnew_vec_res =
trans_upcall(bcx, "upcall_vec_grow",
@@ -5575,16 +6005,17 @@ fn trans_vec_append_glue(@crate_ctxt cx) {
C_int(abi.tydesc_field_size))));
fn take_one(ValueRef elt_tydesc,
- @block_ctxt cx, ValueRef v) -> result {
- call_tydesc_glue_full(cx, v,
+ @block_ctxt cx,
+ ValueRef dst, ValueRef src) -> result {
+ call_tydesc_glue_full(cx, src,
elt_tydesc,
abi.tydesc_field_take_glue_off);
- ret res(cx, v);
+ ret res(cx, src);
}
- auto bcx = iter_sequence_raw(cx, src, src_lim,
+ auto bcx = iter_sequence_raw(cx, dst, src, src_lim,
elt_llsz, bind take_one(elt_tydesc,
- _, _)).bcx;
+ _, _, _)).bcx;
ret call_memcpy(bcx, dst, src, n_bytes);
}
@@ -5644,14 +6075,16 @@ fn make_glues(ModuleRef llmod, type_names tn) -> @glue_fns {
upcall_glues =
_vec.init_fn[ValueRef](bind decl_upcall_glue(llmod, tn, _),
abi.n_upcall_glues as uint),
- no_op_type_glue = make_no_op_type_glue(llmod, tn),
- memcpy_glue = make_memcpy_glue(llmod),
- bzero_glue = make_bzero_glue(llmod),
+ no_op_type_glue = decl_no_op_type_glue(llmod, tn),
+ memcpy_glue = decl_memcpy_glue(llmod),
+ bzero_glue = decl_bzero_glue(llmod),
vec_append_glue = make_vec_append_glue(llmod, tn));
}
-fn trans_crate(session.session sess, @ast.crate crate, str output,
- bool shared) {
+fn make_common_glue(str output) {
+ // FIXME: part of this is repetitive and is probably a good idea
+ // to autogen it, but things like the memcpy implementation are not
+ // and it might be better to just check in a .ll file.
auto llmod =
llvm.LLVMModuleCreateWithNameInContext(_str.buf("rust_out"),
llvm.LLVMGetGlobalContext());
@@ -5663,8 +6096,35 @@ fn trans_crate(session.session sess, @ast.crate crate, str output,
let ValueRef crate_ptr =
llvm.LLVMAddGlobal(llmod, T_crate(tn), _str.buf("rust_crate"));
+ auto intrinsics = declare_intrinsics(llmod);
+
llvm.LLVMSetModuleInlineAsm(llmod, _str.buf(x86.get_module_asm()));
+ auto glues = make_glues(llmod, tn);
+ create_crate_constant(crate_ptr, glues);
+ make_memcpy_glue(glues.memcpy_glue);
+
+ trans_exit_task_glue(glues, new_str_hash[ValueRef](), tn, llmod);
+
+ check_module(llmod);
+
+ llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(output));
+ llvm.LLVMDisposeModule(llmod);
+}
+
+fn trans_crate(session.session sess, @ast.crate crate, str output,
+ bool shared) {
+ auto llmod =
+ llvm.LLVMModuleCreateWithNameInContext(_str.buf("rust_out"),
+ llvm.LLVMGetGlobalContext());
+
+ llvm.LLVMSetDataLayout(llmod, _str.buf(x86.get_data_layout()));
+ llvm.LLVMSetTarget(llmod, _str.buf(x86.get_target_triple()));
+ auto td = mk_target_data(x86.get_data_layout());
+ auto tn = mk_type_names();
+ let ValueRef crate_ptr =
+ llvm.LLVMAddGlobal(llmod, T_crate(tn), _str.buf("rust_crate"));
+
auto intrinsics = declare_intrinsics(llmod);
auto glues = make_glues(llmod, tn);
@@ -5705,13 +6165,14 @@ fn trans_crate(session.session sess, @ast.crate crate, str output,
trans_constants(cx, crate);
trans_mod(cx, crate.node.module);
- trans_exit_task_glue(cx);
trans_vec_append_glue(cx);
- create_crate_constant(cx);
if (!shared) {
trans_main_fn(cx, cx.crate_ptr);
}
+ // Translate the metadata.
+ middle.metadata.write_metadata(cx, crate);
+
check_module(llmod);
llvm.LLVMWriteBitcodeToFile(llmod, _str.buf(output));
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 5a595db6..0a161810 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -81,87 +81,10 @@ tag unify_result {
// Stringification
-fn ast_ty_to_str(&@ast.ty ty) -> str {
-
- fn ast_fn_input_to_str(&rec(ast.mode mode, @ast.ty ty) input) -> str {
- auto s;
- if (mode_is_alias(input.mode)) {
- s = "&";
- } else {
- s = "";
- }
-
- ret s + ast_ty_to_str(input.ty);
- }
-
- fn ast_ty_field_to_str(&ast.ty_field f) -> str {
- ret ast_ty_to_str(f.ty) + " " + f.ident;
- }
-
- auto s;
- alt (ty.node) {
- case (ast.ty_nil) { s = "()"; }
- case (ast.ty_bool) { s = "bool"; }
- case (ast.ty_int) { s = "int"; }
- case (ast.ty_uint) { s = "uint"; }
- case (ast.ty_machine(?tm)) { s = common.ty_mach_to_str(tm); }
- case (ast.ty_char) { s = "char"; }
- case (ast.ty_str) { s = "str"; }
- case (ast.ty_box(?t)) { s = "@" + ast_ty_to_str(t); }
- case (ast.ty_vec(?t)) { s = "vec[" + ast_ty_to_str(t) + "]"; }
- case (ast.ty_type) { s = "type"; }
-
- case (ast.ty_tup(?elts)) {
- auto f = ast_ty_to_str;
- s = "tup(";
- s += _str.connect(_vec.map[@ast.ty,str](f, elts), ",");
- s += ")";
- }
-
- case (ast.ty_rec(?fields)) {
- auto f = ast_ty_field_to_str;
- s = "rec(";
- s += _str.connect(_vec.map[ast.ty_field,str](f, fields), ",");
- s += ")";
- }
-
- case (ast.ty_fn(?proto, ?inputs, ?output)) {
- auto f = ast_fn_input_to_str;
- if (proto == ast.proto_fn) {
- s = "fn(";
- } else {
- s = "iter(";
- }
- auto is = _vec.map[rec(ast.mode mode, @ast.ty ty),str](f, inputs);
- s += _str.connect(is, ", ");
- s += ")";
-
- if (output.node != ast.ty_nil) {
- s += " -> " + ast_ty_to_str(output);
- }
- }
-
- case (ast.ty_path(?path, _)) {
- s = path_to_str(path);
- }
-
- case (ast.ty_mutable(?t)) {
- s = "mutable " + ast_ty_to_str(t);
- }
-
-
- case (_) {
- fail; // FIXME: typestate bug
- }
- }
-
- ret s;
-}
-
fn path_to_str(&ast.path pth) -> str {
auto result = _str.connect(pth.node.idents, ".");
if (_vec.len[@ast.ty](pth.node.types) > 0u) {
- auto f = ast_ty_to_str;
+ auto f = pretty.pprust.ty_to_str;
result += "[";
result += _str.connect(_vec.map[@ast.ty,str](f, pth.node.types), ",");
result += "]";
@@ -169,8 +92,6 @@ fn path_to_str(&ast.path pth) -> str {
ret result;
}
-// FIXME use the pretty-printer for this once it has a concept of an
-// abstract stream
fn ty_to_str(&@t typ) -> str {
fn fn_input_to_str(&rec(ast.mode mode, @t ty) input) -> str {
@@ -452,6 +373,14 @@ fn get_element_type(@t ty, uint i) -> @t {
fail;
}
+fn type_is_box(@t ty) -> bool {
+ alt (ty.struct) {
+ case (ty_box(_)) { ret true; }
+ case (_) { ret false; }
+ }
+ fail;
+}
+
fn type_is_boxed(@t ty) -> bool {
alt (ty.struct) {
case (ty_str) { ret true; }
@@ -596,10 +525,10 @@ fn eq_ty(&@t a, &@t b) -> bool {
fn ann_to_type(&ast.ann ann) -> @t {
alt (ann) {
case (ast.ann_none) {
- // shouldn't happen, but can until the typechecker is complete
- ret plain_ty(ty_var(-1)); // FIXME: broken, broken, broken
+ log "ann_to_type() called on node with no type";
+ fail;
}
- case (ast.ann_type(?ty)) {
+ case (ast.ann_type(?ty, _)) {
ret ty;
}
}
diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs
index 5c7f963c..b2f371c5 100644
--- a/src/comp/middle/typeck.rs
+++ b/src/comp/middle/typeck.rs
@@ -39,10 +39,12 @@ tag any_item {
}
type ty_item_table = hashmap[ast.def_id,any_item];
+type ty_param_table = hashmap[ast.def_id,vec[ast.def_id]];
type crate_ctxt = rec(session.session sess,
@ty_table item_types,
@ty_item_table item_items,
+ @ty_param_table item_ty_params,
vec[ast.obj_field] obj_fields,
mutable int next_var_id);
@@ -83,59 +85,187 @@ fn generalize_ty(@crate_ctxt cx, @ty.t t) -> @ty.t {
// expression.
fn substitute_ty_params(&@crate_ctxt ccx,
@ty.t typ,
- vec[@ast.ty] supplied,
+ vec[ast.def_id] ty_params,
+ vec[@ty.t] supplied,
&span sp) -> @ty.t {
state obj ty_substituter(@crate_ctxt ccx,
- @mutable uint i,
- vec[@ast.ty] supplied,
- @hashmap[int,@ty.t] substs) {
+ vec[ast.def_id] ty_params,
+ vec[@ty.t] supplied) {
fn fold_simple_ty(@ty.t typ) -> @ty.t {
alt (typ.struct) {
- case (ty.ty_var(?vid)) {
- alt (substs.find(vid)) {
- case (some[@ty.t](?resolved_ty)) {
- ret resolved_ty;
- }
- case (none[@ty.t]) {
- if (i >= _vec.len[@ast.ty](supplied)) {
- // Just leave it as an unresolved parameter
- // for now. (We will error out later.)
- ret typ;
- }
-
- auto result = ast_ty_to_ty_crate(ccx,
- supplied.(*i));
- *i += 1u;
- substs.insert(vid, result);
- ret result;
- }
+ case (ty.ty_param(?pid)) {
+ // Find the index of the type parameter.
+ auto ty_param_len = _vec.len[ast.def_id](ty_params);
+ auto i = 0u;
+ while (i < ty_param_len &&
+ !common.def_eq(pid, ty_params.(i))) {
+ i += 1u;
}
+ if (i == ty_param_len) {
+ log "substitute_ty_params(): " +
+ "no ty param for param id!";
+ fail;
+ }
+
+ // Substitute it in.
+ ret supplied.(i);
}
case (_) { ret typ; }
}
}
}
- fn hash_int(&int x) -> uint { ret x as uint; }
- fn eq_int(&int a, &int b) -> bool { ret a == b; }
- auto hasher = hash_int;
- auto eqer = eq_int;
- auto substs = @map.mk_hashmap[int,@ty.t](hasher, eqer);
-
- auto subst_count = @mutable 0u;
- auto substituter = ty_substituter(ccx, subst_count, supplied, substs);
-
- auto result = ty.fold_ty(substituter, typ);
-
- auto supplied_len = _vec.len[@ast.ty](supplied);
- if ((*subst_count) != supplied_len) {
- ccx.sess.span_err(sp, "expected " + _uint.to_str(*subst_count, 10u) +
+ auto ty_param_len = _vec.len[ast.def_id](ty_params);
+ auto supplied_len = _vec.len[@ty.t](supplied);
+ if (ty_param_len != supplied_len) {
+ ccx.sess.span_err(sp, "expected " + _uint.to_str(ty_param_len, 10u) +
" type parameter(s) but found " +
_uint.to_str(supplied_len, 10u) + " parameter(s)");
fail;
}
- ret result;
+ auto substituter = ty_substituter(ccx, ty_params, supplied);
+ ret ty.fold_ty(substituter, typ);
+}
+
+type ty_params_opt_and_ty = tup(option.t[vec[ast.def_id]], @ty.t);
+
+// Returns the type parameters and the type for the given definition.
+fn ty_params_and_ty_for_def(@fn_ctxt fcx, &ast.def defn)
+ -> ty_params_opt_and_ty {
+ alt (defn) {
+ case (ast.def_arg(?id)) {
+ check (fcx.locals.contains_key(id));
+ ret tup(none[vec[ast.def_id]], fcx.locals.get(id));
+ }
+ case (ast.def_local(?id)) {
+ auto t;
+ alt (fcx.locals.find(id)) {
+ case (some[@ty.t](?t1)) { t = t1; }
+ case (none[@ty.t]) { t = plain_ty(ty.ty_local(id)); }
+ }
+ ret tup(none[vec[ast.def_id]], t);
+ }
+ case (ast.def_obj_field(?id)) {
+ check (fcx.locals.contains_key(id));
+ ret tup(none[vec[ast.def_id]], fcx.locals.get(id));
+ }
+ case (ast.def_fn(?id)) {
+ check (fcx.ccx.item_types.contains_key(id));
+ ret tup(some(fcx.ccx.item_ty_params.get(id)),
+ fcx.ccx.item_types.get(id));
+ }
+ case (ast.def_native_fn(?id)) {
+ check (fcx.ccx.item_types.contains_key(id));
+ ret tup(some(fcx.ccx.item_ty_params.get(id)),
+ fcx.ccx.item_types.get(id));
+ }
+ case (ast.def_const(?id)) {
+ check (fcx.ccx.item_types.contains_key(id));
+ ret tup(none[vec[ast.def_id]], fcx.ccx.item_types.get(id));
+ }
+ case (ast.def_variant(?tag_id, ?variant_id)) {
+ check (fcx.ccx.item_types.contains_key(variant_id));
+ ret tup(some(fcx.ccx.item_ty_params.get(tag_id)),
+ fcx.ccx.item_types.get(variant_id));
+ }
+ case (ast.def_binding(?id)) {
+ check (fcx.locals.contains_key(id));
+ ret tup(none[vec[ast.def_id]], fcx.locals.get(id));
+ }
+ case (ast.def_obj(?id)) {
+ check (fcx.ccx.item_types.contains_key(id));
+ ret tup(some(fcx.ccx.item_ty_params.get(id)),
+ fcx.ccx.item_types.get(id));
+ }
+
+ case (ast.def_mod(_)) {
+ // Hopefully part of a path.
+ // TODO: return a type that's more poisonous, perhaps?
+ ret tup(none[vec[ast.def_id]], plain_ty(ty.ty_nil));
+ }
+
+ case (_) {
+ // FIXME: handle other names.
+ fcx.ccx.sess.unimpl("definition variant");
+ fail;
+ }
+ }
+}
+
+// Instantiates the given path, which must refer to an item with the given
+// type parameters and type.
+fn instantiate_path(@fn_ctxt fcx, &ast.path pth, &ty_params_opt_and_ty tpt,
+ &span sp) -> ast.ann {
+ auto ty_params = tpt._0;
+ auto t = tpt._1;
+
+ auto ty_substs_opt;
+ auto ty_substs_len = _vec.len[@ast.ty](pth.node.types);
+ if (ty_substs_len > 0u) {
+ let vec[@ty.t] ty_substs = vec();
+ auto i = 0u;
+ while (i < ty_substs_len) {
+ ty_substs += vec(ast_ty_to_ty_crate(fcx.ccx, pth.node.types.(i)));
+ i += 1u;
+ }
+ ty_substs_opt = some[vec[@ty.t]](ty_substs);
+
+ alt (ty_params) {
+ case (none[vec[ast.def_id]]) {
+ fcx.ccx.sess.span_err(sp, "this kind of item may not take " +
+ "type parameters");
+ fail;
+ }
+ case (some[vec[ast.def_id]](?tps)) {
+ t = substitute_ty_params(fcx.ccx, t, tps, ty_substs, sp);
+ }
+ }
+ } else {
+ ty_substs_opt = none[vec[@ty.t]];
+
+ alt (ty_params) {
+ case (none[vec[ast.def_id]]) { /* nothing */ }
+ case (some[vec[ast.def_id]](_)) {
+ // We will acquire the type parameters through
+ // unification.
+ t = generalize_ty(fcx.ccx, t);
+ }
+ }
+ }
+
+ ret ast.ann_type(t, ty_substs_opt);
+}
+
+// Returns the type parameters and polytype of an item, if it's an item that
+// supports type parameters.
+fn ty_params_for_item(@crate_ctxt ccx, &ast.def d)
+ -> option.t[ty.ty_params_and_ty] {
+ auto params_id;
+ auto types_id;
+ alt (d) {
+ case (ast.def_fn(?id)) { params_id = id; types_id = id; }
+ case (ast.def_obj(?id)) { params_id = id; types_id = id; }
+ case (ast.def_obj_field(_)) { ret none[ty.ty_params_and_ty]; }
+ case (ast.def_mod(_)) { ret none[ty.ty_params_and_ty]; }
+ case (ast.def_const(_)) { ret none[ty.ty_params_and_ty]; }
+ case (ast.def_arg(_)) { ret none[ty.ty_params_and_ty]; }
+ case (ast.def_local(_)) { ret none[ty.ty_params_and_ty]; }
+ case (ast.def_variant(?tid, ?vid)) {
+ params_id = tid;
+ types_id = vid;
+ }
+ case (ast.def_ty(_)) { ret none[ty.ty_params_and_ty]; }
+ case (ast.def_ty_arg(_)) { ret none[ty.ty_params_and_ty]; }
+ case (ast.def_binding(_)) { ret none[ty.ty_params_and_ty]; }
+ case (ast.def_use(_)) { ret none[ty.ty_params_and_ty]; }
+ case (ast.def_native_ty(_)) { ret none[ty.ty_params_and_ty]; }
+ case (ast.def_native_fn(?id)) { params_id = id; types_id = id; }
+ }
+
+ auto tps = ccx.item_ty_params.get(params_id);
+ auto polyty = ccx.item_types.get(types_id);
+ ret some[ty.ty_params_and_ty](tup(tps, polyty));
}
// Parses the programmer's textual representation of a type into our internal
@@ -356,7 +486,7 @@ fn ty_of_native_fn_decl(@ty_item_table id_to_ty_item,
}
fn collect_item_types(session.session sess, @ast.crate crate)
- -> tup(@ast.crate, @ty_table, @ty_item_table) {
+ -> tup(@ast.crate, @ty_table, @ty_item_table, @ty_param_table) {
fn getter(@ty_item_table id_to_ty_item,
@ty_table item_to_ty,
@@ -550,7 +680,10 @@ fn collect_item_types(session.session sess, @ast.crate crate)
item_to_ty.insert(variant.id, result_ty);
- auto variant_t = rec(ann=ast.ann_type(result_ty) with variant);
+ auto variant_t = rec(
+ ann=ast.ann_type(result_ty, none[vec[@ty.t]])
+ with variant
+ );
result += vec(variant_t);
}
@@ -600,16 +733,29 @@ fn collect_item_types(session.session sess, @ast.crate crate)
// Second pass: translate the types of all items.
let @ty_table item_to_ty = @common.new_def_hash[@ty.t]();
+ auto item_ty_params = @common.new_def_hash[vec[ast.def_id]]();
type env = rec(session.session sess,
@ty_item_table id_to_ty_item,
@ty_table item_to_ty,
+ @ty_param_table item_ty_params,
ast.native_abi abi);
let @env e = @rec(sess=sess,
id_to_ty_item=id_to_ty_item,
item_to_ty=item_to_ty,
+ item_ty_params=item_ty_params,
abi=ast.native_abi_cdecl);
+ // Inserts the given type parameters into the type parameter table of the
+ // environment.
+ fn collect_ty_params(&@env e, &ast.def_id id, vec[ast.ty_param] tps) {
+ let vec[ast.def_id] result = vec();
+ for (ast.ty_param tp in tps) {
+ result += vec(tp.id);
+ }
+ e.item_ty_params.insert(id, result);
+ }
+
fn convert(&@env e, @ast.item i) -> @env {
auto abi = e.abi;
alt (i.node) {
@@ -638,29 +784,33 @@ fn collect_item_types(session.session sess, @ast.crate crate)
@ast.ty t, @ast.expr ex,
ast.def_id id, ast.ann a) -> @ast.item {
check (e.item_to_ty.contains_key(id));
- auto ty = e.item_to_ty.get(id);
+ auto typ = e.item_to_ty.get(id);
auto item = ast.item_const(i, t, ex, id,
- ast.ann_type(ty));
+ ast.ann_type(typ, none[vec[@ty.t]]));
ret @fold.respan[ast.item_](sp, item);
}
fn fold_item_fn(&@env e, &span sp, ast.ident i,
&ast._fn f, vec[ast.ty_param] ty_params,
ast.def_id id, ast.ann a) -> @ast.item {
+ collect_ty_params(e, id, ty_params);
+
check (e.item_to_ty.contains_key(id));
- auto ty = e.item_to_ty.get(id);
+ auto typ = e.item_to_ty.get(id);
auto item = ast.item_fn(i, f, ty_params, id,
- ast.ann_type(ty));
+ ast.ann_type(typ, none[vec[@ty.t]]));
ret @fold.respan[ast.item_](sp, item);
}
fn fold_native_item_fn(&@env e, &span sp, ast.ident i,
&ast.fn_decl d, vec[ast.ty_param] ty_params,
ast.def_id id, ast.ann a) -> @ast.native_item {
+ collect_ty_params(e, id, ty_params);
+
check (e.item_to_ty.contains_key(id));
- auto ty = e.item_to_ty.get(id);
+ auto typ = e.item_to_ty.get(id);
auto item = ast.native_item_fn(i, d, ty_params, id,
- ast.ann_type(ty));
+ ast.ann_type(typ, none[vec[@ty.t]]));
ret @fold.respan[ast.native_item_](sp, item);
}
@@ -688,6 +838,8 @@ fn collect_item_types(session.session sess, @ast.crate crate)
fn fold_item_obj(&@env e, &span sp, ast.ident i,
&ast._obj ob, vec[ast.ty_param] ty_params,
ast.def_id id, ast.ann a) -> @ast.item {
+ collect_ty_params(e, id, ty_params);
+
check (e.item_to_ty.contains_key(id));
auto t = e.item_to_ty.get(id);
let vec[method] meth_tys = get_ctor_obj_methods(t);
@@ -704,14 +856,20 @@ fn collect_item_types(session.session sess, @ast.crate crate)
auto meth_tfn = plain_ty(ty.ty_fn(meth_ty.proto,
meth_ty.inputs,
meth_ty.output));
- m_ = rec(ann=ast.ann_type(meth_tfn) with meth.node);
+ m_ = rec(
+ ann=ast.ann_type(meth_tfn, none[vec[@ty.t]])
+ with meth.node
+ );
m = @rec(node=m_ with *meth);
append[@ast.method](methods, m);
}
auto g = bind getter(e.id_to_ty_item, e.item_to_ty, _);
for (ast.obj_field fld in ob.fields) {
let @ty.t fty = ast_ty_to_ty(g, fld.ty);
- let ast.obj_field f = rec(ann=ast.ann_type(fty) with fld);
+ let ast.obj_field f = rec(
+ ann=ast.ann_type(fty, none[vec[@ty.t]])
+ with fld
+ );
append[ast.obj_field](fields, f);
}
@@ -719,17 +877,19 @@ fn collect_item_types(session.session sess, @ast.crate crate)
fields = fields
with ob);
auto item = ast.item_obj(i, ob_, ty_params, id,
- ast.ann_type(t));
+ ast.ann_type(t, none[vec[@ty.t]]));
ret @fold.respan[ast.item_](sp, item);
}
fn fold_item_ty(&@env e, &span sp, ast.ident i,
@ast.ty t, vec[ast.ty_param] ty_params,
ast.def_id id, ast.ann a) -> @ast.item {
+ collect_ty_params(e, id, ty_params);
+
check (e.item_to_ty.contains_key(id));
- auto ty = e.item_to_ty.get(id);
+ auto typ = e.item_to_ty.get(id);
auto item = ast.item_ty(i, t, ty_params, id,
- ast.ann_type(ty));
+ ast.ann_type(typ, none[vec[@ty.t]]));
ret @fold.respan[ast.item_](sp, item);
}
@@ -737,6 +897,8 @@ fn collect_item_types(session.session sess, @ast.crate crate)
vec[ast.variant] variants,
vec[ast.ty_param] ty_params,
ast.def_id id) -> @ast.item {
+ collect_ty_params(e, id, ty_params);
+
auto variants_t = get_tag_variant_types(e.id_to_ty_item,
e.item_to_ty,
id,
@@ -758,7 +920,7 @@ fn collect_item_types(session.session sess, @ast.crate crate)
fold_item_tag = bind fold_item_tag(_,_,_,_,_,_)
with *fld_2);
auto crate_ = fold.fold_crate[@env](e, fld_2, crate);
- ret tup(crate_, item_to_ty, id_to_ty_item);
+ ret tup(crate_, item_to_ty, id_to_ty_item, item_ty_params);
}
fn unify(&@fn_ctxt fcx, @ty.t expected, @ty.t actual) -> ty.unify_result {
@@ -895,29 +1057,40 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat {
alt (pat.node) {
case (ast.pat_wild(?ann)) {
auto t = demand(fcx, pat.span, expected, ann_to_type(ann));
- p_1 = ast.pat_wild(ast.ann_type(t));
+ p_1 = ast.pat_wild(ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.pat_lit(?lit, ?ann)) {
auto t = demand(fcx, pat.span, expected, ann_to_type(ann));
- p_1 = ast.pat_lit(lit, ast.ann_type(t));
+ p_1 = ast.pat_lit(lit, ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.pat_bind(?id, ?did, ?ann)) {
auto t = demand(fcx, pat.span, expected, ann_to_type(ann));
fcx.locals.insert(did, t);
- p_1 = ast.pat_bind(id, did, ast.ann_type(t));
+ p_1 = ast.pat_bind(id, did, ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.pat_tag(?id, ?subpats, ?vdef_opt, ?ann)) {
auto t = demand(fcx, pat.span, expected, ann_to_type(ann));
+ // Figure out the type parameters of the tag.
+ auto tag_id = option.get[ast.variant_def](vdef_opt)._0;
+ auto ty_params = fcx.ccx.item_ty_params.get(tag_id);
+
+ // Take the type parameters out of the expected type.
+ auto ty_param_substs;
+ alt (t.struct) {
+ case (ty.ty_tag(_, ?tps)) { ty_param_substs = tps; }
+ case (_) {
+ log "demand_pat(): expected type for tag pat isn't " +
+ "actually a tag?!";
+ fail;
+ }
+ }
+ auto tps_opt = some[vec[@ty.t]](ty_param_substs);
+
// The type of the tag isn't enough; we also have to get the type
// of the variant, which is either a tag type in the case of
// nullary variants or a function type in the case of n-ary
// variants.
- //
- // TODO: When we have type-parametric tags, this will get a little
- // trickier. Basically, we have to instantiate the variant type we
- // acquire here with the type parameters provided to us by
- // "expected".
auto vdef = option.get[ast.variant_def](vdef_opt);
auto variant_ty = fcx.ccx.item_types.get(vdef._1);
@@ -927,18 +1100,23 @@ fn demand_pat(&@fn_ctxt fcx, @ty.t expected, @ast.pat pat) -> @ast.pat {
case (ty.ty_tag(_, _)) {
// Nullary tag variant.
check (subpats_len == 0u);
- p_1 = ast.pat_tag(id, subpats, vdef_opt, ast.ann_type(t));
+ p_1 = ast.pat_tag(id, subpats, vdef_opt,
+ ast.ann_type(t, tps_opt));
}
case (ty.ty_fn(_, ?args, ?tag_ty)) {
+ // N-ary tag variant.
let vec[@ast.pat] new_subpats = vec();
auto i = 0u;
for (arg a in args) {
- auto new_subpat = demand_pat(fcx, a.ty, subpats.(i));
+ auto subpat_ty = substitute_ty_params(fcx.ccx, a.ty,
+ ty_params, ty_param_substs, pat.span);
+ auto new_subpat = demand_pat(fcx, subpat_ty,
+ subpats.(i));
new_subpats += vec(new_subpat);
i += 1u;
}
p_1 = ast.pat_tag(id, new_subpats, vdef_opt,
- ast.ann_type(tag_ty));
+ ast.ann_type(tag_ty, tps_opt));
}
}
}
@@ -977,7 +1155,7 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e,
fail;
}
}
- e_1 = ast.expr_vec(es_1, ast.ann_type(t));
+ e_1 = ast.expr_vec(es_1, ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_tup(?es_0, ?ann)) {
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
@@ -996,7 +1174,7 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e,
fail;
}
}
- e_1 = ast.expr_tup(elts_1, ast.ann_type(t));
+ e_1 = ast.expr_tup(elts_1, ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_rec(?fields_0, ?base_0, ?ann)) {
@@ -1049,11 +1227,12 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e,
fail;
}
}
- e_1 = ast.expr_rec(fields_1, base_1, ast.ann_type(t));
+ e_1 = ast.expr_rec(fields_1, base_1,
+ ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_bind(?sube, ?es, ?ann)) {
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
- e_1 = ast.expr_bind(sube, es, ast.ann_type(t));
+ e_1 = ast.expr_bind(sube, es, ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_call(?sube, ?es, ?ann)) {
// NB: we call 'demand_full' and pass in adk only in cases where
@@ -1061,25 +1240,28 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e,
// like expr_binary or expr_bind can't, so there's no need.
auto t = demand_full(fcx, e.span, expected,
ann_to_type(ann), adk);
- e_1 = ast.expr_call(sube, es, ast.ann_type(t));
+ e_1 = ast.expr_call(sube, es, ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_binary(?bop, ?lhs, ?rhs, ?ann)) {
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
- e_1 = ast.expr_binary(bop, lhs, rhs, ast.ann_type(t));
+ e_1 = ast.expr_binary(bop, lhs, rhs,
+ ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_unary(?uop, ?sube, ?ann)) {
// See note in expr_unary for why we're calling demand_full.
auto t = demand_full(fcx, e.span, expected,
ann_to_type(ann), adk);
- e_1 = ast.expr_unary(uop, sube, ast.ann_type(t));
+ e_1 = ast.expr_unary(uop, sube,
+ ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_lit(?lit, ?ann)) {
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
- e_1 = ast.expr_lit(lit, ast.ann_type(t));
+ e_1 = ast.expr_lit(lit, ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_cast(?sube, ?ast_ty, ?ann)) {
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
- e_1 = ast.expr_cast(sube, ast_ty, ast.ann_type(t));
+ e_1 = ast.expr_cast(sube, ast_ty,
+ ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_if(?cond, ?then_0, ?else_0, ?ann)) {
auto t = demand_full(fcx, e.span, expected,
@@ -1094,62 +1276,102 @@ fn demand_expr_full(&@fn_ctxt fcx, @ty.t expected, @ast.expr e,
else_1 = some[@ast.expr](e_1);
}
}
- e_1 = ast.expr_if(cond, then_1, else_1, ast.ann_type(t));
+ e_1 = ast.expr_if(cond, then_1, else_1,
+ ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_for(?decl, ?seq, ?bloc, ?ann)) {
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
- e_1 = ast.expr_for(decl, seq, bloc, ast.ann_type(t));
+ e_1 = ast.expr_for(decl, seq, bloc,
+ ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_for_each(?decl, ?seq, ?bloc, ?ann)) {
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
- e_1 = ast.expr_for_each(decl, seq, bloc, ast.ann_type(t));
+ e_1 = ast.expr_for_each(decl, seq, bloc,
+ ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_while(?cond, ?bloc, ?ann)) {
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
- e_1 = ast.expr_while(cond, bloc, ast.ann_type(t));
+ e_1 = ast.expr_while(cond, bloc,
+ ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_do_while(?bloc, ?cond, ?ann)) {
auto t = demand(fcx, e.span, expected, ann_to_type(ann));
- e_1 = ast.expr_do_while(bloc, cond, ast.ann_type(t));
+ e_1 = ast.expr_do_while(bloc, cond,
+ ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_block(?bloc, ?ann)) {
auto t = demand_full(fcx, e.span, expected,
ann_to_type(ann), adk);
- e_1 = ast.expr_block(bloc, ast.ann_type(t));
+ e_1 = ast.expr_block(bloc, ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_assign(?lhs_0, ?rhs_0, ?ann)) {
auto t = demand_full(fcx, e.span, expected,
ann_to_type(ann), adk);
auto lhs_1 = demand_expr(fcx, expected, lhs_0);
auto rhs_1 = demand_expr(fcx, expected, rhs_0);
- e_1 = ast.expr_assign(lhs_1, rhs_1, ast.ann_type(t));
+ e_1 = ast.expr_assign(lhs_1, rhs_1,
+ ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_assign_op(?op, ?lhs_0, ?rhs_0, ?ann)) {
auto t = demand_full(fcx, e.span, expected,
ann_to_type(ann), adk);
auto lhs_1 = demand_expr(fcx, expected, lhs_0);
auto rhs_1 = demand_expr(fcx, expected, rhs_0);
- e_1 = ast.expr_assign_op(op, lhs_1, rhs_1, ast.ann_type(t));
+ e_1 = ast.expr_assign_op(op, lhs_1, rhs_1,
+ ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_field(?lhs, ?rhs, ?ann)) {
auto t = demand_full(fcx, e.span, expected,
ann_to_type(ann), adk);
- e_1 = ast.expr_field(lhs, rhs, ast.ann_type(t));
+ e_1 = ast.expr_field(lhs, rhs, ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_index(?base, ?index, ?ann)) {
auto t = demand_full(fcx, e.span, expected,
ann_to_type(ann), adk);
- e_1 = ast.expr_index(base, index, ast.ann_type(t));
+ e_1 = ast.expr_index(base, index,
+ ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_path(?pth, ?d, ?ann)) {
auto t = demand_full(fcx, e.span, expected,
ann_to_type(ann), adk);
- e_1 = ast.expr_path(pth, d, ast.ann_type(t));
+
+ // Fill in the type parameter substitutions if they weren't
+ // provided by the programmer.
+ auto ty_params_opt;
+ alt (ann) {
+ case (ast.ann_none) {
+ log "demand_expr(): no type annotation for path expr; " +
+ "did you pass it to check_expr() first?";
+ fail;
+ }
+ case (ast.ann_type(_, ?tps_opt)) {
+ alt (tps_opt) {
+ case (none[vec[@ty.t]]) {
+ auto defn = option.get[ast.def](d);
+ alt (ty_params_for_item(fcx.ccx, defn)) {
+ case (none[ty.ty_params_and_ty]) {
+ ty_params_opt = none[vec[@ty.t]];
+ }
+ case (some[ty.ty_params_and_ty](?tpt)) {
+ auto tps = ty.resolve_ty_params(tpt, t);
+ ty_params_opt = some[vec[@ty.t]](tps);
+ }
+ }
+ }
+ case (some[vec[@ty.t]](?tps)) {
+ ty_params_opt = some[vec[@ty.t]](tps);
+ }
+ }
+ }
+ }
+
+ e_1 = ast.expr_path(pth, d, ast.ann_type(t, ty_params_opt));
}
case (ast.expr_ext(?p, ?args, ?body, ?expanded, ?ann)) {
auto t = demand_full(fcx, e.span, expected,
ann_to_type(ann), adk);
- e_1 = ast.expr_ext(p, args, body, expanded, ast.ann_type(t));
+ e_1 = ast.expr_ext(p, args, body, expanded,
+ ast.ann_type(t, none[vec[@ty.t]]));
}
case (ast.expr_fail) { e_1 = e.node; }
case (ast.expr_log(_)) { e_1 = e.node; }
@@ -1192,7 +1414,10 @@ fn writeback_local(&@fn_ctxt fcx, &span sp, @ast.local local)
+ local.ident);
}
auto local_ty = fcx.locals.get(local.id);
- auto local_wb = @rec(ann=ast.ann_type(local_ty) with *local);
+ auto local_wb = @rec(
+ ann=ast.ann_type(local_ty, none[vec[@ty.t]])
+ with *local
+ );
ret @fold.respan[ast.decl_](sp, ast.decl_local(local_wb));
}
@@ -1224,13 +1449,15 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat {
auto new_pat;
alt (pat.node) {
case (ast.pat_wild(_)) {
- new_pat = ast.pat_wild(ast.ann_type(next_ty_var(fcx.ccx)));
+ new_pat = ast.pat_wild(ast.ann_type(next_ty_var(fcx.ccx),
+ none[vec[@ty.t]]));
}
case (ast.pat_lit(?lt, _)) {
- new_pat = ast.pat_lit(lt, ast.ann_type(check_lit(lt)));
+ new_pat = ast.pat_lit(lt, ast.ann_type(check_lit(lt),
+ none[vec[@ty.t]]));
}
case (ast.pat_bind(?id, ?def_id, _)) {
- auto ann = ast.ann_type(next_ty_var(fcx.ccx));
+ auto ann = ast.ann_type(next_ty_var(fcx.ccx), none[vec[@ty.t]]);
new_pat = ast.pat_bind(id, def_id, ann);
}
case (ast.pat_tag(?p, ?subpats, ?vdef_opt, _)) {
@@ -1238,6 +1465,12 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat {
auto t = fcx.ccx.item_types.get(vdef._1);
auto len = _vec.len[ast.ident](p.node.idents);
auto last_id = p.node.idents.(len - 1u);
+
+ auto ty_params = fcx.ccx.item_ty_params.get(vdef._0);
+ auto tag_ty = fcx.ccx.item_types.get(vdef._0);
+ auto tpt = tup(some(ty_params), tag_ty);
+ auto ann = instantiate_path(fcx, p, tpt, pat.span);
+
alt (t.struct) {
// N-ary variants have function types.
case (ty.ty_fn(_, ?args, ?tag_ty)) {
@@ -1247,8 +1480,9 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat {
// TODO: pluralize properly
auto err_msg = "tag type " + last_id + " has " +
_uint.to_str(subpats_len, 10u) +
- " fields, but this pattern has " +
- _uint.to_str(arg_len, 10u) + " fields";
+ " field(s), but this pattern has " +
+ _uint.to_str(arg_len, 10u) +
+ " field(s)";
fcx.ccx.sess.span_err(pat.span, err_msg);
fail; // TODO: recover
@@ -1259,29 +1493,24 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat {
new_subpats += vec(check_pat(fcx, subpat));
}
- auto ann = ast.ann_type(tag_ty);
new_pat = ast.pat_tag(p, new_subpats, vdef_opt, ann);
}
// Nullary variants have tag types.
case (ty.ty_tag(?tid, _)) {
- // TODO: ty params
-
auto subpats_len = _vec.len[@ast.pat](subpats);
if (subpats_len > 0u) {
// TODO: pluralize properly
auto err_msg = "tag type " + last_id +
- " has no fields," +
+ " has no field(s)," +
" but this pattern has " +
_uint.to_str(subpats_len, 10u) +
- " fields";
+ " field(s)";
fcx.ccx.sess.span_err(pat.span, err_msg);
fail; // TODO: recover
}
- let vec[@ty.t] tys = vec(); // FIXME
- auto ann = ast.ann_type(plain_ty(ty.ty_tag(tid, tys)));
new_pat = ast.pat_tag(p, subpats, vdef_opt, ann);
}
}
@@ -1378,9 +1607,9 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
alt (expr.node) {
case (ast.expr_lit(?lit, _)) {
- auto ty = check_lit(lit);
- ret @fold.respan[ast.expr_](expr.span,
- ast.expr_lit(lit, ast.ann_type(ty)));
+ auto typ = check_lit(lit);
+ auto ann = ast.ann_type(typ, none[vec[@ty.t]]);
+ ret @fold.respan[ast.expr_](expr.span, ast.expr_lit(lit, ann));
}
@@ -1406,9 +1635,11 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
case (ast.gt) { t = plain_ty(ty.ty_bool); }
case (_) { /* fall through */ }
}
+
+ auto ann = ast.ann_type(t, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_binary(binop, lhs_1, rhs_1,
- ast.ann_type(t)));
+ ann));
}
@@ -1435,84 +1666,29 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
}
case (_) { oper_t = strip_boxes(oper_t); }
}
+
+ auto ann = ast.ann_type(oper_t, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
- ast.expr_unary(unop, oper_1,
- ast.ann_type(oper_t)));
+ ast.expr_unary(unop, oper_1, ann));
}
case (ast.expr_path(?pth, ?defopt, _)) {
auto t = plain_ty(ty.ty_nil);
check (defopt != none[ast.def]);
- alt (option.get[ast.def](defopt)) {
- case (ast.def_arg(?id)) {
- check (fcx.locals.contains_key(id));
- t = fcx.locals.get(id);
- }
- case (ast.def_local(?id)) {
- alt (fcx.locals.find(id)) {
- case (some[@ty.t](?t1)) { t = t1; }
- case (none[@ty.t]) { t = plain_ty(ty.ty_local(id)); }
- }
- }
- case (ast.def_obj_field(?id)) {
- check (fcx.locals.contains_key(id));
- t = fcx.locals.get(id);
- }
- case (ast.def_fn(?id)) {
- check (fcx.ccx.item_types.contains_key(id));
- t = generalize_ty(fcx.ccx, fcx.ccx.item_types.get(id));
- }
- case (ast.def_native_fn(?id)) {
- check (fcx.ccx.item_types.contains_key(id));
- t = generalize_ty(fcx.ccx, fcx.ccx.item_types.get(id));
- }
- case (ast.def_const(?id)) {
- check (fcx.ccx.item_types.contains_key(id));
- t = fcx.ccx.item_types.get(id);
- }
- case (ast.def_variant(_, ?variant_id)) {
- check (fcx.ccx.item_types.contains_key(variant_id));
- t = generalize_ty(fcx.ccx,
- fcx.ccx.item_types.get(variant_id));
- }
- case (ast.def_binding(?id)) {
- check (fcx.locals.contains_key(id));
- t = fcx.locals.get(id);
- }
- case (ast.def_obj(?id)) {
- check (fcx.ccx.item_types.contains_key(id));
- t = generalize_ty(fcx.ccx, fcx.ccx.item_types.get(id));
- }
-
- case (ast.def_mod(_)) {
- // Hopefully part of a path.
- }
-
- case (_) {
- // FIXME: handle other names.
- fcx.ccx.sess.unimpl("definition variant for: "
- + _str.connect(pth.node.idents, "."));
- fail;
- }
- }
-
- // Substitute type parameters if the user provided some.
- if (_vec.len[@ast.ty](pth.node.types) > 0u) {
- t = substitute_ty_params(fcx.ccx, t, pth.node.types,
- expr.span);
- }
-
+ auto defn = option.get[ast.def](defopt);
+ auto tpt = ty_params_and_ty_for_def(fcx, defn);
+ auto ann = instantiate_path(fcx, pth, tpt, expr.span);
ret @fold.respan[ast.expr_](expr.span,
- ast.expr_path(pth, defopt,
- ast.ann_type(t)));
+ ast.expr_path(pth, defopt, ann));
}
case (ast.expr_ext(?p, ?args, ?body, ?expanded, _)) {
auto exp_ = check_expr(fcx, expanded);
auto t = expr_ty(exp_);
+ auto ann = ast.ann_type(t, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_ext(p, args, body, exp_,
- ast.ann_type(t)));
+ ann));
}
case (ast.expr_fail) {
@@ -1591,7 +1767,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto lhs_1 = demand_expr(fcx, rhs_t0, lhs_0);
auto rhs_1 = demand_expr(fcx, expr_ty(lhs_1), rhs_0);
- auto ann = ast.ann_type(rhs_t0);
+ auto ann = ast.ann_type(rhs_t0, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_assign(lhs_1, rhs_1, ann));
}
@@ -1605,7 +1781,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto lhs_1 = demand_expr(fcx, rhs_t0, lhs_0);
auto rhs_1 = demand_expr(fcx, expr_ty(lhs_1), rhs_0);
- auto ann = ast.ann_type(rhs_t0);
+ auto ann = ast.ann_type(rhs_t0, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_assign_op(op, lhs_1, rhs_1,
ann));
@@ -1635,9 +1811,10 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto thn_1 = demand_block(fcx, elsopt_t, thn_0);
+ auto ann = ast.ann_type(elsopt_t, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
- ast.expr_if(cond_1, thn_1, elsopt_1,
- ast.ann_type(elsopt_t)));
+ ast.expr_if(cond_1, thn_1,
+ elsopt_1, ann));
}
case (ast.expr_for(?decl, ?seq, ?body, _)) {
@@ -1648,7 +1825,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
// FIXME: enforce that the type of the decl is the element type
// of the seq.
- auto ann = ast.ann_type(plain_ty(ty.ty_nil));
+ auto ann = ast.ann_type(plain_ty(ty.ty_nil), none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_for(decl_1, seq_1,
body_1, ann));
@@ -1659,7 +1836,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto seq_1 = check_expr(fcx, seq);
auto body_1 = check_block(fcx, body);
- auto ann = ast.ann_type(plain_ty(ty.ty_nil));
+ auto ann = ast.ann_type(plain_ty(ty.ty_nil), none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_for_each(decl_1, seq_1,
body_1, ann));
@@ -1670,7 +1847,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto cond_1 = demand_expr(fcx, plain_ty(ty.ty_bool), cond_0);
auto body_1 = check_block(fcx, body);
- auto ann = ast.ann_type(plain_ty(ty.ty_nil));
+ auto ann = ast.ann_type(plain_ty(ty.ty_nil), none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_while(cond_1, body_1, ann));
}
@@ -1680,7 +1857,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto cond_1 = demand_expr(fcx, plain_ty(ty.ty_bool), cond_0);
auto body_1 = check_block(fcx, body);
- auto ann = ast.ann_type(block_ty(body_1));
+ auto ann = ast.ann_type(block_ty(body_1), none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_do_while(body_1, cond_1,
ann));
@@ -1730,7 +1907,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto expr_1 = demand_expr(fcx, pattern_ty, expr_0);
- auto ann = ast.ann_type(result_ty);
+ auto ann = ast.ann_type(result_ty, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_alt(expr_1, arms_1, ann));
}
@@ -1740,10 +1917,10 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto ann;
alt (b_0.node.expr) {
case (some[@ast.expr](?expr)) {
- ann = ast.ann_type(expr_ty(expr));
+ ann = ast.ann_type(expr_ty(expr), none[vec[@ty.t]]);
}
case (none[@ast.expr]) {
- ann = ast.ann_type(plain_ty(ty.ty_nil));
+ ann = ast.ann_type(plain_ty(ty.ty_nil), none[vec[@ty.t]]);
}
}
ret @fold.respan[ast.expr_](expr.span,
@@ -1783,9 +1960,10 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
}
auto t_1 = plain_ty(ty.ty_fn(proto_1, arg_tys_1, rt_1));
+ auto ann = ast.ann_type(t_1, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_bind(result._0, result._1,
- ast.ann_type(t_1)));
+ ann));
}
case (ast.expr_call(?f, ?args, _)) {
@@ -1814,9 +1992,10 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
}
}
+ auto ann = ast.ann_type(rt_1, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_call(result._0, args_1,
- ast.ann_type(rt_1)));
+ ann));
}
case (ast.expr_cast(?e, ?t, _)) {
@@ -1831,9 +2010,10 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
+ " as "
+ ty_to_str(t_1));
}
+
+ auto ann = ast.ann_type(t_1, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
- ast.expr_cast(e_1, t,
- ast.ann_type(t_1)));
+ ast.expr_cast(e_1, t, ann));
}
case (ast.expr_vec(?args, _)) {
@@ -1856,7 +2036,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
demand(fcx, expr.span, t, expr_t);
append[@ast.expr](args_1,expr_1);
}
- auto ann = ast.ann_type(plain_ty(ty.ty_vec(t)));
+ auto ann = ast.ann_type(plain_ty(ty.ty_vec(t)), none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_vec(args_1, ann));
}
@@ -1875,14 +2055,21 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
append[@ty.t](elts_t, expr_t);
}
- auto ann = ast.ann_type(plain_ty(ty.ty_tup(elts_t)));
+ auto ann = ast.ann_type(plain_ty(ty.ty_tup(elts_t)),
+ none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_tup(elts_1, ann));
}
case (ast.expr_rec(?fields, ?base, _)) {
- auto base_1 = base;
+ auto base_1;
+ alt (base) {
+ case (none[@ast.expr]) { base_1 = none[@ast.expr]; }
+ case (some[@ast.expr](?b_0)) {
+ base_1 = some[@ast.expr](check_expr(fcx, b_0));
+ }
+ }
let vec[ast.field] fields_1 = vec();
let vec[field] fields_t = vec();
@@ -1901,7 +2088,8 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
alt (base) {
case (none[@ast.expr]) {
- ann = ast.ann_type(plain_ty(ty.ty_rec(fields_t)));
+ ann = ast.ann_type(plain_ty(ty.ty_rec(fields_t)),
+ none[vec[@ty.t]]);
}
case (some[@ast.expr](?bexpr)) {
@@ -1921,7 +2109,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
}
}
- ann = ast.ann_type(bexpr_t);
+ ann = ast.ann_type(bexpr_t, none[vec[@ty.t]]);
for (ty.field f in fields_t) {
auto found = false;
@@ -1956,7 +2144,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
fcx.ccx.sess.span_err(expr.span,
"bad index on tuple");
}
- auto ann = ast.ann_type(args.(ix));
+ auto ann = ast.ann_type(args.(ix), none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_field(base_1,
field,
@@ -1970,7 +2158,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
fcx.ccx.sess.span_err(expr.span,
"bad index on record");
}
- auto ann = ast.ann_type(fields.(ix).ty);
+ auto ann = ast.ann_type(fields.(ix).ty, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_field(base_1,
field,
@@ -1987,7 +2175,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
auto meth = methods.(ix);
auto t = plain_ty(ty.ty_fn(meth.proto,
meth.inputs, meth.output));
- auto ann = ast.ann_type(t);
+ auto ann = ast.ann_type(t, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_field(base_1,
field,
@@ -2017,7 +2205,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
"non-integral type of vec index: "
+ ty_to_str(idx_t));
}
- auto ann = ast.ann_type(t);
+ auto ann = ast.ann_type(t, none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_index(base_1,
idx_1,
@@ -2031,7 +2219,7 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
+ ty_to_str(idx_t));
}
auto t = ty.ty_machine(common.ty_u8);
- auto ann = ast.ann_type(plain_ty(t));
+ auto ann = ast.ann_type(plain_ty(t), none[vec[@ty.t]]);
ret @fold.respan[ast.expr_](expr.span,
ast.expr_index(base_1,
idx_1,
@@ -2206,7 +2394,7 @@ fn check_item_fn(&@crate_ctxt ccx, &span sp, ast.ident ident, &ast._fn f,
auto output_ty = ast_ty_to_ty_crate(ccx, f.decl.output);
auto fn_sty = ty.ty_fn(f.proto, inputs, output_ty);
- auto fn_ann = ast.ann_type(plain_ty(fn_sty));
+ auto fn_ann = ast.ann_type(plain_ty(fn_sty), none[vec[@ty.t]]);
auto item = ast.item_fn(ident, f, ty_params, id, fn_ann);
ret @fold.respan[ast.item_](sp, item);
@@ -2231,6 +2419,7 @@ fn check_crate(session.session sess, @ast.crate crate) -> @ast.crate {
auto ccx = @rec(sess=sess,
item_types=result._1,
item_items=result._2,
+ item_ty_params=result._3,
obj_fields=fields,
mutable next_var_id=0);
diff --git a/src/comp/pretty/pp.rs b/src/comp/pretty/pp.rs
index 43a9220f..d3145180 100644
--- a/src/comp/pretty/pp.rs
+++ b/src/comp/pretty/pp.rs
@@ -17,17 +17,19 @@ type context = rec(contexttype tp, uint indent);
type ps = @rec(mutable vec[context] context,
uint width,
+ io.writer out,
mutable vec[token] buffered,
mutable uint scandepth,
mutable uint bufferedcol,
mutable uint col,
mutable bool start_of_line);
-fn mkstate(uint width) -> ps {
+fn mkstate(io.writer out, uint width) -> ps {
let vec[context] stack = vec(rec(tp=cx_v, indent=0u));
let vec[token] buff = vec();
ret @rec(mutable context=stack,
width=width,
+ out=out,
mutable buffered=buff,
mutable scandepth=0u,
mutable bufferedcol=0u,
@@ -46,10 +48,22 @@ impure fn pop_context(ps p) {
}
impure fn add_token(ps p, token tok) {
- if (p.scandepth == 0u) {do_token(p, tok);}
+ if (p.width == 0u) {direct_token(p, tok);}
+ else if (p.scandepth == 0u) {do_token(p, tok);}
else {buffer_token(p, tok);}
}
+impure fn direct_token(ps p, token tok) {
+ alt (tok) {
+ case (brk(?sz)) {
+ while (sz > 0u) {p.out.write_str(" "); sz -= 1u;}
+ }
+ case (word(?w)) {p.out.write_str(w);}
+ case (cword(?w)) {p.out.write_str(w);}
+ case (_) {}
+ }
+}
+
impure fn buffer_token(ps p, token tok) {
p.buffered += vec(tok);
p.bufferedcol += token_size(tok);
@@ -101,14 +115,13 @@ impure fn finish_block_scan(ps p, contexttype tp) {
impure fn finish_break_scan(ps p) {
if (p.bufferedcol > p.width) {
- write_str("\n");
- p.col = 0u;
+ line_break(p);
}
else {
auto width;
alt (p.buffered.(0)) {case(brk(?w)) {width = w;}}
auto i = 0u;
- while (i < width) {write_str(" "); i+=1u;}
+ while (i < width) {p.out.write_str(" "); i+=1u;}
p.col += width;
}
p.scandepth = 0u;
@@ -142,20 +155,18 @@ impure fn do_token(ps p, token tok) {
start_scan(p, tok);
}
case (cx_v) {
- write_str("\n");
- p.col = 0u;
- p.start_of_line = true;
+ line_break(p);
}
}
}
case (word(?w)) {
before_print(p, false);
- write_str(w);
+ p.out.write_str(w);
p.col += _str.byte_len(w); // TODO char_len
}
case (cword(?w)) {
before_print(p, true);
- write_str(w);
+ p.out.write_str(w);
p.col += _str.byte_len(w); // TODO char_len
}
case (open(?tp, ?indent)) {
@@ -170,6 +181,12 @@ impure fn do_token(ps p, token tok) {
}
}
+impure fn line_break(ps p) {
+ p.out.write_str("\n");
+ p.col = 0u;
+ p.start_of_line = true;
+}
+
impure fn before_print(ps p, bool closing) {
if (p.start_of_line) {
p.start_of_line = false;
@@ -177,14 +194,10 @@ impure fn before_print(ps p, bool closing) {
if (closing) {ind = base_indent(p);}
else {ind = cur_context(p).indent;}
p.col = ind;
- while (ind > 0u) {write_str(" "); ind -= 1u;}
+ while (ind > 0u) {p.out.write_str(" "); ind -= 1u;}
}
}
-fn write_str(str s) {
- io.writefd(1, _str.bytes(s));
-}
-
fn token_size(token tok) -> uint {
alt (tok) {
case (brk(?sz)) {ret sz;}
diff --git a/src/comp/pretty/pprust.rs b/src/comp/pretty/pprust.rs
index cab778f1..2b64b8e4 100644
--- a/src/comp/pretty/pprust.rs
+++ b/src/comp/pretty/pprust.rs
@@ -11,13 +11,19 @@ import foo = std.io;
const uint indent_unit = 2u;
const int as_prec = 5;
-impure fn print_ast(ast._mod _mod) {
- auto s = pp.mkstate(80u);
+impure fn print_ast(ast._mod _mod, std.io.writer out) {
+ auto s = pp.mkstate(out, 80u);
for (@ast.view_item vitem in _mod.view_items) {print_view_item(s, vitem);}
line(s);
for (@ast.item item in _mod.items) {print_item(s, item);}
}
+fn ty_to_str(&@ast.ty ty) -> str {
+ auto writer = std.io.string_writer();
+ print_type(pp.mkstate(writer.get_writer(), 0u), ty);
+ ret writer.get_str();
+}
+
impure fn hbox(ps s) {
pp.hbox(s, indent_unit);
}
@@ -85,24 +91,21 @@ impure fn print_type(ps s, @ast.ty ty) {
commasep[ast.ty_field](s, fields, f);
pclose(s);
}
- case (ast.ty_fn(?proto,?inputs,?output)) {
- if (proto == ast.proto_fn) {wrd(s, "fn");}
- else {wrd(s, "iter");}
- popen(s);
- impure fn print_arg(ps s, ast.ty_arg input) {
- if (middle.ty.mode_is_alias(input.mode)) {wrd(s, "&");}
- print_type(s, input.ty);
- }
- auto f = print_arg;
- commasep[ast.ty_arg](s, inputs, f);
- pclose(s);
- if (output.node != ast.ty_nil) {
- space(s);
+ case (ast.ty_obj(?methods)) {
+ wrd1(s, "obj");
+ bopen(s);
+ for (ast.ty_method m in methods) {
hbox(s);
- wrd1(s, "->");
- print_type(s, output);
+ print_ty_fn(s, m.proto, option.some[str](m.ident),
+ m.inputs, m.output);
+ wrd(s, ";");
end(s);
+ line(s);
}
+ bclose(s);
+ }
+ case (ast.ty_fn(?proto,?inputs,?output)) {
+ print_ty_fn(s, proto, option.none[str], inputs, output);
}
case (ast.ty_path(?path,_)) {
print_path(s, path);
@@ -376,6 +379,7 @@ impure fn print_expr(ps s, @ast.expr expr) {
wrd1(s, "else");
print_expr(s, _else);
}
+ case (_) { /* fall through */ }
}
}
case (ast.expr_while(?test,?block,_)) {
@@ -503,8 +507,16 @@ impure fn print_expr(ps s, @ast.expr expr) {
wrd1(s, "check");
print_expr(s, expr);
}
- case (_) {wrd(s, "X");}
- // TODO expr_ext(path, vec[@expr], option.t[@expr], @expr, ann);
+ case (ast.expr_ext(?path, ?args, ?body, _, _)) {
+ wrd(s, "#");
+ print_path(s, path);
+ if (_vec.len[@ast.expr](args) > 0u) {
+ popen(s);
+ commasep[@ast.expr](s, args, pe);
+ pclose(s);
+ }
+ // TODO: extension 'body'
+ }
}
end(s);
}
@@ -706,3 +718,28 @@ fn escape_str(str st, char to_escape) -> str {
impure fn print_string(ps s, str st) {
wrd(s, "\""); wrd(s, escape_str(st, '"')); wrd(s, "\"");
}
+
+impure fn print_ty_fn(ps s, ast.proto proto, option.t[str] id,
+ vec[ast.ty_arg] inputs, @ast.ty output) {
+ if (proto == ast.proto_fn) {wrd(s, "fn");}
+ else {wrd(s, "iter");}
+ alt (id) {
+ case (option.some[str](?id)) {space(s); wrd(s, id);}
+ case (_) {}
+ }
+ popen(s);
+ impure fn print_arg(ps s, ast.ty_arg input) {
+ if (middle.ty.mode_is_alias(input.mode)) {wrd(s, "&");}
+ print_type(s, input.ty);
+ }
+ auto f = print_arg;
+ commasep[ast.ty_arg](s, inputs, f);
+ pclose(s);
+ if (output.node != ast.ty_nil) {
+ space(s);
+ hbox(s);
+ wrd1(s, "->");
+ print_type(s, output);
+ end(s);
+ }
+}
diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc
index e4833409..006aca62 100644
--- a/src/comp/rustc.rc
+++ b/src/comp/rustc.rc
@@ -8,13 +8,13 @@ mod front {
mod extfmt;
mod lexer;
mod parser;
- mod pretty;
mod token;
mod eval;
}
mod middle {
mod fold;
+ mod metadata;
mod resolve;
mod trans;
mod ty;
@@ -41,10 +41,12 @@ mod util {
}
auth driver.rustc.main = impure;
+auth middle.metadata = unsafe;
auth middle.trans = unsafe;
auth middle.trans.copy_args_to_allocas = impure;
auth middle.trans.trans_block = impure;
auth lib.llvm = unsafe;
+auth pretty.pprust = impure;
mod lib {
alt (target_os) {
diff --git a/src/comp/util/common.rs b/src/comp/util/common.rs
index 071acea2..63ec2c69 100644
--- a/src/comp/util/common.rs
+++ b/src/comp/util/common.rs
@@ -46,6 +46,10 @@ fn new_str_hash[V]() -> std.map.hashmap[str,V] {
ret std.map.mk_hashmap[str,V](hasher, eqer);
}
+fn def_eq(&ast.def_id a, &ast.def_id b) -> bool {
+ ret a._0 == b._0 && a._1 == b._1;
+}
+
fn new_def_hash[V]() -> std.map.hashmap[ast.def_id,V] {
fn hash(&ast.def_id d) -> uint {
@@ -55,12 +59,8 @@ fn new_def_hash[V]() -> std.map.hashmap[ast.def_id,V] {
ret u;
}
- fn eq(&ast.def_id a, &ast.def_id b) -> bool {
- ret a._0 == b._0 && a._1 == b._1;
- }
-
let std.map.hashfn[ast.def_id] hasher = hash;
- let std.map.eqfn[ast.def_id] eqer = eq;
+ let std.map.eqfn[ast.def_id] eqer = def_eq;
ret std.map.mk_hashmap[ast.def_id,V](hasher, eqer);
}
diff --git a/src/lib/_int.rs b/src/lib/_int.rs
index 38e161bc..ee660f01 100644
--- a/src/lib/_int.rs
+++ b/src/lib/_int.rs
@@ -1,4 +1,3 @@
-import std.sys;
fn add(int x, int y) -> int { ret x + y; }
fn sub(int x, int y) -> int { ret x - y; }
diff --git a/src/lib/_str.rs b/src/lib/_str.rs
index 0e0e7650..3f453349 100644
--- a/src/lib/_str.rs
+++ b/src/lib/_str.rs
@@ -1,6 +1,6 @@
import rustrt.sbuf;
-import std._vec.rustrt.vbuf;
+import _vec.rustrt.vbuf;
native "rust" mod rustrt {
type sbuf;
diff --git a/src/lib/_uint.rs b/src/lib/_uint.rs
index 79b5fa24..ceee9c77 100644
--- a/src/lib/_uint.rs
+++ b/src/lib/_uint.rs
@@ -1,4 +1,3 @@
-import std.sys;
fn add(uint x, uint y) -> uint { ret x + y; }
fn sub(uint x, uint y) -> uint { ret x - y; }
diff --git a/src/lib/_vec.rs b/src/lib/_vec.rs
index 2ffe8bad..680c8884 100644
--- a/src/lib/_vec.rs
+++ b/src/lib/_vec.rs
@@ -1,5 +1,4 @@
import vbuf = rustrt.vbuf;
-import std.option;
type operator2[T,U,V] = fn(&T, &U) -> V;
diff --git a/src/lib/bitv.rs b/src/lib/bitv.rs
index adb3dc86..2322c693 100644
--- a/src/lib/bitv.rs
+++ b/src/lib/bitv.rs
@@ -1,7 +1,3 @@
-import std._uint;
-import std._int;
-import std._vec;
-
// FIXME: With recursive object types, we could implement binary methods like
// union, intersection, and difference. At that point, we could write
// an optimizing version of this module that produces a different obj
diff --git a/src/lib/dbg.rs b/src/lib/dbg.rs
index 774052dc..b63f363e 100644
--- a/src/lib/dbg.rs
+++ b/src/lib/dbg.rs
@@ -5,8 +5,6 @@
* logging.
*/
-import std._vec;
-
// FIXME: handle 64-bit case.
const uint const_refcount = 0x7bad_face_u;
diff --git a/src/lib/deque.rs b/src/lib/deque.rs
index 16023457..776f82e9 100644
--- a/src/lib/deque.rs
+++ b/src/lib/deque.rs
@@ -2,10 +2,6 @@
* A deque, for fun. Untested as of yet. Likely buggy.
*/
-import std.option;
-import std._vec;
-import std._int;
-
type t[T] = obj {
fn size() -> uint;
diff --git a/src/lib/io.rs b/src/lib/io.rs
index 0c4eb39e..34c4a98d 100644
--- a/src/lib/io.rs
+++ b/src/lib/io.rs
@@ -1,7 +1,4 @@
-import std.os.libc;
-import std._str;
-import std._vec;
-
+import os.libc;
type stdio_reader = state obj {
fn getc() -> int;
@@ -91,35 +88,29 @@ tag fileflag {
truncate;
}
-fn writefd(int fd, vec[u8] v) {
- auto len = _vec.len[u8](v);
- auto count = 0u;
- auto vbuf;
- while (count < len) {
- vbuf = _vec.buf_off[u8](v, count);
- auto nout = os.libc.write(fd, vbuf, len);
- if (nout < 0) {
- log "error dumping buffer";
- log sys.rustrt.last_os_error();
- fail;
+state obj fd_buf_writer(int fd, bool must_close) {
+ fn write(vec[u8] v) {
+ auto len = _vec.len[u8](v);
+ auto count = 0u;
+ auto vbuf;
+ while (count < len) {
+ vbuf = _vec.buf_off[u8](v, count);
+ auto nout = os.libc.write(fd, vbuf, len);
+ if (nout < 0) {
+ log "error dumping buffer";
+ log sys.rustrt.last_os_error();
+ fail;
+ }
+ count += nout as uint;
}
- count += nout as uint;
}
-}
-
-fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer {
-
- state obj fd_buf_writer(int fd) {
- fn write(vec[u8] v) {
- writefd(fd, v);
- }
-
- drop {
- os.libc.close(fd);
- }
+ drop {
+ if (must_close) {os.libc.close(fd);}
}
+}
+fn file_buf_writer(str path, vec[fileflag] flags) -> buf_writer {
let int fflags =
os.libc_constants.O_WRONLY() |
os.libc_constants.O_BINARY();
@@ -142,26 +133,58 @@ fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer {
log sys.rustrt.last_os_error();
fail;
}
- ret fd_buf_writer(fd);
+ ret fd_buf_writer(fd, true);
}
type writer =
state obj {
- fn write_str(str s);
- fn write_int(int n);
- fn write_uint(uint n);
+ impure fn write_str(str s);
+ impure fn write_int(int n);
+ impure fn write_uint(uint n);
};
-fn file_writer(str path,
- vec[fileflag] flags)
- -> writer
-{
- state obj fw(buf_writer out) {
- fn write_str(str s) { out.write(_str.bytes(s)); }
- fn write_int(int n) { out.write(_str.bytes(_int.to_str(n, 10u))); }
- fn write_uint(uint n) { out.write(_str.bytes(_uint.to_str(n, 10u))); }
+state obj new_writer(buf_writer out) {
+ impure fn write_str(str s) {
+ out.write(_str.bytes(s));
+ }
+ impure fn write_int(int n) {
+ out.write(_str.bytes(_int.to_str(n, 10u)));
+ }
+ impure fn write_uint(uint n) {
+ out.write(_str.bytes(_uint.to_str(n, 10u)));
+ }
+}
+
+fn file_writer(str path, vec[fileflag] flags) -> writer {
+ ret new_writer(file_buf_writer(path, flags));
+}
+
+// FIXME it would be great if this could be a const named stdout
+fn stdout_writer() -> writer {
+ ret new_writer(fd_buf_writer(1, false));
+}
+
+type str_writer =
+ state obj {
+ fn get_writer() -> writer;
+ fn get_str() -> str;
+ };
+
+type str_buf = @rec(mutable str buf);
+
+// TODO awkward! it's not possible to implement a writer with an extra method
+fn string_writer() -> str_writer {
+ auto buf = @rec(mutable buf = "");
+ state obj str_writer_writer(str_buf buf) {
+ impure fn write_str(str s) { buf.buf += s; }
+ impure fn write_int(int n) { buf.buf += _int.to_str(n, 10u); }
+ impure fn write_uint(uint n) { buf.buf += _uint.to_str(n, 10u); }
+ }
+ state obj str_writer_wrap(writer wr, str_buf buf) {
+ fn get_writer() -> writer {ret wr;}
+ fn get_str() -> str {ret buf.buf;}
}
- ret fw(new_buf_writer(path, flags));
+ ret str_writer_wrap(str_writer_writer(buf), buf);
}
//
diff --git a/src/lib/list.rs b/src/lib/list.rs
index c4661940..58c2cded 100644
--- a/src/lib/list.rs
+++ b/src/lib/list.rs
@@ -1,5 +1,3 @@
-
-import std.option;
import option.some;
import option.none;
diff --git a/src/lib/map.rs b/src/lib/map.rs
index 7f760b65..29e9ba5d 100644
--- a/src/lib/map.rs
+++ b/src/lib/map.rs
@@ -3,12 +3,6 @@
* use, but useful as a stress test for rustboot.
*/
-import std._int;
-import std.sys;
-import std.option;
-import std._vec;
-
-
type hashfn[K] = fn(&K) -> uint;
type eqfn[K] = fn(&K, &K) -> bool;
diff --git a/src/lib/sha1.rs b/src/lib/sha1.rs
index 2a6b74d4..a57ea894 100644
--- a/src/lib/sha1.rs
+++ b/src/lib/sha1.rs
@@ -4,9 +4,6 @@
* point this will want to be rewritten.
*/
-import std._vec;
-import std._str;
-
export sha1;
export mk_sha1;
diff --git a/src/llvmext/Object.cpp b/src/llvmext/Object.cpp
new file mode 100644
index 00000000..f390870f
--- /dev/null
+++ b/src/llvmext/Object.cpp
@@ -0,0 +1,55 @@
+//===- Object.cpp - C bindings to the object file library--------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the C bindings to the file-format-independent object
+// library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/ObjectFile.h"
+#include "llvm-c/Object.h"
+
+using namespace llvm;
+using namespace object;
+
+LLVMObjectFileRef LLVMCreateObjectFile(const char *ObjectPath) {
+ StringRef SR(ObjectPath);
+ return wrap(ObjectFile::createObjectFile(SR));
+}
+
+void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) {
+ delete unwrap(ObjectFile);
+}
+
+LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile) {
+ ObjectFile::section_iterator SI = unwrap(ObjectFile)->begin_sections();
+ return wrap(new ObjectFile::section_iterator(SI));
+}
+
+void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) {
+ delete unwrap(SI);
+}
+
+void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) {
+ ObjectFile::section_iterator UnwrappedSI = *unwrap(SI);
+ ++UnwrappedSI;
+}
+
+const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) {
+ return (*unwrap(SI))->getName().data();
+}
+
+uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) {
+ return (*unwrap(SI))->getSize();
+}
+
+const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) {
+ return (*unwrap(SI))->getContents().data();
+}
+
diff --git a/src/llvmext/README b/src/llvmext/README
new file mode 100644
index 00000000..31495f22
--- /dev/null
+++ b/src/llvmext/README
@@ -0,0 +1,3 @@
+This directory currently contains some LLVM support code. This will generally
+be sent upstream to LLVM in time; for now it lives here.
+
diff --git a/src/llvmext/include/llvm-c/Object.h b/src/llvmext/include/llvm-c/Object.h
new file mode 100644
index 00000000..a65a2352
--- /dev/null
+++ b/src/llvmext/include/llvm-c/Object.h
@@ -0,0 +1,75 @@
+/*===-- llvm-c/Object.h - Object Lib C Iface --------------------*- C++ -*-===*/
+/* */
+/* The LLVM Compiler Infrastructure */
+/* */
+/* This file is distributed under the University of Illinois Open Source */
+/* License. See LICENSE.TXT for details. */
+/* */
+/*===----------------------------------------------------------------------===*/
+/* */
+/* This header declares the C interface to libLLVMObject.a, which */
+/* implements object file reading and writing. */
+/* */
+/* Many exotic languages can interoperate with C code but have a harder time */
+/* with C++ due to name mangling. So in addition to C, this interface enables */
+/* tools written in such languages. */
+/* */
+/*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_C_OBJECT_H
+#define LLVM_C_OBJECT_H
+
+#include "llvm-c/Core.h"
+#include "llvm/Config/llvm-config.h"
+
+#ifdef __cplusplus
+#include "llvm/Object/ObjectFile.h"
+
+extern "C" {
+#endif
+
+
+typedef struct LLVMOpaqueObjectFile *LLVMObjectFileRef;
+
+typedef struct LLVMOpaqueSectionIterator *LLVMSectionIteratorRef;
+
+LLVMObjectFileRef LLVMCreateObjectFile(const char *ObjectPath);
+void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile);
+
+LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile);
+void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI);
+void LLVMMoveToNextSection(LLVMSectionIteratorRef SI);
+const char *LLVMGetSectionName(LLVMSectionIteratorRef SI);
+uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI);
+const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI);
+
+
+#ifdef __cplusplus
+}
+
+namespace llvm {
+ namespace object {
+ inline ObjectFile *unwrap(LLVMObjectFileRef OF) {
+ return reinterpret_cast<ObjectFile*>(OF);
+ }
+
+ inline LLVMObjectFileRef wrap(const ObjectFile *OF) {
+ return reinterpret_cast<LLVMObjectFileRef>(const_cast<ObjectFile*>(OF));
+ }
+
+ inline ObjectFile::section_iterator *unwrap(LLVMSectionIteratorRef SI) {
+ return reinterpret_cast<ObjectFile::section_iterator*>(SI);
+ }
+
+ inline LLVMSectionIteratorRef
+ wrap(const ObjectFile::section_iterator *SI) {
+ return reinterpret_cast<LLVMSectionIteratorRef>
+ (const_cast<ObjectFile::section_iterator*>(SI));
+ }
+ }
+}
+
+#endif /* defined(__cplusplus) */
+
+#endif
+
diff --git a/src/test/run-pass/box-compare.rs b/src/test/run-pass/box-compare.rs
new file mode 100644
index 00000000..5115d510
--- /dev/null
+++ b/src/test/run-pass/box-compare.rs
@@ -0,0 +1,5 @@
+fn main() {
+ check (@1 < @3);
+ check (@@"hello " > @@"hello");
+ check (@@@"hello" != @@@"there");
+} \ No newline at end of file
diff --git a/src/test/run-pass/generic-bind-2.rs b/src/test/run-pass/generic-bind-2.rs
new file mode 100644
index 00000000..95a8cab4
--- /dev/null
+++ b/src/test/run-pass/generic-bind-2.rs
@@ -0,0 +1,10 @@
+fn id[T](&T t) -> T {
+ ret t;
+}
+
+fn main() {
+ auto t = tup(1,2,3,4,5,6,7);
+ check (t._5 == 6);
+ auto f0 = bind id[tup(int,int,int,int,int,int,int)](t);
+ check (f0()._5 == 6);
+}
diff --git a/src/test/run-pass/generic-bind.rs b/src/test/run-pass/generic-bind.rs
index 61085eb5..ef1275e3 100644
--- a/src/test/run-pass/generic-bind.rs
+++ b/src/test/run-pass/generic-bind.rs
@@ -3,6 +3,8 @@ fn id[T](&T t) -> T {
}
fn main() {
- auto f = bind id[int](_);
- check (f(10) == 10);
+ auto t = tup(1,2,3,4,5,6,7);
+ check (t._5 == 6);
+ auto f1 = bind id[tup(int,int,int,int,int,int,int)](_);
+ check (f1(t)._5 == 6);
}
diff --git a/src/test/run-pass/generic-tag-alt.rs b/src/test/run-pass/generic-tag-alt.rs
index 4f04e729..9b19eec7 100644
--- a/src/test/run-pass/generic-tag-alt.rs
+++ b/src/test/run-pass/generic-tag-alt.rs
@@ -2,7 +2,7 @@ tag foo[T] {
arm(T);
}
-fn altfoo[T](foo[T] f) {
+fn altfoo[T](&foo[T] f) {
auto hit = false;
alt (f) {
case (arm[T](?x)) {
diff --git a/src/test/run-pass/generic-tag-local.rs b/src/test/run-pass/generic-tag-local.rs
new file mode 100644
index 00000000..63e2e195
--- /dev/null
+++ b/src/test/run-pass/generic-tag-local.rs
@@ -0,0 +1,8 @@
+tag clam[T] {
+ a(T);
+}
+
+fn main() {
+ auto c = a(3);
+}
+
diff --git a/src/test/run-pass/leak-tag-copy.rs b/src/test/run-pass/leak-tag-copy.rs
new file mode 100644
index 00000000..25d87c6e
--- /dev/null
+++ b/src/test/run-pass/leak-tag-copy.rs
@@ -0,0 +1,9 @@
+tag t {
+ a;
+ b(@int);
+}
+
+fn main() {
+ auto x = b(@10);
+ x = a;
+} \ No newline at end of file
diff --git a/src/test/run-pass/seq-compare.rs b/src/test/run-pass/seq-compare.rs
new file mode 100644
index 00000000..b3fe5701
--- /dev/null
+++ b/src/test/run-pass/seq-compare.rs
@@ -0,0 +1,15 @@
+fn main() {
+ check ("hello" < "hellr");
+ check ("hello " > "hello");
+ check ("hello" != "there");
+
+ check (vec(1,2,3,4) > vec(1,2,3));
+ check (vec(1,2,3) < vec(1,2,3,4));
+ check (vec(1,2,4,4) > vec(1,2,3,4));
+ check (vec(1,2,3,4) < vec(1,2,4,4));
+ check (vec(1,2,3) <= vec(1,2,3));
+ check (vec(1,2,3) <= vec(1,2,3,3));
+ check (vec(1,2,3,4) > vec(1,2,3));
+ check (vec(1,2,3) == vec(1,2,3));
+ check (vec(1,2,3) != vec(1,1,3));
+} \ No newline at end of file
diff --git a/src/test/run-pass/simple-generic-alt.rs b/src/test/run-pass/simple-generic-alt.rs
new file mode 100644
index 00000000..85db5c7c
--- /dev/null
+++ b/src/test/run-pass/simple-generic-alt.rs
@@ -0,0 +1,11 @@
+tag clam[T] {
+ a(T);
+}
+
+fn main() {
+ auto c = a(2);
+ alt (c) {
+ case (a[int](_)) {}
+ }
+}
+
diff --git a/src/test/run-pass/simple-generic-tag.rs b/src/test/run-pass/simple-generic-tag.rs
new file mode 100644
index 00000000..ba6a3242
--- /dev/null
+++ b/src/test/run-pass/simple-generic-tag.rs
@@ -0,0 +1,7 @@
+tag clam[T] {
+ a(T);
+}
+
+fn main() {
+}
+