aboutsummaryrefslogtreecommitdiffhomepage
path: root/compiler/asserts.go
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/asserts.go')
-rw-r--r--compiler/asserts.go31
1 files changed, 31 insertions, 0 deletions
diff --git a/compiler/asserts.go b/compiler/asserts.go
new file mode 100644
index 000000000..4c09264ae
--- /dev/null
+++ b/compiler/asserts.go
@@ -0,0 +1,31 @@
+package compiler
+
+// This file implements functions that do certain safety checks that are
+// required by the Go programming language.
+
+import (
+ "tinygo.org/x/go-llvm"
+)
+
+// emitNilCheck checks whether the given pointer is nil, and panics if it is. It
+// has no effect in well-behaved programs, but makes sure no uncaught nil
+// pointer dereferences exist in valid Go code.
+func (c *Compiler) emitNilCheck(frame *Frame, ptr llvm.Value, blockPrefix string) {
+ // Check whether this is a nil pointer.
+ faultBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, blockPrefix+".nil")
+ nextBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, blockPrefix+".next")
+ frame.blockExits[frame.currentBlock] = nextBlock // adjust outgoing block for phi nodes
+
+ // Compare against nil.
+ nilptr := llvm.ConstPointerNull(ptr.Type())
+ isnil := c.builder.CreateICmp(llvm.IntEQ, ptr, nilptr, "")
+ c.builder.CreateCondBr(isnil, faultBlock, nextBlock)
+
+ // Fail: this is a nil pointer, exit with a panic.
+ c.builder.SetInsertPointAtEnd(faultBlock)
+ c.createRuntimeCall("nilpanic", nil, "")
+ c.builder.CreateUnreachable()
+
+ // Ok: this is a valid pointer.
+ c.builder.SetInsertPointAtEnd(nextBlock)
+}