aboutsummaryrefslogtreecommitdiffhomepage
path: root/compiler/compiler.go
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2023-07-07 15:15:49 +0200
committerRon Evans <[email protected]>2023-08-04 11:59:11 +0200
commita2f886a67a645add0c2e42289e20f89fe402294d (patch)
tree0d8e48a86eda24290e683c623a0fee3494916c26 /compiler/compiler.go
parentf791c821ff5d393c875fe41889b94c19cf5f508d (diff)
downloadtinygo-a2f886a67a645add0c2e42289e20f89fe402294d.tar.gz
tinygo-a2f886a67a645add0c2e42289e20f89fe402294d.zip
compiler: implement clear builtin for slices
Diffstat (limited to 'compiler/compiler.go')
-rw-r--r--compiler/compiler.go35
1 files changed, 35 insertions, 0 deletions
diff --git a/compiler/compiler.go b/compiler/compiler.go
index 46c3a0672..6af6debe8 100644
--- a/compiler/compiler.go
+++ b/compiler/compiler.go
@@ -1600,6 +1600,41 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
cplx = b.CreateInsertValue(cplx, r, 0, "")
cplx = b.CreateInsertValue(cplx, i, 1, "")
return cplx, nil
+ case "clear":
+ value := argValues[0]
+ switch typ := argTypes[0].Underlying().(type) {
+ case *types.Slice:
+ elementType := b.getLLVMType(typ.Elem())
+ elementSize := b.targetData.TypeAllocSize(elementType)
+ elementAlign := b.targetData.ABITypeAlignment(elementType)
+
+ // The pointer to the data to be cleared.
+ llvmBuf := b.CreateExtractValue(value, 0, "buf")
+ if llvmBuf.Type() != b.i8ptrType { // compatibility with LLVM 14
+ llvmBuf = b.CreateBitCast(llvmBuf, b.i8ptrType, "")
+ }
+
+ // The length (in bytes) to be cleared.
+ llvmLen := b.CreateExtractValue(value, 1, "len")
+ llvmLen = b.CreateMul(llvmLen, llvm.ConstInt(llvmLen.Type(), elementSize, false), "")
+
+ // Do the clear operation using the LLVM memset builtin.
+ // This is also correct for nil slices: in those cases, len will be
+ // 0 which means the memset call is a no-op (according to the LLVM
+ // LangRef).
+ memset := b.getMemsetFunc()
+ call := b.createCall(memset.GlobalValueType(), memset, []llvm.Value{
+ llvmBuf, // dest
+ llvm.ConstInt(b.ctx.Int8Type(), 0, false), // val
+ llvmLen, // len
+ llvm.ConstInt(b.ctx.Int1Type(), 0, false), // isVolatile
+ }, "")
+ call.AddCallSiteAttribute(1, b.ctx.CreateEnumAttribute(llvm.AttributeKindID("align"), uint64(elementAlign)))
+
+ return llvm.Value{}, nil
+ default:
+ return llvm.Value{}, b.makeError(pos, "unsupported type in clear builtin: "+typ.String())
+ }
case "copy":
dst := argValues[0]
src := argValues[1]