Skip to content

Phase 01: Integer Literal

Compilerbook step 1. Accept one integer on the command line and emit a complete macOS arm64 assembly program whose _main returns that integer.

Source

main.c

c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
  if (argc != 2) {
    fprintf(stderr, "usage: %s <integer>\n", argv[0]);
    return 1;
  }

  char *end = NULL;
  long value = strtol(argv[1], &end, 10);
  if (*end != '\0') {
    fprintf(stderr, "expected an integer: %s\n", argv[1]);
    return 1;
  }

  printf(".globl _main\n");
  printf("_main:\n");
  printf("    mov x0, #%ld\n", value);
  printf("    ret\n");
  return 0;
}

test.sh

sh
#!/bin/sh
set -eu

try() {
  expected="$1"
  input="$2"

  ./armcc "$input" > tmp.s
  clang tmp.s -o tmp
  set +e
  ./tmp
  actual="$?"
  set -e

  if [ "$actual" = "$expected" ]; then
    echo "$input => $actual"
  else
    echo "$input => expected $expected, got $actual"
    exit 1
  fi
}

reject() {
  input="$1"
  if ./armcc "$input" > tmp.s 2> tmp.err; then
    echo "$input => expected rejection"
    exit 1
  fi
  echo "$input => rejected"
}

try 0 0
try 42 42
reject '1+2'

echo OK