Files
mercury/compiler/Mmakefile
Peter Wang af878d04f9 Some work on the intermodule analysis framework.
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.
2006-01-25 03:27:38 +00:00

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)
#-----------------------------------------------------------------------------#