1
0
mirror of https://git.FreeBSD.org/ports.git synced 2024-11-23 00:43:28 +00:00

lang/ghc844: Create a port out of lang/ghc.

Approved by:	tcberner (mentor)
This commit is contained in:
Gleb Popov 2019-01-05 10:07:40 +00:00
parent 12699055c1
commit 2f72f198df
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=489316
14 changed files with 781 additions and 0 deletions

View File

@ -113,6 +113,7 @@
SUBDIR += gforth
SUBDIR += ghc
SUBDIR += ghc843
SUBDIR += ghc844
SUBDIR += ghc862
SUBDIR += gjs
SUBDIR += gnat_util

29
lang/ghc844/Makefile Normal file
View File

@ -0,0 +1,29 @@
# $FreeBSD$
PORTNAME= ghc
PORTVERSION= ${GHC_VERSION}
CATEGORIES= lang haskell
MASTER_SITES= http://www.haskell.org/ghc/dist/${PORTVERSION}/:source \
LOCAL/arrowd/:boot \
${HACKAGE_SITE}hscolour-${HSCOLOUR_VERSION}/:docs
PKGNAMESUFFIX= ${GHC_VERSION:S/.//g}
DISTFILES= ghc-${PORTVERSION}-src${EXTRACT_SUFX}:source \
hscolour-${HSCOLOUR_VERSION}.tar.gz:docs
EXTRACT_ONLY= ${_DISTFILES:C/hscolour.*$//g}
MAINTAINER= haskell@FreeBSD.org
COMMENT= Compiler for the functional language Haskell
LICENSE= BSD3CLAUSE
LICENSE_FILE= ${WRKSRC}/LICENSE
GHC_VERSION= 8.4.4
HSCOLOUR_VERSION= 1.24.4
LLVM_VERSION= 50
CONFLICTS_INSTALL= ghc-7.4.* ghc-7.6.* ghc-7.8.* ghc-7.10.* ghc-8.0.* ghc-8.4.3
.include "${.CURDIR}/../../lang/ghc/bsd.ghc.mk"
.include <bsd.port.mk>

15
lang/ghc844/distinfo Normal file
View File

@ -0,0 +1,15 @@
TIMESTAMP = 1541010522
SHA256 (ghc-8.4.4-src.tar.xz) = 11117735a58e507c481c09f3f39ae5a314e9fbf49fc3109528f99ea7959004b2
SIZE (ghc-8.4.4-src.tar.xz) = 11319500
SHA256 (ghc-8.4.3-boot-amd64-freebsd.tar.xz) = 0e0324a539d471a813ed4d18c537fb19be22a4e250bd5434a3a911b9d5343724
SIZE (ghc-8.4.3-boot-amd64-freebsd.tar.xz) = 67718400
SHA256 (ghc-8.4.3-boot-i386-freebsd.tar.xz) = 65fcd48b1c0166e028b3f6d50ad295525e6b84490da82663ec66165e57e87972
SIZE (ghc-8.4.3-boot-i386-freebsd.tar.xz) = 66143592
SHA256 (hscolour-1.24.4.tar.gz) = 243332b082294117f37b2c2c68079fa61af68b36223b3fc07594f245e0e5321d
SIZE (hscolour-1.24.4.tar.gz) = 28729
SHA256 (ghc-8.4.3-boot-aarch64-freebsd.tar.xz) = 84611f37d31a43a3216274ee7dcee4b89f2c5ef6ab713222f266b5658c736e05
SIZE (ghc-8.4.3-boot-aarch64-freebsd.tar.xz) = 99933576
SHA256 (ghc-8.4.2-boot-armv6-freebsd.tar.xz) = 61d3a4486dbb904b05a735e98f23a49c2b464d6b19212dd655ff578f36d02f0d
SIZE (ghc-8.4.2-boot-armv6-freebsd.tar.xz) = 107368936
SHA256 (ghc-8.4.2-boot-armv7-freebsd.tar.xz) = eedb9416870bfe82315155751871e31e815b718b381ccf4f7e45a99a6ad7c94d
SIZE (ghc-8.4.2-boot-armv7-freebsd.tar.xz) = 110153548

View File

@ -0,0 +1,20 @@
docdir = %%PREFIX%%/share/doc/ghc-%%GHC_VERSION%%
htmldir = %%PREFIX%%/share/doc/ghc-%%GHC_VERSION%%
mandir = %%PREFIX%%/man
infodir = %%PREFIX%%/info
DYNAMIC_GHC_PROGRAMS = %%WITH_DYNAMIC%%
BUILD_PROF_LIBS = %%WITH_PROFILE%%
HADDOCK_DOCS = %%WITH_DOCS%%
HSCOLOUR_SRCS = %%WITH_DOCS%%
INTEGER_LIBRARY = %%INTEGER_LIBRARY%%
# disable xelatex: PR 231438
BUILD_SPHINX_PDF = NO
BSD_PATH_TO_HSC2HS = %%HSC2HS%%
SRC_HC_OPTS += -I%%NCURSESINC%% -L%%NCURSESLIB%% -I%%LOCALBASE%%/include -L%%LOCALBASE%%/lib
SRC_CC_OPTS += %%CFLAGS%%
EXTRA_HSC2HS_OPTS += -I%%LOCALBASE%%/include --lflag=-L%%LOCALBASE%%/lib
EXTRA_LD_OPTS += -L%%LOCALBASE%%/lib
EXTRA_CABAL_CONFIGURE_FLAGS += --extra-include-dirs=%%LOCALBASE%%/include
EXTRA_CABAL_CONFIGURE_FLAGS += --extra-lib-dirs=%%LOCALBASE%%/lib
libraries/terminfo_CONFIGURE_OPTS += --configure-option=--with-curses-includes=%%NCURSESINC%% --configure-option=--with-curses-libraries=%%NCURSESLIB%%
V = 0

View File

@ -0,0 +1,54 @@
--- aclocal.m4.orig 2018-03-25 21:22:32 UTC
+++ aclocal.m4
@@ -648,6 +648,14 @@ AC_DEFUN([FPTOOLS_SET_C_LD_FLAGS],
$3="$$3 -D_HPUX_SOURCE"
$5="$$5 -D_HPUX_SOURCE"
;;
+ arm*freebsd*)
+ # On arm/freebsd, tell gcc to generate Arm
+ # instructions (ie not Thumb) and to link using the gold linker.
+ # Forcing LD to be ld.gold is done in FIND_LD m4 macro.
+ $2="$$2 -marm"
+ $3="$$3 -Wl,-z,noexecstack"
+ $4="$$4 -z noexecstack"
+ ;;
arm*linux*)
# On arm/linux and arm/android, tell gcc to generate Arm
# instructions (ie not Thumb).
@@ -656,6 +664,11 @@ AC_DEFUN([FPTOOLS_SET_C_LD_FLAGS],
$4="$$4 -z noexecstack"
;;
+ aarch64*freebsd*)
+ $3="$$3 -Wl,-z,noexecstack"
+ $4="$$4 -z noexecstack"
+ ;;
+
aarch64*linux*)
$3="$$3 -Wl,-z,noexecstack"
$4="$$4 -z noexecstack"
@@ -1917,6 +1930,10 @@ case "$1" in
# converts the canonicalized target into someting llvm can understand
AC_DEFUN([GHC_LLVM_TARGET], [
case "$2-$3" in
+ *-freebsd*-gnueabihf)
+ llvm_target_vendor="unknown"
+ llvm_target_os="freebsd-gnueabihf"
+ ;;
hardfloat-*eabi)
llvm_target_vendor="unknown"
llvm_target_os="$3""hf"
@@ -2361,13 +2378,6 @@ AC_DEFUN([FIND_LD],[
[enable_ld_override=yes])
find_ld() {
- # Make sure the user didn't specify LD manually.
- if test "z$LD" != "z"; then
- AC_CHECK_TARGET_TOOL([LD], [ld])
- LD_NO_GOLD=$LD
- return
- fi
-
# Manually iterate over possible names since we want to ensure that, e.g.,
# if ld.lld is installed but gcc doesn't support -fuse-ld=lld, that we
# then still try ld.gold and -fuse-ld=gold.

View File

@ -0,0 +1,22 @@
--- configure.orig 2018-03-06 20:04:54 UTC
+++ configure
@@ -9108,6 +9108,19 @@ $as_echo_n "checking Setting up CFLAGS, LDFLAGS, IGNOR
IGNORE_LINKER_LD_FLAGS="$IGNORE_LINKER_LD_FLAGS -z noexecstack"
;;
+ arm*freebsd*)
+ # On arm/freebsd, tell gcc to generate Arm
+ # instructions (ie not Thumb).
+ CFLAGS="$CFLAGS -marm"
+ LDFLAGS="$LDFLAGS -Wl,-z,noexecstack"
+ IGNORE_LINKER_LD_FLAGS="$IGNORE_LINKER_LD_FLAGS -z noexecstack"
+ ;;
+
+ aarch64*freebsd*)
+ LDFLAGS="$LDFLAGS -Wl,-z,noexecstack"
+ IGNORE_LINKER_LD_FLAGS="$IGNORE_LINKER_LD_FLAGS -z noexecstack"
+ ;;
+
powerpc-ibm-aix*)
# We need `-D_THREAD_SAFE` to unlock the thread-local `errno`.
CFLAGS="$CFLAGS -D_THREAD_SAFE"

View File

@ -0,0 +1,12 @@
--- configure.ac.orig 2018-04-17 19:30:22 UTC
+++ configure.ac
@@ -447,6 +447,9 @@ XCODE_VERSION()
dnl ** Building a cross compiler?
dnl --------------------------------------------------------------
CrossCompiling=NO
+
+build=`echo $build | sed -e 's/amd64-/x86_64-/g; s/armv[[67]]-/arm-/g; s/-freebsd.*$/-freebsd/g'`
+
# If 'host' and 'target' differ, then this means we are building a cross-compiler.
if test "$TargetPlatform" != "$HostPlatform" ; then
CrossCompiling=YES

View File

@ -0,0 +1,231 @@
From d8495549ba9d194815c2d0eaee6797fc7c00756a Mon Sep 17 00:00:00 2001
From: Kavon Farvardin <kavon@farvard.in>
Date: Sun, 28 Oct 2018 12:11:49 -0400
Subject: [PATCH] Fix for T14251 on ARM
We now calculate the SSE register padding needed to fix the calling
convention in LLVM in a robust way: grouping them by whether
registers in that class overlap (with the same class overlapping
itself).
My prior patch assumed that no matter the platform, physical
register Fx aliases with Dx, etc, for our calling convention.
This is unfortunately not the case for any platform except x86-64.
Test Plan:
Only know how to test on x86-64, but it should be tested on ARM with:
`make test WAYS=llvm && make test WAYS=optllvm`
Reviewers: bgamari, angerman
Reviewed By: bgamari
Subscribers: rwbarton, carter
GHC Trac Issues: #15780, #14251, #15747
Differential Revision: https://phabricator.haskell.org/D5254
---
compiler/llvmGen/LlvmCodeGen/Base.hs | 123 ++++++++++++++++++++++----------
compiler/llvmGen/LlvmCodeGen/CodeGen.hs | 6 +-
2 files changed, 90 insertions(+), 39 deletions(-)
diff --git a/compiler/llvmGen/LlvmCodeGen/Base.hs b/compiler/llvmGen/LlvmCodeGen/Base.hs
index ec91bac..0a40b73 100644
--- compiler/llvmGen/LlvmCodeGen/Base.hs
+++ compiler/llvmGen/LlvmCodeGen/Base.hs
@@ -26,7 +26,7 @@ module LlvmCodeGen.Base (
cmmToLlvmType, widthToLlvmFloat, widthToLlvmInt, llvmFunTy,
llvmFunSig, llvmFunArgs, llvmStdFunAttrs, llvmFunAlign, llvmInfAlign,
- llvmPtrBits, tysToParams, llvmFunSection, padLiveArgs, isSSE,
+ llvmPtrBits, tysToParams, llvmFunSection, padLiveArgs, isFPR,
strCLabel_llvm, strDisplayName_llvm, strProcedureName_llvm,
getGlobalPtr, generateExternDecls,
@@ -47,6 +47,7 @@ import CodeGen.Platform ( activeStgRegs )
import DynFlags
import FastString
import Cmm hiding ( succ )
+import CmmUtils ( regsOverlap )
import Outputable as Outp
import Platform
import UniqFM
@@ -58,8 +59,7 @@ import ErrUtils
import qualified Stream
import Control.Monad (ap)
-import Data.List (sort)
-import Data.Maybe (mapMaybe)
+import Data.List (sort, groupBy, head)
-- ----------------------------------------------------------------------------
-- * Some Data Types
@@ -152,36 +152,91 @@ llvmFunArgs dflags live =
map (lmGlobalRegArg dflags) (filter isPassed allRegs)
where platform = targetPlatform dflags
allRegs = activeStgRegs platform
- paddedLive = map (\(_,r) -> r) $ padLiveArgs live
+ paddedLive = map (\(_,r) -> r) $ padLiveArgs dflags live
isLive r = r `elem` alwaysLive || r `elem` paddedLive
- isPassed r = not (isSSE r) || isLive r
-
-
-isSSE :: GlobalReg -> Bool
-isSSE (FloatReg _) = True
-isSSE (DoubleReg _) = True
-isSSE (XmmReg _) = True
-isSSE (YmmReg _) = True
-isSSE (ZmmReg _) = True
-isSSE _ = False
-
-sseRegNum :: GlobalReg -> Maybe Int
-sseRegNum (FloatReg i) = Just i
-sseRegNum (DoubleReg i) = Just i
-sseRegNum (XmmReg i) = Just i
-sseRegNum (YmmReg i) = Just i
-sseRegNum (ZmmReg i) = Just i
-sseRegNum _ = Nothing
-
--- the bool indicates whether the global reg was added as padding.
--- the returned list is not sorted in any particular order,
--- but does indicate the set of live registers needed, with SSE padding.
-padLiveArgs :: LiveGlobalRegs -> [(Bool, GlobalReg)]
-padLiveArgs live = allRegs
+ isPassed r = not (isFPR r) || isLive r
+
+
+isFPR :: GlobalReg -> Bool
+isFPR (FloatReg _) = True
+isFPR (DoubleReg _) = True
+isFPR (XmmReg _) = True
+isFPR (YmmReg _) = True
+isFPR (ZmmReg _) = True
+isFPR _ = False
+
+sameFPRClass :: GlobalReg -> GlobalReg -> Bool
+sameFPRClass (FloatReg _) (FloatReg _) = True
+sameFPRClass (DoubleReg _) (DoubleReg _) = True
+sameFPRClass (XmmReg _) (XmmReg _) = True
+sameFPRClass (YmmReg _) (YmmReg _) = True
+sameFPRClass (ZmmReg _) (ZmmReg _) = True
+sameFPRClass _ _ = False
+
+normalizeFPRNum :: GlobalReg -> GlobalReg
+normalizeFPRNum (FloatReg _) = FloatReg 1
+normalizeFPRNum (DoubleReg _) = DoubleReg 1
+normalizeFPRNum (XmmReg _) = XmmReg 1
+normalizeFPRNum (YmmReg _) = YmmReg 1
+normalizeFPRNum (ZmmReg _) = ZmmReg 1
+normalizeFPRNum _ = error "normalizeFPRNum expected only FPR regs"
+
+getFPRCtor :: GlobalReg -> Int -> GlobalReg
+getFPRCtor (FloatReg _) = FloatReg
+getFPRCtor (DoubleReg _) = DoubleReg
+getFPRCtor (XmmReg _) = XmmReg
+getFPRCtor (YmmReg _) = YmmReg
+getFPRCtor (ZmmReg _) = ZmmReg
+getFPRCtor _ = error "getFPRCtor expected only FPR regs"
+
+fprRegNum :: GlobalReg -> Int
+fprRegNum (FloatReg i) = i
+fprRegNum (DoubleReg i) = i
+fprRegNum (XmmReg i) = i
+fprRegNum (YmmReg i) = i
+fprRegNum (ZmmReg i) = i
+fprRegNum _ = error "fprRegNum expected only FPR regs"
+
+-- | Input: dynflags, and the list of live registers
+--
+-- Output: An augmented list of live registers, where padding was
+-- added to the list of registers to ensure the calling convention is
+-- correctly used by LLVM.
+--
+-- Each global reg in the returned list is tagged with a bool, which
+-- indicates whether the global reg was added as padding, or was an original
+-- live register.
+--
+-- That is, True => padding, False => a real, live global register.
+--
+-- Also, the returned list is not sorted in any particular order.
+--
+padLiveArgs :: DynFlags -> LiveGlobalRegs -> [(Bool, GlobalReg)]
+padLiveArgs dflags live =
+ if platformUnregisterised plat
+ then taggedLive -- not using GHC's register convention for platform.
+ else padding ++ taggedLive
+ where
+ taggedLive = map (\x -> (False, x)) live
+ plat = targetPlatform dflags
+
+ fprLive = filter isFPR live
+ padding = concatMap calcPad $ groupBy sharesClass fprLive
+
+ sharesClass :: GlobalReg -> GlobalReg -> Bool
+ sharesClass a b = sameFPRClass a b || overlappingClass
+ where
+ overlappingClass = regsOverlap dflags (norm a) (norm b)
+ norm = CmmGlobal . normalizeFPRNum
+
+ calcPad :: [GlobalReg] -> [(Bool, GlobalReg)]
+ calcPad rs = getFPRPadding (getFPRCtor $ head rs) rs
+
+getFPRPadding :: (Int -> GlobalReg) -> LiveGlobalRegs -> [(Bool, GlobalReg)]
+getFPRPadding paddingCtor live = padding
where
- sseRegNums = sort $ mapMaybe sseRegNum live
- (_, padding) = foldl assignSlots (1, []) $ sseRegNums
- allRegs = padding ++ map (\r -> (False, r)) live
+ fprRegNums = sort $ map fprRegNum live
+ (_, padding) = foldl assignSlots (1, []) $ fprRegNums
assignSlots (i, acc) regNum
| i == regNum = -- don't need padding here
@@ -195,11 +250,7 @@ padLiveArgs live = allRegs
genPad start n =
take n $ flip map (iterate (+1) start) (\i ->
- (True, FloatReg i))
- -- NOTE: Picking float should be fine for the following reasons:
- -- (1) Float aliases with all the other SSE register types on
- -- the given platform.
- -- (2) The argument is not live anyways.
+ (True, paddingCtor i))
-- | Llvm standard fun attributes
diff --git a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs
index 1873400..21abc65 100644
--- compiler/llvmGen/LlvmCodeGen/CodeGen.hs
+++ compiler/llvmGen/LlvmCodeGen/CodeGen.hs
@@ -1814,14 +1814,14 @@ funPrologue live cmmBlocks = do
-- STG Liveness optimisation done here.
funEpilogue :: LiveGlobalRegs -> LlvmM ([LlvmVar], LlvmStatements)
funEpilogue live = do
+ dflags <- getDynFlags
-- the bool indicates whether the register is padding.
let alwaysNeeded = map (\r -> (False, r)) alwaysLive
- livePadded = alwaysNeeded ++ padLiveArgs live
+ livePadded = alwaysNeeded ++ padLiveArgs dflags live
-- Set to value or "undef" depending on whether the register is
-- actually live
- dflags <- getDynFlags
let loadExpr r = do
(v, _, s) <- getCmmRegVal (CmmGlobal r)
return (Just $ v, s)
@@ -1833,7 +1833,7 @@ funEpilogue live = do
loads <- flip mapM allRegs $ \r -> case () of
_ | (False, r) `elem` livePadded
-> loadExpr r -- if r is not padding, load it
- | not (isSSE r) || (True, r) `elem` livePadded
+ | not (isFPR r) || (True, r) `elem` livePadded
-> loadUndef r
| otherwise -> return (Nothing, nilOL)
--
1.9.1

View File

@ -0,0 +1,21 @@
--- ghc.mk.orig 2017-01-03 15:59:18 UTC
+++ ghc.mk
@@ -96,6 +96,7 @@ endif
# Catch make if it runs away into an infinite loop
ifeq "$(MAKE_RESTARTS)" ""
else ifeq "$(MAKE_RESTARTS)" "1"
+else ifeq "$(MAKE_RESTARTS)" "2"
else
$(error Make has restarted itself $(MAKE_RESTARTS) times; is there a makefile bug? See http://ghc.haskell.org/trac/ghc/wiki/Building/Troubleshooting#Makehasrestarteditself3timesisthereamakefilebug for details)
endif
@@ -459,10 +460,7 @@ PACKAGES_STAGE1 += ghc-boot-th
PACKAGES_STAGE1 += ghc-boot
PACKAGES_STAGE1 += template-haskell
PACKAGES_STAGE1 += ghc-compact
-
-ifeq "$(HADDOCK_DOCS)" "YES"
PACKAGES_STAGE1 += xhtml
-endif
ifeq "$(WITH_TERMINFO)" "YES"
PACKAGES_STAGE1 += terminfo

View File

@ -0,0 +1,39 @@
--- libraries/Cabal/Cabal/Distribution/Simple/Program/Builtin.hs.orig 2017-11-28 16:40:34 UTC
+++ libraries/Cabal/Cabal/Distribution/Simple/Program/Builtin.hs
@@ -59,6 +59,8 @@ import Distribution.Compat.Exception
import Distribution.Verbosity
import Distribution.Version
+import System.FilePath (takeDirectory)
+
import qualified Data.Map as Map
-- ------------------------------------------------------------
@@ -265,11 +267,13 @@ alexProgram = (simpleProgram "alex") {
gccProgram :: Program
gccProgram = (simpleProgram "gcc") {
- programFindVersion = findProgramVersion "-dumpversion" id
- }
+ programFindLocation = \v p -> findProgramOnSearchPath v p "%%CC%%"
+}
arProgram :: Program
-arProgram = simpleProgram "ar"
+arProgram = (simpleProgram "ar") {
+ programFindLocation = \v p -> findProgramOnSearchPath v p "%%AR%%"
+}
stripProgram :: Program
stripProgram = (simpleProgram "strip") {
@@ -337,7 +341,9 @@ greencardProgram :: Program
greencardProgram = simpleProgram "greencard"
ldProgram :: Program
-ldProgram = simpleProgram "ld"
+ldProgram = (simpleProgram "ld") {
+ programFindLocation = \v p -> findProgramOnSearchPath v p "%%LD%%"
+ }
tarProgram :: Program
tarProgram = (simpleProgram "tar") {

View File

@ -0,0 +1,12 @@
--- llvm-targets.orig 2018-03-17 14:04:41 UTC
+++ llvm-targets
@@ -20,4 +20,9 @@
,("aarch64-apple-ios", ("e-m:o-i64:64-i128:128-n32:64-S128", "generic", "+neon"))
,("i386-apple-ios", ("e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128", "yonah", ""))
,("x86_64-apple-ios", ("e-m:o-i64:64-f80:128-n8:16:32:64-S128", "core2", ""))
+,("armv6-unknown-freebsd-gnueabihf", ("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", "arm1176jzf-s", "+strict-align"))
+,("armv7-unknown-freebsd-gnueabihf", ("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", "generic", "+strict-align"))
+,("aarch64-unknown-freebsd", ("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128", "generic", "+neon"))
+,("amd64-portbld-freebsd", ("e-m:e-i64:64-f80:128-n8:16:32:64-S128", "x86-64", ""))
+,("i386-portbld-freebsd", ("e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128", "i486", ""))
]

View File

@ -0,0 +1,250 @@
--- rts/posix/OSMem.c.orig 2017-11-28 16:39:14 UTC
+++ rts/posix/OSMem.c
@@ -36,6 +36,10 @@
#if defined(HAVE_NUMAIF_H)
#include <numaif.h>
#endif
+#if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
#include <errno.h>
@@ -45,6 +49,29 @@
#include <sys/sysctl.h>
#endif
+#ifndef MAP_FAILED
+# define MAP_FAILED ((void *)-1)
+#endif
+
+#if defined(hpux_HOST_OS)
+# ifndef MAP_ANON
+# define MAP_ANON MAP_ANONYMOUS
+# endif
+#endif
+
+#ifndef darwin_HOST_OS
+# undef RESERVE_FLAGS
+# if defined(MAP_GUARD)
+# define RESERVE_FLAGS MAP_GUARD /* FreeBSD */
+# elif defined(MAP_NORESERVE)
+# define RESERVE_FLAGS MAP_NORESERVE | MAP_ANON | MAP_PRIVATE;
+# else
+# if defined(USE_LARGE_ADDRESS_SPACE)
+# error USE_LARGE_ADDRESS_SPACE needs MAP_NORESERVE or MAP_GUARD
+# endif
+# endif
+#endif
+
static void *next_request = 0;
void osMemInit(void)
@@ -98,8 +125,10 @@
The naming is chosen from the Win32 API (VirtualAlloc) which does the
same thing and has done so forever, while support for this in Unix systems
has only been added recently and is hidden in the posix portability mess.
- It is confusing because to get the reserve behavior we need MAP_NORESERVE
- (which tells the kernel not to allocate backing space), but heh...
+ The Linux manpage suggests that mmap must be passed MAP_NORESERVE in order
+ to get reservation-only behavior. It is confusing because to get the reserve
+ behavior we need MAP_NORESERVE (which tells the kernel not to allocate backing
+ space), but heh...
*/
enum
{
@@ -108,6 +137,44 @@
MEM_RESERVE_AND_COMMIT = MEM_RESERVE | MEM_COMMIT
};
+#if defined(linux_HOST_OS)
+static void *
+linux_retry_mmap(int operation, W_ size, void *ret, void *addr, int prot, int flags)
+{
+ if (addr != 0 && (operation & MEM_RESERVE)) {
+ // Try again with no hint address.
+ // It's not clear that this can ever actually help,
+ // but since our alternative is to abort, we may as well try.
+ ret = mmap(0, size, prot, flags, -1, 0);
+ }
+ if (ret == MAP_FAILED && errno == EPERM) {
+ // Linux is not willing to give us any mapping,
+ // so treat this as an out-of-memory condition
+ // (really out of virtual address space).
+ errno = ENOMEM;
+ }
+ return ret;
+}
+#endif /* defined(linux_HOST_OS) */
+
+static void
+post_mmap_madvise(int operation, W_ size, void *ret)
+{
+#if defined(MADV_WILLNEED)
+ if (operation & MEM_COMMIT) {
+ madvise(ret, size, MADV_WILLNEED);
+# if defined(MADV_DODUMP)
+ madvise(ret, size, MADV_DODUMP);
+# endif
+ } else {
+ madvise(ret, size, MADV_DONTNEED);
+# if defined(MADV_DONTDUMP)
+ madvise(ret, size, MADV_DONTDUMP);
+# endif
+ }
+#endif
+}
+
/* Returns NULL on failure; errno set */
static void *
my_mmap (void *addr, W_ size, int operation)
@@ -149,69 +216,44 @@
VM_PROT_READ|VM_PROT_WRITE);
}
-#else
+#else /* defined(darwin_HOST_OS) */
int prot, flags;
- if (operation & MEM_COMMIT)
+ if (operation & MEM_COMMIT) {
prot = PROT_READ | PROT_WRITE;
- else
+ } else {
prot = PROT_NONE;
- if (operation == MEM_RESERVE)
-# if defined(MAP_NORESERVE)
- flags = MAP_NORESERVE;
+ }
+
+ if (operation == MEM_RESERVE) {
+# if defined(RESERVE_FLAGS)
+ flags = RESERVE_FLAGS;
# else
-# if defined(USE_LARGE_ADDRESS_SPACE)
-# error USE_LARGE_ADDRESS_SPACE needs MAP_NORESERVE
-# endif
errorBelch("my_mmap(,,MEM_RESERVE) not supported on this platform");
# endif
- else if (operation == MEM_COMMIT)
- flags = MAP_FIXED;
- else
- flags = 0;
+ } else if (operation == MEM_COMMIT) {
+ flags = MAP_FIXED | MAP_ANON | MAP_PRIVATE;
+ } else {
+ flags = MAP_ANON | MAP_PRIVATE;
+ }
-#if defined(hpux_HOST_OS)
- ret = mmap(addr, size, prot, flags | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-#elif defined(linux_HOST_OS)
- ret = mmap(addr, size, prot, flags | MAP_ANON | MAP_PRIVATE, -1, 0);
- if (ret == (void *)-1 && errno == EPERM) {
+ ret = mmap(addr, size, prot, flags, -1, 0);
+# if defined(linux_HOST_OS)
+ if (ret == MAP_FAILED && errno == EPERM) {
// Linux may return EPERM if it tried to give us
// a chunk of address space below mmap_min_addr,
// See Trac #7500.
- if (addr != 0 && (operation & MEM_RESERVE)) {
- // Try again with no hint address.
- // It's not clear that this can ever actually help,
- // but since our alternative is to abort, we may as well try.
- ret = mmap(0, size, prot, flags | MAP_ANON | MAP_PRIVATE, -1, 0);
- }
- if (ret == (void *)-1 && errno == EPERM) {
- // Linux is not willing to give us any mapping,
- // so treat this as an out-of-memory condition
- // (really out of virtual address space).
- errno = ENOMEM;
- }
+ ret = linux_retry_mmap(operation, size, ret, addr, prot, flags);
}
-
- if (operation & MEM_COMMIT) {
- madvise(ret, size, MADV_WILLNEED);
-#if defined(MADV_DODUMP)
- madvise(ret, size, MADV_DODUMP);
-#endif
- } else {
- madvise(ret, size, MADV_DONTNEED);
-#if defined(MADV_DONTDUMP)
- madvise(ret, size, MADV_DONTDUMP);
-#endif
- }
-
-#else
- ret = mmap(addr, size, prot, flags | MAP_ANON | MAP_PRIVATE, -1, 0);
-#endif
-#endif
-
- if (ret == (void *)-1) {
+# endif
+ if (ret == MAP_FAILED) {
return NULL;
}
+#endif /* defined(darwin_HOST_OS) */
+
+ // Map in committed pages rather than take a fault for each chunk.
+ // Also arrange to include them in core-dump files.
+ post_mmap_madvise(operation, size, ret);
return ret;
}
@@ -435,6 +477,8 @@
void *base, *top;
void *start, *end;
+ ASSERT((len & ~MBLOCK_MASK) == len);
+
/* We try to allocate len + MBLOCK_SIZE,
because we need memory which is MBLOCK_SIZE aligned,
and then we discard what we don't need */
@@ -500,8 +544,19 @@
(void*)startAddress, (void*)minimumAddress);
}
+#if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_SYS_TIME_H)
+ struct rlimit limit;
+ if (!getrlimit(RLIMIT_AS, &limit)
+ && limit.rlim_cur > 0
+ && *len > limit.rlim_cur) {
+ *len = limit.rlim_cur;
+ }
+#endif
+
attempt = 0;
while (1) {
+ *len &= ~MBLOCK_MASK;
+
if (*len < MBLOCK_SIZE) {
// Give up if the system won't even give us 16 blocks worth of heap
barf("osReserveHeapMemory: Failed to allocate heap storage");
@@ -512,9 +567,14 @@
if (at == NULL) {
// This means that mmap failed which we take to mean that we asked
// for too much memory. This can happen due to POSIX resource
- // limits. In this case we reduce our allocation request by a factor
- // of two and try again.
- *len /= 2;
+ // limits. In this case we reduce our allocation request by a
+ // fraction of the current size and try again.
+ //
+ // Note that the previously would instead decrease the request size
+ // by a factor of two; however, this meant that significant amounts
+ // of memory will be wasted (e.g. imagine a machine with 512GB of
+ // physical memory but a 511GB ulimit). See #14492.
+ *len -= *len / 8;
} else if ((W_)at >= minimumAddress) {
// Success! We were given a block of memory starting above the 8 GB
// mark, which is what we were looking for.
@@ -536,7 +596,7 @@
{
void *r = my_mmap(at, size, MEM_COMMIT);
if (r == NULL) {
- barf("Unable to commit %d bytes of memory", size);
+ barf("Unable to commit %" FMT_Word " bytes of memory", size);
}
}

55
lang/ghc844/files/wrap.c Normal file
View File

@ -0,0 +1,55 @@
/* -*- ugly-hack-mode -*- */
/* $FreeBSD$ */
#include <sys/stat.h>
struct old_dirent;
struct old_stat;
__asm(".symver old_readdir_r, readdir_r@FBSD_1.0");
int old_readdir_r(void *dirp, struct old_dirent *entry,
struct old_dirent **result);
__asm(".symver old_stat, stat@FBSD_1.0");
int old_stat(const char * restrict path, struct old_stat * restrict sb);
__asm(".symver old_lstat, lstat@FBSD_1.0");
int old_lstat(const char * restrict path, struct old_stat * restrict sb);
__asm(".symver old_fstat, fstat@FBSD_1.0");
int old_fstat(int fd, struct old_stat *sb);
__asm(".symver old_mknod, mknod@FBSD_1.0");
int old_mknod(const char *path, mode_t mode, uint32_t dev);
int
__wrap_readdir_r(void *dirp, struct old_dirent *entry,
struct old_dirent **result)
{
return (old_readdir_r(dirp, entry, result));
}
int
__wrap_stat(const char * restrict path, struct old_stat * restrict sb)
{
return (old_stat(path, sb));
}
int
__wrap_lstat(const char * restrict path, struct old_stat * restrict sb)
{
return (old_lstat(path, sb));
}
int
__wrap_fstat(int fd, struct old_stat *sb)
{
return (old_fstat(fd, sb));
}
int
__wrap_mknod(const char *path, mode_t mode, uint32_t dev)
{
return (old_mknod(path, mode, dev));
}

20
lang/ghc844/pkg-descr Normal file
View File

@ -0,0 +1,20 @@
The Glasgow Haskell Compiler is a state-of-the-art, open source, compiler and
interactive environment for the functional language Haskell. Highlights:
* Supports the entire Haskell 2010 language plus a wide variety of
extensions.
* Has particularly good support for concurrency and parallelism, including
support for Software Transactional Memory (STM).
* Generates fast code, particularly for concurrent programs.
* Works on several platforms including FreeBSD, Windows, Mac, Linux, most
varieties of Unix, and several different processor architectures.
* Has extensive optimisation capabilities, including inter-module optimisation.
* Compiles Haskell code either directly to native code or using LLVM as a
back-end. It can also generate C code as an intermediate target for porting
to new platforms. The interactive environment compiles Haskell to bytecode,
and supports execution of mixed bytecode/compiled programs.
* Profiling is supported, both by time/allocation and various kinds of heap
profiling.
* Comes with several libraries, and thousands more are available on Hackage.
WWW: http://www.haskell.org/ghc/