On Sun, Jan 24, 2016 at 01:28:34PM +0100, Pascal Stumpf wrote: > On Sun, 24 Jan 2016 04:13:47 +0100, Juan Francisco Cantero Hurtado wrote: > > On Sun, Jan 24, 2016 at 12:07:03AM +0000, Stuart Henderson wrote: > > > I wouldn't say that this works well with gcc. I would recommend against > > > keeping multiple versions of a port without a good and specific reason. > > > > In the gcc case, the latest version is imported, people works on their > > ports and when everything works fine with the latest version, this is > > promoted as the default version and the older version is deleted. If > > some of my ports are broken, I can change MODGCC4_VER and to work > > individually in one port without to break other packages which I use > > but I don't know how to help to fix the problems. > > That's more of a side effect. The actual reason the split is still > there is the fact that some architectures tend to get broken by GCC > upstream frequently. Right now, alpha is stuck on 4.6. > > So far, there has been no need for an arch-based split in LLVM (thank > god). Regarding the update process, I see no reason why this can't be > done like with any other port (submit update, bulk build, fix bugs, > repeat). > > In addition, the LLVM development process is more streamlined. They > focus more on getting the current trunk up to a decent state than > maintaining a bazillion 3.x branches. The 3.4 version we have in our > tree is *ancient* by their standards. Using it is like using OpenBSD > 5.4 and then coming to misc@ with a bug report. You will get told to > retry with -current. Rightfully. > > > > In addition to that, I would like various versions of llvm (not just > > clang) because more and more interpreters/compilers depend of llvm and > > we can't have updated packages because for any reason we can't update > > llvm due to some conflict with other packages. (example: rubinius > > deletion or people wasting their time trying to build an updated llvm > > during the first attemps to port rust) > > But that is not the case right now. Nothing in the tree is specifically > stuck on LLVM 3.4. If that changes, I'd be happy to revisit the > decision.
Just to clarify. I was not asking to keep 3.4 in the tree. I was thinking in future releases of LLVM. Anyway, a lot of opposition to my idea, so go ahead with the update. > > > That said, I'm obviously not going to maintain llvm and others will do > > the hard work, so my request is just a hope and not a red line or > > something similar :) > > > > > > > > > > > On 23 January 2016 22:16:16 GMT+00:00, Juan Francisco Cantero Hurtado > > > <i...@juanfra.info> wrote: > > > >Can you modify the structure of devel/llvm/ to something like > > > >devel/llvm/version/? With lang/gcc works pretty well, we can work with > > > >the latest version while the ports tree uses the stable version by > > > >default. > > > > > > > > > > > >On Sat, Jan 23, 2016 at 07:39:22PM +0100, Pascal Stumpf wrote: > > > >> So here's an updated diff for LLVM 3.7.1. With landry@'s recent > > > >commit, > > > >> xulrunner is no longer a showstopper. > > > >> > > > >> > > > >> Index: Makefile > > > >> =================================================================== > > > >> RCS file: /cvs/ports/devel/llvm/Makefile,v > > > >> retrieving revision 1.108 > > > >> diff -u -p -r1.108 Makefile > > > >> --- Makefile 24 Aug 2015 07:45:56 -0000 1.108 > > > >> +++ Makefile 23 Jan 2016 18:38:51 -0000 > > > >> @@ -8,14 +8,17 @@ DPB_PROPERTIES = parallel > > > >> > > > >> COMMENT = modular, fast C/C++/ObjC compiler, static analyzer and > > > >tools > > > >> > > > >> -LLVM_V = 3.5 > > > >> -DISTNAME = llvm-${LLVM_V}.20140228 > > > >> -REVISION = 35 > > > >> +LLVM_V = 3.7.1 > > > >> +DISTNAME = llvm-${LLVM_V}.src > > > >> +PKGNAME = llvm-${LLVM_V} > > > >> CATEGORIES = devel > > > >> -MASTER_SITES = http://comstyle.com/source/ > > > >> +DISTFILES = llvm-${LLVM_V}.src${EXTRACT_SUFX} \ > > > >> + cfe-${LLVM_V}.src${EXTRACT_SUFX} > > > >> +MASTER_SITES = http://www.llvm.org/releases/${LLVM_V}/ > > > >> EXTRACT_SUFX = .tar.xz > > > >> > > > >> -SHARED_LIBS = clang 1.0 > > > >> +SHARED_LIBS = clang 2.0 \ > > > >> + LTO 0.0 > > > >> > > > >> # packager notes in http://llvm.org/docs/Packaging.html > > > >> HOMEPAGE = http://www.llvm.org/ > > > >> @@ -25,15 +28,21 @@ MAINTAINER= Brad Smith <b...@comstyle.co > > > >> # BSD > > > >> PERMIT_PACKAGE_CDROM = Yes > > > >> > > > >> -WANTLIB = c m pthread stdc++ z > > > >> +WANTLIB = c m pthread z > > > >> > > > >> MODULES = devel/cmake \ > > > >> - lang/python > > > >> + lang/python \ > > > >> + gcc4 > > > >> > > > >> -TEST_DEPENDS = devel/dejagnu \ > > > >> - shells/bash > > > >> +MODGCC4_LANGS = c c++ > > > >> +MODGCC4_ARCHS = * > > > >> + > > > >> +TEST_DEPENDS = devel/dejagnu \ > > > >> + shells/bash \ > > > >> + lang/gcc/${MODGCC4_VERSION},-c++ > > > >> BUILD_DEPENDS += textproc/py-sphinx > > > >> -RUN_DEPENDS += devel/gtest > > > >> +RUN_DEPENDS += devel/gtest \ > > > >> + lang/gcc/${MODGCC4_VERSION},-c++ > > > >> > > > >> SEPARATE_BUILD = Yes > > > >> CONFIGURE_ARGS = -DLLVM_ENABLE_FFI:Bool=False \ > > > >> @@ -47,22 +56,34 @@ CONFIGURE_ARGS = -DLLVM_ENABLE_FFI:Bool= > > > >> # introduced when PIE was enabled > > > >> .if ${MACHINE_ARCH} == "powerpc" > > > >> CONFIGURE_ARGS += -DCMAKE_EXE_LINKER_FLAGS="-Wl,--relax -nopie" > > > >> +CONFIGURE_ARGS += -DCMAKE_SHARED_LINKER_FLAGS="-Wl,--relax -nopie" > > > >> .endif > > > >> > > > >> TEST_TARGET = check > > > >> > > > >> +# XXX sync > > > >> +GCC_VER = 4.9.3 > > > >> +.if ${MACHINE_ARCH} == "amd64" > > > >> +GCC_CONFIG = x86_64-unknown-openbsd${OSREV} > > > >> +.else > > > >> +GCC_CONFIG = ${MACHINE_ARCH}-unknown-openbsd${OSREV} > > > >> +.endif > > > >> CLANG_INCLUDE_PATH = lib/clang/${LLVM_V}/include > > > >> -SUBST_VARS += CLANG_INCLUDE_PATH LLVM_V > > > >> +SUBST_VARS += CLANG_INCLUDE_PATH LLVM_V GCC_VER GCC_CONFIG > > > >> + > > > >> +post-extract: > > > >> + mv ${WRKDIR}/cfe-${LLVM_V}.src ${WRKSRC}/tools/clang > > > >> > > > >> pre-configure: > > > >> - @${SUBST_CMD} ${WRKSRC}/tools/clang/tools/scan-build/scan-build > > > >> + @${SUBST_CMD} ${WRKSRC}/tools/clang/tools/scan-build/scan-build > > > >> \ > > > >> + ${WRKSRC}/tools/clang/lib/Driver/ToolChains.cpp > > > >> + @${SUBST_CMD} ${WRKSRC}/tools/clang/tools/scan-build/scan-build > > > >> \ > > > >> + ${WRKSRC}/tools/clang/lib/Driver/Tools.cpp > > > >> -@ln -s ${MODPY_BIN} ${WRKDIR}/bin/python > > > >> > > > >> post-build: > > > >> cd ${WRKSRC}/docs && make -f Makefile.sphinx man > > > >> - pod2man --release=CVS --center="LLVM" \ > > > >> - ${WRKSRC}/tools/clang/docs/tools/clang.pod \ > > > >> - ${WRKSRC}/docs/_build/man/clang.1 > > > >> + cd ${WRKSRC}/tools/clang/docs && make -f Makefile.sphinx man > > > >> > > > >> post-install: > > > >> ${INSTALL_SCRIPT} > > > >${WRKSRC}/tools/clang/tools/scan-build/ccc-analyzer \ > > > >> @@ -75,7 +96,10 @@ post-install: > > > >> ${PREFIX}/man/man1 > > > >> ${INSTALL_DATA} > > > >> ${WRKSRC}/tools/clang/tools/scan-build/scan-build.1 > > > >\ > > > >> ${PREFIX}/man/man1 > > > >> - # lit is not installed anymore > > > >> + ${INSTALL_DATA} ${WRKSRC}/tools/clang/docs/_build/man/clang.1 \ > > > >> + ${PREFIX}/man/man1 > > > >> + # lit and FileCheck are not installed > > > >> @rm ${PREFIX}/man/man1/lit.1 > > > >> + @rm ${PREFIX}/man/man1/FileCheck.1 > > > >> > > > >> .include <bsd.port.mk> > > > >> Index: distinfo > > > >> =================================================================== > > > >> RCS file: /cvs/ports/devel/llvm/distinfo,v > > > >> retrieving revision 1.13 > > > >> diff -u -p -r1.13 distinfo > > > >> --- distinfo 18 Apr 2014 09:30:48 -0000 1.13 > > > >> +++ distinfo 23 Jan 2016 18:38:51 -0000 > > > >> @@ -1,2 +1,4 @@ > > > >> -SHA256 (llvm-3.5.20140228.tar.xz) = > > > >vBFmbVEiY2CQZf7Boqcebh+s+ejpfpoZ8vY5c3cxgXw= > > > >> -SIZE (llvm-3.5.20140228.tar.xz) = 17945548 > > > >> +SHA256 (cfe-3.7.1.src.tar.xz) = > > > >VuIWTHwqF3LV7So+V0hf9z/wbJff8S7b7qGsxEErBnQ= > > > >> +SHA256 (llvm-3.7.1.src.tar.xz) = > > > >vneU7QzsQtbGgsqONRdTW1RVWj3vq+yDVU28dNtUWtU= > > > >> +SIZE (cfe-3.7.1.src.tar.xz) = 9110616 > > > >> +SIZE (llvm-3.7.1.src.tar.xz) = 14592544 > > > >> Index: patches/patch-CMakeLists_txt > > > >> =================================================================== > > > >> RCS file: patches/patch-CMakeLists_txt > > > >> diff -N patches/patch-CMakeLists_txt > > > >> --- patches/patch-CMakeLists_txt 18 Apr 2014 09:30:48 -0000 > > > >> 1.4 > > > >> +++ /dev/null 1 Jan 1970 00:00:00 -0000 > > > >> @@ -1,15 +0,0 @@ > > > >> -$OpenBSD: patch-CMakeLists_txt,v 1.4 2014/04/18 09:30:48 brad Exp $ > > > >> - > > > >> -Don't confuse scripts who want the version with appended 'svn' goo. > > > >> - > > > >> ---- CMakeLists.txt.orig Sun Mar 2 21:57:43 2014 > > > >> -+++ CMakeLists.txt Sun Mar 2 22:13:02 2014 > > > >> -@@ -29,7 +29,7 @@ set(LLVM_VERSION_MAJOR 3) > > > >> - set(LLVM_VERSION_MINOR 5) > > > >> - > > > >> - if (NOT PACKAGE_VERSION) > > > >> -- set(PACKAGE_VERSION > > > >"${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}svn") > > > >> -+ set(PACKAGE_VERSION > > > >"${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}") > > > >> - endif() > > > >> - > > > >> - option(LLVM_INSTALL_TOOLCHAIN_ONLY "Only include toolchain files in > > > >the 'install' target." OFF) > > > >> Index: patches/patch-Makefile_config_in > > > >> =================================================================== > > > >> RCS file: /cvs/ports/devel/llvm/patches/patch-Makefile_config_in,v > > > >> retrieving revision 1.8 > > > >> diff -u -p -r1.8 patch-Makefile_config_in > > > >> --- patches/patch-Makefile_config_in 18 Apr 2014 09:30:48 -0000 > > > >> 1.8 > > > >> +++ patches/patch-Makefile_config_in 23 Jan 2016 18:38:51 -0000 > > > >> @@ -1,7 +1,7 @@ > > > >> $OpenBSD: patch-Makefile_config_in,v 1.8 2014/04/18 09:30:48 brad > > > >Exp $ > > > >> ---- Makefile.config.in.orig Sun Feb 16 19:19:46 2014 > > > >> -+++ Makefile.config.in Sun Feb 16 19:28:35 2014 > > > >> -@@ -99,11 +99,11 @@ endif > > > >> +--- Makefile.config.in.orig Wed Aug 12 19:12:16 2015 > > > >> ++++ Makefile.config.in Tue Sep 8 21:53:49 2015 > > > >> +@@ -106,11 +106,11 @@ endif > > > >> PROJ_bindir := $(PROJ_prefix)/bin > > > >> PROJ_libdir := $(PROJ_prefix)/lib > > > >> PROJ_datadir := $(PROJ_prefix)/share > > > >> Index: patches/patch-cmake_modules_AddLLVM_cmake > > > >> =================================================================== > > > >> RCS file: patches/patch-cmake_modules_AddLLVM_cmake > > > >> diff -N patches/patch-cmake_modules_AddLLVM_cmake > > > >> --- /dev/null 1 Jan 1970 00:00:00 -0000 > > > >> +++ patches/patch-cmake_modules_AddLLVM_cmake 23 Jan 2016 18:38:51 > > > >-0000 > > > >> @@ -0,0 +1,12 @@ > > > >> +$OpenBSD$ > > > >> +--- cmake/modules/AddLLVM.cmake.orig Fri Sep 11 17:38:23 2015 > > > >> ++++ cmake/modules/AddLLVM.cmake Fri Sep 11 17:39:48 2015 > > > >> +@@ -178,7 +178,7 @@ function(add_link_opts target_name) > > > >> + elseif(${CMAKE_SYSTEM_NAME} MATCHES "SunOS") > > > >> + set_property(TARGET ${target_name} APPEND_STRING PROPERTY > > > >> + LINK_FLAGS " -Wl,-z > > > >-Wl,discard-unused=sections") > > > >> +- elseif(NOT WIN32 AND NOT LLVM_LINKER_IS_GOLD) > > > >> ++ elseif(NOT WIN32 AND NOT LLVM_LINKER_IS_GOLD AND NOT > > > >${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") > > > >> + # Object files are compiled with -ffunction-data-sections. > > > >> + # Versions of bfd ld < 2.23.1 have a bug in --gc-sections > > > >that breaks > > > >> + # tools that use plugins. Always pass --gc-sections once we > > > >require > > > >> Index: patches/patch-cmake_modules_HandleLLVMOptions_cmake > > > >> =================================================================== > > > >> RCS file: > > > >/cvs/ports/devel/llvm/patches/patch-cmake_modules_HandleLLVMOptions_cmake,v > > > >> retrieving revision 1.1 > > > >> diff -u -p -r1.1 patch-cmake_modules_HandleLLVMOptions_cmake > > > >> --- patches/patch-cmake_modules_HandleLLVMOptions_cmake 18 Apr > > > >> 2014 > > > >09:30:48 -0000 1.1 > > > >> +++ patches/patch-cmake_modules_HandleLLVMOptions_cmake 23 Jan > > > >> 2016 > > > >18:38:51 -0000 > > > >> @@ -1,49 +1,13 @@ > > > >> -$OpenBSD: patch-cmake_modules_HandleLLVMOptions_cmake,v 1.1 > > > >2014/04/18 09:30:48 brad Exp $ > > > >> ---- cmake/modules/HandleLLVMOptions.cmake.orig Sat Feb 8 > > > >> 15:05:05 > > > >2014 > > > >> -+++ cmake/modules/HandleLLVMOptions.cmake Sat Feb 8 15:05:17 2014 > > > >> -@@ -7,45 +7,6 @@ include(AddLLVMDefinitions) > > > >> - include(CheckCCompilerFlag) > > > >> - include(CheckCXXCompilerFlag) > > > >> - > > > >> --if(NOT LLVM_FORCE_USE_OLD_TOOLCHAIN) > > > >> -- if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") > > > >> -- if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7) > > > >> -- message(FATAL_ERROR "Host GCC version must be at least 4.7!") > > > >> -- endif() > > > >> -- elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") > > > >> -- if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.1) > > > >> -- message(FATAL_ERROR "Host Clang version must be at least > > > >3.1!") > > > >> -- endif() > > > >> -- > > > >> -- # Also test that we aren't using too old of a version of > > > >libstdc++ with the > > > >> -- # Clang compiler. This is tricky as there is no real way to > > > >check the > > > >> -- # version of libstdc++ directly. Instead we test for a known > > > >bug in > > > >> -- # libstdc++4.6 that is fixed in libstdc++4.7. > > > >> -- if(NOT LLVM_ENABLE_LIBCXX) > > > >> -- set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) > > > >> -- set(OLD_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) > > > >> -- set(CMAKE_REQUIRED_FLAGS "-std=c++0x") > > > >> -- if (ANDROID) > > > >> -- set(CMAKE_REQUIRED_LIBRARIES "atomic") > > > >> -- endif() > > > >> -- check_cxx_source_compiles(" > > > >> --#include <atomic> > > > >> --std::atomic<float> x(0.0f); > > > >> --int main() { return (float)x; }" > > > >> -- LLVM_NO_OLD_LIBSTDCXX) > > > >> -- if(NOT LLVM_NO_OLD_LIBSTDCXX) > > > >> -- message(FATAL_ERROR "Host Clang must be able to find > > > >libstdc++4.7 or newer!") > > > >> -- endif() > > > >> -- set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) > > > >> -- set(CMAKE_REQUIRED_LIBRARIES ${OLD_CMAKE_REQUIRED_LIBRARIES}) > > > >> -- endif() > > > >> -- elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") > > > >> -- if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17.0) > > > >> -- message(FATAL_ERROR "Host Visual Studio must be at least 2012 > > > >(MSVC 17.0)") > > > >> -- endif() > > > >> -- endif() > > > >> --endif() > > > >> -- > > > >> - if( LLVM_ENABLE_ASSERTIONS ) > > > >> - # MSVC doesn't like _DEBUG on release builds. See PR 4379. > > > >> - if( NOT MSVC ) > > > >> +$OpenBSD$ > > > >> +--- cmake/modules/HandleLLVMOptions.cmake.orig Wed Sep 9 > > > >> 14:34:05 > > > >2015 > > > >> ++++ cmake/modules/HandleLLVMOptions.cmake Wed Sep 9 14:34:55 2015 > > > >> +@@ -132,7 +132,8 @@ endif() > > > >> + # Pass -Wl,-z,defs. This makes sure all symbols are defined. > > > >Otherwise a DSO > > > >> + # build might work on ELF but fail on MachO/COFF. > > > >> + if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32 OR CYGWIN OR > > > >> +- ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") AND > > > >> ++ ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" OR > > > >> ++ ${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") AND > > > >> + NOT LLVM_USE_SANITIZER) > > > >> + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} > > > >-Wl,-z,defs") > > > >> + endif() > > > >> Index: patches/patch-include_llvm_CodeGen_SelectionDAGISel_h > > > >> =================================================================== > > > >> RCS file: patches/patch-include_llvm_CodeGen_SelectionDAGISel_h > > > >> diff -N patches/patch-include_llvm_CodeGen_SelectionDAGISel_h > > > >> --- patches/patch-include_llvm_CodeGen_SelectionDAGISel_h 24 Aug > > > >> 2015 > > > >07:45:56 -0000 1.1 > > > >> +++ /dev/null 1 Jan 1970 00:00:00 -0000 > > > >> @@ -1,59 +0,0 @@ > > > >> -$OpenBSD: patch-include_llvm_CodeGen_SelectionDAGISel_h,v 1.1 > > > >2015/08/24 07:45:56 ajacoutot Exp $ > > > >> - > > > >> -r219009 > > > >> -[ISel] Keep matching state consistent when folding during X86 > > > >address match > > > >> - > > > >> -In the X86 backend, matching an address is initiated by the 'addr' > > > >complex > > > >> -pattern and its friends. During this process we may reassociate > > > >and-of-shift > > > >> -into shift-of-and (FoldMaskedShiftToScaledMask) to allow folding of > > > >the > > > >> -shift into the scale of the address. > > > >> - > > > >> -However as demonstrated by the testcase, this can trigger CSE of not > > > >only the > > > >> -shift and the AND which the code is prepared for but also the > > > >underlying load > > > >> -node. In the testcase this node is sitting in the RecordedNode and > > > >MatchScope > > > >> -data structures of the matcher and becomes a deleted node upon CSE. > > > >Returning > > > >> -from the complex pattern function, we try to access it again hitting > > > >an assert > > > >> -because the node is no longer a load even though this was checked > > > >before. > > > >> - > > > >> -Now obviously changing the DAG this late is bending the rules but I > > > >think it > > > >> -makes sense somewhat. Outside of addresses we prefer and-of-shift > > > >because it > > > >> -may lead to smaller immediates (FoldMaskAndShiftToScale is an even > > > >better > > > >> -example because it create a non-canonical node). We currently don't > > > >recognize > > > >> -addresses during DAGCombiner where arguably this canonicalization > > > >should be > > > >> -performed. On the other hand, having this in the matcher allows us > > > >to cover > > > >> -all the cases where an address can be used in an instruction. > > > >> - > > > >> -I've also talked a little bit to Dan Gohman on llvm-dev who added > > > >the RAUW for > > > >> -the new shift node in FoldMaskedShiftToScaledMask. This RAUW is > > > >responsible > > > >> -for initiating the recursive CSE on users > > > >> > > > >-(http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-September/076903.html) > > > >but it > > > >> -is not strictly necessary since the shift is hooked into the visited > > > >user. Of > > > >> -course it's safer to keep the DAG consistent at all times (e.g. for > > > >accurate > > > >> -number of uses, etc.). > > > >> - > > > >> -So rather than changing the fundamentals, I've decided to continue > > > >along the > > > >> -previous patches and detect the CSE. This patch installs a very > > > >targeted > > > >> -DAGUpdateListener for the duration of a complex-pattern match and > > > >updates the > > > >> -matching state accordingly. (Previous patches used HandleSDNode to > > > >detect the > > > >> -CSE but that's not practical here). The listener is only installed > > > >on X86. > > > >> - > > > >> -I tested that there is no measurable overhead due to this while > > > >running > > > >> -through the spec2k BC files with llc. The only thing we pay for is > > > >the > > > >> -creation of the listener. The callback never ever triggers in > > > >spec2k since > > > >> -this is a corner case. > > > >> - > > > >> ---- include/llvm/CodeGen/SelectionDAGISel.h.orig Tue Aug 4 > > > >> 22:44:44 > > > >2015 > > > >> -+++ include/llvm/CodeGen/SelectionDAGISel.h Tue Aug 4 22:46:22 2015 > > > >> -@@ -238,6 +238,12 @@ class SelectionDAGISel : public > > > >MachineFunctionPass { > > > >> - const unsigned char *MatcherTable, > > > >> - unsigned TableSize); > > > >> - > > > >> -+ /// \brief Return true if complex patterns for this target can > > > >mutate the > > > >> -+ /// DAG. > > > >> -+ virtual bool ComplexPatternFuncMutatesDAG() const { > > > >> -+ return false; > > > >> -+ } > > > >> -+ > > > >> - private: > > > >> - > > > >> - // Calls to these functions are generated by tblgen. > > > >> Index: patches/patch-include_llvm_CodeGen_SelectionDAG_h > > > >> =================================================================== > > > >> RCS file: patches/patch-include_llvm_CodeGen_SelectionDAG_h > > > >> diff -N patches/patch-include_llvm_CodeGen_SelectionDAG_h > > > >> --- patches/patch-include_llvm_CodeGen_SelectionDAG_h 15 Nov 2014 > > > >03:26:40 -0000 1.1 > > > >> +++ /dev/null 1 Jan 1970 00:00:00 -0000 > > > >> @@ -1,30 +0,0 @@ > > > >> -$OpenBSD: patch-include_llvm_CodeGen_SelectionDAG_h,v 1.1 2014/11/15 > > > >03:26:40 brad Exp $ > > > >> - > > > >> -r221709 > > > >> -Totally forget deallocated SDNodes in SDDbgInfo. > > > >> - > > > >> -What would happen before that commit is that the SDDbgValues > > > >associated with > > > >> -a deallocated SDNode would be marked Invalidated, but SDDbgInfo > > > >would keep > > > >> -a map entry keyed by the SDNode pointer pointing to this list of > > > >invalidated > > > >> -SDDbgNodes. As the memory gets reused, the list might get wrongly > > > >associated > > > >> -with another new SDNode. As the SDDbgValues are cloned when they are > > > >transfered, > > > >> -this can lead to an exponential number of SDDbgValues being produced > > > >during > > > >> -DAGCombine like in http://llvm.org/bugs/show_bug.cgi?id=20893 > > > >> - > > > >> -Note that the previous behavior wasn't really buggy as the > > > >invalidation made > > > >> -sure that the SDDbgValues won't be used. This commit can be > > > >considered a > > > >> -memory optimization and as such is really hard to validate in a > > > >unit-test. > > > >> - > > > >> ---- include/llvm/CodeGen/SelectionDAG.h.orig Fri Nov 14 21:08:36 > > > >2014 > > > >> -+++ include/llvm/CodeGen/SelectionDAG.h Fri Nov 14 21:09:49 2014 > > > >> -@@ -126,6 +126,10 @@ class SDDbgInfo { (public) > > > >> - DbgValMap[Node].push_back(V); > > > >> - } > > > >> - > > > >> -+ /// \brief Invalidate all DbgValues attached to the node and > > > >remove > > > >> -+ /// it from the Node-to-DbgValues map. > > > >> -+ void erase(const SDNode *Node); > > > >> -+ > > > >> - void clear() { > > > >> - DbgValMap.clear(); > > > >> - DbgValues.clear(); > > > >> Index: patches/patch-include_llvm_Config_config_h_cmake > > > >> =================================================================== > > > >> RCS file: patches/patch-include_llvm_Config_config_h_cmake > > > >> diff -N patches/patch-include_llvm_Config_config_h_cmake > > > >> --- patches/patch-include_llvm_Config_config_h_cmake 26 Jul 2014 > > > >09:27:29 -0000 1.1 > > > >> +++ /dev/null 1 Jan 1970 00:00:00 -0000 > > > >> @@ -1,16 +0,0 @@ > > > >> -$OpenBSD: patch-include_llvm_Config_config_h_cmake,v 1.1 2014/07/26 > > > >09:27:29 pascal Exp $ > > > >> - > > > >> -r213966 > > > >> -Fix arc4random detection. > > > >> - > > > >> ---- include/llvm/Config/config.h.cmake.orig Wed Jul 9 15:45:23 2014 > > > >> -+++ include/llvm/Config/config.h.cmake Wed Jul 9 15:59:51 2014 > > > >> -@@ -34,7 +34,7 @@ > > > >> - #undef GCC_INSTALL_PREFIX > > > >> - > > > >> - /* Define to 1 if you have the `arc4random' function. */ > > > >> --#cmakedefine HAVE_ARC4RANDOM > > > >> -+#cmakedefine HAVE_DECL_ARC4RANDOM ${HAVE_DECL_ARC4RANDOM} > > > >> - > > > >> - /* Define to 1 if you have the `backtrace' function. */ > > > >> - #cmakedefine HAVE_BACKTRACE ${HAVE_BACKTRACE} > > > >> Index: patches/patch-include_llvm_Support_ELF_h > > > >> =================================================================== > > > >> RCS file: patches/patch-include_llvm_Support_ELF_h > > > >> diff -N patches/patch-include_llvm_Support_ELF_h > > > >> --- patches/patch-include_llvm_Support_ELF_h 11 Sep 2014 17:54:13 > > > >-0000 1.1 > > > >> +++ /dev/null 1 Jan 1970 00:00:00 -0000 > > > >> @@ -1,19 +0,0 @@ > > > >> -$OpenBSD: patch-include_llvm_Support_ELF_h,v 1.1 2014/09/11 17:54:13 > > > >brad Exp $ > > > >> - > > > >> -r213427 > > > >> -[PowerPC] 32-bit ELF PIC support > > > >> - > > > >> -This adds initial support for PPC32 ELF PIC (Position Independent > > > >Code; the > > > >> --fPIC variety), thus rectifying a long-standing deficiency in the > > > >PowerPC > > > >> -backend. > > > >> - > > > >> ---- include/llvm/Support/ELF.h.orig Sun Jul 27 00:01:21 2014 > > > >> -+++ include/llvm/Support/ELF.h Sun Jul 27 00:02:18 2014 > > > >> -@@ -437,6 +437,7 @@ enum { > > > >> - R_PPC_GOT16_LO = 15, > > > >> - R_PPC_GOT16_HI = 16, > > > >> - R_PPC_GOT16_HA = 17, > > > >> -+ R_PPC_PLTREL24 = 18, > > > >> - R_PPC_REL32 = 26, > > > >> - R_PPC_TLS = 67, > > > >> - R_PPC_DTPMOD32 = 68, > > > >> Index: patches/patch-include_llvm_Target_TargetInstrInfo_h > > > >> =================================================================== > > > >> RCS file: patches/patch-include_llvm_Target_TargetInstrInfo_h > > > >> diff -N patches/patch-include_llvm_Target_TargetInstrInfo_h > > > >> --- patches/patch-include_llvm_Target_TargetInstrInfo_h 18 Sep > > > >> 2014 > > > >20:19:27 -0000 1.1 > > > >> +++ /dev/null 1 Jan 1970 00:00:00 -0000 > > > >> @@ -1,32 +0,0 @@ > > > >> -$OpenBSD: patch-include_llvm_Target_TargetInstrInfo_h,v 1.1 > > > >2014/09/18 20:19:27 brad Exp $ > > > >> - > > > >> -r217801 > > > >> -Fix a lot of confusion around inserting nops on empty functions. > > > >> - > > > >> -On MachO, and MachO only, we cannot have a truly empty function > > > >since that > > > >> -breaks the linker logic for atomizing the section. > > > >> - > > > >> -When we are emitting a frame pointer, the presence of an unreachable > > > >will > > > >> -create a cfi instruction pointing past the last instruction. This is > > > >perfectly > > > >> -fine. The FDE information encodes the pc range it applies to. If > > > >some tool > > > >> -cannot handle this, we should explicitly say which bug we are > > > >working around > > > >> -and only work around it when it is actually relevant (not for ELF > > > >for example). > > > >> - > > > >> -Given the unreachable we could omit the .cfi_def_cfa_register, but > > > >then > > > >> -again, we could also omit the entire function prologue if we wanted > > > >to. > > > >> - > > > >> ---- include/llvm/Target/TargetInstrInfo.h.orig Mon Sep 15 > > > >> 16:00:35 > > > >2014 > > > >> -+++ include/llvm/Target/TargetInstrInfo.h Mon Sep 15 16:01:15 2014 > > > >> -@@ -661,10 +661,8 @@ class TargetInstrInfo : public MCInstrInfo { > > > >(public) > > > >> - MachineBasicBlock::iterator MI) const; > > > >> - > > > >> - > > > >> -- /// getNoopForMachoTarget - Return the noop instruction to use > > > >for a noop. > > > >> -- virtual void getNoopForMachoTarget(MCInst &NopInst) const { > > > >> -- // Default to just using 'nop' string. > > > >> -- } > > > >> -+ /// Return the noop instruction to use for a noop. > > > >> -+ virtual void getNoopForMachoTarget(MCInst &NopInst) const; > > > >> - > > > >> - > > > >> - /// isPredicated - Returns true if the instruction is already > > > >predicated. > > > >> Index: patches/patch-lib_Analysis_IVUsers_cpp > > > >> =================================================================== > > > >> RCS file: patches/patch-lib_Analysis_IVUsers_cpp > > > >> diff -N patches/patch-lib_Analysis_IVUsers_cpp > > > >> --- patches/patch-lib_Analysis_IVUsers_cpp 10 Jul 2014 22:46:37 > > > >-0000 1.1 > > > >> +++ /dev/null 1 Jan 1970 00:00:00 -0000 > > > >> @@ -1,45 +0,0 @@ > > > >> -$OpenBSD: patch-lib_Analysis_IVUsers_cpp,v 1.1 2014/07/10 22:46:37 > > > >brad Exp $ > > > >> - > > > >> -r203719 > > > >> -PR17473: Don't normalize an expression during postinc transformation > > > >unless it's > > > >> -invertible. > > > >> - > > > >> ---- lib/Analysis/IVUsers.cpp.orig Sun Mar 2 21:57:38 2014 > > > >> -+++ lib/Analysis/IVUsers.cpp Sat Jun 14 03:56:54 2014 > > > >> -@@ -186,15 +186,34 @@ bool IVUsers::AddUsersImpl(Instruction *I, > > > >> - > > > >> - if (AddUserToIVUsers) { > > > >> - // Okay, we found a user that we cannot reduce. > > > >> -- IVUses.push_back(new IVStrideUse(this, User, I)); > > > >> -- IVStrideUse &NewUse = IVUses.back(); > > > >> -+ IVStrideUse &NewUse = AddUser(User, I); > > > >> - // Autodetect the post-inc loop set, populating > > > >NewUse.PostIncLoops. > > > >> - // The regular return value here is discarded; instead of > > > >recording > > > >> - // it, we just recompute it when we need it. > > > >> -+ const SCEV *OriginalISE = ISE; > > > >> - ISE = TransformForPostIncUse(NormalizeAutodetect, > > > >> - ISE, User, I, > > > >> - NewUse.PostIncLoops, > > > >> - *SE, *DT); > > > >> -+ > > > >> -+ // PostIncNormalization effectively simplifies the expression > > > >under > > > >> -+ // pre-increment assumptions. Those assumptions (no wrapping) > > > >might not > > > >> -+ // hold for the post-inc value. Catch such cases by making > > > >sure the > > > >> -+ // transformation is invertible. > > > >> -+ if (OriginalISE != ISE) { > > > >> -+ const SCEV *DenormalizedISE = > > > >> -+ TransformForPostIncUse(Denormalize, ISE, User, I, > > > >> -+ NewUse.PostIncLoops, *SE, *DT); > > > >> -+ > > > >> -+ // If we normalized the expression, but denormalization > > > >doesn't give the > > > >> -+ // original one, discard this user. > > > >> -+ if (OriginalISE != DenormalizedISE) { > > > >> -+ DEBUG(dbgs() << " DISCARDING (NORMALIZATION ISN'T > > > >INVERTIBLE): " > > > >> -+ << *ISE << '\n'); > > > >> -+ IVUses.pop_back(); > > > >> -+ return false; > > > >> -+ } > > > >> -+ } > > > >> - DEBUG(if (SE->getSCEV(I) != ISE) > > > >> - dbgs() << " NORMALIZED TO: " << *ISE << '\n'); > > > >> - } > > > >> Index: patches/patch-lib_CodeGen_AsmPrinter_AsmPrinter_cpp > > > >> =================================================================== > > > >> RCS file: patches/patch-lib_CodeGen_AsmPrinter_AsmPrinter_cpp > > > >> diff -N patches/patch-lib_CodeGen_AsmPrinter_AsmPrinter_cpp > > > >> --- patches/patch-lib_CodeGen_AsmPrinter_AsmPrinter_cpp 18 Sep > > > >> 2014 > > > >20:19:27 -0000 1.1 > > > >> +++ /dev/null 1 Jan 1970 00:00:00 -0000 > > > >> @@ -1,68 +0,0 @@ > > > >> -$OpenBSD: patch-lib_CodeGen_AsmPrinter_AsmPrinter_cpp,v 1.1 > > > >2014/09/18 20:19:27 brad Exp $ > > > >> - > > > >> -r217801 > > > >> -Fix a lot of confusion around inserting nops on empty functions. > > > >> - > > > >> -On MachO, and MachO only, we cannot have a truly empty function > > > >since that > > > >> -breaks the linker logic for atomizing the section. > > > >> - > > > >> -When we are emitting a frame pointer, the presence of an unreachable > > > >will > > > >> -create a cfi instruction pointing past the last instruction. This is > > > >perfectly > > > >> -fine. The FDE information encodes the pc range it applies to. If > > > >some tool > > > >> -cannot handle this, we should explicitly say which bug we are > > > >working around > > > >> -and only work around it when it is actually relevant (not for ELF > > > >for example). > > > >> - > > > >> -Given the unreachable we could omit the .cfi_def_cfa_register, but > > > >then > > > >> -again, we could also omit the entire function prologue if we wanted > > > >to. > > > >> - > > > >> -r217899 > > > >> -Add back a fallback case for targets that do not or cannot implement > > > >getNoopForMachoTarget(). > > > >> - > > > >> ---- lib/CodeGen/AsmPrinter/AsmPrinter.cpp.orig Sun Mar 2 > > > >> 21:57:42 > > > >2014 > > > >> -+++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp Tue Sep 16 22:33:35 2014 > > > >> -@@ -739,14 +739,12 @@ void AsmPrinter::EmitFunctionBody() { > > > >> - > > > >> - // Print out code for the function. > > > >> - bool HasAnyRealCode = false; > > > >> -- const MachineInstr *LastMI = 0; > > > >> - for (MachineFunction::const_iterator I = MF->begin(), E = > > > >MF->end(); > > > >> - I != E; ++I) { > > > >> - // Print a label for the basic block. > > > >> - EmitBasicBlockStart(I); > > > >> - for (MachineBasicBlock::const_iterator II = I->begin(), IE = > > > >I->end(); > > > >> - II != IE; ++II) { > > > >> -- LastMI = II; > > > >> - > > > >> - // Print the assembly for the instruction. > > > >> - if (!II->isLabel() && !II->isImplicitDef() && !II->isKill() > > > >&& > > > >> -@@ -807,24 +805,18 @@ void AsmPrinter::EmitFunctionBody() { > > > >> - } > > > >> - } > > > >> - > > > >> -- // If the last instruction was a prolog label, then we have a > > > >situation where > > > >> -- // we emitted a prolog but no function body. This results in the > > > >ending prolog > > > >> -- // label equaling the end of function label and an invalid "row" > > > >in the > > > >> -- // FDE. We need to emit a noop in this situation so that the > > > >FDE's rows are > > > >> -- // valid. > > > >> -- bool RequiresNoop = LastMI && LastMI->isPrologLabel(); > > > >> -- > > > >> - // If the function is empty and the object file uses > > > >.subsections_via_symbols, > > > >> - // then we need to emit *something* to the function body to > > > >prevent the > > > >> - // labels from collapsing together. Just emit a noop. > > > >> -- if ((MAI->hasSubsectionsViaSymbols() && !HasAnyRealCode) || > > > >RequiresNoop) { > > > >> -+ if ((MAI->hasSubsectionsViaSymbols() && !HasAnyRealCode)) { > > > >> - MCInst Noop; > > > >> - TM.getInstrInfo()->getNoopForMachoTarget(Noop); > > > >> -- if (Noop.getOpcode()) { > > > >> -- OutStreamer.AddComment("avoids zero-length function"); > > > >> -+ OutStreamer.AddComment("avoids zero-length function"); > > > >> -+ > > > >> -+ // Targets can opt-out of emitting the noop here by leaving the > > > >opcode > > > >> -+ // unspecified. > > > >> -+ if (Noop.getOpcode()) > > > >> - OutStreamer.EmitInstruction(Noop, getSubtargetInfo()); > > > >> -- } else // Target not mc-ized yet. > > > >> -- OutStreamer.EmitRawText(StringRef("\tnop\n")); > > > >> - } > > > >> - > > > >> - const Function *F = MF->getFunction(); > > > >> Index: patches/patch-lib_CodeGen_SelectionDAG_LegalizeTypes_h > > > >> =================================================================== > > > >> RCS file: patches/patch-lib_CodeGen_SelectionDAG_LegalizeTypes_h > > > >> diff -N patches/patch-lib_CodeGen_SelectionDAG_LegalizeTypes_h > > > >> --- patches/patch-lib_CodeGen_SelectionDAG_LegalizeTypes_h 14 Aug > > > >2014 01:08:09 -0000 1.1 > > > >> +++ /dev/null 1 Jan 1970 00:00:00 -0000 > > > >> @@ -1,21 +0,0 @@ > > > >> -$OpenBSD: patch-lib_CodeGen_SelectionDAG_LegalizeTypes_h,v 1.1 > > > >2014/08/14 01:08:09 brad Exp $ > > > >> - > > > >> -r211435 > > > >> -Legalizer: Add support for splitting insert_subvectors. > > > >> - > > > >> -We handle this by spilling the whole thing to the stack and doing > > > >the > > > >> -insertion as a store. > > > >> - > > > >> -PR19492. This happens in real code because the vectorizer creates > > > >v2i128 when AVX is > > > >> -enabled. > > > >> - > > > >> ---- lib/CodeGen/SelectionDAG/LegalizeTypes.h.orig Thu Jul 17 > > > >01:03:52 2014 > > > >> -+++ lib/CodeGen/SelectionDAG/LegalizeTypes.h Thu Jul 17 01:04:56 > > > >2014 > > > >> -@@ -570,6 +570,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer { > > > >(priv > > > >> - void SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo, SDValue > > > >&Hi); > > > >> - void SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo, SDValue > > > >&Hi); > > > >> - void SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo, > > > >SDValue &Hi); > > > >> -+ void SplitVecRes_INSERT_SUBVECTOR(SDNode *N, SDValue &Lo, SDValue > > > >&Hi); > > > >> - void SplitVecRes_FPOWI(SDNode *N, SDValue &Lo, SDValue &Hi); > > > >> - void SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, > > > >SDValue &Hi); > > > >> - void SplitVecRes_LOAD(LoadSDNode *N, SDValue &Lo, SDValue &Hi); > > > >> Index: patches/patch-lib_CodeGen_SelectionDAG_LegalizeVectorTypes_cpp > > > >> =================================================================== > > > >> RCS file: > > > >patches/patch-lib_CodeGen_SelectionDAG_LegalizeVectorTypes_cpp > > > >> diff -N > > > >patches/patch-lib_CodeGen_SelectionDAG_LegalizeVectorTypes_cpp > > > >> --- patches/patch-lib_CodeGen_SelectionDAG_LegalizeVectorTypes_cpp > > > >> 14 > > > >Aug 2014 01:08:09 -0000 1.2 > > > >> +++ /dev/null 1 Jan 1970 00:00:00 -0000 > > > >> @@ -1,92 +0,0 @@ > > > >> -$OpenBSD: patch-lib_CodeGen_SelectionDAG_LegalizeVectorTypes_cpp,v > > > >1.2 2014/08/14 01:08:09 brad Exp $ > > > >> - > > > >> -r211435 > > > >> -Legalizer: Add support for splitting insert_subvectors. > > > >> - > > > >> -We handle this by spilling the whole thing to the stack and doing > > > >the > > > >> -insertion as a store. > > > >> - > > > >> -PR19492. This happens in real code because the vectorizer creates > > > >v2i128 when AVX is > > > >> -enabled. > > > >> - > > > >> -r203311 > > > >> -ISel: Make VSELECT selection terminate in cases where the condition > > > >type has to > > > >> -be split and the result type widened. > > > >> - > > > >> -When the condition of a vselect has to be split it makes no sense > > > >widening the > > > >> -vselect and thereby widening the condition. We end up in an endless > > > >loop of > > > >> -widening (vselect result type) and splitting (condition mask type) > > > >doing this. > > > >> -Instead, split both the condition and the vselect and widen the > > > >result. > > > >> - > > > >> ---- lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp.orig Sun Mar > > > >> 2 > > > >21:57:42 2014 > > > >> -+++ lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp Thu Jul 17 > > > >01:10:16 2014 > > > >> -@@ -518,6 +518,7 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode > > > >*N, un > > > >> - case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); > > > >break; > > > >> - case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, > > > >Hi); break; > > > >> - case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, > > > >Hi); break; > > > >> -+ case ISD::INSERT_SUBVECTOR: SplitVecRes_INSERT_SUBVECTOR(N, Lo, > > > >Hi); break; > > > >> - case ISD::FP_ROUND_INREG: SplitVecRes_InregOp(N, Lo, Hi); > > > >break; > > > >> - case ISD::FPOWI: SplitVecRes_FPOWI(N, Lo, Hi); break; > > > >> - case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, > > > >Hi); break; > > > >> -@@ -737,6 +738,43 @@ void > > > >DAGTypeLegalizer::SplitVecRes_EXTRACT_SUBVECTOR(S > > > >> - TLI.getVectorIdxTy())); > > > >> - } > > > >> - > > > >> -+void DAGTypeLegalizer::SplitVecRes_INSERT_SUBVECTOR(SDNode *N, > > > >SDValue &Lo, > > > >> -+ SDValue &Hi) { > > > >> -+ SDValue Vec = N->getOperand(0); > > > >> -+ SDValue SubVec = N->getOperand(1); > > > >> -+ SDValue Idx = N->getOperand(2); > > > >> -+ SDLoc dl(N); > > > >> -+ GetSplitVector(Vec, Lo, Hi); > > > >> -+ > > > >> -+ // Spill the vector to the stack. > > > >> -+ EVT VecVT = Vec.getValueType(); > > > >> -+ EVT SubVecVT = VecVT.getVectorElementType(); > > > >> -+ SDValue StackPtr = DAG.CreateStackTemporary(VecVT); > > > >> -+ SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, > > > >StackPtr, > > > >> -+ MachinePointerInfo(), false, false, > > > >0); > > > >> -+ > > > >> -+ // Store the new subvector into the specified index. > > > >> -+ SDValue SubVecPtr = GetVectorElementPointer(StackPtr, SubVecVT, > > > >Idx); > > > >> -+ Type *VecType = VecVT.getTypeForEVT(*DAG.getContext()); > > > >> -+ unsigned Alignment = > > > >TLI.getDataLayout()->getPrefTypeAlignment(VecType); > > > >> -+ Store = DAG.getStore(Store, dl, SubVec, SubVecPtr, > > > >MachinePointerInfo(), > > > >> -+ false, false, 0); > > > >> -+ > > > >> -+ // Load the Lo part from the stack slot. > > > >> -+ Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, > > > >MachinePointerInfo(), > > > >> -+ false, false, false, 0); > > > >> -+ > > > >> -+ // Increment the pointer to the other part. > > > >> -+ unsigned IncrementSize = Lo.getValueType().getSizeInBits() / 8; > > > >> -+ StackPtr = > > > >> -+ DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr, > > > >> -+ DAG.getConstant(IncrementSize, > > > >StackPtr.getValueType > > > > > > -- > > > Sent from a phone, please excuse the formatting. > > > > > > > -- > > Juan Francisco Cantero Hurtado http://juanfra.info > > > > > -- Juan Francisco Cantero Hurtado http://juanfra.info