111
|
1 /* brig-seg-inst-handler.cc -- brig segment related instruction handling
|
|
2 Copyright (C) 2016-2017 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
|
|
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
|
|
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 }
|