uses util.compiler.CodeGen
component provides Compiler requires io.Output out, io.File:mem, System sys, util.compiler.SyntaxParser, util.compiler.OpParser, util.compiler.TypeShaper, util.compiler.EnvelopeWriter, util.compiler.LiteralsTable, util.compiler.TypeTable, util.compiler.CodeGen, util.compiler.DNCUtil dncUtil, io.FileSystem fileSystem, composition.RecursiveLoader rloader {
String myPaths[]
void Compiler:setSearchPaths(store String paths[])
{
myPaths = paths
}
char[] getDefaulTargetOS()
{
if (sys.getPlatform().osCode == "deb")
return "unix"
else if (sys.getPlatform().osCode == "win")
return "windows"
return "unix"
}
char[] getDefaulTargetChip()
{
if (sys.getPlatform().osCode == "x64")
return "x86_64"
else if (sys.getPlatform().osCode == "x86")
return "x86_32"
return "x86-64"
}
int getCallAddress(ProvidedObject po, ImplementedObject io, char impl[], char name[])
{
int res = INT_MAX
if (impl == null)
{
res = dncUtil.findFunctionIndex(po.localFunctions, name)
if (res != INT_MAX) return io.localFunctions[res].offset
for (int j = 0; j < po.interfaces.arrayLength; j++)
{
res = dncUtil.findFunctionIndex(po.interfaces[j].functions, name)
if (res != INT_MAX) return io.interfaces[j].functions[res].offset
}
}
for (int j = 0; j < po.interfaces.arrayLength; j++)
{
if (impl == po.interfaces[j].type)
{
res = dncUtil.findFunctionIndex(po.interfaces[j].functions, name)
if (res != INT_MAX) return io.interfaces[j].functions[res].offset
}
}
throw new Exception("unknown call offset for $impl:$name()")
}
void compileFile(char sourceCode[], char sourceName[], File ofd, String searchPaths[], Code codeHW, byte targetPlatform, int targetAddressWidth, int hwidSet[], CompileResult cres)
{
//parse the given file
SyntaxParser parser = new SyntaxParser(searchPaths, targetAddressWidth)
ParseResult result = parser.parse(sourceCode, sourceName)
DanaToken tree = result.tree
DanaType types[] = parser.getTypes()
for (int i = 0; i < result.errors.arrayLength; i++)
{
cres.errors = new CompileError[](cres.errors, new CompileError(CompileError.ERROR, result.errors[i].file, true, result.errors[i].line, result.errors[i].message))
}
if (result.errors.arrayLength == 0)
{
OpParser opp = new OpParser(targetAddressWidth)
TypeShaper tshape = new TypeShaper()
DanaType flatTypes[] = tshape.shapeTypes(types, tree)
OpParseResult opResult = opp.parse(sourceName, tree, flatTypes)
for (int i = 0; i < opResult.errors.arrayLength; i++)
{
cres.errors = new CompileError[](cres.errors, new CompileError(CompileError.ERROR, opResult.errors[i].file, true, opResult.errors[i].line, opResult.errors[i].message))
}
for (int i = 0; i < opResult.warnings.arrayLength; i++)
{
cres.errors = new CompileError[](cres.errors, new CompileError(CompileError.WARNING, opResult.errors[i].file, true, opResult.errors[i].line, opResult.errors[i].message))
}
if (opResult.errors.arrayLength == 0)
{
//TODO: determine the host's native endianness for parameter 2
EnvelopeWriter env = new EnvelopeWriter(sourceName, targetAddressWidth, EnvelopeWriter.EM_LITTLE, targetPlatform)
LiteralsTable literals = new LiteralsTable()
TypeTable typeTable = new TypeTable()
CodeGen codeGen = new CodeGen()
CGResult cgr = null
//generate object file header information, type table, and literals table
ImplementedObject implObjects[] = rclone env.prepareEnvelope(opResult, flatTypes, literals)
TypeMapping typeMap[] = env.getTypeMappings()
env.writeEnvelope(ofd, opResult, implObjects, flatTypes, literals, typeTable, 0, true)
FunctionInfo initInfo = env.writeFrameHeader(ofd, new ImplementedFunction(opResult.classInitFunction.name, opResult.classInitFunction), types, literals, env.getTextOffset())
cgr = codeGen.generate(ofd, codeHW, opResult.classInitFunction.instructions, flatTypes, literals, typeTable, typeMap, initInfo, env.getTextOffset(), env.getNNITableOffset(), hwidSet)
env.addRelocations(cgr.relocations)
for (int i = 0; i < opResult.providedObjects.arrayLength; i++)
{
CallRefAddress callRefs[] = null
for (int j = 0; j < opResult.providedObjects[i].interfaces.arrayLength; j++)
{
for (int k = 0; k < opResult.providedObjects[i].interfaces[j].functions.arrayLength; k++)
{
FunctionInfo info = env.writeFrameHeader(ofd, implObjects[i].interfaces[j].functions[k], types, literals, env.getTextOffset())
cgr = codeGen.generate(ofd, codeHW, opResult.providedObjects[i].interfaces[j].functions[k].instructions, flatTypes, literals, typeTable, typeMap, info, env.getTextOffset(), env.getNNITableOffset(), hwidSet)
implObjects[i].interfaces[j].functions[k].offset = info.textOffset
env.addRelocations(cgr.relocations)
callRefs = new CallRefAddress[](callRefs, cgr.callRefs)
}
}
for (int j = 0; j < opResult.providedObjects[i].localFunctions.arrayLength; j++)
{
FunctionInfo info = env.writeFrameHeader(ofd, implObjects[i].localFunctions[j], types, literals, env.getTextOffset())
cgr = codeGen.generate(ofd, codeHW, opResult.providedObjects[i].localFunctions[j].instructions, flatTypes, literals, typeTable, typeMap, info, env.getTextOffset(), env.getNNITableOffset(), hwidSet)
implObjects[i].localFunctions[j].offset = info.textOffset
env.addRelocations(cgr.relocations)
callRefs = new CallRefAddress[](callRefs, cgr.callRefs)
}
FunctionInfo info = env.writeFrameHeader(ofd, implObjects[i].initFunction, types, literals, env.getTextOffset())
cgr = codeGen.generate(ofd, codeHW, opResult.providedObjects[i].initFunction.instructions, flatTypes, literals, typeTable, typeMap, info, env.getTextOffset(), env.getNNITableOffset(), hwidSet)
implObjects[i].initFunction.offset = info.textOffset
env.addRelocations(cgr.relocations)
//iterate through local-call references, patching their offset addresses now that we know
for (int j = 0; j < callRefs.arrayLength; j++)
{
int addr = getCallAddress(opResult.providedObjects[i], implObjects[i], callRefs[j].intf, callRefs[j].name)
codeGen.patchCallAddress(ofd, codeHW, callRefs[j].refAddress, addr)
}
}
//note text-end, and write relocations
env.writeTextEnd(ofd)
env.writeRelocations(ofd)
//now re-write the envelope, with function implementation offsets known
ofd.setPos(0)
env.writeEnvelope(ofd, opResult, implObjects, flatTypes, literals, typeTable, initInfo.textOffset, false)
cres.resultCode = CompileResult.OK
ofd.setPos(0)
cres.objectCode = ofd.read(ofd.getSize())
}
else
{
cres.resultCode = CompileResult.ERROR
}
}
else
{
cres.resultCode = CompileResult.ERROR
}
}
CompileResult Compiler:compile(char sourceName[], char sourceCode[])
{
byte osTarget = EnvelopeWriter.OS_LINUX
int addressWidth = 8
char targetOS[] = getDefaulTargetOS()
char targetChip[] = getDefaulTargetChip()
if (targetOS == "ubc")
{
osTarget = EnvelopeWriter.OS_UBC
}
else if (targetOS == "unix")
{
osTarget = EnvelopeWriter.OS_LINUX
}
else if (targetOS == "windows")
{
osTarget = EnvelopeWriter.OS_WINDOWS
}
IDC codeIDC = null
Code codeHW = null
if (fileSystem.exists("$(sys.getDanaHome())/components/util/compiler/hwi/Code_$(targetOS)_$(targetChip).o"))
{
codeIDC = rloader.load("$(sys.getDanaHome())/components/util/compiler/hwi/Code_$(targetOS)_$(targetChip).o").mainComponent
codeHW = new Code() from codeIDC
}
else
{
throw new Exception("no code generation component found for $(targetOS)/$(targetChip)")
}
addressWidth = codeHW.getAddressWidth()
int hwidSet[] = codeHW.getHWIDSupport()
CompileResult cres = new CompileResult()
File ofd = new File:mem("tmp", File.CREATE)
compileFile(sourceCode, sourceName, ofd, myPaths, codeHW, osTarget, addressWidth, hwidSet, cres)
return cres
}
}