Example #1
0
File: codegen.go Project: vnev/ark
func (v *Codegen) genBoundsCheck(limit llvm.Value, index llvm.Value, indexType parser.Type) {
	segvBlock := llvm.AddBasicBlock(v.currentLLVMFunction(), "boundscheck_segv")
	endBlock := llvm.AddBasicBlock(v.currentLLVMFunction(), "boundscheck_end")
	upperCheckBlock := llvm.AddBasicBlock(v.currentLLVMFunction(), "boundscheck_upper_block")

	tooLow := v.builder().CreateICmp(llvm.IntSGT, llvm.ConstInt(index.Type(), 0, false), index, "boundscheck_lower")
	v.builder().CreateCondBr(tooLow, segvBlock, upperCheckBlock)

	v.builder().SetInsertPointAtEnd(upperCheckBlock)

	// make sure limit and index have same width
	castedLimit := limit
	castedIndex := index
	if index.Type().IntTypeWidth() < limit.Type().IntTypeWidth() {
		if indexType.IsSigned() {
			castedIndex = v.builder().CreateSExt(index, limit.Type(), "")
		} else {
			castedIndex = v.builder().CreateZExt(index, limit.Type(), "")
		}
	} else if index.Type().IntTypeWidth() > limit.Type().IntTypeWidth() {
		castedLimit = v.builder().CreateZExt(limit, index.Type(), "")
	}

	tooHigh := v.builder().CreateICmp(llvm.IntSLE, castedLimit, castedIndex, "boundscheck_upper")
	v.builder().CreateCondBr(tooHigh, segvBlock, endBlock)

	v.builder().SetInsertPointAtEnd(segvBlock)
	v.genRaiseSegfault()
	v.builder().CreateUnreachable()

	v.builder().SetInsertPointAtEnd(endBlock)
}
Example #2
0
File: codegen.go Project: vnev/ark
func (v *Codegen) genBinop(operator parser.BinOpType, resType, lhandType, rhandType parser.Type, lhand, rhand llvm.Value) llvm.Value {
	if lhand.IsNil() || rhand.IsNil() {
		v.err("invalid binary expr")
	} else {
		switch operator {
		// Arithmetic
		case parser.BINOP_ADD:
			if resType.IsFloatingType() {
				return v.builder().CreateFAdd(lhand, rhand, "")
			} else {
				return v.builder().CreateAdd(lhand, rhand, "")
			}
		case parser.BINOP_SUB:
			if resType.IsFloatingType() {
				return v.builder().CreateFSub(lhand, rhand, "")
			} else {
				return v.builder().CreateSub(lhand, rhand, "")
			}
		case parser.BINOP_MUL:
			if resType.IsFloatingType() {
				return v.builder().CreateFMul(lhand, rhand, "")
			} else {
				return v.builder().CreateMul(lhand, rhand, "")
			}
		case parser.BINOP_DIV:
			if resType.IsFloatingType() {
				return v.builder().CreateFDiv(lhand, rhand, "")
			} else {
				if resType.(parser.PrimitiveType).IsSigned() {
					return v.builder().CreateSDiv(lhand, rhand, "")
				} else {
					return v.builder().CreateUDiv(lhand, rhand, "")
				}
			}
		case parser.BINOP_MOD:
			if resType.IsFloatingType() {
				return v.builder().CreateFRem(lhand, rhand, "")
			} else {
				if resType.(parser.PrimitiveType).IsSigned() {
					return v.builder().CreateSRem(lhand, rhand, "")
				} else {
					return v.builder().CreateURem(lhand, rhand, "")
				}
			}

		// Comparison
		case parser.BINOP_GREATER, parser.BINOP_LESS, parser.BINOP_GREATER_EQ, parser.BINOP_LESS_EQ, parser.BINOP_EQ, parser.BINOP_NOT_EQ:
			if lhandType.IsFloatingType() {
				return v.builder().CreateFCmp(comparisonOpToFloatPredicate(operator), lhand, rhand, "")
			} else {
				return v.builder().CreateICmp(comparisonOpToIntPredicate(operator, lhandType.IsSigned()), lhand, rhand, "")
			}

		// Bitwise
		case parser.BINOP_BIT_AND:
			return v.builder().CreateAnd(lhand, rhand, "")
		case parser.BINOP_BIT_OR:
			return v.builder().CreateOr(lhand, rhand, "")
		case parser.BINOP_BIT_XOR:
			return v.builder().CreateXor(lhand, rhand, "")
		case parser.BINOP_BIT_LEFT:
			return v.builder().CreateShl(lhand, rhand, "")
		case parser.BINOP_BIT_RIGHT:
			// TODO make sure both operands are same type (create type cast here?)
			// TODO in semantic.go, make sure rhand is *unsigned* (LLVM always treats it that way)
			// TODO doc this
			if lhandType.IsSigned() {
				return v.builder().CreateAShr(lhand, rhand, "")
			} else {
				return v.builder().CreateLShr(lhand, rhand, "")
			}

		default:
			panic("umimplented binop")
		}
	}

	panic("unreachable")
}