diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-09-24 17:33:06 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-09-24 17:33:06 -0700 |
| commit | 42aa1ea115eca3dcc704eddf020ce87271a41174 (patch) | |
| tree | 3242b53425c599af929446e6776a2f6b3a0c6966 /src/codegen/llvm.zig | |
| parent | 87fd502fb68f8f488e6eba6b1f7d70902d6bfe5a (diff) | |
| download | zig-42aa1ea115eca3dcc704eddf020ce87271a41174.tar.gz zig-42aa1ea115eca3dcc704eddf020ce87271a41174.zip | |
stage2: implement `@memset` and `@memcpy` builtins
Diffstat (limited to 'src/codegen/llvm.zig')
| -rw-r--r-- | src/codegen/llvm.zig | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index b2b87b97d8..b15834c963 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1279,6 +1279,8 @@ pub const FuncGen = struct { .fence => try self.airFence(inst), .atomic_rmw => try self.airAtomicRmw(inst), .atomic_load => try self.airAtomicLoad(inst), + .memset => try self.airMemset(inst), + .memcpy => try self.airMemcpy(inst), .atomic_store_unordered => try self.airAtomicStore(inst, .Unordered), .atomic_store_monotonic => try self.airAtomicStore(inst, .Monotonic), @@ -2426,6 +2428,8 @@ pub const FuncGen = struct { const atomic_load = self.air.instructions.items(.data)[inst].atomic_load; const ptr = try self.resolveInst(atomic_load.ptr); const ptr_ty = self.air.typeOf(atomic_load.ptr); + if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) + return null; const ordering = toLlvmAtomicOrdering(atomic_load.order); const operand_ty = ptr_ty.elemType(); const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false); @@ -2468,6 +2472,55 @@ pub const FuncGen = struct { return null; } + fn airMemset(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + const pl_op = self.air.instructions.items(.data)[inst].pl_op; + const extra = self.air.extraData(Air.Bin, pl_op.payload).data; + const dest_ptr = try self.resolveInst(pl_op.operand); + const ptr_ty = self.air.typeOf(pl_op.operand); + const value = try self.resolveInst(extra.lhs); + const val_is_undef = if (self.air.value(extra.lhs)) |val| val.isUndef() else false; + const len = try self.resolveInst(extra.rhs); + const u8_llvm_ty = self.context.intType(8); + const ptr_u8_llvm_ty = u8_llvm_ty.pointerType(0); + const dest_ptr_u8 = self.builder.buildBitCast(dest_ptr, ptr_u8_llvm_ty, ""); + const fill_char = if (val_is_undef) u8_llvm_ty.constInt(0xaa, .False) else value; + const target = self.dg.module.getTarget(); + const dest_ptr_align = ptr_ty.ptrAlignment(target); + const memset = self.builder.buildMemSet(dest_ptr_u8, fill_char, len, dest_ptr_align); + memset.setVolatile(llvm.Bool.fromBool(ptr_ty.isVolatilePtr())); + + if (val_is_undef and self.dg.module.comp.bin_file.options.valgrind) { + // TODO generate valgrind client request to mark byte range as undefined + // see gen_valgrind_undef() in codegen.cpp + } + return null; + } + + fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + const pl_op = self.air.instructions.items(.data)[inst].pl_op; + const extra = self.air.extraData(Air.Bin, pl_op.payload).data; + const dest_ptr = try self.resolveInst(pl_op.operand); + const dest_ptr_ty = self.air.typeOf(pl_op.operand); + const src_ptr = try self.resolveInst(extra.lhs); + const src_ptr_ty = self.air.typeOf(extra.lhs); + const len = try self.resolveInst(extra.rhs); + const u8_llvm_ty = self.context.intType(8); + const ptr_u8_llvm_ty = u8_llvm_ty.pointerType(0); + const dest_ptr_u8 = self.builder.buildBitCast(dest_ptr, ptr_u8_llvm_ty, ""); + const src_ptr_u8 = self.builder.buildBitCast(src_ptr, ptr_u8_llvm_ty, ""); + const is_volatile = src_ptr_ty.isVolatilePtr() or dest_ptr_ty.isVolatilePtr(); + const target = self.dg.module.getTarget(); + const memcpy = self.builder.buildMemCpy( + dest_ptr_u8, + dest_ptr_ty.ptrAlignment(target), + src_ptr_u8, + src_ptr_ty.ptrAlignment(target), + len, + ); + memcpy.setVolatile(llvm.Bool.fromBool(is_volatile)); + return null; + } + fn getIntrinsic(self: *FuncGen, name: []const u8) *const llvm.Value { const id = llvm.lookupIntrinsicID(name.ptr, name.len); assert(id != 0); |
