haskell-jp / questions #49

あとLLVMも
https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/Backends/LLVM/Installing
これみるとGHC 8.4系だとLLVM5.0なんですね.
最初LLVM7.0が入ったときにビルド時にwarnning出て,6.0にdowngradeしたら黙ったから気付かなかったけど
だがapt searchしても見当らないのであった.
and u zlib!!!
sudo apt install libghc-zlib-prof
うーんまたこうしてaptで入れているのとcabal で入れているのがgotchaになっていく.
ghcのバイナリインストールなら最近は ghcupがオススメです.
初耳
ghcup
祝コンパイル成功!!
まだスタートライン100メートル手前の心境.
cabal new-exec main -- +RTS -p -N8 -smain.log

が起動したので涙でモニタが見えない.
この顛末をqiitaに残すべきかどうか
こんな状態.
yesodやってたころは最終的に必要になったからstack使ったけど今はもっぱらcabalしか使ってないです.
[Network.Simple.TCP.TLS]()というパッケージで以下のようなコードを実行させてchromeでhttpsでアクセスするとスレッドが残ったままになってしまいます(Firefox、Safariでは起こらない)。
{-# LANGUAGE LambdaCase        #-}
{-# LANGUAGE OverloadedStrings #-}

module Lib
    ( someFunc
    ) where

import           Control.Concurrent
import           Control.Monad
import           Data.X509.CertificateStore
import           Network.Simple.TCP.TLS
import           Network.TLS

someFunc :: IO ()
someFunc = do
  credentialLoadX509 "./localhost.pem" "./localhost-key.pem" >>=
    \case
      Right c ->
        void $ forkIO $ serve (makeServerSettings c Nothing) "localhost" "8080" $ \(ctx, _) -> establish ctx
      _ ->
        putStrLn "Error"
  -- 終了させないためだけの処理
  _ <- getLine
  pure ()

establish :: Context -> IO ()
establish ctx = do
  r <- recv ctx
  case r of
    Just r' -> print r'
    _       -> pure ()

[このあたり]()の例外ハンドリングがまずってるんじゃないかと同僚と推測しているのですが、何かお心当たりありませんか
今更 ghc と runghc を混同していたのに気が付きました。今まで ghc として示していた結果は runghc のです。 ghc での結果はこれです(一定)。
0
MyI# 0#
IBI# 0#
1729382256910270464
MyI# 1729382256910270464#
CB
10
CB
CA
CA
無事profile採取できました.
ありがとうございました.
@ has joined the channel
@ has joined the channel
+9 (アラインメントしていない場所)からの8バイト、というのがすごく気持ち悪いです… intel だから読めるけどそれ以外のアーキテクチャだったらアラインメントエラーになるのでは、という感が

そうなんですよね、「+9」は気持ち悪いです。
正しいInt型のコードだと、payloadのInt値を読み取る箇所は、「+8」のコードを正しく吐いていました。ところが、unsafeCoerceで無理矢理に型をひねると、Cmm出力の時点でコードが「+9」を指すように変わりました。(ただ、非保証動作で深そうなので、コード生成のどこで不整合が起きているかは、それ以上追いませんでした ^^;)
stylish-haskellに関する質問です。
指定したディレクトリ内の.hsファイルすべてにstylish-haskellを適用するコマンドってありますか?
src内のhaskellモジュールが結構な数になったので一気に適用できればいいなーと考えたのです。
http://manpages.ubuntu.com/manpages/bionic/man1/stylish-haskell.1.html これでしょうか?
--inplace オプションを指定してワイルドカードで複数ファイルを指定すればよさそうですが…。
実は正しいオプションがあるかもだけど
上記ワンライナーも -i オプション(--inplace の短縮形)使ってるようですね
ワイルドカードの代わりに find の結果を使ってるだけのようです
自己解決しました。このプルリクエストが解決策でした https://github.com/k0001/network-simple-tls/pull/13
ありがとうございます!神は存在した!
find の方を使う場合は、ファイル名やディレクトリ名に特殊な文字(空白や引用符など)が含まれているとあのままでは動かないことにご注意ください
find . -type f -name "*hs" …その他の絞り込み条件… -print0 | xargs -0 stylish-haskell -i のように find の -print0 オプションと xargs の -0 オプションのコンボを使うとどんな変な文字が含まれていても大丈夫になります
find . -type f -name "*hs" -not -path '.git' -not -path '*.stack-work*' -print0 | xargs -0 stylish-haskell -i
こんな感じ?
もとのワンライナーの通りならそうですね
なるほど!ではこっちを使ってみます。ありがとうー
(シェルが zsh なら stylish-haskell -i **/*.hs だけで行けるんですけどね^^;)
@dyoshikawa has joined the channel
git管理しているならfindよりgit ls-files|egrep hs¥$の方が安全という説も
ライブラリのビルド時に使われた GHC の settings の情報 () を取れるモジュールとかってありますか?
NOINLINEプラグマって必ずインライン化を抑制するわけではないのでしょうか?
The NOINLINE pragma does exactly what you’d expect: it stops the named function from being inlined by the compiler. You shouldn’t ever need to do this, unless you’re very cautious about code size.
とあるんだけど,私の手元で-ddump-simpl-statsを見る限り,-Oを付けるとそうでもないような.
小さいコード片なのでINLINEプラグマは正直関係なく,-Oを付けようが付けまいがそれなりにやってくれてそうだけど,NOINLINE付けたときに-Oでビルドすると一番激しく(Grand total simplifier statisticsが大きく,しかも生成されたコードも一番良さげみ見受ける)最適化が走っているような
今試しているコードはこれですが,
プラグマをはずしてから-Oも付けずにddumpすると,
==================== Grand total simplifier statistics ====================
Total ticks:     15

6 PreInlineUnconditionally
  2 x
  2 x
  2 y
1 PostInlineUnconditionally 1 x'
2 UnfoldingDone 2 timesInt
1 LetFloatFromLet 1
4 BetaReduction
  2 x
  2 y
1 KnownBranch 1 wild
3 SimplifierDone 3

:
:
==================== CorePrep ====================
Result size of CorePrep
  = {terms: 53, types: 26, coercions: 0, joins: 0/0}

-- RHS size: {terms: 15, types: 7, coercions: 0, joins: 0/0}
timesInt :: Int -> Int -> Int
timesInt
  = \ (x :: Int) (y :: Int) ->
      case x of { I# x' ->
      case y of { I# y' -> case *# x' y' of sat { __DEFAULT -> I# sat } }
      }

-- RHS size: {terms: 22, types: 9, coercions: 0, joins: 0/0}
cube :: Int -> Int
cube
  = \ (x :: Int) ->
      case x of wild { I# x' ->
      case wild of wild1 { I# y' ->
      case wild1 of { I# y'1 ->
      case *# x' y' of sat { __DEFAULT ->
      case *# sat y'1 of sat { __DEFAULT -> I# sat }
      }
      }
      }
      }
プラグマを付けずに-Oを付けると
==================== Grand total simplifier statistics ====================
Total ticks:     17

4 PreInlineUnconditionally
  2 x
  2 y
3 PostInlineUnconditionally
  2 y'
  1 x'
2 UnfoldingDone 2 timesInt
1 LetFloatFromLet 1
4 BetaReduction
  2 x
  2 y
3 KnownBranch
  2 wild
  1 wild
9 SimplifierDone 9

:
:
==================== CorePrep ====================
Result size of CorePrep
  = {terms: 47, types: 22, coercions: 0, joins: 0/0}

-- RHS size: {terms: 15, types: 7, coercions: 0, joins: 0/0}
timesInt :: Int -> Int -> Int
timesInt
  = \ (x :: Int) (y :: Int) ->
      case x of { I# x' ->
      case y of { I# y' -> case *# x' y' of sat { __DEFAULT -> I# sat } }
      }

-- RHS size: {terms: 16, types: 5, coercions: 0, joins: 0/0}
cube :: Int -> Int
cube
  = \ (x :: Int) ->
      case x of { I# x' ->
      case *# x' x' of sat { __DEFAULT ->
      case *# sat x' of sat { __DEFAULT -> I# sat }
      }
      }
上のコードのようにNOINLINEを付けて-Oを付けなければ
==================== Grand total simplifier statistics ====================
Total ticks:     1

1 LetFloatFromLet 1
2 SimplifierDone 2

:
:
==================== CorePrep ====================
Result size of CorePrep
  = {terms: 39, types: 19, coercions: 0, joins: 0/1}

-- RHS size: {terms: 15, types: 7, coercions: 0, joins: 0/0}
timesInt :: Int -> Int -> Int
timesInt
  = \ (x :: Int) (y :: Int) ->
      case x of { I# x' ->
      case y of { I# y' -> case *# x' y' of sat { __DEFAULT -> I# sat } }
      }

-- RHS size: {terms: 8, types: 2, coercions: 0, joins: 0/1}
cube :: Int -> Int
cube
  = \ (x :: Int) ->
      let {
        sat :: Int
        sat = timesInt x x } in
      timesInt sat x
最後にNOINLINEが付いてて-Oも指定したら
==================== Grand total simplifier statistics ====================
Total ticks:     28

8 PreInlineUnconditionally
  3 w
  3 w
  1 x
  1 y
6 PostInlineUnconditionally
  2 ww
  1 x'
  1 y'
  1 ww
  1 ww
2 UnfoldingDone 2 timesInt
1 LetFloatFromLet 1
1 EtaReduction 1 ww
4 BetaReduction
  2 w
  2 w
6 KnownBranch
  2 ww
  1 wild
  1 wild
  1 ww
  1 ww
9 SimplifierDone 9

:
:
==================== CorePrep ====================
Result size of CorePrep
  = {terms: 53, types: 27, coercions: 0, joins: 0/0}

-- RHS size: {terms: 5, types: 2, coercions: 0, joins: 0/0}
$wtimesInt :: Int# -> Int# -> Int#
$wtimesInt = \ (eta :: Int#) (eta :: Int#) -> *# eta eta

-- RHS size: {terms: 15, types: 7, coercions: 0, joins: 0/0}
timesInt :: Int -> Int -> Int
timesInt
  = \ (w :: Int) (w1 :: Int) ->
      case w of { I# ww1 ->
      case w1 of { I# ww3 ->
      case $wtimesInt ww1 ww3 of ww4 { __DEFAULT -> I# ww4 }
      }
      }

-- RHS size: {terms: 16, types: 5, coercions: 0, joins: 0/0}
cube :: Int -> Int
cube
  = \ (x :: Int) ->
      case x of { I# ww1 ->
      case $wtimesInt ww1 ww1 of ww2 { __DEFAULT ->
      case $wtimesInt ww2 ww1 of ww3 { __DEFAULT -> I# ww3 }
      }
      }

これworker/wrapper変換かかってませんか?
http://hackage.haskell.org/package/ghc-8.6.1/docs/HscTypes.html
これとかのことですかね.
やったことないけど.
すいません,これって HscEnv のことですか? ビルド時の情報を取得する API 見つけられないんですが,どれのことでしょう?
これな気がしますね.別にそこまでコードが肥大化してるわけではないと思いますが (worker には NOINLINE がつくようなので), w/w が入ると問題となるコードとかはあるのでしょうか? あるのでしたら, GHC Trac に投げてみると良いかもしれませんが
https://gitlab.haskell.org/ghc/ghc/blob/ghc-8.6.4-release/compiler/stranal/WorkWrap.hs#L204
DynFlagsの中とかがそうかなと思って見ているところですが違うかな
あ,えっと取りたい構造自体は https://hackage.haskell.org/package/ghc-8.2.1/docs/DynFlags.html#t:Settings の中の sRawSettings に入り,ライブラリのビルド時にそれが使用されることは分かっているのですが,そのライブラリの実行時にその情報を読めるような API はあるのかなというのが,質問です.