Changeset 126 for trunk/UBFTarget.pas
- Timestamp:
- Jan 14, 2022, 7:13:36 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/UBFTarget.pas
r125 r126 11 11 12 12 TMachineCommand = (cmNoOperation, cmInc, cmDec, cmPointerInc, cmPointerDec, 13 cmOutput, cmInput, cmLoopStart, cmLoopEnd, cmDebug, cmSet, cmMultip y);13 cmOutput, cmInput, cmLoopStart, cmLoopEnd, cmDebug, cmSet, cmMultiply); 14 14 15 15 { TMachineOperation } … … 19 19 Parameter: Integer; 20 20 RelIndex: Integer; 21 class function Create(Command: TMachineCommand; Parameter, RelIndex: Integer): TMachineOperation; static; 21 class function Create(Command: TMachineCommand; Parameter: Integer; 22 RelIndex: Integer = 0): TMachineOperation; static; 23 end; 24 25 TMachineOperations = array of TMachineOperation; 26 27 { TProgram } 28 29 TProgram = class 30 private 31 function GetCount: Integer; 32 function GetItem(Index: Integer): TMachineOperation; 33 procedure SetCount(AValue: Integer); 34 procedure SetItem(Index: Integer; AValue: TMachineOperation); 35 public 36 Operations: TMachineOperations; 37 Index: Integer; 38 procedure Assign(Source: TProgram); 39 property Count: Integer read GetCount write SetCount; 40 property Items[Index: Integer]: TMachineOperation read GetItem write SetItem; default; 22 41 end; 23 42 24 43 TOptimizations = record 25 44 AddSub: Boolean; 45 SetZero: Boolean; 26 46 Merge: Boolean; 27 47 RelativeIndexes: Boolean; … … 33 53 TBFTarget = class(TTarget) 34 54 private 35 function Check Clear: Boolean;55 function CheckLoopSetZero: Boolean; 36 56 function CheckOccurenceSumParam(C: TMachineCommand): Integer; 37 57 function CheckOccurence(C: TMachineCommand): Integer; 58 function CheckLoopDecrementCount: Integer; 38 59 procedure OptimizeAddSub; 60 procedure OptimizeSetZero; 39 61 procedure OptimizeMerge; 40 62 procedure OptimizeZeroInitMemory; … … 42 64 procedure OptimizeCopyMultiply; 43 65 protected 44 FProgram: array of TMachineOperation;66 FProgram: TProgram; 45 67 FProgramIndex: Integer; 46 68 function GetOperationText(Operation: TMachineOperation): string; virtual; … … 52 74 Optimizations: TOptimizations; 53 75 constructor Create; override; 76 destructor Destroy; override; 54 77 procedure OptimizeSource; override; 55 78 property ProgramIndex: Integer read FProgramIndex; … … 66 89 SUnsupportedCommand = 'Unsupported command %d'; 67 90 91 { TProgram } 92 93 function TProgram.GetCount: Integer; 94 begin 95 Result := Length(Operations); 96 end; 97 98 function TProgram.GetItem(Index: Integer): TMachineOperation; 99 begin 100 Result := Operations[Index]; 101 end; 102 103 procedure TProgram.SetCount(AValue: Integer); 104 begin 105 SetLength(Operations, AValue); 106 end; 107 108 procedure TProgram.SetItem(Index: Integer; AValue: TMachineOperation); 109 begin 110 Operations[Index] := AValue; 111 end; 112 113 procedure TProgram.Assign(Source: TProgram); 114 begin 115 Count := Source.Count; 116 Move(Pointer(Source.Operations)^, Pointer(Operations)^, SizeOf(TMachineOperation) * Count); 117 end; 118 68 119 { TMachineOperation } 69 120 70 class function TMachineOperation.Create(Command: TMachineCommand; Parameter,71 RelIndex: Integer): TMachineOperation;121 class function TMachineOperation.Create(Command: TMachineCommand; 122 Parameter: Integer; RelIndex: Integer = 0): TMachineOperation; 72 123 begin 73 124 Result.Command := Command; … … 76 127 end; 77 128 78 function TBFTarget.Check Clear: Boolean;79 begin 80 Result := (FProgram[FProgramIndex].Command = cmLoopStart) and ( Length(FProgram)>= FProgramIndex + 2) and129 function TBFTarget.CheckLoopSetZero: Boolean; 130 begin 131 Result := (FProgram[FProgramIndex].Command = cmLoopStart) and (FProgram.Count >= FProgramIndex + 2) and 81 132 (((FProgram[FProgramIndex + 1].Command = cmDec) and (FProgram[FProgramIndex + 1].Parameter = 1)) or 82 133 ((FProgram[FProgramIndex + 1].Command = cmInc) and (FProgram[FProgramIndex + 1].Parameter = -1))) … … 87 138 begin 88 139 Result := 1; 89 while ((FProgramIndex + 1) < Length(FProgram)) and (FProgram[FProgramIndex + 1].Command = C) do begin140 while ((FProgramIndex + 1) < FProgram.Count) and (FProgram[FProgramIndex + 1].Command = C) do begin 90 141 Inc(Result); 91 142 Inc(FProgramIndex); … … 96 147 begin 97 148 Result := FProgram[FProgramIndex].Parameter; 98 while ((FProgramIndex + 1) < Length(FProgram)) and (FProgram[FProgramIndex + 1].Command = C) do begin149 while ((FProgramIndex + 1) < FProgram.Count) and (FProgram[FProgramIndex + 1].Command = C) do begin 99 150 Inc(Result, FProgram[FProgramIndex + 1].Parameter); 100 151 Inc(FProgramIndex); … … 102 153 end; 103 154 155 // Merge multiple sequential occurences of +/-/>/< operations into single fast 156 // operation with parameter value set to number of occurences 104 157 procedure TBFTarget.OptimizeAddSub; 105 158 var 106 NewProgram: array of TMachineOperation; 107 NewProgramIndex: Integer; 108 NewTargetPos: Integer; 159 NewProgram: TProgram; 160 NewTargetIndex: Integer; 109 161 FirstIndex: Integer; 110 162 begin 111 New ProgramIndex := 0;112 New TargetPos := 0;113 SetLength(NewProgram, Length(FProgram));163 NewTargetIndex := 0; 164 NewProgram := TProgram.Create; 165 NewProgram.Count := FProgram.Count; 114 166 115 167 FProgramIndex := 0; 116 while (FProgramIndex < Length(FProgram))do begin168 while FProgramIndex < FProgram.Count do begin 117 169 FirstIndex := FProgramIndex; 118 170 case FProgram[FProgramIndex].Command of 119 171 cmPointerInc: begin 120 NewProgram[NewProgram Index].Command := cmPointerInc;121 NewProgram[NewProgramIndex].Parameter := CheckOccurenceSumParam(cmPointerInc);172 NewProgram[NewProgram.Index] := TMachineOperation.Create(cmPointerInc, 173 CheckOccurenceSumParam(cmPointerInc)); 122 174 end; 123 175 cmPointerDec: begin 124 NewProgram[NewProgram Index].Command := cmPointerDec;125 NewProgram[NewProgramIndex].Parameter := CheckOccurenceSumParam(cmPointerDec);176 NewProgram[NewProgram.Index] := TMachineOperation.Create(cmPointerDec, 177 CheckOccurenceSumParam(cmPointerDec)); 126 178 end; 127 179 cmInc: begin 128 NewProgram[NewProgram Index].Command := cmInc;129 NewProgram[NewProgramIndex].Parameter := CheckOccurenceSumParam(cmInc);180 NewProgram[NewProgram.Index] := TMachineOperation.Create(cmInc, 181 CheckOccurenceSumParam(cmInc)); 130 182 end; 131 183 cmDec: begin 132 NewProgram[NewProgram Index].Command := cmDec;133 NewProgram[NewProgramIndex].Parameter := CheckOccurenceSumParam(cmDec);134 end; 135 else NewProgram[NewProgram Index] := FProgram[FProgramIndex];184 NewProgram[NewProgram.Index] := TMachineOperation.Create(cmDec, 185 CheckOccurenceSumParam(cmDec)); 186 end; 187 else NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 136 188 end; 137 DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, NewProgramIndex, NewTargetPos); 138 Inc(NewTargetPos, Length(GetOperationText(NewProgram[NewProgramIndex]))); 139 Inc(FProgramIndex); 140 Inc(NewProgramIndex); 141 end; 142 SetLength(NewProgram, NewProgramIndex); 143 144 // Replace old program by new program 145 SetLength(FProgram, Length(NewProgram)); 146 Move(Pointer(NewProgram)^, Pointer(FProgram)^, SizeOf(TMachineOperation) * Length(NewProgram)); 147 end; 148 189 DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, NewProgram.Index, NewTargetIndex); 190 Inc(NewTargetIndex, Length(GetOperationText(NewProgram[NewProgram.Index]))); 191 Inc(FProgramIndex); 192 Inc(NewProgram.Index); 193 end; 194 195 NewProgram.Count := NewProgram.Index; 196 FProgram.Assign(NewProgram); 197 FreeAndNil(NewProgram); 198 end; 199 200 // Converts [-] into mSet,0 (=0) command 201 procedure TBFTarget.OptimizeSetZero; 202 var 203 NewProgram: TProgram; 204 FirstIndex: Integer; 205 NewTargetIndex: Integer; 206 begin 207 NewTargetIndex := 0; 208 NewProgram := TProgram.Create; 209 NewProgram.Count := FProgram.Count; 210 211 FProgramIndex := 0; 212 while FProgramIndex < FProgram.Count do begin 213 FirstIndex := FProgramIndex; 214 case FProgram[FProgramIndex].Command of 215 cmLoopStart: begin 216 if CheckLoopSetZero then begin 217 NewProgram[NewProgram.Index] := TMachineOperation.Create(cmSet, 0, 0); 218 Inc(FProgramIndex, 2); 219 end else begin 220 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 221 end; 222 end; 223 else NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 224 end; 225 DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, NewProgram.Index, NewTargetIndex); 226 Inc(NewTargetIndex, Length(GetOperationText(NewProgram[NewProgram.Index]))); 227 Inc(FProgramIndex); 228 Inc(NewProgram.Index); 229 end; 230 NewProgram.Count := NewProgram.Index; 231 FProgram.Assign(NewProgram); 232 FreeAndNil(NewProgram); 233 end; 234 235 // Merge together cmInc, cmDec, cmSet 236 // Merge together cmPointerInc, cmPointerDec 149 237 procedure TBFTarget.OptimizeMerge; 150 238 var 151 NewProgram: array of TMachineOperation; 152 NewProgramIndex: Integer; 239 NewProgram: TProgram; 153 240 PreviousCommand: TMachineCommand; 154 241 FirstIndex: Integer; 155 242 NewTargetIndex: Integer; 156 243 begin 157 // Merge together cmInc, cmDec, cmSet 158 // Merge together cmPointerInc, cmPointerDec 244 NewTargetIndex := 0; 245 NewProgram := TProgram.Create; 246 NewProgram.Count := FProgram.Count; 247 159 248 PreviousCommand := cmNoOperation; 160 NewProgramIndex := 0;161 SetLength(NewProgram, Length(FProgram));162 163 249 FProgramIndex := 0; 164 NewTargetIndex := 0; 165 while (FProgramIndex < Length(FProgram)) do begin 250 while FProgramIndex < FProgram.Count do begin 166 251 FirstIndex := FProgramIndex; 167 252 case FProgram[FProgramIndex].Command of 168 253 cmPointerInc: begin 169 254 if PreviousCommand in [cmPointerInc, cmPointerDec] then begin 170 if NewProgram[NewProgramIndex - 1].Command = cmPointerInc then 171 NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter + 255 if NewProgram[NewProgram.Index - 1].Command = cmPointerInc then 256 NewProgram.Operations[NewProgram.Index - 1].Parameter := NewProgram[NewProgram.Index - 1].Parameter + 257 FProgram[FProgram.Index].Parameter 258 else 259 if NewProgram[NewProgram.Index - 1].Command = cmPointerDec then 260 NewProgram.Operations[NewProgram.Index - 1].Parameter := NewProgram[NewProgram.Index - 1].Parameter - 261 FProgram[FProgram.Index].Parameter; 262 // If value negative then change command 263 if NewProgram[NewProgram.Index - 1].Parameter < 0 then begin 264 NewProgram.Operations[NewProgram.Index - 1].Parameter := -NewProgram[NewProgram.Index - 1].Parameter; 265 if NewProgram[NewProgram.Index - 1].Command = cmPointerInc then 266 NewProgram.Operations[NewProgram.Index - 1].Command := cmPointerDec 267 else NewProgram.Operations[NewProgram.Index - 1].Command := cmPointerInc; 268 end; 269 if NewProgram.Operations[NewProgram.Index - 1].Parameter = 0 then Dec(NewProgram.Index); 270 Dec(NewProgram.Index); 271 end else begin 272 NewProgram[NewProgram.Index] := TMachineOperation.Create(cmPointerInc, 273 FProgram[FProgramIndex].Parameter); 274 end; 275 end; 276 cmPointerDec: begin 277 if PreviousCommand in [cmPointerInc, cmPointerDec] then begin 278 if NewProgram[NewProgram.Index - 1].Command = cmPointerDec then 279 NewProgram.Operations[NewProgram.Index - 1].Parameter := NewProgram[NewProgram.Index - 1].Parameter + 172 280 FProgram[FProgramIndex].Parameter 173 else if NewProgram[NewProgram Index - 1].Command = cmPointerDec then174 NewProgram [NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter -281 else if NewProgram[NewProgram.Index - 1].Command = cmPointerInc then 282 NewProgram.Operations[NewProgram.Index - 1].Parameter := NewProgram[NewProgram.Index - 1].Parameter - 175 283 FProgram[FProgramIndex].Parameter; 176 284 // If value negative then change command 177 if NewProgram[NewProgram Index - 1].Parameter < 0 then begin178 NewProgram [NewProgramIndex - 1].Parameter := -NewProgram[NewProgramIndex - 1].Parameter;179 if NewProgram[NewProgram Index - 1].Command = cmPointerInc then180 NewProgram [NewProgramIndex - 1].Command := cmPointerDec181 else NewProgram [NewProgramIndex - 1].Command := cmPointerInc;285 if NewProgram[NewProgram.Index - 1].Parameter < 0 then begin 286 NewProgram.Operations[NewProgram.Index - 1].Parameter := -NewProgram[NewProgram.Index - 1].Parameter; 287 if NewProgram[NewProgram.Index - 1].Command = cmPointerInc then 288 NewProgram.Operations[NewProgram.Index - 1].Command := cmPointerDec 289 else NewProgram.Operations[NewProgram.Index - 1].Command := cmPointerInc; 182 290 end; 183 if NewProgram[NewProgram Index - 1].Parameter = 0 then Dec(NewProgramIndex);184 Dec(NewProgram Index);185 end else begin 186 NewProgram[NewProgram Index].Command := cmPointerInc;187 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter;188 end; 189 end; 190 cm PointerDec: begin191 if PreviousCommand in [cm PointerInc, cmPointerDec] then begin192 if NewProgram[NewProgram Index - 1].Command = cmPointerDecthen193 NewProgram [NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter +291 if NewProgram[NewProgram.Index - 1].Parameter = 0 then Dec(NewProgram.Index); 292 Dec(NewProgram.Index); 293 end else begin 294 NewProgram[NewProgram.Index] := TMachineOperation.Create(cmPointerDec, 295 FProgram[FProgramIndex].Parameter); 296 end; 297 end; 298 cmInc: begin 299 if PreviousCommand in [cmInc, cmDec, cmSet] then begin 300 if NewProgram[NewProgram.Index - 1].Command in [cmInc, cmSet] then 301 NewProgram.Operations[NewProgram.Index - 1].Parameter := NewProgram[NewProgram.Index - 1].Parameter + 194 302 FProgram[FProgramIndex].Parameter 195 else if NewProgram[NewProgram Index - 1].Command = cmPointerInc then196 NewProgram [NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter -303 else if NewProgram[NewProgram.Index - 1].Command = cmDec then 304 NewProgram.Operations[NewProgram.Index - 1].Parameter := NewProgram[NewProgram.Index - 1].Parameter - 197 305 FProgram[FProgramIndex].Parameter; 198 306 // If value negative then change command 199 if NewProgram[NewProgramIndex - 1].Parameter < 0then begin200 NewProgram [NewProgramIndex - 1].Parameter := -NewProgram[NewProgramIndex - 1].Parameter;201 if NewProgram[NewProgram Index - 1].Command = cmPointerInc then202 NewProgram [NewProgramIndex - 1].Command := cmPointerDec203 else NewProgram [NewProgramIndex - 1].Command := cmPointerInc;307 if (NewProgram[NewProgram.Index - 1].Parameter < 0) and (NewProgram[NewProgram.Index - 1].Command <> cmSet) then begin 308 NewProgram.Operations[NewProgram.Index - 1].Parameter := -NewProgram[NewProgram.Index - 1].Parameter; 309 if NewProgram[NewProgram.Index - 1].Command = cmInc then 310 NewProgram.Operations[NewProgram.Index - 1].Command := cmDec 311 else NewProgram.Operations[NewProgram.Index - 1].Command := cmInc; 204 312 end; 205 if NewProgram[NewProgram Index - 1].Parameter = 0 then Dec(NewProgramIndex);206 Dec(NewProgram Index);207 end else begin 208 NewProgram[NewProgram Index].Command := cmPointerDec;209 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter;210 end; 211 end; 212 cm Inc: begin313 if NewProgram[NewProgram.Index - 1].Parameter = 0 then Dec(NewProgram.Index); 314 Dec(NewProgram.Index); 315 end else begin 316 NewProgram[NewProgram.Index] := TMachineOperation.Create(cmInc, 317 FProgram[FProgramIndex].Parameter); 318 end; 319 end; 320 cmDec: begin 213 321 if PreviousCommand in [cmInc, cmDec, cmSet] then begin 214 if NewProgram[NewProgram Index - 1].Command in [cmInc, cmSet]then215 NewProgram [NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter +322 if NewProgram[NewProgram.Index - 1].Command = cmDec then 323 NewProgram.Operations[NewProgram.Index - 1].Parameter := NewProgram[NewProgram.Index - 1].Parameter + 216 324 FProgram[FProgramIndex].Parameter 217 else if NewProgram[NewProgram Index - 1].Command = cmDecthen218 NewProgram [NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter -325 else if NewProgram[NewProgram.Index - 1].Command in [cmInc, cmSet] then 326 NewProgram.Operations[NewProgram.Index - 1].Parameter := NewProgram[NewProgram.Index - 1].Parameter - 219 327 FProgram[FProgramIndex].Parameter; 220 328 // If value negative then change command 221 if (NewProgram[NewProgram Index - 1].Parameter < 0) and (NewProgram[NewProgramIndex - 1].Command <> cmSet) then begin222 NewProgram [NewProgramIndex - 1].Parameter := -NewProgram[NewProgramIndex - 1].Parameter;223 if NewProgram[NewProgram Index - 1].Command = cmInc then224 NewProgram [NewProgramIndex - 1].Command := cmDec225 else NewProgram [NewProgramIndex - 1].Command := cmInc;329 if (NewProgram[NewProgram.Index - 1].Parameter < 0) and (NewProgram[NewProgram.Index - 1].Command <> cmSet) then begin 330 NewProgram.Operations[NewProgram.Index - 1].Parameter := -NewProgram[NewProgram.Index - 1].Parameter; 331 if NewProgram[NewProgram.Index - 1].Command = cmInc then 332 NewProgram.Operations[NewProgram.Index - 1].Command := cmDec 333 else NewProgram.Operations[NewProgram.Index - 1].Command := cmInc; 226 334 end; 227 if NewProgram[NewProgramIndex - 1].Parameter = 0 then Dec(NewProgramIndex); 228 Dec(NewProgramIndex); 229 end else begin 230 NewProgram[NewProgramIndex].Command := cmInc; 231 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter; 232 end; 233 end; 234 cmDec: begin 235 if PreviousCommand in [cmInc, cmDec, cmSet] then begin 236 if NewProgram[NewProgramIndex - 1].Command = cmDec then 237 NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter + 238 FProgram[FProgramIndex].Parameter 239 else if NewProgram[NewProgramIndex - 1].Command in [cmInc, cmSet] then 240 NewProgram[NewProgramIndex - 1].Parameter := NewProgram[NewProgramIndex - 1].Parameter - 241 FProgram[FProgramIndex].Parameter; 242 // If value negative then change command 243 if (NewProgram[NewProgramIndex - 1].Parameter < 0) and (NewProgram[NewProgramIndex - 1].Command <> cmSet) then begin 244 NewProgram[NewProgramIndex - 1].Parameter := -NewProgram[NewProgramIndex - 1].Parameter; 245 if NewProgram[NewProgramIndex - 1].Command = cmInc then 246 NewProgram[NewProgramIndex - 1].Command := cmDec 247 else NewProgram[NewProgramIndex - 1].Command := cmInc; 248 end; 249 if NewProgram[NewProgramIndex - 1].Parameter = 0 then Dec(NewProgramIndex); 250 Dec(NewProgramIndex); 251 end else begin 252 NewProgram[NewProgramIndex].Command := cmDec; 253 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter; 335 if NewProgram[NewProgram.Index - 1].Parameter = 0 then Dec(NewProgram.Index); 336 Dec(NewProgram.Index); 337 end else begin 338 NewProgram[NewProgram.Index] := TMachineOperation.Create(cmDec, 339 FProgram[FProgramIndex].Parameter); 254 340 end; 255 341 end; … … 257 343 if PreviousCommand in [cmInc, cmDec, cmSet] then begin 258 344 // Set overrides value of previous commands 259 Dec(NewProgramIndex); 260 NewProgram[NewProgramIndex].Command := cmSet; 261 NewProgram[NewProgramIndex].Parameter := FProgram[FProgramIndex].Parameter; 262 end else begin 263 NewProgram[NewProgramIndex] := FProgram[FProgramIndex]; 264 end; 265 end; 266 cmLoopStart: begin 267 if CheckClear then begin 268 NewProgram[NewProgramIndex] := TMachineOperation.Create(cmSet, 0, 0); 269 Inc(FProgramIndex, 2); 270 end else begin 271 NewProgram[NewProgramIndex] := FProgram[FProgramIndex]; 272 end; 273 end; 274 else NewProgram[NewProgramIndex] := FProgram[FProgramIndex]; 345 Dec(NewProgram.Index); 346 NewProgram[NewProgram.Index] := TMachineOperation.Create(cmSet, 347 FProgram[FProgramIndex].Parameter); 348 end else begin 349 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 350 end; 351 end; 352 else NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 275 353 end; 276 354 PreviousCommand := FProgram[FProgramIndex].Command; 277 DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, NewProgramIndex, NewTargetIndex); 278 Inc(NewTargetIndex, Length(GetOperationText(NewProgram[NewProgramIndex]))); 279 Inc(FProgramIndex); 280 Inc(NewProgramIndex); 281 end; 282 SetLength(NewProgram, NewProgramIndex); 283 284 // Replace old program by new program 285 SetLength(FProgram, Length(NewProgram)); 286 Move(Pointer(NewProgram)^, Pointer(FProgram)^, SizeOf(TMachineOperation) * Length(NewProgram)); 355 DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, NewProgram.Index, NewTargetIndex); 356 Inc(NewTargetIndex, Length(GetOperationText(NewProgram[NewProgram.Index]))); 357 Inc(FProgramIndex); 358 Inc(NewProgram.Index); 359 end; 360 361 NewProgram.Count := NewProgram.Index; 362 FProgram.Assign(NewProgram); 363 FreeAndNil(NewProgram); 287 364 end; 288 365 … … 296 373 procedure TBFTarget.OptimizeRelativeIndexes; 297 374 var 298 NewProgram: array of TMachineOperation; 299 NewProgramIndex: Integer; 375 NewProgram: TProgram; 300 376 RelIndex: Integer; 301 377 FirstIndex: Integer; 302 378 NewTargetIndex: Integer; 303 379 begin 304 NewProgramIndex := 0; 305 SetLength(NewProgram, Length(FProgram)); 380 NewTargetIndex := 0; 381 NewProgram := TProgram.Create; 382 NewProgram.Count := FProgram.Count; 306 383 307 384 RelIndex := 0; 308 385 FProgramIndex := 0; 309 NewTargetIndex := 0; 310 while (FProgramIndex < Length(FProgram)) do begin 386 while FProgramIndex < FProgram.Count do begin 311 387 FirstIndex := FProgramIndex; 312 388 case FProgram[FProgramIndex].Command of 313 389 cmPointerInc: begin 314 390 RelIndex := RelIndex + FProgram[FProgramIndex].Parameter; 315 Dec(NewProgram Index);391 Dec(NewProgram.Index); 316 392 end; 317 393 cmPointerDec: begin 318 394 RelIndex := RelIndex - FProgram[FProgramIndex].Parameter; 319 Dec(NewProgram Index);395 Dec(NewProgram.Index); 320 396 end; 321 397 cmInc, cmDec, cmInput, cmOutput, cmSet: begin 322 NewProgram[NewProgram Index] := FProgram[FProgramIndex];323 NewProgram [NewProgramIndex].RelIndex :=324 NewProgram[NewProgram Index].RelIndex + RelIndex;398 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 399 NewProgram.Operations[NewProgram.Index].RelIndex := 400 NewProgram[NewProgram.Index].RelIndex + RelIndex; 325 401 end; 326 402 cmLoopStart, cmLoopEnd: begin 327 403 if RelIndex > 0 then begin 328 NewProgram[NewProgram Index] := TMachineOperation.Create(cmPointerInc,404 NewProgram[NewProgram.Index] := TMachineOperation.Create(cmPointerInc, 329 405 RelIndex, 0); 330 Inc(NewProgram Index);406 Inc(NewProgram.Index); 331 407 RelIndex := 0; 332 408 end else 333 409 if RelIndex < 0 then begin 334 NewProgram[NewProgram Index] := TMachineOperation.Create(cmPointerDec,410 NewProgram[NewProgram.Index] := TMachineOperation.Create(cmPointerDec, 335 411 Abs(RelIndex), 0); 336 Inc(NewProgram Index);412 Inc(NewProgram.Index); 337 413 RelIndex := 0; 338 414 end; 339 NewProgram[NewProgram Index] := FProgram[FProgramIndex];415 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 340 416 end; 341 417 else raise Exception.Create(Format(SUnsupportedCommand, [FProgram[FProgramIndex].Command])); 342 418 end; 343 DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, NewProgramIndex, NewTargetIndex); 344 Inc(NewTargetIndex, Length(GetOperationText(NewProgram[NewProgramIndex]))); 345 Inc(FProgramIndex); 346 Inc(NewProgramIndex); 347 end; 348 SetLength(NewProgram, NewProgramIndex); 349 350 // Replace old program by new program 351 SetLength(FProgram, Length(NewProgram)); 352 Move(Pointer(NewProgram)^, Pointer(FProgram)^, SizeOf(TMachineOperation) * 353 Length(NewProgram)); 354 end; 355 419 DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, NewProgram.Index, NewTargetIndex); 420 Inc(NewTargetIndex, Length(GetOperationText(NewProgram[NewProgram.Index]))); 421 Inc(FProgramIndex); 422 Inc(NewProgram.Index); 423 end; 424 425 NewProgram.Count := NewProgram.Index; 426 FProgram.Assign(NewProgram); 427 FreeAndNil(NewProgram); 428 end; 429 430 function TBFTarget.CheckLoopDecrementCount: Integer; 431 var 432 I: Integer; 433 PointerChange: Integer; 434 begin 435 Result := 0; 436 PointerChange := 0; 437 I := FProgramIndex + 1; 438 while I < FProgram.Count do begin 439 case FProgram[I].Command of 440 cmPointerInc: begin 441 Inc(PointerChange, FProgram[I].Parameter); 442 end; 443 cmPointerDec: begin 444 Dec(PointerChange, FProgram[I].Parameter); 445 end; 446 cmInc: begin 447 end; 448 cmDec: begin 449 if (PointerChange = 0) and (FProgram[I].RelIndex = 0) and 450 (FProgram[I].Parameter = 1) then 451 Inc(Result); 452 end; 453 cmLoopEnd: begin 454 if (Result = 1) and (PointerChange = 0) then begin 455 Break; 456 end; 457 end; 458 else begin 459 // The loop can't be optimized as there are other operations inside 460 Result := 0; 461 Break; 462 end; 463 end; 464 Inc(I); 465 end; 466 end; 467 468 // Optimize copy and multiply loops like [>+<-] or [>++<-] or [>+>+<<-] 356 469 procedure TBFTarget.OptimizeCopyMultiply; 357 470 var 358 NewProgram: array of TMachineOperation; 359 NewProgramIndex: Integer; 360 ProcessLoop: Boolean; 471 NewProgram: TProgram; 472 ProcessingLoop: Boolean; 361 473 PointerChange: Integer; 362 474 NumberOfBaseDecrement: Integer; 363 LoopStartIndex: Integer;364 LoopStartIndexNew: Integer;365 475 FirstIndex: Integer; 366 476 NewTextIndex: Integer; 367 begin 368 NewProgramIndex := 0; 369 SetLength(NewProgram, Length(FProgram)); 477 NoNewCode: Boolean; 478 begin 479 NewProgram := TProgram.Create; 480 NewProgram.Count := FProgram.Count; 370 481 371 482 NumberOfBaseDecrement := 0; 372 Process Loop := False;483 ProcessingLoop := False; 373 484 FProgramIndex := 0; 374 485 NewTextIndex := 0; 375 486 PointerChange := 0; 376 while (FProgramIndex < Length(FProgram))do begin487 while FProgramIndex < FProgram.Count do begin 377 488 FirstIndex := FProgramIndex; 489 NoNewCode := False; 378 490 case FProgram[FProgramIndex].Command of 379 491 cmPointerInc: begin 380 PointerChange := PointerChange + FProgram[FProgramIndex].Parameter;381 NewProgram[NewProgram Index] := FProgram[FProgramIndex];492 Inc(PointerChange, FProgram[FProgramIndex].Parameter); 493 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 382 494 end; 383 495 cmPointerDec: begin 384 PointerChange := PointerChange - FProgram[FProgramIndex].Parameter;385 NewProgram[NewProgram Index] := FProgram[FProgramIndex];496 Dec(PointerChange, FProgram[FProgramIndex].Parameter); 497 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 386 498 end; 387 499 cmInc: begin 388 if not Process Loop then begin389 NewProgram[NewProgram Index] := FProgram[FProgramIndex];500 if not ProcessingLoop then begin 501 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 390 502 end else begin 391 503 if ((FProgram[FProgramIndex].RelIndex + PointerChange) <> 0) then begin 392 NewProgram[NewProgram Index] := FProgram[FProgramIndex];393 NewProgram [NewProgramIndex].Command := cmMultipy;394 end else Dec(NewProgramIndex);504 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 505 NewProgram.Operations[NewProgram.Index].Command := cmMultiply; 506 end else NoNewCode := True; 395 507 end; 396 508 end; 397 509 cmDec: begin 398 if not Process Loop then begin510 if not ProcessingLoop then begin 399 511 if (PointerChange = 0) and (FProgram[FProgramIndex].RelIndex = 0) and 400 512 (FProgram[FProgramIndex].Parameter = 1) then 401 513 Inc(NumberOfBaseDecrement); 402 NewProgram[NewProgram Index] := FProgram[FProgramIndex];514 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 403 515 end else begin 404 516 if ((FProgram[FProgramIndex].RelIndex + PointerChange) <> 0) then begin 405 NewProgram[NewProgram Index] := FProgram[FProgramIndex];406 NewProgram [NewProgramIndex].Command := cmMultipy;407 NewProgram [NewProgramIndex].Parameter := -FProgram[FProgramIndex].Parameter;408 end else Dec(NewProgramIndex);517 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 518 NewProgram.Operations[NewProgram.Index].Command := cmMultiply; 519 NewProgram.Operations[NewProgram.Index].Parameter := -FProgram[FProgramIndex].Parameter; 520 end else NoNewCode := True; 409 521 end; 410 522 end; 411 523 cmInput, cmOutput: begin 412 NewProgram[NewProgram Index] := FProgram[FProgramIndex];524 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 413 525 Inc(NumberOfBaseDecrement, 2); 414 526 end; 415 527 cmSet: begin 416 NewProgram[NewProgram Index] := FProgram[FProgramIndex];528 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 417 529 Inc(NumberOfBaseDecrement, 2); 418 530 end; 419 531 cmLoopStart: begin 420 if not ProcessLoop then begin 421 NumberOfBaseDecrement := 0; 422 PointerChange := 0; 423 LoopStartIndex := FProgramIndex; 424 LoopStartIndexNew := NewProgramIndex; 425 NewProgram[NewProgramIndex] := FProgram[FProgramIndex]; 426 end else begin 427 Dec(NewProgramIndex); 532 if not ProcessingLoop then begin 533 if CheckLoopDecrementCount = 1 then begin 534 PointerChange := 0; 535 ProcessingLoop := True; 536 NoNewCode := True; 537 end else 538 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 539 end else begin 540 NoNewCode := True; 428 541 end; 429 542 end; 430 543 cmLoopEnd: begin 431 if not ProcessLoop then begin 432 if (NumberOfBaseDecrement = 1) and (PointerChange = 0) then begin 433 FProgramIndex := LoopstartIndex - 1; 434 NewProgramIndex := LoopStartIndexNew - 1; 435 ProcessLoop := True; 436 end else begin 437 NewProgram[NewProgramIndex] := FProgram[FProgramIndex]; 438 end; 439 end else begin 440 NewProgram[NewProgramIndex] := TMachineOperation.Create(cmSet, 0, 0); 441 ProcessLoop := False; 442 NumberOfBaseDecrement := 0; 544 if not ProcessingLoop then begin 545 NewProgram[NewProgram.Index] := FProgram[FProgramIndex]; 546 end else begin 547 // Finally set decrementing cell to zero 548 NewProgram[NewProgram.Index] := TMachineOperation.Create(cmSet, 0, 0); 549 ProcessingLoop := False; 443 550 end; 444 551 end; 445 552 else raise Exception.Create(Format(SUnsupportedCommand, [FProgram[FProgramIndex].Command])); 446 553 end; 447 DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, NewProgramIndex, NewTextIndex); 448 Inc(NewTextIndex, Length(GetOperationText(NewProgram[NewProgramIndex]))); 449 Inc(FProgramIndex); 450 Inc(NewProgramIndex); 451 end; 452 SetLength(NewProgram, NewProgramIndex); 453 454 // Replace old program by new program 455 SetLength(FProgram, Length(NewProgram)); 456 Move(Pointer(NewProgram)^, Pointer(FProgram)^, SizeOf(TMachineOperation) * 457 Length(NewProgram)); 554 if NoNewCode then DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, -1, NewTextIndex) 555 else begin 556 DebugSteps.UpdateTargetPos(FirstIndex, FProgramIndex, NewProgram.Index, NewTextIndex); 557 Inc(NewTextIndex, Length(GetOperationText(NewProgram[NewProgram.Index]))); 558 end; 559 Inc(FProgramIndex); 560 if not NoNewCode then Inc(NewProgram.Index); 561 end; 562 563 NewProgram.Count := NewProgram.Index; 564 FProgram.Assign(NewProgram); 565 FreeAndNil(NewProgram); 458 566 end; 459 567 … … 462 570 Result := BrainFuckCommandText[Operation.Command]; 463 571 if Operation.Command in [cmInc, cmDec, cmPointerInc, cmPointerDec, 464 cmSet, cmMultip y] then begin572 cmSet, cmMultiply] then begin 465 573 if Operation.Parameter <> 1 then 466 574 Result := Result + IntToStr(Operation.Parameter); … … 476 584 inherited; 477 585 DebugSteps.Clear; 478 SetLength(FProgram, Length(FSourceCode));586 FProgram.Count := Length(FSourceCode); 479 587 FProgramIndex := 0; 480 588 for I := 1 to Length(FSourceCode) do begin … … 516 624 Inc(FProgramIndex); 517 625 end; 518 SetLength(FProgram, FProgramIndex);626 FProgram.Count := FProgramIndex; 519 627 end; 520 628 … … 524 632 MemorySize := 30000; 525 633 CellSize := 256; 634 FProgram := TProgram.Create; 635 end; 636 637 destructor TBFTarget.Destroy; 638 begin 639 FreeAndNil(FProgram); 640 inherited; 526 641 end; 527 642 … … 532 647 inherited; 533 648 if Optimizations.AddSub then OptimizeAddSub; 649 if Optimizations.SetZero then OptimizeSetZero; 534 650 if Optimizations.Merge then 535 651 repeat 536 OldLength := Length(FProgram);652 OldLength := FProgram.Count; 537 653 OptimizeMerge; 538 until Length(FProgram)= OldLength;654 until FProgram.Count = OldLength; 539 655 OptimizeZeroInitMemory; 540 656 if Optimizations.RelativeIndexes then OptimizeRelativeIndexes;
Note:
See TracChangeset
for help on using the changeset viewer.