private void restoreXml(XmlPullParser parser) throws XmlParseException, DuplicateNameException {
		List<PrototypeModel> modelList = new ArrayList<>();
		boolean seenDefault = false;
		boolean seenThisCall = false;
		String defaultName = null;
		String evalCurrentPrototype = null;
		String evalCalledPrototype = null;

		parser.start("compiler_spec");
		while (parser.peek().isStart()) {
			String name = parser.peek().getName();
			if (name.equals("properties")) {
				restoreProperties(parser);
			}
			else if (name.equals("data_organization")) {
				dataOrganization.restoreXml(parser);
			}
			else if (name.equals("callfixup")) {
				String nm = parser.peek().getAttribute("name");
				pcodeInject.restoreXmlInject(sourceName, nm, InjectPayload.CALLFIXUP_TYPE, parser);
			}
			else if (name.equals("callotherfixup")) {
				String nm = parser.peek().getAttribute("targetop");
				pcodeInject.restoreXmlInject(sourceName, nm, InjectPayload.CALLOTHERFIXUP_TYPE,
					parser);
			}
			else if (name.equals("context_data")) {
				ContextSetting.parseContextData(ctxsetting, parser, this);
			}
			else if (name.equals("stackpointer")) {
				setStackPointer(parser);
			}
			else if (name.equals("spacebase")) {
				restoreSpaceBase(parser);
			}
			else if (name.equals("global")) {
				restoreMemoryTags("global", parser, globalSet);
			}
			else if (name.equals("default_proto")) {
				parser.start();
				PrototypeModel model = addPrototypeModel(modelList, parser);
				parser.end();
				if (!seenDefault) {
					defaultName = model.name;
					seenDefault = true;
				}
				if (model.getName().equals(CALLING_CONVENTION_thiscall)) {
					seenThisCall = true;
				}
			}
			else if (name.equals("prototype")) {
				PrototypeModel model = addPrototypeModel(modelList, parser);
				if (defaultName == null) {
					defaultName = model.name;
				}
				if (model.getName().equals(CALLING_CONVENTION_thiscall)) {
					seenThisCall = true;
				}
			}
			else if (name.equals("modelalias")) {
				XmlElement el = parser.start();
				String aliasName = el.getAttribute("name");
				String parentName = el.getAttribute("parent");
				parser.end(el);
				createModelAlias(aliasName, parentName, modelList);
				if (aliasName.equals(CALLING_CONVENTION_thiscall)) {
					seenThisCall = true;
				}
			}
			else if (name.equals("resolveprototype")) {
				addPrototypeModel(modelList, parser);
			}
			else if (name.equals("eval_current_prototype")) {
				evalCurrentPrototype = parser.start().getAttribute("name");
				parser.end();
			}
			else if (name.equals("eval_called_prototype")) {
				evalCalledPrototype = parser.start().getAttribute("name");
				parser.end();
			}
			else if (name.equals("segmentop")) {
				String source = "cspec: " + language.getLanguageID().getIdAsString();
				InjectPayloadSleigh payload = new InjectPayloadSegment(source);
				payload.restoreXml(parser, language);
				pcodeInject.registerInject(payload);
			}
			else if (name.equals("aggressivetrim")) {
				XmlElement el = parser.start();
				aggressiveTrim = SpecXmlUtils.decodeBoolean(el.getAttribute("signext"));
				parser.end(el);
			}
			else if (name.equals("prefersplit")) {
				restorePreferSplit(parser);
			}
			else if (name.equals("nohighptr")) {
				noHighPtr = new AddressSet();
				restoreMemoryTags("nohighptr", parser, noHighPtr);
			}
			else if (name.equals("readonly")) {
				readOnlySet = new AddressSet();
				restoreMemoryTags("readonly", parser, readOnlySet);
			}
			else if (name.equals("returnaddress")) {
				restoreReturnAddress(parser);
			}
			else if (name.equals("funcptr")) {
				XmlElement subel = parser.start();
				funcPtrAlign = SpecXmlUtils.decodeInt(subel.getAttribute("align"));
				parser.end(subel);
			}
			else if (name.equals("deadcodedelay")) {
				restoreDeadCodeDelay(parser);
			}
			else if (name.equals("inferptrbounds")) {
				restoreInferPtrBounds(parser);
			}
			else {
				XmlElement el = parser.start();
				parser.discardSubTree(el);
			}
		}
		parser.end();

		if (stackPointer == null) {
			stackSpace = new GenericAddressSpace(SpaceNames.STACK_SPACE_NAME,
				language.getDefaultSpace().getSize(),
				language.getDefaultSpace().getAddressableUnitSize(), AddressSpace.TYPE_STACK, 0);
		}
		if (!seenThisCall) {
			createModelAlias(CALLING_CONVENTION_thiscall, defaultName, modelList);
		}
		String dupName =
			modelXrefs(modelList, defaultName, evalCurrentPrototype, evalCalledPrototype);
		if (dupName != null) {
			throw new DuplicateNameException("Multiple prototype models with the name: " + dupName);
		}
	}
Initialize this object from an XML stream.  A single {@code <compiler_spec>} tag is expected.
@param parser is the XML stream
@throws XmlParseException for badly formed XML
@throws DuplicateNameException if we parse more than one PrototypeModel with the same name
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/lang/BasicCompilerSpec.java