void MethodCall::callMethod() { if (_called) return; _called = true; Smoke::ClassFn fn = _smoke->classes[method().classId].classFn; void *ptr = 0; if (_o != 0 && _o->ptr != 0) { const Smoke::Class &cl = _smoke->classes[method().classId]; ptr = _o->smoke->cast( _o->ptr, _o->classId, _o->smoke->idClass(cl.className, true).index ); } _items = -1; /* * special case the QApplication/QCoreApplication constructor call * the int reference has to stay valid all the time, so create an additional pointer here */ if (isConstructor() && ( strcmp(_smoke->methodNames[method().name], "QApplication") == 0 || strcmp(_smoke->methodNames[method().name], "QCoreApplication") == 0)) { int* i = new int(_sp[1].s_int); _stack[1].s_voidp = i; } (*fn)(method().method, ptr, _stack); if (isConstructor()) { Smoke::StackItem _s[2]; _s[1].s_class = qyoto_modules[_smoke].binding; fn(0, _stack[0].s_voidp, _s); _o = alloc_smokeqyoto_object(true, _smoke, method().classId, _stack[0].s_voidp); (*SetSmokeObject)(_target, _o); mapPointer(_target, _o, _o->classId, 0); } else if (isDestructor()) { void *check = (*GetSmokeObject)(_target); if (check) { unmapPointer(_o, _o->classId, 0); (*SetSmokeObject)(_target, 0); free_smokeqyoto_object(_o); } } else { Qyoto::MethodReturnValue r(_smoke, _method, _stack, _retval); } }
bool treeinfo::hasConstructors(const Tree::List& defs) { for (auto def : defs) { if (isConstructor(*def)) { return true; } } return false; }
std::string Node::getPrefixedName() const { if (Node* parent = getParent()) { return parent->getPrefixedName() + (isConstructor() ? ctorScope : "::") + getName(); } return getName(); }
MethodCall::MethodCall(Smoke *smoke, Smoke::Index method, void * target, Smoke::Stack sp, int items) : _cur(-1), _smoke(smoke), _method(method), _target(target), _o(0), _sp(sp), _items(items), _called(false) { if (!isConstructor() && !isStatic()) { _o = (smokeqyoto_object*) (*GetSmokeObject)(_target); if (_o != 0 && _o->ptr != 0) { if ( isDestructor() && (!_o->allocated || IsContainedInstance(_o) || _o->smoke->isDerivedFrom(_o->smoke->className(_o->classId), "QCoreApplication")) ) { _called = true; } } else { // not a constructor, not static, pointer invalid -> object already destroyed _called = true; } } _args = _smoke->argumentList + _smoke->methods[_method].args; _items = _smoke->methods[_method].numArgs; numItems = items; _stack = new Smoke::StackItem[items + 1]; _retval = _sp; }
ConstructorType::ConstructorType(const Type& t) throw(IllegalArgumentException) : Type(t) { PrettyCheckArgument(isNull() || isConstructor(), this); }
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."); } }
bool Function::isMethod() const { return !isConstructor() && !isDestructor() && nameSpace()->kind() == Symbol::SYM_STRUCT; }