Update LLVM to r98631.
This commit is contained in:
parent
9e2446b38c
commit
0f448b8416
@ -1329,7 +1329,7 @@ uninstall-local::
|
||||
|
||||
# TOOLALIAS install.
|
||||
ifdef TOOLALIAS
|
||||
DestToolAlias = $(PROJ_bindir)/$(TOOLALIAS)$(EXEEXT)
|
||||
DestToolAlias = $(DESTDIR)$(PROJ_bindir)/$(TOOLALIAS)$(EXEEXT)
|
||||
|
||||
install-local:: $(DestToolAlias)
|
||||
|
||||
|
@ -1210,6 +1210,7 @@ AC_CHECK_HEADERS([malloc.h setjmp.h signal.h stdint.h termios.h unistd.h])
|
||||
AC_CHECK_HEADERS([utime.h windows.h])
|
||||
AC_CHECK_HEADERS([sys/mman.h sys/param.h sys/resource.h sys/time.h])
|
||||
AC_CHECK_HEADERS([sys/types.h sys/ioctl.h malloc/malloc.h mach/mach.h])
|
||||
AC_CHECK_HEADERS([valgrind/valgrind.h])
|
||||
if test "$ENABLE_THREADS" -eq 1 ; then
|
||||
AC_CHECK_HEADERS(pthread.h,
|
||||
AC_SUBST(HAVE_PTHREAD, 1),
|
||||
|
@ -67,6 +67,7 @@ check_include_file(sys/wait.h HAVE_SYS_WAIT_H)
|
||||
check_include_file(termios.h HAVE_TERMIOS_H)
|
||||
check_include_file(unistd.h HAVE_UNISTD_H)
|
||||
check_include_file(utime.h HAVE_UTIME_H)
|
||||
check_include_file(valgrind/valgrind.h HAVE_VALGRIND_VALGRIND_H)
|
||||
check_include_file(windows.h HAVE_WINDOWS_H)
|
||||
|
||||
# library checks
|
||||
|
@ -1,8 +1,8 @@
|
||||
set(MSVC_LIB_DEPS_LLVMARMAsmParser LLVMARMInfo LLVMMCParser LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMARMAsmPrinter LLVMARMCodeGen LLVMARMInfo LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMARMAsmPrinter LLVMARMCodeGen LLVMARMInfo LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMARMCodeGen LLVMARMInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMARMInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMAlphaAsmPrinter LLVMAlphaInfo LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMAlphaAsmPrinter LLVMAlphaInfo LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMAlphaCodeGen LLVMAlphaInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMAlphaInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMAnalysis LLVMCore LLVMSupport LLVMSystem LLVMTarget)
|
||||
@ -11,12 +11,12 @@ set(MSVC_LIB_DEPS_LLVMAsmParser LLVMCore LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMAsmPrinter LLVMAnalysis LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMBitReader LLVMCore LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMBitWriter LLVMCore LLVMSupport LLVMSystem)
|
||||
set(MSVC_LIB_DEPS_LLVMBlackfinAsmPrinter LLVMAsmPrinter LLVMBlackfinInfo LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMBlackfinAsmPrinter LLVMAsmPrinter LLVMBlackfinInfo LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMBlackfinCodeGen LLVMBlackfinInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMBlackfinInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMCBackend LLVMAnalysis LLVMCBackendInfo LLVMCodeGen LLVMCore LLVMMC LLVMScalarOpts LLVMSupport LLVMSystem LLVMTarget LLVMTransformUtils LLVMipa)
|
||||
set(MSVC_LIB_DEPS_LLVMCBackendInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMCellSPUAsmPrinter LLVMAsmPrinter LLVMCellSPUInfo LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMCellSPUAsmPrinter LLVMAsmPrinter LLVMCellSPUInfo LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMCellSPUCodeGen LLVMCellSPUInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMCellSPUInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMCodeGen LLVMAnalysis LLVMCore LLVMMC LLVMScalarOpts LLVMSupport LLVMSystem LLVMTarget LLVMTransformUtils)
|
||||
@ -29,41 +29,44 @@ set(MSVC_LIB_DEPS_LLVMInstrumentation LLVMAnalysis LLVMCore LLVMSupport LLVMSyst
|
||||
set(MSVC_LIB_DEPS_LLVMInterpreter LLVMCodeGen LLVMCore LLVMExecutionEngine LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMJIT LLVMAnalysis LLVMCodeGen LLVMCore LLVMExecutionEngine LLVMMC LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMLinker LLVMArchive LLVMBitReader LLVMCore LLVMSupport LLVMSystem)
|
||||
set(MSVC_LIB_DEPS_LLVMMBlazeAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMBlazeCodeGen LLVMMBlazeInfo LLVMMC LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMMBlazeCodeGen LLVMCodeGen LLVMCore LLVMMBlazeInfo LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMMBlazeInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMMC LLVMSupport LLVMSystem)
|
||||
set(MSVC_LIB_DEPS_LLVMMCParser LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMMSIL LLVMAnalysis LLVMCodeGen LLVMCore LLVMMSILInfo LLVMScalarOpts LLVMSupport LLVMTarget LLVMTransformUtils LLVMipa)
|
||||
set(MSVC_LIB_DEPS_LLVMMSILInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMMSP430AsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMSP430Info LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMMSP430AsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMSP430Info LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMMSP430CodeGen LLVMCodeGen LLVMCore LLVMMC LLVMMSP430Info LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMMSP430Info LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMMipsAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMipsCodeGen LLVMMipsInfo LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMMipsAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMipsCodeGen LLVMMipsInfo LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMMipsCodeGen LLVMCodeGen LLVMCore LLVMMC LLVMMipsInfo LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMMipsInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMPIC16 LLVMAnalysis LLVMCodeGen LLVMCore LLVMMC LLVMPIC16Info LLVMSelectionDAG LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMPIC16AsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPIC16 LLVMPIC16Info LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMPIC16Info LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMPowerPCAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPowerPCInfo LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMPowerPCAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPowerPCInfo LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMPowerPCCodeGen LLVMCodeGen LLVMCore LLVMMC LLVMPowerPCInfo LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMPowerPCInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMScalarOpts LLVMAnalysis LLVMCore LLVMInstCombine LLVMSupport LLVMSystem LLVMTarget LLVMTransformUtils)
|
||||
set(MSVC_LIB_DEPS_LLVMSelectionDAG LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMSparcAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSparcInfo LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMSelectionDAG LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMSparcAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSparcInfo LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMSparcCodeGen LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSparcInfo LLVMSupport LLVMSystem LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMSparcInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMSupport LLVMSystem)
|
||||
set(MSVC_LIB_DEPS_LLVMSystem )
|
||||
set(MSVC_LIB_DEPS_LLVMSystemZAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMSystemZInfo LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMSystemZAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystemZInfo LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMSystemZCodeGen LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystemZInfo LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMSystemZInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMTarget LLVMCore LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMTransformUtils LLVMAnalysis LLVMCore LLVMSupport LLVMSystem LLVMTarget LLVMipa)
|
||||
set(MSVC_LIB_DEPS_LLVMX86AsmParser LLVMMC LLVMMCParser LLVMSupport LLVMX86Info)
|
||||
set(MSVC_LIB_DEPS_LLVMX86AsmPrinter LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget LLVMX86CodeGen LLVMX86Info)
|
||||
set(MSVC_LIB_DEPS_LLVMX86AsmParser LLVMMC LLVMMCParser LLVMSupport LLVMTarget LLVMX86Info)
|
||||
set(MSVC_LIB_DEPS_LLVMX86AsmPrinter LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMTarget LLVMX86CodeGen LLVMX86Info)
|
||||
set(MSVC_LIB_DEPS_LLVMX86CodeGen LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget LLVMX86Info)
|
||||
set(MSVC_LIB_DEPS_LLVMX86Disassembler LLVMMC LLVMSupport LLVMX86Info)
|
||||
set(MSVC_LIB_DEPS_LLVMX86Info LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMXCore LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget LLVMXCoreInfo)
|
||||
set(MSVC_LIB_DEPS_LLVMXCoreAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMSystem LLVMTarget LLVMXCoreInfo)
|
||||
set(MSVC_LIB_DEPS_LLVMXCoreAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMTarget LLVMXCoreInfo)
|
||||
set(MSVC_LIB_DEPS_LLVMXCoreInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMipa LLVMAnalysis LLVMCore LLVMSupport LLVMSystem)
|
||||
set(MSVC_LIB_DEPS_LLVMipo LLVMAnalysis LLVMCore LLVMSupport LLVMSystem LLVMTarget LLVMTransformUtils LLVMipa)
|
||||
|
169
configure
vendored
169
configure
vendored
@ -16177,6 +16177,175 @@ fi
|
||||
|
||||
done
|
||||
|
||||
|
||||
for ac_header in valgrind/valgrind.h
|
||||
do
|
||||
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
|
||||
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
|
||||
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
fi
|
||||
ac_res=`eval echo '${'$as_ac_Header'}'`
|
||||
{ echo "$as_me:$LINENO: result: $ac_res" >&5
|
||||
echo "${ECHO_T}$ac_res" >&6; }
|
||||
else
|
||||
# Is the header compilable?
|
||||
{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
|
||||
echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
$ac_includes_default
|
||||
#include <$ac_header>
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
|
||||
{ (case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest.$ac_objext'
|
||||
{ (case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
ac_header_compiler=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_header_compiler=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
|
||||
echo "${ECHO_T}$ac_header_compiler" >&6; }
|
||||
|
||||
# Is the header present?
|
||||
{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
|
||||
echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <$ac_header>
|
||||
_ACEOF
|
||||
if { (ac_try="$ac_cpp conftest.$ac_ext"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } >/dev/null; then
|
||||
if test -s conftest.err; then
|
||||
ac_cpp_err=$ac_c_preproc_warn_flag
|
||||
ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
|
||||
else
|
||||
ac_cpp_err=
|
||||
fi
|
||||
else
|
||||
ac_cpp_err=yes
|
||||
fi
|
||||
if test -z "$ac_cpp_err"; then
|
||||
ac_header_preproc=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_header_preproc=no
|
||||
fi
|
||||
|
||||
rm -f conftest.err conftest.$ac_ext
|
||||
{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
|
||||
echo "${ECHO_T}$ac_header_preproc" >&6; }
|
||||
|
||||
# So? What about this header?
|
||||
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
|
||||
yes:no: )
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
|
||||
echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
|
||||
echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
|
||||
ac_header_preproc=yes
|
||||
;;
|
||||
no:yes:* )
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
|
||||
echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
|
||||
echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
|
||||
echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
|
||||
echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
|
||||
echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
|
||||
echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
|
||||
( cat <<\_ASBOX
|
||||
## ----------------------------------- ##
|
||||
## Report this to llvmbugs@cs.uiuc.edu ##
|
||||
## ----------------------------------- ##
|
||||
_ASBOX
|
||||
) | sed "s/^/$as_me: WARNING: /" >&2
|
||||
;;
|
||||
esac
|
||||
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
|
||||
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
|
||||
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
eval "$as_ac_Header=\$ac_header_preproc"
|
||||
fi
|
||||
ac_res=`eval echo '${'$as_ac_Header'}'`
|
||||
{ echo "$as_me:$LINENO: result: $ac_res" >&5
|
||||
echo "${ECHO_T}$ac_res" >&6; }
|
||||
|
||||
fi
|
||||
if test `eval echo '${'$as_ac_Header'}'` = yes; then
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
if test "$ENABLE_THREADS" -eq 1 ; then
|
||||
|
||||
for ac_header in pthread.h
|
||||
|
@ -1679,7 +1679,8 @@ $ llc -regalloc=linearscan file.bc -o ln.s;
|
||||
supported on x86/x86-64 and PowerPC. It is performed if:</p>
|
||||
|
||||
<ul>
|
||||
<li>Caller and callee have the calling convention <tt>fastcc</tt>.</li>
|
||||
<li>Caller and callee have the calling convention <tt>fastcc</tt> or
|
||||
<tt>cc 10</tt> (GHC call convention).</li>
|
||||
|
||||
<li>The call is a tail call - in tail position (ret immediately follows call
|
||||
and ret uses value of call or is void).</li>
|
||||
@ -2161,7 +2162,7 @@ MOVSX32rm16 -> movsx, 32-bit register, 16-bit memory
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-03-08 22:05:02 +0100 (Mon, 08 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-11 01:22:57 +0100 (Thu, 11 Mar 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -255,6 +255,12 @@
|
||||
<li><a href="#int_umul_overflow">'<tt>llvm.umul.with.overflow.*</tt> Intrinsics</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#int_fp16">Half Precision Floating Point Intrinsics</a>
|
||||
<ol>
|
||||
<li><a href="#int_convert_to_fp16">'<tt>llvm.convert.to.fp16</tt>' Intrinsic</a></li>
|
||||
<li><a href="#int_convert_from_fp16">'<tt>llvm.convert.from.fp16</tt>' Intrinsic</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#int_debugger">Debugger intrinsics</a></li>
|
||||
<li><a href="#int_eh">Exception Handling intrinsics</a></li>
|
||||
<li><a href="#int_trampoline">Trampoline Intrinsic</a>
|
||||
@ -691,9 +697,9 @@ define i32 @main() { <i>; i32()* </i>
|
||||
target, without having to conform to an externally specified ABI
|
||||
(Application Binary Interface).
|
||||
<a href="CodeGenerator.html#tailcallopt">Tail calls can only be optimized
|
||||
when this convention is used.</a> This calling convention does not
|
||||
support varargs and requires the prototype of all callees to exactly match
|
||||
the prototype of the function definition.</dd>
|
||||
when this or the GHC convention is used.</a> This calling convention
|
||||
does not support varargs and requires the prototype of all callees to
|
||||
exactly match the prototype of the function definition.</dd>
|
||||
|
||||
<dt><b>"<tt>coldcc</tt>" - The cold calling convention</b>:</dt>
|
||||
<dd>This calling convention attempts to make code in the caller as efficient
|
||||
@ -703,6 +709,26 @@ define i32 @main() { <i>; i32()* </i>
|
||||
does not support varargs and requires the prototype of all callees to
|
||||
exactly match the prototype of the function definition.</dd>
|
||||
|
||||
<dt><b>"<tt>cc <em>10</em></tt>" - GHC convention</b>:</dt>
|
||||
<dd>This calling convention has been implemented specifically for use by the
|
||||
<a href="http://www.haskell.org/ghc">Glasgow Haskell Compiler (GHC)</a>.
|
||||
It passes everything in registers, going to extremes to achieve this by
|
||||
disabling callee save registers. This calling convention should not be
|
||||
used lightly but only for specific situations such as an alternative to
|
||||
the <em>register pinning</em> performance technique often used when
|
||||
implementing functional programming languages.At the moment only X86
|
||||
supports this convention and it has the following limitations:
|
||||
<ul>
|
||||
<li>On <em>X86-32</em> only supports up to 4 bit type parameters. No
|
||||
floating point types are supported.</li>
|
||||
<li>On <em>X86-64</em> only supports up to 10 bit type parameters and
|
||||
6 floating point parameters.</li>
|
||||
</ul>
|
||||
This calling convention supports
|
||||
<a href="CodeGenerator.html#tailcallopt">tail call optimization</a> but
|
||||
requires both the caller and callee are using it.
|
||||
</dd>
|
||||
|
||||
<dt><b>"<tt>cc <<em>n</em>></tt>" - Numbered convention</b>:</dt>
|
||||
<dd>Any calling convention may be specified by number, allowing
|
||||
target-specific calling conventions to be used. Target specific calling
|
||||
@ -6586,6 +6612,97 @@ LLVM</a>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<a name="int_fp16">Half Precision Floating Point Intrinsics</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>Half precision floating point is a storage-only format. This means that it is
|
||||
a dense encoding (in memory) but does not support computation in the
|
||||
format.</p>
|
||||
|
||||
<p>This means that code must first load the half-precision floating point
|
||||
value as an i16, then convert it to float with <a
|
||||
href="#int_convert_from_fp16"><tt>llvm.convert.from.fp16</tt></a>.
|
||||
Computation can then be performed on the float value (including extending to
|
||||
double etc). To store the value back to memory, it is first converted to
|
||||
float if needed, then converted to i16 with
|
||||
<a href="#int_convert_to_fp16"><tt>llvm.convert.to.fp16</tt></a>, then
|
||||
storing as an i16 value.</p>
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="int_convert_to_fp16">'<tt>llvm.convert.to.fp16</tt>' Intrinsic</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<h5>Syntax:</h5>
|
||||
<pre>
|
||||
declare i16 @llvm.convert.to.fp16(f32 %a)
|
||||
</pre>
|
||||
|
||||
<h5>Overview:</h5>
|
||||
<p>The '<tt>llvm.convert.to.fp16</tt>' intrinsic function performs
|
||||
a conversion from single precision floating point format to half precision
|
||||
floating point format.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The intrinsic function contains single argument - the value to be
|
||||
converted.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
<p>The '<tt>llvm.convert.to.fp16</tt>' intrinsic function performs
|
||||
a conversion from single precision floating point format to half precision
|
||||
floating point format. The return value is an <tt>i16</tt> which
|
||||
contains the converted number.</p>
|
||||
|
||||
<h5>Examples:</h5>
|
||||
<pre>
|
||||
%res = call i16 @llvm.convert.to.fp16(f32 %a)
|
||||
store i16 %res, i16* @x, align 2
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="int_convert_from_fp16">'<tt>llvm.convert.from.fp16</tt>' Intrinsic</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<h5>Syntax:</h5>
|
||||
<pre>
|
||||
declare f32 @llvm.convert.from.fp16(i16 %a)
|
||||
</pre>
|
||||
|
||||
<h5>Overview:</h5>
|
||||
<p>The '<tt>llvm.convert.from.fp16</tt>' intrinsic function performs
|
||||
a conversion from half precision floating point format to single precision
|
||||
floating point format.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The intrinsic function contains single argument - the value to be
|
||||
converted.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
<p>The '<tt>llvm.convert.from.fp16</tt>' intrinsic function performs a
|
||||
conversion from half single precision floating point format to single
|
||||
precision floating point format. The input half-float value is represented by
|
||||
an <tt>i16</tt> value.</p>
|
||||
|
||||
<h5>Examples:</h5>
|
||||
<pre>
|
||||
%a = load i16* @x, align 2
|
||||
%res = call f32 @llvm.convert.from.fp16(i16 %a)
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<a name="int_debugger">Debugger Intrinsics</a>
|
||||
@ -7473,7 +7590,7 @@ LLVM</a>.</p>
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-03-08 22:05:02 +0100 (Mon, 08 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-15 05:12:21 +0100 (Mon, 15 Mar 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
22
examples/OCaml-Kaleidoscope/Chapter2/Makefile
Normal file
22
examples/OCaml-Kaleidoscope/Chapter2/Makefile
Normal file
@ -0,0 +1,22 @@
|
||||
##===- examples/OCaml-Kaleidoscope/Chapter2/Makefile -------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 2.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL := ../../..
|
||||
TOOLNAME := OCaml-Kaleidoscope-Ch2
|
||||
EXAMPLE_TOOL := 1
|
||||
UsedComponents := core
|
||||
UsedOcamLibs := llvm
|
||||
|
||||
OCAMLCFLAGS += -pp camlp4of
|
||||
|
||||
include $(LEVEL)/bindings/ocaml/Makefile.ocaml
|
1
examples/OCaml-Kaleidoscope/Chapter2/_tags
Normal file
1
examples/OCaml-Kaleidoscope/Chapter2/_tags
Normal file
@ -0,0 +1 @@
|
||||
<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
|
25
examples/OCaml-Kaleidoscope/Chapter2/ast.ml
Normal file
25
examples/OCaml-Kaleidoscope/Chapter2/ast.ml
Normal file
@ -0,0 +1,25 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Abstract Syntax Tree (aka Parse Tree)
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(* expr - Base type for all expression nodes. *)
|
||||
type expr =
|
||||
(* variant for numeric literals like "1.0". *)
|
||||
| Number of float
|
||||
|
||||
(* variant for referencing a variable, like "a". *)
|
||||
| Variable of string
|
||||
|
||||
(* variant for a binary operator. *)
|
||||
| Binary of char * expr * expr
|
||||
|
||||
(* variant for function calls. *)
|
||||
| Call of string * expr array
|
||||
|
||||
(* proto - This type represents the "prototype" for a function, which captures
|
||||
* its name, and its argument names (thus implicitly the number of arguments the
|
||||
* function takes). *)
|
||||
type proto = Prototype of string * string array
|
||||
|
||||
(* func - This type represents a function definition itself. *)
|
||||
type func = Function of proto * expr
|
52
examples/OCaml-Kaleidoscope/Chapter2/lexer.ml
Normal file
52
examples/OCaml-Kaleidoscope/Chapter2/lexer.ml
Normal file
@ -0,0 +1,52 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Lexer
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
let rec lex = parser
|
||||
(* Skip any whitespace. *)
|
||||
| [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
|
||||
|
||||
(* identifier: [a-zA-Z][a-zA-Z0-9] *)
|
||||
| [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
|
||||
let buffer = Buffer.create 1 in
|
||||
Buffer.add_char buffer c;
|
||||
lex_ident buffer stream
|
||||
|
||||
(* number: [0-9.]+ *)
|
||||
| [< ' ('0' .. '9' as c); stream >] ->
|
||||
let buffer = Buffer.create 1 in
|
||||
Buffer.add_char buffer c;
|
||||
lex_number buffer stream
|
||||
|
||||
(* Comment until end of line. *)
|
||||
| [< ' ('#'); stream >] ->
|
||||
lex_comment stream
|
||||
|
||||
(* Otherwise, just return the character as its ascii value. *)
|
||||
| [< 'c; stream >] ->
|
||||
[< 'Token.Kwd c; lex stream >]
|
||||
|
||||
(* end of stream. *)
|
||||
| [< >] -> [< >]
|
||||
|
||||
and lex_number buffer = parser
|
||||
| [< ' ('0' .. '9' | '.' as c); stream >] ->
|
||||
Buffer.add_char buffer c;
|
||||
lex_number buffer stream
|
||||
| [< stream=lex >] ->
|
||||
[< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
|
||||
|
||||
and lex_ident buffer = parser
|
||||
| [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
|
||||
Buffer.add_char buffer c;
|
||||
lex_ident buffer stream
|
||||
| [< stream=lex >] ->
|
||||
match Buffer.contents buffer with
|
||||
| "def" -> [< 'Token.Def; stream >]
|
||||
| "extern" -> [< 'Token.Extern; stream >]
|
||||
| id -> [< 'Token.Ident id; stream >]
|
||||
|
||||
and lex_comment = parser
|
||||
| [< ' ('\n'); stream=lex >] -> stream
|
||||
| [< 'c; e=lex_comment >] -> e
|
||||
| [< >] -> [< >]
|
122
examples/OCaml-Kaleidoscope/Chapter2/parser.ml
Normal file
122
examples/OCaml-Kaleidoscope/Chapter2/parser.ml
Normal file
@ -0,0 +1,122 @@
|
||||
(*===---------------------------------------------------------------------===
|
||||
* Parser
|
||||
*===---------------------------------------------------------------------===*)
|
||||
|
||||
(* binop_precedence - This holds the precedence for each binary operator that is
|
||||
* defined *)
|
||||
let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
|
||||
|
||||
(* precedence - Get the precedence of the pending binary operator token. *)
|
||||
let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
|
||||
|
||||
(* primary
|
||||
* ::= identifier
|
||||
* ::= numberexpr
|
||||
* ::= parenexpr *)
|
||||
let rec parse_primary = parser
|
||||
(* numberexpr ::= number *)
|
||||
| [< 'Token.Number n >] -> Ast.Number n
|
||||
|
||||
(* parenexpr ::= '(' expression ')' *)
|
||||
| [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
|
||||
|
||||
(* identifierexpr
|
||||
* ::= identifier
|
||||
* ::= identifier '(' argumentexpr ')' *)
|
||||
| [< 'Token.Ident id; stream >] ->
|
||||
let rec parse_args accumulator = parser
|
||||
| [< e=parse_expr; stream >] ->
|
||||
begin parser
|
||||
| [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
|
||||
| [< >] -> e :: accumulator
|
||||
end stream
|
||||
| [< >] -> accumulator
|
||||
in
|
||||
let rec parse_ident id = parser
|
||||
(* Call. *)
|
||||
| [< 'Token.Kwd '(';
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')'">] ->
|
||||
Ast.Call (id, Array.of_list (List.rev args))
|
||||
|
||||
(* Simple variable ref. *)
|
||||
| [< >] -> Ast.Variable id
|
||||
in
|
||||
parse_ident id stream
|
||||
|
||||
| [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
|
||||
|
||||
(* binoprhs
|
||||
* ::= ('+' primary)* *)
|
||||
and parse_bin_rhs expr_prec lhs stream =
|
||||
match Stream.peek stream with
|
||||
(* If this is a binop, find its precedence. *)
|
||||
| Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
|
||||
let token_prec = precedence c in
|
||||
|
||||
(* If this is a binop that binds at least as tightly as the current binop,
|
||||
* consume it, otherwise we are done. *)
|
||||
if token_prec < expr_prec then lhs else begin
|
||||
(* Eat the binop. *)
|
||||
Stream.junk stream;
|
||||
|
||||
(* Parse the primary expression after the binary operator. *)
|
||||
let rhs = parse_primary stream in
|
||||
|
||||
(* Okay, we know this is a binop. *)
|
||||
let rhs =
|
||||
match Stream.peek stream with
|
||||
| Some (Token.Kwd c2) ->
|
||||
(* If BinOp binds less tightly with rhs than the operator after
|
||||
* rhs, let the pending operator take rhs as its lhs. *)
|
||||
let next_prec = precedence c2 in
|
||||
if token_prec < next_prec
|
||||
then parse_bin_rhs (token_prec + 1) rhs stream
|
||||
else rhs
|
||||
| _ -> rhs
|
||||
in
|
||||
|
||||
(* Merge lhs/rhs. *)
|
||||
let lhs = Ast.Binary (c, lhs, rhs) in
|
||||
parse_bin_rhs expr_prec lhs stream
|
||||
end
|
||||
| _ -> lhs
|
||||
|
||||
(* expression
|
||||
* ::= primary binoprhs *)
|
||||
and parse_expr = parser
|
||||
| [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
|
||||
|
||||
(* prototype
|
||||
* ::= id '(' id* ')' *)
|
||||
let parse_prototype =
|
||||
let rec parse_args accumulator = parser
|
||||
| [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
|
||||
| [< >] -> accumulator
|
||||
in
|
||||
|
||||
parser
|
||||
| [< 'Token.Ident id;
|
||||
'Token.Kwd '(' ?? "expected '(' in prototype";
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
|
||||
(* success. *)
|
||||
Ast.Prototype (id, Array.of_list (List.rev args))
|
||||
|
||||
| [< >] ->
|
||||
raise (Stream.Error "expected function name in prototype")
|
||||
|
||||
(* definition ::= 'def' prototype expression *)
|
||||
let parse_definition = parser
|
||||
| [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
|
||||
Ast.Function (p, e)
|
||||
|
||||
(* toplevelexpr ::= expression *)
|
||||
let parse_toplevel = parser
|
||||
| [< e=parse_expr >] ->
|
||||
(* Make an anonymous proto. *)
|
||||
Ast.Function (Ast.Prototype ("", [||]), e)
|
||||
|
||||
(* external ::= 'extern' prototype *)
|
||||
let parse_extern = parser
|
||||
| [< 'Token.Extern; e=parse_prototype >] -> e
|
15
examples/OCaml-Kaleidoscope/Chapter2/token.ml
Normal file
15
examples/OCaml-Kaleidoscope/Chapter2/token.ml
Normal file
@ -0,0 +1,15 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Lexer Tokens
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
|
||||
* these others for known things. *)
|
||||
type token =
|
||||
(* commands *)
|
||||
| Def | Extern
|
||||
|
||||
(* primary *)
|
||||
| Ident of string | Number of float
|
||||
|
||||
(* unknown *)
|
||||
| Kwd of char
|
34
examples/OCaml-Kaleidoscope/Chapter2/toplevel.ml
Normal file
34
examples/OCaml-Kaleidoscope/Chapter2/toplevel.ml
Normal file
@ -0,0 +1,34 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Top-Level parsing and JIT Driver
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(* top ::= definition | external | expression | ';' *)
|
||||
let rec main_loop stream =
|
||||
match Stream.peek stream with
|
||||
| None -> ()
|
||||
|
||||
(* ignore top-level semicolons. *)
|
||||
| Some (Token.Kwd ';') ->
|
||||
Stream.junk stream;
|
||||
main_loop stream
|
||||
|
||||
| Some token ->
|
||||
begin
|
||||
try match token with
|
||||
| Token.Def ->
|
||||
ignore(Parser.parse_definition stream);
|
||||
print_endline "parsed a function definition.";
|
||||
| Token.Extern ->
|
||||
ignore(Parser.parse_extern stream);
|
||||
print_endline "parsed an extern.";
|
||||
| _ ->
|
||||
(* Evaluate a top-level expression into an anonymous function. *)
|
||||
ignore(Parser.parse_toplevel stream);
|
||||
print_endline "parsed a top-level expr";
|
||||
with Stream.Error s ->
|
||||
(* Skip token for error recovery. *)
|
||||
Stream.junk stream;
|
||||
print_endline s;
|
||||
end;
|
||||
print_string "ready> "; flush stdout;
|
||||
main_loop stream
|
21
examples/OCaml-Kaleidoscope/Chapter2/toy.ml
Normal file
21
examples/OCaml-Kaleidoscope/Chapter2/toy.ml
Normal file
@ -0,0 +1,21 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Main driver code.
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
let main () =
|
||||
(* Install standard binary operators.
|
||||
* 1 is the lowest precedence. *)
|
||||
Hashtbl.add Parser.binop_precedence '<' 10;
|
||||
Hashtbl.add Parser.binop_precedence '+' 20;
|
||||
Hashtbl.add Parser.binop_precedence '-' 20;
|
||||
Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *)
|
||||
|
||||
(* Prime the first token. *)
|
||||
print_string "ready> "; flush stdout;
|
||||
let stream = Lexer.lex (Stream.of_channel stdin) in
|
||||
|
||||
(* Run the main "interpreter loop" now. *)
|
||||
Toplevel.main_loop stream;
|
||||
;;
|
||||
|
||||
main ()
|
24
examples/OCaml-Kaleidoscope/Chapter3/Makefile
Normal file
24
examples/OCaml-Kaleidoscope/Chapter3/Makefile
Normal file
@ -0,0 +1,24 @@
|
||||
##===- examples/OCaml-Kaleidoscope/Chapter3/Makefile -------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 3.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL := ../../..
|
||||
TOOLNAME := OCaml-Kaleidoscope-Ch3
|
||||
EXAMPLE_TOOL := 1
|
||||
UsedComponents := core
|
||||
UsedOcamLibs := llvm llvm_analysis
|
||||
|
||||
OCAMLCFLAGS += -pp camlp4of
|
||||
|
||||
ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml
|
||||
|
||||
include $(LEVEL)/bindings/ocaml/Makefile.ocaml
|
2
examples/OCaml-Kaleidoscope/Chapter3/_tags
Normal file
2
examples/OCaml-Kaleidoscope/Chapter3/_tags
Normal file
@ -0,0 +1,2 @@
|
||||
<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
|
||||
<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
|
25
examples/OCaml-Kaleidoscope/Chapter3/ast.ml
Normal file
25
examples/OCaml-Kaleidoscope/Chapter3/ast.ml
Normal file
@ -0,0 +1,25 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Abstract Syntax Tree (aka Parse Tree)
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(* expr - Base type for all expression nodes. *)
|
||||
type expr =
|
||||
(* variant for numeric literals like "1.0". *)
|
||||
| Number of float
|
||||
|
||||
(* variant for referencing a variable, like "a". *)
|
||||
| Variable of string
|
||||
|
||||
(* variant for a binary operator. *)
|
||||
| Binary of char * expr * expr
|
||||
|
||||
(* variant for function calls. *)
|
||||
| Call of string * expr array
|
||||
|
||||
(* proto - This type represents the "prototype" for a function, which captures
|
||||
* its name, and its argument names (thus implicitly the number of arguments the
|
||||
* function takes). *)
|
||||
type proto = Prototype of string * string array
|
||||
|
||||
(* func - This type represents a function definition itself. *)
|
||||
type func = Function of proto * expr
|
100
examples/OCaml-Kaleidoscope/Chapter3/codegen.ml
Normal file
100
examples/OCaml-Kaleidoscope/Chapter3/codegen.ml
Normal file
@ -0,0 +1,100 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Code Generation
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
|
||||
exception Error of string
|
||||
|
||||
let context = global_context ()
|
||||
let the_module = create_module context "my cool jit"
|
||||
let builder = builder context
|
||||
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
|
||||
let double_type = double_type context
|
||||
|
||||
let rec codegen_expr = function
|
||||
| Ast.Number n -> const_float double_type n
|
||||
| Ast.Variable name ->
|
||||
(try Hashtbl.find named_values name with
|
||||
| Not_found -> raise (Error "unknown variable name"))
|
||||
| Ast.Binary (op, lhs, rhs) ->
|
||||
let lhs_val = codegen_expr lhs in
|
||||
let rhs_val = codegen_expr rhs in
|
||||
begin
|
||||
match op with
|
||||
| '+' -> build_add lhs_val rhs_val "addtmp" builder
|
||||
| '-' -> build_sub lhs_val rhs_val "subtmp" builder
|
||||
| '*' -> build_mul lhs_val rhs_val "multmp" builder
|
||||
| '<' ->
|
||||
(* Convert bool 0/1 to double 0.0 or 1.0 *)
|
||||
let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
|
||||
build_uitofp i double_type "booltmp" builder
|
||||
| _ -> raise (Error "invalid binary operator")
|
||||
end
|
||||
| Ast.Call (callee, args) ->
|
||||
(* Look up the name in the module table. *)
|
||||
let callee =
|
||||
match lookup_function callee the_module with
|
||||
| Some callee -> callee
|
||||
| None -> raise (Error "unknown function referenced")
|
||||
in
|
||||
let params = params callee in
|
||||
|
||||
(* If argument mismatch error. *)
|
||||
if Array.length params == Array.length args then () else
|
||||
raise (Error "incorrect # arguments passed");
|
||||
let args = Array.map codegen_expr args in
|
||||
build_call callee args "calltmp" builder
|
||||
|
||||
let codegen_proto = function
|
||||
| Ast.Prototype (name, args) ->
|
||||
(* Make the function type: double(double,double) etc. *)
|
||||
let doubles = Array.make (Array.length args) double_type in
|
||||
let ft = function_type double_type doubles in
|
||||
let f =
|
||||
match lookup_function name the_module with
|
||||
| None -> declare_function name ft the_module
|
||||
|
||||
(* If 'f' conflicted, there was already something named 'name'. If it
|
||||
* has a body, don't allow redefinition or reextern. *)
|
||||
| Some f ->
|
||||
(* If 'f' already has a body, reject this. *)
|
||||
if block_begin f <> At_end f then
|
||||
raise (Error "redefinition of function");
|
||||
|
||||
(* If 'f' took a different number of arguments, reject. *)
|
||||
if element_type (type_of f) <> ft then
|
||||
raise (Error "redefinition of function with different # args");
|
||||
f
|
||||
in
|
||||
|
||||
(* Set names for all arguments. *)
|
||||
Array.iteri (fun i a ->
|
||||
let n = args.(i) in
|
||||
set_value_name n a;
|
||||
Hashtbl.add named_values n a;
|
||||
) (params f);
|
||||
f
|
||||
|
||||
let codegen_func = function
|
||||
| Ast.Function (proto, body) ->
|
||||
Hashtbl.clear named_values;
|
||||
let the_function = codegen_proto proto in
|
||||
|
||||
(* Create a new basic block to start insertion into. *)
|
||||
let bb = append_block context "entry" the_function in
|
||||
position_at_end bb builder;
|
||||
|
||||
try
|
||||
let ret_val = codegen_expr body in
|
||||
|
||||
(* Finish off the function. *)
|
||||
let _ = build_ret ret_val builder in
|
||||
|
||||
(* Validate the generated code, checking for consistency. *)
|
||||
Llvm_analysis.assert_valid_function the_function;
|
||||
|
||||
the_function
|
||||
with e ->
|
||||
delete_function the_function;
|
||||
raise e
|
52
examples/OCaml-Kaleidoscope/Chapter3/lexer.ml
Normal file
52
examples/OCaml-Kaleidoscope/Chapter3/lexer.ml
Normal file
@ -0,0 +1,52 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Lexer
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
let rec lex = parser
|
||||
(* Skip any whitespace. *)
|
||||
| [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
|
||||
|
||||
(* identifier: [a-zA-Z][a-zA-Z0-9] *)
|
||||
| [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
|
||||
let buffer = Buffer.create 1 in
|
||||
Buffer.add_char buffer c;
|
||||
lex_ident buffer stream
|
||||
|
||||
(* number: [0-9.]+ *)
|
||||
| [< ' ('0' .. '9' as c); stream >] ->
|
||||
let buffer = Buffer.create 1 in
|
||||
Buffer.add_char buffer c;
|
||||
lex_number buffer stream
|
||||
|
||||
(* Comment until end of line. *)
|
||||
| [< ' ('#'); stream >] ->
|
||||
lex_comment stream
|
||||
|
||||
(* Otherwise, just return the character as its ascii value. *)
|
||||
| [< 'c; stream >] ->
|
||||
[< 'Token.Kwd c; lex stream >]
|
||||
|
||||
(* end of stream. *)
|
||||
| [< >] -> [< >]
|
||||
|
||||
and lex_number buffer = parser
|
||||
| [< ' ('0' .. '9' | '.' as c); stream >] ->
|
||||
Buffer.add_char buffer c;
|
||||
lex_number buffer stream
|
||||
| [< stream=lex >] ->
|
||||
[< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
|
||||
|
||||
and lex_ident buffer = parser
|
||||
| [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
|
||||
Buffer.add_char buffer c;
|
||||
lex_ident buffer stream
|
||||
| [< stream=lex >] ->
|
||||
match Buffer.contents buffer with
|
||||
| "def" -> [< 'Token.Def; stream >]
|
||||
| "extern" -> [< 'Token.Extern; stream >]
|
||||
| id -> [< 'Token.Ident id; stream >]
|
||||
|
||||
and lex_comment = parser
|
||||
| [< ' ('\n'); stream=lex >] -> stream
|
||||
| [< 'c; e=lex_comment >] -> e
|
||||
| [< >] -> [< >]
|
6
examples/OCaml-Kaleidoscope/Chapter3/myocamlbuild.ml
Normal file
6
examples/OCaml-Kaleidoscope/Chapter3/myocamlbuild.ml
Normal file
@ -0,0 +1,6 @@
|
||||
open Ocamlbuild_plugin;;
|
||||
|
||||
ocaml_lib ~extern:true "llvm";;
|
||||
ocaml_lib ~extern:true "llvm_analysis";;
|
||||
|
||||
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
|
122
examples/OCaml-Kaleidoscope/Chapter3/parser.ml
Normal file
122
examples/OCaml-Kaleidoscope/Chapter3/parser.ml
Normal file
@ -0,0 +1,122 @@
|
||||
(*===---------------------------------------------------------------------===
|
||||
* Parser
|
||||
*===---------------------------------------------------------------------===*)
|
||||
|
||||
(* binop_precedence - This holds the precedence for each binary operator that is
|
||||
* defined *)
|
||||
let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
|
||||
|
||||
(* precedence - Get the precedence of the pending binary operator token. *)
|
||||
let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
|
||||
|
||||
(* primary
|
||||
* ::= identifier
|
||||
* ::= numberexpr
|
||||
* ::= parenexpr *)
|
||||
let rec parse_primary = parser
|
||||
(* numberexpr ::= number *)
|
||||
| [< 'Token.Number n >] -> Ast.Number n
|
||||
|
||||
(* parenexpr ::= '(' expression ')' *)
|
||||
| [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
|
||||
|
||||
(* identifierexpr
|
||||
* ::= identifier
|
||||
* ::= identifier '(' argumentexpr ')' *)
|
||||
| [< 'Token.Ident id; stream >] ->
|
||||
let rec parse_args accumulator = parser
|
||||
| [< e=parse_expr; stream >] ->
|
||||
begin parser
|
||||
| [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
|
||||
| [< >] -> e :: accumulator
|
||||
end stream
|
||||
| [< >] -> accumulator
|
||||
in
|
||||
let rec parse_ident id = parser
|
||||
(* Call. *)
|
||||
| [< 'Token.Kwd '(';
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')'">] ->
|
||||
Ast.Call (id, Array.of_list (List.rev args))
|
||||
|
||||
(* Simple variable ref. *)
|
||||
| [< >] -> Ast.Variable id
|
||||
in
|
||||
parse_ident id stream
|
||||
|
||||
| [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
|
||||
|
||||
(* binoprhs
|
||||
* ::= ('+' primary)* *)
|
||||
and parse_bin_rhs expr_prec lhs stream =
|
||||
match Stream.peek stream with
|
||||
(* If this is a binop, find its precedence. *)
|
||||
| Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
|
||||
let token_prec = precedence c in
|
||||
|
||||
(* If this is a binop that binds at least as tightly as the current binop,
|
||||
* consume it, otherwise we are done. *)
|
||||
if token_prec < expr_prec then lhs else begin
|
||||
(* Eat the binop. *)
|
||||
Stream.junk stream;
|
||||
|
||||
(* Parse the primary expression after the binary operator. *)
|
||||
let rhs = parse_primary stream in
|
||||
|
||||
(* Okay, we know this is a binop. *)
|
||||
let rhs =
|
||||
match Stream.peek stream with
|
||||
| Some (Token.Kwd c2) ->
|
||||
(* If BinOp binds less tightly with rhs than the operator after
|
||||
* rhs, let the pending operator take rhs as its lhs. *)
|
||||
let next_prec = precedence c2 in
|
||||
if token_prec < next_prec
|
||||
then parse_bin_rhs (token_prec + 1) rhs stream
|
||||
else rhs
|
||||
| _ -> rhs
|
||||
in
|
||||
|
||||
(* Merge lhs/rhs. *)
|
||||
let lhs = Ast.Binary (c, lhs, rhs) in
|
||||
parse_bin_rhs expr_prec lhs stream
|
||||
end
|
||||
| _ -> lhs
|
||||
|
||||
(* expression
|
||||
* ::= primary binoprhs *)
|
||||
and parse_expr = parser
|
||||
| [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
|
||||
|
||||
(* prototype
|
||||
* ::= id '(' id* ')' *)
|
||||
let parse_prototype =
|
||||
let rec parse_args accumulator = parser
|
||||
| [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
|
||||
| [< >] -> accumulator
|
||||
in
|
||||
|
||||
parser
|
||||
| [< 'Token.Ident id;
|
||||
'Token.Kwd '(' ?? "expected '(' in prototype";
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
|
||||
(* success. *)
|
||||
Ast.Prototype (id, Array.of_list (List.rev args))
|
||||
|
||||
| [< >] ->
|
||||
raise (Stream.Error "expected function name in prototype")
|
||||
|
||||
(* definition ::= 'def' prototype expression *)
|
||||
let parse_definition = parser
|
||||
| [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
|
||||
Ast.Function (p, e)
|
||||
|
||||
(* toplevelexpr ::= expression *)
|
||||
let parse_toplevel = parser
|
||||
| [< e=parse_expr >] ->
|
||||
(* Make an anonymous proto. *)
|
||||
Ast.Function (Ast.Prototype ("", [||]), e)
|
||||
|
||||
(* external ::= 'extern' prototype *)
|
||||
let parse_extern = parser
|
||||
| [< 'Token.Extern; e=parse_prototype >] -> e
|
15
examples/OCaml-Kaleidoscope/Chapter3/token.ml
Normal file
15
examples/OCaml-Kaleidoscope/Chapter3/token.ml
Normal file
@ -0,0 +1,15 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Lexer Tokens
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
|
||||
* these others for known things. *)
|
||||
type token =
|
||||
(* commands *)
|
||||
| Def | Extern
|
||||
|
||||
(* primary *)
|
||||
| Ident of string | Number of float
|
||||
|
||||
(* unknown *)
|
||||
| Kwd of char
|
39
examples/OCaml-Kaleidoscope/Chapter3/toplevel.ml
Normal file
39
examples/OCaml-Kaleidoscope/Chapter3/toplevel.ml
Normal file
@ -0,0 +1,39 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Top-Level parsing and JIT Driver
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
|
||||
(* top ::= definition | external | expression | ';' *)
|
||||
let rec main_loop stream =
|
||||
match Stream.peek stream with
|
||||
| None -> ()
|
||||
|
||||
(* ignore top-level semicolons. *)
|
||||
| Some (Token.Kwd ';') ->
|
||||
Stream.junk stream;
|
||||
main_loop stream
|
||||
|
||||
| Some token ->
|
||||
begin
|
||||
try match token with
|
||||
| Token.Def ->
|
||||
let e = Parser.parse_definition stream in
|
||||
print_endline "parsed a function definition.";
|
||||
dump_value (Codegen.codegen_func e);
|
||||
| Token.Extern ->
|
||||
let e = Parser.parse_extern stream in
|
||||
print_endline "parsed an extern.";
|
||||
dump_value (Codegen.codegen_proto e);
|
||||
| _ ->
|
||||
(* Evaluate a top-level expression into an anonymous function. *)
|
||||
let e = Parser.parse_toplevel stream in
|
||||
print_endline "parsed a top-level expr";
|
||||
dump_value (Codegen.codegen_func e);
|
||||
with Stream.Error s | Codegen.Error s ->
|
||||
(* Skip token for error recovery. *)
|
||||
Stream.junk stream;
|
||||
print_endline s;
|
||||
end;
|
||||
print_string "ready> "; flush stdout;
|
||||
main_loop stream
|
26
examples/OCaml-Kaleidoscope/Chapter3/toy.ml
Normal file
26
examples/OCaml-Kaleidoscope/Chapter3/toy.ml
Normal file
@ -0,0 +1,26 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Main driver code.
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
|
||||
let main () =
|
||||
(* Install standard binary operators.
|
||||
* 1 is the lowest precedence. *)
|
||||
Hashtbl.add Parser.binop_precedence '<' 10;
|
||||
Hashtbl.add Parser.binop_precedence '+' 20;
|
||||
Hashtbl.add Parser.binop_precedence '-' 20;
|
||||
Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *)
|
||||
|
||||
(* Prime the first token. *)
|
||||
print_string "ready> "; flush stdout;
|
||||
let stream = Lexer.lex (Stream.of_channel stdin) in
|
||||
|
||||
(* Run the main "interpreter loop" now. *)
|
||||
Toplevel.main_loop stream;
|
||||
|
||||
(* Print out all the generated code. *)
|
||||
dump_module Codegen.the_module
|
||||
;;
|
||||
|
||||
main ()
|
25
examples/OCaml-Kaleidoscope/Chapter4/Makefile
Normal file
25
examples/OCaml-Kaleidoscope/Chapter4/Makefile
Normal file
@ -0,0 +1,25 @@
|
||||
##===- examples/OCaml-Kaleidoscope/Chapter4/Makefile -------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 4.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL := ../../..
|
||||
TOOLNAME := OCaml-Kaleidoscope-Ch4
|
||||
EXAMPLE_TOOL := 1
|
||||
UsedComponents := core
|
||||
UsedOcamLibs := llvm llvm_analysis llvm_executionengine llvm_target \
|
||||
llvm_scalar_opts
|
||||
|
||||
OCAMLCFLAGS += -pp camlp4of
|
||||
|
||||
ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml
|
||||
|
||||
include $(LEVEL)/bindings/ocaml/Makefile.ocaml
|
4
examples/OCaml-Kaleidoscope/Chapter4/_tags
Normal file
4
examples/OCaml-Kaleidoscope/Chapter4/_tags
Normal file
@ -0,0 +1,4 @@
|
||||
<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
|
||||
<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
|
||||
<*.{byte,native}>: use_llvm_executionengine, use_llvm_target
|
||||
<*.{byte,native}>: use_llvm_scalar_opts, use_bindings
|
25
examples/OCaml-Kaleidoscope/Chapter4/ast.ml
Normal file
25
examples/OCaml-Kaleidoscope/Chapter4/ast.ml
Normal file
@ -0,0 +1,25 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Abstract Syntax Tree (aka Parse Tree)
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(* expr - Base type for all expression nodes. *)
|
||||
type expr =
|
||||
(* variant for numeric literals like "1.0". *)
|
||||
| Number of float
|
||||
|
||||
(* variant for referencing a variable, like "a". *)
|
||||
| Variable of string
|
||||
|
||||
(* variant for a binary operator. *)
|
||||
| Binary of char * expr * expr
|
||||
|
||||
(* variant for function calls. *)
|
||||
| Call of string * expr array
|
||||
|
||||
(* proto - This type represents the "prototype" for a function, which captures
|
||||
* its name, and its argument names (thus implicitly the number of arguments the
|
||||
* function takes). *)
|
||||
type proto = Prototype of string * string array
|
||||
|
||||
(* func - This type represents a function definition itself. *)
|
||||
type func = Function of proto * expr
|
7
examples/OCaml-Kaleidoscope/Chapter4/bindings.c
Normal file
7
examples/OCaml-Kaleidoscope/Chapter4/bindings.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* putchard - putchar that takes a double and returns 0. */
|
||||
extern double putchard(double X) {
|
||||
putchar((char)X);
|
||||
return 0;
|
||||
}
|
103
examples/OCaml-Kaleidoscope/Chapter4/codegen.ml
Normal file
103
examples/OCaml-Kaleidoscope/Chapter4/codegen.ml
Normal file
@ -0,0 +1,103 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Code Generation
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
|
||||
exception Error of string
|
||||
|
||||
let context = global_context ()
|
||||
let the_module = create_module context "my cool jit"
|
||||
let builder = builder context
|
||||
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
|
||||
let double_type = double_type context
|
||||
|
||||
let rec codegen_expr = function
|
||||
| Ast.Number n -> const_float double_type n
|
||||
| Ast.Variable name ->
|
||||
(try Hashtbl.find named_values name with
|
||||
| Not_found -> raise (Error "unknown variable name"))
|
||||
| Ast.Binary (op, lhs, rhs) ->
|
||||
let lhs_val = codegen_expr lhs in
|
||||
let rhs_val = codegen_expr rhs in
|
||||
begin
|
||||
match op with
|
||||
| '+' -> build_add lhs_val rhs_val "addtmp" builder
|
||||
| '-' -> build_sub lhs_val rhs_val "subtmp" builder
|
||||
| '*' -> build_mul lhs_val rhs_val "multmp" builder
|
||||
| '<' ->
|
||||
(* Convert bool 0/1 to double 0.0 or 1.0 *)
|
||||
let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
|
||||
build_uitofp i double_type "booltmp" builder
|
||||
| _ -> raise (Error "invalid binary operator")
|
||||
end
|
||||
| Ast.Call (callee, args) ->
|
||||
(* Look up the name in the module table. *)
|
||||
let callee =
|
||||
match lookup_function callee the_module with
|
||||
| Some callee -> callee
|
||||
| None -> raise (Error "unknown function referenced")
|
||||
in
|
||||
let params = params callee in
|
||||
|
||||
(* If argument mismatch error. *)
|
||||
if Array.length params == Array.length args then () else
|
||||
raise (Error "incorrect # arguments passed");
|
||||
let args = Array.map codegen_expr args in
|
||||
build_call callee args "calltmp" builder
|
||||
|
||||
let codegen_proto = function
|
||||
| Ast.Prototype (name, args) ->
|
||||
(* Make the function type: double(double,double) etc. *)
|
||||
let doubles = Array.make (Array.length args) double_type in
|
||||
let ft = function_type double_type doubles in
|
||||
let f =
|
||||
match lookup_function name the_module with
|
||||
| None -> declare_function name ft the_module
|
||||
|
||||
(* If 'f' conflicted, there was already something named 'name'. If it
|
||||
* has a body, don't allow redefinition or reextern. *)
|
||||
| Some f ->
|
||||
(* If 'f' already has a body, reject this. *)
|
||||
if block_begin f <> At_end f then
|
||||
raise (Error "redefinition of function");
|
||||
|
||||
(* If 'f' took a different number of arguments, reject. *)
|
||||
if element_type (type_of f) <> ft then
|
||||
raise (Error "redefinition of function with different # args");
|
||||
f
|
||||
in
|
||||
|
||||
(* Set names for all arguments. *)
|
||||
Array.iteri (fun i a ->
|
||||
let n = args.(i) in
|
||||
set_value_name n a;
|
||||
Hashtbl.add named_values n a;
|
||||
) (params f);
|
||||
f
|
||||
|
||||
let codegen_func the_fpm = function
|
||||
| Ast.Function (proto, body) ->
|
||||
Hashtbl.clear named_values;
|
||||
let the_function = codegen_proto proto in
|
||||
|
||||
(* Create a new basic block to start insertion into. *)
|
||||
let bb = append_block context "entry" the_function in
|
||||
position_at_end bb builder;
|
||||
|
||||
try
|
||||
let ret_val = codegen_expr body in
|
||||
|
||||
(* Finish off the function. *)
|
||||
let _ = build_ret ret_val builder in
|
||||
|
||||
(* Validate the generated code, checking for consistency. *)
|
||||
Llvm_analysis.assert_valid_function the_function;
|
||||
|
||||
(* Optimize the function. *)
|
||||
let _ = PassManager.run_function the_function the_fpm in
|
||||
|
||||
the_function
|
||||
with e ->
|
||||
delete_function the_function;
|
||||
raise e
|
52
examples/OCaml-Kaleidoscope/Chapter4/lexer.ml
Normal file
52
examples/OCaml-Kaleidoscope/Chapter4/lexer.ml
Normal file
@ -0,0 +1,52 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Lexer
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
let rec lex = parser
|
||||
(* Skip any whitespace. *)
|
||||
| [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
|
||||
|
||||
(* identifier: [a-zA-Z][a-zA-Z0-9] *)
|
||||
| [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
|
||||
let buffer = Buffer.create 1 in
|
||||
Buffer.add_char buffer c;
|
||||
lex_ident buffer stream
|
||||
|
||||
(* number: [0-9.]+ *)
|
||||
| [< ' ('0' .. '9' as c); stream >] ->
|
||||
let buffer = Buffer.create 1 in
|
||||
Buffer.add_char buffer c;
|
||||
lex_number buffer stream
|
||||
|
||||
(* Comment until end of line. *)
|
||||
| [< ' ('#'); stream >] ->
|
||||
lex_comment stream
|
||||
|
||||
(* Otherwise, just return the character as its ascii value. *)
|
||||
| [< 'c; stream >] ->
|
||||
[< 'Token.Kwd c; lex stream >]
|
||||
|
||||
(* end of stream. *)
|
||||
| [< >] -> [< >]
|
||||
|
||||
and lex_number buffer = parser
|
||||
| [< ' ('0' .. '9' | '.' as c); stream >] ->
|
||||
Buffer.add_char buffer c;
|
||||
lex_number buffer stream
|
||||
| [< stream=lex >] ->
|
||||
[< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
|
||||
|
||||
and lex_ident buffer = parser
|
||||
| [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
|
||||
Buffer.add_char buffer c;
|
||||
lex_ident buffer stream
|
||||
| [< stream=lex >] ->
|
||||
match Buffer.contents buffer with
|
||||
| "def" -> [< 'Token.Def; stream >]
|
||||
| "extern" -> [< 'Token.Extern; stream >]
|
||||
| id -> [< 'Token.Ident id; stream >]
|
||||
|
||||
and lex_comment = parser
|
||||
| [< ' ('\n'); stream=lex >] -> stream
|
||||
| [< 'c; e=lex_comment >] -> e
|
||||
| [< >] -> [< >]
|
10
examples/OCaml-Kaleidoscope/Chapter4/myocamlbuild.ml
Normal file
10
examples/OCaml-Kaleidoscope/Chapter4/myocamlbuild.ml
Normal file
@ -0,0 +1,10 @@
|
||||
open Ocamlbuild_plugin;;
|
||||
|
||||
ocaml_lib ~extern:true "llvm";;
|
||||
ocaml_lib ~extern:true "llvm_analysis";;
|
||||
ocaml_lib ~extern:true "llvm_executionengine";;
|
||||
ocaml_lib ~extern:true "llvm_target";;
|
||||
ocaml_lib ~extern:true "llvm_scalar_opts";;
|
||||
|
||||
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
|
||||
dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
|
122
examples/OCaml-Kaleidoscope/Chapter4/parser.ml
Normal file
122
examples/OCaml-Kaleidoscope/Chapter4/parser.ml
Normal file
@ -0,0 +1,122 @@
|
||||
(*===---------------------------------------------------------------------===
|
||||
* Parser
|
||||
*===---------------------------------------------------------------------===*)
|
||||
|
||||
(* binop_precedence - This holds the precedence for each binary operator that is
|
||||
* defined *)
|
||||
let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
|
||||
|
||||
(* precedence - Get the precedence of the pending binary operator token. *)
|
||||
let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
|
||||
|
||||
(* primary
|
||||
* ::= identifier
|
||||
* ::= numberexpr
|
||||
* ::= parenexpr *)
|
||||
let rec parse_primary = parser
|
||||
(* numberexpr ::= number *)
|
||||
| [< 'Token.Number n >] -> Ast.Number n
|
||||
|
||||
(* parenexpr ::= '(' expression ')' *)
|
||||
| [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
|
||||
|
||||
(* identifierexpr
|
||||
* ::= identifier
|
||||
* ::= identifier '(' argumentexpr ')' *)
|
||||
| [< 'Token.Ident id; stream >] ->
|
||||
let rec parse_args accumulator = parser
|
||||
| [< e=parse_expr; stream >] ->
|
||||
begin parser
|
||||
| [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
|
||||
| [< >] -> e :: accumulator
|
||||
end stream
|
||||
| [< >] -> accumulator
|
||||
in
|
||||
let rec parse_ident id = parser
|
||||
(* Call. *)
|
||||
| [< 'Token.Kwd '(';
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')'">] ->
|
||||
Ast.Call (id, Array.of_list (List.rev args))
|
||||
|
||||
(* Simple variable ref. *)
|
||||
| [< >] -> Ast.Variable id
|
||||
in
|
||||
parse_ident id stream
|
||||
|
||||
| [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
|
||||
|
||||
(* binoprhs
|
||||
* ::= ('+' primary)* *)
|
||||
and parse_bin_rhs expr_prec lhs stream =
|
||||
match Stream.peek stream with
|
||||
(* If this is a binop, find its precedence. *)
|
||||
| Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
|
||||
let token_prec = precedence c in
|
||||
|
||||
(* If this is a binop that binds at least as tightly as the current binop,
|
||||
* consume it, otherwise we are done. *)
|
||||
if token_prec < expr_prec then lhs else begin
|
||||
(* Eat the binop. *)
|
||||
Stream.junk stream;
|
||||
|
||||
(* Parse the primary expression after the binary operator. *)
|
||||
let rhs = parse_primary stream in
|
||||
|
||||
(* Okay, we know this is a binop. *)
|
||||
let rhs =
|
||||
match Stream.peek stream with
|
||||
| Some (Token.Kwd c2) ->
|
||||
(* If BinOp binds less tightly with rhs than the operator after
|
||||
* rhs, let the pending operator take rhs as its lhs. *)
|
||||
let next_prec = precedence c2 in
|
||||
if token_prec < next_prec
|
||||
then parse_bin_rhs (token_prec + 1) rhs stream
|
||||
else rhs
|
||||
| _ -> rhs
|
||||
in
|
||||
|
||||
(* Merge lhs/rhs. *)
|
||||
let lhs = Ast.Binary (c, lhs, rhs) in
|
||||
parse_bin_rhs expr_prec lhs stream
|
||||
end
|
||||
| _ -> lhs
|
||||
|
||||
(* expression
|
||||
* ::= primary binoprhs *)
|
||||
and parse_expr = parser
|
||||
| [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
|
||||
|
||||
(* prototype
|
||||
* ::= id '(' id* ')' *)
|
||||
let parse_prototype =
|
||||
let rec parse_args accumulator = parser
|
||||
| [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
|
||||
| [< >] -> accumulator
|
||||
in
|
||||
|
||||
parser
|
||||
| [< 'Token.Ident id;
|
||||
'Token.Kwd '(' ?? "expected '(' in prototype";
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
|
||||
(* success. *)
|
||||
Ast.Prototype (id, Array.of_list (List.rev args))
|
||||
|
||||
| [< >] ->
|
||||
raise (Stream.Error "expected function name in prototype")
|
||||
|
||||
(* definition ::= 'def' prototype expression *)
|
||||
let parse_definition = parser
|
||||
| [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
|
||||
Ast.Function (p, e)
|
||||
|
||||
(* toplevelexpr ::= expression *)
|
||||
let parse_toplevel = parser
|
||||
| [< e=parse_expr >] ->
|
||||
(* Make an anonymous proto. *)
|
||||
Ast.Function (Ast.Prototype ("", [||]), e)
|
||||
|
||||
(* external ::= 'extern' prototype *)
|
||||
let parse_extern = parser
|
||||
| [< 'Token.Extern; e=parse_prototype >] -> e
|
15
examples/OCaml-Kaleidoscope/Chapter4/token.ml
Normal file
15
examples/OCaml-Kaleidoscope/Chapter4/token.ml
Normal file
@ -0,0 +1,15 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Lexer Tokens
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
|
||||
* these others for known things. *)
|
||||
type token =
|
||||
(* commands *)
|
||||
| Def | Extern
|
||||
|
||||
(* primary *)
|
||||
| Ident of string | Number of float
|
||||
|
||||
(* unknown *)
|
||||
| Kwd of char
|
49
examples/OCaml-Kaleidoscope/Chapter4/toplevel.ml
Normal file
49
examples/OCaml-Kaleidoscope/Chapter4/toplevel.ml
Normal file
@ -0,0 +1,49 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Top-Level parsing and JIT Driver
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
open Llvm_executionengine
|
||||
|
||||
(* top ::= definition | external | expression | ';' *)
|
||||
let rec main_loop the_fpm the_execution_engine stream =
|
||||
match Stream.peek stream with
|
||||
| None -> ()
|
||||
|
||||
(* ignore top-level semicolons. *)
|
||||
| Some (Token.Kwd ';') ->
|
||||
Stream.junk stream;
|
||||
main_loop the_fpm the_execution_engine stream
|
||||
|
||||
| Some token ->
|
||||
begin
|
||||
try match token with
|
||||
| Token.Def ->
|
||||
let e = Parser.parse_definition stream in
|
||||
print_endline "parsed a function definition.";
|
||||
dump_value (Codegen.codegen_func the_fpm e);
|
||||
| Token.Extern ->
|
||||
let e = Parser.parse_extern stream in
|
||||
print_endline "parsed an extern.";
|
||||
dump_value (Codegen.codegen_proto e);
|
||||
| _ ->
|
||||
(* Evaluate a top-level expression into an anonymous function. *)
|
||||
let e = Parser.parse_toplevel stream in
|
||||
print_endline "parsed a top-level expr";
|
||||
let the_function = Codegen.codegen_func the_fpm e in
|
||||
dump_value the_function;
|
||||
|
||||
(* JIT the function, returning a function pointer. *)
|
||||
let result = ExecutionEngine.run_function the_function [||]
|
||||
the_execution_engine in
|
||||
|
||||
print_string "Evaluated to ";
|
||||
print_float (GenericValue.as_float Codegen.double_type result);
|
||||
print_newline ();
|
||||
with Stream.Error s | Codegen.Error s ->
|
||||
(* Skip token for error recovery. *)
|
||||
Stream.junk stream;
|
||||
print_endline s;
|
||||
end;
|
||||
print_string "ready> "; flush stdout;
|
||||
main_loop the_fpm the_execution_engine stream
|
53
examples/OCaml-Kaleidoscope/Chapter4/toy.ml
Normal file
53
examples/OCaml-Kaleidoscope/Chapter4/toy.ml
Normal file
@ -0,0 +1,53 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Main driver code.
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
open Llvm_executionengine
|
||||
open Llvm_target
|
||||
open Llvm_scalar_opts
|
||||
|
||||
let main () =
|
||||
ignore (initialize_native_target ());
|
||||
|
||||
(* Install standard binary operators.
|
||||
* 1 is the lowest precedence. *)
|
||||
Hashtbl.add Parser.binop_precedence '<' 10;
|
||||
Hashtbl.add Parser.binop_precedence '+' 20;
|
||||
Hashtbl.add Parser.binop_precedence '-' 20;
|
||||
Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *)
|
||||
|
||||
(* Prime the first token. *)
|
||||
print_string "ready> "; flush stdout;
|
||||
let stream = Lexer.lex (Stream.of_channel stdin) in
|
||||
|
||||
(* Create the JIT. *)
|
||||
let the_execution_engine = ExecutionEngine.create Codegen.the_module in
|
||||
let the_fpm = PassManager.create_function Codegen.the_module in
|
||||
|
||||
(* Set up the optimizer pipeline. Start with registering info about how the
|
||||
* target lays out data structures. *)
|
||||
TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
|
||||
|
||||
(* Do simple "peephole" optimizations and bit-twiddling optzn. *)
|
||||
add_instruction_combination the_fpm;
|
||||
|
||||
(* reassociate expressions. *)
|
||||
add_reassociation the_fpm;
|
||||
|
||||
(* Eliminate Common SubExpressions. *)
|
||||
add_gvn the_fpm;
|
||||
|
||||
(* Simplify the control flow graph (deleting unreachable blocks, etc). *)
|
||||
add_cfg_simplification the_fpm;
|
||||
|
||||
ignore (PassManager.initialize the_fpm);
|
||||
|
||||
(* Run the main "interpreter loop" now. *)
|
||||
Toplevel.main_loop the_fpm the_execution_engine stream;
|
||||
|
||||
(* Print out all the generated code. *)
|
||||
dump_module Codegen.the_module
|
||||
;;
|
||||
|
||||
main ()
|
25
examples/OCaml-Kaleidoscope/Chapter5/Makefile
Normal file
25
examples/OCaml-Kaleidoscope/Chapter5/Makefile
Normal file
@ -0,0 +1,25 @@
|
||||
##===- examples/OCaml-Kaleidoscope/Chapter5/Makefile -------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 5.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL := ../../..
|
||||
TOOLNAME := OCaml-Kaleidoscope-Ch5
|
||||
EXAMPLE_TOOL := 1
|
||||
UsedComponents := core
|
||||
UsedOcamLibs := llvm llvm_analysis llvm_executionengine llvm_target \
|
||||
llvm_scalar_opts
|
||||
|
||||
OCAMLCFLAGS += -pp camlp4of
|
||||
|
||||
ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml
|
||||
|
||||
include $(LEVEL)/bindings/ocaml/Makefile.ocaml
|
4
examples/OCaml-Kaleidoscope/Chapter5/_tags
Normal file
4
examples/OCaml-Kaleidoscope/Chapter5/_tags
Normal file
@ -0,0 +1,4 @@
|
||||
<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
|
||||
<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
|
||||
<*.{byte,native}>: use_llvm_executionengine, use_llvm_target
|
||||
<*.{byte,native}>: use_llvm_scalar_opts, use_bindings
|
31
examples/OCaml-Kaleidoscope/Chapter5/ast.ml
Normal file
31
examples/OCaml-Kaleidoscope/Chapter5/ast.ml
Normal file
@ -0,0 +1,31 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Abstract Syntax Tree (aka Parse Tree)
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(* expr - Base type for all expression nodes. *)
|
||||
type expr =
|
||||
(* variant for numeric literals like "1.0". *)
|
||||
| Number of float
|
||||
|
||||
(* variant for referencing a variable, like "a". *)
|
||||
| Variable of string
|
||||
|
||||
(* variant for a binary operator. *)
|
||||
| Binary of char * expr * expr
|
||||
|
||||
(* variant for function calls. *)
|
||||
| Call of string * expr array
|
||||
|
||||
(* variant for if/then/else. *)
|
||||
| If of expr * expr * expr
|
||||
|
||||
(* variant for for/in. *)
|
||||
| For of string * expr * expr * expr option * expr
|
||||
|
||||
(* proto - This type represents the "prototype" for a function, which captures
|
||||
* its name, and its argument names (thus implicitly the number of arguments the
|
||||
* function takes). *)
|
||||
type proto = Prototype of string * string array
|
||||
|
||||
(* func - This type represents a function definition itself. *)
|
||||
type func = Function of proto * expr
|
7
examples/OCaml-Kaleidoscope/Chapter5/bindings.c
Normal file
7
examples/OCaml-Kaleidoscope/Chapter5/bindings.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* putchard - putchar that takes a double and returns 0. */
|
||||
extern double putchard(double X) {
|
||||
putchar((char)X);
|
||||
return 0;
|
||||
}
|
225
examples/OCaml-Kaleidoscope/Chapter5/codegen.ml
Normal file
225
examples/OCaml-Kaleidoscope/Chapter5/codegen.ml
Normal file
@ -0,0 +1,225 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Code Generation
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
|
||||
exception Error of string
|
||||
|
||||
let context = global_context ()
|
||||
let the_module = create_module context "my cool jit"
|
||||
let builder = builder context
|
||||
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
|
||||
let double_type = double_type context
|
||||
|
||||
let rec codegen_expr = function
|
||||
| Ast.Number n -> const_float double_type n
|
||||
| Ast.Variable name ->
|
||||
(try Hashtbl.find named_values name with
|
||||
| Not_found -> raise (Error "unknown variable name"))
|
||||
| Ast.Binary (op, lhs, rhs) ->
|
||||
let lhs_val = codegen_expr lhs in
|
||||
let rhs_val = codegen_expr rhs in
|
||||
begin
|
||||
match op with
|
||||
| '+' -> build_add lhs_val rhs_val "addtmp" builder
|
||||
| '-' -> build_sub lhs_val rhs_val "subtmp" builder
|
||||
| '*' -> build_mul lhs_val rhs_val "multmp" builder
|
||||
| '<' ->
|
||||
(* Convert bool 0/1 to double 0.0 or 1.0 *)
|
||||
let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
|
||||
build_uitofp i double_type "booltmp" builder
|
||||
| _ -> raise (Error "invalid binary operator")
|
||||
end
|
||||
| Ast.Call (callee, args) ->
|
||||
(* Look up the name in the module table. *)
|
||||
let callee =
|
||||
match lookup_function callee the_module with
|
||||
| Some callee -> callee
|
||||
| None -> raise (Error "unknown function referenced")
|
||||
in
|
||||
let params = params callee in
|
||||
|
||||
(* If argument mismatch error. *)
|
||||
if Array.length params == Array.length args then () else
|
||||
raise (Error "incorrect # arguments passed");
|
||||
let args = Array.map codegen_expr args in
|
||||
build_call callee args "calltmp" builder
|
||||
| Ast.If (cond, then_, else_) ->
|
||||
let cond = codegen_expr cond in
|
||||
|
||||
(* Convert condition to a bool by comparing equal to 0.0 *)
|
||||
let zero = const_float double_type 0.0 in
|
||||
let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in
|
||||
|
||||
(* Grab the first block so that we might later add the conditional branch
|
||||
* to it at the end of the function. *)
|
||||
let start_bb = insertion_block builder in
|
||||
let the_function = block_parent start_bb in
|
||||
|
||||
let then_bb = append_block context "then" the_function in
|
||||
|
||||
(* Emit 'then' value. *)
|
||||
position_at_end then_bb builder;
|
||||
let then_val = codegen_expr then_ in
|
||||
|
||||
(* Codegen of 'then' can change the current block, update then_bb for the
|
||||
* phi. We create a new name because one is used for the phi node, and the
|
||||
* other is used for the conditional branch. *)
|
||||
let new_then_bb = insertion_block builder in
|
||||
|
||||
(* Emit 'else' value. *)
|
||||
let else_bb = append_block context "else" the_function in
|
||||
position_at_end else_bb builder;
|
||||
let else_val = codegen_expr else_ in
|
||||
|
||||
(* Codegen of 'else' can change the current block, update else_bb for the
|
||||
* phi. *)
|
||||
let new_else_bb = insertion_block builder in
|
||||
|
||||
(* Emit merge block. *)
|
||||
let merge_bb = append_block context "ifcont" the_function in
|
||||
position_at_end merge_bb builder;
|
||||
let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
|
||||
let phi = build_phi incoming "iftmp" builder in
|
||||
|
||||
(* Return to the start block to add the conditional branch. *)
|
||||
position_at_end start_bb builder;
|
||||
ignore (build_cond_br cond_val then_bb else_bb builder);
|
||||
|
||||
(* Set a unconditional branch at the end of the 'then' block and the
|
||||
* 'else' block to the 'merge' block. *)
|
||||
position_at_end new_then_bb builder; ignore (build_br merge_bb builder);
|
||||
position_at_end new_else_bb builder; ignore (build_br merge_bb builder);
|
||||
|
||||
(* Finally, set the builder to the end of the merge block. *)
|
||||
position_at_end merge_bb builder;
|
||||
|
||||
phi
|
||||
| Ast.For (var_name, start, end_, step, body) ->
|
||||
(* Emit the start code first, without 'variable' in scope. *)
|
||||
let start_val = codegen_expr start in
|
||||
|
||||
(* Make the new basic block for the loop header, inserting after current
|
||||
* block. *)
|
||||
let preheader_bb = insertion_block builder in
|
||||
let the_function = block_parent preheader_bb in
|
||||
let loop_bb = append_block context "loop" the_function in
|
||||
|
||||
(* Insert an explicit fall through from the current block to the
|
||||
* loop_bb. *)
|
||||
ignore (build_br loop_bb builder);
|
||||
|
||||
(* Start insertion in loop_bb. *)
|
||||
position_at_end loop_bb builder;
|
||||
|
||||
(* Start the PHI node with an entry for start. *)
|
||||
let variable = build_phi [(start_val, preheader_bb)] var_name builder in
|
||||
|
||||
(* Within the loop, the variable is defined equal to the PHI node. If it
|
||||
* shadows an existing variable, we have to restore it, so save it
|
||||
* now. *)
|
||||
let old_val =
|
||||
try Some (Hashtbl.find named_values var_name) with Not_found -> None
|
||||
in
|
||||
Hashtbl.add named_values var_name variable;
|
||||
|
||||
(* Emit the body of the loop. This, like any other expr, can change the
|
||||
* current BB. Note that we ignore the value computed by the body, but
|
||||
* don't allow an error *)
|
||||
ignore (codegen_expr body);
|
||||
|
||||
(* Emit the step value. *)
|
||||
let step_val =
|
||||
match step with
|
||||
| Some step -> codegen_expr step
|
||||
(* If not specified, use 1.0. *)
|
||||
| None -> const_float double_type 1.0
|
||||
in
|
||||
|
||||
let next_var = build_add variable step_val "nextvar" builder in
|
||||
|
||||
(* Compute the end condition. *)
|
||||
let end_cond = codegen_expr end_ in
|
||||
|
||||
(* Convert condition to a bool by comparing equal to 0.0. *)
|
||||
let zero = const_float double_type 0.0 in
|
||||
let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in
|
||||
|
||||
(* Create the "after loop" block and insert it. *)
|
||||
let loop_end_bb = insertion_block builder in
|
||||
let after_bb = append_block context "afterloop" the_function in
|
||||
|
||||
(* Insert the conditional branch into the end of loop_end_bb. *)
|
||||
ignore (build_cond_br end_cond loop_bb after_bb builder);
|
||||
|
||||
(* Any new code will be inserted in after_bb. *)
|
||||
position_at_end after_bb builder;
|
||||
|
||||
(* Add a new entry to the PHI node for the backedge. *)
|
||||
add_incoming (next_var, loop_end_bb) variable;
|
||||
|
||||
(* Restore the unshadowed variable. *)
|
||||
begin match old_val with
|
||||
| Some old_val -> Hashtbl.add named_values var_name old_val
|
||||
| None -> ()
|
||||
end;
|
||||
|
||||
(* for expr always returns 0.0. *)
|
||||
const_null double_type
|
||||
|
||||
let codegen_proto = function
|
||||
| Ast.Prototype (name, args) ->
|
||||
(* Make the function type: double(double,double) etc. *)
|
||||
let doubles = Array.make (Array.length args) double_type in
|
||||
let ft = function_type double_type doubles in
|
||||
let f =
|
||||
match lookup_function name the_module with
|
||||
| None -> declare_function name ft the_module
|
||||
|
||||
(* If 'f' conflicted, there was already something named 'name'. If it
|
||||
* has a body, don't allow redefinition or reextern. *)
|
||||
| Some f ->
|
||||
(* If 'f' already has a body, reject this. *)
|
||||
if block_begin f <> At_end f then
|
||||
raise (Error "redefinition of function");
|
||||
|
||||
(* If 'f' took a different number of arguments, reject. *)
|
||||
if element_type (type_of f) <> ft then
|
||||
raise (Error "redefinition of function with different # args");
|
||||
f
|
||||
in
|
||||
|
||||
(* Set names for all arguments. *)
|
||||
Array.iteri (fun i a ->
|
||||
let n = args.(i) in
|
||||
set_value_name n a;
|
||||
Hashtbl.add named_values n a;
|
||||
) (params f);
|
||||
f
|
||||
|
||||
let codegen_func the_fpm = function
|
||||
| Ast.Function (proto, body) ->
|
||||
Hashtbl.clear named_values;
|
||||
let the_function = codegen_proto proto in
|
||||
|
||||
(* Create a new basic block to start insertion into. *)
|
||||
let bb = append_block context "entry" the_function in
|
||||
position_at_end bb builder;
|
||||
|
||||
try
|
||||
let ret_val = codegen_expr body in
|
||||
|
||||
(* Finish off the function. *)
|
||||
let _ = build_ret ret_val builder in
|
||||
|
||||
(* Validate the generated code, checking for consistency. *)
|
||||
Llvm_analysis.assert_valid_function the_function;
|
||||
|
||||
(* Optimize the function. *)
|
||||
let _ = PassManager.run_function the_function the_fpm in
|
||||
|
||||
the_function
|
||||
with e ->
|
||||
delete_function the_function;
|
||||
raise e
|
57
examples/OCaml-Kaleidoscope/Chapter5/lexer.ml
Normal file
57
examples/OCaml-Kaleidoscope/Chapter5/lexer.ml
Normal file
@ -0,0 +1,57 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Lexer
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
let rec lex = parser
|
||||
(* Skip any whitespace. *)
|
||||
| [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
|
||||
|
||||
(* identifier: [a-zA-Z][a-zA-Z0-9] *)
|
||||
| [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
|
||||
let buffer = Buffer.create 1 in
|
||||
Buffer.add_char buffer c;
|
||||
lex_ident buffer stream
|
||||
|
||||
(* number: [0-9.]+ *)
|
||||
| [< ' ('0' .. '9' as c); stream >] ->
|
||||
let buffer = Buffer.create 1 in
|
||||
Buffer.add_char buffer c;
|
||||
lex_number buffer stream
|
||||
|
||||
(* Comment until end of line. *)
|
||||
| [< ' ('#'); stream >] ->
|
||||
lex_comment stream
|
||||
|
||||
(* Otherwise, just return the character as its ascii value. *)
|
||||
| [< 'c; stream >] ->
|
||||
[< 'Token.Kwd c; lex stream >]
|
||||
|
||||
(* end of stream. *)
|
||||
| [< >] -> [< >]
|
||||
|
||||
and lex_number buffer = parser
|
||||
| [< ' ('0' .. '9' | '.' as c); stream >] ->
|
||||
Buffer.add_char buffer c;
|
||||
lex_number buffer stream
|
||||
| [< stream=lex >] ->
|
||||
[< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
|
||||
|
||||
and lex_ident buffer = parser
|
||||
| [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
|
||||
Buffer.add_char buffer c;
|
||||
lex_ident buffer stream
|
||||
| [< stream=lex >] ->
|
||||
match Buffer.contents buffer with
|
||||
| "def" -> [< 'Token.Def; stream >]
|
||||
| "extern" -> [< 'Token.Extern; stream >]
|
||||
| "if" -> [< 'Token.If; stream >]
|
||||
| "then" -> [< 'Token.Then; stream >]
|
||||
| "else" -> [< 'Token.Else; stream >]
|
||||
| "for" -> [< 'Token.For; stream >]
|
||||
| "in" -> [< 'Token.In; stream >]
|
||||
| id -> [< 'Token.Ident id; stream >]
|
||||
|
||||
and lex_comment = parser
|
||||
| [< ' ('\n'); stream=lex >] -> stream
|
||||
| [< 'c; e=lex_comment >] -> e
|
||||
| [< >] -> [< >]
|
10
examples/OCaml-Kaleidoscope/Chapter5/myocamlbuild.ml
Normal file
10
examples/OCaml-Kaleidoscope/Chapter5/myocamlbuild.ml
Normal file
@ -0,0 +1,10 @@
|
||||
open Ocamlbuild_plugin;;
|
||||
|
||||
ocaml_lib ~extern:true "llvm";;
|
||||
ocaml_lib ~extern:true "llvm_analysis";;
|
||||
ocaml_lib ~extern:true "llvm_executionengine";;
|
||||
ocaml_lib ~extern:true "llvm_target";;
|
||||
ocaml_lib ~extern:true "llvm_scalar_opts";;
|
||||
|
||||
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
|
||||
dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
|
158
examples/OCaml-Kaleidoscope/Chapter5/parser.ml
Normal file
158
examples/OCaml-Kaleidoscope/Chapter5/parser.ml
Normal file
@ -0,0 +1,158 @@
|
||||
(*===---------------------------------------------------------------------===
|
||||
* Parser
|
||||
*===---------------------------------------------------------------------===*)
|
||||
|
||||
(* binop_precedence - This holds the precedence for each binary operator that is
|
||||
* defined *)
|
||||
let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
|
||||
|
||||
(* precedence - Get the precedence of the pending binary operator token. *)
|
||||
let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
|
||||
|
||||
(* primary
|
||||
* ::= identifier
|
||||
* ::= numberexpr
|
||||
* ::= parenexpr
|
||||
* ::= ifexpr
|
||||
* ::= forexpr *)
|
||||
let rec parse_primary = parser
|
||||
(* numberexpr ::= number *)
|
||||
| [< 'Token.Number n >] -> Ast.Number n
|
||||
|
||||
(* parenexpr ::= '(' expression ')' *)
|
||||
| [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
|
||||
|
||||
(* identifierexpr
|
||||
* ::= identifier
|
||||
* ::= identifier '(' argumentexpr ')' *)
|
||||
| [< 'Token.Ident id; stream >] ->
|
||||
let rec parse_args accumulator = parser
|
||||
| [< e=parse_expr; stream >] ->
|
||||
begin parser
|
||||
| [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
|
||||
| [< >] -> e :: accumulator
|
||||
end stream
|
||||
| [< >] -> accumulator
|
||||
in
|
||||
let rec parse_ident id = parser
|
||||
(* Call. *)
|
||||
| [< 'Token.Kwd '(';
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')'">] ->
|
||||
Ast.Call (id, Array.of_list (List.rev args))
|
||||
|
||||
(* Simple variable ref. *)
|
||||
| [< >] -> Ast.Variable id
|
||||
in
|
||||
parse_ident id stream
|
||||
|
||||
(* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
|
||||
| [< 'Token.If; c=parse_expr;
|
||||
'Token.Then ?? "expected 'then'"; t=parse_expr;
|
||||
'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
|
||||
Ast.If (c, t, e)
|
||||
|
||||
(* forexpr
|
||||
::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *)
|
||||
| [< 'Token.For;
|
||||
'Token.Ident id ?? "expected identifier after for";
|
||||
'Token.Kwd '=' ?? "expected '=' after for";
|
||||
stream >] ->
|
||||
begin parser
|
||||
| [<
|
||||
start=parse_expr;
|
||||
'Token.Kwd ',' ?? "expected ',' after for";
|
||||
end_=parse_expr;
|
||||
stream >] ->
|
||||
let step =
|
||||
begin parser
|
||||
| [< 'Token.Kwd ','; step=parse_expr >] -> Some step
|
||||
| [< >] -> None
|
||||
end stream
|
||||
in
|
||||
begin parser
|
||||
| [< 'Token.In; body=parse_expr >] ->
|
||||
Ast.For (id, start, end_, step, body)
|
||||
| [< >] ->
|
||||
raise (Stream.Error "expected 'in' after for")
|
||||
end stream
|
||||
| [< >] ->
|
||||
raise (Stream.Error "expected '=' after for")
|
||||
end stream
|
||||
|
||||
| [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
|
||||
|
||||
(* binoprhs
|
||||
* ::= ('+' primary)* *)
|
||||
and parse_bin_rhs expr_prec lhs stream =
|
||||
match Stream.peek stream with
|
||||
(* If this is a binop, find its precedence. *)
|
||||
| Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
|
||||
let token_prec = precedence c in
|
||||
|
||||
(* If this is a binop that binds at least as tightly as the current binop,
|
||||
* consume it, otherwise we are done. *)
|
||||
if token_prec < expr_prec then lhs else begin
|
||||
(* Eat the binop. *)
|
||||
Stream.junk stream;
|
||||
|
||||
(* Parse the primary expression after the binary operator. *)
|
||||
let rhs = parse_primary stream in
|
||||
|
||||
(* Okay, we know this is a binop. *)
|
||||
let rhs =
|
||||
match Stream.peek stream with
|
||||
| Some (Token.Kwd c2) ->
|
||||
(* If BinOp binds less tightly with rhs than the operator after
|
||||
* rhs, let the pending operator take rhs as its lhs. *)
|
||||
let next_prec = precedence c2 in
|
||||
if token_prec < next_prec
|
||||
then parse_bin_rhs (token_prec + 1) rhs stream
|
||||
else rhs
|
||||
| _ -> rhs
|
||||
in
|
||||
|
||||
(* Merge lhs/rhs. *)
|
||||
let lhs = Ast.Binary (c, lhs, rhs) in
|
||||
parse_bin_rhs expr_prec lhs stream
|
||||
end
|
||||
| _ -> lhs
|
||||
|
||||
(* expression
|
||||
* ::= primary binoprhs *)
|
||||
and parse_expr = parser
|
||||
| [< lhs=parse_primary; stream >] -> parse_bin_rhs 0 lhs stream
|
||||
|
||||
(* prototype
|
||||
* ::= id '(' id* ')' *)
|
||||
let parse_prototype =
|
||||
let rec parse_args accumulator = parser
|
||||
| [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
|
||||
| [< >] -> accumulator
|
||||
in
|
||||
|
||||
parser
|
||||
| [< 'Token.Ident id;
|
||||
'Token.Kwd '(' ?? "expected '(' in prototype";
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
|
||||
(* success. *)
|
||||
Ast.Prototype (id, Array.of_list (List.rev args))
|
||||
|
||||
| [< >] ->
|
||||
raise (Stream.Error "expected function name in prototype")
|
||||
|
||||
(* definition ::= 'def' prototype expression *)
|
||||
let parse_definition = parser
|
||||
| [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
|
||||
Ast.Function (p, e)
|
||||
|
||||
(* toplevelexpr ::= expression *)
|
||||
let parse_toplevel = parser
|
||||
| [< e=parse_expr >] ->
|
||||
(* Make an anonymous proto. *)
|
||||
Ast.Function (Ast.Prototype ("", [||]), e)
|
||||
|
||||
(* external ::= 'extern' prototype *)
|
||||
let parse_extern = parser
|
||||
| [< 'Token.Extern; e=parse_prototype >] -> e
|
19
examples/OCaml-Kaleidoscope/Chapter5/token.ml
Normal file
19
examples/OCaml-Kaleidoscope/Chapter5/token.ml
Normal file
@ -0,0 +1,19 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Lexer Tokens
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
|
||||
* these others for known things. *)
|
||||
type token =
|
||||
(* commands *)
|
||||
| Def | Extern
|
||||
|
||||
(* primary *)
|
||||
| Ident of string | Number of float
|
||||
|
||||
(* unknown *)
|
||||
| Kwd of char
|
||||
|
||||
(* control *)
|
||||
| If | Then | Else
|
||||
| For | In
|
49
examples/OCaml-Kaleidoscope/Chapter5/toplevel.ml
Normal file
49
examples/OCaml-Kaleidoscope/Chapter5/toplevel.ml
Normal file
@ -0,0 +1,49 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Top-Level parsing and JIT Driver
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
open Llvm_executionengine
|
||||
|
||||
(* top ::= definition | external | expression | ';' *)
|
||||
let rec main_loop the_fpm the_execution_engine stream =
|
||||
match Stream.peek stream with
|
||||
| None -> ()
|
||||
|
||||
(* ignore top-level semicolons. *)
|
||||
| Some (Token.Kwd ';') ->
|
||||
Stream.junk stream;
|
||||
main_loop the_fpm the_execution_engine stream
|
||||
|
||||
| Some token ->
|
||||
begin
|
||||
try match token with
|
||||
| Token.Def ->
|
||||
let e = Parser.parse_definition stream in
|
||||
print_endline "parsed a function definition.";
|
||||
dump_value (Codegen.codegen_func the_fpm e);
|
||||
| Token.Extern ->
|
||||
let e = Parser.parse_extern stream in
|
||||
print_endline "parsed an extern.";
|
||||
dump_value (Codegen.codegen_proto e);
|
||||
| _ ->
|
||||
(* Evaluate a top-level expression into an anonymous function. *)
|
||||
let e = Parser.parse_toplevel stream in
|
||||
print_endline "parsed a top-level expr";
|
||||
let the_function = Codegen.codegen_func the_fpm e in
|
||||
dump_value the_function;
|
||||
|
||||
(* JIT the function, returning a function pointer. *)
|
||||
let result = ExecutionEngine.run_function the_function [||]
|
||||
the_execution_engine in
|
||||
|
||||
print_string "Evaluated to ";
|
||||
print_float (GenericValue.as_float Codegen.double_type result);
|
||||
print_newline ();
|
||||
with Stream.Error s | Codegen.Error s ->
|
||||
(* Skip token for error recovery. *)
|
||||
Stream.junk stream;
|
||||
print_endline s;
|
||||
end;
|
||||
print_string "ready> "; flush stdout;
|
||||
main_loop the_fpm the_execution_engine stream
|
53
examples/OCaml-Kaleidoscope/Chapter5/toy.ml
Normal file
53
examples/OCaml-Kaleidoscope/Chapter5/toy.ml
Normal file
@ -0,0 +1,53 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Main driver code.
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
open Llvm_executionengine
|
||||
open Llvm_target
|
||||
open Llvm_scalar_opts
|
||||
|
||||
let main () =
|
||||
ignore (initialize_native_target ());
|
||||
|
||||
(* Install standard binary operators.
|
||||
* 1 is the lowest precedence. *)
|
||||
Hashtbl.add Parser.binop_precedence '<' 10;
|
||||
Hashtbl.add Parser.binop_precedence '+' 20;
|
||||
Hashtbl.add Parser.binop_precedence '-' 20;
|
||||
Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *)
|
||||
|
||||
(* Prime the first token. *)
|
||||
print_string "ready> "; flush stdout;
|
||||
let stream = Lexer.lex (Stream.of_channel stdin) in
|
||||
|
||||
(* Create the JIT. *)
|
||||
let the_execution_engine = ExecutionEngine.create Codegen.the_module in
|
||||
let the_fpm = PassManager.create_function Codegen.the_module in
|
||||
|
||||
(* Set up the optimizer pipeline. Start with registering info about how the
|
||||
* target lays out data structures. *)
|
||||
TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
|
||||
|
||||
(* Do simple "peephole" optimizations and bit-twiddling optzn. *)
|
||||
add_instruction_combination the_fpm;
|
||||
|
||||
(* reassociate expressions. *)
|
||||
add_reassociation the_fpm;
|
||||
|
||||
(* Eliminate Common SubExpressions. *)
|
||||
add_gvn the_fpm;
|
||||
|
||||
(* Simplify the control flow graph (deleting unreachable blocks, etc). *)
|
||||
add_cfg_simplification the_fpm;
|
||||
|
||||
ignore (PassManager.initialize the_fpm);
|
||||
|
||||
(* Run the main "interpreter loop" now. *)
|
||||
Toplevel.main_loop the_fpm the_execution_engine stream;
|
||||
|
||||
(* Print out all the generated code. *)
|
||||
dump_module Codegen.the_module
|
||||
;;
|
||||
|
||||
main ()
|
25
examples/OCaml-Kaleidoscope/Chapter6/Makefile
Normal file
25
examples/OCaml-Kaleidoscope/Chapter6/Makefile
Normal file
@ -0,0 +1,25 @@
|
||||
##===- examples/OCaml-Kaleidoscope/Chapter6/Makefile -------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 6.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL := ../../..
|
||||
TOOLNAME := OCaml-Kaleidoscope-Ch6
|
||||
EXAMPLE_TOOL := 1
|
||||
UsedComponents := core
|
||||
UsedOcamLibs := llvm llvm_analysis llvm_executionengine llvm_target \
|
||||
llvm_scalar_opts
|
||||
|
||||
OCAMLCFLAGS += -pp camlp4of
|
||||
|
||||
ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml
|
||||
|
||||
include $(LEVEL)/bindings/ocaml/Makefile.ocaml
|
4
examples/OCaml-Kaleidoscope/Chapter6/_tags
Normal file
4
examples/OCaml-Kaleidoscope/Chapter6/_tags
Normal file
@ -0,0 +1,4 @@
|
||||
<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
|
||||
<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
|
||||
<*.{byte,native}>: use_llvm_executionengine, use_llvm_target
|
||||
<*.{byte,native}>: use_llvm_scalar_opts, use_bindings
|
36
examples/OCaml-Kaleidoscope/Chapter6/ast.ml
Normal file
36
examples/OCaml-Kaleidoscope/Chapter6/ast.ml
Normal file
@ -0,0 +1,36 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Abstract Syntax Tree (aka Parse Tree)
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(* expr - Base type for all expression nodes. *)
|
||||
type expr =
|
||||
(* variant for numeric literals like "1.0". *)
|
||||
| Number of float
|
||||
|
||||
(* variant for referencing a variable, like "a". *)
|
||||
| Variable of string
|
||||
|
||||
(* variant for a unary operator. *)
|
||||
| Unary of char * expr
|
||||
|
||||
(* variant for a binary operator. *)
|
||||
| Binary of char * expr * expr
|
||||
|
||||
(* variant for function calls. *)
|
||||
| Call of string * expr array
|
||||
|
||||
(* variant for if/then/else. *)
|
||||
| If of expr * expr * expr
|
||||
|
||||
(* variant for for/in. *)
|
||||
| For of string * expr * expr * expr option * expr
|
||||
|
||||
(* proto - This type represents the "prototype" for a function, which captures
|
||||
* its name, and its argument names (thus implicitly the number of arguments the
|
||||
* function takes). *)
|
||||
type proto =
|
||||
| Prototype of string * string array
|
||||
| BinOpPrototype of string * string array * int
|
||||
|
||||
(* func - This type represents a function definition itself. *)
|
||||
type func = Function of proto * expr
|
13
examples/OCaml-Kaleidoscope/Chapter6/bindings.c
Normal file
13
examples/OCaml-Kaleidoscope/Chapter6/bindings.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* putchard - putchar that takes a double and returns 0. */
|
||||
extern double putchard(double X) {
|
||||
putchar((char)X);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* printd - printf that takes a double prints it as "%f\n", returning 0. */
|
||||
extern double printd(double X) {
|
||||
printf("%f\n", X);
|
||||
return 0;
|
||||
}
|
251
examples/OCaml-Kaleidoscope/Chapter6/codegen.ml
Normal file
251
examples/OCaml-Kaleidoscope/Chapter6/codegen.ml
Normal file
@ -0,0 +1,251 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Code Generation
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
|
||||
exception Error of string
|
||||
|
||||
let context = global_context ()
|
||||
let the_module = create_module context "my cool jit"
|
||||
let builder = builder context
|
||||
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
|
||||
let double_type = double_type context
|
||||
|
||||
let rec codegen_expr = function
|
||||
| Ast.Number n -> const_float double_type n
|
||||
| Ast.Variable name ->
|
||||
(try Hashtbl.find named_values name with
|
||||
| Not_found -> raise (Error "unknown variable name"))
|
||||
| Ast.Unary (op, operand) ->
|
||||
let operand = codegen_expr operand in
|
||||
let callee = "unary" ^ (String.make 1 op) in
|
||||
let callee =
|
||||
match lookup_function callee the_module with
|
||||
| Some callee -> callee
|
||||
| None -> raise (Error "unknown unary operator")
|
||||
in
|
||||
build_call callee [|operand|] "unop" builder
|
||||
| Ast.Binary (op, lhs, rhs) ->
|
||||
let lhs_val = codegen_expr lhs in
|
||||
let rhs_val = codegen_expr rhs in
|
||||
begin
|
||||
match op with
|
||||
| '+' -> build_add lhs_val rhs_val "addtmp" builder
|
||||
| '-' -> build_sub lhs_val rhs_val "subtmp" builder
|
||||
| '*' -> build_mul lhs_val rhs_val "multmp" builder
|
||||
| '<' ->
|
||||
(* Convert bool 0/1 to double 0.0 or 1.0 *)
|
||||
let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
|
||||
build_uitofp i double_type "booltmp" builder
|
||||
| _ ->
|
||||
(* If it wasn't a builtin binary operator, it must be a user defined
|
||||
* one. Emit a call to it. *)
|
||||
let callee = "binary" ^ (String.make 1 op) in
|
||||
let callee =
|
||||
match lookup_function callee the_module with
|
||||
| Some callee -> callee
|
||||
| None -> raise (Error "binary operator not found!")
|
||||
in
|
||||
build_call callee [|lhs_val; rhs_val|] "binop" builder
|
||||
end
|
||||
| Ast.Call (callee, args) ->
|
||||
(* Look up the name in the module table. *)
|
||||
let callee =
|
||||
match lookup_function callee the_module with
|
||||
| Some callee -> callee
|
||||
| None -> raise (Error "unknown function referenced")
|
||||
in
|
||||
let params = params callee in
|
||||
|
||||
(* If argument mismatch error. *)
|
||||
if Array.length params == Array.length args then () else
|
||||
raise (Error "incorrect # arguments passed");
|
||||
let args = Array.map codegen_expr args in
|
||||
build_call callee args "calltmp" builder
|
||||
| Ast.If (cond, then_, else_) ->
|
||||
let cond = codegen_expr cond in
|
||||
|
||||
(* Convert condition to a bool by comparing equal to 0.0 *)
|
||||
let zero = const_float double_type 0.0 in
|
||||
let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in
|
||||
|
||||
(* Grab the first block so that we might later add the conditional branch
|
||||
* to it at the end of the function. *)
|
||||
let start_bb = insertion_block builder in
|
||||
let the_function = block_parent start_bb in
|
||||
|
||||
let then_bb = append_block context "then" the_function in
|
||||
|
||||
(* Emit 'then' value. *)
|
||||
position_at_end then_bb builder;
|
||||
let then_val = codegen_expr then_ in
|
||||
|
||||
(* Codegen of 'then' can change the current block, update then_bb for the
|
||||
* phi. We create a new name because one is used for the phi node, and the
|
||||
* other is used for the conditional branch. *)
|
||||
let new_then_bb = insertion_block builder in
|
||||
|
||||
(* Emit 'else' value. *)
|
||||
let else_bb = append_block context "else" the_function in
|
||||
position_at_end else_bb builder;
|
||||
let else_val = codegen_expr else_ in
|
||||
|
||||
(* Codegen of 'else' can change the current block, update else_bb for the
|
||||
* phi. *)
|
||||
let new_else_bb = insertion_block builder in
|
||||
|
||||
(* Emit merge block. *)
|
||||
let merge_bb = append_block context "ifcont" the_function in
|
||||
position_at_end merge_bb builder;
|
||||
let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
|
||||
let phi = build_phi incoming "iftmp" builder in
|
||||
|
||||
(* Return to the start block to add the conditional branch. *)
|
||||
position_at_end start_bb builder;
|
||||
ignore (build_cond_br cond_val then_bb else_bb builder);
|
||||
|
||||
(* Set a unconditional branch at the end of the 'then' block and the
|
||||
* 'else' block to the 'merge' block. *)
|
||||
position_at_end new_then_bb builder; ignore (build_br merge_bb builder);
|
||||
position_at_end new_else_bb builder; ignore (build_br merge_bb builder);
|
||||
|
||||
(* Finally, set the builder to the end of the merge block. *)
|
||||
position_at_end merge_bb builder;
|
||||
|
||||
phi
|
||||
| Ast.For (var_name, start, end_, step, body) ->
|
||||
(* Emit the start code first, without 'variable' in scope. *)
|
||||
let start_val = codegen_expr start in
|
||||
|
||||
(* Make the new basic block for the loop header, inserting after current
|
||||
* block. *)
|
||||
let preheader_bb = insertion_block builder in
|
||||
let the_function = block_parent preheader_bb in
|
||||
let loop_bb = append_block context "loop" the_function in
|
||||
|
||||
(* Insert an explicit fall through from the current block to the
|
||||
* loop_bb. *)
|
||||
ignore (build_br loop_bb builder);
|
||||
|
||||
(* Start insertion in loop_bb. *)
|
||||
position_at_end loop_bb builder;
|
||||
|
||||
(* Start the PHI node with an entry for start. *)
|
||||
let variable = build_phi [(start_val, preheader_bb)] var_name builder in
|
||||
|
||||
(* Within the loop, the variable is defined equal to the PHI node. If it
|
||||
* shadows an existing variable, we have to restore it, so save it
|
||||
* now. *)
|
||||
let old_val =
|
||||
try Some (Hashtbl.find named_values var_name) with Not_found -> None
|
||||
in
|
||||
Hashtbl.add named_values var_name variable;
|
||||
|
||||
(* Emit the body of the loop. This, like any other expr, can change the
|
||||
* current BB. Note that we ignore the value computed by the body, but
|
||||
* don't allow an error *)
|
||||
ignore (codegen_expr body);
|
||||
|
||||
(* Emit the step value. *)
|
||||
let step_val =
|
||||
match step with
|
||||
| Some step -> codegen_expr step
|
||||
(* If not specified, use 1.0. *)
|
||||
| None -> const_float double_type 1.0
|
||||
in
|
||||
|
||||
let next_var = build_add variable step_val "nextvar" builder in
|
||||
|
||||
(* Compute the end condition. *)
|
||||
let end_cond = codegen_expr end_ in
|
||||
|
||||
(* Convert condition to a bool by comparing equal to 0.0. *)
|
||||
let zero = const_float double_type 0.0 in
|
||||
let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in
|
||||
|
||||
(* Create the "after loop" block and insert it. *)
|
||||
let loop_end_bb = insertion_block builder in
|
||||
let after_bb = append_block context "afterloop" the_function in
|
||||
|
||||
(* Insert the conditional branch into the end of loop_end_bb. *)
|
||||
ignore (build_cond_br end_cond loop_bb after_bb builder);
|
||||
|
||||
(* Any new code will be inserted in after_bb. *)
|
||||
position_at_end after_bb builder;
|
||||
|
||||
(* Add a new entry to the PHI node for the backedge. *)
|
||||
add_incoming (next_var, loop_end_bb) variable;
|
||||
|
||||
(* Restore the unshadowed variable. *)
|
||||
begin match old_val with
|
||||
| Some old_val -> Hashtbl.add named_values var_name old_val
|
||||
| None -> ()
|
||||
end;
|
||||
|
||||
(* for expr always returns 0.0. *)
|
||||
const_null double_type
|
||||
|
||||
let codegen_proto = function
|
||||
| Ast.Prototype (name, args) | Ast.BinOpPrototype (name, args, _) ->
|
||||
(* Make the function type: double(double,double) etc. *)
|
||||
let doubles = Array.make (Array.length args) double_type in
|
||||
let ft = function_type double_type doubles in
|
||||
let f =
|
||||
match lookup_function name the_module with
|
||||
| None -> declare_function name ft the_module
|
||||
|
||||
(* If 'f' conflicted, there was already something named 'name'. If it
|
||||
* has a body, don't allow redefinition or reextern. *)
|
||||
| Some f ->
|
||||
(* If 'f' already has a body, reject this. *)
|
||||
if block_begin f <> At_end f then
|
||||
raise (Error "redefinition of function");
|
||||
|
||||
(* If 'f' took a different number of arguments, reject. *)
|
||||
if element_type (type_of f) <> ft then
|
||||
raise (Error "redefinition of function with different # args");
|
||||
f
|
||||
in
|
||||
|
||||
(* Set names for all arguments. *)
|
||||
Array.iteri (fun i a ->
|
||||
let n = args.(i) in
|
||||
set_value_name n a;
|
||||
Hashtbl.add named_values n a;
|
||||
) (params f);
|
||||
f
|
||||
|
||||
let codegen_func the_fpm = function
|
||||
| Ast.Function (proto, body) ->
|
||||
Hashtbl.clear named_values;
|
||||
let the_function = codegen_proto proto in
|
||||
|
||||
(* If this is an operator, install it. *)
|
||||
begin match proto with
|
||||
| Ast.BinOpPrototype (name, args, prec) ->
|
||||
let op = name.[String.length name - 1] in
|
||||
Hashtbl.add Parser.binop_precedence op prec;
|
||||
| _ -> ()
|
||||
end;
|
||||
|
||||
(* Create a new basic block to start insertion into. *)
|
||||
let bb = append_block context "entry" the_function in
|
||||
position_at_end bb builder;
|
||||
|
||||
try
|
||||
let ret_val = codegen_expr body in
|
||||
|
||||
(* Finish off the function. *)
|
||||
let _ = build_ret ret_val builder in
|
||||
|
||||
(* Validate the generated code, checking for consistency. *)
|
||||
Llvm_analysis.assert_valid_function the_function;
|
||||
|
||||
(* Optimize the function. *)
|
||||
let _ = PassManager.run_function the_function the_fpm in
|
||||
|
||||
the_function
|
||||
with e ->
|
||||
delete_function the_function;
|
||||
raise e
|
59
examples/OCaml-Kaleidoscope/Chapter6/lexer.ml
Normal file
59
examples/OCaml-Kaleidoscope/Chapter6/lexer.ml
Normal file
@ -0,0 +1,59 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Lexer
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
let rec lex = parser
|
||||
(* Skip any whitespace. *)
|
||||
| [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
|
||||
|
||||
(* identifier: [a-zA-Z][a-zA-Z0-9] *)
|
||||
| [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
|
||||
let buffer = Buffer.create 1 in
|
||||
Buffer.add_char buffer c;
|
||||
lex_ident buffer stream
|
||||
|
||||
(* number: [0-9.]+ *)
|
||||
| [< ' ('0' .. '9' as c); stream >] ->
|
||||
let buffer = Buffer.create 1 in
|
||||
Buffer.add_char buffer c;
|
||||
lex_number buffer stream
|
||||
|
||||
(* Comment until end of line. *)
|
||||
| [< ' ('#'); stream >] ->
|
||||
lex_comment stream
|
||||
|
||||
(* Otherwise, just return the character as its ascii value. *)
|
||||
| [< 'c; stream >] ->
|
||||
[< 'Token.Kwd c; lex stream >]
|
||||
|
||||
(* end of stream. *)
|
||||
| [< >] -> [< >]
|
||||
|
||||
and lex_number buffer = parser
|
||||
| [< ' ('0' .. '9' | '.' as c); stream >] ->
|
||||
Buffer.add_char buffer c;
|
||||
lex_number buffer stream
|
||||
| [< stream=lex >] ->
|
||||
[< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
|
||||
|
||||
and lex_ident buffer = parser
|
||||
| [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
|
||||
Buffer.add_char buffer c;
|
||||
lex_ident buffer stream
|
||||
| [< stream=lex >] ->
|
||||
match Buffer.contents buffer with
|
||||
| "def" -> [< 'Token.Def; stream >]
|
||||
| "extern" -> [< 'Token.Extern; stream >]
|
||||
| "if" -> [< 'Token.If; stream >]
|
||||
| "then" -> [< 'Token.Then; stream >]
|
||||
| "else" -> [< 'Token.Else; stream >]
|
||||
| "for" -> [< 'Token.For; stream >]
|
||||
| "in" -> [< 'Token.In; stream >]
|
||||
| "binary" -> [< 'Token.Binary; stream >]
|
||||
| "unary" -> [< 'Token.Unary; stream >]
|
||||
| id -> [< 'Token.Ident id; stream >]
|
||||
|
||||
and lex_comment = parser
|
||||
| [< ' ('\n'); stream=lex >] -> stream
|
||||
| [< 'c; e=lex_comment >] -> e
|
||||
| [< >] -> [< >]
|
10
examples/OCaml-Kaleidoscope/Chapter6/myocamlbuild.ml
Normal file
10
examples/OCaml-Kaleidoscope/Chapter6/myocamlbuild.ml
Normal file
@ -0,0 +1,10 @@
|
||||
open Ocamlbuild_plugin;;
|
||||
|
||||
ocaml_lib ~extern:true "llvm";;
|
||||
ocaml_lib ~extern:true "llvm_analysis";;
|
||||
ocaml_lib ~extern:true "llvm_executionengine";;
|
||||
ocaml_lib ~extern:true "llvm_target";;
|
||||
ocaml_lib ~extern:true "llvm_scalar_opts";;
|
||||
|
||||
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
|
||||
dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
|
195
examples/OCaml-Kaleidoscope/Chapter6/parser.ml
Normal file
195
examples/OCaml-Kaleidoscope/Chapter6/parser.ml
Normal file
@ -0,0 +1,195 @@
|
||||
(*===---------------------------------------------------------------------===
|
||||
* Parser
|
||||
*===---------------------------------------------------------------------===*)
|
||||
|
||||
(* binop_precedence - This holds the precedence for each binary operator that is
|
||||
* defined *)
|
||||
let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
|
||||
|
||||
(* precedence - Get the precedence of the pending binary operator token. *)
|
||||
let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
|
||||
|
||||
(* primary
|
||||
* ::= identifier
|
||||
* ::= numberexpr
|
||||
* ::= parenexpr
|
||||
* ::= ifexpr
|
||||
* ::= forexpr *)
|
||||
let rec parse_primary = parser
|
||||
(* numberexpr ::= number *)
|
||||
| [< 'Token.Number n >] -> Ast.Number n
|
||||
|
||||
(* parenexpr ::= '(' expression ')' *)
|
||||
| [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
|
||||
|
||||
(* identifierexpr
|
||||
* ::= identifier
|
||||
* ::= identifier '(' argumentexpr ')' *)
|
||||
| [< 'Token.Ident id; stream >] ->
|
||||
let rec parse_args accumulator = parser
|
||||
| [< e=parse_expr; stream >] ->
|
||||
begin parser
|
||||
| [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
|
||||
| [< >] -> e :: accumulator
|
||||
end stream
|
||||
| [< >] -> accumulator
|
||||
in
|
||||
let rec parse_ident id = parser
|
||||
(* Call. *)
|
||||
| [< 'Token.Kwd '(';
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')'">] ->
|
||||
Ast.Call (id, Array.of_list (List.rev args))
|
||||
|
||||
(* Simple variable ref. *)
|
||||
| [< >] -> Ast.Variable id
|
||||
in
|
||||
parse_ident id stream
|
||||
|
||||
(* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
|
||||
| [< 'Token.If; c=parse_expr;
|
||||
'Token.Then ?? "expected 'then'"; t=parse_expr;
|
||||
'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
|
||||
Ast.If (c, t, e)
|
||||
|
||||
(* forexpr
|
||||
::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *)
|
||||
| [< 'Token.For;
|
||||
'Token.Ident id ?? "expected identifier after for";
|
||||
'Token.Kwd '=' ?? "expected '=' after for";
|
||||
stream >] ->
|
||||
begin parser
|
||||
| [<
|
||||
start=parse_expr;
|
||||
'Token.Kwd ',' ?? "expected ',' after for";
|
||||
end_=parse_expr;
|
||||
stream >] ->
|
||||
let step =
|
||||
begin parser
|
||||
| [< 'Token.Kwd ','; step=parse_expr >] -> Some step
|
||||
| [< >] -> None
|
||||
end stream
|
||||
in
|
||||
begin parser
|
||||
| [< 'Token.In; body=parse_expr >] ->
|
||||
Ast.For (id, start, end_, step, body)
|
||||
| [< >] ->
|
||||
raise (Stream.Error "expected 'in' after for")
|
||||
end stream
|
||||
| [< >] ->
|
||||
raise (Stream.Error "expected '=' after for")
|
||||
end stream
|
||||
|
||||
| [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
|
||||
|
||||
(* unary
|
||||
* ::= primary
|
||||
* ::= '!' unary *)
|
||||
and parse_unary = parser
|
||||
(* If this is a unary operator, read it. *)
|
||||
| [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] ->
|
||||
Ast.Unary (op, operand)
|
||||
|
||||
(* If the current token is not an operator, it must be a primary expr. *)
|
||||
| [< stream >] -> parse_primary stream
|
||||
|
||||
(* binoprhs
|
||||
* ::= ('+' primary)* *)
|
||||
and parse_bin_rhs expr_prec lhs stream =
|
||||
match Stream.peek stream with
|
||||
(* If this is a binop, find its precedence. *)
|
||||
| Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
|
||||
let token_prec = precedence c in
|
||||
|
||||
(* If this is a binop that binds at least as tightly as the current binop,
|
||||
* consume it, otherwise we are done. *)
|
||||
if token_prec < expr_prec then lhs else begin
|
||||
(* Eat the binop. *)
|
||||
Stream.junk stream;
|
||||
|
||||
(* Parse the unary expression after the binary operator. *)
|
||||
let rhs = parse_unary stream in
|
||||
|
||||
(* Okay, we know this is a binop. *)
|
||||
let rhs =
|
||||
match Stream.peek stream with
|
||||
| Some (Token.Kwd c2) ->
|
||||
(* If BinOp binds less tightly with rhs than the operator after
|
||||
* rhs, let the pending operator take rhs as its lhs. *)
|
||||
let next_prec = precedence c2 in
|
||||
if token_prec < next_prec
|
||||
then parse_bin_rhs (token_prec + 1) rhs stream
|
||||
else rhs
|
||||
| _ -> rhs
|
||||
in
|
||||
|
||||
(* Merge lhs/rhs. *)
|
||||
let lhs = Ast.Binary (c, lhs, rhs) in
|
||||
parse_bin_rhs expr_prec lhs stream
|
||||
end
|
||||
| _ -> lhs
|
||||
|
||||
(* expression
|
||||
* ::= primary binoprhs *)
|
||||
and parse_expr = parser
|
||||
| [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream
|
||||
|
||||
(* prototype
|
||||
* ::= id '(' id* ')'
|
||||
* ::= binary LETTER number? (id, id)
|
||||
* ::= unary LETTER number? (id) *)
|
||||
let parse_prototype =
|
||||
let rec parse_args accumulator = parser
|
||||
| [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
|
||||
| [< >] -> accumulator
|
||||
in
|
||||
let parse_operator = parser
|
||||
| [< 'Token.Unary >] -> "unary", 1
|
||||
| [< 'Token.Binary >] -> "binary", 2
|
||||
in
|
||||
let parse_binary_precedence = parser
|
||||
| [< 'Token.Number n >] -> int_of_float n
|
||||
| [< >] -> 30
|
||||
in
|
||||
parser
|
||||
| [< 'Token.Ident id;
|
||||
'Token.Kwd '(' ?? "expected '(' in prototype";
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
|
||||
(* success. *)
|
||||
Ast.Prototype (id, Array.of_list (List.rev args))
|
||||
| [< (prefix, kind)=parse_operator;
|
||||
'Token.Kwd op ?? "expected an operator";
|
||||
(* Read the precedence if present. *)
|
||||
binary_precedence=parse_binary_precedence;
|
||||
'Token.Kwd '(' ?? "expected '(' in prototype";
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
|
||||
let name = prefix ^ (String.make 1 op) in
|
||||
let args = Array.of_list (List.rev args) in
|
||||
|
||||
(* Verify right number of arguments for operator. *)
|
||||
if Array.length args != kind
|
||||
then raise (Stream.Error "invalid number of operands for operator")
|
||||
else
|
||||
if kind == 1 then
|
||||
Ast.Prototype (name, args)
|
||||
else
|
||||
Ast.BinOpPrototype (name, args, binary_precedence)
|
||||
| [< >] ->
|
||||
raise (Stream.Error "expected function name in prototype")
|
||||
|
||||
(* definition ::= 'def' prototype expression *)
|
||||
let parse_definition = parser
|
||||
| [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
|
||||
Ast.Function (p, e)
|
||||
|
||||
(* toplevelexpr ::= expression *)
|
||||
let parse_toplevel = parser
|
||||
| [< e=parse_expr >] ->
|
||||
(* Make an anonymous proto. *)
|
||||
Ast.Function (Ast.Prototype ("", [||]), e)
|
||||
|
||||
(* external ::= 'extern' prototype *)
|
||||
let parse_extern = parser
|
||||
| [< 'Token.Extern; e=parse_prototype >] -> e
|
22
examples/OCaml-Kaleidoscope/Chapter6/token.ml
Normal file
22
examples/OCaml-Kaleidoscope/Chapter6/token.ml
Normal file
@ -0,0 +1,22 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Lexer Tokens
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
|
||||
* these others for known things. *)
|
||||
type token =
|
||||
(* commands *)
|
||||
| Def | Extern
|
||||
|
||||
(* primary *)
|
||||
| Ident of string | Number of float
|
||||
|
||||
(* unknown *)
|
||||
| Kwd of char
|
||||
|
||||
(* control *)
|
||||
| If | Then | Else
|
||||
| For | In
|
||||
|
||||
(* operators *)
|
||||
| Binary | Unary
|
49
examples/OCaml-Kaleidoscope/Chapter6/toplevel.ml
Normal file
49
examples/OCaml-Kaleidoscope/Chapter6/toplevel.ml
Normal file
@ -0,0 +1,49 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Top-Level parsing and JIT Driver
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
open Llvm_executionengine
|
||||
|
||||
(* top ::= definition | external | expression | ';' *)
|
||||
let rec main_loop the_fpm the_execution_engine stream =
|
||||
match Stream.peek stream with
|
||||
| None -> ()
|
||||
|
||||
(* ignore top-level semicolons. *)
|
||||
| Some (Token.Kwd ';') ->
|
||||
Stream.junk stream;
|
||||
main_loop the_fpm the_execution_engine stream
|
||||
|
||||
| Some token ->
|
||||
begin
|
||||
try match token with
|
||||
| Token.Def ->
|
||||
let e = Parser.parse_definition stream in
|
||||
print_endline "parsed a function definition.";
|
||||
dump_value (Codegen.codegen_func the_fpm e);
|
||||
| Token.Extern ->
|
||||
let e = Parser.parse_extern stream in
|
||||
print_endline "parsed an extern.";
|
||||
dump_value (Codegen.codegen_proto e);
|
||||
| _ ->
|
||||
(* Evaluate a top-level expression into an anonymous function. *)
|
||||
let e = Parser.parse_toplevel stream in
|
||||
print_endline "parsed a top-level expr";
|
||||
let the_function = Codegen.codegen_func the_fpm e in
|
||||
dump_value the_function;
|
||||
|
||||
(* JIT the function, returning a function pointer. *)
|
||||
let result = ExecutionEngine.run_function the_function [||]
|
||||
the_execution_engine in
|
||||
|
||||
print_string "Evaluated to ";
|
||||
print_float (GenericValue.as_float Codegen.double_type result);
|
||||
print_newline ();
|
||||
with Stream.Error s | Codegen.Error s ->
|
||||
(* Skip token for error recovery. *)
|
||||
Stream.junk stream;
|
||||
print_endline s;
|
||||
end;
|
||||
print_string "ready> "; flush stdout;
|
||||
main_loop the_fpm the_execution_engine stream
|
53
examples/OCaml-Kaleidoscope/Chapter6/toy.ml
Normal file
53
examples/OCaml-Kaleidoscope/Chapter6/toy.ml
Normal file
@ -0,0 +1,53 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Main driver code.
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
open Llvm_executionengine
|
||||
open Llvm_target
|
||||
open Llvm_scalar_opts
|
||||
|
||||
let main () =
|
||||
ignore (initialize_native_target ());
|
||||
|
||||
(* Install standard binary operators.
|
||||
* 1 is the lowest precedence. *)
|
||||
Hashtbl.add Parser.binop_precedence '<' 10;
|
||||
Hashtbl.add Parser.binop_precedence '+' 20;
|
||||
Hashtbl.add Parser.binop_precedence '-' 20;
|
||||
Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *)
|
||||
|
||||
(* Prime the first token. *)
|
||||
print_string "ready> "; flush stdout;
|
||||
let stream = Lexer.lex (Stream.of_channel stdin) in
|
||||
|
||||
(* Create the JIT. *)
|
||||
let the_execution_engine = ExecutionEngine.create Codegen.the_module in
|
||||
let the_fpm = PassManager.create_function Codegen.the_module in
|
||||
|
||||
(* Set up the optimizer pipeline. Start with registering info about how the
|
||||
* target lays out data structures. *)
|
||||
TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
|
||||
|
||||
(* Do simple "peephole" optimizations and bit-twiddling optzn. *)
|
||||
add_instruction_combination the_fpm;
|
||||
|
||||
(* reassociate expressions. *)
|
||||
add_reassociation the_fpm;
|
||||
|
||||
(* Eliminate Common SubExpressions. *)
|
||||
add_gvn the_fpm;
|
||||
|
||||
(* Simplify the control flow graph (deleting unreachable blocks, etc). *)
|
||||
add_cfg_simplification the_fpm;
|
||||
|
||||
ignore (PassManager.initialize the_fpm);
|
||||
|
||||
(* Run the main "interpreter loop" now. *)
|
||||
Toplevel.main_loop the_fpm the_execution_engine stream;
|
||||
|
||||
(* Print out all the generated code. *)
|
||||
dump_module Codegen.the_module
|
||||
;;
|
||||
|
||||
main ()
|
25
examples/OCaml-Kaleidoscope/Chapter7/Makefile
Normal file
25
examples/OCaml-Kaleidoscope/Chapter7/Makefile
Normal file
@ -0,0 +1,25 @@
|
||||
##===- examples/OCaml-Kaleidoscope/Chapter7/Makefile -------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
#
|
||||
# This is the makefile for the Objective Caml kaleidoscope tutorial, chapter 7.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL := ../../..
|
||||
TOOLNAME := OCaml-Kaleidoscope-Ch7
|
||||
EXAMPLE_TOOL := 1
|
||||
UsedComponents := core
|
||||
UsedOcamLibs := llvm llvm_analysis llvm_executionengine llvm_target \
|
||||
llvm_scalar_opts
|
||||
|
||||
OCAMLCFLAGS += -pp camlp4of
|
||||
|
||||
ExcludeSources = $(PROJ_SRC_DIR)/myocamlbuild.ml
|
||||
|
||||
include $(LEVEL)/bindings/ocaml/Makefile.ocaml
|
4
examples/OCaml-Kaleidoscope/Chapter7/_tags
Normal file
4
examples/OCaml-Kaleidoscope/Chapter7/_tags
Normal file
@ -0,0 +1,4 @@
|
||||
<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
|
||||
<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
|
||||
<*.{byte,native}>: use_llvm_executionengine, use_llvm_target
|
||||
<*.{byte,native}>: use_llvm_scalar_opts, use_bindings
|
39
examples/OCaml-Kaleidoscope/Chapter7/ast.ml
Normal file
39
examples/OCaml-Kaleidoscope/Chapter7/ast.ml
Normal file
@ -0,0 +1,39 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Abstract Syntax Tree (aka Parse Tree)
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(* expr - Base type for all expression nodes. *)
|
||||
type expr =
|
||||
(* variant for numeric literals like "1.0". *)
|
||||
| Number of float
|
||||
|
||||
(* variant for referencing a variable, like "a". *)
|
||||
| Variable of string
|
||||
|
||||
(* variant for a unary operator. *)
|
||||
| Unary of char * expr
|
||||
|
||||
(* variant for a binary operator. *)
|
||||
| Binary of char * expr * expr
|
||||
|
||||
(* variant for function calls. *)
|
||||
| Call of string * expr array
|
||||
|
||||
(* variant for if/then/else. *)
|
||||
| If of expr * expr * expr
|
||||
|
||||
(* variant for for/in. *)
|
||||
| For of string * expr * expr * expr option * expr
|
||||
|
||||
(* variant for var/in. *)
|
||||
| Var of (string * expr option) array * expr
|
||||
|
||||
(* proto - This type represents the "prototype" for a function, which captures
|
||||
* its name, and its argument names (thus implicitly the number of arguments the
|
||||
* function takes). *)
|
||||
type proto =
|
||||
| Prototype of string * string array
|
||||
| BinOpPrototype of string * string array * int
|
||||
|
||||
(* func - This type represents a function definition itself. *)
|
||||
type func = Function of proto * expr
|
13
examples/OCaml-Kaleidoscope/Chapter7/bindings.c
Normal file
13
examples/OCaml-Kaleidoscope/Chapter7/bindings.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include <stdio.h>
|
||||
|
||||
/* putchard - putchar that takes a double and returns 0. */
|
||||
extern double putchard(double X) {
|
||||
putchar((char)X);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* printd - printf that takes a double prints it as "%f\n", returning 0. */
|
||||
extern double printd(double X) {
|
||||
printf("%f\n", X);
|
||||
return 0;
|
||||
}
|
370
examples/OCaml-Kaleidoscope/Chapter7/codegen.ml
Normal file
370
examples/OCaml-Kaleidoscope/Chapter7/codegen.ml
Normal file
@ -0,0 +1,370 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Code Generation
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
|
||||
exception Error of string
|
||||
|
||||
let context = global_context ()
|
||||
let the_module = create_module context "my cool jit"
|
||||
let builder = builder context
|
||||
let named_values:(string, llvalue) Hashtbl.t = Hashtbl.create 10
|
||||
let double_type = double_type context
|
||||
|
||||
(* Create an alloca instruction in the entry block of the function. This
|
||||
* is used for mutable variables etc. *)
|
||||
let create_entry_block_alloca the_function var_name =
|
||||
let builder = builder_at context (instr_begin (entry_block the_function)) in
|
||||
build_alloca double_type var_name builder
|
||||
|
||||
let rec codegen_expr = function
|
||||
| Ast.Number n -> const_float double_type n
|
||||
| Ast.Variable name ->
|
||||
let v = try Hashtbl.find named_values name with
|
||||
| Not_found -> raise (Error "unknown variable name")
|
||||
in
|
||||
(* Load the value. *)
|
||||
build_load v name builder
|
||||
| Ast.Unary (op, operand) ->
|
||||
let operand = codegen_expr operand in
|
||||
let callee = "unary" ^ (String.make 1 op) in
|
||||
let callee =
|
||||
match lookup_function callee the_module with
|
||||
| Some callee -> callee
|
||||
| None -> raise (Error "unknown unary operator")
|
||||
in
|
||||
build_call callee [|operand|] "unop" builder
|
||||
| Ast.Binary (op, lhs, rhs) ->
|
||||
begin match op with
|
||||
| '=' ->
|
||||
(* Special case '=' because we don't want to emit the LHS as an
|
||||
* expression. *)
|
||||
let name =
|
||||
match lhs with
|
||||
| Ast.Variable name -> name
|
||||
| _ -> raise (Error "destination of '=' must be a variable")
|
||||
in
|
||||
|
||||
(* Codegen the rhs. *)
|
||||
let val_ = codegen_expr rhs in
|
||||
|
||||
(* Lookup the name. *)
|
||||
let variable = try Hashtbl.find named_values name with
|
||||
| Not_found -> raise (Error "unknown variable name")
|
||||
in
|
||||
ignore(build_store val_ variable builder);
|
||||
val_
|
||||
| _ ->
|
||||
let lhs_val = codegen_expr lhs in
|
||||
let rhs_val = codegen_expr rhs in
|
||||
begin
|
||||
match op with
|
||||
| '+' -> build_add lhs_val rhs_val "addtmp" builder
|
||||
| '-' -> build_sub lhs_val rhs_val "subtmp" builder
|
||||
| '*' -> build_mul lhs_val rhs_val "multmp" builder
|
||||
| '<' ->
|
||||
(* Convert bool 0/1 to double 0.0 or 1.0 *)
|
||||
let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
|
||||
build_uitofp i double_type "booltmp" builder
|
||||
| _ ->
|
||||
(* If it wasn't a builtin binary operator, it must be a user defined
|
||||
* one. Emit a call to it. *)
|
||||
let callee = "binary" ^ (String.make 1 op) in
|
||||
let callee =
|
||||
match lookup_function callee the_module with
|
||||
| Some callee -> callee
|
||||
| None -> raise (Error "binary operator not found!")
|
||||
in
|
||||
build_call callee [|lhs_val; rhs_val|] "binop" builder
|
||||
end
|
||||
end
|
||||
| Ast.Call (callee, args) ->
|
||||
(* Look up the name in the module table. *)
|
||||
let callee =
|
||||
match lookup_function callee the_module with
|
||||
| Some callee -> callee
|
||||
| None -> raise (Error "unknown function referenced")
|
||||
in
|
||||
let params = params callee in
|
||||
|
||||
(* If argument mismatch error. *)
|
||||
if Array.length params == Array.length args then () else
|
||||
raise (Error "incorrect # arguments passed");
|
||||
let args = Array.map codegen_expr args in
|
||||
build_call callee args "calltmp" builder
|
||||
| Ast.If (cond, then_, else_) ->
|
||||
let cond = codegen_expr cond in
|
||||
|
||||
(* Convert condition to a bool by comparing equal to 0.0 *)
|
||||
let zero = const_float double_type 0.0 in
|
||||
let cond_val = build_fcmp Fcmp.One cond zero "ifcond" builder in
|
||||
|
||||
(* Grab the first block so that we might later add the conditional branch
|
||||
* to it at the end of the function. *)
|
||||
let start_bb = insertion_block builder in
|
||||
let the_function = block_parent start_bb in
|
||||
|
||||
let then_bb = append_block context "then" the_function in
|
||||
|
||||
(* Emit 'then' value. *)
|
||||
position_at_end then_bb builder;
|
||||
let then_val = codegen_expr then_ in
|
||||
|
||||
(* Codegen of 'then' can change the current block, update then_bb for the
|
||||
* phi. We create a new name because one is used for the phi node, and the
|
||||
* other is used for the conditional branch. *)
|
||||
let new_then_bb = insertion_block builder in
|
||||
|
||||
(* Emit 'else' value. *)
|
||||
let else_bb = append_block context "else" the_function in
|
||||
position_at_end else_bb builder;
|
||||
let else_val = codegen_expr else_ in
|
||||
|
||||
(* Codegen of 'else' can change the current block, update else_bb for the
|
||||
* phi. *)
|
||||
let new_else_bb = insertion_block builder in
|
||||
|
||||
(* Emit merge block. *)
|
||||
let merge_bb = append_block context "ifcont" the_function in
|
||||
position_at_end merge_bb builder;
|
||||
let incoming = [(then_val, new_then_bb); (else_val, new_else_bb)] in
|
||||
let phi = build_phi incoming "iftmp" builder in
|
||||
|
||||
(* Return to the start block to add the conditional branch. *)
|
||||
position_at_end start_bb builder;
|
||||
ignore (build_cond_br cond_val then_bb else_bb builder);
|
||||
|
||||
(* Set a unconditional branch at the end of the 'then' block and the
|
||||
* 'else' block to the 'merge' block. *)
|
||||
position_at_end new_then_bb builder; ignore (build_br merge_bb builder);
|
||||
position_at_end new_else_bb builder; ignore (build_br merge_bb builder);
|
||||
|
||||
(* Finally, set the builder to the end of the merge block. *)
|
||||
position_at_end merge_bb builder;
|
||||
|
||||
phi
|
||||
| Ast.For (var_name, start, end_, step, body) ->
|
||||
(* Output this as:
|
||||
* var = alloca double
|
||||
* ...
|
||||
* start = startexpr
|
||||
* store start -> var
|
||||
* goto loop
|
||||
* loop:
|
||||
* ...
|
||||
* bodyexpr
|
||||
* ...
|
||||
* loopend:
|
||||
* step = stepexpr
|
||||
* endcond = endexpr
|
||||
*
|
||||
* curvar = load var
|
||||
* nextvar = curvar + step
|
||||
* store nextvar -> var
|
||||
* br endcond, loop, endloop
|
||||
* outloop: *)
|
||||
|
||||
let the_function = block_parent (insertion_block builder) in
|
||||
|
||||
(* Create an alloca for the variable in the entry block. *)
|
||||
let alloca = create_entry_block_alloca the_function var_name in
|
||||
|
||||
(* Emit the start code first, without 'variable' in scope. *)
|
||||
let start_val = codegen_expr start in
|
||||
|
||||
(* Store the value into the alloca. *)
|
||||
ignore(build_store start_val alloca builder);
|
||||
|
||||
(* Make the new basic block for the loop header, inserting after current
|
||||
* block. *)
|
||||
let loop_bb = append_block context "loop" the_function in
|
||||
|
||||
(* Insert an explicit fall through from the current block to the
|
||||
* loop_bb. *)
|
||||
ignore (build_br loop_bb builder);
|
||||
|
||||
(* Start insertion in loop_bb. *)
|
||||
position_at_end loop_bb builder;
|
||||
|
||||
(* Within the loop, the variable is defined equal to the PHI node. If it
|
||||
* shadows an existing variable, we have to restore it, so save it
|
||||
* now. *)
|
||||
let old_val =
|
||||
try Some (Hashtbl.find named_values var_name) with Not_found -> None
|
||||
in
|
||||
Hashtbl.add named_values var_name alloca;
|
||||
|
||||
(* Emit the body of the loop. This, like any other expr, can change the
|
||||
* current BB. Note that we ignore the value computed by the body, but
|
||||
* don't allow an error *)
|
||||
ignore (codegen_expr body);
|
||||
|
||||
(* Emit the step value. *)
|
||||
let step_val =
|
||||
match step with
|
||||
| Some step -> codegen_expr step
|
||||
(* If not specified, use 1.0. *)
|
||||
| None -> const_float double_type 1.0
|
||||
in
|
||||
|
||||
(* Compute the end condition. *)
|
||||
let end_cond = codegen_expr end_ in
|
||||
|
||||
(* Reload, increment, and restore the alloca. This handles the case where
|
||||
* the body of the loop mutates the variable. *)
|
||||
let cur_var = build_load alloca var_name builder in
|
||||
let next_var = build_add cur_var step_val "nextvar" builder in
|
||||
ignore(build_store next_var alloca builder);
|
||||
|
||||
(* Convert condition to a bool by comparing equal to 0.0. *)
|
||||
let zero = const_float double_type 0.0 in
|
||||
let end_cond = build_fcmp Fcmp.One end_cond zero "loopcond" builder in
|
||||
|
||||
(* Create the "after loop" block and insert it. *)
|
||||
let after_bb = append_block context "afterloop" the_function in
|
||||
|
||||
(* Insert the conditional branch into the end of loop_end_bb. *)
|
||||
ignore (build_cond_br end_cond loop_bb after_bb builder);
|
||||
|
||||
(* Any new code will be inserted in after_bb. *)
|
||||
position_at_end after_bb builder;
|
||||
|
||||
(* Restore the unshadowed variable. *)
|
||||
begin match old_val with
|
||||
| Some old_val -> Hashtbl.add named_values var_name old_val
|
||||
| None -> ()
|
||||
end;
|
||||
|
||||
(* for expr always returns 0.0. *)
|
||||
const_null double_type
|
||||
| Ast.Var (var_names, body) ->
|
||||
let old_bindings = ref [] in
|
||||
|
||||
let the_function = block_parent (insertion_block builder) in
|
||||
|
||||
(* Register all variables and emit their initializer. *)
|
||||
Array.iter (fun (var_name, init) ->
|
||||
(* Emit the initializer before adding the variable to scope, this
|
||||
* prevents the initializer from referencing the variable itself, and
|
||||
* permits stuff like this:
|
||||
* var a = 1 in
|
||||
* var a = a in ... # refers to outer 'a'. *)
|
||||
let init_val =
|
||||
match init with
|
||||
| Some init -> codegen_expr init
|
||||
(* If not specified, use 0.0. *)
|
||||
| None -> const_float double_type 0.0
|
||||
in
|
||||
|
||||
let alloca = create_entry_block_alloca the_function var_name in
|
||||
ignore(build_store init_val alloca builder);
|
||||
|
||||
(* Remember the old variable binding so that we can restore the binding
|
||||
* when we unrecurse. *)
|
||||
begin
|
||||
try
|
||||
let old_value = Hashtbl.find named_values var_name in
|
||||
old_bindings := (var_name, old_value) :: !old_bindings;
|
||||
with Not_found -> ()
|
||||
end;
|
||||
|
||||
(* Remember this binding. *)
|
||||
Hashtbl.add named_values var_name alloca;
|
||||
) var_names;
|
||||
|
||||
(* Codegen the body, now that all vars are in scope. *)
|
||||
let body_val = codegen_expr body in
|
||||
|
||||
(* Pop all our variables from scope. *)
|
||||
List.iter (fun (var_name, old_value) ->
|
||||
Hashtbl.add named_values var_name old_value
|
||||
) !old_bindings;
|
||||
|
||||
(* Return the body computation. *)
|
||||
body_val
|
||||
|
||||
let codegen_proto = function
|
||||
| Ast.Prototype (name, args) | Ast.BinOpPrototype (name, args, _) ->
|
||||
(* Make the function type: double(double,double) etc. *)
|
||||
let doubles = Array.make (Array.length args) double_type in
|
||||
let ft = function_type double_type doubles in
|
||||
let f =
|
||||
match lookup_function name the_module with
|
||||
| None -> declare_function name ft the_module
|
||||
|
||||
(* If 'f' conflicted, there was already something named 'name'. If it
|
||||
* has a body, don't allow redefinition or reextern. *)
|
||||
| Some f ->
|
||||
(* If 'f' already has a body, reject this. *)
|
||||
if block_begin f <> At_end f then
|
||||
raise (Error "redefinition of function");
|
||||
|
||||
(* If 'f' took a different number of arguments, reject. *)
|
||||
if element_type (type_of f) <> ft then
|
||||
raise (Error "redefinition of function with different # args");
|
||||
f
|
||||
in
|
||||
|
||||
(* Set names for all arguments. *)
|
||||
Array.iteri (fun i a ->
|
||||
let n = args.(i) in
|
||||
set_value_name n a;
|
||||
Hashtbl.add named_values n a;
|
||||
) (params f);
|
||||
f
|
||||
|
||||
(* Create an alloca for each argument and register the argument in the symbol
|
||||
* table so that references to it will succeed. *)
|
||||
let create_argument_allocas the_function proto =
|
||||
let args = match proto with
|
||||
| Ast.Prototype (_, args) | Ast.BinOpPrototype (_, args, _) -> args
|
||||
in
|
||||
Array.iteri (fun i ai ->
|
||||
let var_name = args.(i) in
|
||||
(* Create an alloca for this variable. *)
|
||||
let alloca = create_entry_block_alloca the_function var_name in
|
||||
|
||||
(* Store the initial value into the alloca. *)
|
||||
ignore(build_store ai alloca builder);
|
||||
|
||||
(* Add arguments to variable symbol table. *)
|
||||
Hashtbl.add named_values var_name alloca;
|
||||
) (params the_function)
|
||||
|
||||
let codegen_func the_fpm = function
|
||||
| Ast.Function (proto, body) ->
|
||||
Hashtbl.clear named_values;
|
||||
let the_function = codegen_proto proto in
|
||||
|
||||
(* If this is an operator, install it. *)
|
||||
begin match proto with
|
||||
| Ast.BinOpPrototype (name, args, prec) ->
|
||||
let op = name.[String.length name - 1] in
|
||||
Hashtbl.add Parser.binop_precedence op prec;
|
||||
| _ -> ()
|
||||
end;
|
||||
|
||||
(* Create a new basic block to start insertion into. *)
|
||||
let bb = append_block context "entry" the_function in
|
||||
position_at_end bb builder;
|
||||
|
||||
try
|
||||
(* Add all arguments to the symbol table and create their allocas. *)
|
||||
create_argument_allocas the_function proto;
|
||||
|
||||
let ret_val = codegen_expr body in
|
||||
|
||||
(* Finish off the function. *)
|
||||
let _ = build_ret ret_val builder in
|
||||
|
||||
(* Validate the generated code, checking for consistency. *)
|
||||
Llvm_analysis.assert_valid_function the_function;
|
||||
|
||||
(* Optimize the function. *)
|
||||
let _ = PassManager.run_function the_function the_fpm in
|
||||
|
||||
the_function
|
||||
with e ->
|
||||
delete_function the_function;
|
||||
raise e
|
60
examples/OCaml-Kaleidoscope/Chapter7/lexer.ml
Normal file
60
examples/OCaml-Kaleidoscope/Chapter7/lexer.ml
Normal file
@ -0,0 +1,60 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Lexer
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
let rec lex = parser
|
||||
(* Skip any whitespace. *)
|
||||
| [< ' (' ' | '\n' | '\r' | '\t'); stream >] -> lex stream
|
||||
|
||||
(* identifier: [a-zA-Z][a-zA-Z0-9] *)
|
||||
| [< ' ('A' .. 'Z' | 'a' .. 'z' as c); stream >] ->
|
||||
let buffer = Buffer.create 1 in
|
||||
Buffer.add_char buffer c;
|
||||
lex_ident buffer stream
|
||||
|
||||
(* number: [0-9.]+ *)
|
||||
| [< ' ('0' .. '9' as c); stream >] ->
|
||||
let buffer = Buffer.create 1 in
|
||||
Buffer.add_char buffer c;
|
||||
lex_number buffer stream
|
||||
|
||||
(* Comment until end of line. *)
|
||||
| [< ' ('#'); stream >] ->
|
||||
lex_comment stream
|
||||
|
||||
(* Otherwise, just return the character as its ascii value. *)
|
||||
| [< 'c; stream >] ->
|
||||
[< 'Token.Kwd c; lex stream >]
|
||||
|
||||
(* end of stream. *)
|
||||
| [< >] -> [< >]
|
||||
|
||||
and lex_number buffer = parser
|
||||
| [< ' ('0' .. '9' | '.' as c); stream >] ->
|
||||
Buffer.add_char buffer c;
|
||||
lex_number buffer stream
|
||||
| [< stream=lex >] ->
|
||||
[< 'Token.Number (float_of_string (Buffer.contents buffer)); stream >]
|
||||
|
||||
and lex_ident buffer = parser
|
||||
| [< ' ('A' .. 'Z' | 'a' .. 'z' | '0' .. '9' as c); stream >] ->
|
||||
Buffer.add_char buffer c;
|
||||
lex_ident buffer stream
|
||||
| [< stream=lex >] ->
|
||||
match Buffer.contents buffer with
|
||||
| "def" -> [< 'Token.Def; stream >]
|
||||
| "extern" -> [< 'Token.Extern; stream >]
|
||||
| "if" -> [< 'Token.If; stream >]
|
||||
| "then" -> [< 'Token.Then; stream >]
|
||||
| "else" -> [< 'Token.Else; stream >]
|
||||
| "for" -> [< 'Token.For; stream >]
|
||||
| "in" -> [< 'Token.In; stream >]
|
||||
| "binary" -> [< 'Token.Binary; stream >]
|
||||
| "unary" -> [< 'Token.Unary; stream >]
|
||||
| "var" -> [< 'Token.Var; stream >]
|
||||
| id -> [< 'Token.Ident id; stream >]
|
||||
|
||||
and lex_comment = parser
|
||||
| [< ' ('\n'); stream=lex >] -> stream
|
||||
| [< 'c; e=lex_comment >] -> e
|
||||
| [< >] -> [< >]
|
10
examples/OCaml-Kaleidoscope/Chapter7/myocamlbuild.ml
Normal file
10
examples/OCaml-Kaleidoscope/Chapter7/myocamlbuild.ml
Normal file
@ -0,0 +1,10 @@
|
||||
open Ocamlbuild_plugin;;
|
||||
|
||||
ocaml_lib ~extern:true "llvm";;
|
||||
ocaml_lib ~extern:true "llvm_analysis";;
|
||||
ocaml_lib ~extern:true "llvm_executionengine";;
|
||||
ocaml_lib ~extern:true "llvm_target";;
|
||||
ocaml_lib ~extern:true "llvm_scalar_opts";;
|
||||
|
||||
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++"]);;
|
||||
dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
|
221
examples/OCaml-Kaleidoscope/Chapter7/parser.ml
Normal file
221
examples/OCaml-Kaleidoscope/Chapter7/parser.ml
Normal file
@ -0,0 +1,221 @@
|
||||
(*===---------------------------------------------------------------------===
|
||||
* Parser
|
||||
*===---------------------------------------------------------------------===*)
|
||||
|
||||
(* binop_precedence - This holds the precedence for each binary operator that is
|
||||
* defined *)
|
||||
let binop_precedence:(char, int) Hashtbl.t = Hashtbl.create 10
|
||||
|
||||
(* precedence - Get the precedence of the pending binary operator token. *)
|
||||
let precedence c = try Hashtbl.find binop_precedence c with Not_found -> -1
|
||||
|
||||
(* primary
|
||||
* ::= identifier
|
||||
* ::= numberexpr
|
||||
* ::= parenexpr
|
||||
* ::= ifexpr
|
||||
* ::= forexpr
|
||||
* ::= varexpr *)
|
||||
let rec parse_primary = parser
|
||||
(* numberexpr ::= number *)
|
||||
| [< 'Token.Number n >] -> Ast.Number n
|
||||
|
||||
(* parenexpr ::= '(' expression ')' *)
|
||||
| [< 'Token.Kwd '('; e=parse_expr; 'Token.Kwd ')' ?? "expected ')'" >] -> e
|
||||
|
||||
(* identifierexpr
|
||||
* ::= identifier
|
||||
* ::= identifier '(' argumentexpr ')' *)
|
||||
| [< 'Token.Ident id; stream >] ->
|
||||
let rec parse_args accumulator = parser
|
||||
| [< e=parse_expr; stream >] ->
|
||||
begin parser
|
||||
| [< 'Token.Kwd ','; e=parse_args (e :: accumulator) >] -> e
|
||||
| [< >] -> e :: accumulator
|
||||
end stream
|
||||
| [< >] -> accumulator
|
||||
in
|
||||
let rec parse_ident id = parser
|
||||
(* Call. *)
|
||||
| [< 'Token.Kwd '(';
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')'">] ->
|
||||
Ast.Call (id, Array.of_list (List.rev args))
|
||||
|
||||
(* Simple variable ref. *)
|
||||
| [< >] -> Ast.Variable id
|
||||
in
|
||||
parse_ident id stream
|
||||
|
||||
(* ifexpr ::= 'if' expr 'then' expr 'else' expr *)
|
||||
| [< 'Token.If; c=parse_expr;
|
||||
'Token.Then ?? "expected 'then'"; t=parse_expr;
|
||||
'Token.Else ?? "expected 'else'"; e=parse_expr >] ->
|
||||
Ast.If (c, t, e)
|
||||
|
||||
(* forexpr
|
||||
::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression *)
|
||||
| [< 'Token.For;
|
||||
'Token.Ident id ?? "expected identifier after for";
|
||||
'Token.Kwd '=' ?? "expected '=' after for";
|
||||
stream >] ->
|
||||
begin parser
|
||||
| [<
|
||||
start=parse_expr;
|
||||
'Token.Kwd ',' ?? "expected ',' after for";
|
||||
end_=parse_expr;
|
||||
stream >] ->
|
||||
let step =
|
||||
begin parser
|
||||
| [< 'Token.Kwd ','; step=parse_expr >] -> Some step
|
||||
| [< >] -> None
|
||||
end stream
|
||||
in
|
||||
begin parser
|
||||
| [< 'Token.In; body=parse_expr >] ->
|
||||
Ast.For (id, start, end_, step, body)
|
||||
| [< >] ->
|
||||
raise (Stream.Error "expected 'in' after for")
|
||||
end stream
|
||||
| [< >] ->
|
||||
raise (Stream.Error "expected '=' after for")
|
||||
end stream
|
||||
|
||||
(* varexpr
|
||||
* ::= 'var' identifier ('=' expression?
|
||||
* (',' identifier ('=' expression)?)* 'in' expression *)
|
||||
| [< 'Token.Var;
|
||||
(* At least one variable name is required. *)
|
||||
'Token.Ident id ?? "expected identifier after var";
|
||||
init=parse_var_init;
|
||||
var_names=parse_var_names [(id, init)];
|
||||
(* At this point, we have to have 'in'. *)
|
||||
'Token.In ?? "expected 'in' keyword after 'var'";
|
||||
body=parse_expr >] ->
|
||||
Ast.Var (Array.of_list (List.rev var_names), body)
|
||||
|
||||
| [< >] -> raise (Stream.Error "unknown token when expecting an expression.")
|
||||
|
||||
(* unary
|
||||
* ::= primary
|
||||
* ::= '!' unary *)
|
||||
and parse_unary = parser
|
||||
(* If this is a unary operator, read it. *)
|
||||
| [< 'Token.Kwd op when op != '(' && op != ')'; operand=parse_expr >] ->
|
||||
Ast.Unary (op, operand)
|
||||
|
||||
(* If the current token is not an operator, it must be a primary expr. *)
|
||||
| [< stream >] -> parse_primary stream
|
||||
|
||||
(* binoprhs
|
||||
* ::= ('+' primary)* *)
|
||||
and parse_bin_rhs expr_prec lhs stream =
|
||||
match Stream.peek stream with
|
||||
(* If this is a binop, find its precedence. *)
|
||||
| Some (Token.Kwd c) when Hashtbl.mem binop_precedence c ->
|
||||
let token_prec = precedence c in
|
||||
|
||||
(* If this is a binop that binds at least as tightly as the current binop,
|
||||
* consume it, otherwise we are done. *)
|
||||
if token_prec < expr_prec then lhs else begin
|
||||
(* Eat the binop. *)
|
||||
Stream.junk stream;
|
||||
|
||||
(* Parse the primary expression after the binary operator. *)
|
||||
let rhs = parse_unary stream in
|
||||
|
||||
(* Okay, we know this is a binop. *)
|
||||
let rhs =
|
||||
match Stream.peek stream with
|
||||
| Some (Token.Kwd c2) ->
|
||||
(* If BinOp binds less tightly with rhs than the operator after
|
||||
* rhs, let the pending operator take rhs as its lhs. *)
|
||||
let next_prec = precedence c2 in
|
||||
if token_prec < next_prec
|
||||
then parse_bin_rhs (token_prec + 1) rhs stream
|
||||
else rhs
|
||||
| _ -> rhs
|
||||
in
|
||||
|
||||
(* Merge lhs/rhs. *)
|
||||
let lhs = Ast.Binary (c, lhs, rhs) in
|
||||
parse_bin_rhs expr_prec lhs stream
|
||||
end
|
||||
| _ -> lhs
|
||||
|
||||
and parse_var_init = parser
|
||||
(* read in the optional initializer. *)
|
||||
| [< 'Token.Kwd '='; e=parse_expr >] -> Some e
|
||||
| [< >] -> None
|
||||
|
||||
and parse_var_names accumulator = parser
|
||||
| [< 'Token.Kwd ',';
|
||||
'Token.Ident id ?? "expected identifier list after var";
|
||||
init=parse_var_init;
|
||||
e=parse_var_names ((id, init) :: accumulator) >] -> e
|
||||
| [< >] -> accumulator
|
||||
|
||||
(* expression
|
||||
* ::= primary binoprhs *)
|
||||
and parse_expr = parser
|
||||
| [< lhs=parse_unary; stream >] -> parse_bin_rhs 0 lhs stream
|
||||
|
||||
(* prototype
|
||||
* ::= id '(' id* ')'
|
||||
* ::= binary LETTER number? (id, id)
|
||||
* ::= unary LETTER number? (id) *)
|
||||
let parse_prototype =
|
||||
let rec parse_args accumulator = parser
|
||||
| [< 'Token.Ident id; e=parse_args (id::accumulator) >] -> e
|
||||
| [< >] -> accumulator
|
||||
in
|
||||
let parse_operator = parser
|
||||
| [< 'Token.Unary >] -> "unary", 1
|
||||
| [< 'Token.Binary >] -> "binary", 2
|
||||
in
|
||||
let parse_binary_precedence = parser
|
||||
| [< 'Token.Number n >] -> int_of_float n
|
||||
| [< >] -> 30
|
||||
in
|
||||
parser
|
||||
| [< 'Token.Ident id;
|
||||
'Token.Kwd '(' ?? "expected '(' in prototype";
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
|
||||
(* success. *)
|
||||
Ast.Prototype (id, Array.of_list (List.rev args))
|
||||
| [< (prefix, kind)=parse_operator;
|
||||
'Token.Kwd op ?? "expected an operator";
|
||||
(* Read the precedence if present. *)
|
||||
binary_precedence=parse_binary_precedence;
|
||||
'Token.Kwd '(' ?? "expected '(' in prototype";
|
||||
args=parse_args [];
|
||||
'Token.Kwd ')' ?? "expected ')' in prototype" >] ->
|
||||
let name = prefix ^ (String.make 1 op) in
|
||||
let args = Array.of_list (List.rev args) in
|
||||
|
||||
(* Verify right number of arguments for operator. *)
|
||||
if Array.length args != kind
|
||||
then raise (Stream.Error "invalid number of operands for operator")
|
||||
else
|
||||
if kind == 1 then
|
||||
Ast.Prototype (name, args)
|
||||
else
|
||||
Ast.BinOpPrototype (name, args, binary_precedence)
|
||||
| [< >] ->
|
||||
raise (Stream.Error "expected function name in prototype")
|
||||
|
||||
(* definition ::= 'def' prototype expression *)
|
||||
let parse_definition = parser
|
||||
| [< 'Token.Def; p=parse_prototype; e=parse_expr >] ->
|
||||
Ast.Function (p, e)
|
||||
|
||||
(* toplevelexpr ::= expression *)
|
||||
let parse_toplevel = parser
|
||||
| [< e=parse_expr >] ->
|
||||
(* Make an anonymous proto. *)
|
||||
Ast.Function (Ast.Prototype ("", [||]), e)
|
||||
|
||||
(* external ::= 'extern' prototype *)
|
||||
let parse_extern = parser
|
||||
| [< 'Token.Extern; e=parse_prototype >] -> e
|
25
examples/OCaml-Kaleidoscope/Chapter7/token.ml
Normal file
25
examples/OCaml-Kaleidoscope/Chapter7/token.ml
Normal file
@ -0,0 +1,25 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Lexer Tokens
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(* The lexer returns these 'Kwd' if it is an unknown character, otherwise one of
|
||||
* these others for known things. *)
|
||||
type token =
|
||||
(* commands *)
|
||||
| Def | Extern
|
||||
|
||||
(* primary *)
|
||||
| Ident of string | Number of float
|
||||
|
||||
(* unknown *)
|
||||
| Kwd of char
|
||||
|
||||
(* control *)
|
||||
| If | Then | Else
|
||||
| For | In
|
||||
|
||||
(* operators *)
|
||||
| Binary | Unary
|
||||
|
||||
(* var definition *)
|
||||
| Var
|
49
examples/OCaml-Kaleidoscope/Chapter7/toplevel.ml
Normal file
49
examples/OCaml-Kaleidoscope/Chapter7/toplevel.ml
Normal file
@ -0,0 +1,49 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Top-Level parsing and JIT Driver
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
open Llvm_executionengine
|
||||
|
||||
(* top ::= definition | external | expression | ';' *)
|
||||
let rec main_loop the_fpm the_execution_engine stream =
|
||||
match Stream.peek stream with
|
||||
| None -> ()
|
||||
|
||||
(* ignore top-level semicolons. *)
|
||||
| Some (Token.Kwd ';') ->
|
||||
Stream.junk stream;
|
||||
main_loop the_fpm the_execution_engine stream
|
||||
|
||||
| Some token ->
|
||||
begin
|
||||
try match token with
|
||||
| Token.Def ->
|
||||
let e = Parser.parse_definition stream in
|
||||
print_endline "parsed a function definition.";
|
||||
dump_value (Codegen.codegen_func the_fpm e);
|
||||
| Token.Extern ->
|
||||
let e = Parser.parse_extern stream in
|
||||
print_endline "parsed an extern.";
|
||||
dump_value (Codegen.codegen_proto e);
|
||||
| _ ->
|
||||
(* Evaluate a top-level expression into an anonymous function. *)
|
||||
let e = Parser.parse_toplevel stream in
|
||||
print_endline "parsed a top-level expr";
|
||||
let the_function = Codegen.codegen_func the_fpm e in
|
||||
dump_value the_function;
|
||||
|
||||
(* JIT the function, returning a function pointer. *)
|
||||
let result = ExecutionEngine.run_function the_function [||]
|
||||
the_execution_engine in
|
||||
|
||||
print_string "Evaluated to ";
|
||||
print_float (GenericValue.as_float Codegen.double_type result);
|
||||
print_newline ();
|
||||
with Stream.Error s | Codegen.Error s ->
|
||||
(* Skip token for error recovery. *)
|
||||
Stream.junk stream;
|
||||
print_endline s;
|
||||
end;
|
||||
print_string "ready> "; flush stdout;
|
||||
main_loop the_fpm the_execution_engine stream
|
57
examples/OCaml-Kaleidoscope/Chapter7/toy.ml
Normal file
57
examples/OCaml-Kaleidoscope/Chapter7/toy.ml
Normal file
@ -0,0 +1,57 @@
|
||||
(*===----------------------------------------------------------------------===
|
||||
* Main driver code.
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
open Llvm
|
||||
open Llvm_executionengine
|
||||
open Llvm_target
|
||||
open Llvm_scalar_opts
|
||||
|
||||
let main () =
|
||||
ignore (initialize_native_target ());
|
||||
|
||||
(* Install standard binary operators.
|
||||
* 1 is the lowest precedence. *)
|
||||
Hashtbl.add Parser.binop_precedence '=' 2;
|
||||
Hashtbl.add Parser.binop_precedence '<' 10;
|
||||
Hashtbl.add Parser.binop_precedence '+' 20;
|
||||
Hashtbl.add Parser.binop_precedence '-' 20;
|
||||
Hashtbl.add Parser.binop_precedence '*' 40; (* highest. *)
|
||||
|
||||
(* Prime the first token. *)
|
||||
print_string "ready> "; flush stdout;
|
||||
let stream = Lexer.lex (Stream.of_channel stdin) in
|
||||
|
||||
(* Create the JIT. *)
|
||||
let the_execution_engine = ExecutionEngine.create Codegen.the_module in
|
||||
let the_fpm = PassManager.create_function Codegen.the_module in
|
||||
|
||||
(* Set up the optimizer pipeline. Start with registering info about how the
|
||||
* target lays out data structures. *)
|
||||
TargetData.add (ExecutionEngine.target_data the_execution_engine) the_fpm;
|
||||
|
||||
(* Promote allocas to registers. *)
|
||||
add_memory_to_register_promotion the_fpm;
|
||||
|
||||
(* Do simple "peephole" optimizations and bit-twiddling optzn. *)
|
||||
add_instruction_combination the_fpm;
|
||||
|
||||
(* reassociate expressions. *)
|
||||
add_reassociation the_fpm;
|
||||
|
||||
(* Eliminate Common SubExpressions. *)
|
||||
add_gvn the_fpm;
|
||||
|
||||
(* Simplify the control flow graph (deleting unreachable blocks, etc). *)
|
||||
add_cfg_simplification the_fpm;
|
||||
|
||||
ignore (PassManager.initialize the_fpm);
|
||||
|
||||
(* Run the main "interpreter loop" now. *)
|
||||
Toplevel.main_loop the_fpm the_execution_engine stream;
|
||||
|
||||
(* Print out all the generated code. *)
|
||||
dump_module Codegen.the_module
|
||||
;;
|
||||
|
||||
main ()
|
15
examples/OCaml-Kaleidoscope/Makefile
Normal file
15
examples/OCaml-Kaleidoscope/Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
##===- examples/OCaml-Kaleidoscope/Makefile ----------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL=../..
|
||||
|
||||
include $(LEVEL)/Makefile.config
|
||||
|
||||
PARALLEL_DIRS:= Chapter2 Chapter3 Chapter4 Chapter5 Chapter6 Chapter7
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
@ -79,6 +79,10 @@ void LLVMAddSCCPPass(LLVMPassManagerRef PM);
|
||||
/** See llvm::createScalarReplAggregatesPass function. */
|
||||
void LLVMAddScalarReplAggregatesPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createScalarReplAggregatesPass function. */
|
||||
void LLVMAddScalarReplAggregatesPassWithThreshold(LLVMPassManagerRef PM,
|
||||
int Threshold);
|
||||
|
||||
/** See llvm::createSimplifyLibCallsPass function. */
|
||||
void LLVMAddSimplifyLibCallsPass(LLVMPassManagerRef PM);
|
||||
|
||||
@ -91,6 +95,9 @@ void LLVMAddConstantPropagationPass(LLVMPassManagerRef PM);
|
||||
/** See llvm::demotePromoteMemoryToRegisterPass function. */
|
||||
void LLVMAddDemoteMemoryToRegisterPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createVerifierPass function. */
|
||||
void LLVMAddVerifierPass(LLVMPassManagerRef PM);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* defined(__cplusplus) */
|
||||
|
@ -279,6 +279,28 @@ static inline void array_pod_sort(IteratorTy Start, IteratorTy End,
|
||||
qsort(&*Start, End-Start, sizeof(*Start), Compare);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Extra additions to <algorithm>
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// For a container of pointers, deletes the pointers and then clears the
|
||||
/// container.
|
||||
template<typename Container>
|
||||
void DeleteContainerPointers(Container &C) {
|
||||
for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I)
|
||||
delete *I;
|
||||
C.clear();
|
||||
}
|
||||
|
||||
/// In a container of pairs (usually a map) whose second element is a pointer,
|
||||
/// deletes the second elements and then clears the container.
|
||||
template<typename Container>
|
||||
void DeleteContainerSeconds(Container &C) {
|
||||
for (typename Container::iterator I = C.begin(), E = C.end(); I != E; ++I)
|
||||
delete I->second;
|
||||
C.clear();
|
||||
}
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <climits>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -42,6 +43,9 @@ namespace llvm {
|
||||
/// is used to estimate the code size cost of inlining it.
|
||||
unsigned NumInsts, NumBlocks;
|
||||
|
||||
/// NumBBInsts - Keeps track of basic block code size estimates.
|
||||
DenseMap<const BasicBlock *, unsigned> NumBBInsts;
|
||||
|
||||
/// NumCalls - Keep track of the number of calls to 'big' functions.
|
||||
unsigned NumCalls;
|
||||
|
||||
|
@ -571,7 +571,7 @@ public:
|
||||
unsigned getSmallConstantTripMultiple() const;
|
||||
|
||||
/// isLCSSAForm - Return true if the Loop is in LCSSA form
|
||||
bool isLCSSAForm() const;
|
||||
bool isLCSSAForm(DominatorTree &DT) const;
|
||||
|
||||
/// isLoopSimplifyForm - Return true if the Loop is in the form that
|
||||
/// the LoopSimplify form transforms loops to, which is sometimes called
|
||||
|
@ -44,6 +44,9 @@ namespace CallingConv {
|
||||
// call does not break any live ranges in the caller side.
|
||||
Cold = 9,
|
||||
|
||||
// GHC - Calling convention used by the Glasgow Haskell Compiler (GHC).
|
||||
GHC = 10,
|
||||
|
||||
// Target - This is the start of the target-specific calling conventions,
|
||||
// e.g. fastcall and thiscall on X86.
|
||||
FirstTargetCC = 64,
|
||||
|
@ -143,8 +143,7 @@ namespace llvm {
|
||||
|
||||
protected:
|
||||
explicit AsmPrinter(formatted_raw_ostream &o, TargetMachine &TM,
|
||||
MCContext &Ctx, MCStreamer &Streamer,
|
||||
const MCAsmInfo *T);
|
||||
MCStreamer &Streamer);
|
||||
|
||||
public:
|
||||
virtual ~AsmPrinter();
|
||||
@ -306,18 +305,10 @@ namespace llvm {
|
||||
unsigned ForcedAlignBits = 0,
|
||||
bool UseFillExpr = true) const;
|
||||
|
||||
/// printLabel - This method prints a local label used by debug and
|
||||
/// exception handling tables.
|
||||
void printLabel(unsigned Id) const;
|
||||
|
||||
/// printDeclare - This method prints a local variable declaration used by
|
||||
/// debug tables.
|
||||
void printDeclare(const MachineInstr *MI) const;
|
||||
|
||||
/// GetGlobalValueSymbol - Return the MCSymbol for the specified global
|
||||
/// value.
|
||||
virtual MCSymbol *GetGlobalValueSymbol(const GlobalValue *GV) const;
|
||||
|
||||
/// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with
|
||||
/// global value name as its base, with the specified suffix, and where the
|
||||
/// symbol is forced to have private linkage if ForcePrivate is true.
|
||||
@ -342,8 +333,7 @@ namespace llvm {
|
||||
/// GetBlockAddressSymbol - Return the MCSymbol used to satisfy BlockAddress
|
||||
/// uses of the specified basic block.
|
||||
MCSymbol *GetBlockAddressSymbol(const BlockAddress *BA) const;
|
||||
MCSymbol *GetBlockAddressSymbol(const Function *F,
|
||||
const BasicBlock *BB) const;
|
||||
MCSymbol *GetBlockAddressSymbol(const BasicBlock *BB) const;
|
||||
|
||||
/// EmitBasicBlockStart - This method prints the label for the specified
|
||||
/// MachineBasicBlock, an alignment (if present) and a comment describing
|
||||
|
@ -38,12 +38,10 @@
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AsmPrinter;
|
||||
class GCStrategy;
|
||||
class Constant;
|
||||
class MCAsmInfo;
|
||||
|
||||
class MCSymbol;
|
||||
|
||||
namespace GC {
|
||||
/// PointKind - The type of a collector-safe point.
|
||||
@ -60,9 +58,9 @@ namespace llvm {
|
||||
///
|
||||
struct GCPoint {
|
||||
GC::PointKind Kind; //< The kind of the safe point.
|
||||
unsigned Num; //< Usually a label.
|
||||
MCSymbol *Label; //< A label.
|
||||
|
||||
GCPoint(GC::PointKind K, unsigned N) : Kind(K), Num(N) {}
|
||||
GCPoint(GC::PointKind K, MCSymbol *L) : Kind(K), Label(L) {}
|
||||
};
|
||||
|
||||
/// GCRoot - Metadata for a pointer to an object managed by the garbage
|
||||
@ -123,8 +121,8 @@ namespace llvm {
|
||||
/// addSafePoint - Notes the existence of a safe point. Num is the ID of the
|
||||
/// label just prior to the safe point (if the code generator is using
|
||||
/// MachineModuleInfo).
|
||||
void addSafePoint(GC::PointKind Kind, unsigned Num) {
|
||||
SafePoints.push_back(GCPoint(Kind, Num));
|
||||
void addSafePoint(GC::PointKind Kind, MCSymbol *Label) {
|
||||
SafePoints.push_back(GCPoint(Kind, Label));
|
||||
}
|
||||
|
||||
/// getFrameSize/setFrameSize - Records the function's frame size.
|
||||
|
@ -28,6 +28,7 @@ namespace llvm {
|
||||
|
||||
class GCMetadataPrinter;
|
||||
class raw_ostream;
|
||||
class MCAsmInfo;
|
||||
|
||||
/// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the
|
||||
/// defaults from Registry.
|
||||
|
@ -35,7 +35,7 @@ class MachineRelocation;
|
||||
class Value;
|
||||
class GlobalValue;
|
||||
class Function;
|
||||
|
||||
|
||||
/// JITCodeEmitter - This class defines two sorts of methods: those for
|
||||
/// emitting the actual bytes of machine code, and those for emitting auxillary
|
||||
/// structures, such as jump tables, relocations, etc.
|
||||
@ -242,7 +242,7 @@ public:
|
||||
|
||||
|
||||
/// emitLabel - Emits a label
|
||||
virtual void emitLabel(uint64_t LabelID) = 0;
|
||||
virtual void emitLabel(MCSymbol *Label) = 0;
|
||||
|
||||
/// allocateSpace - Allocate a block of space in the current output buffer,
|
||||
/// returning null (and setting conditions to indicate buffer overflow) on
|
||||
@ -316,10 +316,10 @@ public:
|
||||
///
|
||||
virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const= 0;
|
||||
|
||||
/// getLabelAddress - Return the address of the specified LabelID, only usable
|
||||
/// after the LabelID has been emitted.
|
||||
/// getLabelAddress - Return the address of the specified Label, only usable
|
||||
/// after the Label has been emitted.
|
||||
///
|
||||
virtual uintptr_t getLabelAddress(uint64_t LabelID) const = 0;
|
||||
virtual uintptr_t getLabelAddress(MCSymbol *Label) const = 0;
|
||||
|
||||
/// Specifies the MachineModuleInfo object. This is used for exception handling
|
||||
/// purposes.
|
||||
|
@ -127,11 +127,11 @@ namespace llvm {
|
||||
bool conflictsWithPhysReg(const LiveInterval &li, VirtRegMap &vrm,
|
||||
unsigned reg);
|
||||
|
||||
/// conflictsWithPhysRegRef - Similar to conflictsWithPhysRegRef except
|
||||
/// it can check use as well.
|
||||
bool conflictsWithPhysRegRef(LiveInterval &li, unsigned Reg,
|
||||
bool CheckUse,
|
||||
SmallPtrSet<MachineInstr*,32> &JoinedCopies);
|
||||
/// conflictsWithSubPhysRegRef - Similar to conflictsWithPhysRegRef except
|
||||
/// it checks for sub-register reference and it can check use as well.
|
||||
bool conflictsWithSubPhysRegRef(LiveInterval &li, unsigned Reg,
|
||||
bool CheckUse,
|
||||
SmallPtrSet<MachineInstr*,32> &JoinedCopies);
|
||||
|
||||
// Interval creation
|
||||
LiveInterval &getOrCreateInterval(unsigned reg) {
|
||||
|
@ -21,7 +21,6 @@ namespace llvm {
|
||||
|
||||
class BasicBlock;
|
||||
class MachineFunction;
|
||||
class MCContext;
|
||||
class MCSymbol;
|
||||
class StringRef;
|
||||
class raw_ostream;
|
||||
@ -352,7 +351,7 @@ public:
|
||||
|
||||
/// getSymbol - Return the MCSymbol for this basic block.
|
||||
///
|
||||
MCSymbol *getSymbol(MCContext &Ctx) const;
|
||||
MCSymbol *getSymbol() const;
|
||||
|
||||
private: // Methods used to maintain doubly linked list of blocks...
|
||||
friend struct ilist_traits<MachineBasicBlock>;
|
||||
|
@ -31,6 +31,7 @@ class MachineRelocation;
|
||||
class Value;
|
||||
class GlobalValue;
|
||||
class Function;
|
||||
class MCSymbol;
|
||||
|
||||
/// MachineCodeEmitter - This class defines two sorts of methods: those for
|
||||
/// emitting the actual bytes of machine code, and those for emitting auxillary
|
||||
@ -247,7 +248,7 @@ public:
|
||||
virtual void processDebugLoc(DebugLoc DL, bool BeforePrintintInsn) {}
|
||||
|
||||
/// emitLabel - Emits a label
|
||||
virtual void emitLabel(uint64_t LabelID) = 0;
|
||||
virtual void emitLabel(MCSymbol *Label) = 0;
|
||||
|
||||
/// allocateSpace - Allocate a block of space in the current output buffer,
|
||||
/// returning null (and setting conditions to indicate buffer overflow) on
|
||||
@ -316,10 +317,10 @@ public:
|
||||
///
|
||||
virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const= 0;
|
||||
|
||||
/// getLabelAddress - Return the address of the specified LabelID, only usable
|
||||
/// getLabelAddress - Return the address of the specified Label, only usable
|
||||
/// after the LabelID has been emitted.
|
||||
///
|
||||
virtual uintptr_t getLabelAddress(uint64_t LabelID) const = 0;
|
||||
virtual uintptr_t getLabelAddress(MCSymbol *Label) const = 0;
|
||||
|
||||
/// Specifies the MachineModuleInfo object. This is used for exception handling
|
||||
/// purposes.
|
||||
|
@ -33,6 +33,7 @@ class MachineRegisterInfo;
|
||||
class MachineFrameInfo;
|
||||
class MachineConstantPool;
|
||||
class MachineJumpTableInfo;
|
||||
class MCContext;
|
||||
class Pass;
|
||||
class TargetMachine;
|
||||
class TargetRegisterClass;
|
||||
@ -71,6 +72,7 @@ struct MachineFunctionInfo {
|
||||
class MachineFunction {
|
||||
Function *Fn;
|
||||
const TargetMachine &Target;
|
||||
MCContext &Ctx;
|
||||
|
||||
// RegInfo - Information about each register in use in the function.
|
||||
MachineRegisterInfo *RegInfo;
|
||||
@ -121,13 +123,16 @@ class MachineFunction {
|
||||
// The alignment of the function.
|
||||
unsigned Alignment;
|
||||
|
||||
MachineFunction(const MachineFunction &); // intentionally unimplemented
|
||||
void operator=(const MachineFunction&); // intentionally unimplemented
|
||||
MachineFunction(const MachineFunction &); // DO NOT IMPLEMENT
|
||||
void operator=(const MachineFunction&); // DO NOT IMPLEMENT
|
||||
|
||||
public:
|
||||
MachineFunction(Function *Fn, const TargetMachine &TM, unsigned FunctionNum);
|
||||
MachineFunction(Function *Fn, const TargetMachine &TM, unsigned FunctionNum,
|
||||
MCContext &Ctx);
|
||||
~MachineFunction();
|
||||
|
||||
MCContext &getContext() const { return Ctx; }
|
||||
|
||||
/// getFunction - Return the LLVM function that this machine code represents
|
||||
///
|
||||
Function *getFunction() const { return Fn; }
|
||||
|
@ -131,6 +131,11 @@ public:
|
||||
MI->addOperand(MachineOperand::CreateMetadata(MD));
|
||||
return *this;
|
||||
}
|
||||
|
||||
const MachineInstrBuilder &addSym(MCSymbol *Sym) const {
|
||||
MI->addOperand(MachineOperand::CreateMCSymbol(Sym));
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/// BuildMI - Builder interface. Specify how to create the initial instruction
|
||||
|
@ -61,7 +61,11 @@ public:
|
||||
/// .set L4_5_set_123, LBB123 - LJTI1_2
|
||||
/// .word L4_5_set_123
|
||||
EK_LabelDifference32,
|
||||
|
||||
|
||||
/// EK_Inline - Jump table entries are emitted inline at their point of
|
||||
/// use. It is the responsibility of the target to emit the entries.
|
||||
EK_Inline,
|
||||
|
||||
/// EK_Custom32 - Each entry is a 32-bit value that is custom lowered by the
|
||||
/// TargetLowering::LowerCustomJumpTableEntry hook.
|
||||
EK_Custom32
|
||||
|
@ -22,13 +22,13 @@
|
||||
#define LLVM_CODEGEN_MACHINELOCATION_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCSymbol;
|
||||
|
||||
class MachineLocation {
|
||||
private:
|
||||
bool IsRegister; // True if location is a register.
|
||||
unsigned Register; // gcc/gdb register number.
|
||||
int Offset; // Displacement if not register.
|
||||
|
||||
public:
|
||||
enum {
|
||||
// The target register number for an abstract frame pointer. The value is
|
||||
@ -36,20 +36,11 @@ public:
|
||||
VirtualFP = ~0U
|
||||
};
|
||||
MachineLocation()
|
||||
: IsRegister(false)
|
||||
, Register(0)
|
||||
, Offset(0)
|
||||
{}
|
||||
: IsRegister(false), Register(0), Offset(0) {}
|
||||
explicit MachineLocation(unsigned R)
|
||||
: IsRegister(true)
|
||||
, Register(R)
|
||||
, Offset(0)
|
||||
{}
|
||||
: IsRegister(true), Register(R), Offset(0) {}
|
||||
MachineLocation(unsigned R, int O)
|
||||
: IsRegister(false)
|
||||
, Register(R)
|
||||
, Offset(O)
|
||||
{}
|
||||
: IsRegister(false), Register(R), Offset(O) {}
|
||||
|
||||
// Accessors
|
||||
bool isReg() const { return IsRegister; }
|
||||
@ -74,29 +65,25 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
/// MachineMove - This class represents the save or restore of a callee saved
|
||||
/// register that exception or debug info needs to know about.
|
||||
class MachineMove {
|
||||
private:
|
||||
unsigned LabelID; // Label ID number for post-instruction
|
||||
// address when result of move takes
|
||||
// effect.
|
||||
MachineLocation Destination; // Move to location.
|
||||
MachineLocation Source; // Move from location.
|
||||
/// Label - Symbol for post-instruction address when result of move takes
|
||||
/// effect.
|
||||
MCSymbol *Label;
|
||||
|
||||
// Move to & from location.
|
||||
MachineLocation Destination, Source;
|
||||
public:
|
||||
MachineMove()
|
||||
: LabelID(0)
|
||||
, Destination()
|
||||
, Source()
|
||||
{}
|
||||
MachineMove() : Label(0) {}
|
||||
|
||||
MachineMove(unsigned ID, MachineLocation &D, MachineLocation &S)
|
||||
: LabelID(ID)
|
||||
, Destination(D)
|
||||
, Source(S)
|
||||
{}
|
||||
MachineMove(MCSymbol *label, const MachineLocation &D,
|
||||
const MachineLocation &S)
|
||||
: Label(label), Destination(D), Source(S) {}
|
||||
|
||||
// Accessors
|
||||
unsigned getLabelID() const { return LabelID; }
|
||||
MCSymbol *getLabel() const { return Label; }
|
||||
const MachineLocation &getDestination() const { return Destination; }
|
||||
const MachineLocation &getSource() const { return Source; }
|
||||
};
|
||||
|
@ -31,48 +31,43 @@
|
||||
#ifndef LLVM_CODEGEN_MACHINEMODULEINFO_H
|
||||
#define LLVM_CODEGEN_MACHINEMODULEINFO_H
|
||||
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/UniqueVector.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/CodeGen/MachineLocation.h"
|
||||
#include "llvm/GlobalValue.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/GlobalValue.h"
|
||||
#include "llvm/Metadata.h"
|
||||
#include "llvm/CodeGen/MachineLocation.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Forward declarations.
|
||||
class Constant;
|
||||
class MCSymbol;
|
||||
class MDNode;
|
||||
class GlobalVariable;
|
||||
class MDNode;
|
||||
class MachineBasicBlock;
|
||||
class MachineFunction;
|
||||
class Module;
|
||||
class PointerType;
|
||||
class StructType;
|
||||
|
||||
|
||||
/// MachineModuleInfoImpl - This class can be derived from and used by targets
|
||||
/// to hold private target-specific information for each Module. Objects of
|
||||
/// type are accessed/created with MMI::getInfo and destroyed when the
|
||||
/// MachineModuleInfo is destroyed.
|
||||
class MachineModuleInfoImpl {
|
||||
public:
|
||||
typedef PointerIntPair<MCSymbol*, 1, bool> StubValueTy;
|
||||
virtual ~MachineModuleInfoImpl();
|
||||
|
||||
typedef std::vector<std::pair<MCSymbol*, MCSymbol*> >
|
||||
SymbolListTy;
|
||||
typedef std::vector<std::pair<MCSymbol*, StubValueTy> > SymbolListTy;
|
||||
protected:
|
||||
static SymbolListTy
|
||||
GetSortedStubs(const DenseMap<MCSymbol*, MCSymbol*> &Map);
|
||||
static SymbolListTy GetSortedStubs(const DenseMap<MCSymbol*, StubValueTy>&);
|
||||
};
|
||||
|
||||
|
||||
@ -82,37 +77,33 @@ protected:
|
||||
/// the current function.
|
||||
///
|
||||
struct LandingPadInfo {
|
||||
MachineBasicBlock *LandingPadBlock; // Landing pad block.
|
||||
SmallVector<unsigned, 1> BeginLabels; // Labels prior to invoke.
|
||||
SmallVector<unsigned, 1> EndLabels; // Labels after invoke.
|
||||
unsigned LandingPadLabel; // Label at beginning of landing pad.
|
||||
Function *Personality; // Personality function.
|
||||
std::vector<int> TypeIds; // List of type ids (filters negative)
|
||||
MachineBasicBlock *LandingPadBlock; // Landing pad block.
|
||||
SmallVector<MCSymbol*, 1> BeginLabels; // Labels prior to invoke.
|
||||
SmallVector<MCSymbol*, 1> EndLabels; // Labels after invoke.
|
||||
MCSymbol *LandingPadLabel; // Label at beginning of landing pad.
|
||||
Function *Personality; // Personality function.
|
||||
std::vector<int> TypeIds; // List of type ids (filters negative)
|
||||
|
||||
explicit LandingPadInfo(MachineBasicBlock *MBB)
|
||||
: LandingPadBlock(MBB)
|
||||
, LandingPadLabel(0)
|
||||
, Personality(NULL)
|
||||
{}
|
||||
: LandingPadBlock(MBB), LandingPadLabel(0), Personality(0) {}
|
||||
};
|
||||
|
||||
class MMIAddrLabelMap;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// MachineModuleInfo - This class contains meta information specific to a
|
||||
/// module. Queries can be made by different debugging and exception handling
|
||||
/// schemes and reformated for specific use.
|
||||
///
|
||||
class MachineModuleInfo : public ImmutablePass {
|
||||
/// Context - This is the MCContext used for the entire code generator.
|
||||
MCContext Context;
|
||||
|
||||
/// ObjFileMMI - This is the object-file-format-specific implementation of
|
||||
/// MachineModuleInfoImpl, which lets targets accumulate whatever info they
|
||||
/// want.
|
||||
MachineModuleInfoImpl *ObjFileMMI;
|
||||
|
||||
// LabelIDList - One entry per assigned label. Normally the entry is equal to
|
||||
// the list index(+1). If the entry is zero then the label has been deleted.
|
||||
// Any other value indicates the label has been deleted by is mapped to
|
||||
// another label.
|
||||
std::vector<unsigned> LabelIDList;
|
||||
|
||||
// FrameMoves - List of moves done by a function's prolog. Used to construct
|
||||
// frame maps by debug and exception handling consumers.
|
||||
std::vector<MachineMove> FrameMoves;
|
||||
@ -123,7 +114,7 @@ class MachineModuleInfo : public ImmutablePass {
|
||||
|
||||
// Map of invoke call site index values to associated begin EH_LABEL for
|
||||
// the current function.
|
||||
DenseMap<unsigned, unsigned> CallSiteMap;
|
||||
DenseMap<MCSymbol*, unsigned> CallSiteMap;
|
||||
|
||||
// The current call site index being processed, if any. 0 if none.
|
||||
unsigned CurCallSite;
|
||||
@ -150,6 +141,11 @@ class MachineModuleInfo : public ImmutablePass {
|
||||
/// llvm.compiler.used.
|
||||
SmallPtrSet<const Function *, 32> UsedFunctions;
|
||||
|
||||
|
||||
/// AddrLabelSymbols - This map keeps track of which symbol is being used for
|
||||
/// the specified basic block's address of label.
|
||||
MMIAddrLabelMap *AddrLabelSymbols;
|
||||
|
||||
bool CallsEHReturn;
|
||||
bool CallsUnwindInit;
|
||||
|
||||
@ -165,7 +161,8 @@ public:
|
||||
VariableDbgInfoMapTy;
|
||||
VariableDbgInfoMapTy VariableDbgInfo;
|
||||
|
||||
MachineModuleInfo();
|
||||
MachineModuleInfo(); // DUMMY CONSTRUCTOR, DO NOT CALL.
|
||||
MachineModuleInfo(const MCAsmInfo &MAI); // Real constructor.
|
||||
~MachineModuleInfo();
|
||||
|
||||
bool doInitialization();
|
||||
@ -174,6 +171,9 @@ public:
|
||||
/// EndFunction - Discard function meta information.
|
||||
///
|
||||
void EndFunction();
|
||||
|
||||
const MCContext &getContext() const { return Context; }
|
||||
MCContext &getContext() { return Context; }
|
||||
|
||||
/// getInfo - Keep track of various per-function pieces of information for
|
||||
/// backends that would like to do so.
|
||||
@ -205,37 +205,30 @@ public:
|
||||
bool callsUnwindInit() const { return CallsUnwindInit; }
|
||||
void setCallsUnwindInit(bool b) { CallsUnwindInit = b; }
|
||||
|
||||
/// NextLabelID - Return the next unique label id.
|
||||
///
|
||||
unsigned NextLabelID() {
|
||||
unsigned ID = (unsigned)LabelIDList.size() + 1;
|
||||
LabelIDList.push_back(ID);
|
||||
return ID;
|
||||
}
|
||||
|
||||
/// InvalidateLabel - Inhibit use of the specified label # from
|
||||
/// MachineModuleInfo, for example because the code was deleted.
|
||||
void InvalidateLabel(unsigned LabelID) {
|
||||
// Remap to zero to indicate deletion.
|
||||
assert(0 < LabelID && LabelID <= LabelIDList.size() &&
|
||||
"Old label ID out of range.");
|
||||
LabelIDList[LabelID - 1] = 0;
|
||||
}
|
||||
|
||||
/// isLabelDeleted - Return true if the label was deleted.
|
||||
/// FIXME: This should eventually be eliminated and use the 'is emitted' bit
|
||||
/// on MCSymbol.
|
||||
bool isLabelDeleted(unsigned LabelID) const {
|
||||
assert(LabelID <= LabelIDList.size() && "Debug label ID out of range.");
|
||||
return LabelID == 0 || LabelIDList[LabelID - 1] == 0;
|
||||
}
|
||||
|
||||
/// getFrameMoves - Returns a reference to a list of moves done in the current
|
||||
/// function's prologue. Used to construct frame maps for debug and exception
|
||||
/// handling comsumers.
|
||||
std::vector<MachineMove> &getFrameMoves() { return FrameMoves; }
|
||||
|
||||
//===-EH-----------------------------------------------------------------===//
|
||||
/// getAddrLabelSymbol - Return the symbol to be used for the specified basic
|
||||
/// block when its address is taken. This cannot be its normal LBB label
|
||||
/// because the block may be accessed outside its containing function.
|
||||
MCSymbol *getAddrLabelSymbol(const BasicBlock *BB);
|
||||
|
||||
/// getAddrLabelSymbolToEmit - Return the symbol to be used for the specified
|
||||
/// basic block when its address is taken. If other blocks were RAUW'd to
|
||||
/// this one, we may have to emit them as well, return the whole set.
|
||||
std::vector<MCSymbol*> getAddrLabelSymbolToEmit(const BasicBlock *BB);
|
||||
|
||||
/// takeDeletedSymbolsForFunction - If the specified function has had any
|
||||
/// references to address-taken blocks generated, but the block got deleted,
|
||||
/// return the symbol now so we can emit it. This prevents emitting a
|
||||
/// reference to a symbol that has no definition.
|
||||
void takeDeletedSymbolsForFunction(const Function *F,
|
||||
std::vector<MCSymbol*> &Result);
|
||||
|
||||
|
||||
//===- EH ---------------------------------------------------------------===//
|
||||
|
||||
/// getOrCreateLandingPadInfo - Find or create an LandingPadInfo for the
|
||||
/// specified MachineBasicBlock.
|
||||
@ -243,12 +236,12 @@ public:
|
||||
|
||||
/// addInvoke - Provide the begin and end labels of an invoke style call and
|
||||
/// associate it with a try landing pad block.
|
||||
void addInvoke(MachineBasicBlock *LandingPad, unsigned BeginLabel,
|
||||
unsigned EndLabel);
|
||||
void addInvoke(MachineBasicBlock *LandingPad,
|
||||
MCSymbol *BeginLabel, MCSymbol *EndLabel);
|
||||
|
||||
/// addLandingPad - Add a new panding pad. Returns the label ID for the
|
||||
/// landing pad entry.
|
||||
unsigned addLandingPad(MachineBasicBlock *LandingPad);
|
||||
MCSymbol *addLandingPad(MachineBasicBlock *LandingPad);
|
||||
|
||||
/// addPersonality - Provide the personality function for the exception
|
||||
/// information.
|
||||
@ -303,12 +296,12 @@ public:
|
||||
}
|
||||
|
||||
/// setCallSiteBeginLabel - Map the begin label for a call site
|
||||
void setCallSiteBeginLabel(unsigned BeginLabel, unsigned Site) {
|
||||
void setCallSiteBeginLabel(MCSymbol *BeginLabel, unsigned Site) {
|
||||
CallSiteMap[BeginLabel] = Site;
|
||||
}
|
||||
|
||||
/// getCallSiteBeginLabel - Get the call site number for a begin label
|
||||
unsigned getCallSiteBeginLabel(unsigned BeginLabel) {
|
||||
unsigned getCallSiteBeginLabel(MCSymbol *BeginLabel) {
|
||||
assert(CallSiteMap.count(BeginLabel) &&
|
||||
"Missing call site number for EH_LABEL!");
|
||||
return CallSiteMap[BeginLabel];
|
||||
|
@ -25,32 +25,34 @@ namespace llvm {
|
||||
class MachineModuleInfoMachO : public MachineModuleInfoImpl {
|
||||
/// FnStubs - Darwin '$stub' stubs. The key is something like "Lfoo$stub",
|
||||
/// the value is something like "_foo".
|
||||
DenseMap<MCSymbol*, MCSymbol*> FnStubs;
|
||||
DenseMap<MCSymbol*, StubValueTy> FnStubs;
|
||||
|
||||
/// GVStubs - Darwin '$non_lazy_ptr' stubs. The key is something like
|
||||
/// "Lfoo$non_lazy_ptr", the value is something like "_foo".
|
||||
DenseMap<MCSymbol*, MCSymbol*> GVStubs;
|
||||
/// "Lfoo$non_lazy_ptr", the value is something like "_foo". The extra bit
|
||||
/// is true if this GV is external.
|
||||
DenseMap<MCSymbol*, StubValueTy> GVStubs;
|
||||
|
||||
/// HiddenGVStubs - Darwin '$non_lazy_ptr' stubs. The key is something like
|
||||
/// "Lfoo$non_lazy_ptr", the value is something like "_foo". Unlike GVStubs
|
||||
/// these are for things with hidden visibility.
|
||||
DenseMap<MCSymbol*, MCSymbol*> HiddenGVStubs;
|
||||
/// these are for things with hidden visibility. The extra bit is true if
|
||||
/// this GV is external.
|
||||
DenseMap<MCSymbol*, StubValueTy> HiddenGVStubs;
|
||||
|
||||
virtual void Anchor(); // Out of line virtual method.
|
||||
public:
|
||||
MachineModuleInfoMachO(const MachineModuleInfo &) {}
|
||||
|
||||
MCSymbol *&getFnStubEntry(MCSymbol *Sym) {
|
||||
StubValueTy &getFnStubEntry(MCSymbol *Sym) {
|
||||
assert(Sym && "Key cannot be null");
|
||||
return FnStubs[Sym];
|
||||
}
|
||||
|
||||
MCSymbol *&getGVStubEntry(MCSymbol *Sym) {
|
||||
StubValueTy &getGVStubEntry(MCSymbol *Sym) {
|
||||
assert(Sym && "Key cannot be null");
|
||||
return GVStubs[Sym];
|
||||
}
|
||||
|
||||
MCSymbol *&getHiddenGVStubEntry(MCSymbol *Sym) {
|
||||
StubValueTy &getHiddenGVStubEntry(MCSymbol *Sym) {
|
||||
assert(Sym && "Key cannot be null");
|
||||
return HiddenGVStubs[Sym];
|
||||
}
|
||||
@ -72,13 +74,13 @@ namespace llvm {
|
||||
class MachineModuleInfoELF : public MachineModuleInfoImpl {
|
||||
/// GVStubs - These stubs are used to materialize global addresses in PIC
|
||||
/// mode.
|
||||
DenseMap<MCSymbol*, MCSymbol*> GVStubs;
|
||||
DenseMap<MCSymbol*, StubValueTy> GVStubs;
|
||||
|
||||
virtual void Anchor(); // Out of line virtual method.
|
||||
public:
|
||||
MachineModuleInfoELF(const MachineModuleInfo &) {}
|
||||
|
||||
MCSymbol *&getGVStubEntry(MCSymbol *Sym) {
|
||||
StubValueTy &getGVStubEntry(MCSymbol *Sym) {
|
||||
assert(Sym && "Key cannot be null");
|
||||
return GVStubs[Sym];
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ class MachineRegisterInfo;
|
||||
class MDNode;
|
||||
class TargetMachine;
|
||||
class raw_ostream;
|
||||
class MCSymbol;
|
||||
|
||||
/// MachineOperand class - Representation of each machine instruction operand.
|
||||
///
|
||||
@ -44,7 +45,8 @@ public:
|
||||
MO_ExternalSymbol, ///< Name of external global symbol
|
||||
MO_GlobalAddress, ///< Address of a global value
|
||||
MO_BlockAddress, ///< Address of a basic block
|
||||
MO_Metadata ///< Metadata reference (for debug info)
|
||||
MO_Metadata, ///< Metadata reference (for debug info)
|
||||
MO_MCSymbol ///< MCSymbol reference (for debug/eh info)
|
||||
};
|
||||
|
||||
private:
|
||||
@ -101,6 +103,7 @@ private:
|
||||
const ConstantFP *CFP; // For MO_FPImmediate.
|
||||
int64_t ImmVal; // For MO_Immediate.
|
||||
const MDNode *MD; // For MO_Metadata.
|
||||
MCSymbol *Sym; // For MO_MCSymbol
|
||||
|
||||
struct { // For MO_Register.
|
||||
unsigned RegNo;
|
||||
@ -167,6 +170,7 @@ public:
|
||||
bool isBlockAddress() const { return OpKind == MO_BlockAddress; }
|
||||
/// isMetadata - Tests if this is a MO_Metadata operand.
|
||||
bool isMetadata() const { return OpKind == MO_Metadata; }
|
||||
bool isMCSymbol() const { return OpKind == MO_MCSymbol; }
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Accessors for Register Operands
|
||||
@ -315,6 +319,11 @@ public:
|
||||
assert(isBlockAddress() && "Wrong MachineOperand accessor");
|
||||
return Contents.OffsetedInfo.Val.BA;
|
||||
}
|
||||
|
||||
MCSymbol *getMCSymbol() const {
|
||||
assert(isMCSymbol() && "Wrong MachineOperand accessor");
|
||||
return Contents.Sym;
|
||||
}
|
||||
|
||||
/// getOffset - Return the offset from the symbol in this operand. This always
|
||||
/// returns 0 for ExternalSymbol operands.
|
||||
@ -473,6 +482,12 @@ public:
|
||||
return Op;
|
||||
}
|
||||
|
||||
static MachineOperand CreateMCSymbol(MCSymbol *Sym) {
|
||||
MachineOperand Op(MachineOperand::MO_MCSymbol);
|
||||
Op.Contents.Sym = Sym;
|
||||
return Op;
|
||||
}
|
||||
|
||||
friend class MachineInstr;
|
||||
friend class MachineRegisterInfo;
|
||||
private:
|
||||
|
@ -137,13 +137,6 @@ public:
|
||||
/// emitted.
|
||||
virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const;
|
||||
|
||||
/// emitLabel - Emits a label
|
||||
virtual void emitLabel(uint64_t LabelID) = 0;
|
||||
|
||||
/// getLabelAddress - Return the address of the specified LabelID, only usable
|
||||
/// after the LabelID has been emitted.
|
||||
virtual uintptr_t getLabelAddress(uint64_t LabelID) const = 0;
|
||||
|
||||
/// emitJumpTables - Emit all the jump tables for a given jump table info
|
||||
/// record to the appropriate section.
|
||||
virtual void emitJumpTables(MachineJumpTableInfo *MJTI) = 0;
|
||||
|
@ -150,9 +150,15 @@ namespace RTLIB {
|
||||
FLOOR_F64,
|
||||
FLOOR_F80,
|
||||
FLOOR_PPCF128,
|
||||
COPYSIGN_F32,
|
||||
COPYSIGN_F64,
|
||||
COPYSIGN_F80,
|
||||
COPYSIGN_PPCF128,
|
||||
|
||||
// CONVERSION
|
||||
FPEXT_F32_F64,
|
||||
FPEXT_F16_F32,
|
||||
FPROUND_F32_F16,
|
||||
FPROUND_F64_F32,
|
||||
FPROUND_F80_F32,
|
||||
FPROUND_PPCF128_F32,
|
||||
|
@ -227,6 +227,7 @@ namespace llvm {
|
||||
private:
|
||||
SDNode *Node; // Representative node.
|
||||
MachineInstr *Instr; // Alternatively, a MachineInstr.
|
||||
MachineInstr *DbgInstr; // A dbg_value referencing this.
|
||||
public:
|
||||
SUnit *OrigNode; // If not this, the node from which
|
||||
// this node was cloned.
|
||||
@ -269,10 +270,10 @@ namespace llvm {
|
||||
/// SUnit - Construct an SUnit for pre-regalloc scheduling to represent
|
||||
/// an SDNode and any nodes flagged to it.
|
||||
SUnit(SDNode *node, unsigned nodenum)
|
||||
: Node(node), Instr(0), OrigNode(0), NodeNum(nodenum), NodeQueueId(0),
|
||||
Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0),
|
||||
isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false),
|
||||
hasPhysRegClobbers(false),
|
||||
: Node(node), Instr(0), DbgInstr(0), OrigNode(0), NodeNum(nodenum),
|
||||
NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0),
|
||||
NumSuccsLeft(0), isTwoAddress(false), isCommutable(false),
|
||||
hasPhysRegDefs(false), hasPhysRegClobbers(false),
|
||||
isPending(false), isAvailable(false), isScheduled(false),
|
||||
isScheduleHigh(false), isCloned(false),
|
||||
isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0),
|
||||
@ -281,10 +282,10 @@ namespace llvm {
|
||||
/// SUnit - Construct an SUnit for post-regalloc scheduling to represent
|
||||
/// a MachineInstr.
|
||||
SUnit(MachineInstr *instr, unsigned nodenum)
|
||||
: Node(0), Instr(instr), OrigNode(0), NodeNum(nodenum), NodeQueueId(0),
|
||||
Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0),
|
||||
isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false),
|
||||
hasPhysRegClobbers(false),
|
||||
: Node(0), Instr(instr), DbgInstr(0), OrigNode(0), NodeNum(nodenum),
|
||||
NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0),
|
||||
NumSuccsLeft(0), isTwoAddress(false), isCommutable(false),
|
||||
hasPhysRegDefs(false), hasPhysRegClobbers(false),
|
||||
isPending(false), isAvailable(false), isScheduled(false),
|
||||
isScheduleHigh(false), isCloned(false),
|
||||
isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0),
|
||||
@ -292,10 +293,10 @@ namespace llvm {
|
||||
|
||||
/// SUnit - Construct a placeholder SUnit.
|
||||
SUnit()
|
||||
: Node(0), Instr(0), OrigNode(0), NodeNum(~0u), NodeQueueId(0),
|
||||
Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0),
|
||||
isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false),
|
||||
hasPhysRegClobbers(false),
|
||||
: Node(0), Instr(0), DbgInstr(0), OrigNode(0), NodeNum(~0u),
|
||||
NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0),
|
||||
NumSuccsLeft(0), isTwoAddress(false), isCommutable(false),
|
||||
hasPhysRegDefs(false), hasPhysRegClobbers(false),
|
||||
isPending(false), isAvailable(false), isScheduled(false),
|
||||
isScheduleHigh(false), isCloned(false),
|
||||
isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0),
|
||||
@ -329,6 +330,20 @@ namespace llvm {
|
||||
return Instr;
|
||||
}
|
||||
|
||||
/// setDbgInstr - Assign the debug instruction for the SUnit.
|
||||
/// This may be used during post-regalloc scheduling.
|
||||
void setDbgInstr(MachineInstr *MI) {
|
||||
assert(!Node && "Setting debug MachineInstr of SUnit with SDNode!");
|
||||
DbgInstr = MI;
|
||||
}
|
||||
|
||||
/// getDbgInstr - Return the debug MachineInstr for this SUnit.
|
||||
/// This may be used during post-regalloc scheduling.
|
||||
MachineInstr *getDbgInstr() const {
|
||||
assert(!Node && "Reading debug MachineInstr of SUnit with SDNode!");
|
||||
return DbgInstr;
|
||||
}
|
||||
|
||||
/// addPred - This adds the specified edge as a pred of the current node if
|
||||
/// not already. It also adds the current node as a successor of the
|
||||
/// specified node.
|
||||
|
@ -35,6 +35,7 @@ class MachineConstantPoolValue;
|
||||
class MachineFunction;
|
||||
class MachineModuleInfo;
|
||||
class SDNodeOrdering;
|
||||
class SDDbgValue;
|
||||
class TargetLowering;
|
||||
|
||||
template<> struct ilist_traits<SDNode> : public ilist_default_traits<SDNode> {
|
||||
@ -57,6 +58,46 @@ private:
|
||||
static void createNode(const SDNode &);
|
||||
};
|
||||
|
||||
/// SDDbgInfo - Keeps track of dbg_value information through SDISel. We do
|
||||
/// not build SDNodes for these so as not to perturb the generated code;
|
||||
/// instead the info is kept off to the side in this structure. SDNodes may
|
||||
/// have an associated dbg_value entry in DbgValMap. Debug info that is not
|
||||
/// associated with any SDNode is held in DbgConstMap. It is possible for
|
||||
/// optimizations to change a variable to a constant, in which case the
|
||||
/// corresponding debug info is moved from the variable to the constant table
|
||||
/// (NYI).
|
||||
class SDDbgInfo {
|
||||
DenseMap<const SDNode*, SDDbgValue*> DbgVblMap;
|
||||
SmallVector<SDDbgValue*, 4> DbgConstMap;
|
||||
|
||||
void operator=(const SDDbgInfo&); // Do not implement.
|
||||
SDDbgInfo(const SDDbgInfo&); // Do not implement.
|
||||
public:
|
||||
SDDbgInfo() {}
|
||||
|
||||
void add(const SDNode *Node, SDDbgValue *V) {
|
||||
DbgVblMap[Node] = V;
|
||||
}
|
||||
void add(SDDbgValue *V) { DbgConstMap.push_back(V); }
|
||||
void remove(const SDNode *Node) {
|
||||
DenseMap<const SDNode*, SDDbgValue*>::iterator Itr =
|
||||
DbgVblMap.find(Node);
|
||||
if (Itr != DbgVblMap.end())
|
||||
DbgVblMap.erase(Itr);
|
||||
}
|
||||
// No need to remove a constant.
|
||||
void clear() {
|
||||
DbgVblMap.clear();
|
||||
DbgConstMap.clear();
|
||||
}
|
||||
SDDbgValue *getSDDbgValue(const SDNode *Node) {
|
||||
return DbgVblMap[Node];
|
||||
}
|
||||
typedef SmallVector<SDDbgValue*, 4>::iterator ConstDbgIterator;
|
||||
ConstDbgIterator DbgConstBegin() { return DbgConstMap.begin(); }
|
||||
ConstDbgIterator DbgConstEnd() { return DbgConstMap.end(); }
|
||||
};
|
||||
|
||||
enum CombineLevel {
|
||||
Unrestricted, // Combine may create illegal operations and illegal types.
|
||||
NoIllegalTypes, // Combine may create illegal operations but no illegal types.
|
||||
@ -119,6 +160,9 @@ class SelectionDAG {
|
||||
/// the ordering of the original LLVM instructions.
|
||||
SDNodeOrdering *Ordering;
|
||||
|
||||
/// DbgInfo - Tracks dbg_value information through SDISel.
|
||||
SDDbgInfo *DbgInfo;
|
||||
|
||||
/// VerifyNode - Sanity check the given node. Aborts if it is invalid.
|
||||
void VerifyNode(SDNode *N);
|
||||
|
||||
@ -339,8 +383,7 @@ public:
|
||||
unsigned char TargetFlags = 0);
|
||||
SDValue getValueType(EVT);
|
||||
SDValue getRegister(unsigned Reg, EVT VT);
|
||||
SDValue getLabel(unsigned Opcode, DebugLoc dl, SDValue Root,
|
||||
unsigned LabelID);
|
||||
SDValue getEHLabel(DebugLoc dl, SDValue Root, MCSymbol *Label);
|
||||
SDValue getBlockAddress(BlockAddress *BA, EVT VT,
|
||||
bool isTarget = false, unsigned char TargetFlags = 0);
|
||||
|
||||
@ -828,6 +871,20 @@ public:
|
||||
/// GetOrdering - Get the order for the SDNode.
|
||||
unsigned GetOrdering(const SDNode *SD) const;
|
||||
|
||||
/// AssignDbgInfo - Assign debug info to the SDNode.
|
||||
void AssignDbgInfo(SDNode *SD, SDDbgValue *db);
|
||||
|
||||
/// RememberDbgInfo - Remember debug info with no associated SDNode.
|
||||
void RememberDbgInfo(SDDbgValue *db);
|
||||
|
||||
/// GetDbgInfo - Get the debug info for the SDNode.
|
||||
SDDbgValue *GetDbgInfo(const SDNode* SD);
|
||||
|
||||
SDDbgInfo::ConstDbgIterator DbgConstBegin() {
|
||||
return DbgInfo->DbgConstBegin();
|
||||
}
|
||||
SDDbgInfo::ConstDbgIterator DbgConstEnd() { return DbgInfo->DbgConstEnd(); }
|
||||
|
||||
void dump() const;
|
||||
|
||||
/// CreateStackTemporary - Create a stack temporary, suitable for holding the
|
||||
|
@ -274,7 +274,6 @@ private:
|
||||
// Calls to these functions are generated by tblgen.
|
||||
SDNode *Select_INLINEASM(SDNode *N);
|
||||
SDNode *Select_UNDEF(SDNode *N);
|
||||
SDNode *Select_EH_LABEL(SDNode *N);
|
||||
void CannotYetSelect(SDNode *N);
|
||||
|
||||
private:
|
||||
|
@ -40,6 +40,7 @@ class MachineBasicBlock;
|
||||
class MachineConstantPoolValue;
|
||||
class SDNode;
|
||||
class Value;
|
||||
class MCSymbol;
|
||||
template <typename T> struct DenseMapInfo;
|
||||
template <typename T> struct simplify_type;
|
||||
template <typename T> struct ilist_traits;
|
||||
@ -438,6 +439,12 @@ namespace ISD {
|
||||
// 5) ISD::CvtCode indicating the type of conversion to do
|
||||
CONVERT_RNDSAT,
|
||||
|
||||
// FP16_TO_FP32, FP32_TO_FP16 - These operators are used to perform
|
||||
// promotions and truncation for half-precision (16 bit) floating
|
||||
// numbers. We need special nodes since FP16 is a storage-only type with
|
||||
// special semantics of operations.
|
||||
FP16_TO_FP32, FP32_TO_FP16,
|
||||
|
||||
// FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW,
|
||||
// FLOG, FLOG2, FLOG10, FEXP, FEXP2,
|
||||
// FCEIL, FTRUNC, FRINT, FNEARBYINT, FFLOOR - Perform various unary floating
|
||||
@ -1383,9 +1390,9 @@ protected:
|
||||
/// This constructor adds no operands itself; operands can be
|
||||
/// set later with InitOperands.
|
||||
SDNode(unsigned Opc, const DebugLoc dl, SDVTList VTs)
|
||||
: NodeType(Opc), OperandsNeedDelete(false), SubclassData(0),
|
||||
NodeId(-1), OperandList(0), ValueList(VTs.VTs), UseList(NULL),
|
||||
NumOperands(0), NumValues(VTs.NumVTs),
|
||||
: NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false),
|
||||
SubclassData(0), NodeId(-1), OperandList(0), ValueList(VTs.VTs),
|
||||
UseList(NULL), NumOperands(0), NumValues(VTs.NumVTs),
|
||||
debugLoc(dl) {}
|
||||
|
||||
/// InitOperands - Initialize the operands list of this with 1 operand.
|
||||
@ -2088,18 +2095,18 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class LabelSDNode : public SDNode {
|
||||
class EHLabelSDNode : public SDNode {
|
||||
SDUse Chain;
|
||||
unsigned LabelID;
|
||||
MCSymbol *Label;
|
||||
friend class SelectionDAG;
|
||||
LabelSDNode(unsigned NodeTy, DebugLoc dl, SDValue ch, unsigned id)
|
||||
: SDNode(NodeTy, dl, getSDVTList(MVT::Other)), LabelID(id) {
|
||||
EHLabelSDNode(DebugLoc dl, SDValue ch, MCSymbol *L)
|
||||
: SDNode(ISD::EH_LABEL, dl, getSDVTList(MVT::Other)), Label(L) {
|
||||
InitOperands(&Chain, ch);
|
||||
}
|
||||
public:
|
||||
unsigned getLabelID() const { return LabelID; }
|
||||
MCSymbol *getLabel() const { return Label; }
|
||||
|
||||
static bool classof(const LabelSDNode *) { return true; }
|
||||
static bool classof(const EHLabelSDNode *) { return true; }
|
||||
static bool classof(const SDNode *N) {
|
||||
return N->getOpcode() == ISD::EH_LABEL;
|
||||
}
|
||||
|
@ -78,12 +78,13 @@ public:
|
||||
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
|
||||
Mangler *Mang, const TargetMachine &TM) const;
|
||||
|
||||
/// getSymbolForDwarfGlobalReference - Return an MCExpr to use for a reference
|
||||
/// getExprForDwarfGlobalReference - Return an MCExpr to use for a reference
|
||||
/// to the specified global variable from exception handling information.
|
||||
///
|
||||
virtual const MCExpr *
|
||||
getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
|
||||
MachineModuleInfo *MMI, unsigned Encoding) const;
|
||||
getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
|
||||
MachineModuleInfo *MMI, unsigned Encoding,
|
||||
MCStreamer &Streamer) const;
|
||||
};
|
||||
|
||||
|
||||
@ -166,11 +167,12 @@ public:
|
||||
return NonLazySymbolPointerSection;
|
||||
}
|
||||
|
||||
/// getSymbolForDwarfGlobalReference - The mach-o version of this method
|
||||
/// getExprForDwarfGlobalReference - The mach-o version of this method
|
||||
/// defaults to returning a stub reference.
|
||||
virtual const MCExpr *
|
||||
getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
|
||||
MachineModuleInfo *MMI, unsigned Encoding) const;
|
||||
getExprForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
|
||||
MachineModuleInfo *MMI, unsigned Encoding,
|
||||
MCStreamer &Streamer) const;
|
||||
|
||||
virtual unsigned getPersonalityEncoding() const;
|
||||
virtual unsigned getLSDAEncoding() const;
|
||||
|
@ -452,6 +452,9 @@
|
||||
/* Define to 1 if the system has the type `u_int64_t'. */
|
||||
#undef HAVE_U_INT64_T
|
||||
|
||||
/* Define to 1 if you have the <valgrind/valgrind.h> header file. */
|
||||
#cmakedefine HAVE_VALGRIND_VALGRIND_H ${HAVE_VALGRIND_VALGRIND_H}
|
||||
|
||||
/* Define to 1 if you have the <windows.h> header file. */
|
||||
#cmakedefine HAVE_WINDOWS_H ${HAVE_WINDOWS_H}
|
||||
|
||||
|
@ -440,6 +440,9 @@
|
||||
/* Define to 1 if the system has the type `u_int64_t'. */
|
||||
#undef HAVE_U_INT64_T
|
||||
|
||||
/* Define to 1 if you have the <valgrind/valgrind.h> header file. */
|
||||
#undef HAVE_VALGRIND_VALGRIND_H
|
||||
|
||||
/* Define to 1 if you have the <windows.h> header file. */
|
||||
#undef HAVE_WINDOWS_H
|
||||
|
||||
|
@ -1984,7 +1984,7 @@ public:
|
||||
};
|
||||
|
||||
template <>
|
||||
struct OperandTraits<ReturnInst> : public OptionalOperandTraits<> {
|
||||
struct OperandTraits<ReturnInst> : public VariadicOperandTraits<> {
|
||||
};
|
||||
|
||||
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ReturnInst, Value)
|
||||
|
@ -450,6 +450,14 @@ def int_flt_rounds : Intrinsic<[llvm_i32_ty]>,
|
||||
def int_trap : Intrinsic<[llvm_void_ty]>,
|
||||
GCCBuiltin<"__builtin_trap">;
|
||||
|
||||
// Intrisics to support half precision floating point format
|
||||
let Properties = [IntrNoMem] in {
|
||||
def int_convert_to_fp16 : Intrinsic<[llvm_i16_ty], [llvm_float_ty]>,
|
||||
GCCBuiltin<"__gnu_f2h_ieee">;
|
||||
def int_convert_from_fp16 : Intrinsic<[llvm_float_ty], [llvm_i16_ty]>,
|
||||
GCCBuiltin<"__gnu_h2f_ieee">;
|
||||
}
|
||||
|
||||
// These convert intrinsics are to support various conversions between
|
||||
// various types with rounding and saturation. NOTE: avoid using these
|
||||
// intrinsics as they might be removed sometime in the future and
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user