Skip to content

Commit 54d5704

Browse files
committed
conditional meta instructions
1 parent b6219e7 commit 54d5704

6 files changed

Lines changed: 59 additions & 26 deletions

File tree

ARM/parser_ast.ml

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ type args =
2222
| Offset of string (* register *) * offset * Arm.addressing_type
2323

2424
type command =
25+
| DUMMY
26+
| ITE of Preprocess.meta_expr * ast * ast
2527
| ASM of Lexing.position * string * args list * Optimizer.tweaking_settings
2628
| BIN of Lexing.position * unprocessed_int32
2729

28-
type ast = command list
30+
and ast = command list
2931

3032
exception CommandError of Lexing.position
3133

@@ -260,11 +262,15 @@ let asm_cmd_to_arm env cmd args =
260262
try (asm_cmd3_to_arm env cmd args)
261263
with StructError -> (asm_cmd1_to_arm env cmd args)
262264

263-
let cmd_to_arm env cmd =
265+
let rec cmd_to_arm env cmd =
264266
match cmd with
267+
| DUMMY -> []
268+
| ITE (e, a1, a2) ->
269+
let i32 = Preprocess.eval_meta_expr env e in
270+
if Preprocess.to_bool i32 then to_arm env a1 else to_arm env a2
265271
| ASM (pos, cmd, args, optimize) ->
266-
begin try (asm_cmd_to_arm env cmd args, optimize)
272+
begin try [asm_cmd_to_arm env cmd args, optimize]
267273
with StructError -> raise (CommandError pos) end
268-
| BIN (_, i) -> (Custom (preprocess env i), Optimizer.NoTweaking)
274+
| BIN (_, i) -> [Custom (preprocess env i), Optimizer.NoTweaking]
269275

270-
let to_arm env ast = List.map (cmd_to_arm env) ast
276+
and to_arm env ast = List.concat_map (cmd_to_arm env) ast

ARM/parser_ast.mli

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ type args =
2121
| Offset of string (* register *) * offset * Arm.addressing_type
2222

2323
type command =
24+
| DUMMY
25+
| ITE of Preprocess.meta_expr * ast * ast
2426
| ASM of Lexing.position * string * args list * Optimizer.tweaking_settings
2527
| BIN of Lexing.position * unprocessed_int32
2628

27-
type ast = command list
29+
and ast = command list
2830

2931
exception CommandError of Lexing.position
3032

ARM/preprocess.ml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ module StrMap = Map.Make(String)
2020
type env = int32 StrMap.t
2121
exception VarNotFound of string
2222

23+
let to_bool i = Int32.equal i Int32.zero |> not
24+
2325
let get_param headers name =
2426
let rec aux lst =
2527
match lst with
@@ -35,7 +37,7 @@ let eval_unary op i =
3537
| OId -> i
3638
| ONeg -> Int32.neg i
3739
| ONot -> Int32.lognot i
38-
| OBNot -> if Int32.equal i Int32.zero then Int32.one else Int32.zero
40+
| OBNot -> if to_bool i then Int32.zero else Int32.one
3941

4042
let eval_binary op i1 i2 =
4143
match op with
@@ -52,11 +54,9 @@ let eval_binary op i1 i2 =
5254
| OEq -> if Int32.equal i1 i2 then Int32.one else Int32.zero
5355
| ONeq -> if Int32.equal i1 i2 then Int32.zero else Int32.one
5456
| OBOr ->
55-
if Int32.equal i1 Int32.zero && Int32.equal i2 Int32.zero
56-
then Int32.zero else Int32.one
57+
if to_bool i1 || to_bool i2 then Int32.one else Int32.zero
5758
| OBAnd ->
58-
if Int32.equal i1 Int32.zero || Int32.equal i2 Int32.zero
59-
then Int32.zero else Int32.one
59+
if to_bool i1 && to_bool i2 then Int32.one else Int32.zero
6060
| OGeq -> if Int32.unsigned_compare i1 i2 >= 0 then Int32.one else Int32.zero
6161
| OGt -> if Int32.unsigned_compare i1 i2 > 0 then Int32.one else Int32.zero
6262
| OLeq -> if Int32.unsigned_compare i1 i2 <= 0 then Int32.one else Int32.zero
@@ -78,7 +78,7 @@ let eval_meta_expr env e =
7878
eval_binary op i1 i2
7979
| MCond (e0, e1, e2) ->
8080
let i0 = aux e0 in
81-
if Int32.equal i0 Int32.zero then aux e2 else aux e1
81+
if to_bool i0 then aux e1 else aux e2
8282
in
8383
aux e
8484

ARM/preprocess.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ exception VarNotFound of string
2222
val get_param : headers -> string -> def_val
2323

2424
val eval_meta_expr : env -> meta_expr -> int32
25+
val to_bool : int32 -> bool
2526

2627
val empty_env : env
2728
val env_from_headers : Format.formatter -> headers -> env

IO/lexer.mll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ rule read = parse
8989
| '|' { OR }
9090
| '^' { XOR }
9191
| '~' { NOT }
92+
| ".if" { IF }
93+
| ".elseif" { ELSEIF }
94+
| ".else" { ELSE }
95+
| ".endif" { ENDIF }
9296
| eof { eof_reached lexbuf ; EOF }
9397
| _ { raise (SyntaxError ("Unexpected char: " ^ Lexing.lexeme lexbuf)) }
9498

IO/parser.mly

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
%{ open Parser_ast %}
22
%{ open Preprocess %}
3+
%{
4+
let encode_cases lst default =
5+
List.fold_right (fun (cond, ast) acc ->
6+
[ITE (cond, ast, acc)]
7+
) lst default |> List.hd
8+
%}
39

410
%token HEADER
511
%token NULL
@@ -36,8 +42,8 @@
3642
%token BAND
3743
%token LSL LSR ASR ROR RRX
3844
%token LEQ GEQ LT GT
39-
%token EOL
40-
%token EOF
45+
%token IF ELSEIF ELSE ENDIF
46+
%token EOL EOF
4147

4248
%nonassoc ARG
4349
%nonassoc COMMA
@@ -59,11 +65,12 @@
5965
%%
6066

6167
%inline binop:
62-
| MOD { OMod } | DIV { ODiv } | TIMES { OMul } | MINUS { OSub } | PLUS { OAdd }
63-
| BAND { OBAnd } | BOR { OBOr } | OR { OOr } | XOR { OXor } | AND { OAnd }
64-
| EQ { OEq } | NEQ { ONeq }
65-
| LT { OLt } | GT { OGt } | LEQ { OLeq } | GEQ { OGeq }
66-
| LSHIFT { OLShift } | RSHIFT { ORShift }
68+
| MOD { OMod } | DIV { ODiv } | TIMES { OMul } | MINUS { OSub } | PLUS { OAdd }
69+
| BAND { OBAnd } | BOR { OBOr } | OR { OOr } | XOR { OXor } | AND { OAnd }
70+
| EQ { OEq } | NEQ { ONeq }
71+
| LT { OLt } | GT { OGt } | LEQ { OLeq } | GEQ { OGeq }
72+
| LSHIFT { OLShift } | RSHIFT { ORShift }
73+
;
6774

6875
meta_expr:
6976
| i = NUMBER { MConst i }
@@ -74,8 +81,8 @@ meta_expr:
7481
| MINUS e = meta_expr %prec UMINUS { MUnary (ONeg, e) }
7582
| NOT e = meta_expr { MUnary (ONot, e) }
7683
| EXCLAM_MARK e = meta_expr { MUnary (OBNot, e) }
77-
| e0 = meta_expr INTERROG_MARK e1 = meta_expr COLON e2 = meta_expr
78-
{ MCond (e0, e1, e2) }
84+
| e0 = meta_expr INTERROG_MARK e1 = meta_expr COLON e2 = meta_expr { MCond (e0, e1, e2) }
85+
;
7986

8087
definition:
8188
| HEADER ; id = ID ; EQUAL ; str = STRING { Param (id, HString str) }
@@ -87,23 +94,36 @@ definition:
8794
;
8895

8996
headers:
90-
| list (EOL) ; HEADER ; EOL | list (EOL) ; HEADER ; EOF { [] }
91-
| list (EOL) ; d = definition ; EOL ; ds = headers { d::ds }
97+
| EOL* ; HEADER ; EOL | EOL* ; HEADER ; EOF { [] }
98+
| EOL* ; d = definition ; EOL ; ds = headers { d::ds }
9299
;
93100

94101
ast:
95-
| list (EOL) ; EOF { [] }
96-
| list (EOL) ; cmd = command ; EOL ; cmds = ast { cmd::cmds }
97-
| list (EOL) ; cmd = command ; EOF { [cmd] }
102+
| cmds = commands ; EOF { cmds }
98103
;
99104

100105
command:
106+
| { DUMMY }
101107
| id = ID ; args = separated_list(COMMA, arg) { ASM ($startpos, id, args, Optimizer.NoTweaking) }
102108
| id = ID ; args = separated_list(COMMA, arg) ; INTERROG_MARK { ASM ($startpos, id, args, Optimizer.TweakMinLength) }
103109
| id = ID ; args = separated_list(COMMA, arg) ; INTERROG_MARK ; i = NUMBER
104110
{ ASM ($startpos, id, args, Optimizer.TweakFixedLength (Utils.uint32_to_int i)) }
105111
| nb = number { BIN ($startpos, nb) }
112+
| e = if_statement ; es = elseif* ; d = default { encode_cases (e::es) d }
113+
;
114+
115+
if_statement:
116+
| IF ; e=meta_expr ; EOL ; cmds = commands { (e, cmds) }
106117
;
118+
elseif:
119+
| ELSEIF ; e=meta_expr ; EOL ; cmds = commands { (e, cmds) }
120+
;
121+
default:
122+
| ELSE ; EOL ; cmds = commands ; ENDIF { cmds }
123+
| ENDIF { [] }
124+
;
125+
126+
%inline commands: cmds=separated_nonempty_list(EOL, command) { cmds } ;
107127

108128
%inline maybe_hash:
109129
| {}

0 commit comments

Comments
 (0)