Skip to content

Commit

Permalink
[Literate] Generate accessors for structures
Browse files Browse the repository at this point in the history
  • Loading branch information
0x8000-0000 committed Jul 6, 2020
1 parent a1c3716 commit 3b75921
Show file tree
Hide file tree
Showing 9 changed files with 1,703 additions and 36 deletions.
110 changes: 79 additions & 31 deletions src/main/java/net/signbit/samx/literate/CppVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,19 @@ private String getBitFieldName(SamXParser.RecordDataContext rdc, int index)
return visitor.getReference();
}

public StructureMember(SamXParser.RecordDataContext rdc, int bitOffset, int unitWidth)
public StructureMember(SamXParser.RecordDataContext rdc, int unitOffset, int bitOffset, int unitWidth)
{
this.unitWidth = unitWidth;

unitOffset = getInt(rdc, 0);
int localUnitOffset = getInt(rdc, 0);
if (localUnitOffset == -1)
{
this.unitOffset = unitOffset;
}
else
{
this.unitOffset = localUnitOffset;
}
width = getInt(rdc, 1);

final String localType = getString(rdc, 2);
Expand Down Expand Up @@ -131,6 +139,8 @@ public boolean isNative()
return "unsigned".equals(type);
}

public boolean isWord() { return (unitWidth == width) && (bitOffset == 0); };

public String getType()
{
if (isNative())
Expand Down Expand Up @@ -233,58 +243,77 @@ public Object visitRecordSet(SamXParser.RecordSetContext ctx)
}
else if ("bitfield".equals(recordType))
{
renderBitfield(ctx);
renderBitField(ctx);
}

return null;
}

private void renderStructure(SamXParser.RecordSetContext ctx)
class StructureDefinition
{
structureMembers = new ArrayList<>();
final int unitWidth;
final ArrayList<StructureMember> fields = new ArrayList<>();
final int dwordCount;

int dwordCount = 0;
int bitOffset = 0;
public StructureDefinition(SamXParser.RecordSetContext ctx)
{
RecordSetVisitor visitor = new RecordSetVisitor(getTokenStream());
RecordSetVisitor.RecordSet rs = (RecordSetVisitor.RecordSet) visitor.visitRecordSet(ctx);

final String unitWidthHeader = ctx.headerRow().NAME(0).getText();
final int unitWidth = unitWidths.getOrDefault(unitWidthHeader, 0);
final String unitWidthHeader = rs.getHeader().getAttributes().get(0);
unitWidth = unitWidths.getOrDefault(unitWidthHeader, 0);

for (SamXParser.RecordRowContext rrc : ctx.recordRow())
{
final SamXParser.RecordDataContext rdc = rrc.recordData();
if (rdc != null)
int unitCount = 0;
int bitOffset = 0;

for (SamXParser.RecordRowContext rrc : ctx.recordRow())
{
if (isDisabled(rdc.condition()))
final SamXParser.RecordDataContext rdc = rrc.recordData();
if (rdc != null)
{
continue;
}
if (isDisabled(rdc.condition()))
{
continue;
}

StructureMember sm = new StructureMember(rdc, bitOffset, unitWidth);
StructureMember sm = new StructureMember(rdc, unitCount, bitOffset, unitWidth);

bitOffset += sm.width;
if (bitOffset == 32)
{
bitOffset = 0;
}
bitOffset += sm.width;
if (bitOffset == 32)
{
bitOffset = 0;
}

structureMembers.add(sm);
if (sm.unitOffset > dwordCount)
{
dwordCount = sm.unitOffset;
structureMembers.add(sm);
if (sm.unitOffset > unitCount)
{
unitCount = sm.unitOffset;
}
}
}

this.dwordCount = unitCount;
}
}


private void renderStructure(SamXParser.RecordSetContext ctx)
{
StructureDefinition sd = new StructureDefinition(ctx);

ST structure = cppGroup.getInstanceOf("/structure");
AttributeVisitor attributes = getAttributes(ctx.blockMetadata().metadata());

structure.add("name", attributes.getId());
structure.add("unitWidth", unitWidth);
structure.add("unitWidth", sd.unitWidth);
structure.add("description", getPlainText(ctx.blockMetadata().description));
structure.add("fields", structureMembers);
structure.add("size", dwordCount + 1);
structure.add("size", sd.dwordCount + 1);

structures.add(structure.render());

// reset structure
structureMembers = new ArrayList<>();
}

private enum FieldIndices
Expand Down Expand Up @@ -353,7 +382,26 @@ public String getDescription()

private String computeNameFromDescription(String description)
{
return description.replace(' ', '_').replace('/', '_');
StringBuilder sb = new StringBuilder();
for (char ch: description.toCharArray())
{
switch (ch)
{
case ' ':
case '/':
sb.append('_');
break;

case '\'':
case '.':
break;

default:
sb.append(ch);
break;
}
}
return sb.toString();
}

class BitField
Expand Down Expand Up @@ -477,7 +525,7 @@ public BitFieldDefinition(SamXParser.RecordSetContext ctx)
RecordSetVisitor visitor = new RecordSetVisitor(getTokenStream());
RecordSetVisitor.RecordSet rs = (RecordSetVisitor.RecordSet) visitor.visitRecordSet(ctx);

final String unitWidthHeader = ctx.headerRow().NAME(0).getText();
final String unitWidthHeader = rs.getHeader().getAttributes().get(0);
unitWidth = unitWidths.getOrDefault(unitWidthHeader, 0);

for (RecordSetVisitor.RecordDataGroup rdg : rs.getGroups())
Expand All @@ -497,7 +545,7 @@ public BitFieldDefinition(SamXParser.RecordSetContext ctx)
}
}

private void renderBitfield(SamXParser.RecordSetContext ctx)
private void renderBitField(SamXParser.RecordSetContext ctx)
{
BitFieldDefinition bfd = new BitFieldDefinition(ctx);

Expand Down
13 changes: 12 additions & 1 deletion src/main/java/net/signbit/samx/visitors/RecordSetVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class AST

}

class RecordHeader extends AST
public class RecordHeader extends AST
{
final ArrayList<String> attributes;
boolean hasTrailingBar = false;
Expand All @@ -52,6 +52,11 @@ class RecordHeader extends AST
hasTrailingBar = true;
}
}

public ArrayList<String> getAttributes()
{
return attributes;
}
}

public class RecordData extends AST
Expand Down Expand Up @@ -234,6 +239,12 @@ public ArrayList<RecordDataGroup> getGroups()
{
return groups;
}

public RecordHeader getHeader()
{
return header;
}

}

public RecordSetVisitor(BufferedTokenStream tokenStream)
Expand Down
50 changes: 46 additions & 4 deletions src/main/resources/net/signbit/samx/literate/cpp_header.stg
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,36 @@ document(filename, guard, namespace, enumerations, bitFields, structures, trueFl
namespace <namespace>
{

namespace impl
{

constexpr uint16_t htons(uint16_t sh)
{
return (sh \>> 8U) | (sh \<\< 8U);
}

constexpr uint32_t htonl(uint32_t lo)
{
return (
((lo & 0x000000FFU) \<\< 24U) |
((lo & 0x0000FF00U) \<\< 8U) |
((lo & 0xFF000000U) \>> 24U) |
((lo & 0x00FF0000U) \>> 8U)
);
}

constexpr uint16_t ntohs(uint16_t sh)
{
return impl::htons(sh);
}

constexpr uint32_t ntohl(uint32_t lo)
{
return impl::htonl(lo);
}

} // namespace impl

<bitFields>

<enumerations>
Expand All @@ -40,7 +70,7 @@ class <name>
{
public:

constexpr explicit <name>(uint<unitWidth>_t data) : m_data{data}
constexpr explicit <name>(uint<unitWidth>_t data = 0U) : m_data{data}
{
}

Expand Down Expand Up @@ -155,18 +185,30 @@ fieldDecl(field) ::= <<
*/
constexpr void set<field.field>(<field.type> val)
{
<if(field.word)>
m_data[<field.unitOffset>] = impl::htonl(val);
<else>
const auto mask = (uint<unitWidth>_t(1U) \<\< <field.width>U) - uint<unitWidth>_t(1U);
assert(<if(field.native)>val<else>uint<unitWidth>_t(val)<endif> \<= mask);

const auto shiftedMask = mask \<\< <field.bitOffset>U;
const auto fieldShift = <unitWidth>U - <field.width>U - <field.bitOffset>U;

const auto shiftedMask = mask \<\< fieldShift;

m_data[<field.unitOffset>] = (m_data[<field.unitOffset>] & (~shiftedMask)) | (<if(field.native)>val<else>uint<unitWidth>_t(val)<endif> \<\< <field.bitOffset>U);
m_data[<field.unitOffset>] = impl::htonl((impl::ntohl(m_data[<field.unitOffset>]) & (~shiftedMask)) | (<if(field.native)>val<else>uint<unitWidth>_t(val)<endif> \<\< fieldShift));
<endif>
}

constexpr <field.type> get<field.field>() const
{
<if(field.word)>
return impl::ntohl(m_data[<field.unitOffset>]);
<else>
const auto mask = (uint<unitWidth>_t(1U) \<\< <field.width>U) - uint<unitWidth>_t(1U);
return <field.type>((m_data[<field.unitOffset>] \>> <field.bitOffset>U) & mask);
const auto fieldShift = <unitWidth>U - <field.width>U - <field.bitOffset>U;

return <field.type>((impl::ntohl(m_data[<field.unitOffset>]) \>> fieldShift) & mask);
<endif>
}

>>
Loading

0 comments on commit 3b75921

Please sign in to comment.