Compare commits

...

12 Commits

Author SHA1 Message Date
c5f6ad4573 wip: qq
Some checks failed
build / build (push) Failing after 29s
2026-04-24 12:16:43 -06:00
e03e918bf4 nix
All checks were successful
build / build (push) Successful in 15s
2026-04-24 12:16:43 -06:00
540a5e03fe update 2026-04-24 08:54:34 -06:00
Francesco Gazzetta
f552132241 Add GHC 9.4.2 to CI 2023-01-05 14:07:51 +01:00
Francesco Gazzetta
8130eefc48 Allow base 4.17 2023-01-05 12:24:23 +01:00
Francesco Gazzetta
ee46313617 Changelog for 1.1.0.0 2022-07-10 22:29:01 +02:00
Francesco Gazzetta
76735e82ac Instr haddocks 2022-07-10 22:27:32 +02:00
Francesco Gazzetta
2c4bbf659f More haddocks 2022-07-04 22:27:08 +02:00
Francesco Gazzetta
b5f10a6dab Export list 2022-07-03 18:54:00 +02:00
Francesco Gazzetta
34642bf965 Update some haddocks 2022-07-03 18:53:49 +02:00
Francesco Gazzetta
970e85a25c Add readme 2022-07-03 18:22:26 +02:00
Francesco Gazzetta
630a29e8c6 Fix function definition 2022-07-03 17:18:37 +02:00
14 changed files with 1004 additions and 42 deletions

View File

@@ -29,6 +29,7 @@ tasks:
"$HOME/.ghcup/bin/ghcup" install ghc "ghc-8.10.7"
"$HOME/.ghcup/bin/ghcup" install ghc "ghc-9.0.2"
"$HOME/.ghcup/bin/ghcup" install ghc "ghc-9.2.2"
"$HOME/.ghcup/bin/ghcup" install ghc "ghc-9.4.2"
cabal update
- 8_10_7-prepare: |
cd qbe-hs
@@ -87,6 +88,25 @@ tasks:
- 9_2_2-haddock: |
cd qbe-hs
cabal haddock all
- 9_4_2-prepare: |
cd qbe-hs
cabal configure -w ghc-9.2.2
- 9_4_2-check: |
cd qbe-hs
cabal check
- 9_4_2-dependencies: |
cd qbe-hs
cabal build all --enable-tests --only-dependencies
cabal build all --only-dependencies
- 9_4_2-build: |
cd qbe-hs
cabal build all
- 9_4_2-test: |
cd qbe-hs
cabal test all --enable-tests
- 9_4_2-haddock: |
cd qbe-hs
cabal haddock all
triggers:
- action: email
condition: failure

1
.envrc Normal file
View File

@@ -0,0 +1 @@
use flake

View File

@@ -0,0 +1,11 @@
name: build
on: [push]
jobs:
build:
runs-on: nixos
steps:
- name: Check out repository code
uses: actions/checkout@v4
- name: build qbe-hs
run: nix build -L .

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@ dist-newstyle
*.hi
.ghc.environment.*
*.tix
.direnv

View File

@@ -1,5 +1,5 @@
# Revision history for qbe-hs
## 0.1.0.0 -- YYYY-mm-dd
## 1.1.0.0 -- 2022-07-10
* First version. Released on an unsuspecting world.
* First version.

55
README.md Normal file
View File

@@ -0,0 +1,55 @@
# qbe-hs
**fork of [qbe-hs](https://git.sr.ht/~fgaz/qbe-hs)**
[![Hackage](https://img.shields.io/hackage/v/qbe.svg)](https://hackage.haskell.org/package/qbe)
[![builds.sr.ht status](https://builds.sr.ht/~fgaz/qbe-hs/commits/master.svg)](https://builds.sr.ht/~fgaz/qbe-hs/commits/master?)
Haskell types and prettyprinter for the [IL](https://c9x.me/compile/doc/il.html)
of the [QBE](https://c9x.me/compile/) compiler backend
## Example
```haskell
helloWorld :: Program
helloWorld = Program [] [helloString] [helloMain]
where
helloString = DataDef [] "str" Nothing
[ FieldExtTy Byte $ String "hello world" :| []
, FieldExtTy Byte $ Const (CInt False 0) :| []
]
helloMain = FuncDef [Export] (Just $ AbiBaseTy Word) "main"
Nothing [] NoVariadic $
Block "start"
[]
[ Call (Just ("r", AbiBaseTy Word)) (ValGlobal "puts")
Nothing
[Arg (AbiBaseTy Long) $ ValGlobal "str"]
[]
]
(Ret $ Just $ ValConst $ CInt False 0)
:| []
```
Gets rendered to
```
data $str =
{b "hello world", b 0}
export
function w $main () {
@start
%r =w call $puts (l $str)
ret 0
}
```
## Contributing
You can send patches to my
[public-inbox mailing list](https://lists.sr.ht/~fgaz/public-inbox)
or to any of the contacts listed at [fgaz.me/about](https://fgaz.me/about).
Or you can send a pull request to the
[GitHub mirror](https://github.com/fgaz/qbe-hs).
Issues are tracked at https://todo.sr.ht/~fgaz/qbe-hs

616
flake.lock generated Normal file
View File

@@ -0,0 +1,616 @@
{
"nodes": {
"HTTP": {
"flake": false,
"locked": {
"lastModified": 1451647621,
"narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=",
"owner": "phadej",
"repo": "HTTP",
"rev": "9bc0996d412fef1787449d841277ef663ad9a915",
"type": "github"
},
"original": {
"owner": "phadej",
"repo": "HTTP",
"type": "github"
}
},
"cabal-34": {
"flake": false,
"locked": {
"lastModified": 1645834128,
"narHash": "sha256-wG3d+dOt14z8+ydz4SL7pwGfe7SiimxcD/LOuPCV6xM=",
"owner": "haskell",
"repo": "cabal",
"rev": "5ff598c67f53f7c4f48e31d722ba37172230c462",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "3.4",
"repo": "cabal",
"type": "github"
}
},
"cabal-36": {
"flake": false,
"locked": {
"lastModified": 1669081697,
"narHash": "sha256-I5or+V7LZvMxfbYgZATU4awzkicBwwok4mVoje+sGmU=",
"owner": "haskell",
"repo": "cabal",
"rev": "8fd619e33d34924a94e691c5fea2c42f0fc7f144",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "3.6",
"repo": "cabal",
"type": "github"
}
},
"cardano-shell": {
"flake": false,
"locked": {
"lastModified": 1608537748,
"narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=",
"owner": "input-output-hk",
"repo": "cardano-shell",
"rev": "9392c75087cb9a3d453998f4230930dea3a95725",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "cardano-shell",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1672831974,
"narHash": "sha256-z9k3MfslLjWQfnjBtEtJZdq3H7kyi2kQtUThfTgdRk0=",
"owner": "input-output-hk",
"repo": "flake-compat",
"rev": "45f2638735f8cdc40fe302742b79f248d23eb368",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"ref": "hkm/gitlab-fix",
"repo": "flake-compat",
"type": "github"
}
},
"hackage": {
"flake": false,
"locked": {
"lastModified": 1776991436,
"narHash": "sha256-nR65DbgoJ8Qm8qEtqmVXzeWZS+cc3FeqaZgFon8qdtc=",
"owner": "input-output-hk",
"repo": "hackage.nix",
"rev": "2a5e0e1854e7f651ce13df74a60d7c2990a63528",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "hackage.nix",
"type": "github"
}
},
"hackage-for-stackage": {
"flake": false,
"locked": {
"lastModified": 1776991429,
"narHash": "sha256-uiuvT6/wp2uNdtVl8kQ70WSyrye6EdRRQ+yor9kIJLU=",
"owner": "input-output-hk",
"repo": "hackage.nix",
"rev": "793f260668f3f8d34f64056e6941d234093fc51e",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"ref": "for-stackage",
"repo": "hackage.nix",
"type": "github"
}
},
"hackage-internal": {
"flake": false,
"locked": {
"lastModified": 1750307553,
"narHash": "sha256-iiafNoeLHwlSLQTyvy8nPe2t6g5AV4PPcpMeH/2/DLs=",
"owner": "input-output-hk",
"repo": "hackage.nix",
"rev": "f7867baa8817fab296528f4a4ec39d1c7c4da4f3",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "hackage.nix",
"type": "github"
}
},
"haskellNix": {
"inputs": {
"HTTP": "HTTP",
"cabal-34": "cabal-34",
"cabal-36": "cabal-36",
"cardano-shell": "cardano-shell",
"flake-compat": "flake-compat",
"hackage": "hackage",
"hackage-for-stackage": "hackage-for-stackage",
"hackage-internal": "hackage-internal",
"hls": "hls",
"hls-1.10": "hls-1.10",
"hls-2.0": "hls-2.0",
"hls-2.10": "hls-2.10",
"hls-2.11": "hls-2.11",
"hls-2.12": "hls-2.12",
"hls-2.2": "hls-2.2",
"hls-2.3": "hls-2.3",
"hls-2.4": "hls-2.4",
"hls-2.5": "hls-2.5",
"hls-2.6": "hls-2.6",
"hls-2.7": "hls-2.7",
"hls-2.8": "hls-2.8",
"hls-2.9": "hls-2.9",
"hpc-coveralls": "hpc-coveralls",
"iserv-proxy": "iserv-proxy",
"nixpkgs": [
"haskellNix",
"nixpkgs-unstable"
],
"nixpkgs-2305": "nixpkgs-2305",
"nixpkgs-2311": "nixpkgs-2311",
"nixpkgs-2405": "nixpkgs-2405",
"nixpkgs-2411": "nixpkgs-2411",
"nixpkgs-2505": "nixpkgs-2505",
"nixpkgs-2511": "nixpkgs-2511",
"nixpkgs-unstable": "nixpkgs-unstable",
"old-ghc-nix": "old-ghc-nix",
"stackage": "stackage"
},
"locked": {
"lastModified": 1776993036,
"narHash": "sha256-M770+TVYcqAlBAGWEi9HeljqNxujcNBlsNmZCwnxQaI=",
"owner": "input-output-hk",
"repo": "haskell.nix",
"rev": "902f9c7fee56b7550293dd691264f0c889e7af26",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "haskell.nix",
"type": "github"
}
},
"hls": {
"flake": false,
"locked": {
"lastModified": 1741604408,
"narHash": "sha256-tuq3+Ip70yu89GswZ7DSINBpwRprnWnl6xDYnS4GOsc=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "682d6894c94087da5e566771f25311c47e145359",
"type": "github"
},
"original": {
"owner": "haskell",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-1.10": {
"flake": false,
"locked": {
"lastModified": 1680000865,
"narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "1.10.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.0": {
"flake": false,
"locked": {
"lastModified": 1687698105,
"narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "783905f211ac63edf982dd1889c671653327e441",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.0.0.1",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.10": {
"flake": false,
"locked": {
"lastModified": 1743069404,
"narHash": "sha256-q4kDFyJDDeoGqfEtrZRx4iqMVEC2MOzCToWsFY+TOzY=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "2318c61db3a01e03700bd4b05665662929b7fe8b",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.10.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.11": {
"flake": false,
"locked": {
"lastModified": 1747306193,
"narHash": "sha256-/MmtpF8+FyQlwfKHqHK05BdsxC9LHV70d/FiMM7pzBM=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "46ef4523ea4949f47f6d2752476239f1c6d806fe",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.11.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.12": {
"flake": false,
"locked": {
"lastModified": 1758709460,
"narHash": "sha256-xkI8MIIVEVARskfWbGAgP5sHG/lyeKnkm0LIOJ19X5w=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "7d983de4fa7ff54369f6dd31444bdb9869aec83e",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.12.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.2": {
"flake": false,
"locked": {
"lastModified": 1693064058,
"narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.2.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.3": {
"flake": false,
"locked": {
"lastModified": 1695910642,
"narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.3.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.4": {
"flake": false,
"locked": {
"lastModified": 1699862708,
"narHash": "sha256-YHXSkdz53zd0fYGIYOgLt6HrA0eaRJi9mXVqDgmvrjk=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "54507ef7e85fa8e9d0eb9a669832a3287ffccd57",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.4.0.1",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.5": {
"flake": false,
"locked": {
"lastModified": 1701080174,
"narHash": "sha256-fyiR9TaHGJIIR0UmcCb73Xv9TJq3ht2ioxQ2mT7kVdc=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "27f8c3d3892e38edaef5bea3870161815c4d014c",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.5.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.6": {
"flake": false,
"locked": {
"lastModified": 1705325287,
"narHash": "sha256-+P87oLdlPyMw8Mgoul7HMWdEvWP/fNlo8jyNtwME8E8=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "6e0b342fa0327e628610f2711f8c3e4eaaa08b1e",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.6.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.7": {
"flake": false,
"locked": {
"lastModified": 1708965829,
"narHash": "sha256-LfJ+TBcBFq/XKoiNI7pc4VoHg4WmuzsFxYJ3Fu+Jf+M=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "50322b0a4aefb27adc5ec42f5055aaa8f8e38001",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.7.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.8": {
"flake": false,
"locked": {
"lastModified": 1715153580,
"narHash": "sha256-Vi/iUt2pWyUJlo9VrYgTcbRviWE0cFO6rmGi9rmALw0=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "dd1be1beb16700de59e0d6801957290bcf956a0a",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.8.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.9": {
"flake": false,
"locked": {
"lastModified": 1719993701,
"narHash": "sha256-wy348++MiMm/xwtI9M3vVpqj2qfGgnDcZIGXw8sF1sA=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "90319a7e62ab93ab65a95f8f2bcf537e34dae76a",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.9.0.1",
"repo": "haskell-language-server",
"type": "github"
}
},
"hpc-coveralls": {
"flake": false,
"locked": {
"lastModified": 1607498076,
"narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=",
"owner": "sevanspowell",
"repo": "hpc-coveralls",
"rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430",
"type": "github"
},
"original": {
"owner": "sevanspowell",
"repo": "hpc-coveralls",
"type": "github"
}
},
"iserv-proxy": {
"flake": false,
"locked": {
"lastModified": 1775620557,
"narHash": "sha256-10x8/G0x3eR/++XRHPx4MBuqlnc6+N+ajIxXyLkG+nU=",
"owner": "stable-haskell",
"repo": "iserv-proxy",
"rev": "3f7b2815307c20a0dfd816bdf4a39ab86af3e0d4",
"type": "github"
},
"original": {
"owner": "stable-haskell",
"ref": "iserv-syms",
"repo": "iserv-proxy",
"type": "github"
}
},
"nixpkgs-2305": {
"locked": {
"lastModified": 1705033721,
"narHash": "sha256-K5eJHmL1/kev6WuqyqqbS1cdNnSidIZ3jeqJ7GbrYnQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a1982c92d8980a0114372973cbdfe0a307f1bdea",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-23.05-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2311": {
"locked": {
"lastModified": 1719957072,
"narHash": "sha256-gvFhEf5nszouwLAkT9nWsDzocUTqLWHuL++dvNjMp9I=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7144d6241f02d171d25fba3edeaf15e0f2592105",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-23.11-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2405": {
"locked": {
"lastModified": 1735564410,
"narHash": "sha256-HB/FA0+1gpSs8+/boEavrGJH+Eq08/R2wWNph1sM1Dg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "1e7a8f391f1a490460760065fa0630b5520f9cf8",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-24.05-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2411": {
"locked": {
"lastModified": 1751290243,
"narHash": "sha256-kNf+obkpJZWar7HZymXZbW+Rlk3HTEIMlpc6FCNz0Ds=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5ab036a8d97cb9476fbe81b09076e6e91d15e1b6",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-24.11-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2505": {
"locked": {
"lastModified": 1764560356,
"narHash": "sha256-M5aFEFPppI4UhdOxwdmceJ9bDJC4T6C6CzCK1E2FZyo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6c8f0cca84510cc79e09ea99a299c9bc17d03cb6",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-25.05-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-2511": {
"locked": {
"lastModified": 1775749320,
"narHash": "sha256-msT6frWJSQ2WR+0cpk+KPcZdLTLagUIsJwQwIX9JNSo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "74b87959b2d16f59f54d8559cf3cf26b9d907949",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-25.11-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1775888245,
"narHash": "sha256-nwASzrRDD1JBEu/o8ekKYEXm/oJW6EMCzCRdrwcLe90=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "13043924aaa7375ce482ebe2494338e058282925",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"old-ghc-nix": {
"flake": false,
"locked": {
"lastModified": 1631092763,
"narHash": "sha256-sIKgO+z7tj4lw3u6oBZxqIhDrzSkvpHtv0Kki+lh9Fg=",
"owner": "angerman",
"repo": "old-ghc-nix",
"rev": "af48a7a7353e418119b6dfe3cd1463a657f342b8",
"type": "github"
},
"original": {
"owner": "angerman",
"ref": "master",
"repo": "old-ghc-nix",
"type": "github"
}
},
"root": {
"inputs": {
"haskellNix": "haskellNix",
"nixpkgs": [
"haskellNix",
"nixpkgs-unstable"
]
}
},
"stackage": {
"flake": false,
"locked": {
"lastModified": 1776990505,
"narHash": "sha256-PC/DD76TdzSvs18mL3O7V4wwt6WRHlzxmdrpKFwz68A=",
"owner": "input-output-hk",
"repo": "stackage.nix",
"rev": "c8e2fb3340b2316c84fede31ac01b5446fe2c880",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "stackage.nix",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

82
flake.nix Normal file
View File

@@ -0,0 +1,82 @@
{
inputs = {
haskellNix.url = "github:input-output-hk/haskell.nix";
# nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
nixpkgs.follows = "haskellNix/nixpkgs-unstable";
};
outputs = { self, nixpkgs, haskellNix, ... }@inputs:
let
supportedSystems = [
"aarch64-darwin" "aarch64-linux"
"x86_64-darwin" "x86_64-linux"
];
overlays = [
haskellNix.overlay
(final: _prev: {
# This overlay adds our project to pkgs
qbe-hs = final.haskell-nix.project' {
src = ./.;
compiler-nix-name = "ghc912";
# This is used by `nix develop .` to open a shell for use with
# `cabal`, `hlint` and `haskell-language-server`
shell.tools = {
cabal = {};
# hlint = {};
# haskell-language-server = {};
};
# Non-Haskell shell tools go here
shell.buildInputs = with final; [
gcc
qbe
];
# passthru = { inherit (final) qbe; };
# This adds `js-unknown-ghcjs-cabal` to the shell.
# shell.crossPlatforms = p: [p.ghcjs];
};
})
];
each-system = f: nixpkgs.lib.genAttrs supportedSystems (system: f rec {
pkgs = import nixpkgs {
inherit system overlays;
};
inherit (pkgs) lib;
inherit system;
});
# haskell-flake
hf =
let
keys = [
"packages" "apps" "devShells"
"hydraJobs" "ciJobs" "checks"
];
in nixpkgs.lib.genAttrs keys
(k: each-system ({ pkgs, ... }: (pkgs.qbe-hs.flake {}).${k}));
in {
# Exposed as a REPL convenience.
_pkgs = each-system ({ pkgs, ... }: pkgs);
packages = each-system ({ pkgs, system, ... }:
hf.packages.${system} // {
default = hf.packages.${system}."qbe:lib:qbe";
});
devShells = each-system
({ pkgs, system, ... }: hf.devShells.${system});
};
nixConfig = {
extra-substituters = [
"https://cache.iog.io"
"https://cache.zw3rk.com"
];
extra-trusted-public-keys = [
"hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ="
"loony-tools:pr9m4BkM/5/eSTZlkQyRt57Jz7OMBxNSUiMC4FkcNfk="
];
allow-import-from-derivation = "true";
};
}

View File

@@ -1,5 +1,5 @@
export
function :t $f
(env %env, w %a, d %b, ...)
{@l
ret }
function :t $f (env %env, w %a, d %b, ...) {
@l
ret
}

View File

@@ -2,8 +2,8 @@
data $str =
{b "hello world", b 0}
export
function w $main
()
{@start
%r =w call $puts (l $str)
ret 0}
function w $main () {
@start
%r =w call $puts (l $str)
ret 0
}

View File

@@ -4,8 +4,9 @@ name: qbe
version: 1.1.0.0
synopsis: Types and prettyprinter for the IL of the QBE compiler backend
description:
This library provides types representing the intermediate language of the QBE
compiler backend.
This library provides types representing
the [intermediate language](https://c9x.me/compile/doc/il.html)
of the [QBE](https://c9x.me/compile/) compiler backend.
It also provides pretty-printing instances based on
the [@prettyprinter@](https://hackage.haskell.org/package/prettyprinter)
library, that emit the textual representation of the IL.
@@ -19,11 +20,13 @@ copyright: 2022 Francesco Gazzetta
category: Language
build-type: Simple
extra-doc-files: CHANGELOG.md
extra-source-files: golden/*.qbe
extra-source-files: README.md golden/*.qbe
tested-with:
, GHC == 8.10.7
, GHC == 9.0.2
, GHC == 9.2.2
, GHC == 9.4.2
, GHC == 9.10.3
source-repository head
type: git
@@ -36,11 +39,15 @@ common common
-Wredundant-constraints
-Wincomplete-uni-patterns
-Wincomplete-record-updates
-fdefer-type-errors
-fno-show-valid-hole-fits
-fdefer-out-of-scope-variables
-Wno-typed-holes
default-language: Haskell2010
library
import: common
exposed-modules: Language.QBE
exposed-modules: Language.QBE Language.QBE.QQ
-- other-modules:
other-extensions: DataKinds
KindSignatures
@@ -51,13 +58,21 @@ library
build-depends: base ^>= 4.16.1.0
|| ^>= 4.14
|| ^>= 4.15
|| ^>= 4.17
|| ^>= 4.20
|| ^>= 4.21
|| ^>= 4.22
, text ^>= 1.2.5
|| ^>= 2.0
, text-short ^>= 0.1
|| ^>= 2.1.4
, text-short >= 0.1 || ^>= 0.1.6.1
, bytestring ^>= 0.11.3
|| ^>= 0.12
, hashable ^>= 1.4.0
, deepseq ^>= 1.4.4
|| ^>= 1.5.0
, deepseq ^>= 1.4.4 || ^>= 1.5
, prettyprinter ^>= 1.7.1
, megaparsec ^>= 9.7.0
, template-haskell
hs-source-dirs: src
test-suite golden
@@ -70,7 +85,7 @@ test-suite golden
, prettyprinter
, filepath ^>= 1.4.2.2
, tasty ^>= 1.4.2.3
, tasty-silver ^>= 3.3.1.1
, tasty-silver ^>= 3.3.1.1 || ^>= 3.3.2.1
other-extensions: TypeApplications
OverloadedStrings
DataKinds

View File

@@ -4,7 +4,79 @@
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
module Language.QBE where
{-|
Module : Language.QBE
Description : Types and Pretty instances for the QBE IL
Copyright : (c) Francesco Gazzetta, 2022
License : BSD-3-Clause
Maintainer : Francesco Gazzetta <fgaz@fgaz.me>
This module contains datatypes representing the various structures of
the [intermediate language](https://c9x.me/compile/doc/il.html)
of the [QBE](https://c9x.me/compile/) compiler backend.
All datatypes also have 'Pretty' instances from
the [@prettyprinter@](https://hackage.haskell.org/package/prettyprinter)
library.
You can render QBE IL source files, or any part of them, with something like:
> render :: Pretty a => a -> Text
> render = renderStrict . layoutPretty defaultLayoutOptions . pretty
>>> render $ Ret $ Just $ ValTemporary "a"
"ret %a"
>>> Text.putStrLn $ render $ Program [] [] [FuncDef [] Nothing "main" …
function w $main () {
@start
-}
module Language.QBE
(
-- * Identifiers
RawIdent
, Sigil(..)
, Ident(..)
-- * Types
, BaseTy(..)
, ExtTy(..)
-- * Constants
, Const(..)
-- * Linkage
, Linkage(..)
-- * Definitions
, Alignment
, Size
, Amount
-- ** Aggregate types
, TypeDef(..)
, SubTy(..)
-- ** Data
, DataDef(..)
, DataItem(..)
, Field(..)
-- ** Functions
, FuncDef(..)
, AbiTy(..)
, Param(..)
, Variadic(..)
, prettyVariadic
-- * Control
, Val(..)
, Block(..)
, Jump(..)
-- * Instructions
, Phi(..)
, PhiArg(..)
, Inst(..)
, Assignment(..)
, pattern (:=)
, IntRepr(..)
, BinaryOp(..)
, Comparison(..)
, Arg(..)
-- * Program
, Program(..)
) where
import Data.Text (Text)
import Data.Text.Short (ShortText)
@@ -15,7 +87,7 @@ import Data.List.NonEmpty (NonEmpty, toList)
import Data.Maybe (maybeToList)
import Prettyprinter
( Pretty(pretty), Doc, (<+>), vsep, hsep, hang, punctuate, group, flatAlt
, space, encloseSep, tupled, comma, equals, braces )
, space, encloseSep, tupled, comma, equals, braces, lbrace, rbrace )
-- Instances
import Data.Hashable (Hashable)
import Control.DeepSeq (NFData)
@@ -24,8 +96,10 @@ import Data.String (IsString)
-- * Identifiers
----------------
-- | A raw identifier string, with no sigil information attached
type RawIdent = ShortText
-- | Sigils are used to differentiate the verious types of 'Ident'ifier.
data Sigil
= AggregateTy -- ^ @:@
| Global -- ^ @$@
@@ -64,7 +138,12 @@ instance Pretty (Ident 'Label) where
-- * Types
----------
data BaseTy = Word | Long | Single | Double
-- | Base types
data BaseTy
= Word -- ^ @w@
| Long -- ^ @l@
| Single -- ^ @s@
| Double -- ^ @d@
deriving (Show, Eq)
instance Pretty BaseTy where
@@ -73,7 +152,11 @@ instance Pretty BaseTy where
pretty Single = pretty 's'
pretty Double = pretty 'd'
data ExtTy = BaseTy BaseTy | Byte | HalfWord
-- | Extended types
data ExtTy
= BaseTy BaseTy
| Byte -- ^ @b@
| HalfWord -- ^ @h@
deriving (Show, Eq)
instance Pretty ExtTy where
@@ -84,12 +167,13 @@ instance Pretty ExtTy where
-- * Constants
--------------
-- | Constant/immediate
data Const
-- MAYBE just use a signed type
= CInt Bool Word64 -- ^ The 'Bool' is whether to negate
| CSingle Float
| CDouble Double
| CGlobal (Ident 'Global)
= CInt Bool Word64 -- ^ 64 bit integer. The 'Bool' is whether to negate.
| CSingle Float -- ^ Single-precision float
| CDouble Double -- ^ Double-precision float
| CGlobal (Ident 'Global) -- ^ Global symbol
deriving (Show, Eq)
instance Pretty Const where
@@ -103,8 +187,8 @@ instance Pretty Const where
------------
data Linkage
= Export
| Section ShortText (Maybe Text)
= Export -- ^ Marks the defined item as visible outside the current file's scope
| Section ShortText (Maybe Text) -- ^ Section name, with optional linker flags
deriving (Show, Eq)
instance Pretty Linkage where
@@ -123,6 +207,7 @@ type Amount = Word64
-- ** Aggregate types
---------------------
-- | Aggregate type
data TypeDef
= TypeDef (Ident 'AggregateTy) (Maybe Alignment) [(SubTy, Maybe Amount)]
| Opaque (Ident 'AggregateTy) Alignment Size
@@ -140,6 +225,7 @@ instance Pretty TypeDef where
"type" <+> pretty ident <+> equals
<+> "align" <+> pretty alignment <+> braces (pretty size)
-- | A type that can be part of an aggregate type
data SubTy
= SubExtTy ExtTy
| SubAggregateTy (Ident 'AggregateTy)
@@ -152,6 +238,7 @@ instance Pretty SubTy where
-- ** Data
----------
-- | Global object definition
data DataDef = DataDef [Linkage] (Ident 'Global) (Maybe Alignment) [Field]
deriving (Show, Eq)
@@ -187,6 +274,7 @@ instance Pretty Field where
-- ** Functions
---------------
-- TODO use record syntax on long types like this one
-- | Function definition. The 'Maybe (Ident \'Temporary)' is the environment
data FuncDef = FuncDef [Linkage] (Maybe AbiTy) (Ident 'Global) (Maybe (Ident 'Temporary)) [Param] Variadic (NonEmpty Block)
deriving (Show, Eq)
@@ -194,12 +282,13 @@ data FuncDef = FuncDef [Linkage] (Maybe AbiTy) (Ident 'Global) (Maybe (Ident 'Te
instance Pretty FuncDef where
pretty (FuncDef linkage abiTy ident env params variadic blocks) = vsep
[ vsep $ pretty <$> linkage
, "function" <+> pretty abiTy <+> pretty ident
, tupled $
, "function" <+> pretty abiTy <+> pretty ident <+> tupled (
maybeToList (("env" <+>) . pretty <$> env)
++ fmap pretty params
++ maybeToList (prettyVariadic variadic)
, braces $ vsep $ toList $ pretty <$> blocks
) <+> lbrace
, vsep $ toList $ pretty <$> blocks
, rbrace
]
data AbiTy = AbiBaseTy BaseTy | AbiAggregateTy (Ident 'AggregateTy)
@@ -209,15 +298,19 @@ instance Pretty AbiTy where
pretty (AbiBaseTy baseTy) = pretty baseTy
pretty (AbiAggregateTy ident) = pretty ident
-- | Function parameter
data Param = Param AbiTy (Ident 'Temporary)
deriving (Show, Eq)
instance Pretty Param where
pretty (Param abiTy ident) = pretty abiTy <+> pretty ident
-- | Indicates the presence or absence of a variadic marker
data Variadic = Variadic | NoVariadic
deriving (Show, Eq)
-- | 'Variadic' → @Just "..."@
-- 'NoVariadic' → @Nothing@
prettyVariadic :: Variadic -> Maybe (Doc a)
prettyVariadic Variadic = Just "..."
prettyVariadic NoVariadic = Nothing
@@ -225,6 +318,7 @@ prettyVariadic NoVariadic = Nothing
-- * Control
------------
-- | Value, either an immediate or a global or temporary identifier.
data Val
= ValConst Const
| ValTemporary (Ident 'Temporary)
@@ -236,6 +330,7 @@ instance Pretty Val where
pretty (ValTemporary ident) = pretty ident
pretty (ValGlobal ident) = pretty ident
-- | Block of instructions beginning with a label and ending with a jump
data Block = Block (Ident 'Label) [Phi] [Inst] Jump
deriving (Show, Eq)
@@ -247,10 +342,11 @@ instance Pretty Block where
, [pretty jump]
]
-- | Jump instructions
data Jump
= Jmp (Ident 'Label)
| Jnz Val (Ident 'Label) (Ident 'Label)
| Ret (Maybe Val)
= Jmp (Ident 'Label) -- ^ Unconditional jump
| Jnz Val (Ident 'Label) (Ident 'Label) -- ^ Conditional jump
| Ret (Maybe Val) -- ^ Function return
deriving (Show, Eq)
instance Pretty Jump where
@@ -264,6 +360,8 @@ instance Pretty Jump where
-- * Instructions
-----------------
-- MAYBE change [PhiArg] to Map (Ident 'Label) Val
-- | Phi instruction
data Phi = Phi Assignment [PhiArg]
deriving (Show, Eq)
@@ -271,23 +369,30 @@ instance Pretty Phi where
pretty (Phi assignment args) =
pretty assignment <+> "phi" <+> hsep (punctuate comma $ pretty <$> args)
-- | Phi instruction argument, associating a 'Val' to a 'Label'
data PhiArg = PhiArg (Ident 'Label) Val
deriving (Show, Eq)
instance Pretty PhiArg where
pretty (PhiArg label val) = pretty label <+> pretty val
-- | Instruction
data Inst
-- Arithmetic and Bits
= BinaryOp Assignment BinaryOp Val Val
| Neg Assignment Val
= BinaryOp Assignment BinaryOp Val Val -- ^ Binary arithmetic and bit operations
| Neg Assignment Val -- ^ @neg@
-- Memory
-- | @stored@/@stores@/@storel@/@storew@/@storeh@/@storeb@
| Store ExtTy Val Val
-- MAYBE collapse all the Loads in a single Load constructor and just discard
-- the intrepr when unused.
| Load Assignment BaseTy Val -- ^ @\<ident\> =\<baseTy\> load\<baseTy\> \<val\>@
| LoadW Assignment IntRepr Val -- ^ @\<ident\> =\<baseTy\> load\<intRepr\>w \<val\>@
-- | @loadw@/@loadl@/@loads@/@loadd@
| Load Assignment BaseTy Val
-- | @loadsw@/@loaduw@
| LoadW Assignment IntRepr Val
-- | @loadsh@/@loaduh@
| LoadH Assignment IntRepr Val
-- | @loadsb@/@loadub@
| LoadB Assignment IntRepr Val
-- Comparisons
| Compare Assignment Comparison BaseTy Val Val
@@ -313,13 +418,17 @@ data Inst
-- | @sltof@/@ultof@
| LtoF Assignment IntRepr Val
-- Cast and Copy
-- | @cast@
| Cast Assignment Val
-- | @copy@
| Copy Assignment Val
-- Calls
-- | the fields are: assignment, function name, environment, arguments, variadic arguments
-- | @call@. The fields are: assignment, function name, environment, arguments, variadic arguments
| Call (Maybe (Ident 'Temporary, AbiTy)) Val (Maybe Val) [Arg] [Arg]
-- Variadic
-- | @vastart@, initializes a variable argument list
| VaStart (Ident 'Temporary)
-- | @vaarg@, fetches the next argument from a variable argument list
| VaArg Assignment (Ident 'Temporary)
deriving (Show, Eq)
@@ -368,6 +477,7 @@ instance Pretty Inst where
pretty (VaStart argList) = "vastart" <+> pretty argList
pretty (VaArg assignment argList) = pretty assignment <+> "vaarg" <+> pretty argList
-- | Represents the @%x =t@ part of an instruction.
data Assignment = Assignment (Ident 'Temporary) BaseTy
deriving (Show, Eq)
@@ -378,9 +488,11 @@ pattern (:=) ident ty = Assignment ident ty
instance Pretty Assignment where
pretty (Assignment ident ty) = pretty ident <+> equals <> pretty ty
-- | Integer representation
data IntRepr = Signed | Unsigned
deriving (Show, Eq)
-- | Binary arithmetic and bit operations
data BinaryOp
-- | @add@
= Add
@@ -453,6 +565,7 @@ instance Pretty IntRepr where
pretty Signed = pretty 's'
pretty Unsigned = pretty 'u'
-- | Function argument
data Arg = Arg AbiTy Val
deriving (Show, Eq)
@@ -462,6 +575,7 @@ instance Pretty Arg where
-- * Program
------------
-- | Datatypre representing a QBE IL source file
data Program = Program [TypeDef] [DataDef] [FuncDef]
deriving (Show, Eq)
@@ -475,7 +589,7 @@ instance Pretty Program where
-- * Utilities
--------------
-- like 'list' and 'tupled'
-- | Like 'list' and 'tupled', but with braces
braced :: [Doc ann] -> Doc ann
braced = group . encloseSep (flatAlt "{ " "{")
(flatAlt " }" "}")

43
src/Language/QBE/QQ.hs Normal file
View File

@@ -0,0 +1,43 @@
{-# LANGUAGE RankNTypes, TypeAbstractions, OverloadedStrings, ScopedTypeVariables #-}
module Language.QBE.QQ
( qbe
)
where
import qualified Language.Haskell.TH as TH
import Language.Haskell.TH.Quote
import Data.Void
import Text.Megaparsec
import Text.Megaparsec.Char
import qualified Text.Megaparsec.Char.Lexer as L
import Language.QBE
import Data.Proxy
type P = Parsec Void String
space = L.space space1 empty empty
lexeme = L.lexeme space1
symbol = L.symbol space1
ident :: Sigil -> P (Ident t)
ident (Proxy @t) = do
case t of
AggregateTy -> char ':'
Ident <$> ""
assignment :: P Assignment
assignment = do
ident
assignmentInst :: P Inst
assignmentInst = _
qbeQuoteExp :: String -> TH.ExpQ
qbeQuoteExp = _
qbe :: QuasiQuoter
qbe = QuasiQuoter
{ quoteExp = qbeQuoteExp
, quotePat = _
}

View File

@@ -113,6 +113,10 @@ helloWorld = Program [] [helloString] [helloMain]
Nothing [] NoVariadic $
Block "start"
[]
[Call (Just ("r", AbiBaseTy Word)) (ValGlobal "puts") Nothing [Arg (AbiBaseTy Long) $ ValGlobal "str"] []]
[ Call (Just ("r", AbiBaseTy Word)) (ValGlobal "puts")
Nothing
[Arg (AbiBaseTy Long) $ ValGlobal "str"]
[]
]
(Ret $ Just $ ValConst $ CInt False 0)
:| []