Started to implement external C interface for the compiler Output a first dummy program
authorBenjamin Segovia <segovia.benjamin@gmail.com>
Wed, 21 Mar 2012 16:58:59 +0000 (16:58 +0000)
committerKeith Packard <keithp@keithp.com>
Fri, 10 Aug 2012 23:15:47 +0000 (16:15 -0700)
12 files changed:
backend/CMakeLists.txt
backend/src/CMakeLists.txt
backend/src/gen/brw_disasm.c
backend/src/gen/brw_eu.h
backend/src/gen/brw_eu_emit.c
backend/src/gen/brw_structs.h
backend/src/gen/program.cpp
backend/src/gen/program.h
backend/src/gen/program.hpp
backend/src/ir/unit.hpp
backend/src/sys/alloc.cpp
backend/src/sys/alloc.hpp

index 75d6c5f..57e6e18 100644 (file)
@@ -50,14 +50,17 @@ endif (GBE_COMPILE_UTESTS)
 ## Linux compilation
 if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
   # Hide all symbols and allows the symbols declared as visible to be exported
-  # set (VISIBILITY_FLAG "-fvisibility=hidden")
+  if (NOT GBE_COMPILE_UTESTS)
+    set (CMAKE_C_CXX_FLAGS "-fvisibility=hidden")
+  endif (NOT GBE_COMPILE_UTESTS)
 
   if (COMPILER STREQUAL "GCC")
-    set (CMAKE_C_CXX_FLAGS "-Wstrict-aliasing=2 -fstrict-aliasing -msse2 -ffast-math -fPIC -Wall")
+    set (CMAKE_C_CXX_FLAGS "${CMAKE_C_CXX_FLAGS} -Wstrict-aliasing=2 -fstrict-aliasing -msse2 -ffast-math -fPIC -Wall")
     set (CMAKE_CXX_FLAGS "${CMAKE_C_CXX_FLAGS}  -Wno-invalid-offsetof -fno-rtti -std=c++0x")
     set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GBE_DEBUG_MEMORY_FLAG}")
     set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GBE_COMPILE_UTESTS_FLAG}")
-    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${VISIBILITY_FLAG} -Wl,-E")
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,-E")
+    set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--no-undefined")
     if (NOT GBE_COMPILE_UTESTS)
       set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
     endif (NOT GBE_COMPILE_UTESTS)
@@ -68,7 +71,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
     set (CMAKE_C_FLAGS "${CMAKE_C_CXX_FLAGS}")
     set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GBE_DEBUG_MEMORY_FLAG}")
     set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GBE_COMPILE_UTESTS_FLAG}")
-    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${VISIBILITY_FLAG} -Wl,-E")
+    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-E")
     set (CMAKE_C_FLAGS_DEBUG          "-g -DGBE_DEBUG=1")
     set (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g -DGBE_DEBUG=1")
     set (CMAKE_C_FLAGS_MINSIZEREL     "-Os -DNDEBUG -DGBE_DEBUG=0")
index 69b542a..c8b38f0 100644 (file)
@@ -43,6 +43,8 @@ else (GBE_USE_BLOB)
     ir/value.cpp
     ir/value.hpp
     gen/program.cpp
+    gen/program.hpp
+    gen/program.h
     gen/brw_disasm.c
     gen/brw_eu_emit.c
     gen/brw_eu.c)
@@ -64,6 +66,12 @@ add_library (gbe SHARED ${GBE_SRC})
 include (${LLVM_DIR}/AddLLVMDefinitions.cmake)
 target_link_libraries (gbe
   LLVMGenBackend
+  LLVMTransformUtils
+  LLVMCore
+  LLVMTarget
+  LLVMAnalysis
+  LLVMCodeGen
+  LLVMScalarOpts
   LLVMSelectionDAG
   LLVMAsmPrinter
   LLVMMCParser
@@ -76,3 +84,6 @@ if (GBE_COMPILE_UTESTS)
   target_link_libraries (tester gbe)
 endif (GBE_COMPILE_UTESTS)
 
+install (TARGETS gbe LIBRARY DESTINATION lib)
+install (FILES gen/program.h DESTINATION include/gen)
+
index 95fc997..9e97285 100644 (file)
@@ -31,7 +31,7 @@
 
 #include <stdint.h>
 
-struct {
+static struct {
     char    *name;
     int            nsrc;
     int            ndst;
@@ -91,7 +91,7 @@ struct {
     [BRW_OPCODE_ENDIF] = { .name = "endif", .nsrc = 2, .ndst = 0 },
 };
 
-char *conditional_modifier[16] = {
+static char *conditional_modifier[16] = {
     [BRW_CONDITIONAL_NONE] = "",
     [BRW_CONDITIONAL_Z] = ".e",
     [BRW_CONDITIONAL_NZ] = ".ne",
@@ -104,17 +104,17 @@ char *conditional_modifier[16] = {
     [BRW_CONDITIONAL_U] = ".u",
 };
 
-char *negate[2] = {
+static char *negate[2] = {
     [0] = "",
     [1] = "-",
 };
 
-char *_abs[2] = {
+static char *_abs[2] = {
     [0] = "",
     [1] = "(abs)",
 };
 
-char *vert_stride[16] = {
+static char *vert_stride[16] = {
     [0] = "0",
     [1] = "1",
     [2] = "2",
@@ -125,7 +125,7 @@ char *vert_stride[16] = {
     [15] = "VxH",
 };
 
-char *width[8] = {
+static char *width[8] = {
     [0] = "1",
     [1] = "2",
     [2] = "4",
@@ -133,44 +133,41 @@ char *width[8] = {
     [4] = "16",
 };
 
-char *horiz_stride[4] = {
+static char *horiz_stride[4] = {
     [0] = "0",
     [1] = "1",
     [2] = "2",
     [3] = "4"
 };
 
-char *chan_sel[4] = {
+static char *chan_sel[4] = {
     [0] = "x",
     [1] = "y",
     [2] = "z",
     [3] = "w",
 };
 
-char *dest_condmod[16] = {
-};
-
-char *debug_ctrl[2] = {
+static char *debug_ctrl[2] = {
     [0] = "",
     [1] = ".breakpoint"
 };
 
-char *saturate[2] = {
+static char *saturate[2] = {
     [0] = "",
     [1] = ".sat"
 };
 
-char *accwr[2] = {
+static char *accwr[2] = {
     [0] = "",
     [1] = "AccWrEnable"
 };
 
-char *wectrl[2] = {
+static char *wectrl[2] = {
     [0] = "WE_normal",
     [1] = "WE_all"
 };
 
-char *exec_size[8] = {
+static char *exec_size[8] = {
     [0] = "1",
     [1] = "2",
     [2] = "4",
@@ -179,12 +176,12 @@ char *exec_size[8] = {
     [5] = "32"
 };
 
-char *pred_inv[2] = {
+static char *pred_inv[2] = {
     [0] = "+",
     [1] = "-"
 };
 
-char *pred_ctrl_align16[16] = {
+static char *pred_ctrl_align16[16] = {
     [1] = "",
     [2] = ".x",
     [3] = ".y",
@@ -194,7 +191,7 @@ char *pred_ctrl_align16[16] = {
     [7] = ".all4h",
 };
 
-char *pred_ctrl_align1[16] = {
+static char *pred_ctrl_align1[16] = {
     [1] = "",
     [2] = ".anyv",
     [3] = ".allv",
@@ -208,36 +205,36 @@ char *pred_ctrl_align1[16] = {
     [11] = ".all16h",
 };
 
-char *thread_ctrl[4] = {
+static char *thread_ctrl[4] = {
     [0] = "",
     [2] = "switch"
 };
 
-char *compr_ctrl[4] = {
+static char *compr_ctrl[4] = {
     [0] = "",
     [1] = "sechalf",
     [2] = "compr",
     [3] = "compr4",
 };
 
-char *dep_ctrl[4] = {
+static char *dep_ctrl[4] = {
     [0] = "",
     [1] = "NoDDClr",
     [2] = "NoDDChk",
     [3] = "NoDDClr,NoDDChk",
 };
 
-char *mask_ctrl[4] = {
+static char *mask_ctrl[4] = {
     [0] = "",
     [1] = "nomask",
 };
 
-char *access_mode[2] = {
+static char *access_mode[2] = {
     [0] = "align1",
     [1] = "align16",
 };
 
-char *reg_encoding[8] = {
+static char *reg_encoding[8] = {
     [0] = "UD",
     [1] = "D",
     [2] = "UW",
@@ -247,7 +244,7 @@ char *reg_encoding[8] = {
     [7] = "F"
 };
 
-int reg_type_size[8] = {
+const int reg_type_size[8] = {
     [0] = 4,
     [1] = 4,
     [2] = 2,
@@ -257,24 +254,14 @@ int reg_type_size[8] = {
     [7] = 4
 };
 
-char *imm_encoding[8] = {
-    [0] = "UD",
-    [1] = "D",
-    [2] = "UW",
-    [3] = "W",
-    [5] = "VF",
-    [6] = "V",
-    [7] = "F"
-};
-
-char *reg_file[4] = {
+static char *reg_file[4] = {
     [0] = "A",
     [1] = "g",
     [2] = "m",
     [3] = "imm",
 };
 
-char *writemask[16] = {
+static char *writemask[16] = {
     [0x0] = ".",
     [0x1] = ".x",
     [0x2] = ".y",
@@ -293,12 +280,12 @@ char *writemask[16] = {
     [0xf] = "",
 };
 
-char *end_of_thread[2] = {
+static char *end_of_thread[2] = {
     [0] = "",
     [1] = "EOT"
 };
 
-char *target_function[16] = {
+static char *target_function[16] = {
     [BRW_SFID_NULL] = "null",
     [BRW_SFID_MATH] = "math",
     [BRW_SFID_SAMPLER] = "sampler",
@@ -309,7 +296,7 @@ char *target_function[16] = {
     [BRW_SFID_THREAD_SPAWNER] = "thread_spawner"
 };
 
-char *target_function_gen6[16] = {
+static char *target_function_gen6[16] = {
     [BRW_SFID_NULL] = "null",
     [BRW_SFID_MATH] = "math",
     [BRW_SFID_SAMPLER] = "sampler",
@@ -322,7 +309,7 @@ char *target_function_gen6[16] = {
     [GEN7_SFID_DATAPORT_DATA_CACHE] = "data"
 };
 
-char *dp_rc_msg_type_gen6[16] = {
+static char *dp_rc_msg_type_gen6[16] = {
     [BRW_DATAPORT_READ_MESSAGE_OWORD_BLOCK_READ] = "OWORD block read",
     [GEN6_DATAPORT_READ_MESSAGE_RENDER_UNORM_READ] = "RT UNORM read",
     [GEN6_DATAPORT_READ_MESSAGE_OWORD_DUAL_BLOCK_READ] = "OWORD dual block read",
@@ -339,7 +326,7 @@ char *dp_rc_msg_type_gen6[16] = {
     [GEN6_DATAPORT_WRITE_MESSAGE_RENDER_TARGET_UNORM_WRITE] = "RT UNORMc write",
 };
 
-char *math_function[16] = {
+static char *math_function[16] = {
     [BRW_MATH_FUNCTION_INV] = "inv",
     [BRW_MATH_FUNCTION_LOG] = "log",
     [BRW_MATH_FUNCTION_EXP] = "exp",
@@ -355,53 +342,53 @@ char *math_function[16] = {
     [BRW_MATH_FUNCTION_INT_DIV_REMAINDER] = "intmod",
 };
 
-char *math_saturate[2] = {
+static char *math_saturate[2] = {
     [0] = "",
     [1] = "sat"
 };
 
-char *math_signed[2] = {
+static char *math_signed[2] = {
     [0] = "",
     [1] = "signed"
 };
 
-char *math_scalar[2] = {
+static char *math_scalar[2] = {
     [0] = "",
     [1] = "scalar"
 };
 
-char *math_precision[2] = {
+static char *math_precision[2] = {
     [0] = "",
     [1] = "partial_precision"
 };
 
-char *urb_opcode[2] = {
+static char *urb_opcode[2] = {
     [0] = "urb_write",
     [1] = "ff_sync",
 };
 
-char *urb_swizzle[4] = {
+static char *urb_swizzle[4] = {
     [BRW_URB_SWIZZLE_NONE] = "",
     [BRW_URB_SWIZZLE_INTERLEAVE] = "interleave",
     [BRW_URB_SWIZZLE_TRANSPOSE] = "transpose",
 };
 
-char *urb_allocate[2] = {
+static char *urb_allocate[2] = {
     [0] = "",
     [1] = "allocate"
 };
 
-char *urb_used[2] = {
+static char *urb_used[2] = {
     [0] = "",
     [1] = "used"
 };
 
-char *urb_complete[2] = {
+static char *urb_complete[2] = {
     [0] = "",
     [1] = "complete"
 };
 
-char *sampler_target_format[4] = {
+static char *sampler_target_format[4] = {
     [0] = "F",
     [2] = "UD",
     [3] = "D"
index 1553ce9..29df8df 100644 (file)
@@ -924,6 +924,8 @@ void brw_math2(struct brw_compile *p,
                struct brw_reg src0,
                struct brw_reg src1);
 
+void brw_EOT(struct brw_compile *p, uint32_t msg_nr);
+
 void brw_oword_block_read(struct brw_compile *p,
                           struct brw_reg dest,
                           struct brw_reg mrf,
index fe0c703..d8ea917 100644 (file)
@@ -44,7 +44,6 @@ static void guess_execution_size(struct brw_compile *p,
       insn->header.execution_size = reg.width;        /* note - definitions are compatible */
 }
 
-
 /**
  * Prior to Sandybridge, the SEND instruction accepted non-MRF source
  * registers, implicitly moving the operand to a message register.
@@ -543,28 +542,8 @@ struct brw_instruction *
 brw_next_insn(struct brw_compile *p, uint32_t opcode)
 {
    struct brw_instruction *insn;
-   assert(0);
-#if 0
-   if (p->nr_insn + 1 > p->store_size) {
-      p->store_size <<= 1;
-      p->store = reralloc(p->mem_ctx, p->store,
-                          struct brw_instruction, p->store_size);
-      if (!p->store)
-         assert(!"realloc eu store memeory failed");
-   }
-#endif
-
    insn = &p->store[p->nr_insn++];
    memcpy(insn, p->current, sizeof(*insn));
-
-   /* Reset this one-shot flag: 
-    */
-
-   if (p->current->header.destreg__conditionalmod) {
-      p->current->header.destreg__conditionalmod = 0;
-      p->current->header.predicate_control = BRW_PREDICATE_NORMAL;
-   }
-
    insn->header.opcode = opcode;
    return insn;
 }
@@ -1634,3 +1613,28 @@ void brw_SAMPLE(struct brw_compile *p,
 
 }
 
+void
+brw_EOT(struct brw_compile *p, uint32_t msg_nr)
+{
+  struct brw_instruction *insn = NULL;
+
+  brw_MOV(p, brw_message_reg(msg_nr), brw_vec8_grf(0,0));
+  insn = next_insn(p, BRW_OPCODE_SEND);
+  brw_set_dest(p, insn, brw_null_reg());
+  brw_set_src0(p, insn, brw_message_reg(msg_nr));
+  brw_set_src1(p, insn, brw_imm_ud(0));
+
+  insn->header.execution_size = BRW_EXECUTE_1;
+  insn->header.predicate_control = 0; /* XXX */
+  insn->header.compression_control = BRW_COMPRESSION_NONE;
+  insn->header.execution_size = BRW_EXECUTE_1;
+  insn->bits3.spawner_gen5.opcode = 0;
+  insn->bits3.spawner_gen5.request = 1;
+  insn->bits3.spawner_gen5.resource = 0;
+  insn->bits3.spawner_gen5.header = 0;
+  insn->bits3.spawner_gen5.response_length = 0;
+  insn->bits3.spawner_gen5.msg_length = 1;
+  insn->bits3.spawner_gen5.end_of_thread = 1;
+  insn->header.destreg__conditionalmod = BRW_SFID_THREAD_SPAWNER;
+}
+
index ca9071a..134daf9 100644 (file)
@@ -489,6 +489,19 @@ struct brw_instruction
          uint32_t end_of_thread:1;
       } generic_gen5;
 
+      struct {
+        uint32_t opcode:1;
+        uint32_t request:1;
+        uint32_t pad0:2;
+        uint32_t resource:1;
+        uint32_t pad1:14;
+        uint32_t header:1;
+        uint32_t response_length:5;
+        uint32_t msg_length:4;
+        uint32_t pad2:2;
+        uint32_t end_of_thread:1;
+      } spawner_gen5;
+
       /** G45 PRM, Volume 4, Section 6.1.1.1 */
       struct {
          uint32_t function:4;
index 324c206..0795abd 100644 (file)
 #include "ir/value.hpp"
 #include "ir/unit.hpp"
 #include "llvm/llvm_to_gen.hpp"
+#include "gen/brw_eu.h"
+#include <cstring>
 
 namespace gbe {
 namespace gen {
 
-  Kernel::Kernel(void) :
-    args(NULL), insns(NULL), argNum(0), insnNum(0), liveness(NULL), dag(NULL)
+  Kernel::Kernel(const std::string &name) :
+    name(name), args(NULL), insns(NULL), argNum(0), insnNum(0), liveness(NULL), dag(NULL)
   {}
   Kernel::~Kernel(void) {
     GBE_SAFE_DELETE_ARRAY(insns);
@@ -52,6 +54,7 @@ namespace gen {
     NOT_IMPLEMENTED;
     return false;
   }
+
   bool Program::buildFromLLVMFile(const char *fileName, std::string &error) {
     ir::Unit unit;
     if (llvmToGen(unit, fileName) == false) {
@@ -61,10 +64,127 @@ namespace gen {
     this->buildFromUnit(unit, error);
     return true;
   }
+
   bool Program::buildFromUnit(const ir::Unit &unit, std::string &error) {
-    return false;
+    const auto &set = unit.getFunctionSet();
+    const uint32_t kernelNum = set.size();
+    if (kernelNum == 0) return true;
+
+    // Dummy functions now
+    for (auto it = set.begin(); it != set.end(); ++it) {
+      const std::string &name = it->first;
+      // const ir::Function &fn = *it->second;
+      Kernel *kernel = GBE_NEW(Kernel, name);
+      brw_compile *p = (brw_compile*) GBE_MALLOC(sizeof(brw_compile));
+      std::memset(p, 0, sizeof(*p));
+      brw_EOT(p, 127);
+      kernel->insnNum = p->nr_insn;
+      kernel->insns = GBE_NEW_ARRAY(brw_instruction, kernel->insnNum);
+      std::memcpy(kernel->insns, p->store, kernel->insnNum * sizeof(brw_instruction));
+      GBE_FREE(p);
+    }
+
+    return true;
   }
 
 } /* namespace gen */
 } /* namespace gbe */
 
+/////////////////////////////////////////////////////////////////////////////
+// C interface for the Gen Programs
+/////////////////////////////////////////////////////////////////////////////
+GBE_EXPORT_SYMBOL
+GenProgram *GenProgramNewFromSource(const char *source) {
+  NOT_IMPLEMENTED;
+  return NULL;
+}
+
+GBE_EXPORT_SYMBOL
+GenProgram *GenProgramNewFromBinary(const char *binary, size_t size) {
+  NOT_IMPLEMENTED;
+  return NULL;
+}
+
+GBE_EXPORT_SYMBOL
+GenProgram *GenProgramNewFromLLVM(const char *fileName,
+                                  size_t stringSize,
+                                  char *err,
+                                  size_t *errSize)
+{
+  using namespace gbe::gen;
+  Program *program = GBE_NEW(Program);
+  std::string error;
+
+  // Try to compile the program
+  if (program->buildFromLLVMFile(fileName, error) == false) {
+    if (err != NULL && errSize != NULL && stringSize > 0u) {
+      const size_t msgSize = std::min(error.size(), stringSize-1u);
+      std::memcpy(err, error.c_str(), msgSize);
+      *errSize = error.size();
+    }
+    GBE_DELETE(program);
+    return NULL;
+  }
+
+  // Everything run fine
+  return (GenProgram *) program;
+}
+
+GBE_EXPORT_SYMBOL
+void GenProgramDelete(GenProgram *genProgram) {
+  gbe::gen::Program *program = (gbe::gen::Program*)(genProgram);
+  GBE_SAFE_DELETE(program);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// C interface for the Gen Kernels
+/////////////////////////////////////////////////////////////////////////////
+GBE_EXPORT_SYMBOL
+uint32_t GenProgramGetKernelNum(const GenProgram *genProgram) {
+  if (genProgram == NULL) return 0;
+  const gbe::gen::Program *program = (const gbe::gen::Program*) genProgram;
+  return program->getKernelNum();
+}
+
+GBE_EXPORT_SYMBOL
+const GenKernel *GenProgramGetKernel(const GenProgram *genProgram, const char *name) {
+  if (genProgram == NULL) return NULL;
+  const gbe::gen::Program *program = (const gbe::gen::Program*) genProgram;
+  return (GenKernel*) program->getKernel(std::string(name));
+}
+
+GBE_EXPORT_SYMBOL
+const char *GenKernelGetCode(const GenKernel *genKernel) {
+  if (genKernel == NULL) return NULL;
+  const gbe::gen::Kernel *kernel = (const gbe::gen::Kernel*) genKernel;
+  return kernel->getCode();
+}
+
+GBE_EXPORT_SYMBOL
+const size_t GenKernelGetCodeSize(const GenKernel *genKernel) {
+  if (genKernel == NULL) return 0u;
+  const gbe::gen::Kernel *kernel = (const gbe::gen::Kernel*) genKernel;
+  return kernel->getCodeSize();
+}
+
+GBE_EXPORT_SYMBOL
+uint32_t GenKernelGetArgNum(const GenKernel *genKernel) {
+  if (genKernel == NULL) return 0u;
+  const gbe::gen::Kernel *kernel = (const gbe::gen::Kernel*) genKernel;
+  return kernel->getArgNum();
+}
+
+GBE_EXPORT_SYMBOL
+uint32_t GenKernelGetArgSize(const GenKernel *genKernel, uint32_t argID) {
+  if (genKernel == NULL) return 0u;
+  const gbe::gen::Kernel *kernel = (const gbe::gen::Kernel*) genKernel;
+  return kernel->getArgSize(argID);
+}
+
+GBE_EXPORT_SYMBOL
+GenArgType GenKernelGetArgType(const GenKernel *genKernel, uint32_t argID) {
+  if (genKernel == NULL) return GEN_ARG_INVALID;
+  const gbe::gen::Kernel *kernel = (const gbe::gen::Kernel*) genKernel;
+  return kernel->getArgType(argID);
+}
+
index bddcc76..0a38995 100644 (file)
@@ -46,7 +46,7 @@ enum GenArgType {
   GEN_ARG_GLOBAL_PTR = 1,       // __global, __constant
   GEN_ARG_STRUCTURE = 2,        // By value structure
   GEN_ARG_IMAGE = 3,            // image2d_t, image3d_t
-  GEN_ARG_INVALUE = 0xffffffff
+  GEN_ARG_INVALID = 0xffffffff
 };
 
 /*! Create a new program from the given source code (zero terminated string) */
@@ -55,6 +55,12 @@ GenProgram *GenProgramNewFromSource(const char *source);
 /*! Create a new program from the given blob */
 GenProgram *GenProgramNewFromBinary(const char *binary, size_t size);
 
+/*! Create a new program from the given LLVM file */
+GenProgram *GenProgramNewFromLLVM(const char *fileName,
+                                  size_t stringSize,
+                                  char *err,
+                                  size_t *errSize);
+
 /*! Destroy and deallocate the given program */
 void GenProgramDelete(GenProgram *program);
 
@@ -62,7 +68,7 @@ void GenProgramDelete(GenProgram *program);
 uint32_t GenProgramGetKernelNum(const GenProgram *program);
 
 /*! Get the kernel from its name */
-const GenKernel GenProgramGetKernel(const GenProgram *program, const char *name);
+const GenKernel *GenProgramGetKernel(const GenProgram *program, const char *name);
 
 /*! Get the Gen ISA source code */
 const char *GenKernelGetCode(const GenKernel *kernel);
@@ -77,7 +83,7 @@ uint32_t GenKernelGetArgNum(const GenKernel *kernel);
 uint32_t GenKernelGetArgSize(const GenKernel *kernel, uint32_t argID);
 
 /*! Get the type of the given argument */
-GenArgType GenKernelGetArgType(const GenKernel *kernel, uint32_t argID);
+enum GenArgType GenKernelGetArgType(const GenKernel *kernel, uint32_t argID);
 
 #ifdef __cplusplus
 }
index 654e025..b117246 100644 (file)
@@ -42,8 +42,7 @@ namespace ir {
 namespace gbe {
 namespace gen {
 
-  struct KernelArgument
-  {
+  struct KernelArgument {
     GenArgType type; //!< Pointer, structure, regular value?
     size_t size;     //!< Size of each argument
   };
@@ -52,10 +51,33 @@ namespace gen {
   struct Kernel : public NonCopyable
   {
     /*! Create an empty kernel with the given name */
-    Kernel(void);
+    Kernel(const std::string &name);
     /*! Destroy it */
     ~Kernel(void);
-
+    /*! Return the instruction stream */
+    INLINE const char *getCode(void) const { return (const char*) insns; }
+    /*! Return the instruction stream size */
+    INLINE size_t getCodeSize(void) const {
+      return insnNum * sizeof(brw_instruction);
+    }
+    /*! Return the number of arguments for the kernel call */
+    INLINE uint32_t getArgNum(void) const { return argNum; }
+    /*! Return the size of the given argument */
+    INLINE uint32_t getArgSize(uint32_t argID) const {
+      if (argID >= argNum)
+        return 0u;
+      else
+        return args[argID].size;
+    }
+    /*! Return the type of the given argument */
+    INLINE GenArgType getArgType(uint32_t argID) const {
+      if (argID >= argNum)
+        return GEN_ARG_INVALID;
+      else
+        return args[argID].type;
+    }
+  private:
+    friend class Program;    //!< Owns the kernels
     std::string name;        //!< Kernel name
     KernelArgument *args;    //!< Each argument
     brw_instruction *insns;  //!< Instruction stream
@@ -73,12 +95,23 @@ namespace gen {
     Program(void);
     /*! Destroy the program */
     ~Program(void);
+    /*! Get the number of kernels in the program */
+    uint32_t getKernelNum(void) const { return kernels.size(); }
+    /*! Get the kernel from its name */
+    Kernel *getKernel(const std::string &name) const {
+      auto it = kernels.find(name);
+      if (it == kernels.end())
+        return NULL;
+      else
+        return it->second;
+    }
     /*! Build a program from a ir::Unit */
     bool buildFromUnit(const ir::Unit &unit, std::string &error);
     /*! Buils a program from a LLVM source code */
     bool buildFromLLVMFile(const char *fileName, std::string &error);
     /*! Buils a program from a OCL string */
     bool buildFromSource(const char *source, std::string &error);
+  private:
     /*! Kernels sorted by their name */
     hash_map<std::string, Kernel*> kernels;
   };
index 9666105..6045609 100644 (file)
@@ -47,10 +47,13 @@ namespace ir {
   class Unit : public NonCopyable
   {
   public:
+    typedef hash_map<std::string, Function*> FunctionSet;
     /*! Create an empty unit */
     Unit(PointerSize pointerSize = POINTER_32_BITS);
     /*! Release everything (*including* the function pointers) */
     ~Unit(void);
+    /*! Get the set of functions defined in the unit */
+    const FunctionSet &getFunctionSet(void) const { return functions; }
     /*! Retrieve the function by its name */
     Function *getFunction(const std::string &name) const;
     /*! Return NULL if the function already exists */
index f048ee0..e3de05d 100644 (file)
@@ -141,9 +141,18 @@ namespace gbe
   static MemDebugger *memDebugger = NULL;
 
   /*! Monitor maximum memory requirement in the compiler */
-  static MutexSys sizeMutex;
+  static MutexSys *sizeMutex = NULL;
+  static bool isMutexInitializing = true;
   static size_t memDebuggerCurrSize(0u);
   static size_t memDebuggerMaxSize(0u);
+  static void SizeMutexDeallocate(void) { if (sizeMutex) delete sizeMutex; }
+  static void SizeMutexAllocate(void) {
+    if (sizeMutex == NULL && isMutexInitializing == false) {
+      isMutexInitializing = true;
+      sizeMutex = new MutexSys;
+      atexit(SizeMutexDeallocate);
+    }
+  }
 
   /*! Stop the memory debugger */
   static void MemDebuggerEnd(void) {
@@ -202,10 +211,11 @@ namespace gbe
     void *ptr = std::malloc(size + sizeof(size_t));
     *(size_t *) ptr = size;
     MemDebuggerInitializeMem((char*) ptr + sizeof(size_t), size);
-    sizeMutex.lock();
+    SizeMutexAllocate();
+    if (sizeMutex) sizeMutex->lock();
     memDebuggerCurrSize += size;
     memDebuggerMaxSize = std::max(memDebuggerCurrSize, memDebuggerMaxSize);
-    sizeMutex.unlock();
+    if (sizeMutex) sizeMutex->unlock();
     return (char *) ptr + sizeof(size_t);
   }
   void memFree(void *ptr) {
@@ -213,9 +223,10 @@ namespace gbe
       char *toFree = (char*) ptr - sizeof(size_t);
       const size_t size = *(size_t *) toFree;
       MemDebuggerInitializeMem(ptr, size);
-      sizeMutex.lock();
+      SizeMutexAllocate();
+      if (sizeMutex) sizeMutex->lock();
       memDebuggerCurrSize -= size;
-      sizeMutex.unlock();
+      if (sizeMutex) sizeMutex->unlock();
       std::free(toFree);
     }
   }
@@ -238,10 +249,11 @@ namespace gbe
     ((void**)aligned)[-1] = mem;
     ((uintptr_t*)aligned)[-2] = uintptr_t(size);
     MemDebuggerInitializeMem(aligned, size);
-    sizeMutex.lock();
+    SizeMutexAllocate();
+    if (sizeMutex) sizeMutex->lock();
     memDebuggerCurrSize += size;
     memDebuggerMaxSize = std::max(memDebuggerCurrSize, memDebuggerMaxSize);
-    sizeMutex.unlock();
+    if (sizeMutex) sizeMutex->unlock();
     return aligned;
   }
 
@@ -250,9 +262,10 @@ namespace gbe
       const size_t size = ((uintptr_t*)ptr)[-2];
       MemDebuggerInitializeMem(ptr, size);
       free(((void**)ptr)[-1]);
-      sizeMutex.lock();
+      SizeMutexAllocate();
+      if (sizeMutex) sizeMutex->lock();
       memDebuggerCurrSize -= size;
-      sizeMutex.unlock();
+      if (sizeMutex) sizeMutex->unlock();
     }
   }
 } /* namespace gbe */
index 8e9fabf..83fd9c7 100644 (file)
@@ -63,6 +63,7 @@ namespace gbe
 
 /*! Declare a structure with custom allocators */
 #define GBE_STRUCT(TYPE)                                     \
+public:                                                      \
   void* operator new(size_t size)   {                        \
     if (AlignOf<TYPE>::value > sizeof(uintptr_t))            \
       return gbe::alignedMalloc(size, AlignOf<TYPE>::value); \
@@ -92,7 +93,6 @@ namespace gbe
 
 /*! Declare a class with custom allocators */
 #define GBE_CLASS(TYPE) \
-public:                 \
   GBE_STRUCT(TYPE)      \
 private: