¿Cómo agregar una función incorporada en un complemento GCC?

5 minutos de lectura

avatar de usuario
eugenio

¿Es posible que un complemento GCC agregue una nueva función integrada? Si es así, ¿cómo hacerlo correctamente?

La versión de GCC es 5.3 (o posterior). El código es compilado y procesado por el complemento escrito en C.

Se menciona en el justificación de los complementos de GCC en gcc-melt.org que esto es factible, pero no puedo ver cómo.

Por lo que puedo ver en las fuentes de GCC, los componentes integrados se crean usando add_builtin_function() de gcc/langhooks.c:

tree
add_builtin_function (const char *name,
      tree type,
      int function_code,
      enum built_in_class cl,
      const char *library_name,
      tree attrs)

Está más o menos claro qué valores deben tener los argumentos de esta función, a excepción de function_codeun ID numérico único de la función.

Parece (ver add_builtin_function_common()), un valor de enum built_in_function se espera allí, pero un complemento GCC no puede cambiar esa enumeración.

No se puede pasar ningún valor aleatorio mayor que END_BUILTINS como function_code tampoco, parece. builtin_decl_implicit() y builtin_decl_explicit() tendría una aserción fallida en ese caso.

Entonces, ¿cuál es la forma correcta de agregar un complemento GCC incorporado (sin usar MELT y demás, solo la API del complemento GCC)?

Actualizar
Miré de nuevo la implementación de add_builtin_function_common() y de langhooks.builtin_function() para C, así como cómo se utilizan en GCC. Parece que 0 es aceptable como function_code en algunos casos. No se puede utilizar builtin_decl_implicit() entonces, pero puede guardar el DECL devuelto por add_builtin_function() y usarlo más tarde.

Parece que el único evento en el que puedo intentar crear integrados de esa manera es PLUGIN_START_UNIT (de lo contrario, GCC puede fallar debido a external_scope variable siendo NULL).

Intenté lo siguiente en esa etapa (fntype fue creado antes):

decl = add_builtin_function (
    "my_helper", fntype,
    0 /* function_code */,
    BUILT_IN_NORMAL /* enum built_in_class cl */,
    NULL /* library_name */,
    NULL_TREE /* attrs */)

my_helper se definió en un archivo fuente C diferente compilado y vinculado con el archivo fuente principal. Luego usé decl para insertar las llamadas a esa función en otras funciones (gimple_build_call) durante mi pase GIMPLE.

GCC no emitió errores y, de hecho, insertó la llamada a my_helper sino como una llamada a una función ordinaria. De hecho, necesitaba una función integrada para evitar una llamada, sino insertar el cuerpo de la función.

Por otra parte, tsan0 pass, que se ejecuta justo después de mi pase, inserta las llamadas de funciones integradas tal como cabría esperar: no hay una llamada explícita como resultado, solo se inserta el cuerpo de la función. Sin embargo, sus elementos integrados están definidos por el propio GCC y no por los complementos.

Así que supongo que mi incorporado todavía necesita algo para ser un incorporado válido, pero no sé qué es. ¿Qué podría ser eso?

  • ¿La función realmente necesita ser incorporada en el sentido de gcc? ¿No podría ser una función regular?

    – Marc Glisse

    13/09/2016 a las 19:32

  • Para el problema que realmente estoy tratando de resolver (descrito aquí con más detalle), no tiene que ser un GCC incorporado per se. Lo que necesito es una forma de insertar el código de una función C en el código de otra sin llamar a la primera. Builtins y en línea son opciones obvias, pero no tengo suerte con ambos hasta ahora. En cuanto a esta pregunta en particular, sí, solo tengo curiosidad acerca de los elementos integrados. Algunos dicen que es posible agregar funciones integradas a través de un complemento de GCC, pero no puedo ver cómo.

    – Eugenio

    14 de septiembre de 2016 a las 9:15


  • @Nisarg: he aplicado la parte relacionada con el formato de su edición, gracias. En cuanto a la última oración, no, no quise preguntar lo que sugirió. Lo he reemplazado ahora para aclarar las cosas.

    – Eugenio

    12/09/2018 a las 19:27

  • Has probado __attribute__((always_inline))?

    – mínimo máximo promedio

    19 de septiembre de 2018 a las 5:33

  • Para que conste, terminé implementando una traducción simple de una secuencia de llamadas a funciones similares a C en secuencias GIMPLE como una solución parcial para este problema. El complemento GCC inserta estas secuencias GIMPLE donde sea necesario. No puede “en línea” las llamadas a los ayudantes que inserta, pero es suficiente para mí en este momento. los detalles son en este compromisover los cambios en i13n/ subdirectorio Funciona para mí, pero hacer que los ayudantes estén integrados podría ser mejor, por supuesto.

    – Eugenio

    19 de septiembre de 2018 a las 13:38


Supongo que lo que quiere hacer (a partir de su comentario y publicación vinculada) es insertar código C en una función. En ese caso, habría pensado que no necesitarías ir tan lejos como para escribir un complemento de compilación. Mira esto Boost.Preprocesadorque puede realizar manipulaciones muy avanzadas del código C usando solo el preprocesador.

  • Tenía la intención de usar las nuevas funciones integradas en el código del kernel, por lo que es solo para lenguaje C. Tengo algo de experiencia con Boost y preferiría evitarlo aquí. Por otro lado, los complementos de GCC han sido compatibles con el kernel de Linux durante un tiempo y probablemente podrían usarse aquí.

    – Eugenio

    29 de julio de 2020 a las 19:56

  • El preprocesador es una biblioteca de solo encabezado que funciona con C y no requiere C++. No veo ninguna razón por la que no debería funcionar en el núcleo.

    – Ari Fordham

    30 de julio de 2020 a las 17:03

  • Bueno, uno nunca sabe hasta que lo intenta 😉 De todos modos, como dije en los comentarios a la pregunta, ya preparé una solución y funcionó bien en 2016, cuando era necesario. Solo quería saber, quizás, alguien podría señalar una forma correcta de crear elementos integrados allí.

    – Eugenio

    31 de julio de 2020 a las 7:37

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad