aboutsummaryrefslogtreecommitdiffstats
path: root/cfrontend
diff options
context:
space:
mode:
authorXavier Leroy <xavierleroy@users.noreply.github.com>2015-04-22 14:27:12 +0200
committerXavier Leroy <xavierleroy@users.noreply.github.com>2015-04-22 14:27:12 +0200
commit0bf99217426a44046ef0aaa7f84a9b2a3646ed89 (patch)
treee4f983980a5001792b90ed8f3dbd8fa241e43eb1 /cfrontend
parent08b2b46f15e70b11c044e4e9a7c8438a96d57ed7 (diff)
parentca4aa822693f4d98de99fd3f13c1523d733e1cb0 (diff)
downloadcompcert-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.ml48
-rw-r--r--cfrontend/Cexec.v16
-rw-r--r--cfrontend/PrintCsyntax.ml30
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)