qute

A software analysis framework built around the QBE intermediate language

git clone https://git.8pit.net/qute.git

 1-- SPDX-FileCopyrightText: 2024 University of Bremen
 2-- SPDX-FileCopyrightText: 2025 Sören Tempel <soeren+git@soeren-tempel.net>
 3--
 4-- SPDX-License-Identifier: MIT AND GPL-3.0-only
 5
 6module Language.QBE.CmdLine
 7  ( BasicArgs (..),
 8    basicArgs,
 9    loadProg,
10  )
11where
12
13import Data.Archive (qbeArchive)
14import Language.QBE (Program, parseAndFind)
15import Language.QBE.Linker (link)
16import Language.QBE.Simulator.Memory qualified as MEM
17import Language.QBE.Types qualified as QBE
18import Options.Applicative qualified as OPT
19
20-- | t'BasicArgs' can be combined/extended with additional parsers using
21-- the '<*>' applicative operator provided by "Options.Applicative".
22data BasicArgs = BasicArgs
23  { -- | Start address of the general-purpose memory.
24    optMemStart :: MEM.Address,
25    -- | Size of the memory in bytes.
26    optMemSize :: MEM.Size,
27    -- | Do not zero-initialize the memory.
28    optMemUndef :: Bool,
29    -- | Path to an .ar archive to preload.
30    optQBEArchive :: Maybe FilePath,
31    -- | Path to the QBE input file.
32    optQBEFile :: FilePath
33  }
34
35-- | "Options.Applicative" parser for t'BasicArgs'.
36basicArgs :: OPT.Parser BasicArgs
37basicArgs =
38  BasicArgs
39    <$> OPT.option
40      OPT.auto
41      ( OPT.long "memory-start"
42          <> OPT.short 'm'
43          <> OPT.value 0x10000
44      )
45    <*> OPT.option
46      OPT.auto
47      ( OPT.long "memory-size"
48          <> OPT.short 's'
49          <> OPT.value (1024 * 1024) -- 1 MB RAM
50          <> OPT.help "Size of the memory region"
51      )
52    <*> OPT.switch
53      ( OPT.long "memory-uninitialized"
54          <> OPT.help "Do not zero-initialize the memory"
55      )
56    <*> OPT.optional
57      ( OPT.strOption
58          ( OPT.long "preload"
59              <> OPT.short 'p'
60              <> OPT.metavar "FILE"
61              <> OPT.help "Preload the given .ar archive consisting of QBE files"
62          )
63      )
64    <*> OPT.argument OPT.str (OPT.metavar "FILE")
65
66------------------------------------------------------------------------
67
68-- | Name of the entry function.
69entryFunc :: QBE.GlobalIdent
70entryFunc = QBE.GlobalIdent "main"
71
72-- | Parse a file and find the 'entryFunc'.
73parseEntryFile :: FilePath -> IO (Program, QBE.FuncDef)
74parseEntryFile filePath =
75  readFile filePath >>= parseAndFind entryFunc
76
77-- | Load the program specified in 'BasicArgs'. Returns the
78-- loaded 'Program' and the entry function.
79loadProg :: BasicArgs -> IO (Program, QBE.FuncDef)
80loadProg opts = do
81  (prog, func) <- parseEntryFile $ optQBEFile opts
82  linked <-
83    case optQBEArchive opts of
84      Nothing -> pure prog
85      Just ar -> (\xs -> link $ prog : xs) <$> qbeArchive ar
86  pure (linked, func)