Module src.backend.ASMNode
Declares the ASMNode class, which represents one line of an IR
Expand source code
"""
Declares the ASMNode class, which represents one line of an IR
"""
x64_regs = ["rax", "rbp", "rsp", "rcx","rdx" ,"rbx" ,"rsi" ,"rdi" ,"r8", "r9" ,"r10" ,"r11" ,"r12", "r13","r14", "r15", "al", "bpl", "spl", "cl", "dl" ,"bl" ,"sil" ,"dil" ,"r8b", "r9b" ,"r10b" ,"r11b" ,"r12b", "r13b", "r14b", "r15b"]
class ASMNode():
"""
The class for a node of assembly, essentially each node is a line in assembly
"""
def __init__(self, command, left, right, **kwarg):
"""
Initializes the ASMNode object
Args:
command: The operation (mov, add, etc.)
left: The left side of the operation (mov x,y), left is x
right: The right side of the operation (mov x,y) right is y
kwargs: A dictionary of values that give various metadata about the command (will it need a register, is it a constant, etc.)
"""
self.command = command
self.left = left if left else ""
self.right = right if right else ""
self.aux = kwarg["aux"] if "aux" in kwarg else None
#determine the left and right offset
self.leftOffset = kwarg["leftOffset"] if "leftOffset" in kwarg else None
self.rightOffset = kwarg["rightOffset"] if "rightOffset" in kwarg else None
#determine if the left operand needs a register, or if the right operand needs a register
self.leftNeedsReg = kwarg["leftNeedsReg"] if "leftNeedsReg" in kwarg else False
self.rightNeedsReg = kwarg["rightNeedsReg"] if "rightNeedsReg" in kwarg else False
#assembly node is fully constructed and shouldnt be modified
self.dontTouch = "dontTouch" in kwarg
#determine if the register is a paramater
self.regIsParam = "regIsParam" in kwarg
#assembly nodes like 'function declaration' store a regDir and stack for passed in parameters
self.regDir = kwarg["regDir"] if "regDir" in kwarg else {}
self.stack = kwarg["stack"] if "stack" in kwarg else []
#determine if the register is in a function declaration
self.functionDecl = "functionDecl" in kwarg
#determines if there are no paramters
self.noParams = "noParams" in kwarg
#determine if the left and right operands are literals
self.leftLiteral = True if self.left and self.left.startswith("$") else False
self.rightLiteral = True if self.right and self.right.startswith("$") else False
#determine if the left has a variable
self.leftHasVar = True if self.left and self.left not in x64_regs else False
#determine if the right has a variable
self.rightHasVar = True if self.right and self.right not in x64_regs else False
self.boilerPlate = kwarg["boilerPlate"] if "boilerPlate" in kwarg else None
def __str__(self):
"""
Returns the string representation of an ASMNode
Returns:
The string representation of the given node
"""
#determine the proper string representation of the assembly line
if self.aux:
return f"""{self.command} \
{self.aux},\
{f'{self.leftOffset}' + '(' if self.leftOffset else ''}\
{'%' if self.left in x64_regs else ''}\
{self.left}\
{')' if self.leftOffset else ''}, \
{f'{self.rightOffset}' + '(' if self.rightOffset else ''}\
{'%' if self.right in x64_regs else ''}\
{self.right}\
{')' if self.rightOffset else ''}"""
elif self.right:
return f"""{self.command} \
{f'{self.leftOffset}' + '(' if self.leftOffset else ''}\
{'%' if self.left in x64_regs else ''}\
{self.left}{')' if self.leftOffset else ''}, \
{f'{self.rightOffset}' + '(' if self.rightOffset else ''}\
{'%' if self.right in x64_regs else ''}\
{self.right}\
{')' if self.rightOffset else ''}"""
elif self.left:
return f"""{self.command} \
{f'{self.leftOffset}' + '(' if self.leftOffset else ''}\
{'%' if self.left in x64_regs else ''}\
{self.left}\
{')' if self.leftOffset else ''}"""
elif self.boilerPlate:
return f"""{self.boilerPlate}"""
else:
return f"{self.command}"
Classes
class ASMNode (command, left, right, **kwarg)
-
The class for a node of assembly, essentially each node is a line in assembly
Initializes the ASMNode object
Args
command
- The operation (mov, add, etc.)
left
- The left side of the operation (mov x,y), left is x
right
- The right side of the operation (mov x,y) right is y
kwargs
- A dictionary of values that give various metadata about the command (will it need a register, is it a constant, etc.)
Expand source code
class ASMNode(): """ The class for a node of assembly, essentially each node is a line in assembly """ def __init__(self, command, left, right, **kwarg): """ Initializes the ASMNode object Args: command: The operation (mov, add, etc.) left: The left side of the operation (mov x,y), left is x right: The right side of the operation (mov x,y) right is y kwargs: A dictionary of values that give various metadata about the command (will it need a register, is it a constant, etc.) """ self.command = command self.left = left if left else "" self.right = right if right else "" self.aux = kwarg["aux"] if "aux" in kwarg else None #determine the left and right offset self.leftOffset = kwarg["leftOffset"] if "leftOffset" in kwarg else None self.rightOffset = kwarg["rightOffset"] if "rightOffset" in kwarg else None #determine if the left operand needs a register, or if the right operand needs a register self.leftNeedsReg = kwarg["leftNeedsReg"] if "leftNeedsReg" in kwarg else False self.rightNeedsReg = kwarg["rightNeedsReg"] if "rightNeedsReg" in kwarg else False #assembly node is fully constructed and shouldnt be modified self.dontTouch = "dontTouch" in kwarg #determine if the register is a paramater self.regIsParam = "regIsParam" in kwarg #assembly nodes like 'function declaration' store a regDir and stack for passed in parameters self.regDir = kwarg["regDir"] if "regDir" in kwarg else {} self.stack = kwarg["stack"] if "stack" in kwarg else [] #determine if the register is in a function declaration self.functionDecl = "functionDecl" in kwarg #determines if there are no paramters self.noParams = "noParams" in kwarg #determine if the left and right operands are literals self.leftLiteral = True if self.left and self.left.startswith("$") else False self.rightLiteral = True if self.right and self.right.startswith("$") else False #determine if the left has a variable self.leftHasVar = True if self.left and self.left not in x64_regs else False #determine if the right has a variable self.rightHasVar = True if self.right and self.right not in x64_regs else False self.boilerPlate = kwarg["boilerPlate"] if "boilerPlate" in kwarg else None def __str__(self): """ Returns the string representation of an ASMNode Returns: The string representation of the given node """ #determine the proper string representation of the assembly line if self.aux: return f"""{self.command} \ {self.aux},\ {f'{self.leftOffset}' + '(' if self.leftOffset else ''}\ {'%' if self.left in x64_regs else ''}\ {self.left}\ {')' if self.leftOffset else ''}, \ {f'{self.rightOffset}' + '(' if self.rightOffset else ''}\ {'%' if self.right in x64_regs else ''}\ {self.right}\ {')' if self.rightOffset else ''}""" elif self.right: return f"""{self.command} \ {f'{self.leftOffset}' + '(' if self.leftOffset else ''}\ {'%' if self.left in x64_regs else ''}\ {self.left}{')' if self.leftOffset else ''}, \ {f'{self.rightOffset}' + '(' if self.rightOffset else ''}\ {'%' if self.right in x64_regs else ''}\ {self.right}\ {')' if self.rightOffset else ''}""" elif self.left: return f"""{self.command} \ {f'{self.leftOffset}' + '(' if self.leftOffset else ''}\ {'%' if self.left in x64_regs else ''}\ {self.left}\ {')' if self.leftOffset else ''}""" elif self.boilerPlate: return f"""{self.boilerPlate}""" else: return f"{self.command}"