xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/brig/brigfrontend/brig-seg-inst-handler.cc (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1 /* brig-seg-inst-handler.cc -- brig segment related instruction handling
2    Copyright (C) 2016-2020 Free Software Foundation, Inc.
3    Contributed by Pekka Jaaskelainen <pekka.jaaskelainen@parmance.com>
4    for General Processor Tech.
5 
6 This file is part of GCC.
7 
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12 
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21 
22 #include <sstream>
23 
24 #include "brig-code-entry-handler.h"
25 #include "brig-util.h"
26 #include "convert.h"
27 #include "tree-pretty-print.h"
28 #include "errors.h"
29 #include "diagnostic-core.h"
30 
brig_seg_inst_handler(brig_to_generic & parent)31 brig_seg_inst_handler::brig_seg_inst_handler (brig_to_generic &parent)
32   : brig_code_entry_handler (parent)
33 {
34 }
35 
36 size_t
operator ()(const BrigBase * base)37 brig_seg_inst_handler::operator () (const BrigBase *base)
38 {
39   const BrigInstBase &inst_base = *(const BrigInstBase *) base;
40 
41   std::vector<tree> operands = build_operands (inst_base);
42 
43   tree expr = NULL_TREE;
44 
45   if (inst_base.opcode == BRIG_OPCODE_STOF)
46     {
47       const BrigInstSegCvt &inst = *(const BrigInstSegCvt *) base;
48 
49       if (inst.segment == BRIG_SEGMENT_GROUP)
50 	expr = build2 (PLUS_EXPR, size_type_node,
51 		       convert_to_integer (size_type_node,
52 					   m_parent.m_cf->m_group_base_arg),
53 		       convert_to_integer (size_type_node, operands[1]));
54       else if (inst.segment == BRIG_SEGMENT_PRIVATE
55 	       || inst.segment == BRIG_SEGMENT_SPILL)
56 	expr = build2 (PLUS_EXPR, size_type_node,
57 		       convert_to_integer (size_type_node,
58 					   m_parent.m_cf->m_private_base_arg),
59 		       convert_to_integer (size_type_node, operands[1]));
60       else
61        gcc_unreachable ();
62 
63       if (!(inst.modifier & BRIG_SEG_CVT_NONULL))
64 	{
65 	  /* Need to convert the null value. -1 is used for 32b segments,
66 	     and 0 for flat/global.  */
67 	  tree cmp
68 	    = build2 (EQ_EXPR, uint32_type_node,
69 		      build_int_cstu (uint32_type_node, -1), operands[1]);
70 
71 	  tree null_check = build3 (COND_EXPR, size_type_node, cmp,
72 				    build_int_cstu (size_type_node, 0), expr);
73 
74 	  expr = null_check;
75 	}
76     }
77   else if (inst_base.opcode == BRIG_OPCODE_FTOS)
78     {
79       const BrigInstSegCvt &inst = *(const BrigInstSegCvt *) base;
80 
81       if (inst.segment == BRIG_SEGMENT_GROUP)
82 	expr = build2 (MINUS_EXPR, size_type_node,
83 		       convert_to_integer (size_type_node,
84 					   m_parent.m_cf->m_group_base_arg),
85 		       convert_to_integer (size_type_node, operands[1]));
86       else if (inst.segment == BRIG_SEGMENT_PRIVATE)
87 	expr = build2 (MINUS_EXPR, size_type_node,
88 		       convert_to_integer (size_type_node,
89 					   m_parent.m_cf->m_private_base_arg),
90 		       convert_to_integer (size_type_node, operands[1]));
91       else
92 	gcc_unreachable ();
93 
94       if (!(inst.modifier & BRIG_SEG_CVT_NONULL))
95 	{
96 	  /* Need to convert the null value. -1 is used for 32b segments,
97 	     and 0 for flat/global.  */
98 	  tree cmp = build2 (EQ_EXPR, size_type_node,
99 			     build_int_cstu (size_type_node, 0), operands[1]);
100 
101 	  tree null_check
102 	    = build3 (COND_EXPR, size_type_node, cmp,
103 		      build_int_cstu (uint32_type_node, -1), expr);
104 	  expr = null_check;
105 	}
106     }
107   else if (inst_base.opcode == BRIG_OPCODE_NULLPTR)
108     {
109       const BrigInstSeg &inst = *(const BrigInstSeg *) base;
110       if (inst.segment == BRIG_SEGMENT_GLOBAL
111 	  || inst.segment == BRIG_SEGMENT_FLAT
112 	  || inst.segment == BRIG_SEGMENT_READONLY)
113 	expr = build_int_cstu (uint64_type_node, 0);
114       else
115 	expr = build_int_cstu (uint32_type_node, -1);
116     }
117   else if (inst_base.opcode == BRIG_OPCODE_SEGMENTP)
118     {
119       const BrigInstSegCvt &inst = *(const BrigInstSegCvt *) base;
120 
121       tree builtin = NULL_TREE;
122       switch (inst.segment)
123 	{
124 	case BRIG_SEGMENT_GLOBAL:
125 	  builtin = builtin_decl_explicit (BUILT_IN_HSAIL_SEGMENTP_GLOBAL);
126 	  break;
127 	case BRIG_SEGMENT_GROUP:
128 	  builtin = builtin_decl_explicit (BUILT_IN_HSAIL_SEGMENTP_GROUP);
129 	  break;
130 	case BRIG_SEGMENT_PRIVATE:
131 	  builtin = builtin_decl_explicit (BUILT_IN_HSAIL_SEGMENTP_PRIVATE);
132 	  break;
133 	default:
134 	  gcc_unreachable ();
135 	}
136 
137       expr = call_builtin (builtin, 2,
138 			   uint32_type_node, uint64_type_node, operands[1],
139 			   ptr_type_node, m_parent.m_cf->m_context_arg);
140     }
141   else
142     gcc_unreachable ();
143 
144   build_output_assignment (inst_base, operands[0], expr);
145   return base->byteCount;
146 }
147