This file is indexed.

/usr/lib/python3/dist-packages/ffc/jitcompiler.py is in python3-ffc 2017.2.0.post0-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# -*- coding: utf-8 -*-
"""This module provides a just-in-time (JIT) form compiler.
It uses dijitso to wrap the generated code into a Python module."""

# Copyright (C) 2007-2017 Anders Logg
#
# This file is part of FFC.
#
# FFC is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# FFC is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with FFC. If not, see <http://www.gnu.org/licenses/>.
#
# Modified by Johan Hake, 2008-2009
# Modified by Ilmar Wilbers, 2008
# Modified by Kristian B. Oelgaard, 2009
# Modified by Joachim Haga, 2011.
# Modified by Martin Sandve Alnæs, 2013-2017

# Python modules
import os
import sys
from hashlib import sha1
from six import string_types

# FEniCS modules
import ufl

# Not importing globally to keep dijitso optional if jit is not used
#import dijitso

# FFC modules
from ffc.log import log
from ffc.log import error
from ffc.log import set_level
from ffc.log import set_prefix
from ffc.log import INFO
from ffc.parameters import validate_jit_parameters, compute_jit_parameters_signature
from ffc.compiler import compile_form, compile_element, compile_coordinate_mapping
from ffc.backends.ufc import get_include_path as get_ufc_include_path
from ffc.backends.ufc import get_ufc_signature, get_ufc_templates_signature
from ffc import __version__ as FFC_VERSION
from ffc.classname import make_classname


def jit_generate(ufl_object, module_name, signature, parameters):
    "Callback function passed to dijitso.jit: generate code and return as strings."
    log(INFO + 5, "Calling FFC just-in-time (JIT) compiler, this may take some time.")

    # Generate actual code for this object
    if isinstance(ufl_object, ufl.Form):
        compile_object = compile_form
    elif isinstance(ufl_object, ufl.FiniteElementBase):
        compile_object = compile_element
    elif isinstance(ufl_object, ufl.Mesh):
        compile_object = compile_coordinate_mapping

    code_h, code_c, dependent_ufl_objects = compile_object(ufl_object,
            prefix=module_name, parameters=parameters, jit=True)

    # Jit compile dependent objects separately,
    # but pass indirect=True to skip instantiating objects.
    # (this is done in here such that it's only triggered
    # if parent jit module is missing, and it's done after
    # compile_object because some misformed ufl objects may
    # require analysis to determine (looking at you Expression...))
    dependencies = []
    for dep in dependent_ufl_objects["element"]:
        dep_module_name = jit(dep, parameters, indirect=True)
        dependencies.append(dep_module_name)
    for dep in dependent_ufl_objects["coordinate_mapping"]:
        dep_module_name = jit(dep, parameters, indirect=True)
        dependencies.append(dep_module_name)
    return code_h, code_c, dependencies


def _string_tuple(param):
    "Split a : separated string or convert a list to a tuple."
    if isinstance(param, (tuple, list)):
        pass
    elif isinstance(param, string_types):
        param = param.split(":")
    else:
        param = ()
    param = tuple(p for p in param if p)
    assert all(isinstance(p, string_types) for p in param)
    return param


def jit_build(ufl_object, module_name, parameters):
    "Wraps dijitso jit with some parameter conversion etc."
    import dijitso

    # FIXME: Expose more dijitso parameters?
    # FIXME: dijitso build params are not part of module_name here.
    #        Currently dijitso doesn't add to the module signature.

    # Translating the C++ flags from ffc parameters to dijitso
    # to get equivalent behaviour to instant code
    build_params = {}
    build_params["debug"] = not parameters["cpp_optimize"]
    build_params["cxxflags_opt"] = tuple(parameters["cpp_optimize_flags"].split())
    build_params["cxxflags_debug"] = ("-O0",)
    build_params["include_dirs"] = (get_ufc_include_path(),) + _string_tuple(parameters.get("external_include_dirs"))
    build_params["lib_dirs"] = _string_tuple(parameters.get("external_library_dirs"))
    build_params["libs"] = _string_tuple(parameters.get("external_libraries"))

    # Interpreting FFC default "" as None, use "." if you want to point to curdir
    cache_dir = parameters.get("cache_dir") or None
    if cache_dir:
        cache_params = {"cache_dir": cache_dir}
    else:
        cache_params = {}

    # This will do some rudimenrary checking of the params and fill in dijitso defaults
    params = dijitso.validate_params({
        "cache": cache_params,
        "build": build_params,
        "generator": parameters,  # ffc parameters, just passed on to jit_generate
    })

    # Carry out jit compilation, calling jit_generate only if needed
    module, signature = dijitso.jit(jitable=ufl_object,
                                    name=module_name,
                                    params=params,
                                    generate=jit_generate)
    return module


def compute_jit_prefix(ufl_object, parameters, kind=None):
    "Compute the prefix (module name) for jit modules."

    # Get signature from ufl object
    if isinstance(ufl_object, ufl.Form):
        kind = "form"
        object_signature = ufl_object.signature()
    elif isinstance(ufl_object, ufl.Mesh):
        # When coordinate mapping is represented by a Mesh, just getting its coordinate element
        kind = "coordinate_mapping"
        ufl_object = ufl_object.ufl_coordinate_element()
        object_signature = repr(ufl_object)  # ** must match below
    elif kind == "coordinate_mapping" and isinstance(ufl_object, ufl.FiniteElementBase):
        # When coordinate mapping is represented by its coordinate element
        object_signature = repr(ufl_object)  # ** must match above
    elif isinstance(ufl_object, ufl.FiniteElementBase):
        kind = "element"
        object_signature = repr(ufl_object)
    else:
        error("Unknown ufl object type %s" % (ufl_object.__class__.__name__,))

    # Compute deterministic string of relevant parameters
    parameters_signature = compute_jit_parameters_signature(parameters)

    # Increase this number at any time to invalidate cache
    # signatures if code generation has changed in important
    # ways without the change being visible in regular signatures:
    jit_version_bump = 3

    # Build combined signature
    signatures = [
        object_signature,
        parameters_signature,
        str(FFC_VERSION),
        str(jit_version_bump),
        get_ufc_signature(),
        get_ufc_templates_signature(),
        kind,
        ]
    string = ";".join(signatures)
    signature = sha1(string.encode('utf-8')).hexdigest()

    # Optionally shorten signature
    max_signature_length = parameters["max_signature_length"]
    if max_signature_length:
        signature = signature[:max_signature_length]

    # Combine into prefix with some info including kind
    prefix = ("ffc_%s_%s" % (kind, signature)).lower()
    return kind, prefix


class FFCError(Exception):
    pass


class FFCJitError(FFCError):
    pass


def jit(ufl_object, parameters=None, indirect=False):
    """Just-in-time compile the given form or element

    Parameters:

      ufl_object : The UFL object to be compiled
      parameters : A set of parameters
    """
    # Check parameters
    parameters = validate_jit_parameters(parameters)

    # FIXME: Setting the log level here becomes a permanent side effect...
    # Set log level
    set_level(parameters["log_level"])
    set_prefix(parameters["log_prefix"])

    # Make unique module name for generated code
    kind, module_name = compute_jit_prefix(ufl_object, parameters)

    # Inspect cache and generate+build if necessary
    module = jit_build(ufl_object, module_name, parameters)

    # Raise exception on failure to build or import module
    if module is None:
        # TODO: To communicate directory name here, need dijitso params to call
        #fail_dir = dijitso.cache.create_fail_dir_path(signature, dijitso_cache_params)
        raise FFCJitError("A directory with files to reproduce the jit build failure has been created.")

    # Construct instance of object from compiled code unless indirect
    if indirect:
        return module_name
    else:
        # FIXME: Streamline number of return arguments here across kinds
        if kind == "form":
            if parameters.get("representation") == "quadrature" or \
                    any(itg.metadata().get("representation") == "quadrature" for itg in ufl_object.integrals()):
                from ffc.quadrature.deprecation import issue_deprecation_warning
                issue_deprecation_warning()

            compiled_form = _instantiate_form(module, module_name)
            return (compiled_form, module, module_name)
            # TODO: module, module_name are never used in dolfin, drop?
            #return _instantiate_form(module, module_name)
        elif kind == "element":
            fe, dm = _instantiate_element_and_dofmap(module, module_name)
            return fe, dm
        elif kind == "coordinate_mapping":
            cm = _instantiate_coordinate_mapping(module, module_name)
            return cm
        else:
            error("Unknown kind %s" % (kind,))


def _instantiate_form(module, prefix):
    "Instantiate an object of the jit-compiled form."
    import dijitso
    classname = make_classname(prefix, "form", "main")
    form = dijitso.extract_factory_function(module, "create_" + classname)()
    return form


def _instantiate_element_and_dofmap(module, prefix):
    "Instantiate objects of the jit-compiled finite_element and dofmap."
    import dijitso
    fe_classname = make_classname(prefix, "finite_element", "main")
    dm_classname = make_classname(prefix, "dofmap", "main")
    fe = dijitso.extract_factory_function(module, "create_" + fe_classname)()
    dm = dijitso.extract_factory_function(module, "create_" + dm_classname)()
    return (fe, dm)


def _instantiate_coordinate_mapping(module, prefix):
    "Instantiate an object of the jit-compiled coordinate_mapping."
    import dijitso
    classname = make_classname(prefix, "coordinate_mapping", "main")
    form = dijitso.extract_factory_function(module, "create_" + classname)()
    return form