This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/JIT/jit_codegenpreds.c

568 lines
18 KiB
C

/*************************************************************************
* *
* Extension for YAP Prolog *
* *
* Copyright G.S.Oliveira, A.F.Silva and Universidade Estadual de Maringá *
* *
* Yap Prolog was developed at NCCUP - Universidade do Porto *
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
* *
**************************************************************************
* *
* File: jit_codegenpreds.c *
* comments: JIT Compiler Codegen Options predicates *
* *
* Last rev: 2013-10-18 *
*************************************************************************/
#include "jit_predicates.hpp"
/* Predicates for LLVM Target Options configuration */
static Int p_enable_framepointer_elimination( USES_REGS1 );
static Int p_more_precise_fp_mad_option( USES_REGS1 );
static Int p_excess_fp_precision( USES_REGS1 );
static Int p_safe_fp_math( USES_REGS1 );
static Int p_rounding_mode_not_changed( USES_REGS1 );
static Int p_no_use_soft_float( USES_REGS1 );
static Int p_disable_jit_exception_handling( USES_REGS1 );
static Int p_disable_jit_emit_debug_info( USES_REGS1 );
static Int p_disable_jit_emit_debug_info_to_disk( USES_REGS1 );
static Int p_no_guaranteed_tail_call_opt( USES_REGS1 );
static Int p_enable_tail_calls( USES_REGS1 );
static Int p_disable_fast_isel( USES_REGS1 );
static Int p_disable_framepointer_elimination( USES_REGS1 );
static Int p_less_precise_fp_mad_option( USES_REGS1 );
static Int p_no_excess_fp_precision( USES_REGS1 );
static Int p_unsafe_fp_math( USES_REGS1 );
static Int p_rounding_mode_dynamically_changed( USES_REGS1 );
static Int p_use_soft_float( USES_REGS1 );
static Int p_enable_jit_exception_handling( USES_REGS1 );
static Int p_enable_jit_emit_debug_info( USES_REGS1 );
static Int p_enable_jit_emit_debug_info_to_disk( USES_REGS1 );
static Int p_guaranteed_tail_call_opt( USES_REGS1 );
static Int p_disable_tail_calls( USES_REGS1 );
static Int p_enable_fast_isel( USES_REGS1 );
static Int p_fp_abitype( USES_REGS1 );
static Int p_default_fp_abitype( USES_REGS1 );
// LLVM Execution Engine level
static Int p_engine_opt_level( USES_REGS1 );
static Int p_reset_engine_opt_level( USES_REGS1 );
// LLVM Execution Engine reloc model
static Int p_relocmodel( USES_REGS1 );
static Int p_reset_relocmodel( USES_REGS1 );
// LLVM Execution Engine code model
static Int p_codemodel( USES_REGS1 );
static Int p_reset_codemodel( USES_REGS1 );
// Enable MC JIT (experimental)
static Int p_enable_mcjit( USES_REGS1 );
// Disable MC JIT (experimental)
static Int p_disable_mcjit( USES_REGS1 );
// LLVM Register Allocator (not implemented -- for some reason, LLVM crashes when I use it on 'JIT_Compiler.cpp')
static Int p_register_allocator( USES_REGS1 );
static Int p_reset_register_allocator( USES_REGS1 );
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
static Int
p_enable_framepointer_elimination( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.noframepointerelim = FALSE;
return TRUE;
}
static Int
p_more_precise_fp_mad_option( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.lessprecisefpmadoption = FALSE;
return TRUE;
}
static Int
p_excess_fp_precision( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.noexcessfpprecision = FALSE;
return TRUE;
}
static Int
p_safe_fp_math( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.unsafefpmath = FALSE;
return TRUE;
}
static Int
p_rounding_mode_not_changed( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.honorsigndependentroundingfpmathoption = FALSE;
return TRUE;
}
static Int
p_no_use_soft_float( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.usesoftfloat = FALSE;
return TRUE;
}
static Int
p_disable_jit_exception_handling( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.jitexceptionhandling = FALSE;
return TRUE;
}
static Int
p_disable_jit_emit_debug_info( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.jitemitdebuginfo = FALSE;
return TRUE;
}
static Int
p_disable_jit_emit_debug_info_to_disk( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.jitemitdebuginfotodisk = FALSE;
return TRUE;
}
static Int
p_no_guaranteed_tail_call_opt( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.guaranteedtailcallopt = FALSE;
return TRUE;
}
static Int
p_enable_tail_calls( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.disabletailcalls = FALSE;
return TRUE;
}
static Int
p_disable_fast_isel( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.fastisel = FALSE;
return TRUE;
}
static Int
p_disable_framepointer_elimination( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.noframepointerelim = TRUE;
return TRUE;
}
static Int
p_less_precise_fp_mad_option( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.lessprecisefpmadoption = TRUE;
return TRUE;
}
static Int
p_no_excess_fp_precision( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.noexcessfpprecision = TRUE;
return TRUE;
}
static Int
p_unsafe_fp_math( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.unsafefpmath = TRUE;
return TRUE;
}
static Int
p_rounding_mode_dynamically_changed( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.honorsigndependentroundingfpmathoption = TRUE;
return TRUE;
}
static Int
p_use_soft_float( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.usesoftfloat = TRUE;
return TRUE;
}
static Int
p_enable_jit_exception_handling( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.jitexceptionhandling = TRUE;
return TRUE;
}
static Int
p_enable_jit_emit_debug_info( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.jitemitdebuginfo = TRUE;
return TRUE;
}
static Int
p_enable_jit_emit_debug_info_to_disk( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.jitemitdebuginfotodisk = TRUE;
return TRUE;
}
static Int
p_guaranteed_tail_call_opt( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.guaranteedtailcallopt = TRUE;
return TRUE;
}
static Int
p_disable_tail_calls( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.disabletailcalls = TRUE;
return TRUE;
}
static Int
p_enable_fast_isel( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.fastisel = TRUE;
return TRUE;
}
static Int
p_fp_abitype( USES_REGS1 )
{
Term t = Deref(ARG1);
Int v;
// valid values for ARG1 are 'integer' and 'atom'
if (IsIntTerm(t)) {
// ARG1 is integer
v = IntOfTerm(t);
if (v < 0 || v > 2) {
// value passed by argument is out of known range (0 = default; 1 = soft; 2 = hard)
Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,"");
return FALSE;
}
ExpEnv.codegen_struc.struc_targetopt.floatabitype = v; // setting 'float abi type'
return TRUE;
}
else if (IsAtomTerm(t)) {
// ARG1 is atom
int i = 0, j = 0;
char *tmp;
// gets string from atom and stores it on 'str'
char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(t))*sizeof(char));
strcpy(str, AtomName(AtomOfTerm(t)));
// Makes upper characters of 'str' (for comparison)
UPPER_ENTRY(str);
// Detects float abi type chosen by user
if (strcmp(str, "DEFAULT") == 0) v = 0;
else if (strcmp(str, "SOFT") == 0) v = 1;
else if (strcmp(str, "HARD") == 0) v = 2;
else {
// value passed by argument is out of known range
Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,"");
return FALSE;
}
ExpEnv.codegen_struc.struc_targetopt.floatabitype = v; // setting 'float abi type'
return TRUE;
}
else {
// ARG1 is not an integer or atom
Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"fp_abitype");
return FALSE;
}
}
static Int
p_default_fp_abitype( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_targetopt.floatabitype = 0;
return TRUE;
}
static Int
p_engine_opt_level( USES_REGS1 )
{
Term t = Deref(ARG1);
Int v;
// valid values for ARG1 are 'integer' and 'atom'
if (IsIntTerm(t)) {
// ARG1 is integer
v = IntOfTerm(t);
if (v < 0 || v > 3) {
// value passed by argument is out of known range (0 = none; 1 = less; 2 = default; 3 = aggressive)
Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,"");
return FALSE;
}
ExpEnv.codegen_struc.struc_enginebuilder.engineoptlevel = v; // setting 'engine opt level'
return TRUE;
}
else if (IsAtomTerm(t)) {
// ARG1 is atom
int i = 0, j = 0;
char *tmp;
// gets string from atom and stores it on 'str'
char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(t))*sizeof(char));
strcpy(str, AtomName(AtomOfTerm(t)));
// Makes upper characters of 'str' (for comparison)
UPPER_ENTRY(str);
// Detects engine opt level chosen by user
if (strcmp(str, "NONE") == 0) v = 0;
else if (strcmp(str, "LESS") == 0) v = 1;
else if (strcmp(str, "DEFAULT") == 0) v = 2;
else if (strcmp(str, "AGGRESSIVE") == 0) v = 3;
else {
// value passed by argument is out of known range
Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,"");
return FALSE;
}
ExpEnv.codegen_struc.struc_enginebuilder.engineoptlevel = v; // setting 'engine opt level'
return TRUE;
}
else {
// ARG1 is not an integer or atom
Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"engine_opt_level");
return FALSE;
}
}
static Int
p_reset_engine_opt_level( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_enginebuilder.engineoptlevel = 3;
return TRUE;
}
static Int
p_relocmodel( USES_REGS1 )
{
Term t = Deref(ARG1);
Int v;
// valid values for ARG1 are 'integer' and 'atom'
if (IsIntTerm(t)) {
// ARG1 is integer
v = IntOfTerm(t);
if (v < 0 || v > 3) {
// value passed by argument is out of known range (0 = default; 1 = static; 2 = PIC; 3 = DynamicNoPIC)
Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,"");
return FALSE;
}
ExpEnv.codegen_struc.struc_enginebuilder.relocmodel = v; // setting 'reloc model'
return TRUE;
}
else if (IsAtomTerm(t)) {
// ARG1 is atom
int i = 0, j = 0;
char *tmp;
// gets string from atom and stores it on 'str'
char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(t))*sizeof(char));
strcpy(str, AtomName(AtomOfTerm(t)));
// Makes upper characters of 'str' (for comparison)
UPPER_ENTRY(str);
// Detects reloc model chosen by user
if (strcmp(str, "DEFAULT") == 0) v = 0;
else if (strcmp(str, "STATIC") == 0) v = 1;
else if (strcmp(str, "PIC") == 0) v = 2;
else if (strcmp(str, "DYNAMICNOPIC") == 0) v = 3;
else {
// value passed by argument is out of known range
Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,"");
return FALSE;
}
ExpEnv.codegen_struc.struc_enginebuilder.relocmodel = v; // setting 'reloc model'
return TRUE;
}
else {
// ARG1 is not an integer or atom
Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"relocmodel");
return FALSE;
}
}
static Int
p_reset_relocmodel( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_enginebuilder.relocmodel = 0;
return TRUE;
}
static Int
p_codemodel( USES_REGS1 )
{
Term t = Deref(ARG1);
Int v;
// valid values for ARG1 are 'integer' and 'atom'
if (IsIntTerm(t)) {
// ARG1 is integer
v = IntOfTerm(t);
if (v < 0 || v > 5) {
// value passed by argument is out of known range (0 = default; 1 = JITDefault; 2 = small; 3 = kernel; 4 = medium; 5 = large)
Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,"");
return FALSE;
}
ExpEnv.codegen_struc.struc_enginebuilder.codemodel = v; // setting 'code model'
return TRUE;
}
else if (IsAtomTerm(t)) {
// ARG1 is atom
int i = 0, j = 0;
char *tmp;
// gets string from atom and stores it on 'str'
char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(t))*sizeof(char));
strcpy(str, AtomName(AtomOfTerm(t)));
// Makes upper characters of 'str' (for comparison)
UPPER_ENTRY(str);
// Detects code chosen by user
if (strcmp(str, "DEFAULT") == 0) v = 0;
else if (strcmp(str, "JITDEFAULT") == 0) v = 1;
else if (strcmp(str, "SMALL") == 0) v = 2;
else if (strcmp(str, "KERNEL") == 0) v = 3;
else if (strcmp(str, "MEDIUM") == 0) v = 4;
else if (strcmp(str, "LARGE") == 0) v = 5;
else {
// value passed by argument is out of known range
Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,"");
return FALSE;
}
ExpEnv.codegen_struc.struc_enginebuilder.codemodel = v; // setting 'code model'
return TRUE;
}
else {
// ARG1 is not an integer or atom
Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"codemodel");
return FALSE;
}
}
static Int
p_reset_codemodel( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_enginebuilder.codemodel = 1;
return TRUE;
}
static Int
p_enable_mcjit( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_enginebuilder.usemcjit = 1;
return TRUE;
}
static Int
p_disable_mcjit( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_enginebuilder.usemcjit = 0;
return TRUE;
}
static Int
p_register_allocator( USES_REGS1 )
{
Term t = Deref(ARG1);
// valid values for ARG1 are 'integer' and 'atom'
if (IsIntTerm(t)) {
// ARG1 is integer
Int v = IntOfTerm(t);
if (v < 0 || v > 3) {
// value passed by argument is out of known range (0 = basic; 1 = fast; 2 = greedy; 3 = PBQP)
Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,"");
return FALSE;
}
ExpEnv.codegen_struc.struc_enginebuilder.regallocator = (enumRegAllocator)v; // setting 'register allocator'
return TRUE;
}
else if (IsAtomTerm(t)) {
// ARG1 is atom
enumRegAllocator v;
int i = 0, j = 0;
char *tmp;
// gets string from atom and stores it on 'str'
char *str = (char*)malloc(YAP_AtomNameLength(AtomOfTerm(t))*sizeof(char));
strcpy(str, AtomName(AtomOfTerm(t)));
// Makes upper characters of 'str' (for comparison)
UPPER_ENTRY(str);
// Detects register allocator chosen by user
if (strcmp(str, "BASIC") == 0) v = REG_ALLOC_BASIC;
else if (strcmp(str, "FAST") == 0) v = REG_ALLOC_FAST;
else if (strcmp(str, "GREEDY") == 0) v = REG_ALLOC_GREEDY;
else if (strcmp(str, "PBQP") == 0) v = REG_ALLOC_PBQP;
else {
// value passed by argument is out of known range
Yap_Error(OUT_OF_KNOWNRANGE_ERROR,t,"");
return FALSE;
}
ExpEnv.codegen_struc.struc_enginebuilder.regallocator = v; // setting 'register allocator'
return TRUE;
}
else {
// ARG1 is not an integer or atom
Yap_NilError(INVALID_PARAMETER_TYPE_ERROR,"register_allocator");
return FALSE;
}
}
static Int
p_reset_register_allocator( USES_REGS1 )
{
ExpEnv.codegen_struc.struc_enginebuilder.regallocator = REG_ALLOC_GREEDY;
return TRUE;
}
#pragma GCC diagnostic pop
void
Yap_InitJitCodegenPreds( void )
{
Yap_InitCPred("enable_framepointer_elimination", 0, p_enable_framepointer_elimination, SafePredFlag);
Yap_InitCPred("more_precise_fp_mad_option", 0, p_more_precise_fp_mad_option, SafePredFlag);
Yap_InitCPred("excess_fp_precision", 0, p_excess_fp_precision, SafePredFlag);
Yap_InitCPred("safe_fp_math", 0, p_safe_fp_math, SafePredFlag);
Yap_InitCPred("rounding_mode_not_changed", 0, p_rounding_mode_not_changed, SafePredFlag);
Yap_InitCPred("no_use_soft_float", 0, p_no_use_soft_float, SafePredFlag);
Yap_InitCPred("disable_jit_exception_handling", 0, p_disable_jit_exception_handling, SafePredFlag);
Yap_InitCPred("disable_jit_emit_debug_info", 0, p_disable_jit_emit_debug_info, SafePredFlag);
Yap_InitCPred("disable_jit_emit_debug_info_to_disk", 0, p_disable_jit_emit_debug_info_to_disk, SafePredFlag);
Yap_InitCPred("no_guaranteed_tail_call_opt", 0, p_no_guaranteed_tail_call_opt, SafePredFlag);
Yap_InitCPred("enable_tail_calls", 0, p_enable_tail_calls, SafePredFlag);
Yap_InitCPred("disable_fast_isel", 0, p_disable_fast_isel, SafePredFlag);
Yap_InitCPred("disable_framepointer_elimination", 0, p_disable_framepointer_elimination, SafePredFlag);
Yap_InitCPred("less_precise_fp_mad_option", 0, p_less_precise_fp_mad_option, SafePredFlag);
Yap_InitCPred("no_excess_fp_precision", 0, p_no_excess_fp_precision, SafePredFlag);
Yap_InitCPred("unsafe_fp_math", 0, p_unsafe_fp_math, SafePredFlag);
Yap_InitCPred("rounding_mode_dynamically_changed", 0, p_rounding_mode_dynamically_changed, SafePredFlag);
Yap_InitCPred("use_soft_float", 0, p_use_soft_float, SafePredFlag);
Yap_InitCPred("enable_jit_exception_handling", 0, p_enable_jit_exception_handling, SafePredFlag);
Yap_InitCPred("enable_jit_emit_debug_info", 0, p_enable_jit_emit_debug_info, SafePredFlag);
Yap_InitCPred("enable_jit_emit_debug_info_to_disk", 0, p_enable_jit_emit_debug_info_to_disk, SafePredFlag);
Yap_InitCPred("guaranteed_tail_call_opt", 0, p_guaranteed_tail_call_opt, SafePredFlag);
Yap_InitCPred("disable_tail_calls", 0, p_disable_tail_calls, SafePredFlag);
Yap_InitCPred("enable_fast_isel", 0, p_enable_fast_isel, SafePredFlag);
Yap_InitCPred("fp_abitype", 1, p_fp_abitype, SafePredFlag);
Yap_InitCPred("default_fp_abitype", 0, p_default_fp_abitype, SafePredFlag);
Yap_InitCPred("engine_opt_level", 1, p_engine_opt_level, SafePredFlag);
Yap_InitCPred("reset_engine_opt_level", 0, p_reset_engine_opt_level, SafePredFlag);
Yap_InitCPred("relocmodel", 1, p_relocmodel, SafePredFlag);
Yap_InitCPred("reset_relocmodel", 0, p_reset_relocmodel, SafePredFlag);
Yap_InitCPred("codemodel", 1, p_codemodel, SafePredFlag);
Yap_InitCPred("reset_codemodel", 0, p_reset_codemodel, SafePredFlag);
Yap_InitCPred("enable_mcjit", 0, p_enable_mcjit, SafePredFlag);
Yap_InitCPred("disable_mcjit", 0, p_disable_mcjit, SafePredFlag);
Yap_InitCPred("register_allocator", 1, p_register_allocator, SafePredFlag);
Yap_InitCPred("reset_register_allocator", 0, p_reset_register_allocator, SafePredFlag);
}