Vendor import of llvm release_30 branch r142614:
http://llvm.org/svn/llvm-project/llvm/branches/release_30@142614
This commit is contained in:
parent
1176aa5264
commit
7b3392326c
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,6 +22,7 @@
|
||||
# Explicit files to ignore (only matches one).
|
||||
#==============================================================================#
|
||||
.gitusers
|
||||
autom4te.cache
|
||||
cscope.files
|
||||
cscope.out
|
||||
autoconf/aclocal.m4
|
||||
|
@ -82,7 +82,7 @@ set(LLVM_ALL_TARGETS
|
||||
)
|
||||
|
||||
# List of targets with JIT support:
|
||||
set(LLVM_TARGETS_WITH_JIT X86 PowerPC ARM)
|
||||
set(LLVM_TARGETS_WITH_JIT X86 PowerPC ARM Mips)
|
||||
|
||||
if( MSVC )
|
||||
set(LLVM_TARGETS_TO_BUILD X86
|
||||
@ -181,12 +181,16 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
include_directories( ${LLVM_BINARY_DIR}/include ${LLVM_MAIN_INCLUDE_DIR})
|
||||
|
||||
if( ${CMAKE_SYSTEM_NAME} MATCHES SunOS )
|
||||
SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-include llvm/Support/Solaris.h")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -include llvm/Support/Solaris.h")
|
||||
endif( ${CMAKE_SYSTEM_NAME} MATCHES SunOS )
|
||||
|
||||
include(AddLLVM)
|
||||
include(TableGen)
|
||||
|
||||
macro(llvm_tablegen)
|
||||
tablegen(LLVM ${ARGN})
|
||||
endmacro()
|
||||
|
||||
if( MINGW )
|
||||
# People report that -O3 is unreliable on MinGW. The traditional
|
||||
# build also uses -O2 for that reason:
|
||||
@ -195,19 +199,10 @@ endif()
|
||||
|
||||
# Put this before tblgen. Else we have a circular dependence.
|
||||
add_subdirectory(lib/Support)
|
||||
|
||||
set(LLVM_TABLEGEN "tblgen" CACHE
|
||||
STRING "Native TableGen executable. Saves building one when cross-compiling.")
|
||||
# Effective tblgen executable to be used:
|
||||
set(LLVM_TABLEGEN_EXE ${LLVM_TABLEGEN})
|
||||
add_subdirectory(lib/TableGen)
|
||||
|
||||
add_subdirectory(utils/TableGen)
|
||||
|
||||
if( CMAKE_CROSSCOMPILING )
|
||||
# This adds a dependency on target `tblgen', so must go after utils/TableGen
|
||||
include( CrossCompileLLVM )
|
||||
endif( CMAKE_CROSSCOMPILING )
|
||||
|
||||
add_subdirectory(include/llvm)
|
||||
|
||||
add_subdirectory(lib)
|
||||
|
10
CREDITS.TXT
10
CREDITS.TXT
@ -32,6 +32,10 @@ E: dberlin@dberlin.org
|
||||
D: ET-Forest implementation.
|
||||
D: Sparse bitmap
|
||||
|
||||
N: David Blaikie
|
||||
E: dblaikie@gmail.com
|
||||
D: General bug fixing/fit & finish, mostly in Clang
|
||||
|
||||
N: Neil Booth
|
||||
E: neil@daikokuya.co.uk
|
||||
D: APFloat implementation.
|
||||
@ -241,6 +245,10 @@ E: duraid@octopus.com.au
|
||||
W: http://kinoko.c.u-tokyo.ac.jp/~duraid/
|
||||
D: IA64 backend, BigBlock register allocator
|
||||
|
||||
N: John McCall
|
||||
E: rjmccall@apple.com
|
||||
D: Clang semantic analysis and IR generation
|
||||
|
||||
N: Michael McCracken
|
||||
E: michael.mccracken@gmail.com
|
||||
D: Line number support for llvmgcc
|
||||
@ -274,6 +282,8 @@ N: Jakob Stoklund Olesen
|
||||
E: stoklund@2pi.dk
|
||||
D: Machine code verifier
|
||||
D: Blackfin backend
|
||||
D: Fast register allocator
|
||||
D: Greedy register allocator
|
||||
|
||||
N: Richard Osborne
|
||||
E: richard@xmos.com
|
||||
|
14
Makefile
14
Makefile
@ -10,7 +10,7 @@
|
||||
LEVEL := .
|
||||
|
||||
# Top-Level LLVM Build Stages:
|
||||
# 1. Build lib/Support, which is used by utils (tblgen).
|
||||
# 1. Build lib/Support and lib/TableGen, which are used by utils (tblgen).
|
||||
# 2. Build utils, which is used by VMCore.
|
||||
# 3. Build VMCore, which builds the Intrinsics.inc file used by libs.
|
||||
# 4. Build libs, which are needed by llvm-config.
|
||||
@ -27,10 +27,10 @@ LEVEL := .
|
||||
ifneq ($(findstring llvmCore, $(RC_ProjectName)),llvmCore) # Normal build (not "Apple-style").
|
||||
|
||||
ifeq ($(BUILD_DIRS_ONLY),1)
|
||||
DIRS := lib/Support utils
|
||||
OPTIONAL_DIRS :=
|
||||
DIRS := lib/Support lib/TableGen utils
|
||||
OPTIONAL_DIRS := tools/clang/utils/TableGen
|
||||
else
|
||||
DIRS := lib/Support utils lib/VMCore lib tools/llvm-shlib \
|
||||
DIRS := lib/Support lib/TableGen utils lib/VMCore lib tools/llvm-shlib \
|
||||
tools/llvm-config tools runtime docs unittests
|
||||
OPTIONAL_DIRS := projects bindings
|
||||
endif
|
||||
@ -118,7 +118,8 @@ cross-compile-build-tools:
|
||||
unset CFLAGS ; \
|
||||
unset CXXFLAGS ; \
|
||||
$(PROJ_SRC_DIR)/configure --build=$(BUILD_TRIPLE) \
|
||||
--host=$(BUILD_TRIPLE) --target=$(BUILD_TRIPLE); \
|
||||
--host=$(BUILD_TRIPLE) --target=$(BUILD_TRIPLE) \
|
||||
--disable-polly ; \
|
||||
cd .. ; \
|
||||
fi; \
|
||||
(unset SDKROOT; \
|
||||
@ -187,8 +188,7 @@ FilesToConfig := \
|
||||
include/llvm/Config/AsmPrinters.def \
|
||||
include/llvm/Config/AsmParsers.def \
|
||||
include/llvm/Config/Disassemblers.def \
|
||||
include/llvm/Support/DataTypes.h \
|
||||
tools/llvmc/src/Base.td
|
||||
include/llvm/Support/DataTypes.h
|
||||
FilesToConfigPATH := $(addprefix $(LLVM_OBJ_ROOT)/,$(FilesToConfig))
|
||||
|
||||
all-local:: $(FilesToConfigPATH)
|
||||
|
@ -188,30 +188,6 @@ LIBS := @LIBS@
|
||||
# Targets that we should build
|
||||
TARGETS_TO_BUILD=@TARGETS_TO_BUILD@
|
||||
|
||||
# Path to location for LLVM C/C++ front-end. You can modify this if you
|
||||
# want to override the value set by configure.
|
||||
LLVMGCCDIR := @LLVMGCCDIR@
|
||||
|
||||
# Full pathnames of LLVM C/C++ front-end 'cc1' and 'cc1plus' binaries:
|
||||
LLVMGCC := @LLVMGCC@
|
||||
LLVMGXX := @LLVMGXX@
|
||||
LLVMCC1 := @LLVMCC1@
|
||||
LLVMCC1PLUS := @LLVMCC1PLUS@
|
||||
LLVMGCC_LANGS := @LLVMGCC_LANGS@
|
||||
LLVMGCC_DRAGONEGG := @LLVMGCC_DRAGONEGG@
|
||||
|
||||
# Information on Clang, if configured.
|
||||
CLANGPATH := @CLANGPATH@
|
||||
CLANGXXPATH := @CLANGXXPATH@
|
||||
ENABLE_BUILT_CLANG := @ENABLE_BUILT_CLANG@
|
||||
|
||||
# The LLVM capable compiler to use.
|
||||
LLVMCC_OPTION := @LLVMCC_OPTION@
|
||||
|
||||
# The flag used to emit LLVM IR.
|
||||
LLVMCC_EMITIR_FLAG = @LLVMCC_EMITIR_FLAG@
|
||||
LLVMCC_DISABLEOPT_FLAGS := @LLVMCC_DISABLEOPT_FLAGS@
|
||||
|
||||
# Path to directory where object files should be stored during a build.
|
||||
# Set OBJ_ROOT to "." if you do not want to use a separate place for
|
||||
# object files.
|
||||
@ -338,17 +314,6 @@ endif
|
||||
# Location of the plugin header file for gold.
|
||||
BINUTILS_INCDIR := @BINUTILS_INCDIR@
|
||||
|
||||
# When ENABLE_LLVMC_DYNAMIC is enabled, LLVMC will link libCompilerDriver
|
||||
# dynamically. This is needed to make dynamic plugins work on some targets
|
||||
# (Windows).
|
||||
ENABLE_LLVMC_DYNAMIC = 0
|
||||
#@ENABLE_LLVMC_DYNAMIC@
|
||||
|
||||
# When ENABLE_LLVMC_DYNAMIC_PLUGINS is enabled, LLVMC will have dynamic plugin
|
||||
# support (via the -load option).
|
||||
ENABLE_LLVMC_DYNAMIC_PLUGINS = 1
|
||||
#@ENABLE_LLVMC_DYNAMIC_PLUGINS@
|
||||
|
||||
# Optional flags supported by the compiler
|
||||
# -Wno-missing-field-initializers
|
||||
NO_MISSING_FIELD_INITIALIZERS = @NO_MISSING_FIELD_INITIALIZERS@
|
||||
|
117
Makefile.rules
117
Makefile.rules
@ -190,19 +190,6 @@ uninstall:: uninstall-local
|
||||
install-local:: all-local
|
||||
install-bytecode:: install-bytecode-local
|
||||
|
||||
###############################################################################
|
||||
# LLVMC: Provide rules for compiling llvmc-based driver
|
||||
###############################################################################
|
||||
|
||||
ifdef LLVMC_BASED_DRIVER
|
||||
|
||||
TOOLNAME = $(LLVMC_BASED_DRIVER)
|
||||
|
||||
LLVMLIBS = CompilerDriver.a
|
||||
LINK_COMPONENTS = support
|
||||
|
||||
endif # LLVMC_BASED_DRIVER
|
||||
|
||||
###############################################################################
|
||||
# VARIABLES: Set up various variables based on configuration data
|
||||
###############################################################################
|
||||
@ -463,11 +450,11 @@ Echo = @$(EchoCmd)
|
||||
ifndef LLVMAS
|
||||
LLVMAS := $(LLVMToolDir)/llvm-as$(EXEEXT)
|
||||
endif
|
||||
ifndef TBLGEN
|
||||
ifndef LLVM_TBLGEN
|
||||
ifeq ($(LLVM_CROSS_COMPILING),1)
|
||||
TBLGEN := $(BuildLLVMToolDir)/tblgen$(BUILD_EXEEXT)
|
||||
LLVM_TBLGEN := $(BuildLLVMToolDir)/llvm-tblgen$(BUILD_EXEEXT)
|
||||
else
|
||||
TBLGEN := $(LLVMToolDir)/tblgen$(EXEEXT)
|
||||
LLVM_TBLGEN := $(LLVMToolDir)/llvm-tblgen$(EXEEXT)
|
||||
endif
|
||||
endif
|
||||
LLVM_CONFIG := $(LLVMToolDir)/llvm-config
|
||||
@ -636,7 +623,7 @@ CPP.BaseFlags += -include llvm/Support/Solaris.h
|
||||
endif # !HOST_OS - AuroraUX.
|
||||
|
||||
LD.Flags += -L$(LibDir) -L$(LLVMLibDir)
|
||||
CPP.BaseFlags += -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS
|
||||
CPP.BaseFlags += -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
|
||||
# All -I flags should go here, so that they don't confuse llvm-config.
|
||||
CPP.Flags += $(sort -I$(PROJ_OBJ_DIR) -I$(PROJ_SRC_DIR) \
|
||||
$(patsubst %,-I%/include,\
|
||||
@ -697,10 +684,11 @@ DataInstall = $(INSTALL) -m 0644
|
||||
# When compiling under Mingw/Cygwin, the tblgen tool expects Windows
|
||||
# paths. In this case, the SYSPATH function (defined in
|
||||
# Makefile.config) transforms Unix paths into Windows paths.
|
||||
TableGen = $(TBLGEN) -I $(call SYSPATH, $(PROJ_SRC_DIR)) \
|
||||
TableGen.Flags= -I $(call SYSPATH, $(PROJ_SRC_DIR)) \
|
||||
-I $(call SYSPATH, $(LLVM_SRC_ROOT)/include) \
|
||||
-I $(call SYSPATH, $(PROJ_SRC_ROOT)/include) \
|
||||
-I $(call SYSPATH, $(PROJ_SRC_ROOT)/lib/Target)
|
||||
LLVMTableGen = $(LLVM_TBLGEN) $(TableGen.Flags)
|
||||
|
||||
Archive = $(AR) $(AR.Flags)
|
||||
LArchive = $(LLVMToolDir)/llvm-ar rcsf
|
||||
@ -1686,10 +1674,6 @@ ifdef TARGET
|
||||
TABLEGEN_INC_FILES_COMMON = 1
|
||||
endif
|
||||
|
||||
ifdef LLVMC_BASED_DRIVER
|
||||
TABLEGEN_INC_FILES_COMMON = 1
|
||||
endif
|
||||
|
||||
ifdef TABLEGEN_INC_FILES_COMMON
|
||||
|
||||
INCFiles := $(filter %.inc,$(BUILT_SOURCES))
|
||||
@ -1717,87 +1701,87 @@ TDFiles := $(strip $(wildcard $(PROJ_SRC_DIR)/*.td) \
|
||||
$(LLVM_SRC_ROOT)/include/llvm/CodeGen/ValueTypes.td) \
|
||||
$(wildcard $(LLVM_SRC_ROOT)/include/llvm/Intrinsics*.td)
|
||||
|
||||
# All of these files depend on tblgen and the .td files.
|
||||
$(INCTMPFiles) : $(TBLGEN) $(TDFiles)
|
||||
# All .inc.tmp files depend on the .td files.
|
||||
$(INCTMPFiles) : $(TDFiles)
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenRegisterInfo.inc.tmp): \
|
||||
$(ObjDir)/%GenRegisterInfo.inc.tmp : %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenRegisterInfo.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) register info implementation with tblgen"
|
||||
$(Verb) $(TableGen) -gen-register-info -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-register-info -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenInstrInfo.inc.tmp): \
|
||||
$(ObjDir)/%GenInstrInfo.inc.tmp : %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenInstrInfo.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) instruction information with tblgen"
|
||||
$(Verb) $(TableGen) -gen-instr-info -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-instr-info -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenAsmWriter.inc.tmp): \
|
||||
$(ObjDir)/%GenAsmWriter.inc.tmp : %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenAsmWriter.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) assembly writer with tblgen"
|
||||
$(Verb) $(TableGen) -gen-asm-writer -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-asm-writer -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenAsmWriter1.inc.tmp): \
|
||||
$(ObjDir)/%GenAsmWriter1.inc.tmp : %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenAsmWriter1.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) assembly writer #1 with tblgen"
|
||||
$(Verb) $(TableGen) -gen-asm-writer -asmwriternum=1 -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-asm-writer -asmwriternum=1 -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenAsmMatcher.inc.tmp): \
|
||||
$(ObjDir)/%GenAsmMatcher.inc.tmp : %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenAsmMatcher.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) assembly matcher with tblgen"
|
||||
$(Verb) $(TableGen) -gen-asm-matcher -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-asm-matcher -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenMCCodeEmitter.inc.tmp): \
|
||||
$(ObjDir)/%GenMCCodeEmitter.inc.tmp: %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenMCCodeEmitter.inc.tmp: %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) MC code emitter with tblgen"
|
||||
$(Verb) $(TableGen) -gen-emitter -mc-emitter -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-emitter -mc-emitter -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenMCPseudoLowering.inc.tmp): \
|
||||
$(ObjDir)/%GenMCPseudoLowering.inc.tmp: %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenMCPseudoLowering.inc.tmp: %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) MC Pseudo instruction expander with tblgen"
|
||||
$(Verb) $(TableGen) -gen-pseudo-lowering -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-pseudo-lowering -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenCodeEmitter.inc.tmp): \
|
||||
$(ObjDir)/%GenCodeEmitter.inc.tmp: %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenCodeEmitter.inc.tmp: %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) code emitter with tblgen"
|
||||
$(Verb) $(TableGen) -gen-emitter -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-emitter -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenDAGISel.inc.tmp): \
|
||||
$(ObjDir)/%GenDAGISel.inc.tmp : %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenDAGISel.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) DAG instruction selector implementation with tblgen"
|
||||
$(Verb) $(TableGen) -gen-dag-isel -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-dag-isel -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenDisassemblerTables.inc.tmp): \
|
||||
$(ObjDir)/%GenDisassemblerTables.inc.tmp : %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenDisassemblerTables.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) disassembly tables with tblgen"
|
||||
$(Verb) $(TableGen) -gen-disassembler -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-disassembler -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenEDInfo.inc.tmp): \
|
||||
$(ObjDir)/%GenEDInfo.inc.tmp : %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenEDInfo.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) enhanced disassembly information with tblgen"
|
||||
$(Verb) $(TableGen) -gen-enhanced-disassembly-info -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-enhanced-disassembly-info -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenFastISel.inc.tmp): \
|
||||
$(ObjDir)/%GenFastISel.inc.tmp : %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenFastISel.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) \"fast\" instruction selector implementation with tblgen"
|
||||
$(Verb) $(TableGen) -gen-fast-isel -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-fast-isel -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenSubtargetInfo.inc.tmp): \
|
||||
$(ObjDir)/%GenSubtargetInfo.inc.tmp : %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenSubtargetInfo.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) subtarget information with tblgen"
|
||||
$(Verb) $(TableGen) -gen-subtarget -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-subtarget -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenCallingConv.inc.tmp): \
|
||||
$(ObjDir)/%GenCallingConv.inc.tmp : %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenCallingConv.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) calling convention information with tblgen"
|
||||
$(Verb) $(TableGen) -gen-callingconv -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-callingconv -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(TARGET:%=$(ObjDir)/%GenIntrinsics.inc.tmp): \
|
||||
$(ObjDir)/%GenIntrinsics.inc.tmp : %.td $(ObjDir)/.dir
|
||||
$(ObjDir)/%GenIntrinsics.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) intrinsics information with tblgen"
|
||||
$(Verb) $(TableGen) -gen-tgt-intrinsic -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-tgt-intrinsic -o $(call SYSPATH, $@) $<
|
||||
|
||||
$(ObjDir)/ARMGenDecoderTables.inc.tmp : ARM.td $(ObjDir)/.dir
|
||||
$(ObjDir)/ARMGenDecoderTables.inc.tmp : ARM.td $(ObjDir)/.dir $(LLVM_TBLGEN)
|
||||
$(Echo) "Building $(<F) decoder tables with tblgen"
|
||||
$(Verb) $(TableGen) -gen-arm-decoder -o $(call SYSPATH, $@) $<
|
||||
$(Verb) $(LLVMTableGen) -gen-arm-decoder -o $(call SYSPATH, $@) $<
|
||||
|
||||
|
||||
clean-local::
|
||||
@ -1805,27 +1789,6 @@ clean-local::
|
||||
|
||||
endif # TARGET
|
||||
|
||||
ifdef LLVMC_BASED_DRIVER
|
||||
|
||||
TDSrc := $(sort $(strip $(wildcard $(PROJ_SRC_DIR)/*.td)) \
|
||||
$(strip $(wildcard $(PROJ_OBJ_DIR)/*.td)))
|
||||
|
||||
TDCommon := $(strip $(wildcard \
|
||||
$(LLVM_SRC_ROOT)/include/llvm/CompilerDriver/*.td))
|
||||
|
||||
TDFiles := $(TDSrc) $(TDCommon)
|
||||
|
||||
$(INCTMPFiles) : $(TBLGEN) $(TDFiles)
|
||||
|
||||
$(ObjDir)/%.inc.tmp: %.td $(ObjDir)/.dir
|
||||
$(Echo) "Building LLVMC compilation graph description with tblgen"
|
||||
$(Verb) $(TableGen) -gen-llvmc -o $(call SYSPATH, $@) $<
|
||||
|
||||
clean-local::
|
||||
-$(Verb) $(RM) -f $(INCFiles)
|
||||
|
||||
endif # LLVMC_BASED_DRIVER
|
||||
|
||||
###############################################################################
|
||||
# OTHER RULES: Other rules needed
|
||||
###############################################################################
|
||||
|
@ -13,4 +13,3 @@ assistance with LLVM.
|
||||
|
||||
If you're writing a package for LLVM, see docs/Packaging.html for our
|
||||
suggestions.
|
||||
|
||||
|
@ -14,9 +14,9 @@ clean() {
|
||||
### Periods should be escaped with backslash for use by grep.
|
||||
###
|
||||
### If you update these, please also update docs/GettingStarted.html
|
||||
want_autoconf_version='2\.60'
|
||||
want_autoconf_version='2\.61'
|
||||
want_autoheader_version=$want_autoconf_version
|
||||
want_aclocal_version='1\.9\.6'
|
||||
want_aclocal_version='1\.10'
|
||||
want_libtool_version='1\.5\.22'
|
||||
### END NOTE #########################################################
|
||||
|
||||
|
249
autoconf/config.guess
vendored
249
autoconf/config.guess
vendored
@ -1,10 +1,10 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
# Free Software Foundation, Inc.
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
# 2011 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2009-09-18'
|
||||
timestamp='2011-08-20'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@ -56,8 +56,9 @@ version="\
|
||||
GNU config.guess ($timestamp)
|
||||
|
||||
Originally written by Per Bothner.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@ -180,7 +181,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
os=netbsd
|
||||
os=netbsd
|
||||
;;
|
||||
esac
|
||||
# The OS release
|
||||
@ -223,7 +224,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
|
||||
;;
|
||||
*5.*)
|
||||
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
|
||||
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
|
||||
;;
|
||||
esac
|
||||
# According to Compaq, /usr/sbin/psrinfo has been available on
|
||||
@ -269,7 +270,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
# A Xn.n version is an unreleased experimental baselevel.
|
||||
# 1.2 uses "1.2" for uname -r.
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
exit ;;
|
||||
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
|
||||
exitcode=$?
|
||||
trap '' 0
|
||||
exit $exitcode ;;
|
||||
Alpha\ *:Windows_NT*:*)
|
||||
# How do we know it's Interix rather than the generic POSIX subsystem?
|
||||
# Should we change UNAME_MACHINE based on the output of uname instead
|
||||
@ -295,7 +299,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
echo s390-ibm-zvmoe
|
||||
exit ;;
|
||||
*:OS400:*:*)
|
||||
echo powerpc-ibm-os400
|
||||
echo powerpc-ibm-os400
|
||||
exit ;;
|
||||
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
|
||||
echo arm-acorn-riscix${UNAME_RELEASE}
|
||||
@ -334,8 +338,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
exit ;;
|
||||
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
|
||||
AUX_ARCH="i386"
|
||||
echo ${AUX_ARCH}-pc-auroraux`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
echo i386-pc-auroraux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
|
||||
eval $set_cc_for_build
|
||||
@ -395,23 +398,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
# MiNT. But MiNT is downward compatible to TOS, so this should
|
||||
# be no problem.
|
||||
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
|
||||
echo m68k-atari-mint${UNAME_RELEASE}
|
||||
echo m68k-atari-mint${UNAME_RELEASE}
|
||||
exit ;;
|
||||
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
|
||||
echo m68k-atari-mint${UNAME_RELEASE}
|
||||
exit ;;
|
||||
exit ;;
|
||||
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
|
||||
echo m68k-atari-mint${UNAME_RELEASE}
|
||||
echo m68k-atari-mint${UNAME_RELEASE}
|
||||
exit ;;
|
||||
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
|
||||
echo m68k-milan-mint${UNAME_RELEASE}
|
||||
exit ;;
|
||||
echo m68k-milan-mint${UNAME_RELEASE}
|
||||
exit ;;
|
||||
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
|
||||
echo m68k-hades-mint${UNAME_RELEASE}
|
||||
exit ;;
|
||||
echo m68k-hades-mint${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
|
||||
echo m68k-unknown-mint${UNAME_RELEASE}
|
||||
exit ;;
|
||||
echo m68k-unknown-mint${UNAME_RELEASE}
|
||||
exit ;;
|
||||
m68k:machten:*:*)
|
||||
echo m68k-apple-machten${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@ -481,8 +484,8 @@ EOF
|
||||
echo m88k-motorola-sysv3
|
||||
exit ;;
|
||||
AViiON:dgux:*:*)
|
||||
# DG/UX returns AViiON for all architectures
|
||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||
# DG/UX returns AViiON for all architectures
|
||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
|
||||
then
|
||||
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
|
||||
@ -495,7 +498,7 @@ EOF
|
||||
else
|
||||
echo i586-dg-dgux${UNAME_RELEASE}
|
||||
fi
|
||||
exit ;;
|
||||
exit ;;
|
||||
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
|
||||
echo m88k-dolphin-sysv3
|
||||
exit ;;
|
||||
@ -552,7 +555,7 @@ EOF
|
||||
echo rs6000-ibm-aix3.2
|
||||
fi
|
||||
exit ;;
|
||||
*:AIX:*:[456])
|
||||
*:AIX:*:[4567])
|
||||
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
|
||||
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
|
||||
IBM_ARCH=rs6000
|
||||
@ -595,52 +598,52 @@ EOF
|
||||
9000/[678][0-9][0-9])
|
||||
if [ -x /usr/bin/getconf ]; then
|
||||
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
|
||||
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
|
||||
case "${sc_cpu_version}" in
|
||||
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
|
||||
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
|
||||
532) # CPU_PA_RISC2_0
|
||||
case "${sc_kernel_bits}" in
|
||||
32) HP_ARCH="hppa2.0n" ;;
|
||||
64) HP_ARCH="hppa2.0w" ;;
|
||||
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
|
||||
case "${sc_cpu_version}" in
|
||||
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
|
||||
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
|
||||
532) # CPU_PA_RISC2_0
|
||||
case "${sc_kernel_bits}" in
|
||||
32) HP_ARCH="hppa2.0n" ;;
|
||||
64) HP_ARCH="hppa2.0w" ;;
|
||||
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
|
||||
esac ;;
|
||||
esac
|
||||
esac ;;
|
||||
esac
|
||||
fi
|
||||
if [ "${HP_ARCH}" = "" ]; then
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
|
||||
#define _HPUX_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#define _HPUX_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main ()
|
||||
{
|
||||
#if defined(_SC_KERNEL_BITS)
|
||||
long bits = sysconf(_SC_KERNEL_BITS);
|
||||
#endif
|
||||
long cpu = sysconf (_SC_CPU_VERSION);
|
||||
int main ()
|
||||
{
|
||||
#if defined(_SC_KERNEL_BITS)
|
||||
long bits = sysconf(_SC_KERNEL_BITS);
|
||||
#endif
|
||||
long cpu = sysconf (_SC_CPU_VERSION);
|
||||
|
||||
switch (cpu)
|
||||
{
|
||||
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
|
||||
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
|
||||
case CPU_PA_RISC2_0:
|
||||
#if defined(_SC_KERNEL_BITS)
|
||||
switch (bits)
|
||||
{
|
||||
case 64: puts ("hppa2.0w"); break;
|
||||
case 32: puts ("hppa2.0n"); break;
|
||||
default: puts ("hppa2.0"); break;
|
||||
} break;
|
||||
#else /* !defined(_SC_KERNEL_BITS) */
|
||||
puts ("hppa2.0"); break;
|
||||
#endif
|
||||
default: puts ("hppa1.0"); break;
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
switch (cpu)
|
||||
{
|
||||
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
|
||||
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
|
||||
case CPU_PA_RISC2_0:
|
||||
#if defined(_SC_KERNEL_BITS)
|
||||
switch (bits)
|
||||
{
|
||||
case 64: puts ("hppa2.0w"); break;
|
||||
case 32: puts ("hppa2.0n"); break;
|
||||
default: puts ("hppa2.0"); break;
|
||||
} break;
|
||||
#else /* !defined(_SC_KERNEL_BITS) */
|
||||
puts ("hppa2.0"); break;
|
||||
#endif
|
||||
default: puts ("hppa1.0"); break;
|
||||
}
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
|
||||
test -z "$HP_ARCH" && HP_ARCH=hppa
|
||||
@ -731,22 +734,22 @@ EOF
|
||||
exit ;;
|
||||
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
|
||||
echo c1-convex-bsd
|
||||
exit ;;
|
||||
exit ;;
|
||||
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
|
||||
if getsysinfo -f scalar_acc
|
||||
then echo c32-convex-bsd
|
||||
else echo c2-convex-bsd
|
||||
fi
|
||||
exit ;;
|
||||
exit ;;
|
||||
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
|
||||
echo c34-convex-bsd
|
||||
exit ;;
|
||||
exit ;;
|
||||
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
|
||||
echo c38-convex-bsd
|
||||
exit ;;
|
||||
exit ;;
|
||||
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
|
||||
echo c4-convex-bsd
|
||||
exit ;;
|
||||
exit ;;
|
||||
CRAY*Y-MP:*:*:*)
|
||||
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit ;;
|
||||
@ -770,14 +773,14 @@ EOF
|
||||
exit ;;
|
||||
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
|
||||
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
||||
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit ;;
|
||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
||||
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit ;;
|
||||
5000:UNIX_System_V:4.*:*)
|
||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
|
||||
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
|
||||
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit ;;
|
||||
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
|
||||
@ -789,8 +792,8 @@ EOF
|
||||
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:FreeBSD:*:*)
|
||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||
case ${UNAME_MACHINE} in
|
||||
UNAME_PROCESSOR=`/usr/bin/uname -p`
|
||||
case ${UNAME_PROCESSOR} in
|
||||
amd64)
|
||||
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
|
||||
*)
|
||||
@ -804,18 +807,18 @@ EOF
|
||||
echo ${UNAME_MACHINE}-pc-mingw32
|
||||
exit ;;
|
||||
i*:windows32*:*)
|
||||
# uname -m includes "-pc" on this system.
|
||||
echo ${UNAME_MACHINE}-mingw32
|
||||
# uname -m includes "-pc" on this system.
|
||||
echo ${UNAME_MACHINE}-mingw32
|
||||
exit ;;
|
||||
i*:PW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-pw32
|
||||
exit ;;
|
||||
*:Interix*:[3456]*)
|
||||
case ${UNAME_MACHINE} in
|
||||
*:Interix*:*)
|
||||
case ${UNAME_MACHINE} in
|
||||
x86)
|
||||
echo i586-pc-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
EM64T | authenticamd | genuineintel)
|
||||
authenticamd | genuineintel | EM64T)
|
||||
echo x86_64-unknown-interix${UNAME_RELEASE}
|
||||
exit ;;
|
||||
IA64)
|
||||
@ -866,7 +869,7 @@ EOF
|
||||
EV6) UNAME_MACHINE=alphaev6 ;;
|
||||
EV67) UNAME_MACHINE=alphaev67 ;;
|
||||
EV68*) UNAME_MACHINE=alphaev68 ;;
|
||||
esac
|
||||
esac
|
||||
objdump --private-headers /bin/sh | grep -q ld.so.1
|
||||
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
|
||||
@ -878,7 +881,13 @@ EOF
|
||||
then
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
else
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnueabi
|
||||
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep -q __ARM_PCS_VFP
|
||||
then
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnueabi
|
||||
else
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
|
||||
fi
|
||||
fi
|
||||
exit ;;
|
||||
avr32*:Linux:*:*)
|
||||
@ -891,10 +900,18 @@ EOF
|
||||
echo crisv32-axis-linux-gnu
|
||||
exit ;;
|
||||
frv:Linux:*:*)
|
||||
echo frv-unknown-linux-gnu
|
||||
echo frv-unknown-linux-gnu
|
||||
exit ;;
|
||||
i*86:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-linux-gnu
|
||||
LIBC=gnu
|
||||
eval $set_cc_for_build
|
||||
sed 's/^ //' << EOF >$dummy.c
|
||||
#ifdef __dietlibc__
|
||||
LIBC=dietlibc
|
||||
#endif
|
||||
EOF
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
|
||||
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
|
||||
exit ;;
|
||||
ia64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
@ -921,11 +938,7 @@ EOF
|
||||
#endif
|
||||
#endif
|
||||
EOF
|
||||
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
|
||||
/^CPU/{
|
||||
s: ::g
|
||||
p
|
||||
}'`"
|
||||
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
|
||||
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
|
||||
;;
|
||||
or32:Linux:*:*)
|
||||
@ -955,7 +968,7 @@ EOF
|
||||
echo ${UNAME_MACHINE}-ibm-linux
|
||||
exit ;;
|
||||
sh64*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit ;;
|
||||
sh*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
@ -963,6 +976,9 @@ EOF
|
||||
sparc:Linux:*:* | sparc64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit ;;
|
||||
tile*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit ;;
|
||||
vax:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-dec-linux-gnu
|
||||
exit ;;
|
||||
@ -970,7 +986,7 @@ EOF
|
||||
echo x86_64-unknown-linux-gnu
|
||||
exit ;;
|
||||
xtensa*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
echo ${UNAME_MACHINE}-unknown-linux-gnu
|
||||
exit ;;
|
||||
i*86:DYNIX/ptx:4*:*)
|
||||
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
|
||||
@ -979,11 +995,11 @@ EOF
|
||||
echo i386-sequent-sysv4
|
||||
exit ;;
|
||||
i*86:UNIX_SV:4.2MP:2.*)
|
||||
# Unixware is an offshoot of SVR4, but it has its own version
|
||||
# number series starting with 2...
|
||||
# I am not positive that other SVR4 systems won't match this,
|
||||
# Unixware is an offshoot of SVR4, but it has its own version
|
||||
# number series starting with 2...
|
||||
# I am not positive that other SVR4 systems won't match this,
|
||||
# I just have to hope. -- rms.
|
||||
# Use sysv4.2uw... so that sysv4* matches it.
|
||||
# Use sysv4.2uw... so that sysv4* matches it.
|
||||
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
|
||||
exit ;;
|
||||
i*86:OS/2:*:*)
|
||||
@ -1015,7 +1031,7 @@ EOF
|
||||
fi
|
||||
exit ;;
|
||||
i*86:*:5:[678]*)
|
||||
# UnixWare 7.x, OpenUNIX and OpenServer 6.
|
||||
# UnixWare 7.x, OpenUNIX and OpenServer 6.
|
||||
case `/bin/uname -X | grep "^Machine"` in
|
||||
*486*) UNAME_MACHINE=i486 ;;
|
||||
*Pentium) UNAME_MACHINE=i586 ;;
|
||||
@ -1043,13 +1059,13 @@ EOF
|
||||
exit ;;
|
||||
pc:*:*:*)
|
||||
# Left here for compatibility:
|
||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||
# the processor, so we play safe by assuming i586.
|
||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||
# the processor, so we play safe by assuming i586.
|
||||
# Note: whatever this is, it MUST be the same as what config.sub
|
||||
# prints for the "djgpp" host, or else GDB configury will decide that
|
||||
# this is a cross-build.
|
||||
echo i586-pc-msdosdjgpp
|
||||
exit ;;
|
||||
exit ;;
|
||||
Intel:Mach:3*:*)
|
||||
echo i386-pc-mach3
|
||||
exit ;;
|
||||
@ -1084,8 +1100,8 @@ EOF
|
||||
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
|
||||
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
|
||||
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
|
||||
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& { echo i486-ncr-sysv4; exit; } ;;
|
||||
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
|
||||
&& { echo i486-ncr-sysv4; exit; } ;;
|
||||
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
|
||||
OS_REL='.3'
|
||||
test -r /etc/.relid \
|
||||
@ -1128,10 +1144,10 @@ EOF
|
||||
echo ns32k-sni-sysv
|
||||
fi
|
||||
exit ;;
|
||||
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
|
||||
# says <Richard.M.Bartel@ccMail.Census.GOV>
|
||||
echo i586-unisys-sysv4
|
||||
exit ;;
|
||||
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
|
||||
# says <Richard.M.Bartel@ccMail.Census.GOV>
|
||||
echo i586-unisys-sysv4
|
||||
exit ;;
|
||||
*:UNIX_System_V:4*:FTX*)
|
||||
# From Gerald Hewes <hewes@openmarket.com>.
|
||||
# How about differentiating between stratus architectures? -djm
|
||||
@ -1157,11 +1173,11 @@ EOF
|
||||
exit ;;
|
||||
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
|
||||
if [ -d /usr/nec ]; then
|
||||
echo mips-nec-sysv${UNAME_RELEASE}
|
||||
echo mips-nec-sysv${UNAME_RELEASE}
|
||||
else
|
||||
echo mips-unknown-sysv${UNAME_RELEASE}
|
||||
echo mips-unknown-sysv${UNAME_RELEASE}
|
||||
fi
|
||||
exit ;;
|
||||
exit ;;
|
||||
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
|
||||
echo powerpc-be-beos
|
||||
exit ;;
|
||||
@ -1226,6 +1242,9 @@ EOF
|
||||
*:QNX:*:4*)
|
||||
echo i386-pc-qnx
|
||||
exit ;;
|
||||
NEO-?:NONSTOP_KERNEL:*:*)
|
||||
echo neo-tandem-nsk${UNAME_RELEASE}
|
||||
exit ;;
|
||||
NSE-?:NONSTOP_KERNEL:*:*)
|
||||
echo nse-tandem-nsk${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@ -1271,13 +1290,13 @@ EOF
|
||||
echo pdp10-unknown-its
|
||||
exit ;;
|
||||
SEI:*:*:SEIUX)
|
||||
echo mips-sei-seiux${UNAME_RELEASE}
|
||||
echo mips-sei-seiux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:DragonFly:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
|
||||
exit ;;
|
||||
*:*VMS:*:*)
|
||||
UNAME_MACHINE=`(uname -p) 2>/dev/null`
|
||||
UNAME_MACHINE=`(uname -p) 2>/dev/null`
|
||||
case "${UNAME_MACHINE}" in
|
||||
A*) echo alpha-dec-vms ; exit ;;
|
||||
I*) echo ia64-dec-vms ; exit ;;
|
||||
@ -1317,11 +1336,11 @@ main ()
|
||||
#include <sys/param.h>
|
||||
printf ("m68k-sony-newsos%s\n",
|
||||
#ifdef NEWSOS4
|
||||
"4"
|
||||
"4"
|
||||
#else
|
||||
""
|
||||
""
|
||||
#endif
|
||||
); exit (0);
|
||||
); exit (0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
186
autoconf/config.sub
vendored
186
autoconf/config.sub
vendored
@ -1,10 +1,10 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
||||
# Free Software Foundation, Inc.
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
# 2011 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2009-08-19'
|
||||
timestamp='2011-08-23'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
@ -75,8 +75,9 @@ Report bugs and patches to <config-patches@gnu.org>."
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free
|
||||
Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@ -123,8 +124,9 @@ esac
|
||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
|
||||
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
||||
linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
kopensolaris*-gnu* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
@ -156,8 +158,8 @@ case $os in
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
-bluegene*)
|
||||
os=-cnk
|
||||
-bluegene*)
|
||||
os=-cnk
|
||||
;;
|
||||
-sim | -cisco | -oki | -wec | -winbond)
|
||||
os=
|
||||
@ -173,10 +175,10 @@ case $os in
|
||||
os=-chorusos
|
||||
basic_machine=$1
|
||||
;;
|
||||
-chorusrdb)
|
||||
os=-chorusrdb
|
||||
-chorusrdb)
|
||||
os=-chorusrdb
|
||||
basic_machine=$1
|
||||
;;
|
||||
;;
|
||||
-hiux*)
|
||||
os=-hiuxwe2
|
||||
;;
|
||||
@ -249,6 +251,7 @@ case $basic_machine in
|
||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||
| am33_2.0 \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
|
||||
| be32 | be64 \
|
||||
| bfin \
|
||||
| c4x | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
@ -256,6 +259,7 @@ case $basic_machine in
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| le32 | le64 \
|
||||
| lm32 \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
| maxq | mb | microblaze | mcore | mep | metag \
|
||||
@ -281,26 +285,39 @@ case $basic_machine in
|
||||
| moxie \
|
||||
| mt \
|
||||
| msp430 \
|
||||
| nds32 | nds32le | nds32be \
|
||||
| nios | nios2 \
|
||||
| ns16k | ns32k \
|
||||
| open8 \
|
||||
| or32 \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle \
|
||||
| pyramid \
|
||||
| rx \
|
||||
| score \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||
| spu | strongarm \
|
||||
| tahoe | thumb | tic4x | tic80 | tron \
|
||||
| v850 | v850e \
|
||||
| spu \
|
||||
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
|
||||
| ubicom32 \
|
||||
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
|
||||
| we32k \
|
||||
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
|
||||
| x86 | xc16x | xstormy16 | xtensa \
|
||||
| z8k | z80)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12)
|
||||
c54x)
|
||||
basic_machine=tic54x-unknown
|
||||
;;
|
||||
c55x)
|
||||
basic_machine=tic55x-unknown
|
||||
;;
|
||||
c6x)
|
||||
basic_machine=tic6x-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12 | picochip)
|
||||
# Motorola 68HC11/12.
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
@ -311,6 +328,18 @@ case $basic_machine in
|
||||
basic_machine=mt-unknown
|
||||
;;
|
||||
|
||||
strongarm | thumb | xscale)
|
||||
basic_machine=arm-unknown
|
||||
;;
|
||||
|
||||
xscaleeb)
|
||||
basic_machine=armeb-unknown
|
||||
;;
|
||||
|
||||
xscaleel)
|
||||
basic_machine=armel-unknown
|
||||
;;
|
||||
|
||||
# We use `pc' rather than `unknown'
|
||||
# because (1) that's what they normally are, and
|
||||
# (2) the word "unknown" tends to confuse beginning users.
|
||||
@ -330,8 +359,9 @@ case $basic_machine in
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* | avr32-* \
|
||||
| be32-* | be64-* \
|
||||
| bfin-* | bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
||||
| clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
@ -340,6 +370,7 @@ case $basic_machine in
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| le32-* | le64-* \
|
||||
| lm32-* \
|
||||
| m32c-* | m32r-* | m32rle-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
@ -365,24 +396,29 @@ case $basic_machine in
|
||||
| mmix-* \
|
||||
| mt-* \
|
||||
| msp430-* \
|
||||
| nds32-* | nds32le-* | nds32be-* \
|
||||
| nios-* | nios2-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| open8-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
||||
| pyramid-* \
|
||||
| romp-* | rs6000-* \
|
||||
| romp-* | rs6000-* | rx-* \
|
||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||
| sparclite-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
|
||||
| tahoe-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tile*-* \
|
||||
| tron-* \
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| ubicom32-* \
|
||||
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
|
||||
| vax-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* \
|
||||
| xstormy16-* | xtensa*-* \
|
||||
| ymp-* \
|
||||
| z8k-* | z80-*)
|
||||
@ -407,7 +443,7 @@ case $basic_machine in
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
abacus)
|
||||
abacus)
|
||||
basic_machine=abacus-unknown
|
||||
;;
|
||||
adobe68k)
|
||||
@ -477,11 +513,20 @@ case $basic_machine in
|
||||
basic_machine=powerpc-ibm
|
||||
os=-cnk
|
||||
;;
|
||||
c54x-*)
|
||||
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c55x-*)
|
||||
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c6x-*)
|
||||
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c90)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
cegcc)
|
||||
cegcc)
|
||||
basic_machine=arm-unknown
|
||||
os=-cegcc
|
||||
;;
|
||||
@ -513,7 +558,7 @@ case $basic_machine in
|
||||
basic_machine=craynv-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
cr16)
|
||||
cr16 | cr16-*)
|
||||
basic_machine=cr16-unknown
|
||||
os=-elf
|
||||
;;
|
||||
@ -729,7 +774,7 @@ case $basic_machine in
|
||||
basic_machine=ns32k-utek
|
||||
os=-sysv
|
||||
;;
|
||||
microblaze)
|
||||
microblaze)
|
||||
basic_machine=microblaze-xilinx
|
||||
;;
|
||||
mingw32)
|
||||
@ -772,6 +817,10 @@ case $basic_machine in
|
||||
basic_machine=i370-ibm
|
||||
os=-mvs
|
||||
;;
|
||||
nacl)
|
||||
basic_machine=le32-unknown
|
||||
os=-nacl
|
||||
;;
|
||||
ncr3000)
|
||||
basic_machine=i486-ncr
|
||||
os=-sysv4
|
||||
@ -836,6 +885,12 @@ case $basic_machine in
|
||||
np1)
|
||||
basic_machine=np1-gould
|
||||
;;
|
||||
neo-tandem)
|
||||
basic_machine=neo-tandem
|
||||
;;
|
||||
nse-tandem)
|
||||
basic_machine=nse-tandem
|
||||
;;
|
||||
nsr-tandem)
|
||||
basic_machine=nsr-tandem
|
||||
;;
|
||||
@ -918,9 +973,10 @@ case $basic_machine in
|
||||
;;
|
||||
power) basic_machine=power-ibm
|
||||
;;
|
||||
ppc) basic_machine=powerpc-unknown
|
||||
ppc | ppcbe) basic_machine=powerpc-unknown
|
||||
;;
|
||||
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
ppc-* | ppcbe-*)
|
||||
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
||||
basic_machine=powerpcle-unknown
|
||||
@ -1014,6 +1070,9 @@ case $basic_machine in
|
||||
basic_machine=i860-stratus
|
||||
os=-sysv4
|
||||
;;
|
||||
strongarm-* | thumb-*)
|
||||
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
sun2)
|
||||
basic_machine=m68000-sun
|
||||
;;
|
||||
@ -1070,20 +1129,8 @@ case $basic_machine in
|
||||
basic_machine=t90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
tic54x | c54x*)
|
||||
basic_machine=tic54x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic55x | c55x*)
|
||||
basic_machine=tic55x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic6x | c6x*)
|
||||
basic_machine=tic6x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tile*)
|
||||
basic_machine=tile-unknown
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
tx39)
|
||||
@ -1153,6 +1200,9 @@ case $basic_machine in
|
||||
xps | xps100)
|
||||
basic_machine=xps100-honeywell
|
||||
;;
|
||||
xscale-* | xscalee[bl]-*)
|
||||
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
|
||||
;;
|
||||
ymp)
|
||||
basic_machine=ymp-cray
|
||||
os=-unicos
|
||||
@ -1250,15 +1300,15 @@ esac
|
||||
if [ x"$os" != x"" ]
|
||||
then
|
||||
case $os in
|
||||
# First match some system type aliases
|
||||
# that might get confused with valid system types.
|
||||
# First match some system type aliases
|
||||
# that might get confused with valid system types.
|
||||
# -solaris* is a basic system type, with this one exception.
|
||||
-solaris1 | -solaris1.*)
|
||||
os=`echo $os | sed -e 's|solaris1|sunos4|'`
|
||||
;;
|
||||
-auroraux)
|
||||
os=-auroraux
|
||||
;;
|
||||
-solaris1 | -solaris1.*)
|
||||
os=`echo $os | sed -e 's|solaris1|sunos4|'`
|
||||
;;
|
||||
-solaris)
|
||||
os=-solaris2
|
||||
;;
|
||||
@ -1277,8 +1327,8 @@ case $os in
|
||||
# -sysv* is not here because it comes later, after sysvr4.
|
||||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* | -sym* \
|
||||
| -kopensolaris* \
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
||||
| -sym* | -kopensolaris* \
|
||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||
| -aos* | -aros* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
@ -1291,7 +1341,8 @@ case $os in
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
|
||||
| -mingw32* | -linux-gnu* | -linux-android* \
|
||||
| -linux-newlib* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
@ -1299,7 +1350,7 @@ case $os in
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@ -1338,7 +1389,7 @@ case $os in
|
||||
-opened*)
|
||||
os=-openedition
|
||||
;;
|
||||
-os400*)
|
||||
-os400*)
|
||||
os=-os400
|
||||
;;
|
||||
-wince*)
|
||||
@ -1387,7 +1438,7 @@ case $os in
|
||||
-sinix*)
|
||||
os=-sysv4
|
||||
;;
|
||||
-tpf*)
|
||||
-tpf*)
|
||||
os=-tpf
|
||||
;;
|
||||
-triton*)
|
||||
@ -1432,6 +1483,8 @@ case $os in
|
||||
-dicos*)
|
||||
os=-dicos
|
||||
;;
|
||||
-nacl*)
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
@ -1454,10 +1507,10 @@ else
|
||||
# system, and we'll never get to this point.
|
||||
|
||||
case $basic_machine in
|
||||
score-*)
|
||||
score-*)
|
||||
os=-elf
|
||||
;;
|
||||
spu-*)
|
||||
spu-*)
|
||||
os=-elf
|
||||
;;
|
||||
*-acorn)
|
||||
@ -1469,8 +1522,17 @@ case $basic_machine in
|
||||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
tic54x-*)
|
||||
os=-coff
|
||||
;;
|
||||
tic55x-*)
|
||||
os=-coff
|
||||
;;
|
||||
tic6x-*)
|
||||
os=-coff
|
||||
;;
|
||||
# This must come before the *-dec entry.
|
||||
pdp10-*)
|
||||
@ -1497,7 +1559,7 @@ case $basic_machine in
|
||||
m68*-cisco)
|
||||
os=-aout
|
||||
;;
|
||||
mep-*)
|
||||
mep-*)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-cisco)
|
||||
@ -1524,7 +1586,7 @@ case $basic_machine in
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
*-knuth)
|
||||
*-knuth)
|
||||
os=-mmixware
|
||||
;;
|
||||
*-wec)
|
||||
|
@ -31,16 +31,15 @@ dnl===
|
||||
dnl===-----------------------------------------------------------------------===
|
||||
dnl Initialize autoconf and define the package name, version number and
|
||||
dnl email address for reporting bugs.
|
||||
AC_INIT([[llvm]],[[3.0svn]],[llvmbugs@cs.uiuc.edu])
|
||||
AC_INIT([[llvm]],[[3.0]],[llvmbugs@cs.uiuc.edu])
|
||||
|
||||
dnl Provide a copyright substitution and ensure the copyright notice is included
|
||||
dnl in the output of --version option of the generated configure script.
|
||||
AC_SUBST(LLVM_COPYRIGHT,["Copyright (c) 2003-2011 University of Illinois at Urbana-Champaign."])
|
||||
AC_COPYRIGHT([Copyright (c) 2003-2011 University of Illinois at Urbana-Champaign.])
|
||||
|
||||
dnl Indicate that we require autoconf 2.59 or later. Ths is needed because we
|
||||
dnl use some autoconf macros only available in 2.59.
|
||||
AC_PREREQ(2.59)
|
||||
dnl Indicate that we require autoconf 2.60 or later.
|
||||
AC_PREREQ(2.60)
|
||||
|
||||
dnl Verify that the source directory is valid. This makes sure that we are
|
||||
dnl configuring LLVM and not some other package (it validates --srcdir argument)
|
||||
@ -58,6 +57,12 @@ if test ${srcdir} != "." ; then
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl We need to check for the compiler up here to avoid anything else
|
||||
dnl starting with a different one.
|
||||
AC_PROG_CC(clang llvm-gcc gcc)
|
||||
AC_PROG_CXX(clang++ llvm-g++ g++)
|
||||
AC_PROG_CPP
|
||||
|
||||
dnl Configure all of the projects present in our source tree. While we could
|
||||
dnl just AC_CONFIG_SUBDIRS on the set of directories in projects that have a
|
||||
dnl configure script, that usage of the AC_CONFIG_SUBDIRS macro is deprecated.
|
||||
@ -299,6 +304,8 @@ AC_CACHE_CHECK([type of operating system we're going to target],
|
||||
llvm_cv_target_os_type="Haiku" ;;
|
||||
*-*-rtems*)
|
||||
llvm_cv_target_os_type="RTEMS" ;;
|
||||
*-*-nacl*)
|
||||
llvm_cv_target_os_type="NativeClient" ;;
|
||||
*-unknown-eabi*)
|
||||
llvm_cv_target_os_type="Freestanding" ;;
|
||||
*)
|
||||
@ -413,7 +420,7 @@ dnl===-----------------------------------------------------------------------===
|
||||
|
||||
dnl --enable-optimized : check whether they want to do an optimized build:
|
||||
AC_ARG_ENABLE(optimized, AS_HELP_STRING(
|
||||
--enable-optimized,[Compile with optimizations enabled (default is NO)]),,enableval=$optimize)
|
||||
--enable-optimized,[Compile with optimizations enabled (default is YES)]),,enableval=$optimize)
|
||||
if test ${enableval} = "no" ; then
|
||||
AC_SUBST(ENABLE_OPTIMIZED,[[]])
|
||||
else
|
||||
@ -431,7 +438,7 @@ fi
|
||||
|
||||
dnl --enable-assertions : check whether they want to turn on assertions or not:
|
||||
AC_ARG_ENABLE(assertions,AS_HELP_STRING(
|
||||
--enable-assertions,[Compile with assertion checks enabled (default is YES)]),, enableval="yes")
|
||||
--enable-assertions,[Compile with assertion checks enabled (default is NO)]),, enableval="no")
|
||||
if test ${enableval} = "yes" ; then
|
||||
AC_SUBST(DISABLE_ASSERTIONS,[[]])
|
||||
else
|
||||
@ -484,7 +491,7 @@ else
|
||||
x86_64) AC_SUBST(TARGET_HAS_JIT,1) ;;
|
||||
Alpha) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
ARM) AC_SUBST(TARGET_HAS_JIT,1) ;;
|
||||
Mips) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
Mips) AC_SUBST(TARGET_HAS_JIT,1) ;;
|
||||
XCore) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
SystemZ) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
@ -573,12 +580,12 @@ esac
|
||||
dnl Allow libstdc++ is embedded in LLVM.dll.
|
||||
AC_ARG_ENABLE(embed-stdcxx,
|
||||
AS_HELP_STRING([--enable-embed-stdcxx],
|
||||
[Build a shared library with embedded libstdc++ for Win32 DLL (default is YES)]),,
|
||||
[Build a shared library with embedded libstdc++ for Win32 DLL (default is NO)]),,
|
||||
enableval=default)
|
||||
case "$enableval" in
|
||||
yes) AC_SUBST(ENABLE_EMBED_STDCXX,[1]) ;;
|
||||
no) AC_SUBST(ENABLE_EMBED_STDCXX,[0]) ;;
|
||||
default) AC_SUBST(ENABLE_EMBED_STDCXX,[1]) ;;
|
||||
default) AC_SUBST(ENABLE_EMBED_STDCXX,[0]) ;;
|
||||
*) AC_MSG_ERROR([Invalid setting for --enable-embed-stdcxx. Use "yes" or "no"]) ;;
|
||||
esac
|
||||
|
||||
@ -658,7 +665,7 @@ for a_target in $TARGETS_TO_BUILD; do
|
||||
[LLVM architecture name for the native architecture, if available])
|
||||
LLVM_NATIVE_TARGET="LLVMInitialize${LLVM_NATIVE_ARCH}Target"
|
||||
LLVM_NATIVE_TARGETINFO="LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo"
|
||||
LLVM_NATIVE_MCASMINFO="LLVMInitialize${LLVM_NATIVE_ARCH}MCAsmInfo"
|
||||
LLVM_NATIVE_TARGETMC="LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC"
|
||||
LLVM_NATIVE_ASMPRINTER="LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter"
|
||||
if test -f ${srcdir}/lib/Target/${LLVM_NATIVE_ARCH}/AsmParser/Makefile ; then
|
||||
LLVM_NATIVE_ASMPARSER="LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser"
|
||||
@ -667,8 +674,8 @@ for a_target in $TARGETS_TO_BUILD; do
|
||||
[LLVM name for the native Target init function, if available])
|
||||
AC_DEFINE_UNQUOTED(LLVM_NATIVE_TARGETINFO, $LLVM_NATIVE_TARGETINFO,
|
||||
[LLVM name for the native TargetInfo init function, if available])
|
||||
AC_DEFINE_UNQUOTED(LLVM_NATIVE_MCASMINFO, $LLVM_NATIVE_MCASMINFO,
|
||||
[LLVM name for the native MCAsmInfo init function, if available])
|
||||
AC_DEFINE_UNQUOTED(LLVM_NATIVE_TARGETMC, $LLVM_NATIVE_TARGETMC,
|
||||
[LLVM name for the native target MC init function, if available])
|
||||
AC_DEFINE_UNQUOTED(LLVM_NATIVE_ASMPRINTER, $LLVM_NATIVE_ASMPRINTER,
|
||||
[LLVM name for the native AsmPrinter init function, if available])
|
||||
if test -f ${srcdir}/lib/Target/${LLVM_NATIVE_ARCH}/AsmParser/Makefile ; then
|
||||
@ -716,97 +723,6 @@ esac
|
||||
AC_DEFINE_UNQUOTED([ENABLE_CBE_PRINTF_A],$ENABLE_CBE_PRINTF_A,
|
||||
[Define if CBE is enabled for printf %a output])
|
||||
|
||||
dnl Allow a specific llvm-gcc/llvm-g++ pair to be used with this LLVM config.
|
||||
AC_ARG_WITH(llvmgccdir,
|
||||
AS_HELP_STRING([--with-llvmgccdir],
|
||||
[Specify location of llvm-gcc install dir (default searches PATH)]),,
|
||||
withval=default)
|
||||
case "$withval" in
|
||||
default) WITH_LLVMGCCDIR=default ;;
|
||||
/* | [[A-Za-z]]:[[\\/]]*) WITH_LLVMGCCDIR=$withval ;;
|
||||
*) AC_MSG_ERROR([Invalid path for --with-llvmgccdir. Provide full path]) ;;
|
||||
esac
|
||||
|
||||
dnl Allow a specific llvm-gcc compiler to be used with this LLVM config.
|
||||
AC_ARG_WITH(llvmgcc,
|
||||
AS_HELP_STRING([--with-llvmgcc],
|
||||
[Specify location of llvm-gcc driver (default searches PATH)]),
|
||||
LLVMGCC=$with_llvmgcc
|
||||
WITH_LLVMGCCDIR="",)
|
||||
|
||||
dnl Allow a specific llvm-g++ compiler to be used with this LLVM config.
|
||||
AC_ARG_WITH(llvmgxx,
|
||||
AS_HELP_STRING([--with-llvmgxx],
|
||||
[Specify location of llvm-g++ driver (default searches PATH)]),
|
||||
LLVMGXX=$with_llvmgxx
|
||||
WITH_LLVMGCCDIR="",)
|
||||
|
||||
if test -n "$LLVMGCC"; then
|
||||
LLVMGCCCOMMAND="$LLVMGCC"
|
||||
fi
|
||||
|
||||
if test -n "$LLVMGXX"; then
|
||||
LLVMGXXCOMMAND="$LLVMGXX"
|
||||
fi
|
||||
|
||||
if test -n "$LLVMGCC" && test -z "$LLVMGXX"; then
|
||||
AC_MSG_ERROR([Invalid llvm-g++. Use --with-llvmgxx when --with-llvmgcc is used]);
|
||||
fi
|
||||
|
||||
if test -n "$LLVMGXX" && test -z "$LLVMGCC"; then
|
||||
AC_MSG_ERROR([Invalid llvm-gcc. Use --with-llvmgcc when --with-llvmgxx is used]);
|
||||
fi
|
||||
|
||||
dnl Allow a specific Clang compiler to be used with this LLVM config.
|
||||
AC_ARG_WITH(clang,
|
||||
AS_HELP_STRING([--with-clang],
|
||||
[Specify location of clang compiler (default is --with-built-clang)]),
|
||||
[],[with_clang=default])
|
||||
|
||||
dnl Enable use of the built Clang.
|
||||
AC_ARG_WITH(built-clang,
|
||||
AS_HELP_STRING([--with-built-clang],
|
||||
[Use the compiled Clang as the LLVM compiler (default=check)]),
|
||||
[],[with_built_clang=check])
|
||||
|
||||
dnl Select the Clang compiler option.
|
||||
dnl
|
||||
dnl If --with-clang is given, always honor that; otherwise honor
|
||||
dnl --with-built-clang, or check if we have the clang sources.
|
||||
AC_MSG_CHECKING([clang compiler])
|
||||
WITH_CLANGPATH=""
|
||||
WITH_BUILT_CLANG=0
|
||||
if test "$with_clang" != "default"; then
|
||||
WITH_CLANGPATH="$with_clang"
|
||||
if ! test -x "$WITH_CLANGPATH"; then
|
||||
AC_MSG_ERROR([invalid --with-clang, path does not specify an executable])
|
||||
fi
|
||||
elif test "$with_built_clang" = "yes"; then
|
||||
WITH_BUILT_CLANG=1
|
||||
elif test "$with_built_clang" = "no"; then
|
||||
WITH_BUILT_CLANG=0
|
||||
else
|
||||
if test "$with_built_clang" != "check"; then
|
||||
AC_MSG_ERROR([invalid value for --with-built-clang.])
|
||||
fi
|
||||
|
||||
if test -f ${srcdir}/tools/clang/README.txt; then
|
||||
WITH_BUILT_CLANG=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! test -z "$WITH_CLANGPATH"; then
|
||||
AC_MSG_RESULT([$WITH_CLANGPATH])
|
||||
WITH_CLANGXXPATH=`"$WITH_CLANGPATH" --print-prog-name=clang++`
|
||||
elif test "$WITH_BUILT_CLANG" = "1"; then
|
||||
AC_MSG_RESULT([built])
|
||||
else
|
||||
AC_MSG_RESULT([none])
|
||||
fi
|
||||
AC_SUBST(CLANGPATH,$WITH_CLANGPATH)
|
||||
AC_SUBST(CLANGXXPATH,$WITH_CLANGXXPATH)
|
||||
AC_SUBST(ENABLE_BUILT_CLANG,$WITH_BUILT_CLANG)
|
||||
|
||||
dnl Override the option to use for optimized builds.
|
||||
AC_ARG_WITH(optimize-option,
|
||||
AS_HELP_STRING([--with-optimize-option],
|
||||
@ -942,8 +858,8 @@ fi
|
||||
dnl Specify the URL where bug reports should be submitted.
|
||||
AC_ARG_WITH(bug-report-url,
|
||||
AS_HELP_STRING([--with-bug-report-url],
|
||||
[Specify the URL where bug reports should be submitted (default=http://llvm.org)]),,
|
||||
withval="http://llvm.org")
|
||||
[Specify the URL where bug reports should be submitted (default=http://llvm.org/bugs/)]),,
|
||||
withval="http://llvm.org/bugs/")
|
||||
AC_DEFINE_UNQUOTED(BUG_REPORT_URL,"$withval",
|
||||
[Bug report URL.])
|
||||
|
||||
@ -963,11 +879,6 @@ dnl=== SECTION 4: Check for programs we need and that they are the right version
|
||||
dnl===
|
||||
dnl===-----------------------------------------------------------------------===
|
||||
|
||||
dnl Check for compilation tools
|
||||
AC_PROG_CPP
|
||||
AC_PROG_CC(gcc)
|
||||
AC_PROG_CXX(g++)
|
||||
|
||||
AC_PROG_NM
|
||||
AC_SUBST(NM)
|
||||
|
||||
@ -1139,55 +1050,6 @@ dnl libtool).
|
||||
AC_LIBTOOL_DLOPEN
|
||||
AC_LIB_LTDL
|
||||
|
||||
if test "$WITH_LLVMGCCDIR" = "default" ; then
|
||||
LLVMGCC="llvm-gcc${EXEEXT}"
|
||||
LLVMGXX="llvm-g++${EXEEXT}"
|
||||
LLVMGCCCOMMAND="$LLVMGCC"
|
||||
LLVMGXXCOMMAND="$LLVMGXX"
|
||||
AC_SUBST(LLVMGCCCOMMAND,$LLVMGCCCOMMAND)
|
||||
AC_SUBST(LLVMGXXCOMMAND,$LLVMGXXCOMMAND)
|
||||
AC_PATH_PROG(LLVMGCC, $LLVMGCC, [])
|
||||
AC_PATH_PROG(LLVMGXX, $LLVMGXX, [])
|
||||
else
|
||||
if test -z "$LLVMGCC"; then
|
||||
LLVMGCC="$WITH_LLVMGCCDIR/bin/llvm-gcc${EXEEXT}"
|
||||
LLVMGCCCOMMAND="$LLVMGCC"
|
||||
fi
|
||||
if test -z "$LLVMGXX"; then
|
||||
LLVMGXX="$WITH_LLVMGCCDIR/bin/llvm-g++${EXEEXT}"
|
||||
LLVMGXXCOMMAND="$LLVMGXX"
|
||||
fi
|
||||
|
||||
AC_SUBST(LLVMGCC,$LLVMGCC)
|
||||
AC_SUBST(LLVMGXX,$LLVMGXX)
|
||||
AC_SUBST(LLVMGCCCOMMAND,$LLVMGCCCOMMAND)
|
||||
AC_SUBST(LLVMGXXCOMMAND,$LLVMGXXCOMMAND)
|
||||
fi
|
||||
|
||||
dnl Select the LLVM capable compiler to use, we default to using llvm-gcc if
|
||||
dnl found, otherwise clang if available.
|
||||
AC_ARG_WITH(llvmcc,
|
||||
AS_HELP_STRING([--with-llvmcc=<name>],
|
||||
[Choose the LLVM capable compiler to use (llvm-gcc, clang, or none; default=check)]),
|
||||
[],[with_llvmcc=check])
|
||||
AC_MSG_CHECKING([LLVM capable compiler])
|
||||
if test "$with_llvmcc" != "check"; then
|
||||
if (test "$with_llvmcc" != "llvm-gcc" &&
|
||||
test "$with_llvmcc" != "clang" &&
|
||||
test "$with_llvmcc" != "none"); then
|
||||
AC_MSG_ERROR([invalid value for --with-llvmcc, expected 'llvm-gcc', 'clang', or 'none'.])
|
||||
fi
|
||||
WITH_LLVMCC="$with_llvmcc"
|
||||
elif test -n "$LLVMGCC"; then
|
||||
WITH_LLVMCC=llvm-gcc
|
||||
elif test -n "$WITH_CLANGPATH" || test "$WITH_BUILT_CLANG" -ne "0"; then
|
||||
WITH_LLVMCC=clang
|
||||
else
|
||||
WITH_LLVMCC=none
|
||||
fi
|
||||
AC_MSG_RESULT([$WITH_LLVMCC])
|
||||
AC_SUBST(LLVMCC_OPTION,$WITH_LLVMCC)
|
||||
|
||||
AC_MSG_CHECKING([tool compatibility])
|
||||
|
||||
dnl Ensure that compilation tools are GCC or a GNU compatible compiler such as
|
||||
@ -1352,7 +1214,6 @@ dnl Generally we're looking for POSIX headers.
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_MMAP_ANONYMOUS
|
||||
AC_HEADER_STAT
|
||||
AC_HEADER_STDC
|
||||
AC_HEADER_SYS_WAIT
|
||||
AC_HEADER_TIME
|
||||
|
||||
@ -1512,9 +1373,9 @@ AC_LINK_IFELSE(
|
||||
]]),
|
||||
AC_LANG_POP([C++])
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(LLVM_MULTITHREADED, 1, Build multithreading support into LLVM),
|
||||
AC_DEFINE(LLVM_HAS_ATOMICS, 1, Has gcc/MSVC atomic intrinsics),
|
||||
AC_MSG_RESULT(no)
|
||||
AC_DEFINE(LLVM_MULTITHREADED, 0, Build multithreading support into LLVM)
|
||||
AC_DEFINE(LLVM_HAS_ATOMICS, 0, Has gcc/MSVC atomic intrinsics)
|
||||
AC_MSG_WARN([LLVM will be built thread-unsafe because atomic builtins are missing]))
|
||||
|
||||
dnl===-----------------------------------------------------------------------===
|
||||
@ -1533,63 +1394,9 @@ if test "$llvm_cv_os_type" = "Linux" -a "$llvm_cv_target_arch" = "x86_64" ; then
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl Check, whether __dso_handle is present
|
||||
dnl Check whether __dso_handle is present
|
||||
AC_CHECK_FUNCS([__dso_handle])
|
||||
|
||||
dnl Check wether llvm-gcc is based on dragonegg
|
||||
AC_CACHE_CHECK([whether llvm-gcc is dragonegg],[llvm_cv_llvmgcc_dragonegg],
|
||||
[llvm_cv_llvmgcc_dragonegg="no"
|
||||
if test -n "$LLVMGCC" ; then
|
||||
cp /dev/null conftest.c
|
||||
$LLVMGCC -fplugin-arg-dragonegg-emit-ir -S -o - conftest.c > /dev/null 2>&1
|
||||
if test $? -eq 0 ; then
|
||||
llvm_cv_llvmgcc_dragonegg="yes"
|
||||
fi
|
||||
rm conftest.c
|
||||
fi])
|
||||
|
||||
dnl Set the flags needed to emit LLVM IR and to disable optimizations
|
||||
dnl in llvmgcc
|
||||
if test "$llvm_cv_llvmgcc_dragonegg" = "yes" ; then
|
||||
LLVMCC_EMITIR_FLAG="-fplugin-arg-dragonegg-emit-ir"
|
||||
LLVMCC_DISABLEOPT_FLAGS="-fplugin-arg-dragonegg-llvm-ir-optimize=0"
|
||||
else
|
||||
LLVMCC_EMITIR_FLAG="-emit-llvm"
|
||||
LLVMCC_DISABLEOPT_FLAGS="-mllvm -disable-llvm-optzns"
|
||||
fi
|
||||
|
||||
AC_SUBST(LLVMCC_EMITIR_FLAG)
|
||||
|
||||
dnl See if the llvm-gcc executable can compile to LLVM assembly
|
||||
AC_CACHE_CHECK([whether llvm-gcc is sane],[llvm_cv_llvmgcc_sanity],
|
||||
[llvm_cv_llvmgcc_sanity="no"
|
||||
if test -n "$LLVMGCC" ; then
|
||||
cp /dev/null conftest.c
|
||||
$LLVMGCC "$LLVMCC_EMITIR_FLAG" -S -o - conftest.c | \
|
||||
grep 'target datalayout =' > /dev/null 2>&1
|
||||
if test $? -eq 0 ; then
|
||||
llvm_cv_llvmgcc_sanity="yes"
|
||||
fi
|
||||
rm conftest.c
|
||||
fi])
|
||||
|
||||
dnl Since we have a sane llvm-gcc, identify it and its sub-tools
|
||||
dnl Furthermore, add some information about the tools
|
||||
if test "$llvm_cv_llvmgcc_sanity" = "yes" ; then
|
||||
AC_MSG_CHECKING([llvm-gcc component support])
|
||||
llvmcc1path=`$LLVMGCC --print-prog-name=cc1`
|
||||
AC_SUBST(LLVMCC1,$llvmcc1path)
|
||||
llvmcc1pluspath=`$LLVMGCC --print-prog-name=cc1plus`
|
||||
AC_SUBST(LLVMCC1PLUS,$llvmcc1pluspath)
|
||||
llvmgccdir=`echo "$llvmcc1path" | sed 's,/libexec/.*,,'`
|
||||
AC_SUBST(LLVMGCCDIR,$llvmgccdir)
|
||||
llvmgcclangs=[`$LLVMGCC -v --help 2>&1 | grep '^Configured with:' | sed 's/^.*--enable-languages=\([^ ]*\).*/\1/'`]
|
||||
AC_SUBST(LLVMGCC_LANGS,$llvmgcclangs)
|
||||
AC_SUBST(LLVMGCC_DRAGONEGG,$llvm_cv_llvmgcc_dragonegg)
|
||||
AC_SUBST(LLVMCC_DISABLEOPT_FLAGS)
|
||||
AC_MSG_RESULT([ok])
|
||||
fi
|
||||
|
||||
dnl Propagate the shared library extension that the libltdl checks did to
|
||||
dnl the Makefiles so we can use it there too
|
||||
AC_SUBST(SHLIBEXT,$libltdl_cv_shlibext)
|
||||
@ -1753,12 +1560,12 @@ if test -f ${srcdir}/tools/clang/README.txt; then
|
||||
AC_CONFIG_FILES([tools/clang/docs/doxygen.cfg])
|
||||
fi
|
||||
|
||||
dnl Configure llvmc's Base plugin
|
||||
AC_CONFIG_FILES([tools/llvmc/src/Base.td])
|
||||
|
||||
dnl Do the first stage of configuration for llvm-config.in.
|
||||
AC_CONFIG_FILES([tools/llvm-config/llvm-config.in])
|
||||
|
||||
dnl OCaml findlib META file
|
||||
AC_CONFIG_FILES([bindings/ocaml/llvm/META.llvm])
|
||||
|
||||
dnl Do special configuration of Makefiles
|
||||
AC_CONFIG_COMMANDS([setup],,[llvm_src="${srcdir}"])
|
||||
AC_CONFIG_MAKEFILE(Makefile)
|
||||
|
63
bindings/ocaml/llvm/META.llvm.in
Normal file
63
bindings/ocaml/llvm/META.llvm.in
Normal file
@ -0,0 +1,63 @@
|
||||
name = "llvm"
|
||||
version = "@PACKAGE_VERSION@"
|
||||
description = "Low Level Virtual Machine OCaml bindings"
|
||||
archive(byte) = "llvm.cma"
|
||||
archive(native) = "llvm.cmxa"
|
||||
directory = "."
|
||||
linkopts = "-ccopt -lstdc++"
|
||||
|
||||
package "analysis" (
|
||||
requires = "llvm"
|
||||
version = "@PACKAGE_VERSION@"
|
||||
description = "Intermediate representation analysis for LLVM"
|
||||
archive(byte) = "llvm_analysis.cma"
|
||||
archive(native) = "llvm_analysis.cmxa"
|
||||
)
|
||||
|
||||
package "bitreader" (
|
||||
requires = "llvm"
|
||||
version = "@PACKAGE_VERSION@"
|
||||
description = "Bitcode reader for LLVM"
|
||||
archive(byte) = "llvm_bitreader.cma"
|
||||
archive(native) = "llvm_bitreader.cmxa"
|
||||
)
|
||||
|
||||
package "bitwriter" (
|
||||
requires = "llvm,unix"
|
||||
version = "@PACKAGE_VERSION@"
|
||||
description = "Bitcode writer for LLVM"
|
||||
archive(byte) = "llvm_bitwriter.cma"
|
||||
archive(native) = "llvm_bitwriter.cmxa"
|
||||
)
|
||||
|
||||
package "executionengine" (
|
||||
requires = "llvm,llvm.target"
|
||||
version = "@PACKAGE_VERSION@"
|
||||
description = "JIT and Interpreter for LLVM"
|
||||
archive(byte) = "llvm_executionengine.cma"
|
||||
archive(native) = "llvm_executionengine.cmxa"
|
||||
)
|
||||
|
||||
package "ipo" (
|
||||
requires = "llvm"
|
||||
version = "@PACKAGE_VERSION@"
|
||||
description = "IPO Transforms for LLVM"
|
||||
archive(byte) = "llvm_ipo.cma"
|
||||
archive(native) = "llvm_ipo.cmxa"
|
||||
)
|
||||
|
||||
package "scalar_opts" (
|
||||
requires = "llvm"
|
||||
version = "@PACKAGE_VERSION@"
|
||||
description = "Scalar Transforms for LLVM"
|
||||
archive(byte) = "llvm_scalar_opts.cma"
|
||||
archive(native) = "llvm_scalar_opts.cmxa"
|
||||
)
|
||||
|
||||
package "target" (
|
||||
requires = "llvm"
|
||||
version = "@PACKAGE_VERSION@"
|
||||
description = "Target Information for LLVM"
|
||||
archive(byte) = "llvm_target.cma"
|
||||
archive(native) = "llvm_target.cmxa"
|
||||
)
|
@ -17,3 +17,24 @@ UsedComponents := core
|
||||
UsedOcamLibs := llvm
|
||||
|
||||
include ../Makefile.ocaml
|
||||
|
||||
all-local:: copy-meta
|
||||
install-local:: install-meta
|
||||
uninstall-local:: uninstall-meta
|
||||
|
||||
DestMETA := $(PROJ_libocamldir)/META.llvm
|
||||
|
||||
# Easy way of generating META in the objdir
|
||||
copy-meta: $(OcamlDir)/META.llvm
|
||||
|
||||
$(OcamlDir)/META.llvm: META.llvm
|
||||
$(Verb) $(CP) -f $< $@
|
||||
|
||||
install-meta:: $(ObjDir)/META.llvm
|
||||
$(Echo) "Install $(BuildMode) $(DestMETA)"
|
||||
$(Verb) $(MKDIR) $(PROJ_libocamldir)
|
||||
$(Verb) $(DataInstall) META.llvm "$(DestMETA)"
|
||||
|
||||
uninstall-meta::
|
||||
$(Echo) "Uninstalling $(DestMETA)"
|
||||
-$(Verb) $(RM) -f "$(DestMETA)"
|
||||
|
@ -94,6 +94,9 @@ module Attribute = struct
|
||||
| Naked
|
||||
| Inlinehint
|
||||
| Stackalignment of int
|
||||
| ReturnsTwice
|
||||
| UWTable
|
||||
| NonLazyBind
|
||||
end
|
||||
|
||||
module Icmp = struct
|
||||
@ -130,6 +133,101 @@ module Fcmp = struct
|
||||
| True
|
||||
end
|
||||
|
||||
module Opcode = struct
|
||||
type t =
|
||||
| Invalid (* not an instruction *)
|
||||
(* Terminator Instructions *)
|
||||
| Ret
|
||||
| Br
|
||||
| Switch
|
||||
| IndirectBr
|
||||
| Invoke
|
||||
| Invalid2
|
||||
| Unreachable
|
||||
(* Standard Binary Operators *)
|
||||
| Add
|
||||
| FAdd
|
||||
| Sub
|
||||
| FSub
|
||||
| Mul
|
||||
| FMul
|
||||
| UDiv
|
||||
| SDiv
|
||||
| FDiv
|
||||
| URem
|
||||
| SRem
|
||||
| FRem
|
||||
(* Logical Operators *)
|
||||
| Shl
|
||||
| LShr
|
||||
| AShr
|
||||
| And
|
||||
| Or
|
||||
| Xor
|
||||
(* Memory Operators *)
|
||||
| Alloca
|
||||
| Load
|
||||
| Store
|
||||
| GetElementPtr
|
||||
(* Cast Operators *)
|
||||
| Trunc
|
||||
| ZExt
|
||||
| SExt
|
||||
| FPToUI
|
||||
| FPToSI
|
||||
| UIToFP
|
||||
| SIToFP
|
||||
| FPTrunc
|
||||
| FPExt
|
||||
| PtrToInt
|
||||
| IntToPtr
|
||||
| BitCast
|
||||
(* Other Operators *)
|
||||
| ICmp
|
||||
| FCmp
|
||||
| PHI
|
||||
| Call
|
||||
| Select
|
||||
| UserOp1
|
||||
| UserOp2
|
||||
| VAArg
|
||||
| ExtractElement
|
||||
| InsertElement
|
||||
| ShuffleVector
|
||||
| ExtractValue
|
||||
| InsertValue
|
||||
| Fence
|
||||
| AtomicCmpXchg
|
||||
| AtomicRMW
|
||||
| Resume
|
||||
| LandingPad
|
||||
| Unwind
|
||||
end
|
||||
|
||||
module ValueKind = struct
|
||||
type t =
|
||||
| NullValue
|
||||
| Argument
|
||||
| BasicBlock
|
||||
| InlineAsm
|
||||
| MDNode
|
||||
| MDString
|
||||
| BlockAddress
|
||||
| ConstantAggregateZero
|
||||
| ConstantArray
|
||||
| ConstantExpr
|
||||
| ConstantFP
|
||||
| ConstantInt
|
||||
| ConstantPointerNull
|
||||
| ConstantStruct
|
||||
| ConstantVector
|
||||
| Function
|
||||
| GlobalAlias
|
||||
| GlobalVariable
|
||||
| UndefValue
|
||||
| Instruction of Opcode.t
|
||||
end
|
||||
|
||||
exception IoError of string
|
||||
|
||||
external register_exns : exn -> unit = "llvm_register_core_exns"
|
||||
@ -163,10 +261,12 @@ external set_data_layout: string -> llmodule -> unit
|
||||
external dump_module : llmodule -> unit = "llvm_dump_module"
|
||||
external set_module_inline_asm : llmodule -> string -> unit
|
||||
= "llvm_set_module_inline_asm"
|
||||
external module_context : llmodule -> llcontext = "LLVMGetModuleContext"
|
||||
|
||||
(*===-- Types -------------------------------------------------------------===*)
|
||||
external classify_type : lltype -> TypeKind.t = "llvm_classify_type"
|
||||
external type_context : lltype -> llcontext = "llvm_type_context"
|
||||
external type_is_sized : lltype -> bool = "llvm_type_is_sized"
|
||||
|
||||
(*--... Operations on integer types ........................................--*)
|
||||
external i1_type : llcontext -> lltype = "llvm_i1_type"
|
||||
@ -197,9 +297,15 @@ external param_types : lltype -> lltype array = "llvm_param_types"
|
||||
external struct_type : llcontext -> lltype array -> lltype = "llvm_struct_type"
|
||||
external packed_struct_type : llcontext -> lltype array -> lltype
|
||||
= "llvm_packed_struct_type"
|
||||
external struct_name : lltype -> string option = "llvm_struct_name"
|
||||
external named_struct_type : llcontext -> string -> lltype =
|
||||
"llvm_named_struct_type"
|
||||
external struct_set_body : lltype -> lltype array -> bool -> unit =
|
||||
"llvm_struct_set_body"
|
||||
external struct_element_types : lltype -> lltype array
|
||||
= "llvm_struct_element_types"
|
||||
external is_packed : lltype -> bool = "llvm_is_packed"
|
||||
external is_opaque : lltype -> bool = "llvm_is_opaque"
|
||||
|
||||
(*--... Operations on pointer, vector, and array types .....................--*)
|
||||
external array_type : lltype -> int -> lltype = "llvm_array_type"
|
||||
@ -216,7 +322,9 @@ external vector_size : lltype -> int = "llvm_vector_size"
|
||||
(*--... Operations on other types ..........................................--*)
|
||||
external void_type : llcontext -> lltype = "llvm_void_type"
|
||||
external label_type : llcontext -> lltype = "llvm_label_type"
|
||||
external type_by_name : llmodule -> string -> lltype option = "llvm_type_by_name"
|
||||
|
||||
external classify_value : llvalue -> ValueKind.t = "llvm_classify_value"
|
||||
(*===-- Values ------------------------------------------------------------===*)
|
||||
external type_of : llvalue -> lltype = "llvm_type_of"
|
||||
external value_name : llvalue -> string = "llvm_value_name"
|
||||
@ -270,6 +378,7 @@ external const_pointer_null : lltype -> llvalue = "LLVMConstPointerNull"
|
||||
external undef : lltype -> llvalue = "LLVMGetUndef"
|
||||
external is_null : llvalue -> bool = "llvm_is_null"
|
||||
external is_undef : llvalue -> bool = "llvm_is_undef"
|
||||
external constexpr_opcode : llvalue -> Opcode.t = "llvm_constexpr_get_opcode"
|
||||
|
||||
(*--... Operations on instructions .........................................--*)
|
||||
external has_metadata : llvalue -> bool = "llvm_has_metadata"
|
||||
@ -280,11 +389,15 @@ external clear_metadata : llvalue -> int -> unit = "llvm_clear_metadata"
|
||||
(*--... Operations on metadata .......,.....................................--*)
|
||||
external mdstring : llcontext -> string -> llvalue = "llvm_mdstring"
|
||||
external mdnode : llcontext -> llvalue array -> llvalue = "llvm_mdnode"
|
||||
external get_mdstring : llvalue -> string option = "llvm_get_mdstring"
|
||||
external get_named_metadata : llmodule -> string -> llvalue array = "llvm_get_namedmd"
|
||||
|
||||
(*--... Operations on scalar constants .....................................--*)
|
||||
external const_int : lltype -> int -> llvalue = "llvm_const_int"
|
||||
external const_of_int64 : lltype -> Int64.t -> bool -> llvalue
|
||||
= "llvm_const_of_int64"
|
||||
external int64_of_const : llvalue -> Int64.t option
|
||||
= "llvm_int64_of_const"
|
||||
external const_int_of_string : lltype -> string -> int -> llvalue
|
||||
= "llvm_const_int_of_string"
|
||||
external const_float : lltype -> float -> llvalue = "llvm_const_float"
|
||||
@ -297,6 +410,8 @@ external const_stringz : llcontext -> string -> llvalue = "llvm_const_stringz"
|
||||
external const_array : lltype -> llvalue array -> llvalue = "llvm_const_array"
|
||||
external const_struct : llcontext -> llvalue array -> llvalue
|
||||
= "llvm_const_struct"
|
||||
external const_named_struct : lltype -> llvalue array -> llvalue
|
||||
= "llvm_const_named_struct"
|
||||
external const_packed_struct : llcontext -> llvalue array -> llvalue
|
||||
= "llvm_const_packed_struct"
|
||||
external const_vector : llvalue array -> llvalue = "llvm_const_vector"
|
||||
@ -530,36 +645,81 @@ let rec fold_right_function_range f i e init =
|
||||
let fold_right_functions f m init =
|
||||
fold_right_function_range f (function_end m) (At_start m) init
|
||||
|
||||
external llvm_add_function_attr : llvalue -> int -> unit
|
||||
external llvm_add_function_attr : llvalue -> int32 -> unit
|
||||
= "llvm_add_function_attr"
|
||||
external llvm_remove_function_attr : llvalue -> int -> unit
|
||||
external llvm_remove_function_attr : llvalue -> int32 -> unit
|
||||
= "llvm_remove_function_attr"
|
||||
external llvm_function_attr : llvalue -> int32 = "llvm_function_attr"
|
||||
|
||||
let pack_attr (attr:Attribute.t) : int =
|
||||
let pack_attr (attr:Attribute.t) : int32 =
|
||||
match attr with
|
||||
Attribute.Zext -> 1 lsl 0
|
||||
| Attribute.Sext -> 1 lsl 1
|
||||
| Attribute.Noreturn -> 1 lsl 2
|
||||
| Attribute.Inreg -> 1 lsl 3
|
||||
| Attribute.Structret -> 1 lsl 4
|
||||
| Attribute.Nounwind -> 1 lsl 5
|
||||
| Attribute.Noalias -> 1 lsl 6
|
||||
| Attribute.Byval -> 1 lsl 7
|
||||
| Attribute.Nest -> 1 lsl 8
|
||||
| Attribute.Readnone -> 1 lsl 9
|
||||
| Attribute.Readonly -> 1 lsl 10
|
||||
| Attribute.Noinline -> 1 lsl 11
|
||||
| Attribute.Alwaysinline -> 1 lsl 12
|
||||
| Attribute.Optsize -> 1 lsl 13
|
||||
| Attribute.Ssp -> 1 lsl 14
|
||||
| Attribute.Sspreq -> 1 lsl 15
|
||||
| Attribute.Alignment n -> n lsl 16
|
||||
| Attribute.Nocapture -> 1 lsl 21
|
||||
| Attribute.Noredzone -> 1 lsl 22
|
||||
| Attribute.Noimplicitfloat -> 1 lsl 23
|
||||
| Attribute.Naked -> 1 lsl 24
|
||||
| Attribute.Inlinehint -> 1 lsl 25
|
||||
| Attribute.Stackalignment n -> n lsl 26
|
||||
Attribute.Zext -> Int32.shift_left 1l 0
|
||||
| Attribute.Sext -> Int32.shift_left 1l 1
|
||||
| Attribute.Noreturn -> Int32.shift_left 1l 2
|
||||
| Attribute.Inreg -> Int32.shift_left 1l 3
|
||||
| Attribute.Structret -> Int32.shift_left 1l 4
|
||||
| Attribute.Nounwind -> Int32.shift_left 1l 5
|
||||
| Attribute.Noalias -> Int32.shift_left 1l 6
|
||||
| Attribute.Byval -> Int32.shift_left 1l 7
|
||||
| Attribute.Nest -> Int32.shift_left 1l 8
|
||||
| Attribute.Readnone -> Int32.shift_left 1l 9
|
||||
| Attribute.Readonly -> Int32.shift_left 1l 10
|
||||
| Attribute.Noinline -> Int32.shift_left 1l 11
|
||||
| Attribute.Alwaysinline -> Int32.shift_left 1l 12
|
||||
| Attribute.Optsize -> Int32.shift_left 1l 13
|
||||
| Attribute.Ssp -> Int32.shift_left 1l 14
|
||||
| Attribute.Sspreq -> Int32.shift_left 1l 15
|
||||
| Attribute.Alignment n -> Int32.shift_left (Int32.of_int n) 16
|
||||
| Attribute.Nocapture -> Int32.shift_left 1l 21
|
||||
| Attribute.Noredzone -> Int32.shift_left 1l 22
|
||||
| Attribute.Noimplicitfloat -> Int32.shift_left 1l 23
|
||||
| Attribute.Naked -> Int32.shift_left 1l 24
|
||||
| Attribute.Inlinehint -> Int32.shift_left 1l 25
|
||||
| Attribute.Stackalignment n -> Int32.shift_left (Int32.of_int n) 26
|
||||
| Attribute.ReturnsTwice -> Int32.shift_left 1l 29
|
||||
| Attribute.UWTable -> Int32.shift_left 1l 30
|
||||
| Attribute.NonLazyBind -> Int32.shift_left 1l 31
|
||||
|
||||
let unpack_attr (a : int32) : Attribute.t list =
|
||||
let l = ref [] in
|
||||
let check attr =
|
||||
Int32.logand (pack_attr attr) a in
|
||||
let checkattr attr =
|
||||
if (check attr) <> 0l then begin
|
||||
l := attr :: !l
|
||||
end
|
||||
in
|
||||
checkattr Attribute.Zext;
|
||||
checkattr Attribute.Sext;
|
||||
checkattr Attribute.Noreturn;
|
||||
checkattr Attribute.Inreg;
|
||||
checkattr Attribute.Structret;
|
||||
checkattr Attribute.Nounwind;
|
||||
checkattr Attribute.Noalias;
|
||||
checkattr Attribute.Byval;
|
||||
checkattr Attribute.Nest;
|
||||
checkattr Attribute.Readnone;
|
||||
checkattr Attribute.Readonly;
|
||||
checkattr Attribute.Noinline;
|
||||
checkattr Attribute.Alwaysinline;
|
||||
checkattr Attribute.Optsize;
|
||||
checkattr Attribute.Ssp;
|
||||
checkattr Attribute.Sspreq;
|
||||
let align = Int32.logand (Int32.shift_right_logical a 16) 31l in
|
||||
if align <> 0l then
|
||||
l := Attribute.Alignment (Int32.to_int align) :: !l;
|
||||
checkattr Attribute.Nocapture;
|
||||
checkattr Attribute.Noredzone;
|
||||
checkattr Attribute.Noimplicitfloat;
|
||||
checkattr Attribute.Naked;
|
||||
checkattr Attribute.Inlinehint;
|
||||
let stackalign = Int32.logand (Int32.shift_right_logical a 26) 7l in
|
||||
if stackalign <> 0l then
|
||||
l := Attribute.Stackalignment (Int32.to_int stackalign) :: !l;
|
||||
checkattr Attribute.ReturnsTwice;
|
||||
checkattr Attribute.UWTable;
|
||||
checkattr Attribute.NonLazyBind;
|
||||
!l;;
|
||||
|
||||
let add_function_attr llval attr =
|
||||
llvm_add_function_attr llval (pack_attr attr)
|
||||
@ -567,9 +727,13 @@ let add_function_attr llval attr =
|
||||
let remove_function_attr llval attr =
|
||||
llvm_remove_function_attr llval (pack_attr attr)
|
||||
|
||||
let function_attr f = unpack_attr (llvm_function_attr f)
|
||||
|
||||
(*--... Operations on params ...............................................--*)
|
||||
external params : llvalue -> llvalue array = "llvm_params"
|
||||
external param : llvalue -> int -> llvalue = "llvm_param"
|
||||
external llvm_param_attr : llvalue -> int32 = "llvm_param_attr"
|
||||
let param_attr p = unpack_attr (llvm_param_attr p)
|
||||
external param_parent : llvalue -> llvalue = "LLVMGetParamParent"
|
||||
external param_begin : llvalue -> (llvalue, llvalue) llpos = "llvm_param_begin"
|
||||
external param_succ : llvalue -> (llvalue, llvalue) llpos = "llvm_param_succ"
|
||||
@ -616,9 +780,9 @@ let rec fold_right_param_range f init i e =
|
||||
let fold_right_params f fn init =
|
||||
fold_right_param_range f init (param_end fn) (At_start fn)
|
||||
|
||||
external llvm_add_param_attr : llvalue -> int -> unit
|
||||
external llvm_add_param_attr : llvalue -> int32 -> unit
|
||||
= "llvm_add_param_attr"
|
||||
external llvm_remove_param_attr : llvalue -> int -> unit
|
||||
external llvm_remove_param_attr : llvalue -> int32 -> unit
|
||||
= "llvm_remove_param_attr"
|
||||
|
||||
let add_param_attr llval attr =
|
||||
@ -650,6 +814,8 @@ external block_end : llvalue -> (llvalue, llbasicblock) llrev_pos
|
||||
= "llvm_block_end"
|
||||
external block_pred : llbasicblock -> (llvalue, llbasicblock) llrev_pos
|
||||
= "llvm_block_pred"
|
||||
external block_terminator : llbasicblock -> llvalue option =
|
||||
"llvm_block_terminator"
|
||||
|
||||
let rec iter_block_range f i e =
|
||||
if i = e then () else
|
||||
@ -702,6 +868,11 @@ external instr_end : llbasicblock -> (llbasicblock, llvalue) llrev_pos
|
||||
external instr_pred : llvalue -> (llbasicblock, llvalue) llrev_pos
|
||||
= "llvm_instr_pred"
|
||||
|
||||
external instr_opcode : llvalue -> Opcode.t = "llvm_instr_get_opcode"
|
||||
external icmp_predicate : llvalue -> Icmp.t option = "llvm_instr_icmp_predicate"
|
||||
|
||||
external icmp_predicate : llvalue -> Icmp.t option = "llvm_instr_icmp_predicate"
|
||||
|
||||
let rec iter_instrs_range f i e =
|
||||
if i = e then () else
|
||||
match i with
|
||||
@ -749,9 +920,9 @@ external instruction_call_conv: llvalue -> int
|
||||
external set_instruction_call_conv: int -> llvalue -> unit
|
||||
= "llvm_set_instruction_call_conv"
|
||||
|
||||
external llvm_add_instruction_param_attr : llvalue -> int -> int -> unit
|
||||
external llvm_add_instruction_param_attr : llvalue -> int -> int32 -> unit
|
||||
= "llvm_add_instruction_param_attr"
|
||||
external llvm_remove_instruction_param_attr : llvalue -> int -> int -> unit
|
||||
external llvm_remove_instruction_param_attr : llvalue -> int -> int32 -> unit
|
||||
= "llvm_remove_instruction_param_attr"
|
||||
|
||||
let add_instruction_param_attr llval i attr =
|
||||
@ -769,6 +940,7 @@ external add_incoming : (llvalue * llbasicblock) -> llvalue -> unit
|
||||
= "llvm_add_incoming"
|
||||
external incoming : llvalue -> (llvalue * llbasicblock) list = "llvm_incoming"
|
||||
|
||||
external delete_instruction : llvalue -> unit = "llvm_delete_instruction"
|
||||
|
||||
(*===-- Instruction builders ----------------------------------------------===*)
|
||||
external builder : llcontext -> llbuilder = "llvm_builder"
|
||||
@ -811,8 +983,15 @@ external build_cond_br : llvalue -> llbasicblock -> llbasicblock -> llbuilder ->
|
||||
llvalue = "llvm_build_cond_br"
|
||||
external build_switch : llvalue -> llbasicblock -> int -> llbuilder -> llvalue
|
||||
= "llvm_build_switch"
|
||||
external build_malloc : lltype -> string -> llbuilder -> llvalue =
|
||||
"llvm_build_malloc"
|
||||
external build_array_malloc : lltype -> llvalue -> string -> llbuilder ->
|
||||
llvalue = "llvm_build_array_malloc"
|
||||
external build_free : llvalue -> llbuilder -> llvalue = "llvm_build_free"
|
||||
external add_case : llvalue -> llvalue -> llbasicblock -> unit
|
||||
= "llvm_add_case"
|
||||
external switch_default_dest : llvalue -> llbasicblock =
|
||||
"LLVMGetSwitchDefaultDest"
|
||||
external build_indirect_br : llvalue -> int -> llbuilder -> llvalue
|
||||
= "llvm_build_indirect_br"
|
||||
external add_destination : llvalue -> llbasicblock -> unit
|
||||
@ -820,7 +999,11 @@ external add_destination : llvalue -> llbasicblock -> unit
|
||||
external build_invoke : llvalue -> llvalue array -> llbasicblock ->
|
||||
llbasicblock -> string -> llbuilder -> llvalue
|
||||
= "llvm_build_invoke_bc" "llvm_build_invoke_nat"
|
||||
external build_unwind : llbuilder -> llvalue = "llvm_build_unwind"
|
||||
external build_landingpad : lltype -> llvalue -> int -> string -> llbuilder ->
|
||||
llvalue = "llvm_build_landingpad"
|
||||
external set_cleanup : llvalue -> bool -> unit = "llvm_set_cleanup"
|
||||
external add_clause : llvalue -> llvalue -> unit = "llvm_add_clause"
|
||||
external build_resume : llvalue -> llbuilder -> llvalue = "llvm_build_resume"
|
||||
external build_unreachable : llbuilder -> llvalue = "llvm_build_unreachable"
|
||||
|
||||
(*--... Arithmetic .........................................................--*)
|
||||
@ -1022,7 +1205,14 @@ let rec string_of_lltype ty =
|
||||
(* FIXME: stop infinite recursion! :) *)
|
||||
match classify_type ty with
|
||||
TypeKind.Integer -> "i" ^ string_of_int (integer_bitwidth ty)
|
||||
| TypeKind.Pointer -> (string_of_lltype (element_type ty)) ^ "*"
|
||||
| TypeKind.Pointer ->
|
||||
(let ety = element_type ty in
|
||||
match classify_type ety with
|
||||
| TypeKind.Struct ->
|
||||
(match struct_name ety with
|
||||
| None -> (string_of_lltype ety)
|
||||
| Some s -> s) ^ "*"
|
||||
| _ -> (string_of_lltype (element_type ty)) ^ "*")
|
||||
| TypeKind.Struct ->
|
||||
let s = "{ " ^ (concat2 ", " (
|
||||
Array.map string_of_lltype (struct_element_types ty)
|
||||
|
@ -139,6 +139,9 @@ module Attribute : sig
|
||||
| Naked
|
||||
| Inlinehint
|
||||
| Stackalignment of int
|
||||
| ReturnsTwice
|
||||
| UWTable
|
||||
| NonLazyBind
|
||||
end
|
||||
|
||||
(** The predicate for an integer comparison ([icmp]) instruction.
|
||||
@ -179,6 +182,103 @@ module Fcmp : sig
|
||||
| True
|
||||
end
|
||||
|
||||
(** The opcodes for LLVM instructions and constant expressions. *)
|
||||
module Opcode : sig
|
||||
type t =
|
||||
| Invalid (* not an instruction *)
|
||||
(* Terminator Instructions *)
|
||||
| Ret
|
||||
| Br
|
||||
| Switch
|
||||
| IndirectBr
|
||||
| Invoke
|
||||
| Invalid2
|
||||
| Unreachable
|
||||
(* Standard Binary Operators *)
|
||||
| Add
|
||||
| FAdd
|
||||
| Sub
|
||||
| FSub
|
||||
| Mul
|
||||
| FMul
|
||||
| UDiv
|
||||
| SDiv
|
||||
| FDiv
|
||||
| URem
|
||||
| SRem
|
||||
| FRem
|
||||
(* Logical Operators *)
|
||||
| Shl
|
||||
| LShr
|
||||
| AShr
|
||||
| And
|
||||
| Or
|
||||
| Xor
|
||||
(* Memory Operators *)
|
||||
| Alloca
|
||||
| Load
|
||||
| Store
|
||||
| GetElementPtr
|
||||
(* Cast Operators *)
|
||||
| Trunc
|
||||
| ZExt
|
||||
| SExt
|
||||
| FPToUI
|
||||
| FPToSI
|
||||
| UIToFP
|
||||
| SIToFP
|
||||
| FPTrunc
|
||||
| FPExt
|
||||
| PtrToInt
|
||||
| IntToPtr
|
||||
| BitCast
|
||||
(* Other Operators *)
|
||||
| ICmp
|
||||
| FCmp
|
||||
| PHI
|
||||
| Call
|
||||
| Select
|
||||
| UserOp1
|
||||
| UserOp2
|
||||
| VAArg
|
||||
| ExtractElement
|
||||
| InsertElement
|
||||
| ShuffleVector
|
||||
| ExtractValue
|
||||
| InsertValue
|
||||
| Fence
|
||||
| AtomicCmpXchg
|
||||
| AtomicRMW
|
||||
| Resume
|
||||
| LandingPad
|
||||
| Unwind
|
||||
end
|
||||
|
||||
(** The kind of an [llvalue], the result of [classify_value v].
|
||||
* See the various [LLVMIsA*] functions. *)
|
||||
module ValueKind : sig
|
||||
type t =
|
||||
| NullValue
|
||||
| Argument
|
||||
| BasicBlock
|
||||
| InlineAsm
|
||||
| MDNode
|
||||
| MDString
|
||||
| BlockAddress
|
||||
| ConstantAggregateZero
|
||||
| ConstantArray
|
||||
| ConstantExpr
|
||||
| ConstantFP
|
||||
| ConstantInt
|
||||
| ConstantPointerNull
|
||||
| ConstantStruct
|
||||
| ConstantVector
|
||||
| Function
|
||||
| GlobalAlias
|
||||
| GlobalVariable
|
||||
| UndefValue
|
||||
| Instruction of Opcode.t
|
||||
end
|
||||
|
||||
(** {6 Iteration} *)
|
||||
|
||||
@ -263,7 +363,9 @@ val dump_module : llmodule -> unit
|
||||
the method [llvm::Module::setModuleInlineAsm]. *)
|
||||
val set_module_inline_asm : llmodule -> string -> unit
|
||||
|
||||
|
||||
(** [module_context m] returns the context of the specified module.
|
||||
* See the method [llvm::Module::getContext] *)
|
||||
val module_context : llmodule -> llcontext
|
||||
|
||||
(** {6 Types} *)
|
||||
|
||||
@ -271,6 +373,11 @@ val set_module_inline_asm : llmodule -> string -> unit
|
||||
See the method [llvm::Type::getTypeID]. *)
|
||||
val classify_type : lltype -> TypeKind.t
|
||||
|
||||
(** [type_is_sized ty] returns whether the type has a size or not.
|
||||
* If it doesn't then it is not safe to call the [TargetData::] methods on it.
|
||||
* *)
|
||||
val type_is_sized : lltype -> bool
|
||||
|
||||
(** [type_context ty] returns the {!llcontext} corresponding to the type [ty].
|
||||
See the method [llvm::Type::getContext]. *)
|
||||
val type_context : lltype -> llcontext
|
||||
@ -339,7 +446,7 @@ val ppc_fp128_type : llcontext -> lltype
|
||||
See the method [llvm::FunctionType::get]. *)
|
||||
val function_type : lltype -> lltype array -> lltype
|
||||
|
||||
(** [va_arg_function_type ret_ty param_tys] is just like
|
||||
(** [var_arg_function_type ret_ty param_tys] is just like
|
||||
[function_type ret_ty param_tys] except that it returns the function type
|
||||
which also takes a variable number of arguments.
|
||||
See the method [llvm::FunctionType::get]. *)
|
||||
@ -372,6 +479,19 @@ val struct_type : llcontext -> lltype array -> lltype
|
||||
[llvm::StructType::get]. *)
|
||||
val packed_struct_type : llcontext -> lltype array -> lltype
|
||||
|
||||
(** [struct_name ty] returns the name of the named structure type [ty],
|
||||
* or None if the structure type is not named *)
|
||||
val struct_name : lltype -> string option
|
||||
|
||||
(** [named_struct_type context name] returns the named structure type [name]
|
||||
* in the context [context].
|
||||
* See the method [llvm::StructType::get]. *)
|
||||
val named_struct_type : llcontext -> string -> lltype
|
||||
|
||||
(** [struct_set_body ty elts ispacked] sets the body of the named struct [ty]
|
||||
* to the [elts] elements.
|
||||
* See the moethd [llvm::StructType::setBody]. *)
|
||||
val struct_set_body : lltype -> lltype array -> bool -> unit
|
||||
|
||||
(** [struct_element_types sty] returns the constituent types of the struct type
|
||||
[sty]. See the method [llvm::StructType::getElementType]. *)
|
||||
@ -382,6 +502,9 @@ val struct_element_types : lltype -> lltype array
|
||||
[false] otherwise. See the method [llvm::StructType::isPacked]. *)
|
||||
val is_packed : lltype -> bool
|
||||
|
||||
(** [is_opaque sty] returns [true] if the structure type [sty] is opaque.
|
||||
[false] otherwise. See the method [llvm::StructType::isOpaque]. *)
|
||||
val is_opaque : lltype -> bool
|
||||
|
||||
(** {7 Operations on pointer, vector, and array types} *)
|
||||
|
||||
@ -431,12 +554,19 @@ val void_type : llcontext -> lltype
|
||||
[llvm::Type::LabelTy]. *)
|
||||
val label_type : llcontext -> lltype
|
||||
|
||||
(** [type_by_name m name] returns the specified type from the current module
|
||||
* if it exists.
|
||||
* See the method [llvm::Module::getTypeByName] *)
|
||||
val type_by_name : llmodule -> string -> lltype option
|
||||
|
||||
(* {6 Values} *)
|
||||
|
||||
(** [type_of v] returns the type of the value [v].
|
||||
See the method [llvm::Value::getType]. *)
|
||||
val type_of : llvalue -> lltype
|
||||
|
||||
val classify_value : llvalue -> ValueKind.t
|
||||
|
||||
(** [value_name v] returns the name of the value [v]. For global values, this is
|
||||
the symbol name. For instructions and basic blocks, it is the SSA register
|
||||
name. It is meaningless for constants.
|
||||
@ -534,7 +664,7 @@ val is_null : llvalue -> bool
|
||||
otherwise. Similar to [llvm::isa<UndefValue>]. *)
|
||||
val is_undef : llvalue -> bool
|
||||
|
||||
|
||||
val constexpr_opcode : llvalue -> Opcode.t
|
||||
(** {7 Operations on instructions} *)
|
||||
|
||||
(** [has_metadata i] returns whether or not the instruction [i] has any
|
||||
@ -567,6 +697,14 @@ val mdstring : llcontext -> string -> llvalue
|
||||
See the method [llvm::MDNode::get]. *)
|
||||
val mdnode : llcontext -> llvalue array -> llvalue
|
||||
|
||||
(** [get_mdstring v] returns the MDString.
|
||||
* See the method [llvm::MDString::getString] *)
|
||||
val get_mdstring : llvalue -> string option
|
||||
|
||||
(** [get_named_metadata m name] return all the MDNodes belonging to the named
|
||||
* metadata (if any).
|
||||
* See the method [llvm::NamedMDNode::getOperand]. *)
|
||||
val get_named_metadata : llmodule -> string -> llvalue array
|
||||
|
||||
(** {7 Operations on scalar constants} *)
|
||||
|
||||
@ -578,6 +716,10 @@ val const_int : lltype -> int -> llvalue
|
||||
[i]. See the method [llvm::ConstantInt::get]. *)
|
||||
val const_of_int64 : lltype -> Int64.t -> bool -> llvalue
|
||||
|
||||
(** [int64_of_const c] returns the int64 value of the [c] constant integer.
|
||||
* None is returned if this is not an integer constant, or bitwidth exceeds 64.
|
||||
* See the method [llvm::ConstantInt::getSExtValue].*)
|
||||
val int64_of_const : llvalue -> Int64.t option
|
||||
|
||||
(** [const_int_of_string ty s r] returns the integer constant of type [ty] and
|
||||
* value [s], with the radix [r]. See the method [llvm::ConstantInt::get]. *)
|
||||
@ -618,9 +760,14 @@ val const_array : lltype -> llvalue array -> llvalue
|
||||
(** [const_struct context elts] returns the structured constant of type
|
||||
[struct_type (Array.map type_of elts)] and containing the values [elts]
|
||||
in the context [context]. This value can in turn be used as the initializer
|
||||
for a global variable. See the method [llvm::ConstantStruct::get]. *)
|
||||
for a global variable. See the method [llvm::ConstantStruct::getAnon]. *)
|
||||
val const_struct : llcontext -> llvalue array -> llvalue
|
||||
|
||||
(** [const_named_struct namedty elts] returns the structured constant of type
|
||||
[namedty] (which must be a named structure type) and containing the values [elts].
|
||||
This value can in turn be used as the initializer
|
||||
for a global variable. See the method [llvm::ConstantStruct::get]. *)
|
||||
val const_named_struct : lltype -> llvalue array -> llvalue
|
||||
|
||||
(** [const_packed_struct context elts] returns the structured constant of
|
||||
type {!packed_struct_type} [(Array.map type_of elts)] and containing the
|
||||
@ -1231,6 +1378,10 @@ val set_gc : string option -> llvalue -> unit
|
||||
[f]. *)
|
||||
val add_function_attr : llvalue -> Attribute.t -> unit
|
||||
|
||||
(** [function_attr f] returns the function attribute for the function [f].
|
||||
* See the method [llvm::Function::getAttributes] *)
|
||||
val function_attr : llvalue -> Attribute.t list
|
||||
|
||||
(** [remove_function_attr f a] removes attribute [a] from the return type of
|
||||
function [f]. *)
|
||||
val remove_function_attr : llvalue -> Attribute.t -> unit
|
||||
@ -1245,6 +1396,11 @@ val params : llvalue -> llvalue array
|
||||
See the method [llvm::Function::getArgumentList]. *)
|
||||
val param : llvalue -> int -> llvalue
|
||||
|
||||
(** [param_attr p] returns the attributes of parameter [p].
|
||||
* See the methods [llvm::Function::getAttributes] and
|
||||
* [llvm::Attributes::getParamAttributes] *)
|
||||
val param_attr : llvalue -> Attribute.t list
|
||||
|
||||
(** [param_parent p] returns the parent function that owns the parameter.
|
||||
See the method [llvm::Argument::getParent]. *)
|
||||
val param_parent : llvalue -> llvalue
|
||||
@ -1359,6 +1515,7 @@ val block_end : llvalue -> (llvalue, llbasicblock) llrev_pos
|
||||
See the method [llvm::Function::iterator::operator--]. *)
|
||||
val block_pred : llbasicblock -> (llvalue, llbasicblock) llrev_pos
|
||||
|
||||
val block_terminator : llbasicblock -> llvalue option
|
||||
|
||||
(** [rev_iter_blocks f fn] applies function [f] to each of the basic blocks
|
||||
of function [fn] in reverse order. Tail recursive. *)
|
||||
@ -1422,6 +1579,9 @@ val instr_pred : llvalue -> (llbasicblock, llvalue) llrev_pos
|
||||
[f1,...,fN] are the instructions of basic block [bb]. Tail recursive. *)
|
||||
val fold_right_instrs: (llvalue -> 'a -> 'a) -> llbasicblock -> 'a -> 'a
|
||||
|
||||
val instr_opcode : llvalue -> Opcode.t
|
||||
|
||||
val icmp_predicate : llvalue -> Icmp.t option
|
||||
|
||||
(** {7 Operations on call sites} *)
|
||||
|
||||
@ -1473,7 +1633,9 @@ val add_incoming : (llvalue * llbasicblock) -> llvalue -> unit
|
||||
See the method [llvm::PHINode::getIncomingValue]. *)
|
||||
val incoming : llvalue -> (llvalue * llbasicblock) list
|
||||
|
||||
|
||||
(** [delete_instruction i] deletes the instruction [i].
|
||||
* See the method [llvm::Instruction::eraseFromParent]. *)
|
||||
val delete_instruction : llvalue -> unit
|
||||
|
||||
(** {6 Instruction builders} *)
|
||||
|
||||
@ -1587,12 +1749,30 @@ val build_cond_br : llvalue -> llbasicblock -> llbasicblock -> llbuilder ->
|
||||
See the method [llvm::LLVMBuilder::CreateSwitch]. *)
|
||||
val build_switch : llvalue -> llbasicblock -> int -> llbuilder -> llvalue
|
||||
|
||||
(** [build_malloc ty name b] creates an [malloc]
|
||||
instruction at the position specified by the instruction builder [b].
|
||||
See the method [llvm::CallInst::CreateMalloc]. *)
|
||||
val build_malloc : lltype -> string -> llbuilder -> llvalue
|
||||
|
||||
(** [build_array_malloc ty val name b] creates an [array malloc]
|
||||
instruction at the position specified by the instruction builder [b].
|
||||
See the method [llvm::CallInst::CreateArrayMalloc]. *)
|
||||
val build_array_malloc : lltype -> llvalue -> string -> llbuilder -> llvalue
|
||||
|
||||
(** [build_free p b] creates a [free]
|
||||
instruction at the position specified by the instruction builder [b].
|
||||
See the method [llvm::LLVMBuilder::CreateFree]. *)
|
||||
val build_free : llvalue -> llbuilder -> llvalue
|
||||
|
||||
(** [add_case sw onval bb] causes switch instruction [sw] to branch to [bb]
|
||||
when its input matches the constant [onval].
|
||||
See the method [llvm::SwitchInst::addCase]. **)
|
||||
val add_case : llvalue -> llvalue -> llbasicblock -> unit
|
||||
|
||||
(** [switch_default_dest sw] returns the default destination of the [switch]
|
||||
* instruction.
|
||||
* See the method [llvm:;SwitchInst::getDefaultDest]. **)
|
||||
val switch_default_dest : llvalue -> llbasicblock
|
||||
|
||||
(** [build_indirect_br addr count b] creates a
|
||||
[indirectbr %addr]
|
||||
@ -1615,12 +1795,25 @@ val add_destination : llvalue -> llbasicblock -> unit
|
||||
val build_invoke : llvalue -> llvalue array -> llbasicblock ->
|
||||
llbasicblock -> string -> llbuilder -> llvalue
|
||||
|
||||
|
||||
(** [build_unwind b] creates an
|
||||
[unwind]
|
||||
(** [build_landingpad ty persfn numclauses name b] creates an
|
||||
[landingpad]
|
||||
instruction at the position specified by the instruction builder [b].
|
||||
See the method [llvm::LLVMBuilder::CreateUnwind]. *)
|
||||
val build_unwind : llbuilder -> llvalue
|
||||
See the method [llvm::LLVMBuilder::CreateLandingPad]. *)
|
||||
val build_landingpad : lltype -> llvalue -> int -> string -> llbuilder ->
|
||||
llvalue
|
||||
|
||||
(** [set_cleanup lp] sets the cleanup flag in the [landingpad]instruction.
|
||||
See the method [llvm::LandingPadInst::setCleanup]. *)
|
||||
val set_cleanup : llvalue -> bool -> unit
|
||||
|
||||
(** [add_clause lp clause] adds the clause to the [landingpad]instruction.
|
||||
See the method [llvm::LandingPadInst::addClause]. *)
|
||||
val add_clause : llvalue -> llvalue -> unit
|
||||
|
||||
(* [build_resume exn b] builds a [resume exn] instruction
|
||||
* at the position specified by the instruction builder [b].
|
||||
* See the method [llvm::LLVMBuilder::CreateResume] *)
|
||||
val build_resume : llvalue -> llbuilder -> llvalue
|
||||
|
||||
(** [build_unreachable b] creates an
|
||||
[unreachable]
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "llvm/Config/config.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Can't use the recommended caml_named_value mechanism for backwards
|
||||
@ -171,6 +172,10 @@ CAMLprim value llvm_classify_type(LLVMTypeRef Ty) {
|
||||
return Val_int(LLVMGetTypeKind(Ty));
|
||||
}
|
||||
|
||||
CAMLprim value llvm_type_is_sized(LLVMTypeRef Ty) {
|
||||
return Val_bool(LLVMTypeIsSized(Ty));
|
||||
}
|
||||
|
||||
/* lltype -> llcontext */
|
||||
CAMLprim LLVMContextRef llvm_type_context(LLVMTypeRef Ty) {
|
||||
return LLVMGetTypeContext(Ty);
|
||||
@ -287,6 +292,34 @@ CAMLprim LLVMTypeRef llvm_packed_struct_type(LLVMContextRef C,
|
||||
Wosize_val(ElementTypes), 1);
|
||||
}
|
||||
|
||||
/* llcontext -> string -> lltype */
|
||||
CAMLprim LLVMTypeRef llvm_named_struct_type(LLVMContextRef C,
|
||||
value Name) {
|
||||
return LLVMStructCreateNamed(C, String_val(Name));
|
||||
}
|
||||
|
||||
CAMLprim value llvm_struct_set_body(LLVMTypeRef Ty,
|
||||
value ElementTypes,
|
||||
value Packed) {
|
||||
LLVMStructSetBody(Ty, (LLVMTypeRef *) ElementTypes,
|
||||
Wosize_val(ElementTypes), Bool_val(Packed));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* lltype -> string option */
|
||||
CAMLprim value llvm_struct_name(LLVMTypeRef Ty)
|
||||
{
|
||||
CAMLparam0();
|
||||
const char *C = LLVMGetStructName(Ty);
|
||||
if (C) {
|
||||
CAMLlocal1(result);
|
||||
result = caml_alloc_small(1, 0);
|
||||
Store_field(result, 0, caml_copy_string(C));
|
||||
CAMLreturn(result);
|
||||
}
|
||||
CAMLreturn(Val_int(0));
|
||||
}
|
||||
|
||||
/* lltype -> lltype array */
|
||||
CAMLprim value llvm_struct_element_types(LLVMTypeRef StructTy) {
|
||||
value Tys = alloc(LLVMCountStructElementTypes(StructTy), 0);
|
||||
@ -299,6 +332,11 @@ CAMLprim value llvm_is_packed(LLVMTypeRef StructTy) {
|
||||
return Val_bool(LLVMIsPackedStruct(StructTy));
|
||||
}
|
||||
|
||||
/* lltype -> bool */
|
||||
CAMLprim value llvm_is_opaque(LLVMTypeRef StructTy) {
|
||||
return Val_bool(LLVMIsOpaqueStruct(StructTy));
|
||||
}
|
||||
|
||||
/*--... Operations on array, pointer, and vector types .....................--*/
|
||||
|
||||
/* lltype -> int -> lltype */
|
||||
@ -349,6 +387,18 @@ CAMLprim LLVMTypeRef llvm_label_type(LLVMContextRef Context) {
|
||||
return LLVMLabelTypeInContext(Context);
|
||||
}
|
||||
|
||||
CAMLprim value llvm_type_by_name(LLVMModuleRef M, value Name)
|
||||
{
|
||||
CAMLparam1(Name);
|
||||
LLVMTypeRef Ty = LLVMGetTypeByName(M, String_val(Name));
|
||||
if (Ty) {
|
||||
value Option = alloc(1, 0);
|
||||
Field(Option, 0) = (value) Ty;
|
||||
CAMLreturn(Option);
|
||||
}
|
||||
CAMLreturn(Val_int(0));
|
||||
}
|
||||
|
||||
/*===-- VALUES ------------------------------------------------------------===*/
|
||||
|
||||
/* llvalue -> lltype */
|
||||
@ -356,6 +406,69 @@ CAMLprim LLVMTypeRef llvm_type_of(LLVMValueRef Val) {
|
||||
return LLVMTypeOf(Val);
|
||||
}
|
||||
|
||||
/* keep in sync with ValueKind.t */
|
||||
enum ValueKind {
|
||||
NullValue=0,
|
||||
Argument,
|
||||
BasicBlock,
|
||||
InlineAsm,
|
||||
MDNode,
|
||||
MDString,
|
||||
BlockAddress,
|
||||
ConstantAggregateZero,
|
||||
ConstantArray,
|
||||
ConstantExpr,
|
||||
ConstantFP,
|
||||
ConstantInt,
|
||||
ConstantPointerNull,
|
||||
ConstantStruct,
|
||||
ConstantVector,
|
||||
Function,
|
||||
GlobalAlias,
|
||||
GlobalVariable,
|
||||
UndefValue,
|
||||
Instruction
|
||||
};
|
||||
|
||||
/* llvalue -> ValueKind.t */
|
||||
#define DEFINE_CASE(Val, Kind) \
|
||||
do {if (LLVMIsA##Kind(Val)) CAMLreturn(Val_int(Kind));} while(0)
|
||||
|
||||
CAMLprim value llvm_classify_value(LLVMValueRef Val) {
|
||||
CAMLparam0();
|
||||
if (!Val)
|
||||
CAMLreturn(Val_int(NullValue));
|
||||
if (LLVMIsAConstant(Val)) {
|
||||
DEFINE_CASE(Val, BlockAddress);
|
||||
DEFINE_CASE(Val, ConstantAggregateZero);
|
||||
DEFINE_CASE(Val, ConstantArray);
|
||||
DEFINE_CASE(Val, ConstantExpr);
|
||||
DEFINE_CASE(Val, ConstantFP);
|
||||
DEFINE_CASE(Val, ConstantInt);
|
||||
DEFINE_CASE(Val, ConstantPointerNull);
|
||||
DEFINE_CASE(Val, ConstantStruct);
|
||||
DEFINE_CASE(Val, ConstantVector);
|
||||
}
|
||||
if (LLVMIsAInstruction(Val)) {
|
||||
CAMLlocal1(result);
|
||||
result = caml_alloc_small(1, 0);
|
||||
Store_field(result, 0, Val_int(LLVMGetInstructionOpcode(Val)));
|
||||
CAMLreturn(result);
|
||||
}
|
||||
if (LLVMIsAGlobalValue(Val)) {
|
||||
DEFINE_CASE(Val, Function);
|
||||
DEFINE_CASE(Val, GlobalAlias);
|
||||
DEFINE_CASE(Val, GlobalVariable);
|
||||
}
|
||||
DEFINE_CASE(Val, Argument);
|
||||
DEFINE_CASE(Val, BasicBlock);
|
||||
DEFINE_CASE(Val, InlineAsm);
|
||||
DEFINE_CASE(Val, MDNode);
|
||||
DEFINE_CASE(Val, MDString);
|
||||
DEFINE_CASE(Val, UndefValue);
|
||||
failwith("Unknown Value class");
|
||||
}
|
||||
|
||||
/* llvalue -> string */
|
||||
CAMLprim value llvm_value_name(LLVMValueRef Val) {
|
||||
return copy_string(LLVMGetValueName(Val));
|
||||
@ -408,6 +521,12 @@ CAMLprim value llvm_is_undef(LLVMValueRef Val) {
|
||||
return Val_bool(LLVMIsUndef(Val));
|
||||
}
|
||||
|
||||
/* llvalue -> Opcode.t */
|
||||
CAMLprim value llvm_constexpr_get_opcode(LLVMValueRef Val) {
|
||||
return LLVMIsAConstantExpr(Val) ?
|
||||
Val_int(LLVMGetConstOpcode(Val)) : Val_int(0);
|
||||
}
|
||||
|
||||
/*--... Operations on instructions .........................................--*/
|
||||
|
||||
/* llvalue -> bool */
|
||||
@ -454,6 +573,32 @@ CAMLprim LLVMValueRef llvm_mdnode(LLVMContextRef C, value ElementVals) {
|
||||
Wosize_val(ElementVals));
|
||||
}
|
||||
|
||||
/* llvalue -> string option */
|
||||
CAMLprim value llvm_get_mdstring(LLVMValueRef V) {
|
||||
CAMLparam0();
|
||||
const char *S;
|
||||
unsigned Len;
|
||||
|
||||
if ((S = LLVMGetMDString(V, &Len))) {
|
||||
CAMLlocal2(Option, Str);
|
||||
|
||||
Str = caml_alloc_string(Len);
|
||||
memcpy(String_val(Str), S, Len);
|
||||
Option = alloc(1,0);
|
||||
Store_field(Option, 0, Str);
|
||||
CAMLreturn(Option);
|
||||
}
|
||||
CAMLreturn(Val_int(0));
|
||||
}
|
||||
|
||||
CAMLprim value llvm_get_namedmd(LLVMModuleRef M, value name)
|
||||
{
|
||||
CAMLparam1(name);
|
||||
CAMLlocal1(Nodes);
|
||||
Nodes = alloc(LLVMGetNamedMetadataNumOperands(M, String_val(name)), 0);
|
||||
LLVMGetNamedMetadataOperands(M, String_val(name), (LLVMValueRef *) Nodes);
|
||||
CAMLreturn(Nodes);
|
||||
}
|
||||
/*--... Operations on scalar constants .....................................--*/
|
||||
|
||||
/* lltype -> int -> llvalue */
|
||||
@ -467,6 +612,19 @@ CAMLprim LLVMValueRef llvm_const_of_int64(LLVMTypeRef IntTy, value N,
|
||||
return LLVMConstInt(IntTy, Int64_val(N), Bool_val(SExt));
|
||||
}
|
||||
|
||||
/* llvalue -> Int64.t */
|
||||
CAMLprim value llvm_int64_of_const(LLVMValueRef Const)
|
||||
{
|
||||
CAMLparam0();
|
||||
if (LLVMIsAConstantInt(Const) &&
|
||||
LLVMGetIntTypeWidth(LLVMTypeOf(Const)) <= 64) {
|
||||
value Option = alloc(1, 0);
|
||||
Field(Option, 0) = caml_copy_int64(LLVMConstIntGetSExtValue(Const));
|
||||
CAMLreturn(Option);
|
||||
}
|
||||
CAMLreturn(Val_int(0));
|
||||
}
|
||||
|
||||
/* lltype -> string -> int -> llvalue */
|
||||
CAMLprim LLVMValueRef llvm_const_int_of_string(LLVMTypeRef IntTy, value S,
|
||||
value Radix) {
|
||||
@ -514,6 +672,11 @@ CAMLprim LLVMValueRef llvm_const_struct(LLVMContextRef C, value ElementVals) {
|
||||
Wosize_val(ElementVals), 0);
|
||||
}
|
||||
|
||||
/* lltype -> llvalue array -> llvalue */
|
||||
CAMLprim LLVMValueRef llvm_const_named_struct(LLVMTypeRef Ty, value ElementVals) {
|
||||
return LLVMConstNamedStruct(Ty, (LLVMValueRef *) Op_val(ElementVals), Wosize_val(ElementVals));
|
||||
}
|
||||
|
||||
/* llcontext -> llvalue array -> llvalue */
|
||||
CAMLprim LLVMValueRef llvm_const_packed_struct(LLVMContextRef C,
|
||||
value ElementVals) {
|
||||
@ -883,15 +1046,22 @@ CAMLprim value llvm_set_gc(value GC, LLVMValueRef Fn) {
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* llvalue -> Attribute.t -> unit */
|
||||
/* llvalue -> int32 -> unit */
|
||||
CAMLprim value llvm_add_function_attr(LLVMValueRef Arg, value PA) {
|
||||
LLVMAddFunctionAttr(Arg, Int_val(PA));
|
||||
LLVMAddFunctionAttr(Arg, Int32_val(PA));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* llvalue -> Attribute.t -> unit */
|
||||
/* llvalue -> int32 */
|
||||
CAMLprim value llvm_function_attr(LLVMValueRef Fn)
|
||||
{
|
||||
CAMLparam0();
|
||||
CAMLreturn(caml_copy_int32(LLVMGetFunctionAttr(Fn)));
|
||||
}
|
||||
|
||||
/* llvalue -> int32 -> unit */
|
||||
CAMLprim value llvm_remove_function_attr(LLVMValueRef Arg, value PA) {
|
||||
LLVMRemoveFunctionAttr(Arg, Int_val(PA));
|
||||
LLVMRemoveFunctionAttr(Arg, Int32_val(PA));
|
||||
return Val_unit;
|
||||
}
|
||||
/*--... Operations on parameters ...........................................--*/
|
||||
@ -903,6 +1073,13 @@ CAMLprim LLVMValueRef llvm_param(LLVMValueRef Fn, value Index) {
|
||||
return LLVMGetParam(Fn, Int_val(Index));
|
||||
}
|
||||
|
||||
/* llvalue -> int */
|
||||
CAMLprim value llvm_param_attr(LLVMValueRef Param)
|
||||
{
|
||||
CAMLparam0();
|
||||
CAMLreturn(caml_copy_int32(LLVMGetAttribute(Param)));
|
||||
}
|
||||
|
||||
/* llvalue -> llvalue */
|
||||
CAMLprim value llvm_params(LLVMValueRef Fn) {
|
||||
value Params = alloc(LLVMCountParams(Fn), 0);
|
||||
@ -910,15 +1087,15 @@ CAMLprim value llvm_params(LLVMValueRef Fn) {
|
||||
return Params;
|
||||
}
|
||||
|
||||
/* llvalue -> Attribute.t -> unit */
|
||||
/* llvalue -> int32 -> unit */
|
||||
CAMLprim value llvm_add_param_attr(LLVMValueRef Arg, value PA) {
|
||||
LLVMAddAttribute(Arg, Int_val(PA));
|
||||
LLVMAddAttribute(Arg, Int32_val(PA));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* llvalue -> Attribute.t -> unit */
|
||||
/* llvalue -> int32 -> unit */
|
||||
CAMLprim value llvm_remove_param_attr(LLVMValueRef Arg, value PA) {
|
||||
LLVMRemoveAttribute(Arg, Int_val(PA));
|
||||
LLVMRemoveAttribute(Arg, Int32_val(PA));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
@ -933,6 +1110,19 @@ CAMLprim value llvm_set_param_alignment(LLVMValueRef Arg, value align) {
|
||||
DEFINE_ITERATORS(
|
||||
block, BasicBlock, LLVMValueRef, LLVMBasicBlockRef, LLVMGetBasicBlockParent)
|
||||
|
||||
/* llbasicblock -> llvalue option */
|
||||
CAMLprim value llvm_block_terminator(LLVMBasicBlockRef Block)
|
||||
{
|
||||
CAMLparam0();
|
||||
LLVMValueRef Term = LLVMGetBasicBlockTerminator(Block);
|
||||
if (Term) {
|
||||
value Option = alloc(1, 0);
|
||||
Field(Option, 0) = (value) Term;
|
||||
CAMLreturn(Option);
|
||||
}
|
||||
CAMLreturn(Val_int(0));
|
||||
}
|
||||
|
||||
/* llvalue -> llbasicblock array */
|
||||
CAMLprim value llvm_basic_blocks(LLVMValueRef Fn) {
|
||||
value MLArray = alloc(LLVMCountBasicBlocks(Fn), 0);
|
||||
@ -968,6 +1158,28 @@ CAMLprim value llvm_value_is_block(LLVMValueRef Val) {
|
||||
DEFINE_ITERATORS(instr, Instruction, LLVMBasicBlockRef, LLVMValueRef,
|
||||
LLVMGetInstructionParent)
|
||||
|
||||
/* llvalue -> Opcode.t */
|
||||
CAMLprim value llvm_instr_get_opcode(LLVMValueRef Inst) {
|
||||
LLVMOpcode o;
|
||||
if (!LLVMIsAInstruction(Inst))
|
||||
failwith("Not an instruction");
|
||||
o = LLVMGetInstructionOpcode(Inst);
|
||||
assert (o <= LLVMUnwind );
|
||||
return Val_int(o);
|
||||
}
|
||||
|
||||
/* llvalue -> ICmp.t */
|
||||
CAMLprim value llvm_instr_icmp_predicate(LLVMValueRef Val) {
|
||||
CAMLparam0();
|
||||
int x = LLVMGetICmpPredicate(Val);
|
||||
if (x) {
|
||||
value Option = alloc(1, 0);
|
||||
Field(Option, 0) = Val_int(x - LLVMIntEQ);
|
||||
CAMLreturn(Option);
|
||||
}
|
||||
CAMLreturn(Val_int(0));
|
||||
}
|
||||
|
||||
|
||||
/*--... Operations on call sites ...........................................--*/
|
||||
|
||||
@ -982,19 +1194,19 @@ CAMLprim value llvm_set_instruction_call_conv(value CC, LLVMValueRef Inst) {
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* llvalue -> int -> Attribute.t -> unit */
|
||||
/* llvalue -> int -> int32 -> unit */
|
||||
CAMLprim value llvm_add_instruction_param_attr(LLVMValueRef Instr,
|
||||
value index,
|
||||
value PA) {
|
||||
LLVMAddInstrAttribute(Instr, Int_val(index), Int_val(PA));
|
||||
LLVMAddInstrAttribute(Instr, Int_val(index), Int32_val(PA));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* llvalue -> int -> Attribute.t -> unit */
|
||||
/* llvalue -> int -> int32 -> unit */
|
||||
CAMLprim value llvm_remove_instruction_param_attr(LLVMValueRef Instr,
|
||||
value index,
|
||||
value PA) {
|
||||
LLVMRemoveInstrAttribute(Instr, Int_val(index), Int_val(PA));
|
||||
LLVMRemoveInstrAttribute(Instr, Int_val(index), Int32_val(PA));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
@ -1045,6 +1257,11 @@ CAMLprim value llvm_incoming(LLVMValueRef PhiNode) {
|
||||
CAMLreturn(Tl);
|
||||
}
|
||||
|
||||
/* llvalue -> unit */
|
||||
CAMLprim value llvm_delete_instruction(LLVMValueRef Instruction) {
|
||||
LLVMInstructionEraseFromParent(Instruction);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/*===-- Instruction builders ----------------------------------------------===*/
|
||||
|
||||
@ -1172,6 +1389,27 @@ CAMLprim LLVMValueRef llvm_build_switch(LLVMValueRef Of,
|
||||
return LLVMBuildSwitch(Builder_val(B), Of, Else, Int_val(EstimatedCount));
|
||||
}
|
||||
|
||||
/* lltype -> string -> llbuilder -> llvalue */
|
||||
CAMLprim LLVMValueRef llvm_build_malloc(LLVMTypeRef Ty, value Name,
|
||||
value B)
|
||||
{
|
||||
return LLVMBuildMalloc(Builder_val(B), Ty, String_val(Name));
|
||||
}
|
||||
|
||||
/* lltype -> llvalue -> string -> llbuilder -> llvalue */
|
||||
CAMLprim LLVMValueRef llvm_build_array_malloc(LLVMTypeRef Ty,
|
||||
LLVMValueRef Val,
|
||||
value Name, value B)
|
||||
{
|
||||
return LLVMBuildArrayMalloc(Builder_val(B), Ty, Val, String_val(Name));
|
||||
}
|
||||
|
||||
/* llvalue -> llbuilder -> llvalue */
|
||||
CAMLprim LLVMValueRef llvm_build_free(LLVMValueRef P, value B)
|
||||
{
|
||||
return LLVMBuildFree(Builder_val(B), P);
|
||||
}
|
||||
|
||||
/* llvalue -> llvalue -> llbasicblock -> unit */
|
||||
CAMLprim value llvm_add_case(LLVMValueRef Switch, LLVMValueRef OnVal,
|
||||
LLVMBasicBlockRef Dest) {
|
||||
@ -1212,9 +1450,33 @@ CAMLprim LLVMValueRef llvm_build_invoke_bc(value Args[], int NumArgs) {
|
||||
Args[4], Args[5]);
|
||||
}
|
||||
|
||||
/* llbuilder -> llvalue */
|
||||
CAMLprim LLVMValueRef llvm_build_unwind(value B) {
|
||||
return LLVMBuildUnwind(Builder_val(B));
|
||||
/* lltype -> llvalue -> int -> string -> llbuilder -> llvalue */
|
||||
CAMLprim LLVMValueRef llvm_build_landingpad(LLVMTypeRef Ty, LLVMValueRef PersFn,
|
||||
value NumClauses, value Name,
|
||||
value B) {
|
||||
return LLVMBuildLandingPad(Builder_val(B), Ty, PersFn, Int_val(NumClauses),
|
||||
String_val(Name));
|
||||
}
|
||||
|
||||
/* llvalue -> llvalue -> unit */
|
||||
CAMLprim value llvm_add_clause(LLVMValueRef LandingPadInst, LLVMValueRef ClauseVal)
|
||||
{
|
||||
LLVMAddClause(LandingPadInst, ClauseVal);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
|
||||
/* llvalue -> bool -> unit */
|
||||
CAMLprim value llvm_set_cleanup(LLVMValueRef LandingPadInst, value flag)
|
||||
{
|
||||
LLVMSetCleanup(LandingPadInst, Bool_val(flag));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* llvalue -> llbuilder -> llvalue */
|
||||
CAMLprim LLVMValueRef llvm_build_resume(LLVMValueRef Exn, value B)
|
||||
{
|
||||
return LLVMBuildResume(Builder_val(B), Exn);
|
||||
}
|
||||
|
||||
/* llbuilder -> llvalue */
|
||||
|
@ -20,8 +20,6 @@ module TargetData = struct
|
||||
external add : t -> [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_targetdata_add"
|
||||
external as_string : t -> string = "llvm_targetdata_as_string"
|
||||
external invalidate_struct_layout : t -> Llvm.lltype -> unit
|
||||
= "llvm_targetdata_invalidate_struct_layout"
|
||||
external dispose : t -> unit = "llvm_targetdata_dispose"
|
||||
end
|
||||
|
||||
|
@ -35,13 +35,6 @@ module TargetData : sig
|
||||
See the constructor llvm::TargetData::TargetData. *)
|
||||
external as_string : t -> string = "llvm_targetdata_as_string"
|
||||
|
||||
(** Struct layouts are speculatively cached. If a TargetDataRef is alive when
|
||||
types are being refined and removed, this method must be called whenever a
|
||||
struct type is removed to avoid a dangling pointer in this cache.
|
||||
See the method llvm::TargetData::InvalidateStructLayoutInfo. *)
|
||||
external invalidate_struct_layout : t -> Llvm.lltype -> unit
|
||||
= "llvm_targetdata_invalidate_struct_layout"
|
||||
|
||||
(** Deallocates a TargetData.
|
||||
See the destructor llvm::TargetData::~TargetData. *)
|
||||
external dispose : t -> unit = "llvm_targetdata_dispose"
|
||||
|
@ -37,13 +37,6 @@ CAMLprim value llvm_targetdata_as_string(LLVMTargetDataRef TD) {
|
||||
return Copy;
|
||||
}
|
||||
|
||||
/* TargetData.t -> Llvm.lltype -> unit */
|
||||
CAMLprim value llvm_targetdata_invalidate_struct_layout(LLVMTargetDataRef TD,
|
||||
LLVMTypeRef Ty) {
|
||||
LLVMInvalidateStructLayout(TD, Ty);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* TargetData.t -> unit */
|
||||
CAMLprim value llvm_targetdata_dispose(LLVMTargetDataRef TD) {
|
||||
LLVMDisposeTargetData(TD);
|
||||
|
@ -8,7 +8,7 @@
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL := ../../..
|
||||
DIRS = scalar
|
||||
DIRS = scalar ipo
|
||||
|
||||
ocamldoc:
|
||||
$(Verb) for i in $(DIRS) ; do \
|
||||
|
20
bindings/ocaml/transforms/ipo/Makefile
Normal file
20
bindings/ocaml/transforms/ipo/Makefile
Normal file
@ -0,0 +1,20 @@
|
||||
##===- bindings/ocaml/transforms/scalar/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 Llvm_scalar_opts interface.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL := ../../../..
|
||||
LIBRARYNAME := llvm_ipo
|
||||
DONT_BUILD_RELINKED := 1
|
||||
UsedComponents := ipo
|
||||
UsedOcamlInterfaces := llvm
|
||||
|
||||
include ../../Makefile.ocaml
|
104
bindings/ocaml/transforms/ipo/ipo_ocaml.c
Normal file
104
bindings/ocaml/transforms/ipo/ipo_ocaml.c
Normal file
@ -0,0 +1,104 @@
|
||||
/*===-- ipo_ocaml.c - LLVM Ocaml Glue -------------------*- C++ -*-===*\
|
||||
|* *|
|
||||
|* The LLVM Compiler Infrastructure *|
|
||||
|* *|
|
||||
|* This file is distributed under the University of Illinois Open Source *|
|
||||
|* License. See LICENSE.TXT for details. *|
|
||||
|* *|
|
||||
|*===----------------------------------------------------------------------===*|
|
||||
|* *|
|
||||
|* This file glues LLVM's ocaml interface to its C interface. These functions *|
|
||||
|* are by and large transparent wrappers to the corresponding C functions. *|
|
||||
|* *|
|
||||
|* Note that these functions intentionally take liberties with the CAMLparamX *|
|
||||
|* macros, since most of the parameters are not GC heap objects. *|
|
||||
|* *|
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#include "llvm-c/Transforms/IPO.h"
|
||||
#include "caml/mlvalues.h"
|
||||
#include "caml/misc.h"
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_argument_promotion(LLVMPassManagerRef PM) {
|
||||
LLVMAddArgumentPromotionPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_constant_merge(LLVMPassManagerRef PM) {
|
||||
LLVMAddConstantMergePass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_dead_arg_elimination(LLVMPassManagerRef PM) {
|
||||
LLVMAddDeadArgEliminationPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_function_attrs(LLVMPassManagerRef PM) {
|
||||
LLVMAddFunctionAttrsPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_function_inlining(LLVMPassManagerRef PM) {
|
||||
LLVMAddFunctionInliningPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_always_inliner_pass(LLVMPassManagerRef PM) {
|
||||
LLVMAddAlwaysInlinerPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_global_dce(LLVMPassManagerRef PM) {
|
||||
LLVMAddGlobalDCEPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_global_optimizer(LLVMPassManagerRef PM) {
|
||||
LLVMAddGlobalOptimizerPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_ipc_propagation(LLVMPassManagerRef PM) {
|
||||
LLVMAddIPConstantPropagationPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_prune_eh(LLVMPassManagerRef PM) {
|
||||
LLVMAddPruneEHPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_ipsccp(LLVMPassManagerRef PM) {
|
||||
LLVMAddIPSCCPPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> bool -> unit */
|
||||
CAMLprim value llvm_add_internalize(LLVMPassManagerRef PM, value AllButMain) {
|
||||
LLVMAddInternalizePass(PM, Bool_val(AllButMain));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_strip_dead_prototypes(LLVMPassManagerRef PM) {
|
||||
LLVMAddStripDeadPrototypesPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [`Module] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_strip_symbols(LLVMPassManagerRef PM) {
|
||||
LLVMAddStripSymbolsPass(PM);
|
||||
return Val_unit;
|
||||
}
|
65
bindings/ocaml/transforms/ipo/llvm_ipo.ml
Normal file
65
bindings/ocaml/transforms/ipo/llvm_ipo.ml
Normal file
@ -0,0 +1,65 @@
|
||||
(*===-- llvm_ipo.mli - LLVM Ocaml Interface ------------*- OCaml -*-===*
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is distributed under the University of Illinois Open Source
|
||||
* License. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(** IPO Transforms.
|
||||
|
||||
This interface provides an ocaml API for LLVM interprocedural optimizations, the
|
||||
classes in the [LLVMIPO] library. *)
|
||||
|
||||
(** See llvm::createAddArgumentPromotionPass *)
|
||||
external add_argument_promotion : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_argument_promotion"
|
||||
|
||||
(** See llvm::createConstantMergePass function. *)
|
||||
external add_constant_merge : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_constant_merge"
|
||||
|
||||
(** See llvm::createDeadArgEliminationPass function. *)
|
||||
external add_dead_arg_elimination :
|
||||
[ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_dead_arg_elimination"
|
||||
|
||||
(** See llvm::createFunctionAttrsPass function. *)
|
||||
external add_function_attrs : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_function_attrs"
|
||||
|
||||
(** See llvm::createFunctionInliningPass function. *)
|
||||
external add_function_inlining : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_function_inlining"
|
||||
|
||||
(** See llvm::createGlobalDCEPass function. *)
|
||||
external add_global_dce : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_global_dce"
|
||||
|
||||
(** See llvm::createGlobalOptimizerPass function. *)
|
||||
external add_global_optimizer : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_global_optimizer"
|
||||
|
||||
(** See llvm::createIPConstantPropagationPass function. *)
|
||||
external add_ipc_propagation : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_ipc_propagation"
|
||||
|
||||
(** See llvm::createPruneEHPass function. *)
|
||||
external add_prune_eh : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_prune_eh"
|
||||
|
||||
(** See llvm::createIPSCCPPass function. *)
|
||||
external add_ipsccp : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_ipsccp"
|
||||
|
||||
(** See llvm::createInternalizePass function. *)
|
||||
external add_internalize : [ | `Module ] Llvm.PassManager.t -> bool -> unit =
|
||||
"llvm_add_internalize"
|
||||
|
||||
(** See llvm::createStripDeadPrototypesPass function. *)
|
||||
external add_strip_dead_prototypes :
|
||||
[ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_strip_dead_prototypes"
|
||||
|
||||
(** See llvm::createStripSymbolsPass function. *)
|
||||
external add_strip_symbols : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_strip_symbols"
|
65
bindings/ocaml/transforms/ipo/llvm_ipo.mli
Normal file
65
bindings/ocaml/transforms/ipo/llvm_ipo.mli
Normal file
@ -0,0 +1,65 @@
|
||||
(*===-- llvm_ipo.mli - LLVM Ocaml Interface ------------*- OCaml -*-===*
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is distributed under the University of Illinois Open Source
|
||||
* License. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===*)
|
||||
|
||||
(** IPO Transforms.
|
||||
|
||||
This interface provides an ocaml API for LLVM interprocedural optimizations, the
|
||||
classes in the [LLVMIPO] library. *)
|
||||
|
||||
(** See llvm::createAddArgumentPromotionPass *)
|
||||
external add_argument_promotion : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
|
||||
"llvm_add_argument_promotion"
|
||||
(** See llvm::createConstantMergePass function. *)
|
||||
external add_constant_merge : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_constant_merge"
|
||||
|
||||
(** See llvm::createDeadArgEliminationPass function. *)
|
||||
external add_dead_arg_elimination :
|
||||
[ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_dead_arg_elimination"
|
||||
|
||||
(** See llvm::createFunctionAttrsPass function. *)
|
||||
external add_function_attrs : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_function_attrs"
|
||||
|
||||
(** See llvm::createFunctionInliningPass function. *)
|
||||
external add_function_inlining : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_function_inlining"
|
||||
|
||||
(** See llvm::createGlobalDCEPass function. *)
|
||||
external add_global_dce : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_global_dce"
|
||||
|
||||
(** See llvm::createGlobalOptimizerPass function. *)
|
||||
external add_global_optimizer : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_global_optimizer"
|
||||
|
||||
(** See llvm::createIPConstantPropagationPass function. *)
|
||||
external add_ipc_propagation : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_ipc_propagation"
|
||||
|
||||
(** See llvm::createPruneEHPass function. *)
|
||||
external add_prune_eh : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_prune_eh"
|
||||
|
||||
(** See llvm::createIPSCCPPass function. *)
|
||||
external add_ipsccp : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_ipsccp"
|
||||
|
||||
(** See llvm::createInternalizePass function. *)
|
||||
external add_internalize : [ | `Module ] Llvm.PassManager.t -> bool -> unit =
|
||||
"llvm_add_internalize"
|
||||
|
||||
(** See llvm::createStripDeadPrototypesPass function. *)
|
||||
external add_strip_dead_prototypes :
|
||||
[ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_strip_dead_prototypes"
|
||||
|
||||
(** See llvm::createStripSymbolsPass function. *)
|
||||
external add_strip_symbols : [ | `Module ] Llvm.PassManager.t -> unit =
|
||||
"llvm_add_strip_symbols"
|
@ -20,6 +20,15 @@ external add_aggressive_dce : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
external
|
||||
add_scalar_repl_aggregation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_scalar_repl_aggregation"
|
||||
|
||||
external
|
||||
add_scalar_repl_aggregation_ssa : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_scalar_repl_aggregation_ssa"
|
||||
|
||||
external
|
||||
add_scalar_repl_aggregation_with_threshold : int -> [<Llvm.PassManager.any] Llvm.PassManager.t
|
||||
-> unit
|
||||
= "llvm_add_scalar_repl_aggregation_with_threshold"
|
||||
external add_ind_var_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t
|
||||
-> unit
|
||||
= "llvm_add_ind_var_simplification"
|
||||
@ -67,6 +76,36 @@ external add_memcpy_opt : [<Llvm.PassManager.any] Llvm.PassManager.t
|
||||
external add_loop_deletion : [<Llvm.PassManager.any] Llvm.PassManager.t
|
||||
-> unit
|
||||
= "llvm_add_loop_deletion"
|
||||
|
||||
external add_loop_idiom : [<Llvm.PassManager.any] Llvm.PassManager.t
|
||||
-> unit
|
||||
= "llvm_add_loop_idiom"
|
||||
|
||||
external
|
||||
add_lib_call_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_lib_call_simplification"
|
||||
|
||||
external
|
||||
add_verifier : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_verifier"
|
||||
|
||||
external
|
||||
add_correlated_value_propagation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_correlated_value_propagation"
|
||||
|
||||
external
|
||||
add_early_cse : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_early_cse"
|
||||
|
||||
external
|
||||
add_lower_expect_intrinsic : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_lower_expect_intrinsic"
|
||||
|
||||
external
|
||||
add_type_based_alias_analysis : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_type_based_alias_analysis"
|
||||
|
||||
external
|
||||
add_basic_alias_analysis : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_basic_alias_analysis"
|
||||
|
||||
|
@ -35,6 +35,17 @@ external
|
||||
add_scalar_repl_aggregation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_scalar_repl_aggregation"
|
||||
|
||||
(** See the [llvm::createScalarReplAggregatesPassSSA] function. *)
|
||||
external
|
||||
add_scalar_repl_aggregation_ssa : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_scalar_repl_aggregation_ssa"
|
||||
|
||||
(** See the [llvm::createScalarReplAggregatesWithThreshold] function. *)
|
||||
external
|
||||
add_scalar_repl_aggregation_with_threshold : int -> [<Llvm.PassManager.any] Llvm.PassManager.t
|
||||
-> unit
|
||||
= "llvm_add_scalar_repl_aggregation_with_threshold"
|
||||
|
||||
(** See the [llvm::createIndVarSimplifyPass] function. *)
|
||||
external add_ind_var_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t
|
||||
-> unit
|
||||
@ -112,7 +123,42 @@ external add_loop_deletion : [<Llvm.PassManager.any] Llvm.PassManager.t
|
||||
-> unit
|
||||
= "llvm_add_loop_deletion"
|
||||
|
||||
external add_loop_idiom : [<Llvm.PassManager.any] Llvm.PassManager.t
|
||||
-> unit
|
||||
= "llvm_add_loop_idiom"
|
||||
|
||||
(** See the [llvm::createSimplifyLibCallsPass] function. *)
|
||||
external
|
||||
add_lib_call_simplification : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_lib_call_simplification"
|
||||
|
||||
(** See the [llvm::createVerifierPass] function. *)
|
||||
external
|
||||
add_verifier : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_verifier"
|
||||
|
||||
(** See the [llvm::createCorrelatedValuePropagationPass] function. *)
|
||||
external
|
||||
add_correlated_value_propagation : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_correlated_value_propagation"
|
||||
|
||||
(** See the [llvm::createEarlyCSE] function. *)
|
||||
external
|
||||
add_early_cse : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_early_cse"
|
||||
|
||||
(** See the [llvm::createLowerExpectIntrinsicPass] function. *)
|
||||
external
|
||||
add_lower_expect_intrinsic : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_lower_expect_intrinsic"
|
||||
|
||||
(** See the [llvm::createTypeBasedAliasAnalysisPass] function. *)
|
||||
external
|
||||
add_type_based_alias_analysis : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_type_based_alias_analysis"
|
||||
|
||||
(** See the [llvm::createBasicAliasAnalysisPass] function. *)
|
||||
external
|
||||
add_basic_alias_analysis : [<Llvm.PassManager.any] Llvm.PassManager.t -> unit
|
||||
= "llvm_add_basic_alias_analysis"
|
||||
|
||||
|
@ -49,6 +49,19 @@ CAMLprim value llvm_add_scalar_repl_aggregation(LLVMPassManagerRef PM) {
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_scalar_repl_aggregation_ssa(LLVMPassManagerRef PM) {
|
||||
LLVMAddScalarReplAggregatesPassSSA(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> int -> unit */
|
||||
CAMLprim value llvm_add_scalar_repl_aggregation_with_threshold(value threshold,
|
||||
LLVMPassManagerRef PM) {
|
||||
LLVMAddScalarReplAggregatesPassWithThreshold(PM, Int_val(threshold));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_ind_var_simplification(LLVMPassManagerRef PM) {
|
||||
LLVMAddIndVarSimplifyPass(PM);
|
||||
@ -69,7 +82,7 @@ CAMLprim value llvm_add_licm(LLVMPassManagerRef PM) {
|
||||
|
||||
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_loop_unswitch(LLVMPassManagerRef PM) {
|
||||
LLVMAddLoopUnrollPass(PM);
|
||||
LLVMAddLoopUnswitchPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
@ -139,8 +152,50 @@ CAMLprim value llvm_add_loop_deletion(LLVMPassManagerRef PM) {
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_loop_idiom(LLVMPassManagerRef PM) {
|
||||
LLVMAddLoopIdiomPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_lib_call_simplification(LLVMPassManagerRef PM) {
|
||||
LLVMAddSimplifyLibCallsPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_verifier(LLVMPassManagerRef PM) {
|
||||
LLVMAddVerifierPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_correlated_value_propagation(LLVMPassManagerRef PM) {
|
||||
LLVMAddCorrelatedValuePropagationPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_early_cse(LLVMPassManagerRef PM) {
|
||||
LLVMAddEarlyCSEPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_lower_expect_intrinsic(LLVMPassManagerRef PM) {
|
||||
LLVMAddLowerExpectIntrinsicPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_type_based_alias_analysis(LLVMPassManagerRef PM) {
|
||||
LLVMAddTypeBasedAliasAnalysisPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* [<Llvm.PassManager.any] Llvm.PassManager.t -> unit */
|
||||
CAMLprim value llvm_add_basic_alias_analysis(LLVMPassManagerRef PM) {
|
||||
LLVMAddBasicAliasAnalysisPass(PM);
|
||||
return Val_unit;
|
||||
}
|
||||
|
@ -198,11 +198,6 @@ if( LLVM_USING_GLIBC )
|
||||
add_llvm_definitions( -D_GNU_SOURCE )
|
||||
endif()
|
||||
|
||||
# Type checks
|
||||
check_type_exists(std::bidirectional_iterator<int,int> "iterator;iostream" HAVE_BI_ITERATOR)
|
||||
check_type_exists(std::iterator<int,int,int> iterator HAVE_STD_ITERATOR)
|
||||
check_type_exists(std::forward_iterator<int,int> iterator HAVE_FWD_ITERATOR)
|
||||
|
||||
set(headers "")
|
||||
if (HAVE_SYS_TYPES_H)
|
||||
set(headers ${headers} "sys/types.h")
|
||||
@ -277,7 +272,7 @@ else()
|
||||
unset(HAVE_FFI_CALL CACHE)
|
||||
endif( LLVM_ENABLE_FFI )
|
||||
|
||||
# Define LLVM_MULTITHREADED if gcc atomic builtins exists.
|
||||
# Define LLVM_HAS_ATOMICS if gcc or MSVC atomic builtins are supported.
|
||||
include(CheckAtomic)
|
||||
|
||||
if( LLVM_ENABLE_PIC )
|
||||
@ -336,7 +331,7 @@ else ()
|
||||
message(STATUS "Native target architecture is ${LLVM_NATIVE_ARCH}")
|
||||
set(LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target)
|
||||
set(LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo)
|
||||
set(LLVM_NATIVE_MCASMINFO LLVMInitialize${LLVM_NATIVE_ARCH}MCAsmInfo)
|
||||
set(LLVM_NATIVE_TARGETMC LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC)
|
||||
set(LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter)
|
||||
endif ()
|
||||
|
||||
|
@ -24,16 +24,17 @@ macro(add_llvm_library name)
|
||||
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX})
|
||||
endif()
|
||||
# The LLVM Target library shall be built before its sublibraries
|
||||
# (asmprinter, etc) because those may use tablegenned files which
|
||||
# generation is triggered by the main LLVM target library. Necessary
|
||||
# for parallel builds:
|
||||
if( CURRENT_LLVM_TARGET )
|
||||
add_dependencies(${name} ${CURRENT_LLVM_TARGET})
|
||||
endif()
|
||||
set_target_properties(${name} PROPERTIES FOLDER "Libraries")
|
||||
endmacro(add_llvm_library name)
|
||||
|
||||
macro(add_llvm_library_dependencies name)
|
||||
# Save the dependencies of the LLVM library in a variable so that we can
|
||||
# query it when resolve llvm-config-style component -> library mappings.
|
||||
set_property(GLOBAL PROPERTY LLVM_LIB_DEPS_${name} ${ARGN})
|
||||
|
||||
# Then add the actual dependencies to the library target.
|
||||
target_link_libraries(${name} ${ARGN})
|
||||
endmacro(add_llvm_library_dependencies name)
|
||||
|
||||
macro(add_llvm_loadable_module name)
|
||||
if( NOT LLVM_ON_UNIX OR CYGWIN )
|
||||
@ -124,16 +125,9 @@ endmacro(add_llvm_utility name)
|
||||
|
||||
|
||||
macro(add_llvm_target target_name)
|
||||
if( TABLEGEN_OUTPUT )
|
||||
add_custom_target(${target_name}Table_gen
|
||||
DEPENDS ${TABLEGEN_OUTPUT})
|
||||
add_dependencies(${target_name}Table_gen ${LLVM_COMMON_DEPENDS})
|
||||
endif( TABLEGEN_OUTPUT )
|
||||
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
include_directories(BEFORE
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_llvm_library(LLVM${target_name} ${ARGN} ${TABLEGEN_OUTPUT})
|
||||
if ( TABLEGEN_OUTPUT )
|
||||
add_dependencies(LLVM${target_name} ${target_name}Table_gen)
|
||||
set_target_properties(${target_name}Table_gen PROPERTIES FOLDER "Tablegenning")
|
||||
endif (TABLEGEN_OUTPUT)
|
||||
set( CURRENT_LLVM_TARGET LLVM${target_name} )
|
||||
endmacro(add_llvm_target)
|
||||
|
@ -3,6 +3,12 @@ set(LLVM_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
get_property(llvm_libs GLOBAL PROPERTY LLVM_LIBS)
|
||||
|
||||
foreach(lib ${llvm_libs})
|
||||
get_property(llvm_lib_deps GLOBAL PROPERTY LLVM_LIB_DEPS_${lib})
|
||||
set(all_llvm_lib_deps
|
||||
"${all_llvm_lib_deps}\nset_property(GLOBAL PROPERTY LLVM_LIB_DEPS_${lib} ${llvm_lib_deps})")
|
||||
endforeach(lib)
|
||||
|
||||
configure_file(
|
||||
LLVMConfig.cmake.in
|
||||
${llvm_cmake_builddir}/LLVMConfig.cmake
|
||||
@ -17,7 +23,6 @@ install(FILES
|
||||
${llvm_cmake_builddir}/LLVMConfig.cmake
|
||||
${llvm_cmake_builddir}/LLVMConfigVersion.cmake
|
||||
LLVM-Config.cmake
|
||||
LLVMLibDeps.cmake
|
||||
DESTINATION share/llvm/cmake)
|
||||
|
||||
install(DIRECTORY .
|
||||
@ -27,8 +32,6 @@ install(DIRECTORY .
|
||||
PATTERN LLVMConfig.cmake EXCLUDE
|
||||
PATTERN LLVMConfigVersion.cmake EXCLUDE
|
||||
PATTERN LLVM-Config.cmake EXCLUDE
|
||||
PATTERN LLVMLibDeps.cmake EXCLUDE
|
||||
PATTERN FindBison.cmake EXCLUDE
|
||||
PATTERN GetTargetTriple.cmake EXCLUDE
|
||||
PATTERN VersionFromVCS.cmake EXCLUDE
|
||||
PATTERN CheckAtomic.cmake EXCLUDE)
|
||||
|
@ -22,8 +22,8 @@ int main() {
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
" LLVM_MULTITHREADED)
|
||||
" LLVM_HAS_ATOMICS)
|
||||
|
||||
if( NOT LLVM_MULTITHREADED )
|
||||
if( NOT LLVM_HAS_ATOMICS )
|
||||
message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing")
|
||||
endif()
|
||||
|
@ -1,26 +0,0 @@
|
||||
|
||||
if( ${LLVM_TABLEGEN} STREQUAL "tblgen" )
|
||||
set(CX_NATIVE_TG_DIR "${CMAKE_BINARY_DIR}/native")
|
||||
set(LLVM_TABLEGEN_EXE "${CX_NATIVE_TG_DIR}/bin/tblgen")
|
||||
|
||||
add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CX_NATIVE_TG_DIR}
|
||||
COMMENT "Creating ${CX_NATIVE_TG_DIR}...")
|
||||
|
||||
add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR}/CMakeCache.txt
|
||||
COMMAND ${CMAKE_COMMAND} -UMAKE_TOOLCHAIN_FILE -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR}
|
||||
WORKING_DIRECTORY ${CX_NATIVE_TG_DIR}
|
||||
DEPENDS ${CX_NATIVE_TG_DIR}
|
||||
COMMENT "Configuring native TableGen...")
|
||||
|
||||
add_custom_command(OUTPUT ${LLVM_TABLEGEN_EXE}
|
||||
COMMAND ${CMAKE_BUILD_TOOL}
|
||||
DEPENDS ${CX_NATIVE_TG_DIR}/CMakeCache.txt
|
||||
WORKING_DIRECTORY ${CX_NATIVE_TG_DIR}/utils/TableGen
|
||||
COMMENT "Building native TableGen...")
|
||||
add_custom_target(NativeTableGen DEPENDS ${LLVM_TABLEGEN_EXE})
|
||||
|
||||
add_dependencies(tblgen NativeTableGen)
|
||||
|
||||
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CX_NATIVE_TG_DIR})
|
||||
endif()
|
@ -1,52 +0,0 @@
|
||||
# - Try to find Bison
|
||||
# Once done this will define
|
||||
#
|
||||
# BISON_FOUND - system has Bison
|
||||
# BISON_EXECUTABLE - path of the bison executable
|
||||
# BISON_VERSION - the version string, like "2.5.31"
|
||||
#
|
||||
|
||||
MACRO(FIND_BISON)
|
||||
FIND_PROGRAM(BISON_EXECUTABLE NAMES bison)
|
||||
|
||||
IF(BISON_EXECUTABLE)
|
||||
SET(BISON_FOUND TRUE)
|
||||
|
||||
EXECUTE_PROCESS(COMMAND ${BISON_EXECUTABLE} --version
|
||||
OUTPUT_VARIABLE _BISON_VERSION
|
||||
)
|
||||
string (REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" BISON_VERSION "${_bison_VERSION}")
|
||||
ENDIF(BISON_EXECUTABLE)
|
||||
|
||||
IF(BISON_FOUND)
|
||||
IF(NOT Bison_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found Bison: ${BISON_EXECUTABLE}")
|
||||
ENDIF(NOT Bison_FIND_QUIETLY)
|
||||
ELSE(BISON_FOUND)
|
||||
IF(Bison_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find Bison")
|
||||
ENDIF(Bison_FIND_REQUIRED)
|
||||
ENDIF(BISON_FOUND)
|
||||
ENDMACRO(FIND_BISON)
|
||||
|
||||
MACRO(BISON_GENERATOR _PREFIX _Y_INPUT _H_OUTPUT _CPP_OUTPUT)
|
||||
IF(BISON_EXECUTABLE)
|
||||
GET_FILENAME_COMPONENT(_Y_DIR ${_Y_INPUT} PATH)
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${_CPP_OUTPUT}
|
||||
OUTPUT ${_H_OUTPUT}
|
||||
DEPENDS ${_Y_INPUT}
|
||||
COMMAND ${BISON_EXECUTABLE}
|
||||
ARGS
|
||||
-p ${_PREFIX} -o"${_CPP_OUTPUT}"
|
||||
--defines="${_H_OUTPUT}" ${_Y_INPUT}
|
||||
WORKING_DIRECTORY ${_Y_DIR}
|
||||
)
|
||||
SET_SOURCE_FILES_PROPERTIES(
|
||||
${_CPP_OUTPUT} ${_H_OUTPUT}
|
||||
GENERATED
|
||||
)
|
||||
ELSE(BISON_EXECUTABLE)
|
||||
MESSAGE(SEND_ERROR "Can't find bison program, and it's required")
|
||||
ENDIF(BISON_EXECUTABLE)
|
||||
ENDMACRO(BISON_GENERATOR)
|
@ -155,6 +155,7 @@ if( MSVC )
|
||||
-wd4351 # Suppress 'new behavior: elements of array 'array' will be default initialized'
|
||||
-wd4355 # Suppress ''this' : used in base member initializer list'
|
||||
-wd4503 # Suppress ''identifier' : decorated name length exceeded, name was truncated'
|
||||
-wd4551 # Suppress 'function call missing argument list'
|
||||
-wd4624 # Suppress ''derived class' : destructor could not be generated because a base class destructor is inaccessible'
|
||||
-wd4715 # Suppress ''function' : not all control paths return a value'
|
||||
-wd4800 # Suppress ''type' : forcing value to bool 'true' or 'false' (performance warning)'
|
||||
@ -185,7 +186,8 @@ elseif( LLVM_COMPILER_IS_GCC_COMPATIBLE )
|
||||
endif (LLVM_ENABLE_WERROR)
|
||||
endif( MSVC )
|
||||
|
||||
add_llvm_definitions( -D__STDC_LIMIT_MACROS )
|
||||
add_llvm_definitions( -D__STDC_CONSTANT_MACROS )
|
||||
add_llvm_definitions( -D__STDC_FORMAT_MACROS )
|
||||
add_llvm_definitions( -D__STDC_LIMIT_MACROS )
|
||||
|
||||
option(LLVM_INCLUDE_TESTS "Generate build targets for the LLVM unit tests." ON)
|
||||
|
@ -135,14 +135,14 @@ function(explicit_map_components_to_libraries out_libs)
|
||||
string(TOUPPER "${c}" capitalized)
|
||||
list(FIND capitalized_libs LLVM${capitalized} lib_idx)
|
||||
if( lib_idx LESS 0 )
|
||||
# The component is unknown. Maybe is an omitted target?
|
||||
is_llvm_target_library(${c} iltl_result)
|
||||
if( NOT iltl_result )
|
||||
message(FATAL_ERROR "Library `${c}' not found in list of llvm libraries.")
|
||||
endif()
|
||||
# The component is unknown. Maybe is an omitted target?
|
||||
is_llvm_target_library(${c} iltl_result)
|
||||
if( NOT iltl_result )
|
||||
message(FATAL_ERROR "Library `${c}' not found in list of llvm libraries.")
|
||||
endif()
|
||||
else( lib_idx LESS 0 )
|
||||
list(GET llvm_libs ${lib_idx} canonical_lib)
|
||||
list(APPEND expanded_components ${canonical_lib})
|
||||
list(GET llvm_libs ${lib_idx} canonical_lib)
|
||||
list(APPEND expanded_components ${canonical_lib})
|
||||
endif( lib_idx LESS 0 )
|
||||
endif( NOT idx LESS 0 )
|
||||
endforeach(c)
|
||||
@ -152,7 +152,8 @@ function(explicit_map_components_to_libraries out_libs)
|
||||
set(processed)
|
||||
while( cursor LESS lst_size )
|
||||
list(GET expanded_components ${cursor} lib)
|
||||
list(APPEND expanded_components ${MSVC_LIB_DEPS_${lib}})
|
||||
get_property(lib_deps GLOBAL PROPERTY LLVM_LIB_DEPS_${lib})
|
||||
list(APPEND expanded_components ${lib_deps})
|
||||
# Remove duplicates at the front:
|
||||
list(REVERSE expanded_components)
|
||||
list(REMOVE_DUPLICATES expanded_components)
|
||||
@ -175,29 +176,3 @@ function(explicit_map_components_to_libraries out_libs)
|
||||
endforeach(c)
|
||||
set(${out_libs} ${result} PARENT_SCOPE)
|
||||
endfunction(explicit_map_components_to_libraries)
|
||||
|
||||
|
||||
# The library dependency data is contained in the file
|
||||
# LLVMLibDeps.cmake on this directory. It is automatically generated
|
||||
# by tools/llvm-config/CMakeLists.txt when the build comprises all the
|
||||
# targets and we are on a environment Posix enough to build the
|
||||
# llvm-config script. This, in practice, just excludes MSVC.
|
||||
|
||||
# When you remove or rename a library from the build, be sure to
|
||||
# remove its file from lib/ as well, or the GenLibDeps.pl script will
|
||||
# include it on its analysis!
|
||||
|
||||
# The format generated by GenLibDeps.pl
|
||||
|
||||
# LLVMARMAsmPrinter.o: LLVMARMCodeGen.o libLLVMAsmPrinter.a libLLVMCodeGen.a libLLVMCore.a libLLVMSupport.a libLLVMTarget.a
|
||||
|
||||
# is translated to:
|
||||
|
||||
# set(MSVC_LIB_DEPS_LLVMARMAsmPrinter LLVMARMCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMSupport LLVMTarget)
|
||||
|
||||
# It is necessary to remove the `lib' prefix and the `.a'.
|
||||
|
||||
# This 'sed' script should do the trick:
|
||||
# sed -e s'#\.a##g' -e 's#libLLVM#LLVM#g' -e 's#: # #' -e 's#\(.*\)#set(MSVC_LIB_DEPS_\1)#' ~/llvm/tools/llvm-config/LibDeps.txt
|
||||
|
||||
include(LLVMLibDeps)
|
||||
|
@ -12,6 +12,8 @@ set(LLVM_TARGETS_TO_BUILD @LLVM_TARGETS_TO_BUILD@)
|
||||
|
||||
set(LLVM_TARGETS_WITH_JIT @LLVM_TARGETS_WITH_JIT@)
|
||||
|
||||
@all_llvm_lib_deps@
|
||||
|
||||
set(TARGET_TRIPLE "@TARGET_TRIPLE@")
|
||||
|
||||
set(LLVM_TOOLS_BINARY_DIR @LLVM_TOOLS_BINARY_DIR@)
|
||||
|
@ -1,83 +0,0 @@
|
||||
set(MSVC_LIB_DEPS_LLVMARMAsmParser LLVMARMCodeGen LLVMARMInfo LLVMMC LLVMMCParser LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMARMAsmPrinter LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMARMCodeGen LLVMARMAsmPrinter LLVMARMDesc LLVMARMInfo LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMARMDesc LLVMARMInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMARMDisassembler LLVMARMCodeGen LLVMARMDesc LLVMARMInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMARMInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMAlphaCodeGen LLVMAlphaDesc LLVMAlphaInfo LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMAlphaDesc LLVMAlphaInfo LLVMMC)
|
||||
set(MSVC_LIB_DEPS_LLVMAlphaInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMAnalysis LLVMCore LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMArchive LLVMBitReader LLVMCore LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMAsmParser LLVMCore LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMAsmPrinter LLVMAnalysis LLVMCodeGen LLVMCore LLVMMC LLVMMCParser LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMBitReader LLVMCore LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMBitWriter LLVMCore LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMBlackfinCodeGen LLVMAsmPrinter LLVMBlackfinDesc LLVMBlackfinInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMBlackfinDesc LLVMBlackfinInfo LLVMMC)
|
||||
set(MSVC_LIB_DEPS_LLVMBlackfinInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMCBackend LLVMAnalysis LLVMCBackendInfo LLVMCodeGen LLVMCore LLVMMC LLVMScalarOpts LLVMSupport LLVMTarget LLVMTransformUtils)
|
||||
set(MSVC_LIB_DEPS_LLVMCBackendInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMCellSPUCodeGen LLVMAsmPrinter LLVMCellSPUDesc LLVMCellSPUInfo LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMCellSPUDesc LLVMCellSPUInfo LLVMMC)
|
||||
set(MSVC_LIB_DEPS_LLVMCellSPUInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMCodeGen LLVMAnalysis LLVMCore LLVMMC LLVMScalarOpts LLVMSupport LLVMTarget LLVMTransformUtils)
|
||||
set(MSVC_LIB_DEPS_LLVMCore LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMCppBackend LLVMCore LLVMCppBackendInfo LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMCppBackendInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMExecutionEngine LLVMCore LLVMMC LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMInstCombine LLVMAnalysis LLVMCore LLVMSupport LLVMTarget LLVMTransformUtils)
|
||||
set(MSVC_LIB_DEPS_LLVMInstrumentation LLVMAnalysis LLVMCore LLVMSupport LLVMTransformUtils)
|
||||
set(MSVC_LIB_DEPS_LLVMInterpreter LLVMCodeGen LLVMCore LLVMExecutionEngine LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMJIT LLVMCodeGen LLVMCore LLVMExecutionEngine LLVMMC LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMLinker LLVMArchive LLVMBitReader LLVMCore LLVMSupport LLVMTransformUtils)
|
||||
set(MSVC_LIB_DEPS_LLVMMBlazeAsmParser LLVMMBlazeCodeGen LLVMMBlazeInfo LLVMMC LLVMMCParser LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMMBlazeAsmPrinter LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMMBlazeCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMBlazeAsmPrinter LLVMMBlazeDesc LLVMMBlazeInfo LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMMBlazeDesc LLVMMBlazeInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMMBlazeDisassembler LLVMMBlazeCodeGen LLVMMBlazeDesc LLVMMBlazeInfo LLVMMC)
|
||||
set(MSVC_LIB_DEPS_LLVMMBlazeInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMMCDisassembler LLVMARMAsmParser LLVMARMCodeGen LLVMARMDesc LLVMARMDisassembler LLVMARMInfo LLVMAlphaCodeGen LLVMAlphaDesc LLVMAlphaInfo LLVMBlackfinCodeGen LLVMBlackfinDesc LLVMBlackfinInfo LLVMCBackend LLVMCBackendInfo LLVMCellSPUCodeGen LLVMCellSPUDesc LLVMCellSPUInfo LLVMCppBackend LLVMCppBackendInfo LLVMMBlazeAsmParser LLVMMBlazeCodeGen LLVMMBlazeDesc LLVMMBlazeDisassembler LLVMMBlazeInfo LLVMMC LLVMMCParser LLVMMSP430CodeGen LLVMMSP430Desc LLVMMSP430Info LLVMMipsCodeGen LLVMMipsDesc LLVMMipsInfo LLVMPTXCodeGen LLVMPTXDesc LLVMPTXInfo LLVMPowerPCCodeGen LLVMPowerPCDesc LLVMPowerPCInfo LLVMSparcCodeGen LLVMSparcDesc LLVMSparcInfo LLVMSupport LLVMSystemZCodeGen LLVMSystemZDesc LLVMSystemZInfo LLVMTarget LLVMX86AsmParser LLVMX86CodeGen LLVMX86Desc LLVMX86Disassembler LLVMX86Info LLVMXCoreCodeGen LLVMXCoreDesc LLVMXCoreInfo)
|
||||
set(MSVC_LIB_DEPS_LLVMMCJIT LLVMCore LLVMExecutionEngine LLVMRuntimeDyld LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMMCParser LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMMSP430AsmPrinter LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMMSP430CodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMSP430AsmPrinter LLVMMSP430Desc LLVMMSP430Info LLVMSelectionDAG LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMMSP430Desc LLVMMC LLVMMSP430Info)
|
||||
set(MSVC_LIB_DEPS_LLVMMSP430Info LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMMipsAsmPrinter LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMMipsCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMipsAsmPrinter LLVMMipsDesc LLVMMipsInfo LLVMSelectionDAG LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMMipsDesc LLVMMC LLVMMipsInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMMipsInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMObject LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMPTXCodeGen LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPTXDesc LLVMPTXInfo LLVMSelectionDAG LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMPTXDesc LLVMMC LLVMPTXInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMPTXInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMPowerPCAsmPrinter LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMPowerPCCodeGen LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPowerPCAsmPrinter LLVMPowerPCDesc LLVMPowerPCInfo LLVMSelectionDAG LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMPowerPCDesc LLVMMC LLVMPowerPCInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMPowerPCInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMRuntimeDyld LLVMObject LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMScalarOpts LLVMAnalysis LLVMCore LLVMInstCombine LLVMSupport LLVMTarget LLVMTransformUtils)
|
||||
set(MSVC_LIB_DEPS_LLVMSelectionDAG LLVMAnalysis LLVMCodeGen LLVMCore LLVMMC LLVMSupport LLVMTarget LLVMTransformUtils)
|
||||
set(MSVC_LIB_DEPS_LLVMSparcCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSparcDesc LLVMSparcInfo LLVMSupport LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMSparcDesc LLVMMC LLVMSparcInfo LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMSparcInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMSupport )
|
||||
set(MSVC_LIB_DEPS_LLVMSystemZCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystemZDesc LLVMSystemZInfo LLVMTarget)
|
||||
set(MSVC_LIB_DEPS_LLVMSystemZDesc LLVMMC LLVMSystemZInfo)
|
||||
set(MSVC_LIB_DEPS_LLVMSystemZInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMTarget LLVMCore LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMTransformUtils LLVMAnalysis LLVMCore LLVMSupport LLVMTarget LLVMipa)
|
||||
set(MSVC_LIB_DEPS_LLVMX86AsmParser LLVMMC LLVMMCParser LLVMSupport LLVMTarget LLVMX86Info)
|
||||
set(MSVC_LIB_DEPS_LLVMX86AsmPrinter LLVMMC LLVMSupport LLVMX86Utils)
|
||||
set(MSVC_LIB_DEPS_LLVMX86CodeGen LLVMAnalysis LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget LLVMX86AsmPrinter LLVMX86Desc LLVMX86Info LLVMX86Utils)
|
||||
set(MSVC_LIB_DEPS_LLVMX86Desc LLVMMC LLVMSupport LLVMX86Info)
|
||||
set(MSVC_LIB_DEPS_LLVMX86Disassembler LLVMMC LLVMSupport LLVMX86Info)
|
||||
set(MSVC_LIB_DEPS_LLVMX86Info LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMX86Utils LLVMCore LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMXCoreCodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMSelectionDAG LLVMSupport LLVMTarget LLVMXCoreDesc LLVMXCoreInfo)
|
||||
set(MSVC_LIB_DEPS_LLVMXCoreDesc LLVMMC LLVMXCoreInfo)
|
||||
set(MSVC_LIB_DEPS_LLVMXCoreInfo LLVMMC LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMipa LLVMAnalysis LLVMCore LLVMSupport)
|
||||
set(MSVC_LIB_DEPS_LLVMipo LLVMAnalysis LLVMCore LLVMScalarOpts LLVMSupport LLVMTarget LLVMTransformUtils LLVMipa)
|
@ -2,7 +2,7 @@
|
||||
# Extra parameters for `tblgen' may come after `ofn' parameter.
|
||||
# Adds the name of the generated file to TABLEGEN_OUTPUT.
|
||||
|
||||
macro(tablegen ofn)
|
||||
macro(tablegen project ofn)
|
||||
file(GLOB local_tds "*.td")
|
||||
file(GLOB_RECURSE global_tds "${LLVM_MAIN_SRC_DIR}/include/llvm/*.td")
|
||||
|
||||
@ -14,14 +14,14 @@ macro(tablegen ofn)
|
||||
endif()
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
|
||||
# Generate tablegen output in a temporary file.
|
||||
COMMAND ${LLVM_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
COMMAND ${${project}_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-I ${LLVM_MAIN_SRC_DIR}/lib/Target -I ${LLVM_MAIN_INCLUDE_DIR}
|
||||
${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
|
||||
# The file in LLVM_TARGET_DEFINITIONS may be not in the current
|
||||
# directory and local_tds may not contain it, so we must
|
||||
# explicitly list it here:
|
||||
DEPENDS ${LLVM_TABLEGEN_EXE} ${local_tds} ${global_tds}
|
||||
DEPENDS ${${project}_TABLEGEN_EXE} ${local_tds} ${global_tds}
|
||||
${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
|
||||
COMMENT "Building ${ofn}..."
|
||||
)
|
||||
@ -44,3 +44,82 @@ macro(tablegen ofn)
|
||||
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${ofn}
|
||||
PROPERTIES GENERATED 1)
|
||||
endmacro(tablegen)
|
||||
|
||||
function(add_public_tablegen_target target)
|
||||
# Creates a target for publicly exporting tablegen dependencies.
|
||||
if( TABLEGEN_OUTPUT )
|
||||
add_custom_target(${target}
|
||||
DEPENDS ${TABLEGEN_OUTPUT})
|
||||
add_dependencies(${target} ${LLVM_COMMON_DEPENDS})
|
||||
endif( TABLEGEN_OUTPUT )
|
||||
endfunction()
|
||||
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
set(CX_NATIVE_TG_DIR "${CMAKE_BINARY_DIR}/native")
|
||||
|
||||
add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CX_NATIVE_TG_DIR}
|
||||
COMMENT "Creating ${CX_NATIVE_TG_DIR}...")
|
||||
|
||||
add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR}/CMakeCache.txt
|
||||
COMMAND ${CMAKE_COMMAND} -UMAKE_TOOLCHAIN_FILE -DCMAKE_BUILD_TYPE=Release
|
||||
-DLLVM_BUILD_POLLY=OFF ${CMAKE_SOURCE_DIR}
|
||||
WORKING_DIRECTORY ${CX_NATIVE_TG_DIR}
|
||||
DEPENDS ${CX_NATIVE_TG_DIR}
|
||||
COMMENT "Configuring native TableGen...")
|
||||
|
||||
add_custom_target(ConfigureNativeTableGen DEPENDS ${CX_NATIVE_TG_DIR}/CMakeCache.txt)
|
||||
|
||||
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CX_NATIVE_TG_DIR})
|
||||
endif()
|
||||
|
||||
macro(add_tablegen target project)
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_TOOLS_BINARY_DIR})
|
||||
|
||||
add_llvm_utility(${target} ${ARGN})
|
||||
|
||||
set(${project}_TABLEGEN "${target}" CACHE
|
||||
STRING "Native TableGen executable. Saves building one when cross-compiling.")
|
||||
|
||||
# Upgrade existing LLVM_TABLEGEN setting.
|
||||
if(${project} STREQUAL LLVM)
|
||||
if(${LLVM_TABLEGEN} STREQUAL tblgen)
|
||||
set(LLVM_TABLEGEN "${target}" CACHE
|
||||
STRING "Native TableGen executable. Saves building one when cross-compiling."
|
||||
FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Effective tblgen executable to be used:
|
||||
set(${project}_TABLEGEN_EXE ${${project}_TABLEGEN} PARENT_SCOPE)
|
||||
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
if( ${${project}_TABLEGEN} STREQUAL "${target}" )
|
||||
set(${project}_TABLEGEN_EXE "${CX_NATIVE_TG_DIR}/bin/${target}")
|
||||
set(${project}_TABLEGEN_EXE ${${project}_TABLEGEN_EXE} PARENT_SCOPE)
|
||||
|
||||
add_custom_command(OUTPUT ${${project}_TABLEGEN_EXE}
|
||||
COMMAND ${CMAKE_BUILD_TOOL} ${target}
|
||||
DEPENDS ${CX_NATIVE_TG_DIR}/CMakeCache.txt
|
||||
WORKING_DIRECTORY ${CX_NATIVE_TG_DIR}
|
||||
COMMENT "Building native TableGen...")
|
||||
add_custom_target(${project}NativeTableGen DEPENDS ${${project}_TABLEGEN_EXE})
|
||||
add_dependencies(${project}NativeTableGen ConfigureNativeTableGen)
|
||||
|
||||
add_dependencies(${target} ${project}NativeTableGen)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(${target} LLVMSupport LLVMTableGen)
|
||||
if( MINGW )
|
||||
target_link_libraries(${target} imagehlp psapi)
|
||||
if(CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
set_target_properties(${target} PROPERTIES LINK_FLAGS -Wl,--stack,16777216)
|
||||
endif(CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
endif( MINGW )
|
||||
if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD AND NOT BEOS )
|
||||
target_link_libraries(${target} pthread)
|
||||
endif()
|
||||
|
||||
install(TARGETS ${target} RUNTIME DESTINATION bin)
|
||||
endmacro()
|
||||
|
569
docs/Atomics.html
Normal file
569
docs/Atomics.html
Normal file
@ -0,0 +1,569 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>LLVM Atomic Instructions and Concurrency Guide</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<link rel="stylesheet" href="llvm.css" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>
|
||||
LLVM Atomic Instructions and Concurrency Guide
|
||||
</h1>
|
||||
|
||||
<ol>
|
||||
<li><a href="#introduction">Introduction</a></li>
|
||||
<li><a href="#outsideatomic">Optimization outside atomic</a></li>
|
||||
<li><a href="#atomicinst">Atomic instructions</a></li>
|
||||
<li><a href="#ordering">Atomic orderings</a></li>
|
||||
<li><a href="#iropt">Atomics and IR optimization</a></li>
|
||||
<li><a href="#codegen">Atomics and Codegen</a></li>
|
||||
</ol>
|
||||
|
||||
<div class="doc_author">
|
||||
<p>Written by Eli Friedman</p>
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<h2>
|
||||
<a name="introduction">Introduction</a>
|
||||
</h2>
|
||||
<!-- *********************************************************************** -->
|
||||
|
||||
<div>
|
||||
|
||||
<p>Historically, LLVM has not had very strong support for concurrency; some
|
||||
minimal intrinsics were provided, and <code>volatile</code> was used in some
|
||||
cases to achieve rough semantics in the presence of concurrency. However, this
|
||||
is changing; there are now new instructions which are well-defined in the
|
||||
presence of threads and asynchronous signals, and the model for existing
|
||||
instructions has been clarified in the IR.</p>
|
||||
|
||||
<p>The atomic instructions are designed specifically to provide readable IR and
|
||||
optimized code generation for the following:</p>
|
||||
<ul>
|
||||
<li>The new C++0x <code><atomic></code> header.
|
||||
(<a href="http://www.open-std.org/jtc1/sc22/wg21/">C++0x draft available here</a>.)
|
||||
(<a href="http://www.open-std.org/jtc1/sc22/wg14/">C1x draft available here</a>)</li>
|
||||
<li>Proper semantics for Java-style memory, for both <code>volatile</code> and
|
||||
regular shared variables.
|
||||
(<a href="http://java.sun.com/docs/books/jls/third_edition/html/memory.html">Java Specification</a>)</li>
|
||||
<li>gcc-compatible <code>__sync_*</code> builtins.
|
||||
(<a href="http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html">Description</a>)</li>
|
||||
<li>Other scenarios with atomic semantics, including <code>static</code>
|
||||
variables with non-trivial constructors in C++.</li>
|
||||
</ul>
|
||||
|
||||
<p>Atomic and volatile in the IR are orthogonal; "volatile" is the C/C++
|
||||
volatile, which ensures that every volatile load and store happens and is
|
||||
performed in the stated order. A couple examples: if a
|
||||
SequentiallyConsistent store is immediately followed by another
|
||||
SequentiallyConsistent store to the same address, the first store can
|
||||
be erased. This transformation is not allowed for a pair of volatile
|
||||
stores. On the other hand, a non-volatile non-atomic load can be moved
|
||||
across a volatile load freely, but not an Acquire load.</p>
|
||||
|
||||
<p>This document is intended to provide a guide to anyone either writing a
|
||||
frontend for LLVM or working on optimization passes for LLVM with a guide
|
||||
for how to deal with instructions with special semantics in the presence of
|
||||
concurrency. This is not intended to be a precise guide to the semantics;
|
||||
the details can get extremely complicated and unreadable, and are not
|
||||
usually necessary.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<h2>
|
||||
<a name="outsideatomic">Optimization outside atomic</a>
|
||||
</h2>
|
||||
<!-- *********************************************************************** -->
|
||||
|
||||
<div>
|
||||
|
||||
<p>The basic <code>'load'</code> and <code>'store'</code> allow a variety of
|
||||
optimizations, but can lead to undefined results in a concurrent environment;
|
||||
see <a href="#o_nonatomic">NonAtomic</a>. This section specifically goes
|
||||
into the one optimizer restriction which applies in concurrent environments,
|
||||
which gets a bit more of an extended description because any optimization
|
||||
dealing with stores needs to be aware of it.</p>
|
||||
|
||||
<p>From the optimizer's point of view, the rule is that if there
|
||||
are not any instructions with atomic ordering involved, concurrency does
|
||||
not matter, with one exception: if a variable might be visible to another
|
||||
thread or signal handler, a store cannot be inserted along a path where it
|
||||
might not execute otherwise. Take the following example:</p>
|
||||
|
||||
<pre>
|
||||
/* C code, for readability; run through clang -O2 -S -emit-llvm to get
|
||||
equivalent IR */
|
||||
int x;
|
||||
void f(int* a) {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (a[i])
|
||||
x += 1;
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The following is equivalent in non-concurrent situations:</p>
|
||||
|
||||
<pre>
|
||||
int x;
|
||||
void f(int* a) {
|
||||
int xtemp = x;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
if (a[i])
|
||||
xtemp += 1;
|
||||
}
|
||||
x = xtemp;
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>However, LLVM is not allowed to transform the former to the latter: it could
|
||||
indirectly introduce undefined behavior if another thread can access x at
|
||||
the same time. (This example is particularly of interest because before the
|
||||
concurrency model was implemented, LLVM would perform this
|
||||
transformation.)</p>
|
||||
|
||||
<p>Note that speculative loads are allowed; a load which
|
||||
is part of a race returns <code>undef</code>, but does not have undefined
|
||||
behavior.</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<h2>
|
||||
<a name="atomicinst">Atomic instructions</a>
|
||||
</h2>
|
||||
<!-- *********************************************************************** -->
|
||||
|
||||
<div>
|
||||
|
||||
<p>For cases where simple loads and stores are not sufficient, LLVM provides
|
||||
various atomic instructions. The exact guarantees provided depend on the
|
||||
ordering; see <a href="#ordering">Atomic orderings</a></p>
|
||||
|
||||
<p><code>load atomic</code> and <code>store atomic</code> provide the same
|
||||
basic functionality as non-atomic loads and stores, but provide additional
|
||||
guarantees in situations where threads and signals are involved.</p>
|
||||
|
||||
<p><code>cmpxchg</code> and <code>atomicrmw</code> are essentially like an
|
||||
atomic load followed by an atomic store (where the store is conditional for
|
||||
<code>cmpxchg</code>), but no other memory operation can happen on any thread
|
||||
between the load and store. Note that LLVM's cmpxchg does not provide quite
|
||||
as many options as the C++0x version.</p>
|
||||
|
||||
<p>A <code>fence</code> provides Acquire and/or Release ordering which is not
|
||||
part of another operation; it is normally used along with Monotonic memory
|
||||
operations. A Monotonic load followed by an Acquire fence is roughly
|
||||
equivalent to an Acquire load.</p>
|
||||
|
||||
<p>Frontends generating atomic instructions generally need to be aware of the
|
||||
target to some degree; atomic instructions are guaranteed to be lock-free,
|
||||
and therefore an instruction which is wider than the target natively supports
|
||||
can be impossible to generate.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<h2>
|
||||
<a name="ordering">Atomic orderings</a>
|
||||
</h2>
|
||||
<!-- *********************************************************************** -->
|
||||
|
||||
<div>
|
||||
|
||||
<p>In order to achieve a balance between performance and necessary guarantees,
|
||||
there are six levels of atomicity. They are listed in order of strength;
|
||||
each level includes all the guarantees of the previous level except for
|
||||
Acquire/Release. (See also <a href="LangRef.html#ordering">LangRef</a>.)</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="o_notatomic">NotAtomic</a>
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
|
||||
<p>NotAtomic is the obvious, a load or store which is not atomic. (This isn't
|
||||
really a level of atomicity, but is listed here for comparison.) This is
|
||||
essentially a regular load or store. If there is a race on a given memory
|
||||
location, loads from that location return undef.</p>
|
||||
|
||||
<dl>
|
||||
<dt>Relevant standard</dt>
|
||||
<dd>This is intended to match shared variables in C/C++, and to be used
|
||||
in any other context where memory access is necessary, and
|
||||
a race is impossible. (The precise definition is in
|
||||
<a href="LangRef.html#memmodel">LangRef</a>.)
|
||||
<dt>Notes for frontends</dt>
|
||||
<dd>The rule is essentially that all memory accessed with basic loads and
|
||||
stores by multiple threads should be protected by a lock or other
|
||||
synchronization; otherwise, you are likely to run into undefined
|
||||
behavior. If your frontend is for a "safe" language like Java,
|
||||
use Unordered to load and store any shared variable. Note that NotAtomic
|
||||
volatile loads and stores are not properly atomic; do not try to use
|
||||
them as a substitute. (Per the C/C++ standards, volatile does provide
|
||||
some limited guarantees around asynchronous signals, but atomics are
|
||||
generally a better solution.)
|
||||
<dt>Notes for optimizers</dt>
|
||||
<dd>Introducing loads to shared variables along a codepath where they would
|
||||
not otherwise exist is allowed; introducing stores to shared variables
|
||||
is not. See <a href="#outsideatomic">Optimization outside
|
||||
atomic</a>.</dd>
|
||||
<dt>Notes for code generation</dt>
|
||||
<dd>The one interesting restriction here is that it is not allowed to write
|
||||
to bytes outside of the bytes relevant to a store. This is mostly
|
||||
relevant to unaligned stores: it is not allowed in general to convert
|
||||
an unaligned store into two aligned stores of the same width as the
|
||||
unaligned store. Backends are also expected to generate an i8 store
|
||||
as an i8 store, and not an instruction which writes to surrounding
|
||||
bytes. (If you are writing a backend for an architecture which cannot
|
||||
satisfy these restrictions and cares about concurrency, please send an
|
||||
email to llvmdev.)</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="o_unordered">Unordered</a>
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
|
||||
<p>Unordered is the lowest level of atomicity. It essentially guarantees that
|
||||
races produce somewhat sane results instead of having undefined behavior.
|
||||
It also guarantees the operation to be lock-free, so it do not depend on
|
||||
the data being part of a special atomic structure or depend on a separate
|
||||
per-process global lock. Note that code generation will fail for
|
||||
unsupported atomic operations; if you need such an operation, use explicit
|
||||
locking.</p>
|
||||
|
||||
<dl>
|
||||
<dt>Relevant standard</dt>
|
||||
<dd>This is intended to match the Java memory model for shared
|
||||
variables.</dd>
|
||||
<dt>Notes for frontends</dt>
|
||||
<dd>This cannot be used for synchronization, but is useful for Java and
|
||||
other "safe" languages which need to guarantee that the generated
|
||||
code never exhibits undefined behavior. Note that this guarantee
|
||||
is cheap on common platforms for loads of a native width, but can
|
||||
be expensive or unavailable for wider loads, like a 64-bit store
|
||||
on ARM. (A frontend for Java or other "safe" languages would normally
|
||||
split a 64-bit store on ARM into two 32-bit unordered stores.)
|
||||
<dt>Notes for optimizers</dt>
|
||||
<dd>In terms of the optimizer, this prohibits any transformation that
|
||||
transforms a single load into multiple loads, transforms a store
|
||||
into multiple stores, narrows a store, or stores a value which
|
||||
would not be stored otherwise. Some examples of unsafe optimizations
|
||||
are narrowing an assignment into a bitfield, rematerializing
|
||||
a load, and turning loads and stores into a memcpy call. Reordering
|
||||
unordered operations is safe, though, and optimizers should take
|
||||
advantage of that because unordered operations are common in
|
||||
languages that need them.</dd>
|
||||
<dt>Notes for code generation</dt>
|
||||
<dd>These operations are required to be atomic in the sense that if you
|
||||
use unordered loads and unordered stores, a load cannot see a value
|
||||
which was never stored. A normal load or store instruction is usually
|
||||
sufficient, but note that an unordered load or store cannot
|
||||
be split into multiple instructions (or an instruction which
|
||||
does multiple memory operations, like <code>LDRD</code> on ARM).</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="o_monotonic">Monotonic</a>
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
|
||||
<p>Monotonic is the weakest level of atomicity that can be used in
|
||||
synchronization primitives, although it does not provide any general
|
||||
synchronization. It essentially guarantees that if you take all the
|
||||
operations affecting a specific address, a consistent ordering exists.
|
||||
|
||||
<dl>
|
||||
<dt>Relevant standard</dt>
|
||||
<dd>This corresponds to the C++0x/C1x <code>memory_order_relaxed</code>;
|
||||
see those standards for the exact definition.
|
||||
<dt>Notes for frontends</dt>
|
||||
<dd>If you are writing a frontend which uses this directly, use with caution.
|
||||
The guarantees in terms of synchronization are very weak, so make
|
||||
sure these are only used in a pattern which you know is correct.
|
||||
Generally, these would either be used for atomic operations which
|
||||
do not protect other memory (like an atomic counter), or along with
|
||||
a <code>fence</code>.</dd>
|
||||
<dt>Notes for optimizers</dt>
|
||||
<dd>In terms of the optimizer, this can be treated as a read+write on the
|
||||
relevant memory location (and alias analysis will take advantage of
|
||||
that). In addition, it is legal to reorder non-atomic and Unordered
|
||||
loads around Monotonic loads. CSE/DSE and a few other optimizations
|
||||
are allowed, but Monotonic operations are unlikely to be used in ways
|
||||
which would make those optimizations useful.</dd>
|
||||
<dt>Notes for code generation</dt>
|
||||
<dd>Code generation is essentially the same as that for unordered for loads
|
||||
and stores. No fences are required. <code>cmpxchg</code> and
|
||||
<code>atomicrmw</code> are required to appear as a single operation.</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="o_acquire">Acquire</a>
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
|
||||
<p>Acquire provides a barrier of the sort necessary to acquire a lock to access
|
||||
other memory with normal loads and stores.
|
||||
|
||||
<dl>
|
||||
<dt>Relevant standard</dt>
|
||||
<dd>This corresponds to the C++0x/C1x <code>memory_order_acquire</code>. It
|
||||
should also be used for C++0x/C1x <code>memory_order_consume</code>.
|
||||
<dt>Notes for frontends</dt>
|
||||
<dd>If you are writing a frontend which uses this directly, use with caution.
|
||||
Acquire only provides a semantic guarantee when paired with a Release
|
||||
operation.</dd>
|
||||
<dt>Notes for optimizers</dt>
|
||||
<dd>Optimizers not aware of atomics can treat this like a nothrow call.
|
||||
It is also possible to move stores from before an Acquire load
|
||||
or read-modify-write operation to after it, and move non-Acquire
|
||||
loads from before an Acquire operation to after it.</dd>
|
||||
<dt>Notes for code generation</dt>
|
||||
<dd>Architectures with weak memory ordering (essentially everything relevant
|
||||
today except x86 and SPARC) require some sort of fence to maintain
|
||||
the Acquire semantics. The precise fences required varies widely by
|
||||
architecture, but for a simple implementation, most architectures provide
|
||||
a barrier which is strong enough for everything (<code>dmb</code> on ARM,
|
||||
<code>sync</code> on PowerPC, etc.). Putting such a fence after the
|
||||
equivalent Monotonic operation is sufficient to maintain Acquire
|
||||
semantics for a memory operation.</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="o_acquire">Release</a>
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
|
||||
<p>Release is similar to Acquire, but with a barrier of the sort necessary to
|
||||
release a lock.
|
||||
|
||||
<dl>
|
||||
<dt>Relevant standard</dt>
|
||||
<dd>This corresponds to the C++0x/C1x <code>memory_order_release</code>.</dd>
|
||||
<dt>Notes for frontends</dt>
|
||||
<dd>If you are writing a frontend which uses this directly, use with caution.
|
||||
Release only provides a semantic guarantee when paired with a Acquire
|
||||
operation.</dd>
|
||||
<dt>Notes for optimizers</dt>
|
||||
<dd>Optimizers not aware of atomics can treat this like a nothrow call.
|
||||
It is also possible to move loads from after a Release store
|
||||
or read-modify-write operation to before it, and move non-Release
|
||||
stores from after an Release operation to before it.</dd>
|
||||
<dt>Notes for code generation</dt>
|
||||
<dd>See the section on Acquire; a fence before the relevant operation is
|
||||
usually sufficient for Release. Note that a store-store fence is not
|
||||
sufficient to implement Release semantics; store-store fences are
|
||||
generally not exposed to IR because they are extremely difficult to
|
||||
use correctly.</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="o_acqrel">AcquireRelease</a>
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
|
||||
<p>AcquireRelease (<code>acq_rel</code> in IR) provides both an Acquire and a
|
||||
Release barrier (for fences and operations which both read and write memory).
|
||||
|
||||
<dl>
|
||||
<dt>Relevant standard</dt>
|
||||
<dd>This corresponds to the C++0x/C1x <code>memory_order_acq_rel</code>.
|
||||
<dt>Notes for frontends</dt>
|
||||
<dd>If you are writing a frontend which uses this directly, use with caution.
|
||||
Acquire only provides a semantic guarantee when paired with a Release
|
||||
operation, and vice versa.</dd>
|
||||
<dt>Notes for optimizers</dt>
|
||||
<dd>In general, optimizers should treat this like a nothrow call; the
|
||||
the possible optimizations are usually not interesting.</dd>
|
||||
<dt>Notes for code generation</dt>
|
||||
<dd>This operation has Acquire and Release semantics; see the sections on
|
||||
Acquire and Release.</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="o_seqcst">SequentiallyConsistent</a>
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
|
||||
<p>SequentiallyConsistent (<code>seq_cst</code> in IR) provides
|
||||
Acquire semantics for loads and Release semantics for
|
||||
stores. Additionally, it guarantees that a total ordering exists
|
||||
between all SequentiallyConsistent operations.
|
||||
|
||||
<dl>
|
||||
<dt>Relevant standard</dt>
|
||||
<dd>This corresponds to the C++0x/C1x <code>memory_order_seq_cst</code>,
|
||||
Java volatile, and the gcc-compatible <code>__sync_*</code> builtins
|
||||
which do not specify otherwise.
|
||||
<dt>Notes for frontends</dt>
|
||||
<dd>If a frontend is exposing atomic operations, these are much easier to
|
||||
reason about for the programmer than other kinds of operations, and using
|
||||
them is generally a practical performance tradeoff.</dd>
|
||||
<dt>Notes for optimizers</dt>
|
||||
<dd>Optimizers not aware of atomics can treat this like a nothrow call.
|
||||
For SequentiallyConsistent loads and stores, the same reorderings are
|
||||
allowed as for Acquire loads and Release stores, except that
|
||||
SequentiallyConsistent operations may not be reordered.</dd>
|
||||
<dt>Notes for code generation</dt>
|
||||
<dd>SequentiallyConsistent loads minimally require the same barriers
|
||||
as Acquire operations and SequentiallyConsistent stores require
|
||||
Release barriers. Additionally, the code generator must enforce
|
||||
ordering between SequentiallyConsistent stores followed by
|
||||
SequentiallyConsistent loads. This is usually done by emitting
|
||||
either a full fence before the loads or a full fence after the
|
||||
stores; which is preferred varies by architecture.</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<h2>
|
||||
<a name="iropt">Atomics and IR optimization</a>
|
||||
</h2>
|
||||
<!-- *********************************************************************** -->
|
||||
|
||||
<div>
|
||||
|
||||
<p>Predicates for optimizer writers to query:
|
||||
<ul>
|
||||
<li>isSimple(): A load or store which is not volatile or atomic. This is
|
||||
what, for example, memcpyopt would check for operations it might
|
||||
transform.</li>
|
||||
<li>isUnordered(): A load or store which is not volatile and at most
|
||||
Unordered. This would be checked, for example, by LICM before hoisting
|
||||
an operation.</li>
|
||||
<li>mayReadFromMemory()/mayWriteToMemory(): Existing predicate, but note
|
||||
that they return true for any operation which is volatile or at least
|
||||
Monotonic.</li>
|
||||
<li>Alias analysis: Note that AA will return ModRef for anything Acquire or
|
||||
Release, and for the address accessed by any Monotonic operation.</li>
|
||||
</ul>
|
||||
|
||||
<p>To support optimizing around atomic operations, make sure you are using
|
||||
the right predicates; everything should work if that is done. If your
|
||||
pass should optimize some atomic operations (Unordered operations in
|
||||
particular), make sure it doesn't replace an atomic load or store with
|
||||
a non-atomic operation.</p>
|
||||
|
||||
<p>Some examples of how optimizations interact with various kinds of atomic
|
||||
operations:
|
||||
<ul>
|
||||
<li>memcpyopt: An atomic operation cannot be optimized into part of a
|
||||
memcpy/memset, including unordered loads/stores. It can pull operations
|
||||
across some atomic operations.
|
||||
<li>LICM: Unordered loads/stores can be moved out of a loop. It just treats
|
||||
monotonic operations like a read+write to a memory location, and anything
|
||||
stricter than that like a nothrow call.
|
||||
<li>DSE: Unordered stores can be DSE'ed like normal stores. Monotonic stores
|
||||
can be DSE'ed in some cases, but it's tricky to reason about, and not
|
||||
especially important.
|
||||
<li>Folding a load: Any atomic load from a constant global can be
|
||||
constant-folded, because it cannot be observed. Similar reasoning allows
|
||||
scalarrepl with atomic loads and stores.
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<h2>
|
||||
<a name="codegen">Atomics and Codegen</a>
|
||||
</h2>
|
||||
<!-- *********************************************************************** -->
|
||||
|
||||
<div>
|
||||
|
||||
<p>Atomic operations are represented in the SelectionDAG with
|
||||
<code>ATOMIC_*</code> opcodes. On architectures which use barrier
|
||||
instructions for all atomic ordering (like ARM), appropriate fences are
|
||||
split out as the DAG is built.</p>
|
||||
|
||||
<p>The MachineMemOperand for all atomic operations is currently marked as
|
||||
volatile; this is not correct in the IR sense of volatile, but CodeGen
|
||||
handles anything marked volatile very conservatively. This should get
|
||||
fixed at some point.</p>
|
||||
|
||||
<p>Common architectures have some way of representing at least a pointer-sized
|
||||
lock-free <code>cmpxchg</code>; such an operation can be used to implement
|
||||
all the other atomic operations which can be represented in IR up to that
|
||||
size. Backends are expected to implement all those operations, but not
|
||||
operations which cannot be implemented in a lock-free manner. It is
|
||||
expected that backends will give an error when given an operation which
|
||||
cannot be implemented. (The LLVM code generator is not very helpful here
|
||||
at the moment, but hopefully that will change.)</p>
|
||||
|
||||
<p>The implementation of atomics on LL/SC architectures (like ARM) is currently
|
||||
a bit of a mess; there is a lot of copy-pasted code across targets, and
|
||||
the representation is relatively unsuited to optimization (it would be nice
|
||||
to be able to optimize loops involving cmpxchg etc.).</p>
|
||||
|
||||
<p>On x86, all atomic loads generate a <code>MOV</code>.
|
||||
SequentiallyConsistent stores generate an <code>XCHG</code>, other stores
|
||||
generate a <code>MOV</code>. SequentiallyConsistent fences generate an
|
||||
<code>MFENCE</code>, other fences do not cause any code to be generated.
|
||||
cmpxchg uses the <code>LOCK CMPXCHG</code> instruction.
|
||||
<code>atomicrmw xchg</code> uses <code>XCHG</code>,
|
||||
<code>atomicrmw add</code> and <code>atomicrmw sub</code> use
|
||||
<code>XADD</code>, and all other <code>atomicrmw</code> operations generate
|
||||
a loop with <code>LOCK CMPXCHG</code>. Depending on the users of the
|
||||
result, some <code>atomicrmw</code> operations can be translated into
|
||||
operations like <code>LOCK AND</code>, but that does not work in
|
||||
general.</p>
|
||||
|
||||
<p>On ARM, MIPS, and many other RISC architectures, Acquire, Release, and
|
||||
SequentiallyConsistent semantics require barrier instructions
|
||||
for every such operation. Loads and stores generate normal instructions.
|
||||
<code>cmpxchg</code> and <code>atomicrmw</code> can be represented using
|
||||
a loop with LL/SC-style instructions which take some sort of exclusive
|
||||
lock on a cache line (<code>LDREX</code> and <code>STREX</code> on
|
||||
ARM, etc.). At the moment, the IR does not provide any way to represent a
|
||||
weak <code>cmpxchg</code> which would not require a loop.</p>
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
|
||||
<hr>
|
||||
<address>
|
||||
<a href="http://jigsaw.w3.org/css-validator/check/referer"><img
|
||||
src="http://jigsaw.w3.org/css-validator/images/vcss-blue" alt="Valid CSS"></a>
|
||||
<a href="http://validator.w3.org/check/referer"><img
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
|
||||
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-08-09 02:07:00 -0700 (Tue, 09 Aug 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -216,18 +216,6 @@ non-obvious ways. Here are some hints and tips:<p>
|
||||
the list of specified optimizations to be randomized and applied to the
|
||||
program. This process will repeat until a bug is found or the user
|
||||
kills <tt>bugpoint</tt>.
|
||||
|
||||
<li><p><tt>bugpoint</tt> does not understand the <tt>-O</tt> option
|
||||
that is used to specify optimization level to <tt>opt</tt>. You
|
||||
can use e.g.</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<p><tt>opt -O2 -debug-pass=Arguments foo.bc -disable-output</tt></p>
|
||||
</div>
|
||||
|
||||
<p>to get a list of passes that are used with <tt>-O2</tt> and
|
||||
then pass this list to <tt>bugpoint</tt>.</p>
|
||||
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
@ -243,7 +231,7 @@ non-obvious ways. Here are some hints and tips:<p>
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-08-30 20:26:11 +0200 (Tue, 30 Aug 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -340,7 +340,7 @@
|
||||
on Visual C++ and Xcode,
|
||||
<tt>"-sv"</tt> on others.</dd>
|
||||
|
||||
<dt><b>LLVM_LIT_TOOLS_DIR</b>:STRING</dt>
|
||||
<dt><b>LLVM_LIT_TOOLS_DIR</b>:PATH</dt>
|
||||
<dd>The path to GnuWin32 tools for tests. Valid on Windows host.
|
||||
Defaults to "", then Lit seeks tools according to %PATH%.
|
||||
Lit can find tools(eg. grep, sort, &c) on LLVM_LIT_TOOLS_DIR at first,
|
||||
@ -423,8 +423,9 @@
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${LLVM_ROOT}/share/llvm/cmake")
|
||||
include(LLVMConfig)
|
||||
<b># Now set the header and library paths:</b>
|
||||
include_directories( ${LLVM_ROOT}/include )
|
||||
link_directories( ${LLVM_ROOT}/lib )
|
||||
include_directories( ${LLVM_INCLUDE_DIRS} )
|
||||
link_directories( ${LLVM_LIBRARY_DIRS} )
|
||||
add_definitions( ${LLVM_DEFINITIONS} )
|
||||
<b># Let's suppose we want to build a JIT compiler with support for
|
||||
# binary code (no interpreter):</b>
|
||||
llvm_map_components_to_libraries(REQ_LLVM_LIBRARIES jit native)
|
||||
|
@ -114,6 +114,7 @@
|
||||
<li><a href="#ppc_prolog">Prolog/Epilog</a></li>
|
||||
<li><a href="#ppc_dynamic">Dynamic Allocation</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#ptx">The PTX backend</a></li>
|
||||
</ul></li>
|
||||
|
||||
</ol>
|
||||
@ -1768,22 +1769,28 @@ bool RegMapping_Fer::compatible_class(MachineFunction &mf,
|
||||
different register allocators:</p>
|
||||
|
||||
<ul>
|
||||
<li><i>Linear Scan</i> — <i>The default allocator</i>. This is the
|
||||
well-know linear scan register allocator. Whereas the
|
||||
<i>Simple</i> and <i>Local</i> algorithms use a direct mapping
|
||||
implementation technique, the <i>Linear Scan</i> implementation
|
||||
uses a spiller in order to place load and stores.</li>
|
||||
|
||||
<li><i>Fast</i> — This register allocator is the default for debug
|
||||
builds. It allocates registers on a basic block level, attempting to keep
|
||||
values in registers and reusing registers as appropriate.</li>
|
||||
|
||||
<li><i>Basic</i> — This is an incremental approach to register
|
||||
allocation. Live ranges are assigned to registers one at a time in
|
||||
an order that is driven by heuristics. Since code can be rewritten
|
||||
on-the-fly during allocation, this framework allows interesting
|
||||
allocators to be developed as extensions. It is not itself a
|
||||
production register allocator but is a potentially useful
|
||||
stand-alone mode for triaging bugs and as a performance baseline.
|
||||
|
||||
<li><i>Greedy</i> — <i>The default allocator</i>. This is a
|
||||
highly tuned implementation of the <i>Basic</i> allocator that
|
||||
incorporates global live range splitting. This allocator works hard
|
||||
to minimize the cost of spill code.
|
||||
|
||||
<li><i>PBQP</i> — A Partitioned Boolean Quadratic Programming (PBQP)
|
||||
based register allocator. This allocator works by constructing a PBQP
|
||||
problem representing the register allocation problem under consideration,
|
||||
solving this using a PBQP solver, and mapping the solution back to a
|
||||
register assignment.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p>The type of register allocator used in <tt>llc</tt> can be chosen with the
|
||||
@ -1805,7 +1812,121 @@ $ llc -regalloc=pbqp file.bc -o pbqp.s;
|
||||
<h3>
|
||||
<a name="proepicode">Prolog/Epilog Code Insertion</a>
|
||||
</h3>
|
||||
<div><p>To Be Written</p></div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<h4>
|
||||
<a name="compact_unwind">Compact Unwind</a>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
|
||||
<p>Throwing an exception requires <em>unwinding</em> out of a function. The
|
||||
information on how to unwind a given function is traditionally expressed in
|
||||
DWARF unwind (a.k.a. frame) info. But that format was originally developed
|
||||
for debuggers to backtrace, and each Frame Description Entry (FDE) requires
|
||||
~20-30 bytes per function. There is also the cost of mapping from an address
|
||||
in a function to the corresponding FDE at runtime. An alternative unwind
|
||||
encoding is called <em>compact unwind</em> and requires just 4-bytes per
|
||||
function.</p>
|
||||
|
||||
<p>The compact unwind encoding is a 32-bit value, which is encoded in an
|
||||
architecture-specific way. It specifies which registers to restore and from
|
||||
where, and how to unwind out of the function. When the linker creates a final
|
||||
linked image, it will create a <code>__TEXT,__unwind_info</code>
|
||||
section. This section is a small and fast way for the runtime to access
|
||||
unwind info for any given function. If we emit compact unwind info for the
|
||||
function, that compact unwind info will be encoded in
|
||||
the <code>__TEXT,__unwind_info</code> section. If we emit DWARF unwind info,
|
||||
the <code>__TEXT,__unwind_info</code> section will contain the offset of the
|
||||
FDE in the <code>__TEXT,__eh_frame</code> section in the final linked
|
||||
image.</p>
|
||||
|
||||
<p>For X86, there are three modes for the compact unwind encoding:</p>
|
||||
|
||||
<dl>
|
||||
<dt><i>Function with a Frame Pointer (<code>EBP</code> or <code>RBP</code>)</i></dt>
|
||||
<dd><p><code>EBP/RBP</code>-based frame, where <code>EBP/RBP</code> is pushed
|
||||
onto the stack immediately after the return address,
|
||||
then <code>ESP/RSP</code> is moved to <code>EBP/RBP</code>. Thus to
|
||||
unwind, <code>ESP/RSP</code> is restored with the
|
||||
current <code>EBP/RBP</code> value, then <code>EBP/RBP</code> is restored
|
||||
by popping the stack, and the return is done by popping the stack once
|
||||
more into the PC. All non-volatile registers that need to be restored must
|
||||
have been saved in a small range on the stack that
|
||||
starts <code>EBP-4</code> to <code>EBP-1020</code> (<code>RBP-8</code>
|
||||
to <code>RBP-1020</code>). The offset (divided by 4 in 32-bit mode and 8
|
||||
in 64-bit mode) is encoded in bits 16-23 (mask: <code>0x00FF0000</code>).
|
||||
The registers saved are encoded in bits 0-14
|
||||
(mask: <code>0x00007FFF</code>) as five 3-bit entries from the following
|
||||
table:</p>
|
||||
<table border="1" cellspacing="0">
|
||||
<tr>
|
||||
<th>Compact Number</th>
|
||||
<th>i386 Register</th>
|
||||
<th>x86-64 Regiser</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td><code>EBX</code></td>
|
||||
<td><code>RBX</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td><code>ECX</code></td>
|
||||
<td><code>R12</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td><code>EDX</code></td>
|
||||
<td><code>R13</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td><code>EDI</code></td>
|
||||
<td><code>R14</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td><code>ESI</code></td>
|
||||
<td><code>R15</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6</td>
|
||||
<td><code>EBP</code></td>
|
||||
<td><code>RBP</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</dd>
|
||||
|
||||
<dt><i>Frameless with a Small Constant Stack Size (<code>EBP</code>
|
||||
or <code>RBP</code> is not used as a frame pointer)</i></dt>
|
||||
<dd><p>To return, a constant (encoded in the compact unwind encoding) is added
|
||||
to the <code>ESP/RSP</code>. Then the return is done by popping the stack
|
||||
into the PC. All non-volatile registers that need to be restored must have
|
||||
been saved on the stack immediately after the return address. The stack
|
||||
size (divided by 4 in 32-bit mode and 8 in 64-bit mode) is encoded in bits
|
||||
16-23 (mask: <code>0x00FF0000</code>). There is a maximum stack size of
|
||||
1024 bytes in 32-bit mode and 2048 in 64-bit mode. The number of registers
|
||||
saved is encoded in bits 9-12 (mask: <code>0x00001C00</code>). Bits 0-9
|
||||
(mask: <code>0x000003FF</code>) contain which registers were saved and
|
||||
their order. (See
|
||||
the <code>encodeCompactUnwindRegistersWithoutFrame()</code> function
|
||||
in <code>lib/Target/X86FrameLowering.cpp</code> for the encoding
|
||||
algorithm.)</p></dd>
|
||||
|
||||
<dt><i>Frameless with a Large Constant Stack Size (<code>EBP</code>
|
||||
or <code>RBP</code> is not used as a frame pointer)</i></dt>
|
||||
<dd><p>This case is like the "Frameless with a Small Constant Stack Size"
|
||||
case, but the stack size is too large to encode in the compact unwind
|
||||
encoding. Instead it requires that the function contains "<code>subl
|
||||
$nnnnnn, %esp</code>" in its prolog. The compact encoding contains the
|
||||
offset to the <code>$nnnnnn</code> value in the function in bits 9-12
|
||||
(mask: <code>0x00001C00</code>).</p></dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="latemco">Late Machine Code Optimizations</a>
|
||||
@ -2165,7 +2286,7 @@ is the key:</p>
|
||||
<td class="yes"></td> <!-- PowerPC -->
|
||||
<td class="unknown"></td> <!-- Sparc -->
|
||||
<td class="unknown"></td> <!-- SystemZ -->
|
||||
<td class="yes"><a href="#feat_inlineasm_x86">*</a></td> <!-- X86 -->
|
||||
<td class="yes"></td> <!-- X86 -->
|
||||
<td class="unknown"></td> <!-- XCore -->
|
||||
</tr>
|
||||
|
||||
@ -2261,9 +2382,6 @@ disassembling machine opcode bytes into MCInst's.</p>
|
||||
<p>This box indicates whether the target supports most popular inline assembly
|
||||
constraints and modifiers.</p>
|
||||
|
||||
<p id="feat_inlineasm_x86">X86 lacks reliable support for inline assembly
|
||||
constraints relating to the X86 floating point stack.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
@ -2792,6 +2910,70 @@ MOVSX32rm16 -> movsx, 32-bit register, 16-bit memory
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="ptx">The PTX backend</a>
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
|
||||
<p>The PTX code generator lives in the lib/Target/PTX directory. It is
|
||||
currently a work-in-progress, but already supports most of the code
|
||||
generation functionality needed to generate correct PTX kernels for
|
||||
CUDA devices.</p>
|
||||
|
||||
<p>The code generator can target PTX 2.0+, and shader model 1.0+. The
|
||||
PTX ISA Reference Manual is used as the primary source of ISA
|
||||
information, though an effort is made to make the output of the code
|
||||
generator match the output of the NVidia nvcc compiler, whenever
|
||||
possible.</p>
|
||||
|
||||
<p>Code Generator Options:</p>
|
||||
<table border="1" cellspacing="0">
|
||||
<tr>
|
||||
<th>Option</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>double</code></td>
|
||||
<td align="left">If enabled, the map_f64_to_f32 directive is
|
||||
disabled in the PTX output, allowing native double-precision
|
||||
arithmetic</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>no-fma</code></td>
|
||||
<td align="left">Disable generation of Fused-Multiply Add
|
||||
instructions, which may be beneficial for some devices</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>smxy / computexy</code></td>
|
||||
<td align="left">Set shader model/compute capability to x.y,
|
||||
e.g. sm20 or compute13</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>Working:</p>
|
||||
<ul>
|
||||
<li>Arithmetic instruction selection (including combo FMA)</li>
|
||||
<li>Bitwise instruction selection</li>
|
||||
<li>Control-flow instruction selection</li>
|
||||
<li>Function calls (only on SM 2.0+ and no return arguments)</li>
|
||||
<li>Addresses spaces (0 = global, 1 = constant, 2 = local, 4 =
|
||||
shared)</li>
|
||||
<li>Thread synchronization (bar.sync)</li>
|
||||
<li>Special register reads ([N]TID, [N]CTAID, PMx, CLOCK, etc.)</li>
|
||||
</ul>
|
||||
|
||||
<p>In Progress:</p>
|
||||
<ul>
|
||||
<li>Robust call instruction selection</li>
|
||||
<li>Stack frame allocation</li>
|
||||
<li>Device-specific instruction scheduling optimizations</li>
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -2806,7 +2988,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: 2011-05-23 00:28:47 +0200 (Mon, 23 May 2011) $
|
||||
Last modified: $Date: 2011-09-19 20:15:46 +0200 (Mon, 19 Sep 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -854,8 +854,12 @@ rules:</p>
|
||||
|
||||
<ul>
|
||||
<li><p><b>Type names</b> (including classes, structs, enums, typedefs, etc)
|
||||
should be nouns and start with an upper-case letter (e.g.
|
||||
<tt>TextFileReader</tt>).</p></li>
|
||||
should be nouns and start with an upper-case letter (e.g.
|
||||
<tt>TextFileReader</tt>).</p></li>
|
||||
|
||||
<li><p><b>Variable names</b> should be nouns (as they represent state). The
|
||||
name should be camel case, and start with an upper case letter (e.g.
|
||||
<tt>Leader</tt> or <tt>Boats</tt>).</p></li>
|
||||
|
||||
<li><p><b>Function names</b> should be verb phrases (as they represent
|
||||
actions), and command-like function should be imperative. The name should
|
||||
@ -1522,7 +1526,7 @@ something.</p>
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-08-12 21:49:16 +0200 (Fri, 12 Aug 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -69,9 +69,6 @@ options) arguments to the tool you are interested in.</p>
|
||||
<li><a href="/cmds/llvm-config.html"><b>llvm-config</b></a> -
|
||||
print out LLVM compilation options, libraries, etc. as configured</li>
|
||||
|
||||
<li><a href="/cmds/llvmc.html"><b>llvmc</b></a> -
|
||||
a generic customizable compiler driver</li>
|
||||
|
||||
<li><a href="/cmds/llvm-diff.html"><b>llvm-diff</b></a> -
|
||||
structurally compare two modules</li>
|
||||
|
||||
@ -79,25 +76,6 @@ options) arguments to the tool you are interested in.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<h2>
|
||||
<a name="frontend">C and C++ Front-end Commands</a>
|
||||
</h2>
|
||||
<!-- *********************************************************************** -->
|
||||
|
||||
<div>
|
||||
<ul>
|
||||
|
||||
<li><a href="/cmds/llvmgcc.html"><b>llvm-gcc</b></a> -
|
||||
GCC-based C front-end for LLVM
|
||||
|
||||
<li><a href="/cmds/llvmgxx.html"><b>llvm-g++</b></a> -
|
||||
GCC-based C++ front-end for LLVM</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<h2>
|
||||
<a name="debug">Debugging Tools</a>
|
||||
@ -151,7 +129,7 @@ options) arguments to the tool you are interested in.</p>
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
|
||||
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-09-20 20:24:04 +0200 (Tue, 20 Sep 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -37,11 +37,23 @@ B<llvm-extract> will write raw bitcode regardless of the output device.
|
||||
Extract the function named I<function-name> from the LLVM bitcode. May be
|
||||
specified multiple times to extract multiple functions at once.
|
||||
|
||||
=item B<--rfunc> I<function-regular-expr>
|
||||
|
||||
Extract the function(s) matching I<function-regular-expr> from the LLVM bitcode.
|
||||
All functions matching the regular expression will be extracted. May be
|
||||
specified multiple times.
|
||||
|
||||
=item B<--glob> I<global-name>
|
||||
|
||||
Extract the global variable named I<global-name> from the LLVM bitcode. May be
|
||||
specified multiple times to extract multiple global variables at once.
|
||||
|
||||
=item B<--rglob> I<glob-regular-expr>
|
||||
|
||||
Extract the global variable(s) matching I<global-regular-expr> from the LLVM
|
||||
bitcode. All global variables matching the regular expression will be extracted.
|
||||
May be specified multiple times.
|
||||
|
||||
=item B<-help>
|
||||
|
||||
Print a summary of command line options.
|
||||
|
@ -1,190 +0,0 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
llvmc - The LLVM Compiler Driver (WIP)
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<llvmc> [I<options>] I<filenames...>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<llvmc> is a configurable driver for invoking other LLVM (and non-LLVM) tools
|
||||
in order to compile, optimize and link software for multiple languages. For
|
||||
those familiar with FSF's B<gcc> tool, it is very similar. Please note that
|
||||
B<llvmc> is considered an experimental tool.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=head2 Built-in Options
|
||||
|
||||
LLVMC has some built-in options that can't be overridden in the
|
||||
configuration libraries.
|
||||
|
||||
=over
|
||||
|
||||
=item B<-o> I<filename>
|
||||
|
||||
Output file name.
|
||||
|
||||
=item B<-x> I<language>
|
||||
|
||||
Specify the language of the following input files until the next B<-x>
|
||||
option.
|
||||
|
||||
=item B<-load> I<plugin_name>
|
||||
|
||||
Load the specified plugin DLL. Example:
|
||||
S<-load $LLVM_DIR/Release/lib/LLVMCSimple.so>.
|
||||
|
||||
=item B<-v> or B<--verbose>
|
||||
|
||||
Enable verbose mode, i.e. print out all executed commands.
|
||||
|
||||
=item B<--check-graph>
|
||||
|
||||
Check the compilation for common errors like mismatched output/input language
|
||||
names, multiple default edges and cycles. Because of plugins, these checks can't
|
||||
be performed at compile-time. Exit with code zero if no errors were found, and
|
||||
return the number of found errors otherwise. Hidden option, useful for debugging
|
||||
LLVMC plugins.
|
||||
|
||||
=item B<--view-graph>
|
||||
|
||||
Show a graphical representation of the compilation graph and exit. Requires that
|
||||
you have I<dot> and I<gv> programs installed. Hidden option, useful for
|
||||
debugging LLVMC plugins.
|
||||
|
||||
=item B<--write-graph>
|
||||
|
||||
Write a I<compilation-graph.dot> file in the current directory with the
|
||||
compilation graph description in Graphviz format (identical to the file used by
|
||||
the B<--view-graph> option). The B<-o> option can be used to set the output file
|
||||
name. Hidden option, useful for debugging LLVMC plugins.
|
||||
|
||||
=item B<--save-temps>
|
||||
|
||||
Write temporary files to the current directory and do not delete them on
|
||||
exit. This option can also take an argument: the I<--save-temps=obj> switch will
|
||||
write files into the directory specified with the I<-o> option. The
|
||||
I<--save-temps=cwd> and I<--save-temps> switches are both synonyms for the
|
||||
default behaviour.
|
||||
|
||||
=item B<--temp-dir> I<directory>
|
||||
|
||||
Store temporary files in the given directory. This directory is deleted on exit
|
||||
unless I<--save-temps> is specified. If I<--save-temps=obj> is also specified,
|
||||
I<--temp-dir> is given the precedence.
|
||||
|
||||
=item B<-help>
|
||||
|
||||
Print a summary of command-line options and exit.
|
||||
|
||||
=item B<-help-hidden>
|
||||
|
||||
Print a summary of command-line options and exit. Print help even for
|
||||
options intended for developers.
|
||||
|
||||
=item B<--version>
|
||||
|
||||
Print version information and exit.
|
||||
|
||||
=item B<@>I<file>
|
||||
|
||||
Read command-line options from I<file>. The options read are inserted
|
||||
in place of the original @I<file> option. If I<file> does not exist, or
|
||||
cannot be read, then the option will be treated literally, and not
|
||||
removed.
|
||||
|
||||
Options in I<file> are separated by whitespace. A whitespace character
|
||||
may be included in an option by surrounding the entire option in
|
||||
either single or double quotes. Any character (including a backslash)
|
||||
may be included by prefixing the character to be included with a
|
||||
backslash. The file may itself contain additional @I<file> options;
|
||||
any such options will be processed recursively.
|
||||
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head2 Control Options
|
||||
|
||||
By default, LLVMC is built with some standard configuration libraries
|
||||
that define the following options:
|
||||
|
||||
=over
|
||||
|
||||
=item B<-clang>
|
||||
|
||||
Use Clang instead of llvm-gcc.
|
||||
|
||||
=item B<-opt>
|
||||
|
||||
Enable optimization passes with B<opt>. To pass options to the B<opt> program
|
||||
use the B<-Wo,> option.
|
||||
|
||||
=item B<-I> I<directory>
|
||||
|
||||
Add a directory to the header file search path.
|
||||
|
||||
=item B<-L> I<directory>
|
||||
|
||||
Add I<directory> to the library search path.
|
||||
|
||||
=item B<-F> I<directory>
|
||||
|
||||
Add I<directory> to the framework search path.
|
||||
|
||||
=item B<-l>I<name>
|
||||
|
||||
Link in the library libI<name>.[bc | a | so]. This library should
|
||||
be a bitcode library.
|
||||
|
||||
=item B<-framework> I<name>
|
||||
|
||||
Link in the library libI<name>.[bc | a | so]. This library should
|
||||
be a bitcode library.
|
||||
|
||||
=item B<-emit-llvm>
|
||||
|
||||
Output LLVM bitcode (with B<-c>) or assembly (with B<-S>) instead of native
|
||||
object (or assembly). If B<-emit-llvm> is given without either B<-c> or B<-S>
|
||||
it has no effect.
|
||||
|
||||
=item B<-Wa>
|
||||
|
||||
Pass options to assembler.
|
||||
|
||||
=item B<-Wl>
|
||||
|
||||
Pass options to linker.
|
||||
|
||||
=item B<-Wo>
|
||||
|
||||
Pass options to opt.
|
||||
|
||||
=item B<-Wllc>
|
||||
|
||||
Pass options to llc (code generator).
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXIT STATUS
|
||||
|
||||
If B<llvmc> succeeds, it will exit with code 0. Otherwise, if an
|
||||
error occurs, it will exit with a non-zero value. If one of the
|
||||
compilation tools returns a non-zero status, pending actions will be
|
||||
discarded and B<llvmc> will return the same result code as the failing
|
||||
compilation tool.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<llvm-gcc|llvmgcc>, L<llvm-g++|llvmgxx>, L<llvm-as|llvm-as>,
|
||||
L<llvm-dis|llvm-dis>, L<llc|llc>, L<llvm-link|llvm-link>
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Maintained by the LLVM Team (L<http://llvm.org/>).
|
||||
|
||||
=cut
|
@ -1,76 +0,0 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
llvm-gcc - LLVM C front-end
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<llvm-gcc> [I<options>] I<filename>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<llvm-gcc> command is the LLVM C front end. It is a modified
|
||||
version of gcc that compiles C/ObjC programs into native objects, LLVM
|
||||
bitcode or LLVM assembly language, depending upon the options.
|
||||
|
||||
By default, B<llvm-gcc> compiles to native objects just like GCC does. If the
|
||||
B<-emit-llvm> and B<-c> options are given then it will generate LLVM bitcode files
|
||||
instead. If B<-emit-llvm> and B<-S> are given, then it will generate LLVM
|
||||
assembly.
|
||||
|
||||
Being derived from the GNU Compiler Collection, B<llvm-gcc> has many
|
||||
of gcc's features and accepts most of gcc's options. It handles a
|
||||
number of gcc's extensions to the C programming language. See the gcc
|
||||
documentation for details.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over
|
||||
|
||||
=item B<--help>
|
||||
|
||||
Print a summary of command line options.
|
||||
|
||||
=item B<-o> I<filename>
|
||||
|
||||
Specify the output file to be I<filename>.
|
||||
|
||||
=item B<-I> I<directory>
|
||||
|
||||
Add a directory to the header file search path. This option can be
|
||||
repeated.
|
||||
|
||||
=item B<-L> I<directory>
|
||||
|
||||
Add I<directory> to the library search path. This option can be
|
||||
repeated.
|
||||
|
||||
=item B<-l>I<name>
|
||||
|
||||
Link in the library libI<name>.[bc | a | so]. This library should
|
||||
be a bitcode library.
|
||||
|
||||
=item B<-emit-llvm>
|
||||
|
||||
Make the output be LLVM bitcode (with B<-c>) or assembly (with B<-s>) instead
|
||||
of native object (or assembly). If B<-emit-llvm> is given without either B<-c>
|
||||
or B<-S> it has no effect.
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXIT STATUS
|
||||
|
||||
If B<llvm-gcc> succeeds, it will exit with 0. Otherwise, if an error
|
||||
occurs, it will exit with a non-zero value.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<llvm-g++|llvmgxx>
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Maintained by the LLVM Team (L<http://llvm.org/>).
|
||||
|
||||
=cut
|
||||
|
@ -1,85 +0,0 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
llvm-g++ - LLVM C++ front-end
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<llvm-g++> [I<options>] I<filename>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<llvm-g++> command is the LLVM C++ front end. It is a modified
|
||||
version of g++ that compiles C++/ObjC++ programs into native code,
|
||||
LLVM bitcode or assembly language, depending upon the options.
|
||||
|
||||
By default, B<llvm-g++> compiles to native objects just like GCC does. If the
|
||||
B<-emit-llvm> option is given then it will generate LLVM bitcode files instead.
|
||||
If B<-S> (assembly) is also given, then it will generate LLVM assembly.
|
||||
|
||||
Being derived from the GNU Compiler Collection, B<llvm-g++> has many
|
||||
of g++'s features and accepts most of g++'s options. It handles a
|
||||
number of g++'s extensions to the C++ programming language.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over
|
||||
|
||||
=item B<--help>
|
||||
|
||||
Print a summary of command line options.
|
||||
|
||||
=item B<-S>
|
||||
|
||||
Do not generate an LLVM bitcode file. Rather, compile the source
|
||||
file into an LLVM assembly language file.
|
||||
|
||||
=item B<-c>
|
||||
|
||||
Do not generate a linked executable. Rather, compile the source
|
||||
file into an LLVM bitcode file. This bitcode file can then be
|
||||
linked with other bitcode files later on to generate a full LLVM
|
||||
executable.
|
||||
|
||||
=item B<-o> I<filename>
|
||||
|
||||
Specify the output file to be I<filename>.
|
||||
|
||||
=item B<-I> I<directory>
|
||||
|
||||
Add a directory to the header file search path. This option can be
|
||||
repeated.
|
||||
|
||||
=item B<-L> I<directory>
|
||||
|
||||
Add I<directory> to the library search path. This option can be
|
||||
repeated.
|
||||
|
||||
=item B<-l>I<name>
|
||||
|
||||
Link in the library libI<name>.[bc | a | so]. This library should
|
||||
be a bitcode library.
|
||||
|
||||
=item B<-emit-llvm>
|
||||
|
||||
Make the output be LLVM bitcode (or assembly) instead of native object (or
|
||||
assembly).
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXIT STATUS
|
||||
|
||||
If B<llvm-g++> succeeds, it will exit with 0. Otherwise, if an error
|
||||
occurs, it will exit with a non-zero value.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<llvm-gcc|llvmgcc>
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Maintained by the LLVM Team (L<http://llvm.org/>).
|
||||
|
||||
=cut
|
||||
|
@ -1,687 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
|
||||
<title>Customizing LLVMC: Reference Manual</title>
|
||||
<link rel="stylesheet" href="llvm.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="customizing-llvmc-reference-manual">
|
||||
<h1 class="title">Customizing LLVMC: Reference Manual</h1>
|
||||
|
||||
<!-- This file was automatically generated by rst2html.
|
||||
Please do not edit directly!
|
||||
The ReST source lives in the directory 'tools/llvmc/doc'. -->
|
||||
<div class="contents topic" id="contents">
|
||||
<p class="topic-title first">Contents</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#introduction" id="id7">Introduction</a></li>
|
||||
<li><a class="reference internal" href="#compiling-with-llvmc" id="id8">Compiling with <tt class="docutils literal">llvmc</tt></a></li>
|
||||
<li><a class="reference internal" href="#predefined-options" id="id9">Predefined options</a></li>
|
||||
<li><a class="reference internal" href="#compiling-llvmc-based-drivers" id="id10">Compiling LLVMC-based drivers</a></li>
|
||||
<li><a class="reference internal" href="#customizing-llvmc-the-compilation-graph" id="id11">Customizing LLVMC: the compilation graph</a></li>
|
||||
<li><a class="reference internal" href="#describing-options" id="id12">Describing options</a></li>
|
||||
<li><a class="reference internal" href="#conditional-evaluation" id="id13">Conditional evaluation</a></li>
|
||||
<li><a class="reference internal" href="#writing-a-tool-description" id="id14">Writing a tool description</a><ul>
|
||||
<li><a class="reference internal" href="#id4" id="id15">Actions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#language-map" id="id16">Language map</a></li>
|
||||
<li><a class="reference internal" href="#option-preprocessor" id="id17">Option preprocessor</a></li>
|
||||
<li><a class="reference internal" href="#more-advanced-topics" id="id18">More advanced topics</a><ul>
|
||||
<li><a class="reference internal" href="#hooks-and-environment-variables" id="id19">Hooks and environment variables</a></li>
|
||||
<li><a class="reference internal" href="#debugging" id="id20">Debugging</a></li>
|
||||
<li><a class="reference internal" href="#conditioning-on-the-executable-name" id="id21">Conditioning on the executable name</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="doc_author">
|
||||
<p>Written by <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a></p>
|
||||
</div><div class="section" id="introduction">
|
||||
<h1><a class="toc-backref" href="#id7">Introduction</a></h1>
|
||||
<p>LLVMC is a generic compiler driver, designed to be customizable and
|
||||
extensible. It plays the same role for LLVM as the <tt class="docutils literal">gcc</tt> program does for
|
||||
GCC - LLVMC's job is essentially to transform a set of input files into a set of
|
||||
targets depending on configuration rules and user options. What makes LLVMC
|
||||
different is that these transformation rules are completely customizable - in
|
||||
fact, LLVMC knows nothing about the specifics of transformation (even the
|
||||
command-line options are mostly not hard-coded) and regards the transformation
|
||||
structure as an abstract graph. The structure of this graph is described in
|
||||
high-level TableGen code, from which an efficient C++ representation is
|
||||
automatically derived. This makes it possible to adapt LLVMC for other
|
||||
purposes - for example, as a build tool for game resources.</p>
|
||||
<p>Because LLVMC employs <a class="reference external" href="http://llvm.org/docs/TableGenFundamentals.html">TableGen</a> as its configuration language, you
|
||||
need to be familiar with it to customize LLVMC.</p>
|
||||
</div>
|
||||
<div class="section" id="compiling-with-llvmc">
|
||||
<h1><a class="toc-backref" href="#id8">Compiling with <tt class="docutils literal">llvmc</tt></a></h1>
|
||||
<p>LLVMC tries hard to be as compatible with <tt class="docutils literal">gcc</tt> as possible,
|
||||
although there are some small differences. Most of the time, however,
|
||||
you shouldn't be able to notice them:</p>
|
||||
<pre class="literal-block">
|
||||
$ # This works as expected:
|
||||
$ llvmc -O3 -Wall hello.cpp
|
||||
$ ./a.out
|
||||
hello
|
||||
</pre>
|
||||
<p>One nice feature of LLVMC is that one doesn't have to distinguish between
|
||||
different compilers for different languages (think <tt class="docutils literal">g++</tt> vs. <tt class="docutils literal">gcc</tt>) - the
|
||||
right toolchain is chosen automatically based on input language names (which
|
||||
are, in turn, determined from file extensions). If you want to force files
|
||||
ending with ".c" to compile as C++, use the <tt class="docutils literal"><span class="pre">-x</span></tt> option, just like you would
|
||||
do it with <tt class="docutils literal">gcc</tt>:</p>
|
||||
<pre class="literal-block">
|
||||
$ # hello.c is really a C++ file
|
||||
$ llvmc -x c++ hello.c
|
||||
$ ./a.out
|
||||
hello
|
||||
</pre>
|
||||
<p>On the other hand, when using LLVMC as a linker to combine several C++
|
||||
object files you should provide the <tt class="docutils literal"><span class="pre">--linker</span></tt> option since it's
|
||||
impossible for LLVMC to choose the right linker in that case:</p>
|
||||
<pre class="literal-block">
|
||||
$ llvmc -c hello.cpp
|
||||
$ llvmc hello.o
|
||||
[A lot of link-time errors skipped]
|
||||
$ llvmc --linker=c++ hello.o
|
||||
$ ./a.out
|
||||
hello
|
||||
</pre>
|
||||
<p>By default, LLVMC uses <tt class="docutils literal"><span class="pre">llvm-gcc</span></tt> to compile the source code. It is also
|
||||
possible to choose the <tt class="docutils literal">clang</tt> compiler with the <tt class="docutils literal"><span class="pre">-clang</span></tt> option.</p>
|
||||
</div>
|
||||
<div class="section" id="predefined-options">
|
||||
<h1><a class="toc-backref" href="#id9">Predefined options</a></h1>
|
||||
<p>LLVMC has some built-in options that can't be overridden in the TableGen code:</p>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">-o</span> FILE</tt> - Output file name.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">-x</span> LANGUAGE</tt> - Specify the language of the following input files
|
||||
until the next -x option.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">-v</span></tt> - Enable verbose mode, i.e. print out all executed commands.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">--save-temps</span></tt> - Write temporary files to the current directory and do not
|
||||
delete them on exit. This option can also take an argument: the
|
||||
<tt class="docutils literal"><span class="pre">--save-temps=obj</span></tt> switch will write files into the directory specified with
|
||||
the <tt class="docutils literal"><span class="pre">-o</span></tt> option. The <tt class="docutils literal"><span class="pre">--save-temps=cwd</span></tt> and <tt class="docutils literal"><span class="pre">--save-temps</span></tt> switches are
|
||||
both synonyms for the default behaviour.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">--temp-dir</span> DIRECTORY</tt> - Store temporary files in the given directory. This
|
||||
directory is deleted on exit unless <tt class="docutils literal"><span class="pre">--save-temps</span></tt> is specified. If
|
||||
<tt class="docutils literal"><span class="pre">--save-temps=obj</span></tt> is also specified, <tt class="docutils literal"><span class="pre">--temp-dir</span></tt> is given the
|
||||
precedence.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">--check-graph</span></tt> - Check the compilation for common errors like mismatched
|
||||
output/input language names, multiple default edges and cycles. Exit with code
|
||||
zero if no errors were found, and return the number of found errors
|
||||
otherwise. Hidden option, useful for debugging.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">--view-graph</span></tt> - Show a graphical representation of the compilation graph
|
||||
and exit. Requires that you have <tt class="docutils literal">dot</tt> and <tt class="docutils literal">gv</tt> programs installed. Hidden
|
||||
option, useful for debugging.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">--write-graph</span></tt> - Write a <tt class="docutils literal"><span class="pre">compilation-graph.dot</span></tt> file in the current
|
||||
directory with the compilation graph description in Graphviz format (identical
|
||||
to the file used by the <tt class="docutils literal"><span class="pre">--view-graph</span></tt> option). The <tt class="docutils literal"><span class="pre">-o</span></tt> option can be
|
||||
used to set the output file name. Hidden option, useful for debugging.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">--help</span></tt>, <tt class="docutils literal"><span class="pre">--help-hidden</span></tt>, <tt class="docutils literal"><span class="pre">--version</span></tt> - These options have
|
||||
their standard meaning.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="compiling-llvmc-based-drivers">
|
||||
<h1><a class="toc-backref" href="#id10">Compiling LLVMC-based drivers</a></h1>
|
||||
<p>It's easiest to start working on your own LLVMC driver by copying the skeleton
|
||||
project which lives under <tt class="docutils literal">$LLVMC_DIR/examples/Skeleton</tt>:</p>
|
||||
<pre class="literal-block">
|
||||
$ cd $LLVMC_DIR/examples
|
||||
$ cp -r Skeleton MyDriver
|
||||
$ cd MyDriver
|
||||
$ ls
|
||||
AutoGenerated.td Hooks.cpp Main.cpp Makefile
|
||||
</pre>
|
||||
<p>As you can see, our basic driver consists of only three files (not counting the
|
||||
build script). <tt class="docutils literal">AutoGenerated.td</tt> contains TableGen description of the
|
||||
compilation graph; its format is documented in the following
|
||||
sections. <tt class="docutils literal">Hooks.cpp</tt> is an empty file that should be used for hook
|
||||
definitions (see <a class="reference internal" href="#hooks">below</a>). <tt class="docutils literal">Main.cpp</tt> is just a helper used to compile the
|
||||
auto-generated C++ code produced from TableGen source.</p>
|
||||
<p>The first thing that you should do is to change the <tt class="docutils literal">LLVMC_BASED_DRIVER</tt>
|
||||
variable in the <tt class="docutils literal">Makefile</tt>:</p>
|
||||
<pre class="literal-block">
|
||||
LLVMC_BASED_DRIVER=MyDriver
|
||||
</pre>
|
||||
<p>It can also be a good idea to put your TableGen code into a file with a less
|
||||
generic name:</p>
|
||||
<pre class="literal-block">
|
||||
$ touch MyDriver.td
|
||||
$ vim AutoGenerated.td
|
||||
[...]
|
||||
include "MyDriver.td"
|
||||
</pre>
|
||||
<p>If you have more than one TableGen source file, they all should be included from
|
||||
<tt class="docutils literal">AutoGenerated.td</tt>, since this file is used by the build system to generate
|
||||
C++ code.</p>
|
||||
<p>To build your driver, just <tt class="docutils literal">cd</tt> to its source directory and run <tt class="docutils literal">make</tt>. The
|
||||
resulting executable will be put into <tt class="docutils literal"><span class="pre">$LLVM_OBJ_DIR/$(BuildMode)/bin</span></tt>.</p>
|
||||
<p>If you're compiling LLVM with different source and object directories, then you
|
||||
must perform the following additional steps before running <tt class="docutils literal">make</tt>:</p>
|
||||
<pre class="literal-block">
|
||||
# LLVMC_SRC_DIR = $LLVM_SRC_DIR/tools/llvmc/
|
||||
# LLVMC_OBJ_DIR = $LLVM_OBJ_DIR/tools/llvmc/
|
||||
$ mkdir $LLVMC_OBJ_DIR/examples/MyDriver/
|
||||
$ cp $LLVMC_SRC_DIR/examples/MyDriver/Makefile \
|
||||
$LLVMC_OBJ_DIR/examples/MyDriver/
|
||||
$ cd $LLVMC_OBJ_DIR/examples/MyDriver
|
||||
$ make
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="customizing-llvmc-the-compilation-graph">
|
||||
<h1><a class="toc-backref" href="#id11">Customizing LLVMC: the compilation graph</a></h1>
|
||||
<p>Each TableGen configuration file should include the common definitions:</p>
|
||||
<pre class="literal-block">
|
||||
include "llvm/CompilerDriver/Common.td"
|
||||
</pre>
|
||||
<p>Internally, LLVMC stores information about possible source transformations in
|
||||
form of a graph. Nodes in this graph represent tools, and edges between two
|
||||
nodes represent a transformation path. A special "root" node is used to mark
|
||||
entry points for the transformations. LLVMC also assigns a weight to each edge
|
||||
(more on this later) to choose between several alternative edges.</p>
|
||||
<p>The definition of the compilation graph (see file <tt class="docutils literal">llvmc/src/Base.td</tt> for an
|
||||
example) is just a list of edges:</p>
|
||||
<pre class="literal-block">
|
||||
def CompilationGraph : CompilationGraph<[
|
||||
Edge<"root", "llvm_gcc_c">,
|
||||
Edge<"root", "llvm_gcc_assembler">,
|
||||
...
|
||||
|
||||
Edge<"llvm_gcc_c", "llc">,
|
||||
Edge<"llvm_gcc_cpp", "llc">,
|
||||
...
|
||||
|
||||
OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"),
|
||||
(inc_weight))>,
|
||||
OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"),
|
||||
(inc_weight))>,
|
||||
...
|
||||
|
||||
OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker",
|
||||
(case (input_languages_contain "c++"), (inc_weight),
|
||||
(or (parameter_equals "linker", "g++"),
|
||||
(parameter_equals "linker", "c++")), (inc_weight))>,
|
||||
...
|
||||
|
||||
]>;
|
||||
</pre>
|
||||
<p>As you can see, the edges can be either default or optional, where optional
|
||||
edges are differentiated by an additional <tt class="docutils literal">case</tt> expression used to calculate
|
||||
the weight of this edge. Notice also that we refer to tools via their names (as
|
||||
strings). This makes it possible to add edges to an existing compilation graph
|
||||
without having to know about all tool definitions used in the graph.</p>
|
||||
<p>The default edges are assigned a weight of 1, and optional edges get a weight of
|
||||
0 + 2*N where N is the number of tests that evaluated to true in the <tt class="docutils literal">case</tt>
|
||||
expression. It is also possible to provide an integer parameter to
|
||||
<tt class="docutils literal">inc_weight</tt> and <tt class="docutils literal">dec_weight</tt> - in this case, the weight is increased (or
|
||||
decreased) by the provided value instead of the default 2. Default weight of an
|
||||
optional edge can be changed by using the <tt class="docutils literal">default</tt> clause of the <tt class="docutils literal">case</tt>
|
||||
construct.</p>
|
||||
<p>When passing an input file through the graph, LLVMC picks the edge with the
|
||||
maximum weight. To avoid ambiguity, there should be only one default edge
|
||||
between two nodes (with the exception of the root node, which gets a special
|
||||
treatment - there you are allowed to specify one default edge <em>per language</em>).</p>
|
||||
<p>When multiple compilation graphs are defined, they are merged together. Multiple
|
||||
edges with the same end nodes are not allowed (i.e. the graph is not a
|
||||
multigraph), and will lead to a compile-time error.</p>
|
||||
<p>To get a visual representation of the compilation graph (useful for debugging),
|
||||
run <tt class="docutils literal">llvmc <span class="pre">--view-graph</span></tt>. You will need <tt class="docutils literal">dot</tt> and <tt class="docutils literal">gsview</tt> installed for
|
||||
this to work properly.</p>
|
||||
</div>
|
||||
<div class="section" id="describing-options">
|
||||
<h1><a class="toc-backref" href="#id12">Describing options</a></h1>
|
||||
<p>Command-line options supported by the driver are defined by using an
|
||||
<tt class="docutils literal">OptionList</tt>:</p>
|
||||
<pre class="literal-block">
|
||||
def Options : OptionList<[
|
||||
(switch_option "E", (help "Help string")),
|
||||
(alias_option "quiet", "q")
|
||||
...
|
||||
]>;
|
||||
</pre>
|
||||
<p>As you can see, the option list is just a list of DAGs, where each DAG is an
|
||||
option description consisting of the option name and some properties. More than
|
||||
one option list can be defined (they are all merged together in the end), which
|
||||
can be handy if one wants to separate option groups syntactically.</p>
|
||||
<ul>
|
||||
<li><p class="first">Possible option types:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal">switch_option</tt> - a simple boolean switch without arguments, for example
|
||||
<tt class="docutils literal"><span class="pre">-O2</span></tt> or <tt class="docutils literal"><span class="pre">-time</span></tt>. At most one occurrence is allowed by default.</li>
|
||||
<li><tt class="docutils literal">parameter_option</tt> - option that takes one argument, for example
|
||||
<tt class="docutils literal"><span class="pre">-std=c99</span></tt>. It is also allowed to use spaces instead of the equality
|
||||
sign: <tt class="docutils literal"><span class="pre">-std</span> c99</tt>. At most one occurrence is allowed.</li>
|
||||
<li><tt class="docutils literal">parameter_list_option</tt> - same as the above, but more than one option
|
||||
occurrence is allowed.</li>
|
||||
<li><tt class="docutils literal">prefix_option</tt> - same as the parameter_option, but the option name and
|
||||
argument do not have to be separated. Example: <tt class="docutils literal"><span class="pre">-ofile</span></tt>. This can be also
|
||||
specified as <tt class="docutils literal"><span class="pre">-o</span> file</tt>; however, <tt class="docutils literal"><span class="pre">-o=file</span></tt> will be parsed incorrectly
|
||||
(<tt class="docutils literal">=file</tt> will be interpreted as option value). At most one occurrence is
|
||||
allowed.</li>
|
||||
<li><tt class="docutils literal">prefix_list_option</tt> - same as the above, but more than one occurrence of
|
||||
the option is allowed; example: <tt class="docutils literal"><span class="pre">-lm</span> <span class="pre">-lpthread</span></tt>.</li>
|
||||
<li><tt class="docutils literal">alias_option</tt> - a special option type for creating aliases. Unlike other
|
||||
option types, aliases are not allowed to have any properties besides the
|
||||
aliased option name.
|
||||
Usage example: <tt class="docutils literal">(alias_option "preprocess", "E")</tt></li>
|
||||
<li><tt class="docutils literal">switch_list_option</tt> - like <tt class="docutils literal">switch_option</tt> with the <tt class="docutils literal">zero_or_more</tt>
|
||||
property, but remembers how many times the switch was turned on. Useful
|
||||
mostly for forwarding. Example: when <tt class="docutils literal"><span class="pre">-foo</span></tt> is a switch option (with the
|
||||
<tt class="docutils literal">zero_or_more</tt> property), the command <tt class="docutils literal">driver <span class="pre">-foo</span> <span class="pre">-foo</span></tt> is forwarded
|
||||
as <tt class="docutils literal"><span class="pre">some-tool</span> <span class="pre">-foo</span></tt>, but when <tt class="docutils literal"><span class="pre">-foo</span></tt> is a switch list, the same command
|
||||
is forwarded as <tt class="docutils literal"><span class="pre">some-tool</span> <span class="pre">-foo</span> <span class="pre">-foo</span></tt>.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
<li><p class="first">Possible option properties:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal">help</tt> - help string associated with this option. Used for <tt class="docutils literal"><span class="pre">--help</span></tt>
|
||||
output.</li>
|
||||
<li><tt class="docutils literal">required</tt> - this option must be specified exactly once (or, in case of
|
||||
the list options without the <tt class="docutils literal">multi_val</tt> property, at least
|
||||
once). Incompatible with <tt class="docutils literal">optional</tt> and <tt class="docutils literal">one_or_more</tt>.</li>
|
||||
<li><tt class="docutils literal">optional</tt> - the option can be specified either zero times or exactly
|
||||
once. The default for switch options. Useful only for list options in
|
||||
conjunction with <tt class="docutils literal">multi_val</tt>. Incompatible with <tt class="docutils literal">required</tt>,
|
||||
<tt class="docutils literal">zero_or_more</tt> and <tt class="docutils literal">one_or_more</tt>.</li>
|
||||
<li><tt class="docutils literal">one_or_more</tt> - the option must be specified at least once. Can be useful
|
||||
to allow switch options be both obligatory and be specified multiple
|
||||
times. For list options is useful only in conjunction with <tt class="docutils literal">multi_val</tt>;
|
||||
for ordinary it is synonymous with <tt class="docutils literal">required</tt>. Incompatible with
|
||||
<tt class="docutils literal">required</tt>, <tt class="docutils literal">optional</tt> and <tt class="docutils literal">zero_or_more</tt>.</li>
|
||||
<li><tt class="docutils literal">zero_or_more</tt> - the option can be specified zero or more times. Useful
|
||||
to allow a single switch option to be specified more than
|
||||
once. Incompatible with <tt class="docutils literal">required</tt>, <tt class="docutils literal">optional</tt> and <tt class="docutils literal">one_or_more</tt>.</li>
|
||||
<li><tt class="docutils literal">hidden</tt> - the description of this option will not appear in
|
||||
the <tt class="docutils literal"><span class="pre">--help</span></tt> output (but will appear in the <tt class="docutils literal"><span class="pre">--help-hidden</span></tt>
|
||||
output).</li>
|
||||
<li><tt class="docutils literal">really_hidden</tt> - the option will not be mentioned in any help
|
||||
output.</li>
|
||||
<li><tt class="docutils literal">comma_separated</tt> - Indicates that any commas specified for an option's
|
||||
value should be used to split the value up into multiple values for the
|
||||
option. This property is valid only for list options. In conjunction with
|
||||
<tt class="docutils literal">forward_value</tt> can be used to implement option forwarding in style of
|
||||
gcc's <tt class="docutils literal"><span class="pre">-Wa,</span></tt>.</li>
|
||||
<li><tt class="docutils literal">multi_val n</tt> - this option takes <em>n</em> arguments (can be useful in some
|
||||
special cases). Usage example: <tt class="docutils literal">(parameter_list_option "foo", (multi_val
|
||||
3))</tt>; the command-line syntax is '-foo a b c'. Only list options can have
|
||||
this attribute; you can, however, use the <tt class="docutils literal">one_or_more</tt>, <tt class="docutils literal">optional</tt>
|
||||
and <tt class="docutils literal">required</tt> properties.</li>
|
||||
<li><tt class="docutils literal">init</tt> - this option has a default value, either a string (if it is a
|
||||
parameter), or a boolean (if it is a switch; as in C++, boolean constants
|
||||
are called <tt class="docutils literal">true</tt> and <tt class="docutils literal">false</tt>). List options can't have <tt class="docutils literal">init</tt>
|
||||
attribute.
|
||||
Usage examples: <tt class="docutils literal">(switch_option "foo", (init true))</tt>; <tt class="docutils literal">(prefix_option
|
||||
"bar", (init <span class="pre">"baz"))</span></tt>.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="conditional-evaluation">
|
||||
<span id="case"></span><h1><a class="toc-backref" href="#id13">Conditional evaluation</a></h1>
|
||||
<p>The 'case' construct is the main means by which programmability is achieved in
|
||||
LLVMC. It can be used to calculate edge weights, program actions and modify the
|
||||
shell commands to be executed. The 'case' expression is designed after the
|
||||
similarly-named construct in functional languages and takes the form <tt class="docutils literal">(case
|
||||
(test_1), statement_1, (test_2), statement_2, ... (test_N), statement_N)</tt>. The
|
||||
statements are evaluated only if the corresponding tests evaluate to true.</p>
|
||||
<p>Examples:</p>
|
||||
<pre class="literal-block">
|
||||
// Edge weight calculation
|
||||
|
||||
// Increases edge weight by 5 if "-A" is provided on the
|
||||
// command-line, and by 5 more if "-B" is also provided.
|
||||
(case
|
||||
(switch_on "A"), (inc_weight 5),
|
||||
(switch_on "B"), (inc_weight 5))
|
||||
|
||||
|
||||
// Tool command line specification
|
||||
|
||||
// Evaluates to "cmdline1" if the option "-A" is provided on the
|
||||
// command line; to "cmdline2" if "-B" is provided;
|
||||
// otherwise to "cmdline3".
|
||||
|
||||
(case
|
||||
(switch_on "A"), "cmdline1",
|
||||
(switch_on "B"), "cmdline2",
|
||||
(default), "cmdline3")
|
||||
</pre>
|
||||
<p>Note the slight difference in 'case' expression handling in contexts of edge
|
||||
weights and command line specification - in the second example the value of the
|
||||
<tt class="docutils literal">"B"</tt> switch is never checked when switch <tt class="docutils literal">"A"</tt> is enabled, and the whole
|
||||
expression always evaluates to <tt class="docutils literal">"cmdline1"</tt> in that case.</p>
|
||||
<p>Case expressions can also be nested, i.e. the following is legal:</p>
|
||||
<pre class="literal-block">
|
||||
(case (switch_on "E"), (case (switch_on "o"), ..., (default), ...)
|
||||
(default), ...)
|
||||
</pre>
|
||||
<p>You should, however, try to avoid doing that because it hurts readability. It is
|
||||
usually better to split tool descriptions and/or use TableGen inheritance
|
||||
instead.</p>
|
||||
<ul class="simple">
|
||||
<li>Possible tests are:<ul>
|
||||
<li><tt class="docutils literal">switch_on</tt> - Returns true if a given command-line switch is provided by
|
||||
the user. Can be given multiple arguments, in that case <tt class="docutils literal">(switch_on "foo",
|
||||
"bar", "baz")</tt> is equivalent to <tt class="docutils literal">(and (switch_on <span class="pre">"foo"),</span> (switch_on
|
||||
<span class="pre">"bar"),</span> (switch_on <span class="pre">"baz"))</span></tt>.
|
||||
Example: <tt class="docutils literal">(switch_on "opt")</tt>.</li>
|
||||
<li><tt class="docutils literal">any_switch_on</tt> - Given a number of switch options, returns true if any of
|
||||
the switches is turned on.
|
||||
Example: <tt class="docutils literal">(any_switch_on "foo", "bar", "baz")</tt> is equivalent to <tt class="docutils literal">(or
|
||||
(switch_on <span class="pre">"foo"),</span> (switch_on <span class="pre">"bar"),</span> (switch_on <span class="pre">"baz"))</span></tt>.</li>
|
||||
<li><tt class="docutils literal">parameter_equals</tt> - Returns true if a command-line parameter (first
|
||||
argument) equals a given value (second argument).
|
||||
Example: <tt class="docutils literal">(parameter_equals "W", "all")</tt>.</li>
|
||||
<li><tt class="docutils literal">element_in_list</tt> - Returns true if a command-line parameter list (first
|
||||
argument) contains a given value (second argument).
|
||||
Example: <tt class="docutils literal">(element_in_list "l", "pthread")</tt>.</li>
|
||||
<li><tt class="docutils literal">input_languages_contain</tt> - Returns true if a given language
|
||||
belongs to the current input language set.
|
||||
Example: <tt class="docutils literal">(input_languages_contain <span class="pre">"c++")</span></tt>.</li>
|
||||
<li><tt class="docutils literal">in_language</tt> - Evaluates to true if the input file language is equal to
|
||||
the argument. At the moment works only with <tt class="docutils literal">command</tt> and <tt class="docutils literal">actions</tt> (on
|
||||
non-join nodes).
|
||||
Example: <tt class="docutils literal">(in_language <span class="pre">"c++")</span></tt>.</li>
|
||||
<li><tt class="docutils literal">not_empty</tt> - Returns true if a given option (which should be either a
|
||||
parameter or a parameter list) is set by the user. Like <tt class="docutils literal">switch_on</tt>, can
|
||||
be also given multiple arguments.
|
||||
Examples: <tt class="docutils literal">(not_empty "o")</tt>, <tt class="docutils literal">(not_empty "o", "l")</tt>.</li>
|
||||
<li><tt class="docutils literal">any_not_empty</tt> - Returns true if <tt class="docutils literal">not_empty</tt> returns true for any of
|
||||
the provided options.
|
||||
Example: <tt class="docutils literal">(any_not_empty "foo", "bar", "baz")</tt> is equivalent to <tt class="docutils literal">(or
|
||||
(not_empty <span class="pre">"foo"),</span> (not_empty <span class="pre">"bar"),</span> (not_empty <span class="pre">"baz"))</span></tt>.</li>
|
||||
<li><tt class="docutils literal">empty</tt> - The opposite of <tt class="docutils literal">not_empty</tt>. Equivalent to <tt class="docutils literal">(not (not_empty
|
||||
X))</tt>. Can be given multiple arguments.</li>
|
||||
<li><tt class="docutils literal">any_not_empty</tt> - Returns true if <tt class="docutils literal">not_empty</tt> returns true for any of
|
||||
the provided options.
|
||||
Example: <tt class="docutils literal">(any_empty "foo", "bar", "baz")</tt> is equivalent to <tt class="docutils literal">(or
|
||||
(not_empty <span class="pre">"foo"),</span> (not_empty <span class="pre">"bar"),</span> (not_empty <span class="pre">"baz"))</span></tt>.</li>
|
||||
<li><tt class="docutils literal">single_input_file</tt> - Returns true if there was only one input file
|
||||
provided on the command-line. Used without arguments:
|
||||
<tt class="docutils literal">(single_input_file)</tt>.</li>
|
||||
<li><tt class="docutils literal">multiple_input_files</tt> - Equivalent to <tt class="docutils literal">(not (single_input_file))</tt> (the
|
||||
case of zero input files is considered an error).</li>
|
||||
<li><tt class="docutils literal">default</tt> - Always evaluates to true. Should always be the last
|
||||
test in the <tt class="docutils literal">case</tt> expression.</li>
|
||||
<li><tt class="docutils literal">and</tt> - A standard logical combinator that returns true iff all of
|
||||
its arguments return true. Used like this: <tt class="docutils literal">(and (test1), (test2),
|
||||
... (testN))</tt>. Nesting of <tt class="docutils literal">and</tt> and <tt class="docutils literal">or</tt> is allowed, but not
|
||||
encouraged.</li>
|
||||
<li><tt class="docutils literal">or</tt> - A logical combinator that returns true iff any of its arguments
|
||||
return true.
|
||||
Example: <tt class="docutils literal">(or (test1), (test2), ... (testN))</tt>.</li>
|
||||
<li><tt class="docutils literal">not</tt> - Standard unary logical combinator that negates its
|
||||
argument.
|
||||
Example: <tt class="docutils literal">(not (or (test1), (test2), ... <span class="pre">(testN)))</span></tt>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="writing-a-tool-description">
|
||||
<h1><a class="toc-backref" href="#id14">Writing a tool description</a></h1>
|
||||
<p>As was said earlier, nodes in the compilation graph represent tools, which are
|
||||
described separately. A tool definition looks like this (taken from the
|
||||
<tt class="docutils literal">llvmc/src/Base.td</tt> file):</p>
|
||||
<pre class="literal-block">
|
||||
def llvm_gcc_cpp : Tool<[
|
||||
(in_language "c++"),
|
||||
(out_language "llvm-assembler"),
|
||||
(output_suffix "bc"),
|
||||
(command "llvm-g++ -c -emit-llvm"),
|
||||
(sink)
|
||||
]>;
|
||||
</pre>
|
||||
<p>This defines a new tool called <tt class="docutils literal">llvm_gcc_cpp</tt>, which is an alias for
|
||||
<tt class="docutils literal"><span class="pre">llvm-g++</span></tt>. As you can see, a tool definition is just a list of properties;
|
||||
most of them should be self-explanatory. The <tt class="docutils literal">sink</tt> property means that this
|
||||
tool should be passed all command-line options that aren't mentioned in the
|
||||
option list.</p>
|
||||
<p>The complete list of all currently implemented tool properties follows.</p>
|
||||
<ul class="simple">
|
||||
<li>Possible tool properties:<ul>
|
||||
<li><tt class="docutils literal">in_language</tt> - input language name. Can be given multiple arguments, in
|
||||
case the tool supports multiple input languages. Used for typechecking and
|
||||
mapping file extensions to tools.</li>
|
||||
<li><tt class="docutils literal">out_language</tt> - output language name. Multiple output languages are
|
||||
allowed. Used for typechecking the compilation graph.</li>
|
||||
<li><tt class="docutils literal">output_suffix</tt> - output file suffix. Can also be changed dynamically, see
|
||||
documentation on <a class="reference internal" href="#actions">actions</a>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal">command</tt> - the actual command used to run the tool. You can use output
|
||||
redirection with <tt class="docutils literal">></tt>, hook invocations (<tt class="docutils literal">$CALL</tt>), environment variables
|
||||
(via <tt class="docutils literal">$ENV</tt>) and the <tt class="docutils literal">case</tt> construct.</li>
|
||||
<li><tt class="docutils literal">join</tt> - this tool is a "join node" in the graph, i.e. it gets a list of
|
||||
input files and joins them together. Used for linkers.</li>
|
||||
<li><tt class="docutils literal">sink</tt> - all command-line options that are not handled by other tools are
|
||||
passed to this tool.</li>
|
||||
<li><tt class="docutils literal">actions</tt> - A single big <tt class="docutils literal">case</tt> expression that specifies how this tool
|
||||
reacts on command-line options (described in more detail <a class="reference internal" href="#actions">below</a>).</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal">out_file_option</tt>, <tt class="docutils literal">in_file_option</tt> - Options appended to the
|
||||
<tt class="docutils literal">command</tt> string to designate output and input files. Default values are
|
||||
<tt class="docutils literal"><span class="pre">"-o"</span></tt> and <tt class="docutils literal">""</tt>, respectively.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<div class="section" id="id4">
|
||||
<span id="actions"></span><h2><a class="toc-backref" href="#id15">Actions</a></h2>
|
||||
<p>A tool often needs to react to command-line options, and this is precisely what
|
||||
the <tt class="docutils literal">actions</tt> property is for. The next example illustrates this feature:</p>
|
||||
<pre class="literal-block">
|
||||
def llvm_gcc_linker : Tool<[
|
||||
(in_language "object-code"),
|
||||
(out_language "executable"),
|
||||
(output_suffix "out"),
|
||||
(command "llvm-gcc"),
|
||||
(join),
|
||||
(actions (case (not_empty "L"), (forward "L"),
|
||||
(not_empty "l"), (forward "l"),
|
||||
(not_empty "dummy"),
|
||||
[(append_cmd "-dummy1"), (append_cmd "-dummy2")])
|
||||
]>;
|
||||
</pre>
|
||||
<p>The <tt class="docutils literal">actions</tt> tool property is implemented on top of the omnipresent <tt class="docutils literal">case</tt>
|
||||
expression. It associates one or more different <em>actions</em> with given
|
||||
conditions - in the example, the actions are <tt class="docutils literal">forward</tt>, which forwards a given
|
||||
option unchanged, and <tt class="docutils literal">append_cmd</tt>, which appends a given string to the tool
|
||||
execution command. Multiple actions can be associated with a single condition by
|
||||
using a list of actions (used in the example to append some dummy options). The
|
||||
same <tt class="docutils literal">case</tt> construct can also be used in the <tt class="docutils literal">cmd_line</tt> property to modify
|
||||
the tool command line.</p>
|
||||
<p>The "join" property used in the example means that this tool behaves like a
|
||||
linker.</p>
|
||||
<p>The list of all possible actions follows.</p>
|
||||
<ul>
|
||||
<li><p class="first">Possible actions:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal">append_cmd</tt> - Append a string to the tool invocation command.
|
||||
Example: <tt class="docutils literal">(case (switch_on <span class="pre">"pthread"),</span> (append_cmd <span class="pre">"-lpthread"))</span></tt>.</li>
|
||||
<li><tt class="docutils literal">error</tt> - Exit with error.
|
||||
Example: <tt class="docutils literal">(error "Mixing <span class="pre">-c</span> and <span class="pre">-S</span> is not <span class="pre">allowed!")</span></tt>.</li>
|
||||
<li><tt class="docutils literal">warning</tt> - Print a warning.
|
||||
Example: <tt class="docutils literal">(warning "Specifying both <span class="pre">-O1</span> and <span class="pre">-O2</span> is <span class="pre">meaningless!")</span></tt>.</li>
|
||||
<li><tt class="docutils literal">forward</tt> - Forward the option unchanged.
|
||||
Example: <tt class="docutils literal">(forward "Wall")</tt>.</li>
|
||||
<li><tt class="docutils literal">forward_as</tt> - Change the option's name, but forward the argument
|
||||
unchanged.
|
||||
Example: <tt class="docutils literal">(forward_as "O0", <span class="pre">"--disable-optimization")</span></tt>.</li>
|
||||
<li><tt class="docutils literal">forward_value</tt> - Forward only option's value. Cannot be used with switch
|
||||
options (since they don't have values), but works fine with lists.
|
||||
Example: <tt class="docutils literal">(forward_value <span class="pre">"Wa,")</span></tt>.</li>
|
||||
<li><tt class="docutils literal">forward_transformed_value</tt> - As above, but applies a hook to the
|
||||
option's value before forwarding (see <a class="reference internal" href="#hooks">below</a>). When
|
||||
<tt class="docutils literal">forward_transformed_value</tt> is applied to a list
|
||||
option, the hook must have signature
|
||||
<tt class="docutils literal"><span class="pre">std::string</span> <span class="pre">hooks::HookName</span> (const <span class="pre">std::vector<std::string>&)</span></tt>.
|
||||
Example: <tt class="docutils literal">(forward_transformed_value "m", "ConvertToMAttr")</tt>.</li>
|
||||
<li><tt class="docutils literal">output_suffix</tt> - Modify the output suffix of this tool.
|
||||
Example: <tt class="docutils literal">(output_suffix "i")</tt>.</li>
|
||||
<li><tt class="docutils literal">stop_compilation</tt> - Stop compilation after this tool processes its
|
||||
input. Used without arguments.
|
||||
Example: <tt class="docutils literal">(stop_compilation)</tt>.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="language-map">
|
||||
<h1><a class="toc-backref" href="#id16">Language map</a></h1>
|
||||
<p>If you are adding support for a new language to LLVMC, you'll need to modify the
|
||||
language map, which defines mappings from file extensions to language names. It
|
||||
is used to choose the proper toolchain(s) for a given input file set. Language
|
||||
map definition looks like this:</p>
|
||||
<pre class="literal-block">
|
||||
def LanguageMap : LanguageMap<
|
||||
[LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
|
||||
LangToSuffixes<"c", ["c"]>,
|
||||
...
|
||||
]>;
|
||||
</pre>
|
||||
<p>For example, without those definitions the following command wouldn't work:</p>
|
||||
<pre class="literal-block">
|
||||
$ llvmc hello.cpp
|
||||
llvmc: Unknown suffix: cpp
|
||||
</pre>
|
||||
<p>The language map entries are needed only for the tools that are linked from the
|
||||
root node. A tool can have multiple output languages.</p>
|
||||
</div>
|
||||
<div class="section" id="option-preprocessor">
|
||||
<h1><a class="toc-backref" href="#id17">Option preprocessor</a></h1>
|
||||
<p>It is sometimes useful to run error-checking code before processing the
|
||||
compilation graph. For example, if optimization options "-O1" and "-O2" are
|
||||
implemented as switches, we might want to output a warning if the user invokes
|
||||
the driver with both of these options enabled.</p>
|
||||
<p>The <tt class="docutils literal">OptionPreprocessor</tt> feature is reserved specially for these
|
||||
occasions. Example (adapted from <tt class="docutils literal">llvm/src/Base.td.in</tt>):</p>
|
||||
<pre class="literal-block">
|
||||
def Preprocess : OptionPreprocessor<
|
||||
(case (not (any_switch_on "O0", "O1", "O2", "O3")),
|
||||
(set_option "O2"),
|
||||
(and (switch_on "O3"), (any_switch_on "O0", "O1", "O2")),
|
||||
(unset_option "O0", "O1", "O2"),
|
||||
(and (switch_on "O2"), (any_switch_on "O0", "O1")),
|
||||
(unset_option "O0", "O1"),
|
||||
(and (switch_on "O1"), (switch_on "O0")),
|
||||
(unset_option "O0"))
|
||||
>;
|
||||
</pre>
|
||||
<p>Here, <tt class="docutils literal">OptionPreprocessor</tt> is used to unset all spurious <tt class="docutils literal"><span class="pre">-O</span></tt> options so
|
||||
that they are not forwarded to the compiler. If no optimization options are
|
||||
specified, <tt class="docutils literal"><span class="pre">-O2</span></tt> is enabled.</p>
|
||||
<p><tt class="docutils literal">OptionPreprocessor</tt> is basically a single big <tt class="docutils literal">case</tt> expression, which is
|
||||
evaluated only once right after the driver is started. The only allowed actions
|
||||
in <tt class="docutils literal">OptionPreprocessor</tt> are <tt class="docutils literal">error</tt>, <tt class="docutils literal">warning</tt>, and two special actions:
|
||||
<tt class="docutils literal">unset_option</tt> and <tt class="docutils literal">set_option</tt>. As their names suggest, they can be used to
|
||||
set or unset a given option. To set an option with <tt class="docutils literal">set_option</tt>, use the
|
||||
two-argument form: <tt class="docutils literal">(set_option "parameter", VALUE)</tt>. Here, <tt class="docutils literal">VALUE</tt> can be
|
||||
either a string, a string list, or a boolean constant.</p>
|
||||
<p>For convenience, <tt class="docutils literal">set_option</tt> and <tt class="docutils literal">unset_option</tt> also work with multiple
|
||||
arguments. That is, instead of <tt class="docutils literal">[(unset_option <span class="pre">"A"),</span> (unset_option <span class="pre">"B")]</span></tt> you
|
||||
can use <tt class="docutils literal">(unset_option "A", "B")</tt>. Obviously, <tt class="docutils literal">(set_option "A", "B")</tt> is
|
||||
only valid if both <tt class="docutils literal">A</tt> and <tt class="docutils literal">B</tt> are switches.</p>
|
||||
</div>
|
||||
<div class="section" id="more-advanced-topics">
|
||||
<h1><a class="toc-backref" href="#id18">More advanced topics</a></h1>
|
||||
<div class="section" id="hooks-and-environment-variables">
|
||||
<span id="hooks"></span><h2><a class="toc-backref" href="#id19">Hooks and environment variables</a></h2>
|
||||
<p>Normally, LLVMC searches for programs in the system <tt class="docutils literal">PATH</tt>. Sometimes, this is
|
||||
not sufficient: for example, we may want to specify tool paths or names in the
|
||||
configuration file. This can be achieved via the hooks mechanism. To write your
|
||||
own hooks, add their definitions to the <tt class="docutils literal">Hooks.cpp</tt> or drop a <tt class="docutils literal">.cpp</tt> file
|
||||
into your driver directory. Hooks should live in the <tt class="docutils literal">hooks</tt> namespace and
|
||||
have the signature <tt class="docutils literal"><span class="pre">std::string</span> <span class="pre">hooks::MyHookName</span> ([const char* Arg0 [ const
|
||||
char* Arg2 [, <span class="pre">...]]])</span></tt>. They can be used from the <tt class="docutils literal">command</tt> tool property:</p>
|
||||
<pre class="literal-block">
|
||||
(command "$CALL(MyHook)/path/to/file -o $CALL(AnotherHook)")
|
||||
</pre>
|
||||
<p>To pass arguments to hooks, use the following syntax:</p>
|
||||
<pre class="literal-block">
|
||||
(command "$CALL(MyHook, 'Arg1', 'Arg2', 'Arg # 3')/path/to/file -o1 -o2")
|
||||
</pre>
|
||||
<p>It is also possible to use environment variables in the same manner:</p>
|
||||
<pre class="literal-block">
|
||||
(command "$ENV(VAR1)/path/to/file -o $ENV(VAR2)")
|
||||
</pre>
|
||||
<p>To change the command line string based on user-provided options use
|
||||
the <tt class="docutils literal">case</tt> expression (documented <a class="reference internal" href="#case">above</a>):</p>
|
||||
<pre class="literal-block">
|
||||
(command
|
||||
(case
|
||||
(switch_on "E"),
|
||||
"llvm-g++ -E -x c $INFILE -o $OUTFILE",
|
||||
(default),
|
||||
"llvm-g++ -c -x c $INFILE -o $OUTFILE -emit-llvm"))
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="debugging">
|
||||
<h2><a class="toc-backref" href="#id20">Debugging</a></h2>
|
||||
<p>When writing LLVMC-based drivers, it can be useful to get a visual view of the
|
||||
resulting compilation graph. This can be achieved via the command line option
|
||||
<tt class="docutils literal"><span class="pre">--view-graph</span></tt> (which assumes that <a class="reference external" href="http://www.graphviz.org/">Graphviz</a> and <a class="reference external" href="http://pages.cs.wisc.edu/~ghost/">Ghostview</a> are
|
||||
installed). There is also a <tt class="docutils literal"><span class="pre">--write-graph</span></tt> option that creates a Graphviz
|
||||
source file (<tt class="docutils literal"><span class="pre">compilation-graph.dot</span></tt>) in the current directory.</p>
|
||||
<p>Another useful <tt class="docutils literal">llvmc</tt> option is <tt class="docutils literal"><span class="pre">--check-graph</span></tt>. It checks the compilation
|
||||
graph for common errors like mismatched output/input language names, multiple
|
||||
default edges and cycles. When invoked with <tt class="docutils literal"><span class="pre">--check-graph</span></tt>, <tt class="docutils literal">llvmc</tt> doesn't
|
||||
perform any compilation tasks and returns the number of encountered errors as
|
||||
its status code. In the future, these checks will be performed at compile-time
|
||||
and this option will disappear.</p>
|
||||
</div>
|
||||
<div class="section" id="conditioning-on-the-executable-name">
|
||||
<h2><a class="toc-backref" href="#id21">Conditioning on the executable name</a></h2>
|
||||
<p>For now, the executable name (the value passed to the driver in <tt class="docutils literal">argv[0]</tt>) is
|
||||
accessible only in the C++ code (i.e. hooks). Use the following code:</p>
|
||||
<pre class="literal-block">
|
||||
namespace llvmc {
|
||||
extern const char* ProgramName;
|
||||
}
|
||||
|
||||
namespace hooks {
|
||||
|
||||
std::string MyHook() {
|
||||
//...
|
||||
if (strcmp(ProgramName, "mydriver") == 0) {
|
||||
//...
|
||||
|
||||
}
|
||||
|
||||
} // end namespace hooks
|
||||
</pre>
|
||||
<p>In general, you're encouraged not to make the behaviour dependent on the
|
||||
executable file name, and use command-line switches instead. See for example how
|
||||
the <tt class="docutils literal">llvmc</tt> program behaves when it needs to choose the correct linker options
|
||||
(think <tt class="docutils literal">g++</tt> vs. <tt class="docutils literal">gcc</tt>).</p>
|
||||
<hr />
|
||||
<address>
|
||||
<a href="http://jigsaw.w3.org/css-validator/check/referer">
|
||||
<img src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
|
||||
alt="Valid CSS" /></a>
|
||||
<a href="http://validator.w3.org/check?uri=referer">
|
||||
<img src="http://www.w3.org/Icons/valid-xhtml10-blue"
|
||||
alt="Valid XHTML 1.0 Transitional"/></a>
|
||||
|
||||
<a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a><br />
|
||||
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br />
|
||||
|
||||
Last modified: $Date: 2011-05-07 00:11:29 +0200 (Sat, 07 May 2011) $
|
||||
</address></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,125 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
|
||||
<title>Tutorial - Using LLVMC</title>
|
||||
<link rel="stylesheet" href="llvm.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="tutorial-using-llvmc">
|
||||
<h1 class="title">Tutorial - Using LLVMC</h1>
|
||||
|
||||
<!-- This file was automatically generated by rst2html.
|
||||
Please do not edit directly!
|
||||
The ReST source lives in the directory 'tools/llvmc/doc'. -->
|
||||
<div class="contents topic" id="contents">
|
||||
<p class="topic-title first">Contents</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#introduction" id="id1">Introduction</a></li>
|
||||
<li><a class="reference internal" href="#using-the-llvmc-program" id="id2">Using the <tt class="docutils literal">llvmc</tt> program</a></li>
|
||||
<li><a class="reference internal" href="#using-llvmc-to-generate-toolchain-drivers" id="id3">Using LLVMC to generate toolchain drivers</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="doc_author">
|
||||
<p>Written by <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a></p>
|
||||
</div><div class="section" id="introduction">
|
||||
<h1><a class="toc-backref" href="#id1">Introduction</a></h1>
|
||||
<p>LLVMC is a generic compiler driver, which plays the same role for LLVM as the
|
||||
<tt class="docutils literal">gcc</tt> program does for GCC - the difference being that LLVMC is designed to be
|
||||
more adaptable and easier to customize. Most of LLVMC functionality is
|
||||
implemented via high-level TableGen code, from which a corresponding C++ source
|
||||
file is automatically generated. This tutorial describes the basic usage and
|
||||
configuration of LLVMC.</p>
|
||||
</div>
|
||||
<div class="section" id="using-the-llvmc-program">
|
||||
<h1><a class="toc-backref" href="#id2">Using the <tt class="docutils literal">llvmc</tt> program</a></h1>
|
||||
<p>In general, <tt class="docutils literal">llvmc</tt> tries to be command-line compatible with <tt class="docutils literal">gcc</tt> as much
|
||||
as possible, so most of the familiar options work:</p>
|
||||
<pre class="literal-block">
|
||||
$ llvmc -O3 -Wall hello.cpp
|
||||
$ ./a.out
|
||||
hello
|
||||
</pre>
|
||||
<p>This will invoke <tt class="docutils literal"><span class="pre">llvm-g++</span></tt> under the hood (you can see which commands are
|
||||
executed by using the <tt class="docutils literal"><span class="pre">-v</span></tt> option). For further help on command-line LLVMC
|
||||
usage, refer to the <tt class="docutils literal">llvmc <span class="pre">--help</span></tt> output.</p>
|
||||
</div>
|
||||
<div class="section" id="using-llvmc-to-generate-toolchain-drivers">
|
||||
<h1><a class="toc-backref" href="#id3">Using LLVMC to generate toolchain drivers</a></h1>
|
||||
<p>LLVMC-based drivers are written mostly using <a class="reference external" href="http://llvm.org/docs/TableGenFundamentals.html">TableGen</a>, so you need to be
|
||||
familiar with it to get anything done.</p>
|
||||
<p>Start by compiling <tt class="docutils literal">example/Simple</tt>, which is a primitive wrapper for
|
||||
<tt class="docutils literal">gcc</tt>:</p>
|
||||
<pre class="literal-block">
|
||||
$ cd $LLVM_OBJ_DIR/tools/examples/Simple
|
||||
$ make
|
||||
$ cat > hello.c
|
||||
#include <stdio.h>
|
||||
int main() { printf("Hello\n"); }
|
||||
$ $LLVM_BIN_DIR/Simple -v hello.c
|
||||
gcc hello.c -o hello.out
|
||||
$ ./hello.out
|
||||
Hello
|
||||
</pre>
|
||||
<p>We have thus produced a simple driver called, appropriately, <tt class="docutils literal">Simple</tt>, from
|
||||
the input TableGen file <tt class="docutils literal">Simple.td</tt>. The <tt class="docutils literal">llvmc</tt> program itself is generated
|
||||
using a similar process (see <tt class="docutils literal">llvmc/src</tt>). Contents of the file <tt class="docutils literal">Simple.td</tt>
|
||||
look like this:</p>
|
||||
<pre class="literal-block">
|
||||
// Include common definitions
|
||||
include "llvm/CompilerDriver/Common.td"
|
||||
|
||||
// Tool descriptions
|
||||
def gcc : Tool<
|
||||
[(in_language "c"),
|
||||
(out_language "executable"),
|
||||
(output_suffix "out"),
|
||||
(command "gcc"),
|
||||
(sink),
|
||||
|
||||
// -o is what is used by default, out_file_option here is included for
|
||||
// instructive purposes.
|
||||
(out_file_option "-o")
|
||||
]>;
|
||||
|
||||
// Language map
|
||||
def LanguageMap : LanguageMap<[(lang_to_suffixes "c", "c")]>;
|
||||
|
||||
// Compilation graph
|
||||
def CompilationGraph : CompilationGraph<[(edge "root", "gcc")]>;
|
||||
</pre>
|
||||
<p>As you can see, this file consists of three parts: tool descriptions, language
|
||||
map, and the compilation graph definition.</p>
|
||||
<p>At the heart of LLVMC is the idea of a compilation graph: vertices in this graph
|
||||
are tools, and edges represent a transformation path between two tools (for
|
||||
example, assembly source produced by the compiler can be transformed into
|
||||
executable code by an assembler). The compilation graph is basically a list of
|
||||
edges; a special node named <tt class="docutils literal">root</tt> is used to mark graph entry points.</p>
|
||||
<p>Tool descriptions are represented as property lists: most properties in the
|
||||
example above should be self-explanatory; the <tt class="docutils literal">sink</tt> property means that all
|
||||
options lacking an explicit description should be forwarded to this tool.</p>
|
||||
<p>The <tt class="docutils literal">LanguageMap</tt> associates a language name with a list of suffixes and is
|
||||
used for deciding which toolchain corresponds to a given input file.</p>
|
||||
<p>To learn more about writing your own drivers with LLVMC, refer to the reference
|
||||
manual and examples in the <tt class="docutils literal">examples</tt> directory. Of a particular interest is
|
||||
the <tt class="docutils literal">Skeleton</tt> example, which can serve as a template for your LLVMC-based
|
||||
drivers.</p>
|
||||
<hr />
|
||||
<address>
|
||||
<a href="http://jigsaw.w3.org/css-validator/check/referer">
|
||||
<img src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
|
||||
alt="Valid CSS" /></a>
|
||||
<a href="http://validator.w3.org/check?uri=referer">
|
||||
<img src="http://www.w3.org/Icons/valid-xhtml10-blue"
|
||||
alt="Valid XHTML 1.0 Transitional"/></a>
|
||||
|
||||
<a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a><br />
|
||||
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br />
|
||||
|
||||
Last modified: $Date: 2008-12-11 11:34:48 -0600 (Thu, 11 Dec 2008) $
|
||||
</address></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -207,7 +207,11 @@
|
||||
|
||||
<li><b>Chris Lattner</b>: Everything not covered by someone else.</li>
|
||||
|
||||
<li><b>Duncan Sands</b>: llvm-gcc 4.2.</li>
|
||||
<li><b>John McCall</b>: Clang LLVM IR generation.</li>
|
||||
|
||||
<li><b>Jakob Olesen</b>: Register allocators and TableGen.</li>
|
||||
|
||||
<li><b>Duncan Sands</b>: dragonegg and llvm-gcc 4.2.</li>
|
||||
</ol>
|
||||
|
||||
<p>Note that code ownership is completely different than reviewers: anyone can
|
||||
@ -492,8 +496,9 @@
|
||||
|
||||
<div>
|
||||
<p>This section addresses the issues of copyright, license and patents for the
|
||||
LLVM project. Currently, the University of Illinois is the LLVM copyright
|
||||
holder and the terms of its license to LLVM users and developers is the
|
||||
LLVM project. The copyright holder for the code is held by the individual
|
||||
contributors of the code and the terms of its license to LLVM users and
|
||||
developers is the
|
||||
<a href="http://www.opensource.org/licenses/UoI-NCSA.php">University of
|
||||
Illinois/NCSA Open Source License</a>.</p>
|
||||
|
||||
@ -611,7 +616,7 @@
|
||||
Written by the
|
||||
<a href="mailto:llvm-oversight@cs.uiuc.edu">LLVM Oversight Group</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-10-07 19:26:38 +0200 (Fri, 07 Oct 2011) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -33,9 +33,6 @@
|
||||
</ol></li>
|
||||
<li><a href="#format_common_intrinsics">Exception Handling Intrinsics</a>
|
||||
<ol>
|
||||
<li><a href="#llvm_eh_exception"><tt>llvm.eh.exception</tt></a></li>
|
||||
<li><a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a></li>
|
||||
<li><a href="#llvm_eh_resume"><tt>llvm.eh.resume</tt></a></li>
|
||||
<li><a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a></li>
|
||||
<li><a href="#llvm_eh_sjlj_setjmp"><tt>llvm.eh.sjlj.setjmp</tt></a></li>
|
||||
<li><a href="#llvm_eh_sjlj_longjmp"><tt>llvm.eh.sjlj.longjmp</tt></a></li>
|
||||
@ -48,7 +45,6 @@
|
||||
<li><a href="#unwind_tables">Exception Handling Frame</a></li>
|
||||
<li><a href="#exception_tables">Exception Tables</a></li>
|
||||
</ol></li>
|
||||
<li><a href="#todo">ToDo</a></li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr></table>
|
||||
@ -69,7 +65,7 @@
|
||||
handling information takes, which is useful for those interested in creating
|
||||
front-ends or dealing directly with the information. Further, this document
|
||||
provides specific examples of what exception handling information is used for
|
||||
in C/C++.</p>
|
||||
in C and C++.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
@ -96,8 +92,8 @@
|
||||
Exception Handling</a>. A description of the exception frame format can be
|
||||
found at
|
||||
<a href="http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html">Exception
|
||||
Frames</a>, with details of the DWARF 3 specification at
|
||||
<a href="http://www.eagercon.com/dwarf/dwarf3std.htm">DWARF 3 Standard</a>.
|
||||
Frames</a>, with details of the DWARF 4 specification at
|
||||
<a href="http://dwarfstd.org/Dwarf4Std.php">DWARF 4 Standard</a>.
|
||||
A description for the C++ exception table formats can be found at
|
||||
<a href="http://www.codesourcery.com/cxx-abi/exceptions.pdf">Exception Handling
|
||||
Tables</a>.</p>
|
||||
@ -116,10 +112,10 @@
|
||||
<a href="#llvm_eh_sjlj_longjmp"><tt>llvm.eh.sjlj.longjmp</tt></a> to
|
||||
handle control flow for exception handling.</p>
|
||||
|
||||
<p>For each function which does exception processing, be it try/catch blocks
|
||||
or cleanups, that function registers itself on a global frame list. When
|
||||
exceptions are being unwound, the runtime uses this list to identify which
|
||||
functions need processing.<p>
|
||||
<p>For each function which does exception processing — be
|
||||
it <tt>try</tt>/<tt>catch</tt> blocks or cleanups — that function
|
||||
registers itself on a global frame list. When exceptions are unwinding, the
|
||||
runtime uses this list to identify which functions need processing.<p>
|
||||
|
||||
<p>Landing pad selection is encoded in the call site entry of the function
|
||||
context. The runtime returns to the function via
|
||||
@ -134,6 +130,7 @@
|
||||
exceptions are thrown. As exceptions are, by their nature, intended for
|
||||
uncommon code paths, DWARF exception handling is generally preferred to
|
||||
SJLJ.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
@ -148,19 +145,19 @@
|
||||
|
||||
<p>The runtime first attempts to find an <i>exception frame</i> corresponding to
|
||||
the function where the exception was thrown. If the programming language
|
||||
(e.g. C++) supports exception handling, the exception frame contains a
|
||||
supports exception handling (e.g. C++), the exception frame contains a
|
||||
reference to an exception table describing how to process the exception. If
|
||||
the language (e.g. C) does not support exception handling, or if the
|
||||
the language does not support exception handling (e.g. C), or if the
|
||||
exception needs to be forwarded to a prior activation, the exception frame
|
||||
contains information about how to unwind the current activation and restore
|
||||
the state of the prior activation. This process is repeated until the
|
||||
exception is handled. If the exception is not handled and no activations
|
||||
exception is handled. If the exception is not handled and no activations
|
||||
remain, then the application is terminated with an appropriate error
|
||||
message.</p>
|
||||
|
||||
<p>Because different programming languages have different behaviors when
|
||||
handling exceptions, the exception handling ABI provides a mechanism for
|
||||
supplying <i>personalities.</i> An exception handling personality is defined
|
||||
supplying <i>personalities</i>. An exception handling personality is defined
|
||||
by way of a <i>personality function</i> (e.g. <tt>__gxx_personality_v0</tt>
|
||||
in C++), which receives the context of the exception, an <i>exception
|
||||
structure</i> containing the exception object type and value, and a reference
|
||||
@ -168,19 +165,20 @@
|
||||
for the current compile unit is specified in a <i>common exception
|
||||
frame</i>.</p>
|
||||
|
||||
<p>The organization of an exception table is language dependent. For C++, an
|
||||
<p>The organization of an exception table is language dependent. For C++, an
|
||||
exception table is organized as a series of code ranges defining what to do
|
||||
if an exception occurs in that range. Typically, the information associated
|
||||
if an exception occurs in that range. Typically, the information associated
|
||||
with a range defines which types of exception objects (using C++ <i>type
|
||||
info</i>) that are handled in that range, and an associated action that
|
||||
should take place. Actions typically pass control to a <i>landing
|
||||
should take place. Actions typically pass control to a <i>landing
|
||||
pad</i>.</p>
|
||||
|
||||
<p>A landing pad corresponds to the code found in the <i>catch</i> portion of
|
||||
a <i>try</i>/<i>catch</i> sequence. When execution resumes at a landing
|
||||
pad, it receives the exception structure and a selector corresponding to
|
||||
the <i>type</i> of exception thrown. The selector is then used to determine
|
||||
which <i>catch</i> should actually process the exception.</p>
|
||||
<p>A landing pad corresponds roughly to the code found in the <tt>catch</tt>
|
||||
portion of a <tt>try</tt>/<tt>catch</tt> sequence. When execution resumes at
|
||||
a landing pad, it receives an <i>exception structure</i> and a
|
||||
<i>selector value</i> corresponding to the <i>type</i> of exception
|
||||
thrown. The selector is then used to determine which <i>catch</i> should
|
||||
actually process the exception.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -193,11 +191,8 @@
|
||||
|
||||
<div>
|
||||
|
||||
<p>At the time of this writing, only C++ exception handling support is available
|
||||
in LLVM. So the remainder of this document will be somewhat C++-centric.</p>
|
||||
|
||||
<p>From the C++ developers perspective, exceptions are defined in terms of the
|
||||
<tt>throw</tt> and <tt>try</tt>/<tt>catch</tt> statements. In this section
|
||||
<p>From a C++ developer's perspective, exceptions are defined in terms of the
|
||||
<tt>throw</tt> and <tt>try</tt>/<tt>catch</tt> statements. In this section
|
||||
we will describe the implementation of LLVM exception handling in terms of
|
||||
C++ examples.</p>
|
||||
|
||||
@ -209,17 +204,22 @@
|
||||
<div>
|
||||
|
||||
<p>Languages that support exception handling typically provide a <tt>throw</tt>
|
||||
operation to initiate the exception process. Internally, a throw operation
|
||||
breaks down into two steps. First, a request is made to allocate exception
|
||||
space for an exception structure. This structure needs to survive beyond the
|
||||
current activation. This structure will contain the type and value of the
|
||||
object being thrown. Second, a call is made to the runtime to raise the
|
||||
exception, passing the exception structure as an argument.</p>
|
||||
operation to initiate the exception process. Internally, a <tt>throw</tt>
|
||||
operation breaks down into two steps.</p>
|
||||
|
||||
<p>In C++, the allocation of the exception structure is done by
|
||||
the <tt>__cxa_allocate_exception</tt> runtime function. The exception
|
||||
raising is handled by <tt>__cxa_throw</tt>. The type of the exception is
|
||||
represented using a C++ RTTI structure.</p>
|
||||
<ol>
|
||||
<li>A request is made to allocate exception space for an exception structure.
|
||||
This structure needs to survive beyond the current activation. This
|
||||
structure will contain the type and value of the object being thrown.</li>
|
||||
|
||||
<li>A call is made to the runtime to raise the exception, passing the
|
||||
exception structure as an argument.</li>
|
||||
</ol>
|
||||
|
||||
<p>In C++, the allocation of the exception structure is done by the
|
||||
<tt>__cxa_allocate_exception</tt> runtime function. The exception raising is
|
||||
handled by <tt>__cxa_throw</tt>. The type of the exception is represented
|
||||
using a C++ RTTI structure.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -231,81 +231,68 @@
|
||||
<div>
|
||||
|
||||
<p>A call within the scope of a <i>try</i> statement can potentially raise an
|
||||
exception. In those circumstances, the LLVM C++ front-end replaces the call
|
||||
with an <tt>invoke</tt> instruction. Unlike a call, the <tt>invoke</tt> has
|
||||
two potential continuation points: where to continue when the call succeeds
|
||||
as per normal; and where to continue if the call raises an exception, either
|
||||
by a throw or the unwinding of a throw.</p>
|
||||
exception. In those circumstances, the LLVM C++ front-end replaces the call
|
||||
with an <tt>invoke</tt> instruction. Unlike a call, the <tt>invoke</tt> has
|
||||
two potential continuation points:</p>
|
||||
|
||||
<ol>
|
||||
<li>where to continue when the call succeeds as per normal, and</li>
|
||||
|
||||
<li>where to continue if the call raises an exception, either by a throw or
|
||||
the unwinding of a throw</li>
|
||||
</ol>
|
||||
|
||||
<p>The term used to define a the place where an <tt>invoke</tt> continues after
|
||||
an exception is called a <i>landing pad</i>. LLVM landing pads are
|
||||
an exception is called a <i>landing pad</i>. LLVM landing pads are
|
||||
conceptually alternative function entry points where an exception structure
|
||||
reference and a type info index are passed in as arguments. The landing pad
|
||||
reference and a type info index are passed in as arguments. The landing pad
|
||||
saves the exception structure reference and then proceeds to select the catch
|
||||
block that corresponds to the type info of the exception object.</p>
|
||||
|
||||
<p>Two LLVM intrinsic functions are used to convey information about the landing
|
||||
pad to the back end.</p>
|
||||
<p>The LLVM <a href="LangRef.html#i_landingpad"><tt>landingpad</tt>
|
||||
instruction</a> is used to convey information about the landing pad to the
|
||||
back end. For C++, the <tt>landingpad</tt> instruction returns a pointer and
|
||||
integer pair corresponding to the pointer to the <i>exception structure</i>
|
||||
and the <i>selector value</i> respectively.</p>
|
||||
|
||||
<ol>
|
||||
<li><a href="#llvm_eh_exception"><tt>llvm.eh.exception</tt></a> takes no
|
||||
arguments and returns a pointer to the exception structure. This only
|
||||
returns a sensible value if called after an <tt>invoke</tt> has branched
|
||||
to a landing pad. Due to code generation limitations, it must currently
|
||||
be called in the landing pad itself.</li>
|
||||
|
||||
<li><a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> takes a minimum
|
||||
of three arguments. The first argument is the reference to the exception
|
||||
structure. The second argument is a reference to the personality function
|
||||
to be used for this <tt>try</tt>/<tt>catch</tt> sequence. Each of the
|
||||
remaining arguments is either a reference to the type info for
|
||||
a <tt>catch</tt> statement, a <a href="#throw_filters">filter</a>
|
||||
expression, or the number zero (<tt>0</tt>) representing
|
||||
a <a href="#cleanups">cleanup</a>. The exception is tested against the
|
||||
arguments sequentially from first to last. The result of
|
||||
the <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> is a
|
||||
positive number if the exception matched a type info, a negative number if
|
||||
it matched a filter, and zero if it matched a cleanup. If nothing is
|
||||
matched, the behaviour of the program
|
||||
is <a href="#restrictions">undefined</a>. This only returns a sensible
|
||||
value if called after an <tt>invoke</tt> has branched to a landing pad.
|
||||
Due to codegen limitations, it must currently be called in the landing pad
|
||||
itself. If a type info matched, then the selector value is the index of
|
||||
the type info in the exception table, which can be obtained using the
|
||||
<a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a>
|
||||
intrinsic.</li>
|
||||
</ol>
|
||||
<p>The <tt>landingpad</tt> instruction takes a reference to the personality
|
||||
function to be used for this <tt>try</tt>/<tt>catch</tt> sequence. The
|
||||
remainder of the instruction is a list of <i>cleanup</i>, <i>catch</i>,
|
||||
and <i>filter</i> clauses. The exception is tested against the clauses
|
||||
sequentially from first to last. The selector value is a positive number if
|
||||
the exception matched a type info, a negative number if it matched a filter,
|
||||
and zero if it matched a cleanup. If nothing is matched, the behavior of
|
||||
the program is <a href="#restrictions">undefined</a>. If a type info matched,
|
||||
then the selector value is the index of the type info in the exception table,
|
||||
which can be obtained using the
|
||||
<a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a> intrinsic.</p>
|
||||
|
||||
<p>Once the landing pad has the type info selector, the code branches to the
|
||||
code for the first catch. The catch then checks the value of the type info
|
||||
code for the first catch. The catch then checks the value of the type info
|
||||
selector against the index of type info for that catch. Since the type info
|
||||
index is not known until all the type info have been gathered in the backend,
|
||||
the catch code will call the
|
||||
<a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a> intrinsic
|
||||
to determine the index for a given type info. If the catch fails to match
|
||||
the selector then control is passed on to the next catch. Note: Since the
|
||||
landing pad will not be used if there is no match in the list of type info on
|
||||
the call to <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>, then
|
||||
neither the last catch nor <i>catch all</i> need to perform the check
|
||||
against the selector.</p>
|
||||
index is not known until all the type infos have been gathered in the
|
||||
backend, the catch code must call the
|
||||
<a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a> intrinsic to
|
||||
determine the index for a given type info. If the catch fails to match the
|
||||
selector then control is passed on to the next catch.</p>
|
||||
|
||||
<p>Finally, the entry and exit of catch code is bracketed with calls
|
||||
to <tt>__cxa_begin_catch</tt> and <tt>__cxa_end_catch</tt>.</p>
|
||||
<p>Finally, the entry and exit of catch code is bracketed with calls to
|
||||
<tt>__cxa_begin_catch</tt> and <tt>__cxa_end_catch</tt>.</p>
|
||||
|
||||
<ul>
|
||||
<li><tt>__cxa_begin_catch</tt> takes a exception structure reference as an
|
||||
<li><tt>__cxa_begin_catch</tt> takes an exception structure reference as an
|
||||
argument and returns the value of the exception object.</li>
|
||||
|
||||
<li><tt>__cxa_end_catch</tt> takes no arguments. This function:<br><br>
|
||||
<ol>
|
||||
<li>Locates the most recently caught exception and decrements its handler
|
||||
count,</li>
|
||||
<li>Removes the exception from the "caught" stack if the handler count
|
||||
goes to zero, and</li>
|
||||
<li>Destroys the exception if the handler count goes to zero, and the
|
||||
<li>Removes the exception from the <i>caught</i> stack if the handler
|
||||
count goes to zero, and</li>
|
||||
<li>Destroys the exception if the handler count goes to zero and the
|
||||
exception was not re-thrown by throw.</li>
|
||||
</ol>
|
||||
<p>Note: a rethrow from within the catch may replace this call with
|
||||
<p><b>Note:</b> a rethrow from within the catch may replace this call with
|
||||
a <tt>__cxa_rethrow</tt>.</p></li>
|
||||
</ul>
|
||||
|
||||
@ -318,28 +305,26 @@
|
||||
|
||||
<div>
|
||||
|
||||
<p>A cleanup is extra code which needs to be run as part of unwinding
|
||||
a scope. C++ destructors are a prominent example, but other
|
||||
languages and language extensions provide a variety of different
|
||||
kinds of cleanup. In general, a landing pad may need to run
|
||||
arbitrary amounts of cleanup code before actually entering a catch
|
||||
block. To indicate the presence of cleanups, a landing pad's call
|
||||
to <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> should
|
||||
end with the argument <tt>i32 0</tt>; otherwise, the unwinder will
|
||||
not stop at the landing pad if there are no catches or filters that
|
||||
require it to.</p>
|
||||
<p>A cleanup is extra code which needs to be run as part of unwinding a scope.
|
||||
C++ destructors are a typical example, but other languages and language
|
||||
extensions provide a variety of different kinds of cleanups. In general, a
|
||||
landing pad may need to run arbitrary amounts of cleanup code before actually
|
||||
entering a catch block. To indicate the presence of cleanups, a
|
||||
<a href="LangRef.html#i_landingpad"><tt>landingpad</tt> instruction</a>
|
||||
should have a <i>cleanup</i> clause. Otherwise, the unwinder will not stop at
|
||||
the landing pad if there are no catches or filters that require it to.</p>
|
||||
|
||||
<p>Do not allow a new exception to propagate out of the execution of a
|
||||
cleanup. This can corrupt the internal state of the unwinder.
|
||||
Different languages describe different high-level semantics for
|
||||
these situations: for example, C++ requires that the process be
|
||||
terminated, whereas Ada cancels both exceptions and throws a third.</p>
|
||||
<p><b>Note:</b> Do not allow a new exception to propagate out of the execution
|
||||
of a cleanup. This can corrupt the internal state of the unwinder.
|
||||
Different languages describe different high-level semantics for these
|
||||
situations: for example, C++ requires that the process be terminated, whereas
|
||||
Ada cancels both exceptions and throws a third.</p>
|
||||
|
||||
<p>When all cleanups have completed, if the exception is not handled
|
||||
by the current function, resume unwinding by calling the
|
||||
<a href="#llvm_eh_resume"><tt>llvm.eh.resume</tt></a> intrinsic,
|
||||
passing in the results of <tt>llvm.eh.exception</tt> and
|
||||
<tt>llvm.eh.selector</tt> for the original landing pad.</p>
|
||||
<p>When all cleanups are finished, if the exception is not handled by the
|
||||
current function, resume unwinding by calling the
|
||||
<a href="LangRef.html#i_resume"><tt>resume</tt> instruction</a>, passing in
|
||||
the result of the <tt>landingpad</tt> instruction for the original landing
|
||||
pad.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -350,23 +335,21 @@
|
||||
|
||||
<div>
|
||||
|
||||
<p>C++ allows the specification of which exception types can be thrown from a
|
||||
function. To represent this a top level landing pad may exist to filter out
|
||||
invalid types. To express this in LLVM code the landing pad will
|
||||
call <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>. The
|
||||
arguments are a reference to the exception structure, a reference to the
|
||||
personality function, the length of the filter expression (the number of type
|
||||
infos plus one), followed by the type infos themselves.
|
||||
<a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> will return a
|
||||
negative value if the exception does not match any of the type infos. If no
|
||||
match is found then a call to <tt>__cxa_call_unexpected</tt> should be made,
|
||||
otherwise <tt>_Unwind_Resume</tt>. Each of these functions requires a
|
||||
reference to the exception structure. Note that the most general form of an
|
||||
<a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> call can contain
|
||||
any number of type infos, filter expressions and cleanups (though having more
|
||||
than one cleanup is pointless). The LLVM C++ front-end can generate such
|
||||
<a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> calls due to
|
||||
inlining creating nested exception handling scopes.</p>
|
||||
<p>C++ allows the specification of which exception types may be thrown from a
|
||||
function. To represent this, a top level landing pad may exist to filter out
|
||||
invalid types. To express this in LLVM code the
|
||||
<a href="LangRef.html#i_landingpad"><tt>landingpad</tt> instruction</a> will
|
||||
have a filter clause. The clause consists of an array of type infos.
|
||||
<tt>landingpad</tt> will return a negative value if the exception does not
|
||||
match any of the type infos. If no match is found then a call
|
||||
to <tt>__cxa_call_unexpected</tt> should be made, otherwise
|
||||
<tt>_Unwind_Resume</tt>. Each of these functions requires a reference to the
|
||||
exception structure. Note that the most general form of a
|
||||
<a href="LangRef.html#i_landingpad"><tt>landingpad</tt> instruction</a> can
|
||||
have any number of catch, cleanup, and filter clauses (though having more
|
||||
than one cleanup is pointless). The LLVM C++ front-end can generate such
|
||||
<a href="LangRef.html#i_landingpad"><tt>landingpad</tt> instructions</a> due
|
||||
to inlining creating nested exception handling scopes.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -377,29 +360,23 @@
|
||||
|
||||
<div>
|
||||
|
||||
<p>The unwinder delegates the decision of whether to stop in a call
|
||||
frame to that call frame's language-specific personality function.
|
||||
Not all personalities functions guarantee that they will stop to
|
||||
perform cleanups: for example, the GNU C++ personality doesn't do
|
||||
so unless the exception is actually caught somewhere further up the
|
||||
stack. When using this personality to implement EH for a language
|
||||
that guarantees that cleanups will always be run, be sure to
|
||||
indicate a catch-all in the
|
||||
<a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> call
|
||||
rather than just cleanups.</p>
|
||||
<p>The unwinder delegates the decision of whether to stop in a call frame to
|
||||
that call frame's language-specific personality function. Not all unwinders
|
||||
guarantee that they will stop to perform cleanups. For example, the GNU C++
|
||||
unwinder doesn't do so unless the exception is actually caught somewhere
|
||||
further up the stack.</p>
|
||||
|
||||
<p>In order for inlining to behave correctly, landing pads must be
|
||||
prepared to handle selector results that they did not originally
|
||||
advertise. Suppose that a function catches exceptions of
|
||||
type <tt>A</tt>, and it's inlined into a function that catches
|
||||
exceptions of type <tt>B</tt>. The inliner will update the
|
||||
selector for the inlined landing pad to include the fact
|
||||
that <tt>B</tt> is caught. If that landing pad assumes that it
|
||||
will only be entered to catch an <tt>A</tt>, it's in for a rude
|
||||
surprise. Consequently, landing pads must test for the selector
|
||||
results they understand and then resume exception propagation
|
||||
with the <a href="#llvm_eh_resume"><tt>llvm.eh.resume</tt></a>
|
||||
intrinsic if none of the conditions match.</p>
|
||||
<p>In order for inlining to behave correctly, landing pads must be prepared to
|
||||
handle selector results that they did not originally advertise. Suppose that
|
||||
a function catches exceptions of type <tt>A</tt>, and it's inlined into a
|
||||
function that catches exceptions of type <tt>B</tt>. The inliner will update
|
||||
the <tt>landingpad</tt> instruction for the inlined landing pad to include
|
||||
the fact that <tt>B</tt> is also caught. If that landing pad assumes that it
|
||||
will only be entered to catch an <tt>A</tt>, it's in for a rude awakening.
|
||||
Consequently, landing pads must test for the selector results they understand
|
||||
and then resume exception propagation with the
|
||||
<a href="LangRef.html#i_resume"><tt>resume</tt> instruction</a> if none of
|
||||
the conditions match.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -412,67 +389,13 @@
|
||||
|
||||
<div>
|
||||
|
||||
<p>LLVM uses several intrinsic functions (name prefixed with "llvm.eh") to
|
||||
<p>In addition to the
|
||||
<a href="LangRef.html#i_landingpad"><tt>landingpad</tt></a> and
|
||||
<a href="LangRef.html#i_resume"><tt>resume</tt></a> instructions, LLVM uses
|
||||
several intrinsic functions (name prefixed with <i><tt>llvm.eh</tt></i>) to
|
||||
provide exception handling information at various points in generated
|
||||
code.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h4>
|
||||
<a name="llvm_eh_exception">llvm.eh.exception</a>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
|
||||
<pre>
|
||||
i8* %<a href="#llvm_eh_exception">llvm.eh.exception</a>()
|
||||
</pre>
|
||||
|
||||
<p>This intrinsic returns a pointer to the exception structure.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h4>
|
||||
<a name="llvm_eh_selector">llvm.eh.selector</a>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
|
||||
<pre>
|
||||
i32 %<a href="#llvm_eh_selector">llvm.eh.selector</a>(i8*, i8*, ...)
|
||||
</pre>
|
||||
|
||||
<p>This intrinsic is used to compare the exception with the given type infos,
|
||||
filters and cleanups.</p>
|
||||
|
||||
<p><a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> takes a
|
||||
minimum of three arguments. The first argument is the reference to
|
||||
the exception structure. The second argument is a reference to the
|
||||
personality function to be used for this try catch sequence. Each
|
||||
of the remaining arguments is either a reference to the type info
|
||||
for a catch statement, a <a href="#throw_filters">filter</a>
|
||||
expression, or the number zero representing
|
||||
a <a href="#cleanups">cleanup</a>. The exception is tested against
|
||||
the arguments sequentially from first to last. The result of
|
||||
the <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a> is a
|
||||
positive number if the exception matched a type info, a negative
|
||||
number if it matched a filter, and zero if it matched a cleanup.
|
||||
If nothing is matched, or if only a cleanup is matched, different
|
||||
personality functions may or may not cause control to stop at the
|
||||
landing pad; see <a href="#restrictions">the restrictions</a> for
|
||||
more information. If a type info matched then the selector value
|
||||
is the index of the type info in the exception table, which can be
|
||||
obtained using the
|
||||
<a href="#llvm_eh_typeid_for"><tt>llvm.eh.typeid.for</tt></a> intrinsic.</p>
|
||||
|
||||
<p>If a landing pad containing a call to <tt>llvm.eh.selector</tt> is
|
||||
inlined into an <tt>invoke</tt> instruction, the selector arguments
|
||||
for the outer landing pad are appended to those of the inlined
|
||||
landing pad. Consequently, landing pads must be written to ignore
|
||||
selector values that they did not originally advertise.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h4>
|
||||
<a name="llvm_eh_typeid_for">llvm.eh.typeid.for</a>
|
||||
@ -481,40 +404,13 @@
|
||||
<div>
|
||||
|
||||
<pre>
|
||||
i32 %<a href="#llvm_eh_typeid_for">llvm.eh.typeid.for</a>(i8*)
|
||||
i32 @llvm.eh.typeid.for(i8* %type_info)
|
||||
</pre>
|
||||
|
||||
<p>This intrinsic returns the type info index in the exception table of the
|
||||
current function. This value can be used to compare against the result
|
||||
of <a href="#llvm_eh_selector"><tt>llvm.eh.selector</tt></a>. The single
|
||||
argument is a reference to a type info.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h4>
|
||||
<a name="llvm_eh_resume">llvm.eh.resume</a>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
|
||||
<pre>
|
||||
void %<a href="#llvm_eh_resume">llvm.eh.resume</a>(i8*, i32) noreturn
|
||||
</pre>
|
||||
|
||||
<p>This intrinsic is used to resume propagation of an exception after
|
||||
landing at a landing pad. The first argument should be the result
|
||||
of <a href="#llvm_eh_exception">llvm.eh.exception</a> for that
|
||||
landing pad, and the second argument should be the result of
|
||||
<a href="#llvm_eh_selector">llvm.eh.selector</a>. When a call to
|
||||
this intrinsic is inlined into an invoke, the call is transformed
|
||||
into a branch to the invoke's unwind destination, using its
|
||||
arguments in place of the calls
|
||||
to <a href="#llvm_eh_exception">llvm.eh.exception</a> and
|
||||
<a href="#llvm_eh_selector">llvm.eh.selector</a> there.</p>
|
||||
|
||||
<p>This intrinsic is not implicitly <tt>nounwind</tt>; calls to it
|
||||
will always throw. It may not be invoked.</p>
|
||||
of <a href="LangRef.html#i_landingpad"><tt>landingpad</tt> instruction</a>.
|
||||
The single argument is a reference to a type info.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -526,16 +422,16 @@
|
||||
<div>
|
||||
|
||||
<pre>
|
||||
i32 %<a href="#llvm_eh_sjlj_setjmp">llvm.eh.sjlj.setjmp</a>(i8*)
|
||||
i32 @llvm.eh.sjlj.setjmp(i8* %setjmp_buf)
|
||||
</pre>
|
||||
|
||||
<p>The SJLJ exception handling uses this intrinsic to force register saving for
|
||||
the current function and to store the address of the following instruction
|
||||
for use as a destination address by <a href="#llvm_eh_sjlj_longjmp">
|
||||
<tt>llvm.eh.sjlj.longjmp</tt></a>. The buffer format and the overall
|
||||
functioning of this intrinsic is compatible with the GCC
|
||||
<tt>__builtin_setjmp</tt> implementation, allowing code built with the
|
||||
two compilers to interoperate.</p>
|
||||
<p>For SJLJ based exception handling, this intrinsic forces register saving for
|
||||
the current function and stores the address of the following instruction for
|
||||
use as a destination address
|
||||
by <a href="#llvm_eh_sjlj_longjmp"><tt>llvm.eh.sjlj.longjmp</tt></a>. The
|
||||
buffer format and the overall functioning of this intrinsic is compatible
|
||||
with the GCC <tt>__builtin_setjmp</tt> implementation allowing code built
|
||||
with the clang and GCC to interoperate.</p>
|
||||
|
||||
<p>The single parameter is a pointer to a five word buffer in which the calling
|
||||
context is saved. The front end places the frame pointer in the first word,
|
||||
@ -555,16 +451,15 @@
|
||||
<div>
|
||||
|
||||
<pre>
|
||||
void %<a href="#llvm_eh_sjlj_longjmp">llvm.eh.sjlj.setjmp</a>(i8*)
|
||||
void @llvm.eh.sjlj.longjmp(i8* %setjmp_buf)
|
||||
</pre>
|
||||
|
||||
<p>The <a href="#llvm_eh_sjlj_longjmp"><tt>llvm.eh.sjlj.longjmp</tt></a>
|
||||
intrinsic is used to implement <tt>__builtin_longjmp()</tt> for SJLJ
|
||||
style exception handling. The single parameter is a pointer to a
|
||||
buffer populated by <a href="#llvm_eh_sjlj_setjmp">
|
||||
<tt>llvm.eh.sjlj.setjmp</tt></a>. The frame pointer and stack pointer
|
||||
are restored from the buffer, then control is transferred to the
|
||||
destination address.</p>
|
||||
<p>For SJLJ based exception handling, the <tt>llvm.eh.sjlj.longjmp</tt>
|
||||
intrinsic is used to implement <tt>__builtin_longjmp()</tt>. The single
|
||||
parameter is a pointer to a buffer populated
|
||||
by <a href="#llvm_eh_sjlj_setjmp"><tt>llvm.eh.sjlj.setjmp</tt></a>. The frame
|
||||
pointer and stack pointer are restored from the buffer, then control is
|
||||
transferred to the destination address.</p>
|
||||
|
||||
</div>
|
||||
<!-- ======================================================================= -->
|
||||
@ -575,14 +470,13 @@
|
||||
<div>
|
||||
|
||||
<pre>
|
||||
i8* %<a href="#llvm_eh_sjlj_lsda">llvm.eh.sjlj.lsda</a>()
|
||||
i8* @llvm.eh.sjlj.lsda()
|
||||
</pre>
|
||||
|
||||
<p>Used for SJLJ based exception handling, the <a href="#llvm_eh_sjlj_lsda">
|
||||
<tt>llvm.eh.sjlj.lsda</tt></a> intrinsic returns the address of the Language
|
||||
Specific Data Area (LSDA) for the current function. The SJLJ front-end code
|
||||
stores this address in the exception handling function context for use by the
|
||||
runtime.</p>
|
||||
<p>For SJLJ based exception handling, the <tt>llvm.eh.sjlj.lsda</tt> intrinsic
|
||||
returns the address of the Language Specific Data Area (LSDA) for the current
|
||||
function. The SJLJ front-end code stores this address in the exception
|
||||
handling function context for use by the runtime.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -594,13 +488,13 @@
|
||||
<div>
|
||||
|
||||
<pre>
|
||||
void %<a href="#llvm_eh_sjlj_callsite">llvm.eh.sjlj.callsite</a>(i32)
|
||||
void @llvm.eh.sjlj.callsite(i32 %call_site_num)
|
||||
</pre>
|
||||
|
||||
<p>For SJLJ based exception handling, the <a href="#llvm_eh_sjlj_callsite">
|
||||
<tt>llvm.eh.sjlj.callsite</tt></a> intrinsic identifies the callsite value
|
||||
associated with the following invoke instruction. This is used to ensure
|
||||
that landing pad entries in the LSDA are generated in the matching order.</p>
|
||||
<p>For SJLJ based exception handling, the <tt>llvm.eh.sjlj.callsite</tt>
|
||||
intrinsic identifies the callsite value associated with the
|
||||
following <tt>invoke</tt> instruction. This is used to ensure that landing
|
||||
pad entries in the LSDA are generated in matching order.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -612,12 +506,12 @@
|
||||
<div>
|
||||
|
||||
<pre>
|
||||
void %<a href="#llvm_eh_sjlj_dispatchsetup">llvm.eh.sjlj.dispatchsetup</a>(i32)
|
||||
void @llvm.eh.sjlj.dispatchsetup(i32 %dispatch_value)
|
||||
</pre>
|
||||
|
||||
<p>For SJLJ based exception handling, the <a href="#llvm_eh_sjlj_dispatchsetup">
|
||||
<tt>llvm.eh.sjlj.dispatchsetup</tt></a> intrinsic is used by targets to do
|
||||
any unwind-edge setup they need. By default, no action is taken. </p>
|
||||
<p>For SJLJ based exception handling, the <tt>llvm.eh.sjlj.dispatchsetup</tt>
|
||||
intrinsic is used by targets to do any unwind edge setup they need. By
|
||||
default, no action is taken.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -631,7 +525,7 @@
|
||||
<div>
|
||||
|
||||
<p>There are two tables that are used by the exception handling runtime to
|
||||
determine which actions should take place when an exception is thrown.</p>
|
||||
determine which actions should be taken when an exception is thrown.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
@ -641,13 +535,13 @@
|
||||
<div>
|
||||
|
||||
<p>An exception handling frame <tt>eh_frame</tt> is very similar to the unwind
|
||||
frame used by dwarf debug info. The frame contains all the information
|
||||
frame used by DWARF debug info. The frame contains all the information
|
||||
necessary to tear down the current frame and restore the state of the prior
|
||||
frame. There is an exception handling frame for each function in a compile
|
||||
frame. There is an exception handling frame for each function in a compile
|
||||
unit, plus a common exception handling frame that defines information common
|
||||
to all functions in the unit.</p>
|
||||
|
||||
<p>Todo - Table details here.</p>
|
||||
<!-- Todo - Table details here. -->
|
||||
|
||||
</div>
|
||||
|
||||
@ -659,31 +553,17 @@
|
||||
<div>
|
||||
|
||||
<p>An exception table contains information about what actions to take when an
|
||||
exception is thrown in a particular part of a function's code. There is one
|
||||
exception table per function except leaf routines and functions that have
|
||||
only calls to non-throwing functions will not need an exception table.</p>
|
||||
exception is thrown in a particular part of a function's code. There is one
|
||||
exception table per function, except leaf functions and functions that have
|
||||
calls only to non-throwing functions. They do not need an exception
|
||||
table.</p>
|
||||
|
||||
<p>Todo - Table details here.</p>
|
||||
<!-- Todo - Table details here. -->
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h2>
|
||||
<a name="todo">ToDo</a>
|
||||
</h2>
|
||||
|
||||
<div>
|
||||
|
||||
<ol>
|
||||
|
||||
<li>Testing/Testing/Testing.</li>
|
||||
|
||||
</ol>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
|
||||
<hr>
|
||||
@ -695,7 +575,7 @@
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-05-28 09:45:59 +0200 (Sat, 28 May 2011) $
|
||||
Last modified: $Date: 2011-09-27 22:16:57 +0200 (Tue, 27 Sep 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -72,9 +72,6 @@
|
||||
<li>After Subversion update, rebuilding gives the error "No rule to make
|
||||
target".</li>
|
||||
|
||||
<li><a href="#llvmc">The <tt>llvmc</tt> program gives me errors/doesn't
|
||||
work.</a></li>
|
||||
|
||||
<li><a href="#srcdir-objdir">When I compile LLVM-GCC with srcdir == objdir,
|
||||
it fails. Why?</a></li>
|
||||
</ol></li>
|
||||
@ -419,16 +416,6 @@ Stop.
|
||||
rebuilding.</p>
|
||||
</div>
|
||||
|
||||
<div class="question">
|
||||
<p><a name="llvmc">The <tt>llvmc</tt> program gives me errors/doesn't
|
||||
work.</a></p>
|
||||
</div>
|
||||
|
||||
<div class="answer">
|
||||
<p><tt>llvmc</tt> is experimental and isn't really supported. We suggest
|
||||
using <tt>llvm-gcc</tt> instead.</p>
|
||||
</div>
|
||||
|
||||
<div class="question">
|
||||
<p><a name="srcdir-objdir">When I compile LLVM-GCC with srcdir == objdir, it
|
||||
fails. Why?</a></p>
|
||||
@ -540,10 +527,7 @@ Stop.
|
||||
<p>Currently, there isn't much. LLVM supports an intermediate representation
|
||||
which is useful for code representation but will not support the high level
|
||||
(abstract syntax tree) representation needed by most compilers. There are no
|
||||
facilities for lexical nor semantic analysis. There is, however, a <i>mostly
|
||||
implemented</i> configuration-driven
|
||||
<a href="CompilerDriver.html">compiler driver</a> which simplifies the task
|
||||
of running optimizations, linking, and executable generation.</p>
|
||||
facilities for lexical nor semantic analysis.</p>
|
||||
</div>
|
||||
|
||||
<div class="question">
|
||||
@ -933,7 +917,7 @@ F.i:
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
|
||||
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-19 01:59:50 +0200 (Tue, 19 Apr 2011) $
|
||||
Last modified: $Date: 2011-09-20 02:42:28 +0200 (Tue, 20 Sep 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -290,10 +290,8 @@ doing so is very simple. (This code is heavily commented to help you
|
||||
understand the data structure, but there are only 20 lines of meaningful
|
||||
code.)</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="doc_code"><pre
|
||||
>/// @brief The map for a single function's stack frame. One of these is
|
||||
<pre class="doc_code">
|
||||
/// @brief The map for a single function's stack frame. One of these is
|
||||
/// compiled as constant data into the executable for each function.
|
||||
///
|
||||
/// Storage of metadata values is elided if the %metadata parameter to
|
||||
@ -338,7 +336,9 @@ void visitGCRoots(void (*Visitor)(void **Root, const void *Meta)) {
|
||||
for (unsigned e = R->Map->NumRoots; i != e; ++i)
|
||||
Visitor(&R->Roots[i], NULL);
|
||||
}
|
||||
}</pre></div>
|
||||
}</pre>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
@ -395,12 +395,12 @@ program.</p>
|
||||
<a name="gcattr">Specifying GC code generation: <tt>gc "..."</tt></a>
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
|
||||
<div class="doc_code"><tt>
|
||||
define <i>ty</i> @<i>name</i>(...) <span style="text-decoration: underline">gc "<i>name</i>"</span> { ...
|
||||
</tt></div>
|
||||
|
||||
<div>
|
||||
|
||||
<p>The <tt>gc</tt> function attribute is used to specify the desired GC style
|
||||
to the compiler. Its programmatic equivalent is the <tt>setGC</tt> method of
|
||||
<tt>Function</tt>.</p>
|
||||
@ -420,12 +420,12 @@ programs that use different garbage collection algorithms (or none at all).</p>
|
||||
<a name="gcroot">Identifying GC roots on the stack: <tt>llvm.gcroot</tt></a>
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
|
||||
<div class="doc_code"><tt>
|
||||
void @llvm.gcroot(i8** %ptrloc, i8* %metadata)
|
||||
</tt></div>
|
||||
|
||||
<div>
|
||||
|
||||
<p>The <tt>llvm.gcroot</tt> intrinsic is used to inform LLVM that a stack
|
||||
variable references an object on the heap and is to be tracked for garbage
|
||||
collection. The exact impact on generated code is specified by a <a
|
||||
@ -453,7 +453,7 @@ the stack frame.</p>
|
||||
|
||||
<p>Consider the following fragment of Java code:</p>
|
||||
|
||||
<pre>
|
||||
<pre class="doc_code">
|
||||
{
|
||||
Object X; // A null-initialized reference to an object
|
||||
...
|
||||
@ -463,7 +463,7 @@ the stack frame.</p>
|
||||
<p>This block (which may be located in the middle of a function or in a loop
|
||||
nest), could be compiled to this LLVM code:</p>
|
||||
|
||||
<pre>
|
||||
<pre class="doc_code">
|
||||
Entry:
|
||||
;; In the entry block for the function, allocate the
|
||||
;; stack space for X, which is an LLVM pointer.
|
||||
@ -537,12 +537,12 @@ are used.</p>
|
||||
<a name="gcwrite">Write barrier: <tt>llvm.gcwrite</tt></a>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
|
||||
<div class="doc_code"><tt>
|
||||
void @llvm.gcwrite(i8* %value, i8* %object, i8** %derived)
|
||||
</tt></div>
|
||||
|
||||
<div>
|
||||
|
||||
<p>For write barriers, LLVM provides the <tt>llvm.gcwrite</tt> intrinsic
|
||||
function. It has exactly the same semantics as a non-volatile <tt>store</tt> to
|
||||
the derived pointer (the third argument). The exact code generated is specified
|
||||
@ -559,12 +559,12 @@ implement reference counting.</p>
|
||||
<a name="gcread">Read barrier: <tt>llvm.gcread</tt></a>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
|
||||
<div class="doc_code"><tt>
|
||||
i8* @llvm.gcread(i8* %object, i8** %derived)<br>
|
||||
</tt></div>
|
||||
|
||||
<div>
|
||||
|
||||
<p>For read barriers, LLVM provides the <tt>llvm.gcread</tt> intrinsic function.
|
||||
It has exactly the same semantics as a non-volatile <tt>load</tt> from the
|
||||
derived pointer (the second argument). The exact code generated is specified by
|
||||
@ -1379,7 +1379,7 @@ Fergus Henderson. International Symposium on Memory Management 2002.</p>
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-08-12 08:17:17 +0200 (Fri, 12 Aug 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -441,13 +441,13 @@ href="GCCFEBuildInstrs.html">try to compile it</a> on your platform.</p>
|
||||
|
||||
<tr>
|
||||
<td><a href="http://www.gnu.org/software/autoconf/">GNU Autoconf</a></td>
|
||||
<td>2.60</td>
|
||||
<td>2.61</td>
|
||||
<td>Configuration script builder<sup><a href="#sf4">4</a></sup></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><a href="http://www.gnu.org/software/automake/">GNU Automake</a></td>
|
||||
<td>1.9.6</td>
|
||||
<td>1.10</td>
|
||||
<td>aclocal macro generator<sup><a href="#sf4">4</a></sup></td>
|
||||
</tr>
|
||||
|
||||
@ -471,8 +471,8 @@ href="GCCFEBuildInstrs.html">try to compile it</a> on your platform.</p>
|
||||
<li><a name="sf3">Only needed if you want to run the automated test
|
||||
suite in the <tt>llvm/test</tt> directory.</a></li>
|
||||
<li><a name="sf4">If you want to make changes to the configure scripts,
|
||||
you will need GNU autoconf (2.60), and consequently, GNU M4 (version 1.4
|
||||
or higher). You will also need automake (1.9.6). We only use aclocal
|
||||
you will need GNU autoconf (2.61), and consequently, GNU M4 (version 1.4
|
||||
or higher). You will also need automake (1.10). We only use aclocal
|
||||
from that package.</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
@ -747,6 +747,7 @@ revision), you can checkout it from the '<tt>tags</tt>' directory (instead of
|
||||
subdirectories of the '<tt>tags</tt>' directory:</p>
|
||||
|
||||
<ul>
|
||||
<li>Release 3.0: <b>RELEASE_30/final</b></li>
|
||||
<li>Release 2.9: <b>RELEASE_29/final</b></li>
|
||||
<li>Release 2.8: <b>RELEASE_28</b></li>
|
||||
<li>Release 2.7: <b>RELEASE_27</b></li>
|
||||
@ -802,10 +803,150 @@ instructions</a> to successfully get and build the LLVM GCC front-end.</p>
|
||||
now mirrors reflect only <tt>trunk</tt> for each project. You can do the
|
||||
read-only GIT clone of LLVM via:</p>
|
||||
|
||||
<pre>
|
||||
% git clone http://llvm.org/git/llvm.git
|
||||
<pre class="doc_code">
|
||||
git clone http://llvm.org/git/llvm.git
|
||||
</pre>
|
||||
|
||||
<p>If you want to check out clang too, run:</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
git clone http://llvm.org/git/llvm.git
|
||||
cd llvm/tools
|
||||
git clone http://llvm.org/git/clang.git
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Since the upstream repository is in Subversion, you should use
|
||||
<tt>"git pull --rebase"</tt>
|
||||
instead of <tt>"git pull"</tt> to avoid generating a non-linear
|
||||
history in your clone.
|
||||
To configure <tt>"git pull"</tt> to pass <tt>--rebase</tt> by default
|
||||
on the master branch, run the following command:
|
||||
</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
git config branch.master.rebase true
|
||||
</pre>
|
||||
|
||||
<h4>Sending patches with Git</h4>
|
||||
<div>
|
||||
<p>
|
||||
Please read <a href="DeveloperPolicy.html#patches">Developer Policy</a>, too.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Assume <tt>master</tt> points the upstream and <tt>mybranch</tt> points your
|
||||
working branch, and <tt>mybranch</tt> is rebased onto <tt>master</tt>.
|
||||
At first you may check sanity of whitespaces:
|
||||
</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
git diff --check master..mybranch
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The easiest way to generate a patch is as below:
|
||||
</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
git diff master..mybranch > /path/to/mybranch.diff
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
It is a little different from svn-generated diff. git-diff-generated diff has
|
||||
prefixes like <tt>a/</tt> and <tt>b/</tt>. Don't worry, most developers might
|
||||
know it could be accepted with <tt>patch -p1 -N</tt>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
But you may generate patchset with git-format-patch. It generates
|
||||
by-each-commit patchset. To generate patch files to attach to your article:
|
||||
</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
git format-patch --no-attach master..mybranch -o /path/to/your/patchset
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
If you would like to send patches directly, you may use git-send-email or
|
||||
git-imap-send. Here is an example to generate the patchset in Gmail's [Drafts].
|
||||
</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
git format-patch --attach master..mybranch --stdout | git imap-send
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Then, your .git/config should have [imap] sections.
|
||||
</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
[imap]
|
||||
host = imaps://imap.gmail.com
|
||||
user = <em>your.gmail.account</em>@gmail.com
|
||||
pass = <em>himitsu!</em>
|
||||
port = 993
|
||||
sslverify = false
|
||||
; in English
|
||||
folder = "[Gmail]/Drafts"
|
||||
; example for Japanese, "Modified UTF-7" encoded.
|
||||
folder = "[Gmail]/&Tgtm+DBN-"
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
|
||||
<h4>For developers to work with git-svn</h4>
|
||||
<div>
|
||||
|
||||
<p>To set up clone from which you can submit code using
|
||||
<tt>git-svn</tt>, run:</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
git clone http://llvm.org/git/llvm.git
|
||||
cd llvm
|
||||
git svn init https://llvm.org/svn/llvm-project/llvm/trunk --username=<username>
|
||||
git config svn-remote.svn.fetch :refs/remotes/origin/master
|
||||
git svn rebase -l # -l avoids fetching ahead of the git mirror.
|
||||
|
||||
# If you have clang too:
|
||||
cd tools
|
||||
git clone http://llvm.org/git/clang.git
|
||||
cd clang
|
||||
git svn init https://llvm.org/svn/llvm-project/cfe/trunk --username=<username>
|
||||
git config svn-remote.svn.fetch :refs/remotes/origin/master
|
||||
git svn rebase -l
|
||||
</pre>
|
||||
|
||||
<p>To update this clone without generating git-svn tags that conflict
|
||||
with the upstream git repo, run:</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
git fetch && (cd tools/clang && git fetch) # Get matching revisions of both trees.
|
||||
git checkout master
|
||||
git svn rebase -l
|
||||
(cd tools/clang &&
|
||||
git checkout master &&
|
||||
git svn rebase -l)
|
||||
</pre>
|
||||
|
||||
<p>This leaves your working directories on their master branches, so
|
||||
you'll need to <tt>checkout</tt> each working branch individually and
|
||||
<tt>rebase</tt> it on top of its parent branch. (Note: This script is
|
||||
intended for relative newbies to git. If you have more experience,
|
||||
you can likely improve on it.)</p>
|
||||
|
||||
<p>The git-svn metadata can get out of sync after you mess around with
|
||||
branches and <code>dcommit</code>. When that happens, <code>git svn
|
||||
dcommit</code> stops working, complaining about files with uncommitted
|
||||
changes. The fix is to rebuild the metadata:</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
rm -rf .git/svn
|
||||
git svn rebase -l
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
@ -1362,13 +1503,9 @@ different <a href="#tools">tools</a>.</p>
|
||||
at runtime in both interpreted and JIT compiled fashions.</dd>
|
||||
|
||||
<dt><tt><b>llvm/lib/Support/</b></tt></dt>
|
||||
<dd> This directory contains the source code that corresponds to the header
|
||||
files located in <tt>llvm/include/Support/</tt>.</dd>
|
||||
|
||||
<!--FIXME: obsoleted -->
|
||||
<dt><tt><b>llvm/lib/System/</b></tt></dt>
|
||||
<dd>This directory contains the operating system abstraction layer that
|
||||
shields LLVM from platform-specific coding.</dd>
|
||||
<dd> This directory contains the source code that corresponds to the header
|
||||
files located in <tt>llvm/include/ADT/</tt>
|
||||
and <tt>llvm/include/Support/</tt>.</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
@ -1455,16 +1592,6 @@ information is in the <a href="CommandGuide/index.html">Command Guide</a>.</p>
|
||||
href="HowToSubmitABug.html">HowToSubmitABug.html</a> for more information
|
||||
on using <tt>bugpoint</tt>.</dd>
|
||||
|
||||
<dt><tt><b>llvmc</b></tt></dt>
|
||||
<dd>The LLVM Compiler Driver. This program can
|
||||
be configured to utilize both LLVM and non-LLVM compilation tools to enable
|
||||
pre-processing, translation, optimization, assembly, and linking of programs
|
||||
all from one command line. <tt>llvmc</tt> also takes care of processing the
|
||||
dependent libraries found in bitcode. This reduces the need to get the
|
||||
traditional <tt>-l<name></tt> options right on the command line. Please
|
||||
note that this tool, while functional, is still experimental and not feature
|
||||
complete.</dd>
|
||||
|
||||
<dt><tt><b>llvm-ar</b></tt></dt>
|
||||
<dd>The archiver produces an archive containing
|
||||
the given LLVM bitcode files, optionally with an index for faster
|
||||
@ -1480,9 +1607,9 @@ information is in the <a href="CommandGuide/index.html">Command Guide</a>.</p>
|
||||
|
||||
<dt><tt><b>llvm-ld</b></tt></dt>
|
||||
<dd><tt>llvm-ld</tt> is a general purpose and extensible linker for LLVM.
|
||||
This is the linker invoked by <tt>llvmc</tt>. It performs standard link time
|
||||
optimizations and allows optimization modules to be loaded and run so that
|
||||
language specific optimizations can be applied at link time.</dd>
|
||||
It performs standard link time optimizations and allows optimization
|
||||
modules to be loaded and run so that language specific optimizations can
|
||||
be applied at link time.</dd>
|
||||
|
||||
<dt><tt><b>llvm-link</b></tt></dt>
|
||||
<dd><tt>llvm-link</tt>, not surprisingly, links multiple LLVM modules into
|
||||
@ -1743,7 +1870,7 @@ out:</p>
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.x10sys.com/rspencer/">Reid Spencer</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-10-17 08:31:32 +0200 (Mon, 17 Oct 2011) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -75,6 +75,7 @@ placed.
|
||||
<h2><a name="usage">Usage</a></h2>
|
||||
<!--=========================================================================-->
|
||||
<div>
|
||||
|
||||
<p>The linker takes a <tt>-plugin</tt> option that points to the path of
|
||||
the plugin <tt>.so</tt> file. To find out what link command <tt>gcc</tt>
|
||||
would run in a given situation, run <tt>gcc -v <em>[...]</em></tt> and look
|
||||
@ -82,19 +83,21 @@ placed.
|
||||
<tt>ld-new -plugin /path/to/LLVMgold.so</tt> to test it out. Once you're
|
||||
ready to switch to using gold, backup your existing <tt>/usr/bin/ld</tt>
|
||||
then replace it with <tt>ld-new</tt>.</p>
|
||||
<p>You can produce bitcode files from <tt>llvm-gcc</tt> using
|
||||
|
||||
<p>You can produce bitcode files from <tt>clang</tt> using
|
||||
<tt>-emit-llvm</tt> or <tt>-flto</tt>, or the <tt>-O4</tt> flag which is
|
||||
synonymous with <tt>-O3 -flto</tt>.</p>
|
||||
<p><tt>llvm-gcc</tt> has a <tt>-use-gold-plugin</tt> option which looks
|
||||
for the gold plugin in the same directories as it looks for <tt>cc1</tt> and
|
||||
passes the <tt>-plugin</tt> option to ld. It will not look for an alternate
|
||||
|
||||
<p><tt>Clang</tt> has a <tt>-use-gold-plugin</tt> option which looks for the
|
||||
gold plugin in the same directories as it looks for <tt>cc1</tt> and passes
|
||||
the <tt>-plugin</tt> option to <tt>ld</tt>. It will not look for an alternate
|
||||
linker, which is why you need gold to be the installed system linker in your
|
||||
path.</p>
|
||||
|
||||
<p>If you want <tt>ar</tt> and <tt>nm</tt> to work seamlessly as well, install
|
||||
<tt>LLVMgold.so</tt> to <tt>/usr/lib/bfd-plugins</tt>. If you built your
|
||||
own gold, be sure to install the <tt>ar</tt> and <tt>nm-new</tt> you built to
|
||||
<tt>/usr/bin</tt>.
|
||||
<p>
|
||||
<tt>/usr/bin</tt>.<p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
@ -137,11 +140,12 @@ void foo4(void) {
|
||||
}
|
||||
|
||||
--- command lines ---
|
||||
$ llvm-gcc -flto a.c -c -o a.o # <-- a.o is LLVM bitcode file
|
||||
$ clang -flto a.c -c -o a.o # <-- a.o is LLVM bitcode file
|
||||
$ ar q a.a a.o # <-- a.a is an archive with LLVM bitcode
|
||||
$ llvm-gcc b.c -c -o b.o # <-- b.o is native object file
|
||||
$ llvm-gcc -use-gold-plugin a.a b.o -o main # <-- link with LLVMgold plugin
|
||||
$ clang b.c -c -o b.o # <-- b.o is native object file
|
||||
$ clang -use-gold-plugin a.a b.o -o main # <-- link with LLVMgold plugin
|
||||
</pre>
|
||||
|
||||
<p>Gold informs the plugin that foo3 is never referenced outside the IR,
|
||||
leading LLVM to delete that function. However, unlike in the
|
||||
<a href="LinkTimeOptimization.html#example1">libLTO
|
||||
@ -158,20 +162,21 @@ $ llvm-gcc -use-gold-plugin a.a b.o -o main # <-- link with LLVMgold plugin
|
||||
</h2>
|
||||
<!--=========================================================================-->
|
||||
<div>
|
||||
<p>Once your system <tt>ld</tt>, <tt>ar</tt> and <tt>nm</tt> all support LLVM
|
||||
bitcode, everything is in place for an easy to use LTO build of autotooled
|
||||
projects:</p>
|
||||
<p>Once your system <tt>ld</tt>, <tt>ar</tt>, and <tt>nm</tt> all support LLVM
|
||||
bitcode, everything is in place for an easy to use LTO build of autotooled
|
||||
projects:</p>
|
||||
|
||||
<ul>
|
||||
<li>Follow the instructions <a href="#build">on how to build LLVMgold.so</a>.</li>
|
||||
<li>Install the newly built binutils to <tt>$PREFIX</tt></li>
|
||||
<li>Copy <tt>Release/lib/LLVMgold.so</tt> to
|
||||
<tt>$PREFIX/libexec/gcc/x86_64-unknown-linux-gnu/4.2.1/</tt> and
|
||||
<tt>$PREFIX/lib/bfd-plugins/</tt></li>
|
||||
<li>Set environment variables (<tt>$PREFIX</tt> is where you installed llvm-gcc and
|
||||
binutils):
|
||||
<pre class="doc_code">
|
||||
export CC="$PREFIX/bin/llvm-gcc -use-gold-plugin"
|
||||
export CXX="$PREFIX/bin/llvm-g++ -use-gold-plugin"
|
||||
<tt>$PREFIX/libexec/gcc/x86_64-unknown-linux-gnu/4.2.1/</tt> and
|
||||
<tt>$PREFIX/lib/bfd-plugins/</tt></li>
|
||||
<li>Set environment variables (<tt>$PREFIX</tt> is where you installed clang and
|
||||
binutils):
|
||||
<pre class="doc_code">
|
||||
export CC="$PREFIX/bin/clang -use-gold-plugin"
|
||||
export CXX="$PREFIX/bin/clang++ -use-gold-plugin"
|
||||
export AR="$PREFIX/bin/ar"
|
||||
export NM="$PREFIX/bin/nm"
|
||||
export RANLIB=/bin/true #ranlib is not needed, and doesn't support .bc files in .a
|
||||
@ -179,18 +184,22 @@ export CFLAGS="-O4"
|
||||
</pre>
|
||||
</li>
|
||||
<li>Or you can just set your path:
|
||||
<pre class="doc_code">
|
||||
<pre class="doc_code">
|
||||
export PATH="$PREFIX/bin:$PATH"
|
||||
export CC="llvm-gcc -use-gold-plugin"
|
||||
export CXX="llvm-g++ -use-gold-plugin"
|
||||
export CC="clang -use-gold-plugin"
|
||||
export CXX="clang++ -use-gold-plugin"
|
||||
export RANLIB=/bin/true
|
||||
export CFLAGS="-O4"
|
||||
</pre>
|
||||
</li>
|
||||
<li>Configure & build the project as usual: <tt>./configure && make && make check</tt> </li>
|
||||
</pre></li>
|
||||
<li>Configure & build the project as usual:
|
||||
<pre class="doc_code">
|
||||
% ./configure && make && make check
|
||||
</pre></li>
|
||||
</ul>
|
||||
<p> The environment variable settings may work for non-autotooled projects
|
||||
too, but you may need to set the <tt>LD</tt> environment variable as well.</p>
|
||||
|
||||
<p>The environment variable settings may work for non-autotooled projects
|
||||
too, but you may need to set the <tt>LD</tt> environment variable as
|
||||
well.</p>
|
||||
</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
|
@ -29,7 +29,7 @@
|
||||
<div>
|
||||
|
||||
<p>This document contains information about successfully releasing LLVM —
|
||||
including subprojects: e.g., <tt>llvm-gcc</tt> and <tt>clang</tt> — to
|
||||
including subprojects: e.g., <tt>clang</tt> and <tt>dragonegg</tt> — to
|
||||
the public. It is the Release Manager's responsibility to ensure that a high
|
||||
quality build of LLVM is released.</p>
|
||||
|
||||
@ -92,7 +92,6 @@
|
||||
<ol>
|
||||
<li><a href="#dist">Build the LLVM Source Distributions</a></li>
|
||||
<li><a href="#build">Build LLVM</a></li>
|
||||
<li><a href="#llvmgccbin">Build the LLVM-GCC Binary Distribution</a></li>
|
||||
<li><a href="#clangbin">Build the Clang Binary Distribution</a></li>
|
||||
<li><a href="#target-build">Target Specific Build Details</a></li>
|
||||
</ol>
|
||||
@ -100,7 +99,6 @@
|
||||
<li><a href="#release-qualify">Release Qualification Criteria</a>
|
||||
<ol>
|
||||
<li><a href="#llvm-qualify">Qualify LLVM</a></li>
|
||||
<li><a href="#llvmgcc-qualify">Qualify LLVM-GCC</a></li>
|
||||
<li><a href="#clang-qualify">Qualify Clang</a></li>
|
||||
<li><a href="#targets">Specific Target Qualification Details</a></li>
|
||||
</ol>
|
||||
@ -149,25 +147,25 @@
|
||||
<li><p>Verify that the current Subversion trunk is in decent shape by
|
||||
examining nightly tester and buildbot results.</p></li>
|
||||
|
||||
<li><p>Create the release branch for <tt>llvm</tt>, <tt>llvm-gcc-4.2</tt>,
|
||||
<tt>clang</tt>, and the <tt>test-suite</tt> from the last known good
|
||||
revision. The branch's name is <tt>release_XY</tt>, where <tt>X</tt> is
|
||||
the major and <tt>Y</tt> the minor release numbers. The branches should be
|
||||
created using the following commands:</p>
|
||||
<li><p>Create the release branch for <tt>llvm</tt>, <tt>clang</tt>,
|
||||
the <tt>test-suite</tt>, and <tt>dragonegg</tt> from the last known good
|
||||
revision. The branch's name is <tt>release_<i>XY</i></tt>,
|
||||
where <tt>X</tt> is the major and <tt>Y</tt> the minor release
|
||||
numbers. The branches should be created using the following commands:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
$ svn copy https://llvm.org/svn/llvm-project/llvm/trunk \
|
||||
https://llvm.org/svn/llvm-project/llvm/branches/release_<i>XY</i>
|
||||
|
||||
$ svn copy https://llvm.org/svn/llvm-project/llvm-gcc-4.2/trunk \
|
||||
https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_<i>XY</i>
|
||||
$ svn copy https://llvm.org/svn/llvm-project/cfe/trunk \
|
||||
https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i>
|
||||
|
||||
$ svn copy https://llvm.org/svn/llvm-project/dragonegg/trunk \
|
||||
https://llvm.org/svn/llvm-project/dragonegg/branches/release_<i>XY</i>
|
||||
|
||||
$ svn copy https://llvm.org/svn/llvm-project/test-suite/trunk \
|
||||
https://llvm.org/svn/llvm-project/test-suite/branches/release_<i>XY</i>
|
||||
|
||||
$ svn copy https://llvm.org/svn/llvm-project/cfe/trunk \
|
||||
https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i>
|
||||
</pre>
|
||||
</div></li>
|
||||
|
||||
@ -182,11 +180,11 @@ $ svn copy https://llvm.org/svn/llvm-project/cfe/trunk \
|
||||
<pre>
|
||||
$ svn co https://llvm.org/svn/llvm-project/llvm/branches/release_<i>XY</i> llvm-<i>X.Y</i>
|
||||
|
||||
$ svn co https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_<i>XY</i> llvm-gcc-4.2-<i>X.Y</i>
|
||||
$ svn co https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i> clang-<i>X.Y</i>
|
||||
|
||||
$ svn co https://llvm.org/svn/llvm-project/dragonegg/branches/release_<i>XY</i> dragonegg-<i>X.Y</i>
|
||||
|
||||
$ svn co https://llvm.org/svn/llvm-project/test-suite/branches/release_<i>XY</i> test-suite-<i>X.Y</i>
|
||||
|
||||
$ svn co https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i> clang-<i>X.Y</i>
|
||||
</pre>
|
||||
</div></li>
|
||||
</ol>
|
||||
@ -214,10 +212,10 @@ $ svn co https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i> clang-
|
||||
|
||||
<div>
|
||||
|
||||
<p>Create release candidates for <tt>llvm</tt>, <tt>llvm-gcc</tt>,
|
||||
<tt>clang</tt>, and the LLVM <tt>test-suite</tt> by tagging the branch with
|
||||
the respective release candidate number. For instance, to create <b>Release
|
||||
Candidate 1</b> you would issue the following commands:</p>
|
||||
<p>Create release candidates for <tt>llvm</tt>, <tt>clang</tt>,
|
||||
<tt>dragonegg</tt>, and the LLVM <tt>test-suite</tt> by tagging the branch
|
||||
with the respective release candidate number. For instance, to
|
||||
create <b>Release Candidate 1</b> you would issue the following commands:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
@ -225,17 +223,17 @@ $ svn mkdir https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_<i>XY</i>
|
||||
$ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_<i>XY</i> \
|
||||
https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_<i>XY</i>/rc1
|
||||
|
||||
$ svn mkdir https://llvm.org/svn/llvm-project/llvm-gcc-4.2/tags/RELEASE_<i>XY</i>
|
||||
$ svn copy https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_<i>XY</i> \
|
||||
https://llvm.org/svn/llvm-project/llvm-gcc-4.2/tags/RELEASE_<i>XY</i>/rc1
|
||||
$ svn mkdir https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>
|
||||
$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i> \
|
||||
https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>/rc1
|
||||
|
||||
$ svn mkdir https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_<i>XY</i>
|
||||
$ svn copy https://llvm.org/svn/llvm-project/dragonegg/branches/release_<i>XY</i> \
|
||||
https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_<i>XY</i>/rc1
|
||||
|
||||
$ svn mkdir https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_<i>XY</i>
|
||||
$ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_<i>XY</i> \
|
||||
https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_<i>XY</i>/rc1
|
||||
|
||||
$ svn mkdir https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>
|
||||
$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i> \
|
||||
https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>/rc1
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -251,14 +249,14 @@ $ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_<i>XY</i> \
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
$ svn export https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_<i>XY</i>/rc1 llvm-<i>X.Y</i>rc1
|
||||
$ svn export https://llvm.org/svn/llvm-project/llvm-gcc-4.2/tags/RELEASE_<i>XY</i>/rc1 llvm-gcc4.2-<i>X.Y</i>rc1
|
||||
$ svn export https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_<i>XY</i>/rc1 llvm-test-<i>X.Y</i>rc1
|
||||
$ svn export https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>/rc1 clang-<i>X.Y</i>rc1
|
||||
$ svn export https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_<i>XY</i>/rc1 dragonegg-<i>X.Y</i>rc1
|
||||
$ svn export https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_<i>XY</i>/rc1 llvm-test-<i>X.Y</i>rc1
|
||||
|
||||
$ tar -cvf - llvm-<i>X.Y</i>rc1 | gzip > llvm-<i>X.Y</i>rc1.src.tar.gz
|
||||
$ tar -cvf - llvm-test-<i>X.Y</i>rc1 | gzip > llvm-test-<i>X.Y</i>rc1.src.tar.gz
|
||||
$ tar -cvf - llvm-gcc4.2-<i>X.Y</i>rc1 | gzip > llvm-gcc-4.2-<i>X.Y</i>rc1.src.tar.gz
|
||||
$ tar -cvf - clang-<i>X.Y</i>rc1 | gzip > clang-<i>X.Y</i>rc1.src.tar.gz
|
||||
$ tar -cvf - dragonegg-<i>X.Y</i>rc1 | gzip > dragonegg-<i>X.Y</i>rc1.src.tar.gz
|
||||
$ tar -cvf - llvm-test-<i>X.Y</i>rc1 | gzip > llvm-test-<i>X.Y</i>rc1.src.tar.gz
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -271,7 +269,7 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip > clang-<i>X.Y</i>rc1.src.tar.g
|
||||
|
||||
<div>
|
||||
|
||||
<p>The builds of <tt>llvm</tt>, <tt>llvm-gcc</tt>, and <tt>clang</tt>
|
||||
<p>The builds of <tt>llvm</tt>, <tt>clang</tt>, and <tt>dragonegg</tt>
|
||||
<em>must</em> be free of errors and warnings in Debug, Release+Asserts, and
|
||||
Release builds. If all builds are clean, then the release passes Build
|
||||
Qualification.</p>
|
||||
@ -292,35 +290,7 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip > clang-<i>X.Y</i>rc1.src.tar.g
|
||||
|
||||
<p>Build <tt>Debug</tt>, <tt>Release+Asserts</tt>, and <tt>Release</tt> versions
|
||||
of <tt>llvm</tt> on all supported platforms. Directions to build
|
||||
<tt>llvm</tt> are
|
||||
<a href="GettingStarted.html#quickstart">here</a>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h4><a name="llvmgccbin">Build the LLVM GCC Binary Distribution</a></h4>
|
||||
|
||||
<div>
|
||||
|
||||
<p>Creating the <tt>llvm-gcc</tt> binary distribution (Release/Optimized)
|
||||
requires performing the following steps for each supported platform:</p>
|
||||
|
||||
<ol>
|
||||
<li><p>Build the <tt>llvm-gcc</tt> front-end by following the directions in
|
||||
the <tt>README.LLVM</tt> file. The front-end must be compiled with C, C++,
|
||||
Objective-C (Mac only), Objective-C++ (Mac only), and Fortran
|
||||
support.</p></li>
|
||||
|
||||
<li><p>Boostrapping must be enabled.</p></li>
|
||||
|
||||
<li><p>Be sure to build with <tt>LLVM_VERSION_INFO=X.Y</tt>, where <tt>X</tt>
|
||||
is the major and <tt>Y</tt> is the minor release numbers.</p></li>
|
||||
|
||||
<li><p>Copy the installation directory to a directory named for the specific
|
||||
target. For example on Red Hat Enterprise Linux, the directory would be
|
||||
named <tt>llvm-gcc4.2-2.6-x86-linux-RHEL4</tt>. Archive and compress the
|
||||
new directory.</p></li>
|
||||
</ol>
|
||||
<tt>llvm</tt> are <a href="GettingStarted.html#quickstart">here</a>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -337,8 +307,8 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip > clang-<i>X.Y</i>rc1.src.tar.g
|
||||
<li>Build clang according to the directions
|
||||
<a href="http://clang.llvm.org/get_started.html">here</a>.</li>
|
||||
|
||||
<li>Build both a debug and release version of clang. The binary will be the
|
||||
release build.</lI>
|
||||
<li>Build both a Debug and Release version of clang. The binary will be the
|
||||
Release build.</lI>
|
||||
|
||||
<li>Package <tt>clang</tt> (details to follow).</li>
|
||||
</ol>
|
||||
@ -351,18 +321,18 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip > clang-<i>X.Y</i>rc1.src.tar.g
|
||||
<div>
|
||||
|
||||
<p>The table below specifies which compilers are used for each Arch/OS
|
||||
combination when qualifying the build of <tt>llvm</tt>, <tt>llvm-gcc</tt>,
|
||||
and <tt>clang</tt>.</p>
|
||||
combination when qualifying the build of <tt>llvm</tt>, <tt>clang</tt>,
|
||||
and <tt>dragonegg</tt>.</p>
|
||||
|
||||
<table>
|
||||
<tr><th>Architecture</th><th>OS</th><th>compiler</th></tr>
|
||||
<tr><td>x86-32</td><td>Mac OS 10.5</td><td>gcc 4.0.1</td></tr>
|
||||
<tr><td>x86-32</td><td>Linux</td><td>gcc 4.2.X, gcc 4.3.X</td></tr>
|
||||
<tr><td>x86-32</td><td>FreeBSD</td><td>gcc 4.2.X</td></tr>
|
||||
<tr><td>x86-32</td><td>mingw</td><td>gcc 3.4.5</td></tr>
|
||||
<tr><td>x86-64</td><td>Mac OS 10.5</td><td>gcc 4.0.1</td></tr>
|
||||
<tr><td>x86-64</td><td>Linux</td><td>gcc 4.2.X, gcc 4.3.X</td></tr>
|
||||
<tr><td>x86-64</td><td>FreeBSD</td><td>gcc 4.2.X</td></tr>
|
||||
<tr><th>Architecture</th> <th>OS</th> <th>compiler</th></tr>
|
||||
<tr><td>x86-32</td> <td>Mac OS 10.5</td> <td>gcc 4.0.1</td></tr>
|
||||
<tr><td>x86-32</td> <td>Linux</td> <td>gcc 4.2.X, gcc 4.3.X</td></tr>
|
||||
<tr><td>x86-32</td> <td>FreeBSD</td> <td>gcc 4.2.X</td></tr>
|
||||
<tr><td>x86-32</td> <td>mingw</td> <td>gcc 3.4.5</td></tr>
|
||||
<tr><td>x86-64</td> <td>Mac OS 10.5</td> <td>gcc 4.0.1</td></tr>
|
||||
<tr><td>x86-64</td> <td>Linux</td> <td>gcc 4.2.X, gcc 4.3.X</td></tr>
|
||||
<tr><td>x86-64</td> <td>FreeBSD</td> <td>gcc 4.2.X</td></tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
@ -394,21 +364,8 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip > clang-<i>X.Y</i>rc1.src.tar.g
|
||||
<div>
|
||||
|
||||
<p>LLVM is qualified when it has a clean test run without a front-end. And it
|
||||
has no regressions when using either <tt>llvm-gcc</tt> or <tt>clang</tt> with
|
||||
the <tt>test-suite</tt> from the previous release.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h4><a name="llvmgcc-qualify">Qualify LLVM-GCC</a></h4>
|
||||
|
||||
<div>
|
||||
|
||||
<p><tt>LLVM-GCC</tt> is qualified when front-end specific tests in the
|
||||
<tt>llvm</tt> regression test suite all pass and there are no regressions in
|
||||
the <tt>test-suite</tt>.</p>
|
||||
|
||||
<p>We do not use the GCC DejaGNU test suite as release criteria.</p>
|
||||
has no regressions when using either <tt>clang</tt> or <tt>dragonegg</tt>
|
||||
with the <tt>test-suite</tt> from the previous release.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -429,13 +386,13 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip > clang-<i>X.Y</i>rc1.src.tar.g
|
||||
<div>
|
||||
|
||||
<table>
|
||||
<tr><th>Architecture</th><th>OS</th><th>llvm-gcc baseline</th><th>clang baseline</th><th>tests</th></tr>
|
||||
<tr><td>x86-32</td><td>Linux</td><td>last release</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr>
|
||||
<tr><td>x86-32</td><td>FreeBSD</td><td>none</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite</td></tr>
|
||||
<tr><td>x86-32</td><td>mingw</td><td>last release</td><td>none</td><td>QT</td></tr>
|
||||
<tr><td>x86-64</td><td>Mac OS 10.X</td><td>last release</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr>
|
||||
<tr><td>x86-64</td><td>Linux</td><td>last release</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr>
|
||||
<tr><td>x86-64</td><td>FreeBSD</td><td>none</td><td>last release</td><td>llvm dejagnu, clang tests, test-suite</td></tr>
|
||||
<tr><th>Architecture</th> <th>OS</th> <th>clang baseline</th> <th>tests</th></tr>
|
||||
<tr><td>x86-32</td> <td>Linux</td> <td>last release</td> <td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr>
|
||||
<tr><td>x86-32</td> <td>FreeBSD</td> <td>last release</td> <td>llvm dejagnu, clang tests, test-suite</td></tr>
|
||||
<tr><td>x86-32</td> <td>mingw</td> <td>none</td> <td>QT</td></tr>
|
||||
<tr><td>x86-64</td> <td>Mac OS 10.X</td> <td>last release</td> <td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr>
|
||||
<tr><td>x86-64</td> <td>Linux</td> <td>last release</td> <td>llvm dejagnu, clang tests, test-suite (including spec)</td></tr>
|
||||
<tr><td>x86-64</td> <td>FreeBSD</td> <td>last release</td> <td>llvm dejagnu, clang tests, test-suite</td></tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
@ -452,14 +409,12 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip > clang-<i>X.Y</i>rc1.src.tar.g
|
||||
|
||||
<ol>
|
||||
<li>Download <tt>llvm-<i>X.Y</i></tt>, <tt>llvm-test-<i>X.Y</i></tt>, and the
|
||||
appropriate <tt>llvm-gcc</tt> and/or <tt>clang</tt> binary. Build
|
||||
LLVM. Run <tt>make check</tt> and the full LLVM test suite (<tt>make
|
||||
TEST=nightly report</tt>).</li>
|
||||
appropriate <tt>clang</tt> binary. Build LLVM. Run <tt>make check</tt> and
|
||||
the full LLVM test suite (<tt>make TEST=nightly report</tt>).</li>
|
||||
|
||||
<li>Download <tt>llvm-<i>X.Y</i></tt>, <tt>llvm-test-<i>X.Y</i></tt>, and the
|
||||
<tt>llvm-gcc</tt> and/or <tt>clang</tt> source. Compile everything. Run
|
||||
<tt>make check</tt> and the full LLVM test suite (<tt>make TEST=nightly
|
||||
report</tt>).</li>
|
||||
<tt>clang</tt> sources. Compile everything. Run <tt>make check</tt> and
|
||||
the full LLVM test suite (<tt>make TEST=nightly report</tt>).</li>
|
||||
</ol>
|
||||
|
||||
<p>Ask LLVM developers to submit the test suite report and <tt>make check</tt>
|
||||
@ -538,14 +493,14 @@ $ tar -cvf - clang-<i>X.Y</i>rc1 | gzip > clang-<i>X.Y</i>rc1.src.tar.g
|
||||
$ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_<i>XY</i>/Final
|
||||
|
||||
$ svn copy https://llvm.org/svn/llvm-project/llvm-gcc-4.2/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/llvm-gcc-4.2/tags/RELEASE_<i>XY</i>/Final
|
||||
$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>/Final
|
||||
|
||||
$ svn copy https://llvm.org/svn/llvm-project/dragonegg/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_<i>XY</i>/Final
|
||||
|
||||
$ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_<i>XY</i>/Final
|
||||
|
||||
$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_<i>XY</i>/Final
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -559,7 +514,7 @@ $ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
|
||||
<div>
|
||||
|
||||
<p>The LLVM demo page must be updated to use the new release. This consists of
|
||||
using the new <tt>llvm-gcc</tt> binary and building LLVM.</p>
|
||||
using the new <tt>clang</tt> binary and building LLVM.</p>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h4><a name="webupdates">Update the LLVM Website</a></h4>
|
||||
@ -574,8 +529,8 @@ $ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
|
||||
|
||||
<li>Create a new subdirectory <tt>X.Y</tt> in the releases directory.</li>
|
||||
|
||||
<li>Commit the <tt>llvm</tt>, <tt>test-suite</tt>, <tt>llvm-gcc</tt> source,
|
||||
<tt>clang source</tt>, <tt>clang binaries</tt>, and <tt>llvm-gcc</tt>
|
||||
<li>Commit the <tt>llvm</tt>, <tt>test-suite</tt>, <tt>clang</tt> source,
|
||||
<tt>clang binaries</tt>, <tt>dragonegg</tt> source, and <tt>dragonegg</tt>
|
||||
binaries in this new directory.</li>
|
||||
|
||||
<li>Copy and commit the <tt>llvm/docs</tt> and <tt>LICENSE.txt</tt> files
|
||||
@ -619,7 +574,7 @@ $ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-10-17 22:32:14 +0200 (Mon, 17 Oct 2011) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -35,6 +35,10 @@
|
||||
<td><a href="#DSA">DSA</a></td>
|
||||
<td><a href="#DSE">DSE</a></td>
|
||||
</tr>
|
||||
<tr><th colspan="8"><b>- <a href="#F">F</a> -</b></th></tr>
|
||||
<tr>
|
||||
<td><a href="#FCA">FCA</a></td>
|
||||
</tr>
|
||||
<tr><th colspan="8"><b>- <a href="#G">G</a> -</b></th></tr>
|
||||
<tr>
|
||||
<td><a href="#GC">GC</a></td>
|
||||
@ -137,6 +141,14 @@ href="http://www.program-transformation.org/Transform/BURG">BURG</a> tool.</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<h3><a name="F">- F -</a></h3>
|
||||
<div>
|
||||
<dl>
|
||||
<dt><a name="FCA"><b>FCA</b></a></dt>
|
||||
<dd>First Class Aggregate</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<h3><a name="G">- G -</a></h3>
|
||||
<div>
|
||||
<dl>
|
||||
@ -272,7 +284,7 @@ href="http://www.program-transformation.org/Transform/BURG">BURG</a> tool.</dd>
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a><a
|
||||
href="http://llvm.org/">The LLVM Team</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-09-27 20:44:01 +0200 (Tue, 27 Sep 2011) $
|
||||
</address>
|
||||
<!-- vim: sw=2
|
||||
-->
|
||||
|
@ -79,7 +79,7 @@ conservative escape analysis.
|
||||
<p>The following example illustrates the advantages of LTO's integrated
|
||||
approach and clean interface. This example requires a system linker which
|
||||
supports LTO through the interface described in this document. Here,
|
||||
llvm-gcc transparently invokes system linker. </p>
|
||||
clang transparently invokes system linker. </p>
|
||||
<ul>
|
||||
<li> Input source file <tt>a.c</tt> is compiled into LLVM bitcode form.
|
||||
<li> Input source file <tt>main.c</tt> is compiled into native object code.
|
||||
@ -89,27 +89,29 @@ conservative escape analysis.
|
||||
extern int foo1(void);
|
||||
extern void foo2(void);
|
||||
extern void foo4(void);
|
||||
|
||||
--- a.c ---
|
||||
#include "a.h"
|
||||
|
||||
static signed int i = 0;
|
||||
|
||||
void foo2(void) {
|
||||
i = -1;
|
||||
i = -1;
|
||||
}
|
||||
|
||||
static int foo3() {
|
||||
foo4();
|
||||
return 10;
|
||||
foo4();
|
||||
return 10;
|
||||
}
|
||||
|
||||
int foo1(void) {
|
||||
int data = 0;
|
||||
int data = 0;
|
||||
|
||||
if (i < 0) { data = foo3(); }
|
||||
if (i < 0)
|
||||
data = foo3();
|
||||
|
||||
data = data + 42;
|
||||
return data;
|
||||
data = data + 42;
|
||||
return data;
|
||||
}
|
||||
|
||||
--- main.c ---
|
||||
@ -117,30 +119,35 @@ return data;
|
||||
#include "a.h"
|
||||
|
||||
void foo4(void) {
|
||||
printf ("Hi\n");
|
||||
printf("Hi\n");
|
||||
}
|
||||
|
||||
int main() {
|
||||
return foo1();
|
||||
return foo1();
|
||||
}
|
||||
|
||||
--- command lines ---
|
||||
$ llvm-gcc --emit-llvm -c a.c -o a.o # <-- a.o is LLVM bitcode file
|
||||
$ llvm-gcc -c main.c -o main.o # <-- main.o is native object file
|
||||
$ llvm-gcc a.o main.o -o main # <-- standard link command without any modifications
|
||||
$ clang -emit-llvm -c a.c -o a.o # <-- a.o is LLVM bitcode file
|
||||
$ clang -c main.c -o main.o # <-- main.o is native object file
|
||||
$ clang a.o main.o -o main # <-- standard link command without any modifications
|
||||
</pre>
|
||||
<p>In this example, the linker recognizes that <tt>foo2()</tt> is an
|
||||
externally visible symbol defined in LLVM bitcode file. The linker completes
|
||||
its usual symbol resolution
|
||||
pass and finds that <tt>foo2()</tt> is not used anywhere. This information
|
||||
is used by the LLVM optimizer and it removes <tt>foo2()</tt>. As soon as
|
||||
<tt>foo2()</tt> is removed, the optimizer recognizes that condition
|
||||
<tt>i < 0</tt> is always false, which means <tt>foo3()</tt> is never
|
||||
used. Hence, the optimizer removes <tt>foo3()</tt>, also. And this in turn,
|
||||
enables linker to remove <tt>foo4()</tt>. This example illustrates the
|
||||
advantage of tight integration with the linker. Here, the optimizer can not
|
||||
remove <tt>foo3()</tt> without the linker's input.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>In this example, the linker recognizes that <tt>foo2()</tt> is an
|
||||
externally visible symbol defined in LLVM bitcode file. The linker
|
||||
completes its usual symbol resolution pass and finds that <tt>foo2()</tt>
|
||||
is not used anywhere. This information is used by the LLVM optimizer and
|
||||
it removes <tt>foo2()</tt>.</li>
|
||||
<li>As soon as <tt>foo2()</tt> is removed, the optimizer recognizes that condition
|
||||
<tt>i < 0</tt> is always false, which means <tt>foo3()</tt> is never
|
||||
used. Hence, the optimizer also removes <tt>foo3()</tt>.</li>
|
||||
<li>And this in turn, enables linker to remove <tt>foo4()</tt>.</li>
|
||||
</ul>
|
||||
|
||||
<p>This example illustrates the advantage of tight integration with the
|
||||
linker. Here, the optimizer can not remove <tt>foo3()</tt> without the
|
||||
linker's input.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
@ -385,7 +392,7 @@ of the native object files.</p>
|
||||
|
||||
Devang Patel and Nick Kledzik<br>
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-09-18 14:51:05 +0200 (Sun, 18 Sep 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -161,7 +161,6 @@ perl -e '$/ = undef; for (split(/\n/, <>)) { s:^ *///? ?::; print " <p>\n" if !
|
||||
<tr><td><a href="#loop-unswitch">-loop-unswitch</a></td><td>Unswitch loops</td></tr>
|
||||
<tr><td><a href="#loweratomic">-loweratomic</a></td><td>Lower atomic intrinsics to non-atomic form</td></tr>
|
||||
<tr><td><a href="#lowerinvoke">-lowerinvoke</a></td><td>Lower invoke and unwind, for unwindless code generators</td></tr>
|
||||
<tr><td><a href="#lowersetjmp">-lowersetjmp</a></td><td>Lower Set Jump</td></tr>
|
||||
<tr><td><a href="#lowerswitch">-lowerswitch</a></td><td>Lower SwitchInst's to branches</td></tr>
|
||||
<tr><td><a href="#mem2reg">-mem2reg</a></td><td>Promote Memory to Register</td></tr>
|
||||
<tr><td><a href="#memcpyopt">-memcpyopt</a></td><td>MemCpy Optimization</td></tr>
|
||||
@ -1476,35 +1475,6 @@ if (X < 3) {</pre>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-------------------------------------------------------------------------- -->
|
||||
<h3>
|
||||
<a name="lowersetjmp">-lowersetjmp: Lower Set Jump</a>
|
||||
</h3>
|
||||
<div>
|
||||
<p>
|
||||
Lowers <tt>setjmp</tt> and <tt>longjmp</tt> to use the LLVM invoke and unwind
|
||||
instructions as necessary.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Lowering of <tt>longjmp</tt> is fairly trivial. We replace the call with a
|
||||
call to the LLVM library function <tt>__llvm_sjljeh_throw_longjmp()</tt>.
|
||||
This unwinds the stack for us calling all of the destructors for
|
||||
objects allocated on the stack.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
At a <tt>setjmp</tt> call, the basic block is split and the <tt>setjmp</tt>
|
||||
removed. The calls in a function that have a <tt>setjmp</tt> are converted to
|
||||
invoke where the except part checks to see if it's a <tt>longjmp</tt>
|
||||
exception and, if so, if it's handled in the function. If it is, then it gets
|
||||
the value returned by the <tt>longjmp</tt> and goes to where the basic block
|
||||
was split. <tt>invoke</tt> instructions are handled in a similar fashion with
|
||||
the original except block being executed if it isn't a <tt>longjmp</tt>
|
||||
except that is handled by that function.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-------------------------------------------------------------------------- -->
|
||||
<h3>
|
||||
<a name="lowerswitch">-lowerswitch: Lower SwitchInst's to branches</a>
|
||||
@ -2071,7 +2041,7 @@ if (X < 3) {</pre>
|
||||
|
||||
<a href="mailto:rspencer@x10sys.com">Reid Spencer</a><br>
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-08-04 00:18:20 +0200 (Thu, 04 Aug 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -59,6 +59,7 @@ option</a></li>
|
||||
<li><a href="#dss_arrayref">llvm/ADT/ArrayRef.h</a></li>
|
||||
<li><a href="#dss_fixedarrays">Fixed Size Arrays</a></li>
|
||||
<li><a href="#dss_heaparrays">Heap Allocated Arrays</a></li>
|
||||
<li><a href="#dss_tinyptrvector">"llvm/ADT/TinyPtrVector.h"</a></li>
|
||||
<li><a href="#dss_smallvector">"llvm/ADT/SmallVector.h"</a></li>
|
||||
<li><a href="#dss_vector"><vector></a></li>
|
||||
<li><a href="#dss_deque"><deque></a></li>
|
||||
@ -67,6 +68,13 @@ option</a></li>
|
||||
<li><a href="#dss_packedvector">llvm/ADT/PackedVector.h</a></li>
|
||||
<li><a href="#dss_other">Other Sequential Container Options</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#ds_string">String-like containers</a>
|
||||
<ul>
|
||||
<li><a href="#dss_stringref">llvm/ADT/StringRef.h</a></li>
|
||||
<li><a href="#dss_twine">llvm/ADT/Twine.h</a></li>
|
||||
<li><a href="#dss_smallstring">llvm/ADT/SmallString.h</a></li>
|
||||
<li><a href="#dss_stdstring">std::string</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#ds_set">Set-Like Containers (std::set, SmallSet, SetVector, etc)</a>
|
||||
<ul>
|
||||
<li><a href="#dss_sortedvectorset">A sorted 'vector'</a></li>
|
||||
@ -91,10 +99,6 @@ option</a></li>
|
||||
<li><a href="#dss_inteqclasses">"llvm/ADT/IntEqClasses.h"</a></li>
|
||||
<li><a href="#dss_othermap">Other Map-Like Container Options</a></li>
|
||||
</ul></li>
|
||||
<li><a href="#ds_string">String-like containers</a>
|
||||
<!--<ul>
|
||||
todo
|
||||
</ul>--></li>
|
||||
<li><a href="#ds_bit">BitVector-like containers</a>
|
||||
<ul>
|
||||
<li><a href="#dss_bitvector">A dense bitvector</a></li>
|
||||
@ -875,6 +879,9 @@ elements (but could contain many), for example, it's much better to use
|
||||
. Doing so avoids (relatively) expensive malloc/free calls, which dwarf the
|
||||
cost of adding the elements to the container. </p>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="ds_sequential">Sequential Containers (std::vector, std::list, etc)</a>
|
||||
@ -883,7 +890,7 @@ cost of adding the elements to the container. </p>
|
||||
<div>
|
||||
There are a variety of sequential containers available for you, based on your
|
||||
needs. Pick the first in this section that will do what you want.
|
||||
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<h4>
|
||||
<a name="dss_arrayref">llvm/ADT/ArrayRef.h</a>
|
||||
@ -926,6 +933,22 @@ destructors will be run for every element in the array (re-sizable vectors only
|
||||
construct those elements actually used).</p>
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<h4>
|
||||
<a name="dss_tinyptrvector">"llvm/ADT/TinyPtrVector.h"</a>
|
||||
</h4>
|
||||
|
||||
|
||||
<div>
|
||||
<p><tt>TinyPtrVector<Type></tt> is a highly specialized collection class
|
||||
that is optimized to avoid allocation in the case when a vector has zero or one
|
||||
elements. It has two major restrictions: 1) it can only hold values of pointer
|
||||
type, and 2) it cannot hold a null pointer.</p>
|
||||
|
||||
<p>Since this container is highly specialized, it is rarely used.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<h4>
|
||||
<a name="dss_smallvector">"llvm/ADT/SmallVector.h"</a>
|
||||
@ -1190,9 +1213,187 @@ std::priority_queue, std::stack, etc. These provide simplified access to an
|
||||
underlying container but don't affect the cost of the container itself.</p>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="ds_string">String-like containers</a>
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
|
||||
<p>
|
||||
There are a variety of ways to pass around and use strings in C and C++, and
|
||||
LLVM adds a few new options to choose from. Pick the first option on this list
|
||||
that will do what you need, they are ordered according to their relative cost.
|
||||
</p>
|
||||
<p>
|
||||
Note that is is generally preferred to <em>not</em> pass strings around as
|
||||
"<tt>const char*</tt>"'s. These have a number of problems, including the fact
|
||||
that they cannot represent embedded nul ("\0") characters, and do not have a
|
||||
length available efficiently. The general replacement for '<tt>const
|
||||
char*</tt>' is StringRef.
|
||||
</p>
|
||||
|
||||
<p>For more information on choosing string containers for APIs, please see
|
||||
<a href="#string_apis">Passing strings</a>.</p>
|
||||
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<h4>
|
||||
<a name="dss_stringref">llvm/ADT/StringRef.h</a>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
The StringRef class is a simple value class that contains a pointer to a
|
||||
character and a length, and is quite related to the <a
|
||||
href="#dss_arrayref">ArrayRef</a> class (but specialized for arrays of
|
||||
characters). Because StringRef carries a length with it, it safely handles
|
||||
strings with embedded nul characters in it, getting the length does not require
|
||||
a strlen call, and it even has very convenient APIs for slicing and dicing the
|
||||
character range that it represents.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
StringRef is ideal for passing simple strings around that are known to be live,
|
||||
either because they are C string literals, std::string, a C array, or a
|
||||
SmallVector. Each of these cases has an efficient implicit conversion to
|
||||
StringRef, which doesn't result in a dynamic strlen being executed.
|
||||
</p>
|
||||
|
||||
<p>StringRef has a few major limitations which make more powerful string
|
||||
containers useful:</p>
|
||||
|
||||
<ol>
|
||||
<li>You cannot directly convert a StringRef to a 'const char*' because there is
|
||||
no way to add a trailing nul (unlike the .c_str() method on various stronger
|
||||
classes).</li>
|
||||
|
||||
|
||||
<li>StringRef doesn't own or keep alive the underlying string bytes.
|
||||
As such it can easily lead to dangling pointers, and is not suitable for
|
||||
embedding in datastructures in most cases (instead, use an std::string or
|
||||
something like that).</li>
|
||||
|
||||
<li>For the same reason, StringRef cannot be used as the return value of a
|
||||
method if the method "computes" the result string. Instead, use
|
||||
std::string.</li>
|
||||
|
||||
<li>StringRef's do not allow you to mutate the pointed-to string bytes and it
|
||||
doesn't allow you to insert or remove bytes from the range. For editing
|
||||
operations like this, it interoperates with the <a
|
||||
href="#dss_twine">Twine</a> class.</li>
|
||||
</ol>
|
||||
|
||||
<p>Because of its strengths and limitations, it is very common for a function to
|
||||
take a StringRef and for a method on an object to return a StringRef that
|
||||
points into some string that it owns.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<h4>
|
||||
<a name="dss_twine">llvm/ADT/Twine.h</a>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
The Twine class is used as an intermediary datatype for APIs that want to take
|
||||
a string that can be constructed inline with a series of concatenations.
|
||||
Twine works by forming recursive instances of the Twine datatype (a simple
|
||||
value object) on the stack as temporary objects, linking them together into a
|
||||
tree which is then linearized when the Twine is consumed. Twine is only safe
|
||||
to use as the argument to a function, and should always be a const reference,
|
||||
e.g.:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
void foo(const Twine &T);
|
||||
...
|
||||
StringRef X = ...
|
||||
unsigned i = ...
|
||||
foo(X + "." + Twine(i));
|
||||
</pre>
|
||||
|
||||
<p>This example forms a string like "blarg.42" by concatenating the values
|
||||
together, and does not form intermediate strings containing "blarg" or
|
||||
"blarg.".
|
||||
</p>
|
||||
|
||||
<p>Because Twine is constructed with temporary objects on the stack, and
|
||||
because these instances are destroyed at the end of the current statement,
|
||||
it is an inherently dangerous API. For example, this simple variant contains
|
||||
undefined behavior and will probably crash:</p>
|
||||
|
||||
<pre>
|
||||
void foo(const Twine &T);
|
||||
...
|
||||
StringRef X = ...
|
||||
unsigned i = ...
|
||||
const Twine &Tmp = X + "." + Twine(i);
|
||||
foo(Tmp);
|
||||
</pre>
|
||||
|
||||
<p>... because the temporaries are destroyed before the call. That said,
|
||||
Twine's are much more efficient than intermediate std::string temporaries, and
|
||||
they work really well with StringRef. Just be aware of their limitations.</p>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<h4>
|
||||
<a name="dss_smallstring">llvm/ADT/SmallString.h</a>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
|
||||
<p>SmallString is a subclass of <a href="#dss_smallvector">SmallVector</a> that
|
||||
adds some convenience APIs like += that takes StringRef's. SmallString avoids
|
||||
allocating memory in the case when the preallocated space is enough to hold its
|
||||
data, and it calls back to general heap allocation when required. Since it owns
|
||||
its data, it is very safe to use and supports full mutation of the string.</p>
|
||||
|
||||
<p>Like SmallVector's, the big downside to SmallString is their sizeof. While
|
||||
they are optimized for small strings, they themselves are not particularly
|
||||
small. This means that they work great for temporary scratch buffers on the
|
||||
stack, but should not generally be put into the heap: it is very rare to
|
||||
see a SmallString as the member of a frequently-allocated heap data structure
|
||||
or returned by-value.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<h4>
|
||||
<a name="dss_stdstring">std::string</a>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
|
||||
<p>The standard C++ std::string class is a very general class that (like
|
||||
SmallString) owns its underlying data. sizeof(std::string) is very reasonable
|
||||
so it can be embedded into heap data structures and returned by-value.
|
||||
On the other hand, std::string is highly inefficient for inline editing (e.g.
|
||||
concatenating a bunch of stuff together) and because it is provided by the
|
||||
standard library, its performance characteristics depend a lot of the host
|
||||
standard library (e.g. libc++ and MSVC provide a highly optimized string
|
||||
class, GCC contains a really slow implementation).
|
||||
</p>
|
||||
|
||||
<p>The major disadvantage of std::string is that almost every operation that
|
||||
makes them larger can allocate memory, which is slow. As such, it is better
|
||||
to use SmallVector or Twine as a scratch buffer, but then use std::string to
|
||||
persist the result.</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!-- end of strings -->
|
||||
</div>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="ds_set">Set-Like Containers (std::set, SmallSet, SetVector, etc)</a>
|
||||
@ -1381,12 +1582,13 @@ elements out of (linear time), unless you use it's "pop_back" method, which is
|
||||
faster.
|
||||
</p>
|
||||
|
||||
<p>SetVector is an adapter class that defaults to using std::vector and std::set
|
||||
for the underlying containers, so it is quite expensive. However,
|
||||
<tt>"llvm/ADT/SetVector.h"</tt> also provides a SmallSetVector class, which
|
||||
defaults to using a SmallVector and SmallSet of a specified size. If you use
|
||||
this, and if your sets are dynamically smaller than N, you will save a lot of
|
||||
heap traffic.</p>
|
||||
<p><tt>SetVector</tt> is an adapter class that defaults to
|
||||
using <tt>std::vector</tt> and a size 16 <tt>SmallSet</tt> for the underlying
|
||||
containers, so it is quite expensive. However,
|
||||
<tt>"llvm/ADT/SetVector.h"</tt> also provides a <tt>SmallSetVector</tt>
|
||||
class, which defaults to using a <tt>SmallVector</tt> and <tt>SmallSet</tt>
|
||||
of a specified size. If you use this, and if your sets are dynamically
|
||||
smaller than <tt>N</tt>, you will save a lot of heap traffic.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -1634,20 +1836,6 @@ always better.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="ds_string">String-like containers</a>
|
||||
</h3>
|
||||
|
||||
<div>
|
||||
|
||||
<p>
|
||||
TODO: const char* vs stringref vs smallstring vs std::string. Describe twine,
|
||||
xref to #string_apis.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<h3>
|
||||
<a name="ds_bit">Bit storage containers (BitVector, SparseBitVector)</a>
|
||||
@ -3867,7 +4055,7 @@ arguments. An argument has a pointer to the parent Function.</p>
|
||||
<a href="mailto:dhurjati@cs.uiuc.edu">Dinakar Dhurjati</a> and
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-07-12 13:37:02 +0200 (Tue, 12 Jul 2011) $
|
||||
Last modified: $Date: 2011-10-11 08:33:56 +0200 (Tue, 11 Oct 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
File diff suppressed because it is too large
Load Diff
99
docs/SegmentedStacks.html
Normal file
99
docs/SegmentedStacks.html
Normal file
@ -0,0 +1,99 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Segmented Stacks in LLVM</title>
|
||||
<link rel="stylesheet" href="llvm.css" type="text/css">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Segmented Stacks in LLVM</h1>
|
||||
<div class="doc_author">
|
||||
<p>Written by <a href="mailto:sanjoy@playingwithpointers.com">Sanjoy Das</a></p>
|
||||
</div>
|
||||
|
||||
<ol>
|
||||
<li><a href="#intro">Introduction</a></li>
|
||||
<li><a href="#implementation">Implementation Details</a>
|
||||
<ol>
|
||||
<li><a href="#morestack">Allocating Stacklets</a></li>
|
||||
<li><a href="#alloca">Variable Sized Allocas</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><a href="#results">Results</a>
|
||||
<ol>
|
||||
<li><a href="#go">Go on LLVM</a></li>
|
||||
<li><a href="#abi">Runtime ABI</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<h2><a name="intro">Introduction</a></h2>
|
||||
<div>
|
||||
<p>
|
||||
Segmented stack allows stack space to be allocated incrementally than as a monolithic chunk (of some worst case size) at thread initialization. This is done by allocating stack blocks (henceforth called <em>stacklets</em>) and linking them into a doubly linked list. The function prologue is responsible for checking if the current stacklet has enough space for the function to execute; and if not, call into the libgcc runtime to allocate more stack space. Support for segmented stacks on x86 / Linux is currently being worked on.
|
||||
</p>
|
||||
<p>
|
||||
The runtime functionality is <a href="http://gcc.gnu.org/wiki/SplitStacks">already there in libgcc</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h2><a name="implementation">Implementation Details</a></h2>
|
||||
<div>
|
||||
<h3><a name="morestack">Allocating Stacklets</a></h3>
|
||||
<div>
|
||||
<p>
|
||||
As mentioned above, the function prologue checks if the current stacklet has enough space. The current approach is to use a slot in the TCB to store the current stack limit (minus the amount of space needed to allocate a new block) - this slot's offset is again dictated by <code>libgcc</code>. The generated assembly looks like this on x86-64:
|
||||
</p>
|
||||
<pre>
|
||||
leaq -8(%rsp), %r10
|
||||
cmpq %fs:112, %r10
|
||||
jg .LBB0_2
|
||||
|
||||
# More stack space needs to be allocated
|
||||
movabsq $8, %r10 # The amount of space needed
|
||||
movabsq $0, %r11 # The total size of arguments passed on stack
|
||||
callq __morestack
|
||||
ret # The reason for this extra return is explained below
|
||||
.LBB0_2:
|
||||
# Usual prologue continues here
|
||||
</pre>
|
||||
<p>
|
||||
The size of function arguments on the stack needs to be passed to <code> __morestack</code> (this function is implemented in <code>libgcc</code>) since that number of bytes has to be copied from the previous stacklet to the current one. This is so that SP (and FP) relative addressing of function arguments work as expected.
|
||||
</p>
|
||||
<p>
|
||||
The unusual <code>ret</code> is needed to have the function which made a call to <code>__morestack</code> return correctly. <code>__morestack</code>, instead of returning, calls into <code>.LBB0_2</code>. This is possible since both, the size of the <code>ret</code> instruction and the PC of call to <code>__morestack</code> are known. When the function body returns, control is transferred back to <code>__morestack</code>. <code>__morestack</code> then de-allocates the new stacklet, restores the correct SP value, and does a second return, which returns control to the correct caller.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h3><a name="alloca">Variable Sized Allocas</a></h3>
|
||||
<div>
|
||||
<p>
|
||||
The section on <a href="#morestack">allocating stacklets</a> automatically assumes that every stack frame will be of fixed size. However, LLVM allows the use of the <code>llvm.alloca</code> intrinsic to allocate dynamically sized blocks of memory on the stack. When faced with such a variable-sized alloca, code is generated to
|
||||
</p>
|
||||
<ul>
|
||||
<li>Check if the current stacklet has enough space. If yes, just bump the SP, like in the normal case.</li>
|
||||
<li>If not, generate a call to <code>libgcc</code>, which allocates the memory from the heap.</li>
|
||||
</ul>
|
||||
<p>
|
||||
The memory allocated from the heap is linked into a list in the current stacklet, and freed along with the same. This prevents a memory leak.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<address>
|
||||
<a href="http://jigsaw.w3.org/css-validator/check/referer">
|
||||
<img src="http://jigsaw.w3.org/css-validator/images/vcss-blue" alt="Valid CSS">
|
||||
</a>
|
||||
<a href="http://validator.w3.org/check/referer">
|
||||
<img src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01">
|
||||
</a>
|
||||
<a href="mailto:sanjoy@playingwithpointers.com">Sanjoy Das</a><br>
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date$
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -298,8 +298,8 @@ height="369">
|
||||
of tags are loosely bound to the tag values of DWARF information entries.
|
||||
However, that does not restrict the use of the information supplied to DWARF
|
||||
targets. To facilitate versioning of debug information, the tag is augmented
|
||||
with the current debug version (LLVMDebugVersion = 8 << 16 or 0x80000 or
|
||||
524288.)</a></p>
|
||||
with the current debug version (LLVMDebugVersion = 8 << 16 or
|
||||
0x80000 or 524288.)</a></p>
|
||||
|
||||
<p>The details of the various descriptors follow.</p>
|
||||
|
||||
@ -324,6 +324,10 @@ height="369">
|
||||
i1, ;; True if this is optimized.
|
||||
metadata, ;; Flags
|
||||
i32 ;; Runtime version
|
||||
metadata ;; List of enums types
|
||||
metadata ;; List of retained types
|
||||
metadata ;; List of subprograms
|
||||
metadata ;; List of global variables
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -337,7 +341,8 @@ height="369">
|
||||
<p>Compile unit descriptors provide the root context for objects declared in a
|
||||
specific compilation unit. File descriptors are defined using this context.
|
||||
These descriptors are collected by a named metadata
|
||||
<tt>!llvm.dbg.cu</tt>.
|
||||
<tt>!llvm.dbg.cu</tt>. Compile unit descriptor keeps track of subprograms,
|
||||
global variables and type information.
|
||||
|
||||
</div>
|
||||
|
||||
@ -355,7 +360,7 @@ height="369">
|
||||
;; (DW_TAG_file_type)
|
||||
metadata, ;; Source file name
|
||||
metadata, ;; Source file directory (includes trailing slash)
|
||||
metadata ;; Reference to compile unit where defined
|
||||
metadata ;; Unused
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -365,8 +370,7 @@ height="369">
|
||||
provide context for source line correspondence. </p>
|
||||
|
||||
<p>Each input file is encoded as a separate file descriptor in LLVM debugging
|
||||
information output. Each file descriptor would be defined using a
|
||||
compile unit. </p>
|
||||
information output. </p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -434,6 +438,7 @@ global variables are collected by named metadata <tt>!llvm.dbg.gv</tt>.</p>
|
||||
Function *,;; Pointer to LLVM function
|
||||
metadata, ;; Lists function template parameters
|
||||
metadata ;; Function declaration descriptor
|
||||
metadata ;; List of function variables
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -467,10 +472,23 @@ global variables are collected by named metadata <tt>!llvm.dbg.gv</tt>.</p>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>These descriptors provide debug information about nested blocks within a
|
||||
<p>This descriptor provides debug information about nested blocks within a
|
||||
subprogram. The line number and column numbers are used to dinstinguish
|
||||
two lexical blocks at same depth. </p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
!3 = metadata !{
|
||||
i32, ;; Tag = 11 + <a href="#LLVMDebugVersion">LLVMDebugVersion</a> (DW_TAG_lexical_block)
|
||||
metadata ;; Reference to the scope we're annotating with a file change
|
||||
metadata,;; Reference to the file the scope is enclosed in.
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>This descriptor provides a wrapper around a lexical scope to handle file
|
||||
changes in the middle of a lexical block.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
@ -485,7 +503,7 @@ global variables are collected by named metadata <tt>!llvm.dbg.gv</tt>.</p>
|
||||
!4 = metadata !{
|
||||
i32, ;; Tag = 36 + <a href="#LLVMDebugVersion">LLVMDebugVersion</a>
|
||||
;; (DW_TAG_base_type)
|
||||
metadata, ;; Reference to context (typically a compile unit)
|
||||
metadata, ;; Reference to context
|
||||
metadata, ;; Name (may be "" for anonymous types)
|
||||
metadata, ;; Reference to file where defined (may be NULL)
|
||||
i32, ;; Line number where defined (may be 0)
|
||||
@ -500,7 +518,7 @@ global variables are collected by named metadata <tt>!llvm.dbg.gv</tt>.</p>
|
||||
|
||||
<p>These descriptors define primitive types used in the code. Example int, bool
|
||||
and float. The context provides the scope of the type, which is usually the
|
||||
top level. Since basic types are not usually user defined the compile unit
|
||||
top level. Since basic types are not usually user defined the context
|
||||
and line number can be left as NULL and 0. The size, alignment and offset
|
||||
are expressed in bits and can be 64 bit values. The alignment is used to
|
||||
round the offset when embedded in a
|
||||
@ -585,7 +603,7 @@ DW_TAG_restrict_type = 55
|
||||
the <a href="#format_derived_type">derived type</a>. </p>
|
||||
|
||||
<p><a href="#format_derived_type">Derived type</a> location can be determined
|
||||
from the compile unit and line number. The size, alignment and offset are
|
||||
from the context and line number. The size, alignment and offset are
|
||||
expressed in bits and can be 64 bit values. The alignment is used to round
|
||||
the offset when embedded in a <a href="#format_composite_type">composite
|
||||
type</a> (example to keep float doubles on 64 bit boundaries.) The offset is
|
||||
@ -675,7 +693,7 @@ DW_TAG_inheritance = 28
|
||||
the formal arguments to the subroutine.</p>
|
||||
|
||||
<p><a href="#format_composite_type">Composite type</a> location can be
|
||||
determined from the compile unit and line number. The size, alignment and
|
||||
determined from the context and line number. The size, alignment and
|
||||
offset are expressed in bits and can be 64 bit values. The alignment is used
|
||||
to round the offset when embedded in
|
||||
a <a href="#format_composite_type">composite type</a> (as an example, to keep
|
||||
@ -750,7 +768,9 @@ DW_TAG_inheritance = 28
|
||||
metadata, ;; Reference to file where defined
|
||||
i32, ;; 24 bit - Line number where defined
|
||||
;; 8 bit - Argument number. 1 indicates 1st argument.
|
||||
metadata ;; Type descriptor
|
||||
metadata, ;; Type descriptor
|
||||
i32, ;; flags
|
||||
metadata ;; (optional) Reference to inline location
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -772,7 +792,7 @@ DW_TAG_return_variable = 258
|
||||
has no source correspondent.</p>
|
||||
|
||||
<p>The context is either the subprogram or block where the variable is defined.
|
||||
Name the source variable name. Compile unit and line indicate where the
|
||||
Name the source variable name. Context and line indicate where the
|
||||
variable was defined. Type descriptor defines the declared type of the
|
||||
variable.</p>
|
||||
|
||||
@ -1794,7 +1814,7 @@ enum Trees {
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-05-31 20:06:14 +0200 (Tue, 31 May 2011) $
|
||||
Last modified: $Date: 2011-10-12 00:59:11 +0200 (Wed, 12 Oct 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -911,7 +911,7 @@ This should highlight the APIs in <tt>TableGen/Record.h</tt>.</p>
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-10-07 20:25:05 +0200 (Fri, 07 Oct 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -227,11 +227,13 @@ the pass itself.</p>
|
||||
<p>Now that we have a way to compile our new pass, we just have to write it.
|
||||
Start out with:</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
<b>#include</b> "<a href="http://llvm.org/doxygen/Pass_8h-source.html">llvm/Pass.h</a>"
|
||||
<b>#include</b> "<a href="http://llvm.org/doxygen/Function_8h-source.html">llvm/Function.h</a>"
|
||||
<b>#include</b> "<a href="http://llvm.org/doxygen/raw__ostream_8h.html">llvm/Support/raw_ostream.h</a>"
|
||||
</pre></div>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>Which are needed because we are writing a <tt><a
|
||||
href="http://llvm.org/doxygen/classllvm_1_1Pass.html">Pass</a></tt>,
|
||||
@ -240,53 +242,66 @@ href="http://llvm.org/doxygen/classllvm_1_1Function.html">Function</a></tt>'s,
|
||||
and we will be doing some printing.</p>
|
||||
|
||||
<p>Next we have:</p>
|
||||
<div class="doc_code"><pre>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
<b>using namespace llvm;</b>
|
||||
</pre></div>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>... which is required because the functions from the include files
|
||||
live in the llvm namespace.
|
||||
</p>
|
||||
live in the llvm namespace.</p>
|
||||
|
||||
<p>Next we have:</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
<b>namespace</b> {
|
||||
</pre></div>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>... which starts out an anonymous namespace. Anonymous namespaces are to C++
|
||||
what the "<tt>static</tt>" keyword is to C (at global scope). It makes the
|
||||
things declared inside of the anonymous namespace only visible to the current
|
||||
things declared inside of the anonymous namespace visible only to the current
|
||||
file. If you're not familiar with them, consult a decent C++ book for more
|
||||
information.</p>
|
||||
|
||||
<p>Next, we declare our pass itself:</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
<b>struct</b> Hello : <b>public</b> <a href="#FunctionPass">FunctionPass</a> {
|
||||
</pre></div><p>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>This declares a "<tt>Hello</tt>" class that is a subclass of <tt><a
|
||||
href="http://llvm.org/doxygen/classllvm_1_1FunctionPass.html">FunctionPass</a></tt>.
|
||||
The different builtin pass subclasses are described in detail <a
|
||||
href="#passtype">later</a>, but for now, know that <a
|
||||
href="#FunctionPass"><tt>FunctionPass</tt></a>'s operate a function at a
|
||||
href="#FunctionPass"><tt>FunctionPass</tt></a>'s operate on a function at a
|
||||
time.</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
static char ID;
|
||||
Hello() : FunctionPass(ID) {}
|
||||
</pre></div><p>
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
static char ID;
|
||||
Hello() : FunctionPass(ID) {}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p> This declares pass identifier used by LLVM to identify pass. This allows LLVM to
|
||||
avoid using expensive C++ runtime information.</p>
|
||||
<p>This declares pass identifier used by LLVM to identify pass. This allows LLVM
|
||||
to avoid using expensive C++ runtime information.</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
<b>virtual bool</b> <a href="#runOnFunction">runOnFunction</a>(Function &F) {
|
||||
errs() << "<i>Hello: </i>" << F.getName() << "\n";
|
||||
errs() << "<i>Hello: </i>";
|
||||
errs().write_escaped(F.getName()) << "\n";
|
||||
<b>return false</b>;
|
||||
}
|
||||
}; <i>// end of struct Hello</i>
|
||||
</pre></div>
|
||||
} <i>// end of anonymous namespace</i>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>We declare a "<a href="#runOnFunction"><tt>runOnFunction</tt></a>" method,
|
||||
which overloads an abstract virtual method inherited from <a
|
||||
@ -294,31 +309,34 @@ href="#FunctionPass"><tt>FunctionPass</tt></a>. This is where we are supposed
|
||||
to do our thing, so we just print out our message with the name of each
|
||||
function.</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
char Hello::ID = 0;
|
||||
</pre></div>
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
char Hello::ID = 0;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p> We initialize pass ID here. LLVM uses ID's address to identify pass so
|
||||
<p>We initialize pass ID here. LLVM uses ID's address to identify a pass, so
|
||||
initialization value is not important.</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
static RegisterPass<Hello> X("<i>hello</i>", "<i>Hello World Pass</i>",
|
||||
false /* Only looks at CFG */,
|
||||
false /* Analysis Pass */);
|
||||
} <i>// end of anonymous namespace</i>
|
||||
</pre></div>
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
static RegisterPass<Hello> X("<i>hello</i>", "<i>Hello World Pass</i>",
|
||||
false /* Only looks at CFG */,
|
||||
false /* Analysis Pass */);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>Lastly, we <a href="#registration">register our class</a> <tt>Hello</tt>,
|
||||
giving it a command line
|
||||
argument "<tt>hello</tt>", and a name "<tt>Hello World Pass</tt>".
|
||||
Last two arguments describe its behavior.
|
||||
If a pass walks CFG without modifying it then third argument is set to true.
|
||||
If a pass is an analysis pass, for example dominator tree pass, then true
|
||||
is supplied as fourth argument. </p>
|
||||
<p>Lastly, we <a href="#registration">register our class</a> <tt>Hello</tt>,
|
||||
giving it a command line argument "<tt>hello</tt>", and a name "<tt>Hello World
|
||||
Pass</tt>". The last two arguments describe its behavior: if a pass walks CFG
|
||||
without modifying it then the third argument is set to <tt>true</tt>; if a pass
|
||||
is an analysis pass, for example dominator tree pass, then <tt>true</tt> is
|
||||
supplied as the fourth argument.</p>
|
||||
|
||||
<p>As a whole, the <tt>.cpp</tt> file looks like:</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
<b>#include</b> "<a href="http://llvm.org/doxygen/Pass_8h-source.html">llvm/Pass.h</a>"
|
||||
<b>#include</b> "<a href="http://llvm.org/doxygen/Function_8h-source.html">llvm/Function.h</a>"
|
||||
<b>#include</b> "<a href="http://llvm.org/doxygen/raw__ostream_8h.html">llvm/Support/raw_ostream.h</a>"
|
||||
@ -332,24 +350,26 @@ is supplied as fourth argument. </p>
|
||||
Hello() : FunctionPass(ID) {}
|
||||
|
||||
<b>virtual bool</b> <a href="#runOnFunction">runOnFunction</a>(Function &F) {
|
||||
errs() << "<i>Hello: </i>" << F.getName() << "\n";
|
||||
errs() << "<i>Hello: </i>";
|
||||
errs().write_escaped(F.getName()) << '\n';
|
||||
<b>return false</b>;
|
||||
}
|
||||
};
|
||||
|
||||
char Hello::ID = 0;
|
||||
static RegisterPass<Hello> X("hello", "Hello World Pass", false, false);
|
||||
}
|
||||
|
||||
</pre></div>
|
||||
};
|
||||
}
|
||||
|
||||
char Hello::ID = 0;
|
||||
static RegisterPass<Hello> X("hello", "Hello World Pass", false, false);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>Now that it's all together, compile the file with a simple "<tt>gmake</tt>"
|
||||
command in the local directory and you should get a new file
|
||||
"<tt>Debug+Asserts/lib/Hello.so</tt>" under the top level directory of the LLVM
|
||||
source tree (not in the local directory). Note that everything in this file is
|
||||
contained in an anonymous namespace: this reflects the fact that passes are self
|
||||
contained units that do not need external interfaces (although they can have
|
||||
them) to be useful.</p>
|
||||
contained in an anonymous namespace — this reflects the fact that passes
|
||||
are self contained units that do not need external interfaces (although they can
|
||||
have them) to be useful.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -1929,7 +1949,7 @@ Despite that, we have kept the LLVM passes SMP ready, and you should too.</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: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-10-11 09:03:52 +0200 (Tue, 11 Oct 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
1465
docs/doxygen.cfg.in
1465
docs/doxygen.cfg.in
File diff suppressed because it is too large
Load Diff
@ -63,6 +63,11 @@ Discusses how to get up and running quickly with the LLVM infrastructure.
|
||||
Everything from unpacking and compilation of the distribution to execution of
|
||||
some tools.</li>
|
||||
|
||||
<li><a href="CMake.html">LLVM CMake guide</a> - An addendum to the main Getting
|
||||
Started guide for those using the <a href="http://www.cmake.org/">CMake build
|
||||
system</a>.
|
||||
</li>
|
||||
|
||||
<li><a href="GettingStartedVS.html">Getting Started with the LLVM System using
|
||||
Microsoft Visual Studio</a> - An addendum to the main Getting Started guide for
|
||||
those using Visual Studio on Windows.</li>
|
||||
@ -87,7 +92,6 @@ Current tools:
|
||||
<a href="/cmds/opt.html">opt</a>,
|
||||
<a href="/cmds/llc.html">llc</a>,
|
||||
<a href="/cmds/lli.html">lli</a>,
|
||||
<a href="/cmds/llvmc.html">llvmc</a>
|
||||
<a href="/cmds/llvmgcc.html">llvm-gcc</a>,
|
||||
<a href="/cmds/llvmgxx.html">llvm-g++</a>,
|
||||
<a href="/cmds/bugpoint.html">bugpoint</a>,
|
||||
@ -216,14 +220,6 @@ in LLVM.</li>
|
||||
<li><a href="Bugpoint.html">Bugpoint</a> - automatic bug finder and test-case
|
||||
reducer description and usage information.</li>
|
||||
|
||||
<li><a href="CompilerDriverTutorial.html">Compiler Driver (llvmc) Tutorial</a>
|
||||
- This document is a tutorial introduction to the usage and
|
||||
configuration of the LLVM compiler driver tool, <tt>llvmc</tt>.</li>
|
||||
|
||||
<li><a href="CompilerDriver.html">Compiler Driver (llvmc)
|
||||
Reference</a> - This document describes the design and configuration
|
||||
of <tt>llvmc</tt> in more detail.</li>
|
||||
|
||||
<li><a href="BitCodeFormat.html">LLVM Bitcode File Format</a> - This describes
|
||||
the file format and encoding used for LLVM "bc" files.</li>
|
||||
|
||||
@ -289,7 +285,7 @@ times each day, making it a high volume list.</li>
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
|
||||
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-07-06 20:31:02 +0200 (Wed, 06 Jul 2011) $
|
||||
Last modified: $Date: 2011-10-11 18:35:07 +0200 (Tue, 11 Oct 2011) $
|
||||
</address>
|
||||
</body></html>
|
||||
|
||||
|
@ -70,6 +70,14 @@ h4, .doc_subsubsection { margin: 2.0em 0.5em 0.5em 0.5em;
|
||||
display: table;
|
||||
}
|
||||
|
||||
blockquote pre {
|
||||
padding: 1em 2em 1em 1em;
|
||||
border: solid 1px gray;
|
||||
background: #eeeeee;
|
||||
margin: 0 1em 0 1em;
|
||||
display: table;
|
||||
}
|
||||
|
||||
h2+div, h2+p {text-align: left; padding-left: 20pt; padding-right: 10pt;}
|
||||
h3+div, h3+p {text-align: left; padding-left: 20pt; padding-right: 10pt;}
|
||||
h4+div, h4+p {text-align: left; padding-left: 20pt; padding-right: 10pt;}
|
||||
|
@ -801,10 +801,10 @@ course.) To build this, just compile with:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
# Compile
|
||||
g++ -g -O3 toy.cpp
|
||||
# Run
|
||||
./a.out
|
||||
# Compile
|
||||
clang++ -g -O3 toy.cpp
|
||||
# Run
|
||||
./a.out
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -1225,7 +1225,7 @@ int main() {
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-10-16 10:07:38 +0200 (Sun, 16 Oct 2011) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -266,7 +266,7 @@ Value *CallExprAST::Codegen() {
|
||||
if (ArgsV.back() == 0) return 0;
|
||||
}
|
||||
|
||||
return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
|
||||
return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -308,11 +308,11 @@ bodies and external function declarations. The code starts with:</p>
|
||||
<pre>
|
||||
Function *PrototypeAST::Codegen() {
|
||||
// Make the function type: double(double,double) etc.
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
std::vector<Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
|
||||
Doubles, false);
|
||||
|
||||
|
||||
Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule);
|
||||
</pre>
|
||||
</div>
|
||||
@ -532,9 +532,9 @@ functions. For example:
|
||||
<pre>
|
||||
ready> <b>4+5</b>;
|
||||
Read top-level expression:
|
||||
define double @""() {
|
||||
define double @0() {
|
||||
entry:
|
||||
ret double 9.000000e+00
|
||||
ret double 9.000000e+00
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -553,13 +553,13 @@ ready> <b>def foo(a b) a*a + 2*a*b + b*b;</b>
|
||||
Read function definition:
|
||||
define double @foo(double %a, double %b) {
|
||||
entry:
|
||||
%multmp = fmul double %a, %a
|
||||
%multmp1 = fmul double 2.000000e+00, %a
|
||||
%multmp2 = fmul double %multmp1, %b
|
||||
%addtmp = fadd double %multmp, %multmp2
|
||||
%multmp3 = fmul double %b, %b
|
||||
%addtmp4 = fadd double %addtmp, %multmp3
|
||||
ret double %addtmp4
|
||||
%multmp = fmul double %a, %a
|
||||
%multmp1 = fmul double 2.000000e+00, %a
|
||||
%multmp2 = fmul double %multmp1, %b
|
||||
%addtmp = fadd double %multmp, %multmp2
|
||||
%multmp3 = fmul double %b, %b
|
||||
%addtmp4 = fadd double %addtmp, %multmp3
|
||||
ret double %addtmp4
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -573,10 +573,10 @@ ready> <b>def bar(a) foo(a, 4.0) + bar(31337);</b>
|
||||
Read function definition:
|
||||
define double @bar(double %a) {
|
||||
entry:
|
||||
%calltmp = call double @foo(double %a, double 4.000000e+00)
|
||||
%calltmp1 = call double @bar(double 3.133700e+04)
|
||||
%addtmp = fadd double %calltmp, %calltmp1
|
||||
ret double %addtmp
|
||||
%calltmp = call double @foo(double %a, double 4.000000e+00)
|
||||
%calltmp1 = call double @bar(double 3.133700e+04)
|
||||
%addtmp = fadd double %calltmp, %calltmp1
|
||||
ret double %addtmp
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -593,10 +593,10 @@ declare double @cos(double)
|
||||
|
||||
ready> <b>cos(1.234);</b>
|
||||
Read top-level expression:
|
||||
define double @""() {
|
||||
define double @1() {
|
||||
entry:
|
||||
%calltmp = call double @cos(double 1.234000e+00)
|
||||
ret double %calltmp
|
||||
%calltmp = call double @cos(double 1.234000e+00)
|
||||
ret double %calltmp
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -609,37 +609,37 @@ entry:
|
||||
ready> <b>^D</b>
|
||||
; ModuleID = 'my cool jit'
|
||||
|
||||
define double @""() {
|
||||
define double @0() {
|
||||
entry:
|
||||
%addtmp = fadd double 4.000000e+00, 5.000000e+00
|
||||
ret double %addtmp
|
||||
%addtmp = fadd double 4.000000e+00, 5.000000e+00
|
||||
ret double %addtmp
|
||||
}
|
||||
|
||||
define double @foo(double %a, double %b) {
|
||||
entry:
|
||||
%multmp = fmul double %a, %a
|
||||
%multmp1 = fmul double 2.000000e+00, %a
|
||||
%multmp2 = fmul double %multmp1, %b
|
||||
%addtmp = fadd double %multmp, %multmp2
|
||||
%multmp3 = fmul double %b, %b
|
||||
%addtmp4 = fadd double %addtmp, %multmp3
|
||||
ret double %addtmp4
|
||||
%multmp = fmul double %a, %a
|
||||
%multmp1 = fmul double 2.000000e+00, %a
|
||||
%multmp2 = fmul double %multmp1, %b
|
||||
%addtmp = fadd double %multmp, %multmp2
|
||||
%multmp3 = fmul double %b, %b
|
||||
%addtmp4 = fadd double %addtmp, %multmp3
|
||||
ret double %addtmp4
|
||||
}
|
||||
|
||||
define double @bar(double %a) {
|
||||
entry:
|
||||
%calltmp = call double @foo(double %a, double 4.000000e+00)
|
||||
%calltmp1 = call double @bar(double 3.133700e+04)
|
||||
%addtmp = fadd double %calltmp, %calltmp1
|
||||
ret double %addtmp
|
||||
%calltmp = call double @foo(double %a, double 4.000000e+00)
|
||||
%calltmp1 = call double @bar(double 3.133700e+04)
|
||||
%addtmp = fadd double %calltmp, %calltmp1
|
||||
ret double %addtmp
|
||||
}
|
||||
|
||||
declare double @cos(double)
|
||||
|
||||
define double @""() {
|
||||
define double @1() {
|
||||
entry:
|
||||
%calltmp = call double @cos(double 1.234000e+00)
|
||||
ret double %calltmp
|
||||
%calltmp = call double @cos(double 1.234000e+00)
|
||||
ret double %calltmp
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -670,10 +670,10 @@ our makefile/command line about which options to use:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
# Compile
|
||||
g++ -g -O3 toy.cpp `llvm-config --cppflags --ldflags --libs core` -o toy
|
||||
# Run
|
||||
./toy
|
||||
# Compile
|
||||
clang++ -g -O3 toy.cpp `llvm-config --cppflags --ldflags --libs core` -o toy
|
||||
# Run
|
||||
./toy
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -1081,13 +1081,13 @@ Value *CallExprAST::Codegen() {
|
||||
if (ArgsV.back() == 0) return 0;
|
||||
}
|
||||
|
||||
return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
|
||||
return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
|
||||
}
|
||||
|
||||
Function *PrototypeAST::Codegen() {
|
||||
// Make the function type: double(double,double) etc.
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
std::vector<Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
|
||||
Doubles, false);
|
||||
|
||||
@ -1262,7 +1262,7 @@ int main() {
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-10-16 10:07:38 +0200 (Sun, 16 Oct 2011) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -343,9 +343,10 @@ code that is statically linked into your application.</p>
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
ready> <b>4+5;</b>
|
||||
define double @""() {
|
||||
Read top-level expression:
|
||||
define double @0() {
|
||||
entry:
|
||||
ret double 9.000000e+00
|
||||
ret double 9.000000e+00
|
||||
}
|
||||
|
||||
<em>Evaluated to 9.000000</em>
|
||||
@ -363,16 +364,17 @@ ready> <b>def testfunc(x y) x + y*2; </b>
|
||||
Read function definition:
|
||||
define double @testfunc(double %x, double %y) {
|
||||
entry:
|
||||
%multmp = fmul double %y, 2.000000e+00
|
||||
%addtmp = fadd double %multmp, %x
|
||||
ret double %addtmp
|
||||
%multmp = fmul double %y, 2.000000e+00
|
||||
%addtmp = fadd double %multmp, %x
|
||||
ret double %addtmp
|
||||
}
|
||||
|
||||
ready> <b>testfunc(4, 10);</b>
|
||||
define double @""() {
|
||||
Read top-level expression:
|
||||
define double @1() {
|
||||
entry:
|
||||
%calltmp = call double @testfunc(double 4.000000e+00, double 1.000000e+01)
|
||||
ret double %calltmp
|
||||
%calltmp = call double @testfunc(double 4.000000e+00, double 1.000000e+01)
|
||||
ret double %calltmp
|
||||
}
|
||||
|
||||
<em>Evaluated to 24.000000</em>
|
||||
@ -404,21 +406,34 @@ Read extern:
|
||||
declare double @cos(double)
|
||||
|
||||
ready> <b>sin(1.0);</b>
|
||||
Read top-level expression:
|
||||
define double @2() {
|
||||
entry:
|
||||
ret double 0x3FEAED548F090CEE
|
||||
}
|
||||
|
||||
<em>Evaluated to 0.841471</em>
|
||||
|
||||
ready> <b>def foo(x) sin(x)*sin(x) + cos(x)*cos(x);</b>
|
||||
Read function definition:
|
||||
define double @foo(double %x) {
|
||||
entry:
|
||||
%calltmp = call double @sin(double %x)
|
||||
%multmp = fmul double %calltmp, %calltmp
|
||||
%calltmp2 = call double @cos(double %x)
|
||||
%multmp4 = fmul double %calltmp2, %calltmp2
|
||||
%addtmp = fadd double %multmp, %multmp4
|
||||
ret double %addtmp
|
||||
%calltmp = call double @sin(double %x)
|
||||
%multmp = fmul double %calltmp, %calltmp
|
||||
%calltmp2 = call double @cos(double %x)
|
||||
%multmp4 = fmul double %calltmp2, %calltmp2
|
||||
%addtmp = fadd double %multmp, %multmp4
|
||||
ret double %addtmp
|
||||
}
|
||||
|
||||
ready> <b>foo(4.0);</b>
|
||||
Read top-level expression:
|
||||
define double @3() {
|
||||
entry:
|
||||
%calltmp = call double @foo(double 4.000000e+00)
|
||||
ret double %calltmp
|
||||
}
|
||||
|
||||
<em>Evaluated to 1.000000</em>
|
||||
</pre>
|
||||
</div>
|
||||
@ -484,10 +499,10 @@ LLVM JIT and optimizer. To build this example, use:
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
# Compile
|
||||
g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
|
||||
# Run
|
||||
./toy
|
||||
# Compile
|
||||
clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
|
||||
# Run
|
||||
./toy
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -509,9 +524,9 @@ at runtime.</p>
|
||||
#include "llvm/Analysis/Verifier.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Support/IRBuilder.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <map>
|
||||
@ -905,13 +920,13 @@ Value *CallExprAST::Codegen() {
|
||||
if (ArgsV.back() == 0) return 0;
|
||||
}
|
||||
|
||||
return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
|
||||
return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
|
||||
}
|
||||
|
||||
Function *PrototypeAST::Codegen() {
|
||||
// Make the function type: double(double,double) etc.
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
std::vector<Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
|
||||
Doubles, false);
|
||||
|
||||
@ -1013,6 +1028,9 @@ static void HandleTopLevelExpression() {
|
||||
// Evaluate a top-level expression into an anonymous function.
|
||||
if (FunctionAST *F = ParseTopLevelExpr()) {
|
||||
if (Function *LF = F->Codegen()) {
|
||||
fprintf(stderr, "Read top-level expression:");
|
||||
LF->dump();
|
||||
|
||||
// JIT the function, returning a function pointer.
|
||||
void *FPtr = TheExecutionEngine->getPointerToFunction(LF);
|
||||
|
||||
@ -1076,7 +1094,7 @@ int main() {
|
||||
|
||||
// Create the JIT. This takes ownership of the module.
|
||||
std::string ErrStr;
|
||||
TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create();
|
||||
TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create();
|
||||
if (!TheExecutionEngine) {
|
||||
fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str());
|
||||
exit(1);
|
||||
@ -1129,7 +1147,7 @@ TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create();
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-10-16 10:07:38 +0200 (Sun, 16 Oct 2011) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -259,20 +259,20 @@ declare double @bar()
|
||||
|
||||
define double @baz(double %x) {
|
||||
entry:
|
||||
%ifcond = fcmp one double %x, 0.000000e+00
|
||||
br i1 %ifcond, label %then, label %else
|
||||
%ifcond = fcmp one double %x, 0.000000e+00
|
||||
br i1 %ifcond, label %then, label %else
|
||||
|
||||
then: ; preds = %entry
|
||||
%calltmp = call double @foo()
|
||||
br label %ifcont
|
||||
%calltmp = call double @foo()
|
||||
br label %ifcont
|
||||
|
||||
else: ; preds = %entry
|
||||
%calltmp1 = call double @bar()
|
||||
br label %ifcont
|
||||
%calltmp1 = call double @bar()
|
||||
br label %ifcont
|
||||
|
||||
ifcont: ; preds = %else, %then
|
||||
%iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ]
|
||||
ret double %iftmp
|
||||
%iftmp = phi double [ %calltmp, %then ], [ %calltmp1, %else ]
|
||||
ret double %iftmp
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -660,25 +660,25 @@ declare double @putchard(double)
|
||||
|
||||
define double @printstar(double %n) {
|
||||
entry:
|
||||
; initial value = 1.0 (inlined into phi)
|
||||
br label %loop
|
||||
; initial value = 1.0 (inlined into phi)
|
||||
br label %loop
|
||||
|
||||
loop: ; preds = %loop, %entry
|
||||
%i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ]
|
||||
; body
|
||||
%calltmp = call double @putchard(double 4.200000e+01)
|
||||
; increment
|
||||
%nextvar = fadd double %i, 1.000000e+00
|
||||
%i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ]
|
||||
; body
|
||||
%calltmp = call double @putchard(double 4.200000e+01)
|
||||
; increment
|
||||
%nextvar = fadd double %i, 1.000000e+00
|
||||
|
||||
; termination test
|
||||
%cmptmp = fcmp ult double %i, %n
|
||||
%booltmp = uitofp i1 %cmptmp to double
|
||||
%loopcond = fcmp one double %booltmp, 0.000000e+00
|
||||
br i1 %loopcond, label %loop, label %afterloop
|
||||
; termination test
|
||||
%cmptmp = fcmp ult double %i, %n
|
||||
%booltmp = uitofp i1 %cmptmp to double
|
||||
%loopcond = fcmp one double %booltmp, 0.000000e+00
|
||||
br i1 %loopcond, label %loop, label %afterloop
|
||||
|
||||
afterloop: ; preds = %loop
|
||||
; loop always returns 0.0
|
||||
ret double 0.000000e+00
|
||||
; loop always returns 0.0
|
||||
ret double 0.000000e+00
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -829,10 +829,11 @@ statement.</p>
|
||||
</div>
|
||||
|
||||
<p>With the code for the body of the loop complete, we just need to finish up
|
||||
the control flow for it. This code remembers the end block (for the phi node), then creates the block for the loop exit ("afterloop"). Based on the value of the
|
||||
exit condition, it creates a conditional branch that chooses between executing
|
||||
the loop again and exiting the loop. Any future code is emitted in the
|
||||
"afterloop" block, so it sets the insertion position to it.</p>
|
||||
the control flow for it. This code remembers the end block (for the phi node),
|
||||
then creates the block for the loop exit ("afterloop"). Based on the value of
|
||||
the exit condition, it creates a conditional branch that chooses between
|
||||
executing the loop again and exiting the loop. Any future code is emitted in
|
||||
the "afterloop" block, so it sets the insertion position to it.</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
@ -880,10 +881,10 @@ if/then/else and for expressions.. To build this example, use:
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
# Compile
|
||||
g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
|
||||
# Run
|
||||
./toy
|
||||
# Compile
|
||||
clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
|
||||
# Run
|
||||
./toy
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -900,9 +901,9 @@ if/then/else and for expressions.. To build this example, use:
|
||||
#include "llvm/Analysis/Verifier.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Support/IRBuilder.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <map>
|
||||
@ -1397,7 +1398,7 @@ Value *CallExprAST::Codegen() {
|
||||
if (ArgsV.back() == 0) return 0;
|
||||
}
|
||||
|
||||
return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
|
||||
return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
|
||||
}
|
||||
|
||||
Value *IfExprAST::Codegen() {
|
||||
@ -1546,8 +1547,8 @@ Value *ForExprAST::Codegen() {
|
||||
|
||||
Function *PrototypeAST::Codegen() {
|
||||
// Make the function type: double(double,double) etc.
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
std::vector<Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
|
||||
Doubles, false);
|
||||
|
||||
@ -1765,7 +1766,7 @@ int main() {
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-10-16 10:07:38 +0200 (Sun, 16 Oct 2011) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -293,8 +293,8 @@ Value *BinaryExprAST::Codegen() {
|
||||
Function *F = TheModule->getFunction(std::string("binary")+Op);
|
||||
assert(F && "binary operator not found!");
|
||||
|
||||
Value *Ops[] = { L, R };
|
||||
return Builder.CreateCall(F, Ops, Ops+2, "binop");</b>
|
||||
Value *Ops[2] = { L, R };
|
||||
return Builder.CreateCall(F, Ops, "binop");</b>
|
||||
}
|
||||
|
||||
</pre>
|
||||
@ -505,7 +505,9 @@ defined to print out the specified value and a newline):</p>
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
ready> <b>extern printd(x);</b>
|
||||
Read extern: declare double @printd(double)
|
||||
Read extern:
|
||||
declare double @printd(double)
|
||||
|
||||
ready> <b>def binary : 1 (x y) 0; # Low-precedence operator that ignores operands.</b>
|
||||
..
|
||||
ready> <b>printd(123) : printd(456) : printd(789);</b>
|
||||
@ -555,6 +557,9 @@ def binary& 6 (LHS RHS)
|
||||
def binary = 9 (LHS RHS)
|
||||
!(LHS < RHS | LHS > RHS);
|
||||
|
||||
# Define ':' for sequencing: as a low-precedence operator that ignores operands
|
||||
# and just returns the RHS.
|
||||
def binary : 1 (x y) y;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -579,9 +584,10 @@ def printdensity(d)
|
||||
else
|
||||
putchard(42); # '*'</b>
|
||||
...
|
||||
ready> <b>printdensity(1): printdensity(2): printdensity(3) :
|
||||
printdensity(4): printdensity(5): printdensity(9): putchard(10);</b>
|
||||
*++..
|
||||
ready> <b>printdensity(1): printdensity(2): printdensity(3):
|
||||
printdensity(4): printdensity(5): printdensity(9):
|
||||
putchard(10);</b>
|
||||
**++.
|
||||
Evaluated to 0.000000
|
||||
</pre>
|
||||
</div>
|
||||
@ -593,7 +599,7 @@ converge:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
# determine whether the specific location diverges.
|
||||
# Determine whether the specific location diverges.
|
||||
# Solve for z = z^2 + c in the complex plane.
|
||||
def mandleconverger(real imag iters creal cimag)
|
||||
if iters > 255 | (real*real + imag*imag > 4) then
|
||||
@ -603,25 +609,25 @@ def mandleconverger(real imag iters creal cimag)
|
||||
2*real*imag + cimag,
|
||||
iters+1, creal, cimag);
|
||||
|
||||
# return the number of iterations required for the iteration to escape
|
||||
# Return the number of iterations required for the iteration to escape
|
||||
def mandleconverge(real imag)
|
||||
mandleconverger(real, imag, 0, real, imag);
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>This "z = z<sup>2</sup> + c" function is a beautiful little creature that is the basis
|
||||
for computation of the <a
|
||||
href="http://en.wikipedia.org/wiki/Mandelbrot_set">Mandelbrot Set</a>. Our
|
||||
<tt>mandelconverge</tt> function returns the number of iterations that it takes
|
||||
for a complex orbit to escape, saturating to 255. This is not a very useful
|
||||
function by itself, but if you plot its value over a two-dimensional plane,
|
||||
you can see the Mandelbrot set. Given that we are limited to using putchard
|
||||
here, our amazing graphical output is limited, but we can whip together
|
||||
<p>This "<code>z = z<sup>2</sup> + c</code>" function is a beautiful little
|
||||
creature that is the basis for computation of
|
||||
the <a href="http://en.wikipedia.org/wiki/Mandelbrot_set">Mandelbrot Set</a>.
|
||||
Our <tt>mandelconverge</tt> function returns the number of iterations that it
|
||||
takes for a complex orbit to escape, saturating to 255. This is not a very
|
||||
useful function by itself, but if you plot its value over a two-dimensional
|
||||
plane, you can see the Mandelbrot set. Given that we are limited to using
|
||||
putchard here, our amazing graphical output is limited, but we can whip together
|
||||
something using the density plotter above:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
# compute and plot the mandlebrot set with the specified 2 dimensional range
|
||||
# Compute and plot the mandlebrot set with the specified 2 dimensional range
|
||||
# info.
|
||||
def mandelhelp(xmin xmax xstep ymin ymax ystep)
|
||||
for y = ymin, y < ymax, ystep in (
|
||||
@ -808,13 +814,19 @@ if/then/else and for expressions.. To build this example, use:
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
# Compile
|
||||
g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
|
||||
# Run
|
||||
./toy
|
||||
# Compile
|
||||
clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
|
||||
# Run
|
||||
./toy
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>On some platforms, you will need to specify -rdynamic or -Wl,--export-dynamic
|
||||
when linking. This ensures that symbols defined in the main executable are
|
||||
exported to the dynamic linker and so are available for symbol resolution at
|
||||
run time. This is not needed if you compile your support code into a shared
|
||||
library, although doing that will cause problems on Windows.</p>
|
||||
|
||||
<p>Here is the code:</p>
|
||||
|
||||
<div class="doc_code">
|
||||
@ -828,9 +840,9 @@ if/then/else and for expressions.. To build this example, use:
|
||||
#include "llvm/Analysis/Verifier.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Support/IRBuilder.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <map>
|
||||
@ -1409,8 +1421,8 @@ Value *BinaryExprAST::Codegen() {
|
||||
Function *F = TheModule->getFunction(std::string("binary")+Op);
|
||||
assert(F && "binary operator not found!");
|
||||
|
||||
Value *Ops[] = { L, R };
|
||||
return Builder.CreateCall(F, Ops, Ops+2, "binop");
|
||||
Value *Ops[2] = { L, R };
|
||||
return Builder.CreateCall(F, Ops, "binop");
|
||||
}
|
||||
|
||||
Value *CallExprAST::Codegen() {
|
||||
@ -1429,7 +1441,7 @@ Value *CallExprAST::Codegen() {
|
||||
if (ArgsV.back() == 0) return 0;
|
||||
}
|
||||
|
||||
return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
|
||||
return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
|
||||
}
|
||||
|
||||
Value *IfExprAST::Codegen() {
|
||||
@ -1578,8 +1590,8 @@ Value *ForExprAST::Codegen() {
|
||||
|
||||
Function *PrototypeAST::Codegen() {
|
||||
// Make the function type: double(double,double) etc.
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
std::vector<Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
|
||||
Doubles, false);
|
||||
|
||||
@ -1811,7 +1823,7 @@ int main() {
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-10-16 10:07:38 +0200 (Sun, 16 Oct 2011) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -102,19 +102,19 @@ The LLVM IR that we want for this example looks like this:</p>
|
||||
|
||||
define i32 @test(i1 %Condition) {
|
||||
entry:
|
||||
br i1 %Condition, label %cond_true, label %cond_false
|
||||
br i1 %Condition, label %cond_true, label %cond_false
|
||||
|
||||
cond_true:
|
||||
%X.0 = load i32* @G
|
||||
br label %cond_next
|
||||
%X.0 = load i32* @G
|
||||
br label %cond_next
|
||||
|
||||
cond_false:
|
||||
%X.1 = load i32* @H
|
||||
br label %cond_next
|
||||
%X.1 = load i32* @H
|
||||
br label %cond_next
|
||||
|
||||
cond_next:
|
||||
%X.2 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
|
||||
ret i32 %X.2
|
||||
%X.2 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
|
||||
ret i32 %X.2
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -174,12 +174,12 @@ being declared with global variable definitions, they are declared with the
|
||||
<pre>
|
||||
define i32 @example() {
|
||||
entry:
|
||||
%X = alloca i32 ; type of %X is i32*.
|
||||
...
|
||||
%tmp = load i32* %X ; load the stack value %X from the stack.
|
||||
%tmp2 = add i32 %tmp, 1 ; increment it
|
||||
store i32 %tmp2, i32* %X ; store it back
|
||||
...
|
||||
%X = alloca i32 ; type of %X is i32*.
|
||||
...
|
||||
%tmp = load i32* %X ; load the stack value %X from the stack.
|
||||
%tmp2 = add i32 %tmp, 1 ; increment it
|
||||
store i32 %tmp2, i32* %X ; store it back
|
||||
...
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -196,22 +196,22 @@ example to use the alloca technique to avoid using a PHI node:</p>
|
||||
|
||||
define i32 @test(i1 %Condition) {
|
||||
entry:
|
||||
%X = alloca i32 ; type of %X is i32*.
|
||||
br i1 %Condition, label %cond_true, label %cond_false
|
||||
%X = alloca i32 ; type of %X is i32*.
|
||||
br i1 %Condition, label %cond_true, label %cond_false
|
||||
|
||||
cond_true:
|
||||
%X.0 = load i32* @G
|
||||
store i32 %X.0, i32* %X ; Update X
|
||||
br label %cond_next
|
||||
%X.0 = load i32* @G
|
||||
store i32 %X.0, i32* %X ; Update X
|
||||
br label %cond_next
|
||||
|
||||
cond_false:
|
||||
%X.1 = load i32* @H
|
||||
store i32 %X.1, i32* %X ; Update X
|
||||
br label %cond_next
|
||||
%X.1 = load i32* @H
|
||||
store i32 %X.1, i32* %X ; Update X
|
||||
br label %cond_next
|
||||
|
||||
cond_next:
|
||||
%X.2 = load i32* %X ; Read X
|
||||
ret i32 %X.2
|
||||
%X.2 = load i32* %X ; Read X
|
||||
ret i32 %X.2
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -242,19 +242,19 @@ $ <b>llvm-as < example.ll | opt -mem2reg | llvm-dis</b>
|
||||
|
||||
define i32 @test(i1 %Condition) {
|
||||
entry:
|
||||
br i1 %Condition, label %cond_true, label %cond_false
|
||||
br i1 %Condition, label %cond_true, label %cond_false
|
||||
|
||||
cond_true:
|
||||
%X.0 = load i32* @G
|
||||
br label %cond_next
|
||||
%X.0 = load i32* @G
|
||||
br label %cond_next
|
||||
|
||||
cond_false:
|
||||
%X.1 = load i32* @H
|
||||
br label %cond_next
|
||||
%X.1 = load i32* @H
|
||||
br label %cond_next
|
||||
|
||||
cond_next:
|
||||
%X.01 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
|
||||
ret i32 %X.01
|
||||
%X.01 = phi i32 [ %X.1, %cond_false ], [ %X.0, %cond_true ]
|
||||
ret i32 %X.01
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -542,30 +542,30 @@ recursive fib function. Before the optimization:</p>
|
||||
<pre>
|
||||
define double @fib(double %x) {
|
||||
entry:
|
||||
<b>%x1 = alloca double
|
||||
store double %x, double* %x1
|
||||
%x2 = load double* %x1</b>
|
||||
%cmptmp = fcmp ult double %x2, 3.000000e+00
|
||||
%booltmp = uitofp i1 %cmptmp to double
|
||||
%ifcond = fcmp one double %booltmp, 0.000000e+00
|
||||
br i1 %ifcond, label %then, label %else
|
||||
<b>%x1 = alloca double
|
||||
store double %x, double* %x1
|
||||
%x2 = load double* %x1</b>
|
||||
%cmptmp = fcmp ult double %x2, 3.000000e+00
|
||||
%booltmp = uitofp i1 %cmptmp to double
|
||||
%ifcond = fcmp one double %booltmp, 0.000000e+00
|
||||
br i1 %ifcond, label %then, label %else
|
||||
|
||||
then: ; preds = %entry
|
||||
br label %ifcont
|
||||
br label %ifcont
|
||||
|
||||
else: ; preds = %entry
|
||||
<b>%x3 = load double* %x1</b>
|
||||
%subtmp = fsub double %x3, 1.000000e+00
|
||||
%calltmp = call double @fib(double %subtmp)
|
||||
<b>%x4 = load double* %x1</b>
|
||||
%subtmp5 = fsub double %x4, 2.000000e+00
|
||||
%calltmp6 = call double @fib(double %subtmp5)
|
||||
%addtmp = fadd double %calltmp, %calltmp6
|
||||
br label %ifcont
|
||||
<b>%x3 = load double* %x1</b>
|
||||
%subtmp = fsub double %x3, 1.000000e+00
|
||||
%calltmp = call double @fib(double %subtmp)
|
||||
<b>%x4 = load double* %x1</b>
|
||||
%subtmp5 = fsub double %x4, 2.000000e+00
|
||||
%calltmp6 = call double @fib(double %subtmp5)
|
||||
%addtmp = fadd double %calltmp, %calltmp6
|
||||
br label %ifcont
|
||||
|
||||
ifcont: ; preds = %else, %then
|
||||
%iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
|
||||
ret double %iftmp
|
||||
%iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
|
||||
ret double %iftmp
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -584,25 +584,25 @@ PHI node for it, so we still just make the PHI.</p>
|
||||
<pre>
|
||||
define double @fib(double %x) {
|
||||
entry:
|
||||
%cmptmp = fcmp ult double <b>%x</b>, 3.000000e+00
|
||||
%booltmp = uitofp i1 %cmptmp to double
|
||||
%ifcond = fcmp one double %booltmp, 0.000000e+00
|
||||
br i1 %ifcond, label %then, label %else
|
||||
%cmptmp = fcmp ult double <b>%x</b>, 3.000000e+00
|
||||
%booltmp = uitofp i1 %cmptmp to double
|
||||
%ifcond = fcmp one double %booltmp, 0.000000e+00
|
||||
br i1 %ifcond, label %then, label %else
|
||||
|
||||
then:
|
||||
br label %ifcont
|
||||
br label %ifcont
|
||||
|
||||
else:
|
||||
%subtmp = fsub double <b>%x</b>, 1.000000e+00
|
||||
%calltmp = call double @fib(double %subtmp)
|
||||
%subtmp5 = fsub double <b>%x</b>, 2.000000e+00
|
||||
%calltmp6 = call double @fib(double %subtmp5)
|
||||
%addtmp = fadd double %calltmp, %calltmp6
|
||||
br label %ifcont
|
||||
%subtmp = fsub double <b>%x</b>, 1.000000e+00
|
||||
%calltmp = call double @fib(double %subtmp)
|
||||
%subtmp5 = fsub double <b>%x</b>, 2.000000e+00
|
||||
%calltmp6 = call double @fib(double %subtmp5)
|
||||
%addtmp = fadd double %calltmp, %calltmp6
|
||||
br label %ifcont
|
||||
|
||||
ifcont: ; preds = %else, %then
|
||||
%iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
|
||||
ret double %iftmp
|
||||
%iftmp = phi double [ 1.000000e+00, %then ], [ %addtmp, %else ]
|
||||
ret double %iftmp
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -617,21 +617,21 @@ such blatent inefficiencies :).</p>
|
||||
<pre>
|
||||
define double @fib(double %x) {
|
||||
entry:
|
||||
%cmptmp = fcmp ult double %x, 3.000000e+00
|
||||
%booltmp = uitofp i1 %cmptmp to double
|
||||
%ifcond = fcmp ueq double %booltmp, 0.000000e+00
|
||||
br i1 %ifcond, label %else, label %ifcont
|
||||
%cmptmp = fcmp ult double %x, 3.000000e+00
|
||||
%booltmp = uitofp i1 %cmptmp to double
|
||||
%ifcond = fcmp ueq double %booltmp, 0.000000e+00
|
||||
br i1 %ifcond, label %else, label %ifcont
|
||||
|
||||
else:
|
||||
%subtmp = fsub double %x, 1.000000e+00
|
||||
%calltmp = call double @fib(double %subtmp)
|
||||
%subtmp5 = fsub double %x, 2.000000e+00
|
||||
%calltmp6 = call double @fib(double %subtmp5)
|
||||
%addtmp = fadd double %calltmp, %calltmp6
|
||||
ret double %addtmp
|
||||
%subtmp = fsub double %x, 1.000000e+00
|
||||
%calltmp = call double @fib(double %subtmp)
|
||||
%subtmp5 = fsub double %x, 2.000000e+00
|
||||
%calltmp6 = call double @fib(double %subtmp5)
|
||||
%addtmp = fadd double %calltmp, %calltmp6
|
||||
ret double %addtmp
|
||||
|
||||
ifcont:
|
||||
ret double 1.000000e+00
|
||||
ret double 1.000000e+00
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -988,10 +988,10 @@ variables and var/in support. To build this example, use:
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
# Compile
|
||||
g++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
|
||||
# Run
|
||||
./toy
|
||||
# Compile
|
||||
clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy
|
||||
# Run
|
||||
./toy
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -1008,9 +1008,9 @@ variables and var/in support. To build this example, use:
|
||||
#include "llvm/Analysis/Verifier.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Support/IRBuilder.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <map>
|
||||
@ -1686,8 +1686,8 @@ Value *BinaryExprAST::Codegen() {
|
||||
Function *F = TheModule->getFunction(std::string("binary")+Op);
|
||||
assert(F && "binary operator not found!");
|
||||
|
||||
Value *Ops[] = { L, R };
|
||||
return Builder.CreateCall(F, Ops, Ops+2, "binop");
|
||||
Value *Ops[2] = { L, R };
|
||||
return Builder.CreateCall(F, Ops, "binop");
|
||||
}
|
||||
|
||||
Value *CallExprAST::Codegen() {
|
||||
@ -1706,7 +1706,7 @@ Value *CallExprAST::Codegen() {
|
||||
if (ArgsV.back() == 0) return 0;
|
||||
}
|
||||
|
||||
return Builder.CreateCall(CalleeF, ArgsV.begin(), ArgsV.end(), "calltmp");
|
||||
return Builder.CreateCall(CalleeF, ArgsV, "calltmp");
|
||||
}
|
||||
|
||||
Value *IfExprAST::Codegen() {
|
||||
@ -1907,8 +1907,8 @@ Value *VarExprAST::Codegen() {
|
||||
|
||||
Function *PrototypeAST::Codegen() {
|
||||
// Make the function type: double(double,double) etc.
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
std::vector<Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
|
||||
Doubles, false);
|
||||
|
||||
@ -2158,7 +2158,7 @@ int main() {
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org/">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-04-23 02:30:22 +0200 (Sat, 23 Apr 2011) $
|
||||
Last modified: $Date: 2011-10-16 10:07:38 +0200 (Sun, 16 Oct 2011) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -11,6 +11,7 @@ LEVEL := ../..
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
||||
HTML := $(wildcard $(PROJ_SRC_DIR)/*.html)
|
||||
PNG := $(wildcard $(PROJ_SRC_DIR)/*.png)
|
||||
EXTRA_DIST := $(HTML) index.html
|
||||
HTML_DIR := $(DESTDIR)$(PROJ_docsdir)/html/tutorial
|
||||
|
||||
@ -18,6 +19,7 @@ install-local:: $(HTML)
|
||||
$(Echo) Installing HTML Tutorial Documentation
|
||||
$(Verb) $(MKDIR) $(HTML_DIR)
|
||||
$(Verb) $(DataInstall) $(HTML) $(HTML_DIR)
|
||||
$(Verb) $(DataInstall) $(PNG) $(HTML_DIR)
|
||||
$(Verb) $(DataInstall) $(PROJ_SRC_DIR)/index.html $(HTML_DIR)
|
||||
|
||||
uninstall-local::
|
||||
|
@ -80,8 +80,8 @@ void BrainF::header(LLVMContext& C) {
|
||||
//%arr = malloc i8, i32 %d
|
||||
ConstantInt *val_mem = ConstantInt::get(C, APInt(32, memtotal));
|
||||
BasicBlock* BB = builder->GetInsertBlock();
|
||||
const Type* IntPtrTy = IntegerType::getInt32Ty(C);
|
||||
const Type* Int8Ty = IntegerType::getInt8Ty(C);
|
||||
Type* IntPtrTy = IntegerType::getInt32Ty(C);
|
||||
Type* Int8Ty = IntegerType::getInt8Ty(C);
|
||||
Constant* allocsize = ConstantExpr::getSizeOf(Int8Ty);
|
||||
allocsize = ConstantExpr::getTruncOrBitCast(allocsize, IntPtrTy);
|
||||
ptr_arr = CallInst::CreateMalloc(BB, IntPtrTy, Int8Ty, allocsize, val_mem,
|
||||
@ -162,8 +162,7 @@ void BrainF::header(LLVMContext& C) {
|
||||
};
|
||||
|
||||
Constant *msgptr = ConstantExpr::
|
||||
getGetElementPtr(aberrormsg, gep_params,
|
||||
array_lengthof(gep_params));
|
||||
getGetElementPtr(aberrormsg, gep_params);
|
||||
|
||||
Value *puts_params[] = {
|
||||
msgptr
|
||||
|
@ -31,9 +31,9 @@
|
||||
#include "llvm/Bitcode/ReaderWriter.h"
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
#include "llvm/ExecutionEngine/JIT.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
@ -40,7 +40,8 @@
|
||||
//
|
||||
// Cases -1 and 7 are caught by a C++ test harness where the validity of
|
||||
// of a C++ catch(...) clause catching a generated exception with a
|
||||
// type info type of 7 is questionable.
|
||||
// type info type of 7 is explained by: example in rules 1.6.4 in
|
||||
// http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22)
|
||||
//
|
||||
// This code uses code from the llvm compiler-rt project and the llvm
|
||||
// Kaleidoscope project.
|
||||
@ -56,11 +57,16 @@
|
||||
#include "llvm/Intrinsics.h"
|
||||
#include "llvm/Analysis/Verifier.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Support/IRBuilder.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
|
||||
#ifdef OLD_EXC_SYSTEM
|
||||
// See use of UpgradeExceptionHandling(...) below
|
||||
#include "llvm/AutoUpgrade.h"
|
||||
#endif
|
||||
|
||||
// FIXME: Although all systems tested with (Linux, OS X), do not need this
|
||||
// header file included. A user on ubuntu reported, undefined symbols
|
||||
@ -81,7 +87,7 @@
|
||||
#endif
|
||||
|
||||
// System C++ ABI unwind types from:
|
||||
// http://refspecs.freestandards.org/abi-eh-1.21.html
|
||||
// http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22)
|
||||
|
||||
extern "C" {
|
||||
|
||||
@ -182,6 +188,9 @@ static std::vector<std::string> ourTypeInfoNames;
|
||||
static std::map<int, std::string> ourTypeInfoNamesIndex;
|
||||
|
||||
static llvm::StructType *ourTypeInfoType;
|
||||
#ifndef OLD_EXC_SYSTEM
|
||||
static llvm::StructType *ourCaughtResultType;
|
||||
#endif
|
||||
static llvm::StructType *ourExceptionType;
|
||||
static llvm::StructType *ourUnwindExceptionType;
|
||||
|
||||
@ -209,7 +218,7 @@ typedef std::vector<llvm::Type*> ArgTypes;
|
||||
/// @param isVarArg function uses vararg arguments
|
||||
/// @returns function instance
|
||||
llvm::Function *createFunction(llvm::Module &module,
|
||||
const llvm::Type *retType,
|
||||
llvm::Type *retType,
|
||||
const ArgTypes &theArgTypes,
|
||||
const ArgNames &theArgNames,
|
||||
const std::string &functName,
|
||||
@ -246,7 +255,7 @@ llvm::Function *createFunction(llvm::Module &module,
|
||||
/// @returns AllocaInst instance
|
||||
static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function &function,
|
||||
const std::string &varName,
|
||||
const llvm::Type *type,
|
||||
llvm::Type *type,
|
||||
llvm::Constant *initWith = 0) {
|
||||
llvm::BasicBlock &block = function.getEntryBlock();
|
||||
llvm::IRBuilder<> tmp(&block, block.begin());
|
||||
@ -893,9 +902,8 @@ void generateStringPrint(llvm::LLVMContext &context,
|
||||
builder.CreateStore(stringConstant, stringVar);
|
||||
}
|
||||
|
||||
llvm::Value *cast =
|
||||
builder.CreatePointerCast(stringVar,
|
||||
builder.getInt8PtrTy());
|
||||
llvm::Value *cast = builder.CreatePointerCast(stringVar,
|
||||
builder.getInt8PtrTy());
|
||||
builder.CreateCall(printFunct, cast);
|
||||
}
|
||||
|
||||
@ -937,9 +945,8 @@ void generateIntegerPrint(llvm::LLVMContext &context,
|
||||
builder.CreateStore(stringConstant, stringVar);
|
||||
}
|
||||
|
||||
llvm::Value *cast =
|
||||
builder.CreateBitCast(stringVar,
|
||||
builder.getInt8PtrTy());
|
||||
llvm::Value *cast = builder.CreateBitCast(stringVar,
|
||||
builder.getInt8PtrTy());
|
||||
builder.CreateCall2(&printFunct, &toPrint, cast);
|
||||
}
|
||||
|
||||
@ -962,6 +969,9 @@ void generateIntegerPrint(llvm::LLVMContext &context,
|
||||
/// @param unwindResumeBlock unwind resume block
|
||||
/// @param exceptionCaughtFlag reference exception caught/thrown status storage
|
||||
/// @param exceptionStorage reference to exception pointer storage
|
||||
#ifndef OLD_EXC_SYSTEM
|
||||
/// @param caughtResultStorage reference to landingpad result storage
|
||||
#endif
|
||||
/// @returns newly created block
|
||||
static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
|
||||
llvm::Module &module,
|
||||
@ -972,28 +982,42 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
|
||||
llvm::BasicBlock &terminatorBlock,
|
||||
llvm::BasicBlock &unwindResumeBlock,
|
||||
llvm::Value **exceptionCaughtFlag,
|
||||
llvm::Value **exceptionStorage) {
|
||||
llvm::Value **exceptionStorage
|
||||
#ifndef OLD_EXC_SYSTEM
|
||||
,llvm::Value **caughtResultStorage
|
||||
#endif
|
||||
) {
|
||||
assert(exceptionCaughtFlag &&
|
||||
"ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag "
|
||||
"is NULL");
|
||||
assert(exceptionStorage &&
|
||||
"ExceptionDemo::createFinallyBlock(...):exceptionStorage "
|
||||
"is NULL");
|
||||
|
||||
#ifndef OLD_EXC_SYSTEM
|
||||
assert(caughtResultStorage &&
|
||||
"ExceptionDemo::createFinallyBlock(...):caughtResultStorage "
|
||||
"is NULL");
|
||||
#endif
|
||||
|
||||
*exceptionCaughtFlag =
|
||||
createEntryBlockAlloca(toAddTo,
|
||||
"exceptionCaught",
|
||||
ourExceptionNotThrownState->getType(),
|
||||
ourExceptionNotThrownState);
|
||||
*exceptionCaughtFlag = createEntryBlockAlloca(toAddTo,
|
||||
"exceptionCaught",
|
||||
ourExceptionNotThrownState->getType(),
|
||||
ourExceptionNotThrownState);
|
||||
|
||||
const llvm::PointerType *exceptionStorageType =
|
||||
builder.getInt8PtrTy();
|
||||
*exceptionStorage =
|
||||
createEntryBlockAlloca(toAddTo,
|
||||
"exceptionStorage",
|
||||
exceptionStorageType,
|
||||
llvm::ConstantPointerNull::get(
|
||||
exceptionStorageType));
|
||||
llvm::PointerType *exceptionStorageType = builder.getInt8PtrTy();
|
||||
*exceptionStorage = createEntryBlockAlloca(toAddTo,
|
||||
"exceptionStorage",
|
||||
exceptionStorageType,
|
||||
llvm::ConstantPointerNull::get(
|
||||
exceptionStorageType));
|
||||
#ifndef OLD_EXC_SYSTEM
|
||||
*caughtResultStorage = createEntryBlockAlloca(toAddTo,
|
||||
"caughtResultStorage",
|
||||
ourCaughtResultType,
|
||||
llvm::ConstantAggregateZero::get(
|
||||
ourCaughtResultType));
|
||||
#endif
|
||||
|
||||
llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
|
||||
blockName,
|
||||
@ -1010,10 +1034,10 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
|
||||
bufferToPrint.str(),
|
||||
USE_GLOBAL_STR_CONSTS);
|
||||
|
||||
llvm::SwitchInst *theSwitch =
|
||||
builder.CreateSwitch(builder.CreateLoad(*exceptionCaughtFlag),
|
||||
&terminatorBlock,
|
||||
2);
|
||||
llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad(
|
||||
*exceptionCaughtFlag),
|
||||
&terminatorBlock,
|
||||
2);
|
||||
theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock);
|
||||
theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock);
|
||||
|
||||
@ -1121,29 +1145,35 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
|
||||
"normal",
|
||||
ret);
|
||||
// Unwind block for invoke
|
||||
llvm::BasicBlock *exceptionBlock =
|
||||
llvm::BasicBlock::Create(context, "exception", ret);
|
||||
llvm::BasicBlock *exceptionBlock = llvm::BasicBlock::Create(context,
|
||||
"exception",
|
||||
ret);
|
||||
|
||||
// Block which routes exception to correct catch handler block
|
||||
llvm::BasicBlock *exceptionRouteBlock =
|
||||
llvm::BasicBlock::Create(context, "exceptionRoute", ret);
|
||||
llvm::BasicBlock *exceptionRouteBlock = llvm::BasicBlock::Create(context,
|
||||
"exceptionRoute",
|
||||
ret);
|
||||
|
||||
// Foreign exception handler
|
||||
llvm::BasicBlock *externalExceptionBlock =
|
||||
llvm::BasicBlock::Create(context, "externalException", ret);
|
||||
llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context,
|
||||
"externalException",
|
||||
ret);
|
||||
|
||||
// Block which calls _Unwind_Resume
|
||||
llvm::BasicBlock *unwindResumeBlock =
|
||||
llvm::BasicBlock::Create(context, "unwindResume", ret);
|
||||
llvm::BasicBlock *unwindResumeBlock = llvm::BasicBlock::Create(context,
|
||||
"unwindResume",
|
||||
ret);
|
||||
|
||||
// Clean up block which delete exception if needed
|
||||
llvm::BasicBlock *endBlock =
|
||||
llvm::BasicBlock::Create(context, "end", ret);
|
||||
llvm::BasicBlock *endBlock = llvm::BasicBlock::Create(context, "end", ret);
|
||||
|
||||
std::string nextName;
|
||||
std::vector<llvm::BasicBlock*> catchBlocks(numExceptionsToCatch);
|
||||
llvm::Value *exceptionCaughtFlag = NULL;
|
||||
llvm::Value *exceptionStorage = NULL;
|
||||
#ifndef OLD_EXC_SYSTEM
|
||||
llvm::Value *caughtResultStorage = NULL;
|
||||
#endif
|
||||
|
||||
// Finally block which will branch to unwindResumeBlock if
|
||||
// exception is not caught. Initializes/allocates stack locations.
|
||||
@ -1156,7 +1186,11 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
|
||||
*endBlock,
|
||||
*unwindResumeBlock,
|
||||
&exceptionCaughtFlag,
|
||||
&exceptionStorage);
|
||||
&exceptionStorage
|
||||
#ifndef OLD_EXC_SYSTEM
|
||||
,&caughtResultStorage
|
||||
#endif
|
||||
);
|
||||
|
||||
for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
|
||||
nextName = ourTypeInfoNames[exceptionTypesToCatch[i]];
|
||||
@ -1181,8 +1215,7 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
|
||||
builder.CreateInvoke(&toInvoke,
|
||||
normalBlock,
|
||||
exceptionBlock,
|
||||
args.begin(),
|
||||
args.end());
|
||||
args);
|
||||
|
||||
// End Block
|
||||
|
||||
@ -1193,8 +1226,7 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
|
||||
builder,
|
||||
"Gen: In end block: exiting in " + ourId + ".\n",
|
||||
USE_GLOBAL_STR_CONSTS);
|
||||
llvm::Function *deleteOurException =
|
||||
module.getFunction("deleteOurException");
|
||||
llvm::Function *deleteOurException = module.getFunction("deleteOurException");
|
||||
|
||||
// Note: function handles NULL exceptions
|
||||
builder.CreateCall(deleteOurException,
|
||||
@ -1218,28 +1250,57 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
|
||||
|
||||
builder.SetInsertPoint(unwindResumeBlock);
|
||||
|
||||
llvm::Function *resumeOurException =
|
||||
module.getFunction("_Unwind_Resume");
|
||||
|
||||
#ifndef OLD_EXC_SYSTEM
|
||||
builder.CreateResume(builder.CreateLoad(caughtResultStorage));
|
||||
#else
|
||||
llvm::Function *resumeOurException = module.getFunction("_Unwind_Resume");
|
||||
builder.CreateCall(resumeOurException,
|
||||
builder.CreateLoad(exceptionStorage));
|
||||
builder.CreateUnreachable();
|
||||
#endif
|
||||
|
||||
// Exception Block
|
||||
|
||||
builder.SetInsertPoint(exceptionBlock);
|
||||
|
||||
llvm::Function *ehException = module.getFunction("llvm.eh.exception");
|
||||
llvm::Function *personality = module.getFunction("ourPersonality");
|
||||
|
||||
#ifndef OLD_EXC_SYSTEM
|
||||
llvm::LandingPadInst *caughtResult =
|
||||
builder.CreateLandingPad(ourCaughtResultType,
|
||||
personality,
|
||||
numExceptionsToCatch,
|
||||
"landingPad");
|
||||
|
||||
caughtResult->setCleanup(true);
|
||||
|
||||
for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
|
||||
// Set up type infos to be caught
|
||||
caughtResult->addClause(module.getGlobalVariable(
|
||||
ourTypeInfoNames[exceptionTypesToCatch[i]]));
|
||||
}
|
||||
|
||||
llvm::Value *unwindException = builder.CreateExtractValue(caughtResult, 0);
|
||||
llvm::Value *retTypeInfoIndex = builder.CreateExtractValue(caughtResult, 1);
|
||||
|
||||
// FIXME: Redundant storage which, beyond utilizing value of
|
||||
// caughtResultStore for unwindException storage, may be alleviated
|
||||
// alltogether with a block rearrangement
|
||||
builder.CreateStore(caughtResult, caughtResultStorage);
|
||||
builder.CreateStore(unwindException, exceptionStorage);
|
||||
builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
|
||||
#else
|
||||
llvm::Function *ehException = module.getFunction("llvm.eh.exception");
|
||||
|
||||
// Retrieve thrown exception
|
||||
llvm::Value *unwindException = builder.CreateCall(ehException);
|
||||
|
||||
// Store exception and flag
|
||||
builder.CreateStore(unwindException, exceptionStorage);
|
||||
builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
|
||||
llvm::Function *personality = module.getFunction("ourPersonality");
|
||||
llvm::Value *functPtr =
|
||||
builder.CreatePointerCast(personality,
|
||||
builder.getInt8PtrTy());
|
||||
llvm::Value *functPtr = builder.CreatePointerCast(personality,
|
||||
builder.getInt8PtrTy());
|
||||
|
||||
args.clear();
|
||||
args.push_back(unwindException);
|
||||
@ -1263,9 +1324,8 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
|
||||
// handles this call. This landing pad (this exception block), will be
|
||||
// called either because it nees to cleanup (call finally) or a type
|
||||
// info was found which matched the thrown exception.
|
||||
llvm::Value *retTypeInfoIndex = builder.CreateCall(ehSelector,
|
||||
args.begin(),
|
||||
args.end());
|
||||
llvm::Value *retTypeInfoIndex = builder.CreateCall(ehSelector, args);
|
||||
#endif
|
||||
|
||||
// Retrieve exception_class member from thrown exception
|
||||
// (_Unwind_Exception instance). This member tells us whether or not
|
||||
@ -1305,10 +1365,10 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
|
||||
// (OurException instance).
|
||||
//
|
||||
// Note: ourBaseFromUnwindOffset is usually negative
|
||||
llvm::Value *typeInfoThrown =
|
||||
builder.CreatePointerCast(builder.CreateConstGEP1_64(unwindException,
|
||||
llvm::Value *typeInfoThrown = builder.CreatePointerCast(
|
||||
builder.CreateConstGEP1_64(unwindException,
|
||||
ourBaseFromUnwindOffset),
|
||||
ourExceptionType->getPointerTo());
|
||||
ourExceptionType->getPointerTo());
|
||||
|
||||
// Retrieve thrown exception type info type
|
||||
//
|
||||
@ -1331,10 +1391,9 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
|
||||
USE_GLOBAL_STR_CONSTS);
|
||||
|
||||
// Route to matched type info catch block or run cleanup finally block
|
||||
llvm::SwitchInst *switchToCatchBlock =
|
||||
builder.CreateSwitch(retTypeInfoIndex,
|
||||
finallyBlock,
|
||||
numExceptionsToCatch);
|
||||
llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex,
|
||||
finallyBlock,
|
||||
numExceptionsToCatch);
|
||||
|
||||
unsigned nextTypeToCatch;
|
||||
|
||||
@ -1344,6 +1403,12 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
|
||||
llvm::Type::getInt32Ty(context), i),
|
||||
catchBlocks[nextTypeToCatch]);
|
||||
}
|
||||
|
||||
#ifdef OLD_EXC_SYSTEM
|
||||
// Must be run before verifier
|
||||
UpgradeExceptionHandling(&module);
|
||||
#endif
|
||||
|
||||
|
||||
llvm::verifyFunction(*ret);
|
||||
fpm.run(*ret);
|
||||
@ -1395,15 +1460,13 @@ llvm::Function *createThrowExceptionFunction(llvm::Module &module,
|
||||
"entry",
|
||||
ret);
|
||||
// Throws a foreign exception
|
||||
llvm::BasicBlock *nativeThrowBlock =
|
||||
llvm::BasicBlock::Create(context,
|
||||
"nativeThrow",
|
||||
ret);
|
||||
llvm::BasicBlock *nativeThrowBlock = llvm::BasicBlock::Create(context,
|
||||
"nativeThrow",
|
||||
ret);
|
||||
// Throws one of our Exceptions
|
||||
llvm::BasicBlock *generatedThrowBlock =
|
||||
llvm::BasicBlock::Create(context,
|
||||
"generatedThrow",
|
||||
ret);
|
||||
llvm::BasicBlock *generatedThrowBlock = llvm::BasicBlock::Create(context,
|
||||
"generatedThrow",
|
||||
ret);
|
||||
// Retrieved runtime type info type to throw
|
||||
llvm::Value *exceptionType = namedValues["exceptTypeToThrow"];
|
||||
|
||||
@ -1445,15 +1508,13 @@ llvm::Function *createThrowExceptionFunction(llvm::Module &module,
|
||||
|
||||
builder.SetInsertPoint(generatedThrowBlock);
|
||||
|
||||
llvm::Function *createOurException =
|
||||
module.getFunction("createOurException");
|
||||
llvm::Function *raiseOurException =
|
||||
module.getFunction("_Unwind_RaiseException");
|
||||
llvm::Function *createOurException = module.getFunction("createOurException");
|
||||
llvm::Function *raiseOurException = module.getFunction(
|
||||
"_Unwind_RaiseException");
|
||||
|
||||
// Creates exception to throw with runtime type info type.
|
||||
llvm::Value *exception =
|
||||
builder.CreateCall(createOurException,
|
||||
namedValues["exceptTypeToThrow"]);
|
||||
llvm::Value *exception = builder.CreateCall(createOurException,
|
||||
namedValues["exceptTypeToThrow"]);
|
||||
|
||||
// Throw generated Exception
|
||||
builder.CreateCall(raiseOurException, exception);
|
||||
@ -1501,32 +1562,29 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module,
|
||||
createStandardUtilityFunctions(numTypeInfos,
|
||||
module,
|
||||
builder);
|
||||
llvm::Function *nativeThrowFunct =
|
||||
module.getFunction(nativeThrowFunctName);
|
||||
llvm::Function *nativeThrowFunct = module.getFunction(nativeThrowFunctName);
|
||||
|
||||
// Create exception throw function using the value ~0 to cause
|
||||
// foreign exceptions to be thrown.
|
||||
llvm::Function *throwFunct =
|
||||
createThrowExceptionFunction(module,
|
||||
builder,
|
||||
fpm,
|
||||
"throwFunct",
|
||||
~0,
|
||||
*nativeThrowFunct);
|
||||
llvm::Function *throwFunct = createThrowExceptionFunction(module,
|
||||
builder,
|
||||
fpm,
|
||||
"throwFunct",
|
||||
~0,
|
||||
*nativeThrowFunct);
|
||||
// Inner function will catch even type infos
|
||||
unsigned innerExceptionTypesToCatch[] = {6, 2, 4};
|
||||
size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) /
|
||||
sizeof(unsigned);
|
||||
sizeof(unsigned);
|
||||
|
||||
// Generate inner function.
|
||||
llvm::Function *innerCatchFunct =
|
||||
createCatchWrappedInvokeFunction(module,
|
||||
builder,
|
||||
fpm,
|
||||
*throwFunct,
|
||||
"innerCatchFunct",
|
||||
numExceptionTypesToCatch,
|
||||
innerExceptionTypesToCatch);
|
||||
llvm::Function *innerCatchFunct = createCatchWrappedInvokeFunction(module,
|
||||
builder,
|
||||
fpm,
|
||||
*throwFunct,
|
||||
"innerCatchFunct",
|
||||
numExceptionTypesToCatch,
|
||||
innerExceptionTypesToCatch);
|
||||
|
||||
// Outer function will catch odd type infos
|
||||
unsigned outerExceptionTypesToCatch[] = {3, 1, 5};
|
||||
@ -1534,14 +1592,13 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module,
|
||||
sizeof(unsigned);
|
||||
|
||||
// Generate outer function
|
||||
llvm::Function *outerCatchFunct =
|
||||
createCatchWrappedInvokeFunction(module,
|
||||
builder,
|
||||
fpm,
|
||||
*innerCatchFunct,
|
||||
"outerCatchFunct",
|
||||
numExceptionTypesToCatch,
|
||||
outerExceptionTypesToCatch);
|
||||
llvm::Function *outerCatchFunct = createCatchWrappedInvokeFunction(module,
|
||||
builder,
|
||||
fpm,
|
||||
*innerCatchFunct,
|
||||
"outerCatchFunct",
|
||||
numExceptionTypesToCatch,
|
||||
outerExceptionTypesToCatch);
|
||||
|
||||
// Return outer function to run
|
||||
return(outerCatchFunct);
|
||||
@ -1607,12 +1664,12 @@ void runExceptionThrow(llvm::ExecutionEngine *engine,
|
||||
exc.what());
|
||||
}
|
||||
catch (...) {
|
||||
// Catch all exceptions including our generated ones. I'm not sure
|
||||
// why this latter functionality should work, as it seems that
|
||||
// our exceptions should be foreign to C++ (the _Unwind_Exception::
|
||||
// exception_class should be different from the one used by C++), and
|
||||
// therefore C++ should ignore the generated exceptions.
|
||||
|
||||
// Catch all exceptions including our generated ones. This latter
|
||||
// functionality works according to the example in rules 1.6.4 of
|
||||
// http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22),
|
||||
// given that these will be exceptions foreign to C++
|
||||
// (the _Unwind_Exception::exception_class should be different from
|
||||
// the one used by C++).
|
||||
fprintf(stderr,
|
||||
"\nrunExceptionThrow(...):In C++ catch all.\n");
|
||||
}
|
||||
@ -1640,17 +1697,31 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
|
||||
|
||||
// Setup exception catch state
|
||||
ourExceptionNotThrownState =
|
||||
llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0),
|
||||
llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0),
|
||||
ourExceptionThrownState =
|
||||
llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1),
|
||||
llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1),
|
||||
ourExceptionCaughtState =
|
||||
llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2),
|
||||
llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2),
|
||||
|
||||
|
||||
|
||||
// Create our type info type
|
||||
ourTypeInfoType = llvm::StructType::get(context,
|
||||
TypeArray(builder.getInt32Ty()));
|
||||
TypeArray(builder.getInt32Ty()));
|
||||
|
||||
#ifndef OLD_EXC_SYSTEM
|
||||
|
||||
llvm::Type *caughtResultFieldTypes[] = {
|
||||
builder.getInt8PtrTy(),
|
||||
builder.getInt32Ty()
|
||||
};
|
||||
|
||||
// Create our landingpad result type
|
||||
ourCaughtResultType = llvm::StructType::get(context,
|
||||
TypeArray(caughtResultFieldTypes));
|
||||
|
||||
#endif
|
||||
|
||||
// Create OurException type
|
||||
ourExceptionType = llvm::StructType::get(context,
|
||||
TypeArray(ourTypeInfoType));
|
||||
@ -1667,7 +1738,7 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
|
||||
|
||||
// Calculate offset of OurException::unwindException member.
|
||||
ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -
|
||||
((uintptr_t) &(dummyException.unwindException));
|
||||
((uintptr_t) &(dummyException.unwindException));
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,
|
||||
@ -1724,7 +1795,7 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
|
||||
|
||||
// print32Int
|
||||
|
||||
const llvm::Type *retType = builder.getVoidTy();
|
||||
llvm::Type *retType = builder.getVoidTy();
|
||||
|
||||
argTypes.clear();
|
||||
argTypes.push_back(builder.getInt32Ty());
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "llvm/ExecutionEngine/Interpreter.h"
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
using namespace llvm;
|
||||
|
||||
static Function *CreateFibFunction(Module *M, LLVMContext &Context) {
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include "llvm/ExecutionEngine/JIT.h"
|
||||
#include "llvm/ExecutionEngine/Interpreter.h"
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/IRBuilder.h"
|
||||
|
@ -7,9 +7,9 @@
|
||||
#include "llvm/Analysis/Verifier.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Support/IRBuilder.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -7,9 +7,9 @@
|
||||
#include "llvm/Analysis/Verifier.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Support/IRBuilder.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -7,9 +7,9 @@
|
||||
#include "llvm/Analysis/Verifier.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Support/IRBuilder.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -7,9 +7,9 @@
|
||||
#include "llvm/Analysis/Verifier.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Support/IRBuilder.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "llvm/ExecutionEngine/JIT.h"
|
||||
#include "llvm/ExecutionEngine/Interpreter.h"
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include <iostream>
|
||||
using namespace llvm;
|
||||
|
||||
|
@ -115,7 +115,10 @@ typedef enum {
|
||||
LLVMNoImplicitFloatAttribute = 1<<23,
|
||||
LLVMNakedAttribute = 1<<24,
|
||||
LLVMInlineHintAttribute = 1<<25,
|
||||
LLVMStackAlignment = 7<<26
|
||||
LLVMStackAlignment = 7<<26,
|
||||
LLVMReturnsTwice = 1 << 29,
|
||||
LLVMUWTable = 1 << 30,
|
||||
LLVMNonLazyBind = 1 << 31
|
||||
} LLVMAttribute;
|
||||
|
||||
typedef enum {
|
||||
@ -125,7 +128,7 @@ typedef enum {
|
||||
LLVMSwitch = 3,
|
||||
LLVMIndirectBr = 4,
|
||||
LLVMInvoke = 5,
|
||||
LLVMUnwind = 6,
|
||||
/* removed 6 due to API changes */
|
||||
LLVMUnreachable = 7,
|
||||
|
||||
/* Standard Binary Operators */
|
||||
@ -176,14 +179,26 @@ typedef enum {
|
||||
LLVMPHI = 44,
|
||||
LLVMCall = 45,
|
||||
LLVMSelect = 46,
|
||||
/* UserOp1 */
|
||||
/* UserOp2 */
|
||||
LLVMUserOp1 = 47,
|
||||
LLVMUserOp2 = 48,
|
||||
LLVMVAArg = 49,
|
||||
LLVMExtractElement = 50,
|
||||
LLVMInsertElement = 51,
|
||||
LLVMShuffleVector = 52,
|
||||
LLVMExtractValue = 53,
|
||||
LLVMInsertValue = 54
|
||||
LLVMInsertValue = 54,
|
||||
|
||||
/* Atomic operators */
|
||||
LLVMFence = 55,
|
||||
LLVMAtomicCmpXchg = 56,
|
||||
LLVMAtomicRMW = 57,
|
||||
|
||||
/* Exception Handling Operators */
|
||||
LLVMResume = 58,
|
||||
LLVMLandingPad = 59,
|
||||
LLVMUnwind = 60
|
||||
|
||||
|
||||
} LLVMOpcode;
|
||||
|
||||
typedef enum {
|
||||
@ -274,6 +289,11 @@ typedef enum {
|
||||
LLVMRealPredicateTrue /**< Always true (always folded) */
|
||||
} LLVMRealPredicate;
|
||||
|
||||
typedef enum {
|
||||
LLVMLandingPadCatch, /**< A catch clause */
|
||||
LLVMLandingPadFilter /**< A filter clause */
|
||||
} LLVMLandingPadClauseTy;
|
||||
|
||||
void LLVMInitializeCore(LLVMPassRegistryRef R);
|
||||
|
||||
|
||||
@ -340,6 +360,7 @@ LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M);
|
||||
|
||||
/** See llvm::LLVMTypeKind::getTypeID. */
|
||||
LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty);
|
||||
LLVMBool LLVMTypeIsSized(LLVMTypeRef Ty);
|
||||
|
||||
/** See llvm::LLVMType::getContext. */
|
||||
LLVMContextRef LLVMGetTypeContext(LLVMTypeRef Ty);
|
||||
@ -388,6 +409,7 @@ LLVMTypeRef LLVMStructTypeInContext(LLVMContextRef C, LLVMTypeRef *ElementTypes,
|
||||
LLVMTypeRef LLVMStructType(LLVMTypeRef *ElementTypes, unsigned ElementCount,
|
||||
LLVMBool Packed);
|
||||
LLVMTypeRef LLVMStructCreateNamed(LLVMContextRef C, const char *Name);
|
||||
const char *LLVMGetStructName(LLVMTypeRef Ty);
|
||||
void LLVMStructSetBody(LLVMTypeRef StructTy, LLVMTypeRef *ElementTypes,
|
||||
unsigned ElementCount, LLVMBool Packed);
|
||||
|
||||
@ -427,8 +449,11 @@ LLVMTypeRef LLVMX86MMXType(void);
|
||||
macro(Argument) \
|
||||
macro(BasicBlock) \
|
||||
macro(InlineAsm) \
|
||||
macro(MDNode) \
|
||||
macro(MDString) \
|
||||
macro(User) \
|
||||
macro(Constant) \
|
||||
macro(BlockAddress) \
|
||||
macro(ConstantAggregateZero) \
|
||||
macro(ConstantArray) \
|
||||
macro(ConstantExpr) \
|
||||
@ -448,29 +473,32 @@ LLVMTypeRef LLVMX86MMXType(void);
|
||||
macro(IntrinsicInst) \
|
||||
macro(DbgInfoIntrinsic) \
|
||||
macro(DbgDeclareInst) \
|
||||
macro(EHExceptionInst) \
|
||||
macro(EHSelectorInst) \
|
||||
macro(MemIntrinsic) \
|
||||
macro(MemCpyInst) \
|
||||
macro(MemMoveInst) \
|
||||
macro(MemSetInst) \
|
||||
macro(CmpInst) \
|
||||
macro(FCmpInst) \
|
||||
macro(ICmpInst) \
|
||||
macro(FCmpInst) \
|
||||
macro(ICmpInst) \
|
||||
macro(ExtractElementInst) \
|
||||
macro(GetElementPtrInst) \
|
||||
macro(InsertElementInst) \
|
||||
macro(InsertValueInst) \
|
||||
macro(LandingPadInst) \
|
||||
macro(PHINode) \
|
||||
macro(SelectInst) \
|
||||
macro(ShuffleVectorInst) \
|
||||
macro(StoreInst) \
|
||||
macro(TerminatorInst) \
|
||||
macro(BranchInst) \
|
||||
macro(IndirectBrInst) \
|
||||
macro(InvokeInst) \
|
||||
macro(ReturnInst) \
|
||||
macro(SwitchInst) \
|
||||
macro(UnreachableInst) \
|
||||
macro(UnwindInst) \
|
||||
macro(ResumeInst) \
|
||||
macro(UnaryInstruction) \
|
||||
macro(AllocaInst) \
|
||||
macro(CastInst) \
|
||||
@ -533,6 +561,11 @@ LLVMValueRef LLVMMDString(const char *Str, unsigned SLen);
|
||||
LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals,
|
||||
unsigned Count);
|
||||
LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count);
|
||||
const char *LLVMGetMDString(LLVMValueRef V, unsigned* Len);
|
||||
int LLVMGetMDNodeNumOperands(LLVMValueRef V);
|
||||
LLVMValueRef *LLVMGetMDNodeOperand(LLVMValueRef V, unsigned i);
|
||||
unsigned LLVMGetNamedMetadataNumOperands(LLVMModuleRef M, const char* name);
|
||||
void LLVMGetNamedMetadataOperands(LLVMModuleRef M, const char* name, LLVMValueRef *Dest);
|
||||
|
||||
/* Operations on scalar constants */
|
||||
LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N,
|
||||
@ -728,6 +761,7 @@ LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB);
|
||||
LLVMBool LLVMValueIsBasicBlock(LLVMValueRef Val);
|
||||
LLVMBasicBlockRef LLVMValueAsBasicBlock(LLVMValueRef Val);
|
||||
LLVMValueRef LLVMGetBasicBlockParent(LLVMBasicBlockRef BB);
|
||||
LLVMValueRef LLVMGetBasicBlockTerminator(LLVMBasicBlockRef BB);
|
||||
unsigned LLVMCountBasicBlocks(LLVMValueRef Fn);
|
||||
void LLVMGetBasicBlocks(LLVMValueRef Fn, LLVMBasicBlockRef *BasicBlocks);
|
||||
LLVMBasicBlockRef LLVMGetFirstBasicBlock(LLVMValueRef Fn);
|
||||
@ -747,16 +781,21 @@ LLVMBasicBlockRef LLVMAppendBasicBlock(LLVMValueRef Fn, const char *Name);
|
||||
LLVMBasicBlockRef LLVMInsertBasicBlock(LLVMBasicBlockRef InsertBeforeBB,
|
||||
const char *Name);
|
||||
void LLVMDeleteBasicBlock(LLVMBasicBlockRef BB);
|
||||
void LLVMRemoveBasicBlockFromParent(LLVMBasicBlockRef BB);
|
||||
|
||||
void LLVMMoveBasicBlockBefore(LLVMBasicBlockRef BB, LLVMBasicBlockRef MovePos);
|
||||
void LLVMMoveBasicBlockAfter(LLVMBasicBlockRef BB, LLVMBasicBlockRef MovePos);
|
||||
|
||||
/* Operations on instructions */
|
||||
LLVMBasicBlockRef LLVMGetInstructionParent(LLVMValueRef Inst);
|
||||
LLVMValueRef LLVMGetFirstInstruction(LLVMBasicBlockRef BB);
|
||||
LLVMValueRef LLVMGetLastInstruction(LLVMBasicBlockRef BB);
|
||||
|
||||
/* Operations on instructions */
|
||||
LLVMBasicBlockRef LLVMGetInstructionParent(LLVMValueRef Inst);
|
||||
LLVMValueRef LLVMGetNextInstruction(LLVMValueRef Inst);
|
||||
LLVMValueRef LLVMGetPreviousInstruction(LLVMValueRef Inst);
|
||||
void LLVMInstructionEraseFromParent(LLVMValueRef Inst);
|
||||
LLVMOpcode LLVMGetInstructionOpcode(LLVMValueRef Inst);
|
||||
LLVMIntPredicate LLVMGetICmpPredicate(LLVMValueRef Inst);
|
||||
|
||||
/* Operations on call sites */
|
||||
void LLVMSetInstructionCallConv(LLVMValueRef Instr, unsigned CC);
|
||||
@ -771,6 +810,9 @@ void LLVMSetInstrParamAlignment(LLVMValueRef Instr, unsigned index,
|
||||
LLVMBool LLVMIsTailCall(LLVMValueRef CallInst);
|
||||
void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall);
|
||||
|
||||
/* Operations on switch instructions (only) */
|
||||
LLVMBasicBlockRef LLVMGetSwitchDefaultDest(LLVMValueRef SwitchInstr);
|
||||
|
||||
/* Operations on phi nodes */
|
||||
void LLVMAddIncoming(LLVMValueRef PhiNode, LLVMValueRef *IncomingValues,
|
||||
LLVMBasicBlockRef *IncomingBlocks, unsigned Count);
|
||||
@ -818,7 +860,10 @@ LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn,
|
||||
LLVMValueRef *Args, unsigned NumArgs,
|
||||
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
|
||||
const char *Name);
|
||||
LLVMValueRef LLVMBuildUnwind(LLVMBuilderRef);
|
||||
LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty,
|
||||
LLVMValueRef PersFn, unsigned NumClauses,
|
||||
const char *Name);
|
||||
LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn);
|
||||
LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef);
|
||||
|
||||
/* Add a case to the switch instruction */
|
||||
@ -828,6 +873,12 @@ void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal,
|
||||
/* Add a destination to the indirectbr instruction */
|
||||
void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest);
|
||||
|
||||
/* Add a catch or filter clause to the landingpad instruction */
|
||||
void LLVMAddClause(LLVMValueRef LandingPad, LLVMValueRef ClauseVal);
|
||||
|
||||
/* Set the 'cleanup' flag in the landingpad instruction */
|
||||
void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val);
|
||||
|
||||
/* Arithmetic */
|
||||
LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS,
|
||||
const char *Name);
|
||||
@ -1136,7 +1187,7 @@ namespace llvm {
|
||||
return reinterpret_cast<Type**>(Tys);
|
||||
}
|
||||
|
||||
inline LLVMTypeRef *wrap(const Type **Tys) {
|
||||
inline LLVMTypeRef *wrap(Type **Tys) {
|
||||
return reinterpret_cast<LLVMTypeRef*>(const_cast<Type**>(Tys));
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ typedef int (*LLVMOpInfoCallback)(void *DisInfo, uint64_t PC,
|
||||
*/
|
||||
struct LLVMOpInfoSymbol1 {
|
||||
uint64_t Present; /* 1 if this symbol is present */
|
||||
char *Name; /* symbol name if not NULL */
|
||||
const char *Name; /* symbol name if not NULL */
|
||||
uint64_t Value; /* symbol value if name is NULL */
|
||||
};
|
||||
|
||||
@ -93,11 +93,35 @@ struct LLVMOpInfo1 {
|
||||
* disassembler for things like adding a comment for a PC plus a constant
|
||||
* offset load instruction to use a symbol name instead of a load address value.
|
||||
* It is passed the block information is saved when the disassembler context is
|
||||
* created and a value of a symbol to look up. If no symbol is found NULL is
|
||||
* returned.
|
||||
* created and the ReferenceValue to look up as a symbol. If no symbol is found
|
||||
* for the ReferenceValue NULL is returned. The ReferenceType of the
|
||||
* instruction is passed indirectly as is the PC of the instruction in
|
||||
* ReferencePC. If the output reference can be determined its type is returned
|
||||
* indirectly in ReferenceType along with ReferenceName if any, or that is set
|
||||
* to NULL.
|
||||
*/
|
||||
typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo,
|
||||
uint64_t SymbolValue);
|
||||
uint64_t ReferenceValue,
|
||||
uint64_t *ReferenceType,
|
||||
uint64_t ReferencePC,
|
||||
const char **ReferenceName);
|
||||
/**
|
||||
* The reference types on input and output.
|
||||
*/
|
||||
/* No input reference type or no output reference type. */
|
||||
#define LLVMDisassembler_ReferenceType_InOut_None 0
|
||||
|
||||
/* The input reference is from a branch instruction. */
|
||||
#define LLVMDisassembler_ReferenceType_In_Branch 1
|
||||
/* The input reference is from a PC relative load instruction. */
|
||||
#define LLVMDisassembler_ReferenceType_In_PCrel_Load 2
|
||||
|
||||
/* The output reference is to as symbol stub. */
|
||||
#define LLVMDisassembler_ReferenceType_Out_SymbolStub 1
|
||||
/* The output reference is to a symbol address in a literal pool. */
|
||||
#define LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr 2
|
||||
/* The output reference is to a cstring address in a literal pool. */
|
||||
#define LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr 3
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -59,14 +59,14 @@ namespace llvm {
|
||||
return reinterpret_cast<LLVMObjectFileRef>(const_cast<ObjectFile*>(OF));
|
||||
}
|
||||
|
||||
inline ObjectFile::section_iterator *unwrap(LLVMSectionIteratorRef SI) {
|
||||
return reinterpret_cast<ObjectFile::section_iterator*>(SI);
|
||||
inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
|
||||
return reinterpret_cast<section_iterator*>(SI);
|
||||
}
|
||||
|
||||
inline LLVMSectionIteratorRef
|
||||
wrap(const ObjectFile::section_iterator *SI) {
|
||||
wrap(const section_iterator *SI) {
|
||||
return reinterpret_cast<LLVMSectionIteratorRef>
|
||||
(const_cast<ObjectFile::section_iterator*>(SI));
|
||||
(const_cast<section_iterator*>(SI));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ extern "C" {
|
||||
enum LLVMByteOrdering { LLVMBigEndian, LLVMLittleEndian };
|
||||
|
||||
typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef;
|
||||
typedef struct LLVMOpaqueTargetLibraryInfotData *LLVMTargetLibraryInfoRef;
|
||||
typedef struct LLVMStructLayout *LLVMStructLayoutRef;
|
||||
|
||||
/* Declare all of the target-initialization functions that are available. */
|
||||
@ -42,7 +43,7 @@ typedef struct LLVMStructLayout *LLVMStructLayoutRef;
|
||||
#undef LLVM_TARGET /* Explicit undef to make SWIG happier */
|
||||
|
||||
#define LLVM_TARGET(TargetName) \
|
||||
void LLVMInitialize##TargetName##MCAsmInfo(void);
|
||||
void LLVMInitialize##TargetName##TargetMC(void);
|
||||
#include "llvm/Config/Targets.def"
|
||||
#undef LLVM_TARGET /* Explicit undef to make SWIG happier */
|
||||
|
||||
@ -72,7 +73,7 @@ static inline LLVMBool LLVMInitializeNativeTarget(void) {
|
||||
#ifdef LLVM_NATIVE_TARGET
|
||||
LLVM_NATIVE_TARGETINFO();
|
||||
LLVM_NATIVE_TARGET();
|
||||
LLVM_NATIVE_MCASMINFO();
|
||||
LLVM_NATIVE_TARGETMC();
|
||||
return 0;
|
||||
#else
|
||||
return 1;
|
||||
@ -90,6 +91,11 @@ LLVMTargetDataRef LLVMCreateTargetData(const char *StringRep);
|
||||
See the method llvm::PassManagerBase::add. */
|
||||
void LLVMAddTargetData(LLVMTargetDataRef, LLVMPassManagerRef);
|
||||
|
||||
/** Adds target library information to a pass manager. This does not take
|
||||
ownership of the target library info.
|
||||
See the method llvm::PassManagerBase::add. */
|
||||
void LLVMAddTargetLibraryInfo(LLVMTargetLibraryInfoRef, LLVMPassManagerRef);
|
||||
|
||||
/** Converts target data to a target layout string. The string must be disposed
|
||||
with LLVMDisposeMessage.
|
||||
See the constructor llvm::TargetData::TargetData. */
|
||||
@ -157,6 +163,7 @@ void LLVMDisposeTargetData(LLVMTargetDataRef);
|
||||
|
||||
namespace llvm {
|
||||
class TargetData;
|
||||
class TargetLibraryInfo;
|
||||
|
||||
inline TargetData *unwrap(LLVMTargetDataRef P) {
|
||||
return reinterpret_cast<TargetData*>(P);
|
||||
@ -165,6 +172,15 @@ namespace llvm {
|
||||
inline LLVMTargetDataRef wrap(const TargetData *P) {
|
||||
return reinterpret_cast<LLVMTargetDataRef>(const_cast<TargetData*>(P));
|
||||
}
|
||||
|
||||
inline TargetLibraryInfo *unwrap(LLVMTargetLibraryInfoRef P) {
|
||||
return reinterpret_cast<TargetLibraryInfo*>(P);
|
||||
}
|
||||
|
||||
inline LLVMTargetLibraryInfoRef wrap(const TargetLibraryInfo *P) {
|
||||
TargetLibraryInfo *X = const_cast<TargetLibraryInfo*>(P);
|
||||
return reinterpret_cast<LLVMTargetLibraryInfoRef>(X);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* defined(__cplusplus) */
|
||||
|
@ -36,6 +36,9 @@ void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM);
|
||||
/** See llvm::createFunctionInliningPass function. */
|
||||
void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createAlwaysInlinerPass function. */
|
||||
void LLVMAddAlwaysInlinerPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createGlobalDCEPass function. */
|
||||
void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM);
|
||||
|
||||
@ -45,9 +48,6 @@ void LLVMAddGlobalOptimizerPass(LLVMPassManagerRef PM);
|
||||
/** See llvm::createIPConstantPropagationPass function. */
|
||||
void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createLowerSetJmpPass function. */
|
||||
void LLVMAddLowerSetJmpPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createPruneEHPass function. */
|
||||
void LLVMAddPruneEHPass(LLVMPassManagerRef PM);
|
||||
|
||||
@ -57,9 +57,6 @@ void LLVMAddIPSCCPPass(LLVMPassManagerRef PM);
|
||||
/** See llvm::createInternalizePass function. */
|
||||
void LLVMAddInternalizePass(LLVMPassManagerRef, unsigned AllButMain);
|
||||
|
||||
// FIXME: Remove in LLVM 3.0.
|
||||
void LLVMAddRaiseAllocationsPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createStripDeadPrototypesPass function. */
|
||||
void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM);
|
||||
|
||||
|
90
include/llvm-c/Transforms/PassManagerBuilder.h
Normal file
90
include/llvm-c/Transforms/PassManagerBuilder.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*===-- llvm-c/Transform/PassManagerBuilder.h - PMB C Interface ---*- C -*-===*\
|
||||
|* *|
|
||||
|* The LLVM Compiler Infrastructure *|
|
||||
|* *|
|
||||
|* This file is distributed under the University of Illinois Open Source *|
|
||||
|* License. See LICENSE.TXT for details. *|
|
||||
|* *|
|
||||
|*===----------------------------------------------------------------------===*|
|
||||
|* *|
|
||||
|* This header declares the C interface to the PassManagerBuilder class. *|
|
||||
|* *|
|
||||
\*===----------------------------------------------------------------------===*/
|
||||
|
||||
#ifndef LLVM_C_PASSMANAGERBUILDER
|
||||
#define LLVM_C_PASSMANAGERBUILDER
|
||||
|
||||
#include "llvm-c/Core.h"
|
||||
|
||||
typedef struct LLVMOpaquePassManagerBuilder *LLVMPassManagerBuilderRef;
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** See llvm::PassManagerBuilder. */
|
||||
LLVMPassManagerBuilderRef LLVMPassManagerBuilderCreate(void);
|
||||
void LLVMPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB);
|
||||
|
||||
/** See llvm::PassManagerBuilder::OptLevel. */
|
||||
void
|
||||
LLVMPassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB,
|
||||
unsigned OptLevel);
|
||||
|
||||
/** See llvm::PassManagerBuilder::SizeLevel. */
|
||||
void
|
||||
LLVMPassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB,
|
||||
unsigned SizeLevel);
|
||||
|
||||
/** See llvm::PassManagerBuilder::DisableUnitAtATime. */
|
||||
void
|
||||
LLVMPassManagerBuilderSetDisableUnitAtATime(LLVMPassManagerBuilderRef PMB,
|
||||
LLVMBool Value);
|
||||
|
||||
/** See llvm::PassManagerBuilder::DisableUnrollLoops. */
|
||||
void
|
||||
LLVMPassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB,
|
||||
LLVMBool Value);
|
||||
|
||||
/** See llvm::PassManagerBuilder::DisableSimplifyLibCalls */
|
||||
void
|
||||
LLVMPassManagerBuilderSetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef PMB,
|
||||
LLVMBool Value);
|
||||
|
||||
/** See llvm::PassManagerBuilder::Inliner. */
|
||||
void
|
||||
LLVMPassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB,
|
||||
unsigned Threshold);
|
||||
|
||||
/** See llvm::PassManagerBuilder::populateFunctionPassManager. */
|
||||
void
|
||||
LLVMPassManagerBuilderPopulateFunctionPassManager(LLVMPassManagerBuilderRef PMB,
|
||||
LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::PassManagerBuilder::populateModulePassManager. */
|
||||
void
|
||||
LLVMPassManagerBuilderPopulateModulePassManager(LLVMPassManagerBuilderRef PMB,
|
||||
LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::PassManagerBuilder::populateLTOPassManager. */
|
||||
void LLVMPassManagerBuilderPopulateLTOPassManager(LLVMPassManagerBuilderRef PMB,
|
||||
LLVMPassManagerRef PM,
|
||||
bool Internalize,
|
||||
bool RunInliner);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
inline PassManagerBuilder *unwrap(LLVMPassManagerBuilderRef P) {
|
||||
return reinterpret_cast<PassManagerBuilder*>(P);
|
||||
}
|
||||
|
||||
inline LLVMPassManagerBuilderRef wrap(PassManagerBuilder *P) {
|
||||
return reinterpret_cast<LLVMPassManagerBuilderRef>(P);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -107,6 +107,9 @@ void LLVMAddCorrelatedValuePropagationPass(LLVMPassManagerRef PM);
|
||||
/** See llvm::createEarlyCSEPass function */
|
||||
void LLVMAddEarlyCSEPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createLowerExpectIntrinsicPass function */
|
||||
void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createTypeBasedAliasAnalysisPass function */
|
||||
void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM);
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#ifndef LLVM_APINT_H
|
||||
#define LLVM_APINT_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
@ -160,7 +161,7 @@ class APInt {
|
||||
/// not assume that the string is well-formed and (2) grows the
|
||||
/// result to hold the input.
|
||||
///
|
||||
/// @param radix 2, 8, 10, or 16
|
||||
/// @param radix 2, 8, 10, 16, or 36
|
||||
/// @brief Convert a char array into an APInt
|
||||
void fromString(unsigned numBits, StringRef str, uint8_t radix);
|
||||
|
||||
@ -176,6 +177,9 @@ class APInt {
|
||||
/// out-of-line slow case for inline constructor
|
||||
void initSlowCase(unsigned numBits, uint64_t val, bool isSigned);
|
||||
|
||||
/// shared code between two array constructors
|
||||
void initFromArray(ArrayRef<uint64_t> array);
|
||||
|
||||
/// out-of-line slow case for inline copy constructor
|
||||
void initSlowCase(const APInt& that);
|
||||
|
||||
@ -230,19 +234,26 @@ class APInt {
|
||||
clearUnusedBits();
|
||||
}
|
||||
|
||||
/// Note that numWords can be smaller or larger than the corresponding bit
|
||||
/// width but any extraneous bits will be dropped.
|
||||
/// Note that bigVal.size() can be smaller or larger than the corresponding
|
||||
/// bit width but any extraneous bits will be dropped.
|
||||
/// @param numBits the bit width of the constructed APInt
|
||||
/// @param numWords the number of words in bigVal
|
||||
/// @param bigVal a sequence of words to form the initial value of the APInt
|
||||
/// @brief Construct an APInt of numBits width, initialized as bigVal[].
|
||||
APInt(unsigned numBits, ArrayRef<uint64_t> bigVal);
|
||||
/// Equivalent to APInt(numBits, ArrayRef<uint64_t>(bigVal, numWords)), but
|
||||
/// deprecated because this constructor is prone to ambiguity with the
|
||||
/// APInt(unsigned, uint64_t, bool) constructor.
|
||||
///
|
||||
/// If this overload is ever deleted, care should be taken to prevent calls
|
||||
/// from being incorrectly captured by the APInt(unsigned, uint64_t, bool)
|
||||
/// constructor.
|
||||
APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]);
|
||||
|
||||
/// This constructor interprets the string \arg str in the given radix. The
|
||||
/// interpretation stops when the first character that is not suitable for the
|
||||
/// radix is encountered, or the end of the string. Acceptable radix values
|
||||
/// are 2, 8, 10 and 16. It is an error for the value implied by the string to
|
||||
/// require more bits than numBits.
|
||||
/// are 2, 8, 10, 16, and 36. It is an error for the value implied by the
|
||||
/// string to require more bits than numBits.
|
||||
///
|
||||
/// @param numBits the bit width of the constructed APInt
|
||||
/// @param str the string to be interpreted
|
||||
@ -342,7 +353,8 @@ class APInt {
|
||||
|
||||
if (isSingleWord())
|
||||
return isUIntN(N, VAL);
|
||||
return APInt(N, getNumWords(), pVal).zext(getBitWidth()) == (*this);
|
||||
return APInt(N, makeArrayRef(pVal, getNumWords())).zext(getBitWidth())
|
||||
== (*this);
|
||||
}
|
||||
|
||||
/// @brief Check if this APInt has an N-bits signed integer value.
|
||||
@ -1245,13 +1257,13 @@ class APInt {
|
||||
bool formatAsCLiteral = false) const;
|
||||
|
||||
/// Considers the APInt to be unsigned and converts it into a string in the
|
||||
/// radix given. The radix can be 2, 8, 10 or 16.
|
||||
/// radix given. The radix can be 2, 8, 10 16, or 36.
|
||||
void toStringUnsigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
|
||||
toString(Str, Radix, false, false);
|
||||
}
|
||||
|
||||
/// Considers the APInt to be signed and converts it into a string in the
|
||||
/// radix given. The radix can be 2, 8, 10 or 16.
|
||||
/// radix given. The radix can be 2, 8, 10, 16, or 36.
|
||||
void toStringSigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
|
||||
toString(Str, Radix, true, false);
|
||||
}
|
||||
|
@ -147,7 +147,53 @@ namespace llvm {
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
|
||||
/// @name ArrayRef Convenience constructors
|
||||
/// @{
|
||||
|
||||
/// Construct an ArrayRef from a single element.
|
||||
template<typename T>
|
||||
ArrayRef<T> makeArrayRef(const T &OneElt) {
|
||||
return OneElt;
|
||||
}
|
||||
|
||||
/// Construct an ArrayRef from a pointer and length.
|
||||
template<typename T>
|
||||
ArrayRef<T> makeArrayRef(const T *data, size_t length) {
|
||||
return ArrayRef<T>(data, length);
|
||||
}
|
||||
|
||||
/// Construct an ArrayRef from a range.
|
||||
template<typename T>
|
||||
ArrayRef<T> makeArrayRef(const T *begin, const T *end) {
|
||||
return ArrayRef<T>(begin, end);
|
||||
}
|
||||
|
||||
/// Construct an ArrayRef from a SmallVector.
|
||||
template <typename T>
|
||||
ArrayRef<T> makeArrayRef(const SmallVectorImpl<T> &Vec) {
|
||||
return Vec;
|
||||
}
|
||||
|
||||
/// Construct an ArrayRef from a SmallVector.
|
||||
template <typename T, unsigned N>
|
||||
ArrayRef<T> makeArrayRef(const SmallVector<T, N> &Vec) {
|
||||
return Vec;
|
||||
}
|
||||
|
||||
/// Construct an ArrayRef from a std::vector.
|
||||
template<typename T>
|
||||
ArrayRef<T> makeArrayRef(const std::vector<T> &Vec) {
|
||||
return Vec;
|
||||
}
|
||||
|
||||
/// Construct an ArrayRef from a C array.
|
||||
template<typename T, size_t N>
|
||||
ArrayRef<T> makeArrayRef(const T (&Arr)[N]) {
|
||||
return ArrayRef<T>(Arr);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name ArrayRef Comparison Operators
|
||||
/// @{
|
||||
|
||||
|
@ -540,6 +540,12 @@ class DenseMapIterator {
|
||||
++Ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename KeyT, typename ValueT, typename KeyInfoT, typename ValueInfoT>
|
||||
static inline size_t
|
||||
capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT, ValueInfoT> &X) {
|
||||
return X.getMemorySize();
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
|
@ -51,7 +51,7 @@ struct DenseMapInfo<T*> {
|
||||
template<> struct DenseMapInfo<char> {
|
||||
static inline char getEmptyKey() { return ~0; }
|
||||
static inline char getTombstoneKey() { return ~0 - 1; }
|
||||
static unsigned getHashValue(const char& Val) { return Val * 37; }
|
||||
static unsigned getHashValue(const char& Val) { return Val * 37U; }
|
||||
static bool isEqual(const char &LHS, const char &RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
@ -61,7 +61,7 @@ template<> struct DenseMapInfo<char> {
|
||||
template<> struct DenseMapInfo<unsigned> {
|
||||
static inline unsigned getEmptyKey() { return ~0; }
|
||||
static inline unsigned getTombstoneKey() { return ~0U - 1; }
|
||||
static unsigned getHashValue(const unsigned& Val) { return Val * 37; }
|
||||
static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
|
||||
static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
@ -96,7 +96,7 @@ template<> struct DenseMapInfo<unsigned long long> {
|
||||
template<> struct DenseMapInfo<int> {
|
||||
static inline int getEmptyKey() { return 0x7fffffff; }
|
||||
static inline int getTombstoneKey() { return -0x7fffffff - 1; }
|
||||
static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37); }
|
||||
static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); }
|
||||
static bool isEqual(const int& LHS, const int& RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
@ -109,7 +109,7 @@ template<> struct DenseMapInfo<long> {
|
||||
}
|
||||
static inline long getTombstoneKey() { return getEmptyKey() - 1L; }
|
||||
static unsigned getHashValue(const long& Val) {
|
||||
return (unsigned)(Val * 37L);
|
||||
return (unsigned)(Val * 37UL);
|
||||
}
|
||||
static bool isEqual(const long& LHS, const long& RHS) {
|
||||
return LHS == RHS;
|
||||
@ -121,7 +121,7 @@ template<> struct DenseMapInfo<long long> {
|
||||
static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; }
|
||||
static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; }
|
||||
static unsigned getHashValue(const long long& Val) {
|
||||
return (unsigned)(Val * 37LL);
|
||||
return (unsigned)(Val * 37ULL);
|
||||
}
|
||||
static bool isEqual(const long long& LHS,
|
||||
const long long& RHS) {
|
||||
@ -142,7 +142,7 @@ struct DenseMapInfo<std::pair<T, U> > {
|
||||
}
|
||||
static inline Pair getTombstoneKey() {
|
||||
return std::make_pair(FirstInfo::getTombstoneKey(),
|
||||
SecondInfo::getEmptyKey());
|
||||
SecondInfo::getTombstoneKey());
|
||||
}
|
||||
static unsigned getHashValue(const Pair& PairVal) {
|
||||
uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32
|
||||
@ -158,7 +158,7 @@ struct DenseMapInfo<std::pair<T, U> > {
|
||||
return (unsigned)key;
|
||||
}
|
||||
static bool isEqual(const Pair &LHS, const Pair &RHS) {
|
||||
return FirstInfo::isEqual(LHS.first, RHS.first) &&
|
||||
return FirstInfo::isEqual(LHS.first, RHS.first) &&
|
||||
SecondInfo::isEqual(LHS.second, RHS.second);
|
||||
}
|
||||
};
|
||||
|
@ -28,7 +28,7 @@ class DenseSet {
|
||||
MapTy TheMap;
|
||||
public:
|
||||
DenseSet(const DenseSet &Other) : TheMap(Other.TheMap) {}
|
||||
explicit DenseSet(unsigned NumInitBuckets = 64) : TheMap(NumInitBuckets) {}
|
||||
explicit DenseSet(unsigned NumInitBuckets = 0) : TheMap(NumInitBuckets) {}
|
||||
|
||||
bool empty() const { return TheMap.empty(); }
|
||||
unsigned size() const { return TheMap.size(); }
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user