Allow constant pointer inference into multiple address spaces

This commit is contained in:
caheckman 2019-12-19 17:32:07 -05:00
parent b5e2efff77
commit 2e80935edb
12 changed files with 181 additions and 30 deletions

View file

@ -94,7 +94,6 @@ Architecture::Architecture(void)
aggressive_ext_trim = false;
readonlypropagate = false;
infer_pointers = true;
pointer_lowerbound = 0x1000;
funcptr_align = 0;
flowoptions = 0;
defaultfp = (ProtoModel *)0;
@ -306,21 +305,19 @@ void Architecture::collectBehaviors(vector<OpBehavior *> &behave) const
}
}
/// A \b near pointer is some form of truncated pointer that needs
/// \e segment or other information to fully form an address.
/// This method searches for a user-defined segment op registered
/// for the space
/// for the given space.
/// \param spc is the address space to check
/// \return true if the space supports a segment operation
bool Architecture::hasNearPointers(AddrSpace *spc) const
/// \return the SegmentOp object or null
SegmentOp *Architecture::getSegmentOp(AddrSpace *spc) const
{
if (spc->getIndex() >= userops.numSegmentOps()) return false;
if (spc->getIndex() >= userops.numSegmentOps()) return (SegmentOp *)0;
SegmentOp *segdef = userops.getSegmentOp(spc->getIndex());
if (segdef == (SegmentOp *)0) return false;
if (segdef == (SegmentOp *)0) return (SegmentOp *)0;
if (segdef->getResolve().space != (AddrSpace *)0)
return true;
return false;
return segdef;
return (SegmentOp *)0;
}
/// Establish details of the prototype for a given function symbol
@ -601,6 +598,12 @@ void Architecture::buildInstructions(DocumentStorage &store)
TypeOp::registerInstructions(inst,types,translate);
}
void Architecture::postSpecFile(void)
{
cacheAddrSpaceProperties();
}
/// Once the processor is known, the Translate object can be built and
/// fully initialized. Processor and compiler specific configuration is performed
/// \param store will hold parsed configuration information
@ -615,8 +618,6 @@ void Architecture::restoreFromSpec(DocumentStorage &store)
insertSpace( new FspecSpace(this,translate,"fspec",numSpaces()));
insertSpace( new IopSpace(this,translate,"iop",numSpaces()));
insertSpace( new JoinSpace(this,translate,"join",numSpaces()));
if (translate->getDefaultSize() < 3) // For small architectures
pointer_lowerbound = 0x100; // assume constants are pointers starting at a much lower bound
userops.initialize(this);
if (translate->getAlignment() <= 8)
min_funcsymbol_size = translate->getAlignment();
@ -642,6 +643,48 @@ void Architecture::initializeSegments(void)
}
}
/// Determine the minimum pointer size for the space and whether or not there are near pointers.
/// Set up an ordered list of inferable spaces (where constant pointers can be infered).
/// Inferable spaces include the default space and anything explicitly listed
/// in the cspec \<global> tag that is not a register space. An initial list of potential spaces is
/// passed in that needs to be ordered, filtered, and deduplicated.
void Architecture::cacheAddrSpaceProperties(void)
{
vector<AddrSpace *> copyList = inferPtrSpaces;
copyList.push_back(getDefaultSpace()); // Make sure the default space is their
inferPtrSpaces.clear();
sort(copyList.begin(),copyList.end(),AddrSpace::compareByIndex);
AddrSpace *lastSpace = (AddrSpace *)0;
for(int4 i=0;i<copyList.size();++i) {
AddrSpace *spc = copyList[i];
if (spc == lastSpace) continue;
lastSpace = spc;
if (spc->getDelay() == 0) continue; // Don't put in a register space
if (spc->getType() == IPTR_SPACEBASE) continue;
if (spc->isOtherSpace()) continue;
if (spc->isOverlay()) continue;
inferPtrSpaces.push_back(spc);
}
int4 defPos = -1;
for(int4 i=0;i<inferPtrSpaces.size();++i) {
AddrSpace *spc = inferPtrSpaces[i];
if (spc == getDefaultSpace())
defPos = i;
SegmentOp *segOp = getSegmentOp(spc);
if (segOp != (SegmentOp *)0) {
int4 val = segOp->getInnerSize();
markNearPointers(spc, val);
}
}
if (defPos > 0) { // Make sure the default space comes first
AddrSpace *tmp = inferPtrSpaces[0];
inferPtrSpaces[0] = inferPtrSpaces[defPos];
inferPtrSpaces[defPos] = tmp;
}
}
/// Recover information out of a \<rule> tag and build the new Rule object.
/// \param el is the XML element
void Architecture::parseDynamicRule(const Element *el)
@ -749,7 +792,9 @@ void Architecture::parseGlobal(const Element *el)
for(iter=list.begin();iter!=list.end();++iter) {
Range range;
range.restoreXml(*iter,this);
symboltab->addRange(scope,range.getSpace(),range.getFirst(),range.getLast());
AddrSpace *spc = range.getSpace();
inferPtrSpaces.push_back(spc);
symboltab->addRange(scope,spc,range.getFirst(),range.getLast());
if (range.getSpace()->isOverlayBase()) { // If the address space is overlayed
// We need to duplicate the range being marked as global into the overlay space(s)
int4 num = numSpaces();