diff options
Diffstat (limited to 'src/Assembly/StringConversion.v')
-rw-r--r-- | src/Assembly/StringConversion.v | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/src/Assembly/StringConversion.v b/src/Assembly/StringConversion.v new file mode 100644 index 000000000..c365c5824 --- /dev/null +++ b/src/Assembly/StringConversion.v @@ -0,0 +1,386 @@ +Require Export Language Conversion. +Require Export String Ascii Basics Sumbool. +Require Import QhasmCommon QhasmEvalCommon QhasmUtil Qhasm. +Require Import NArith NPeano. +Require Export Bedrock.Word. + +Module QhasmString <: Language. + Definition Params := unit. + Definition Program := fun (_: Params) => string. + Definition State := fun (_: Params) => unit. + + Definition evaluatesTo x (p: Program x) (i o: State x): Prop := True. +End QhasmString. + +Module StringConversion <: Conversion Qhasm QhasmString. + Import Qhasm ListNotations. + + (* The easy one *) + Definition convertState x y (st: QhasmString.State y): option (Qhasm.State x) := None. + + (* Hexadecimal Primitives *) + + Section Hex. + Local Open Scope string_scope. + + Definition natToDigit (n : nat) : string := + match n with + | 0 => "0" | 1 => "1" | 2 => "2" | 3 => "3" + | 4 => "4" | 5 => "5" | 6 => "6" | 7 => "7" + | 8 => "8" | 9 => "9" | 10 => "A" | 11 => "B" + | 12 => "C" | 13 => "D" | 14 => "E" | _ => "F" + end. + + Fixpoint nToHex' (n: N) (digitsLeft: nat): string := + match digitsLeft with + | O => "" + | S nextLeft => + match n with + | N0 => "0" + | _ => (nToHex' (N.shiftr_nat n 4) nextLeft) ++ + (natToDigit (N.to_nat (N.land n 15%N))) + end + end. + + Definition nToHex (n: N): string := + let size := (N.size n) in + let div4 := fun x => (N.shiftr x 2%N) in + let size' := (size + 4 - (N.land size 3))%N in + nToHex' n (N.to_nat (div4 size')). + + End Hex. + + (* Conversion of elements *) + + Section Elements. + Local Open Scope string_scope. + + Definition nameSuffix (n: nat): string := + (nToHex (N.of_nat n)). + + Coercion wordToString {n} (w: word n): string := + "0x" ++ (nToHex (wordToN w)). + + Coercion constToString {n} (c: Const n): string := + match c with | constant _ _ w => wordToString w end. + + Coercion regToString {n} (r: Reg n): string := + match r with + | reg _ W32 n => "w" ++ (nameSuffix n) + | reg _ W64 n => "d" ++ (nameSuffix n) + end. + + Coercion natToString (n: nat): string := + "0x" ++ (nToHex (N.of_nat n)). + + Coercion stackToString {n} (s: Stack n): string := + match s with + | stack _ W32 n => "ws" ++ (nameSuffix n) + | stack _ W64 n => "ds" ++ (nameSuffix n) + end. + + Coercion memToString {n m} (s: Mem n m): string := + match s with + | mem _ _ W32 v => "wm" ++ (nameSuffix v) + | mem _ _ W64 v => "dm" ++ (nameSuffix v) + end. + + Coercion stringToSome (x: string): option string := Some x. + + Definition stackLocation {n} (s: Stack n): word 32 := + combine (natToWord 8 n) (natToWord 24 n). + + Definition assignmentToString (a: Assignment): option string := + let f := fun x => if (Nat.eq_dec x 32) then "32" else "64" in + match a with + | ARegStack n r s => r ++ " = *(int" ++ f n ++ " *)" ++ s + | AStackReg n s r => "*(int" ++ f n ++ " *) " ++ s ++ " = " ++ r + | ARegMem n m r v i => r ++ " = " ++ "*(int" ++ f n ++ " *) (" ++ v ++ " + " ++ i ++ ")" + | AMemReg n m v i r => "*(int" ++ f n ++ " *) (" ++ v ++ " + " ++ i ++ ") = " ++ r + | ARegReg n a b => a ++ " = " ++ b + | AConstInt n r c => r ++ " = " ++ c + end. + + Coercion intOpToString (b: IntOp): string := + match b with + | Add => "+" + | Sub => "-" + | Xor => "^" + | And => "&" + | Or => "|" + end. + + Coercion dualOpToString (b: DualOp): string := + match b with + | Mult => "*" + end. + + Coercion carryOpToString (b: CarryOp): string := + match b with + | AddWithCarry => "+" + end. + + Coercion rotOpToString (r: RotOp): string := + match r with + | Shl => "<<" + | Shr => ">>" + end. + + Definition operationToString (op: Operation): option string := + let f := fun x => if (Nat.eq_dec x 32) then "32" else "64" in + match op with + | IOpConst n o r c => + r ++ " " ++ o ++ "= " ++ c + | IOpReg n o a b => + a ++ " " ++ o ++ "= " ++ b + | IOpMem n _ o a b i => + a ++ " " ++ o ++ "= *(int" ++ (f n) ++ "* " ++ b ++ " + " ++ i ++ ")" + | IOpStack n o a b => + a ++ " " ++ o ++ "= " ++ b + | DOp n o a b x => + match x with + | Some r => + "inline " ++ r ++ " " ++ a ++ " " ++ o ++ "= " ++ b + | None => a ++ " " ++ o ++ "= " ++ b + end + | COp n o a b => + a ++ " " ++ o ++ "= " ++ b + | ROp n o r i => + r ++ " " ++ o ++ "= " ++ i + end. + + Definition testOpToString (t: TestOp): bool * string := + match t with + | TEq => (true, "=") + | TLt => (true, "<") + | TGt => (true, ">") + | TLe => (false, ">") + | TGe => (false, "<") + end. + + Definition conditionalToString (c: Conditional): string * string := + match c with + | CTrue => ("=? 0", "=") + | CZero n r => ("=? " ++ r, "=") + | CReg n t a b => + match (testOpToString t) with + | (true, s) => + (s ++ "? " ++ a ++ " - " ++ b, s) + | (false, s) => + (s ++ "? " ++ a ++ " - " ++ b, "!" ++ s) + end + + | CConst n t a b => + match (testOpToString t) with + | (true, s) => + (s ++ "? " ++ a ++ " - " ++ b, s) + | (false, s) => + (s ++ "? " ++ a ++ " - " ++ b, "!" ++ s) + end + end. + + End Elements. + + Section Parsing. + Definition convM {n m} (x: list (Mapping n)): list (Mapping m). + destruct (Nat.eq_dec n m); subst. exact x. exact []. + Defined. + + Arguments regM [n] r. + Arguments stackM [n] s. + Arguments memM [n m] x i. + Arguments constM [n] x. + + Fixpoint entries (width: nat) (prog: list QhasmStatement): list (Mapping width) := + match prog with + | cons s next => + match s with + | QAssign a => + match a with + | ARegStack n r s => convM [regM r; stackM s] + | AStackReg n s r => convM [regM r; stackM s] + | ARegMem n m a b i => convM [regM a; memM b i] + | AMemReg n m a i b => convM [memM a i; regM b] + | ARegReg n a b => convM [regM a; regM b] + | AConstInt n r c => convM [regM r; constM c] + end + | QOp o => + match o with + | IOpConst _ o a c => convM [regM a; constM c] + | IOpReg _ o a b => convM [regM a; regM b] + | IOpStack _ o a b => convM [regM a; stackM b] + | IOpMem _ _ o a b i => convM [regM a; memM b i] + | DOp _ o a b (Some x) => convM [regM a; regM b; regM x] + | DOp _ o a b None => convM [regM a; regM b] + | ROp _ o a i => convM [regM a] + | COp _ o a b => convM [regM a; regM b] + end + | QCond c _ => + match c with + | CTrue => [] + | CZero n r => convM [regM r] + | CReg n o a b => convM [regM a; regM b] + | CConst n o a c => convM [regM a; constM c] + end + | _ => [] + end ++ (entries width next) + | nil => nil + end. + + Definition flatMapOpt {A B} (lst: list A) (f: A -> option B): list B := + fold_left + (fun lst a => match (f a) with | Some x => cons x lst | _ => lst end) + lst []. + + Definition flatMapList {A B} (lst: list A) (f: A -> list B): list B := + fold_left (fun lst a => lst ++ (f a)) lst []. + + Fixpoint dedup {n} (l : list (Mapping n)) : list (Mapping n) := + match l with + | [] => [] + | x::xs => + if in_dec EvalUtil.mapping_dec x xs + then dedup xs + else x::(dedup xs) + end. + + Definition getRegNames (n: nat) (lst: list (Mapping n)): list nat := + flatMapOpt (dedup lst) (fun e => + match e with | regM (reg _ _ x) => Some x | _ => None end). + + Definition getStackNames (n: nat) (lst: list (Mapping n)): list nat := + flatMapOpt (dedup lst) (fun e => + match e with | stackM (stack _ _ x) => Some x | _ => None end). + + Definition getMemNames (n: nat) (lst: list (Mapping n)): list nat := + flatMapOpt (dedup lst) (fun e => + match e with | memM _ (mem _ _ _ x) _ => Some x | _ => None end). + + Fixpoint getInputs' (n: nat) (prog: list QhasmStatement) (init: list (Mapping n)): list (Mapping n) := + let f := fun rs => filter (fun x => + negb (proj1_sig (bool_of_sumbool (in_dec EvalUtil.mapping_dec x init)))) rs in + let g := fun {w} p => (@convM w n (fst p), @convM w n (snd p)) in + match prog with + | [] => [] + | cons p ps => + let requiredCommaUsed := match p with + | QAssign a => + match a with + | ARegStack n r s => g ([stackM s], [regM r; stackM s]) + | AStackReg n s r => g ([regM r], [regM r; stackM s]) + | ARegMem n m r x i => g ([memM x i], [regM r; memM x i]) + | AMemReg n m x i r => g ([regM r], [regM r; memM x i]) + | ARegReg n a b => g ([regM b], [regM a; regM b]) + | AConstInt n r c => g ([], [regM r]) + end + | QOp o => + match o with + | IOpConst _ o a c => g ([regM a], [regM a]) + | IOpReg _ o a b => g ([regM a], [regM a; regM b]) + | IOpStack _ o a b => g ([regM a], [regM a; stackM b]) + | IOpMem _ _ o a b i => g ([regM a], [regM a; memM b i]) + | DOp _ o a b (Some x) => g ([regM a; regM b], [regM a; regM b; regM x]) + | DOp _ o a b None => g ([regM a; regM b], [regM a; regM b]) + | ROp _ o a i => g ([regM a], [regM a]) + | COp _ o a b => g ([regM a], [regM a; regM b]) + end + | QCond c _ => + match c with + | CTrue => ([], []) + | CZero n r => g ([], [regM r]) + | CReg n o a b => g ([], [regM a; regM b]) + | CConst n o a c => g ([], [regM a]) + end + | _ => ([], []) + end in match requiredCommaUsed with + | (r, u) => ((f r) ++ (getInputs' n ps ((f u) ++ init))) + end + end. + + Definition getInputs (n: nat) (prog: list QhasmStatement) := getInputs' n prog []. + + Definition mappingDeclaration {n} (x: Mapping n): option string := + match x with + | regM (reg _ w x) => + match w with + | W32 => Some ("int32 " ++ (reg w x))%string + | W64 => Some ("int64 " ++ (reg w x))%string + end + + | stackM (stack _ w x) => + match w with + | W32 => Some ("stack32 " ++ (stack w x))%string + | W64 => Some ("stack64 " ++ (stack w x))%string + end + + | memM _ (mem _ m w x) _ => + match w with + | W32 => Some ("stack32 " ++ (@mem _ m w x))%string + | W64 => Some ("stack64 " ++ (@mem _ m w x))%string + end + + | _ => None + end. + + Definition inputDeclaration {n} (x: Mapping n): option string := + match x with + | regM r => Some ("input " ++ r)%string + | stackM s => Some ("input " ++ s)%string + | memM _ m i => Some ("input " ++ m)%string + | _ => None + end. + + End Parsing. + + (* Macroscopic Conversion Methods *) + Definition optionToList {A} (o: option A): list A := + match o with + | Some a => [a] + | None => [] + end. + + Definition convertStatement (statement: QhasmStatement): list string := + match statement with + | QAssign a => optionToList (assignmentToString a) + | QOp o => optionToList (operationToString o) + | QCond c l => + match (conditionalToString c) with + | (s1, s2) => + let s' := ("goto lbl" ++ l ++ " if " ++ s2)%string in + [s1; s'] + end + | QLabel l => [("lbl" ++ l ++ ": ")%string] + | QCall l => [("push %eip+2")%string; ("goto" ++ l)%string] + | QRet => [("pop %eip")%string] + end. + + Transparent Qhasm.Program QhasmString.Program. + + Definition convertProgram x y (prog: Qhasm.Program x): option (QhasmString.Program y) := + let decls := fun x => flatMapList (dedup (entries x prog)) + (compose optionToList mappingDeclaration) in + + let inputs := fun x => flatMapList (getInputs x prog) + (compose optionToList inputDeclaration) in + + let stmts := (flatMapList prog convertStatement) in + let enter := [("enter prog")%string] in + let leave := [("leave")%string] in + let blank := [EmptyString] in + let newline := String (ascii_of_nat 10) EmptyString in + + Some (fold_left (fun x y => (x ++ newline ++ y)%string) + (decls 32 ++ inputs 32 ++ + decls 64 ++ inputs 64 ++ blank ++ + enter ++ blank ++ + stmts ++ blank ++ + leave ++ blank) EmptyString). + + Lemma convert_spec: forall pa pb a a' b b' prog prog', + convertProgram pa pb prog = Some prog' -> + convertState pa pb a = Some a' -> + convertState pa pb b = Some b' -> + QhasmString.evaluatesTo pb prog' a b <-> Qhasm.evaluatesTo pa prog a' b'. + Admitted. + +End StringConversion. |