"Fossies" - the Fresh Open Source Software Archive

Member "ponyc-0.33.2/src/libponyc/codegen/genprim.c" (3 Feb 2020, 68932 Bytes) of package /linux/misc/ponyc-0.33.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "genprim.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 0.33.1_vs_0.33.2.

    1 #include "genprim.h"
    2 #include "gencall.h"
    3 #include "genexpr.h"
    4 #include "genfun.h"
    5 #include "genname.h"
    6 #include "genopt.h"
    7 #include "genserialise.h"
    8 #include "gentrace.h"
    9 #include "../pkg/package.h"
   10 #include "../pkg/platformfuns.h"
   11 #include "../pkg/program.h"
   12 #include "../pass/names.h"
   13 #include "../type/assemble.h"
   14 #include "../type/cap.h"
   15 #include "../../libponyrt/mem/heap.h"
   16 #include "ponyassert.h"
   17 
   18 #include <string.h>
   19 
   20 #define FIND_METHOD(name, cap) \
   21   const char* strtab_name = stringtab(name); \
   22   reach_method_t* m = reach_method(t, cap, strtab_name, NULL); \
   23   if(m == NULL) return; \
   24   m->intrinsic = true; \
   25   compile_type_t* c_t = (compile_type_t*)t->c_type; \
   26   (void)c_t; \
   27   compile_method_t* c_m = (compile_method_t*)m->c_method; \
   28   (void)c_m;
   29 
   30 #define BOX_FUNCTION(gen, gen_data) \
   31   box_function(c, (generate_box_fn)gen, gen_data);
   32 
   33 #define GENERIC_FUNCTION(name, gen) \
   34   generic_function(c, t, stringtab(name), gen);
   35 
   36 typedef void (*generate_box_fn)(compile_t*, void*, token_id);
   37 typedef void (*generate_gen_fn)(compile_t*, reach_type_t*, reach_method_t*);
   38 
   39 static void start_function(compile_t* c, reach_type_t* t, reach_method_t* m,
   40   LLVMTypeRef result, LLVMTypeRef* params, unsigned count)
   41 {
   42   compile_method_t* c_m = (compile_method_t*)m->c_method;
   43   c_m->func_type = LLVMFunctionType(result, params, count, false);
   44   c_m->func = codegen_addfun(c, m->full_name, c_m->func_type, true);
   45   genfun_param_attrs(c, t, m, c_m->func);
   46   codegen_startfun(c, c_m->func, NULL, NULL, NULL, false);
   47 }
   48 
   49 static void box_function(compile_t* c, generate_box_fn gen, void* gen_data)
   50 {
   51   gen(c, gen_data, TK_BOX);
   52   gen(c, gen_data, TK_REF);
   53   gen(c, gen_data, TK_VAL);
   54 }
   55 
   56 static void generic_function(compile_t* c, reach_type_t* t, const char* name,
   57   generate_gen_fn gen)
   58 {
   59   reach_method_name_t* n = reach_method_name(t, name);
   60 
   61   if(n == NULL)
   62     return;
   63 
   64   size_t i = HASHMAP_BEGIN;
   65   reach_method_t* m;
   66   while((m = reach_methods_next(&n->r_methods, &i)) != NULL)
   67   {
   68     m->intrinsic = true;
   69     gen(c, t, m);
   70   }
   71 }
   72 
   73 static LLVMValueRef field_loc(compile_t* c, LLVMValueRef offset,
   74   LLVMTypeRef structure, LLVMTypeRef ftype, int index)
   75 {
   76   LLVMValueRef size = LLVMConstInt(c->intptr,
   77     LLVMOffsetOfElement(c->target_data, structure, index), false);
   78   LLVMValueRef f_offset = LLVMBuildInBoundsGEP(c->builder, offset, &size, 1,
   79     "");
   80 
   81   return LLVMBuildBitCast(c->builder, f_offset,
   82     LLVMPointerType(ftype, 0), "");
   83 }
   84 
   85 static LLVMValueRef field_value(compile_t* c, LLVMValueRef object, int index)
   86 {
   87   LLVMValueRef field = LLVMBuildStructGEP(c->builder, object, index, "");
   88   return LLVMBuildLoad(c->builder, field, "");
   89 }
   90 
   91 static void pointer_create(compile_t* c, reach_type_t* t)
   92 {
   93   FIND_METHOD("create", TK_NONE);
   94   start_function(c, t, m, c_t->use_type, &c_t->use_type, 1);
   95 
   96   LLVMValueRef result = LLVMConstNull(c_t->use_type);
   97 
   98   LLVMBuildRet(c->builder, result);
   99   codegen_finishfun(c);
  100 }
  101 
  102 static void pointer_alloc(compile_t* c, reach_type_t* t,
  103   compile_type_t* t_elem)
  104 {
  105   FIND_METHOD("_alloc", TK_NONE);
  106 
  107   LLVMTypeRef params[2];
  108   params[0] = c_t->use_type;
  109   params[1] = c->intptr;
  110   start_function(c, t, m, c_t->use_type, params, 2);
  111 
  112   // Set up a constant integer for the allocation size.
  113   size_t size = (size_t)LLVMABISizeOfType(c->target_data, t_elem->mem_type);
  114   LLVMValueRef l_size = LLVMConstInt(c->intptr, size, false);
  115 
  116   LLVM_DECLARE_ATTRIBUTEREF(noalias_attr, noalias, 0);
  117   LLVM_DECLARE_ATTRIBUTEREF(deref_attr, dereferenceable_or_null, size);
  118   LLVM_DECLARE_ATTRIBUTEREF(align_attr, align, HEAP_MIN);
  119 
  120   LLVMAddAttributeAtIndex(c_m->func, LLVMAttributeReturnIndex, noalias_attr);
  121   LLVMAddAttributeAtIndex(c_m->func, LLVMAttributeReturnIndex, deref_attr);
  122   LLVMAddAttributeAtIndex(c_m->func, LLVMAttributeReturnIndex, align_attr);
  123 
  124   LLVMValueRef len = LLVMGetParam(c_m->func, 1);
  125   LLVMValueRef args[2];
  126   args[0] = codegen_ctx(c);
  127   args[1] = LLVMBuildMul(c->builder, len, l_size, "");
  128 
  129   LLVMValueRef result = gencall_runtime(c, "pony_alloc", args, 2, "");
  130   result = LLVMBuildBitCast(c->builder, result, c_t->use_type, "");
  131 
  132   LLVMBuildRet(c->builder, result);
  133   codegen_finishfun(c);
  134 }
  135 
  136 static void pointer_realloc(compile_t* c, reach_type_t* t,
  137   compile_type_t* t_elem)
  138 {
  139   FIND_METHOD("_realloc", TK_NONE);
  140 
  141   LLVMTypeRef params[2];
  142   params[0] = c_t->use_type;
  143   params[1] = c->intptr;
  144   start_function(c, t, m, c_t->use_type, params, 2);
  145 
  146   // Set up a constant integer for the allocation size.
  147   size_t size = (size_t)LLVMABISizeOfType(c->target_data, t_elem->mem_type);
  148   LLVMValueRef l_size = LLVMConstInt(c->intptr, size, false);
  149 
  150   LLVM_DECLARE_ATTRIBUTEREF(noalias_attr, noalias, 0);
  151   LLVM_DECLARE_ATTRIBUTEREF(deref_attr, dereferenceable_or_null, size);
  152   LLVM_DECLARE_ATTRIBUTEREF(align_attr, align, HEAP_MIN);
  153 
  154   LLVMAddAttributeAtIndex(c_m->func, LLVMAttributeReturnIndex, noalias_attr);
  155   LLVMAddAttributeAtIndex(c_m->func, LLVMAttributeReturnIndex, deref_attr);
  156   LLVMAddAttributeAtIndex(c_m->func, LLVMAttributeReturnIndex, align_attr);
  157 
  158   LLVMValueRef args[3];
  159   args[0] = codegen_ctx(c);
  160   args[1] = LLVMGetParam(c_m->func, 0);
  161 
  162   LLVMValueRef len = LLVMGetParam(c_m->func, 1);
  163   args[2] = LLVMBuildMul(c->builder, len, l_size, "");
  164 
  165   LLVMValueRef result = gencall_runtime(c, "pony_realloc", args, 3, "");
  166   result = LLVMBuildBitCast(c->builder, result, c_t->use_type, "");
  167 
  168   LLVMBuildRet(c->builder, result);
  169   codegen_finishfun(c);
  170 }
  171 
  172 static void pointer_unsafe(compile_t* c, reach_type_t* t)
  173 {
  174   FIND_METHOD("_unsafe", TK_NONE);
  175   start_function(c, t, m, c_t->use_type, &c_t->use_type, 1);
  176 
  177   LLVMBuildRet(c->builder, LLVMGetParam(c_m->func, 0));
  178   codegen_finishfun(c);
  179 }
  180 
  181 static void pointer_convert(compile_t* c, reach_type_t* t, reach_method_t* m)
  182 {
  183   m->intrinsic = true;
  184   compile_type_t* c_t = (compile_type_t*)t->c_type;
  185   compile_method_t* c_m = (compile_method_t*)m->c_method;
  186 
  187   compile_type_t* t_result = (compile_type_t*)m->result->c_type;
  188 
  189   start_function(c, t, m, t_result->use_type, &c_t->use_type, 1);
  190 
  191   LLVMValueRef ptr = LLVMGetParam(c_m->func, 0);
  192   ptr = LLVMBuildBitCast(c->builder, ptr, t_result->use_type, "");
  193 
  194   LLVMBuildRet(c->builder, ptr);
  195   codegen_finishfun(c);
  196 }
  197 
  198 static void pointer_apply(compile_t* c, void* data, token_id cap)
  199 {
  200   reach_type_t* t = ((reach_type_t**)data)[0];
  201   reach_type_t* t_elem = ((reach_type_t**)data)[1];
  202   compile_type_t* c_t_elem = (compile_type_t*)t_elem->c_type;
  203 
  204   FIND_METHOD("_apply", cap);
  205 
  206   LLVMTypeRef params[2];
  207   params[0] = c_t->use_type;
  208   params[1] = c->intptr;
  209   start_function(c, t, m, c_t_elem->use_type, params, 2);
  210 
  211   LLVMValueRef ptr = LLVMGetParam(c_m->func, 0);
  212   LLVMValueRef index = LLVMGetParam(c_m->func, 1);
  213 
  214   LLVMValueRef elem_ptr = LLVMBuildBitCast(c->builder, ptr,
  215     LLVMPointerType(c_t_elem->mem_type, 0), "");
  216   LLVMValueRef loc = LLVMBuildInBoundsGEP(c->builder, elem_ptr, &index, 1, "");
  217   LLVMValueRef result = LLVMBuildLoad(c->builder, loc, "");
  218 
  219   ast_t* tcap = ast_childidx(t->ast, 3);
  220   token_id tmp_cap = ast_id(tcap);
  221   ast_setid(tcap, cap);
  222 
  223   ast_setid(tcap, tmp_cap);
  224 
  225   result = gen_assign_cast(c, c_t_elem->use_type, result, t_elem->ast_cap);
  226   LLVMBuildRet(c->builder, result);
  227   codegen_finishfun(c);
  228 }
  229 
  230 static void pointer_update(compile_t* c, reach_type_t* t,
  231   reach_type_t* t_elem)
  232 {
  233   compile_type_t* c_t_elem = (compile_type_t*)t_elem->c_type;
  234 
  235   FIND_METHOD("_update", TK_NONE);
  236 
  237   LLVMTypeRef params[3];
  238   params[0] = c_t->use_type;
  239   params[1] = c->intptr;
  240   params[2] = c_t_elem->use_type;
  241   start_function(c, t, m, c_t_elem->use_type, params, 3);
  242 
  243   LLVMValueRef ptr = LLVMGetParam(c_m->func, 0);
  244   LLVMValueRef index = LLVMGetParam(c_m->func, 1);
  245 
  246   LLVMValueRef elem_ptr = LLVMBuildBitCast(c->builder, ptr,
  247     LLVMPointerType(c_t_elem->mem_type, 0), "");
  248   LLVMValueRef loc = LLVMBuildInBoundsGEP(c->builder, elem_ptr, &index, 1, "");
  249   LLVMValueRef result = LLVMBuildLoad(c->builder, loc, "");
  250 
  251   LLVMValueRef value = LLVMGetParam(c_m->func, 2);
  252   value = gen_assign_cast(c, c_t_elem->mem_type, value, t_elem->ast_cap);
  253   LLVMBuildStore(c->builder, value, loc);
  254 
  255   result = gen_assign_cast(c, c_t_elem->use_type, result, t_elem->ast_cap);
  256   LLVMBuildRet(c->builder, result);
  257   codegen_finishfun(c);
  258 }
  259 
  260 static void pointer_offset(compile_t* c, void* data, token_id cap)
  261 {
  262   reach_type_t* t = ((reach_type_t**)data)[0];
  263   compile_type_t* t_elem = ((compile_type_t**)data)[1];
  264 
  265   FIND_METHOD("_offset", cap);
  266 
  267   LLVMTypeRef params[3];
  268   params[0] = c_t->use_type;
  269   params[1] = c->intptr;
  270   start_function(c, t, m, c_t->use_type, params, 2);
  271 
  272   LLVMValueRef ptr = LLVMGetParam(c_m->func, 0);
  273   LLVMValueRef n = LLVMGetParam(c_m->func, 1);
  274 
  275   // Return ptr + (n * sizeof(len)).
  276   LLVMValueRef elem_ptr = LLVMBuildBitCast(c->builder, ptr,
  277     LLVMPointerType(t_elem->mem_type, 0), "");
  278   LLVMValueRef loc = LLVMBuildInBoundsGEP(c->builder, elem_ptr, &n, 1, "");
  279   LLVMValueRef result = LLVMBuildBitCast(c->builder, loc, c_t->use_type, "");
  280 
  281   LLVMBuildRet(c->builder, result);
  282   codegen_finishfun(c);
  283 }
  284 
  285 static void pointer_element_size(compile_t* c, reach_type_t* t,
  286   compile_type_t* t_elem)
  287 {
  288   FIND_METHOD("_element_size", TK_NONE);
  289   start_function(c, t, m, c->intptr, &c_t->use_type, 1);
  290 
  291   size_t size = (size_t)LLVMABISizeOfType(c->target_data, t_elem->mem_type);
  292   LLVMValueRef l_size = LLVMConstInt(c->intptr, size, false);
  293 
  294   LLVMBuildRet(c->builder, l_size);
  295   codegen_finishfun(c);
  296 }
  297 
  298 static void pointer_insert(compile_t* c, reach_type_t* t,
  299   compile_type_t* t_elem)
  300 {
  301   FIND_METHOD("_insert", TK_NONE);
  302 
  303   LLVMTypeRef params[3];
  304   params[0] = c_t->use_type;
  305   params[1] = c->intptr;
  306   params[2] = c->intptr;
  307   start_function(c, t, m, c_t->use_type, params, 3);
  308 
  309   // Set up a constant integer for the allocation size.
  310   size_t size = (size_t)LLVMABISizeOfType(c->target_data, t_elem->mem_type);
  311   LLVMValueRef l_size = LLVMConstInt(c->intptr, size, false);
  312 
  313   LLVMValueRef ptr = LLVMGetParam(c_m->func, 0);
  314   LLVMValueRef n = LLVMGetParam(c_m->func, 1);
  315   LLVMValueRef len = LLVMGetParam(c_m->func, 2);
  316 
  317   LLVMValueRef src = LLVMBuildBitCast(c->builder, ptr,
  318     LLVMPointerType(t_elem->mem_type, 0), "");
  319   LLVMValueRef dst = LLVMBuildInBoundsGEP(c->builder, src, &n, 1, "");
  320   dst = LLVMBuildBitCast(c->builder, dst, c_t->use_type, "");
  321   LLVMValueRef elen = LLVMBuildMul(c->builder, len, l_size, "");
  322 
  323   // llvm.memmove.*(ptr + (n * sizeof(elem)), ptr, len * sizeof(elem))
  324   gencall_memmove(c, dst, ptr, elen);
  325 
  326   // Return ptr.
  327   LLVMBuildRet(c->builder, ptr);
  328   codegen_finishfun(c);
  329 }
  330 
  331 static void pointer_delete(compile_t* c, reach_type_t* t,
  332   reach_type_t* t_elem)
  333 {
  334   compile_type_t* c_t_elem = (compile_type_t*)t_elem->c_type;
  335 
  336   FIND_METHOD("_delete", TK_NONE);
  337 
  338   LLVMTypeRef params[3];
  339   params[0] = c_t->use_type;
  340   params[1] = c->intptr;
  341   params[2] = c->intptr;
  342   start_function(c, t, m, c_t_elem->use_type, params, 3);
  343 
  344   // Set up a constant integer for the allocation size.
  345   size_t size = (size_t)LLVMABISizeOfType(c->target_data, c_t_elem->mem_type);
  346   LLVMValueRef l_size = LLVMConstInt(c->intptr, size, false);
  347 
  348   LLVMValueRef ptr = LLVMGetParam(c_m->func, 0);
  349   LLVMValueRef n = LLVMGetParam(c_m->func, 1);
  350   LLVMValueRef len = LLVMGetParam(c_m->func, 2);
  351 
  352   LLVMValueRef elem_ptr = LLVMBuildBitCast(c->builder, ptr,
  353     LLVMPointerType(c_t_elem->mem_type, 0), "");
  354   LLVMValueRef result = LLVMBuildLoad(c->builder, elem_ptr, "");
  355 
  356   LLVMValueRef src = LLVMBuildInBoundsGEP(c->builder, elem_ptr, &n, 1, "");
  357   src = LLVMBuildBitCast(c->builder, src, c_t->use_type, "");
  358   LLVMValueRef elen = LLVMBuildMul(c->builder, len, l_size, "");
  359 
  360   // llvm.memmove.*(ptr, ptr + (n * sizeof(elem)), len * sizeof(elem))
  361   gencall_memmove(c, ptr, src, elen);
  362 
  363   // Return ptr[0].
  364   result = gen_assign_cast(c, c_t_elem->use_type, result, t_elem->ast_cap);
  365   LLVMBuildRet(c->builder, result);
  366   codegen_finishfun(c);
  367 }
  368 
  369 static void pointer_copy_to(compile_t* c, void* data, token_id cap)
  370 {
  371   reach_type_t* t = ((reach_type_t**)data)[0];
  372   compile_type_t* t_elem = ((compile_type_t**)data)[1];
  373 
  374   FIND_METHOD("_copy_to", cap);
  375 
  376   LLVMTypeRef params[3];
  377   params[0] = c_t->use_type;
  378   params[1] = c_t->use_type;
  379   params[2] = c->intptr;
  380   start_function(c, t, m, c_t->use_type, params, 3);
  381 
  382   // Set up a constant integer for the allocation size.
  383   size_t size = (size_t)LLVMABISizeOfType(c->target_data, t_elem->mem_type);
  384   LLVMValueRef l_size = LLVMConstInt(c->intptr, size, false);
  385 
  386   LLVMValueRef ptr = LLVMGetParam(c_m->func, 0);
  387   LLVMValueRef ptr2 = LLVMGetParam(c_m->func, 1);
  388   LLVMValueRef n = LLVMGetParam(c_m->func, 2);
  389   LLVMValueRef elen = LLVMBuildMul(c->builder, n, l_size, "");
  390 
  391   // llvm.memcpy.*(ptr2, ptr, n * sizeof(elem), 1, 0)
  392   gencall_memcpy(c, ptr2, ptr, elen);
  393 
  394   LLVMBuildRet(c->builder, ptr);
  395   codegen_finishfun(c);
  396 }
  397 
  398 static void pointer_usize(compile_t* c, reach_type_t* t)
  399 {
  400   FIND_METHOD("usize", TK_NONE);
  401   start_function(c, t, m, c->intptr, &c_t->use_type, 1);
  402 
  403   LLVMValueRef ptr = LLVMGetParam(c_m->func, 0);
  404   LLVMValueRef result = LLVMBuildPtrToInt(c->builder, ptr, c->intptr, "");
  405 
  406   LLVMBuildRet(c->builder, result);
  407   codegen_finishfun(c);
  408 }
  409 
  410 static void pointer_is_null(compile_t* c, reach_type_t* t)
  411 {
  412   FIND_METHOD("is_null", TK_NONE);
  413   start_function(c, t, m, c->i1, &c_t->use_type, 1);
  414 
  415   LLVMValueRef ptr = LLVMGetParam(c_m->func, 0);
  416   LLVMValueRef test = LLVMBuildIsNull(c->builder, ptr, "");
  417 
  418   LLVMBuildRet(c->builder, test);
  419   codegen_finishfun(c);
  420 }
  421 
  422 static void pointer_eq(compile_t* c, reach_type_t* t)
  423 {
  424   FIND_METHOD("eq", TK_NONE);
  425   LLVMTypeRef params[2];
  426   params[0] = c_t->use_type;
  427   params[1] = c_t->use_type;
  428   start_function(c, t, m, c->i1, params, 2);
  429 
  430   LLVMValueRef ptr = LLVMGetParam(c_m->func, 0);
  431   LLVMValueRef ptr2 = LLVMGetParam(c_m->func, 1);
  432   LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntEQ, ptr, ptr2, "");
  433 
  434   LLVMBuildRet(c->builder, test);
  435   codegen_finishfun(c);
  436 }
  437 
  438 static void pointer_lt(compile_t* c, reach_type_t* t)
  439 {
  440   FIND_METHOD("lt", TK_NONE);
  441   LLVMTypeRef params[2];
  442   params[0] = c_t->use_type;
  443   params[1] = c_t->use_type;
  444   start_function(c, t, m, c->i1, params, 2);
  445 
  446   LLVMValueRef ptr = LLVMGetParam(c_m->func, 0);
  447   LLVMValueRef ptr2 = LLVMGetParam(c_m->func, 1);
  448   LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntULT, ptr, ptr2, "");
  449 
  450   LLVMBuildRet(c->builder, test);
  451   codegen_finishfun(c);
  452 }
  453 
  454 void genprim_pointer_methods(compile_t* c, reach_type_t* t)
  455 {
  456   ast_t* typeargs = ast_childidx(t->ast, 2);
  457   ast_t* typearg = ast_child(typeargs);
  458   reach_type_t* t_elem = reach_type(c->reach, typearg);
  459   compile_type_t* c_t_elem = (compile_type_t*)t_elem->c_type;
  460 
  461   void* box_args[2];
  462   box_args[0] = t;
  463   box_args[1] = t_elem;
  464 
  465   void* c_box_args[2];
  466   c_box_args[0] = t;
  467   c_box_args[1] = c_t_elem;
  468 
  469   pointer_create(c, t);
  470   pointer_alloc(c, t, c_t_elem);
  471 
  472   pointer_realloc(c, t, c_t_elem);
  473   pointer_unsafe(c, t);
  474   GENERIC_FUNCTION("_convert", pointer_convert);
  475   BOX_FUNCTION(pointer_apply, box_args);
  476   pointer_update(c, t, t_elem);
  477   BOX_FUNCTION(pointer_offset, c_box_args);
  478   pointer_element_size(c, t, c_t_elem);
  479   pointer_insert(c, t, c_t_elem);
  480   pointer_delete(c, t, t_elem);
  481   BOX_FUNCTION(pointer_copy_to, c_box_args);
  482   pointer_usize(c, t);
  483   pointer_is_null(c, t);
  484   pointer_eq(c, t);
  485   pointer_lt(c, t);
  486 }
  487 
  488 static void nullable_pointer_create(compile_t* c, reach_type_t* t, compile_type_t* t_elem)
  489 {
  490   FIND_METHOD("create", TK_NONE);
  491 
  492   LLVMTypeRef params[2];
  493   params[0] = c_t->use_type;
  494   params[1] = t_elem->use_type;
  495   start_function(c, t, m, c_t->use_type, params, 2);
  496 
  497   LLVMValueRef param = LLVMGetParam(c_m->func, 1);
  498   LLVMValueRef result = LLVMBuildBitCast(c->builder, param, c_t->use_type, "");
  499   LLVMBuildRet(c->builder, result);
  500   codegen_finishfun(c);
  501 }
  502 
  503 static void nullable_pointer_none(compile_t* c, reach_type_t* t)
  504 {
  505   FIND_METHOD("none", TK_NONE);
  506   start_function(c, t, m, c_t->use_type, &c_t->use_type, 1);
  507 
  508   LLVMBuildRet(c->builder, LLVMConstNull(c_t->use_type));
  509   codegen_finishfun(c);
  510 }
  511 
  512 static void nullable_pointer_apply(compile_t* c, void* data, token_id cap)
  513 {
  514   // Returns the receiver if it isn't null.
  515   reach_type_t* t = ((reach_type_t**)data)[0];
  516   compile_type_t* t_elem = ((compile_type_t**)data)[1];
  517 
  518   FIND_METHOD("apply", cap);
  519   start_function(c, t, m, t_elem->use_type, &c_t->use_type, 1);
  520 
  521   LLVMValueRef result = LLVMGetParam(c_m->func, 0);
  522   LLVMValueRef test = LLVMBuildIsNull(c->builder, result, "");
  523 
  524   LLVMBasicBlockRef is_false = codegen_block(c, "");
  525   LLVMBasicBlockRef is_true = codegen_block(c, "");
  526   LLVMBuildCondBr(c->builder, test, is_true, is_false);
  527 
  528   LLVMPositionBuilderAtEnd(c->builder, is_false);
  529   result = LLVMBuildBitCast(c->builder, result, t_elem->use_type, "");
  530 
  531   LLVMBuildRet(c->builder, result);
  532 
  533   LLVMPositionBuilderAtEnd(c->builder, is_true);
  534   gencall_error(c);
  535 
  536   codegen_finishfun(c);
  537 }
  538 
  539 static void nullable_pointer_is_none(compile_t* c, reach_type_t* t, token_id cap)
  540 {
  541   // Returns true if the receiver is null.
  542   FIND_METHOD("is_none", cap);
  543   start_function(c, t, m, c->i1, &c_t->use_type, 1);
  544 
  545   LLVMValueRef receiver = LLVMGetParam(c_m->func, 0);
  546   LLVMValueRef test = LLVMBuildIsNull(c->builder, receiver, "");
  547 
  548   LLVMBuildRet(c->builder, test);
  549   codegen_finishfun(c);
  550 }
  551 
  552 void genprim_nullable_pointer_methods(compile_t* c, reach_type_t* t)
  553 {
  554   ast_t* typeargs = ast_childidx(t->ast, 2);
  555   ast_t* typearg = ast_child(typeargs);
  556   compile_type_t* t_elem =
  557     (compile_type_t*)reach_type(c->reach, typearg)->c_type;
  558 
  559   void* box_args[2];
  560   box_args[0] = t;
  561   box_args[1] = t_elem;
  562 
  563   nullable_pointer_create(c, t, t_elem);
  564   nullable_pointer_none(c, t);
  565   BOX_FUNCTION(nullable_pointer_apply, box_args);
  566   BOX_FUNCTION(nullable_pointer_is_none, t);
  567 }
  568 
  569 static void donotoptimise_apply(compile_t* c, reach_type_t* t,
  570   reach_method_t* m)
  571 {
  572   m->intrinsic = true;
  573   compile_type_t* c_t = (compile_type_t*)t->c_type;
  574   compile_method_t* c_m = (compile_method_t*)m->c_method;
  575 
  576   ast_t* typearg = ast_child(m->typeargs);
  577   compile_type_t* t_elem =
  578     (compile_type_t*)reach_type(c->reach, typearg)->c_type;
  579   compile_type_t* t_result = (compile_type_t*)m->result->c_type;
  580 
  581   LLVMTypeRef params[2];
  582   params[0] = c_t->use_type;
  583   params[1] = t_elem->use_type;
  584 
  585   start_function(c, t, m, t_result->use_type, params, 2);
  586 
  587   LLVMValueRef obj = LLVMGetParam(c_m->func, 1);
  588   LLVMTypeRef void_fn = LLVMFunctionType(c->void_type, &t_elem->use_type, 1,
  589     false);
  590   LLVMValueRef asmstr = LLVMConstInlineAsm(void_fn, "", "imr,~{memory}", true,
  591     false);
  592   LLVMValueRef call = LLVMBuildCall(c->builder, asmstr, &obj, 1, "");
  593 
  594   bool is_ptr = LLVMGetTypeKind(t_elem->use_type) == LLVMPointerTypeKind;
  595 
  596   LLVM_DECLARE_ATTRIBUTEREF(nounwind_attr, nounwind, 0);
  597   LLVM_DECLARE_ATTRIBUTEREF(readonly_attr, readonly, 0);
  598   LLVM_DECLARE_ATTRIBUTEREF(inacc_or_arg_mem_attr,
  599     inaccessiblemem_or_argmemonly, 0);
  600 
  601   LLVMAddCallSiteAttribute(call, LLVMAttributeFunctionIndex, nounwind_attr);
  602 
  603   if(is_ptr)
  604     LLVMAddCallSiteAttribute(call, 1, readonly_attr);
  605 
  606   LLVMAddCallSiteAttribute(call, LLVMAttributeFunctionIndex,
  607     inacc_or_arg_mem_attr);
  608 
  609   LLVMBuildRet(c->builder, t_result->instance);
  610   codegen_finishfun(c);
  611 }
  612 
  613 static void donotoptimise_observe(compile_t* c, reach_type_t* t, token_id cap)
  614 {
  615   FIND_METHOD("observe", cap);
  616   compile_type_t* t_result = (compile_type_t*)m->result->c_type;
  617 
  618   start_function(c, t, m, t_result->use_type, &c_t->use_type, 1);
  619 
  620   LLVMTypeRef void_fn = LLVMFunctionType(c->void_type, NULL, 0, false);
  621   LLVMValueRef asmstr = LLVMConstInlineAsm(void_fn, "", "~{memory}", true,
  622     false);
  623   LLVMValueRef call = LLVMBuildCall(c->builder, asmstr, NULL, 0, "");
  624 
  625   LLVM_DECLARE_ATTRIBUTEREF(nounwind_attr, nounwind, 0);
  626   LLVM_DECLARE_ATTRIBUTEREF(inacc_or_arg_mem_attr,
  627     inaccessiblemem_or_argmemonly, 0);
  628 
  629   LLVMAddCallSiteAttribute(call, LLVMAttributeFunctionIndex, nounwind_attr);
  630   LLVMAddCallSiteAttribute(call, LLVMAttributeFunctionIndex,
  631     inacc_or_arg_mem_attr);
  632 
  633   LLVMBuildRet(c->builder, t_result->instance);
  634   codegen_finishfun(c);
  635 }
  636 
  637 void genprim_donotoptimise_methods(compile_t* c, reach_type_t* t)
  638 {
  639   GENERIC_FUNCTION("apply", donotoptimise_apply);
  640   BOX_FUNCTION(donotoptimise_observe, t);
  641 }
  642 
  643 static void trace_array_elements(compile_t* c, reach_type_t* t,
  644   LLVMValueRef ctx, LLVMValueRef object, LLVMValueRef pointer)
  645 {
  646   // Get the type argument for the array. This will be used to generate the
  647   // per-element trace call.
  648   ast_t* typeargs = ast_childidx(t->ast, 2);
  649   ast_t* typearg = ast_child(typeargs);
  650 
  651   if(!gentrace_needed(c, typearg, typearg))
  652     return;
  653 
  654   reach_type_t* t_elem = reach_type(c->reach, typearg);
  655   compile_type_t* c_t_elem = (compile_type_t*)t_elem->c_type;
  656 
  657   pointer = LLVMBuildBitCast(c->builder, pointer,
  658     LLVMPointerType(c_t_elem->mem_type, 0), "");
  659 
  660   LLVMBasicBlockRef entry_block = LLVMGetInsertBlock(c->builder);
  661   LLVMBasicBlockRef cond_block = codegen_block(c, "cond");
  662   LLVMBasicBlockRef body_block = codegen_block(c, "body");
  663   LLVMBasicBlockRef post_block = codegen_block(c, "post");
  664 
  665   // Read the size.
  666   LLVMValueRef size = field_value(c, object, 1);
  667   LLVMBuildBr(c->builder, cond_block);
  668 
  669   // While the index is less than the size, trace an element. The initial
  670   // index when coming from the entry block is zero.
  671   LLVMPositionBuilderAtEnd(c->builder, cond_block);
  672   LLVMValueRef phi = LLVMBuildPhi(c->builder, c->intptr, "");
  673   LLVMValueRef zero = LLVMConstInt(c->intptr, 0, false);
  674   LLVMAddIncoming(phi, &zero, &entry_block, 1);
  675   LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntULT, phi, size, "");
  676   LLVMBuildCondBr(c->builder, test, body_block, post_block);
  677 
  678   // The phi node is the index. Get the element and trace it.
  679   LLVMPositionBuilderAtEnd(c->builder, body_block);
  680   LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(c->builder, pointer, &phi, 1,
  681     "");
  682   LLVMValueRef elem = LLVMBuildLoad(c->builder, elem_ptr, "");
  683   elem = gen_assign_cast(c, c_t_elem->use_type, elem, typearg);
  684   gentrace(c, ctx, elem, elem, typearg, typearg);
  685 
  686   // Add one to the phi node and branch back to the cond block.
  687   LLVMValueRef one = LLVMConstInt(c->intptr, 1, false);
  688   LLVMValueRef inc = LLVMBuildAdd(c->builder, phi, one, "");
  689   body_block = LLVMGetInsertBlock(c->builder);
  690   LLVMAddIncoming(phi, &inc, &body_block, 1);
  691   LLVMBuildBr(c->builder, cond_block);
  692 
  693   LLVMMoveBasicBlockAfter(post_block, LLVMGetInsertBlock(c->builder));
  694   LLVMPositionBuilderAtEnd(c->builder, post_block);
  695 }
  696 
  697 void genprim_array_trace(compile_t* c, reach_type_t* t)
  698 {
  699   compile_type_t* c_t = (compile_type_t*)t->c_type;
  700   codegen_startfun(c, c_t->trace_fn, NULL, NULL, NULL, false);
  701   LLVMSetFunctionCallConv(c_t->trace_fn, LLVMCCallConv);
  702   LLVMSetLinkage(c_t->trace_fn, LLVMExternalLinkage);
  703   LLVMValueRef ctx = LLVMGetParam(c_t->trace_fn, 0);
  704   LLVMValueRef arg = LLVMGetParam(c_t->trace_fn, 1);
  705 
  706   // Read the base pointer.
  707   LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, c_t->use_type, "");
  708   LLVMValueRef pointer = field_value(c, object, 3);
  709 
  710   // Trace the base pointer.
  711   LLVMValueRef args[2];
  712   args[0] = ctx;
  713   args[1] = pointer;
  714   gencall_runtime(c, "pony_trace", args, 2, "");
  715 
  716   trace_array_elements(c, t, ctx, object, pointer);
  717   LLVMBuildRetVoid(c->builder);
  718   codegen_finishfun(c);
  719 }
  720 
  721 void genprim_array_serialise_trace(compile_t* c, reach_type_t* t)
  722 {
  723   // Generate the serialise_trace function.
  724   compile_type_t* c_t = (compile_type_t*)t->c_type;
  725   c_t->serialise_trace_fn = codegen_addfun(c, genname_serialise_trace(t->name),
  726     c->trace_type, true);
  727 
  728   codegen_startfun(c, c_t->serialise_trace_fn, NULL, NULL, NULL, false);
  729   LLVMSetFunctionCallConv(c_t->serialise_trace_fn, LLVMCCallConv);
  730   LLVMSetLinkage(c_t->serialise_trace_fn, LLVMExternalLinkage);
  731 
  732   LLVMValueRef ctx = LLVMGetParam(c_t->serialise_trace_fn, 0);
  733   LLVMValueRef arg = LLVMGetParam(c_t->serialise_trace_fn, 1);
  734   LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, c_t->use_type, "");
  735 
  736   LLVMValueRef size = field_value(c, object, 1);
  737 
  738   LLVMBasicBlockRef trace_block = codegen_block(c, "trace");
  739   LLVMBasicBlockRef post_block = codegen_block(c, "post");
  740 
  741   LLVMValueRef cond = LLVMBuildICmp(c->builder, LLVMIntNE, size,
  742     LLVMConstInt(c->intptr, 0, false), "");
  743   LLVMBuildCondBr(c->builder, cond, trace_block, post_block);
  744 
  745   LLVMPositionBuilderAtEnd(c->builder, trace_block);
  746 
  747   // Calculate the size of the element type.
  748   ast_t* typeargs = ast_childidx(t->ast, 2);
  749   ast_t* typearg = ast_child(typeargs);
  750   compile_type_t* t_elem =
  751     (compile_type_t*)reach_type(c->reach, typearg)->c_type;
  752 
  753   size_t abisize = (size_t)LLVMABISizeOfType(c->target_data, t_elem->use_type);
  754   LLVMValueRef l_size = LLVMConstInt(c->intptr, abisize, false);
  755 
  756   // Reserve space for the array elements.
  757   LLVMValueRef pointer = field_value(c, object, 3);
  758 
  759   LLVMValueRef args[3];
  760   args[0] = ctx;
  761   args[1] = pointer;
  762   args[2] = LLVMBuildMul(c->builder, size, l_size, "");
  763   gencall_runtime(c, "pony_serialise_reserve", args, 3, "");
  764 
  765   // Trace the array elements.
  766   trace_array_elements(c, t, ctx, object, pointer);
  767 
  768   LLVMBuildBr(c->builder, post_block);
  769 
  770   LLVMPositionBuilderAtEnd(c->builder, post_block);
  771 
  772   LLVMBuildRetVoid(c->builder);
  773   codegen_finishfun(c);
  774 }
  775 
  776 void genprim_array_serialise(compile_t* c, reach_type_t* t)
  777 {
  778   // Generate the serialise function.
  779   compile_type_t* c_t = (compile_type_t*)t->c_type;
  780   c_t->serialise_fn = codegen_addfun(c, genname_serialise(t->name),
  781     c->serialise_type, true);
  782 
  783   codegen_startfun(c, c_t->serialise_fn, NULL, NULL, NULL, false);
  784   LLVMSetFunctionCallConv(c_t->serialise_fn, LLVMCCallConv);
  785   LLVMSetLinkage(c_t->serialise_fn, LLVMExternalLinkage);
  786 
  787   LLVMValueRef ctx = LLVMGetParam(c_t->serialise_fn, 0);
  788   LLVMValueRef arg = LLVMGetParam(c_t->serialise_fn, 1);
  789   LLVMValueRef addr = LLVMGetParam(c_t->serialise_fn, 2);
  790   LLVMValueRef offset = LLVMGetParam(c_t->serialise_fn, 3);
  791   LLVMValueRef mut = LLVMGetParam(c_t->serialise_fn, 4);
  792 
  793   LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, c_t->structure_ptr,
  794     "");
  795   LLVMValueRef offset_addr = LLVMBuildInBoundsGEP(c->builder, addr, &offset, 1,
  796     "");
  797 
  798   genserialise_typeid(c, t, offset_addr);
  799 
  800   // Don't serialise our contents if we are opaque.
  801   LLVMBasicBlockRef body_block = codegen_block(c, "body");
  802   LLVMBasicBlockRef post_block = codegen_block(c, "post");
  803 
  804   LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntNE, mut,
  805     LLVMConstInt(c->i32, PONY_TRACE_OPAQUE, false), "");
  806   LLVMBuildCondBr(c->builder, test, body_block, post_block);
  807   LLVMPositionBuilderAtEnd(c->builder, body_block);
  808 
  809   // Write the size twice, effectively rewriting alloc to be the same as size.
  810   LLVMValueRef size = field_value(c, object, 1);
  811 
  812   LLVMValueRef size_loc = field_loc(c, offset_addr, c_t->structure,
  813     c->intptr, 1);
  814   LLVMBuildStore(c->builder, size, size_loc);
  815 
  816   LLVMValueRef alloc_loc = field_loc(c, offset_addr, c_t->structure,
  817     c->intptr, 2);
  818   LLVMBuildStore(c->builder, size, alloc_loc);
  819 
  820   // Write the pointer.
  821   LLVMValueRef ptr = field_value(c, object, 3);
  822 
  823   // The resulting offset will only be invalid (i.e. have the high bit set) if
  824   // the size is zero. For an opaque array, we don't serialise the contents,
  825   // so we don't get here, so we don't end up with an invalid offset.
  826   LLVMValueRef args[5];
  827   args[0] = ctx;
  828   args[1] = ptr;
  829   LLVMValueRef ptr_offset = gencall_runtime(c, "pony_serialise_offset",
  830     args, 2, "");
  831 
  832   LLVMValueRef ptr_loc = field_loc(c, offset_addr, c_t->structure, c->intptr, 3);
  833   LLVMBuildStore(c->builder, ptr_offset, ptr_loc);
  834 
  835   LLVMValueRef ptr_offset_addr = LLVMBuildInBoundsGEP(c->builder, addr,
  836     &ptr_offset, 1, "");
  837 
  838   // Serialise elements.
  839   ast_t* typeargs = ast_childidx(t->ast, 2);
  840   ast_t* typearg = ast_child(typeargs);
  841   reach_type_t* t_elem = reach_type(c->reach, typearg);
  842   compile_type_t* c_t_e = (compile_type_t*)t_elem->c_type;
  843 
  844   size_t abisize = (size_t)LLVMABISizeOfType(c->target_data, c_t_e->mem_type);
  845   LLVMValueRef l_size = LLVMConstInt(c->intptr, abisize, false);
  846 
  847   if((t_elem->underlying == TK_PRIMITIVE) && (c_t_e->primitive != NULL))
  848   {
  849     // memcpy machine words
  850     size = LLVMBuildMul(c->builder, size, l_size, "");
  851     gencall_memcpy(c, ptr_offset_addr, ptr, size);
  852   } else {
  853     ptr = LLVMBuildBitCast(c->builder, ptr,
  854       LLVMPointerType(c_t_e->use_type, 0), "");
  855 
  856     LLVMBasicBlockRef entry_block = LLVMGetInsertBlock(c->builder);
  857     LLVMBasicBlockRef cond_elem_block = codegen_block(c, "cond");
  858     LLVMBasicBlockRef body_elem_block = codegen_block(c, "body");
  859     LLVMBasicBlockRef post_elem_block = codegen_block(c, "post");
  860 
  861     LLVMValueRef offset_var = LLVMBuildAlloca(c->builder, c->void_ptr, "");
  862     LLVMBuildStore(c->builder, ptr_offset_addr, offset_var);
  863 
  864     LLVMBuildBr(c->builder, cond_elem_block);
  865 
  866     // While the index is less than the size, serialise an element. The
  867     // initial index when coming from the entry block is zero.
  868     LLVMPositionBuilderAtEnd(c->builder, cond_elem_block);
  869     LLVMValueRef phi = LLVMBuildPhi(c->builder, c->intptr, "");
  870     LLVMValueRef zero = LLVMConstInt(c->intptr, 0, false);
  871     LLVMAddIncoming(phi, &zero, &entry_block, 1);
  872     LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntULT, phi, size, "");
  873     LLVMBuildCondBr(c->builder, test, body_elem_block, post_elem_block);
  874 
  875     // The phi node is the index. Get the element and serialise it.
  876     LLVMPositionBuilderAtEnd(c->builder, body_elem_block);
  877     LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(c->builder, ptr, &phi, 1, "");
  878 
  879     ptr_offset_addr = LLVMBuildLoad(c->builder, offset_var, "");
  880     genserialise_element(c, t_elem, false, ctx, elem_ptr, ptr_offset_addr);
  881     ptr_offset_addr = LLVMBuildInBoundsGEP(c->builder, ptr_offset_addr, &l_size,
  882       1, "");
  883     LLVMBuildStore(c->builder, ptr_offset_addr, offset_var);
  884 
  885     // Add one to the phi node and branch back to the cond block.
  886     LLVMValueRef one = LLVMConstInt(c->intptr, 1, false);
  887     LLVMValueRef inc = LLVMBuildAdd(c->builder, phi, one, "");
  888     body_block = LLVMGetInsertBlock(c->builder);
  889     LLVMAddIncoming(phi, &inc, &body_block, 1);
  890     LLVMBuildBr(c->builder, cond_elem_block);
  891 
  892     LLVMMoveBasicBlockAfter(post_elem_block, LLVMGetInsertBlock(c->builder));
  893     LLVMPositionBuilderAtEnd(c->builder, post_elem_block);
  894   }
  895 
  896   LLVMBuildBr(c->builder, post_block);
  897   LLVMMoveBasicBlockAfter(post_block, LLVMGetInsertBlock(c->builder));
  898   LLVMPositionBuilderAtEnd(c->builder, post_block);
  899   LLVMBuildRetVoid(c->builder);
  900   codegen_finishfun(c);
  901 }
  902 
  903 void genprim_array_deserialise(compile_t* c, reach_type_t* t)
  904 {
  905   // Generate the deserisalise function.
  906   compile_type_t* c_t = (compile_type_t*)t->c_type;
  907   c_t->deserialise_fn = codegen_addfun(c, genname_deserialise(t->name),
  908     c->trace_type, true);
  909 
  910   codegen_startfun(c, c_t->deserialise_fn, NULL, NULL, NULL, false);
  911   LLVMSetFunctionCallConv(c_t->deserialise_fn, LLVMCCallConv);
  912   LLVMSetLinkage(c_t->deserialise_fn, LLVMExternalLinkage);
  913 
  914   LLVMValueRef ctx = LLVMGetParam(c_t->deserialise_fn, 0);
  915   LLVMValueRef arg = LLVMGetParam(c_t->deserialise_fn, 1);
  916 
  917   LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, c_t->structure_ptr,
  918     "");
  919   gendeserialise_typeid(c, c_t, object);
  920 
  921   // Deserialise the array contents.
  922   LLVMValueRef alloc = field_value(c, object, 2);
  923   LLVMValueRef ptr_offset = field_value(c, object, 3);
  924   ptr_offset = LLVMBuildPtrToInt(c->builder, ptr_offset, c->intptr, "");
  925 
  926   ast_t* typeargs = ast_childidx(t->ast, 2);
  927   ast_t* typearg = ast_child(typeargs);
  928 
  929   reach_type_t* t_elem = reach_type(c->reach, typearg);
  930   compile_type_t* c_t_e = (compile_type_t*)t_elem->c_type;
  931   size_t abisize = (size_t)LLVMABISizeOfType(c->target_data, c_t_e->use_type);
  932   LLVMValueRef l_size = LLVMConstInt(c->intptr, abisize, false);
  933 
  934   LLVMValueRef args[3];
  935   args[0] = ctx;
  936   args[1] = ptr_offset;
  937   args[2] = LLVMBuildMul(c->builder, alloc, l_size, "");
  938   LLVMValueRef ptr = gencall_runtime(c, "pony_deserialise_block", args, 3, "");
  939 
  940   LLVMValueRef ptr_loc = LLVMBuildStructGEP(c->builder, object, 3, "");
  941   LLVMBuildStore(c->builder, ptr, ptr_loc);
  942 
  943   if((t_elem->underlying == TK_PRIMITIVE) && (c_t_e->primitive != NULL))
  944   {
  945     // Do nothing. A memcpy is sufficient.
  946   } else {
  947     LLVMValueRef size = field_value(c, object, 1);
  948     ptr = LLVMBuildBitCast(c->builder, ptr,
  949       LLVMPointerType(c_t_e->use_type, 0), "");
  950 
  951     LLVMBasicBlockRef entry_block = LLVMGetInsertBlock(c->builder);
  952     LLVMBasicBlockRef cond_block = codegen_block(c, "cond");
  953     LLVMBasicBlockRef body_block = codegen_block(c, "body");
  954     LLVMBasicBlockRef post_block = codegen_block(c, "post");
  955 
  956     LLVMBuildBr(c->builder, cond_block);
  957 
  958     // While the index is less than the size, deserialise an element. The
  959     // initial index when coming from the entry block is zero.
  960     LLVMPositionBuilderAtEnd(c->builder, cond_block);
  961     LLVMValueRef phi = LLVMBuildPhi(c->builder, c->intptr, "");
  962     LLVMValueRef zero = LLVMConstInt(c->intptr, 0, false);
  963     LLVMAddIncoming(phi, &zero, &entry_block, 1);
  964     LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntULT, phi, size, "");
  965     LLVMBuildCondBr(c->builder, test, body_block, post_block);
  966 
  967     // The phi node is the index. Get the element and deserialise it.
  968     LLVMPositionBuilderAtEnd(c->builder, body_block);
  969     LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(c->builder, ptr, &phi, 1, "");
  970     gendeserialise_element(c, t_elem, false, ctx, elem_ptr);
  971 
  972     // Add one to the phi node and branch back to the cond block.
  973     LLVMValueRef one = LLVMConstInt(c->intptr, 1, false);
  974     LLVMValueRef inc = LLVMBuildAdd(c->builder, phi, one, "");
  975     body_block = LLVMGetInsertBlock(c->builder);
  976     LLVMAddIncoming(phi, &inc, &body_block, 1);
  977     LLVMBuildBr(c->builder, cond_block);
  978 
  979     LLVMMoveBasicBlockAfter(post_block, LLVMGetInsertBlock(c->builder));
  980     LLVMPositionBuilderAtEnd(c->builder, post_block);
  981   }
  982 
  983   LLVMBuildRetVoid(c->builder);
  984   codegen_finishfun(c);
  985 }
  986 
  987 void genprim_string_serialise_trace(compile_t* c, reach_type_t* t)
  988 {
  989   // Generate the serialise_trace function.
  990   compile_type_t* c_t = (compile_type_t*)t->c_type;
  991   c_t->serialise_trace_fn = codegen_addfun(c, genname_serialise_trace(t->name),
  992     c->serialise_type, true);
  993 
  994   codegen_startfun(c, c_t->serialise_trace_fn, NULL, NULL, NULL, false);
  995   LLVMSetFunctionCallConv(c_t->serialise_trace_fn, LLVMCCallConv);
  996   LLVMSetLinkage(c_t->serialise_trace_fn, LLVMExternalLinkage);
  997 
  998   LLVMValueRef ctx = LLVMGetParam(c_t->serialise_trace_fn, 0);
  999   LLVMValueRef arg = LLVMGetParam(c_t->serialise_trace_fn, 1);
 1000   LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, c_t->use_type, "");
 1001 
 1002   LLVMValueRef size = field_value(c, object, 1);
 1003 
 1004   LLVMValueRef alloc = LLVMBuildAdd(c->builder, size,
 1005     LLVMConstInt(c->intptr, 1, false), "");
 1006 
 1007   // Reserve space for the contents.
 1008   LLVMValueRef ptr = field_value(c, object, 3);
 1009 
 1010   LLVMValueRef args[3];
 1011   args[0] = ctx;
 1012   args[1] = ptr;
 1013   args[2] = alloc;
 1014   gencall_runtime(c, "pony_serialise_reserve", args, 3, "");
 1015 
 1016   LLVMBuildRetVoid(c->builder);
 1017   codegen_finishfun(c);
 1018 }
 1019 
 1020 void genprim_string_serialise(compile_t* c, reach_type_t* t)
 1021 {
 1022   // Generate the serialise function.
 1023   compile_type_t* c_t = (compile_type_t*)t->c_type;
 1024   c_t->serialise_fn = codegen_addfun(c, genname_serialise(t->name),
 1025     c->serialise_type, true);
 1026 
 1027   codegen_startfun(c, c_t->serialise_fn, NULL, NULL, NULL, false);
 1028   LLVMSetFunctionCallConv(c_t->serialise_fn, LLVMCCallConv);
 1029   LLVMSetLinkage(c_t->serialise_fn, LLVMExternalLinkage);
 1030 
 1031   LLVMValueRef ctx = LLVMGetParam(c_t->serialise_fn, 0);
 1032   LLVMValueRef arg = LLVMGetParam(c_t->serialise_fn, 1);
 1033   LLVMValueRef addr = LLVMGetParam(c_t->serialise_fn, 2);
 1034   LLVMValueRef offset = LLVMGetParam(c_t->serialise_fn, 3);
 1035   LLVMValueRef mut = LLVMGetParam(c_t->serialise_fn, 4);
 1036 
 1037   LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, c_t->structure_ptr,
 1038     "");
 1039   LLVMValueRef offset_addr = LLVMBuildInBoundsGEP(c->builder, addr, &offset, 1,
 1040     "");
 1041 
 1042   genserialise_typeid(c, t, offset_addr);
 1043 
 1044   // Don't serialise our contents if we are opaque.
 1045   LLVMBasicBlockRef body_block = codegen_block(c, "body");
 1046   LLVMBasicBlockRef post_block = codegen_block(c, "post");
 1047 
 1048   LLVMValueRef test = LLVMBuildICmp(c->builder, LLVMIntNE, mut,
 1049     LLVMConstInt(c->i32, PONY_TRACE_OPAQUE, false), "");
 1050   LLVMBuildCondBr(c->builder, test, body_block, post_block);
 1051   LLVMPositionBuilderAtEnd(c->builder, body_block);
 1052 
 1053   // Write the size, and rewrite alloc to be size + 1.
 1054   LLVMValueRef size = field_value(c, object, 1);
 1055   LLVMValueRef size_loc = field_loc(c, offset_addr, c_t->structure,
 1056     c->intptr, 1);
 1057   LLVMBuildStore(c->builder, size, size_loc);
 1058 
 1059   LLVMValueRef alloc = LLVMBuildAdd(c->builder, size,
 1060     LLVMConstInt(c->intptr, 1, false), "");
 1061   LLVMValueRef alloc_loc = field_loc(c, offset_addr, c_t->structure,
 1062     c->intptr, 2);
 1063   LLVMBuildStore(c->builder, alloc, alloc_loc);
 1064 
 1065   // Write the pointer.
 1066   LLVMValueRef ptr = field_value(c, object, 3);
 1067 
 1068   LLVMValueRef args[5];
 1069   args[0] = ctx;
 1070   args[1] = ptr;
 1071   LLVMValueRef ptr_offset = gencall_runtime(c, "pony_serialise_offset",
 1072     args, 2, "");
 1073 
 1074   LLVMValueRef ptr_loc = field_loc(c, offset_addr, c_t->structure, c->intptr, 3);
 1075   LLVMBuildStore(c->builder, ptr_offset, ptr_loc);
 1076 
 1077   // Serialise the string contents.
 1078   LLVMValueRef dst =  LLVMBuildInBoundsGEP(c->builder, addr, &ptr_offset, 1,
 1079     "");
 1080   LLVMValueRef src = LLVMBuildBitCast(c->builder, field_value(c, object, 3),
 1081     c->void_ptr, "");
 1082   gencall_memcpy(c, dst, src, alloc);
 1083 
 1084   LLVMBuildBr(c->builder, post_block);
 1085   LLVMPositionBuilderAtEnd(c->builder, post_block);
 1086   LLVMBuildRetVoid(c->builder);
 1087   codegen_finishfun(c);
 1088 }
 1089 
 1090 void genprim_string_deserialise(compile_t* c, reach_type_t* t)
 1091 {
 1092   // Generate the deserisalise function.
 1093   compile_type_t* c_t = (compile_type_t*)t->c_type;
 1094   c_t->deserialise_fn = codegen_addfun(c, genname_deserialise(t->name),
 1095     c->trace_type, true);
 1096 
 1097   codegen_startfun(c, c_t->deserialise_fn, NULL, NULL, NULL, false);
 1098   LLVMSetFunctionCallConv(c_t->deserialise_fn, LLVMCCallConv);
 1099   LLVMSetLinkage(c_t->deserialise_fn, LLVMExternalLinkage);
 1100 
 1101   LLVMValueRef ctx = LLVMGetParam(c_t->deserialise_fn, 0);
 1102   LLVMValueRef arg = LLVMGetParam(c_t->deserialise_fn, 1);
 1103 
 1104   LLVMValueRef object = LLVMBuildBitCast(c->builder, arg, c_t->structure_ptr,
 1105     "");
 1106   gendeserialise_typeid(c, c_t, object);
 1107 
 1108   // Deserialise the string contents.
 1109   LLVMValueRef alloc = field_value(c, object, 2);
 1110   LLVMValueRef ptr_offset = field_value(c, object, 3);
 1111   ptr_offset = LLVMBuildPtrToInt(c->builder, ptr_offset, c->intptr, "");
 1112 
 1113   LLVMValueRef args[3];
 1114   args[0] = ctx;
 1115   args[1] = ptr_offset;
 1116   args[2] = alloc;
 1117   LLVMValueRef ptr_addr = gencall_runtime(c, "pony_deserialise_block", args, 3,
 1118     "");
 1119 
 1120   LLVMValueRef ptr = LLVMBuildStructGEP(c->builder, object, 3, "");
 1121   LLVMBuildStore(c->builder, ptr_addr, ptr);
 1122 
 1123   LLVMBuildRetVoid(c->builder);
 1124   codegen_finishfun(c);
 1125 }
 1126 
 1127 static void platform_freebsd(compile_t* c, reach_type_t* t, token_id cap)
 1128 {
 1129   FIND_METHOD("freebsd", cap);
 1130   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1131 
 1132   LLVMValueRef result =
 1133     LLVMConstInt(c->i1, target_is_freebsd(c->opt->triple), false);
 1134   LLVMBuildRet(c->builder, result);
 1135   codegen_finishfun(c);
 1136 }
 1137 
 1138 static void platform_dragonfly(compile_t* c, reach_type_t* t, token_id cap)
 1139 {
 1140   FIND_METHOD("dragonfly", cap);
 1141   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1142 
 1143   LLVMValueRef result =
 1144     LLVMConstInt(c->i1, target_is_dragonfly(c->opt->triple), false);
 1145   LLVMBuildRet(c->builder, result);
 1146   codegen_finishfun(c);
 1147 }
 1148 
 1149 static void platform_openbsd(compile_t* c, reach_type_t* t, token_id cap)
 1150 {
 1151   FIND_METHOD("openbsd", cap);
 1152   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1153 
 1154   LLVMValueRef result =
 1155     LLVMConstInt(c->i1, target_is_openbsd(c->opt->triple), false);
 1156   LLVMBuildRet(c->builder, result);
 1157   codegen_finishfun(c);
 1158 }
 1159 
 1160 static void platform_linux(compile_t* c, reach_type_t* t, token_id cap)
 1161 {
 1162   FIND_METHOD("linux", cap);
 1163   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1164 
 1165   LLVMValueRef result =
 1166     LLVMConstInt(c->i1, target_is_linux(c->opt->triple), false);
 1167   LLVMBuildRet(c->builder, result);
 1168   codegen_finishfun(c);
 1169 }
 1170 
 1171 static void platform_osx(compile_t* c, reach_type_t* t, token_id cap)
 1172 {
 1173   FIND_METHOD("osx", cap);
 1174   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1175 
 1176   LLVMValueRef result =
 1177     LLVMConstInt(c->i1, target_is_macosx(c->opt->triple), false);
 1178   LLVMBuildRet(c->builder, result);
 1179   codegen_finishfun(c);
 1180 }
 1181 
 1182 static void platform_windows(compile_t* c, reach_type_t* t, token_id cap)
 1183 {
 1184   FIND_METHOD("windows", cap);
 1185   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1186 
 1187   LLVMValueRef result =
 1188     LLVMConstInt(c->i1, target_is_windows(c->opt->triple), false);
 1189   LLVMBuildRet(c->builder, result);
 1190   codegen_finishfun(c);
 1191 }
 1192 
 1193 static void platform_x86(compile_t* c, reach_type_t* t, token_id cap)
 1194 {
 1195   FIND_METHOD("x86", cap);
 1196   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1197 
 1198   LLVMValueRef result =
 1199     LLVMConstInt(c->i1, target_is_x86(c->opt->triple), false);
 1200   LLVMBuildRet(c->builder, result);
 1201   codegen_finishfun(c);
 1202 }
 1203 
 1204 static void platform_arm(compile_t* c, reach_type_t* t, token_id cap)
 1205 {
 1206   FIND_METHOD("arm", cap);
 1207   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1208 
 1209   LLVMValueRef result =
 1210     LLVMConstInt(c->i1, target_is_arm(c->opt->triple), false);
 1211   LLVMBuildRet(c->builder, result);
 1212   codegen_finishfun(c);
 1213 }
 1214 
 1215 static void platform_lp64(compile_t* c, reach_type_t* t, token_id cap)
 1216 {
 1217   FIND_METHOD("lp64", cap);
 1218   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1219 
 1220   LLVMValueRef result =
 1221     LLVMConstInt(c->i1, target_is_lp64(c->opt->triple), false);
 1222   LLVMBuildRet(c->builder, result);
 1223   codegen_finishfun(c);
 1224 }
 1225 
 1226 static void platform_llp64(compile_t* c, reach_type_t* t, token_id cap)
 1227 {
 1228   FIND_METHOD("llp64", cap);
 1229   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1230 
 1231   LLVMValueRef result =
 1232     LLVMConstInt(c->i1, target_is_llp64(c->opt->triple), false);
 1233   LLVMBuildRet(c->builder, result);
 1234   codegen_finishfun(c);
 1235 }
 1236 
 1237 static void platform_ilp32(compile_t* c, reach_type_t* t, token_id cap)
 1238 {
 1239   FIND_METHOD("ilp32", cap);
 1240   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1241 
 1242   LLVMValueRef result =
 1243     LLVMConstInt(c->i1, target_is_ilp32(c->opt->triple), false);
 1244   LLVMBuildRet(c->builder, result);
 1245   codegen_finishfun(c);
 1246 }
 1247 
 1248 static void platform_bigendian(compile_t* c, reach_type_t* t, token_id cap)
 1249 {
 1250   FIND_METHOD("bigendian", cap);
 1251   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1252 
 1253   LLVMValueRef result =
 1254     LLVMConstInt(c->i1, target_is_bigendian(c->opt->triple), false);
 1255   LLVMBuildRet(c->builder, result);
 1256   codegen_finishfun(c);
 1257 }
 1258 
 1259 static void platform_littleendian(compile_t* c, reach_type_t* t, token_id cap)
 1260 {
 1261   FIND_METHOD("littleendian", cap);
 1262   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1263 
 1264   LLVMValueRef result =
 1265     LLVMConstInt(c->i1, target_is_littleendian(c->opt->triple), false);
 1266   LLVMBuildRet(c->builder, result);
 1267   codegen_finishfun(c);
 1268 }
 1269 
 1270 static void platform_native128(compile_t* c, reach_type_t* t, token_id cap)
 1271 {
 1272   FIND_METHOD("native128", cap);
 1273   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1274 
 1275   LLVMValueRef result =
 1276     LLVMConstInt(c->i1, target_is_native128(c->opt->triple), false);
 1277   LLVMBuildRet(c->builder, result);
 1278   codegen_finishfun(c);
 1279 }
 1280 
 1281 static void platform_debug(compile_t* c, reach_type_t* t, token_id cap)
 1282 {
 1283   FIND_METHOD("debug", cap);
 1284   start_function(c, t, m, c->i1, &c_t->use_type, 1);
 1285 
 1286   LLVMValueRef result = LLVMConstInt(c->i1, !c->opt->release, false);
 1287   LLVMBuildRet(c->builder, result);
 1288   codegen_finishfun(c);
 1289 }
 1290 
 1291 void genprim_platform_methods(compile_t* c, reach_type_t* t)
 1292 {
 1293   BOX_FUNCTION(platform_freebsd, t);
 1294   BOX_FUNCTION(platform_dragonfly, t);
 1295   BOX_FUNCTION(platform_openbsd, t);
 1296   BOX_FUNCTION(platform_linux, t);
 1297   BOX_FUNCTION(platform_osx, t);
 1298   BOX_FUNCTION(platform_windows, t);
 1299   BOX_FUNCTION(platform_x86, t);
 1300   BOX_FUNCTION(platform_arm, t);
 1301   BOX_FUNCTION(platform_lp64, t);
 1302   BOX_FUNCTION(platform_llp64, t);
 1303   BOX_FUNCTION(platform_ilp32, t);
 1304   BOX_FUNCTION(platform_bigendian, t);
 1305   BOX_FUNCTION(platform_littleendian, t);
 1306   BOX_FUNCTION(platform_native128, t);
 1307   BOX_FUNCTION(platform_debug, t);
 1308 }
 1309 
 1310 typedef struct num_conv_t
 1311 {
 1312   const char* type_name;
 1313   const char* fun_name;
 1314   LLVMTypeRef type;
 1315   int size;
 1316   bool is_signed;
 1317   bool is_float;
 1318 } num_conv_t;
 1319 
 1320 static void number_value(compile_t* c, num_conv_t* type, token_id cap)
 1321 {
 1322   reach_type_t* t = reach_type_name(c->reach, type->type_name);
 1323 
 1324   if(t == NULL)
 1325     return;
 1326 
 1327   FIND_METHOD("_value", cap);
 1328   start_function(c, t, m, type->type, &type->type, 1);
 1329 
 1330   LLVMValueRef arg = LLVMGetParam(c_m->func, 0);
 1331   LLVMBuildRet(c->builder, arg);
 1332 
 1333   codegen_finishfun(c);
 1334 }
 1335 
 1336 static LLVMBasicBlockRef handle_nan(compile_t* c, LLVMValueRef arg,
 1337   LLVMTypeRef int_type, uint64_t exp, uint64_t mantissa)
 1338 {
 1339   LLVMBasicBlockRef nan = codegen_block(c, "");
 1340   LLVMBasicBlockRef non_nan = codegen_block(c, "");
 1341 
 1342   LLVMValueRef exp_mask = LLVMConstInt(int_type, exp, false);
 1343   LLVMValueRef mant_mask = LLVMConstInt(int_type, mantissa, false);
 1344 
 1345   LLVMValueRef bits = LLVMBuildBitCast(c->builder, arg, int_type, "");
 1346   LLVMValueRef exp_res = LLVMBuildAnd(c->builder, bits, exp_mask, "");
 1347   LLVMValueRef mant_res = LLVMBuildAnd(c->builder, bits, mant_mask, "");
 1348 
 1349   exp_res = LLVMBuildICmp(c->builder, LLVMIntEQ, exp_res, exp_mask, "");
 1350   mant_res = LLVMBuildICmp(c->builder, LLVMIntNE, mant_res,
 1351     LLVMConstNull(int_type), "");
 1352 
 1353   LLVMValueRef is_nan = LLVMBuildAnd(c->builder, exp_res, mant_res, "");
 1354   LLVMBuildCondBr(c->builder, is_nan, nan, non_nan);
 1355 
 1356   LLVMPositionBuilderAtEnd(c->builder, nan);
 1357 
 1358   return non_nan;
 1359 }
 1360 
 1361 static LLVMValueRef handle_overflow_saturate(compile_t* c, LLVMValueRef arg,
 1362   LLVMTypeRef from, LLVMTypeRef to, LLVMValueRef to_max, LLVMValueRef to_min,
 1363   bool sign)
 1364 {
 1365   LLVMBasicBlockRef overflow = codegen_block(c, "");
 1366   LLVMBasicBlockRef test_underflow = codegen_block(c, "");
 1367   LLVMBasicBlockRef underflow = codegen_block(c, "");
 1368   LLVMBasicBlockRef normal = codegen_block(c, "");
 1369 
 1370   LLVMValueRef to_fmax;
 1371   if(sign)
 1372     to_fmax = LLVMBuildSIToFP(c->builder, to_max, from, "");
 1373   else
 1374     to_fmax = LLVMBuildUIToFP(c->builder, to_max, from, "");
 1375   LLVMValueRef is_overflow = LLVMBuildFCmp(c->builder, LLVMRealOGT, arg,
 1376     to_fmax, "");
 1377   LLVMBuildCondBr(c->builder, is_overflow, overflow, test_underflow);
 1378 
 1379   LLVMPositionBuilderAtEnd(c->builder, overflow);
 1380   LLVMBuildRet(c->builder, to_max);
 1381 
 1382   LLVMPositionBuilderAtEnd(c->builder, test_underflow);
 1383 
 1384   LLVMValueRef to_fmin;
 1385   if(sign)
 1386     to_fmin = LLVMBuildSIToFP(c->builder, to_min, from, "");
 1387   else
 1388     to_fmin = LLVMBuildUIToFP(c->builder, to_min, from, "");
 1389   LLVMValueRef is_underflow = LLVMBuildFCmp(c->builder, LLVMRealOLT, arg,
 1390     to_fmin, "");
 1391   LLVMBuildCondBr(c->builder, is_underflow, underflow, normal);
 1392 
 1393   LLVMPositionBuilderAtEnd(c->builder, underflow);
 1394   LLVMBuildRet(c->builder, to_min);
 1395 
 1396   LLVMPositionBuilderAtEnd(c->builder, normal);
 1397 
 1398   if(sign)
 1399     return LLVMBuildFPToSI(c->builder, arg, to, "");
 1400   return LLVMBuildFPToUI(c->builder, arg, to, "");
 1401 }
 1402 
 1403 static LLVMValueRef f32_to_si_saturation(compile_t* c, LLVMValueRef arg,
 1404   num_conv_t* to)
 1405 {
 1406   LLVMBasicBlockRef test_overflow = handle_nan(c, arg, c->i32, 0x7F800000,
 1407     0x007FFFFF);
 1408   LLVMBuildRet(c->builder, LLVMConstNull(to->type));
 1409   LLVMPositionBuilderAtEnd(c->builder, test_overflow);
 1410   LLVMValueRef to_max = LLVMConstNull(to->type);
 1411   LLVMValueRef to_min = LLVMBuildNot(c->builder, to_max, "");
 1412   to_max = LLVMBuildLShr(c->builder, to_min, LLVMConstInt(to->type, 1, false),
 1413     "");
 1414   to_min = LLVMBuildXor(c->builder, to_max, to_min, "");
 1415   return handle_overflow_saturate(c, arg, c->f32, to->type, to_max, to_min,
 1416     true);
 1417 }
 1418 
 1419 static LLVMValueRef f64_to_si_saturation(compile_t* c, LLVMValueRef arg,
 1420   num_conv_t* to)
 1421 {
 1422   LLVMBasicBlockRef test_overflow = handle_nan(c, arg, c->i64,
 1423     0x7FF0000000000000, 0x000FFFFFFFFFFFFF);
 1424   LLVMBuildRet(c->builder, LLVMConstNull(to->type));
 1425   LLVMPositionBuilderAtEnd(c->builder, test_overflow);
 1426   LLVMValueRef to_max = LLVMConstNull(to->type);
 1427   LLVMValueRef to_min = LLVMBuildNot(c->builder, to_max, "");
 1428   to_max = LLVMBuildLShr(c->builder, to_min, LLVMConstInt(to->type, 1, false),
 1429     "");
 1430   to_min = LLVMBuildXor(c->builder, to_max, to_min, "");
 1431   return handle_overflow_saturate(c, arg, c->f64, to->type, to_max, to_min,
 1432     true);
 1433 }
 1434 
 1435 static LLVMValueRef f32_to_ui_saturation(compile_t* c, LLVMValueRef arg,
 1436   num_conv_t* to)
 1437 {
 1438   LLVMBasicBlockRef test_overflow = handle_nan(c, arg, c->i32, 0x7F800000,
 1439     0x007FFFFF);
 1440   LLVMBuildRet(c->builder, LLVMConstNull(to->type));
 1441   LLVMPositionBuilderAtEnd(c->builder, test_overflow);
 1442   LLVMValueRef to_min = LLVMConstNull(to->type);
 1443   LLVMValueRef to_max = LLVMBuildNot(c->builder, to_min, "");
 1444   return handle_overflow_saturate(c, arg, c->f32, to->type, to_max, to_min,
 1445     false);
 1446 }
 1447 
 1448 static LLVMValueRef f32_to_u128_saturation(compile_t* c, LLVMValueRef arg)
 1449 {
 1450   LLVMBasicBlockRef test_overflow = handle_nan(c, arg, c->i32, 0x7F800000,
 1451     0x007FFFFF);
 1452   LLVMBuildRet(c->builder, LLVMConstNull(c->i128));
 1453   LLVMPositionBuilderAtEnd(c->builder, test_overflow);
 1454 
 1455   LLVMBasicBlockRef overflow = codegen_block(c, "");
 1456   LLVMBasicBlockRef test_underflow = codegen_block(c, "");
 1457   LLVMBasicBlockRef underflow = codegen_block(c, "");
 1458   LLVMBasicBlockRef normal = codegen_block(c, "");
 1459 
 1460   LLVMValueRef min = LLVMConstNull(c->f32);
 1461   LLVMValueRef max = LLVMConstInf(c->f32, false);
 1462 
 1463   LLVMValueRef is_overflow = LLVMBuildFCmp(c->builder, LLVMRealOGE, arg, max,
 1464     "");
 1465   LLVMBuildCondBr(c->builder, is_overflow, overflow, test_underflow);
 1466 
 1467   LLVMPositionBuilderAtEnd(c->builder, overflow);
 1468   LLVMBuildRet(c->builder, LLVMBuildNot(c->builder, LLVMConstNull(c->i128),
 1469     ""));
 1470 
 1471   LLVMPositionBuilderAtEnd(c->builder, test_underflow);
 1472   LLVMValueRef is_underflow = LLVMBuildFCmp(c->builder, LLVMRealOLT, arg, min,
 1473     "");
 1474   LLVMBuildCondBr(c->builder, is_underflow, underflow, normal);
 1475 
 1476   LLVMPositionBuilderAtEnd(c->builder, underflow);
 1477   LLVMBuildRet(c->builder, LLVMConstNull(c->i128));
 1478 
 1479   LLVMPositionBuilderAtEnd(c->builder, normal);
 1480   return LLVMBuildFPToUI(c->builder, arg, c->i128, "");
 1481 }
 1482 
 1483 static LLVMValueRef f64_to_ui_saturation(compile_t* c, LLVMValueRef arg,
 1484   num_conv_t* to)
 1485 {
 1486   LLVMBasicBlockRef test_overflow = handle_nan(c, arg, c->i64,
 1487     0x7FF0000000000000, 0x000FFFFFFFFFFFFF);
 1488   LLVMBuildRet(c->builder, LLVMConstNull(to->type));
 1489   LLVMPositionBuilderAtEnd(c->builder, test_overflow);
 1490   LLVMValueRef to_min = LLVMConstNull(to->type);
 1491   LLVMValueRef to_max = LLVMBuildNot(c->builder, to_min, "");
 1492   return handle_overflow_saturate(c, arg, c->f64, to->type, to_max, to_min,
 1493     false);
 1494 }
 1495 
 1496 static LLVMValueRef f64_to_f32_saturation(compile_t* c, LLVMValueRef arg)
 1497 {
 1498   LLVMBasicBlockRef test_overflow = handle_nan(c, arg, c->i64,
 1499     0x7FF0000000000000, 0x000FFFFFFFFFFFFF);
 1500   LLVMBuildRet(c->builder, LLVMConstNaN(c->f32));
 1501 
 1502   LLVMBasicBlockRef overflow = codegen_block(c, "");
 1503   LLVMBasicBlockRef test_underflow = codegen_block(c, "");
 1504   LLVMBasicBlockRef underflow = codegen_block(c, "");
 1505   LLVMBasicBlockRef normal = codegen_block(c, "");
 1506 
 1507   LLVMPositionBuilderAtEnd(c->builder, test_overflow);
 1508   LLVMValueRef f32_max = LLVMConstInt(c->i32, 0x7F7FFFFF, false);
 1509   f32_max = LLVMBuildBitCast(c->builder, f32_max, c->f32, "");
 1510   f32_max = LLVMBuildFPExt(c->builder, f32_max, c->f64, "");
 1511   LLVMValueRef is_overflow = LLVMBuildFCmp(c->builder, LLVMRealOGT, arg,
 1512     f32_max, "");
 1513   LLVMBuildCondBr(c->builder, is_overflow, overflow, test_underflow);
 1514 
 1515   LLVMPositionBuilderAtEnd(c->builder, overflow);
 1516   LLVMBuildRet(c->builder, LLVMConstInf(c->f32, false));
 1517 
 1518   LLVMPositionBuilderAtEnd(c->builder, test_underflow);
 1519   LLVMValueRef f32_min = LLVMConstInt(c->i32, 0xFF7FFFFF, false);
 1520   f32_min = LLVMBuildBitCast(c->builder, f32_min, c->f32, "");
 1521   f32_min = LLVMBuildFPExt(c->builder, f32_min, c->f64, "");
 1522   LLVMValueRef is_underflow = LLVMBuildFCmp(c->builder, LLVMRealOLT, arg,
 1523     f32_min, "");
 1524   LLVMBuildCondBr(c->builder, is_underflow, underflow, normal);
 1525 
 1526   LLVMPositionBuilderAtEnd(c->builder, underflow);
 1527   LLVMBuildRet(c->builder, LLVMConstInf(c->f32, true));
 1528 
 1529   LLVMPositionBuilderAtEnd(c->builder, normal);
 1530   return LLVMBuildFPTrunc(c->builder, arg, c->f32, "");
 1531 }
 1532 
 1533 static LLVMValueRef u128_to_f32_saturation(compile_t* c, LLVMValueRef arg)
 1534 {
 1535   LLVMValueRef val_f64 = LLVMBuildUIToFP(c->builder, arg, c->f64, "");
 1536   LLVMValueRef f32_max = LLVMConstInt(c->i32, 0x7F7FFFFF, false);
 1537   f32_max = LLVMBuildBitCast(c->builder, f32_max, c->f32, "");
 1538   f32_max = LLVMBuildFPExt(c->builder, f32_max, c->f64, "");
 1539   LLVMValueRef is_overflow = LLVMBuildFCmp(c->builder, LLVMRealOGT, val_f64,
 1540     f32_max, "");
 1541   LLVMValueRef result = LLVMBuildUIToFP(c->builder, arg, c->f32, "");
 1542   return LLVMBuildSelect(c->builder, is_overflow, LLVMConstInf(c->f32, false),
 1543     result, "");
 1544 }
 1545 
 1546 static void number_conversion(compile_t* c, void** data, token_id cap)
 1547 {
 1548   num_conv_t* from = (num_conv_t*)data[0];
 1549   num_conv_t* to = (num_conv_t*)data[1];
 1550   bool native128 = data[2] != 0;
 1551 
 1552   if(!native128 &&
 1553     ((from->is_float && (to->size > 64)) ||
 1554     (to->is_float && (from->size > 64)))
 1555     )
 1556   {
 1557     return;
 1558   }
 1559 
 1560   reach_type_t* t = reach_type_name(c->reach, from->type_name);
 1561 
 1562   if(t == NULL)
 1563     return;
 1564 
 1565   FIND_METHOD(to->fun_name, cap);
 1566   start_function(c, t, m, to->type, &from->type, 1);
 1567 
 1568   LLVMValueRef arg = LLVMGetParam(c_m->func, 0);
 1569   LLVMValueRef result;
 1570 
 1571   if(from->is_float)
 1572   {
 1573     if(to->is_float)
 1574     {
 1575       if(from->size < to->size)
 1576         result = LLVMBuildFPExt(c->builder, arg, to->type, "");
 1577       else if(from->size > to->size)
 1578         result = f64_to_f32_saturation(c, arg);
 1579       else
 1580         result = arg;
 1581     } else if(to->is_signed) {
 1582       if(from->size < 64)
 1583         result = f32_to_si_saturation(c, arg, to);
 1584       else
 1585         result = f64_to_si_saturation(c, arg, to);
 1586     } else {
 1587       if(from->size < 64)
 1588       {
 1589         if(to->size > 64)
 1590           result = f32_to_u128_saturation(c, arg);
 1591         else
 1592           result = f32_to_ui_saturation(c, arg, to);
 1593       } else
 1594         result = f64_to_ui_saturation(c, arg, to);
 1595     }
 1596   } else if(to->is_float) {
 1597     if(from->is_signed)
 1598       result = LLVMBuildSIToFP(c->builder, arg, to->type, "");
 1599     else if((from->size > 64) && (to->size < 64))
 1600       result = u128_to_f32_saturation(c, arg);
 1601     else
 1602       result = LLVMBuildUIToFP(c->builder, arg, to->type, "");
 1603   } else if(from->size > to->size) {
 1604       result = LLVMBuildTrunc(c->builder, arg, to->type, "");
 1605   } else if(from->size < to->size) {
 1606     if(from->is_signed)
 1607       result = LLVMBuildSExt(c->builder, arg, to->type, "");
 1608     else
 1609       result = LLVMBuildZExt(c->builder, arg, to->type, "");
 1610   } else {
 1611     result = arg;
 1612   }
 1613 
 1614   LLVMBuildRet(c->builder, result);
 1615   codegen_finishfun(c);
 1616 }
 1617 
 1618 static void unsafe_number_conversion(compile_t* c, void** data, token_id cap)
 1619 {
 1620   num_conv_t* from = (num_conv_t*)data[0];
 1621   num_conv_t* to = (num_conv_t*)data[1];
 1622   bool native128 = data[2] != 0;
 1623 
 1624   if(!native128 &&
 1625     ((from->is_float && (to->size > 64)) ||
 1626     (to->is_float && (from->size > 64)))
 1627     )
 1628   {
 1629     return;
 1630   }
 1631 
 1632   reach_type_t* t = reach_type_name(c->reach, from->type_name);
 1633 
 1634   if(t == NULL)
 1635     return;
 1636 
 1637   const char* name = genname_unsafe(to->fun_name);
 1638 
 1639   FIND_METHOD(name, cap);
 1640   start_function(c, t, m, to->type, &from->type, 1);
 1641 
 1642   LLVMValueRef arg = LLVMGetParam(c_m->func, 0);
 1643   LLVMValueRef result;
 1644 
 1645   if(from->is_float)
 1646   {
 1647     if(to->is_float)
 1648     {
 1649       if(from->size < to->size)
 1650         result = LLVMBuildFPExt(c->builder, arg, to->type, "");
 1651       else if(from->size > to->size)
 1652         result = LLVMBuildFPTrunc(c->builder, arg, to->type, "");
 1653       else
 1654         result = arg;
 1655     } else if(to->is_signed) {
 1656       result = LLVMBuildFPToSI(c->builder, arg, to->type, "");
 1657     } else {
 1658       result = LLVMBuildFPToUI(c->builder, arg, to->type, "");
 1659     }
 1660   } else if(to->is_float) {
 1661     if(from->is_signed)
 1662       result = LLVMBuildSIToFP(c->builder, arg, to->type, "");
 1663     else
 1664       result = LLVMBuildUIToFP(c->builder, arg, to->type, "");
 1665   } else if(from->size > to->size) {
 1666       result = LLVMBuildTrunc(c->builder, arg, to->type, "");
 1667   } else if(from->size < to->size) {
 1668     if(from->is_signed)
 1669       result = LLVMBuildSExt(c->builder, arg, to->type, "");
 1670     else
 1671       result = LLVMBuildZExt(c->builder, arg, to->type, "");
 1672   } else {
 1673     result = arg;
 1674   }
 1675 
 1676   LLVMBuildRet(c->builder, result);
 1677   codegen_finishfun(c);
 1678 }
 1679 
 1680 static void number_conversions(compile_t* c)
 1681 {
 1682   num_conv_t ilp32_conv[] =
 1683   {
 1684     {"I8", "i8", c->i8, 8, true, false},
 1685     {"I16", "i16", c->i16, 16, true, false},
 1686     {"I32", "i32", c->i32, 32, true, false},
 1687     {"I64", "i64", c->i64, 64, true, false},
 1688 
 1689     {"U8", "u8", c->i8, 8, false, false},
 1690     {"U16", "u16", c->i16, 16, false, false},
 1691     {"U32", "u32", c->i32, 32, false, false},
 1692     {"U64", "u64", c->i64, 64, false, false},
 1693     {"I128", "i128", c->i128, 128, true, false},
 1694     {"U128", "u128", c->i128, 128, false, false},
 1695 
 1696     {"ILong", "ilong", c->i32, 32, true, false},
 1697     {"ULong", "ulong", c->i32, 32, false, false},
 1698     {"ISize", "isize", c->i32, 32, true, false},
 1699     {"USize", "usize", c->i32, 32, false, false},
 1700 
 1701     {"F32", "f32", c->f32, 32, false, true},
 1702     {"F64", "f64", c->f64, 64, false, true},
 1703 
 1704     {NULL, NULL, NULL, false, false, false}
 1705   };
 1706 
 1707   num_conv_t lp64_conv[] =
 1708   {
 1709     {"I8", "i8", c->i8, 8, true, false},
 1710     {"I16", "i16", c->i16, 16, true, false},
 1711     {"I32", "i32", c->i32, 32, true, false},
 1712     {"I64", "i64", c->i64, 64, true, false},
 1713 
 1714     {"U8", "u8", c->i8, 8, false, false},
 1715     {"U16", "u16", c->i16, 16, false, false},
 1716     {"U32", "u32", c->i32, 32, false, false},
 1717     {"U64", "u64", c->i64, 64, false, false},
 1718     {"I128", "i128", c->i128, 128, true, false},
 1719     {"U128", "u128", c->i128, 128, false, false},
 1720 
 1721     {"ILong", "ilong", c->i64, 64, true, false},
 1722     {"ULong", "ulong", c->i64, 64, false, false},
 1723     {"ISize", "isize", c->i64, 64, true, false},
 1724     {"USize", "usize", c->i64, 64, false, false},
 1725 
 1726     {"F32", "f32", c->f32, 32, false, true},
 1727     {"F64", "f64", c->f64, 64, false, true},
 1728 
 1729     {NULL, NULL, NULL, false, false, false}
 1730   };
 1731 
 1732   num_conv_t llp64_conv[] =
 1733   {
 1734     {"I8", "i8", c->i8, 8, true, false},
 1735     {"I16", "i16", c->i16, 16, true, false},
 1736     {"I32", "i32", c->i32, 32, true, false},
 1737     {"I64", "i64", c->i64, 64, true, false},
 1738 
 1739     {"U8", "u8", c->i8, 8, false, false},
 1740     {"U16", "u16", c->i16, 16, false, false},
 1741     {"U32", "u32", c->i32, 32, false, false},
 1742     {"U64", "u64", c->i64, 64, false, false},
 1743     {"I128", "i128", c->i128, 128, true, false},
 1744     {"U128", "u128", c->i128, 128, false, false},
 1745 
 1746     {"ILong", "ilong", c->i32, 32, true, false},
 1747     {"ULong", "ulong", c->i32, 32, false, false},
 1748     {"ISize", "isize", c->i64, 64, true, false},
 1749     {"USize", "usize", c->i64, 64, false, false},
 1750 
 1751     {"F32", "f32", c->f32, 32, false, true},
 1752     {"F64", "f64", c->f64, 64, false, true},
 1753 
 1754     {NULL, NULL, NULL, false, false, false}
 1755   };
 1756 
 1757   num_conv_t* conv = NULL;
 1758 
 1759   if(target_is_ilp32(c->opt->triple))
 1760     conv = ilp32_conv;
 1761   else if(target_is_lp64(c->opt->triple))
 1762     conv = lp64_conv;
 1763   else if(target_is_llp64(c->opt->triple))
 1764     conv = llp64_conv;
 1765 
 1766   pony_assert(conv != NULL);
 1767 
 1768   void* data[3];
 1769   data[2] = (void*)target_is_native128(c->opt->triple);
 1770 
 1771   for(num_conv_t* from = conv; from->type_name != NULL; from++)
 1772   {
 1773     BOX_FUNCTION(number_value, from);
 1774     data[0] = from;
 1775     for(num_conv_t* to = conv; to->type_name != NULL; to++)
 1776     {
 1777       data[1] = to;
 1778       BOX_FUNCTION(number_conversion, data);
 1779       BOX_FUNCTION(unsafe_number_conversion, data);
 1780     }
 1781   }
 1782 }
 1783 
 1784 static void f32__nan(compile_t* c, reach_type_t* t)
 1785 {
 1786   FIND_METHOD("_nan", TK_NONE);
 1787   start_function(c, t, m, c->f32, &c->f32, 1);
 1788 
 1789   LLVMValueRef result = LLVMConstNaN(c->f32);
 1790   LLVMBuildRet(c->builder, result);
 1791   codegen_finishfun(c);
 1792 }
 1793 
 1794 static void f32__inf(compile_t* c, reach_type_t* t)
 1795 {
 1796   FIND_METHOD("_inf", TK_NONE);
 1797   LLVMTypeRef params[2];
 1798   params[0] = c->f32;
 1799   params[1] = c->i1;
 1800   start_function(c, t, m, c->f32, params, 2);
 1801 
 1802   LLVMValueRef sign = LLVMGetParam(c_m->func, 1);
 1803   LLVMValueRef result = LLVMBuildSelect(c->builder, sign,
 1804     LLVMConstInf(c->f32, true), LLVMConstInf(c->f32, false), "");
 1805   LLVMBuildRet(c->builder, result);
 1806   codegen_finishfun(c);
 1807 }
 1808 
 1809 static void f32_from_bits(compile_t* c, reach_type_t* t)
 1810 {
 1811   FIND_METHOD("from_bits", TK_NONE);
 1812 
 1813   LLVMTypeRef params[2];
 1814   params[0] = c->f32;
 1815   params[1] = c->i32;
 1816   start_function(c, t, m, c->f32, params, 2);
 1817 
 1818   LLVMValueRef result = LLVMBuildBitCast(c->builder, LLVMGetParam(c_m->func, 1),
 1819     c->f32, "");
 1820   LLVMBuildRet(c->builder, result);
 1821   codegen_finishfun(c);
 1822 }
 1823 
 1824 static void f32_bits(compile_t* c, reach_type_t* t, token_id cap)
 1825 {
 1826   FIND_METHOD("bits", cap);
 1827   start_function(c, t, m, c->i32, &c->f32, 1);
 1828 
 1829   LLVMValueRef result = LLVMBuildBitCast(c->builder, LLVMGetParam(c_m->func, 0),
 1830     c->i32, "");
 1831   LLVMBuildRet(c->builder, result);
 1832   codegen_finishfun(c);
 1833 }
 1834 
 1835 static void f64__nan(compile_t* c, reach_type_t* t)
 1836 {
 1837   FIND_METHOD("_nan", TK_NONE);
 1838   start_function(c, t, m, c->f64, &c->f64, 1);
 1839 
 1840   LLVMValueRef result = LLVMConstNaN(c->f64);
 1841   LLVMBuildRet(c->builder, result);
 1842   codegen_finishfun(c);
 1843 }
 1844 
 1845 static void f64__inf(compile_t* c, reach_type_t* t)
 1846 {
 1847   FIND_METHOD("_inf", TK_NONE);
 1848   LLVMTypeRef params[2];
 1849   params[0] = c->f64;
 1850   params[1] = c->i1;
 1851   start_function(c, t, m, c->f64, params, 2);
 1852 
 1853   LLVMValueRef sign = LLVMGetParam(c_m->func, 1);
 1854   LLVMValueRef result = LLVMBuildSelect(c->builder, sign,
 1855     LLVMConstInf(c->f64, true), LLVMConstInf(c->f64, false), "");
 1856   LLVMBuildRet(c->builder, result);
 1857   codegen_finishfun(c);
 1858 }
 1859 
 1860 static void f64_from_bits(compile_t* c, reach_type_t* t)
 1861 {
 1862   FIND_METHOD("from_bits", TK_NONE);
 1863 
 1864   LLVMTypeRef params[2];
 1865   params[0] = c->f64;
 1866   params[1] = c->i64;
 1867   start_function(c, t, m, c->f64, params, 2);
 1868 
 1869   LLVMValueRef result = LLVMBuildBitCast(c->builder, LLVMGetParam(c_m->func, 1),
 1870     c->f64, "");
 1871   LLVMBuildRet(c->builder, result);
 1872   codegen_finishfun(c);
 1873 }
 1874 
 1875 static void f64_bits(compile_t* c, reach_type_t* t, token_id cap)
 1876 {
 1877   FIND_METHOD("bits", cap);
 1878   start_function(c, t, m, c->i64, &c->f64, 1);
 1879 
 1880   LLVMValueRef result = LLVMBuildBitCast(c->builder, LLVMGetParam(c_m->func, 0),
 1881     c->i64, "");
 1882   LLVMBuildRet(c->builder, result);
 1883   codegen_finishfun(c);
 1884 }
 1885 
 1886 static void fp_intrinsics(compile_t* c)
 1887 {
 1888   reach_type_t* t;
 1889 
 1890   if((t = reach_type_name(c->reach, "F32")) != NULL)
 1891   {
 1892     f32__nan(c, t);
 1893     f32__inf(c, t);
 1894     f32_from_bits(c, t);
 1895     BOX_FUNCTION(f32_bits, t);
 1896   }
 1897 
 1898   if((t = reach_type_name(c->reach, "F64")) != NULL)
 1899   {
 1900     f64__nan(c, t);
 1901     f64__inf(c, t);
 1902     f64_from_bits(c, t);
 1903     BOX_FUNCTION(f64_bits, t);
 1904   }
 1905 }
 1906 
 1907 static void make_cpuid(compile_t* c)
 1908 {
 1909   if(target_is_x86(c->opt->triple))
 1910   {
 1911     LLVMTypeRef elems[4] = {c->i32, c->i32, c->i32, c->i32};
 1912     LLVMTypeRef r_type = LLVMStructTypeInContext(c->context, elems, 4, false);
 1913     LLVMTypeRef f_type = LLVMFunctionType(r_type, &c->i32, 1, false);
 1914     LLVMValueRef fun = codegen_addfun(c, "internal.x86.cpuid", f_type, false);
 1915     LLVMSetFunctionCallConv(fun, LLVMCCallConv);
 1916     codegen_startfun(c, fun, NULL, NULL, NULL, false);
 1917 
 1918     LLVMValueRef cpuid = LLVMConstInlineAsm(f_type,
 1919       "cpuid", "={ax},={bx},={cx},={dx},{ax}", false, false);
 1920     LLVMValueRef zero = LLVMConstInt(c->i32, 0, false);
 1921 
 1922     LLVMValueRef result = LLVMBuildCall(c->builder, cpuid, &zero, 1, "");
 1923     LLVMBuildRet(c->builder, result);
 1924 
 1925     codegen_finishfun(c);
 1926   } else {
 1927     (void)c;
 1928   }
 1929 }
 1930 
 1931 static void make_rdtscp(compile_t* c)
 1932 {
 1933   if(target_is_x86(c->opt->triple))
 1934   {
 1935 #if PONY_LLVM >= 800
 1936     // { i64, i32 } @llvm.x86.rdtscp()
 1937     LLVMTypeRef r_type_fields[2] = { c->i64, c->i32 };
 1938     LLVMTypeRef r_type = LLVMStructTypeInContext(c->context, r_type_fields, 2,
 1939       true);
 1940     LLVMTypeRef f_type = LLVMFunctionType(r_type, NULL, 0, false);
 1941     LLVMValueRef rdtscp = LLVMAddFunction(c->module, "llvm.x86.rdtscp", f_type);
 1942 
 1943     // i64 @internal.x86.rdtscp(i32*)
 1944     LLVMTypeRef i32_ptr = LLVMPointerType(c->i32, 0);
 1945     f_type = LLVMFunctionType(c->i64, &i32_ptr, 1, false);
 1946     LLVMValueRef fun = codegen_addfun(c, "internal.x86.rdtscp", f_type, false);
 1947     LLVMSetFunctionCallConv(fun, LLVMCCallConv);
 1948 
 1949     codegen_startfun(c, fun, NULL, NULL, NULL, false);
 1950     LLVMValueRef result = LLVMBuildCall(c->builder, rdtscp, NULL, 0, "");
 1951     LLVMValueRef second = LLVMBuildExtractValue(c->builder, result, 1, "");
 1952     LLVMValueRef argptr = LLVMGetParam(fun, 0);
 1953     LLVMBuildStore(c->builder, second, argptr);
 1954     LLVMValueRef first = LLVMBuildExtractValue(c->builder, result, 0, "");
 1955     LLVMBuildRet(c->builder, first);
 1956     codegen_finishfun(c);
 1957 #else
 1958     // i64 @llvm.x86.rdtscp(i8*)
 1959     LLVMTypeRef f_type = LLVMFunctionType(c->i64, &c->void_ptr, 1, false);
 1960     LLVMValueRef rdtscp = LLVMAddFunction(c->module, "llvm.x86.rdtscp",
 1961       f_type);
 1962 
 1963     // i64 @internal.x86.rdtscp(i32*)
 1964     LLVMTypeRef i32_ptr = LLVMPointerType(c->i32, 0);
 1965     f_type = LLVMFunctionType(c->i64, &i32_ptr, 1, false);
 1966     LLVMValueRef fun = codegen_addfun(c, "internal.x86.rdtscp", f_type, false);
 1967     LLVMSetFunctionCallConv(fun, LLVMCCallConv);
 1968     codegen_startfun(c, fun, NULL, NULL, NULL, false);
 1969 
 1970     // Cast i32* to i8* and call the intrinsic.
 1971     LLVMValueRef arg = LLVMGetParam(fun, 0);
 1972     arg = LLVMBuildBitCast(c->builder, arg, c->void_ptr, "");
 1973     LLVMValueRef result = LLVMBuildCall(c->builder, rdtscp, &arg, 1, "");
 1974     LLVMBuildRet(c->builder, result);
 1975 
 1976     codegen_finishfun(c);
 1977 #endif
 1978   } else {
 1979     (void)c;
 1980   }
 1981 }
 1982 
 1983 static LLVMValueRef make_signature_array(compile_t* c, compile_type_t* c_t,
 1984   const char* signature)
 1985 {
 1986   LLVMValueRef args[SIGNATURE_LENGTH];
 1987 
 1988   for(size_t i = 0; i < SIGNATURE_LENGTH; i++)
 1989     args[i] = LLVMConstInt(c->i8, signature[i], false);
 1990 
 1991   LLVMValueRef sig = LLVMConstArray(c->i8, args, SIGNATURE_LENGTH);
 1992   LLVMValueRef g_sig = LLVMAddGlobal(c->module, LLVMTypeOf(sig), "");
 1993   LLVMSetLinkage(g_sig, LLVMPrivateLinkage);
 1994   LLVMSetInitializer(g_sig, sig);
 1995   LLVMSetGlobalConstant(g_sig, true);
 1996   LLVMSetUnnamedAddr(g_sig, true);
 1997 
 1998   args[0] = LLVMConstInt(c->i32, 0, false);
 1999   args[1] = LLVMConstInt(c->i32, 0, false);
 2000 
 2001   LLVMValueRef ptr = LLVMConstInBoundsGEP(g_sig, args, 2);
 2002 
 2003   args[0] = c_t->desc;
 2004   args[1] = LLVMConstInt(c->intptr, SIGNATURE_LENGTH, false);
 2005   args[2] = args[1];
 2006   args[3] = ptr;
 2007 
 2008   LLVMValueRef inst = LLVMConstNamedStruct(c_t->structure, args, 4);
 2009   LLVMValueRef g_inst = LLVMAddGlobal(c->module, c_t->structure, "");
 2010   LLVMSetInitializer(g_inst, inst);
 2011   LLVMSetGlobalConstant(g_inst, true);
 2012   LLVMSetLinkage(g_inst, LLVMPrivateLinkage);
 2013   LLVMSetUnnamedAddr(g_inst, true);
 2014 
 2015   return g_inst;
 2016 }
 2017 
 2018 void genprim_signature(compile_t* c)
 2019 {
 2020   reach_type_t* t = reach_type_name(c->reach, "Array_U8_val");
 2021 
 2022   if(t == NULL)
 2023     return;
 2024 
 2025   compile_type_t* c_t = (compile_type_t*)t->c_type;
 2026 
 2027   ast_t* def = (ast_t*)ast_data(t->ast);
 2028   pony_assert(def != NULL);
 2029 
 2030   ast_t* program = ast_nearest(def, TK_PROGRAM);
 2031   pony_assert(program != NULL);
 2032 
 2033   const char* signature = program_signature(program);
 2034   LLVMValueRef g_array = make_signature_array(c, c_t, signature);
 2035 
 2036   // Array_U8_val* @internal.signature()
 2037   LLVMTypeRef f_type = LLVMFunctionType(c_t->use_type, NULL, 0, false);
 2038   LLVMValueRef fun = codegen_addfun(c, "internal.signature", f_type, false);
 2039   LLVMSetFunctionCallConv(fun, LLVMCCallConv);
 2040   codegen_startfun(c, fun, NULL, NULL, NULL, false);
 2041   LLVMBuildRet(c->builder, g_array);
 2042   codegen_finishfun(c);
 2043 }
 2044 
 2045 void genprim_builtins(compile_t* c)
 2046 {
 2047   number_conversions(c);
 2048   fp_intrinsics(c);
 2049   make_cpuid(c);
 2050   make_rdtscp(c);
 2051 }
 2052 
 2053 void genprim_reachable_init(compile_t* c, ast_t* program)
 2054 {
 2055   // Look for primitives in all packages that have _init or _final methods.
 2056   // Mark them as reachable.
 2057   ast_t* package = ast_child(program);
 2058 
 2059   while(package != NULL)
 2060   {
 2061     ast_t* module = ast_child(package);
 2062 
 2063     while(module != NULL)
 2064     {
 2065       ast_t* entity = ast_child(module);
 2066 
 2067       while(entity != NULL)
 2068       {
 2069         if(ast_id(entity) == TK_PRIMITIVE)
 2070         {
 2071           AST_GET_CHILDREN(entity, id, typeparams);
 2072 
 2073           if(ast_id(typeparams) == TK_NONE)
 2074           {
 2075             ast_t* type = type_builtin(c->opt, entity, ast_name(id));
 2076             ast_t* finit = ast_get(entity, c->str__init, NULL);
 2077             ast_t* ffinal = ast_get(entity, c->str__final, NULL);
 2078 
 2079             if(finit != NULL)
 2080             {
 2081               reach(c->reach, type, c->str__init, NULL, c->opt);
 2082               ast_free_unattached(finit);
 2083             }
 2084 
 2085             if(ffinal != NULL)
 2086             {
 2087               reach(c->reach, type, c->str__final, NULL, c->opt);
 2088               ast_free_unattached(ffinal);
 2089             }
 2090 
 2091             ast_free_unattached(type);
 2092           }
 2093         }
 2094 
 2095         entity = ast_sibling(entity);
 2096       }
 2097 
 2098       module = ast_sibling(module);
 2099     }
 2100 
 2101     package = ast_sibling(package);
 2102   }
 2103 }