Exemplo n.º 1
0
void QsCodeParser::setQuickDoc(Node *quickNode,
                               const Doc& doc,
                               const QStringList& qtParams,
                               const QStringList& quickParams)
{
    QRegExp quickifyCommand("\\\\" + COMMAND_QUICKIFY + "([^\n]*)(?:\n|$)");

    if (quickNode->type() == Node::Function) {
	FunctionNode *quickFunc = (FunctionNode *) quickNode;
	quickFunc->setOverload(false);
    }

    if (doc.metaCommandsUsed().contains(COMMAND_QUICKIFY)) {
	QString source = doc.source();
	int pos = source.indexOf(quickifyCommand);
	if (pos != -1) {
	    QString quickifiedSource = quickNode->doc().source();
	    if (!qtParams.isEmpty() && qtParams != quickParams)
		renameParameters(quickifiedSource, doc, qtParams,
				  quickParams);
	    applyReplacementList(quickifiedSource, doc);

	    do {
		QString extract = quickifiedSource;
		QString arg = quickifyCommand.cap(1).simplified();
		if (!arg.isEmpty()) {
		    if (arg.startsWith("/") && arg.endsWith("/") &&
			 arg.length() > 2) {
			QString pattern = arg.mid(1, arg.length() - 2);
			extractRegExp(QRegExp(pattern), extract, doc);
		    }
                    else {
			extractTarget(arg, extract, doc);
		    }
		}
		source.replace(pos, quickifyCommand.matchedLength(), extract);
		pos += extract.length();
	    } while ((pos = source.indexOf(quickifyCommand, pos)) != -1);

	    QRegExp quickcodeRegExp(
		    "\\\\" + COMMAND_QUICKCODE + "(.*)\\\\" +
		    COMMAND_ENDQUICKCODE);
	    quickcodeRegExp.setMinimal(true);
	    source.replace(quickcodeRegExp, "");
	}

	Doc quickDoc(doc.location(),
                     doc.location(),
                     source,
                     (CppCodeParser::topicCommands() + topicCommands() +
                      CppCodeParser::otherMetaCommands()) << COMMAND_REPLACE);
	quickNode->setDoc(quickDoc, true);
	processOtherMetaCommands(quickDoc, quickNode);
    }
    else {
	quickNode->setDoc(doc, true);
	processOtherMetaCommands(doc, quickNode);
    }
}
Exemplo n.º 2
0
//
// The tail-call optimzation may result in a function ending in a jump (b) 
// to another functions.  At compile time the compiler does not know 
// if the target of the jump will be in the same mode (arm vs thumb).
// The arm/thumb instruction set has a way to change modes in a bl(x)
// insruction, but no instruction to change mode in a jump (b) instruction.
// In those rare cases, the linker needs to insert a shim of code to 
// make the mode switch.
//
void doPass(const Options& opts, ld::Internal& state)
{	
	// only make branch shims in final linked images
	if ( opts.outputKind() == Options::kObjectFile )
		return;

	// only ARM need branch islands
	if ( opts.architecture() != CPU_TYPE_ARM )
		return;
	
	const bool makingKextBundle = (opts.outputKind() == Options::kKextBundle);

	// scan all sections
	for (std::vector<ld::Internal::FinalSection*>::iterator sit=state.sections.begin(); sit != state.sections.end(); ++sit) {
		ld::Internal::FinalSection* sect = *sit;
		std::map<const Atom*, const Atom*> atomToThumbMap;
		std::map<const Atom*, const Atom*> thumbToAtomMap;
		std::vector<const Atom*> shims;
		// scan section for branch instructions that need to switch mode
		for (std::vector<const ld::Atom*>::iterator ait=sect->atoms.begin();  ait != sect->atoms.end(); ++ait) {
			const ld::Atom* atom = *ait;
			const ld::Atom* target = NULL;
			bool targetIsProxy;
			for (ld::Fixup::iterator fit = atom->fixupsBegin(), end=atom->fixupsEnd(); fit != end; ++fit) {
				switch ( fit->kind ) {
					case ld::Fixup::kindStoreTargetAddressThumbBranch22:
						extractTarget(fit, state, &target);
						targetIsProxy = (target->definition() == ld::Atom::definitionProxy);
						if ( ! target->isThumb() ) {
							const uint8_t* fixUpLocation = atom->rawContentPointer();
							// <rdar://problem/9544194> don't try to scan atom for branches if atom unwilling to supply raw content
							if ( fixUpLocation == NULL )
								break;
							fixUpLocation += fit->offsetInAtom;
							uint32_t instruction = *((uint32_t*)fixUpLocation);
							bool is_b = ((instruction & 0xD000F800) == 0x9000F000);
							// need shim for branch from thumb to arm, or for call to function outside kext
							if ( is_b || (targetIsProxy && makingKextBundle) ) {
								if ( _s_log ) fprintf(stderr, "need to add thumb->arm instr=0x%08X shim to %s for %s\n", instruction, target->name(), atom->name()); 
								const Atom* shim = NULL;
								std::map<const Atom*, const Atom*>::iterator pos = thumbToAtomMap.find(target);
								if ( pos == thumbToAtomMap.end() ) {
									if ( opts.archSupportsThumb2() ) {
										// <rdar://problem/9116044> make long-branch style shims for arm kexts
										if ( makingKextBundle && opts.allowTextRelocs() )
											shim = new NoPICThumb2ToArmShimAtom(target, *sect);
										else
											shim = new Thumb2ToArmShimAtom(target, *sect);
									}
									else {
										shim = new Thumb1ToArmShimAtom(target, *sect);
									}
									shims.push_back(shim);
									thumbToAtomMap[target] = shim;
								}
								else {
									shim = pos->second;
								}
								fit->binding = ld::Fixup::bindingDirectlyBound;
								fit->u.target = shim;
							}
						}
						break;
					case ld::Fixup::kindStoreTargetAddressARMBranch24:
						extractTarget(fit, state, &target);
						targetIsProxy = (target->definition() == ld::Atom::definitionProxy);
						if ( target->isThumb() || (targetIsProxy && makingKextBundle) ) {
							const uint8_t* fixUpLocation = atom->rawContentPointer();
							// <rdar://problem/9544194> don't try to scan atom for branches if atom unwilling to supply raw content
							if ( fixUpLocation == NULL )
								break;
							fixUpLocation += fit->offsetInAtom;
							uint32_t instruction = *((uint32_t*)fixUpLocation);
							bool is_b = ((instruction & 0x0F000000) == 0x0A000000) && ((instruction & 0xF0000000) != 0xF0000000);
							// need shim for branch from arm to thumb, or for call to function outside kext
							if ( is_b || (targetIsProxy && makingKextBundle) ) {
								if ( _s_log ) fprintf(stderr, "need to add arm->thumb instr=0x%08X shim to %s for %s\n", instruction, target->name(), atom->name()); 
								const Atom* shim = NULL;
								std::map<const Atom*, const Atom*>::iterator pos = atomToThumbMap.find(target);
								if ( pos == atomToThumbMap.end() ) {
									// <rdar://problem/9116044> make long-branch style shims for arm kexts
									if ( makingKextBundle && opts.allowTextRelocs() )
										shim = new NoPICARMtoThumbShimAtom(target, *sect);
									else
										shim = new ARMtoThumbShimAtom(target, *sect);
									shims.push_back(shim);
									atomToThumbMap[target] = shim;
								}
								else {
									shim = pos->second;
								}
								fit->binding = ld::Fixup::bindingDirectlyBound;
								fit->u.target = shim;
							}
						}
						break;
					
					//case ld::Fixup::kindStoreARMBranch24:
					//case ld::Fixup::kindStoreThumbBranch22:
					// Note: these fixups will only be seen if the the b/bl is to a symbol plus addend
					// for now we don't handle making shims.  If a shim is needed there will
					// be an error later.
					//	break;
					default:
						break;
				}
			}
		}

		// append all new shims to end of __text
		sect->atoms.insert(sect->atoms.end(), shims.begin(), shims.end());
	}
}