Adding saturated builtins. Remove LLVM 12 support. Remove old llvm optimizer use.

This commit is contained in:
Christoffer Lerno
2022-09-17 11:38:28 +02:00
committed by Christoffer Lerno
parent fd9d300b06
commit a66c0942f8
18 changed files with 217 additions and 235 deletions

View File

@@ -164,7 +164,7 @@ jobs:
fail-fast: false
matrix:
build_type: [Release, Debug]
llvm_version: [12, 13, 14, 15, 16]
llvm_version: [13, 14, 15, 16]
steps:
- uses: actions/checkout@v3
@@ -182,10 +182,7 @@ jobs:
fi
sudo apt-get update
sudo apt-get install -y clang-${{matrix.llvm_version}} llvm-${{matrix.llvm_version}} llvm-${{matrix.llvm_version}}-dev lld-${{matrix.llvm_version}} liblld-${{matrix.llvm_version}}-dev
if [[ "${{matrix.llvm_version}}" > 12 ]]; then
sudo apt-get install -y libmlir-${{matrix.llvm_version}} libmlir-${{matrix.llvm_version}}-dev mlir-${{matrix.llvm_version}}-tools
fi
- name: CMake
run: |
@@ -251,7 +248,7 @@ jobs:
fail-fast: false
matrix:
build_type: [Release, Debug]
llvm_version: [12, 13, 14]
llvm_version: [13, 14]
steps:
- uses: actions/checkout@v3
- name: Download LLVM

View File

@@ -44,7 +44,7 @@ if(C3_USE_MIMALLOC)
endif()
if (NOT C3_LLVM_VERSION STREQUAL "auto")
if (${C3_LLVM_VERSION} VERSION_LESS 12 OR ${C3_LLVM_VERSION} VERSION_GREATER 16)
if (${C3_LLVM_VERSION} VERSION_LESS 13 OR ${C3_LLVM_VERSION} VERSION_GREATER 16)
message(FATAL_ERROR "LLVM ${C3_LLVM_VERSION} is not supported!")
endif()
endif()

View File

@@ -261,7 +261,7 @@ You can try it out by running some sample code: `c3c.exe compile ../resources/ex
1. Make sure you have a C compiler that handles C11 and a C++ compiler, such as GCC or Clang. Git also needs to be installed.
2. Install CMake: `sudo apt install cmake`
3. Install LLVM 12 (or greater: C3C supports LLVM 12-16): `sudo apt-get install clang-12 zlib1g zlib1g-dev libllvm12 llvm-12 llvm-12-dev llvm-12-runtime liblld-12-dev liblld-12`
3. Install LLVM 13 (or greater: C3C supports LLVM 13-16): `sudo apt-get install clang-13 zlib1g zlib1g-dev libllvm13 llvm-13 llvm-13-dev llvm-13-runtime liblld-13-dev liblld-13`
4. Clone the C3C github repository: `git clone https://github.com/c3lang/c3c.git`
5. Enter the C3C directory `cd c3c`.
6. Create a build directory `mkdir build`
@@ -277,7 +277,7 @@ You can try it out by running some sample code: `./c3c compile ../resources/exam
#### Compiling on other Linux / Unix variants
1. Install CMake.
2. Install or compile LLVM and LLD *libraries* (version 12+ or higher)
2. Install or compile LLVM and LLD *libraries* (version 13+ or higher)
3. Clone the C3C github repository: `git clone https://github.com/c3lang/c3c.git`
4. Enter the C3C directory `cd c3c`.
5. Create a build directory `mkdir build`

View File

@@ -29,17 +29,14 @@ else
fi
TAG="$1"
if [ "$1" = 20 ]; then
UBUNTU_VERSION="20.04"
LLVM_VERSION="12"
elif [ "$1" = 21 ]; then
if [ "$1" = 21 ]; then
UBUNTU_VERSION="21.10"
LLVM_VERSION="13"
elif [ "$1" = 22 ]; then
UBUNTU_VERSION="22.04"
LLVM_VERSION="14"
else
echo "ERROR: expected 20, 21 or 22 as Ubuntu version argument" 1>&2
echo "ERROR: expected 21 or 22 as Ubuntu version argument" 1>&2
exit 2
fi
IMAGE="$IMAGE:$TAG"

View File

@@ -114,7 +114,6 @@ static void usage(void)
OUTPUT(" -L <library dir> - Append the directory to the linker search paths.");
OUTPUT(" -z <argument> - Send the <argument> as a parameter to the linker.");
OUTPUT(" --forcelinker - Force built in linker usage when doing non-cross linking.");
OUTPUT(" --newoptimizer - Use new optimizer pipeline.");
OUTPUT("");
OUTPUT(" --reloc=<option> - Relocation model: none, pic, PIC, pie, PIE");
OUTPUT(" --x86vec=<option> - Set max level of vector instructions: none, mmx, sse, avx, avx512.");
@@ -465,21 +464,9 @@ static void parse_option(BuildOptions *options)
options->symtab_size = next_highest_power_of_2(symtab);
return;
}
if (match_longopt("newoptimizer"))
{
options->use_new_optimizer = true;
return;
}
if (match_longopt("forcelinker"))
{
if (llvm_version_major > 12)
{
options->force_linker = true;
}
else
{
printf("Force linking ignored on LLVM 12 and earlier.\n");
}
return;
}
if (match_longopt("version"))

View File

@@ -257,7 +257,6 @@ typedef struct BuildOptions_
bool test_mode;
bool no_stdlib;
bool force_linker;
bool use_new_optimizer;
const char *panicfn;
const char *cc;
const char *build_dir;
@@ -334,7 +333,6 @@ typedef struct
bool no_stdlib;
bool emit_object_files;
bool force_linker;
bool use_new_optimizer;
OptimizationLevel optimization_level;
SizeOptimizationLevel size_optimization_level;
DebugInfo debug_info;

View File

@@ -195,7 +195,6 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
target->emit_llvm = options->emit_llvm;
target->emit_asm = options->emit_asm;
target->force_linker = options->force_linker;
target->use_new_optimizer = options->use_new_optimizer;
target->panicfn = options->panicfn;
if (options->macos.sdk) target->macos.sdk = options->macos.sdk;
if (options->win.sdk) target->win.sdk = options->win.sdk;

View File

@@ -813,6 +813,9 @@ typedef enum
BUILTIN_RINT,
BUILTIN_ROUND,
BUILTIN_ROUNDEVEN,
BUILTIN_SAT_ADD,
BUILTIN_SAT_SUB,
BUILTIN_SAT_SHL,
BUILTIN_SIN,
BUILTIN_SHUFFLEVECTOR,
BUILTIN_SQRT,

View File

@@ -4,8 +4,9 @@
#include "llvm_codegen_internal.h"
#if LLVM_VERSION_MAJOR > 12
#include <llvm-c/Error.h>
#include <llvm-c/Comdat.h>
typedef struct LLVMOpaquePassBuilderOptions *LLVMPassBuilderOptionsRef;
LLVMErrorRef LLVMRunPasses(LLVMModuleRef M, const char *Passes,
LLVMTargetMachineRef TM,
@@ -14,7 +15,6 @@ LLVMPassBuilderOptionsRef LLVMCreatePassBuilderOptions(void);
void LLVMPassBuilderOptionsSetVerifyEach(LLVMPassBuilderOptionsRef Options, LLVMBool VerifyEach);
void LLVMPassBuilderOptionsSetDebugLogging(LLVMPassBuilderOptionsRef Options, LLVMBool DebugLogging);
void LLVMDisposePassBuilderOptions(LLVMPassBuilderOptionsRef Options);
#endif
const char* llvm_version = LLVM_VERSION_STRING;
const char* llvm_target = LLVM_DEFAULT_TARGET_TRIPLE;
@@ -637,6 +637,7 @@ void llvm_codegen_setup()
intrinsic_id.sadd_overflow = lookup_intrinsic("llvm.sadd.with.overflow");
intrinsic_id.sadd_sat = lookup_intrinsic("llvm.sadd.sat");
intrinsic_id.sin = lookup_intrinsic("llvm.sin");
intrinsic_id.sshl_sat = lookup_intrinsic("llvm.sshl.sat");
intrinsic_id.smax = lookup_intrinsic("llvm.smax");
intrinsic_id.smin = lookup_intrinsic("llvm.smin");
intrinsic_id.smul_overflow = lookup_intrinsic("llvm.smul.with.overflow");
@@ -651,6 +652,7 @@ void llvm_codegen_setup()
intrinsic_id.umin = lookup_intrinsic("llvm.umin");
intrinsic_id.umul_overflow = lookup_intrinsic("llvm.umul.with.overflow");
intrinsic_id.usub_overflow = lookup_intrinsic("llvm.usub.with.overflow");
intrinsic_id.ushl_sat = lookup_intrinsic("llvm.ushl.sat");
intrinsic_id.usub_sat = lookup_intrinsic("llvm.usub.sat");
intrinsic_id.vector_reduce_fmax = lookup_intrinsic("llvm.vector.reduce.fmax");
intrinsic_id.vector_reduce_fmin = lookup_intrinsic("llvm.vector.reduce.fmin");
@@ -806,46 +808,8 @@ static void llvm_emit_type_decls(GenContext *context, Decl *decl)
}
}
static inline void llvm_opt_old(GenContext *c)
{
LLVMPassManagerBuilderRef pass_manager_builder = LLVMPassManagerBuilderCreate();
LLVMPassManagerBuilderSetOptLevel(pass_manager_builder, (unsigned)active_target.optimization_level);
LLVMPassManagerBuilderSetSizeLevel(pass_manager_builder, (unsigned)active_target.size_optimization_level);
LLVMPassManagerBuilderSetDisableUnrollLoops(pass_manager_builder, active_target.optimization_level == OPTIMIZATION_NONE);
if (active_target.optimization_level != OPTIMIZATION_NONE)
{
LLVMPassManagerBuilderUseInlinerWithThreshold(pass_manager_builder, (unsigned)get_inlining_threshold());
}
LLVMPassManagerRef pass_manager = LLVMCreatePassManager();
LLVMPassManagerRef function_pass_manager = LLVMCreateFunctionPassManagerForModule(c->module);
LLVMAddAnalysisPasses(c->machine, function_pass_manager);
LLVMAddAnalysisPasses(c->machine, pass_manager);
LLVMPassManagerBuilderPopulateModulePassManager(pass_manager_builder, pass_manager);
LLVMPassManagerBuilderPopulateFunctionPassManager(pass_manager_builder, function_pass_manager);
// IMPROVE
// In LLVM Opt, LoopVectorize and SLPVectorize settings are part of the PassManagerBuilder
// Anything else we need to manually add?
LLVMPassManagerBuilderDispose(pass_manager_builder);
// Run function passes
LLVMInitializeFunctionPassManager(function_pass_manager);
LLVMValueRef current_function = LLVMGetFirstFunction(c->module);
while (current_function)
{
LLVMRunFunctionPassManager(function_pass_manager, current_function);
current_function = LLVMGetNextFunction(current_function);
}
LLVMFinalizeFunctionPassManager(function_pass_manager);
LLVMDisposePassManager(function_pass_manager);
// Run module pass
LLVMRunPassManager(pass_manager, c->module);
LLVMDisposePassManager(pass_manager);
}
#if LLVM_VERSION_MAJOR > 12
static inline void llvm_opt_new(GenContext *c)
static inline void llvm_optimize(GenContext *c)
{
LLVMPassBuilderOptionsRef options = LLVMCreatePassBuilderOptions();
LLVMPassBuilderOptionsSetVerifyEach(options, active_target.emit_llvm);
@@ -884,20 +848,11 @@ static inline void llvm_opt_new(GenContext *c)
}
LLVMDisposePassBuilderOptions(options);
}
#endif
const char *llvm_codegen(void *context)
{
GenContext *c = context;
#if LLVM_VERSION_MAJOR > 12
if (active_target.use_new_optimizer)
{
llvm_opt_new(c);
}
else
#endif
{
llvm_opt_old(c);
}
llvm_optimize(c);
// Serialize the LLVM IR, if requested, also verify the IR in this case
if (active_target.emit_llvm)

View File

@@ -4346,6 +4346,9 @@ unsigned llvm_get_intrinsic(BuiltinFunction func)
case BUILTIN_ABS:
case BUILTIN_SHUFFLEVECTOR:
case BUILTIN_REVERSE:
case BUILTIN_SAT_ADD:
case BUILTIN_SAT_SHL:
case BUILTIN_SAT_SUB:
UNREACHABLE
case BUILTIN_SYSCLOCK:
return intrinsic_id.readcyclecounter;
@@ -4454,11 +4457,7 @@ static inline LLVMValueRef llvm_syscall_asm(GenContext *c, LLVMTypeRef func_type
{
return LLVMGetInlineAsm(func_type, call, strlen(call),
scratch_buffer_to_string(), scratch_buffer.len,
true, true, LLVMInlineAsmDialectATT
#if LLVM_VERSION_MAJOR > 12
, /* can throw */ false
#endif
);
true, true, LLVMInlineAsmDialectATT, /* can throw */ false);
}
static inline void llvm_emit_syscall(GenContext *c, BEValue *be_value, Expr *expr)
@@ -4582,39 +4581,53 @@ INLINE void llvm_emit_reverse(GenContext *c, BEValue *result_value, Expr *expr)
llvm_value_set(result_value, LLVMBuildShuffleVector(c->builder, arg1, arg2, mask, "reverse"), rtype);
}
INLINE unsigned llvm_intrinsic_by_type(Type *type, unsigned int_intrinsic, unsigned uint_intrinsic, unsigned float_intrinsic)
{
type = type_flatten(type);
RETRY:
switch (type->type_kind)
{
case ALL_SIGNED_INTS:
return int_intrinsic;
case TYPE_BOOL:
case ALL_UNSIGNED_INTS:
return uint_intrinsic;
case ALL_FLOATS:
return float_intrinsic;
case TYPE_VECTOR:
type = type->array.base;
goto RETRY;
default:
UNREACHABLE
}
}
void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr)
{
BuiltinFunction func = exprptr(expr->call_expr.function)->builtin_expr.builtin;
if (func == BUILTIN_UNREACHABLE)
unsigned intrinsic;
switch (func)
{
case BUILTIN_UNREACHABLE:
llvm_value_set(result_value, LLVMBuildUnreachable(c->builder), type_void);
c->current_block = NULL;
c->current_block_is_target = false;
LLVMBasicBlockRef after_unreachable = llvm_basic_block_new(c, "after.unreachable");
llvm_emit_block(c, after_unreachable);
return;
}
if (func == BUILTIN_SHUFFLEVECTOR)
{
case BUILTIN_SHUFFLEVECTOR:
llvm_emit_shufflevector(c, result_value, expr);
return;
}
if (func == BUILTIN_REVERSE)
{
case BUILTIN_REVERSE:
llvm_emit_reverse(c, result_value, expr);
return;
}
if (func == BUILTIN_STACKTRACE)
{
case BUILTIN_STACKTRACE:
if (!c->debug.enable_stacktrace)
{
llvm_value_set(result_value, llvm_get_zero(c, type_voidptr), type_voidptr);
return;
}
llvm_value_set(result_value, llvm_emit_bitcast(c, c->debug.stack_slot, type_voidptr), type_voidptr);
return;
}
if (func == BUILTIN_VOLATILE_STORE)
case BUILTIN_VOLATILE_STORE:
{
BEValue value;
llvm_emit_expr(c, &value, expr->call_expr.arguments[0]);
@@ -4626,7 +4639,7 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr)
if (store) LLVMSetVolatile(store, true);
return;
}
if (func == BUILTIN_VOLATILE_LOAD)
case BUILTIN_VOLATILE_LOAD:
{
llvm_emit_expr(c, result_value, expr->call_expr.arguments[0]);
llvm_value_rvalue(c, result_value);
@@ -4636,81 +4649,45 @@ void llvm_emit_builtin_call(GenContext *c, BEValue *result_value, Expr *expr)
LLVMSetVolatile(result_value->value, true);
return;
}
if (func == BUILTIN_SYSCALL)
{
case BUILTIN_SYSCALL:
llvm_emit_syscall(c, result_value, expr);
return;
}
unsigned intrinsic;
if (func == BUILTIN_MAX)
{
Type *type = type_flatten(expr->call_expr.arguments[0]->type);
RETRY:
switch (type->type_kind)
{
case ALL_SIGNED_INTS:
intrinsic = intrinsic_id.smax;
case BUILTIN_MAX:
intrinsic = llvm_intrinsic_by_type(expr->call_expr.arguments[0]->type,
intrinsic_id.smax,
intrinsic_id.umax,
intrinsic_id.maxnum);
break;
case TYPE_BOOL:
case ALL_UNSIGNED_INTS:
intrinsic = intrinsic_id.umax;
case BUILTIN_MIN:
intrinsic = llvm_intrinsic_by_type(expr->call_expr.arguments[0]->type,
intrinsic_id.smin,
intrinsic_id.umin,
intrinsic_id.minnum);
break;
case ALL_FLOATS:
intrinsic = intrinsic_id.maxnum;
case BUILTIN_ABS:
intrinsic = llvm_intrinsic_by_type(expr->call_expr.arguments[0]->type,
intrinsic_id.abs,
intrinsic_id.abs,
intrinsic_id.fabs);
break;
case BUILTIN_SAT_SHL:
intrinsic = llvm_intrinsic_by_type(expr->call_expr.arguments[0]->type,
intrinsic_id.sshl_sat,
intrinsic_id.ushl_sat, 0);
break;
case BUILTIN_SAT_ADD:
intrinsic = llvm_intrinsic_by_type(expr->call_expr.arguments[0]->type,
intrinsic_id.sadd_sat,
intrinsic_id.uadd_sat, 0);
break;
case BUILTIN_SAT_SUB:
intrinsic = llvm_intrinsic_by_type(expr->call_expr.arguments[0]->type,
intrinsic_id.ssub_sat,
intrinsic_id.usub_sat, 0);
break;
case TYPE_VECTOR:
type = type->array.base;
goto RETRY;
default:
UNREACHABLE
}
}
else if (func == BUILTIN_MIN)
{
Type *type = type_flatten(expr->call_expr.arguments[0]->type);
RETRY2:
switch (type->type_kind)
{
case ALL_SIGNED_INTS:
intrinsic = intrinsic_id.smin;
break;
case TYPE_BOOL:
case ALL_UNSIGNED_INTS:
intrinsic = intrinsic_id.umin;
break;
case ALL_FLOATS:
intrinsic = intrinsic_id.minnum;
break;
case TYPE_VECTOR:
type = type->array.base;
goto RETRY2;
default:
UNREACHABLE
}
}
else if (func == BUILTIN_ABS)
{
Type *type = type_flatten(expr->call_expr.arguments[0]->type);
RETRY3:
switch (type->type_kind)
{
case TYPE_BOOL:
case ALL_INTS:
intrinsic = intrinsic_id.abs;
break;
case ALL_FLOATS:
intrinsic = intrinsic_id.fabs;
break;
case TYPE_VECTOR:
type = type->array.base;
goto RETRY3;
default:
UNREACHABLE
}
}
else
{
intrinsic = llvm_get_intrinsic(func);
break;
}
llvm_emit_intrinsic_expr(c, intrinsic, result_value, expr);
}

View File

@@ -12,13 +12,6 @@
#include <llvm-c/Analysis.h>
#include <llvm-c/BitWriter.h>
#include <llvm-c/DebugInfo.h>
#include <llvm-c/Transforms/PassManagerBuilder.h>
#include <llvm-c/Transforms/InstCombine.h>
#include <llvm-c/Transforms/Vectorize.h>
#include <llvm-c/Transforms/Scalar.h>
#include <llvm-c/Transforms/IPO.h>
#include <llvm-c/Transforms/Utils.h>
#include <llvm-c/Comdat.h>
#include "dwarf.h"
#define SLICE_MAX_UNROLL 4

View File

@@ -1188,10 +1188,8 @@ static inline void llvm_emit_asm_block_stmt(GenContext *c, Ast *ast)
strlen(clobbers),
ast->asm_block_stmt.is_volatile,
true,
ast->asm_block_stmt.is_string ? LLVMInlineAsmDialectIntel : LLVMInlineAsmDialectATT
#if LLVM_VERSION_MAJOR > 12
, /* can throw */ false
#endif
ast->asm_block_stmt.is_string ? LLVMInlineAsmDialectIntel : LLVMInlineAsmDialectATT,
/* can throw */ false
);
LLVMValueRef res = LLVMBuildCall2(c->builder, asm_fn_type, asm_fn, args, param_count, "");
#if LLVM_VERSION_MAJOR > 13

View File

@@ -2534,6 +2534,9 @@ static inline unsigned builtin_expected_args(BuiltinFunction func)
case BUILTIN_MIN:
case BUILTIN_POW:
case BUILTIN_VOLATILE_STORE:
case BUILTIN_SAT_ADD:
case BUILTIN_SAT_SUB:
case BUILTIN_SAT_SHL:
return 2;
case BUILTIN_FMA:
case BUILTIN_FSHL:
@@ -2854,6 +2857,15 @@ static inline bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *ex
arg_count)) return false;
rtype = args[0]->type;
break;
case BUILTIN_SAT_SHL:
case BUILTIN_SAT_SUB:
case BUILTIN_SAT_ADD:
if (!sema_check_builtin_args(args,
(BuiltinArg[]) { BA_INTLIKE, BA_INTLIKE },
arg_count)) return false;
if (!sema_check_builtin_args_match(args, 2)) return false;
rtype = args[0]->type;
break;
case BUILTIN_REVERSE:
if (!sema_check_builtin_args(args, (BuiltinArg[]) { BA_VEC }, arg_count)) return false;
rtype = args[0]->type;

View File

@@ -208,6 +208,9 @@ void symtab_init(uint32_t capacity)
builtin_list[BUILTIN_RINT] = KW_DEF("rint");
builtin_list[BUILTIN_ROUND] = KW_DEF("round");
builtin_list[BUILTIN_ROUNDEVEN] = KW_DEF("roundeven");
builtin_list[BUILTIN_SAT_ADD] = KW_DEF("sat_add");
builtin_list[BUILTIN_SAT_SHL] = KW_DEF("sat_shl");
builtin_list[BUILTIN_SAT_SUB] = KW_DEF("sat_sub");
builtin_list[BUILTIN_SIN] = KW_DEF("sin");
builtin_list[BUILTIN_SHUFFLEVECTOR] = KW_DEF("shufflevector");
builtin_list[BUILTIN_SQRT] = KW_DEF("sqrt");

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.3.45"
#define COMPILER_VERSION "0.3.46"

View File

@@ -0,0 +1,38 @@
// #target: macos-x64
module test;
import std::io;
fn void main()
{
char a = 123;
char b = 222;
io::printfln("%s %s", $$sat_add(a, b), $$sat_add((ichar)a, (ichar)30));
io::printfln("%s %s", $$sat_sub(a, b), $$sat_sub((ichar)-120, (ichar)10));
b = 3;
io::printfln("%s %s", $$sat_shl(a, b), $$sat_shl((ichar)a, (ichar)1));
b = 222;
char[<2>] x = { 123, 222 };
char[<2>] y = { 143, 50 };
ichar[<2>] z = { 120, -120 };
ichar[<2>] w = { -44, 30 };
io::printfln("%s %s", $$sat_add(x, y), $$sat_add(z, z));
io::printfln("%s %s", $$sat_sub(x, y), $$sat_sub(w, z));
io::printfln("%s %s", $$sat_shl(x, char[<2>] { 1, 1 }), $$sat_shl(z, ichar[<2>] { 1, 1 }));
}
/* #expect: test.ll
call i8 @llvm.uadd.sat.i8
call i8 @llvm.sadd.sat.i8
call i8 @llvm.usub.sat.i8
call i8 @llvm.ssub.sat.i8
call i8 @llvm.ushl.sat.i8
call i8 @llvm.sshl.sat.i8
call <2 x i8> @llvm.uadd.sat.v2i8
call <2 x i8> @llvm.sadd.sat.v2i8
call <2 x i8> @llvm.usub.sat.v2i8
call <2 x i8> @llvm.ssub.sat.v2i8
call <2 x i8> @llvm.ushl.sat.v2i8
call <2 x i8> @llvm.sshl.sat.v2i8

View File

@@ -0,0 +1,38 @@
// #target: macos-x64
module test;
import std::io;
fn void main()
{
char a = 123;
char b = 222;
io::printfln("%s %s", $$sat_add(a, b), $$sat_add((ichar)a, (ichar)30));
io::printfln("%s %s", $$sat_sub(a, b), $$sat_sub((ichar)-120, (ichar)10));
b = 3;
io::printfln("%s %s", $$sat_shl(a, b), $$sat_shl((ichar)a, (ichar)1));
b = 222;
char[<2>] x = { 123, 222 };
char[<2>] y = { 143, 50 };
ichar[<2>] z = { 120, -120 };
ichar[<2>] w = { -44, 30 };
io::printfln("%s %s", $$sat_add(x, y), $$sat_add(z, z));
io::printfln("%s %s", $$sat_sub(x, y), $$sat_sub(w, z));
io::printfln("%s %s", $$sat_shl(x, char[<2>] { 1, 1 }), $$sat_shl(z, ichar[<2>] { 1, 1 }));
}
/* #expect: test.ll
call i8 @llvm.uadd.sat.i8
call i8 @llvm.sadd.sat.i8
call i8 @llvm.usub.sat.i8
call i8 @llvm.ssub.sat.i8
call i8 @llvm.ushl.sat.i8
call i8 @llvm.sshl.sat.i8
call <2 x i8> @llvm.uadd.sat.v2i8
call <2 x i8> @llvm.sadd.sat.v2i8
call <2 x i8> @llvm.usub.sat.v2i8
call <2 x i8> @llvm.ssub.sat.v2i8
call <2 x i8> @llvm.ushl.sat.v2i8
call <2 x i8> @llvm.sshl.sat.v2i8

View File

@@ -166,20 +166,7 @@ extern "C" {
}
int llvm_version_major = LLVM_VERSION_MAJOR;
#if LLVM_VERSION_MAJOR < 13
#if _MSC_VER
__declspec(selectany)
#else
__attribute__((weak))
#endif
LLVMAttributeRef LLVMCreateTypeAttribute(LLVMContextRef C, unsigned KindID,
LLVMTypeRef type_ref)
{
auto &Ctx = *llvm::unwrap(C);
auto AttrKind = (llvm::Attribute::AttrKind)KindID;
return wrap(llvm::Attribute::get(Ctx, AttrKind, llvm::unwrap(type_ref)));
}
#endif
LLVMValueRef LLVMConstBswap(LLVMValueRef ConstantVal)
{
llvm::Constant *Val = llvm::unwrap<llvm::Constant>(ConstantVal);