public void encodePrototype(Encoder encoder, PcodeDataTypeManager dtmanage, int firstVarArg)
			throws IOException {
		encoder.openElement(ELEM_PROTOTYPE);
		if (extrapop == PrototypeModel.UNKNOWN_EXTRAPOP) {
			encoder.writeString(ATTRIB_EXTRAPOP, "unknown");
		}
		else {
			encoder.writeSignedInteger(ATTRIB_EXTRAPOP, extrapop);
		}
		encoder.writeString(ATTRIB_MODEL, modelname);
		if (modellock) {
			encoder.writeBool(ATTRIB_MODELLOCK, modellock);
		}
		if (dotdotdot) {
			encoder.writeBool(ATTRIB_DOTDOTDOT, dotdotdot);
		}
		if (voidinputlock) {
			encoder.writeBool(ATTRIB_VOIDLOCK, voidinputlock);
		}
		if (isinline) {
			encoder.writeBool(ATTRIB_INLINE, isinline);
		}
		if (noreturn) {
			encoder.writeBool(ATTRIB_NORETURN, noreturn);
		}
		if (custom) {
			encoder.writeBool(ATTRIB_CUSTOM, custom);
		}
		if (isConstruct) {
			encoder.writeBool(ATTRIB_CONSTRUCTOR, isConstruct);
		}
		if (isDestruct) {
			encoder.writeBool(ATTRIB_DESTRUCTOR, isDestruct);
		}
		encoder.openElement(ELEM_RETURNSYM);
		if (outputlock) {
			encoder.writeBool(ATTRIB_TYPELOCK, outputlock);
		}
		int sz = returntype.getLength();
		if (sz < 0) {
			Msg.warn(this, "Bad returntype size");
			sz = 1;
		}
		if ((returnstorage != null) && returnstorage.isValid() &&
			(!returnstorage.isVoidStorage())) {
			int logicalsize = 0;		// Assume logicalsize of return matches datatype size
			if (sz != returnstorage.size()) {	// If the sizes do no match
				logicalsize = sz;		// force the logical size on the varnode
			}
			AddressXML.encode(encoder, returnstorage.getVarnodes(), logicalsize);
		}
		else {
			// Decompiler will use model for storage.  Don't specify where return type is stored
			encoder.openElement(ELEM_ADDR);
			encoder.closeElement(ELEM_ADDR);
		}

		dtmanage.encodeTypeRef(encoder, returntype, sz);
		encoder.closeElement(ELEM_RETURNSYM);
		if (injectname != null) {
			encoder.openElement(ELEM_INJECT);
			encoder.writeString(ATTRIB_CONTENT, injectname);
			encoder.closeElement(ELEM_INJECT);
		}
		if (params != null) {
			encoder.openElement(ELEM_INTERNALLIST);
			if (firstVarArg >= 0) {
				// Encoding detail because we are not sending the storage address
				encoder.writeSignedInteger(ATTRIB_FIRST, firstVarArg);
			}
			for (ParameterDefinition param : params) {
				encoder.openElement(ELEM_PARAM);
				String name = param.getName();
				DataType dt = param.getDataType();
				boolean namelock = false;
				if ((name != null) && (name.length() > 0)) {
					encoder.writeString(ATTRIB_NAME, name);
					namelock = true;
				}
				encoder.writeBool(ATTRIB_TYPELOCK, true);
				encoder.writeBool(ATTRIB_NAMELOCK, namelock);
				encoder.openElement(ELEM_ADDR);
				encoder.closeElement(ELEM_ADDR);	// Blank address
				sz = dt.getLength();
				if (sz < 0) {
					sz = 1;
				}
				dtmanage.encodeTypeRef(encoder, dt, sz);
				encoder.closeElement(ELEM_PARAM);
			}
			encoder.closeElement(ELEM_INTERNALLIST);
		}
		encoder.closeElement(ELEM_PROTOTYPE);
	}
Encode this function prototype to a stream.
@param encoder is the stream encoder
@param dtmanage is the DataTypeManager for building type reference tags
@param firstVarArg is index of first variable argument or -1
@throws IOException for errors in the underlying stream
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/pcode/FunctionPrototype.java