160
160
opts = [] :: [compile :option ()], % Options.
161
161
dialyzer = false :: boolean (), % Help dialyzer or not.
162
162
ws = [] :: [warning ()], % Warnings.
163
- file = [{file ," " }] % File.
163
+ file = [{file ," " }], % File.
164
+ load_nif = false :: boolean () % true if calls erlang:load_nif/2
164
165
}).
165
166
166
167
% % XXX: The following type declarations do not belong in this module
171
172
172
173
-record (imodule , {name = [],
173
174
exports = ordsets :new (),
174
- nifs = sets :new ([{version , 2 }]),
175
+ nifs = none ::
176
+ 'none' | sets :set (), % Is a set if the attribute is
177
+ % present in the module.
175
178
attrs = [],
176
179
defs = [],
177
180
file = [],
178
181
opts = [],
179
- ws = []}).
182
+ ws = [],
183
+ load_nif = false :: boolean () % true if calls erlang:load_nif/2
184
+ }).
180
185
181
186
-spec module ([form ()], [compile :option ()]) ->
182
187
{'ok' ,cerl :c_module (),[warning ()]}.
@@ -186,19 +191,28 @@ module(Forms0, Opts) ->
186
191
Module = foldl (fun (F , Acc ) ->
187
192
form (F , Acc , Opts )
188
193
end , # imodule {}, Forms ),
189
- # imodule {name = Mod ,exports = Exp0 ,attrs = As0 ,defs = Kfs0 ,ws = Ws } = Module ,
194
+ # imodule {name = Mod ,exports = Exp0 ,attrs = As0 ,
195
+ defs = Kfs0 ,ws = Ws ,load_nif = LoadNif ,nifs = Nifs } = Module ,
190
196
Exp = case member (export_all , Opts ) of
191
197
true -> defined_functions (Forms );
192
198
false -> Exp0
193
199
end ,
194
200
Cexp = [# c_var {name = FA } || {_ ,_ }= FA <- Exp ],
201
+ Kfs1 = reverse (Kfs0 ),
202
+ Kfs = if LoadNif and (Nifs =:= none ) ->
203
+ insert_nif_start (Kfs1 );
204
+ true ->
205
+ Kfs1
206
+ end ,
195
207
As = reverse (As0 ),
196
- Kfs = reverse ( Kfs0 ),
208
+
197
209
{ok ,# c_module {name = # c_literal {val = Mod },exports = Cexp ,attrs = As ,defs = Kfs },Ws }.
198
210
199
- form ({function ,_ ,_ ,_ ,_ }= F0 , # imodule {defs = Defs }= Module , Opts ) ->
200
- {F ,Ws } = function (F0 , Module , Opts ),
201
- Module # imodule {defs = [F |Defs ],ws = Ws };
211
+ form ({function ,_ ,_ ,_ ,_ }= F0 ,
212
+ # imodule {defs = Defs ,load_nif = LoadNif0 }= Module ,
213
+ Opts ) ->
214
+ {F ,Ws ,LoadNif } = function (F0 , Module , Opts ),
215
+ Module # imodule {defs = [F |Defs ],ws = Ws ,load_nif = LoadNif or LoadNif0 };
202
216
form ({attribute ,_ ,module ,Mod }, Module , _Opts ) ->
203
217
true = is_atom (Mod ),
204
218
Module # imodule {name = Mod };
@@ -211,7 +225,13 @@ form({attribute,_,export,Es}, #imodule{exports=Exp0}=Module, _Opts) ->
211
225
Exp = ordsets :union (ordsets :from_list (Es ), Exp0 ),
212
226
Module # imodule {exports = Exp };
213
227
form ({attribute ,_ ,nifs ,Ns }, # imodule {nifs = Nifs0 }= Module , _Opts ) ->
214
- Nifs = sets :union (sets :from_list (Ns , [{version ,2 }]), Nifs0 ),
228
+ Nifs1 = case Nifs0 of
229
+ none ->
230
+ sets :new ([{version , 2 }]);
231
+ _ ->
232
+ Nifs0
233
+ end ,
234
+ Nifs = sets :union (sets :from_list (Ns , [{version ,2 }]), Nifs1 ),
215
235
Module # imodule {nifs = Nifs };
216
236
form ({attribute ,_ ,_ ,_ }= F , # imodule {attrs = As }= Module , _Opts ) ->
217
237
Module # imodule {attrs = [attribute (F )|As ]};
@@ -249,9 +269,9 @@ function({function,_,Name,Arity,Cs0}, Module, Opts)
249
269
% % ok = function_dump(Name, Arity, "ubody:~n~p~n",[B1]),
250
270
{B2 ,St3 } = cbody (B1 , Nifs , St2 ),
251
271
% % ok = function_dump(Name, Arity, "cbody:~n~p~n",[B2]),
252
- {B3 ,# core {ws = Ws }} = lbody (B2 , St3 ),
272
+ {B3 ,# core {ws = Ws , load_nif = LoadNif }} = lbody (B2 , St3 ),
253
273
% % ok = function_dump(Name, Arity, "lbody:~n~p~n",[B3]),
254
- {{# c_var {name = {Name ,Arity }},B3 },Ws }
274
+ {{# c_var {name = {Name ,Arity }},B3 },Ws , LoadNif }
255
275
catch
256
276
Class :Error :Stack ->
257
277
io :fwrite (" Function: ~w /~w \n " , [Name ,Arity ]),
@@ -860,6 +880,9 @@ expr({call,L,{remote,_,M0,F0},As0}, St0) ->
860
880
name = # c_literal {val = match_fail },
861
881
args = [Tuple ]},
862
882
{Fail ,Aps ,St1 };
883
+ {# c_literal {val = erlang },# c_literal {val = load_nif },[_ ,_ ]} ->
884
+ {# icall {anno = # a {anno = Anno },module = M1 ,name = F1 ,args = As1 },
885
+ Aps ,St1 # core {load_nif = true }};
863
886
{_ ,_ ,_ } ->
864
887
{# icall {anno = # a {anno = Anno },module = M1 ,name = F1 ,args = As1 },Aps ,St1 }
865
888
end ;
@@ -3031,6 +3054,9 @@ ren_is_subst(_V, []) -> no.
3031
3054
% % from case/receive. In subblocks/clauses the AfterVars of the block
3032
3055
% % are just the exported variables.
3033
3056
3057
+ cbody (B0 , none , St0 ) ->
3058
+ {B1 ,_ ,_ ,St1 } = cexpr (B0 , [], St0 ),
3059
+ {B1 ,St1 };
3034
3060
cbody (B0 , Nifs , St0 ) ->
3035
3061
{B1 ,_ ,_ ,St1 } = cexpr (B0 , [], St0 ),
3036
3062
B2 = case sets :is_element (St1 # core .function ,Nifs ) of
@@ -3879,6 +3905,18 @@ is_simple(_) -> false.
3879
3905
3880
3906
is_simple_list (Es ) -> lists :all (fun is_simple /1 , Es ).
3881
3907
3908
+ insert_nif_start ([VF = {V ,F = # c_fun {body = Body }}|Funs ]) ->
3909
+ case Body of
3910
+ # c_seq {arg = # c_primop {name = # c_literal {val = nif_start }}} ->
3911
+ [VF |insert_nif_start (Funs )];
3912
+ # c_case {} ->
3913
+ NifStart = # c_primop {name = # c_literal {val = nif_start },args = []},
3914
+ [{V ,F # c_fun {body = # c_seq {arg = NifStart ,body = Body }}}
3915
+ |insert_nif_start (Funs )]
3916
+ end ;
3917
+ insert_nif_start ([]) ->
3918
+ [].
3919
+
3882
3920
% %%
3883
3921
% %% Handling of warnings.
3884
3922
% %%
0 commit comments