Peter Collingbourne | ad9841e | 2014-11-27 00:06:42 +0000 | [diff] [blame] | 1 | //===- errors.go - IR generation for run-time panics ----------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file implements IR generation for triggering run-time panics. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | package irgen |
| 15 | |
| 16 | import ( |
| 17 | "llvm.org/llvm/bindings/go/llvm" |
| 18 | ) |
| 19 | |
| 20 | const ( |
| 21 | // From go-runtime-error.c |
| 22 | gccgoRuntimeErrorSLICE_INDEX_OUT_OF_BOUNDS = 0 |
| 23 | gccgoRuntimeErrorARRAY_INDEX_OUT_OF_BOUNDS = 1 |
| 24 | gccgoRuntimeErrorSTRING_INDEX_OUT_OF_BOUNDS = 2 |
| 25 | gccgoRuntimeErrorSLICE_SLICE_OUT_OF_BOUNDS = 3 |
| 26 | gccgoRuntimeErrorARRAY_SLICE_OUT_OF_BOUNDS = 4 |
| 27 | gccgoRuntimeErrorSTRING_SLICE_OUT_OF_BOUNDS = 5 |
| 28 | gccgoRuntimeErrorNIL_DEREFERENCE = 6 |
| 29 | gccgoRuntimeErrorMAKE_SLICE_OUT_OF_BOUNDS = 7 |
| 30 | gccgoRuntimeErrorMAKE_MAP_OUT_OF_BOUNDS = 8 |
| 31 | gccgoRuntimeErrorMAKE_CHAN_OUT_OF_BOUNDS = 9 |
| 32 | gccgoRuntimeErrorDIVISION_BY_ZERO = 10 |
| 33 | gccgoRuntimeErrorCount = 11 |
| 34 | ) |
| 35 | |
| 36 | func (fr *frame) setBranchWeightMetadata(br llvm.Value, trueweight, falseweight uint64) { |
| 37 | mdprof := llvm.MDKindID("prof") |
| 38 | |
Peter Collingbourne | 8bcc05d | 2014-12-13 02:26:00 +0000 | [diff] [blame] | 39 | mdnode := llvm.GlobalContext().MDNode([]llvm.Metadata{ |
| 40 | llvm.GlobalContext().MDString("branch_weights"), |
| 41 | llvm.ConstInt(llvm.Int32Type(), trueweight, false).ConstantAsMetadata(), |
| 42 | llvm.ConstInt(llvm.Int32Type(), falseweight, false).ConstantAsMetadata(), |
Peter Collingbourne | ad9841e | 2014-11-27 00:06:42 +0000 | [diff] [blame] | 43 | }) |
| 44 | |
| 45 | br.SetMetadata(mdprof, mdnode) |
| 46 | } |
| 47 | |
| 48 | func (fr *frame) condBrRuntimeError(cond llvm.Value, errcode uint64) { |
| 49 | if cond.IsNull() { |
| 50 | return |
| 51 | } |
| 52 | |
| 53 | errorbb := fr.runtimeErrorBlocks[errcode] |
| 54 | newbb := errorbb.C == nil |
| 55 | if newbb { |
| 56 | errorbb = llvm.AddBasicBlock(fr.function, "") |
| 57 | fr.runtimeErrorBlocks[errcode] = errorbb |
| 58 | } |
| 59 | |
| 60 | contbb := llvm.AddBasicBlock(fr.function, "") |
| 61 | |
| 62 | br := fr.builder.CreateCondBr(cond, errorbb, contbb) |
| 63 | fr.setBranchWeightMetadata(br, 1, 1000) |
| 64 | |
| 65 | if newbb { |
| 66 | fr.builder.SetInsertPointAtEnd(errorbb) |
| 67 | fr.runtime.runtimeError.call(fr, llvm.ConstInt(llvm.Int32Type(), errcode, false)) |
| 68 | fr.builder.CreateUnreachable() |
| 69 | } |
| 70 | |
| 71 | fr.builder.SetInsertPointAtEnd(contbb) |
| 72 | } |