authorgravatar for evan@lagerdata.comEvan Haas <evan@lagerdata.com> 2021-03-08 07:01:19-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-06 11:22:27-07:00
log8de14a98a68752cc834848343f2e7867ee8ca6c9
tree7e6bc3259ec3926054830613d63025afa8e19117
parent38d8aab4d283efe2f43c7e18411f6df7e1c2d04b

translate-c: Add support for vector expressions

Includes vector types, __builtin_shufflevector, and __builtin_convertvector

7 files changed, 515 insertions(+), 8 deletions(-)

lib/std/meta.zig+32
...@@ -1297,3 +1297,35 @@ pub fn globalOption(comptime name: []const u8, comptime T: type) ?T {...@@ -1297,3 +1297,35 @@ pub fn globalOption(comptime name: []const u8, comptime T: type) ?T {
1297 return null;1297 return null;
1298 return @as(T, @field(root, name));1298 return @as(T, @field(root, name));
1299}1299}
1300
1301/// This function is for translate-c and is not intended for general use.
1302/// Convert from clang __builtin_shufflevector index to Zig @shuffle index
1303/// clang requires __builtin_shufflevector index arguments to be integer constants.
1304/// negative values for `this_index` indicate "don't care" so we arbitrarily choose 0
1305/// clang enforces that `this_index` is less than the total number of vector elements
1306/// See https://ziglang.org/documentation/master/#shuffle
1307/// See https://clang.llvm.org/docs/LanguageExtensions.html#langext-builtin-shufflevector
1308pub fn shuffleVectorIndex(comptime this_index: c_int, comptime source_vector_len: usize) i32 {
1309 if (this_index <= 0) return 0;
1310
1311 const positive_index = @intCast(usize, this_index);
1312 if (positive_index < source_vector_len) return @intCast(i32, this_index);
1313 const b_index = positive_index - source_vector_len;
1314 return ~@intCast(i32, b_index);
1315}
1316
1317test "shuffleVectorIndex" {
1318 const vector_len: usize = 4;
1319
1320 testing.expect(shuffleVectorIndex(-1, vector_len) == 0);
1321
1322 testing.expect(shuffleVectorIndex(0, vector_len) == 0);
1323 testing.expect(shuffleVectorIndex(1, vector_len) == 1);
1324 testing.expect(shuffleVectorIndex(2, vector_len) == 2);
1325 testing.expect(shuffleVectorIndex(3, vector_len) == 3);
1326
1327 testing.expect(shuffleVectorIndex(4, vector_len) == -1);
1328 testing.expect(shuffleVectorIndex(5, vector_len) == -2);
1329 testing.expect(shuffleVectorIndex(6, vector_len) == -3);
1330 testing.expect(shuffleVectorIndex(7, vector_len) == -4);
1331}
\ No newline at end of file
src/clang.zig+27
...@@ -300,6 +300,14 @@ pub const ConstantExpr = opaque {};...@@ -300,6 +300,14 @@ pub const ConstantExpr = opaque {};
300300
301pub const ContinueStmt = opaque {};301pub const ContinueStmt = opaque {};
302302
303pub const ConvertVectorExpr = opaque {
304 pub const getSrcExpr = ZigClangConvertVectorExpr_getSrcExpr;
305 extern fn ZigClangConvertVectorExpr_getSrcExpr(*const ConvertVectorExpr) *const Expr;
306
307 pub const getTypeSourceInfo_getType = ZigClangConvertVectorExpr_getTypeSourceInfo_getType;
308 extern fn ZigClangConvertVectorExpr_getTypeSourceInfo_getType(*const ConvertVectorExpr) QualType;
309};
310
303pub const DecayedType = opaque {311pub const DecayedType = opaque {
304 pub const getDecayedType = ZigClangDecayedType_getDecayedType;312 pub const getDecayedType = ZigClangDecayedType_getDecayedType;
305 extern fn ZigClangDecayedType_getDecayedType(*const DecayedType) QualType;313 extern fn ZigClangDecayedType_getDecayedType(*const DecayedType) QualType;
...@@ -748,6 +756,14 @@ pub const ReturnStmt = opaque {...@@ -748,6 +756,14 @@ pub const ReturnStmt = opaque {
748 extern fn ZigClangReturnStmt_getRetValue(*const ReturnStmt) ?*const Expr;756 extern fn ZigClangReturnStmt_getRetValue(*const ReturnStmt) ?*const Expr;
749};757};
750758
759pub const ShuffleVectorExpr = opaque {
760 pub const getNumSubExprs = ZigClangShuffleVectorExpr_getNumSubExprs;
761 extern fn ZigClangShuffleVectorExpr_getNumSubExprs(*const ShuffleVectorExpr) c_uint;
762
763 pub const getExpr = ZigClangShuffleVectorExpr_getExpr;
764 extern fn ZigClangShuffleVectorExpr_getExpr(*const ShuffleVectorExpr, c_uint) *const Expr;
765};
766
751pub const SourceManager = opaque {767pub const SourceManager = opaque {
752 pub const getSpellingLoc = ZigClangSourceManager_getSpellingLoc;768 pub const getSpellingLoc = ZigClangSourceManager_getSpellingLoc;
753 extern fn ZigClangSourceManager_getSpellingLoc(*const SourceManager, Loc: SourceLocation) SourceLocation;769 extern fn ZigClangSourceManager_getSpellingLoc(*const SourceManager, Loc: SourceLocation) SourceLocation;
...@@ -837,6 +853,9 @@ pub const Type = opaque {...@@ -837,6 +853,9 @@ pub const Type = opaque {
837 pub const isRecordType = ZigClangType_isRecordType;853 pub const isRecordType = ZigClangType_isRecordType;
838 extern fn ZigClangType_isRecordType(*const Type) bool;854 extern fn ZigClangType_isRecordType(*const Type) bool;
839855
856 pub const isVectorType = ZigClangType_isVectorType;
857 extern fn ZigClangType_isVectorType(*const Type) bool;
858
840 pub const isIncompleteOrZeroLengthArrayType = ZigClangType_isIncompleteOrZeroLengthArrayType;859 pub const isIncompleteOrZeroLengthArrayType = ZigClangType_isIncompleteOrZeroLengthArrayType;
841 extern fn ZigClangType_isIncompleteOrZeroLengthArrayType(*const Type, *const ASTContext) bool;860 extern fn ZigClangType_isIncompleteOrZeroLengthArrayType(*const Type, *const ASTContext) bool;
842861
...@@ -937,6 +956,14 @@ pub const VarDecl = opaque {...@@ -937,6 +956,14 @@ pub const VarDecl = opaque {
937 extern fn ZigClangVarDecl_getTypeSourceInfo_getType(*const VarDecl) QualType;956 extern fn ZigClangVarDecl_getTypeSourceInfo_getType(*const VarDecl) QualType;
938};957};
939958
959pub const VectorType = opaque {
960 pub const getElementType = ZigClangVectorType_getElementType;
961 extern fn ZigClangVectorType_getElementType(*const VectorType) QualType;
962
963 pub const getNumElements = ZigClangVectorType_getNumElements;
964 extern fn ZigClangVectorType_getNumElements(*const VectorType) c_uint;
965};
966
940pub const WhileStmt = opaque {967pub const WhileStmt = opaque {
941 pub const getCond = ZigClangWhileStmt_getCond;968 pub const getCond = ZigClangWhileStmt_getCond;
942 extern fn ZigClangWhileStmt_getCond(*const WhileStmt) *const Expr;969 extern fn ZigClangWhileStmt_getCond(*const WhileStmt) *const Expr;
src/translate_c.zig+215
...@@ -1123,6 +1123,16 @@ fn transStmt(...@@ -1123,6 +1123,16 @@ fn transStmt(
1123 const gen_sel = @ptrCast(*const clang.GenericSelectionExpr, stmt);1123 const gen_sel = @ptrCast(*const clang.GenericSelectionExpr, stmt);
1124 return transExpr(c, scope, gen_sel.getResultExpr(), result_used);1124 return transExpr(c, scope, gen_sel.getResultExpr(), result_used);
1125 },1125 },
1126 .ConvertVectorExprClass => {
1127 const conv_vec = @ptrCast(*const clang.ConvertVectorExpr, stmt);
1128 const conv_vec_node = try transConvertVectorExpr(c, scope, stmt.getBeginLoc(), conv_vec);
1129 return maybeSuppressResult(c, scope, result_used, conv_vec_node);
1130 },
1131 .ShuffleVectorExprClass => {
1132 const shuffle_vec_expr = @ptrCast(*const clang.ShuffleVectorExpr, stmt);
1133 const shuffle_vec_node = try transShuffleVectorExpr(c, scope, shuffle_vec_expr);
1134 return maybeSuppressResult(c, scope, result_used, shuffle_vec_node);
1135 },
1126 // When adding new cases here, see comment for maybeBlockify()1136 // When adding new cases here, see comment for maybeBlockify()
1127 else => {1137 else => {
1128 return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "TODO implement translation of stmt class {s}", .{@tagName(sc)});1138 return fail(c, error.UnsupportedTranslation, stmt.getBeginLoc(), "TODO implement translation of stmt class {s}", .{@tagName(sc)});
...@@ -1130,6 +1140,128 @@ fn transStmt(...@@ -1130,6 +1140,128 @@ fn transStmt(
1130 }1140 }
1131}1141}
11321142
1143/// See https://clang.llvm.org/docs/LanguageExtensions.html#langext-builtin-convertvector
1144fn transConvertVectorExpr(
1145 c: *Context,
1146 scope: *Scope,
1147 source_loc: clang.SourceLocation,
1148 expr: *const clang.ConvertVectorExpr,
1149) TransError!Node {
1150 const base_stmt = @ptrCast(*const clang.Stmt, expr);
1151
1152 var block_scope = try Scope.Block.init(c, scope, true);
1153 defer block_scope.deinit();
1154
1155 const src_expr = expr.getSrcExpr();
1156 const src_type = qualTypeCanon(src_expr.getType());
1157 const src_vector_ty = @ptrCast(*const clang.VectorType, src_type);
1158 const src_element_qt = src_vector_ty.getElementType();
1159 const src_element_type_node = try transQualType(c, &block_scope.base, src_element_qt, base_stmt.getBeginLoc());
1160
1161 const src_expr_node = try transExpr(c, &block_scope.base, src_expr, .used);
1162
1163 const dst_qt = expr.getTypeSourceInfo_getType();
1164 const dst_type_node = try transQualType(c, &block_scope.base, dst_qt, base_stmt.getBeginLoc());
1165 const dst_vector_ty = @ptrCast(*const clang.VectorType, qualTypeCanon(dst_qt));
1166 const num_elements = dst_vector_ty.getNumElements();
1167 const dst_element_qt = dst_vector_ty.getElementType();
1168
1169 // workaround for https://github.com/ziglang/zig/issues/8322
1170 // we store the casted results into temp variables and use those
1171 // to initialize the vector. Eventually we can just directly
1172 // construct the init_list from casted source members
1173 var i: usize = 0;
1174 while (i < num_elements) : (i += 1) {
1175 const mangled_name = try block_scope.makeMangledName(c, "tmp");
1176 const value = try Tag.array_access.create(c.arena, .{
1177 .lhs = src_expr_node,
1178 .rhs = try transCreateNodeNumber(c, i, .int),
1179 });
1180 const tmp_decl_node = try Tag.var_simple.create(c.arena, .{
1181 .name = mangled_name,
1182 .init = try transCCast(c, &block_scope.base, base_stmt.getBeginLoc(), dst_element_qt, src_element_qt, value),
1183 });
1184 try block_scope.statements.append(tmp_decl_node);
1185 }
1186
1187 const init_list = try c.arena.alloc(Node, num_elements);
1188 for (init_list) |*init, init_index| {
1189 const tmp_decl = block_scope.statements.items[init_index];
1190 const name = tmp_decl.castTag(.var_simple).?.data.name;
1191 init.* = try Tag.identifier.create(c.arena, name);
1192 }
1193
1194 const vec_init = try Tag.array_init.create(c.arena, .{
1195 .cond = dst_type_node,
1196 .cases = init_list,
1197 });
1198
1199 const break_node = try Tag.break_val.create(c.arena, .{
1200 .label = block_scope.label,
1201 .val = vec_init,
1202 });
1203 try block_scope.statements.append(break_node);
1204 return block_scope.complete(c);
1205}
1206
1207fn makeShuffleMask(c: *Context, scope: *Scope, expr: *const clang.ShuffleVectorExpr, vector_len: Node) TransError!Node {
1208 const num_subexprs = expr.getNumSubExprs();
1209 assert(num_subexprs >= 3); // two source vectors + at least 1 index expression
1210 const mask_len = num_subexprs - 2;
1211
1212 const mask_type = try Tag.std_meta_vector.create(c.arena, .{
1213 .lhs = try transCreateNodeNumber(c, mask_len, .int),
1214 .rhs = try Tag.type.create(c.arena, "i32"),
1215 });
1216
1217 const init_list = try c.arena.alloc(Node, mask_len);
1218
1219 for (init_list) |*init, i| {
1220 const index_expr = try transExprCoercing(c, scope, expr.getExpr(@intCast(c_uint, i + 2)), .used);
1221 const converted_index = try Tag.std_meta_shuffle_vector_index.create(c.arena, .{ .lhs = index_expr, .rhs = vector_len });
1222 init.* = converted_index;
1223 }
1224
1225 const mask_init = try Tag.array_init.create(c.arena, .{
1226 .cond = mask_type,
1227 .cases = init_list,
1228 });
1229 return Tag.@"comptime".create(c.arena, mask_init);
1230}
1231
1232/// @typeInfo(@TypeOf(vec_node)).Vector.<field>
1233fn vectorTypeInfo(arena: *mem.Allocator, vec_node: Node, field: []const u8) TransError!Node {
1234 const typeof_call = try Tag.typeof.create(arena, vec_node);
1235 const typeinfo_call = try Tag.typeinfo.create(arena, typeof_call);
1236 const vector_type_info = try Tag.field_access.create(arena, .{ .lhs = typeinfo_call, .field_name = "Vector" });
1237 return Tag.field_access.create(arena, .{ .lhs = vector_type_info, .field_name = field });
1238}
1239
1240fn transShuffleVectorExpr(
1241 c: *Context,
1242 scope: *Scope,
1243 expr: *const clang.ShuffleVectorExpr,
1244) TransError!Node {
1245 const base_expr = @ptrCast(*const clang.Expr, expr);
1246 const num_subexprs = expr.getNumSubExprs();
1247 if (num_subexprs < 3) return fail(c, error.UnsupportedTranslation, base_expr.getBeginLoc(), "ShuffleVector needs at least 1 index", .{});
1248
1249 const a = try transExpr(c, scope, expr.getExpr(0), .used);
1250 const b = try transExpr(c, scope, expr.getExpr(1), .used);
1251
1252 // clang requires first two arguments to __builtin_shufflevector to be same type
1253 const vector_child_type = try vectorTypeInfo(c.arena, a, "child");
1254 const vector_len = try vectorTypeInfo(c.arena, a, "len");
1255 const shuffle_mask = try makeShuffleMask(c, scope, expr, vector_len);
1256
1257 return Tag.shuffle.create(c.arena, .{
1258 .element_type = vector_child_type,
1259 .a = a,
1260 .b = b,
1261 .mask_vector = shuffle_mask,
1262 });
1263}
1264
1133/// Translate a "simple" offsetof expression containing exactly one component,1265/// Translate a "simple" offsetof expression containing exactly one component,
1134/// when that component is of kind .Field - e.g. offsetof(mytype, myfield)1266/// when that component is of kind .Field - e.g. offsetof(mytype, myfield)
1135fn transSimpleOffsetOfExpr(1267fn transSimpleOffsetOfExpr(
...@@ -1935,6 +2067,10 @@ fn cIsEnum(qt: clang.QualType) bool {...@@ -1935,6 +2067,10 @@ fn cIsEnum(qt: clang.QualType) bool {
1935 return qt.getCanonicalType().getTypeClass() == .Enum;2067 return qt.getCanonicalType().getTypeClass() == .Enum;
1936}2068}
19372069
2070fn cIsVector(qt: clang.QualType) bool {
2071 return qt.getCanonicalType().getTypeClass() == .Vector;
2072}
2073
1938/// Get the underlying int type of an enum. The C compiler chooses a signed int2074/// Get the underlying int type of an enum. The C compiler chooses a signed int
1939/// type that is large enough to hold all of the enum's values. It is not required2075/// type that is large enough to hold all of the enum's values. It is not required
1940/// to be the smallest possible type that can hold all the values.2076/// to be the smallest possible type that can hold all the values.
...@@ -1991,6 +2127,11 @@ fn transCCast(...@@ -1991,6 +2127,11 @@ fn transCCast(
1991 // @bitCast(dest_type, intermediate_value)2127 // @bitCast(dest_type, intermediate_value)
1992 return Tag.bit_cast.create(c.arena, .{ .lhs = dst_node, .rhs = src_int_expr });2128 return Tag.bit_cast.create(c.arena, .{ .lhs = dst_node, .rhs = src_int_expr });
1993 }2129 }
2130 if (cIsVector(src_type) or cIsVector(dst_type)) {
2131 // C cast where at least 1 operand is a vector requires them to be same size
2132 // @bitCast(dest_type, val)
2133 return Tag.bit_cast.create(c.arena, .{ .lhs = dst_node, .rhs = expr });
2134 }
1994 if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) {2135 if (cIsInteger(dst_type) and qualTypeIsPtr(src_type)) {
1995 // @intCast(dest_type, @ptrToInt(val))2136 // @intCast(dest_type, @ptrToInt(val))
1996 const ptr_to_int = try Tag.ptr_to_int.create(c.arena, expr);2137 const ptr_to_int = try Tag.ptr_to_int.create(c.arena, expr);
...@@ -2209,6 +2350,63 @@ fn transInitListExprArray(...@@ -2209,6 +2350,63 @@ fn transInitListExprArray(
2209 }2350 }
2210}2351}
22112352
2353fn transInitListExprVector(
2354 c: *Context,
2355 scope: *Scope,
2356 loc: clang.SourceLocation,
2357 expr: *const clang.InitListExpr,
2358 ty: *const clang.Type,
2359) TransError!Node {
2360
2361 const qt = getExprQualType(c, @ptrCast(*const clang.Expr, expr));
2362 const vector_type = try transQualType(c, scope, qt, loc);
2363 const init_count = expr.getNumInits();
2364
2365 if (init_count == 0) {
2366 return Tag.container_init.create(c.arena, .{
2367 .lhs = vector_type,
2368 .inits = try c.arena.alloc(ast.Payload.ContainerInit.Initializer, 0),
2369 });
2370 }
2371
2372 var block_scope = try Scope.Block.init(c, scope, true);
2373 defer block_scope.deinit();
2374
2375 // workaround for https://github.com/ziglang/zig/issues/8322
2376 // we store the initializers in temp variables and use those
2377 // to initialize the vector. Eventually we can just directly
2378 // construct the init_list from casted source members
2379 var i: usize = 0;
2380 while (i < init_count) : (i += 1) {
2381 const mangled_name = try block_scope.makeMangledName(c, "tmp");
2382 const init_expr = expr.getInit(@intCast(c_uint, i));
2383 const tmp_decl_node = try Tag.var_simple.create(c.arena, .{
2384 .name = mangled_name,
2385 .init = try transExpr(c, &block_scope.base, init_expr, .used),
2386 });
2387 try block_scope.statements.append(tmp_decl_node);
2388 }
2389
2390 const init_list = try c.arena.alloc(Node, init_count);
2391 for (init_list) |*init, init_index| {
2392 const tmp_decl = block_scope.statements.items[init_index];
2393 const name = tmp_decl.castTag(.var_simple).?.data.name;
2394 init.* = try Tag.identifier.create(c.arena, name);
2395 }
2396
2397 const array_init = try Tag.array_init.create(c.arena, .{
2398 .cond = vector_type,
2399 .cases = init_list,
2400 });
2401 const break_node = try Tag.break_val.create(c.arena, .{
2402 .label = block_scope.label,
2403 .val = array_init,
2404 });
2405 try block_scope.statements.append(break_node);
2406
2407 return block_scope.complete(c);
2408}
2409
2212fn transInitListExpr(2410fn transInitListExpr(
2213 c: *Context,2411 c: *Context,
2214 scope: *Scope,2412 scope: *Scope,
...@@ -2235,6 +2433,14 @@ fn transInitListExpr(...@@ -2235,6 +2433,14 @@ fn transInitListExpr(
2235 expr,2433 expr,
2236 qual_type,2434 qual_type,
2237 ));2435 ));
2436 } else if (qual_type.isVectorType()) {
2437 return maybeSuppressResult(c, scope, used, try transInitListExprVector(
2438 c,
2439 scope,
2440 source_loc,
2441 expr,
2442 qual_type,
2443 ));
2238 } else {2444 } else {
2239 const type_name = c.str(qual_type.getTypeClassName());2445 const type_name = c.str(qual_type.getTypeClassName());
2240 return fail(c, error.UnsupportedType, source_loc, "unsupported initlist type: '{s}'", .{type_name});2446 return fail(c, error.UnsupportedType, source_loc, "unsupported initlist type: '{s}'", .{type_name});
...@@ -4085,6 +4291,15 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan...@@ -4085,6 +4291,15 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan
4085 };4291 };
4086 return Tag.typeof.create(c.arena, underlying_expr);4292 return Tag.typeof.create(c.arena, underlying_expr);
4087 },4293 },
4294 .Vector => {
4295 const vector_ty = @ptrCast(*const clang.VectorType, ty);
4296 const num_elements = vector_ty.getNumElements();
4297 const element_qt = vector_ty.getElementType();
4298 return Tag.std_meta_vector.create(c.arena, .{
4299 .lhs = try transCreateNodeNumber(c, num_elements, .int),
4300 .rhs = try transQualType(c, scope, element_qt, source_loc),
4301 });
4302 },
4088 else => {4303 else => {
4089 const type_name = c.str(ty.getTypeClassName());4304 const type_name = c.str(ty.getTypeClassName());
4090 return fail(c, error.UnsupportedType, source_loc, "unsupported type: '{s}'", .{type_name});4305 return fail(c, error.UnsupportedType, source_loc, "unsupported type: '{s}'", .{type_name});
src/translate_c/ast.zig+95-8
...@@ -66,6 +66,7 @@ pub const Node = extern union {...@@ -66,6 +66,7 @@ pub const Node = extern union {
66 @"enum",66 @"enum",
67 @"struct",67 @"struct",
68 @"union",68 @"union",
69 @"comptime",
69 array_init,70 array_init,
70 tuple,71 tuple,
71 container_init,72 container_init,
...@@ -154,6 +155,8 @@ pub const Node = extern union {...@@ -154,6 +155,8 @@ pub const Node = extern union {
154 div_exact,155 div_exact,
155 /// @byteOffsetOf(lhs, rhs)156 /// @byteOffsetOf(lhs, rhs)
156 byte_offset_of,157 byte_offset_of,
158 /// @shuffle(type, a, b, mask)
159 shuffle,
157160
158 negate,161 negate,
159 negate_wrap,162 negate_wrap,
...@@ -172,6 +175,7 @@ pub const Node = extern union {...@@ -172,6 +175,7 @@ pub const Node = extern union {
172 sizeof,175 sizeof,
173 alignof,176 alignof,
174 typeof,177 typeof,
178 typeinfo,
175 type,179 type,
176180
177 optional_type,181 optional_type,
...@@ -182,6 +186,10 @@ pub const Node = extern union {...@@ -182,6 +186,10 @@ pub const Node = extern union {
182186
183 /// @import("std").meta.sizeof(operand)187 /// @import("std").meta.sizeof(operand)
184 std_meta_sizeof,188 std_meta_sizeof,
189 /// @import("std").meta.shuffleVectorIndex(lhs, rhs)
190 std_meta_shuffle_vector_index,
191 /// @import("std").meta.Vector(lhs, rhs)
192 std_meta_vector,
185 /// @import("std").mem.zeroes(operand)193 /// @import("std").mem.zeroes(operand)
186 std_mem_zeroes,194 std_mem_zeroes,
187 /// @import("std").mem.zeroInit(lhs, rhs)195 /// @import("std").mem.zeroInit(lhs, rhs)
...@@ -233,6 +241,7 @@ pub const Node = extern union {...@@ -233,6 +241,7 @@ pub const Node = extern union {
233241
234 .std_mem_zeroes,242 .std_mem_zeroes,
235 .@"return",243 .@"return",
244 .@"comptime",
236 .discard,245 .discard,
237 .std_math_Log2Int,246 .std_math_Log2Int,
238 .negate,247 .negate,
...@@ -255,6 +264,7 @@ pub const Node = extern union {...@@ -255,6 +264,7 @@ pub const Node = extern union {
255 .sizeof,264 .sizeof,
256 .alignof,265 .alignof,
257 .typeof,266 .typeof,
267 .typeinfo,
258 => Payload.UnOp,268 => Payload.UnOp,
259269
260 .add,270 .add,
...@@ -308,6 +318,8 @@ pub const Node = extern union {...@@ -308,6 +318,8 @@ pub const Node = extern union {
308 .align_cast,318 .align_cast,
309 .array_access,319 .array_access,
310 .std_mem_zeroinit,320 .std_mem_zeroinit,
321 .std_meta_shuffle_vector_index,
322 .std_meta_vector,
311 .ptr_cast,323 .ptr_cast,
312 .div_exact,324 .div_exact,
313 .byte_offset_of,325 .byte_offset_of,
...@@ -346,6 +358,7 @@ pub const Node = extern union {...@@ -346,6 +358,7 @@ pub const Node = extern union {
346 .pub_inline_fn => Payload.PubInlineFn,358 .pub_inline_fn => Payload.PubInlineFn,
347 .field_access => Payload.FieldAccess,359 .field_access => Payload.FieldAccess,
348 .string_slice => Payload.StringSlice,360 .string_slice => Payload.StringSlice,
361 .shuffle => Payload.Shuffle,
349 };362 };
350 }363 }
351364
...@@ -678,6 +691,16 @@ pub const Payload = struct {...@@ -678,6 +691,16 @@ pub const Payload = struct {
678 end: usize,691 end: usize,
679 },692 },
680 };693 };
694
695 pub const Shuffle = struct {
696 base: Payload,
697 data: struct {
698 element_type: Node,
699 a: Node,
700 b: Node,
701 mask_vector: Node,
702 },
703 };
681};704};
682705
683/// Converts the nodes into a Zig ast.706/// Converts the nodes into a Zig ast.
...@@ -868,6 +891,16 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -868,6 +891,16 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
868 const import_node = try renderStdImport(c, "mem", "zeroInit");891 const import_node = try renderStdImport(c, "mem", "zeroInit");
869 return renderCall(c, import_node, &.{ payload.lhs, payload.rhs });892 return renderCall(c, import_node, &.{ payload.lhs, payload.rhs });
870 },893 },
894 .std_meta_shuffle_vector_index => {
895 const payload = node.castTag(.std_meta_shuffle_vector_index).?.data;
896 const import_node = try renderStdImport(c, "meta", "shuffleVectorIndex");
897 return renderCall(c, import_node, &.{ payload.lhs, payload.rhs });
898 },
899 .std_meta_vector => {
900 const payload = node.castTag(.std_meta_vector).?.data;
901 const import_node = try renderStdImport(c, "meta", "Vector");
902 return renderCall(c, import_node, &.{ payload.lhs, payload.rhs });
903 },
871 .call => {904 .call => {
872 const payload = node.castTag(.call).?.data;905 const payload = node.castTag(.call).?.data;
873 const lhs = try renderNode(c, payload.lhs);906 const lhs = try renderNode(c, payload.lhs);
...@@ -964,6 +997,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -964,6 +997,17 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
964 },997 },
965 });998 });
966 },999 },
1000 .@"comptime" => {
1001 const payload = node.castTag(.@"comptime").?.data;
1002 return c.addNode(.{
1003 .tag = .@"comptime",
1004 .main_token = try c.addToken(.keyword_comptime, "comptime"),
1005 .data = .{
1006 .lhs = try renderNode(c, payload),
1007 .rhs = undefined,
1008 },
1009 });
1010 },
967 .type => {1011 .type => {
968 const payload = node.castTag(.type).?.data;1012 const payload = node.castTag(.type).?.data;
969 return c.addNode(.{1013 return c.addNode(.{
...@@ -1217,6 +1261,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1217,6 +1261,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1217 const payload = node.castTag(.sizeof).?.data;1261 const payload = node.castTag(.sizeof).?.data;
1218 return renderBuiltinCall(c, "@sizeOf", &.{payload});1262 return renderBuiltinCall(c, "@sizeOf", &.{payload});
1219 },1263 },
1264 .shuffle => {
1265 const payload = node.castTag(.shuffle).?.data;
1266 return renderBuiltinCall(c, "@shuffle", &.{
1267 payload.element_type,
1268 payload.a,
1269 payload.b,
1270 payload.mask_vector,
1271 });
1272 },
1220 .alignof => {1273 .alignof => {
1221 const payload = node.castTag(.alignof).?.data;1274 const payload = node.castTag(.alignof).?.data;
1222 return renderBuiltinCall(c, "@alignOf", &.{payload});1275 return renderBuiltinCall(c, "@alignOf", &.{payload});
...@@ -1225,6 +1278,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -1225,6 +1278,10 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
1225 const payload = node.castTag(.typeof).?.data;1278 const payload = node.castTag(.typeof).?.data;
1226 return renderBuiltinCall(c, "@TypeOf", &.{payload});1279 return renderBuiltinCall(c, "@TypeOf", &.{payload});
1227 },1280 },
1281 .typeinfo => {
1282 const payload = node.castTag(.typeinfo).?.data;
1283 return renderBuiltinCall(c, "@typeInfo", &.{payload});
1284 },
1228 .negate => return renderPrefixOp(c, node, .negation, .minus, "-"),1285 .negate => return renderPrefixOp(c, node, .negation, .minus, "-"),
1229 .negate_wrap => return renderPrefixOp(c, node, .negation_wrap, .minus_percent, "-%"),1286 .negate_wrap => return renderPrefixOp(c, node, .negation_wrap, .minus_percent, "-%"),
1230 .bit_not => return renderPrefixOp(c, node, .bit_not, .tilde, "~"),1287 .bit_not => return renderPrefixOp(c, node, .bit_not, .tilde, "~"),
...@@ -2085,9 +2142,12 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {...@@ -2085,9 +2142,12 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
2085 .sizeof,2142 .sizeof,
2086 .alignof,2143 .alignof,
2087 .typeof,2144 .typeof,
2145 .typeinfo,
2088 .std_meta_sizeof,2146 .std_meta_sizeof,
2089 .std_meta_cast,2147 .std_meta_cast,
2090 .std_meta_promoteIntLiteral,2148 .std_meta_promoteIntLiteral,
2149 .std_meta_vector,
2150 .std_meta_shuffle_vector_index,
2091 .std_mem_zeroinit,2151 .std_mem_zeroinit,
2092 .integer_literal,2152 .integer_literal,
2093 .float_literal,2153 .float_literal,
...@@ -2118,6 +2178,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {...@@ -2118,6 +2178,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
2118 .bool_to_int,2178 .bool_to_int,
2119 .div_exact,2179 .div_exact,
2120 .byte_offset_of,2180 .byte_offset_of,
2181 .shuffle,
2121 => {2182 => {
2122 // no grouping needed2183 // no grouping needed
2123 return renderNode(c, node);2184 return renderNode(c, node);
...@@ -2185,6 +2246,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {...@@ -2185,6 +2246,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
2185 .discard,2246 .discard,
2186 .@"continue",2247 .@"continue",
2187 .@"return",2248 .@"return",
2249 .@"comptime",
2188 .usingnamespace_builtins,2250 .usingnamespace_builtins,
2189 .while_true,2251 .while_true,
2190 .if_not_break,2252 .if_not_break,
...@@ -2327,6 +2389,8 @@ fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !Node...@@ -2327,6 +2389,8 @@ fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !Node
2327 _ = try c.addToken(.l_paren, "(");2389 _ = try c.addToken(.l_paren, "(");
2328 var arg_1: NodeIndex = 0;2390 var arg_1: NodeIndex = 0;
2329 var arg_2: NodeIndex = 0;2391 var arg_2: NodeIndex = 0;
2392 var arg_3: NodeIndex = 0;
2393 var arg_4: NodeIndex = 0;
2330 switch (args.len) {2394 switch (args.len) {
2331 0 => {},2395 0 => {},
2332 1 => {2396 1 => {
...@@ -2337,18 +2401,41 @@ fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !Node...@@ -2337,18 +2401,41 @@ fn renderBuiltinCall(c: *Context, builtin: []const u8, args: []const Node) !Node
2337 _ = try c.addToken(.comma, ",");2401 _ = try c.addToken(.comma, ",");
2338 arg_2 = try renderNode(c, args[1]);2402 arg_2 = try renderNode(c, args[1]);
2339 },2403 },
2404 4 => {
2405 arg_1 = try renderNode(c, args[0]);
2406 _ = try c.addToken(.comma, ",");
2407 arg_2 = try renderNode(c, args[1]);
2408 _ = try c.addToken(.comma, ",");
2409 arg_3 = try renderNode(c, args[2]);
2410 _ = try c.addToken(.comma, ",");
2411 arg_4 = try renderNode(c, args[3]);
2412 },
2340 else => unreachable, // expand this function as needed.2413 else => unreachable, // expand this function as needed.
2341 }2414 }
23422415
2343 _ = try c.addToken(.r_paren, ")");2416 _ = try c.addToken(.r_paren, ")");
2344 return c.addNode(.{2417 if (args.len <= 2) {
2345 .tag = .builtin_call_two,2418 return c.addNode(.{
2346 .main_token = builtin_tok,2419 .tag = .builtin_call_two,
2347 .data = .{2420 .main_token = builtin_tok,
2348 .lhs = arg_1,2421 .data = .{
2349 .rhs = arg_2,2422 .lhs = arg_1,
2350 },2423 .rhs = arg_2,
2351 });2424 },
2425 });
2426 } else {
2427 std.debug.assert(args.len == 4);
2428
2429 const params = try c.listToSpan(&.{ arg_1, arg_2, arg_3, arg_4 });
2430 return c.addNode(.{
2431 .tag = .builtin_call,
2432 .main_token = builtin_tok,
2433 .data = .{
2434 .lhs = params.start,
2435 .rhs = params.end,
2436 },
2437 });
2438 }
2352}2439}
23532440
2354fn renderVar(c: *Context, node: Node) !NodeIndex {2441fn renderVar(c: *Context, node: Node) !NodeIndex {
src/zig_clang.cpp+34
...@@ -2046,6 +2046,11 @@ bool ZigClangType_isRecordType(const ZigClangType *self) {...@@ -2046,6 +2046,11 @@ bool ZigClangType_isRecordType(const ZigClangType *self) {
2046 return casted->isRecordType();2046 return casted->isRecordType();
2047}2047}
20482048
2049bool ZigClangType_isVectorType(const ZigClangType *self) {
2050 auto casted = reinterpret_cast<const clang::Type *>(self);
2051 return casted->isVectorType();
2052}
2053
2049bool ZigClangType_isIncompleteOrZeroLengthArrayType(const ZigClangQualType *self,2054bool ZigClangType_isIncompleteOrZeroLengthArrayType(const ZigClangQualType *self,
2050 const struct ZigClangASTContext *ctx)2055 const struct ZigClangASTContext *ctx)
2051{2056{
...@@ -2738,6 +2743,16 @@ struct ZigClangQualType ZigClangBinaryOperator_getType(const struct ZigClangBina...@@ -2738,6 +2743,16 @@ struct ZigClangQualType ZigClangBinaryOperator_getType(const struct ZigClangBina
2738 return bitcast(casted->getType());2743 return bitcast(casted->getType());
2739}2744}
27402745
2746const struct ZigClangExpr *ZigClangConvertVectorExpr_getSrcExpr(const struct ZigClangConvertVectorExpr *self) {
2747 auto casted = reinterpret_cast<const clang::ConvertVectorExpr *>(self);
2748 return reinterpret_cast<const struct ZigClangExpr *>(casted->getSrcExpr());
2749}
2750
2751struct ZigClangQualType ZigClangConvertVectorExpr_getTypeSourceInfo_getType(const struct ZigClangConvertVectorExpr *self) {
2752 auto casted = reinterpret_cast<const clang::ConvertVectorExpr *>(self);
2753 return bitcast(casted->getTypeSourceInfo()->getType());
2754}
2755
2741struct ZigClangQualType ZigClangDecayedType_getDecayedType(const struct ZigClangDecayedType *self) {2756struct ZigClangQualType ZigClangDecayedType_getDecayedType(const struct ZigClangDecayedType *self) {
2742 auto casted = reinterpret_cast<const clang::DecayedType *>(self);2757 auto casted = reinterpret_cast<const clang::DecayedType *>(self);
2743 return bitcast(casted->getDecayedType());2758 return bitcast(casted->getDecayedType());
...@@ -2843,6 +2858,16 @@ struct ZigClangQualType ZigClangValueDecl_getType(const struct ZigClangValueDecl...@@ -2843,6 +2858,16 @@ struct ZigClangQualType ZigClangValueDecl_getType(const struct ZigClangValueDecl
2843 return bitcast(casted->getType());2858 return bitcast(casted->getType());
2844}2859}
28452860
2861struct ZigClangQualType ZigClangVectorType_getElementType(const struct ZigClangVectorType *self) {
2862 auto casted = reinterpret_cast<const clang::VectorType *>(self);
2863 return bitcast(casted->getElementType());
2864}
2865
2866unsigned ZigClangVectorType_getNumElements(const struct ZigClangVectorType *self) {
2867 auto casted = reinterpret_cast<const clang::VectorType *>(self);
2868 return casted->getNumElements();
2869}
2870
2846const struct ZigClangExpr *ZigClangWhileStmt_getCond(const struct ZigClangWhileStmt *self) {2871const struct ZigClangExpr *ZigClangWhileStmt_getCond(const struct ZigClangWhileStmt *self) {
2847 auto casted = reinterpret_cast<const clang::WhileStmt *>(self);2872 auto casted = reinterpret_cast<const clang::WhileStmt *>(self);
2848 return reinterpret_cast<const struct ZigClangExpr *>(casted->getCond());2873 return reinterpret_cast<const struct ZigClangExpr *>(casted->getCond());
...@@ -2922,6 +2947,15 @@ struct ZigClangSourceLocation ZigClangUnaryExprOrTypeTraitExpr_getBeginLoc(...@@ -2922,6 +2947,15 @@ struct ZigClangSourceLocation ZigClangUnaryExprOrTypeTraitExpr_getBeginLoc(
2922 return bitcast(casted->getBeginLoc());2947 return bitcast(casted->getBeginLoc());
2923}2948}
29242949
2950unsigned ZigClangShuffleVectorExpr_getNumSubExprs(const ZigClangShuffleVectorExpr *self) {
2951 auto casted = reinterpret_cast<const clang::ShuffleVectorExpr *>(self);
2952 return casted->getNumSubExprs();
2953}
2954
2955const struct ZigClangExpr *ZigClangShuffleVectorExpr_getExpr(const struct ZigClangShuffleVectorExpr *self, unsigned idx) {
2956 auto casted = reinterpret_cast<const clang::ShuffleVectorExpr *>(self);
2957 return reinterpret_cast<const struct ZigClangExpr *>(casted->getExpr(idx));
2958}
29252959
2926enum ZigClangUnaryExprOrTypeTrait_Kind ZigClangUnaryExprOrTypeTraitExpr_getKind(2960enum ZigClangUnaryExprOrTypeTrait_Kind ZigClangUnaryExprOrTypeTraitExpr_getKind(
2927 const struct ZigClangUnaryExprOrTypeTraitExpr *self)2961 const struct ZigClangUnaryExprOrTypeTraitExpr *self)
src/zig_clang.h+10
...@@ -1064,6 +1064,7 @@ ZIG_EXTERN_C bool ZigClangType_isBooleanType(const struct ZigClangType *self);...@@ -1064,6 +1064,7 @@ ZIG_EXTERN_C bool ZigClangType_isBooleanType(const struct ZigClangType *self);
1064ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self);1064ZIG_EXTERN_C bool ZigClangType_isVoidType(const struct ZigClangType *self);
1065ZIG_EXTERN_C bool ZigClangType_isArrayType(const struct ZigClangType *self);1065ZIG_EXTERN_C bool ZigClangType_isArrayType(const struct ZigClangType *self);
1066ZIG_EXTERN_C bool ZigClangType_isRecordType(const struct ZigClangType *self);1066ZIG_EXTERN_C bool ZigClangType_isRecordType(const struct ZigClangType *self);
1067ZIG_EXTERN_C bool ZigClangType_isVectorType(const struct ZigClangType *self);
1067ZIG_EXTERN_C bool ZigClangType_isIncompleteOrZeroLengthArrayType(const ZigClangQualType *self, const struct ZigClangASTContext *ctx);1068ZIG_EXTERN_C bool ZigClangType_isIncompleteOrZeroLengthArrayType(const ZigClangQualType *self, const struct ZigClangASTContext *ctx);
1068ZIG_EXTERN_C bool ZigClangType_isConstantArrayType(const ZigClangType *self);1069ZIG_EXTERN_C bool ZigClangType_isConstantArrayType(const ZigClangType *self);
1069ZIG_EXTERN_C const char *ZigClangType_getTypeClassName(const struct ZigClangType *self);1070ZIG_EXTERN_C const char *ZigClangType_getTypeClassName(const struct ZigClangType *self);
...@@ -1199,6 +1200,9 @@ ZIG_EXTERN_C const struct ZigClangExpr *ZigClangBinaryOperator_getLHS(const stru...@@ -1199,6 +1200,9 @@ ZIG_EXTERN_C const struct ZigClangExpr *ZigClangBinaryOperator_getLHS(const stru
1199ZIG_EXTERN_C const struct ZigClangExpr *ZigClangBinaryOperator_getRHS(const struct ZigClangBinaryOperator *);1200ZIG_EXTERN_C const struct ZigClangExpr *ZigClangBinaryOperator_getRHS(const struct ZigClangBinaryOperator *);
1200ZIG_EXTERN_C struct ZigClangQualType ZigClangBinaryOperator_getType(const struct ZigClangBinaryOperator *);1201ZIG_EXTERN_C struct ZigClangQualType ZigClangBinaryOperator_getType(const struct ZigClangBinaryOperator *);
12011202
1203ZIG_EXTERN_C const struct ZigClangExpr *ZigClangConvertVectorExpr_getSrcExpr(const struct ZigClangConvertVectorExpr *);
1204ZIG_EXTERN_C struct ZigClangQualType ZigClangConvertVectorExpr_getTypeSourceInfo_getType(const struct ZigClangConvertVectorExpr *);
1205
1202ZIG_EXTERN_C struct ZigClangQualType ZigClangDecayedType_getDecayedType(const struct ZigClangDecayedType *);1206ZIG_EXTERN_C struct ZigClangQualType ZigClangDecayedType_getDecayedType(const struct ZigClangDecayedType *);
12031207
1204ZIG_EXTERN_C const struct ZigClangCompoundStmt *ZigClangStmtExpr_getSubStmt(const struct ZigClangStmtExpr *);1208ZIG_EXTERN_C const struct ZigClangCompoundStmt *ZigClangStmtExpr_getSubStmt(const struct ZigClangStmtExpr *);
...@@ -1228,6 +1232,9 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangUnaryOperator_getBeginLoc(con...@@ -1228,6 +1232,9 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangUnaryOperator_getBeginLoc(con
12281232
1229ZIG_EXTERN_C struct ZigClangQualType ZigClangValueDecl_getType(const struct ZigClangValueDecl *);1233ZIG_EXTERN_C struct ZigClangQualType ZigClangValueDecl_getType(const struct ZigClangValueDecl *);
12301234
1235ZIG_EXTERN_C struct ZigClangQualType ZigClangVectorType_getElementType(const struct ZigClangVectorType *);
1236ZIG_EXTERN_C unsigned ZigClangVectorType_getNumElements(const struct ZigClangVectorType *);
1237
1231ZIG_EXTERN_C const struct ZigClangExpr *ZigClangWhileStmt_getCond(const struct ZigClangWhileStmt *);1238ZIG_EXTERN_C const struct ZigClangExpr *ZigClangWhileStmt_getCond(const struct ZigClangWhileStmt *);
1232ZIG_EXTERN_C const struct ZigClangStmt *ZigClangWhileStmt_getBody(const struct ZigClangWhileStmt *);1239ZIG_EXTERN_C const struct ZigClangStmt *ZigClangWhileStmt_getBody(const struct ZigClangWhileStmt *);
12331240
...@@ -1252,6 +1259,9 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangUnaryExprOrTypeTraitExpr_getTypeOfA...@@ -1252,6 +1259,9 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangUnaryExprOrTypeTraitExpr_getTypeOfA
1252ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangUnaryExprOrTypeTraitExpr_getBeginLoc(const struct ZigClangUnaryExprOrTypeTraitExpr *);1259ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangUnaryExprOrTypeTraitExpr_getBeginLoc(const struct ZigClangUnaryExprOrTypeTraitExpr *);
1253ZIG_EXTERN_C enum ZigClangUnaryExprOrTypeTrait_Kind ZigClangUnaryExprOrTypeTraitExpr_getKind(const struct ZigClangUnaryExprOrTypeTraitExpr *);1260ZIG_EXTERN_C enum ZigClangUnaryExprOrTypeTrait_Kind ZigClangUnaryExprOrTypeTraitExpr_getKind(const struct ZigClangUnaryExprOrTypeTraitExpr *);
12541261
1262ZIG_EXTERN_C unsigned ZigClangShuffleVectorExpr_getNumSubExprs(const struct ZigClangShuffleVectorExpr *);
1263ZIG_EXTERN_C const struct ZigClangExpr *ZigClangShuffleVectorExpr_getExpr(const struct ZigClangShuffleVectorExpr *, unsigned);
1264
1255ZIG_EXTERN_C const struct ZigClangStmt *ZigClangDoStmt_getBody(const struct ZigClangDoStmt *);1265ZIG_EXTERN_C const struct ZigClangStmt *ZigClangDoStmt_getBody(const struct ZigClangDoStmt *);
1256ZIG_EXTERN_C const struct ZigClangExpr *ZigClangDoStmt_getCond(const struct ZigClangDoStmt *);1266ZIG_EXTERN_C const struct ZigClangExpr *ZigClangDoStmt_getCond(const struct ZigClangDoStmt *);
12571267
test/run_translated_c.zig+102
...@@ -1308,4 +1308,106 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {...@@ -1308,4 +1308,106 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
1308 \\ ufoo = (uval += 100000000); // compile error if @truncate() not inserted1308 \\ ufoo = (uval += 100000000); // compile error if @truncate() not inserted
1309 \\}1309 \\}
1310 , "");1310 , "");
1311
1312 cases.add("basic vector expressions",
1313 \\#include <stdlib.h>
1314 \\#include <stdint.h>
1315 \\typedef int16_t __v8hi __attribute__((__vector_size__(16)));
1316 \\int main(int argc, char**argv) {
1317 \\ __v8hi uninitialized;
1318 \\ __v8hi empty_init = {};
1319 \\ __v8hi partial_init = {0, 1, 2, 3};
1320 \\
1321 \\ __v8hi a = {0, 1, 2, 3, 4, 5, 6, 7};
1322 \\ __v8hi b = (__v8hi) {100, 200, 300, 400, 500, 600, 700, 800};
1323 \\
1324 \\ __v8hi sum = a + b;
1325 \\ for (int i = 0; i < 8; i++) {
1326 \\ if (sum[i] != a[i] + b[i]) abort();
1327 \\ }
1328 \\ return 0;
1329 \\}
1330 , "");
1331
1332 cases.add("__builtin_shufflevector",
1333 \\#include <stdlib.h>
1334 \\#include <stdint.h>
1335 \\typedef int16_t __v4hi __attribute__((__vector_size__(8)));
1336 \\typedef int16_t __v8hi __attribute__((__vector_size__(16)));
1337 \\int main(int argc, char**argv) {
1338 \\ __v8hi v8_a = {0, 1, 2, 3, 4, 5, 6, 7};
1339 \\ __v8hi v8_b = {100, 200, 300, 400, 500, 600, 700, 800};
1340 \\ __v8hi shuffled = __builtin_shufflevector(v8_a, v8_b, 0, 1, 2, 3, 8, 9, 10, 11);
1341 \\ for (int i = 0; i < 8; i++) {
1342 \\ if (i < 4) {
1343 \\ if (shuffled[i] != v8_a[i]) abort();
1344 \\ } else {
1345 \\ if (shuffled[i] != v8_b[i - 4]) abort();
1346 \\ }
1347 \\ }
1348 \\ shuffled = __builtin_shufflevector(
1349 \\ (__v8hi) {-1, -1, -1, -1, -1, -1, -1, -1},
1350 \\ (__v8hi) {42, 42, 42, 42, 42, 42, 42, 42},
1351 \\ 0, 1, 2, 3, 8, 9, 10, 11
1352 \\ );
1353 \\ for (int i = 0; i < 8; i++) {
1354 \\ if (i < 4) {
1355 \\ if (shuffled[i] != -1) abort();
1356 \\ } else {
1357 \\ if (shuffled[i] != 42) abort();
1358 \\ }
1359 \\ }
1360 \\ __v4hi shuffled_to_fewer_elements = __builtin_shufflevector(v8_a, v8_b, 0, 1, 8, 9);
1361 \\ for (int i = 0; i < 4; i++) {
1362 \\ if (i < 2) {
1363 \\ if (shuffled_to_fewer_elements[i] != v8_a[i]) abort();
1364 \\ } else {
1365 \\ if (shuffled_to_fewer_elements[i] != v8_b[i - 2]) abort();
1366 \\ }
1367 \\ }
1368 \\ __v4hi v4_a = {0, 1, 2, 3};
1369 \\ __v4hi v4_b = {100, 200, 300, 400};
1370 \\ __v8hi shuffled_to_more_elements = __builtin_shufflevector(v4_a, v4_b, 0, 1, 2, 3, 4, 5, 6, 7);
1371 \\ for (int i = 0; i < 4; i++) {
1372 \\ if (shuffled_to_more_elements[i] != v4_a[i]) abort();
1373 \\ if (shuffled_to_more_elements[i + 4] != v4_b[i]) abort();
1374 \\ }
1375 \\ return 0;
1376 \\}
1377 , "");
1378
1379 cases.add("__builtin_convertvector",
1380 \\#include <stdlib.h>
1381 \\#include <stdint.h>
1382 \\typedef int16_t __v8hi __attribute__((__vector_size__(16)));
1383 \\typedef uint16_t __v8hu __attribute__((__vector_size__(16)));
1384 \\int main(int argc, char**argv) {
1385 \\ __v8hi signed_vector = { 1, 2, 3, 4, -1, -2, -3,-4};
1386 \\ __v8hu unsigned_vector = __builtin_convertvector(signed_vector, __v8hu);
1387 \\
1388 \\ for (int i = 0; i < 8; i++) {
1389 \\ if (unsigned_vector[i] != (uint16_t)signed_vector[i]) abort();
1390 \\ }
1391 \\ return 0;
1392 \\}
1393 , "");
1394
1395 cases.add("vector casting",
1396 \\#include <stdlib.h>
1397 \\#include <stdint.h>
1398 \\typedef int8_t __v8qi __attribute__((__vector_size__(8)));
1399 \\typedef uint8_t __v8qu __attribute__((__vector_size__(8)));
1400 \\int main(int argc, char**argv) {
1401 \\ __v8qi signed_vector = { 1, 2, 3, 4, -1, -2, -3,-4};
1402 \\
1403 \\ uint64_t big_int = (uint64_t) signed_vector;
1404 \\ if (big_int != 0x01020304FFFEFDFCULL && big_int != 0xFCFDFEFF04030201ULL) abort();
1405 \\ __v8qu unsigned_vector = (__v8qu) big_int;
1406 \\ for (int i = 0; i < 8; i++) {
1407 \\ if (unsigned_vector[i] != (uint8_t)signed_vector[i] && unsigned_vector[i] != (uint8_t)signed_vector[7 - i]) abort();
1408 \\ }
1409 \\ return 0;
1410 \\}
1411 , "");
1412
1311}1413}