mirror of
https://github.com/michaelcmartin/Ophis.git
synced 2024-12-30 10:30:47 +00:00
Improve .incbin to let its arguments be arbitrary expressions
This introduces a new IR node for mutable-during-assembly ranges. In the common case, where offset and range are hardcoded or missing, it continues with the older, more efficient behavior.
This commit is contained in:
parent
9ea0962e52
commit
9323067e91
@ -53,26 +53,43 @@ def pragmaRequire(ppt, line, result):
|
|||||||
def pragmaIncbin(ppt, line, result):
|
def pragmaIncbin(ppt, line, result):
|
||||||
"Includes a binary file"
|
"Includes a binary file"
|
||||||
filename = line.expect("STRING").value
|
filename = line.expect("STRING").value
|
||||||
offset = 0
|
offset = IR.ConstantExpr(0)
|
||||||
size = -1
|
size = None
|
||||||
if str(line.lookahead(0)) == ",":
|
if str(line.lookahead(0)) == ",":
|
||||||
line.pop()
|
line.pop()
|
||||||
offset = line.expect("NUM").value
|
offset = FE.parse_expr(line)
|
||||||
if str(line.lookahead(0)) == ",":
|
if str(line.lookahead(0)) == ",":
|
||||||
line.pop()
|
line.pop()
|
||||||
size = line.expect("NUM").value
|
size = FE.parse_expr(line)
|
||||||
line.expect("EOL")
|
line.expect("EOL")
|
||||||
if type(filename) == str:
|
if type(filename) == str:
|
||||||
try:
|
try:
|
||||||
f = file(os.path.join(FE.context_directory, filename), "rb")
|
f = file(os.path.join(FE.context_directory, filename), "rb")
|
||||||
f.seek(offset)
|
if offset.hardcoded and (size is None or size.hardcoded):
|
||||||
bytes = f.read(size)
|
# We know how big it will be, we can just use the values.
|
||||||
|
if size is None:
|
||||||
|
size = IR.ConstantExpr(-1)
|
||||||
|
f.seek(offset.value())
|
||||||
|
bytes = f.read(size.value())
|
||||||
|
bytes = [IR.ConstantExpr(ord(x)) for x in bytes]
|
||||||
|
result.append(IR.Node(ppt, "Byte", *bytes))
|
||||||
|
else:
|
||||||
|
# offset or length could change based on label placement.
|
||||||
|
# This seems like an unbelievably bad idea, but since we
|
||||||
|
# don't have constant prop it will happen for any symbolic
|
||||||
|
# alias. Don't use symbolic aliases when extracting tiny
|
||||||
|
# pieces out of humongous files, I guess.
|
||||||
|
bytes = f.read()
|
||||||
|
bytes = [IR.ConstantExpr(ord(x)) for x in bytes]
|
||||||
|
if size is None:
|
||||||
|
size = IR.SequenceExpr([IR.ConstantExpr(len(bytes)),
|
||||||
|
"-",
|
||||||
|
offset])
|
||||||
|
result.append(IR.Node(ppt, "ByteRange", offset, size, *bytes))
|
||||||
f.close()
|
f.close()
|
||||||
except IOError:
|
except IOError:
|
||||||
Err.log("Could not read " + filename)
|
Err.log("Could not read " + filename)
|
||||||
return
|
return
|
||||||
bytes = [IR.ConstantExpr(ord(x)) for x in bytes]
|
|
||||||
result.append(IR.Node(ppt, "Byte", *bytes))
|
|
||||||
|
|
||||||
|
|
||||||
def pragmaCharmap(ppt, line, result):
|
def pragmaCharmap(ppt, line, result):
|
||||||
|
@ -366,6 +366,10 @@ class PCTracker(Pass):
|
|||||||
def visitByte(self, node, env):
|
def visitByte(self, node, env):
|
||||||
env.incPC(len(node.data))
|
env.incPC(len(node.data))
|
||||||
|
|
||||||
|
def visitByteRange(self, node, env):
|
||||||
|
if node.data[1].valid(env):
|
||||||
|
env.incPC(node.data[1].value(env))
|
||||||
|
|
||||||
def visitWord(self, node, env):
|
def visitWord(self, node, env):
|
||||||
env.incPC(len(node.data) * 2)
|
env.incPC(len(node.data) * 2)
|
||||||
|
|
||||||
@ -744,6 +748,19 @@ class Assembler(Pass):
|
|||||||
env.incPC(len(node.data))
|
env.incPC(len(node.data))
|
||||||
self.data += len(node.data)
|
self.data += len(node.data)
|
||||||
|
|
||||||
|
def visitByteRange(self, node, env):
|
||||||
|
offset = node.data[0].value(env) + 2
|
||||||
|
length = node.data[1].value(env)
|
||||||
|
if offset < 2:
|
||||||
|
Err.log("Negative offset in .incbin")
|
||||||
|
elif offset + length > len(node.data):
|
||||||
|
Err.log("File too small for .incbin subrange")
|
||||||
|
else:
|
||||||
|
for expr in node.data[offset:(offset + length)]:
|
||||||
|
self.outputbyte(expr, env)
|
||||||
|
env.incPC(length)
|
||||||
|
self.data += length
|
||||||
|
|
||||||
def visitWord(self, node, env):
|
def visitWord(self, node, env):
|
||||||
for expr in node.data:
|
for expr in node.data:
|
||||||
self.outputword(expr, env)
|
self.outputword(expr, env)
|
||||||
|
Loading…
Reference in New Issue
Block a user