示例#1
0
		llvm::Value*
		LivenessEmitter::emitIsLiveCall(const AST::Type* const type, llvm::Value* const value) {
			auto& module = irEmitter_.module();
			
			// Call __islive method.
			if (type->isObject()) {
				TypeInfo typeInfo(module);
				if (!typeInfo.objectHasLivenessIndicator(*(type->getObjectType()))) {
					// Assume value is always live.
					return ConstantGenerator(module).getBool(true);
				}
				
				// Call __islive method.
				const auto methodName = module.getCString("__islive");
				const auto functionType = type->getObjectType()->getFunction(methodName).type();
				
				MethodInfo methodInfo(type, methodName, functionType, {});
				const auto contextArg = RefPendingResult(value, type);
				
				CallEmitter callEmitter(irEmitter_);
				return callEmitter.emitDynamicMethodCall(methodInfo, contextArg, {});
			}
			
			llvm_unreachable("Unknown __islive value type.");
		}
示例#2
0
		void
		LivenessEmitter::emitSetOuterLive(const AST::TypeInstance& typeInstance,
		                                  llvm::Value* const objectPointerValue) {
			auto& module = irEmitter_.module();
			
			const auto livenessIndicator =
			    LivenessInfo(module).getLivenessIndicator(typeInstance);
			
			switch (livenessIndicator.kind()) {
				case LivenessIndicator::NONE: {
					// Nothing to do.
					break;
				}
				case LivenessIndicator::MEMBER_INVALID_STATE: {
					// Nothing to do; the expectation is that the member is already in a valid state.
					break;
				}
				case LivenessIndicator::CUSTOM_METHODS: {
					// Nothing to do; the expectation is that the object is already in a live state
					// (or that it is in a notionally 'dead' state but it doesn't matter).
					break;
				}
				case LivenessIndicator::SUFFIX_BYTE:
				case LivenessIndicator::GAP_BYTE: {
					// Store one into gap/suffix byte to represent live state.
					const auto bytePtr = emitLivenessBytePtr(typeInstance, livenessIndicator, objectPointerValue);
					irEmitter_.emitRawStore(ConstantGenerator(module).getI8(1),
					                        bytePtr);
					break;
				}
			}
		}
void CtrGenerator::visit(const P_ConstraintLoop& loop) {
	const char* name     = loop.iter;

	int begin=ConstantGenerator(scopes.top()).eval_integer(loop.first_value); //scope.it_first_value(name);
	int end=ConstantGenerator(scopes.top()).eval_integer(loop.last_value); //scope.it_last_value(name);

	if (!scopes.empty())
		scopes.push(scopes.top());
	else
		scopes.push(Scope());

	scopes.top().add_iterator(name);

	for (int i=begin; i<=end; i++) {
		scopes.top().set_iter_value(name,i);
		visit(loop.ctrs);
	}
	scopes.pop();
}
示例#4
0
		llvm::Value*
		LivenessEmitter::emitLivenessByteOffset(const AST::TypeInstance& typeInstance,
		                                        const LivenessIndicator livenessIndicator) {
			if (livenessIndicator.isSuffixByte()) {
				return genSuffixByteOffset(irEmitter_.function(), typeInstance);
			} else if (livenessIndicator.isGapByte()) {
				return ConstantGenerator(irEmitter_.module()).getI64(livenessIndicator.gapByteOffset());
			} else {
				llvm_unreachable("Cannot get byte offset of non-byte liveness indicator.");
			}
		}
示例#5
0
		llvm::Value* Function::unwindState() {
			if (unwindState_ == nullptr) {
				const auto i8Type = TypeGenerator(module_).getI8Type();
				
				// Zero state means 'normal execution'.
				const auto zero = ConstantGenerator(module_).getI8(0);
				unwindState_ = getEntryBuilder().CreateAlloca(i8Type, nullptr, "unwindState");
				getEntryBuilder().CreateStore(zero, unwindState_);
			}
			
			return unwindState_;
		}
示例#6
0
		llvm::Value* VoidPrimitive::emitMethod(IREmitter& irEmitter,
		                                       const MethodID methodID,
		                                       llvm::ArrayRef<AST::Value> /*typeTemplateArguments*/,
		                                       llvm::ArrayRef<AST::Value> /*functionTemplateArguments*/,
		                                       PendingResultArray /*args*/,
		                                       llvm::Value* /*resultPtr*/) const {
			auto& module = irEmitter.module();
			
			switch (methodID) {
				case METHOD_MOVE:
					return ConstantGenerator(module).getVoidUndef();
				default:
					llvm_unreachable("Unknown void_t primitive method.");
			}
		}
示例#7
0
		VirtualMethodComponents getVirtualMethodComponents(Function& function, const bool isStatic, llvm::Value* const interfaceMethodValue) {
			auto& builder = function.getBuilder();
			auto& module = function.module();
			
			if (isStatic) {
				const auto objectPointer = ConstantGenerator(module).getNull(TypeGenerator(module).getI8PtrType());
				const auto typeInfoValue = builder.CreateExtractValue(interfaceMethodValue, { 0 }, "typeInfo");
				const VirtualObjectComponents virtualObjectComponents(getTypeInfoComponents(function, typeInfoValue), objectPointer);
				
				const auto hashValue = builder.CreateExtractValue(interfaceMethodValue, { 1 }, "methodHash");
				return VirtualMethodComponents(virtualObjectComponents, hashValue);
			} else {
				const auto interfaceStructValue = builder.CreateExtractValue(interfaceMethodValue, { 0 }, "interface");
				const auto hashValue = builder.CreateExtractValue(interfaceMethodValue, { 1 }, "methodHash");
				return VirtualMethodComponents(getVirtualObjectComponents(function, interfaceStructValue), hashValue);
			}
		}
void ExprGenerator::visit(const P_ExprIndex& e) {
	int index=ConstantGenerator(scope).eval_integer(e.right);

	visit(e.left);

	int real_index=e.matlab_style? index-1 : index;

	if (real_index<0)
		throw SyntaxError("negative index. Note: indices in Matlab-style (using parenthesis like in \"x(i)\") start from 1 (not 0).");
	if (real_index>LEFT.dim.max_index())
		throw SyntaxError("index out of bounds. Note: indices in C-style (using square brackets like in \"x[i]\") start from 0 (not 1).");

	if (fold) {
		const ExprConstant* c=dynamic_cast<const ExprConstant*>(&LEFT);
		if (c) {
			clone.insert(e, &ExprConstant::new_(c->get()[real_index]));
			//delete c; // not now (see comment in ExprCopy.h)
			return;
		}
	}

	const ExprConstantRef* s=dynamic_cast<const ExprConstantRef*>(&LEFT);
	if (s) {
		if (dynamic_cast<const P_ExprIndex*>(e.father)) {
			clone.insert(e, new ExprConstantRef(s->value[real_index]));
		} else {
			// "last time": we cannot keep reference anymore.
			clone.insert(e, &ExprConstant::new_(s->value[real_index]));
		}
		//delete s; // not now: there may be inside a DAG (via a function) (see comment in ExprCopy.h)
		return;
	}

	mark(e.left);
	clone.insert(e, &(LEFT[real_index]));
}
示例#9
0
llvm::Value* genFloatPrimitiveMethodCall(Function& function, const SEM::Type* type, const String& methodName, const SEM::FunctionType functionType,
        llvm::ArrayRef<SEM::Value> templateArgs, PendingResultArray args, llvm::Value* const hintResultValue) {
    auto& module = function.module();
    auto& builder = function.getBuilder();

    const auto& typeName = type->getObjectType()->name().first();

    const auto methodID = module.context().getMethodID(CanonicalizeMethodName(methodName));

    const auto methodOwner = methodID.isConstructor() ? nullptr : args[0].resolveWithoutBind(function);

    if (methodName == "__move_to") {
        const auto moveToPtr = args[1].resolve(function);
        const auto moveToPosition = args[2].resolve(function);

        const auto destPtr = builder.CreateInBoundsGEP(moveToPtr, moveToPosition);
        const auto castedDestPtr = builder.CreatePointerCast(destPtr, genPointerType(module, type));

        genMoveStore(function, methodOwner, castedDestPtr, type);
        return ConstantGenerator(module).getVoidUndef();
    } else if (methodName == "create") {
        return ConstantGenerator(module).getPrimitiveFloat(typeName, 0.0);
    } else if (methodName == "__setdead" || methodName == "__set_dead") {
        // Do nothing.
        return ConstantGenerator(module).getVoidUndef();
    } else if (methodName == "__islive" || methodName == "__is_live") {
        return ConstantGenerator(module).getI1(true);
    } else if (methodName.starts_with("implicit_cast_") || methodName.starts_with("cast_")) {
        const auto argType = functionType.parameterTypes().front();
        const auto operand = args[0].resolve(function);
        const auto selfType = genType(module, type);
        if (isFloatType(module, argType)) {
            if (methodName.starts_with("implicit_cast_")) {
                return builder.CreateFPExt(operand, selfType);
            } else {
                return builder.CreateFPTrunc(operand, selfType);
            }
        } else if (isUnsignedIntegerType(module, argType)) {
            return builder.CreateUIToFP(operand, selfType);
        } else if (isSignedIntegerType(module, argType)) {
            return builder.CreateSIToFP(operand, selfType);
        } else {
            llvm_unreachable("Unknown float cast source type.");
        }
    } else if (isUnaryOp(methodName)) {
        const auto zero = ConstantGenerator(module).getPrimitiveFloat(typeName, 0.0);

        if (methodName == "implicit_cast" || methodName == "cast") {
            return callCastMethod(function, methodOwner, type, methodName, templateArgs.front().typeRefType(), hintResultValue);
        } else if (methodName == "implicit_copy" || methodName == "copy" || methodName == "plus") {
            return methodOwner;
        } else if (methodName == "minus") {
            return builder.CreateFNeg(methodOwner);
        } else if (methodName == "isZero") {
            return builder.CreateFCmpOEQ(methodOwner, zero);
        } else if (methodName == "isPositive") {
            return builder.CreateFCmpOGT(methodOwner, zero);
        } else if (methodName == "isNegative") {
            return builder.CreateFCmpOLT(methodOwner, zero);
        } else if (methodName == "abs") {
            // Generates: (value < 0) ? -value : value.
            const auto lessThanZero = builder.CreateFCmpOLT(methodOwner, zero);
            return builder.CreateSelect(lessThanZero, builder.CreateFNeg(methodOwner), methodOwner);
        } else if (methodName == "sqrt") {
            llvm::Type* const intrinsicTypes[] = { methodOwner->getType() };
            const auto sqrtIntrinsic = llvm::Intrinsic::getDeclaration(module.getLLVMModulePtr(), llvm::Intrinsic::sqrt, intrinsicTypes);
            llvm::Value* const sqrtArgs[] = { methodOwner };
            return builder.CreateCall(sqrtIntrinsic, sqrtArgs);
        } else {
            llvm_unreachable("Unknown primitive unary op.");
        }
    } else if (isBinaryOp(methodName)) {
        const auto operand = args[1].resolveWithoutBind(function);

        if (methodName == "add") {
            return builder.CreateFAdd(methodOwner, operand);
        } else if (methodName == "subtract") {
            return builder.CreateFSub(methodOwner, operand);
        } else if (methodName == "multiply") {
            return builder.CreateFMul(methodOwner, operand);
        } else if (methodName == "divide") {
            return builder.CreateFDiv(methodOwner, operand);
        } else if (methodName == "modulo") {
            return builder.CreateFRem(methodOwner, operand);
        } else if (methodName == "equal") {
            return builder.CreateFCmpOEQ(methodOwner, operand);
        } else if (methodName == "not_equal") {
            return builder.CreateFCmpONE(methodOwner, operand);
        } else if (methodName == "less_than") {
            return builder.CreateFCmpOLT(methodOwner, operand);
        } else if (methodName == "less_than_or_equal") {
            return builder.CreateFCmpOLE(methodOwner, operand);
        } else if (methodName == "greater_than") {
            return builder.CreateFCmpOGT(methodOwner, operand);
        } else if (methodName == "greater_than_or_equal") {
            return builder.CreateFCmpOGE(methodOwner, operand);
        } else if (methodName == "compare") {
            const auto isLessThan = builder.CreateFCmpOLT(methodOwner, operand);
            const auto isGreaterThan = builder.CreateFCmpOGT(methodOwner, operand);
            const auto minusOne = ConstantGenerator(module).getI8(-1);
            const auto zero = ConstantGenerator(module).getI8(0);
            const auto plusOne = ConstantGenerator(module).getI8(1);
            return builder.CreateSelect(isLessThan, minusOne,
                                        builder.CreateSelect(isGreaterThan, plusOne, zero));
        } else {
            llvm_unreachable("Unknown primitive binary op.");
        }
    } else {
        printf("%s\n", methodName.c_str());
        llvm_unreachable("Unknown primitive method.");
    }
}
示例#10
0
		void TemplateBuilder::updateAllInstructions(Module& module) {
			for (const auto instruction: instructions_) {
				instruction->setOperand(1, ConstantGenerator(module).getI64(bitsRequired()));
			}
		}
示例#11
0
		llvm::Value* genPtrLvalPrimitiveMethodCall(Function& function, const SEM::Type* type, const String& methodName, SEM::FunctionType /*functionType*/,
				PendingResultArray args, llvm::Value* const hintResultValue) {
			auto& module = function.module();
			auto& builder = function.getBuilder();
			
			const auto methodOwner = args[0].resolveWithoutBind(function);
			const auto targetType = type->templateArguments().front().typeRefType();
			
			const auto methodID = module.context().getMethodID(CanonicalizeMethodName(methodName));
			
			switch (methodID) {
				case METHOD_MOVETO: {
					const auto moveToPtr = args[1].resolve(function);
					const auto moveToPosition = args[2].resolve(function);
					
					const auto destPtr = builder.CreateInBoundsGEP(moveToPtr, moveToPosition);
					const auto castedDestPtr = builder.CreatePointerCast(destPtr, genPointerType(module, type));
					
					genMoveStore(function, methodOwner, castedDestPtr, type);
					return ConstantGenerator(module).getVoidUndef();
				}
				case METHOD_ADDRESS:
				case METHOD_DISSOLVE:
					return methodOwner;
				case METHOD_ASSIGN: {
					const auto operand = args[1].resolve(function);
					
					// Destroy existing value.
					genDestructorCall(function, targetType, methodOwner);
					
					// Assign new value.
					genMoveStore(function, operand, methodOwner, targetType);
					
					return ConstantGenerator(module).getVoidUndef();
				}
				case METHOD_MOVE: {
					const auto returnValuePtr = genAlloca(function, targetType, hintResultValue);
					const auto loadedValue = genMoveLoad(function, methodOwner, targetType);
					genMoveStore(function, loadedValue, returnValuePtr, targetType);
					return genMoveLoad(function, returnValuePtr, targetType);
				}
				case METHOD_SETVALUE: {
					const auto operand = args[1].resolve(function);
					
					// Assign new value.
					genMoveStore(function, operand, methodOwner, targetType);
					
					return ConstantGenerator(module).getVoidUndef();
				}
				case METHOD_EXTRACTVALUE: {
					return genMoveLoad(function, methodOwner, targetType);
				}
				case METHOD_DESTROYVALUE: {
					// Destroy existing value.
					genDestructorCall(function, targetType, methodOwner);
					return ConstantGenerator(module).getVoidUndef();
				}
				default:
					llvm_unreachable("Unknown ptr_lval primitive method.");
			}
		}