GP-2544 Allow a joined pentry to overlap non-contiguous groups

This commit is contained in:
caheckman 2023-01-20 21:01:41 -05:00
parent f022b9a4d5
commit 38535dcb86
4 changed files with 95 additions and 99 deletions

View file

@ -78,28 +78,20 @@ void ParamEntry::resolveJoin(list<ParamEntry> &curList)
return; return;
} }
joinrec = spaceid->getManager()->findJoin(addressbase); joinrec = spaceid->getManager()->findJoin(addressbase);
int4 mingrp = 1000; groupSet.clear();
int4 maxgrp = -1;
for(int4 i=0;i<joinrec->numPieces();++i) { for(int4 i=0;i<joinrec->numPieces();++i) {
const ParamEntry *entry = findEntryByStorage(curList, joinrec->getPiece(i)); const ParamEntry *entry = findEntryByStorage(curList, joinrec->getPiece(i));
if (entry != (const ParamEntry *)0) { if (entry != (const ParamEntry *)0) {
if (entry->group < mingrp) groupSet.insert(groupSet.end(),entry->groupSet.begin(),entry->groupSet.end());
mingrp = entry->group;
int4 max = entry->group + entry->groupsize;
if (max > maxgrp)
maxgrp = max;
// For output <pentry>, if the most signifigant part overlaps with an earlier <pentry> // For output <pentry>, if the most signifigant part overlaps with an earlier <pentry>
// the least signifigant part is marked for extra checks, and vice versa. // the least signifigant part is marked for extra checks, and vice versa.
flags |= (i==0) ? extracheck_low : extracheck_high; flags |= (i==0) ? extracheck_low : extracheck_high;
} }
} }
if (maxgrp < 0 || mingrp >= 1000) if (groupSet.empty())
throw LowlevelError("<pentry> join must overlap at least one previous entry"); throw LowlevelError("<pentry> join must overlap at least one previous entry");
group = mingrp; sort(groupSet.begin(),groupSet.end());
groupsize = (maxgrp - mingrp);
flags |= overlapping; flags |= overlapping;
if (groupsize > joinrec->numPieces())
throw LowlevelError("<pentry> join must overlap sequential entries");
} }
/// Search for overlaps of \b this with any previous entry. If an overlap is discovered, /// Search for overlaps of \b this with any previous entry. If an overlap is discovered,
@ -111,9 +103,7 @@ void ParamEntry::resolveOverlap(list<ParamEntry> &curList)
{ {
if (joinrec != (JoinRecord *)0) if (joinrec != (JoinRecord *)0)
return; // Overlaps with join records dealt with in resolveJoin return; // Overlaps with join records dealt with in resolveJoin
int4 grpsize = 0; vector<int4> overlapSet;
int4 mingrp = 1000;
int4 maxgrp = -1;
list<ParamEntry>::const_iterator iter,enditer; list<ParamEntry>::const_iterator iter,enditer;
Address addr(spaceid,addressbase); Address addr(spaceid,addressbase);
enditer = curList.end(); enditer = curList.end();
@ -123,12 +113,7 @@ void ParamEntry::resolveOverlap(list<ParamEntry> &curList)
if (!entry.intersects(addr, size)) continue; if (!entry.intersects(addr, size)) continue;
if (contains(entry)) { // If this contains the intersecting entry if (contains(entry)) { // If this contains the intersecting entry
if (entry.isOverlap()) continue; // Don't count resources (already counted overlapped entry) if (entry.isOverlap()) continue; // Don't count resources (already counted overlapped entry)
if (entry.group < mingrp) overlapSet.insert(overlapSet.end(),entry.groupSet.begin(),entry.groupSet.end());
mingrp = entry.group;
int4 max = entry.group + entry.groupsize;
if (max > maxgrp)
maxgrp = max;
grpsize += entry.groupsize;
// For output <pentry>, if the most signifigant part overlaps with an earlier <pentry> // For output <pentry>, if the most signifigant part overlaps with an earlier <pentry>
// the least signifigant part is marked for extra checks, and vice versa. // the least signifigant part is marked for extra checks, and vice versa.
if (addressbase == entry.addressbase) if (addressbase == entry.addressbase)
@ -140,14 +125,36 @@ void ParamEntry::resolveOverlap(list<ParamEntry> &curList)
throw LowlevelError("Illegal overlap of <pentry> in compiler spec"); throw LowlevelError("Illegal overlap of <pentry> in compiler spec");
} }
if (grpsize == 0) return; // No overlaps if (overlapSet.empty()) return; // No overlaps
if (grpsize != (maxgrp - mingrp)) sort(overlapSet.begin(),overlapSet.end());
throw LowlevelError("<pentry> must overlap sequential entries"); groupSet = overlapSet;
group = mingrp;
groupsize = grpsize;
flags |= overlapping; flags |= overlapping;
} }
/// \param op2 is the other entry to compare
/// \return \b true if the group sets associated with each ParamEntry intersect at all
bool ParamEntry::groupOverlap(const ParamEntry &op2) const
{
int4 i = 0;
int4 j = 0;
int4 valThis = groupSet[i];
int4 valOther = op2.groupSet[j];
while(valThis != valOther) {
if (valThis < valOther) {
i += 1;
if (i >= groupSet.size()) return false;
valThis = groupSet[i];
}
else {
j += 1;
if (j >= op2.groupSet.size()) return false;
valOther = op2.groupSet[j];
}
}
return true;
}
/// This entry must properly contain the other memory range, and /// This entry must properly contain the other memory range, and
/// the entry properties must be compatible. A \e join ParamEntry can /// the entry properties must be compatible. A \e join ParamEntry can
/// subsume another \e join ParamEntry, but we expect the addressbase to be identical. /// subsume another \e join ParamEntry, but we expect the addressbase to be identical.
@ -379,7 +386,7 @@ OpCode ParamEntry::assumedExtension(const Address &addr,int4 sz,VarnodeData &res
int4 ParamEntry::getSlot(const Address &addr,int4 skip) const int4 ParamEntry::getSlot(const Address &addr,int4 skip) const
{ {
int4 res = group; int4 res = groupSet[0];
if (alignment != 0) { if (alignment != 0) {
uintb diff = addr.getOffset() + skip - addressbase; uintb diff = addr.getOffset() + skip - addressbase;
int4 baseslot = (int4)diff / alignment; int4 baseslot = (int4)diff / alignment;
@ -389,7 +396,7 @@ int4 ParamEntry::getSlot(const Address &addr,int4 skip) const
res += baseslot; res += baseslot;
} }
else if (skip != 0) { else if (skip != 0) {
res += (groupsize-1); res = groupSet.back();
} }
return res; return res;
} }
@ -456,7 +463,6 @@ void ParamEntry::decode(Decoder &decoder,bool normalstack,bool grouped,list<Para
size = minsize = -1; // Must be filled in size = minsize = -1; // Must be filled in
alignment = 0; // default alignment = 0; // default
numslots = 1; numslots = 1;
groupsize = 1; // default
uint4 elemId = decoder.openElement(ELEM_PENTRY); uint4 elemId = decoder.openElement(ELEM_PENTRY);
for(;;) { for(;;) {
@ -646,16 +652,15 @@ Address ParamListStandard::assignAddress(const Datatype *tp,vector<int4> &status
const ParamEntry &curEntry( *iter ); const ParamEntry &curEntry( *iter );
int4 grp = curEntry.getGroup(); int4 grp = curEntry.getGroup();
if (status[grp]<0) continue; if (status[grp]<0) continue;
if ((curEntry.getType() != TYPE_UNKNOWN)&& if ((curEntry.getType() != TYPE_UNKNOWN) && tp->getMetatype() != curEntry.getType())
tp->getMetatype() != curEntry.getType())
continue; // Wrong type continue; // Wrong type
Address res = curEntry.getAddrBySlot(status[grp],tp->getSize()); Address res = curEntry.getAddrBySlot(status[grp],tp->getSize());
if (res.isInvalid()) continue; // If -tp- doesn't fit an invalid address is returned if (res.isInvalid()) continue; // If -tp- doesn't fit an invalid address is returned
if (curEntry.isExclusion()) { if (curEntry.isExclusion()) {
int4 maxgrp = grp + curEntry.getGroupSize(); const vector<int4> &groupSet(curEntry.getAllGroups());
for(int4 j=grp;j<maxgrp;++j) // For an exclusion entry for(int4 j=0;j<groupSet.size();++j) // For an exclusion entry
status[j] = -1; // some number of groups are taken up status[groupSet[j]] = -1; // some number of groups are taken up
} }
return res; return res;
} }
@ -852,18 +857,18 @@ void ParamListStandard::separateSections(ParamActive *active,vector<int4> &trial
/// ///
/// Only one trial within an exclusion group can have active use, mark all others as unused. /// Only one trial within an exclusion group can have active use, mark all others as unused.
/// \param active is the set of trials, which must be sorted on group /// \param active is the set of trials, which must be sorted on group
/// \param groupUpper is the biggest group number to be marked /// \param activeTrial is the index of the trial whose groups are to be considered active
/// \param groupStart is the index of the first trial in the smallest group to be marked /// \param trialStart is the index of the first trial to mark
/// \param index is the specified trial index that is \e not to be marked void ParamListStandard::markGroupNoUse(ParamActive *active,int4 activeTrial,int4 trialStart)
void ParamListStandard::markGroupNoUse(ParamActive *active,int4 groupUpper,int4 groupStart,int4 index)
{ {
int4 numTrials = active->getNumTrials(); int4 numTrials = active->getNumTrials();
for(int4 i=groupStart;i<numTrials;++i) { // Mark entries in the group range as definitely not used const ParamEntry *activeEntry = active->getTrial(activeTrial).getEntry();
if (i == index) continue; // The trial NOT to mark for(int4 i=trialStart;i<numTrials;++i) { // Mark entries intersecting the group set as definitely not used
if (i == activeTrial) continue; // The trial NOT to mark
ParamTrial &othertrial(active->getTrial(i)); ParamTrial &othertrial(active->getTrial(i));
if (othertrial.isDefinitelyNotUsed()) continue; if (othertrial.isDefinitelyNotUsed()) continue;
if (othertrial.getEntry()->getGroup() > groupUpper) break; if (!othertrial.getEntry()->groupOverlap(*activeEntry)) break;
othertrial.markNoUse(); othertrial.markNoUse();
} }
} }
@ -889,7 +894,7 @@ void ParamListStandard::markBestInactive(ParamActive *active,int4 group,int4 gro
const ParamEntry *entry = trial.getEntry(); const ParamEntry *entry = trial.getEntry();
int4 grp = entry->getGroup(); int4 grp = entry->getGroup();
if (grp != group) break; if (grp != group) break;
if (entry->getGroupSize() > 1) continue; // Covering multiple slots automatically give low score if (entry->getAllGroups().size() > 1) continue; // Covering multiple slots automatically give low score
int4 score = 0; int4 score = 0;
if (trial.hasAncestorRealistic()) { if (trial.hasAncestorRealistic()) {
score += 5; score += 5;
@ -904,7 +909,7 @@ void ParamListStandard::markBestInactive(ParamActive *active,int4 group,int4 gro
} }
} }
if (bestTrial >= 0) if (bestTrial >= 0)
markGroupNoUse(active, group, groupStart, bestTrial); markGroupNoUse(active, bestTrial, groupStart);
} }
/// \brief Enforce exclusion rules for the given set of parameter trials /// \brief Enforce exclusion rules for the given set of parameter trials
@ -932,8 +937,7 @@ void ParamListStandard::forceExclusionGroup(ParamActive *active)
inactiveCount = 0; inactiveCount = 0;
} }
if (curtrial.isActive()) { if (curtrial.isActive()) {
int4 groupUpper = grp + curtrial.getEntry()->getGroupSize() - 1; // This entry covers some number of groups markGroupNoUse(active, i, groupStart);
markGroupNoUse(active, groupUpper, groupStart, i);
} }
else { else {
inactiveCount += 1; inactiveCount += 1;
@ -969,9 +973,9 @@ void ParamListStandard::forceNoUse(ParamActive *active, int4 start, int4 stop)
} }
else { // First trial in a new group (or next element in same non-exclusion group) else { // First trial in a new group (or next element in same non-exclusion group)
if (alldefnouse) // If all in the last group were defnotused if (alldefnouse) // If all in the last group were defnotused
seendefnouse = true;// then force everything afterword to be defnotused seendefnouse = true;// then force everything afterward to be defnotused
alldefnouse = curtrial.isDefinitelyNotUsed(); alldefnouse = curtrial.isDefinitelyNotUsed();
curgroup = grp + curtrial.getEntry()->getGroupSize() - 1; curgroup = grp;
} }
if (seendefnouse) if (seendefnouse)
curtrial.markInactive(); curtrial.markInactive();
@ -1131,7 +1135,7 @@ void ParamListStandard::parsePentry(Decoder &decoder,vector<EffectRecord> &effec
else if (autokill) // If a register parameter AND we automatically generate killedbycall else if (autokill) // If a register parameter AND we automatically generate killedbycall
effectlist.push_back(EffectRecord(entry.back(),EffectRecord::killedbycall)); effectlist.push_back(EffectRecord(entry.back(),EffectRecord::killedbycall));
int4 maxgroup = entry.back().getGroup() + entry.back().getGroupSize(); int4 maxgroup = entry.back().getAllGroups().back() + 1;
if (maxgroup > numgroup) if (maxgroup > numgroup)
numgroup = maxgroup; numgroup = maxgroup;
} }
@ -1250,7 +1254,7 @@ bool ParamListStandard::possibleParamWithSlot(const Address &loc,int4 size,int4
if (entryNum == (const ParamEntry *)0) return false; if (entryNum == (const ParamEntry *)0) return false;
slot = entryNum->getSlot(loc,0); slot = entryNum->getSlot(loc,0);
if (entryNum->isExclusion()) { if (entryNum->isExclusion()) {
slotsize = entryNum->getGroupSize(); slotsize = entryNum->getAllGroups().size();
} }
else { else {
slotsize = ((size-1) / entryNum->getAlign()) + 1; slotsize = ((size-1) / entryNum->getAlign()) + 1;

View file

@ -101,8 +101,7 @@ public:
private: private:
uint4 flags; ///< Boolean properties of the parameter uint4 flags; ///< Boolean properties of the parameter
type_metatype type; ///< Data-type class that this entry must match type_metatype type; ///< Data-type class that this entry must match
int4 group; ///< Group of (mutually exclusive) entries that this entry belongs to vector<int4> groupSet; ///< Group(s) \b this entry belongs to
int4 groupsize; ///< The number of consecutive groups taken by the entry
AddrSpace *spaceid; ///< Address space containing the range AddrSpace *spaceid; ///< Address space containing the range
uintb addressbase; ///< Starting offset of the range uintb addressbase; ///< Starting offset of the range
int4 size; ///< Size of the range in bytes int4 size; ///< Size of the range in bytes
@ -117,9 +116,10 @@ private:
/// \brief Is the logical value left-justified within its container /// \brief Is the logical value left-justified within its container
bool isLeftJustified(void) const { return (((flags&force_left_justify)!=0)||(!spaceid->isBigEndian())); } bool isLeftJustified(void) const { return (((flags&force_left_justify)!=0)||(!spaceid->isBigEndian())); }
public: public:
ParamEntry(int4 grp) { group=grp; } ///< Constructor for use with decode ParamEntry(int4 grp) { groupSet.push_back(grp); } ///< Constructor for use with decode
int4 getGroup(void) const { return group; } ///< Get the group id \b this belongs to int4 getGroup(void) const { return groupSet[0]; } ///< Get the group id \b this belongs to
int4 getGroupSize(void) const { return groupsize; } ///< Get the number of groups occupied by \b this const vector<int4> &getAllGroups(void) const { return groupSet; } ///< Get all group numbers \b this overlaps
bool groupOverlap(const ParamEntry &op2) const; ///< Check if \b this and op2 occupy any of the same groups
int4 getSize(void) const { return size; } ///< Get the size of the memory range in bytes. int4 getSize(void) const { return size; } ///< Get the size of the memory range in bytes.
int4 getMinSize(void) const { return minsize; } ///< Get the minimum size of a logical value contained in \b this int4 getMinSize(void) const { return minsize; } ///< Get the minimum size of a logical value contained in \b this
int4 getAlign(void) const { return alignment; } ///< Get the alignment of \b this entry int4 getAlign(void) const { return alignment; } ///< Get the alignment of \b this entry
@ -567,7 +567,7 @@ protected:
const ParamEntry *selectUnreferenceEntry(int4 grp,type_metatype prefType) const; ///< Select entry to fill an unreferenced param const ParamEntry *selectUnreferenceEntry(int4 grp,type_metatype prefType) const; ///< Select entry to fill an unreferenced param
void buildTrialMap(ParamActive *active) const; ///< Build map from parameter trials to model ParamEntrys void buildTrialMap(ParamActive *active) const; ///< Build map from parameter trials to model ParamEntrys
void separateSections(ParamActive *active,vector<int4> &trialStart) const; void separateSections(ParamActive *active,vector<int4> &trialStart) const;
static void markGroupNoUse(ParamActive *active,int4 groupUpper,int4 groupStart,int4 index); static void markGroupNoUse(ParamActive *active,int4 activeTrial,int4 trialStart);
static void markBestInactive(ParamActive *active,int4 group,int4 groupStart,type_metatype prefType); static void markBestInactive(ParamActive *active,int4 group,int4 groupStart,type_metatype prefType);
static void forceExclusionGroup(ParamActive *active); static void forceExclusionGroup(ParamActive *active);
static void forceNoUse(ParamActive *active,int4 start,int4 stop); static void forceNoUse(ParamActive *active,int4 start,int4 stop);

View file

@ -50,8 +50,7 @@ public class ParamEntry {
private int flags; private int flags;
private int type; // Restriction on DataType this entry must match private int type; // Restriction on DataType this entry must match
private int group; // Group of (mutually exclusive) entries that this entry belongs to private int[] groupSet; // Group(s) this entry belongs to
private int groupsize; // The number of consecutive groups taken by the entry
private AddressSpace spaceid; // Space of this range private AddressSpace spaceid; // Space of this range
private long addressbase; // Start of the range private long addressbase; // Start of the range
private int size; // size of the range private int size; // size of the range
@ -61,15 +60,16 @@ public class ParamEntry {
private Varnode[] joinrec; private Varnode[] joinrec;
public ParamEntry(int grp) { // For use with restoreXml public ParamEntry(int grp) { // For use with restoreXml
group = grp; groupSet = new int[1];
groupSet[0] = grp;
} }
public int getGroup() { public int getGroup() {
return group; return groupSet[0];
} }
public int getGroupSize() { public int[] getAllGroups() {
return groupsize; return groupSet;
} }
public int getSize() { public int getSize() {
@ -265,7 +265,7 @@ public class ParamEntry {
* @return the slot index * @return the slot index
*/ */
public int getSlot(Address addr, int skip) { public int getSlot(Address addr, int skip) {
int res = group; int res = groupSet[0];
if (alignment != 0) { if (alignment != 0) {
long diff = addr.getOffset() + skip - addressbase; long diff = addr.getOffset() + skip - addressbase;
int baseslot = (int) diff / alignment; int baseslot = (int) diff / alignment;
@ -277,7 +277,7 @@ public class ParamEntry {
} }
} }
else if (skip != 0) { else if (skip != 0) {
res += (groupsize - 1); res = groupSet[groupSet.length - 1];
} }
return res; return res;
} }
@ -366,29 +366,24 @@ public class ParamEntry {
if (joinrec == null) { if (joinrec == null) {
return; return;
} }
int mingrp = 1000; ArrayList<Integer> newGroupSet = new ArrayList<>();
int maxgrp = -1;
for (Varnode piece : joinrec) { for (Varnode piece : joinrec) {
ParamEntry entry = findEntryByStorage(curList, piece); ParamEntry entry = findEntryByStorage(curList, piece);
if (entry != null) { if (entry != null) {
if (entry.group < mingrp) { for (int group : entry.groupSet) {
mingrp = entry.group; newGroupSet.add(group);
}
int max = entry.group + entry.groupsize;
if (max > maxgrp) {
maxgrp = max;
} }
} }
} }
if (maxgrp < 0 || mingrp >= 1000) { if (newGroupSet.isEmpty()) {
throw new XmlParseException("<pentry> join must overlap at least one previous entry"); throw new XmlParseException("<pentry> join must overlap at least one previous entry");
} }
group = mingrp; newGroupSet.sort(null);
groupsize = (maxgrp - mingrp); groupSet = new int[newGroupSet.size()];
flags |= OVERLAPPING; for (int i = 0; i < groupSet.length; ++i) {
if (groupsize > joinrec.length) { groupSet[i] = newGroupSet.get(i);
throw new XmlParseException("<pentry> join must overlap sequential entries");
} }
flags |= OVERLAPPING;
} }
/** /**
@ -401,9 +396,7 @@ public class ParamEntry {
if (joinrec != null) { if (joinrec != null) {
return; return;
} }
int grpsize = 0; ArrayList<Integer> newGroupSet = new ArrayList<>();
int mingrp = 1000;
int maxgrp = -1;
Address addr = spaceid.getAddress(addressbase); Address addr = spaceid.getAddress(addressbase);
for (ParamEntry entry : curList) { for (ParamEntry entry : curList) {
if (entry == this) { if (entry == this) {
@ -416,27 +409,22 @@ public class ParamEntry {
if (entry.isOverlap()) { if (entry.isOverlap()) {
continue; // Don't count resources (already counted overlapped pentry) continue; // Don't count resources (already counted overlapped pentry)
} }
if (entry.group < mingrp) { for (int group : entry.groupSet) {
mingrp = entry.group; newGroupSet.add(group);
} }
int max = entry.group + entry.groupsize;
if (max > maxgrp) {
maxgrp = max;
}
grpsize += entry.groupsize;
} }
else { else {
throw new XmlParseException("Illegal overlap of <pentry> in compiler spec"); throw new XmlParseException("Illegal overlap of <pentry> in compiler spec");
} }
} }
if (grpsize == 0) { if (newGroupSet.isEmpty()) {
return; // No overlaps return; // No overlaps
} }
if (grpsize != (maxgrp - mingrp)) { newGroupSet.sort(null);
throw new XmlParseException("<pentry> must overlap sequential entries"); groupSet = new int[newGroupSet.size()];
for (int i = 0; i < groupSet.length; ++i) {
groupSet[i] = newGroupSet.get(i);
} }
group = mingrp;
groupsize = grpsize;
flags |= OVERLAPPING; flags |= OVERLAPPING;
} }
@ -486,7 +474,6 @@ public class ParamEntry {
size = minsize = -1; // Must be filled in size = minsize = -1; // Must be filled in
alignment = 0; // default alignment = 0; // default
numslots = 1; numslots = 1;
groupsize = 1; // default
XmlElement el = parser.start("pentry"); XmlElement el = parser.start("pentry");
Iterator<Entry<String, String>> iter = el.getAttributes().entrySet().iterator(); Iterator<Entry<String, String>> iter = el.getAttributes().entrySet().iterator();
@ -606,9 +593,14 @@ public class ParamEntry {
if (numslots != obj.numslots) { if (numslots != obj.numslots) {
return false; return false;
} }
if (group != obj.group || groupsize != obj.groupsize) { if (groupSet.length != obj.groupSet.length) {
return false; return false;
} }
for (int i = 0; i < groupSet.length; ++i) {
if (groupSet[i] != obj.groupSet[i]) {
return false;
}
}
if (!SystemUtilities.isArrayEqual(joinrec, obj.joinrec)) { if (!SystemUtilities.isArrayEqual(joinrec, obj.joinrec)) {
return false; return false;
} }

View file

@ -107,10 +107,9 @@ public class ParamListStandard implements ParamList {
continue; // -tp- does not fit in this entry continue; // -tp- does not fit in this entry
} }
if (element.isExclusion()) { if (element.isExclusion()) {
int maxgrp = grp + element.getGroupSize(); for (int group : element.getAllGroups()) {
for (int j = grp; j < maxgrp; ++j) {
// For an exclusion entry // For an exclusion entry
status[j] = -1; // some number of groups are taken up status[group] = -1; // some number of groups are taken up
} }
if (element.isFloatExtended()) { if (element.isFloatExtended()) {
sz = element.getSize(); // Still use the entire container size, when assigning storage sz = element.getSize(); // Still use the entire container size, when assigning storage
@ -264,7 +263,8 @@ public class ParamListStandard implements ParamList {
if (pentry.getSpace().isStackSpace()) { if (pentry.getSpace().isStackSpace()) {
spacebase = pentry.getSpace(); spacebase = pentry.getSpace();
} }
int maxgroup = pentry.getGroup() + pentry.getGroupSize(); int[] groupSet = pentry.getAllGroups();
int maxgroup = groupSet[groupSet.length - 1] + 1;
if (maxgroup > numgroup) { if (maxgroup > numgroup) {
numgroup = maxgroup; numgroup = maxgroup;
} }
@ -379,7 +379,7 @@ public class ParamListStandard implements ParamList {
ParamEntry curentry = entry[num]; ParamEntry curentry = entry[num];
res.slot = curentry.getSlot(loc, 0); res.slot = curentry.getSlot(loc, 0);
if (curentry.isExclusion()) { if (curentry.isExclusion()) {
res.slotsize = curentry.getGroupSize(); res.slotsize = curentry.getAllGroups().length;
} }
else { else {
res.slotsize = ((size - 1) / curentry.getAlign()) + 1; res.slotsize = ((size - 1) / curentry.getAlign()) + 1;