Skip to content

Commit

Permalink
Easily copy and pass structs into and out of funcs
Browse files Browse the repository at this point in the history
  • Loading branch information
DerelictDrone committed Nov 14, 2023
1 parent 4ad73dc commit 704ae26
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 16 deletions.
7 changes: 6 additions & 1 deletion lua/wire/client/hlzasm/hc_codetree.lua
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,12 @@ function HCOMP:GenerateLeaf(leaf,needResult)

-- Make register operand temporary if requested
if genOperands[i].ForceTemporary then
local initReg = genOperands[i].Register
local initReg
if genOperands[i].Register then
initReg = genOperands[i].Register
elseif genOperands[i].MemoryRegister then
initReg = genOperands[i].MemoryRegister
end
genOperands[i].ForceTemporary = false

if self.RegisterBusy[initReg] then
Expand Down
3 changes: 2 additions & 1 deletion lua/wire/client/hlzasm/hc_compiler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,8 @@ function HCOMP:StartCompile(sourceCode,fileName,writeByteCallback,writeByteCalle

-- All functions defined so far
self.Functions = {}

-- Details about the current function that we're building
self.CurFunction = {}
-- All macros defined so far
self.Defines = {}
self.Defines["__LINE__"] = 0
Expand Down
115 changes: 108 additions & 7 deletions lua/wire/client/hlzasm/hc_expression.lua
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,33 @@ function HCOMP:Expression_FunctionCall(label) local TOKEN = self.TOKEN

-- Push arguments to stack in reverse order
for argNo = #argumentExpression,1,-1 do
local pushLeaf = self:NewLeaf()
pushLeaf.Opcode = "push"
pushLeaf.Operands[1] = argumentExpression[argNo]
table.insert(genLeaves,pushLeaf)
local pushLeaf
if argumentExpression[argNo].Memory then
if argumentExpression[argNo].Memory.CopySize then
for i=argumentExpression[argNo].Memory.CopySize-1,0,-1 do
pushLeaf = self:NewLeaf()
pushLeaf.Comment = " passing large variable, byte "..i
pushLeaf.Opcode = "push"
local a = argumentExpression[argNo]
local copiedArg = {
CurrentPosition = argumentExpression[argNo].CurrentPosition,
Memory = a.Memory,
MemAddrOffset = i
}
-- Memory will update globally when it receives the final value
-- so we wrap it into a new copy of the table with a constant num
-- because setting the const in memory would update the same table multiple times
pushLeaf.Operands[1] = copiedArg
table.insert(genLeaves,pushLeaf)
end
argumentCount = argumentCount + argumentExpression[argNo].Memory.CopySize-1
end
else
pushLeaf = self:NewLeaf()
pushLeaf.Opcode = "push"
pushLeaf.Operands[1] = argumentExpression[argNo]
table.insert(genLeaves,pushLeaf)
end

if functionEntry then
if functionEntry.Parameters[argNo] then
Expand Down Expand Up @@ -145,6 +168,18 @@ function HCOMP:Expression_FunctionCall(label) local TOKEN = self.TOKEN
end

-- Return EAX as the return value
if self.Functions[label] then
if self.StructSize[self.Functions[label].ReturnType] then
-- Return as memory register that requests copy of x size
return { MemoryRegister = 1, ForceTemporary = true, CopySize = self.StructSize[self.Functions[label].ReturnType], PreviousLeaf = genLeaves[#genLeaves]}
end
elseif self.CurFunction then
if self.CurFunction.ReturnType then
if self.StructSize[self.CurFunction.ReturnType] then
return { MemoryRegister = 1, ForceTemporary = true, CopySize = self.StructSize[self.CurFunction.ReturnType], PreviousLeaf = genLeaves[#genLeaves]}
end
end
end
return { Register = 1, ForceTemporary = true, PreviousLeaf = genLeaves[#genLeaves] }
end

Expand Down Expand Up @@ -332,7 +367,7 @@ function HCOMP:Expression_Level3() local TOKEN = self.TOKEN
addressLeaf.Operands[2] = { Constant = structData[memberName].Offset }
operationLeaf = { MemoryPointer = addressLeaf }
else
operationLeaf = { Stack = structLabel.StackOffset+structData[memberName].Offset }
operationLeaf = { Stack = structLabel.StackOffset+structData[memberName].Offset-1 }
end
elseif structLabel.Type == "Variable" then
if structLabel.PointerToStruct then
Expand Down Expand Up @@ -373,7 +408,12 @@ function HCOMP:Expression_Level3() local TOKEN = self.TOKEN
else -- Parse variable access
if label.Type == "Variable" then -- Read from a variable
-- Array variables are resolved as pointers at constant expression stage
operationLeaf = { Memory = label, ForceType = forceType }
if label.Struct then
operationLeaf = { Memory = label, ForceType = forceType }
operationLeaf.Memory.CopySize = self.StructSize[label.Struct]
else
operationLeaf = { Memory = label, ForceType = forceType }
end
elseif label.Type == "Unknown" then -- Read from an unknown variable
operationLeaf = { UnknownOperationByLabel = label, ForceType = forceType }
elseif label.Type == "Stack" then -- Read from stack
Expand Down Expand Up @@ -485,7 +525,68 @@ function HCOMP:Expression_Level0()

if self:MatchToken(self.TOKEN.EQUAL) then -- =
local rightLeaf = self:Expression_LevelLeaf(0)

if leftLeaf.Memory then
if rightLeaf.Memory then
if leftLeaf.Memory.CopySize and rightLeaf.Memory.CopySize then
local topLeaf = self:NewOpcode("mov",leftLeaf,rightLeaf)
local curLeaf = topLeaf
local tempLeftLeaf,tempRightLeaf
for i=1,math.min(leftLeaf.Memory.CopySize,rightLeaf.Memory.CopySize)-1 do
tempLeftLeaf = {
CurrentPosition = leftLeaf.CurrentPosition,
Memory = leftLeaf.Memory,
MemAddrOffset = i
}
tempRightLeaf = {
CurrentPosition = rightLeaf.CurrentPosition,
Memory = rightLeaf.Memory,
MemAddrOffset = i
}
curLeaf.PreviousLeaf = self:NewOpcode("mov",tempLeftLeaf,tempRightLeaf)
curLeaf = curLeaf.PreviousLeaf
end
-- example of generated output (because previousleaf is parsed before the leaf containing previousleaf)
-- MOV #0+2,#3+2
-- MOV #0+1,#3+1
-- MOV #0,#3
-- * Mark these both with an offset so they won't warn
leftLeaf.MemAddrOffset = 0
rightLeaf.MemAddrOffset = 0
curLeaf.Comment = topLeaf.Comment
topLeaf.Comment = nil
return topLeaf
end
elseif rightLeaf.MemoryRegister then
if leftLeaf.Memory.CopySize and rightLeaf.CopySize then
local topLeaf = self:NewOpcode("mov",leftLeaf,rightLeaf)
local curLeaf = topLeaf
local tempLeftLeaf
for i=1,math.min(leftLeaf.Memory.CopySize,rightLeaf.CopySize)-1 do
tempLeftLeaf = {
CurrentPosition = leftLeaf.CurrentPosition,
Memory = leftLeaf.Memory,
MemAddrOffset = i
}
curLeaf.PreviousLeaf = self:NewOpcode("inc",{Register = rightLeaf.MemoryRegister})
curLeaf = curLeaf.PreviousLeaf
curLeaf.PreviousLeaf = self:NewOpcode("mov",tempLeftLeaf,rightLeaf)
curLeaf = curLeaf.PreviousLeaf
end
-- example of generated output (because previousleaf is parsed before the leaf containing previousleaf)
-- MOV #0+2,#R0
-- INC R0
-- MOV #0+1,#R0
-- INC R0
-- MOV #0,#R0
-- * Mark these both with an offset so they won't warn
leftLeaf.MemAddrOffset = 0
rightLeaf.MemAddrOffset = 0
curLeaf.Comment = topLeaf.Comment
topLeaf.Comment = nil
return topLeaf
end
end
end
-- Mark this leaf as an explict assign operation
local operationLeaf = self:NewOpcode("mov",leftLeaf,rightLeaf)
operationLeaf.ExplictAssign = true
Expand Down
27 changes: 25 additions & 2 deletions lua/wire/client/hlzasm/hc_output.lua
Original file line number Diff line number Diff line change
Expand Up @@ -363,9 +363,28 @@ function HCOMP:PrintBlock(block,file,isLibrary)
printText = printText .. "#" .. block.Operands[i].MemoryPointer
end
elseif block.Operands[i].Memory then
if not block.Operands[i].MemAddrOffset then
if block.Operands[i].Memory.CopySize then
if block.Operands[1].Memory and i ~= 1 then
if block.Operands[i].Memory.CopySize then
self:Warning("Operation will only use first byte of large variables on left and right, use &varname to get a pointer instead")
end
else
if not block.Operands[i].MemAddrOffset then
PrintTable(block.Operands[i])
self:Warning("Operation will only use first byte of large variable on right, use &varname to get a pointer instead")
end
end
end
end
if istable(block.Operands[i].Memory) then
if block.Operands[i].Memory.Value
then printText = printText .. "#" .. block.Operands[i].Memory.Value
then
if block.Operands[i].MemAddrOffset then
printText = printText .. "#" .. block.Operands[i].Memory.Value + block.Operands[i].MemAddrOffset
else
printText = printText .. "#" .. block.Operands[i].Memory.Value
end
else printText = printText .. "#" .. block.Operands[i].Memory.Name
end
else
Expand Down Expand Up @@ -530,7 +549,11 @@ function HCOMP:OperandRM(operand,block)
end
elseif operand.Memory then
if istable(operand.Memory) then -- label
operand.Value = operand.Memory.Value
if operand.MemAddrOffset then
operand.Value = operand.Memory.Value + operand.MemAddrOffset
else
operand.Value = operand.Memory.Value
end
else -- constant
operand.Value = operand.Memory
end
Expand Down
43 changes: 38 additions & 5 deletions lua/wire/client/hlzasm/hc_syntax.lua
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,15 @@ function HCOMP:DefineVariable(isFunctionParam,isForwardDecl,isRegisterDecl,isStr
-- Create function entrypoint
local label
label = self:DefineLabel(varName)

self:PreviousToken() -- LPAREN
self:PreviousToken() -- Func Name
self:PreviousToken() -- Type Name
self:MatchToken(TOKEN.IDENT) -- Type Name
local returnType = self.TokenData
self:MatchToken(TOKEN.IDENT)
local funcName = self.TokenData
self.CurFunction = {Name = funcName, ReturnType = returnType}
self:NextToken()
label.Type = "Pointer"
label.Defined = true

Expand Down Expand Up @@ -1134,12 +1142,37 @@ function HCOMP:Statement() local TOKEN = self.TOKEN
if self:MatchToken(TOKEN.RETURN) and self.HeadLeaf then
if not self:MatchToken(TOKEN.COLON) then
local returnExpression = self:Expression()
local copyLargeVariable = false
if self.StructSize[self.CurFunction.ReturnType] then
copyLargeVariable = true -- Converts this to automatically return ptr to large variable
end
local returnLeaf = self:NewLeaf()
returnLeaf.Opcode = "mov"
returnLeaf.Operands[1] = { Register = 1 }
returnLeaf.Operands[2] = returnExpression
returnLeaf.ExplictAssign = true
local preReturnLeaf,postReturnLeaf
if copyLargeVariable then
local finalReturnExpression = returnExpression
returnLeaf.Opcode = "mov"
returnLeaf.Operands[1] = { Register = 1 }
if returnExpression.Stack then
finalReturnExpression = { Register = 8 } -- EBP, the stack frame register, where the stack ptr is local to
postReturnLeaf = self:NewOpcode("add",returnLeaf.Operands[1],{Constant = returnExpression.Stack})
-- MOV EAX,EBP
-- ADD EAX,(stack-pos)
end
returnLeaf.Operands[2] = finalReturnExpression
returnLeaf.ExplictAssign = true
else
returnLeaf.Opcode = "mov"
returnLeaf.Operands[1] = { Register = 1 }
returnLeaf.Operands[2] = returnExpression
returnLeaf.ExplictAssign = true
end
if preReturnLeaf then
self:AddLeafToTail(preReturnLeaf)
end
self:AddLeafToTail(returnLeaf)
if postReturnLeaf then
self:AddLeafToTail(postReturnLeaf)
end
end
self:MatchToken(TOKEN.COLON)

Expand Down

0 comments on commit 704ae26

Please sign in to comment.