@@ -118,7 +118,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted
118118{
119119 char buf [128 ];
120120
121- if (insn -> op == IR_FUNC || insn -> op == IR_SYM ) {
121+ if (insn -> op == IR_FUNC || insn -> op == IR_SYM || insn -> op == IR_LABEL ) {
122122 fprintf (f , "%s" , ir_get_str (ctx , insn -> val .name ));
123123 return ;
124124 } else if (insn -> op == IR_STR ) {
@@ -290,6 +290,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted
290290#define ir_op_kind_prb IR_OPND_PROB
291291#define ir_op_kind_opt IR_OPND_PROB
292292#define ir_op_kind_pro IR_OPND_PROTO
293+ #define ir_op_kind_lbl IR_OPND_LABEL_REF
293294
294295#define _IR_OP_FLAGS (name , flags , op1 , op2 , op3 ) \
295296 IR_OP_FLAGS(ir_op_flag_ ## flags, ir_op_kind_ ## op1, ir_op_kind_ ## op2, ir_op_kind_ ## op3),
@@ -689,6 +690,13 @@ ir_ref ir_const_str(ir_ctx *ctx, ir_ref str)
689690 return ir_const_ex (ctx , val , IR_ADDR , IR_OPTX (IR_STR , IR_ADDR , 0 ));
690691}
691692
693+ ir_ref ir_const_label (ir_ctx * ctx , ir_ref str )
694+ {
695+ ir_val val ;
696+ val .u64 = str ;
697+ return ir_const_ex (ctx , val , IR_ADDR , IR_OPTX (IR_LABEL , IR_ADDR , 0 ));
698+ }
699+
692700ir_ref ir_str (ir_ctx * ctx , const char * s )
693701{
694702 size_t len ;
@@ -879,6 +887,17 @@ static ir_ref _ir_fold_cse(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir
879887 return IR_UNUSED ;
880888}
881889
890+ IR_ALWAYS_INLINE ir_ref _ir_fold_cast (ir_ctx * ctx , ir_ref ref , ir_type type )
891+ {
892+ if (ctx -> ir_base [ref ].type == type ) {
893+ return ref ;
894+ } else if (IR_IS_CONST_REF (ref ) && !IR_IS_SYM_CONST (ctx -> ir_base [ref ].op )) {
895+ return ir_const (ctx , ctx -> ir_base [ref ].val , type );
896+ } else {
897+ return ir_emit1 (ctx , IR_OPT (IR_BITCAST , type ), ref );
898+ }
899+ }
900+
882901#define IR_FOLD (X ) IR_FOLD1(X, __LINE__)
883902#define IR_FOLD1 (X , Y ) IR_FOLD2(X, Y)
884903#define IR_FOLD2 (X , Y ) case IR_RULE_ ## Y:
@@ -1158,7 +1177,7 @@ ir_ref ir_bind(ir_ctx *ctx, ir_ref var, ir_ref def)
11581177 IR_ASSERT (var < 0 );
11591178 if (!ir_hashtab_add (ctx -> binding , def , var )) {
11601179 /* Add a copy with different binding */
1161- def = ir_emit2 (ctx , IR_OPT (IR_COPY , ctx -> ir_base [def ].type ), def , 1 );
1180+ def = ir_emit2 (ctx , IR_OPT (IR_COPY , ctx -> ir_base [def ].type ), def , IR_COPY_HARD );
11621181 ir_hashtab_add (ctx -> binding , def , var );
11631182 }
11641183 return def ;
@@ -1836,8 +1855,49 @@ int ir_mem_flush(void *ptr, size_t size)
18361855 return 1 ;
18371856}
18381857#else
1858+
1859+ #if defined(__linux__ ) && defined(__x86_64__ ) && defined(PKEY_DISABLE_WRITE )
1860+ # define HAVE_PKEY_MPROTECT 1
1861+ #endif
1862+
1863+ #ifdef HAVE_PKEY_MPROTECT
1864+
1865+ #ifndef PKEY_DISABLE_EXECUTE
1866+ # define PKEY_DISABLE_EXECUTE 0
1867+ #endif
1868+
1869+ int pkey_mprotect (void * addr , size_t len , int prot , int pkey ) __attribute__((weak ));
1870+ int pkey_alloc (unsigned int , unsigned int ) __attribute__((weak ));
1871+ int pkey_free (int ) __attribute__((weak ));
1872+ int pkey_set (int , unsigned ) __attribute__((weak ));
1873+
1874+ static int ir_pkey = 0 ;
1875+ #endif
1876+
18391877void * ir_mem_mmap (size_t size )
18401878{
1879+ #ifdef HAVE_PKEY_MPROTECT
1880+ if (!ir_pkey && pkey_mprotect ) {
1881+ int key = pkey_alloc (0 , PKEY_DISABLE_WRITE );
1882+ if (key > 0 ) {
1883+ ir_pkey = key ;
1884+ }
1885+ }
1886+ if (ir_pkey > 0 ) {
1887+ void * ret = mmap (NULL , size , PROT_EXEC |PROT_READ |PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS , -1 , 0 );
1888+ if (ret == MAP_FAILED ) {
1889+ return NULL ;
1890+ }
1891+ if (pkey_mprotect (ret , size , PROT_EXEC |PROT_READ |PROT_WRITE , ir_pkey ) != 0 ) {
1892+ #ifdef IR_DEBUG
1893+ fprintf (stderr , "pkey_mprotect() failed\n" );
1894+ #endif
1895+ munmap (ret , size );
1896+ return NULL ;
1897+ }
1898+ return ret ;
1899+ }
1900+ #endif
18411901 int prot_flags = PROT_EXEC ;
18421902#if defined(__NetBSD__ )
18431903 prot_flags |= PROT_MPROTECT (PROT_READ |PROT_WRITE );
@@ -1852,11 +1912,28 @@ void *ir_mem_mmap(size_t size)
18521912int ir_mem_unmap (void * ptr , size_t size )
18531913{
18541914 munmap (ptr , size );
1915+ #ifdef HAVE_PKEY_MPROTECT
1916+ // if (ir_pkey > 0) {
1917+ // pkey_free(ir_pkey);
1918+ // ir_pkey = 0;
1919+ // }
1920+ #endif
18551921 return 1 ;
18561922}
18571923
18581924int ir_mem_protect (void * ptr , size_t size )
18591925{
1926+ #ifdef HAVE_PKEY_MPROTECT
1927+ if (ir_pkey > 0 ) {
1928+ if (pkey_set (ir_pkey , PKEY_DISABLE_WRITE )) {
1929+ #ifdef IR_DEBUG
1930+ fprintf (stderr , "mprotect() failed\n" );
1931+ #endif
1932+ return 0 ;
1933+ }
1934+ return 1 ;
1935+ }
1936+ #endif
18601937 if (mprotect (ptr , size , PROT_READ | PROT_EXEC ) != 0 ) {
18611938#ifdef IR_DEBUG
18621939 fprintf (stderr , "mprotect() failed\n" );
@@ -1868,6 +1945,17 @@ int ir_mem_protect(void *ptr, size_t size)
18681945
18691946int ir_mem_unprotect (void * ptr , size_t size )
18701947{
1948+ #ifdef HAVE_PKEY_MPROTECT
1949+ if (ir_pkey > 0 ) {
1950+ if (pkey_set (ir_pkey , PKEY_DISABLE_EXECUTE )) {
1951+ #ifdef IR_DEBUG
1952+ fprintf (stderr , "mprotect() failed\n" );
1953+ #endif
1954+ return 0 ;
1955+ }
1956+ return 1 ;
1957+ }
1958+ #endif
18711959 if (mprotect (ptr , size , PROT_READ | PROT_WRITE ) != 0 ) {
18721960#ifdef IR_DEBUG
18731961 fprintf (stderr , "mprotect() failed\n" );
@@ -2070,7 +2158,26 @@ IR_ALWAYS_INLINE ir_ref ir_find_aliasing_load_i(ir_ctx *ctx, ir_ref ref, ir_type
20702158 }
20712159 } else if (insn -> op == IR_RSTORE ) {
20722160 modified_regset |= (1 << insn -> op3 );
2073- } else if (insn -> op == IR_MERGE || insn -> op == IR_LOOP_BEGIN || insn -> op == IR_CALL || insn -> op == IR_VSTORE ) {
2161+ } else if (insn -> op == IR_CALL ) {
2162+ ir_insn * func = & ctx -> ir_base [insn -> op2 ];
2163+ ir_ref func_proto ;
2164+ const ir_proto_t * proto ;
2165+
2166+ if (func -> op == IR_FUNC || func -> op == IR_FUNC_ADDR ) {
2167+ func_proto = func -> proto ;
2168+ } else if (func -> op == IR_PROTO ) {
2169+ func_proto = func -> op2 ;
2170+ } else {
2171+ break ;
2172+ }
2173+ if (!func_proto ) {
2174+ break ;
2175+ }
2176+ proto = (const ir_proto_t * )ir_get_str (ctx , func_proto );
2177+ if (!(proto -> flags & (IR_CONST_FUNC |IR_PURE_FUNC ))) {
2178+ break ;
2179+ }
2180+ } else if (insn -> op == IR_MERGE || insn -> op == IR_LOOP_BEGIN || insn -> op == IR_VSTORE ) {
20742181 return IR_UNUSED ;
20752182 }
20762183 ref = insn -> op1 ;
@@ -2116,7 +2223,26 @@ IR_ALWAYS_INLINE ir_ref ir_find_aliasing_vload_i(ir_ctx *ctx, ir_ref ref, ir_typ
21162223 break ;
21172224 }
21182225 }
2119- } else if (insn -> op == IR_MERGE || insn -> op == IR_LOOP_BEGIN || insn -> op == IR_CALL || insn -> op == IR_STORE ) {
2226+ } else if (insn -> op == IR_CALL ) {
2227+ ir_insn * func = & ctx -> ir_base [insn -> op2 ];
2228+ ir_ref func_proto ;
2229+ const ir_proto_t * proto ;
2230+
2231+ if (func -> op == IR_FUNC || func -> op == IR_FUNC_ADDR ) {
2232+ func_proto = func -> proto ;
2233+ } else if (func -> op == IR_PROTO ) {
2234+ func_proto = func -> op2 ;
2235+ } else {
2236+ break ;
2237+ }
2238+ if (!func_proto ) {
2239+ break ;
2240+ }
2241+ proto = (const ir_proto_t * )ir_get_str (ctx , func_proto );
2242+ if (!(proto -> flags & (IR_CONST_FUNC |IR_PURE_FUNC ))) {
2243+ break ;
2244+ }
2245+ } else if (insn -> op == IR_MERGE || insn -> op == IR_LOOP_BEGIN || insn -> op == IR_STORE ) {
21202246 break ;
21212247 }
21222248 ref = insn -> op1 ;
@@ -3013,6 +3139,16 @@ void _ir_IJMP(ir_ctx *ctx, ir_ref addr)
30133139 ctx -> control = IR_UNUSED ;
30143140}
30153141
3142+ ir_ref _ir_IGOTO (ir_ctx * ctx , ir_ref addr )
3143+ {
3144+ ir_ref ref ;
3145+
3146+ IR_ASSERT (ctx -> control );
3147+ ctx -> control = ref = ir_emit2 (ctx , IR_IGOTO , ctx -> control , addr );
3148+ ctx -> control = IR_UNUSED ;
3149+ return ref ;
3150+ }
3151+
30163152ir_ref _ir_ADD_OFFSET (ir_ctx * ctx , ir_ref addr , uintptr_t offset )
30173153{
30183154 if (offset ) {
@@ -3135,6 +3271,18 @@ void _ir_VSTORE(ir_ctx *ctx, ir_ref var, ir_ref val)
31353271 ctx -> control = ir_emit3 (ctx , IR_VSTORE , ctx -> control , var , val );
31363272}
31373273
3274+ ir_ref _ir_VLOAD_v (ir_ctx * ctx , ir_type type , ir_ref var )
3275+ {
3276+ IR_ASSERT (ctx -> control );
3277+ return ctx -> control = ir_emit2 (ctx , IR_OPT (IR_VLOAD_v , type ), ctx -> control , var );
3278+ }
3279+
3280+ void _ir_VSTORE_v (ir_ctx * ctx , ir_ref var , ir_ref val )
3281+ {
3282+ IR_ASSERT (ctx -> control );
3283+ ctx -> control = ir_emit3 (ctx , IR_VSTORE_v , ctx -> control , var , val );
3284+ }
3285+
31383286ir_ref _ir_TLS (ir_ctx * ctx , ir_ref index , ir_ref offset )
31393287{
31403288 IR_ASSERT (ctx -> control );
@@ -3193,6 +3341,18 @@ void _ir_STORE(ir_ctx *ctx, ir_ref addr, ir_ref val)
31933341 ctx -> control = ir_emit3 (ctx , IR_STORE , ctx -> control , addr , val );
31943342}
31953343
3344+ ir_ref _ir_LOAD_v (ir_ctx * ctx , ir_type type , ir_ref addr )
3345+ {
3346+ IR_ASSERT (ctx -> control );
3347+ return ctx -> control = ir_emit2 (ctx , IR_OPT (IR_LOAD_v , type ), ctx -> control , addr );
3348+ }
3349+
3350+ void _ir_STORE_v (ir_ctx * ctx , ir_ref addr , ir_ref val )
3351+ {
3352+ IR_ASSERT (ctx -> control );
3353+ ctx -> control = ir_emit3 (ctx , IR_STORE_v , ctx -> control , addr , val );
3354+ }
3355+
31963356void _ir_VA_START (ir_ctx * ctx , ir_ref list )
31973357{
31983358 IR_ASSERT (ctx -> control );
@@ -3217,11 +3377,13 @@ ir_ref _ir_VA_ARG(ir_ctx *ctx, ir_type type, ir_ref list)
32173377 return ctx -> control = ir_emit2 (ctx , IR_OPT (IR_VA_ARG , type ), ctx -> control , list );
32183378}
32193379
3220- ir_ref _ir_VA_ARG_EX (ir_ctx * ctx , ir_type type , ir_ref list , size_t size )
3380+ ir_ref _ir_VA_ARG_EX (ir_ctx * ctx , ir_type type , ir_ref list , size_t size , size_t align )
32213381{
32223382 IR_ASSERT (ctx -> control );
3223- IR_ASSERT (size <= 0x7fffffff );
3224- return ctx -> control = ir_emit3 (ctx , IR_OPT (IR_VA_ARG , type ), ctx -> control , list , (ir_ref )size );
3383+ IR_ASSERT (size <= 0x0fffffff );
3384+ IR_ASSERT (align != 0 && ((align & (align - 1 )) == 0 ) && align <= 128 );
3385+ return ctx -> control = ir_emit3 (ctx , IR_OPT (IR_VA_ARG , type ), ctx -> control , list ,
3386+ (ir_ref )IR_VA_ARG_OP3 (size , align ));
32253387}
32263388
32273389ir_ref _ir_BLOCK_BEGIN (ir_ctx * ctx )
0 commit comments