| author | |
| committer | |
| log | ea393b2bca7587955df81d149caecc5522944d15 |
| tree | 1391b7c5e6a462e86c8730e9a74c046b2d95a827 |
| parent | e09465fc49d86cc4aa9338106862d3e059ae3303 |
9 files changed, 91 insertions(+), 21 deletions(-)
src/Module.zig+1-1| ... | @@ -4761,7 +4761,7 @@ pub fn populateTestFunctions(mod: *Module) !void { | ... | @@ -4761,7 +4761,7 @@ pub fn populateTestFunctions(mod: *Module) !void { |
| 4761 | const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file; | 4761 | const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file; |
| 4762 | const builtin_namespace = builtin_file.root_decl.?.namespace; | 4762 | const builtin_namespace = builtin_file.root_decl.?.namespace; |
| 4763 | const decl = builtin_namespace.decls.get("test_functions").?; | 4763 | const decl = builtin_namespace.decls.get("test_functions").?; |
| 4764 | var buf: Type.Payload.ElemType = undefined; | 4764 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 4765 | const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType(); | 4765 | const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType(); |
| 4766 | 4766 | ||
| 4767 | const array_decl = d: { | 4767 | const array_decl = d: { |
src/Sema.zig+1-1| ... | @@ -8390,7 +8390,7 @@ fn fieldVal( | ... | @@ -8390,7 +8390,7 @@ fn fieldVal( |
| 8390 | .Pointer => switch (object_ty.ptrSize()) { | 8390 | .Pointer => switch (object_ty.ptrSize()) { |
| 8391 | .Slice => { | 8391 | .Slice => { |
| 8392 | if (mem.eql(u8, field_name, "ptr")) { | 8392 | if (mem.eql(u8, field_name, "ptr")) { |
| 8393 | const buf = try arena.create(Type.Payload.ElemType); | 8393 | const buf = try arena.create(Type.SlicePtrFieldTypeBuffer); |
| 8394 | const result_ty = object_ty.slicePtrFieldType(buf); | 8394 | const result_ty = object_ty.slicePtrFieldType(buf); |
| 8395 | if (try sema.resolveMaybeUndefVal(block, object_src, object)) |val| { | 8395 | if (try sema.resolveMaybeUndefVal(block, object_src, object)) |val| { |
| 8396 | if (val.isUndef()) return sema.addConstUndef(result_ty); | 8396 | if (val.isUndef()) return sema.addConstUndef(result_ty); |
src/codegen.zig+1-1| ... | @@ -4873,7 +4873,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { | ... | @@ -4873,7 +4873,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 4873 | switch (typed_value.ty.zigTypeTag()) { | 4873 | switch (typed_value.ty.zigTypeTag()) { |
| 4874 | .Pointer => switch (typed_value.ty.ptrSize()) { | 4874 | .Pointer => switch (typed_value.ty.ptrSize()) { |
| 4875 | .Slice => { | 4875 | .Slice => { |
| 4876 | var buf: Type.Payload.ElemType = undefined; | 4876 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 4877 | const ptr_type = typed_value.ty.slicePtrFieldType(&buf); | 4877 | const ptr_type = typed_value.ty.slicePtrFieldType(&buf); |
| 4878 | const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val }); | 4878 | const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val }); |
| 4879 | const slice_len = typed_value.val.sliceLen(); | 4879 | const slice_len = typed_value.val.sliceLen(); |
src/codegen/c.zig+1-1| ... | @@ -251,7 +251,7 @@ pub const DeclGen = struct { | ... | @@ -251,7 +251,7 @@ pub const DeclGen = struct { |
| 251 | try writer.writeByte('('); | 251 | try writer.writeByte('('); |
| 252 | try dg.renderType(writer, t); | 252 | try dg.renderType(writer, t); |
| 253 | try writer.writeAll("){"); | 253 | try writer.writeAll("){"); |
| 254 | var buf: Type.Payload.ElemType = undefined; | 254 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 255 | try dg.renderValue(writer, t.slicePtrFieldType(&buf), val); | 255 | try dg.renderValue(writer, t.slicePtrFieldType(&buf), val); |
| 256 | try writer.writeAll(", "); | 256 | try writer.writeAll(", "); |
| 257 | try writer.print("{d}", .{val.sliceLen()}); | 257 | try writer.print("{d}", .{val.sliceLen()}); |
src/codegen/llvm.zig+32-8| ... | @@ -554,7 +554,8 @@ pub const DeclGen = struct { | ... | @@ -554,7 +554,8 @@ pub const DeclGen = struct { |
| 554 | @intCast(c_uint, fn_param_len), | 554 | @intCast(c_uint, fn_param_len), |
| 555 | .False, | 555 | .False, |
| 556 | ); | 556 | ); |
| 557 | const llvm_fn = self.llvmModule().addFunction(decl.name, fn_type); | 557 | const llvm_addrspace = self.llvmAddressSpace(decl.@"addrspace"); |
| 558 | const llvm_fn = self.llvmModule().addFunctionInAddressSpace(decl.name, fn_type, llvm_addrspace); | ||
| 558 | 559 | ||
| 559 | const is_extern = decl.val.tag() == .extern_fn; | 560 | const is_extern = decl.val.tag() == .extern_fn; |
| 560 | if (!is_extern) { | 561 | if (!is_extern) { |
| ... | @@ -576,7 +577,27 @@ pub const DeclGen = struct { | ... | @@ -576,7 +577,27 @@ pub const DeclGen = struct { |
| 576 | if (llvm_module.getNamedGlobal(decl.name)) |val| return val; | 577 | if (llvm_module.getNamedGlobal(decl.name)) |val| return val; |
| 577 | // TODO: remove this redundant `llvmType`, it is also called in `genTypedValue`. | 578 | // TODO: remove this redundant `llvmType`, it is also called in `genTypedValue`. |
| 578 | const llvm_type = try self.llvmType(decl.ty); | 579 | const llvm_type = try self.llvmType(decl.ty); |
| 579 | return llvm_module.addGlobal(llvm_type, decl.name); | 580 | const llvm_addrspace = self.llvmAddressSpace(decl.@"addrspace"); |
| 581 | return llvm_module.addGlobalInAddressSpace(llvm_type, decl.name, llvm_addrspace); | ||
| 582 | } | ||
| 583 | |||
| 584 | fn llvmAddressSpace(self: DeclGen, address_space: std.builtin.AddressSpace) c_uint { | ||
| 585 | const target = self.module.getTarget(); | ||
| 586 | return switch (address_space) { | ||
| 587 | .generic => llvm.address_space.default, | ||
| 588 | .gs => switch (target.cpu.arch) { | ||
| 589 | .i386, .x86_64 => llvm.address_space.x86.gs, | ||
| 590 | else => unreachable, | ||
| 591 | }, | ||
| 592 | .fs => switch (target.cpu.arch) { | ||
| 593 | .i386, .x86_64 => llvm.address_space.x86.fs, | ||
| 594 | else => unreachable, | ||
| 595 | }, | ||
| 596 | .ss => switch (target.cpu.arch) { | ||
| 597 | .i386, .x86_64 => llvm.address_space.x86.ss, | ||
| 598 | else => unreachable, | ||
| 599 | }, | ||
| 600 | }; | ||
| 580 | } | 601 | } |
| 581 | 602 | ||
| 582 | fn llvmType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type { | 603 | fn llvmType(self: *DeclGen, t: Type) error{ OutOfMemory, CodegenFail }!*const llvm.Type { |
| ... | @@ -605,7 +626,7 @@ pub const DeclGen = struct { | ... | @@ -605,7 +626,7 @@ pub const DeclGen = struct { |
| 605 | .Bool => return self.context.intType(1), | 626 | .Bool => return self.context.intType(1), |
| 606 | .Pointer => { | 627 | .Pointer => { |
| 607 | if (t.isSlice()) { | 628 | if (t.isSlice()) { |
| 608 | var buf: Type.Payload.ElemType = undefined; | 629 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 609 | const ptr_type = t.slicePtrFieldType(&buf); | 630 | const ptr_type = t.slicePtrFieldType(&buf); |
| 610 | 631 | ||
| 611 | const fields: [2]*const llvm.Type = .{ | 632 | const fields: [2]*const llvm.Type = .{ |
| ... | @@ -615,7 +636,8 @@ pub const DeclGen = struct { | ... | @@ -615,7 +636,8 @@ pub const DeclGen = struct { |
| 615 | return self.context.structType(&fields, fields.len, .False); | 636 | return self.context.structType(&fields, fields.len, .False); |
| 616 | } else { | 637 | } else { |
| 617 | const elem_type = try self.llvmType(t.elemType()); | 638 | const elem_type = try self.llvmType(t.elemType()); |
| 618 | return elem_type.pointerType(0); | 639 | const llvm_addrspace = self.llvmAddressSpace(t.ptrAddressSpace()); |
| 640 | return elem_type.pointerType(llvm_addrspace); | ||
| 619 | } | 641 | } |
| 620 | }, | 642 | }, |
| 621 | .Array => { | 643 | .Array => { |
| ... | @@ -681,7 +703,8 @@ pub const DeclGen = struct { | ... | @@ -681,7 +703,8 @@ pub const DeclGen = struct { |
| 681 | @intCast(c_uint, llvm_params.len), | 703 | @intCast(c_uint, llvm_params.len), |
| 682 | llvm.Bool.fromBool(is_var_args), | 704 | llvm.Bool.fromBool(is_var_args), |
| 683 | ); | 705 | ); |
| 684 | return llvm_fn_ty.pointerType(0); | 706 | const llvm_addrspace = self.llvmAddressSpace(t.fnAddressSpace()); |
| 707 | return llvm_fn_ty.pointerType(llvm_addrspace); | ||
| 685 | }, | 708 | }, |
| 686 | .ComptimeInt => unreachable, | 709 | .ComptimeInt => unreachable, |
| 687 | .ComptimeFloat => unreachable, | 710 | .ComptimeFloat => unreachable, |
| ... | @@ -749,7 +772,7 @@ pub const DeclGen = struct { | ... | @@ -749,7 +772,7 @@ pub const DeclGen = struct { |
| 749 | .Pointer => switch (tv.val.tag()) { | 772 | .Pointer => switch (tv.val.tag()) { |
| 750 | .decl_ref => { | 773 | .decl_ref => { |
| 751 | if (tv.ty.isSlice()) { | 774 | if (tv.ty.isSlice()) { |
| 752 | var buf: Type.Payload.ElemType = undefined; | 775 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 753 | const ptr_ty = tv.ty.slicePtrFieldType(&buf); | 776 | const ptr_ty = tv.ty.slicePtrFieldType(&buf); |
| 754 | var slice_len: Value.Payload.U64 = .{ | 777 | var slice_len: Value.Payload.U64 = .{ |
| 755 | .base = .{ .tag = .int_u64 }, | 778 | .base = .{ .tag = .int_u64 }, |
| ... | @@ -779,12 +802,13 @@ pub const DeclGen = struct { | ... | @@ -779,12 +802,13 @@ pub const DeclGen = struct { |
| 779 | decl.alive = true; | 802 | decl.alive = true; |
| 780 | const val = try self.resolveGlobalDecl(decl); | 803 | const val = try self.resolveGlobalDecl(decl); |
| 781 | const llvm_var_type = try self.llvmType(tv.ty); | 804 | const llvm_var_type = try self.llvmType(tv.ty); |
| 782 | const llvm_type = llvm_var_type.pointerType(0); | 805 | const llvm_addrspace = self.llvmAddressSpace(decl.@"addrspace"); |
| 806 | const llvm_type = llvm_var_type.pointerType(llvm_addrspace); | ||
| 783 | return val.constBitCast(llvm_type); | 807 | return val.constBitCast(llvm_type); |
| 784 | }, | 808 | }, |
| 785 | .slice => { | 809 | .slice => { |
| 786 | const slice = tv.val.castTag(.slice).?.data; | 810 | const slice = tv.val.castTag(.slice).?.data; |
| 787 | var buf: Type.Payload.ElemType = undefined; | 811 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 788 | const fields: [2]*const llvm.Value = .{ | 812 | const fields: [2]*const llvm.Value = .{ |
| 789 | try self.genTypedValue(.{ | 813 | try self.genTypedValue(.{ |
| 790 | .ty = tv.ty.slicePtrFieldType(&buf), | 814 | .ty = tv.ty.slicePtrFieldType(&buf), |
src/codegen/llvm/bindings.zig+8| ... | @@ -197,6 +197,9 @@ pub const Module = opaque { | ... | @@ -197,6 +197,9 @@ pub const Module = opaque { |
| 197 | pub const addFunction = LLVMAddFunction; | 197 | pub const addFunction = LLVMAddFunction; |
| 198 | extern fn LLVMAddFunction(*const Module, Name: [*:0]const u8, FunctionTy: *const Type) *const Value; | 198 | extern fn LLVMAddFunction(*const Module, Name: [*:0]const u8, FunctionTy: *const Type) *const Value; |
| 199 | 199 | ||
| 200 | pub const addFunctionInAddressSpace = ZigLLVMAddFunctionInAddressSpace; | ||
| 201 | extern fn ZigLLVMAddFunctionInAddressSpace(*const Module, Name: [*:0]const u8, FunctionTy: *const Type, AddressSpace: c_uint) *const Value; | ||
| 202 | |||
| 200 | pub const getNamedFunction = LLVMGetNamedFunction; | 203 | pub const getNamedFunction = LLVMGetNamedFunction; |
| 201 | extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value; | 204 | extern fn LLVMGetNamedFunction(*const Module, Name: [*:0]const u8) ?*const Value; |
| 202 | 205 | ||
| ... | @@ -209,6 +212,9 @@ pub const Module = opaque { | ... | @@ -209,6 +212,9 @@ pub const Module = opaque { |
| 209 | pub const addGlobal = LLVMAddGlobal; | 212 | pub const addGlobal = LLVMAddGlobal; |
| 210 | extern fn LLVMAddGlobal(M: *const Module, Ty: *const Type, Name: [*:0]const u8) *const Value; | 213 | extern fn LLVMAddGlobal(M: *const Module, Ty: *const Type, Name: [*:0]const u8) *const Value; |
| 211 | 214 | ||
| 215 | pub const addGlobalInAddressSpace = LLVMAddGlobalInAddressSpace; | ||
| 216 | extern fn LLVMAddGlobalInAddressSpace(M: *const Module, Ty: *const Type, Name: [*:0]const u8, AddressSpace: c_uint) *const Value; | ||
| 217 | |||
| 212 | pub const getNamedGlobal = LLVMGetNamedGlobal; | 218 | pub const getNamedGlobal = LLVMGetNamedGlobal; |
| 213 | extern fn LLVMGetNamedGlobal(M: *const Module, Name: [*:0]const u8) ?*const Value; | 219 | extern fn LLVMGetNamedGlobal(M: *const Module, Name: [*:0]const u8) ?*const Value; |
| 214 | 220 | ||
| ... | @@ -975,6 +981,8 @@ pub const TypeKind = enum(c_int) { | ... | @@ -975,6 +981,8 @@ pub const TypeKind = enum(c_int) { |
| 975 | }; | 981 | }; |
| 976 | 982 | ||
| 977 | pub const address_space = struct { | 983 | pub const address_space = struct { |
| 984 | pub const default = 0; | ||
| 985 | |||
| 978 | // See llvm/lib/Target/X86/X86.h | 986 | // See llvm/lib/Target/X86/X86.h |
| 979 | pub const x86_64 = x86; | 987 | pub const x86_64 = x86; |
| 980 | pub const x86 = struct { | 988 | pub const x86 = struct { |
src/type.zig+39-9| ... | @@ -2161,42 +2161,72 @@ pub const Type = extern union { | ... | @@ -2161,42 +2161,72 @@ pub const Type = extern union { |
| 2161 | }; | 2161 | }; |
| 2162 | } | 2162 | } |
| 2163 | 2163 | ||
| 2164 | pub fn slicePtrFieldType(self: Type, buffer: *Payload.ElemType) Type { | 2164 | pub const SlicePtrFieldTypeBuffer = union { |
| 2165 | elem_type: Payload.ElemType, | ||
| 2166 | pointer: Payload.Pointer, | ||
| 2167 | }; | ||
| 2168 | |||
| 2169 | pub fn slicePtrFieldType(self: Type, buffer: *SlicePtrFieldTypeBuffer) Type { | ||
| 2165 | switch (self.tag()) { | 2170 | switch (self.tag()) { |
| 2166 | .const_slice_u8 => return Type.initTag(.manyptr_const_u8), | 2171 | .const_slice_u8 => return Type.initTag(.manyptr_const_u8), |
| 2167 | 2172 | ||
| 2168 | .const_slice => { | 2173 | .const_slice => { |
| 2169 | const elem_type = self.castTag(.const_slice).?.data; | 2174 | const elem_type = self.castTag(.const_slice).?.data; |
| 2170 | buffer.* = .{ | 2175 | buffer.elem_type = .{ |
| 2171 | .base = .{ .tag = .many_const_pointer }, | 2176 | .base = .{ .tag = .many_const_pointer }, |
| 2172 | .data = elem_type, | 2177 | .data = elem_type, |
| 2173 | }; | 2178 | }; |
| 2174 | return Type.initPayload(&buffer.base); | 2179 | return Type.initPayload(&buffer.elem_type.base); |
| 2175 | }, | 2180 | }, |
| 2176 | .mut_slice => { | 2181 | .mut_slice => { |
| 2177 | const elem_type = self.castTag(.mut_slice).?.data; | 2182 | const elem_type = self.castTag(.mut_slice).?.data; |
| 2178 | buffer.* = .{ | 2183 | buffer.elem_type = .{ |
| 2179 | .base = .{ .tag = .many_mut_pointer }, | 2184 | .base = .{ .tag = .many_mut_pointer }, |
| 2180 | .data = elem_type, | 2185 | .data = elem_type, |
| 2181 | }; | 2186 | }; |
| 2182 | return Type.initPayload(&buffer.base); | 2187 | return Type.initPayload(&buffer.elem_type.base); |
| 2183 | }, | 2188 | }, |
| 2184 | 2189 | ||
| 2185 | .pointer => { | 2190 | .pointer => { |
| 2186 | const payload = self.castTag(.pointer).?.data; | 2191 | const payload = self.castTag(.pointer).?.data; |
| 2187 | assert(payload.size == .Slice); | 2192 | assert(payload.size == .Slice); |
| 2188 | if (payload.mutable) { | 2193 | |
| 2189 | buffer.* = .{ | 2194 | if (payload.sentinel != null or |
| 2195 | payload.@"align" != 0 or | ||
| 2196 | payload.@"addrspace" != .generic or | ||
| 2197 | payload.bit_offset != 0 or | ||
| 2198 | payload.host_size != 0 or | ||
| 2199 | payload.@"allowzero" or | ||
| 2200 | payload.@"volatile" | ||
| 2201 | ) { | ||
| 2202 | buffer.pointer = .{ | ||
| 2203 | .data = .{ | ||
| 2204 | .pointee_type = payload.pointee_type, | ||
| 2205 | .sentinel = payload.sentinel, | ||
| 2206 | .@"align" = payload.@"align", | ||
| 2207 | .@"addrspace" = payload.@"addrspace", | ||
| 2208 | .bit_offset = payload.bit_offset, | ||
| 2209 | .host_size = payload.host_size, | ||
| 2210 | .@"allowzero" = payload.@"allowzero", | ||
| 2211 | .mutable = payload.mutable, | ||
| 2212 | .@"volatile" = payload.@"volatile", | ||
| 2213 | .size = .Many | ||
| 2214 | }, | ||
| 2215 | }; | ||
| 2216 | return Type.initPayload(&buffer.pointer.base); | ||
| 2217 | } else if (payload.mutable) { | ||
| 2218 | buffer.elem_type = .{ | ||
| 2190 | .base = .{ .tag = .many_mut_pointer }, | 2219 | .base = .{ .tag = .many_mut_pointer }, |
| 2191 | .data = payload.pointee_type, | 2220 | .data = payload.pointee_type, |
| 2192 | }; | 2221 | }; |
| 2222 | return Type.initPayload(&buffer.elem_type.base); | ||
| 2193 | } else { | 2223 | } else { |
| 2194 | buffer.* = .{ | 2224 | buffer.elem_type = .{ |
| 2195 | .base = .{ .tag = .many_const_pointer }, | 2225 | .base = .{ .tag = .many_const_pointer }, |
| 2196 | .data = payload.pointee_type, | 2226 | .data = payload.pointee_type, |
| 2197 | }; | 2227 | }; |
| 2228 | return Type.initPayload(&buffer.elem_type.base); | ||
| 2198 | } | 2229 | } |
| 2199 | return Type.initPayload(&buffer.base); | ||
| 2200 | }, | 2230 | }, |
| 2201 | 2231 | ||
| 2202 | else => unreachable, | 2232 | else => unreachable, |
src/zig_llvm.cpp+5| ... | @@ -416,6 +416,11 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) { | ... | @@ -416,6 +416,11 @@ ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref) { |
| 416 | return wrap(Type::getTokenTy(*unwrap(context_ref))); | 416 | return wrap(Type::getTokenTy(*unwrap(context_ref))); |
| 417 | } | 417 | } |
| 418 | 418 | ||
| 419 | LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, LLVMTypeRef FunctionTy, unsigned AddressSpace) { | ||
| 420 | Function* func = Function::Create(unwrap<FunctionType>(FunctionTy), GlobalValue::ExternalLinkage, AddressSpace, Name, unwrap(M)); | ||
| 421 | return wrap(func); | ||
| 422 | } | ||
| 423 | |||
| 419 | LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, | 424 | LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, |
| 420 | unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, const char *Name) | 425 | unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, const char *Name) |
| 421 | { | 426 | { |
src/zig_llvm.h+3| ... | @@ -65,6 +65,9 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co | ... | @@ -65,6 +65,9 @@ ZIG_EXTERN_C LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, co |
| 65 | 65 | ||
| 66 | ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref); | 66 | ZIG_EXTERN_C LLVMTypeRef ZigLLVMTokenTypeInContext(LLVMContextRef context_ref); |
| 67 | 67 | ||
| 68 | ZIG_EXTERN_C LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, | ||
| 69 | LLVMTypeRef FunctionTy, unsigned AddressSpace); | ||
| 70 | |||
| 68 | enum ZigLLVM_CallingConv { | 71 | enum ZigLLVM_CallingConv { |
| 69 | ZigLLVM_C = 0, | 72 | ZigLLVM_C = 0, |
| 70 | ZigLLVM_Fast = 8, | 73 | ZigLLVM_Fast = 8, |