diff options
author | Xavier Leroy <xavierleroy@users.noreply.github.com> | 2015-04-22 14:27:12 +0200 |
---|---|---|
committer | Xavier Leroy <xavierleroy@users.noreply.github.com> | 2015-04-22 14:27:12 +0200 |
commit | 0bf99217426a44046ef0aaa7f84a9b2a3646ed89 (patch) | |
tree | e4f983980a5001792b90ed8f3dbd8fa241e43eb1 /cfrontend | |
parent | 08b2b46f15e70b11c044e4e9a7c8438a96d57ed7 (diff) | |
parent | ca4aa822693f4d98de99fd3f13c1523d733e1cb0 (diff) | |
download | compcert-0bf99217426a44046ef0aaa7f84a9b2a3646ed89.tar.gz compcert-0bf99217426a44046ef0aaa7f84a9b2a3646ed89.zip |
Merge pull request #40 from AbsInt/inline-asm
GCC-style extended inline asm.
The subset implemented is:
- zero or one output
- output constraints "=r" (to register) or "=m" (to memory)
- zero, one or several inputs
- input constraints "r" (in register), "m" (in memory), "i" and "n" (compile-time integer constant)
- clobbered registers (the 3rd argument)
- both anonymous (%3) and named (%[name]) operands
- modifiers %R and %Q to refer to the most significant / least significant part of a register pair holding a 64-bit integer. (Undocumented GCC ARM feature.)
All asm statements are treated as "volatile", possibly modifying memory and condition codes.
Diffstat (limited to 'cfrontend')
-rw-r--r-- | cfrontend/C2C.ml | 48 | ||||
-rw-r--r-- | cfrontend/Cexec.v | 16 | ||||
-rw-r--r-- | cfrontend/PrintCsyntax.ml | 30 |
3 files changed, 72 insertions, 22 deletions
diff --git a/cfrontend/C2C.ml b/cfrontend/C2C.ml index fd10efb4..b6b9defe 100644 --- a/cfrontend/C2C.ml +++ b/cfrontend/C2C.ml @@ -114,18 +114,14 @@ let currentLocation = ref Cutil.no_loc let updateLoc l = currentLocation := l -let numErrors = ref 0 - let error msg = - incr numErrors; - eprintf "%aError: %s\n" Cutil.printloc !currentLocation msg + Cerrors.error "%aError: %s" Cutil.formatloc !currentLocation msg let unsupported msg = - incr numErrors; - eprintf "%aUnsupported feature: %s\n" Cutil.printloc !currentLocation msg + Cerrors.error "%aUnsupported feature: %s" Cutil.formatloc !currentLocation msg let warning msg = - eprintf "%aWarning: %s\n" Cutil.printloc !currentLocation msg + Cerrors.warning "%aWarning: %s\n" Cutil.formatloc !currentLocation msg let string_of_errmsg msg = let string_of_err = function @@ -831,6 +827,30 @@ and convertExprList env el = | [] -> Enil | e1 :: el' -> Econs(convertExpr env e1, convertExprList env el') +(* Extended assembly *) + +let convertAsm loc env txt outputs inputs clobber = + let (txt', output', inputs') = + ExtendedAsm.transf_asm loc env txt outputs inputs clobber in + let clobber' = + List.map intern_string clobber in + let ty_res = + match output' with None -> TVoid [] | Some e -> e.etyp in + (* Build the Ebuiltin expression *) + let e = + let tinputs = convertTypArgs env [] inputs' in + let toutput = convertTyp env ty_res in + Ebuiltin(EF_inline_asm(intern_string txt', + signature_of_type tinputs toutput cc_default, + clobber'), + tinputs, + convertExprList env inputs', + convertTyp env ty_res) in + (* Add an assignment to the output, if any *) + match output' with + | None -> e + | Some lhs -> Eassign (convertLvalue env lhs, e, typeof e) + (* Separate the cases of a switch statement body *) type switchlabel = @@ -891,7 +911,9 @@ let rec convertStmt ploc env s = | C.Sdo e -> add_lineno ploc s.sloc (swrap (Ctyping.sdo (convertExpr env e))) | C.Sseq(s1, s2) -> - Ssequence(convertStmt ploc env s1, convertStmt s1.sloc env s2) + let s1' = convertStmt ploc env s1 in + let s2' = convertStmt s1.sloc env s2 in + Ssequence(s1', s2') | C.Sif(e, s1, s2) -> let te = convertExpr env e in add_lineno ploc s.sloc @@ -940,11 +962,11 @@ let rec convertStmt ploc env s = unsupported "nested blocks"; Sskip | C.Sdecl _ -> unsupported "inner declarations"; Sskip - | C.Sasm txt -> + | C.Sasm(attrs, txt, outputs, inputs, clobber) -> if not !Clflags.option_finline_asm then unsupported "inline 'asm' statement (consider adding option -finline-asm)"; add_lineno ploc s.sloc - (Sdo (Ebuiltin (EF_inline_asm (intern_string txt), Tnil, Enil, Tvoid))) + (Sdo (convertAsm s.sloc env txt outputs inputs clobber)) and convertSwitch ploc env is_64 = function | [] -> @@ -1211,7 +1233,7 @@ let public_globals gl = (** Convert a [C.program] into a [Csyntax.program] *) let convertProgram p = - numErrors := 0; + Cerrors.reset(); stringNum := 0; Hashtbl.clear decl_atom; Hashtbl.clear stringTable; @@ -1236,9 +1258,7 @@ let convertProgram p = prog_main = intern_string "main"; prog_types = typs; prog_comp_env = ce } in - if !numErrors > 0 - then None - else Some p' + if Cerrors.check_errors () then None else Some p' with Env.Error msg -> error (Env.error_message msg); None diff --git a/cfrontend/Cexec.v b/cfrontend/Cexec.v index 7c00ab47..aba3c094 100644 --- a/cfrontend/Cexec.v +++ b/cfrontend/Cexec.v @@ -405,18 +405,18 @@ Hypothesis do_external_function_complete: do_external_function id sg ge w vargs m = Some(w', t, vres, m'). Variable do_inline_assembly: - ident -> Senv.t -> world -> list val -> mem -> option (world * trace * val * mem). + ident -> signature -> Senv.t -> world -> list val -> mem -> option (world * trace * val * mem). Hypothesis do_inline_assembly_sound: - forall txt ge vargs m t vres m' w w', - do_inline_assembly txt ge w vargs m = Some(w', t, vres, m') -> - inline_assembly_sem txt ge vargs m t vres m' /\ possible_trace w t w'. + forall txt sg ge vargs m t vres m' w w', + do_inline_assembly txt sg ge w vargs m = Some(w', t, vres, m') -> + inline_assembly_sem txt sg ge vargs m t vres m' /\ possible_trace w t w'. Hypothesis do_inline_assembly_complete: - forall txt ge vargs m t vres m' w w', - inline_assembly_sem txt ge vargs m t vres m' -> + forall txt sg ge vargs m t vres m' w w', + inline_assembly_sem txt sg ge vargs m t vres m' -> possible_trace w t w' -> - do_inline_assembly txt ge w vargs m = Some(w', t, vres, m'). + do_inline_assembly txt sg ge w vargs m = Some(w', t, vres, m'). Definition do_ef_volatile_load (chunk: memory_chunk) (w: world) (vargs: list val) (m: mem) : option (world * trace * val * mem) := @@ -541,7 +541,7 @@ Definition do_external (ef: external_function): | EF_memcpy sz al => do_ef_memcpy sz al | EF_annot text targs => do_ef_annot text targs | EF_annot_val text targ => do_ef_annot_val text targ - | EF_inline_asm text => do_inline_assembly text ge + | EF_inline_asm text sg clob => do_inline_assembly text sg ge end. Lemma do_ef_external_sound: diff --git a/cfrontend/PrintCsyntax.ml b/cfrontend/PrintCsyntax.ml index 882272b8..39de282b 100644 --- a/cfrontend/PrintCsyntax.ml +++ b/cfrontend/PrintCsyntax.ml @@ -236,6 +236,8 @@ let rec expr p (prec, e) = expr (prec1, a1) (name_binop op) expr (prec2, a2) | Ecast(a1, ty) -> fprintf p "(%s) %a" (name_type ty) expr (prec', a1) + | Eassign(res, Ebuiltin(EF_inline_asm(txt, sg, clob), _, args, _), _) -> + extended_asm p txt (Some res) args clob | Eassign(a1, a2, _) -> fprintf p "%a =@ %a" expr (prec1, a1) expr (prec2, a2) | Eassignop(op, a1, a2, _, _) -> @@ -262,6 +264,8 @@ let rec expr p (prec, e) = (extern_atom txt) exprlist (false, args) | Ebuiltin(EF_external(id, sg), _, args, _) -> fprintf p "%s@[<hov 1>(%a)@]" (extern_atom id) exprlist (true, args) + | Ebuiltin(EF_inline_asm(txt, sg, clob), _, args, _) -> + extended_asm p txt None args clob | Ebuiltin(_, _, args, _) -> fprintf p "<unknown builtin>@[<hov 1>(%a)@]" exprlist (true, args) | Eparen(a1, tycast, ty) -> @@ -277,6 +281,32 @@ and exprlist p (first, rl) = expr p (2, r); exprlist p (false, rl) +and extended_asm p txt res args clob = + fprintf p "asm volatile (@[<hv 0>%S" (extern_atom txt); + fprintf p "@ :"; + begin match res with + | None -> () + | Some e -> fprintf p " \"=r\"(%a)" expr (0, e) + end; + let rec inputs p (first, el) = + match el with + | Enil -> () + | Econs(e1, el) -> + if not first then fprintf p ",@ "; + fprintf p "\"r\"(%a)" expr (0, e1); + inputs p (false, el) in + fprintf p "@ : @[<hov 0>%a@]" inputs (true, args); + begin match clob with + | [] -> () + | c1 :: cl -> + fprintf p "@ : @[<hov 0>%S" (extern_atom c1); + List.iter + (fun c -> fprintf p ",@ %S" (extern_atom c)) + cl; + fprintf p "@]" + end; + fprintf p ")@]" + let print_expr p e = expr p (0, e) let print_exprlist p el = exprlist p (true, el) |