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."); }
void createPrimitiveMethod(Module& module, const SEM::TypeInstance* const typeInstance, SEM::Function* const semFunction, llvm::Function& llvmFunction) { const auto argInfo = getFunctionArgInfo(module, semFunction->type()); Function function(module, llvmFunction, argInfo, &(module.templateBuilder(TemplatedObject::TypeInstance(typeInstance)))); const auto debugSubprogram = genDebugFunctionInfo(module, semFunction, &llvmFunction); assert(debugSubprogram); function.attachDebugInfo(*debugSubprogram); function.setDebugPosition(semFunction->debugInfo()->scopeLocation.range().start()); SEM::ValueArray templateArgs; for (const auto& templateVar: semFunction->templateVariables()) { templateArgs.push_back(templateVar->selfRefValue()); } PendingResultArray args; const auto contextValue = argInfo.hasContextArgument() ? function.getContextValue(typeInstance) : nullptr; RefPendingResult contextPendingResult(contextValue, typeInstance->selfType()); if (argInfo.hasContextArgument()) { args.push_back(contextPendingResult); } // Need an array to store all the pending results // being referred to in 'genTrivialPrimitiveFunctionCall'. Array<ValuePendingResult, 10> pendingResultArgs; const auto& argTypes = semFunction->type().parameterTypes(); for (size_t i = 0; i < argTypes.size(); i++) { const auto argValue = function.getArg(i); pendingResultArgs.push_back(ValuePendingResult(argValue, argTypes[i])); args.push_back(pendingResultArgs.back()); } MethodInfo methodInfo(typeInstance->selfType(), semFunction->name().last(), semFunction->type(), std::move(templateArgs)); const auto hintResultValue = argInfo.hasReturnVarArgument() ? function.getReturnVar() : nullptr; const auto result = genTrivialPrimitiveFunctionCall(function, std::move(methodInfo), std::move(args), hintResultValue); const auto returnType = semFunction->type().returnType(); // Return the result in the appropriate way. if (argInfo.hasReturnVarArgument()) { genMoveStore(function, result, function.getReturnVar(), returnType); function.getBuilder().CreateRetVoid(); } else if (!returnType->isBuiltInVoid()) { function.returnValue(result); } else { function.getBuilder().CreateRetVoid(); } // Check the generated function is correct. function.verify(); }
/** * Função que le a segunda parte de informações gerais de um arquivo .class * * @param referência ao classfile. * @param referência ao arquivo sendo lido. */ void secondGeneralInfo(classFile* cf, FILE* file){ cf->access_flags = le2Bytes(file); cf->this_class = le2Bytes(file); cf->super_class = le2Bytes(file); cf->interfaces_count = le2Bytes(file); interfaceInfo(cf,file,cf->interfaces_count); cf->fields_count = le2Bytes(file); fieldInfo(cf,file,cf->fields_count); cf->methods_count = le2Bytes(file); methodInfo(cf,file,cf->methods_count); cf->attributes_count = le2Bytes(file); attributeInfo(cf,file,cf->attributes_count); }
llvm::Value* callRawCastMethod(Function& function, llvm::Value* const castFromValue, const SEM::Type* const castFromType, const String& targetMethodName, const SEM::Type* const castToType, llvm::Value* const hintResultValue) { const bool isVarArg = false; const bool isMethod = false; const bool isTemplated = false; auto noexceptPredicate = SEM::Predicate::True(); const auto returnType = castToType; const SEM::TypeArray parameterTypes = castFromValue != nullptr ? SEM::TypeArray{ castFromType } : SEM::TypeArray{}; SEM::FunctionAttributes functionAttributes(isVarArg, isMethod, isTemplated, std::move(noexceptPredicate)); const SEM::FunctionType functionType(std::move(functionAttributes), returnType, parameterTypes.copy()); MethodInfo methodInfo(castToType, targetMethodName, functionType, {}); PendingResultArray args; const ValuePendingResult contextPendingResult(castFromValue, castFromType); if (castFromValue != nullptr) { args.push_back(contextPendingResult); } return genStaticMethodCall(function, std::move(methodInfo), std::move(args), hintResultValue); }
void LivenessEmitter::emitSetInvalidCall(const AST::Type* const type, llvm::Value* const value) { auto& module = irEmitter_.module(); // Call __setinvalid method. if (type->isObject()) { const auto methodName = module.getCString("__setinvalid"); const auto functionType = type->getObjectType()->getFunction(methodName).type(); MethodInfo methodInfo(type, methodName, functionType, {}); const auto contextArg = RefPendingResult(value, type); CallEmitter callEmitter(irEmitter_); callEmitter.emitDynamicMethodCall(methodInfo, contextArg, {}); return; } else if (type->isTemplateVar()) { // TODO! return; } llvm_unreachable("Unknown __setinvalid value type."); }
void PythonQtSignalTarget::call(void **arguments) const { PyObject* result = call(_callable, methodInfo(), arguments); if (result) { Py_DECREF(result); } }
void PythonQtSignalTarget::call(void **arguments) const { // Note: we check if the callable is a PyFunctionObject and has a fixed number of arguments // if that is the case, we only pass these arguments to python and skip the additional arguments from the signal int numPythonArgs = -1; if (PyFunction_Check(_callable)) { PyObject* o = _callable; PyFunctionObject* func = (PyFunctionObject*)o; PyCodeObject* code = (PyCodeObject*)func->func_code; if (!(code->co_flags & 0x04)) { numPythonArgs = code->co_argcount; } else { // variable numbers of arguments allowed } } else if (PyMethod_Check(_callable)) { PyObject* o = _callable; PyMethodObject* method = (PyMethodObject*)o; if (PyFunction_Check(method->im_func)) { PyFunctionObject* func = (PyFunctionObject*)method->im_func; PyCodeObject* code = (PyCodeObject*)func->func_code; if (!(code->co_flags & 0x04)) { numPythonArgs = code->co_argcount - 1; // we subtract one because the first is "self" } else { // variable numbers of arguments allowed } } } const PythonQtMethodInfo* m = methodInfo(); // parameterCount includes return value: int count = m->parameterCount(); if (numPythonArgs!=-1) { if (count>numPythonArgs+1) { // take less arguments count = numPythonArgs+1; } } PyObject* pargs = NULL; if (count>1) { pargs = PyTuple_New(count-1); } bool err = false; // transform Qt values to Python const QList<PythonQtMethodInfo::ParameterInfo>& params = m->parameters(); for (int i = 1; i < count; i++) { const PythonQtMethodInfo::ParameterInfo& param = params.at(i); PyObject* arg = PythonQtConv::ConvertQtValueToPython(param, arguments[i]); if (arg) { // steals reference, no unref PyTuple_SetItem(pargs, i-1,arg); } else { err = true; break; } } if (!err) { PyErr_Clear(); PyObject* result = PyObject_CallObject(_callable, pargs); if (result) { // ok Py_DECREF(result); } else { PythonQt::self()->handleError(); } } if (pargs) { // free the arguments again Py_DECREF(pargs); } }