Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2009 VMware, Inc.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28.  
  29. #include "util/u_debug.h"
  30.  
  31. #include "lp_bld_type.h"
  32. #include "lp_bld_const.h"
  33. #include "lp_bld_init.h"
  34.  
  35.  
  36. LLVMTypeRef
  37. lp_build_elem_type(struct gallivm_state *gallivm, struct lp_type type)
  38. {
  39.    if (type.floating) {
  40.       switch(type.width) {
  41.       case 16:
  42.          return LLVMIntTypeInContext(gallivm->context, 16);
  43.          break;
  44.       case 32:
  45.          return LLVMFloatTypeInContext(gallivm->context);
  46.          break;
  47.       case 64:
  48.          return LLVMDoubleTypeInContext(gallivm->context);
  49.          break;
  50.       default:
  51.          assert(0);
  52.          return LLVMFloatTypeInContext(gallivm->context);
  53.       }
  54.    }
  55.    else {
  56.       return LLVMIntTypeInContext(gallivm->context, type.width);
  57.    }
  58. }
  59.  
  60.  
  61. LLVMTypeRef
  62. lp_build_vec_type(struct gallivm_state *gallivm,struct lp_type type)
  63. {
  64.    LLVMTypeRef elem_type = lp_build_elem_type(gallivm, type);
  65.    if (type.length == 1)
  66.       return elem_type;
  67.    else
  68.       return LLVMVectorType(elem_type, type.length);
  69. }
  70.  
  71.  
  72. /**
  73.  * This function is a mirror of lp_build_elem_type() above.
  74.  *
  75.  * XXX: I'm not sure if it wouldn't be easier/efficient to just recreate the
  76.  * type and check for identity.
  77.  */
  78. boolean
  79. lp_check_elem_type(struct lp_type type, LLVMTypeRef elem_type)
  80. {
  81.    LLVMTypeKind elem_kind;
  82.  
  83.    assert(elem_type);
  84.    if(!elem_type)
  85.       return FALSE;
  86.  
  87.    elem_kind = LLVMGetTypeKind(elem_type);
  88.  
  89.    if (type.floating) {
  90.       switch(type.width) {
  91.       case 16:
  92.          if(elem_kind != LLVMIntegerTypeKind)
  93.             return FALSE;
  94.          break;
  95.       case 32:
  96.          if(elem_kind != LLVMFloatTypeKind)
  97.             return FALSE;
  98.          break;
  99.       case 64:
  100.          if(elem_kind != LLVMDoubleTypeKind)
  101.             return FALSE;
  102.          break;
  103.       default:
  104.          assert(0);
  105.          return FALSE;
  106.       }
  107.    }
  108.    else {
  109.       if(elem_kind != LLVMIntegerTypeKind)
  110.          return FALSE;
  111.  
  112.       if(LLVMGetIntTypeWidth(elem_type) != type.width)
  113.          return FALSE;
  114.    }
  115.  
  116.    return TRUE;
  117. }
  118.  
  119.  
  120. boolean
  121. lp_check_vec_type(struct lp_type type, LLVMTypeRef vec_type)
  122. {
  123.    LLVMTypeRef elem_type;
  124.  
  125.    assert(vec_type);
  126.    if(!vec_type)
  127.       return FALSE;
  128.  
  129.    if (type.length == 1)
  130.       return lp_check_elem_type(type, vec_type);
  131.  
  132.    if(LLVMGetTypeKind(vec_type) != LLVMVectorTypeKind)
  133.       return FALSE;
  134.  
  135.    if(LLVMGetVectorSize(vec_type) != type.length)
  136.       return FALSE;
  137.  
  138.    elem_type = LLVMGetElementType(vec_type);
  139.  
  140.    return lp_check_elem_type(type, elem_type);
  141. }
  142.  
  143.  
  144. boolean
  145. lp_check_value(struct lp_type type, LLVMValueRef val)
  146. {
  147.    LLVMTypeRef vec_type;
  148.  
  149.    assert(val);
  150.    if(!val)
  151.       return FALSE;
  152.  
  153.    vec_type = LLVMTypeOf(val);
  154.  
  155.    return lp_check_vec_type(type, vec_type);
  156. }
  157.  
  158.  
  159. LLVMTypeRef
  160. lp_build_int_elem_type(struct gallivm_state *gallivm, struct lp_type type)
  161. {
  162.    return LLVMIntTypeInContext(gallivm->context, type.width);
  163. }
  164.  
  165.  
  166. LLVMTypeRef
  167. lp_build_int_vec_type(struct gallivm_state *gallivm, struct lp_type type)
  168. {
  169.    LLVMTypeRef elem_type = lp_build_int_elem_type(gallivm, type);
  170.    if (type.length == 1)
  171.       return elem_type;
  172.    else
  173.       return LLVMVectorType(elem_type, type.length);
  174. }
  175.  
  176.  
  177. /**
  178.  * Create element of vector type
  179.  */
  180. struct lp_type
  181. lp_elem_type(struct lp_type type)
  182. {
  183.    struct lp_type res_type;
  184.  
  185.    assert(type.length > 1);
  186.    res_type = type;
  187.    res_type.length = 1;
  188.  
  189.    return res_type;
  190. }
  191.  
  192.  
  193. /**
  194.  * Create unsigned integer type variation of given type.
  195.  */
  196. struct lp_type
  197. lp_uint_type(struct lp_type type)
  198. {
  199.    struct lp_type res_type;
  200.  
  201.    assert(type.length <= LP_MAX_VECTOR_LENGTH);
  202.    memset(&res_type, 0, sizeof res_type);
  203.    res_type.width = type.width;
  204.    res_type.length = type.length;
  205.  
  206.    return res_type;
  207. }
  208.  
  209.  
  210. /**
  211.  * Create signed integer type variation of given type.
  212.  */
  213. struct lp_type
  214. lp_int_type(struct lp_type type)
  215. {
  216.    struct lp_type res_type;
  217.  
  218.    assert(type.length <= LP_MAX_VECTOR_LENGTH);
  219.    memset(&res_type, 0, sizeof res_type);
  220.    res_type.width = type.width;
  221.    res_type.length = type.length;
  222.    res_type.sign = 1;
  223.  
  224.    return res_type;
  225. }
  226.  
  227.  
  228. /**
  229.  * Return the type with twice the bit width (hence half the number of elements).
  230.  */
  231. struct lp_type
  232. lp_wider_type(struct lp_type type)
  233. {
  234.    struct lp_type res_type;
  235.  
  236.    memcpy(&res_type, &type, sizeof res_type);
  237.    res_type.width *= 2;
  238.    res_type.length /= 2;
  239.  
  240.    assert(res_type.length);
  241.  
  242.    return res_type;
  243. }
  244.  
  245.  
  246. /**
  247.  * Return the size of the LLVMType in bits.
  248.  * XXX this function doesn't necessarily handle all LLVM types.
  249.  */
  250. unsigned
  251. lp_sizeof_llvm_type(LLVMTypeRef t)
  252. {
  253.    LLVMTypeKind k = LLVMGetTypeKind(t);
  254.  
  255.    switch (k) {
  256.    case LLVMIntegerTypeKind:
  257.       return LLVMGetIntTypeWidth(t);
  258.    case LLVMFloatTypeKind:
  259.       return 8 * sizeof(float);
  260.    case LLVMDoubleTypeKind:
  261.       return 8 * sizeof(double);
  262.    case LLVMVectorTypeKind:
  263.       {
  264.          LLVMTypeRef elem = LLVMGetElementType(t);
  265.          unsigned len = LLVMGetVectorSize(t);
  266.          return len * lp_sizeof_llvm_type(elem);
  267.       }
  268.       break;
  269.    case LLVMArrayTypeKind:
  270.       {
  271.          LLVMTypeRef elem = LLVMGetElementType(t);
  272.          unsigned len = LLVMGetArrayLength(t);
  273.          return len * lp_sizeof_llvm_type(elem);
  274.       }
  275.       break;
  276.    default:
  277.       assert(0 && "Unexpected type in lp_get_llvm_type_size()");
  278.       return 0;
  279.    }
  280. }
  281.  
  282.  
  283. /**
  284.  * Return string name for a LLVMTypeKind.  Useful for debugging.
  285.  */
  286. const char *
  287. lp_typekind_name(LLVMTypeKind t)
  288. {
  289.    switch (t) {
  290.    case LLVMVoidTypeKind:
  291.       return "LLVMVoidTypeKind";
  292.    case LLVMFloatTypeKind:
  293.       return "LLVMFloatTypeKind";
  294.    case LLVMDoubleTypeKind:
  295.       return "LLVMDoubleTypeKind";
  296.    case LLVMX86_FP80TypeKind:
  297.       return "LLVMX86_FP80TypeKind";
  298.    case LLVMFP128TypeKind:
  299.       return "LLVMFP128TypeKind";
  300.    case LLVMPPC_FP128TypeKind:
  301.       return "LLVMPPC_FP128TypeKind";
  302.    case LLVMLabelTypeKind:
  303.       return "LLVMLabelTypeKind";
  304.    case LLVMIntegerTypeKind:
  305.       return "LLVMIntegerTypeKind";
  306.    case LLVMFunctionTypeKind:
  307.       return "LLVMFunctionTypeKind";
  308.    case LLVMStructTypeKind:
  309.       return "LLVMStructTypeKind";
  310.    case LLVMArrayTypeKind:
  311.       return "LLVMArrayTypeKind";
  312.    case LLVMPointerTypeKind:
  313.       return "LLVMPointerTypeKind";
  314. #if HAVE_LLVM < 0x0300
  315.    case LLVMOpaqueTypeKind:
  316.       return "LLVMOpaqueTypeKind";
  317. #endif
  318.    case LLVMVectorTypeKind:
  319.       return "LLVMVectorTypeKind";
  320.    case LLVMMetadataTypeKind:
  321.       return "LLVMMetadataTypeKind";
  322. #if HAVE_LLVM == 0x0207
  323.    case LLVMUnionTypeKind:
  324.       return "LLVMUnionTypeKind";
  325. #endif
  326.    default:
  327.       return "unknown LLVMTypeKind";
  328.    }
  329. }
  330.  
  331.  
  332. /**
  333.  * Print an LLVMTypeRef.  Like LLVMDumpValue().  For debugging.
  334.  */
  335. void
  336. lp_dump_llvmtype(LLVMTypeRef t)
  337. {
  338.    LLVMTypeKind k = LLVMGetTypeKind(t);
  339.  
  340.    if (k == LLVMVectorTypeKind) {
  341.       LLVMTypeRef te = LLVMGetElementType(t);
  342.       LLVMTypeKind ke = LLVMGetTypeKind(te);
  343.       unsigned len = LLVMGetVectorSize(t);
  344.       if (ke == LLVMIntegerTypeKind) {
  345.          unsigned b = LLVMGetIntTypeWidth(te);
  346.          debug_printf("Vector [%u] of %u-bit Integer\n", len, b);
  347.       }
  348.       else {
  349.          debug_printf("Vector [%u] of %s\n", len, lp_typekind_name(ke));
  350.       }
  351.    }
  352.    else if (k == LLVMArrayTypeKind) {
  353.       LLVMTypeRef te = LLVMGetElementType(t);
  354.       LLVMTypeKind ke = LLVMGetTypeKind(te);
  355.       unsigned len = LLVMGetArrayLength(t);
  356.       debug_printf("Array [%u] of %s\n", len, lp_typekind_name(ke));
  357.    }
  358.    else if (k == LLVMIntegerTypeKind) {
  359.       unsigned b = LLVMGetIntTypeWidth(t);
  360.       debug_printf("%u-bit Integer\n", b);
  361.    }
  362.    else if (k == LLVMPointerTypeKind) {
  363.       LLVMTypeRef te = LLVMGetElementType(t);
  364.       debug_printf("Pointer to ");
  365.       lp_dump_llvmtype(te);
  366.    }
  367.    else {
  368.       debug_printf("%s\n", lp_typekind_name(k));
  369.    }
  370. }
  371.  
  372.  
  373. void
  374. lp_build_context_init(struct lp_build_context *bld,
  375.                       struct gallivm_state *gallivm,
  376.                       struct lp_type type)
  377. {
  378.    bld->gallivm = gallivm;
  379.    bld->type = type;
  380.  
  381.    bld->int_elem_type = lp_build_int_elem_type(gallivm, type);
  382.    if (type.floating)
  383.       bld->elem_type = lp_build_elem_type(gallivm, type);
  384.    else
  385.       bld->elem_type = bld->int_elem_type;
  386.  
  387.    if (type.length == 1) {
  388.       bld->int_vec_type = bld->int_elem_type;
  389.       bld->vec_type = bld->elem_type;
  390.    }
  391.    else {
  392.       bld->int_vec_type = LLVMVectorType(bld->int_elem_type, type.length);
  393.       bld->vec_type = LLVMVectorType(bld->elem_type, type.length);
  394.    }
  395.  
  396.    bld->undef = LLVMGetUndef(bld->vec_type);
  397.    bld->zero = LLVMConstNull(bld->vec_type);
  398.    bld->one = lp_build_one(gallivm, type);
  399. }
  400.  
  401.  
  402. /**
  403.  * Count the number of instructions in a function.
  404.  */
  405. unsigned
  406. lp_build_count_instructions(LLVMValueRef function)
  407. {
  408.    unsigned num_instrs = 0;
  409.    LLVMBasicBlockRef block;
  410.  
  411.    block = LLVMGetFirstBasicBlock(function);
  412.    while (block) {
  413.       LLVMValueRef instr;
  414.       instr = LLVMGetFirstInstruction(block);
  415.       while (instr) {
  416.          ++num_instrs;
  417.  
  418.          instr = LLVMGetNextInstruction(instr);
  419.       }
  420.       block = LLVMGetNextBasicBlock(block);
  421.    }
  422.  
  423.    return num_instrs;
  424. }
  425.