1  #include <stdlib.h>
       2  #include <stdio.h>
       3  #include <stddef.h>
       4  
       5  #include "libgccjit.h"
       6  
       7  #include "harness.h"
       8  
       9  #define ARRAY_SIZE (4)
      10  
      11  /* Verify that struct layout works properly when adding an array field.  */
      12  struct array_holder
      13  {
      14    float m_before;
      15    int m_ints[ARRAY_SIZE];
      16    float m_after;
      17  };
      18  
      19  void
      20  create_code (gcc_jit_context *ctxt, void *user_data)
      21  {
      22    /* Let's try to inject the equivalent of:
      23  
      24       void
      25       test_array (struct array_holder *ah)
      26       {
      27  	ah->m_before = 4.0f;
      28  	for i in 0 to (ARRAY_SIZE - 1):
      29  	  ah->m_ints[i] = (i * i);
      30  	ah->m_after = 2.0f;
      31       }
      32    */
      33    gcc_jit_type *void_type =
      34      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_VOID);
      35    gcc_jit_type *float_type =
      36      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_FLOAT);
      37    gcc_jit_type *int_type =
      38      gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_INT);
      39  
      40    gcc_jit_field *field_m_before =
      41      gcc_jit_context_new_field (ctxt, NULL, float_type, "m_before");
      42    gcc_jit_field *field_m_ints =
      43      gcc_jit_context_new_field (
      44      ctxt, NULL,
      45      gcc_jit_context_new_array_type (ctxt, NULL, int_type, ARRAY_SIZE),
      46      "m_ints");
      47    gcc_jit_field *field_m_after =
      48      gcc_jit_context_new_field (ctxt, NULL, float_type, "m_after");
      49  
      50    gcc_jit_field *fields[] = {
      51      field_m_before,
      52      field_m_ints,
      53      field_m_after,
      54    };
      55  
      56    gcc_jit_struct *struct_type =
      57      gcc_jit_context_new_struct_type (
      58        ctxt,
      59        NULL,
      60        "array_holder",
      61        3, fields);
      62  
      63    gcc_jit_type *struct_ptr_type =
      64      gcc_jit_type_get_pointer (gcc_jit_struct_as_type (struct_type));
      65  
      66    /* Build the test_fn.  */
      67    gcc_jit_param *param_ah =
      68      gcc_jit_context_new_param (ctxt, NULL, struct_ptr_type, "ah");
      69    gcc_jit_function *func =
      70      gcc_jit_context_new_function (ctxt, NULL,
      71  				  GCC_JIT_FUNCTION_EXPORTED,
      72  				  void_type,
      73  				  "test_array",
      74  				  1, ¶m_ah,
      75  				  0);
      76  
      77    gcc_jit_block *initial = gcc_jit_function_new_block (func, "initial");
      78    gcc_jit_block *loop_test = gcc_jit_function_new_block (func, "loop_test");
      79    gcc_jit_block *loop_body = gcc_jit_function_new_block (func, "loop_body");
      80    gcc_jit_block *final = gcc_jit_function_new_block (func, "final");
      81  
      82    /* "ah->m_before = 4.0f;" */
      83    gcc_jit_block_add_assignment (
      84      initial, NULL,
      85      gcc_jit_rvalue_dereference_field (
      86        gcc_jit_param_as_rvalue (param_ah), NULL, field_m_before),
      87      gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 4));
      88  
      89    gcc_jit_block_add_comment (initial, NULL,
      90  			     "for i in 0 to (ARRAY_SIZE - 1):");
      91    gcc_jit_lvalue *i =
      92      gcc_jit_function_new_local (func, NULL, int_type, "i");
      93    gcc_jit_block_add_assignment (initial, NULL,
      94        i,
      95        gcc_jit_context_zero (ctxt, int_type));
      96  
      97    gcc_jit_block_end_with_jump (initial, NULL, loop_test);
      98  
      99    gcc_jit_block_end_with_conditional (loop_test, NULL,
     100      gcc_jit_context_new_comparison (
     101        ctxt, NULL,
     102        GCC_JIT_COMPARISON_LT,
     103        gcc_jit_lvalue_as_rvalue (i),
     104        gcc_jit_context_new_rvalue_from_int (ctxt, int_type, ARRAY_SIZE)),
     105      loop_body,
     106      final);
     107  
     108    gcc_jit_block_add_comment (loop_body, NULL, "ah->m_ints[i] = (i * i);");
     109    gcc_jit_block_add_assignment (
     110      loop_body, NULL,
     111      gcc_jit_context_new_array_access (
     112        ctxt, NULL,
     113        gcc_jit_lvalue_as_rvalue (gcc_jit_rvalue_dereference_field (
     114  	gcc_jit_param_as_rvalue (param_ah),
     115  	NULL,
     116  	field_m_ints)),
     117        gcc_jit_lvalue_as_rvalue (i)),
     118      gcc_jit_context_new_binary_op (
     119        ctxt, NULL,
     120        GCC_JIT_BINARY_OP_MULT,
     121        int_type,
     122        gcc_jit_lvalue_as_rvalue (i),
     123        gcc_jit_lvalue_as_rvalue (i)));
     124  
     125    /* "i++" */
     126    gcc_jit_block_add_assignment_op (
     127      loop_body, NULL,
     128      i,
     129      GCC_JIT_BINARY_OP_PLUS,
     130      gcc_jit_context_one (ctxt, int_type));
     131  
     132    gcc_jit_block_end_with_jump (loop_body, NULL, loop_test);
     133  
     134   /* ah->m_after = 2.0f; */
     135    gcc_jit_block_add_assignment (
     136      final, NULL,
     137      gcc_jit_rvalue_dereference_field (
     138        gcc_jit_param_as_rvalue (param_ah), NULL, field_m_after),
     139      gcc_jit_context_new_rvalue_from_int (ctxt, float_type, 2));
     140    gcc_jit_block_end_with_void_return (final, NULL);
     141  
     142  }
     143  
     144  void
     145  verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
     146  {
     147    typedef void (*fn_type) (struct array_holder *ah);
     148  
     149    CHECK_NON_NULL (result);
     150    fn_type test_array =
     151      (fn_type)gcc_jit_result_get_code (result, "test_array");
     152    CHECK_NON_NULL (test_array);
     153  
     154    struct array_holder ah;
     155    memset (&ah, 0xf0, sizeof (ah));
     156  
     157    test_array (&ah);
     158    CHECK_VALUE (ah.m_before, 4.0f);
     159    CHECK_VALUE (ah.m_ints[0], 0);
     160    CHECK_VALUE (ah.m_ints[1], 1);
     161    CHECK_VALUE (ah.m_ints[2], 4);
     162    CHECK_VALUE (ah.m_ints[3], 9);
     163    CHECK_VALUE (ah.m_after, 2.0f);
     164  
     165  }