mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-20 16:31:04 +00:00
Estimated hours taken: 45 Branches: main Some work on the intermodule analysis framework. The main changes are that modules and analysis results have statuses associated with them, which are saved in the `.analysis' files, and there is now code to handle intermodule dependency graphs (that record which modules are dependent on a particular analysis result). Automatic recompilation of modules that use out of date or invalid analysis results from other modules is not handled yet. analysis/README: analysis/analysis.m: analysis/analysis.file.m: Remove the `FuncInfo' type variable everywhere. This was originally designed to be used by analyses to store "extra" information that would be passed from an analysis implementation through the analysis framework, back to methods defined by the analysis implementation itself. The main problem was that `FuncInfo' made `Call' or `Answer' values hard to compare, as a `FuncInfo' value always had to be present for a comparison to be made (because the methods in the partial_order typeclass required FuncInfos). One example of when this is hard to satisfy is when we are ready to write everything out to disk at the end of all analyses. At this step there is much comparing of Call and Answer values, but this step is not invoked by any particular analysis pass. To compare values we would need to get the FuncInfos from somewhere, which means we would have to store FuncInfos in the analysis_info maps as well. And any time you have two FuncInfos, you need to choose one of the FuncInfos arbitrarily. Since FuncInfos would have to be read/written with every Call and Answer value, including IMDGs, I have changed it so that that any information which might be be stored in a `FuncInfo' should be stored in the corresponding `Call' value itself. Change the format of analysis result files to include an overall status for the module and a status for each analysis result. The statuses record whether the module or analysis result could be improved by further compilation, or if the module or analysis result is no longer valid. Add code to read and write intermodule dependency graphs (IMDGs). The IMDG file for module M records all the modules which depend on an analysis result for a procedure defined in M. Bump analysis file format version numbers as they are incompatible with earlier versions. compiler/mercury_compile.m: Make `mercury_compile_after_front_end' use state variables for copies of the HLDS and update it to match changes in the intermodule analysis framework. compiler/mmc_analysis.m: Add the trail usage analysis to the list of analyses to be used with the intermodule analysis framework. Update the entry for unused argument elimination. Add predicate `module_id_func_id'. compiler/add_pragma.m: compiler/hlds_module.m: compiler/trailing_analysis.m: Make the trail usage analysis pass able to make use of the intermodule analysis framework. Associate each `trailing_status' in the `trailing_info' map with an `analysis_status', i.e. whether it is optimal or not. compiler/unused_args.m: Update to match the removal of `FuncInfo' arguments and the addition of analysis statuses. Record the unused argument analysis result for a procedure even if all of the procedures arguments are used, so that callers of the procedure will know not to request more precise answers. Record the dependence of the current module on analysis results from other modules. compiler/goal_util.m: Add predicate `pred_proc_ids_from_goal/2'. compiler/make.m: compiler/make.dependencies.m: compiler/make.program_target.m: compiler/make.util.m: compiler/modules.m: scripts/Mmake.vars.in: Make `mmc --make' and `mmake' realclean `.analysis', `.imdg' and `.request' files of non-library modules. Files for imported library modules won't be deleted, but they probably shouldn't be generated in the first place. NEWS: library/list.m: Add a `list.map2_foldl2' predicate. compiler/Mmakefile: Add the `analysis' directory to the list of directories to be processed by mtags.
346 lines
11 KiB
Plaintext
346 lines
11 KiB
Plaintext
#-----------------------------------------------------------------------------#
|
|
# Copyright (C) 1995-2003, 2005-2006 The University of Melbourne.
|
|
# This file may only be copied under the terms of the GNU General
|
|
# Public Licence - see the file COPYING in the Mercury distribution.
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
# Mmake - this is Mmake file for building the Mercury compiler
|
|
|
|
MERCURY_DIR=..
|
|
LINK_STATIC=yes
|
|
include $(MERCURY_DIR)/Mmake.common
|
|
-include Mmake.compiler.params
|
|
|
|
# Override the default rule in `mmake --use-mmc-make' that asks `mmc' to
|
|
# create a missing optional params file for us.
|
|
Mmake.compiler.params:
|
|
|
|
# Module-specific options should go in Mercury.options so they
|
|
# can be found by `mmc --make'.
|
|
# Mercury.options uses $(GCC_SRC_DIR), so make sure it is
|
|
# in the environment of `mmc --make'.
|
|
GCC_SRC_DIR := $(MERCURY_DIR)/$(GCC_SRC_DIR)
|
|
export GCC_SRC_DIR
|
|
include Mercury.options
|
|
|
|
MAIN_TARGET=all
|
|
|
|
MERCURY_MAIN_MODULES = top_level mlds_to_gcc
|
|
|
|
VPATH = $(LIBRARY_DIR) $(MDBCOMP_DIR) $(BROWSER_DIR) $(ANALYSIS_DIR)
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
# Specify how to link in the GCC back-end.
|
|
# This uses the file `mercury_gcc_backend_libs', which is generated by
|
|
# the gcc Makefile (from gcc/mercury/Make-lang.in), which contains
|
|
# a list of the object files and libraries that we need to link in.
|
|
ifeq ($(ENABLE_GCC_BACK_END),yes)
|
|
GCC_LIBS = $(shell cat $(GCC_SRC_DIR)/gcc/mercury_gcc_backend_libs)
|
|
GCC_EXTRA_LIBS = $(filter -l%,$(GCC_LIBS))
|
|
GCC_MAIN_LIBS = $(patsubst %,$(GCC_SRC_DIR)/gcc/%,$(filter-out -l%,$(GCC_LIBS)))
|
|
GCC_BACKEND_LIBS = $(GCC_MAIN_LIBS) $(GCC_EXTRA_LIBS)
|
|
else
|
|
GCC_MAIN_LIBS =
|
|
GCC_BACKEND_LIBS =
|
|
endif
|
|
|
|
# Ensure that we rebuild the GCC libbackend.a, etc., if it is out-of-date
|
|
.PHONY: force
|
|
force: ;
|
|
|
|
$(GCC_MAIN_LIBS): force
|
|
cd $(GCC_SRC_DIR)/gcc && $(MAKE) mercury_gcc_backend_libs
|
|
|
|
MCFLAGS += --flags COMP_FLAGS $(CONFIG_OVERRIDE)
|
|
MLOBJS := ../main.$O ../analysis/lib$(ANALYSIS_LIB_NAME).$A $(MLOBJS)
|
|
ALL_MLLIBS = $(MLLIBS) $(EXTRA_MLLIBS) $(GCC_BACKEND_LIBS)
|
|
MLFLAGS += --no-main --shared
|
|
C2INITARGS += $(ANALYSIS_DIR)/$(ANALYSIS_LIB_NAME).init
|
|
C2INITARGS += $(MDBCOMP_DIR)/$(MDBCOMP_LIB_NAME).init
|
|
|
|
#
|
|
# Work-around for a fixed limit: on alpha-dec-osf3.2, if we compile with
|
|
# `-O5', then when linking mercury_compile we get an error message of the form
|
|
#
|
|
# /usr/bin/ld:
|
|
# Too many GOT entries in object file '/usr/lib/cmplrs/cc/libexc_init.a';
|
|
# Found 8190 (6660 locals + 1530 globals) but max is 8189
|
|
#
|
|
# unless we link it statically.
|
|
#
|
|
ifeq ($(FULLARCH),alpha-dec-osf3.2)
|
|
MLFLAGS += --static
|
|
MCFLAGS += --linkage static
|
|
endif
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
# Rules for preprocessing `.pp' files.
|
|
# `.pp_date' files are used as timestamps as for interface files.
|
|
|
|
#
|
|
# Rule to generate foo.m from foo.pp by applying `sed $(PP_SED_EXPR)'
|
|
#
|
|
# Note that we set hash="#" for use in $(PP_SED_EXPR).
|
|
# This seems to be the easiest way to get a "#" character;
|
|
# we can't just use a Make variable since "#" is a comment character
|
|
# in Make and so its hard to create a variable with that value.
|
|
#
|
|
$(dates_subdir)%.pp_date: %.pp
|
|
-hash="#"; \
|
|
m_file=$(<:.pp=.m); \
|
|
[ ! -f $$m_file ] || chmod +w $$m_file; \
|
|
sed $(PP_SED_EXPR) $< > $$m_file.tmp && \
|
|
mercury_update_interface -v $$m_file && \
|
|
touch $@ && \
|
|
chmod -w $$m_file
|
|
|
|
#
|
|
# Define $(PP_SED_EXPR) appropriately for each preprocessed module.
|
|
#
|
|
PP_SED_EXPR = $(PP_SED_EXPR-$*)
|
|
PP_SED_EXPR-aditi_backend = $(ADITI_SED_EXPR)
|
|
PP_SED_EXPR-rl_file = $(ADITI_SED_EXPR)
|
|
PP_SED_EXPR-rl_out = $(ADITI_SED_EXPR)
|
|
PP_SED_EXPR-maybe_mlds_to_gcc = $(GCC_SED_EXPR)
|
|
|
|
#
|
|
# For Aditi .pp files, enable/disable code within
|
|
# `#if INCLUDE_ADITI_OUTPUT ... #else .. #endif'
|
|
#
|
|
ifeq ($(INCLUDE_ADITI_OUTPUT),yes)
|
|
# Remove the #if line and everything between the #else and #endif lines.
|
|
ADITI_SED_EXPR = -e "/^$${hash}if *INCLUDE_ADITI_OUTPUT/s/.*//" \
|
|
-e "/^$${hash}else/,/^$${hash}endif/s/.*//"
|
|
else
|
|
# Remove everything between the #if line and the #else line,
|
|
# and the #endif line.
|
|
ADITI_SED_EXPR = -e "/^$${hash}if *INCLUDE_ADITI_OUTPUT/,/^$${hash}else/s/.*//" \
|
|
-e "/^$${hash}endif/s/.*//"
|
|
endif
|
|
|
|
#
|
|
# For GCC .pp files, enable/disable code within
|
|
# `#if ENABLE_GCC_BACK_END ... #else .. #endif'
|
|
#
|
|
ifeq ($(ENABLE_GCC_BACK_END),yes)
|
|
# Remove the #if line and everything between the #else and #endif lines.
|
|
GCC_SED_EXPR = -e "/^$${hash}if *ENABLE_GCC_BACK_END/s/.*//" \
|
|
-e "/^$${hash}else/,/^$${hash}endif/s/.*//"
|
|
else
|
|
# Remove everything between the #if line and the #else line,
|
|
# and the #endif line.
|
|
GCC_SED_EXPR = -e "/^$${hash}if *ENABLE_GCC_BACK_END/,/^$${hash}else/s/.*//" \
|
|
-e "/^$${hash}endif/s/.*//"
|
|
endif
|
|
|
|
PREPROCESSED_MODULES = aditi_backend rl_file rl_out maybe_mlds_to_gcc
|
|
PREPROCESSED_FILES = $(PREPROCESSED_MODULES:%=%.pp)
|
|
PREPROCESSED_M_FILES = $(PREPROCESSED_MODULES:%=%.m)
|
|
PP_DATE_FILES = $(PREPROCESSED_MODULES:%=$(dates_subdir)%.pp_date)
|
|
|
|
# Force regeneration of the preprocessed modules.
|
|
# This is necessary if the setting of `INCLUDE_ADITI_OUTPUT' has changed.
|
|
regenerate_preprocessed_files:
|
|
-[ -d ./$(dates_subdir) ] || mkdir -p ./$(dates_subdir)
|
|
touch $(PREPROCESSED_FILES)
|
|
MMAKE_DIR=$(SCRIPTS_DIR) $(MMAKE) $(PREPROCESSED_M_FILES)
|
|
|
|
# The `.m' files for the preprocessed modules depend on the `.pp_date' files.
|
|
$(PREPROCESSED_M_FILES): %.m: $(dates_subdir)%.pp_date
|
|
@:
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
# targets
|
|
|
|
# specify the name of the top-level module to build
|
|
MC_PROG = top_level
|
|
|
|
# mercury_compile
|
|
|
|
.PHONY: depend
|
|
depend: $(MC_PROG).depend
|
|
|
|
$(MC_PROG).depend: regenerate_preprocessed_files Mercury.modules COMP_FLAGS
|
|
|
|
# This directory contains source files for which the module
|
|
# name doesn't match the file name, so smart recompilation
|
|
# won't work without the Mercury.modules file.
|
|
.PHONY: Mercury.modules
|
|
Mercury.modules: COMP_FLAGS
|
|
$(MC) $(ALL_GRADEFLAGS) $(ALL_MCFLAGS) -f *.m
|
|
|
|
.PHONY: all
|
|
all: mercury $(TAGS_FILE_EXISTS)
|
|
|
|
.PHONY: mercury
|
|
mercury: mercury_compile
|
|
|
|
.PHONY: libmmc
|
|
libmmc: libmercury_compile.a mercury_compile_init.$O
|
|
|
|
# The executable was previous known as `mercury_compile',
|
|
# but now we generate it as `top_level'. For compatibility with
|
|
# various existing code, we make links to the old names.
|
|
|
|
LN = ln
|
|
|
|
ifneq ("$(EXT_FOR_EXE)","")
|
|
.PHONY: mercury_compile
|
|
mercury_compile: mercury_compile$(EXT_FOR_EXE)
|
|
endif
|
|
|
|
mercury_compile$(EXT_FOR_EXE): $(MC_PROG)$(EXT_FOR_EXE)
|
|
rm -f mercury_compile$(EXT_FOR_EXE)
|
|
$(LN) $(MC_PROG)$(EXT_FOR_EXE) mercury_compile$(EXT_FOR_EXE) || \
|
|
cp $(MC_PROG)$(EXT_FOR_EXE) mercury_compile$(EXT_FOR_EXE)
|
|
ifeq ($(findstring il,$(GRADE)),il)
|
|
# set the stack size to 100M -- the default of 1M is too low
|
|
-editbin /nologo /stack:100000000 mercury_compile$(EXT_FOR_EXE)
|
|
cp ../analysis/*.dll ../browser/*.dll .
|
|
endif
|
|
|
|
libmercury_compile.a: lib$(MC_PROG).a
|
|
rm -f libmercury_compile.a
|
|
cp lib$(MC_PROG).a libmercury_compile.a
|
|
ar d libmercury_compile.a main.o
|
|
|
|
mercury_compile_init.$O: $(MC_PROG)_init.$O
|
|
rm -f mercury_compile_init.$O
|
|
$(LN) $(MC_PROG)_init.$O mercury_compile_init.$O || \
|
|
cp $(MC_PROG)_init.$O mercury_compile_init.$O
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
# The GCC back-end stuff is conditionally compiled out of maybe_mlds_to_gcc.m.
|
|
# But we want to make sure that the GCC back-end continues to compile,
|
|
# even when the compiler was configured without the GCC back-end.
|
|
# So we include the following rules, which tell Mmake to build the
|
|
# dependencies for mlds_to_gcc and to build mlds_to_gcc.c and gcc.c.
|
|
# (We used to just build mlds_to_gcc.err, but that caused bootstrapping problems
|
|
# with the source distribution; using the .c files is little more robust.)
|
|
|
|
ifeq ("$(filter il% java%,$(GRADE))","")
|
|
|
|
.PHONY: depend
|
|
depend: COMP_FLAGS mlds_to_gcc.depend
|
|
|
|
mlds_to_gcc.depend: regenerate_preprocessed_files
|
|
|
|
.PHONY: mercury
|
|
mercury: mlds_to_gcc.c gcc.c
|
|
|
|
.PHONY: cs
|
|
cs: mlds_to_gcc.c gcc.c
|
|
|
|
endif
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
# Add some additional dependencies, so that Mmake knows to remake the
|
|
# compiler if one of the libraries changes.
|
|
|
|
ifeq ($(findstring il,$(GRADE)),il)
|
|
MS_CSCFLAGS=/lib:`$(FIX_PATH_FOR_CSC) ../analysis`
|
|
|
|
# This line works around an Mmake bug: mmake doesn't record
|
|
# dependencies properly with --transitive-intermodule-optimization
|
|
%.il: opts
|
|
else
|
|
$(MC_PROG): ../main.$O
|
|
$(MC_PROG): $(RUNTIME_DIR)/lib$(RT_LIB_NAME).$A
|
|
$(MC_PROG): $(LIBRARY_DIR)/lib$(STD_LIB_NAME).$A
|
|
$(MC_PROG): $(MDBCOMP_DIR)/lib$(MDBCOMP_LIB_NAME).$A
|
|
$(MC_PROG): $(BROWSER_DIR)/lib$(BROWSER_LIB_NAME).$A
|
|
$(MC_PROG): $(TRACE_DIR)/lib$(TRACE_LIB_NAME).$A
|
|
$(MC_PROG): $(ANALYSIS_DIR)/lib$(ANALYSIS_LIB_NAME).$A
|
|
# XXX should also depend on $(BOEHM_GC_DIR)/libgc(_prof).$A, but only
|
|
# if in .gc(.prof) grade
|
|
$(MC_PROG): $(GCC_MAIN_LIBS)
|
|
endif
|
|
|
|
$(MC_PROG)_init.c: $(UTIL_DIR)/mkinit
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
.PHONY: check
|
|
check: $(MC_PROG).check
|
|
|
|
.PHONY: ints
|
|
ints: $(MC_PROG).ints
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
tags: $(PREPROCESSED_M_FILES) *.m $(LIBRARY_DIR)/*.m $(MDBCOMP_DIR)/*.m \
|
|
$(ANALYSIS_DIR)/*.m
|
|
$(MTAGS) $(MTAGSFLAGS) *.m $(LIBRARY_DIR)/*.m $(MDBCOMP_DIR)/*.m \
|
|
$(ANALYSIS_DIR)/*.m
|
|
|
|
.PHONY: tags_file_exists
|
|
tags_file_exists:
|
|
@if test ! -f tags; then echo making tags ; \
|
|
$(MTAGS) $(MTAGSFLAGS) *.m $(LIBRARY_DIR)/*.m ; fi
|
|
|
|
$(MC_PROG).stats: source_stats.awk $($(MC_PROG).ms)
|
|
awk -f `vpath_find source_stats.awk` \
|
|
`vpath_find $($(MC_PROG).ms)` > $@
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
.PHONY: dates
|
|
dates:
|
|
touch $($(MC_PROG).dates)
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
# Note that the cs and os targets don't build top_level_init.{c,o}
|
|
.PHONY: os cs ss ils
|
|
ifneq ($(MMAKE_USE_MMC_MAKE),yes)
|
|
os: $($(MC_PROG).os)
|
|
cs: $($(MC_PROG).cs)
|
|
ss: $($(MC_PROG).ss)
|
|
ils: $($(MC_PROG).ils)
|
|
opts: $($(MC_PROG).opts)
|
|
else
|
|
os: $(MC_PROG).os
|
|
cs: $(MC_PROG).cs
|
|
ss: $(MC_PROG).ss
|
|
ils: $(MC_PROG).ils
|
|
opts: $(MC_PROG).opts
|
|
endif
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
clean_local:
|
|
rm -f ../main.$O $(PREPROCESSED_M_FILES) $(PP_DATE_FILES)
|
|
|
|
realclean_local:
|
|
rm -f tags $(MC_PROG).stats Mercury.modules \
|
|
COMP_FLAGS COMP_FLAGS.date mercury_compile$(EXT_FOR_EXE)
|
|
|
|
#-----------------------------------------------------------------------------#
|
|
#-----------------------------------------------------------------------------#
|
|
|
|
# Installation targets
|
|
|
|
.PHONY: install
|
|
install: install_mercury
|
|
|
|
.PHONY: install_all
|
|
install_all: install_mercury
|
|
|
|
.PHONY: install_mercury
|
|
install_mercury: install_compiler
|
|
|
|
.PHONY: install_dirs
|
|
install_dirs:
|
|
-[ -d $(INSTALL_MERC_BIN_DIR) ] || mkdir -p $(INSTALL_MERC_BIN_DIR)
|
|
|
|
.PHONY: install_compiler
|
|
install_compiler: mercury_compile install_dirs
|
|
cp `vpath_find mercury_compile$(EXT_FOR_EXE)` $(INSTALL_MERC_BIN_DIR)
|
|
|
|
#-----------------------------------------------------------------------------#
|