Skip to content

Commit

Permalink
Support char (byte integer) on Gen
Browse files Browse the repository at this point in the history
  • Loading branch information
kntkymt committed Dec 21, 2023
1 parent cb2d402 commit da3964e
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 11 deletions.
74 changes: 63 additions & 11 deletions Sources/Generator/Generator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public final class Generator {
var result = ""

// g: .zeroじゃApple Clangは動かない?
result += ".comm g,\(node.type.memorySize),8\n"
let alignment = isElementOrReferenceTypeMemorySizeOf(1, identifierName: node.identifierName) ? 0 : 8
result += ".comm \(node.identifierName),\(node.type.memorySize),\(alignment)\n"

globalVariables[node.identifierName] = node.type

Expand All @@ -86,13 +87,17 @@ public final class Generator {

// 配列の場合は先頭アドレスのまま返す
// 配列以外の場合はアドレスの中身を返す
if variables[casted.identifierName]?.type.kind != .arrayType {
if let variableType = getVariableType(name: casted.identifierName), variableType.kind != .arrayType {
// アドレスをpop
result += " ldr x0, [sp]\n"
result += " add sp, sp, #16\n"

// アドレスを値に変換してpush
result += " ldr x0, [x0]\n"
if variableType.memorySize == 1 {
result += " ldrb w0, [x0]\n"
} else {
result += " ldr x0, [x0]\n"
}
result += " str x0, [sp, #-16]!\n"
}

Expand Down Expand Up @@ -180,7 +185,12 @@ public final class Generator {
// 結果のアドレスの値をロードしてスタックに積む
result += " ldr x0, [sp]\n"
result += " add sp, sp, #16\n"
result += " ldr x0, [x0]\n"

if isElementOrReferenceTypeMemorySizeOf(1, identifierName: casted.identifierNode.identifierName) {
result += " ldrb w0, [x0]\n"
} else {
result += " ldr x0, [x0]\n"
}
result += " str x0, [sp, #-16]!\n"

return result
Expand Down Expand Up @@ -335,7 +345,12 @@ public final class Generator {
result += " add sp, sp, #16\n"

// 値をアドレスとして読み、アドレスが指す値をロード
result += " ldr x0, [x0]\n"
if let identifier = casted.right as? IdentifierNode, isElementOrReferenceTypeMemorySizeOf(1, identifierName: identifier.identifierName) {
result += " ldrb w0, [x0]\n"
} else {
result += " ldr x0, [x0]\n"
}

result += " str x0, [sp, #-16]!\n"

case .address:
Expand Down Expand Up @@ -374,7 +389,16 @@ public final class Generator {
result += " add sp, sp, #16\n"

// assign
result += " str x0, [x1]\n"
if let identifier = casted.left as? IdentifierNode, getVariableType(name: identifier.identifierName)?.memorySize == 1 {
result += " strb w0, [x1]\n"
} else if let pointer = casted.left as? PrefixOperatorExpressionNode, pointer.operatorKind == .reference, let identifier = pointer.right as? IdentifierNode, isElementOrReferenceTypeMemorySizeOf(1, identifierName: identifier.identifierName) {
result += " strb w0, [x1]\n"
} else if let subscriptCall = casted.left as? SubscriptCallExpressionNode,
isElementOrReferenceTypeMemorySizeOf(1, identifierName: subscriptCall.identifierNode.identifierName) {
result += " strb w0, [x1]\n"
} else {
result += " str x0, [x1]\n"
}

result += " str x0, [sp, #-16]!\n"

Expand All @@ -392,10 +416,9 @@ public final class Generator {
if binaryOperator.operatorKind == .add || binaryOperator.operatorKind == .sub {
// addまたはsubの時、一方が変数でポインタ型または配列だったら、他方を8倍する
// 8は8バイト(ポインタの指すサイズ、今は全部8バイトなので)
if let identifier = casted.left as? IdentifierNode,
variables[identifier.identifierName]?.type is PointerTypeNode || variables[identifier.identifierName]?.type is ArrayTypeNode {
if let identifier = casted.left as? IdentifierNode, isElementOrReferenceTypeMemorySizeOf(8, identifierName: identifier.identifierName) {
result += " lsl x0, x0, #3\n"
} else if let identifier = casted.right as? IdentifierNode, variables[identifier.identifierName]?.type is PointerTypeNode || variables[identifier.identifierName]?.type is ArrayTypeNode {
} else if let identifier = casted.right as? IdentifierNode, isElementOrReferenceTypeMemorySizeOf(8, identifierName: identifier.identifierName) {
result += " lsl x1, x1, #3\n"
}
}
Expand Down Expand Up @@ -459,6 +482,31 @@ public final class Generator {

// MARK: - Private

/// local or global variableから変数を検索する
private func getVariableType(name: String) -> (any TypeNodeProtocol)? {
if let type = variables[name]?.type {
type
} else if let type = globalVariables[name] {
type
} else {
nil
}
}

private func isElementOrReferenceTypeMemorySizeOf(_ size: Int, identifierName: String) -> Bool {
guard let identifierType = getVariableType(name: identifierName) else { return false }

if let pointerType = identifierType as? PointerTypeNode {
return pointerType.referenceType.memorySize == size
}

if let arrayType = identifierType as? ArrayTypeNode {
return arrayType.elementType.memorySize == size
}

return false
}

/// nameの変数のアドレスをスタックにpushするコードを生成する
private func generatePushVariableAddress(node: IdentifierNode) throws -> String {
var result = ""
Expand Down Expand Up @@ -487,8 +535,12 @@ public final class Generator {

result += " ldr x0, [sp]\n"
result += " add sp, sp, #16\n"
// subscriptの方は8倍
result += " lsl x0, x0, 3\n"
// subscript内の値は要素のメモリサイズに応じてn倍する
if let arrayType = getVariableType(name: node.identifierNode.identifierName) as? ArrayTypeNode, arrayType.elementType.memorySize == 8 {
result += " lsl x0, x0, 3\n"
} else if let pointerType = getVariableType(name: node.identifierNode.identifierName) as? PointerTypeNode, pointerType.referenceType.memorySize == 8 {
result += " lsl x0, x0, 3\n"
}

result += " ldr x1, [sp]\n"
result += " add sp, sp, #16\n"
Expand Down
7 changes: 7 additions & 0 deletions test_exectable.sh
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,12 @@ assert 10 "int g; int main() { g = 10; return g; }"
assert 100 "int g; int main() { g = 10; return g * 10; }"
assert 30 "int g; int sub() { g = 30; return 0; } int main() { g = 20; sub(); return g; }"
assert 30 "int g[10]; int main() { g[2] = 10; g[3] = 20; return g[2] + g[2 + 1]; }"
assert 10 "int main() { char x; x = 10; return x; }"
assert 30 "int main() { char x; x = 10; char* p; p = &x; *p = 30; return x; }"
assert 3 "int main() { char x[3]; x[0] = -1; x[1] = 2; int y; y = 4; return x[0] + y; }"
assert 15 "char x; int main() { x = 15; return x; }"
assert 3 "char x[3]; int main() { x[0] = -1; x[1] = 2; int y; y = 4; return x[0] + y; }"
assert 150 "int main() { int x; x = 300; return x / 2; }"
assert 22 "int main() { char x; x = 300; return x / 2; }"

echo OK

0 comments on commit da3964e

Please sign in to comment.