#include "radeon_llvm_emit.h"
#include "radeon_elf_util.h"
#include "util/u_memory.h"
+#include "pipe/p_shader_tokens.h"
#include <llvm-c/Target.h>
#include <llvm-c/TargetMachine.h>
#define FS_STRING_LEN 30
#define TRIPLE_STRING_LEN 7
+/**
+ * Shader types for the LLVM backend.
+ */
+enum radeon_llvm_shader_type {
+ RADEON_LLVM_SHADER_PS = 0,
+ RADEON_LLVM_SHADER_VS = 1,
+ RADEON_LLVM_SHADER_GS = 2,
+ RADEON_LLVM_SHADER_CS = 3,
+};
+
/**
* Set the shader type we want to compile
*
*/
void radeon_llvm_shader_type(LLVMValueRef F, unsigned type)
{
- char Str[2];
- sprintf(Str, "%1d", type);
+ char Str[2];
+ enum radeon_llvm_shader_type llvm_type;
+
+ switch (type) {
+ case TGSI_PROCESSOR_VERTEX:
+ case TGSI_PROCESSOR_TESS_CTRL:
+ case TGSI_PROCESSOR_TESS_EVAL:
+ llvm_type = RADEON_LLVM_SHADER_VS;
+ break;
+ case TGSI_PROCESSOR_GEOMETRY:
+ llvm_type = RADEON_LLVM_SHADER_GS;
+ break;
+ case TGSI_PROCESSOR_FRAGMENT:
+ llvm_type = RADEON_LLVM_SHADER_PS;
+ break;
+ case TGSI_PROCESSOR_COMPUTE:
+ llvm_type = RADEON_LLVM_SHADER_CS;
+ break;
+ default:
+ assert(0);
+ }
- LLVMAddTargetDependentFunctionAttr(F, "ShaderType", Str);
+ sprintf(Str, "%1d", llvm_type);
+
+ LLVMAddTargetDependentFunctionAttr(F, "ShaderType", Str);
+
+ if (type != TGSI_PROCESSOR_COMPUTE) {
+ LLVMAddTargetDependentFunctionAttr(F, "unsafe-fp-math", "true");
+ }
}
-static void init_r600_target() {
+static void init_r600_target()
+{
static unsigned initialized = 0;
if (!initialized) {
+#if HAVE_LLVM < 0x0307
LLVMInitializeR600TargetInfo();
LLVMInitializeR600Target();
LLVMInitializeR600TargetMC();
LLVMInitializeR600AsmPrinter();
+#else
+ LLVMInitializeAMDGPUTargetInfo();
+ LLVMInitializeAMDGPUTarget();
+ LLVMInitializeAMDGPUTargetMC();
+ LLVMInitializeAMDGPUAsmPrinter();
+
+#endif
initialized = 1;
}
}
-static LLVMTargetRef get_r600_target() {
+LLVMTargetRef radeon_llvm_get_r600_target(const char *triple)
+{
LLVMTargetRef target = NULL;
+ char *err_message = NULL;
- for (target = LLVMGetFirstTarget(); target;
- target = LLVMGetNextTarget(target)) {
- if (!strncmp(LLVMGetTargetName(target), "r600", 4)) {
- break;
- }
- }
+ init_r600_target();
- if (!target) {
- fprintf(stderr, "Can't find target r600\n");
+ if (LLVMGetTargetFromTriple(triple, &target, &err_message)) {
+ fprintf(stderr, "Cannot find target for triple %s ", triple);
+ if (err_message) {
+ fprintf(stderr, "%s\n", err_message);
+ }
+ LLVMDisposeMessage(err_message);
return NULL;
}
return target;
#if HAVE_LLVM >= 0x0305
-static void radeonDiagnosticHandler(LLVMDiagnosticInfoRef di, void *context) {
+static void radeonDiagnosticHandler(LLVMDiagnosticInfoRef di, void *context)
+{
if (LLVMGetDiagInfoSeverity(di) == LLVMDSError) {
unsigned int *diagnosticflag = (unsigned int *)context;
char *diaginfo_message = LLVMGetDiagInfoDescription(di);
* @returns 0 for success, 1 for failure
*/
unsigned radeon_llvm_compile(LLVMModuleRef M, struct radeon_shader_binary *binary,
- const char * gpu_family, unsigned dump) {
+ const char *gpu_family, unsigned dump, LLVMTargetMachineRef tm)
+{
- LLVMTargetRef target;
- LLVMTargetMachineRef tm;
char cpu[CPU_STRING_LEN];
char fs[FS_STRING_LEN];
char *err;
+ bool dispose_tm = false;
LLVMContextRef llvm_ctx;
unsigned rval = 0;
LLVMMemoryBufferRef out_buffer;
char triple[TRIPLE_STRING_LEN];
LLVMBool mem_err;
- /* initialise */
- init_r600_target();
-
- target = get_r600_target();
- if (!target) {
- return 1;
+ if (!tm) {
+ strncpy(triple, "r600--", TRIPLE_STRING_LEN);
+ LLVMTargetRef target = radeon_llvm_get_r600_target(triple);
+ if (!target) {
+ return 1;
+ }
+ strncpy(cpu, gpu_family, CPU_STRING_LEN);
+ memset(fs, 0, sizeof(fs));
+ if (dump) {
+ strncpy(fs, "+DumpCode", FS_STRING_LEN);
+ }
+ tm = LLVMCreateTargetMachine(target, triple, cpu, fs,
+ LLVMCodeGenLevelDefault, LLVMRelocDefault,
+ LLVMCodeModelDefault);
+ dispose_tm = true;
}
-
- strncpy(cpu, gpu_family, CPU_STRING_LEN);
- memset(fs, 0, sizeof(fs));
if (dump) {
LLVMDumpModule(M);
- strncpy(fs, "+DumpCode", FS_STRING_LEN);
}
- strncpy(triple, "r600--", TRIPLE_STRING_LEN);
-
/* Setup Diagnostic Handler*/
llvm_ctx = LLVMGetModuleContext(M);
rval = 0;
/* Compile IR*/
- tm = LLVMCreateTargetMachine(target, triple, cpu, fs,
- LLVMCodeGenLevelDefault, LLVMRelocDefault,
- LLVMCodeModelDefault);
mem_err = LLVMTargetMachineEmitToMemoryBuffer(tm, M, LLVMObjectFile, &err,
&out_buffer);
buffer_size = LLVMGetBufferSize(out_buffer);
buffer_data = LLVMGetBufferStart(out_buffer);
- radeon_elf_read(buffer_data, buffer_size, binary, dump);
+ radeon_elf_read(buffer_data, buffer_size, binary);
/* Clean up */
LLVMDisposeMemoryBuffer(out_buffer);
- LLVMDisposeTargetMachine(tm);
+
+ if (dispose_tm) {
+ LLVMDisposeTargetMachine(tm);
+ }
return rval;
}