Skip to content

Commit

Permalink
Generate a nop instruction after some ais annotations (#137)
Browse files Browse the repository at this point in the history
* Generate a nop instruction after ais annotations.

In order to prevent the merging of ais annotations with following
Labels a nop instruction is inserted, but only if the annotation
is followed immediately by a label.

The insertion of nop instructions is performed during the
expansion of builtin and pseudo assembler instructions and is
processor independent, by inserting a __builtin_nop built-in.

* Add Pnop instruction to ARM, RISC-V, and x86

ARM as well as RISC-V don't have nop instructions that can
be easily encoded by for example add with zero instructions.
For x86 we used to use `mov X0, X0` for nop but this may
not be as efficient as the true nop instruction.

* Implement __builtin_nop on all supported target architectures.

This builtin is not yet made available on the C side for all architectures.

Bug 24067
  • Loading branch information
bschommer authored and xavierleroy committed Sep 12, 2018
1 parent 25ba736 commit 591073b
Show file tree
Hide file tree
Showing 14 changed files with 64 additions and 28 deletions.
2 changes: 2 additions & 0 deletions arm/Asm.v
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ Inductive instruction : Type :=
| Prev16: ireg -> ireg -> instruction (**r reverse bytes and reverse bits. *)
| Prsc: ireg -> ireg -> shift_op -> instruction (**r reverse subtract without carry. *)
| Psbc: ireg -> ireg -> shift_op -> instruction (**r add with carry *)
| Pnop : instruction (**r nop instruction *)
(* Add, sub, rsb versions with s suffix *)
| Padds: ireg -> ireg -> shift_op -> instruction (**r integer addition with update of condition flags *)
| Psubs: ireg -> ireg -> shift_op -> instruction (**r integer subtraction with update of condition flags *)
Expand Down Expand Up @@ -805,6 +806,7 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out
| Pfsqrt _ _
| Prsc _ _ _
| Psbc _ _ _
| Pnop
| Padds _ _ _
| Psubs _ _ _
| Prsbs _ _ _
Expand Down
3 changes: 2 additions & 1 deletion arm/AsmToJSON.ml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ let mnemonic_names = [ "Padc"; "Padd"; "Padds"; "Pand";"Pannot"; "Pasr"; "Pb"; "
"Pftouizs"; "Pfuitod"; "Pfuitos"; "Pinlineasm"; "Pisb"; "Plabel"; "Pldr";
"Ploadsymbol_lbl"; "Pldr_p"; "Pldrb"; "Pldrb_p"; "Pldrh"; "Pldrh_p"; "Pldrsb";
"Pldrsh"; "Plsl"; "Plsr"; "Pmla"; "Pmov"; "Pmovite";
"Pmovt"; "Pmovw"; "Pmul"; "Pmvn"; "Ploadsymbol_imm"; "Porr";
"Pmovt"; "Pmovw"; "Pmul"; "Pmvn"; "Ploadsymbol_imm"; "Pnop"; "Porr";
"Ppush"; "Prev"; "Prev16"; "Prsb"; "Prsbs"; "Prsc"; "Psbc"; "Psbfx"; "Psdiv"; "Psmull";
"Pstr"; "Pstr_p"; "Pstrb"; "Pstrb_p"; "Pstrh"; "Pstrh_p"; "Psub"; "Psubs"; "Pudiv";
"Pumull" ]
Expand Down Expand Up @@ -263,6 +263,7 @@ let pp_instructions pp ic =
| Pmovw(r1, n) -> instruction pp "Pmovw" [Ireg r1; Long n]
| Pmul(r1, r2, r3) -> instruction pp "Pmul" [Ireg r1; Ireg r2; Ireg r3]
| Pmvn(r1, so) -> instruction pp "Pmvn" [Ireg r1; Shift so]
| Pnop -> instruction pp "Pnop" []
| Porr(r1, r2, so) -> instruction pp "Porr" [Ireg r1; Ireg r2; Shift so]
| Ppush(rl) -> instruction pp "Ppush" (List.map (fun r -> Ireg r) rl)
| Prev(r1, r2) -> instruction pp "Prev" [Ireg r1; Ireg r2]
Expand Down
7 changes: 3 additions & 4 deletions arm/Asmexpand.ml
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@ let expand_builtin_inline name args res =
(* Vararg stuff *)
| "__builtin_va_start", [BA(IR a)], _ ->
expand_builtin_va_start a
| "__builtin_nop", [], _ ->
emit Pnop
(* Catch-all *)
| _ ->
raise (Error ("unrecognized builtin " ^ name))
Expand Down Expand Up @@ -665,10 +667,7 @@ let expand_function id fn =
try
set_current_function fn;
fixup_arguments Incoming fn.fn_sig;
if !Clflags.option_g then
expand_debug id 13 preg_to_dwarf expand_instruction fn.fn_code
else
List.iter expand_instruction fn.fn_code;
expand id 13 preg_to_dwarf expand_instruction fn.fn_code;
let fn = get_current_function () in
let fn = Constantexpand.expand_constants fn in
Errors.OK fn
Expand Down
4 changes: 3 additions & 1 deletion arm/TargetPrinter.ml
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ struct
fprintf oc " vsqrt.f64 %a, %a\n" freg f1 freg f2
| Psbc (r1,r2,sa) ->
fprintf oc " sbc %a, %a, %a\n" ireg r1 ireg r2 shift_op sa
| Pnop ->
fprintf oc " nop\n"
| Pstr(r1, r2, sa) | Pstr_a(r1, r2, sa) ->
fprintf oc " str %a, [%a, %a]\n" ireg r1 ireg r2 shift_op sa
| Pstrb(r1, r2, sa) ->
Expand Down Expand Up @@ -463,7 +465,7 @@ struct
| 1 -> let annot = annot_text preg_annot "sp" (camlstring_of_coqstring txt) args in
fprintf oc "%s annotation: %S\n" comment annot
| 2 -> let lbl = new_label () in
fprintf oc "%a: " label lbl;
fprintf oc "%a:\n" label lbl;
AisAnnot.add_ais_annot lbl preg_annot "r13" (camlstring_of_coqstring txt) args
| _ -> assert false
end
Expand Down
32 changes: 32 additions & 0 deletions backend/Asmexpandaux.ml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,16 @@ let translate_annot sp preg_to_dwarf annot =
| [] -> None
| a::_ -> aux a)

let builtin_nop =
let signature ={sig_args = []; sig_res = None; sig_cc = cc_default} in
let name = coqstring_of_camlstring "__builtin_nop" in
Pbuiltin(EF_builtin(name,signature),[],BR_none)

let rec lbl_follows = function
| Pbuiltin (EF_debug _, _, _):: rest ->
lbl_follows rest
| Plabel _ :: _ -> true
| _ -> false

let expand_debug id sp preg simple l =
let get_lbl = function
Expand Down Expand Up @@ -142,6 +152,11 @@ let expand_debug id sp preg simple l =
| _ ->
aux None scopes rest
end
| (Pbuiltin(EF_annot (kind, _, _),_,_) as annot)::rest ->
if P.to_int kind = 2 && lbl_follows rest then begin
simple annot; simple builtin_nop; aux None scopes rest
end else
simple annot; aux None scopes rest
| (Plabel lbl)::rest -> simple (Plabel lbl); aux (Some lbl) scopes rest
| i::rest -> simple i; aux None scopes rest in
(* We need to move all closing debug annotations before the last real statement *)
Expand All @@ -155,3 +170,20 @@ let expand_debug id sp preg simple l =
| b::rest -> List.rev ((List.rev (b::bcc)@List.rev acc)@rest) (* We found the first non debug location *)
| [] -> List.rev acc (* This actually can never happen *) in
aux None [] (move_debug [] [] (List.rev l))

let expand_simple simple l =
let rec aux = function
| (Pbuiltin(EF_annot (kind, _, _),_,_) as annot)::rest ->
if P.to_int kind = 2 && lbl_follows rest then begin
simple annot; simple builtin_nop; aux rest
end else
simple annot; aux rest
| i::rest -> simple i; aux rest
| [] -> () in
aux l

let expand id sp preg simple l =
if !Clflags.option_g then
expand_debug id sp preg simple l
else
expand_simple simple l
6 changes: 3 additions & 3 deletions backend/Asmexpandaux.mli
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ val set_current_function: coq_function -> unit
(* Set the current function *)
val get_current_function: unit -> coq_function
(* Get the current function *)
val expand_debug: positive -> int -> (preg -> int) -> (instruction -> unit) -> instruction list -> unit
(* Expand builtin debug function. Takes the function id, the register number of the stackpointer, a
function to get the dwarf mapping of varibale names and for the expansion of simple instructions *)
val expand: positive -> int -> (preg -> int) -> (instruction -> unit) -> instruction list -> unit
(* Expand the instruction sequence of a function. Takes the function id, the register number of the stackpointer, a
function to get the dwarf mapping of varibale names and for the expansion of simple instructions *)
7 changes: 2 additions & 5 deletions powerpc/Asmexpand.ml
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ let expand_instruction instr =
expand_builtin_memcpy (Z.to_int sz) (Z.to_int al) args
| EF_annot_val(kind,txt, targ) ->
expand_annot_val kind txt targ args res
| EF_annot _ | EF_debug _ | EF_inline_asm _ ->
| EF_annot _ | EF_debug _ | EF_inline_asm _ ->
emit instr
| _ ->
assert false
Expand Down Expand Up @@ -932,10 +932,7 @@ let preg_to_dwarf = function
let expand_function id fn =
try
set_current_function fn;
if !Clflags.option_g then
expand_debug id 1 preg_to_dwarf expand_instruction fn.fn_code
else
List.iter expand_instruction fn.fn_code;
expand id 1 preg_to_dwarf expand_instruction fn.fn_code;
Errors.OK (get_current_function ())
with Error s ->
Errors.Error (Errors.msg (coqstring_of_camlstring s))
Expand Down
2 changes: 1 addition & 1 deletion powerpc/TargetPrinter.ml
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ module Target (System : SYSTEM):TARGET =
fprintf oc "%s annotation: %S\n" comment annot

| 2 -> let lbl = new_label () in
fprintf oc "%a: " label lbl;
fprintf oc "%a:\n" label lbl;
add_ais_annot lbl preg_annot "r1" (camlstring_of_coqstring txt) args
| _ -> assert false
end
Expand Down
4 changes: 3 additions & 1 deletion riscV/Asm.v
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,8 @@ Inductive instruction : Type :=
| Ploadsi (rd: freg) (f: float32) (**r load an immediate single *)
| Pbtbl (r: ireg) (tbl: list label) (**r N-way branch through a jump table *)
| Pbuiltin: external_function -> list (builtin_arg preg)
-> builtin_res preg -> instruction. (**r built-in function (pseudo) *)
-> builtin_res preg -> instruction (**r built-in function (pseudo) *)
| Pnop : instruction. (**r nop instruction *)


(** The pseudo-instructions are the following:
Expand Down Expand Up @@ -985,6 +986,7 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out
| Pfmsubd _ _ _ _
| Pfnmaddd _ _ _ _
| Pfnmsubd _ _ _ _
| Pnop
=> Stuck
end.

Expand Down
8 changes: 3 additions & 5 deletions riscV/Asmexpand.ml
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,8 @@ let expand_builtin_inline name args res =
(fun rl ->
emit (Pmulw (rl, X a, X b));
emit (Pmulhuw (rh, X a, X b)))

| "__builtin_nop", [], _ ->
emit Pnop
(* Catch-all *)
| _ ->
raise (Error ("unrecognized builtin " ^ name))
Expand Down Expand Up @@ -598,10 +599,7 @@ let preg_to_dwarf = function
let expand_function id fn =
try
set_current_function fn;
if !Clflags.option_g then
expand_debug id (* sp= *) 2 preg_to_dwarf expand_instruction fn.fn_code
else
List.iter expand_instruction fn.fn_code;
expand id (* sp= *) 2 preg_to_dwarf expand_instruction fn.fn_code;
Errors.OK (get_current_function ())
with Error s ->
Errors.Error (Errors.msg (coqstring_of_camlstring s))
Expand Down
4 changes: 3 additions & 1 deletion riscV/TargetPrinter.ml
Original file line number Diff line number Diff line change
Expand Up @@ -564,14 +564,16 @@ module Target : TARGET =
fprintf oc " jr x5\n";
jumptables := (lbl, tbl) :: !jumptables;
fprintf oc "%s end pseudoinstr btbl\n" comment
| Pnop ->
fprintf oc " nop\n"
| Pbuiltin(ef, args, res) ->
begin match ef with
| EF_annot(kind,txt, targs) ->
begin match (P.to_int kind) with
| 1 -> let annot = annot_text preg_annot "x2" (camlstring_of_coqstring txt) args in
fprintf oc "%s annotation: %S\n" comment annot
| 2 -> let lbl = new_label () in
fprintf oc "%a: " label lbl;
fprintf oc "%a:\n" label lbl;
add_ais_annot lbl preg_annot "x2" (camlstring_of_coqstring txt) args
| _ -> assert false
end
Expand Down
2 changes: 2 additions & 0 deletions x86/Asm.v
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ Inductive instruction: Type :=
| Pmovsb
| Pmovsw
| Pmovw_rm (rd: ireg) (ad: addrmode)
| Pnop
| Prep_movsl
| Psbbl_rr (rd: ireg) (r2: ireg)
| Psqrtsd (rd: freg) (r1: freg)
Expand Down Expand Up @@ -1001,6 +1002,7 @@ Definition exec_instr (f: function) (i: instruction) (rs: regset) (m: mem) : out
| Pmovsb
| Pmovsw
| Pmovw_rm _ _
| Pnop
| Prep_movsl
| Psbbl_rr _ _
| Psqrtsd _ _
Expand Down
7 changes: 2 additions & 5 deletions x86/Asmexpand.ml
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ let expand_builtin_inline name args res =
()
(* no operation *)
| "__builtin_nop", [], _ ->
emit (Pmov_rr (RAX,RAX))
emit Pnop
(* Catch-all *)
| _ ->
raise (Error ("unrecognized builtin " ^ name))
Expand Down Expand Up @@ -632,10 +632,7 @@ let preg_to_dwarf = function
let expand_function id fn =
try
set_current_function fn;
if !Clflags.option_g then
expand_debug id (int_reg_to_dwarf RSP) preg_to_dwarf expand_instruction fn.fn_code
else
List.iter expand_instruction fn.fn_code;
expand id (int_reg_to_dwarf RSP) preg_to_dwarf expand_instruction fn.fn_code;
Errors.OK (get_current_function ())
with Error s ->
Errors.Error (Errors.msg (coqstring_of_camlstring s))
Expand Down
4 changes: 3 additions & 1 deletion x86/TargetPrinter.ml
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,8 @@ module Target(System: SYSTEM):TARGET =
fprintf oc " movsw\n";
| Pmovw_rm (rd, a) ->
fprintf oc " movw %a, %a\n" addressing a ireg16 rd
| Pnop ->
fprintf oc " nop\n"
| Prep_movsl ->
fprintf oc " rep movsl\n"
| Psbbl_rr (res,a1) ->
Expand All @@ -814,7 +816,7 @@ module Target(System: SYSTEM):TARGET =
| 1 -> let annot = annot_text preg_annot "esp" (camlstring_of_coqstring txt) args in
fprintf oc "%s annotation: %S\n" comment annot
| 2 -> let lbl = new_label () in
fprintf oc "%a: \n" label lbl;
fprintf oc "%a:\n" label lbl;
let sp = if Archi.ptr64 then "rsp" else "esp" in
add_ais_annot lbl preg_ais_annot sp (camlstring_of_coqstring txt) args
| _ -> assert false
Expand Down

0 comments on commit 591073b

Please sign in to comment.