github.com/axw/llgo@v0.0.0-20160805011314-95b5fe4dca20/irgen/errors.go (about)

     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  
    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(),
    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  }