Permalink
Browse files

Populate tree.

  • Loading branch information...
1 parent c01efc6 commit d6b7c96c3eb29b9244ece0c046d3f372ff432d04 @graydon graydon committed Jun 24, 2010
Sorry, we could not display the entire diff because it was too big.
View
2 .gitignore
@@ -1,4 +1,6 @@
*~
+*.x86
+*.llvm
*.out
*.exe
*.orig
View
9 AUTHORS.txt
@@ -1,7 +1,12 @@
-Rust authors:
+Initial author, project lead, target of blame:
Graydon Hoare <graydon@mozilla.com>
+
+Other authors:
+
Andreas Gal <gal@mozilla.com>
+Brendan Eich <brendan@mozilla.org>
Dave Herman <dherman@mozilla.com>
+Michael Bebenita <mbebenita@mozilla.com>
Patrick Walton <pwalton@mozilla.com>
-Brendan Eich <brendan@mozilla.com>
+Roy Frostig <rfrostig@mozilla.com>
View
32 LICENSE.txt
@@ -53,7 +53,8 @@ The following third party packages are included:
All rights reserved.
Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
+ modification, are permitted provided that the following conditions are
+ met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
@@ -71,9 +72,10 @@ The following third party packages are included:
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-* Two header files that are part of the Valgrind package. These files are found
- at src/rt/valgrind.h and src/rt/memcheck.h, within this distribution. These
- files are redistributed under the following terms, as noted in them:
+* Two header files that are part of the Valgrind package. These files are
+ found at src/rt/valgrind.h and src/rt/memcheck.h, within this
+ distribution. These files are redistributed under the following terms, as
+ noted in them:
for src/rt/valgrind.h:
@@ -158,20 +160,20 @@ well as the collective work itslf, is distributed under the following terms:
Copyright (c) 2006-2010 Graydon Hoare
Copyright (c) 2009-2010 Mozilla Foundation
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
View
5 doc/Makefile
@@ -5,7 +5,8 @@ all: rust.pdf rust.html
texi2pdf $<
%.html: %.texi
- makeinfo --html --force --no-split --output=$@ $<
+ makeinfo --html --ifhtml --force --no-split --output=$@ $<
clean:
- rm -f rust.aux rust.cp rust.fn rust.ky rust.log rust.pdf rust.html rust.pg rust.toc rust.tp rust.vr
+ rm -f rust.aux rust.cp rust.fn rust.ky rust.log rust.pdf \
+ rust.html rust.pg rust.toc rust.tp rust.vr
View
3,244 doc/rust.texi
3,244 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
391 src/Makefile
@@ -19,27 +19,29 @@ endif
CFG_INFO := $(info cfg: building on $(CFG_OSTYPE) $(CFG_CPUTYPE))
-CFG_GCC_COMPILE_FLAGS :=
+CFG_GCC_CFLAGS :=
CFG_GCC_LINK_FLAGS :=
CFG_VALGRIND :=
CFG_LLVM_CONFIG := llvm-config
-CFG_BOOT_FLAGS :=
+CFG_BOOT_FLAGS := $(FLAGS)
ifeq ($(CFG_OSTYPE), Linux)
CFG_RUNTIME := librustrt.so
CFG_STDLIB := libstd.so
- CFG_GCC_COMPILE_FLAGS += -fPIC
+ CFG_GCC_CFLAGS += -fPIC
CFG_GCC_LINK_FLAGS += -shared -fPIC -ldl -lpthread
ifeq ($(CFG_CPUTYPE), x86_64)
- CFG_GCC_COMPILE_FLAGS += -m32
+ CFG_GCC_CFLAGS += -m32
CFG_GCC_LINK_FLAGS += -m32
endif
CFG_NATIVE := 1
CFG_UNIXY := 1
CFG_VALGRIND := $(shell which valgrind)
ifdef CFG_VALGRIND
- CFG_VALGRIND += --run-libc-freeres=no --leak-check=full --quiet --vex-iropt-level=0
+ CFG_VALGRIND += --leak-check=full \
+ --quiet --vex-iropt-level=0 \
+ --suppressions=etc/x86.supp
endif
endif
@@ -52,7 +54,7 @@ ifeq ($(CFG_OSTYPE), Darwin)
# "on an i386" when the whole userspace is 64-bit and the compiler
# emits 64-bit binaries by default. So we just force -m32 here. Smarter
# approaches welcome!
- CFG_GCC_COMPILE_FLAGS += -m32
+ CFG_GCC_CFLAGS += -m32
CFG_GCC_LINK_FLAGS += -m32
endif
@@ -73,7 +75,7 @@ ifdef CFG_WINDOWSY
CFG_EXE_SUFFIX := .exe
CFG_BOOT := ./rustboot.exe
CFG_COMPILER := ./rustc.exe
- CFG_GCC_COMPILE_FLAGS += -march=i686
+ CFG_GCC_CFLAGS += -march=i686
CFG_GCC_LINK_FLAGS += -shared -fPIC
CFG_RUN_TARG = $(1)
# FIXME: support msvc at some point
@@ -99,22 +101,22 @@ ifdef CFG_UNIXY
endif
CFG_OBJ_SUFFIX := .o
CFG_EXE_SUFFIX := .exe
- CFG_GCC_COMPILE_FLAGS :=
+ CFG_GCC_CFLAGS :=
CFG_GCC_LINK_FLAGS := -shared
ifeq ($(CFG_CPUTYPE), x86_64)
- CFG_GCC_COMPILE_FLAGS += -m32
+ CFG_GCC_CFLAGS += -m32
CFG_GCC_LINK_FLAGS += -m32
endif
endif
endif
ifdef CFG_GCC
CFG_INFO := $(info cfg: using gcc)
- CFG_GCC_COMPILE_FLAGS += -Wall -Werror -fno-rtti -fno-exceptions -g
+ CFG_GCC_CFLAGS += -Wall -Werror -fno-rtti -fno-exceptions -g
CFG_GCC_LINK_FLAGS += -g
- CFG_COMPILE_C = $(CFG_GCC_CROSS)g++ $(CFG_GCC_COMPILE_FLAGS) -c -o $(1) $(2)
+ CFG_COMPILE_C = $(CFG_GCC_CROSS)g++ $(CFG_GCC_CFLAGS) -c -o $(1) $(2)
CFG_LINK_C = $(CFG_GCC_CROSS)g++ $(CFG_GCC_LINK_FLAGS) -o $(1)
- CFG_DEPEND_C = $(CFG_GCC_CROSS)g++ $(CFG_GCC_COMPILE_FLAGS) -MT "$(1)" -MM $(2)
+ CFG_DEPEND_C = $(CFG_GCC_CROSS)g++ $(CFG_GCC_CFLAGS) -MT "$(1)" -MM $(2)
else
CFG_ERR := $(error please try on a system with gcc)
endif
@@ -153,19 +155,21 @@ ifneq ($(CFG_LLVM_CONFIG),)
$(info cfg: using LLVM version 2.8svn)
else
CFG_LLVM_CONFIG :=
- $(info cfg: incompatible LLVM version $(CFG_LLVM_VERSION), expected 2.8svn)
+ $(info cfg: incompatible LLVM version $(CFG_LLVM_VERSION), \
+ expected 2.8svn)
endif
endif
ifdef CFG_LLVM_CONFIG
VARIANT=llvm
WHERE := $(shell ocamlc -where)
LLVM_LIBS := llvm.cma llvm_bitwriter.cma
LLVM_NATIVE_LIBS := llvm.cmxa llvm_bitwiter.cmxa
- LLVM_CLIBS := $(shell for c in `$(CFG_LLVM_CONFIG) --ldflags --libs` -lllvm -lllvm_bitwriter; do echo -cclib && echo $$c; done | xargs echo)
+ LLVM_CLIBS := $(shell for c in `$(CFG_LLVM_CONFIG) --ldflags --libs` \
+ -lllvm -lllvm_bitwriter; do echo -cclib && echo $$c; done | xargs echo)
LLVM_INCS := -I boot/llvm -I $(WHERE)
- LLVM_MLS := $(addprefix boot/llvm/, llabi.ml llasm.ml llfinal.ml lltrans.ml \
- llemit.ml)
- CFG_LLC_COMPILE_FLAGS := -march=x86
+ LLVM_MLS := $(addprefix boot/llvm/, llabi.ml llasm.ml llfinal.ml \
+ lltrans.ml llemit.ml)
+ CFG_LLC_CFLAGS := -march=x86
$(info cfg: found llvm-config at $(CFG_LLVM_CONFIG))
else
VARIANT=x86
@@ -190,7 +194,8 @@ ML_INCS := -I boot/fe -I boot/me -I boot/be -I boot/driver/$(VARIANT) \
ML_LIBS := unix.cma nums.cma bigarray.cma
ML_NATIVE_LIBS := unix.cmxa nums.cmxa bigarray.cmxa
OCAMLC_FLAGS := -g $(ML_INCS) -w Ael -warn-error Ael
-OCAMLOPT_FLAGS := $(ML_INCS) -w Ael -warn-error Ael $(CFG_OCAMLOPT_PROFILE_FLAGS)
+OCAMLOPT_FLAGS := $(ML_INCS) -w Ael -warn-error Ael \
+ $(CFG_OCAMLOPT_PROFILE_FLAGS)
ifdef CFG_LLVM_CONFIG
ML_LIBS += $(LLVM_LIBS) -custom -cclib -lstdc++ $(LLVM_CLIBS)
@@ -205,11 +210,12 @@ DRIVER_BOT_MLS := $(addprefix boot/driver/, session.ml)
BE_MLS := $(addprefix boot/be/, x86.ml ra.ml pe.ml elf.ml \
macho.ml)
IL_MLS := $(addprefix boot/be/, asm.ml il.ml abi.ml)
-ME_MLS := $(addprefix boot/me/, walk.ml semant.ml resolve.ml alias.ml type.ml dead.ml \
- typestate.ml mode.ml mutable.ml gctype.ml loop.ml layout.ml transutil.ml \
- trans.ml dwarf.ml)
-FE_MLS := $(addprefix boot/fe/, ast.ml token.ml lexer.ml parser.ml pexp.ml item.ml cexp.ml)
-DRIVER_TOP_MLS := $(addprefix boot/driver/, $(VARIANT)/glue.ml lib.ml main.ml)
+ME_MLS := $(addprefix boot/me/, walk.ml semant.ml resolve.ml alias.ml \
+ type.ml dead.ml effect.ml typestate.ml loop.ml layout.ml \
+ transutil.ml trans.ml dwarf.ml)
+FE_MLS := $(addprefix boot/fe/, ast.ml token.ml lexer.ml parser.ml pexp.ml \
+ item.ml cexp.ml)
+DRIVER_TOP_MLS := $(addprefix boot/driver/, lib.ml $(VARIANT)/glue.ml main.ml)
BOOT_MLS := $(UTIL_BOT_MLS) $(DRIVER_BOT_MLS) $(FE_MLS) $(IL_MLS) $(ME_MLS) \
$(BE_MLS) $(LLVM_MLS) $(DRIVER_TOP_MLS)
@@ -226,8 +232,12 @@ RUNTIME_CS := rt/rust.cpp \
rt/rust_comm.cpp \
rt/rust_dom.cpp \
rt/rust_task.cpp \
+ rt/rust_chan.cpp \
rt/rust_upcall.cpp \
+ rt/rust_log.cpp \
+ rt/rust_timer.cpp \
rt/isaac/randport.cpp
+
RUNTIME_HDR := rt/rust.h \
rt/rust_dwarf.h \
rt/rust_internal.h \
@@ -253,7 +263,8 @@ $(CFG_RUNTIME): $(RUNTIME_OBJS) $(MKFILES) $(RUNTIME_HDR)
$(CFG_STDLIB): $(STDLIB_CRATE) $(CFG_BOOT) $(MKFILES)
@$(call CFG_ECHO, compile: $<)
- $(CFG_QUIET)OCAMLRUNPARAM="b1" $(CFG_BOOT) $(CFG_BOOT_FLAGS) -shared -o $@ $(STDLIB_CRATE)
+ $(CFG_QUIET)OCAMLRUNPARAM="b1" $(CFG_BOOT) $(CFG_BOOT_FLAGS) \
+ -shared -o $@ $(STDLIB_CRATE)
%$(CFG_OBJ_SUFFIX): %.cpp $(MKFILES)
@$(call CFG_ECHO, compile: $<)
@@ -262,7 +273,8 @@ $(CFG_STDLIB): $(STDLIB_CRATE) $(CFG_BOOT) $(MKFILES)
ifdef CFG_NATIVE
$(CFG_BOOT): $(BOOT_CMXS) $(MKFILES)
@$(call CFG_ECHO, compile: $<)
- $(CFG_QUIET)ocamlopt$(OPT) -o $@ $(OCAMLOPT_FLAGS) $(ML_NATIVE_LIBS) $(BOOT_CMXS)
+ $(CFG_QUIET)ocamlopt$(OPT) -o $@ $(OCAMLOPT_FLAGS) $(ML_NATIVE_LIBS) \
+ $(BOOT_CMXS)
else
$(CFG_BOOT): $(BOOT_CMOS) $(MKFILES)
@$(call CFG_ECHO, compile: $<)
@@ -288,7 +300,7 @@ endif
# Main compiler targets and rules
######################################################################
-$(CFG_COMPILER): $(COMPILER_CRATE) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB)
+$(CFG_COMPILER): $(COMPILER_INPUTS) $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB)
@$(call CFG_ECHO, compile: $<)
$(CFG_QUIET)OCAMLRUNPARAM="b1" $(CFG_BOOT) $(CFG_BOOT_FLAGS) -o $@ $<
$(CFG_QUIET)chmod 0755 $@
@@ -302,75 +314,92 @@ self: $(CFG_COMPILER)
# Testing
######################################################################
-TEST_XFAILS_X86 := test/run-pass/mlist_cycle.rs \
+TEST_XFAILS_X86 := test/run-pass/mlist-cycle.rs \
test/run-pass/clone-with-exterior.rs \
+ test/run-pass/obj-as.rs \
test/run-pass/rec-auto.rs \
test/run-pass/vec-slice.rs \
test/run-pass/generic-fn-infer.rs \
+ test/run-pass/generic-recursive-tag.rs \
test/run-pass/generic-tag.rs \
+ test/run-pass/generic-tag-alt.rs \
test/run-pass/bind-obj-ctor.rs \
+ test/run-pass/task-comm.rs \
test/compile-fail/rec-missing-fields.rs \
test/compile-fail/infinite-tag-type-recursion.rs \
test/compile-fail/infinite-vec-type-recursion.rs
TEST_XFAILS_LLVM := $(addprefix test/run-pass/, \
acyclic-unwind.rs \
alt-tag.rs \
+ argv.rs \
basic.rs \
bind-obj-ctor.rs \
bind-thunk.rs \
bind-trivial.rs \
+ bitwise.rs \
+ box-unbox.rs \
cast.rs \
char.rs \
clone-with-exterior.rs \
comm.rs \
+ command-line-args.rs \
complex.rs \
dead-code-one-arm-if.rs \
deep.rs \
div-mod.rs \
drop-on-ret.rs \
+ else-if.rs \
+ export-non-interference.rs \
exterior.rs \
- foreach-simple.rs \
- foreach-simple-outer-slot.rs \
foreach-put-structured.rs \
- vec-slice.rs \
- simple-obj.rs \
- import.rs \
+ foreach-simple-outer-slot.rs \
+ foreach-simple.rs \
fun-call-variants.rs \
fun-indirect-call.rs \
generic-derived-type.rs \
generic-drop-glue.rs \
+ generic-exterior-box.rs \
+ generic-fn-infer.rs \
generic-fn.rs \
- generic-obj.rs \
generic-obj-with-derived-type.rs \
+ generic-obj.rs \
+ generic-recursive-tag.rs \
+ generic-tag-alt.rs \
generic-tag.rs \
+ generic-type-synonym.rs \
generic-type.rs \
- generic-fn-infer.rs \
- vec-append.rs \
- vec-concat.rs \
- vec-drop.rs \
- mutable-vec-drop.rs \
+ i32-sub.rs \
+ i8-incr.rs \
+ import.rs \
inner-module.rs \
large-records.rs \
+ lazy-and-or.rs \
lazychan.rs \
linear-for-loop.rs \
+ list.rs \
many.rs \
+ mlist-cycle.rs \
mlist.rs \
- mlist_cycle.rs \
+ mutable-vec-drop.rs \
mutual-recursion-group.rs \
+ native-mod.rc \
+ native-opaque-type.rs \
native.rc \
- command-line-args.rs \
- native_mod.rc \
+ obj-as.rs \
+ obj-drop.rs \
+ obj-dtor.rs \
+ obj-with-vec.rs \
opeq.rs \
+ preempt.rs \
pred.rs \
readalias.rs \
rec-auto.rs \
rec-extend.rs \
+ rec-tup.rs \
rec.rs \
- rec_tup.rs \
return-nil.rs \
- i32-sub.rs \
- i8-incr.rs \
+ simple-obj.rs \
spawn-fn.rs \
spawn.rs \
stateful-obj.rs \
@@ -383,31 +412,31 @@ TEST_XFAILS_LLVM := $(addprefix test/run-pass/, \
tail-direct.rs \
threads.rs \
tup.rs \
+ type-sizes.rs \
u32-decr.rs \
u8-incr-decr.rs \
u8-incr.rs \
unit.rs \
user.rs \
+ utf8.rs \
+ vec-append.rs \
+ vec-concat.rs \
+ vec-drop.rs \
+ vec-slice.rs \
vec.rs \
writealias.rs \
yield.rs \
yield2.rs \
- native-opaque-type.rs \
- type-sizes.rs \
- obj-drop.rs \
- obj-dtor.rs \
- obj-with-vec.rs \
- else-if.rs \
- lazy-and-or.rs \
+ task-comm.rs \
) \
$(addprefix test/run-fail/, \
explicit-fail.rs \
fail.rs \
linked-failure.rs \
pred.rs \
- vec_overrun.rs \
- str_overrun.rs \
- vec_underrun.rs \
+ vec-overrun.rs \
+ str-overrun.rs \
+ vec-underrun.rs \
) \
$(addprefix test/compile-fail/, \
rec-missing-fields.rs \
@@ -416,149 +445,167 @@ TEST_XFAILS_LLVM := $(addprefix test/run-pass/, \
)
ifdef CFG_WINDOWSY
-TEST_XFAILS_X86 += test/run-pass/native_mod.rc
-TEST_XFAILS_LLVM += test/run-pass/native_mod.rc
+TEST_XFAILS_X86 += test/run-pass/native-mod.rc
+TEST_XFAILS_LLVM += test/run-pass/native-mod.rc
+else
+TEST_XFAILS_X86 += test/run-pass/preempt.rs
+TEST_XFAILS_LLVM += test/run-pass/preempt.rs
endif
-TEST_RUN_PASS_CRATES_X86 := $(filter-out $(TEST_XFAILS_X86), $(wildcard test/run-pass/*.rc))
-TEST_RUN_PASS_CRATES_LLVM := $(filter-out $(TEST_XFAILS_LLVM), $(wildcard test/run-pass/*.rc))
-TEST_RUN_PASS_SOURCES_X86 := $(filter-out $(TEST_XFAILS_X86), $(wildcard test/run-pass/*.rs))
-TEST_RUN_PASS_SOURCES_LLVM := $(filter-out $(TEST_XFAILS_LLVM), $(wildcard test/run-pass/*.rs))
-TEST_RUN_PASS_EXTRAS := $(wildcard test/run-pass/*/*.rs)
-TEST_RUN_PASS_EXES_X86 := \
- $(TEST_RUN_PASS_CRATES_X86:.rc=.x86$(CFG_EXE_SUFFIX)) \
- $(TEST_RUN_PASS_SOURCES_X86:.rs=.x86$(CFG_EXE_SUFFIX))
-TEST_RUN_PASS_EXES_LLVM := \
- $(TEST_RUN_PASS_CRATES_LLVM:.rc=.llvm$(CFG_EXE_SUFFIX)) \
- $(TEST_RUN_PASS_SOURCES_LLVM:.rs=.llvm$(CFG_EXE_SUFFIX))
-TEST_RUN_PASS_OUTS_X86 := \
- $(TEST_RUN_PASS_EXES_X86:.x86$(CFG_EXE_SUFFIX)=.x86.out)
-TEST_RUN_PASS_OUTS_LLVM := \
- $(TEST_RUN_PASS_EXES_LLVM:.llvm$(CFG_EXE_SUFFIX)=.llvm.out)
-
-
-TEST_RUN_FAIL_CRATES_X86 := $(filter-out $(TEST_XFAILS_X86), $(wildcard test/run-fail/*.rc))
-TEST_RUN_FAIL_CRATES_LLVM := $(filter-out $(TEST_XFAILS_LLVM), $(wildcard test/run-fail/*.rc))
-TEST_RUN_FAIL_SOURCES_X86 := $(filter-out $(TEST_XFAILS_X86), $(wildcard test/run-fail/*.rs))
-TEST_RUN_FAIL_SOURCES_LLVM := $(filter-out $(TEST_XFAILS_LLVM), $(wildcard test/run-fail/*.rs))
-TEST_RUN_FAIL_EXTRAS := $(wildcard test/run-fail/*/*.rs)
-TEST_RUN_FAIL_EXES_X86 := \
- $(TEST_RUN_FAIL_CRATES_X86:.rc=.x86$(CFG_EXE_SUFFIX)) \
- $(TEST_RUN_FAIL_SOURCES_X86:.rs=.x86$(CFG_EXE_SUFFIX))
-TEST_RUN_FAIL_EXES_LLVM := \
- $(TEST_RUN_FAIL_CRATES_LLVM:.rc=.llvm$(CFG_EXE_SUFFIX)) \
- $(TEST_RUN_FAIL_SOURCES_LLVM:.rs=.llvm$(CFG_EXE_SUFFIX))
-TEST_RUN_FAIL_OUTS_X86 := \
- $(TEST_RUN_FAIL_EXES_X86:.x86$(CFG_EXE_SUFFIX)=.x86.out)
-TEST_RUN_FAIL_OUTS_LLVM := \
- $(TEST_RUN_FAIL_EXES_LLVM:.llvm$(CFG_EXE_SUFFIX)=.llvm.out)
-
-
-TEST_COMPILE_FAIL_CRATES_X86 := $(filter-out $(TEST_XFAILS_X86), $(wildcard test/compile-fail/*.rc))
-TEST_COMPILE_FAIL_CRATES_LLVM := $(filter-out $(TEST_XFAILS_LLVM), $(wildcard test/compile-fail/*.rc))
-TEST_COMPILE_FAIL_SOURCES_X86 := $(filter-out $(TEST_XFAILS_X86), $(wildcard test/compile-fail/*.rs))
-TEST_COMPILE_FAIL_SOURCES_LLVM := $(filter-out $(TEST_XFAILS_LLVM), $(wildcard test/compile-fail/*.rs))
-TEST_COMPILE_FAIL_EXTRAS := $(wildcard test/compile-fail/*/*.rs)
-TEST_COMPILE_FAIL_EXES_X86 := \
- $(TEST_COMPILE_FAIL_CRATES_X86:.rc=.x86$(CFG_EXE_SUFFIX)) \
- $(TEST_COMPILE_FAIL_SOURCES_X86:.rs=.x86$(CFG_EXE_SUFFIX))
-TEST_COMPILE_FAIL_EXES_LLVM := \
- $(TEST_COMPILE_FAIL_CRATES_LLVM:.rc=.llvm$(CFG_EXE_SUFFIX)) \
- $(TEST_COMPILE_FAIL_SOURCES_LLVM:.rs=.llvm$(CFG_EXE_SUFFIX))
-TEST_COMPILE_FAIL_OUTS_X86 := \
- $(TEST_COMPILE_FAIL_EXES_X86:.x86$(CFG_EXE_SUFFIX)=.x86.out)
-TEST_COMPILE_FAIL_OUTS_LLVM := \
- $(TEST_COMPILE_FAIL_EXES_LLVM:.llvm$(CFG_EXE_SUFFIX)=.llvm.out)
-
-ALL_TEST_CRATES := $(TEST_COMPILE_FAIL_CRATES_X86) \
- $(TEST_RUN_FAIL_CRATES_X86) \
- $(TEST_RUN_PASS_CRATES_X86)
-
-ALL_TEST_SOURCES := $(TEST_COMPILE_FAIL_SOURCES_X86) \
- $(TEST_RUN_FAIL_SOURCES_X86) \
- $(TEST_RUN_PASS_SOURCES_X86)
+RPASS_RC := $(wildcard test/run-pass/*.rc)
+RPASS_RS := $(wildcard test/run-pass/*.rs)
+RFAIL_RC := $(wildcard test/run-fail/*.rc)
+RFAIL_RS := $(wildcard test/run-fail/*.rs)
+CFAIL_RC := $(wildcard test/compile-fail/*.rc)
+CFAIL_RS := $(wildcard test/compile-fail/*.rs)
+
+TEST_RPASS_CRATES_X86 := $(filter-out $(TEST_XFAILS_X86), $(RPASS_RC))
+TEST_RPASS_CRATES_LLVM := $(filter-out $(TEST_XFAILS_LLVM), $(RPASS_RC))
+TEST_RPASS_SOURCES_X86 := $(filter-out $(TEST_XFAILS_X86), $(RPASS_RS))
+TEST_RPASS_SOURCES_LLVM := $(filter-out $(TEST_XFAILS_LLVM), $(RPASS_RS))
+TEST_RPASS_EXTRAS := $(wildcard test/run-pass/*/*.rs)
+TEST_RPASS_EXES_X86 := \
+ $(TEST_RPASS_CRATES_X86:.rc=.x86$(CFG_EXE_SUFFIX)) \
+ $(TEST_RPASS_SOURCES_X86:.rs=.x86$(CFG_EXE_SUFFIX))
+TEST_RPASS_EXES_LLVM := \
+ $(TEST_RPASS_CRATES_LLVM:.rc=.llvm$(CFG_EXE_SUFFIX)) \
+ $(TEST_RPASS_SOURCES_LLVM:.rs=.llvm$(CFG_EXE_SUFFIX))
+TEST_RPASS_OUTS_X86 := \
+ $(TEST_RPASS_EXES_X86:.x86$(CFG_EXE_SUFFIX)=.x86.out)
+TEST_RPASS_OUTS_LLVM := \
+ $(TEST_RPASS_EXES_LLVM:.llvm$(CFG_EXE_SUFFIX)=.llvm.out)
+
+
+TEST_RFAIL_CRATES_X86 := $(filter-out $(TEST_XFAILS_X86), $(RFAIL_RC))
+TEST_RFAIL_CRATES_LLVM := $(filter-out $(TEST_XFAILS_LLVM), $(RFAIL_RC))
+TEST_RFAIL_SOURCES_X86 := $(filter-out $(TEST_XFAILS_X86), $(RFAIL_RS))
+TEST_RFAIL_SOURCES_LLVM := $(filter-out $(TEST_XFAILS_LLVM), $(RFAIL_RS))
+TEST_RFAIL_EXTRAS := $(wildcard test/run-fail/*/*.rs)
+TEST_RFAIL_EXES_X86 := \
+ $(TEST_RFAIL_CRATES_X86:.rc=.x86$(CFG_EXE_SUFFIX)) \
+ $(TEST_RFAIL_SOURCES_X86:.rs=.x86$(CFG_EXE_SUFFIX))
+TEST_RFAIL_EXES_LLVM := \
+ $(TEST_RFAIL_CRATES_LLVM:.rc=.llvm$(CFG_EXE_SUFFIX)) \
+ $(TEST_RFAIL_SOURCES_LLVM:.rs=.llvm$(CFG_EXE_SUFFIX))
+TEST_RFAIL_OUTS_X86 := \
+ $(TEST_RFAIL_EXES_X86:.x86$(CFG_EXE_SUFFIX)=.x86.out)
+TEST_RFAIL_OUTS_LLVM := \
+ $(TEST_RFAIL_EXES_LLVM:.llvm$(CFG_EXE_SUFFIX)=.llvm.out)
+
+
+TEST_CFAIL_CRATES_X86 := $(filter-out $(TEST_XFAILS_X86), $(CFAIL_RC))
+TEST_CFAIL_CRATES_LLVM := $(filter-out $(TEST_XFAILS_LLVM), $(CFAIL_RC))
+TEST_CFAIL_SOURCES_X86 := $(filter-out $(TEST_XFAILS_X86), $(CFAIL_RS))
+TEST_CFAIL_SOURCES_LLVM := $(filter-out $(TEST_XFAILS_LLVM), $(CFAIL_RS))
+TEST_CFAIL_EXTRAS := $(wildcard test/compile-fail/*/*.rs)
+TEST_CFAIL_EXES_X86 := \
+ $(TEST_CFAIL_CRATES_X86:.rc=.x86$(CFG_EXE_SUFFIX)) \
+ $(TEST_CFAIL_SOURCES_X86:.rs=.x86$(CFG_EXE_SUFFIX))
+TEST_CFAIL_EXES_LLVM := \
+ $(TEST_CFAIL_CRATES_LLVM:.rc=.llvm$(CFG_EXE_SUFFIX)) \
+ $(TEST_CFAIL_SOURCES_LLVM:.rs=.llvm$(CFG_EXE_SUFFIX))
+TEST_CFAIL_OUTS_X86 := \
+ $(TEST_CFAIL_EXES_X86:.x86$(CFG_EXE_SUFFIX)=.x86.out)
+TEST_CFAIL_OUTS_LLVM := \
+ $(TEST_CFAIL_EXES_LLVM:.llvm$(CFG_EXE_SUFFIX)=.llvm.out)
+
+ALL_TEST_CRATES := $(TEST_CFAIL_CRATES_X86) \
+ $(TEST_RFAIL_CRATES_X86) \
+ $(TEST_RPASS_CRATES_X86)
+
+ALL_TEST_SOURCES := $(TEST_CFAIL_SOURCES_X86) \
+ $(TEST_RFAIL_SOURCES_X86) \
+ $(TEST_RPASS_SOURCES_X86)
ALL_TEST_INPUTS := $(wildcard test/*/*.rs test/*/*/*.rs test/*/*.rc)
-check_nocompile: $(TEST_COMPILE_FAIL_OUTS_X86)
+check_nocompile: $(TEST_CFAIL_OUTS_X86)
+
+check: tidy \
+ $(TEST_RPASS_EXES_X86) $(TEST_RFAIL_EXES_X86) \
+ $(TEST_RPASS_OUTS_X86) $(TEST_RFAIL_OUTS_X86) \
+ $(TEST_CFAIL_OUTS_X86)
-check: $(TEST_RUN_PASS_EXES_X86) $(TEST_RUN_FAIL_EXES_X86) \
- $(TEST_RUN_PASS_OUTS_X86) $(TEST_RUN_FAIL_OUTS_X86) \
- $(TEST_COMPILE_FAIL_OUTS_X86)
ifeq ($(VARIANT),llvm)
-ALL_TEST_CRATES += $(TEST_COMPILE_FAIL_CRATES_LLVM) \
- $(TEST_RUN_FAIL_CRATES_LLVM) \
- $(TEST_RUN_PASS_CRATES_LLVM)
+ALL_TEST_CRATES += $(TEST_CFAIL_CRATES_LLVM) \
+ $(TEST_RFAIL_CRATES_LLVM) \
+ $(TEST_RPASS_CRATES_LLVM)
-ALL_TEST_SOURCES += $(TEST_COMPILE_FAIL_SOURCES_LLVM) \
- $(TEST_RUN_FAIL_SOURCES_LLVM) \
- $(TEST_RUN_PASS_SOURCES_LLVM)
+ALL_TEST_SOURCES += $(TEST_CFAIL_SOURCES_LLVM) \
+ $(TEST_RFAIL_SOURCES_LLVM) \
+ $(TEST_RPASS_SOURCES_LLVM)
-check_nocompile: $(TEST_COMPILE_FAIL_OUTS_LLVM)
+check_nocompile: $(TEST_CFAIL_OUTS_LLVM)
-check: $(TEST_RUN_PASS_EXES_LLVM) $(TEST_RUN_FAIL_EXES_LLVM) \
- $(TEST_RUN_PASS_OUTS_LLVM) $(TEST_RUN_FAIL_OUTS_LLVM) \
- $(TEST_COMPILE_FAIL_OUTS_LLVM)
+check: tidy \
+ $(TEST_RPASS_EXES_LLVM) $(TEST_RFAIL_EXES_LLVM) \
+ $(TEST_RPASS_OUTS_LLVM) $(TEST_RFAIL_OUTS_LLVM) \
+ $(TEST_CFAIL_OUTS_LLVM)
endif
+REQ := $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB)
+BOOT := $(CFG_QUIET)OCAMLRUNPARAM="b1" $(CFG_BOOT) $(CFG_BOOT_FLAGS)
+
test/run-pass/%.out: test/run-pass/%$(CFG_EXE_SUFFIX) $(CFG_RUNTIME)
@$(call CFG_ECHO, run: $<)
$(CFG_QUIET)$(call CFG_RUN_TARG, $<) > $@
test/run-fail/%.out: test/run-fail/%$(CFG_EXE_SUFFIX) $(CFG_RUNTIME)
@$(call CFG_ECHO, run: $<)
$(CFG_QUIET)rm -f $@
- $(CFG_QUIET)$(call CFG_RUN_TARG, $<) >$@ 2>&1 ; X=$$? ; if [ $$X -eq 0 ] ; then exit 1 ; else exit 0 ; fi
- $(CFG_QUIET)grep --text --quiet "`awk -F: '/error-pattern/ { print $$2 }' $(basename $(basename $@)).rs | tr -d '\n\r'`" $@
+ $(CFG_QUIET)$(call CFG_RUN_TARG, $<) >$@ 2>&1 ; X=$$? ; \
+ if [ $$X -eq 0 ] ; then exit 1 ; else exit 0 ; fi
+ $(CFG_QUIET)grep --text --quiet \
+ "`awk -F: '/error-pattern/ { print $$2 }' \
+ $(basename $(basename $@)).rs | tr -d '\n\r'`" $@
-test/compile-fail/%.x86.out: test/compile-fail/%.rs $(CFG_BOOT) $(CFG_RUNTIME)
+test/compile-fail/%.x86.out: test/compile-fail/%.rs $(REQ)
@$(call CFG_ECHO, compile [x86]: $<)
$(CFG_QUIET)rm -f $@
- $(CFG_QUIET)OCAMLRUNPARAM="b1" $(CFG_BOOT) -o $(@:.out=$(CFG_EXE_SUFFIX)) $< >$@ 2>&1 || true
- $(CFG_QUIET)grep --text --quiet "`awk -F: '/error-pattern/ { print $$2 }' $< | tr -d '\n\r'`" $@
+ $(BOOT) -o $(@:.out=$(CFG_EXE_SUFFIX)) $< >$@ 2>&1 || true
+ $(CFG_QUIET)grep --text --quiet \
+ "`awk -F: '/error-pattern/ { print $$2 }' $< | tr -d '\n\r'`" $@
-test/compile-fail/%.llvm.out: test/compile-fail/%.rs $(CFG_BOOT) $(CFG_RUNTIME)
+test/compile-fail/%.llvm.out: test/compile-fail/%.rs $(REQ)
@$(call CFG_ECHO, compile [llvm]: $<)
$(CFG_QUIET)rm -f $@
- $(CFG_QUIET)OCAMLRUNPARAM="b1" $(CFG_BOOT) $(CFG_BOOT_FLAGS) -o $(@:.out=$(CFG_EXE_SUFFIX)) $< >$@ 2>&1 || true
- $(CFG_QUIET)grep --text --quiet "`awk -F: '/error-pattern/ { print $$2 }' $< | tr -d '\n\r'`" $@
+ $(BOOT) -o $(@:.out=$(CFG_EXE_SUFFIX)) $< >$@ 2>&1 || true
+ $(CFG_QUIET)grep --text --quiet \
+ "`awk -F: '/error-pattern/ { print $$2 }' $< | tr -d '\n\r'`" $@
-test/run-pass/%.x86$(CFG_EXE_SUFFIX): test/run-pass/%.rc $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB)
+test/run-pass/%.x86$(CFG_EXE_SUFFIX): test/run-pass/%.rc $(REQ)
@$(call CFG_ECHO, compile [x86]: $<)
- $(CFG_QUIET)OCAMLRUNPARAM="b1" $(CFG_BOOT) $(CFG_BOOT_FLAGS) -o $@ $<
- $(CFG_QUIET)chmod 0755 $@
+ $(BOOT) -o $@ $<
%.s: %.bc
@$(call CFG_ECHO, compile [llvm]: $<)
- $(CFG_QUIET)llc $(CFG_LLC_COMPILE_FLAGS) -o $@ $<
+ $(CFG_QUIET)llc $(CFG_LLC_CFLAGS) -o $@ $<
%.llvm$(CFG_EXE_SUFFIX): %.s $(CFG_RUNTIME)
@$(call CFG_ECHO, compile [llvm]: $<)
- $(CFG_QUIET)gcc $(CFG_GCC_COMPILE_FLAGS) -o $@ $< -L. -lrustrt
+ $(CFG_QUIET)gcc $(CFG_GCC_CFLAGS) -o $@ $< -L. -lrustrt
-test/run-pass/%.bc: test/run-pass/%.rc $(CFG_BOOT) $(CFG_STDLIB)
+test/run-pass/%.bc: test/run-pass/%.rc $(REQ)
@$(call CFG_ECHO, compile [llvm]: $<)
- $(CFG_QUIET)OCAMLRUNPARAM="b1" $(CFG_BOOT) $(CFG_BOOT_FLAGS) -o $@ -llvm $<
+ $(BOOT) -o $@ -llvm $<
-test/run-pass/%.x86$(CFG_EXE_SUFFIX): test/run-pass/%.rs $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB)
+test/run-pass/%.x86$(CFG_EXE_SUFFIX): test/run-pass/%.rs $(REQ)
@$(call CFG_ECHO, compile [x86]: $<)
- $(CFG_QUIET)OCAMLRUNPARAM="b1" $(CFG_BOOT) $(CFG_BOOT_FLAGS) -o $@ $<
- $(CFG_QUIET)chmod 0755 $@
+ $(BOOT) -o $@ $<
-test/run-pass/%.bc: test/run-pass/%.rs $(CFG_BOOT) $(CFG_STDLIB)
+test/run-pass/%.bc: test/run-pass/%.rs $(REQ)
@$(call CFG_ECHO, compile [llvm]: $<)
- $(CFG_QUIET)OCAMLRUNPARAM="b1" $(CFG_BOOT) $(CFG_BOOT_FLAGS) -o $@ -llvm $<
+ $(BOOT) -o $@ -llvm $<
-test/run-fail/%.x86$(CFG_EXE_SUFFIX): test/run-fail/%.rs $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB)
+test/run-fail/%.x86$(CFG_EXE_SUFFIX): test/run-fail/%.rs $(REQ)
@$(call CFG_ECHO, compile [x86]: $<)
- $(CFG_QUIET)OCAMLRUNPARAM="b1" $(CFG_BOOT) $(CFG_BOOT_FLAGS) -o $@ $<
- $(CFG_QUIET)chmod 0755 $@
+ $(BOOT) -o $@ $<
-test/run-fail/%.bc: test/run-fail/%.rs $(CFG_BOOT) $(CFG_STDLIB)
+test/run-fail/%.bc: test/run-fail/%.rs $(REQ)
@$(call CFG_ECHO, compile [llvm]: $<)
- $(CFG_QUIET)OCAMLRUNPARAM="b1" $(CFG_BOOT) $(CFG_BOOT_FLAGS) -o $@ -llvm $<
+ $(BOOT) -o $@ -llvm $<
######################################################################
@@ -570,7 +617,9 @@ C_DEPFILES := $(RUNTIME_CS:%.cpp=%.d)
%.d: %.cpp $(MKFILES)
@$(call CFG_ECHO, dep: $<)
- $(CFG_QUIET)$(call CFG_DEPEND_C, $@ $(patsubst %.cpp, %$(CFG_OBJ_SUFFIX), $<), $(RUNTIME_INCS)) $< $(CFG_PATH_MUNGE) >$@
+ $(CFG_QUIET)$(call CFG_DEPEND_C, $@ \
+ $(patsubst %.cpp, %$(CFG_OBJ_SUFFIX), $<), \
+ $(RUNTIME_INCS)) $< $(CFG_PATH_MUNGE) >$@
%.d: %.ml $(MKFILES)
@$(call CFG_ECHO, dep: $<)
@@ -593,15 +642,15 @@ CRATE_DEPFILES := $(ALL_TEST_CRATES:%.rc=%.d) $(STDLIB_DEPFILE)
$(STDLIB_DEPFILE): $(STDLIB_CRATE) $(MKFILES) $(CFG_BOOT)
@$(call CFG_ECHO, dep: $<)
- $(CFG_QUIET)$(CFG_BOOT) $(CFG_BOOT_FLAGS) -shared -rdeps $< $(CFG_PATH_MUNGE) >$@
+ $(BOOT) -shared -rdeps $< $(CFG_PATH_MUNGE) >$@
%.d: %.rc $(MKFILES) $(CFG_BOOT)
@$(call CFG_ECHO, dep: $<)
- $(CFG_QUIET)$(CFG_BOOT) $(CFG_BOOT_FLAGS) -rdeps $< $(CFG_PATH_MUNGE) >$@
+ $(BOOT) -rdeps $< $(CFG_PATH_MUNGE) >$@
%.d: %.rs $(MKFILES) $(CFG_BOOT)
@$(call CFG_ECHO, dep: $<)
- $(CFG_QUIET)$(CFG_BOOT) $(CFG_BOOT_FLAGS) -rdeps $< $(CFG_PATH_MUNGE) >$@
+ $(BOOT) -rdeps $< $(CFG_PATH_MUNGE) >$@
ifneq ($(MAKECMDGOALS),clean)
-include $(CRATE_DEPFILES)
@@ -622,8 +671,9 @@ PKG_3RDPARTY := rt/valgrind.h rt/memcheck.h \
rt/bigint/bigint.h rt/bigint/bigint_int.cpp \
rt/bigint/bigint_ext.cpp rt/bigint/low_primes.h
PKG_FILES := README \
+ $(wildcard etc/*.*) \
$(MKFILES) $(BOOT_MLS) boot/fe/lexer.mll \
- $(COMPILER_CRATE) $(COMPILER_INPUTS) \
+ $(COMPILER_INPUTS) \
$(STDLIB_CRATE) $(STDLIB_INPUTS) \
$(RUNTIME_CS) $(RUNTIME_HDR) $(PKG_3RDPARTY) \
$(ALL_TEST_INPUTS)
@@ -658,20 +708,29 @@ distcheck:
# Cleanup
######################################################################
-.PHONY: clean
+.PHONY: clean tidy
+
+tidy:
+ @$(call CFG_ECHO, check: formatting)
+ $(CFG_QUIET) python etc/tidy.py \
+ $(wildcard ../*.txt) \
+ ../README \
+ $(filter-out boot/fe/lexer.ml $(PKG_3RDPARTY), $(PKG_FILES))
clean:
@$(call CFG_ECHO, cleaning)
- $(CFG_QUIET)rm -f $(RUNTIME_OBJS) $(BOOT_CMOS) $(BOOT_CMIS) $(BOOT_CMXS) $(BOOT_OBJS)
+ $(CFG_QUIET)rm -f $(RUNTIME_OBJS)
+ $(CFG_QUIET)rm -f $(BOOT_CMOS) $(BOOT_CMIS) $(BOOT_CMXS) $(BOOT_OBJS)
$(CFG_QUIET)rm -f $(CFG_COMPILER)
$(CFG_QUIET)rm -f $(ML_DEPFILES) $(C_DEPFILES) $(CRATE_DEPFILES)
$(CFG_QUIET)rm -f boot/fe/lexer.ml
$(CFG_QUIET)rm -f $(CFG_BOOT) $(CFG_RUNTIME) $(CFG_STDLIB)
- $(CFG_QUIET)rm -f $(TEST_RUN_PASS_EXES_X86) $(TEST_RUN_PASS_OUTS_X86)
- $(CFG_QUIET)rm -f $(TEST_RUN_PASS_EXES_LLVM) $(TEST_RUN_PASS_OUTS_LLVM)
- $(CFG_QUIET)rm -f $(TEST_RUN_FAIL_EXES_X86) $(TEST_RUN_FAIL_OUTS_X86)
- $(CFG_QUIET)rm -f $(TEST_RUN_FAIL_EXES_LLVM) $(TEST_RUN_FAIL_OUTS_LLVM)
- $(CFG_QUIET)rm -f $(TEST_COMPILE_FAIL_EXES_X86) $(TEST_COMPILE_FAIL_OUTS_X86)
- $(CFG_QUIET)rm -f $(TEST_COMPILE_FAIL_EXES_LLVM) $(TEST_COMPILE_FAIL_OUTS_LLVM)
+ $(CFG_QUIET)rm -f $(TEST_RPASS_EXES_X86) $(TEST_RPASS_OUTS_X86)
+ $(CFG_QUIET)rm -f $(TEST_RPASS_EXES_LLVM) $(TEST_RPASS_OUTS_LLVM)
+ $(CFG_QUIET)rm -f $(TEST_RFAIL_EXES_X86) $(TEST_RFAIL_OUTS_X86)
+ $(CFG_QUIET)rm -f $(TEST_RFAIL_EXES_LLVM) $(TEST_RFAIL_OUTS_LLVM)
+ $(CFG_QUIET)rm -f $(TEST_CFAIL_EXES_X86) $(TEST_CFAIL_OUTS_X86)
+ $(CFG_QUIET)rm -f $(TEST_CFAIL_EXES_LLVM) $(TEST_CFAIL_OUTS_LLVM)
$(CFG_QUIET)rm -Rf $(PKG_NAME)-*.tar.gz dist
- $(CFG_QUIET)rm -f $(foreach ext,cmx cmi cmo cma o a d exe,$(wildcard boot/*/*.$(ext) boot/*/*/*.$(ext)))
+ $(CFG_QUIET)rm -f $(foreach ext,cmx cmi cmo cma o a d exe,\
+ $(wildcard boot/*/*.$(ext) boot/*/*/*.$(ext)))
View
28 src/README
@@ -0,0 +1,28 @@
+This is preliminary version of the Rust compiler.
+
+Source layout:
+
+boot/ The bootstrap compiler
+boot/fe - Front end (lexer, parser, AST)
+boot/me - Middle end (resolve, check, layout, trans)
+boot/be - Back end (IL, RA, insns, asm, objfiles)
+boot/util - Ubiquitous helpers
+boot/llvm - LLVM-based alternative back end
+boot/driver - Compiler driver
+
+comp/ The self-hosted compiler (doesn't exist yet)
+comp/* - Same structure as in boot/
+
+rt/ The runtime system
+rt/rust_*.cpp - The majority of the runtime services
+rt/isaac - The PRNG used for pseudo-random choices in the runtime
+rt/bigint - The bigint library used for the 'big' type
+rt/uthash - Small hashtable-and-list library for C, used in runtime
+rt/{sync,util} - Small utility classes for the runtime.
+
+test/ Testsuite (for both bootstrap and self-hosted)
+test/compile-fail - Tests that should fail to compile
+test/run-fail - Tests that should compile, run and fail
+test/run-pass - Tests that should compile, run and succeed
+
+Please be gentle, it's a work in progress.
View
207 src/boot/be/abi.ml
@@ -0,0 +1,207 @@
+
+(*
+ * The 'abi' structure is pretty much just a grab-bag of machine
+ * dependencies and structure-layout information. Part of the latter
+ * is shared with trans and semant.
+ *
+ * Make some attempt to factor it as time goes by.
+ *)
+
+(* Word offsets for structure fields in rust-internal.h, and elsewhere in
+ compiler. *)
+
+let rc_base_field_refcnt = 0;;
+
+let task_field_refcnt = rc_base_field_refcnt;;
+let task_field_stk = task_field_refcnt + 1;;
+let task_field_runtime_sp = task_field_stk + 1;;
+let task_field_rust_sp = task_field_runtime_sp + 1;;
+let task_field_gc_alloc_chain = task_field_rust_sp + 1;;
+let task_field_dom = task_field_gc_alloc_chain + 1;;
+let n_visible_task_fields = task_field_dom + 1;;
+
+let dom_field_interrupt_flag = 0;;
+
+let frame_glue_fns_field_mark = 0;;
+let frame_glue_fns_field_drop = 1;;
+let frame_glue_fns_field_reloc = 2;;
+
+let exterior_rc_slot_field_refcnt = 0;;
+let exterior_rc_slot_field_body = 1;;
+
+let exterior_gc_slot_field_next = (-2);;
+let exterior_gc_slot_field_ctrl = (-1);;
+let exterior_gc_slot_field_refcnt = 0;;
+let exterior_gc_slot_field_body = 1;;
+
+let exterior_rc_header_size = 1;;
+let exterior_gc_header_size = 3;;
+
+let exterior_gc_malloc_return_adjustment = 2;;
+
+let stk_field_valgrind_id = 0 + 1;;
+let stk_field_limit = stk_field_valgrind_id + 1;;
+let stk_field_data = stk_field_limit + 1;;
+
+let binding_size = 2;;
+let binding_field_item = 0;;
+let binding_field_binding = 1;;
+
+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_drop_glue = 4;;
+let tydesc_field_free_glue = 5;;
+let tydesc_field_mark_glue = 6;;
+let tydesc_field_obj_drop_glue = 7;;
+
+let vec_elt_rc = 0;;
+let vec_elt_alloc = 1;;
+let vec_elt_fill = 2;;
+let vec_elt_data = 3;;
+
+let calltup_elt_out_ptr = 0;;
+let calltup_elt_task_ptr = 1;;
+let calltup_elt_ty_params = 2;;
+let calltup_elt_args = 3;;
+let calltup_elt_iterator_args = 4;;
+let calltup_elt_indirect_args = 5;;
+
+let iterator_args_elt_block_fn = 0;;
+let iterator_args_elt_outer_frame_ptr = 1;;
+
+let indirect_args_elt_closure = 0;;
+
+(* ty_params, src, dst, tydesc, taskptr. *)
+let worst_case_glue_call_args = 5;;
+
+type abi =
+ {
+ abi_word_sz: int64;
+ abi_word_bits: Il.bits;
+ abi_word_ty: Common.ty_mach;
+
+ abi_is_2addr_machine: bool;
+ abi_has_pcrel_data: bool;
+ abi_has_pcrel_code: bool;
+
+ abi_n_hardregs: int;
+ abi_str_of_hardreg: (int -> string);
+
+ abi_prealloc_quad: (Il.quad' -> Il.quad');
+ abi_constrain_vregs: (Il.quad -> Bits.t array -> unit);
+
+ abi_emit_fn_prologue: (Il.emitter
+ -> Common.size (* framesz *)
+ -> Common.size (* callsz *)
+ -> Common.nabi
+ -> Common.fixup (* grow_task *)
+ -> unit);
+
+ abi_emit_fn_epilogue: (Il.emitter -> unit);
+
+ abi_emit_fn_tail_call: (Il.emitter
+ -> int64 (* caller_callsz *)
+ -> int64 (* caller_argsz *)
+ -> Il.code (* callee_code *)
+ -> int64 (* callee_argsz *)
+ -> unit);
+
+ abi_clobbers: (Il.quad -> Il.hreg list);
+
+ abi_emit_native_call: (Il.emitter
+ -> Il.cell (* ret *)
+ -> Common.nabi
+ -> Common.fixup (* callee *)
+ -> Il.operand array (* args *)
+ -> unit);
+
+ abi_emit_native_void_call: (Il.emitter
+ -> Common.nabi
+ -> Common.fixup (* callee *)
+ -> Il.operand array (* args *)
+ -> unit);
+
+ abi_emit_native_call_in_thunk: (Il.emitter
+ -> Il.cell (* ret *)
+ -> Common.nabi
+ -> Il.operand (* callee *)
+ -> Il.operand array (* args *)
+ -> unit);
+ abi_emit_inline_memcpy: (Il.emitter
+ -> int64 (* n_bytes *)
+ -> Il.reg (* dst_ptr *)
+ -> Il.reg (* src_ptr *)
+ -> Il.reg (* tmp_reg *)
+ -> bool (* ascending *)
+ -> unit);
+
+ (* Global glue. *)
+ abi_activate: (Il.emitter -> unit);
+ abi_yield: (Il.emitter -> unit);
+ abi_unwind: (Il.emitter -> Common.nabi -> Common.fixup -> unit);
+ abi_get_next_pc_thunk:
+ ((Il.reg (* output *)
+ * Common.fixup (* thunk in objfile *)
+ * (Il.emitter -> unit)) (* fn to make thunk *)
+ option);
+
+ abi_sp_reg: Il.reg;
+ abi_fp_reg: Il.reg;
+ abi_dwarf_fp_reg: int;
+ abi_tp_cell: Il.cell;
+ abi_implicit_args_sz: int64;
+ abi_frame_base_sz: int64;
+ abi_frame_info_sz: int64;
+ abi_spill_slot: (Il.spill -> Il.mem);
+ }
+;;
+
+let load_fixup_addr
+ (e:Il.emitter)
+ (out_reg:Il.reg)
+ (fix:Common.fixup)
+ (rty:Il.referent_ty)
+ : unit =
+
+ let cell = Il.Reg (out_reg, Il.AddrTy rty) in
+ let op = Il.ImmPtr (fix, rty) in
+ Il.emit e (Il.lea cell op);
+;;
+
+let load_fixup_codeptr
+ (e:Il.emitter)
+ (out_reg:Il.reg)
+ (fixup:Common.fixup)
+ (has_pcrel_code:bool)
+ (indirect:bool)
+ : Il.code =
+ if indirect
+ then
+ begin
+ load_fixup_addr e out_reg fixup (Il.ScalarTy (Il.AddrTy Il.CodeTy));
+ Il.CodePtr (Il.Cell (Il.Mem (Il.RegIn (out_reg, None),
+ Il.ScalarTy (Il.AddrTy Il.CodeTy))))
+ end
+ else
+ if has_pcrel_code
+ then (Il.CodePtr (Il.ImmPtr (fixup, Il.CodeTy)))
+ else
+ begin
+ load_fixup_addr e out_reg fixup Il.CodeTy;
+ Il.CodePtr (Il.Cell (Il.Reg (out_reg, Il.AddrTy Il.CodeTy)))
+ end
+;;
+
+
+(*
+ * Local Variables:
+ * fill-column: 78;
+ * indent-tabs-mode: nil
+ * buffer-file-coding-system: utf-8-unix
+ * compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+ * End:
+ *)
View
755 src/boot/be/asm.ml
@@ -0,0 +1,755 @@
+(*
+
+ Our assembler is an all-at-once, buffer-in-memory job, very simple
+ minded. I have 1gb of memory on my laptop: I don't expect to ever
+ emit a program that large with this code.
+
+ It is based on the 'frag' type, which has a variant for every major
+ type of machine-blob we know how to write (bytes, zstrings, BSS
+ blocks, words of various sorts).
+
+ A frag can contain symbolic references between the sub-parts of
+ it. These are accomplished through ref cells we call fixups, and a
+ 2-pass (resolution and writing) process defined recursively over
+ the frag structure.
+
+ Fixups are defined by wrapping a frag in a DEF pseudo-frag with
+ a fixup attached. This will record information about the wrapped
+ frag -- positions and sizes -- in the fixup during resolution.
+
+ We say "positions" and "sizes" there, in plural, because both a
+ file number and a memory number is recorded for each concept.
+
+ File numbers refer to positions and sizes in the file we're
+ generating, and are based on the native int type for the host
+ platform -- usually 31 or 62 bits -- whereas the expressions that
+ *use* position fixups tend to promote them up to 32 or 64 bits
+ somehow. On a 32 bit platform, you can't generate output buffers
+ with 64-bit positions (ocaml limitation!)
+
+ Memory numbers are 64 bit, always, and refer to sizes and positions
+ of frags when they are loaded into memory in the target. When
+ you're generating code for a 32-bit target, or using a memory
+ number in a context that's less than 64 bits, the value is
+ range-checked and truncated. But in all other respects, we imagine
+ a 32-bit address space is just the prefix of the continuing 64-bit
+ address space. If you need to pin an object at a particular place
+ from the point 2^32-1, say, you will need to do arithmetic and use
+ the MEMPOS pseudo-frag, that sets the current memory position as
+ it's being processed.
+
+ Fixups can be *used* anywhere else in the frag tree, as many times
+ as you like. If you try to write an unresolved fixup, the emitter
+ faults. When you specify the use of a fixup, you need to specify
+ whether you want to use its file size, file position, memory size,
+ or memory position.
+
+ Positions, addresses, sizes and such, of course, are in bytes.
+
+ Expressions are evaluated to an int64 (signed), even if the
+ expression is an int32 or less. Depending on how you use the result
+ of the expression, a range check error may fire (for example, if
+ the expression evaluates to -2^24 and you're emitting a word16).
+
+ Word endianness is per-file. At the moment this seems acceptable.
+
+ Because we want to be *very specific* about the time and place
+ arithmetic promotions occur, we define two separate expression-tree
+ types (with the same polymorphic constructors) and two separate
+ evaluation functions, with an explicit operator for marking the
+ promotion-points.
+
+*)
+
+open Common;;
+
+
+let log (sess:Session.sess) =
+ Session.log "asm"
+ sess.Session.sess_log_asm
+ sess.Session.sess_log_out
+;;
+
+let iflog (sess:Session.sess) (thunk:(unit -> unit)) : unit =
+ if sess.Session.sess_log_asm
+ then thunk ()
+ else ()
+;;
+
+exception Bad_fit of string;;
+exception Undef_sym of string;;
+
+type ('a, 'b) expr =
+ IMM of 'a
+ | ADD of (('a, 'b) expr) * (('a, 'b) expr)
+ | SUB of (('a, 'b) expr) * (('a, 'b) expr)
+ | MUL of (('a, 'b) expr) * (('a, 'b) expr)
+ | DIV of (('a, 'b) expr) * (('a, 'b) expr)
+ | REM of (('a, 'b) expr) * (('a, 'b) expr)
+ | MAX of (('a, 'b) expr) * (('a, 'b) expr)
+ | ALIGN of (('a, 'b) expr) * (('a, 'b) expr)
+ | SLL of (('a, 'b) expr) * int
+ | SLR of (('a, 'b) expr) * int
+ | SAR of (('a, 'b) expr) * int
+ | AND of (('a, 'b) expr) * (('a, 'b) expr)
+ | XOR of (('a, 'b) expr) * (('a, 'b) expr)
+ | OR of (('a, 'b) expr) * (('a, 'b) expr)
+ | NOT of (('a, 'b) expr)
+ | NEG of (('a, 'b) expr)
+ | F_POS of fixup
+ | F_SZ of fixup
+ | M_POS of fixup
+ | M_SZ of fixup
+ | EXT of 'b
+
+type expr32 = (int32, int) expr
+;;
+
+type expr64 = (int64, expr32) expr
+;;
+
+
+let rec eval32 (e:expr32)
+ : int32 =
+ let chop64 kind name v =
+ let x = Int64.to_int32 v in
+ if (Int64.compare v (Int64.of_int32 x)) = 0 then
+ x
+ else raise (Bad_fit (kind
+ ^ " fixup "
+ ^ name
+ ^ " overflowed 32 bits in eval32: "
+ ^ Int64.to_string v))
+ in
+ let expandInt _ _ v = Int32.of_int v in
+ let checkdef kind name v inj =
+ match v with
+ None ->
+ raise (Undef_sym (kind ^ " fixup " ^ name
+ ^ " undefined in eval32"))
+ | Some x -> inj kind name x
+ in
+ match e with
+ IMM i -> i
+ | ADD (a, b) -> Int32.add (eval32 a) (eval32 b)
+ | SUB (a, b) -> Int32.sub (eval32 a) (eval32 b)
+ | MUL (a, b) -> Int32.mul (eval32 a) (eval32 b)
+ | DIV (a, b) -> Int32.div (eval32 a) (eval32 b)
+ | REM (a, b) -> Int32.rem (eval32 a) (eval32 b)
+ | MAX (a, b) -> i32_max (eval32 a) (eval32 b)
+ | ALIGN (a, b) -> i32_align (eval32 a) (eval32 b)
+ | SLL (a, b) -> Int32.shift_left (eval32 a) b
+ | SLR (a, b) -> Int32.shift_right_logical (eval32 a) b
+ | SAR (a, b) -> Int32.shift_right (eval32 a) b
+ | AND (a, b) -> Int32.logand (eval32 a) (eval32 b)
+ | XOR (a, b) -> Int32.logxor (eval32 a) (eval32 b)
+ | OR (a, b) -> Int32.logor (eval32 a) (eval32 b)
+ | NOT a -> Int32.lognot (eval32 a)
+ | NEG a -> Int32.neg (eval32 a)
+ | F_POS f ->
+ checkdef "file position"
+ f.fixup_name f.fixup_file_pos expandInt
+ | F_SZ f ->
+ checkdef "file size"
+ f.fixup_name f.fixup_file_sz expandInt
+ | M_POS f ->
+ checkdef "mem position"
+ f.fixup_name f.fixup_mem_pos chop64
+ | M_SZ f ->
+ checkdef "mem size" f.fixup_name f.fixup_mem_sz chop64
+ | EXT i -> Int32.of_int i
+;;
+
+let rec eval64 (e:expr64)
+ : int64 =
+ let checkdef kind name v inj =
+ match v with
+ None ->
+ raise (Undef_sym (kind ^ " fixup '"
+ ^ name ^ "' undefined in eval64"))
+ | Some x -> inj x
+ in
+ match e with
+ IMM i -> i
+ | ADD (a, b) -> Int64.add (eval64 a) (eval64 b)
+ | SUB (a, b) -> Int64.sub (eval64 a) (eval64 b)
+ | MUL (a, b) -> Int64.mul (eval64 a) (eval64 b)
+ | DIV (a, b) -> Int64.div (eval64 a) (eval64 b)
+ | REM (a, b) -> Int64.rem (eval64 a) (eval64 b)
+ | MAX (a, b) -> i64_max (eval64 a) (eval64 b)
+ | ALIGN (a, b) -> i64_align (eval64 a) (eval64 b)
+ | SLL (a, b) -> Int64.shift_left (eval64 a) b
+ | SLR (a, b) -> Int64.shift_right_logical (eval64 a) b
+ | SAR (a, b) -> Int64.shift_right (eval64 a) b
+ | AND (a, b) -> Int64.logand (eval64 a) (eval64 b)
+ | XOR (a, b) -> Int64.logxor (eval64 a) (eval64 b)
+ | OR (a, b) -> Int64.logor (eval64 a) (eval64 b)
+ | NOT a -> Int64.lognot (eval64 a)
+ | NEG a -> Int64.neg (eval64 a)
+ | F_POS f ->
+ checkdef "file position"
+ f.fixup_name f.fixup_file_pos Int64.of_int
+ | F_SZ f ->
+ checkdef "file size"
+ f.fixup_name f.fixup_file_sz Int64.of_int
+ | M_POS f ->
+ checkdef "mem position"
+ f.fixup_name f.fixup_mem_pos (fun x -> x)
+ | M_SZ f ->
+ checkdef "mem size"
+ f.fixup_name f.fixup_mem_sz (fun x -> x)
+ | EXT e -> Int64.of_int32 (eval32 e)
+;;
+
+
+type frag =
+ MARK (* MARK == 'PAD (IMM 0L)' *)
+ | SEQ of frag array
+ | PAD of int
+ | BSS of int64
+ | MEMPOS of int64
+ | BYTE of int
+ | BYTES of int array
+ | CHAR of char
+ | STRING of string
+ | ZSTRING of string
+ | ULEB128 of expr64
+ | SLEB128 of expr64
+ | WORD of (ty_mach * expr64)
+ | ALIGN_FILE of (int * frag)
+ | ALIGN_MEM of (int * frag)
+ | DEF of (fixup * frag)
+ | RELAX of relaxation
+
+and relaxation =
+ { relax_options: frag array;
+ relax_choice: int ref; }
+;;
+
+exception Relax_more of relaxation;;
+
+let new_relaxation (frags:frag array) =
+ RELAX { relax_options = frags;
+ relax_choice = ref ((Array.length frags) - 1); }
+;;
+
+
+let rec write_frag
+ ~(sess:Session.sess)
+ ~(lsb0:bool)
+ ~(buf:Buffer.t)
+ ~(frag:frag)
+ : unit =
+ let relax = Queue.create () in
+ let bump_relax r =
+ iflog sess (fun _ ->
+ log sess "bumping relaxation to position %d"
+ ((!(r.relax_choice)) - 1));
+ r.relax_choice := (!(r.relax_choice)) - 1;
+ if !(r.relax_choice) < 0
+ then bug () "relaxation ran out of options"
+ in
+ let rec loop _ =
+ Queue.clear relax;
+ Buffer.clear buf;
+ resolve_frag_full relax frag;
+ lower_frag ~sess ~lsb0 ~buf ~relax ~frag;
+ if Queue.is_empty relax
+ then ()
+ else
+ begin
+ iflog sess (fun _ -> log sess "relaxing");
+ Queue.iter bump_relax relax;
+ loop ()
+ end
+ in
+ loop ()
+
+
+and resolve_frag_full (relax:relaxation Queue.t) (frag:frag)
+ : unit =
+ let file_pos = ref 0 in
+ let mem_pos = ref 0L in
+ let bump i =
+ mem_pos := Int64.add (!mem_pos) (Int64.of_int i);
+ file_pos := (!file_pos) + i
+ in
+
+ let uleb (e:expr64) : unit =
+ let rec loop value =
+ let value = Int64.shift_right_logical value 7 in
+ if value = 0L
+ then bump 1
+ else
+ begin
+ bump 1;
+ loop value
+ end
+ in
+ loop (eval64 e)
+ in
+
+ let sleb (e:expr64) : unit =
+ let rec loop value =
+ let byte = Int64.logand value 0xf7L in
+ let value = Int64.shift_right value 7 in
+ let signbit = Int64.logand byte 0x40L in
+ if (((value = 0L) && (signbit = 0L)) ||
+ ((value = -1L) && (signbit = 0x40L)))
+ then bump 1
+ else
+ begin
+ bump 1;
+ loop value
+ end
+ in
+ loop (eval64 e)
+ in
+ let rec resolve_frag it =
+ match it with
+ | MARK -> ()
+ | SEQ frags -> Array.iter resolve_frag frags
+ | PAD i -> bump i
+ | BSS i -> mem_pos := Int64.add (!mem_pos) i
+ | MEMPOS i -> mem_pos := i
+ | BYTE _ -> bump 1
+ | BYTES ia -> bump (Array.length ia)
+ | CHAR _ -> bump 1
+ | STRING s -> bump (String.length s)
+ | ZSTRING s -> bump ((String.length s) + 1)
+ | ULEB128 e -> uleb e
+ | SLEB128 e -> sleb e
+ | WORD (mach,_) -> bump (bytes_of_ty_mach mach)
+ | ALIGN_FILE (n, frag) ->
+ let spill = (!file_pos) mod n in
+ let pad = (n - spill) mod n in
+ file_pos := (!file_pos) + pad;
+ (*
+ * NB: aligning the file *causes* likewise alignment of
+ * memory, since we implement "file alignment" by
+ * padding!
+ *)
+ mem_pos := Int64.add (!mem_pos) (Int64.of_int pad);
+ resolve_frag frag
+
+ | ALIGN_MEM (n, frag) ->
+ let n64 = Int64.of_int n in
+ let spill = Int64.rem (!mem_pos) n64 in
+ let pad = Int64.rem (Int64.sub n64 spill) n64 in
+ mem_pos := Int64.add (!mem_pos) pad;
+ resolve_frag frag
+
+ | DEF (f, i) ->
+ let fpos1 = !file_pos in
+ let mpos1 = !mem_pos in
+ resolve_frag i;
+ f.fixup_file_pos <- Some fpos1;
+ f.fixup_mem_pos <- Some mpos1;
+ f.fixup_file_sz <- Some ((!file_pos) - fpos1);
+ f.fixup_mem_sz <- Some (Int64.sub (!mem_pos) mpos1)
+
+ | RELAX rel ->
+ begin
+ try
+ resolve_frag rel.relax_options.(!(rel.relax_choice))
+ with
+ Bad_fit _ -> Queue.add rel relax
+ end
+ in
+ resolve_frag frag
+
+and lower_frag
+ ~(sess:Session.sess)
+ ~(lsb0:bool)
+ ~(buf:Buffer.t)
+ ~(relax:relaxation Queue.t)
+ ~(frag:frag)
+ : unit =
+ let byte (i:int) =
+ if i < 0
+ then raise (Bad_fit "byte underflow")
+ else
+ if i > 255
+ then raise (Bad_fit "byte overflow")
+ else Buffer.add_char buf (Char.chr i)
+ in
+
+ let uleb (e:expr64) : unit =
+ let emit1 k = Buffer.add_char buf (Char.chr (Int64.to_int k)) in
+ let rec loop value =
+ let byte = Int64.logand value 0x7fL in
+ let value = Int64.shift_right_logical value 7 in
+ if value = 0L
+ then emit1 byte
+ else
+ begin
+ emit1 (Int64.logor byte 0x80L);
+ loop value
+ end
+ in
+ loop (eval64 e)
+ in
+
+ let sleb (e:expr64) : unit =
+ let emit1 k = Buffer.add_char buf (Char.chr (Int64.to_int k)) in
+ let rec loop value =
+ let byte = Int64.logand value 0x7fL in
+ let value = Int64.shift_right value 7 in
+ let signbit = Int64.logand byte 0x40L in
+ if (((value = 0L) && (signbit = 0L)) ||
+ ((value = -1L) && (signbit = 0x40L)))
+ then emit1 byte
+ else
+ begin
+ emit1 (Int64.logor byte 0x80L);
+ loop value
+ end
+ in
+ loop (eval64 e)
+ in
+
+ let word (nbytes:int) (signed:bool) (e:expr64) =
+ let i = eval64 e in
+
+ (*
+ FIXME:
+
+ We should really base the entire assembler and memory-position
+ system on Big_int.big_int, but in ocaml the big_int type lacks,
+ oh, just about every useful function (no format string spec, no
+ bitwise ops, blah blah) so it's useless; we're stuck on int64
+ for bootstrapping.
+
+ For the time being we're just going to require you to represent
+ those few unsigned 64 bit terms you have in mind via their
+ signed bit pattern. Suboptimal but it's the best we can do.
+ *)
+
+ let (top,bot) =
+ if nbytes >= 8
+ then
+ if signed
+ then (Int64.max_int,Int64.min_int)
+ else (Int64.max_int,0L)
+ else
+ if signed
+ then
+ let bound = (Int64.shift_left 1L ((8 * nbytes) - 1)) in
+ (Int64.sub bound 1L, Int64.neg bound)
+ else
+ let bound = (Int64.shift_left 1L (8 * nbytes)) in
+ (Int64.sub bound 1L, 0L)
+ in
+
+ let mask1 = Int64.logand 0xffL in
+ let shift = Int64.shift_right_logical in
+ let emit1 k = Buffer.add_char buf (Char.chr (Int64.to_int k)) in
+ if Int64.compare i bot = (-1)
+ then raise (Bad_fit ("word underflow: "
+ ^ (Int64.to_string i)
+ ^ " into "
+ ^ (string_of_int nbytes)
+ ^ (if signed then " signed" else " unsigned")
+ ^ " bytes"))
+ else
+ if Int64.compare i top = 1
+ then raise (Bad_fit ("word overflow: "
+ ^ (Int64.to_string i)
+ ^ " into "
+ ^ (string_of_int nbytes)
+ ^ (if signed then " signed" else " unsigned")
+ ^ " bytes"))
+ else
+ if lsb0
+ then
+ for n = 0 to (nbytes - 1) do
+ emit1 (mask1 (shift i (8*n)))
+ done
+ else
+ for n = (nbytes - 1) downto 0 do
+ emit1 (mask1 (shift i (8*n)))
+ done
+ in
+ match frag with
+ MARK -> ()
+
+ | SEQ frags ->
+ Array.iter
+ begin
+ fun frag ->
+ lower_frag ~sess ~lsb0 ~buf ~relax ~frag
+ end frags
+
+ | PAD c ->
+ for i = 1 to c do
+ Buffer.add_char buf '\x00'
+ done
+
+ | BSS _ -> ()
+
+ | MEMPOS _ -> ()
+
+ | BYTE i -> byte i
+
+ | BYTES bs ->
+ iflog sess (fun _ -> log sess "lowering %d bytes"
+ (Array.length bs));
+ Array.iter byte bs
+
+ | CHAR c ->
+ iflog sess (fun _ -> log sess "lowering char: %c" c);
+ Buffer.add_char buf c
+
+ | STRING s ->
+ iflog sess (fun _ -> log sess "lowering string: %s" s);
+ Buffer.add_string buf s
+
+ | ZSTRING s ->
+ iflog sess (fun _ -> log sess "lowering zstring: %s" s);
+ Buffer.add_string buf s;
+ byte 0
+
+ | ULEB128 e -> uleb e
+ | SLEB128 e -> sleb e
+
+ | WORD (m,e) ->
+ iflog sess
+ (fun _ ->
+ log sess "lowering word %s"
+ (string_of_ty_mach m));
+ word (bytes_of_ty_mach m) (mach_is_signed m) e
+
+ | ALIGN_FILE (n, frag) ->
+ let spill = (Buffer.length buf) mod n in
+ let pad = (n - spill) mod n in
+ for i = 1 to pad do
+ Buffer.add_char buf '\x00'
+ done;
+ lower_frag sess lsb0 buf relax frag
+
+ | ALIGN_MEM (_, i) -> lower_frag sess lsb0 buf relax i
+ | DEF (f, i) ->
+ iflog sess (fun _ -> log sess "lowering fixup: %s" f.fixup_name);
+ lower_frag sess lsb0 buf relax i;
+
+ | RELAX rel ->
+ begin
+ try
+ lower_frag sess lsb0 buf relax
+ rel.relax_options.(!(rel.relax_choice))
+ with
+ Bad_fit _ -> Queue.add rel relax
+ end
+;;
+
+let fold_flags (f:'a -> int64) (flags:'a list) : int64 =
+ List.fold_left (Int64.logor) 0x0L (List.map f flags)
+;;
+
+let write_out_frag sess lsb0 frag =
+ let buf = Buffer.create 0xffff in
+ let file = Session.filename_of sess.Session.sess_out in
+ let out = open_out_bin file in
+ write_frag ~sess ~lsb0 ~buf ~frag;
+ Buffer.output_buffer out buf;
+ flush out;
+ close_out out;
+ Unix.chmod file 0o755
+;;
+
+(* Asm-reader stuff for loading info back from mapped files. *)
+(*
+ * Unfortunately the ocaml Bigarray interface takes 'int' indices, so
+ * f.e. can't do 64-bit offsets / files when running on a 32bit platform.
+ * Despite the fact that we can possibly produce them. Sigh. Yet another
+ * "bootstrap compiler limitation".
+ *)
+type asm_reader =
+ {
+ asm_seek: int -> unit;
+ asm_get_u32: unit -> int;
+ asm_get_u16: unit -> int;
+ asm_get_u8: unit -> int;
+ asm_get_uleb: unit -> int;
+ asm_get_zstr: unit -> string;
+ asm_get_zstr_padded: int -> string;
+ asm_get_off: unit -> int;
+ asm_adv: int -> unit;
+ asm_adv_u32: unit -> unit;
+ asm_adv_u16: unit -> unit;
+ asm_adv_u8: unit -> unit;
+ asm_adv_zstr: unit -> unit;
+ asm_close: unit -> unit;
+ }
+;;
+
+type mmap_arr =
+ (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout)
+ Bigarray.Array1.t
+;;
+
+let new_asm_reader (sess:Session.sess) (s:filename) : asm_reader =
+ iflog sess (fun _ -> log sess "opening file %s" s);
+ let fd = Unix.openfile s [ Unix.O_RDONLY ] 0 in
+ let arr = (Bigarray.Array1.map_file
+ fd ~pos:0L
+ Bigarray.int8_unsigned
+ Bigarray.c_layout
+ false (-1))
+ in
+ let tmp = ref Nativeint.zero in
+ let buf = Buffer.create 16 in
+ let off = ref 0 in
+ let is_open = ref true in
+ let get_word_as_int (nbytes:int) : int =
+ assert (!is_open);
+ let lsb0 = true in
+ tmp := Nativeint.zero;
+ if lsb0
+ then
+ for j = nbytes-1 downto 0 do
+ tmp := Nativeint.shift_left (!tmp) 8;
+ tmp := Nativeint.logor (!tmp) (Nativeint.of_int arr.{(!off) + j})
+ done
+ else
+ for j = 0 to nbytes-1 do
+ tmp := Nativeint.shift_left (!tmp) 8;
+ tmp := Nativeint.logor (!tmp) (Nativeint.of_int arr.{(!off) + j})
+ done;
+ off := (!off) + nbytes;
+ Nativeint.to_int (!tmp)
+ in
+ let get_zstr_padded pad_opt =
+ assert (!is_open);
+ let i = ref (!off) in
+ Buffer.clear buf;
+ let buflen_ok _ =
+ match pad_opt with
+ None -> true
+ | Some pad -> (Buffer.length buf) < pad
+ in
+ while arr.{!i} != 0 && (buflen_ok()) do
+ Buffer.add_char buf (Char.chr arr.{!i});
+ incr i
+ done;
+ begin
+ match pad_opt with
+ None -> off := (!off) + (Buffer.length buf) + 1
+ | Some pad ->
+ begin
+ assert ((Buffer.length buf) <= pad);
+ off := (!off) + pad
+ end
+ end;
+ Buffer.contents buf
+ in
+ let bump i =
+ assert (!is_open);
+ off := (!off) + i
+ in
+ {
+ asm_seek = (fun i -> off := i);
+ asm_get_u32 = (fun _ -> get_word_as_int 4);
+ asm_get_u16 = (fun _ -> get_word_as_int 2);
+ asm_get_u8 = (fun _ -> get_word_as_int 1);
+ asm_get_uleb =
+ begin
+ fun _ ->
+ let rec loop result shift =
+ let byte = arr.{!off} in
+ incr off;
+ let result = result lor ((byte land 0x7f) lsl shift) in
+ if (byte land 0x80) = 0
+ then result
+ else loop result (shift+7)
+ in
+ loop 0 0
+ end;
+ asm_get_zstr = (fun _ -> get_zstr_padded None);
+ asm_get_zstr_padded = (fun pad -> get_zstr_padded (Some pad));
+ asm_get_off = (fun _ -> !off);
+ asm_adv = bump;
+ asm_adv_u32 = (fun _ -> bump 4);
+ asm_adv_u16 = (fun _ -> bump 2);
+ asm_adv_u8 = (fun _ -> bump 1);
+ asm_adv_zstr = (fun _ -> while arr.{!off} != 0
+ do incr off done);
+ asm_close = (fun _ ->
+ assert (!is_open);
+ Unix.close fd;
+ is_open := false)
+ }
+;;
+
+
+(*
+ * Metadata note-section encoding / decoding.
+ *
+ * Since the only object format that defines a "note" section at all is
+ * ELF, we model the contents of the metadata section on ELF's
+ * notes. But the same blob of data is stuck into PE and Mach-O files
+ * too.
+ *
+ * The format is essentially just the ELF note format:
+ *
+ * <un-padded-size-of-name:u32>
+ * <size-of-desc:u32>
+ * <type-code=0:u32>
+ * <name="rust":zstr>
+ * <0-pad to 4-byte boundary>
+ * <n=meta-count:u32>
+ * <k1:zstr> <v1:zstr>
+ * ...
+ * <kn:zstr> <vn:zstr>
+ * <0-pad to 4-byte boundary>
+ *
+ *)
+let note_rust_frags (meta:(Ast.ident * string) array) : frag =
+ let desc_fixup = new_fixup ".rust.note metadata" in
+ let desc =
+ DEF (desc_fixup,
+ SEQ [|
+ WORD (TY_u32, IMM (Int64.of_int (Array.length meta)));
+ SEQ (Array.map
+ (fun (k,v) -> SEQ [| ZSTRING k; ZSTRING v; |])
+ meta);
+ ALIGN_FILE (4, MARK) |])
+ in
+ let name = "rust" in
+ let ty = 0L in
+ let padded_name = SEQ [| ZSTRING name;
+ ALIGN_FILE (4, MARK) |]
+ in
+ let name_sz = IMM (Int64.of_int ((String.length name) + 1)) in
+ SEQ [| WORD (TY_u32, name_sz);
+ WORD (TY_u32, F_SZ desc_fixup);
+ WORD (TY_u32, IMM ty);
+ padded_name;
+ desc;|]
+;;
+
+let read_rust_note (ar:asm_reader) : (Ast.ident * string) array =
+ ar.asm_adv_u32 ();
+ ar.asm_adv_u32 ();
+ assert ((ar.asm_get_u32 ()) = 0);
+ let rust_name = ar.asm_get_zstr_padded 8 in
+ assert (rust_name = "rust");
+ let n = ar.asm_get_u32() in
+ let meta = Queue.create () in
+ for i = 1 to n
+ do
+ let k = ar.asm_get_zstr() in
+ let v = ar.asm_get_zstr() in
+ Queue.add (k,v) meta
+ done;
+ queue_to_arr meta
+;;
+
+(*
+ * Local Variables:
+ * fill-column: 78;
+ * indent-tabs-mode: nil
+ * buffer-file-coding-system: utf-8-unix
+ * compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+ * End:
+ *)
View
1,760 src/boot/be/elf.ml
@@ -0,0 +1,1760 @@
+(*
+ * Module for writing System V ELF files.
+ *
+ * FIXME: Presently heavily infected with x86 and elf32 specificities,
+ * though they are reasonably well marked. Needs to be refactored to
+ * depend on abi fields if it's to be usable for other elf
+ * configurations.
+ *)
+
+open Asm;;
+open Common;;
+
+let log (sess:Session.sess) =
+ Session.log "obj (elf)"
+ sess.Session.sess_log_obj
+ sess.Session.sess_log_out
+;;
+
+let iflog (sess:Session.sess) (thunk:(unit -> unit)) : unit =
+ if sess.Session.sess_log_obj
+ then thunk ()
+ else ()
+;;
+
+
+(* Fixed sizes of structs involved in elf32 spec. *)
+let elf32_ehsize = 52L;;
+let elf32_phentsize = 32L;;
+let elf32_shentsize = 40L;;
+let elf32_symsize = 16L;;
+let elf32_rela_entsz = 0xcL;;
+
+type ei_class =
+ ELFCLASSNONE
+ | ELFCLASS32
+ | ELFCLASS64
+;;
+
+
+type ei_data =
+ ELFDATANONE
+ | ELFDATA2LSB
+ | ELFDATA2MSB
+;;
+
+
+let elf_identification ei_class ei_data =
+ SEQ
+ [|
+ STRING "\x7fELF";
+ BYTES
+ [|
+ (match ei_class with (* EI_CLASS *)
+ ELFCLASSNONE -> 0
+ | ELFCLASS32 -> 1
+ | ELFCLASS64 -> 2);
+ (match ei_data with (* EI_DATA *)
+ ELFDATANONE -> 0
+ | ELFDATA2LSB -> 1
+ | ELFDATA2MSB -> 2);
+ 1; (* EI_VERSION = EV_CURRENT *)
+ 0; (* EI_PAD #7 *)
+ 0; (* EI_PAD #8 *)
+ 0; (* EI_PAD #9 *)
+ 0; (* EI_PAD #A *)
+ 0; (* EI_PAD #B *)
+ 0; (* EI_PAD #C *)
+ 0; (* EI_PAD #D *)
+ 0; (* EI_PAD #E *)
+ 0; (* EI_PAD #F *)
+ |]
+ |]
+;;
+
+
+type e_type =
+ ET_NONE
+ | ET_REL
+ | ET_EXEC
+ | ET_DYN
+ | ET_CORE
+;;
+
+
+type e_machine =
+ (* Maybe support more later. *)
+ EM_NONE
+ | EM_386
+ | EM_X86_64
+;;
+
+
+type e_version =
+ EV_NONE
+ | EV_CURRENT
+;;
+
+
+let elf32_header
+ ~(sess:Session.sess)
+ ~(ei_data:ei_data)
+ ~(e_type:e_type)
+ ~(e_machine:e_machine)
+ ~(e_version:e_version)
+ ~(e_entry_fixup:fixup)
+ ~(e_phoff_fixup:fixup)
+ ~(e_shoff_fixup:fixup)
+ ~(e_phnum:int64)
+ ~(e_shnum:int64)
+ ~(e_shstrndx:int64)
+ : frag =
+ let elf_header_fixup = new_fixup "elf header" in
+ let entry_pos =
+ if sess.Session.sess_library_mode
+ then (IMM 0L)
+ else (M_POS e_entry_fixup)
+ in
+ DEF
+ (elf_header_fixup,
+ SEQ [| elf_identification ELFCLASS32 ei_data;
+ WORD (TY_u16, (IMM (match e_type with
+ ET_NONE -> 0L
+ | ET_REL -> 1L
+ | ET_EXEC -> 2L
+ | ET_DYN -> 3L
+ | ET_CORE -> 4L)));
+ WORD (TY_u16, (IMM (match e_machine with
+ EM_NONE -> 0L
+ | EM_386 -> 3L
+ | EM_X86_64 -> 62L)));
+ WORD (TY_u32, (IMM (match e_version with
+ EV_NONE -> 0L
+ | EV_CURRENT -> 1L)));
+ WORD (TY_u32, entry_pos);
+ WORD (TY_u32, (F_POS e_phoff_fixup));
+ WORD (TY_u32, (F_POS e_shoff_fixup));
+ WORD (TY_u32, (IMM 0L)); (* e_flags *)
+ WORD (TY_u16, (IMM elf32_ehsize));
+ WORD (TY_u16, (IMM elf32_phentsize));
+ WORD (TY_u16, (IMM e_phnum));
+ WORD (TY_u16, (IMM elf32_shentsize));
+ WORD (TY_u16, (IMM e_shnum));
+ WORD (TY_u16, (IMM e_shstrndx));
+ |])
+;;
+
+
+type sh_type =
+ SHT_NULL
+ | SHT_PROGBITS
+ | SHT_SYMTAB
+ | SHT_STRTAB
+ | SHT_RELA
+ | SHT_HASH
+ | SHT_DYNAMIC
+ | SHT_NOTE
+ | SHT_NOBITS
+ | SHT_REL
+ | SHT_SHLIB
+ | SHT_DYNSYM
+;;
+
+
+type sh_flags =
+ SHF_WRITE
+ | SHF_ALLOC
+ | SHF_EXECINSTR
+;;
+
+
+let section_header
+ ~(shstring_table_fixup:fixup)
+ ~(shname_string_fixup:fixup)
+ ~(sh_type:sh_type)
+ ~(sh_flags:sh_flags list)
+ ~(section_fixup:fixup option)
+ ~(sh_addralign:int64)
+ ~(sh_entsize:int64)
+ ~(sh_link:int64 option)
+ : frag =
+ SEQ
+ [|
+ WORD (TY_i32, (SUB
+ ((F_POS shname_string_fixup),
+ (F_POS shstring_table_fixup))));
+ WORD (TY_u32, (IMM (match sh_type with
+ SHT_NULL -> 0L
+ | SHT_PROGBITS -> 1L
+ | SHT_SYMTAB -> 2L
+ | SHT_STRTAB -> 3L
+ | SHT_RELA -> 4L
+ | SHT_HASH -> 5L
+ | SHT_DYNAMIC -> 6L
+ | SHT_NOTE -> 7L
+ | SHT_NOBITS -> 8L
+ | SHT_REL -> 9L
+ | SHT_SHLIB -> 10L
+ | SHT_DYNSYM -> 11L)));
+ WORD (TY_u32, (IMM (fold_flags
+ (fun f -> match f with
+ SHF_WRITE -> 0x1L
+ | SHF_ALLOC -> 0x2L
+ | SHF_EXECINSTR -> 0x4L) sh_flags)));
+ WORD (TY_u32, (match section_fixup with
+ None -> (IMM 0L)
+ | Some s -> (M_POS s)));
+ WORD (TY_u32, (match section_fixup with
+ None -> (IMM 0L)
+ | Some s -> (F_POS s)));
+ WORD (TY_u32, (match section_fixup with
+ None -> (IMM 0L)
+ | Some s -> (F_SZ s)));
+ WORD (TY_u32, (IMM (match sh_link with
+ None -> 0L
+ | Some i -> i)));
+ WORD (TY_u32, (IMM 0L)); (* sh_info *)
+ WORD (TY_u32, (IMM sh_addralign));
+ WORD (TY_u32, (IMM sh_entsize));
+ |]
+;;
+
+
+type p_type =
+ PT_NULL
+ | PT_LOAD
+ | PT_DYNAMIC
+ | PT_INTERP
+ | PT_NOTE
+ | PT_SHLIB
+ | PT_PHDR
+;;
+
+
+type p_flag =
+ PF_X
+ | PF_W
+ | PF_R
+;;
+
+
+let program_header
+ ~(p_type:p_type)
+ ~(segment_fixup:fixup)
+ ~(p_flags:p_flag list)
+ ~(p_align:int64)
+ : frag =
+ SEQ
+ [|
+ WORD (TY_u32, (IMM (match p_type with
+ PT_NULL -> 0L
+ | PT_LOAD -> 1L
+ | PT_DYNAMIC -> 2L
+ | PT_INTERP -> 3L
+ | PT_NOTE -> 4L
+ | PT_SHLIB -> 5L
+ | PT_PHDR -> 6L)));
+ WORD (TY_u32, (F_POS segment_fixup));
+ WORD (TY_u32, (M_POS segment_fixup));
+ WORD (TY_u32, (M_POS segment_fixup));
+ WORD (TY_u32, (F_SZ segment_fixup));
+ WORD (TY_u32, (M_SZ segment_fixup));
+ WORD (TY_u32, (IMM (fold_flags
+ (fun f ->
+ match f with
+ PF_X -> 0x1L
+ | PF_W -> 0x2L
+ | PF_R -> 0x4L)
+ p_flags)));
+ WORD (TY_u32, (IMM p_align));
+ |]
+;;
+
+
+type st_bind =
+ STB_LOCAL
+ | STB_GLOBAL
+ | STB_WEAK
+;;
+
+
+type st_type =
+ STT_NOTYPE
+ | STT_OBJECT
+ | STT_FUNC
+ | STT_SECTION
+ | STT_FILE
+;;
+
+
+(* Special symbol-section indices *)
+let shn_UNDEF = 0L;;
+let shn_ABS = 0xfff1L;;
+let shn_ABS = 0xfff2L;;
+
+
+let symbol
+ ~(string_table_fixup:fixup)
+ ~(name_string_fixup:fixup)
+ ~(sym_target_fixup:fixup option)
+ ~(st_bind:st_bind)
+ ~(st_type:st_type)
+ ~(st_shndx:int64)
+ : frag =
+ let st_bind_num =
+ match st_bind with
+ STB_LOCAL -> 0L
+ | STB_GLOBAL -> 1L
+ | STB_WEAK -> 2L
+ in
+ let st_type_num =
+ match st_type with
+ STT_NOTYPE -> 0L
+ | STT_OBJECT -> 1L
+ | STT_FUNC -> 2L
+ | STT_SECTION -> 3L
+ | STT_FILE -> 4L
+ in
+ SEQ
+ [|
+ WORD (TY_u32, (SUB
+ ((F_POS name_string_fixup),
+ (F_POS string_table_fixup))));
+ WORD (TY_u32, (match sym_target_fixup with
+ None -> (IMM 0L)
+ | Some f -> (M_POS f)));
+ WORD (TY_u32, (match sym_target_fixup with
+ None -> (IMM 0L)
+ | Some f -> (M_SZ f)));
+ WORD (TY_u8, (* st_info *)
+ (OR
+ ((SLL ((IMM st_bind_num), 4)),
+ (AND ((IMM st_type_num), (IMM 0xfL))))));
+ WORD (TY_u8, (IMM 0L)); (* st_other *)
+ WORD (TY_u16, (IMM st_shndx));
+ |]
+;;
+
+type d_tag =
+ DT_NULL
+ | DT_NEEDED
+ | DT_PLTRELSZ
+ | DT_PLTGOT
+ | DT_HASH
+ | DT_STRTAB
+ | DT_SYMTAB
+ | DT_RELA
+ | DT_RELASZ
+ | DT_RELAENT
+ | DT_STRSZ
+ | DT_SYMENT
+ | DT_INIT
+ | DT_FINI
+ | DT_SONAME
+ | DT_RPATH
+ | DT_SYMBOLIC
+ | DT_REL
+ | DT_RELSZ
+ | DT_RELENT
+ | DT_PLTREL
+ | DT_DEBUG
+ | DT_TEXTREL
+ | DT_JMPREL
+ | DT_BIND_NOW
+ | DT_INIT_ARRAY
+ | DT_FINI_ARRAY
+ | DT_INIT_ARRAYSZ
+ | DT_FINI_ARRAYSZ
+ | DT_RUNPATH
+ | DT_FLAGS
+ | DT_ENCODING
+ | DT_PREINIT_ARRAY
+ | DT_PREINIT_ARRAYSZ
+;;
+
+type elf32_dyn = (d_tag * expr64);;
+
+let elf32_num_of_dyn_tag tag =
+ match tag with
+ DT_NULL -> 0L
+ | DT_NEEDED -> 1L
+ | DT_PLTRELSZ -> 2L
+ | DT_PLTGOT -> 3L
+ | DT_HASH -> 4L
+ | DT_STRTAB -> 5L
+ | DT_SYMTAB -> 6L
+ | DT_RELA -> 7L
+ | DT_RELASZ -> 8L
+ | DT_RELAENT -> 9L
+ | DT_STRSZ -> 10L
+ | DT_SYMENT -> 11L
+ | DT_INIT -> 12L
+ | DT_FINI -> 13L
+ | DT_SONAME -> 14L
+ | DT_RPATH -> 15L
+ | DT_SYMBOLIC -> 16L
+ | DT_REL -> 17L
+ | DT_RELSZ -> 18L
+ | DT_RELENT -> 19L
+ | DT_PLTREL -> 20L
+ | DT_DEBUG -> 21L
+ | DT_TEXTREL -> 22L
+ | DT_JMPREL -> 23L
+ | DT_BIND_NOW -> 24L
+ | DT_INIT_ARRAY -> 25L
+ | DT_FINI_ARRAY -> 26L
+ | DT_INIT_ARRAYSZ -> 27L
+ | DT_FINI_ARRAYSZ -> 28L
+ | DT_RUNPATH -> 29L
+ | DT_FLAGS -> 30L
+ | DT_ENCODING -> 31L
+ | DT_PREINIT_ARRAY -> 32L
+ | DT_PREINIT_ARRAYSZ -> 33L
+;;
+
+let elf32_dyn_frag d =
+ let (tag, expr) = d in
+ let tagval = elf32_num_of_dyn_tag tag in
+ SEQ [| WORD (TY_u32, (IMM tagval)); WORD (TY_u32, expr) |]
+;;
+
+type elf32_386_reloc_type =
+ R_386_NONE
+ | R_386_32
+ | R_386_PC32
+ | R_386_GOT32
+ | R_386_PLT32
+ | R_386_COPY
+ | R_386_GLOB_DAT
+ | R_386_JMP_SLOT
+ | R_386_RELATIVE
+ | R_386_GOTOFF
+ | R_386_GOTPC
+;;
+
+
+type elf32_386_rela =
+ { elf32_386_rela_type: elf32_386_reloc_type;
+ elf32_386_rela_offset: expr64;
+ elf32_386_rela_sym: expr64;