aboutsummaryrefslogtreecommitdiffstats
path: root/cfrontend/C2C.ml
diff options
context:
space:
mode:
Diffstat (limited to 'cfrontend/C2C.ml')
-rw-r--r--cfrontend/C2C.ml239
1 files changed, 143 insertions, 96 deletions
diff --git a/cfrontend/C2C.ml b/cfrontend/C2C.ml
index ef028255..3c71718c 100644
--- a/cfrontend/C2C.ml
+++ b/cfrontend/C2C.ml
@@ -6,10 +6,11 @@
(* *)
(* Copyright Institut National de Recherche en Informatique et en *)
(* Automatique. All rights reserved. This file is distributed *)
-(* under the terms of the GNU General Public License as published by *)
-(* the Free Software Foundation, either version 2 of the License, or *)
-(* (at your option) any later version. This file is also distributed *)
-(* under the terms of the INRIA Non-Commercial License Agreement. *)
+(* under the terms of the GNU Lesser General Public License as *)
+(* published by the Free Software Foundation, either version 2.1 of *)
+(* the License, or (at your option) any later version. *)
+(* This file is also distributed under the terms of the *)
+(* INRIA Non-Commercial License Agreement. *)
(* *)
(* *********************************************************************)
@@ -252,83 +253,11 @@ let builtins_generic = {
(TVoid [],
[TPtr(TVoid [], [])],
false);
- "__compcert_va_int32",
- (TInt(IUInt, []),
- [TPtr(TVoid [], [])],
- false);
- "__compcert_va_int64",
- (TInt(IULongLong, []),
- [TPtr(TVoid [], [])],
- false);
- "__compcert_va_float64",
- (TFloat(FDouble, []),
- [TPtr(TVoid [], [])],
- false);
- "__compcert_va_composite",
- (TPtr(TVoid [], []),
- [TPtr(TVoid [], []); TInt(IULong, [])],
- false);
- (* Helper functions for int64 arithmetic *)
- "__compcert_i64_dtos",
- (TInt(ILongLong, []),
- [TFloat(FDouble, [])],
- false);
- "__compcert_i64_dtou",
- (TInt(IULongLong, []),
- [TFloat(FDouble, [])],
- false);
- "__compcert_i64_stod",
- (TFloat(FDouble, []),
- [TInt(ILongLong, [])],
- false);
- "__compcert_i64_utod",
- (TFloat(FDouble, []),
- [TInt(IULongLong, [])],
- false);
- "__compcert_i64_stof",
- (TFloat(FFloat, []),
- [TInt(ILongLong, [])],
- false);
- "__compcert_i64_utof",
- (TFloat(FFloat, []),
- [TInt(IULongLong, [])],
- false);
- "__compcert_i64_sdiv",
- (TInt(ILongLong, []),
- [TInt(ILongLong, []); TInt(ILongLong, [])],
- false);
- "__compcert_i64_udiv",
- (TInt(IULongLong, []),
- [TInt(IULongLong, []); TInt(IULongLong, [])],
- false);
- "__compcert_i64_smod",
- (TInt(ILongLong, []),
- [TInt(ILongLong, []); TInt(ILongLong, [])],
- false);
- "__compcert_i64_umod",
- (TInt(IULongLong, []),
- [TInt(IULongLong, []); TInt(IULongLong, [])],
- false);
- "__compcert_i64_shl",
- (TInt(ILongLong, []),
- [TInt(ILongLong, []); TInt(IInt, [])],
- false);
- "__compcert_i64_shr",
- (TInt(IULongLong, []),
- [TInt(IULongLong, []); TInt(IInt, [])],
- false);
- "__compcert_i64_sar",
- (TInt(ILongLong, []),
- [TInt(ILongLong, []); TInt(IInt, [])],
- false);
- "__compcert_i64_smulh",
- (TInt(ILongLong, []),
- [TInt(ILongLong, []); TInt(ILongLong, [])],
- false);
- "__compcert_i64_umulh",
- (TInt(IULongLong, []),
- [TInt(IULongLong, []); TInt(IULongLong, [])],
- false)
+ (* Optimization hints *)
+ "__builtin_unreachable",
+ (TVoid [], [], false);
+ "__builtin_expect",
+ (TInt(ILong, []), [TInt(ILong, []); TInt(ILong, [])], false)
]
}
@@ -552,10 +481,16 @@ let convertAttr a =
let n = Cutil.alignas_attribute a in
if n > 0 then Some (N.of_int (log2 n)) else None }
-let convertCallconv va unproto attr =
+let convertCallconv _tres targs va attr =
+ let vararg =
+ match targs with
+ | None -> None
+ | Some tl -> if va then Some (Z.of_uint (List.length tl)) else None in
let sr =
Cutil.find_custom_attributes ["structreturn"; "__structreturn"] attr in
- { AST.cc_vararg = va; cc_unproto = unproto; cc_structret = sr <> [] }
+ { AST.cc_vararg = vararg;
+ AST.cc_unproto = (targs = None);
+ AST.cc_structret = (sr <> []) }
(** Types *)
@@ -600,7 +535,7 @@ let checkFunctionType env tres targs =
end
end
-let rec convertTyp env t =
+let rec convertTyp env ?bitwidth t =
match t with
| C.TVoid a -> Tvoid
| C.TInt(ik, a) ->
@@ -623,7 +558,7 @@ let rec convertTyp env t =
| Some tl -> convertParams env tl
end,
convertTyp env tres,
- convertCallconv va (targs = None) a)
+ convertCallconv tres targs va a)
| C.TNamed _ ->
convertTyp env (Cutil.unroll env t)
| C.TStruct(id, a) ->
@@ -631,7 +566,21 @@ let rec convertTyp env t =
| C.TUnion(id, a) ->
Tunion(intern_string id.name, convertAttr a)
| C.TEnum(id, a) ->
- convertIkind Cutil.enum_ikind (convertAttr a)
+ let ik =
+ match bitwidth with
+ | None -> Cutil.enum_ikind
+ | Some w ->
+ let info = Env.find_enum env id in
+ let representable sg =
+ List.for_all (fun (_, v, _) -> Cutil.int_representable v w sg)
+ info.Env.ei_members in
+ if representable false then
+ Cutil.unsigned_ikind_of Cutil.enum_ikind
+ else if representable true then
+ Cutil.signed_ikind_of Cutil.enum_ikind
+ else
+ Cutil.enum_ikind in
+ convertIkind ik (convertAttr a)
and convertParams env = function
| [] -> Tnil
@@ -667,9 +616,16 @@ let rec convertTypAnnotArgs env = function
convertTypAnnotArgs env el)
let convertField env f =
- if f.fld_bitfield <> None then
- unsupported "bit field in struct or union (consider adding option [-fbitfields])";
- (intern_string f.fld_name, convertTyp env f.fld_typ)
+ let id = intern_string f.fld_name
+ and ty = convertTyp env ?bitwidth: f.fld_bitfield f.fld_typ in
+ match f.fld_bitfield with
+ | None -> Member_plain(id, ty)
+ | Some w ->
+ match ty with
+ | Tint(sz, sg, attr) ->
+ Member_bitfield(id, sz, sg, attr, Z.of_uint w, f.fld_name = "")
+ | _ ->
+ fatal_error "bitfield must have type int"
let convertCompositedef env su id attr members =
if Cutil.find_custom_attributes ["packed";"__packed__"] attr <> [] then
@@ -772,6 +728,11 @@ let convertFloat f kind =
(** Expressions *)
+let check_volatile_bitfield env e =
+ if Cutil.is_bitfield env e
+ && List.mem AVolatile (Cutil.attributes_of_type env e.etyp) then
+ warning Diagnostics.Unnamed "access to a volatile bit field, the 'volatile' qualifier is ignored"
+
let ezero = Eval(Vint(coqint_of_camlint 0l), type_int32s)
let ewrap = function
@@ -786,6 +747,7 @@ let rec convertExpr env e =
| C.EUnop((C.Oderef|C.Odot _|C.Oarrow _), _)
| C.EBinop(C.Oindex, _, _, _) ->
let l = convertLvalue env e in
+ check_volatile_bitfield env e;
ewrap (Ctyping.evalof l)
| C.EConst(C.CInt(i, k, _)) ->
@@ -855,6 +817,7 @@ let rec convertExpr env e =
if Cutil.is_composite_type env e2.etyp
&& List.mem AVolatile (Cutil.attributes_of_type env e2.etyp) then
warning Diagnostics.Unnamed "assignment of a value of volatile composite type, the 'volatile' qualifier is ignored";
+ check_volatile_bitfield env e1;
ewrap (Ctyping.eassign e1' e2')
| C.EBinop((C.Oadd_assign|C.Osub_assign|C.Omul_assign|C.Odiv_assign|
C.Omod_assign|C.Oand_assign|C.Oor_assign|C.Oxor_assign|
@@ -875,6 +838,7 @@ let rec convertExpr env e =
| _ -> assert false in
let e1' = convertLvalue env e1 in
let e2' = convertExpr env e2 in
+ check_volatile_bitfield env e1;
ewrap (Ctyping.eassignop op' e1' e2')
| C.EBinop(C.Ocomma, e1, e2, _) ->
ewrap (Ctyping.ecomma (convertExpr env e1) (convertExpr env e2))
@@ -983,13 +947,16 @@ let rec convertExpr env e =
ewrap (Ctyping.eselection (convertExpr env arg1)
(convertExpr env arg2) (convertExpr env arg3))
+ | C.ECall({edesc = C.EVar {name = "__builtin_expect"}}, [arg1; arg2]) ->
+ convertExpr env arg1
+
| C.ECall({edesc = C.EVar {name = "printf"}}, args)
when !Clflags.option_interp ->
let targs = convertTypArgs env [] args
and tres = convertTyp env e.etyp in
let sg =
signature_of_type targs tres
- { AST.cc_vararg = true; cc_unproto = false; cc_structret = false} in
+ { AST.cc_vararg = Some (coqint_of_camlint 1l); cc_unproto = false; cc_structret = false} in
Ebuiltin( AST.EF_external(coqstring_of_camlstring "printf", sg),
targs, convertExprList env args, tres)
@@ -1256,7 +1223,8 @@ let convertFundef loc env fd =
a_loc = loc };
(id', AST.Gfun(Ctypes.Internal
{fn_return = ret;
- fn_callconv = convertCallconv fd.fd_vararg false fd.fd_attrib;
+ fn_callconv = convertCallconv fd.fd_ret (Some fd.fd_params)
+ fd.fd_vararg fd.fd_attrib;
fn_params = params;
fn_vars = vars;
fn_body = body'}))
@@ -1264,7 +1232,6 @@ let convertFundef loc env fd =
(** External function declaration *)
let re_builtin = Str.regexp "__builtin_"
-let re_runtime = Str.regexp "__compcert_i64_"
let convertFundecl env (sto, id, ty, optinit) =
let (args, res, cconv) =
@@ -1277,7 +1244,6 @@ let convertFundecl env (sto, id, ty, optinit) =
let ef =
if id.name = "malloc" then AST.EF_malloc else
if id.name = "free" then AST.EF_free else
- if Str.string_match re_runtime id.name 0 then AST.EF_runtime(id'', sg) else
if Str.string_match re_builtin id.name 0
&& List.mem_assoc id.name builtins.builtin_functions
then AST.EF_builtin(id'', sg)
@@ -1326,8 +1292,13 @@ let convertGlobvar loc env (sto, id, ty, optinit) =
if sto = C.Storage_extern then [] else [AST.Init_space sz]
| Some i ->
convertInitializer env ty i in
+ let initialized =
+ if optinit = None then Sections.Uninit else
+ if List.exists (function AST.Init_addrof _ -> true | _ -> false) init'
+ then Sections.Init_reloc
+ else Sections.Init in
let (section, access) =
- Sections.for_variable env loc id' ty (optinit <> None) in
+ Sections.for_variable env loc id' ty initialized in
if Z.gt sz (Z.of_uint64 0xFFFF_FFFFL) then
error "'%s' is too big (%s bytes)"
id.name (Z.to_string sz);
@@ -1394,6 +1365,81 @@ let rec convertCompositedefs env res gl =
| _ ->
convertCompositedefs env res gl'
+(** Add declarations for the helper functions
+ (for varargs and for int64 arithmetic) *)
+
+let helper_functions () = [
+ "__compcert_va_int32",
+ Tint(I32, Unsigned, noattr),
+ [Tpointer(Tvoid, noattr)];
+ "__compcert_va_int64",
+ Tlong(Unsigned, noattr),
+ [Tpointer(Tvoid, noattr)];
+ "__compcert_va_float64",
+ Tfloat(F64, noattr),
+ [Tpointer(Tvoid, noattr)];
+ "__compcert_va_composite",
+ Tpointer(Tvoid, noattr),
+ [Tpointer(Tvoid, noattr); convertIkind (Cutil.size_t_ikind()) noattr];
+ "__compcert_i64_dtos",
+ Tlong(Signed, noattr),
+ [Tfloat(F64, noattr)];
+ "__compcert_i64_dtou",
+ Tlong(Unsigned, noattr),
+ [Tfloat(F64, noattr)];
+ "__compcert_i64_stod",
+ Tfloat(F64, noattr),
+ [Tlong(Signed, noattr)];
+ "__compcert_i64_utod",
+ Tfloat(F64, noattr),
+ [Tlong(Unsigned, noattr)];
+ "__compcert_i64_stof",
+ Tfloat(F32, noattr),
+ [Tlong(Signed, noattr)];
+ "__compcert_i64_utof",
+ Tfloat(F32, noattr),
+ [Tlong(Unsigned, noattr)];
+ "__compcert_i64_sdiv",
+ Tlong(Signed, noattr),
+ [Tlong(Signed, noattr); Tlong(Signed, noattr)];
+ "__compcert_i64_udiv",
+ Tlong(Unsigned, noattr),
+ [Tlong(Unsigned, noattr); Tlong(Unsigned, noattr)];
+ "__compcert_i64_smod",
+ Tlong(Signed, noattr),
+ [Tlong(Signed, noattr); Tlong(Signed, noattr)];
+ "__compcert_i64_umod",
+ Tlong(Unsigned, noattr),
+ [Tlong(Unsigned, noattr); Tlong(Unsigned, noattr)];
+ "__compcert_i64_shl",
+ Tlong(Signed, noattr),
+ [Tlong(Signed, noattr); Tint(I32, Signed, noattr)];
+ "__compcert_i64_shr",
+ Tlong(Unsigned, noattr),
+ [Tlong(Unsigned, noattr); Tint(I32, Signed, noattr)];
+ "__compcert_i64_sar",
+ Tlong(Signed, noattr),
+ [Tlong(Signed, noattr); Tint(I32, Signed, noattr)];
+ "__compcert_i64_smulh",
+ Tlong(Signed, noattr),
+ [Tlong(Signed, noattr); Tlong(Signed, noattr)];
+ "__compcert_i64_umulh",
+ Tlong(Unsigned, noattr),
+ [Tlong(Unsigned, noattr); Tlong(Unsigned, noattr)]
+]
+
+let helper_function_declaration (name, tyres, tyargs) =
+ let tyargs =
+ List.fold_right (fun t tl -> Tcons(t, tl)) tyargs Tnil in
+ let ef =
+ AST.EF_runtime(coqstring_of_camlstring name,
+ signature_of_type tyargs tyres AST.cc_default) in
+ (intern_string name,
+ AST.Gfun (Ctypes.External(ef, tyargs, tyres, AST.cc_default)))
+
+let add_helper_functions globs =
+ List.map helper_function_declaration (helper_functions()) @ globs
+
(** Build environment of typedefs, structs, unions and enums *)
let rec translEnv env = function
@@ -1491,10 +1537,11 @@ let convertProgram p =
comp_env := ce;
let gl1 = convertGlobdecls env [] p in
let gl2 = globals_for_strings gl1 in
+ let gl3 = add_helper_functions gl2 in
comp_env := Maps.PTree.empty;
let p' =
- { prog_defs = gl2;
- prog_public = public_globals gl2;
+ { prog_defs = gl3;
+ prog_public = public_globals gl3;
prog_main = intern_string !Clflags.main_function_name;
prog_types = typs;
prog_comp_env = ce } in