Subversion Repositories Kolibri OS

Rev

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.    case LLVMVectorTypeKind:
  315.       return "LLVMVectorTypeKind";
  316.    case LLVMMetadataTypeKind:
  317.       return "LLVMMetadataTypeKind";
  318.    default:
  319.       return "unknown LLVMTypeKind";
  320.    }
  321. }
  322.  
  323.  
  324. /**
  325.  * Print an LLVMTypeRef.  Like LLVMDumpValue().  For debugging.
  326.  */
  327. void
  328. lp_dump_llvmtype(LLVMTypeRef t)
  329. {
  330.    LLVMTypeKind k = LLVMGetTypeKind(t);
  331.  
  332.    if (k == LLVMVectorTypeKind) {
  333.       LLVMTypeRef te = LLVMGetElementType(t);
  334.       LLVMTypeKind ke = LLVMGetTypeKind(te);
  335.       unsigned len = LLVMGetVectorSize(t);
  336.       if (ke == LLVMIntegerTypeKind) {
  337.          unsigned b = LLVMGetIntTypeWidth(te);
  338.          debug_printf("Vector [%u] of %u-bit Integer\n", len, b);
  339.       }
  340.       else {
  341.          debug_printf("Vector [%u] of %s\n", len, lp_typekind_name(ke));
  342.       }
  343.    }
  344.    else if (k == LLVMArrayTypeKind) {
  345.       LLVMTypeRef te = LLVMGetElementType(t);
  346.       LLVMTypeKind ke = LLVMGetTypeKind(te);
  347.       unsigned len = LLVMGetArrayLength(t);
  348.       debug_printf("Array [%u] of %s\n", len, lp_typekind_name(ke));
  349.    }
  350.    else if (k == LLVMIntegerTypeKind) {
  351.       unsigned b = LLVMGetIntTypeWidth(t);
  352.       debug_printf("%u-bit Integer\n", b);
  353.    }
  354.    else if (k == LLVMPointerTypeKind) {
  355.       LLVMTypeRef te = LLVMGetElementType(t);
  356.       debug_printf("Pointer to ");
  357.       lp_dump_llvmtype(te);
  358.    }
  359.    else {
  360.       debug_printf("%s\n", lp_typekind_name(k));
  361.    }
  362. }
  363.  
  364.  
  365. void
  366. lp_build_context_init(struct lp_build_context *bld,
  367.                       struct gallivm_state *gallivm,
  368.                       struct lp_type type)
  369. {
  370.    bld->gallivm = gallivm;
  371.    bld->type = type;
  372.  
  373.    bld->int_elem_type = lp_build_int_elem_type(gallivm, type);
  374.    if (type.floating)
  375.       bld->elem_type = lp_build_elem_type(gallivm, type);
  376.    else
  377.       bld->elem_type = bld->int_elem_type;
  378.  
  379.    if (type.length == 1) {
  380.       bld->int_vec_type = bld->int_elem_type;
  381.       bld->vec_type = bld->elem_type;
  382.    }
  383.    else {
  384.       bld->int_vec_type = LLVMVectorType(bld->int_elem_type, type.length);
  385.       bld->vec_type = LLVMVectorType(bld->elem_type, type.length);
  386.    }
  387.  
  388.    bld->undef = LLVMGetUndef(bld->vec_type);
  389.    bld->zero = LLVMConstNull(bld->vec_type);
  390.    bld->one = lp_build_one(gallivm, type);
  391. }
  392.  
  393.  
  394. /**
  395.  * Count the number of instructions in a function.
  396.  */
  397. static unsigned
  398. lp_build_count_instructions(LLVMValueRef function)
  399. {
  400.    unsigned num_instrs = 0;
  401.    LLVMBasicBlockRef block;
  402.  
  403.    block = LLVMGetFirstBasicBlock(function);
  404.    while (block) {
  405.       LLVMValueRef instr;
  406.       instr = LLVMGetFirstInstruction(block);
  407.       while (instr) {
  408.          ++num_instrs;
  409.  
  410.          instr = LLVMGetNextInstruction(instr);
  411.       }
  412.       block = LLVMGetNextBasicBlock(block);
  413.    }
  414.  
  415.    return num_instrs;
  416. }
  417.  
  418.  
  419. /**
  420.  * Count the number of instructions in a module.
  421.  */
  422. unsigned
  423. lp_build_count_ir_module(LLVMModuleRef module)
  424. {
  425.    LLVMValueRef func;
  426.    unsigned num_instrs = 0;
  427.  
  428.    func = LLVMGetFirstFunction(module);
  429.    while (func) {
  430.       num_instrs += lp_build_count_instructions(func);
  431.       func = LLVMGetNextFunction(func);
  432.    }
  433.    return num_instrs;
  434. }
  435.