#!/usr/bin/env python

import sys
import os

def main(argv=None):
  if argv is None:
    argv = sys.argv
  progname = argv[0]

  if len(argv) != 2:
    print "Usage: " + argv[0] + " <maximum arity>"
    exit(1)

  n = int(argv[1])

  print "/* MACHINE GENERATED - do not edit this file */"
  print ""

  for i in range(0, n + 1):
    print "_DEVICE_QUALIFIER void __barrier_invariant_" + str(i) + "(bool expr"
    for j in range(0, i):
      print "  , size_t inst_expr_" + str(j)
    print ");"

  for i in range(0, n + 1):
    print "#if !defined(__1D_WORK_GROUP) && !defined(__1D_THREAD_BLOCK)"
    definition = "#define __barrier_invariant_" + str(i) + "(X"
    for j in range(0, i):
      definition += ", I" + str(j)
    definition += ") !!! Barrier invariants currently only supported for 1D thread groups !!!"
    print definition
    print "#else"
    definition = "#define __barrier_invariant_" + str(i) + "(X"
    for j in range(0, i):
      definition += ", I" + str(j)
    definition += ") \\"
    print definition
    print "    __non_temporal_loads_begin(), \\"
    call = "    __barrier_invariant_" + str(i) + "(X"
    for j in range(0, i):
      call += ", I" + str(j)
    call += "), \\"
    print call
    print "    __non_temporal_loads_end()"
    print "#endif"

  for i in range(0, n + 1):
    print "void __barrier_invariant_binary_" + str(i) + "(bool expr"
    for j in range(0, i):
      print "  , size_t inst_expr_" + str(j) + "_0, size_t inst_expr_" + str(j) + "_1"
    print ");"

  for i in range(0, n + 1):
    print "#if !defined(__1D_WORK_GROUP) && !defined(__1D_THREAD_BLOCK)"
    definition = "#define __barrier_invariant_binary_" + str(i) + "(X"
    for j in range(0, i):
      definition += ", I" + str(j) + "_0, I" + str(j) + "_1"
    definition += ") !!! Barrier invariants currently only supported for 1D thread groups !!!"
    print definition
    print "#else"
    definition = "#define __barrier_invariant_binary_" + str(i) + "(X"
    for j in range(0, i):
      definition += ", I" + str(j) + "_0, I" + str(j) + "_1"
    definition += ") \\"
    print definition
    print "    __non_temporal_loads_begin(), \\"
    call = "    __barrier_invariant_binary_" + str(i) + "(X"
    for j in range(0, i):
      call += ", I" + str(j) + "_0, I" + str(j) + "_1"
    call += "), \\"
    print call
    print "    __non_temporal_loads_end()"
    print "#endif"


if __name__ == '__main__':
  sys.exit(main())
