uses HWI
const byte OBJ_VERSION = 7
const byte OS_TYPE = 1
const byte TYPE_NULL = 0
const byte TYPE_LITERAL = 1
const byte TYPE_PATTERN = 2
const byte TYPE_FUNCTION = 3
const byte TYPE_UNUSED_D = 4
const byte TYPE_OBJECT = 5
const byte TYPE_DATA = 6
const byte TYPE_ARRAY = 7
const byte TYPE_VAR = 8
const byte TYPE_UNUSED_C = 9
const byte TYPE_EVENTSOURCE = 10
const byte TYPE_UNUSED_A = 11
const byte TYPE_UNUSED_B = 12
const byte TYPE_PTRH = 13
const byte TYPE_DECIMAL = 14
const byte F_RECURSE_POINT = 128 //TODO: this is a shared flag with OpParser, we need to surface this in a public type
data DanaCommonHeader {
const byte OBJECT_MAGIC[] = new byte[](0x44, 0x41, 0x4E, 0x41, 0x0, 0x1)
byte magic[6]
byte checksum[4] //optional (if it's 0 then it's not configured for this object)
byte objectType[2] //byte 1 is OBJECT_TYPE_X; byte 2 is unused
byte hostType[2] //byte 1 is address-size; byte 2 is endianness?
byte vpuType[2] //VM architecture code indicating which architecture this object was compiled for; this must match the VM's own vpuType code (basically it indicates that all of the instructions are in the expected places and the instruction set itself is compatible)
}
data DanaMachineHeader64 {
//machine code
int8 textOffset
int8 textSize
//local relocations; a list of addresses to add the start address of this object to
int8 lrTableOffset
int8 lrTableSize
int8 lrTableCount
//infoSections: offset to the first extended infoSection, if any (0 is none)
int8 infoSectionsOffset
int8 infoSectionsSize
int8 infoSectionsCount
}
data DanaMachineHeader32 {
//machine code
int4 textOffset
int4 textSize
//local relocations; a list of addresses to add the start address of this object to
int4 lrTableOffset
int4 lrTableSize
int4 lrTableCount
//infoSections: offset to the first extended infoSection, if any (0 is none)
int4 infoSectionsOffset
int4 infoSectionsSize
int4 infoSectionsCount
}
data SourceHeader {
int componentSize
int objectDefinitions
int bindportDefinitions
int objectsCount
int bindportsCount
int classInitFunction //void f() to initialise class/static globals
int classStateSpec //points to a DanaType
int typeMappings //points to an array of integers, each of which points at a typelink
int typeMappingsCount
int sourceNameOffset
int2 capabilities //if this component has any special capabilities (unused)
}
data RelocationRecord {
int addr
}
data TypeOffset {
char name[]
int offset
int fieldsOffset
}
data DanaTypeRecord {
int1 typeClass
const byte F_BOOL = 1
const byte F_CHAR = 2
const byte F_GC_NOCYCLE = 128
int1 flags
int esize
int fieldsOffset
int fieldCount
}
//an info section header
data DanaInfoSection64{
byte sectionType[4] //type code identifying the section's purpose (0.x.x.x, D.N.x.x, F.R.x.x are reserved)
byte contentType[4] //type code identifying the kind of content (json, xml, jpeg, etc.)
int8 size //size of the section's content, excluding this header
}
data DanaInfoSection32{
byte sectionType[4] //type code identifying the section's purpose (0.x.x.x, D.N.x.x, F.R.x.x are reserved)
byte contentType[4] //type code identifying the kind of content (json, xml, jpeg, etc.)
int4 size //size of the section's content, excluding this header
}
data ConInt64 {
int8 value
}
data ConInt32 {
int4 value
}
data StringTable {
int offset
char str[]
}
data Relocation {
int offset
}
component provides EnvelopeWriter requires data.adt.List, data.StringBuilder, data.query.Search search, data.StringUtil stringUtil, data.IntUtil iu, io.Output out, DNCUtil dncUtil {
int addressWidth
bool evenAddressLock = true
byte targetEndianMode = EnvelopeWriter.EM_BIG
byte myEndianMode = EnvelopeWriter.EM_BIG //Dana is always EM_BIG, so this is redundant, but here as a potential future config option
byte osType = OS_TYPE
int LIVE_TYPE_FIELD_COUNT = 4
int LIVE_POINTER_FIELD_COUNT = 2
int LIVE_BINDPOINT_FIELD_COUNT = 6
int LIVE_INTERFACE_FIELD_COUNT = LIVE_BINDPOINT_FIELD_COUNT + 1
int LIVE_OBJECT_SPEC_FIELD_COUNT = 8
int LIVE_BINDPORT_FIELD_COUNT = LIVE_BINDPOINT_FIELD_COUNT + 8
int LIVE_COMPONENT_FIELD_COUNT = LIVE_POINTER_FIELD_COUNT + 14
int LIVE_VFRAME_FIELD_COUNT = 18
int VFRAME_HEADER_FIELD_COUNT = 11
bool EAL_PATTERNS = true
List relocations
SourceHeader sourceHdr = new SourceHeader()
char sourceName[]
bool firstWrite = true
int fileTextOffset
int fileTextSize
int fileNNITableOffset
int fileLiteralsOffset
int fileRelocationsOffset
int fileRelocationsSize
int fileRelocationsCount
int fileInfoSectionsOffset
int fileInfoSectionsCount
int fileInfoSectionsSize
int fileTypeMappingsOffset
int fileInfoStaticStateOffset
TypeOffset typeOffsetList[]
TypeMapping typeMappings[]
EnvelopeWriter:EnvelopeWriter(char name[], int aw, opt byte emode, byte ost)
{
relocations = new List()
sourceName = name
addressWidth = aw
if (isset emode) targetEndianMode = emode
if (isset ost) osType = ost
}
int getLiveTypeSize()
{
return addressWidth * LIVE_TYPE_FIELD_COUNT
}
int getLivePointerSize()
{
return addressWidth * LIVE_POINTER_FIELD_COUNT
}
int getLiveComponentSize()
{
return addressWidth * LIVE_COMPONENT_FIELD_COUNT
}
int getLiveObjectSpecSize()
{
return addressWidth * LIVE_OBJECT_SPEC_FIELD_COUNT
}
int getLiveInterfaceSize()
{
return addressWidth * LIVE_INTERFACE_FIELD_COUNT
}
int getLiveBindportSize()
{
return addressWidth * LIVE_BINDPORT_FIELD_COUNT
}
int getVFrameSize()
{
return addressWidth * LIVE_VFRAME_FIELD_COUNT
}
int getVFrameHeaderSize()
{
return addressWidth * VFRAME_HEADER_FIELD_COUNT
}
bool isByteAlignedType(DanaType t)
{
return t.class == DanaType.INTERFACE || t.class == DanaType.DATA || (t.class == DanaType.ARRAY && t.storageSize == 0)
}
int translateTypeClass(int class)
{
if (class == DanaType.INTEGER)
{
return TYPE_LITERAL
}
else if (class == DanaType.DECIMAL)
{
return TYPE_DECIMAL
}
else if (class == DanaType.DATA)
{
return TYPE_DATA
}
else if (class == DanaType.INTERFACE)
{
return TYPE_OBJECT
}
else if (class == DanaType.ARRAY)
{
return TYPE_ARRAY
}
else if (class == DanaType.VAR)
{
return TYPE_VAR
}
return TYPE_NULL
}
int getTypeSize(DanaType t, DanaType types[])
{
if (t.class == DanaType.INTERFACE || t.class == DanaType.DATA || (t.class == DanaType.ARRAY && t.storageSize == 0))
{
return getLivePointerSize()
}
else if (t.class == DanaType.ARRAY)
{
//TODO: fixed-length multi-dimensional arrays, where we need to multiply-up the storage size...?
DanaType arType = types.findFirst(DanaType.[name], new DanaType(name = t.fields[0].type))
return (arType.storageSize * t.storageSize)
}
else
{
return t.storageSize
}
}
int addressAlign(File fd)
{
if (evenAddressLock)
{
int pos = fd.getPos()
int rm = 0
if (pos % addressWidth != 0)
rm = addressWidth - (pos % addressWidth)
int tot = rm
byte pb = 0
while (rm > 0)
{
fd.write(pb)
rm --
}
return tot
}
return 0
}
byte[] endianSwap(byte bytes[])
{
if (myEndianMode != targetEndianMode)
{
byte result[] = new byte[bytes.arrayLength]
int rindex = result.arrayLength - 1
for (int i = 0; i < result.arrayLength; i++)
{
result[rindex - i] = bytes[i]
}
return result
}
else
{
return bytes
}
}
void setConValue(ConInt32 v32, ConInt64 v64, int8 value)
{
if (addressWidth == 8)
v64.value = value
else if (addressWidth == 4)
v32.value = value
}
char[] getStringNT(char str[])
{
char res[] = new char[str.arrayLength + 1]
res =[] str
return res
}
int getPatternStorageSize(DanaType t, DanaType types[])
{
int total = 0
for (int i = 0; i < t.fields.arrayLength; i ++)
{
if (t.fields[i].qualifier != "constant")
{
//DanaType fieldType = types.findFirst(DanaType.[name], new DanaType(name = t.fields[i].type))
DanaType fieldType = dncUtil.findType(types, t.fields[i].type)
if (fieldType == null)
{
throw new Exception("unknown/null field type of $(t.fields[i].type) in type '$(t.name)'")
}
if (fieldType.class == DanaType.DATA
|| (fieldType.class == DanaType.ARRAY && fieldType.storageSize == 0)
|| fieldType.class == DanaType.INTERFACE)
{
total += getLivePointerSize()
}
else if (fieldType.class == DanaType.ARRAY)
{
//TODO: fixed-length multi-dimensional arrays, where we need to multiply-up the storage size...?
//DanaType arType = types.findFirst(DanaType.[name], new DanaType(name = fieldType.fields[0].type))
DanaType arType = dncUtil.findType(types, fieldType.fields[0].type)
total += (arType.storageSize * fieldType.storageSize)
}
else
{
total += fieldType.storageSize
}
if (evenAddressLock && isByteAlignedType(fieldType))
{
if (total % addressWidth != 0)
{
total += (addressWidth - (total % addressWidth))
}
}
}
}
return total
}
int getFieldCount(DanaType t)
{
int result = 0
for (int i = 0; i < t.fields.arrayLength; i++)
{
if (t.fields[i].qualifier != "constant")
result ++
}
return result
}
void writeCommonHeader(File fd)
{
//DanaCommonHeader hdr = new DanaCommonHeader(DanaCommonHeader.OBJECT_MAGIC, null, null, new byte[](8, 1), new byte[](OS_TYPE, OBJ_VERSION)) //TODO: this line causes a runtime segfault!
DanaCommonHeader hdr = new DanaCommonHeader()
hdr.magic = DanaCommonHeader.OBJECT_MAGIC
hdr.hostType[0] = addressWidth
hdr.hostType[1] = 1
hdr.vpuType[0] = osType
hdr.vpuType[1] = OBJ_VERSION
fd.write(dana.serial(hdr))
}
void writeMachineHeader(File fd)
{
if (addressWidth == 8)
{
DanaMachineHeader64 hdr = new DanaMachineHeader64()
//machine code
hdr.textOffset = fileTextOffset
hdr.textSize = fileTextSize
//local relocations; a list of addresses to add the start address of this object to
hdr.lrTableOffset = fileRelocationsOffset
hdr.lrTableSize = fileRelocationsSize
hdr.lrTableCount = fileRelocationsCount
//infoSections: offset to the first extended infoSection, if any (0 is none)
hdr.infoSectionsOffset = fileInfoSectionsOffset //TODO: we need DNIL for load to work properly...(see how util.ObjectFile does this?)
hdr.infoSectionsSize = fileInfoSectionsSize
hdr.infoSectionsCount = fileInfoSectionsCount
fd.write(dana.serial(hdr))
}
else if (addressWidth == 4)
{
DanaMachineHeader32 hdr = new DanaMachineHeader32()
//machine code
hdr.textOffset = fileTextOffset
hdr.textSize = fileTextSize
//local relocations; a list of addresses to add the start address of this object to
hdr.lrTableOffset = fileRelocationsOffset
hdr.lrTableSize = fileRelocationsSize
hdr.lrTableCount = fileRelocationsCount
//infoSections: offset to the first extended infoSection, if any (0 is none)
hdr.infoSectionsOffset = fileInfoSectionsOffset //TODO: we need DNIL for load to work properly...(see how util.ObjectFile does this?)
hdr.infoSectionsSize = fileInfoSectionsSize
hdr.infoSectionsCount = fileInfoSectionsCount
fd.write(dana.serial(hdr))
}
}
int getTotalComponentSize(OpParseResult parseResult, DanaType types[])
{
int objectsSize = 0
for (int i = 0; i < parseResult.providedObjects.arrayLength; i++)
{
objectsSize += getLiveObjectSpecSize()
objectsSize += getLiveInterfaceSize() * parseResult.providedObjects[i].interfaces.arrayLength
}
return getLiveComponentSize() + objectsSize + (getLiveBindportSize() * parseResult.requiredInterfaces.arrayLength) + getPatternStorageSize(parseResult.staticGlobals, types)
}
void writeComponentSourceHeader(File fd, char name[], OpParseResult parseResult, DanaType types[], LiteralsTable literals, int textOffset, int classInitOffset, List reloc)
{
//SourceHeader hdr = new SourceHeader()
//hdr.componentSize = getTotalComponentSize(parseResult, types)
//hdr.objectDefinitions = sourceHdr.objectDefinitions
//hdr.bindportDefinitions = sourceHdr.bindportDefinitions
//hdr.objectsCount = parseResult.providedObjects.arrayLength
//hdr.bindportsCount = parseResult.requiredInterfaces.arrayLength
//hdr.classInitFunction = 0 //TODO
//hdr.classStateSpec = 0 //TODO
//hdr.typeMappings = 0 //TODO
//hdr.typeMappingsCount = 0 //TODO
//hdr.sourceNameOffset = fileLiteralsOffset + getLiteralOffset(literals, getStringNT(name))
//hdr.capabilities = 0
//fd.write(dana.serial(hdr))
//this header is written host-endian
ConInt64 con64 = new ConInt64()
ConInt32 con32 = new ConInt32()
byte conBytes[] = null
if (addressWidth == 8)
conBytes = dana.serial(con64)
else if (addressWidth == 4)
conBytes = dana.serial(con32)
setConValue(con32, con64, getTotalComponentSize(parseResult, types))
fd.write(endianSwap(conBytes))
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, sourceHdr.objectDefinitions)
fd.write(endianSwap(conBytes))
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, sourceHdr.bindportDefinitions)
fd.write(endianSwap(conBytes))
setConValue(con32, con64, parseResult.providedObjects.arrayLength)
fd.write(endianSwap(conBytes))
setConValue(con32, con64, parseResult.requiredInterfaces.arrayLength)
fd.write(endianSwap(conBytes))
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, classInitOffset)
fd.write(endianSwap(conBytes))
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, fileInfoStaticStateOffset)
fd.write(endianSwap(conBytes))
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, fileTypeMappingsOffset)
fd.write(endianSwap(conBytes))
setConValue(con32, con64, typeMappings.arrayLength)
fd.write(endianSwap(conBytes))
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, literals.getOffsetOf(getStringNT(name)))
fd.write(endianSwap(conBytes))
setConValue(con32, con64, 0)
fd.write(endianSwap(conBytes))
}
void writeNNITable(File fd, int textOffset)
{
if (addressWidth == 8)
{
int8 table[] = new int8[256]
fd.write(dana.serial(table))
}
else if (addressWidth == 4)
{
int4 table[] = new int4[256]
fd.write(dana.serial(table))
}
}
void writeDanaType(File fd, int textOffset, byte class, byte flags, int size, int fieldsOffset, int fieldsCount, List reloc)
{
ConInt64 con64 = new ConInt64()
ConInt32 con32 = new ConInt32()
byte conBytes[] = null
if (addressWidth == 8)
conBytes = dana.serial(con64)
else if (addressWidth == 4)
conBytes = dana.serial(con32)
fd.write(class)
fd.write(flags)
addressAlign(fd)
setConValue(con32, con64, size)
fd.write(endianSwap(conBytes))
//relocation entry
if (fieldsCount != 0 && reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, fieldsOffset)
fd.write(endianSwap(conBytes))
setConValue(con32, con64, fieldsCount)
fd.write(endianSwap(conBytes))
}
void writeDanaTypeField(File fd, StringTable strTable, char name[], int textOffset, int typeOffset, List reloc)
{
ConInt64 con64 = new ConInt64()
ConInt32 con32 = new ConInt32()
byte conBytes[] = null
byte b = 0
if (addressWidth == 8)
conBytes = dana.serial(con64)
else if (addressWidth == 4)
conBytes = dana.serial(con32)
//DanaTypeField.type
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, typeOffset)
fd.write(endianSwap(conBytes))
if (strTable != null && name != null)
{
//DanaTypeField.fieldName
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
//setConValue(con32, con64, strTable.offset + strTable.str.find(name))
setConValue(con32, con64, strTable.offset + dncUtil.findString(strTable.str, name))
fd.write(endianSwap(conBytes))
//DanaTypeField.fieldNameLength
setConValue(con32, con64, name.arrayLength)
fd.write(endianSwap(conBytes))
}
else
{
//DanaTypeField.fieldName
setConValue(con32, con64, 0)
fd.write(conBytes)
//DanaTypeField.fieldNameLength
setConValue(con32, con64, 0)
fd.write(conBytes)
}
//DanaTypeField.flags
fd.write(b)
addressAlign(fd)
//DanaTypeField.offset
setConValue(con32, con64, 0)
fd.write(conBytes)
}
VariableRef[] writeDanaTypeFields(File fd, StringTable strTable, int textOffset, DanaType type, DanaType types[], TypeOffset offsets[], List reloc)
{
ConInt64 con64 = new ConInt64()
ConInt32 con32 = new ConInt32()
byte conBytes[] = null
if (addressWidth == 8)
conBytes = dana.serial(con64)
else if (addressWidth == 4)
conBytes = dana.serial(con32)
int offset = 0
//out.println("writing fields of type $(type.name)")
VariableRef result[] = new VariableRef[type.fields.arrayLength]
for (int i = 0; i < type.fields.arrayLength; i++)
{
if (type.fields[i].qualifier != "constant")
{
int fieldTypeAddr = 0
//DanaType fieldType = types.findFirst(DanaType.[name], new DanaType(name = type.fields[i].type))
DanaType fieldType = dncUtil.findType(types, type.fields[i].type)
TypeOffset fieldTypeOffset = offsets.findFirst(TypeOffset.[name], new TypeOffset(fieldType.name))
//in the first pass, offset may not exist for the field (as it hasn't been written out yet)
if (fieldTypeOffset != null)
fieldTypeAddr = fieldTypeOffset.offset
//out.println(" - write field type $(fieldType.name), offset $(fieldTypeAddr) ($(fieldTypeAddr-textOffset)), offset-in $(offset), storage-size $(fieldType.storageSize)")
if (EAL_PATTERNS)
{
if (evenAddressLock && isByteAlignedType(fieldType))
{
//out.println(" - considering offset adjustment for $(offset % addressWidth)")
if ((offset % addressWidth) != 0)
{
offset += (addressWidth - (offset % addressWidth))
//out.println(" - offset adjustment made, to $(offset)")
}
}
}
int vsize = getTypeSize(fieldType, types)
//DanaTypeField.type
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, fieldTypeAddr)
fd.write(endianSwap(conBytes))
if (strTable != null && (type.class == TYPE_DATA || type.class == TYPE_FUNCTION || type.class == TYPE_EVENTSOURCE))
{
//printf("NAME: %s\n", fields -> name);
//DanaTypeField.fieldName
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
//setConValue(con32, con64, strTable.offset + strTable.str.find(type.fields[i].name))
setConValue(con32, con64, strTable.offset + dncUtil.findString(strTable.str, type.fields[i].name))
fd.write(endianSwap(conBytes))
//DanaTypeField.fieldNameLength
setConValue(con32, con64, type.fields[i].name.arrayLength)
fd.write(endianSwap(conBytes))
}
else
{
//DanaTypeField.fieldName
setConValue(con32, con64, 0)
fd.write(conBytes)
//DanaTypeField.fieldNameLength
setConValue(con32, con64, 0)
fd.write(conBytes)
}
//DanaTypeField.flags
byte b = 0
if ((type.fields[i].flags & F_RECURSE_POINT) == F_RECURSE_POINT)
b |= 0x1
if (type.fields[i].qualifier.find("store") != StringUtil.NOT_FOUND)
b |= 0x2
if (type.fields[i].qualifier.find("opt") != StringUtil.NOT_FOUND)
b |= 0x4
fd.write(b)
addressAlign(fd)
//DanaTypeField.offset
setConValue(con32, con64, offset)
fd.write(endianSwap(conBytes))
result[i] = new VariableRef(fieldTypeAddr, offset, translateTypeClass(fieldType.class))
offset += vsize
}
}
return result
}
int writeDanaObjectType(File fd, StringTable strTable, int textOffset, DanaType type, DanaType types[], TypeOffset offsets[], List reloc)
{
int fieldsOffset
int fieldCount
//out.println("write object type $(type.name)")
//write all functions
int functionOffsets[]
for (int i = 0; i < type.fields.arrayLength; i++)
{
//DanaType fieldType = types.findFirst(DanaType.[name], new DanaType(name = type.fields[i].type))
DanaType fieldType = dncUtil.findType(types, type.fields[i].type)
TypeOffset fieldTypeOffset = offsets.findFirst(TypeOffset.[name], new TypeOffset(fieldType.name))
if (fieldType.class == DanaType.FUNCTION)
{
functionOffsets = new int[](functionOffsets, fd.getPos() - textOffset)
fieldsOffset = (fd.getPos() - textOffset) + getLiveTypeSize()
fieldCount = fieldType.fields.arrayLength
//out.println(" - write function type $(fieldType.name)")
byte flags = 0
//if (fieldType.isConstructor) flags = 2 //TODO (isn't this just a naming equivalence check??)
writeDanaType(fd, textOffset, TYPE_FUNCTION, flags, getPatternStorageSize(fieldType, types), fieldsOffset, fieldCount, reloc)
writeDanaTypeFields(fd, strTable, textOffset, fieldType, types, offsets, reloc)
}
}
fieldsOffset = (fd.getPos() - textOffset) + getLiveTypeSize()
fieldCount = functionOffsets.arrayLength// + t -> object -> eventSourcesCount;
int functionListTypeOffset = (fd.getPos() - textOffset)
writeDanaType(fd, textOffset, TYPE_DATA, 0, type.storageSize, fieldsOffset, fieldCount, reloc)
// (fields)
int j = 0
for (int i = 0; i < type.fields.arrayLength; i++)
{
//DanaType fieldType = types.findFirst(DanaType.[name], new DanaType(name = type.fields[i].type))
DanaType fieldType = dncUtil.findType(types, type.fields[i].type)
TypeOffset fieldTypeOffset = offsets.findFirst(TypeOffset.[name], new TypeOffset(fieldType.name))
if (fieldType.class == DanaType.FUNCTION)
{
writeDanaTypeField(fd, strTable, type.fields[i].name, textOffset, functionOffsets[j], reloc)
j ++
}
}
//write all events
int eventOffsets[]
for (int i = 0; i < type.fields.arrayLength; i++)
{
//DanaType fieldType = types.findFirst(DanaType.[name], new DanaType(name = type.fields[i].type))
DanaType fieldType = dncUtil.findType(types, type.fields[i].type)
TypeOffset fieldTypeOffset = offsets.findFirst(TypeOffset.[name], new TypeOffset(fieldType.name))
if (fieldType.class == DanaType.EVENT)
{
eventOffsets = new int[](eventOffsets, fd.getPos() - textOffset)
fieldsOffset = (fd.getPos() - textOffset) + getLiveTypeSize()
fieldCount = fieldType.fields.arrayLength
byte flags = 0
writeDanaType(fd, textOffset, TYPE_EVENTSOURCE, flags, getPatternStorageSize(fieldType, types), fieldsOffset, fieldCount, reloc)
writeDanaTypeFields(fd, strTable, textOffset, fieldType, types, offsets, reloc)
}
}
fieldsOffset = (fd.getPos() - textOffset) + getLiveTypeSize()
fieldCount = eventOffsets.arrayLength
int eventListTypeOffset = (fd.getPos() - textOffset)
writeDanaType(fd, textOffset, TYPE_DATA, 0, type.storageSize, fieldsOffset, fieldCount, reloc)
// (fields)
int qi = 0
for (int i = 0; i < type.fields.arrayLength; i++)
{
//DanaType fieldType = types.findFirst(DanaType.[name], new DanaType(name = type.fields[i].type))
DanaType fieldType = dncUtil.findType(types, type.fields[i].type)
TypeOffset fieldTypeOffset = offsets.findFirst(TypeOffset.[name], new TypeOffset(fieldType.name))
if (fieldType.class == DanaType.EVENT)
{
writeDanaTypeField(fd, strTable, type.fields[i].name, textOffset, eventOffsets[qi], reloc)
qi ++
}
}
//write all transfer fields
int transferListTypeOffset = (fd.getPos() - textOffset)
fieldsOffset = (fd.getPos() - textOffset) + getLiveTypeSize()
fieldCount = 0
for (int i = 0; i < type.fields.arrayLength; i++)
{
DanaType fieldType = dncUtil.findType(types, type.fields[i].type)
//DanaType fieldType = types.findFirst(DanaType.[name], new DanaType(name = type.fields[i].type))
TypeOffset fieldTypeOffset = offsets.findFirst(TypeOffset.[name], new TypeOffset(fieldType.name))
if (fieldType.class != DanaType.FUNCTION && fieldType.class != DanaType.EVENT && type.fields[i].qualifier == "transfer")
{
fieldCount ++
}
}
writeDanaType(fd, textOffset, TYPE_DATA, 0, type.storageSize, fieldsOffset, fieldCount, reloc)
// (fields)
for (int i = 0; i < type.fields.arrayLength; i++)
{
//DanaType fieldType = types.findFirst(DanaType.[name], new DanaType(name = type.fields[i].type))
DanaType fieldType = dncUtil.findType(types, type.fields[i].type)
TypeOffset fieldTypeOffset = offsets.findFirst(TypeOffset.[name], new TypeOffset(fieldType.name))
if (fieldType.class != DanaType.FUNCTION && fieldType.class != DanaType.EVENT && type.fields[i].qualifier == "transfer")
{
writeDanaTypeField(fd, strTable, type.fields[i].name, textOffset, fieldTypeOffset.offset, reloc)
}
}
//and finally the object itself, with its fields pointing to the lists of functions / events / transfers
fieldsOffset = (fd.getPos() - textOffset) + getLiveTypeSize()
fieldCount = 3
byte flags = 0
if (type.name == "lang.Proxy") flags = 0x1
if (type.name == "lang.Morph") flags = 0x2
int typeOffset = (fd.getPos() - textOffset)
writeDanaType(fd, textOffset, TYPE_OBJECT, flags, type.storageSize, fieldsOffset, fieldCount, reloc)
writeDanaTypeField(fd, strTable, ".functions", textOffset, functionListTypeOffset, reloc)
writeDanaTypeField(fd, strTable, ".events", textOffset, eventListTypeOffset, reloc)
writeDanaTypeField(fd, strTable, ".state", textOffset, transferListTypeOffset, reloc)
return typeOffset
}
TypeOffset[] writeTypes(File fd, DanaType types[], int textOffset, List reloc)
{
//write all field names to a string table
StringBuilder build = new StringBuilder()
for (int i = 0; i < types.arrayLength; i++)
{
if (types[i].class == DanaType.DATA)
{
for (int j = 0; j < types[i].fields.arrayLength; j++)
{
build.add(types[i].fields[j].name)
}
}
else if (types[i].class == DanaType.INTERFACE)
{
for (int j = 0; j < types[i].fields.arrayLength; j++)
{
build.add(types[i].fields[j].name)
DanaType fieldType = dncUtil.findType(types, types[i].fields[j].type)
if (fieldType.class == DanaType.FUNCTION)
{
for (int n = 0; n < fieldType.fields.arrayLength; n ++)
{
build.add(fieldType.fields[n].name)
}
}
}
}
}
build.add(".functions")
build.add(".events")
build.add(".state")
StringTable strTable = new StringTable(fd.getPos() - textOffset, build.get())
fd.write(strTable.str)
addressAlign(fd)
//write all types, populating the offset list first so it doesn't matter if types and the types of their fields appear out of order
TypeOffset offsets[] = typeOffsetList
if (firstWrite)
{
offsets = new TypeOffset[types.arrayLength]
for (int i = 0; i < types.arrayLength; i++)
{
offsets[i] = new TypeOffset(types[i].name)
}
}
for (int i = 0; i < types.arrayLength; i++)
{
if (firstWrite)
{
TypeOffset tOffset = offsets.findFirst(TypeOffset.[name], new TypeOffset(types[i].name))
tOffset.offset = fd.getPos() - textOffset
}
if (types[i].class == DanaType.INTEGER)
{
byte flags = 0
if (types[i].name == "bool")
flags = DanaTypeRecord.F_BOOL
else if (types[i].name == "char")
flags = DanaTypeRecord.F_CHAR
writeDanaType(fd, textOffset, TYPE_LITERAL, flags, types[i].storageSize, 0, 0, reloc)
}
else if (types[i].class == DanaType.DECIMAL)
{
writeDanaType(fd, textOffset, TYPE_DECIMAL, 0, types[i].storageSize, 0, 0, reloc)
}
else if (types[i].class == DanaType.DATA)
{
byte flags = 0
if (types[i].flags == DanaType.F_NO_CYCLE)
{
flags = DanaTypeRecord.F_GC_NOCYCLE
}
if (firstWrite) offsets[i].fieldsOffset = offsets[i].offset + getLiveTypeSize()
int size = getPatternStorageSize(types[i], types)
writeDanaType(fd, textOffset, TYPE_DATA, flags, size, offsets[i].fieldsOffset, getFieldCount(types[i]), reloc)
writeDanaTypeFields(fd, strTable, textOffset, types[i], types, offsets, reloc)
}
else if (types[i].class == DanaType.ARRAY)
{
byte flags = 0
if (types[i].flags == DanaType.F_NO_CYCLE) flags = DanaTypeRecord.F_GC_NOCYCLE
TypeOffset fieldTypeOffset = offsets.findFirst(TypeOffset.[name], new TypeOffset(types[i].fields[0].type))
if (fieldTypeOffset == null) throw new Exception("array type $(types[i].fields[0].type) not found in offsets table")
//out.println(" - found array type $(types[i].fields[0].type) for $(types[i].name), offset $(fieldTypeOffset.offset)")
if (firstWrite) offsets[i].fieldsOffset = offsets[i].offset + getLiveTypeSize()
writeDanaType(fd, textOffset, TYPE_ARRAY, flags, types[i].storageSize, offsets[i].fieldsOffset, 1, reloc)
writeDanaTypeField(fd, null, null, textOffset, fieldTypeOffset.offset, reloc)
}
else if (types[i].class == DanaType.INTERFACE)
{
int offset = writeDanaObjectType(fd, strTable, textOffset, types[i], types, offsets, reloc)
if (firstWrite) offsets[i].offset = offset
}
}
return offsets
}
void writeInterfaceRecords(File fd)
{
//build a local string table
//write the interface details
//return their offsets
//TODO: re-use writeInterfaceDetails() for this
}
int writeGlobalStateDefinitions(File fd, OpParseResult opr, DanaType types[], TypeOffset typeOffsets[], int textOffset, List reloc)
{
StringBuilder build = new StringBuilder()
for (int i = 0; i < types.arrayLength; i++)
{
if (types[i].class == DanaType.DATA)
{
for (int j = 0; j < types[i].fields.arrayLength; j++)
{
build.add(types[i].fields[j].name)
}
}
else if (types[i].class == DanaType.INTERFACE)
{
for (int j = 0; j < types[i].fields.arrayLength; j++)
{
build.add(types[i].fields[j].name)
}
}
}
StringTable strTable = new StringTable(fd.getPos() - textOffset, build.get())
fd.write(strTable.str)
addressAlign(fd)
int pos = fd.getPos() - textOffset
int fieldsOffset = (fd.getPos() - textOffset) + getLiveTypeSize()
int size = getPatternStorageSize(opr.staticGlobals, types)
writeDanaType(fd, textOffset, TYPE_DATA, 0, size, fieldsOffset, opr.staticGlobals.fields.arrayLength, reloc)
writeDanaTypeFields(fd, strTable, textOffset, opr.staticGlobals, types, typeOffsets, reloc)
return pos
}
void writeFunctionLinks(File fd, ImplementedInterface impIntf, int textOffset, List reloc)
{
ConInt64 con64 = new ConInt64()
ConInt32 con32 = new ConInt32()
byte conBytes[] = null
if (addressWidth == 8)
conBytes = dana.serial(con64)
else if (addressWidth == 4)
conBytes = dana.serial(con32)
//just write the function-implementation offset for every function in this interface, in the correct order
for (int i = 0; i < impIntf.functions.arrayLength; i++)
{
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
//out.println("flink @ $(impIntf.functions[i].offset)")
setConValue(con32, con64, impIntf.functions[i].offset)
fd.write(endianSwap(conBytes))
}
}
void writeInterfaceDetails(File fd, StringTable strTable, char name[], char semantic[], int typeOffset, int functionLinksAddr, int flags, int textOffset, List reloc)
{
ConInt64 con64 = new ConInt64()
ConInt32 con32 = new ConInt32()
byte conBytes[] = null
if (addressWidth == 8)
conBytes = dana.serial(con64)
else if (addressWidth == 4)
conBytes = dana.serial(con32)
// InterfaceDetails.name
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, strTable.offset + strTable.str.find(name))
fd.write(endianSwap(conBytes))
// InterfaceDetails.nameLen
setConValue(con32, con64, name.arrayLength)
fd.write(endianSwap(conBytes))
// InterfaceDetails.type
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, typeOffset)
fd.write(endianSwap(conBytes))
// InterfaceDetails.variantNameLen
setConValue(con32, con64, semantic.arrayLength)
fd.write(endianSwap(conBytes))
// InterfaceDetails.variantName
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, strTable.offset + strTable.str.find(semantic))
fd.write(endianSwap(conBytes))
// InterfaceDetails.functionBindings
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, functionLinksAddr)
fd.write(endianSwap(conBytes))
// InterfaceDetails.flags
setConValue(con32, con64, flags)
fd.write(endianSwap(conBytes))
}
bool hasEventFields(char typeName[], DanaType types[])
{
DanaType t = types.findFirst(DanaType.[name], new DanaType(name = typeName))
for (int i = 0; i < t.fields.arrayLength; i++)
{
DanaType f = types.findFirst(DanaType.[name], new DanaType(name = t.fields[i].type))
if (f.class == DanaType.EVENT) return true
}
return false
}
int writeProvidedObjectDefinitions(File fd, ProvidedObject objects[], ImplementedObject iObjects[], DanaType types[], TypeOffset typeOffsets[], int textOffset, List reloc)
{
ConInt64 con64 = new ConInt64()
ConInt32 con32 = new ConInt32()
byte conBytes[] = null
if (addressWidth == 8)
conBytes = dana.serial(con64)
else if (addressWidth == 4)
conBytes = dana.serial(con32)
//build a local string table
StringBuilder build = new StringBuilder()
for (int i = 0; i < objects.arrayLength; i++)
{
build.add(objects[i].mainInterface)
build.add(objects[i].semantic)
build.add("$(objects[i].mainInterface):$(objects[i].semantic)")
for (int j = 0; j < objects[i].subInterfaces.arrayLength; j ++)
{
build.add(objects[i].subInterfaces[j].string)
}
//TODO: transfer fields?
}
StringTable strTable = new StringTable(fd.getPos() - textOffset, build.get())
fd.write(strTable.str)
addressAlign(fd)
int detailsLinks[] = new int[objects.arrayLength]
//write function links, interface details, and provided object specs
for (int i = 0; i < objects.arrayLength; i ++)
{
int functionLinkBlocks[] = new int[objects[i].subInterfaces.arrayLength + 1]
ImplementedObject iObject = iObjects[i]
for (int j = 0; j < objects[i].interfaces.arrayLength; j++)
{
functionLinkBlocks[j] = fd.getPos() - textOffset
writeFunctionLinks(fd, iObject.interfaces[j], textOffset, reloc)
}
detailsLinks[i] = fd.getPos() - textOffset
TypeOffset typeOffset = typeOffsets.findFirst(TypeOffset.[name], new TypeOffset(objects[i].mainInterface))
if (typeOffset == null) out.println("[error: provided type '$(objects[i].mainInterface)' has no offset]")
//out.println("$(objects[i].mainInterface) intf type offset is $(typeOffset.offset) of $(typeOffset.name)")
char fullName[] = objects[i].mainInterface
if (objects[i].semantic != null)
{
fullName = "$fullName:$(objects[i].semantic)"
}
writeInterfaceDetails(fd, strTable, fullName, objects[i].semantic, typeOffset.offset, functionLinkBlocks[0], 0, textOffset, reloc)
for (int j = 0; j < objects[i].subInterfaces.arrayLength; j++)
{
typeOffset = typeOffsets.findFirst(TypeOffset.[name], new TypeOffset(objects[i].subInterfaces[j].string))
writeInterfaceDetails(fd, strTable, objects[i].subInterfaces[j].string, null, typeOffset.offset, functionLinkBlocks[j+1], 0, textOffset, reloc)
}
}
//write the state specs
int stateLinks[] = new int[objects.arrayLength]
int transferStateLinks[] = new int[objects.arrayLength]
int eventSinkFunctionLinks[] = new int[objects.arrayLength]
for (int i = 0; i < objects.arrayLength; i ++)
{
stateLinks[i] = fd.getPos() - textOffset
int fieldsOffset = (fd.getPos() - textOffset) + getLiveTypeSize()
int size = getPatternStorageSize(objects[i].instanceGlobals, types)
writeDanaType(fd, textOffset, TYPE_DATA, 0, size, fieldsOffset, objects[i].instanceGlobals.fields.arrayLength, reloc)
writeDanaTypeFields(fd, strTable, textOffset, objects[i].instanceGlobals, types, typeOffsets, reloc)
}
for (int i = 0; i < objects.arrayLength; i ++)
{
transferStateLinks[i] = fd.getPos() - textOffset
int fieldsOffset = (fd.getPos() - textOffset) + getLiveTypeSize()
int size = getPatternStorageSize(objects[i].transferState, types)
writeDanaType(fd, textOffset, TYPE_DATA, 0, size, fieldsOffset, objects[i].transferState.fields.arrayLength, reloc)
writeDanaTypeFields(fd, strTable, textOffset, objects[i].transferState, types, typeOffsets, reloc)
}
for (int i = 0; i < objects.arrayLength; i ++)
{
eventSinkFunctionLinks[i] = fd.getPos() - textOffset
//write all the function links, relocated
for (int j = 0; j < objects[i].localFunctions.arrayLength; j++)
{
if (objects[i].localFunctions[j].ftype == OpFunction.EVENTSINK)
{
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, iObjects[i].localFunctions[j].offset)
fd.write(endianSwap(conBytes))
}
}
}
//write the object spec records
int providedObjectsAddr = fd.getPos() - textOffset
for (int i = 0; i < objects.arrayLength; i ++)
{
//StaticObjectSpec.interfaces
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, detailsLinks[i])
fd.write(endianSwap(conBytes))
//StaticObjectSpec.interfacesCount
setConValue(con32, con64, objects[i].subInterfaces.arrayLength + 1)
fd.write(endianSwap(conBytes))
//StaticObjectSpec.objectInitFunction
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, iObjects[i].initFunction.offset) // ?? TODO. (we need to build a separate, internal, list of function offsets, per-prov-object)
fd.write(endianSwap(conBytes))
//StaticObjectSpec.eventDispatchCount
if (hasEventFields(objects[i].mainInterface, types))
setConValue(con32, con64, 1)
else
setConValue(con32, con64, 0)
fd.write(endianSwap(conBytes))
//StaticObjectSpec.eventQueueCount
setConValue(con32, con64, objects[i].eventSinkCount)
fd.write(endianSwap(conBytes))
//StaticObjectSpec.transferStateSpec
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, transferStateLinks[i])
fd.write(endianSwap(conBytes))
//StaticObjectSpec.stateSpec
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, stateLinks[i])
fd.write(endianSwap(conBytes))
//StaticObjectSpec.eventQueueFunctionBindings
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, eventSinkFunctionLinks[i])
fd.write(endianSwap(conBytes))
}
return providedObjectsAddr
}
int writeRequiredInterfaceDefinitions(File fd, RequiredInterface requiredInterfaces[], TypeOffset typeOffsets[], int textOffset, List reloc)
{
//build a local string table
StringBuilder build = new StringBuilder()
for (int i = 0; i < requiredInterfaces.arrayLength; i++)
{
build.add(requiredInterfaces[i].name)
build.add(requiredInterfaces[i].semantic)
build.add("$(requiredInterfaces[i].name):$(requiredInterfaces[i].semantic)")
}
StringTable strTable = new StringTable(fd.getPos() - textOffset, build.get())
fd.write(strTable.str)
addressAlign(fd)
//interface details (re-use the above util function)
int publicBindportsAddr = fd.getPos() - textOffset
for (int i = 0; i < requiredInterfaces.arrayLength; i++)
{
char fullName[] = requiredInterfaces[i].name
if (requiredInterfaces[i].semantic.arrayLength != 0)
{
fullName = "$fullName:$(requiredInterfaces[i].semantic)"
}
TypeOffset typeOffset = typeOffsets.findFirst(TypeOffset.[name], new TypeOffset(requiredInterfaces[i].name))
if (typeOffset == null) out.println("[error: type '$(requiredInterfaces[i].name)' has no offset]")
writeInterfaceDetails(fd, strTable, fullName, requiredInterfaces[i].semantic, typeOffset.offset, 0, requiredInterfaces[i].isNative, textOffset, reloc)
}
return publicBindportsAddr
}
int writeLiteralsTable(File fd, LiteralsTable litTable, int textOffset)
{
int offset = fd.getPos() - textOffset
fd.write(litTable.getBytes())
addressAlign(fd)
return offset
}
void writeTypeMappings(File fd, TypeOffset typeOffsets[], int textOffset, List reloc)
{
ConInt64 con64 = new ConInt64()
ConInt32 con32 = new ConInt32()
byte conBytes[] = null
if (addressWidth == 8)
conBytes = dana.serial(con64)
else if (addressWidth == 4)
conBytes = dana.serial(con32)
fileTypeMappingsOffset = fd.getPos() - textOffset
for (int i = 0; i < typeMappings.arrayLength; i++)
{
//out.println("write index $i type mapping for $(typeMappings[i].name)")
TypeOffset typeOffset = typeOffsets.findFirst(TypeOffset.[name], new TypeOffset(typeMappings[i].name))
int offset = typeOffset.offset
if (reloc != null) reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, offset)
fd.write(endianSwap(conBytes))
}
}
ImplementedObject[] buildImplementedInterfaces(ProvidedObject objects[], DanaType types[])
{
//build a list of function offset records, for all interface and local functions
ImplementedObject iObjects[] = null
for (int i = 0; i < objects.arrayLength; i++)
{
ImplementedObject iObject = new ImplementedObject(objects[i].mainInterface, objects[i].semantic)
iObject.initFunction = new ImplementedFunction(null, objects[i].initFunction)
iObjects = new ImplementedObject[](iObjects, iObject)
//add interface functions
for (int j = 0; j < objects[i].interfaces.arrayLength; j++)
{
ImplementedInterface newIntf = new ImplementedInterface(objects[i].interfaces[j].type)
iObject.interfaces = new ImplementedInterface[](iObject.interfaces, newIntf)
//add the functions
for (int k = 0; k < objects[i].interfaces[j].functions.arrayLength; k++)
{
ImplementedFunction newFunc = new ImplementedFunction(objects[i].interfaces[j].functions[k].name, objects[i].interfaces[j].functions[k])
newIntf.functions = new ImplementedFunction[](newIntf.functions, newFunc)
}
}
//add local functions
for (int j = 0; j < objects[i].localFunctions.arrayLength; j++)
{
ImplementedFunction newFunc = new ImplementedFunction(objects[i].localFunctions[j].name, objects[i].localFunctions[j])
iObject.localFunctions = new ImplementedFunction[](iObject.localFunctions, newFunc)
}
}
return iObjects
}
void collectLiterals(OpToken instructions[], LiteralsTable litTable)
{
for (int i = 0; i < instructions.arrayLength; i++)
{
if (instructions[i].type == HWI.OP_ID_GET_LITERAL_PTR)
{
litTable.add(instructions[i].refValue)
}
collectLiterals(instructions[i].parameters, litTable)
}
}
void buildLiteralTable(OpParseResult result, LiteralsTable litTable)
{
//find all the literal values, from OpTypes.LITERAL token values
for (int i = 0; i < result.providedObjects.arrayLength; i++)
{
for (int j = 0; j < result.providedObjects[i].interfaces.arrayLength; j++)
{
for (int k = 0; k < result.providedObjects[i].interfaces[j].functions.arrayLength; k++)
{
collectLiterals(result.providedObjects[i].interfaces[j].functions[k].instructions, litTable)
litTable.add(getStringNT(result.providedObjects[i].interfaces[j].functions[k].name))
}
}
for (int j = 0; j < result.providedObjects[i].localFunctions.arrayLength; j++)
{
collectLiterals(result.providedObjects[i].localFunctions[j].instructions, litTable)
litTable.add(getStringNT(result.providedObjects[i].localFunctions[j].name))
}
collectLiterals(result.providedObjects[i].initFunction.instructions, litTable)
litTable.add(getStringNT(result.providedObjects[i].initFunction.name))
}
collectLiterals(result.classInitFunction.instructions, litTable)
litTable.add(getStringNT(result.classInitFunction.name))
}
void addTypeMapping(DanaType t)
{
for (int i = 0; i < typeMappings.arrayLength; i++)
{
if (typeMappings[i].name == t.name)
{
return
}
}
typeMappings = new TypeMapping[](typeMappings, new TypeMapping(t.name, typeMappings.arrayLength))
}
void collectTypeMappings(OpToken instructions[])
{
for (int i = 0; i < instructions.arrayLength; i++)
{
if (instructions[i].refType != null)
{
addTypeMapping(instructions[i].refType)
}
collectTypeMappings(instructions[i].parameters)
}
}
void buildTypeMappingTable(OpParseResult result)
{
//find all the literal values, from OpTypes.LITERAL token values
for (int i = 0; i < result.providedObjects.arrayLength; i++)
{
for (int j = 0; j < result.providedObjects[i].interfaces.arrayLength; j++)
{
for (int k = 0; k < result.providedObjects[i].interfaces[j].functions.arrayLength; k++)
{
collectTypeMappings(result.providedObjects[i].interfaces[j].functions[k].instructions)
}
}
for (int j = 0; j < result.providedObjects[i].localFunctions.arrayLength; j++)
{
collectTypeMappings(result.providedObjects[i].localFunctions[j].instructions)
}
collectTypeMappings(result.providedObjects[i].initFunction.instructions)
}
collectTypeMappings(result.classInitFunction.instructions)
}
ImplementedObject[] EnvelopeWriter:prepareEnvelope(OpParseResult parseResult, DanaType types[], LiteralsTable literals)
{
//TODO: build a list of implemented-interfaces, with function names in the right order (expanded/flattened for inherentence), for each ProvidedObject (used by writeProvidedObjectDefinitions())
buildLiteralTable(parseResult, literals)
literals.add(getStringNT(parseResult.classInitFunction.name))
literals.add(getStringNT(sourceName))
buildTypeMappingTable(parseResult)
return buildImplementedInterfaces(parseResult.providedObjects, types)
}
TypeMapping[] EnvelopeWriter:getTypeMappings()
{
return typeMappings
}
bool EnvelopeWriter:writeEnvelope(File ofd, OpParseResult parseResult, ImplementedObject iObjects[], DanaType types[], LiteralsTable literals, TypeTable typeTable, int classInitOffset, bool reloc)
{
//note: passing in a non-null relocations List, to any function, implies "reloc = true"
List buildReloc = relocations
if (!reloc) buildReloc = null
writeCommonHeader(ofd)
writeMachineHeader(ofd)
fileTextOffset = ofd.getPos()
int cshPosition = ofd.getPos()
writeComponentSourceHeader(ofd, sourceName, parseResult, types, literals, fileTextOffset, classInitOffset, buildReloc)
fileNNITableOffset = ofd.getPos() - fileTextOffset
writeNNITable(ofd, fileTextOffset)
TypeOffset typeOffsets[] = writeTypes(ofd, types, fileTextOffset, buildReloc)
writeInterfaceRecords(ofd)
fileInfoStaticStateOffset = writeGlobalStateDefinitions(ofd, parseResult, types, typeOffsets, fileTextOffset, buildReloc)
sourceHdr.objectDefinitions = writeProvidedObjectDefinitions(ofd, parseResult.providedObjects, iObjects, types, typeOffsets, fileTextOffset, buildReloc)
sourceHdr.bindportDefinitions = writeRequiredInterfaceDefinitions(ofd, parseResult.requiredInterfaces, typeOffsets, fileTextOffset, buildReloc)
fileLiteralsOffset = writeLiteralsTable(ofd, literals, fileTextOffset)
writeTypeMappings(ofd, typeOffsets, fileTextOffset, buildReloc)
if (firstWrite)
{
typeOffsetList = typeOffsets
for (int i = 0; i < types.arrayLength; i++)
{
typeTable.add(types[i].name, typeOffsets[i].offset)
}
}
firstWrite = false
literals.setOffset(fileLiteralsOffset)
return true
}
int EnvelopeWriter:getTextOffset()
{
return fileTextOffset
}
int EnvelopeWriter:getNNITableOffset()
{
return fileNNITableOffset
}
int getCoreParamCount(Parameter params[])
{
int result = 0
for (int i = 0; i < params.arrayLength; i++)
{
if ((params[i].qualifier & Parameter.Q_OPT) != Parameter.Q_OPT)
{
result ++
}
}
return result
}
//this function is roughly writeFunctionNNI() from compiler.c
FunctionInfo EnvelopeWriter:writeFrameHeader(File fd, ImplementedFunction function, DanaType types[], LiteralsTable literals, int textOffset)
{
List reloc = relocations
FunctionInfo result = new FunctionInfo()
ConInt64 con64 = new ConInt64()
ConInt32 con32 = new ConInt32()
byte conBytes[] = null
if (addressWidth == 8)
conBytes = dana.serial(con64)
else if (addressWidth == 4)
conBytes = dana.serial(con32)
addressAlign(fd)
//optimiseInstructionStream(f); //TODO??
result.localsReferenceOffset = fd.getPos() - textOffset
//out.println("write frame header for $(function.function.name)")
result.dataContentSize = getPatternStorageSize(function.function.variables, types)
int fieldsOffset = (fd.getPos() - textOffset) + getLiveTypeSize()
int fieldCount = function.function.variables.fields.arrayLength
//out.println("fields-offset $(fieldsOffset)")
writeDanaType(fd, textOffset, TYPE_PATTERN, 0, result.dataContentSize, fieldsOffset, fieldCount, reloc)
result.variables = writeDanaTypeFields(fd, null, textOffset, function.function.variables, types, typeOffsetList, reloc)
//registers
if (result.registerCount == 0) result.registerCount = 1 //bit of a hack to guarantee at least one register for function call returns...
//thread header
result.textOffset = fd.getPos() - textOffset
//patch references to this function, now that its offset is known
int cp = fd.getPos()
for (int j = 0; j < function.references.arrayLength; j++)
{
fd.setPos(function.references[j] + textOffset)
setConValue(con32, con64, result.textOffset)
fd.write(endianSwap(conBytes))
}
fd.setPos(cp)
//f -> scopeCount += 1;
int frameSize = getVFrameSize() + result.dataContentSize
result.codeStart = getVFrameHeaderSize()
// - VFrameHeader -
// VFrameHeader.frameSize
setConValue(con32, con64, frameSize)
fd.write(endianSwap(conBytes))
// VFrameHeader.proxyHeader
setConValue(con32, con64, 0)
fd.write(endianSwap(conBytes))
// VFrameHeader.formalParamsCount
setConValue(con32, con64, function.function.parameters.arrayLength)
fd.write(endianSwap(conBytes))
// VFrameHeader.formalParamsCore
setConValue(con32, con64, getCoreParamCount(function.function.parameters))
fd.write(endianSwap(conBytes))
// VFrameHeader.pcLoc
reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, result.textOffset + result.codeStart)
fd.write(endianSwap(conBytes))
// VFrameHeader.eiiLoc (not used)
result.exPos = fd.getPos()
reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, 8)
fd.write(endianSwap(conBytes))
// VFrameHeader.localsDef
reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, result.localsReferenceOffset)
fd.write(endianSwap(conBytes))
// VFrameHeader.functionName
reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, literals.getOffsetOf(getStringNT(function.name)))
fd.write(endianSwap(conBytes))
// VFrameHeader.xRegisterCount (configured by nni)
reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, 0)
fd.write(endianSwap(conBytes))
reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, 0)
fd.write(endianSwap(conBytes))
reloc.add(new Relocation(fd.getPos() - textOffset))
setConValue(con32, con64, 0)
fd.write(endianSwap(conBytes))
return result
}
void EnvelopeWriter:addRelocations(int list[])
{
for (int i = 0; i < list.arrayLength; i++)
{
relocations.add(new Relocation(list[i]))
}
}
void EnvelopeWriter:writeTextEnd(File fd)
{
addressAlign(fd)
fileTextSize = fd.getPos() - fileTextOffset
}
void EnvelopeWriter:writeRelocations(File fd)
{
ConInt64 con64 = new ConInt64()
ConInt32 con32 = new ConInt32()
byte conBytes[] = null
if (addressWidth == 8)
conBytes = dana.serial(con64)
else if (addressWidth == 4)
conBytes = dana.serial(con32)
fileRelocationsOffset = fd.getPos()
fileRelocationsCount = relocations.getLength()
for (Relocation r = relocations.getFirst(); r != null; r = relocations.getNext())
{
setConValue(con32, con64, r.offset)
fd.write(conBytes)
}
fileRelocationsSize = fd.getPos() - fileRelocationsOffset
}
void EnvelopeWriter:writeInfoSection(File fd, char id[], char contentType[], byte content[])
{
if (fileInfoSectionsOffset == 0) fileInfoSectionsOffset = fd.getPos()
fileInfoSectionsCount ++
if (addressWidth == 8)
{
DanaInfoSection64 dis = new DanaInfoSection64()
dis.sectionType =[] id
dis.contentType =[] contentType
dis.size = content.arrayLength
fd.write(dana.serial(dis))
fd.write(content)
}
else
{
DanaInfoSection32 dis = new DanaInfoSection32()
dis.sectionType =[] id
dis.contentType =[] contentType
dis.size = content.arrayLength
fd.write(dana.serial(dis))
fd.write(content)
}
fileInfoSectionsSize = fd.getPos() - fileInfoSectionsOffset
}
}