Compilerbauhome Compilerbau: Die virtuelle ppl-Maschine Prof. Dr. Uwe Schmidt FH Wedel

Die virtuelle ppl-Maschine


weiter

Die virtuelle ppl-Maschine

Die Komponenten der ppl-VM
Die Zielmaschine realisiert eine getypte Architektur: Alle Werte sind mit einem Typ markiert (tagged architectures). tagged architectures gibt es in Hardware realisiert nur in Spezialrechnern, ein Beispiel waren in den 80er Jahren LISP-Maschinen. Für general purpose Architekturen ist dieser Ansatz nicht flexibel genug. Für in Software realisierte Maschinen ist dieser Ansatz aber durchaus gängig. Hier wurde dieser Ansatz unter anderem zum Erkennen von Fehlern im Compiler gewählt.
 
Es gibt einen Wert undefiniert, mit dem der Speicher initialisiert wird, um Fehler im Gebrauch von nicht initialisierten Programmvariablen zu erkennen. Neben den Datentypen aus der Quellsprache, wie Zahlen, Bilder und Listen gibt es noch einen Typ für Codeadressen. Dieser wird für Unterprogrammsprünge benötigt.
 
Der Zustand einer VM besteht aus dem Codesegment (instr), aus dem Programmzähler (pc), dieser muss in das Codesegment zeigen, aus dem Speicher für die globalen Variablen, das statische Datensegment (mem), dem Laufzeitkeller, einer Liste von Datensegmenten (frames), dem Keller für die Auswertung arithmetischer Ausdrücke (stack) und einem Statusregister (status), das Fehlersituationen anzeigt.
weiter

weiter

Die Datenstruktur für die Maschine ppl/src/PPL/MachineArchitecture.hs

   1module PPL.MachineArchitecture where
   2
   3import PPL.Instructions
   4import PPL.Picture
   5
   6import Data.Array
   7
   8type MProg      = Array Int Instr       -- the machine programm
   9
  10-- machine values are tagged
  11-- there is an undefined value for initializing variable
  12-- if this value is read from the data memory, an error is issued
  13-- 
  14
  15data MV
  16    = VUndef
  17    | VInt      Int
  18    | VFloat    Double
  19    | VString   String
  20    | VPic      Picture
  21    | VList     [MV]
  22    | VCodeAddr Int
  23
  24data MStatus
  25    = Ok                -- continue
  26    | Exc       String  -- exception in instr exec
  27
  28-- the memory for program variables
  29
  30type Mem        = [MV]
  31
  32-- the evaluation stack
  33
  34type Stack      = [MV]
  35
  36-- the complete machine state
  37
  38data MS         = MS { instr    :: ! MProg
  39                     , pc       :: ! Int
  40                     , mem      :: ! Mem
  41                     , stack    :: ! Stack
  42                     , frames   :: ! [Mem]
  43                     , status   :: ! MStatus
  44                     }
  45
  46-- -------------------------------------------------------------------
  47
  48-- machine state access functions
  49
  50-- -------------------------------------------------------------------
  51
  52-- pc access
  53
  54getPc           :: MS -> Int
  55getPc ms        = pc ms
  56
  57setPc           :: Int -> MS -> MS
  58setPc pc1 ms    = ms { pc = pc1 }
  59
  60incrPc          :: MS -> MS
  61incrPc ms       = ms { pc = (getPc ms + 1) }
  62
  63legalPc         :: MS -> Bool
  64legalPc ms
  65    = pc1 >= lb && pc1 <= ub
  66      where
  67      (lb, ub) = bounds (instr ms)
  68      pc1 = pc ms
  69
  70getInstr        :: MS -> Instr
  71getInstr ms
  72    = instr ms ! pc ms
  73
  74-- -------------------------------------------------------------------
  75
  76-- memory access
  77
  78-- global memory
  79
  80legalMemAddr    :: Address -> MS -> Bool
  81legalMemAddr (AbsA addr) ms
  82    = addr >= 0 && addr < ub
  83      where
  84      ub = length (mem ms)
  85
  86legalMemAddr (LocA addr) ms
  87    = not (null stackframes)
  88      && addr >= 0
  89      && addr < ub
  90      where
  91      ub = length (head stackframes)
  92      stackframes = frames ms
  93
  94readMem         :: Address -> MS -> MV
  95                -- pre: legalMemAddr
  96readMem (AbsA addr) ms
  97    = (mem ms) !! addr
  98
  99readMem (LocA addr) ms
 100    = head (frames ms) !! addr
 101
 102
 103writeMem        :: Address -> MV -> MS -> MS
 104                -- pre: legalMemAddr
 105writeMem (AbsA addr) val ms
 106    = ms { mem = substVal addr val (mem ms) }
 107
 108writeMem (LocA addr) val ms
 109    = ms { frames = substVal addr val top : rest }
 110      where
 111      (top : rest) = frames ms
 112
 113substVal        :: Int -> MV -> Mem -> Mem
 114substVal ix val l
 115    = left ++ (val : tail right)
 116      where
 117      (left, right) = splitAt ix l
 118
 119allocFrame      :: Int -> MS -> MS
 120allocFrame size ms
 121    = ms { frames = newframe : frames ms }
 122      where
 123      newframe = replicate size VUndef
 124
 125freeFrame       :: MS -> MS
 126                -- pre: not empty stack of frames
 127freeFrame ms
 128    = ms { frames = tail (frames ms) }
 129
 130nullFrames      :: MS -> Bool
 131nullFrames ms   = null (frames ms)
 132
 133-- -------------------------------------------------------------------
 134
 135-- stack access
 136
 137pushValue :: MV -> MS -> MS
 138pushValue val ms
 139    = ms { stack = (val : stack ms) }
 140
 141popValue        :: MS -> (MS, MV)
 142popValue ms
 143    = ( ms { stack = st1 }, val )
 144      where
 145      (val : st1) = stack ms
 146      -- pre: not emptyStack
 147
 148emptyStack      :: MS -> Bool
 149emptyStack ms
 150    = null (stack ms)
 151
 152
 153-- -------------------------------------------------------------------
 154--
 155-- status register
 156
 157programTerminated       :: String
 158programTerminated       = "program terminated"
 159
 160programAborted          :: String
 161programAborted          = "program aborted"
 162
 163statusIsTerminated      :: MS -> Bool
 164statusIsTerminated ms
 165    = case status ms
 166      of
 167      Exc e     -> e == programTerminated
 168      _         -> False
 169
 170statusIsExc     :: MS -> Bool
 171statusIsExc ms
 172    = case status ms
 173      of
 174      Exc _e    -> not (statusIsTerminated ms)
 175      _         -> False
 176
 177statusIsOk              :: MS -> Bool
 178statusIsOk ms
 179    = case status ms
 180      of
 181      Ok        -> True
 182      _         -> False
 183
 184getExc  :: MS -> String
 185getExc ms
 186    = let
 187      Exc exc = status ms
 188      in
 189      exc
 190
 191setExc          :: String -> MS -> MS
 192setExc e ms     = ms { status = Exc e }
 193
 194clearStatus     :: MS -> MS
 195clearStatus ms  = ms { status = Ok }
 196
 197-- -------------------------------------------------------------------
weiter

weiter

Die Datenstruktur für die Maschineninstruktionen: ppl/src/PPL/Instructions.hs

   1module PPL.Instructions where
   2
   3type Code       = [Instr]
   4
   5data Instr
   6    = LoadI             Int             -- load int const
   7    | LoadF             Double          -- load float const
   8    | LoadS             String          -- load string const
   9    | LoadU                             -- load undefined value
  10    | LoadEL                            -- load empty list
  11    | Load              Address         -- read data memory
  12    | Store             Address         -- write data memory
  13    | Pop                               -- remove arg from stack
  14    | Dup                               -- duplicate top of stack
  15    | Compute           Opcode          -- evaluate something
  16    | SysCall           Subroutine      -- system call (svc)
  17    | PushJ             Dest            -- subroutine call
  18    | PopJ                              -- computed jump (subroutine return)
  19    | Entry             Int             -- allocate stack frame
  20    | Exit                              -- delete stack frame
  21    | Branch            Bool Dest       -- gotos and branches
  22    | Jump              Dest
  23    | Label             Label           -- symbolic jump target
  24    | IllegalInstr      String          -- not yet implemented
  25    deriving (Eq, Show)
  26
  27data Address
  28    = LocA Int          -- local address
  29    | AbsA Int          -- global address
  30    deriving (Eq, Show)
  31
  32data Dest
  33    = Symb      Label
  34    | Disp      Int
  35    deriving (Eq, Show)
  36
  37data Opcode
  38    = OPabort
  39    | OPabove
  40    | OPaddf
  41    | OPaddi
  42    | OPappendl
  43    | OPbitmap
  44    | OPblack
  45    | OPblackAndWhite
  46    | OPconcatHorizontal
  47    | OPconcatVertical
  48    | OPconcl
  49    | OPconcs
  50    | OPcut
  51    | OPdecri
  52    | OPdiff
  53    | OPdivf
  54    | OPdivi
  55    | OPeqf
  56    | OPeqi
  57    | OPf2s
  58    | OPflipDiagonal
  59    | OPflipHorizontal
  60    | OPflipVertical
  61    | OPgamma
  62    | OPgef
  63    | OPgei
  64    | OPgrey
  65    | OPgtf
  66    | OPgti
  67    | OPheight
  68    | OPi2f
  69    | OPi2s
  70    | OPincri
  71    | OPindexl
  72    | OPinverseDiff
  73    | OPinverseMean
  74    | OPinvert
  75    | OPisemptyl
  76    | OPlengthl
  77    | OPmaxf
  78    | OPmaxi
  79    | OPmaxp
  80    | OPmean
  81    | OPmergeHorizontal
  82    | OPmergeVertical
  83    | OPminf
  84    | OPmini
  85    | OPminp
  86    | OPmodi
  87    | OPmulf
  88    | OPmuli
  89    | OPmulp
  90    | OPpartitionHorizontal
  91    | OPpartitionVertical
  92    | OPpaste
  93    | OPconsl
  94    | OPreduceColor
  95    | OPreplicate
  96    | OPresize
  97    | OProtate
  98    | OPround
  99    | OPscale
 100    | OPshift
 101    | OPshrink
 102    | OPsideBySide
 103    | OPsplitHorizontal
 104    | OPsplitVertical
 105    | OPsubf
 106    | OPsubi
 107    | OPtaill
 108    | OPterminate
 109    | OPtrunc
 110    | OPwhite
 111    | OPwidth
 112    deriving (Eq, Show)
 113
 114type Arg        = String
 115type Comment    = String
 116type Label      = String
 117type Subroutine = String
 118
 119type DataSeg    = Int
 120
 121type Executable = (Code, DataSeg)
weiter

weiter

Ein Testprogramm: ppl/examples/ggt.ppl

   1-- test with functions and procedures
   2
   3function ggt(x,y : int) : int
   4  if x = y
   5  then x
   6  else if x > y
   7  then ggt(x - yy)
   8  else ggt(yx)
   9;
  10
  11procedure test(i,j : int)
  12  writeln("ggt("
  13           + i.toString
  14           + ","
  15           + j.toString
  16           + ") = "
  17           + ggt(i,j).toString
  18          )
  19;
  20 
  21begin
  22 test(13,8)
  23end
weiter

weiter

der Assemblercode: ppl/examples/ggt.gencode

   1.text
   2        loadi   13
   3        loadi   8
   4        pushj   _test
   5        pop
   6        terminate
   7_ggt:
   8        entry   3
   9        store   l[0]
  10s_ggt:
  11        store   l[1]
  12        store   l[2]
  13        load    l[2]
  14        load    l[1]
  15        eqi
  16        brfalse l0
  17        load    l[2]
  18        jmp     l1
  19l0:
  20        load    l[2]
  21        load    l[1]
  22        gti
  23        brfalse l2
  24        load    l[2]
  25        load    l[1]
  26        subi
  27        load    l[1]
  28        pushj   _ggt
  29        jmp     l3
  30l2:
  31        load    l[1]
  32        load    l[2]
  33        pushj   _ggt
  34l3:
  35l1:
  36e_ggt:
  37        load    l[0]
  38        exit
  39        popj
  40_test:
  41        entry   3
  42        store   l[0]
  43s_test:
  44        store   l[1]
  45        store   l[2]
  46        loads   "ggt("
  47        load    l[2]
  48        i2s
  49        concs
  50        loads   ","
  51        concs
  52        load    l[1]
  53        i2s
  54        concs
  55        loads   ") = "
  56        concs
  57        load    l[2]
  58        load    l[1]
  59        pushj   _ggt
  60        i2s
  61        concs
  62        svc     writeln
  63        pop
  64        undef
  65e_test:
  66        load    l[0]
  67        exit
  68        popj
  69
  70.data   0
weiter

weiter

der Testlauf: der trace des Maschinencodes ppl/examples/ggt.trc

start execution
      0:        loadi   13
      1:        loadi   8
      2:        pushj   28              --> 30
     30:        entry   3
     31:        store   l[0]
     32:        store   l[1]
     33:        store   l[2]
     34:        loads   "ggt("
     35:        load    l[2]
     36:        i2s
     37:        concs
     38:        loads   ","
     39:        concs
     40:        load    l[1]
     41:        i2s
     42:        concs
     43:        loads   ") = "
     44:        concs
     45:        load    l[2]
     46:        load    l[1]
     47:        pushj   -42             --> 5
      5:        entry   3
      6:        store   l[0]
      7:        store   l[1]
      8:        dup
      9:        store   l[2]
     10:        load    l[1]
     11:        eqi
     12:        brfalse 3               --> 15
     15:        load    l[2]
     16:        load    l[1]
     17:        gti
     18:        brfalse 6               --> 24
     19:        load    l[2]
     20:        load    l[1]
     21:        subi
     22:        load    l[1]
     23:        jmp     -16             --> 7
      7:        store   l[1]
      8:        dup
      9:        store   l[2]
     10:        load    l[1]
     11:        eqi
     12:        brfalse 3               --> 15
     15:        load    l[2]
     16:        load    l[1]
     17:        gti
     18:        brfalse 6               --> 24
     24:        load    l[1]
     25:        load    l[2]
     26:        jmp     -19             --> 7
      7:        store   l[1]
      8:        dup
      9:        store   l[2]
     10:        load    l[1]
     11:        eqi
     12:        brfalse 3               --> 15
     15:        load    l[2]
     16:        load    l[1]
     17:        gti
     18:        brfalse 6               --> 24
     19:        load    l[2]
     20:        load    l[1]
     21:        subi
     22:        load    l[1]
     23:        jmp     -16             --> 7
      7:        store   l[1]
      8:        dup
      9:        store   l[2]
     10:        load    l[1]
     11:        eqi
     12:        brfalse 3               --> 15
     15:        load    l[2]
     16:        load    l[1]
     17:        gti
     18:        brfalse 6               --> 24
     24:        load    l[1]
     25:        load    l[2]
     26:        jmp     -19             --> 7
      7:        store   l[1]
      8:        dup
      9:        store   l[2]
     10:        load    l[1]
     11:        eqi
     12:        brfalse 3               --> 15
     15:        load    l[2]
     16:        load    l[1]
     17:        gti
     18:        brfalse 6               --> 24
     19:        load    l[2]
     20:        load    l[1]
     21:        subi
     22:        load    l[1]
     23:        jmp     -16             --> 7
      7:        store   l[1]
      8:        dup
      9:        store   l[2]
     10:        load    l[1]
     11:        eqi
     12:        brfalse 3               --> 15
     15:        load    l[2]
     16:        load    l[1]
     17:        gti
     18:        brfalse 6               --> 24
     24:        load    l[1]
     25:        load    l[2]
     26:        jmp     -19             --> 7
      7:        store   l[1]
      8:        dup
      9:        store   l[2]
     10:        load    l[1]
     11:        eqi
     12:        brfalse 3               --> 15
     15:        load    l[2]
     16:        load    l[1]
     17:        gti
     18:        brfalse 6               --> 24
     19:        load    l[2]
     20:        load    l[1]
     21:        subi
     22:        load    l[1]
     23:        jmp     -16             --> 7
      7:        store   l[1]
      8:        dup
      9:        store   l[2]
     10:        load    l[1]
     11:        eqi
     12:        brfalse 3               --> 15
     15:        load    l[2]
     16:        load    l[1]
     17:        gti
     18:        brfalse 6               --> 24
     24:        load    l[1]
     25:        load    l[2]
     26:        jmp     -19             --> 7
      7:        store   l[1]
      8:        dup
      9:        store   l[2]
     10:        load    l[1]
     11:        eqi
     12:        brfalse 3               --> 15
     15:        load    l[2]
     16:        load    l[1]
     17:        gti
     18:        brfalse 6               --> 24
     19:        load    l[2]
     20:        load    l[1]
     21:        subi
     22:        load    l[1]
     23:        jmp     -16             --> 7
      7:        store   l[1]
      8:        dup
      9:        store   l[2]
     10:        load    l[1]
     11:        eqi
     12:        brfalse 3               --> 15
     13:        load    l[2]
     14:        jmp     13              --> 27
     27:        load    l[0]
     28:        exit
     29:        popj
     48:        i2s
     49:        concs
     50:        svc     writeln
     51:        load    l[0]
     52:        exit
     53:        popj
      3:        pop
      4:        terminate
 
execution terminated
weiter

Letzte Änderung: 14.02.2012
© Prof. Dr. Uwe Schmidt
Prof. Dr. Uwe Schmidt FH Wedel