Skip to content

Commit ad69b97

Browse files
committed
generic
1 parent 1df5df0 commit ad69b97

File tree

13 files changed

+188
-96
lines changed

13 files changed

+188
-96
lines changed

src/cil.ml

Lines changed: 82 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ and typ =
277277

278278
| TBuiltin_va_list of attributes
279279
(** This is the same as the gcc's type with the same name *)
280+
| TDefault
280281

281282
(** Various kinds of integers *)
282283
and ikind =
@@ -546,9 +547,12 @@ and exp =
546547
* It is not printed. Given an lval of type
547548
* [TArray(T)] produces an expression of type
548549
* [TPtr(T)]. *)
550+
| Generic of exp * ((typ * exp) list)
549551

550552
and wstring_type = | Wchar_t | Char16_t | Char32_t
551553

554+
and encoding = No_encoding | Utf8
555+
552556
(** Literal constants *)
553557
and constant =
554558
| CInt64 of int64 * ikind * string option
@@ -557,7 +561,7 @@ and constant =
557561
* {!Cil.integer} or {!Cil.kinteger} to create these. Watch
558562
* out for integers that cannot be represented on 64 bits.
559563
* OCAML does not give Overflow exceptions. *)
560-
| CStr of string(** String constant (of pointer type) *)
564+
| CStr of string * encoding (** String constant (of pointer type) *)
561565
| CWStr of int64 list * wstring_type (** Wide string constant (of type "wchar_t *") *)
562566
| CChr of char (** Character constant. This has type int, so use
563567
* charConstToInt to read the value in case
@@ -1422,7 +1426,7 @@ type attributeClass =
14221426
let attributeHash: (string, attributeClass) H.t =
14231427
let table = H.create 13 in
14241428
List.iter (fun a -> H.add table a (AttrName false))
1425-
[ "section"; "constructor"; "destructor"; "unused"; "used"; "weak";
1429+
[ "section"; "constructor"; "destructor"; "unused"; "used"; "weak";
14261430
"no_instrument_function"; "alias"; "no_check_memory_usage";
14271431
"exception"; "model"; (* "restrict"; *)
14281432
"aconst"; "__asm__" (* Gcc uses this to specify the name to be used in
@@ -1436,8 +1440,8 @@ let attributeHash: (string, attributeClass) H.t =
14361440

14371441
List.iter (fun a -> H.add table a (AttrFunType false))
14381442
[ "format"; "regparm"; "longcall";
1439-
"noinline"; "always_inline"; "gnu_inline"; "leaf";
1440-
"artificial"; "warn_unused_result"; "nonnull"; "c_noreturn";
1443+
"noinline"; "always_inline"; "gnu_inline"; "leaf"; "c_noreturn";
1444+
"artificial"; "warn_unused_result"; "nonnull";
14411445
];
14421446

14431447
List.iter (fun a -> H.add table a (AttrFunType true))
@@ -1532,6 +1536,7 @@ let rec typeAttrs = function
15321536
| TEnum (enum, a) -> addAttributes enum.eattr a
15331537
| TFun (_, _, _, a) -> a
15341538
| TBuiltin_va_list a -> a
1539+
| TDefault -> []
15351540

15361541

15371542
let setTypeAttrs t a =
@@ -1546,6 +1551,7 @@ let setTypeAttrs t a =
15461551
| TEnum (enum, _) -> TEnum (enum, a)
15471552
| TFun (r, args, v, _) -> TFun(r,args,v,a)
15481553
| TBuiltin_va_list _ -> TBuiltin_va_list a
1554+
| TDefault -> TDefault
15491555

15501556

15511557
let typeAddAttributes a0 t =
@@ -1568,6 +1574,7 @@ begin
15681574
| TComp (comp, a) -> TComp (comp, add a)
15691575
| TNamed (t, a) -> TNamed (t, add a)
15701576
| TBuiltin_va_list a -> TBuiltin_va_list (add a)
1577+
| TDefault -> TDefault
15711578
end
15721579

15731580
let typeRemoveAttributes (anl: string list) t =
@@ -1583,6 +1590,7 @@ let typeRemoveAttributes (anl: string list) t =
15831590
| TComp (comp, a) -> TComp (comp, drop a)
15841591
| TNamed (t, a) -> TNamed (t, drop a)
15851592
| TBuiltin_va_list a -> TBuiltin_va_list (drop a)
1593+
| TDefault -> TDefault
15861594

15871595
let unrollType (t: typ) : typ =
15881596
let rec withAttrs (al: attributes) (t: typ) : typ =
@@ -1652,7 +1660,7 @@ let getComplexFkind = function
16521660
let var vi : lval = (Var vi, NoOffset)
16531661
(* let assign vi e = Instrs(Set (var vi, e), lu) *)
16541662

1655-
let mkString s = Const(CStr s)
1663+
let mkString s = Const(CStr (s, No_encoding))
16561664

16571665

16581666
let mkWhile ~(guard:exp) ~(body: stmt list) : stmt list =
@@ -1790,7 +1798,7 @@ let d_const () c =
17901798
text (prefix ^ (Int64.to_string i ^ suffix))
17911799
)
17921800

1793-
| CStr(s) -> text ("\"" ^ escape_string s ^ "\"")
1801+
| CStr(s, enc) -> let prefix = match enc with No_encoding -> "" | Utf8 -> "u8" in text (prefix ^ "\"" ^ escape_string s ^ "\"")
17941802
| CWStr(s, st) ->
17951803
(* text ("L\"" ^ escape_string s ^ "\"") *)
17961804
let prefix = match st with Wchar_t -> "L" | Char16_t -> "u" | Char32_t -> "U" in
@@ -1872,6 +1880,7 @@ let getParenthLevel (e: exp) =
18721880

18731881
| Lval(Var _, NoOffset) -> 0 (* Plain variables *)
18741882
| Const _ -> 0 (* Constants *)
1883+
| Generic _ -> 0 (*TODO*)
18751884

18761885

18771886
let getParenthLevelAttrParam (a: attrparam) =
@@ -1945,7 +1954,7 @@ let rec typeOf (e: exp) : typ =
19451954
(* The type of a string is a pointer to characters ! The only case when
19461955
* you would want it to be an array is as an argument to sizeof, but we
19471956
* have SizeOfStr for that *)
1948-
| Const(CStr s) -> !stringLiteralType
1957+
| Const(CStr (_, _)) -> !stringLiteralType
19491958

19501959
| Const(CWStr (s,st)) -> TPtr((match st with Wchar_t -> !wcharType | Char16_t -> !char16Type | Char32_t -> !char32Type), [])
19511960

@@ -1968,6 +1977,7 @@ let rec typeOf (e: exp) : typ =
19681977
TArray (t,_, a) -> TPtr(t, a)
19691978
| _ -> E.s (E.bug "typeOf: StartOf on a non-array")
19701979
end
1980+
| Generic (e, lst) -> match lst with (t, e1) :: rest -> typeOf e1 | _ -> voidType
19711981

19721982
and typeOfInit (i: init) : typ =
19731983
match i with
@@ -2257,6 +2267,7 @@ let rec alignOf_int t =
22572267

22582268
| TFun _ as t -> raise (SizeOfError ("function", t))
22592269
| TVoid _ as t -> raise (SizeOfError ("void", t))
2270+
| TDefault -> raise (SizeOfError ("default", t))
22602271
in
22612272
match filterAttributes "aligned" (typeAttrs t) @ filterAttributes "alignas" (typeAttrs t) with
22622273
[] ->
@@ -2266,25 +2277,46 @@ let rec alignOf_int t =
22662277
ignore (warn "ignoring recursive align attributes on %a"
22672278
(!pd_type) t);
22682279
alignOfType ()
2269-
| (Attr(_, [a]) as at)::rest -> begin
2270-
if rest <> [] then
2271-
ignore (warn "ignoring duplicate align attributes on %a"
2272-
(!pd_type) t);
2273-
match intOfAttrparam a with
2274-
| Some 0 -> alignOfType ()
2280+
| (Attr(_, [a]) as at)::rest ->
2281+
let is_power_of_two n =
2282+
let log2 = (log10 (float_of_int n)) /. (log10 2.) in
2283+
ceil log2 = floor log2
2284+
in
2285+
let rec strictest_alignment (current:int) (lst:attribute list) =
2286+
match lst with
2287+
[] -> current
2288+
| (Attr(_, [a]) as at)::rest -> begin
2289+
match intOfAttrparam a with
2290+
Some 0 -> strictest_alignment current rest
2291+
| Some n ->
2292+
if not (is_power_of_two n) then begin
2293+
ignore(warn "Invalid alignment value specified by attribute %a\n" (!pd_attr) at);
2294+
strictest_alignment current rest
2295+
end
2296+
else strictest_alignment (max current n) rest
2297+
| None ->
2298+
ignore (warn "alignment attribute \"%a\" not understood on %a" (!pd_attr) at (!pd_type) t);
2299+
strictest_alignment current rest
2300+
end
2301+
| Attr(_, []) :: rest ->
2302+
!M.theMachine.M.alignof_aligned
2303+
| at ::_ ->
2304+
ignore (warn "alignment attribute \"%a\" not understood on %a"
2305+
(!pd_attr) at (!pd_type) t);
2306+
strictest_alignment current rest
2307+
in
2308+
let current = match intOfAttrparam a with
2309+
Some 0 -> alignOfType ()
22752310
| Some n ->
2276-
let is_power_of_two n =
2277-
let log2 = (log10 (float_of_int n)) /. (log10 2.) in
2278-
ceil log2 = floor log2
2279-
in
22802311
if not (is_power_of_two n) then
22812312
alignOfType (ignore(warn "Invalid alignment value specified by attribute %a\n" (!pd_attr) at))
22822313
else n
22832314
| None ->
2284-
ignore (warn "alignment attribute \"%a\" not understood on %a"
2285-
(!pd_attr) at (!pd_type) t);
2286-
alignOfType ()
2287-
end
2315+
ignore (warn "alignment attribute \"%a\" not understood on %a"
2316+
(!pd_attr) at (!pd_type) t);
2317+
alignOfType ()
2318+
in
2319+
strictest_alignment current rest
22882320
| Attr(_, [])::rest ->
22892321
(* aligned with no arg means a power of two at least as large as
22902322
any alignment on the system.*)
@@ -2579,6 +2611,7 @@ and bitsSizeOf t =
25792611
0
25802612

25812613
| TFun _ -> raise (SizeOfError ("function", t))
2614+
| TDefault -> raise (SizeOfError("default", t))
25822615

25832616

25842617
and addTrailing nrbits roundto =
@@ -2856,6 +2889,8 @@ let rec isConstant = function
28562889
| AddrOf (Mem e, off) | StartOf(Mem e, off)
28572890
-> isConstant e && isConstantOffset off
28582891
| AddrOfLabel _ -> true
2892+
| Generic _ -> false (*TODO*)
2893+
28592894
and isConstantOffset = function
28602895
NoOffset -> true
28612896
| Field(fi, off) -> isConstantOffset off
@@ -3535,7 +3570,7 @@ class defaultCilPrinterClass : cilPrinter = object (self)
35353570
| Real e ->
35363571
text "__real__(" ++ self#pExp () e ++ chr ')'
35373572
| SizeOfStr s ->
3538-
text "sizeof(" ++ d_const () (CStr s) ++ chr ')'
3573+
text "sizeof(" ++ d_const () (CStr (s, No_encoding)) ++ chr ')'
35393574

35403575
| AlignOf (t) ->
35413576
text "__alignof__(" ++ self#pType None () t ++ chr ')'
@@ -3563,6 +3598,14 @@ class defaultCilPrinterClass : cilPrinter = object (self)
35633598

35643599
| StartOf(lv) -> self#pLval () lv
35653600

3601+
| Generic(e, lst) ->
3602+
let rec print_generic_exp l doc =
3603+
match l with
3604+
| [] -> doc
3605+
| (t, e1) :: rest -> print_generic_exp rest (doc ++ text ", " ++ (self#pType None () t) ++ text ":" ++ self#pExp () e1)
3606+
in
3607+
text "_Generic(" ++ self#pExp () e ++ print_generic_exp lst nil ++ text ")"
3608+
35663609
(* Print an expression, given the precedence of the context in which it
35673610
* appears. *)
35683611
method private pExpPrec (contextprec: int) () (e: exp) =
@@ -4499,6 +4542,7 @@ class defaultCilPrinterClass : cilPrinter = object (self)
44994542
++ self#pAttrs () a
45004543
++ text " "
45014544
++ name
4545+
| TDefault -> text "default"
45024546

45034547

45044548
(**** PRINTING ATTRIBUTES *********)
@@ -4842,6 +4886,7 @@ class plainCilPrinterClass =
48424886
end
48434887
| TBuiltin_va_list a ->
48444888
dprintf "TBuiltin_va_list(%a)" self#pAttrs a
4889+
| TDefault -> dprintf "TDefault"
48454890

48464891

48474892
(* Some plain pretty-printers. Unlike the above these expose all the
@@ -4856,8 +4901,9 @@ class plainCilPrinterClass =
48564901
(Int64.format fmt i)
48574902
d_ikind ik
48584903
(match so with Some s -> s | _ -> "None")
4859-
| CStr(s) ->
4860-
text ("CStr(\"" ^ escape_string s ^ "\")")
4904+
| CStr(s, enc) ->
4905+
let enc_string = match enc with No_encoding -> "_" | Utf8 -> "UTF8" in
4906+
text ("CStr(\"" ^ escape_string s ^ "\"," ^ enc_string ^ ")")
48614907
| CWStr(s,_) ->
48624908
dprintf "CWStr(%a)" d_const c
48634909

@@ -4908,7 +4954,7 @@ class plainCilPrinterClass =
49084954
| SizeOfE (e) ->
49094955
text "sizeofE(" ++ self#pExp () e ++ chr ')'
49104956
| SizeOfStr (s) ->
4911-
text "sizeofStr(" ++ d_const () (CStr s) ++ chr ')'
4957+
text "sizeofStr(" ++ d_const () (CStr (s, No_encoding)) ++ chr ')'
49124958
| AlignOf (t) ->
49134959
text "__alignof__(" ++ self#pType None () t ++ chr ')'
49144960
| AlignOfE (e) ->
@@ -4924,6 +4970,13 @@ class plainCilPrinterClass =
49244970
| StartOf lv -> dprintf "StartOf(%a)" self#pLval lv
49254971
| AddrOf (lv) -> dprintf "AddrOf(%a)" self#pLval lv
49264972
| AddrOfLabel (sref) -> dprintf "AddrOfLabel(%a)" self#pStmt !sref
4973+
| Generic(e, lst) ->
4974+
let rec print_generic_exp l doc =
4975+
match l with
4976+
| [] -> doc
4977+
| (t, e1) :: rest -> print_generic_exp rest (doc ++ text "," ++ (self#pType None () t) ++ text ":" ++ self#pExp () e1)
4978+
in
4979+
text "_Generic(" ++ self#pExp () e ++ text "," ++ print_generic_exp lst nil
49274980

49284981

49294982

@@ -5444,6 +5497,8 @@ and childrenExp (vis: cilVisitor) (e: exp) : exp =
54445497
| StartOf lv ->
54455498
let lv' = vLval lv in
54465499
if lv' != lv then StartOf lv' else e
5500+
| Generic(e, lst) -> e (*TODO*)
5501+
54475502

54485503
and visitCilInit (vis: cilVisitor) (forglob: varinfo)
54495504
(atoff: offset) (i: init) : init =
@@ -6235,6 +6290,7 @@ let rec typeSigWithAttrs ?(ignoreSign=false) doattr t =
62356290
TSFun(typeSig rt, (Util.list_map_opt (fun (_, atype, _) -> (typeSig atype)) args), isva, doattr a)
62366291
| TNamed(t, a) -> typeSigAddAttrs (doattr a) (typeSig t.ttype)
62376292
| TBuiltin_va_list al -> TSBase (TBuiltin_va_list (doattr al))
6293+
| TDefault -> TSBase (TDefault)
62386294

62396295
let typeSig t =
62406296
typeSigWithAttrs (fun al -> al) t
@@ -6262,7 +6318,7 @@ let typeSigAttrs = function
62626318

62636319

62646320
let dExp: doc -> exp =
6265-
fun d -> Const(CStr(sprint ~width:!lineLength d))
6321+
fun d -> Const(CStr(sprint ~width:!lineLength d, No_encoding))
62666322

62676323
let dInstr: doc -> location -> instr =
62686324
fun d l -> Asm([], [sprint ~width:!lineLength d], [], [], [], l)

src/cil.mli

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ and typ =
242242

243243
| TBuiltin_va_list of attributes
244244
(** This is the same as the gcc's type with the same name *)
245+
| TDefault
245246

246247
(**
247248
There are a number of functions for querying the kind of a type. These are
@@ -640,11 +641,14 @@ and exp =
640641
* not sure which one to use. In C this operation is implicit, the
641642
* [StartOf] operator is not printed. We have it in CIL because it makes
642643
* the typing rules simpler. *)
644+
| Generic of exp * ((typ * exp) list)
643645

644646
(** {b Constants.} *)
645647

646648
and wstring_type = | Wchar_t | Char16_t | Char32_t
647649

650+
and encoding = No_encoding | Utf8
651+
648652
(** Literal constants *)
649653
and constant =
650654
| CInt64 of int64 * ikind * string option
@@ -653,7 +657,7 @@ and constant =
653657
* constant as, for example, 0xF instead of 15.) Use {!Cil.integer} or
654658
* {!Cil.kinteger} to create these. Watch out for integers that cannot be
655659
* represented on 64 bits. OCAML does not give Overflow exceptions. *)
656-
| CStr of string
660+
| CStr of string * encoding
657661
(** String constant. The escape characters inside the string have been
658662
* already interpreted. This constant has pointer to character type! The
659663
* only case when you would like a string literal to have an array type

src/ext/ccl/ccl.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1055,7 +1055,7 @@ let rec evaluateExp (e : exp) (state : state) : summary =
10551055
end;
10561056
SFacts tFacts
10571057
end
1058-
| Const (CStr s) ->
1058+
| Const (CStr (s, _)) ->
10591059
SFacts (FactSet.singleton ("*", ANT 0))
10601060
| Const _ ->
10611061
begin

src/ext/cqualann/cqualann.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,10 @@ class stringVisitor
300300

301301
method! vexpr e = begin
302302
match e with
303-
Const(CStr s) ->
303+
Const(CStr (s, _)) ->
304304
(* ignore (E.log "String without cast: %a\n" d_plainexp e); *)
305305
ChangeTo(global4String s false)
306-
| CastE(t, Const(CStr s)) ->
306+
| CastE(t, Const(CStr (s, _))) ->
307307
let taint = baseTypeContainsSmallocAttribute t in
308308
(* ignore (E.log "%stainted String: %a\n" *)
309309
(* (if taint then "" else "Un") d_plainexp e); *)

src/ext/llvm/llvmgen.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ class llvmGeneratorClass : llvmGenerator = object (self)
589589
method mkConstant (c:constant) : llvmValue =
590590
match c with
591591
| CInt64 (i, ik, _) -> LInt (i, ik)
592-
| CStr s -> LGetelementptr [ LGlobal (self#addString s); lzerop; lzerop ]
592+
| CStr (s, _) -> LGetelementptr [ LGlobal (self#addString s); lzerop; lzerop ]
593593
| CWStr (ws,_) -> LGetelementptr [ LGlobal (self#addWString ws); lzerop; lzerop ]
594594
| CChr c -> LInt (Int64.of_int (Char.code c), IInt)
595595
| CReal (f, fk, _) -> LFloat (f, fk)

src/ext/pta/ptranal.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ and analyze_expr_as_lval (e : exp) : A.lvalue =
231231
and analyze_expr (e : exp ) : A.tau =
232232
let result =
233233
match e with
234-
Const (CStr s) ->
234+
Const (CStr (s, _)) ->
235235
if !model_strings then
236236
A.address (A.make_lvalue
237237
false

src/formatparse.mly

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,11 +560,11 @@ constant:
560560
| ARG_g { let currentArg = $1 in
561561
((fun args ->
562562
match getArg currentArg args with
563-
Fg s -> Const(CStr s)
563+
Fg s -> Const(CStr (s, No_encoding))
564564
| a -> wrongArgType currentArg "string" a),
565565

566566
fun e -> match e with
567-
Const(CStr s) ->
567+
Const(CStr (s, _)) ->
568568
Some [ Fg s ]
569569
| _ -> None)
570570
}

0 commit comments

Comments
 (0)