コード例 #1
0
ファイル: Instructions.cpp プロジェクト: DrItanium/saphyr
RValue Inst::PointerMath(int type, RValue ptr, RValue val, CodeContext& context)
{
	if (type != ParserBase::TT_INC && type != ParserBase::TT_DEC) {
		context.addError("pointer arithmetic only valid using ++/-- operators");
		return ptr;
	}
	auto ptrVal = GetElementPtrInst::Create(ptr, val.value(), "", context);
	return RValue(ptrVal, ptr.stype());
}
コード例 #2
0
ファイル: Instructions.cpp プロジェクト: DrItanium/saphyr
RValue Inst::Deref(CodeContext& context, RValue value, bool recursive)
{
	auto retVal = RValue(value.value(), value.stype());
	while (retVal.stype()->isPointer()) {
		retVal = RValue(new LoadInst(retVal, "", context), retVal.stype()->subType());
		if (!recursive)
			break;
	}
	return retVal;
}
コード例 #3
0
ファイル: Instructions.cpp プロジェクト: DrItanium/saphyr
bool Inst::CastMatch(CodeContext& context, RValue& lhs, RValue& rhs, bool upcast)
{
	auto ltype = lhs.stype();
	auto rtype = rhs.stype();

	if (ltype == rtype) {
		return false;
	} else if (ltype->isComplex() || rtype->isComplex()) {
		context.addError("can not cast complex types");
		return true;
	} else if (ltype->isPointer() || rtype->isPointer()) {
		// different pointer types can't be cast automatically
		// the operations need to handle pointers specially
		return false;
	}

	auto toType = SType::numericConv(context, ltype, rtype, upcast);
	return CastTo(context, lhs, toType, upcast) || CastTo(context, rhs, toType, upcast);
}
コード例 #4
0
ファイル: Instructions.cpp プロジェクト: DrItanium/saphyr
RValue Inst::BinaryOp(int type, RValue lhs, RValue rhs, CodeContext& context)
{
	if (!lhs || !rhs)
		return RValue();

	if (CastMatch(context, lhs, rhs, true))
		return RValue();

	switch ((lhs.stype()->isPointer() << 1) | rhs.stype()->isPointer()) {
	default:
	case 0: // no pointer
	{
		auto llvmOp = getOperator(type, lhs.stype(), context);
		return RValue(BinaryOperator::Create(llvmOp, lhs, rhs, "", context), lhs.stype());
	}
	case 1: // lhs != ptr, rhs == ptr
		swap(lhs, rhs);
	case 2: // lhs == ptr, rhs != ptr
		return PointerMath(type, lhs, rhs, context);
	case 3: // both ptr
		context.addError("can't perform operation with two pointers");
		return lhs;
	}
}
コード例 #5
0
ファイル: Instructions.cpp プロジェクト: DrItanium/saphyr
RValue Inst::Cmp(int type, RValue lhs, RValue rhs, CodeContext& context)
{
	if (CastMatch(context, lhs, rhs))
		return RValue();
	auto pred = getPredicate(type, lhs.stype(), context);
	auto cmpType = lhs.stype()->isVec()? lhs.stype()->subType() : lhs.stype();
	auto op = cmpType->isFloating()? Instruction::FCmp : Instruction::ICmp;
	auto cmp = CmpInst::Create(op, pred, lhs, rhs, "", context);
	auto retType = lhs.stype()->isVec()?
		SType::getVec(context, SType::getBool(context), lhs.stype()->size()) :
		SType::getBool(context);
	return RValue(cmp, retType);
}
コード例 #6
0
ファイル: Instructions.cpp プロジェクト: DrItanium/saphyr
bool Inst::CastTo(CodeContext& context, RValue& value, SType* type, bool upcast)
{
	auto valueType = value.stype();

	if (type == valueType) {
		// non-assignment and non-comparison operations with enum types
		// must result in an int type to keep enum variables within range.
		if (upcast && valueType->isEnum())
			value.castToSubtype();
		return false;
	} else if (type->isComplex() || valueType->isComplex()) {
		context.addError("can not cast complex types");
		return true;
	} else if (type->isPointer()) {
		if (value.isNullPtr()) {
			// NOTE: discard current null value and create
			// a new one using the right type
			value = RValue::getNullPtr(context, type);
			return false;
		} else if (type->subType()->isVoid()) {
			value = RValue(new BitCastInst(value, *type, "", context), type);
			return false;
		}
		context.addError("can't cast value to pointer type");
		return true;
	} else if (type->isVec()) {
		// unwrap enum type
		if (valueType->isEnum())
			valueType = value.castToSubtype();

		if (valueType->isNumeric()) {
			CastTo(context, value, type->subType(), upcast);

			auto i32 = SType::getInt(context, 32);
			auto mask = RValue::getZero(context, SType::getVec(context, i32, type->size()));
			auto udef = UndefValue::get(*SType::getVec(context, type->subType(), 1));
			auto instEle = InsertElementInst::Create(udef, value, RValue::getZero(context, i32), "", context);
			auto retVal = new ShuffleVectorInst(instEle, udef, mask, "", context);

			value = RValue(retVal, type);
			return false;
		} else if (valueType->isPointer()) {
			context.addError("can not cast pointer to vec type");
			return true;
		} else if (type->size() != valueType->size()) {
			context.addError("can not cast vec types of different sizes");
			return true;
		} else if (type->subType()->isBool()) {
			// cast to bool is value != 0
			auto pred = getPredicate(ParserBase::TT_NEQ, valueType, context);
			auto op = valueType->subType()->isFloating()? Instruction::FCmp : Instruction::ICmp;
			auto val = CmpInst::Create(op, pred, value, RValue::getZero(context, valueType), "", context);
			value = RValue(val, type);
			return false;
		} else {
			auto op = getCastOp(valueType->subType(), type->subType());
			auto val = CastInst::Create(op, value, *type, "", context);
			value = RValue(val, type);
			return false;
		}
	} else if (type->isEnum()) {
		// casting to enum would violate value constraints
		context.addError("can't cast to enum type");
		return true;
	} else if (type->isBool()) {
		if (valueType->isVec()) {
			context.addError("can not cast vec type to bool");
			return true;
		} else if (valueType->isEnum()) {
			valueType = value.castToSubtype();
		}

		// cast to bool is value != 0
		auto pred = getPredicate(ParserBase::TT_NEQ, valueType, context);
		auto op = valueType->isFloating()? Instruction::FCmp : Instruction::ICmp;
		auto val = CmpInst::Create(op, pred, value, RValue::getZero(context, valueType), "", context);
		value = RValue(val, type);
		return false;
	}

	if (valueType->isPointer()) {
		context.addError("can't cast pointer to numeric type");
		return true;
	}

	// unwrap enum type
	if (valueType->isEnum())
		valueType = value.castToSubtype();

	auto op = getCastOp(valueType, type);
	auto val = op != Instruction::AddrSpaceCast? CastInst::Create(op, value, *type, "", context) : value;
	value = RValue(val, type);
	return false;
}
コード例 #7
0
ファイル: Instructions.cpp プロジェクト: DrItanium/saphyr
RValue Inst::Load(CodeContext& context, RValue value)
{
	return RValue(new LoadInst(value, "", context), value.stype());
}