PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/sasl/src/codegen/cgs_sisd.cpp

#
C++ | 344 lines | 271 code | 66 blank | 7 comment | 22 complexity | 39a38dec81aaa121b0dd3bad6271c1fc MD5 | raw file
Possible License(s): BSD-3-Clause, JSON, MPL-2.0-no-copyleft-exception, GPL-2.0, GPL-3.0, LGPL-3.0, BSD-2-Clause, LGPL-2.1
  1. #include <sasl/include/codegen/cgs_sisd.h>
  2. #include <sasl/include/syntax_tree/declaration.h>
  3. #include <sasl/include/semantic/symbol.h>
  4. #include <sasl/include/semantic/semantics.h>
  5. #include <sasl/include/codegen/cg_contexts.h>
  6. #include <sasl/enums/enums_utility.h>
  7. #include <eflib/include/diagnostics/assert.h>
  8. #include <eflib/include/platform/cpuinfo.h>
  9. #include <eflib/include/utility/unref_declarator.h>
  10. #include <eflib/include/platform/disable_warnings.h>
  11. #include <llvm/IR/IRBuilder.h>
  12. #include <llvm/IR/Function.h>
  13. #include <llvm/IR/Module.h>
  14. #include <llvm/IR/Intrinsics.h>
  15. #include <llvm/IR/TypeBuilder.h>
  16. #include <llvm/Support/CFG.h>
  17. #include <eflib/include/platform/enable_warnings.h>
  18. #include <eflib/include/platform/boost_begin.h>
  19. #include <boost/unordered_map.hpp>
  20. #include <boost/lexical_cast.hpp>
  21. #include <eflib/include/platform/boost_end.h>
  22. using sasl::syntax_tree::node;
  23. using sasl::syntax_tree::function_full_def;
  24. using sasl::syntax_tree::parameter_full;
  25. using sasl::syntax_tree::tynode;
  26. using sasl::syntax_tree::declaration;
  27. using sasl::syntax_tree::variable_declaration;
  28. using sasl::syntax_tree::struct_type;
  29. using sasl::semantic::node_semantic;
  30. using sasl::semantic::node_semantic;
  31. using eflib::support_feature;
  32. using eflib::cpu_sse2;
  33. using namespace sasl::utility;
  34. using llvm::APInt;
  35. using llvm::Argument;
  36. using llvm::LLVMContext;
  37. using llvm::Function;
  38. using llvm::FunctionType;
  39. using llvm::IntegerType;
  40. using llvm::Type;
  41. using llvm::PointerType;
  42. using llvm::Value;
  43. using llvm::BasicBlock;
  44. using llvm::Constant;
  45. using llvm::ConstantInt;
  46. using llvm::ConstantVector;
  47. using llvm::StructType;
  48. using llvm::VectorType;
  49. using llvm::UndefValue;
  50. using llvm::StoreInst;
  51. using llvm::TypeBuilder;
  52. using llvm::SwitchInst;
  53. using llvm::CmpInst;
  54. using llvm::PHINode;
  55. using llvm::DefaultIRBuilder;
  56. namespace Intrinsic = llvm::Intrinsic;
  57. using boost::any;
  58. using boost::shared_ptr;
  59. using boost::enable_if;
  60. using boost::is_integral;
  61. using boost::unordered_map;
  62. using boost::lexical_cast;
  63. using std::vector;
  64. using std::string;
  65. BEGIN_NS_SASL_CODEGEN();
  66. namespace {
  67. template <typename T> APInt apint( T v )
  68. {
  69. return APInt( sizeof(v) << 3, static_cast<uint64_t>(v), boost::is_signed<T>::value );
  70. }
  71. void mask_to_indexes( char indexes[4], uint32_t mask ){
  72. for( int i = 0; i < 4; ++i ){
  73. // XYZW is 1,2,3,4 but LLVM used 0,1,2,3
  74. char comp_index = static_cast<char>( (mask >> i*8) & 0xFF );
  75. if( comp_index == 0 ){
  76. indexes[i] = -1;
  77. break;
  78. }
  79. indexes[i] = comp_index - 1;
  80. }
  81. }
  82. uint32_t indexes_to_mask( char indexes[4] ){
  83. uint32_t mask = 0;
  84. for( int i = 0; i < 4; ++i ){
  85. mask += (uint32_t)( (indexes[i] + 1) << (i*8) );
  86. }
  87. return mask;
  88. }
  89. uint32_t indexes_to_mask( char idx0, char idx1, char idx2, char idx3 ){
  90. char indexes[4] = { idx0, idx1, idx2, idx3 };
  91. return indexes_to_mask( indexes );
  92. }
  93. void dbg_print_blocks( Function* fn ){
  94. #ifdef _DEBUG
  95. /*printf( "Function: 0x%X\n", fn );
  96. for( Function::BasicBlockListType::iterator it = fn->getBasicBlockList().begin(); it != fn->getBasicBlockList().end(); ++it ){
  97. printf( " Block: 0x%X\n", &(*it) );
  98. }*/
  99. fn = fn;
  100. #else
  101. fn = fn;
  102. #endif
  103. }
  104. }
  105. cgs_sisd::cgs_sisd()
  106. : cg_service(1)
  107. {
  108. }
  109. void cgs_sisd::store( multi_value& lhs, multi_value const& rhs ){
  110. assert(parallel_factor_ == 1);
  111. value_array src(parallel_factor_, NULL);
  112. value_array address(parallel_factor_, NULL);
  113. value_kinds kind = lhs.kind();
  114. if( kind == value_kinds::reference ){
  115. src = rhs.load( lhs.abi() );
  116. address = lhs.raw();
  117. } else if ( kind == value_kinds::elements ){
  118. elem_indexes indexes;
  119. multi_value const* root = NULL;
  120. bool is_swizzle = merge_swizzle(root, indexes, lhs);
  121. if( is_swizzle && is_vector( root->hint()) ){
  122. assert( lhs.parent()->storable() );
  123. multi_value rhs_rvalue = rhs.to_rvalue();
  124. multi_value ret_v = root->to_rvalue();
  125. for(size_t i = 0; i < vector_size(rhs.hint()); ++i)
  126. {
  127. ret_v = emit_insert_val( ret_v, indexes[i], emit_extract_val(rhs_rvalue, i) );
  128. }
  129. src = ret_v.load( lhs.abi() );
  130. address = root->load_ref();
  131. } else {
  132. src = rhs.load( lhs.abi() );
  133. address = lhs.load_ref();
  134. }
  135. }
  136. assert( valid_all(src) );
  137. assert( valid_all(address) );
  138. ext_->store(src, address);
  139. }
  140. multi_value cgs_sisd::cast_ints( multi_value const& v, cg_type* dest_tyi )
  141. {
  142. builtin_types hint_src = v.hint();
  143. builtin_types hint_dst = dest_tyi->hint();
  144. builtin_types scalar_hint_src = scalar_of(hint_src);
  145. Type* dest_ty = dest_tyi->ty(v.abi());
  146. Type* elem_ty = type_( scalar_of(hint_dst), abis::llvm );
  147. cast_ops::id op = is_signed(scalar_hint_src) ? cast_ops::i2i_signed : cast_ops::i2i_unsigned;
  148. unary_intrin_functor cast_sv_fn = ext_->bind_cast_sv(elem_ty, op);
  149. value_array val = ext_->call_unary_intrin(dest_ty, v.load(), cast_sv_fn);
  150. return create_value( dest_tyi, builtin_types::none, val, value_kinds::value, v.abi() );
  151. }
  152. multi_value cgs_sisd::cast_i2f( multi_value const& v, cg_type* dest_tyi )
  153. {
  154. builtin_types hint_i = v.hint();
  155. builtin_types hint_f = dest_tyi->hint();
  156. builtin_types scalar_hint_i = scalar_of(hint_i);
  157. Type* dest_ty = dest_tyi->ty(v.abi());
  158. Type* elem_ty = type_( scalar_of(hint_f), abis::llvm );
  159. cast_ops::id op = is_signed(hint_i) ? cast_ops::i2f : cast_ops::u2f;
  160. unary_intrin_functor cast_sv_fn = ext_->bind_cast_sv(elem_ty, op);
  161. value_array val = ext_->call_unary_intrin(dest_ty, v.load(), cast_sv_fn);
  162. return create_value( dest_tyi, builtin_types::none, val, value_kinds::value, v.abi() );
  163. }
  164. multi_value cgs_sisd::cast_f2i( multi_value const& v, cg_type* dest_tyi )
  165. {
  166. builtin_types hint_i = dest_tyi->hint();
  167. builtin_types hint_f = v.hint();
  168. builtin_types scalar_hint_i = scalar_of(hint_i);
  169. Type* dest_ty = dest_tyi->ty(v.abi());
  170. Type* elem_ty = type_( scalar_of(hint_i), abis::llvm );
  171. cast_ops::id op = is_signed(hint_i) ? cast_ops::f2i : cast_ops::f2u;
  172. unary_intrin_functor cast_sv_fn = ext_->bind_cast_sv(elem_ty, op);
  173. value_array val = ext_->call_unary_intrin(dest_ty, v.load(), cast_sv_fn);
  174. return create_value( dest_tyi, builtin_types::none, val, value_kinds::value, v.abi() );
  175. }
  176. multi_value cgs_sisd::cast_f2f( multi_value const& v, cg_type* dest_tyi )
  177. {
  178. EFLIB_UNREF_DECLARATOR(v);
  179. EFLIB_UNREF_DECLARATOR(dest_tyi);
  180. EFLIB_ASSERT_UNIMPLEMENTED();
  181. return multi_value();
  182. }
  183. multi_value cgs_sisd::create_vector( std::vector<multi_value> const& scalars, abis abi ){
  184. builtin_types scalar_hint = scalars[0].hint();
  185. builtin_types hint = vector_of(scalar_hint, scalars.size());
  186. multi_value ret = undef_value(hint, abi);
  187. for( size_t i = 0; i < scalars.size(); ++i )
  188. {
  189. ret = emit_insert_val( ret, (int)i, scalars[i] );
  190. }
  191. return ret;
  192. }
  193. void cgs_sisd::emit_return(){
  194. builder().CreateRetVoid();
  195. }
  196. void cgs_sisd::emit_return( multi_value const& ret_v, abis abi ){
  197. if( abi == abis::unknown ){ abi = fn().abi(); }
  198. if( fn().return_via_arg() )
  199. {
  200. ext_->store( ret_v.load(abi), fn().return_address() );
  201. builder().CreateRetVoid();
  202. }
  203. else
  204. {
  205. Value* ret_value = NULL;
  206. if ( fn().multi_value_args() ) {
  207. ret_value = ext_->get_array( ret_v.load(abi) );
  208. } else {
  209. ret_value = ret_v.load(abi)[0];
  210. }
  211. builder().CreateRet(ret_value);
  212. }
  213. }
  214. Value* cgs_sisd::select_( Value* cond, Value* yes, Value* no )
  215. {
  216. return builder().CreateSelect( cond, yes, no );
  217. }
  218. bool cgs_sisd::prefer_externals() const
  219. {
  220. return false;
  221. }
  222. bool cgs_sisd::prefer_scalar_code() const
  223. {
  224. return false;
  225. }
  226. multi_value cgs_sisd::emit_swizzle( multi_value const& lhs, uint32_t mask )
  227. {
  228. EFLIB_UNREF_DECLARATOR(lhs);
  229. EFLIB_UNREF_DECLARATOR(mask);
  230. EFLIB_ASSERT_UNIMPLEMENTED();
  231. return multi_value();
  232. }
  233. multi_value cgs_sisd::emit_write_mask( multi_value const& vec, uint32_t mask )
  234. {
  235. EFLIB_ASSERT_UNIMPLEMENTED();
  236. EFLIB_UNREF_DECLARATOR(vec);
  237. EFLIB_UNREF_DECLARATOR(mask);
  238. return multi_value();
  239. }
  240. void cgs_sisd::switch_to( multi_value const& cond, std::vector< std::pair<multi_value, insert_point_t> > const& cases, insert_point_t const& default_branch )
  241. {
  242. assert(parallel_factor_ == 1);
  243. Value* v = cond.load()[0];
  244. SwitchInst* inst = builder().CreateSwitch( v, default_branch.block, static_cast<unsigned>(cases.size()) );
  245. for( size_t i_case = 0; i_case < cases.size(); ++i_case ){
  246. inst->addCase( llvm::cast<ConstantInt>( cases[i_case].first.load()[0] ), cases[i_case].second.block );
  247. }
  248. }
  249. multi_value cgs_sisd::cast_i2b( multi_value const& v )
  250. {
  251. assert( is_integer(v.hint()) );
  252. return emit_cmp_ne( v, null_value( v.hint(), v.abi() ) );
  253. }
  254. multi_value cgs_sisd::cast_f2b( multi_value const& v )
  255. {
  256. assert( is_real(v.hint()) );
  257. return emit_cmp_ne( v, null_value( v.hint(), v.abi() ) );
  258. }
  259. multi_value cgs_sisd::emit_ddx( multi_value const& v )
  260. {
  261. // It is not available in SISD mode.
  262. EFLIB_ASSERT_UNIMPLEMENTED();
  263. return v;
  264. }
  265. multi_value cgs_sisd::emit_ddy( multi_value const& v )
  266. {
  267. // It is not available in SISD mode.
  268. EFLIB_ASSERT_UNIMPLEMENTED();
  269. return v;
  270. }
  271. Value* cgs_sisd::phi_( BasicBlock* b0, Value* v0, BasicBlock* b1, Value* v1 )
  272. {
  273. PHINode* phi = builder().CreatePHI( v0->getType(), 2 );
  274. phi->addIncoming(v0, b0);
  275. phi->addIncoming(v1, b1);
  276. return phi;
  277. }
  278. END_NS_SASL_CODEGEN();