Skip to content

Commit 5489c41

Browse files
committed
More LCC support
1 parent dcacb89 commit 5489c41

File tree

12 files changed

+118
-55
lines changed

12 files changed

+118
-55
lines changed

cilly/src/v2/asm.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1320,7 +1320,17 @@ impl Assembly {
13201320
pub(crate) fn get_section(&self, arg: &str) -> Option<&Vec<u8>> {
13211321
self.sections.get(arg)
13221322
}
1323+
1324+
pub(crate) fn guaranted_align(&self) -> u8 {
1325+
*GUARANTED_ALIGN
1326+
}
1327+
1328+
pub fn max_static_size(&self) -> usize {
1329+
*MAX_STATIC_SIZE
1330+
}
13231331
}
1332+
config!(GUARANTED_ALIGN, u8,8);
1333+
config!(MAX_STATIC_SIZE, usize,16);
13241334
/// An initializer, which runs before everything else. By convention, it is used to initialize static / const data. Should not execute any user code
13251335
pub const CCTOR: &str = ".cctor";
13261336
/// An thread-local initializer. Runs before each thread starts. By convention, it is used to initialize thread local data. Should not execute any user code.

cilly/src/v2/c_exporter/c_header.h

+65-25
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
#include <stdio.h>
22
#include <stdint.h>
3-
3+
/* Backup for targets that don't support i128 - TODO: replace this with software emulation!*/
4+
#if !defined(__SIZEOF_INT128__) || defined(__LCC__)
5+
#define __int128_t long long
6+
#define __int128 __int128_t
7+
#define __uint128_t unsigned long long
8+
#define uint128_t unsigned long long
9+
#endif
410
#if !defined(__TINYC__) && !defined(__LCC__)
511
#include <stdbool.h>
612
#elif defined(__LCC__)
@@ -12,7 +18,9 @@
1218
#define false 0
1319
#define true 1
1420
#endif
15-
21+
#ifdef __LCC__
22+
#define __func__ "unknown"
23+
#endif
1624
#include <stdlib.h>
1725
#include <string.h>
1826
#include <math.h>
@@ -39,18 +47,20 @@ inline void* _mm_malloc(size_t size, size_t align){
3947
inline void _mm_free (void *p){
4048
free(p);
4149
}
50+
#endif
51+
#if (defined(__TINYC__) || defined(__SDCC) || defined(__LCC__))
4252
inline uint16_t __builtin_bswap16(uint16_t val){
4353
uint16_t res;
44-
uint8_t* ptr = &val;
45-
uint8_t* rptr = &res;
54+
uint8_t* ptr = (uint8_t*)&val;
55+
uint8_t* rptr = (uint8_t*)&res;
4656
rptr[0] = ptr[1];
4757
rptr[1] = ptr[0];
4858
return res;
4959
}
5060
inline uint32_t __builtin_bswap32(uint32_t val){
5161
uint32_t res;
52-
uint8_t* ptr = &val;
53-
uint8_t* rptr = &res;
62+
uint8_t* ptr = (uint8_t*)&val;
63+
uint8_t* rptr = (uint8_t*)&res;
5464
rptr[0] = ptr[3];
5565
rptr[1] = ptr[2];
5666
rptr[2] = ptr[1];
@@ -59,8 +69,8 @@ inline uint32_t __builtin_bswap32(uint32_t val){
5969
}
6070
inline uint64_t __builtin_bswap64(uint64_t val){
6171
uint64_t res;
62-
uint8_t* ptr = &val;
63-
uint8_t* rptr = &res;
72+
uint8_t* ptr = (uint8_t*)&val;
73+
uint8_t* rptr = (uint8_t*)&res;
6474
rptr[0] = ptr[7];
6575
rptr[1] = ptr[6];
6676
rptr[2] = ptr[5];
@@ -71,6 +81,28 @@ inline uint64_t __builtin_bswap64(uint64_t val){
7181
rptr[7] = ptr[0];
7282
return res;
7383
}
84+
inline uint128_t __builtin_bswap128(uint128_t val){
85+
uint128_t res;
86+
uint8_t* ptr = (uint8_t*)&val;
87+
uint8_t* rptr = (uint8_t*)&res;
88+
rptr[0] = ptr[15];
89+
rptr[1] = ptr[14];
90+
rptr[2] = ptr[13];
91+
rptr[3] = ptr[12];
92+
rptr[4] = ptr[11];
93+
rptr[5] = ptr[10];
94+
rptr[6] = ptr[9];
95+
rptr[7] = ptr[8];
96+
rptr[8] = ptr[7];
97+
rptr[9] = ptr[6];
98+
rptr[10] = ptr[5];
99+
rptr[11] = ptr[4];
100+
rptr[12] = ptr[3];
101+
rptr[13] = ptr[2];
102+
rptr[14] = ptr[1];
103+
rptr[16] = ptr[0];
104+
return res;
105+
}
74106
#endif
75107
#ifdef __clang__
76108
static inline __uint128_t __builtin_bswap128(__uint128_t val){
@@ -115,41 +147,41 @@ __uint128_t __builtin_bswap128(__uint128_t val);
115147
#define FORCE_NOT_ZST char force_not_zst;
116148
#endif
117149

118-
#if !(defined(__SDCC) || defined(_MSC_VER))
150+
#if !(defined(__SDCC) || defined(_MSC_VER) || defined(__LCC__))
119151
#include <alloca.h>
152+
#define register_alloca_aligned(type, align, hash)
153+
#define loc_alloc_aligned(name, type, align, hash) name = (void*)((((size_t)(alloca(sizeof(type) + align) + align - 1)) / align)*align);
120154
#elif defined(_MSC_VER)
121155
#define alloca _alloca
156+
#define register_alloca_aligned(type, align, hash)
157+
#define loc_alloc_aligned(name, type, align, hash) name = (void*)((((size_t)(alloca(sizeof(type) + align) + align - 1)) / align)*align);
122158
#else
123-
#define alloca(arg) ((void*)0)
124-
#endif
125-
/* Backup for targets that don't support i128 - TODO: replace this with software emulation!*/
126-
#if !defined(__SIZEOF_INT128__) || defined(__LCC__)
127-
#define __int128_t long long
128-
#define __int128 __int128_t
129-
#define __uint128_t unsigned long long
159+
#define register_alloca_aligned(type, align, hash) char hash[sizeof(type) + align];
160+
#define loc_alloc_aligned(name, type, align, hash) name = (void*)((((size_t)(&hash + align - 1)) / align)*align);
130161
#endif
162+
131163
#ifdef __clang__
132164
#define __atomic_compare_exchange_4 __atomic_compare_exchange_n
133165
#define __atomic_compare_exchange_8 __atomic_compare_exchange_n
134166
#define _Float128 long double
135-
#elif defined(__SDCC)
167+
#elif (defined(__SDCC) || defined(__LCC__))
136168
// WARNING! Assumes a single-threaded, no-interrupt eviroment!
137169
bool __atomic_compare_exchange_4(uint32_t *ptr, uint32_t *expected, uint32_t desired, bool weak, int success_memorder, int failure_memorder){
138-
if(*ptr == expected){
170+
if(*ptr == *expected){
139171
*ptr = desired;
140172
return true;
141173
}
142174
return false;
143175
}
144176
bool __atomic_compare_exchange_8(uint64_t *ptr, uint64_t *expected, uint64_t desired, bool weak, int success_memorder, int failure_memorder){
145-
if(*ptr == expected){
177+
if(*ptr == *expected){
146178
*ptr = desired;
147179
return true;
148180
}
149181
return false;
150182
}
151183
bool __atomic_compare_exchange_n(uintptr_t *ptr, uintptr_t *expected, uintptr_t desired, bool weak, int success_memorder, int failure_memorder){
152-
if(*ptr == expected){
184+
if(*ptr == *expected){
153185
*ptr = desired;
154186
return true;
155187
}
@@ -195,7 +227,7 @@ static inline void *System_Runtime_InteropServices_NativeMemory_AlignedReallocpv
195227
#define eprintf(...) printf(__VA_ARGS__)
196228
#define BUILTIN_UNSUPORTED(NAME,OUTPUT, ARGLIST) static inline OUTPUT NAME ARGLIST { eprintf("Function " #NAME "is not yet supported!"); abort();}
197229
#endif
198-
#ifdef __SDCC
230+
#if defined(__SDCC) || defined(__LCC__)
199231
#define NAN (0.0 / 0.0)
200232
#endif
201233
#ifdef __SDCC
@@ -326,7 +358,7 @@ static inline __uint128_t System_UInt128_op_Explicitf64u128(double val) {
326358
/*Assumes a 64 bit OS.*/
327359
#define System_Buffers_Binary_BinaryPrimitives_ReverseEndiannessisizeisize(val) (intptr_t) __builtin_bswap64((uint64_t)val)
328360
#define System_Buffers_Binary_BinaryPrimitives_ReverseEndiannessusizeusize __builtin_bswap64
329-
#ifndef __SDCC
361+
#if !(defined(__SDCC) || defined(__LCC__))
330362
static inline int32_t System_Numerics_BitOperations_TrailingZeroCountusizei32(uintptr_t val) {if (val == 0) return sizeof(uintptr_t) * 8; return (int32_t) __builtin_ctzl((uint64_t)val);}
331363
static inline int32_t System_Numerics_BitOperations_TrailingZeroCountu32i32(uint32_t val) {if (val == 0) return sizeof(uint32_t) * 8; return (int32_t) __builtin_ctzl((uint32_t)val);}
332364
static inline int32_t System_Numerics_BitOperations_TrailingZeroCounti32i32(int32_t val) {if (val == 0) return sizeof(int32_t) * 8; return (int32_t) __builtin_ctzl((uint32_t)val);}
@@ -341,6 +373,7 @@ static inline int32_t System_Numerics_BitOperations_LeadingZeroCountusizei32(uin
341373
#define System_Numerics_BitOperations_PopCountu64i32(val) __builtin_popcountl((uint64_t)val)
342374
#define System_UInt128_PopCountu128u128(val) __builtin_popcountl((uint64_t)val)
343375

376+
#define System_Console_WriteLinev() printf("\n")
344377
#define System_Console_WriteLinestv(msg) printf("%s\n", msg)
345378
#define System_Console_WriteLinef64v(val) printf("%f\n", val)
346379

@@ -484,8 +517,12 @@ double fabsf64(double val);
484517
#define System_Double_Sinf64f64 sin
485518
#define System_Double_Absf64f64 fabsf64
486519
#define System_Single_Absf32f32 fabsf32
520+
#define System_Single_Sqrtf32f32(x) (float)sqrt((double)x)
487521
#define System_MathF_Sqrtf32f32(x) (float)sqrt((double)x)
522+
#define System_Double_Sqrtf64f64 sqrt
488523
#define System_MathF_Sqrtf64f64 sqrt
524+
#define System_Single_Floorf32f32(x) (float)floor((double)x)
525+
#define System_Single_Ceilingf32f32(x) (float)ceil((double)x)
489526
#define System_MathF_Roundf32f32(x) (float)round((double)x)
490527
#define System_Single_Powf32f32f32(a, b) (float)pow(a, b)
491528
#define System_Single_Powf64f64f64 pow
@@ -555,11 +592,14 @@ BUILTIN_UNSUPORTED(System_Double_Log2f64f64,double,(double input))
555592
#define System_Math_Floorf64f64(input) floor(input)
556593
#define System_Math_Sqrtf64f64(input) sqrt(input)
557594
#define System_Math_Ceilingf64f64(input) ceil(input)
595+
#define System_Double_Ceilingf64f64(input) ceil(input)
558596
#define System_MathF_Ceilingf32f32(input) (float)ceil((double)input)
559597
#define System_Math_Floorf64f64(input) floor(input)
598+
#define System_Double_Floorf64f64(input) floor(input)
560599
#define System_MathF_Floorf32f32(input) (float)floor((double)input)
561600
#define System_Math_Truncatef64f64(input) trunc(input)
562-
601+
#define System_Double_Truncatef64f64(input) trunc(input)
602+
#define System_Single_Truncatef32f32(input) (float)trunc((double)input)
563603
static inline uint32_t System_Threading_Interlocked_CompareExchangeru32u32u32u32(uint32_t *addr, uint32_t value, uint32_t comparand)
564604
{
565605
uint32_t res = 0;
@@ -612,7 +652,7 @@ static inline intptr_t System_Threading_Interlocked_CompareExchangerisizeisizeis
612652
return comparand;
613653
}
614654
}
615-
#ifndef __SDCC
655+
#if !(defined(__SDCC) || defined(__LCC__))
616656
static inline uint32_t System_Threading_Interlocked_Exchangeru32u32u32(uint32_t *addr, uint32_t val)
617657
{
618658
uint32_t ret;
@@ -704,7 +744,7 @@ static inline uint8_t System_Byte_RotateLeftu8i32u8(uint8_t val, int32_t amount)
704744
if(amount == 0) return val;
705745
return ((val << amount) | (val >> ( (sizeof(uint8_t)*8) - amount)));
706746
}
707-
#ifndef __SDCC
747+
#if !(defined(__SDCC) || defined(__LCC__))
708748
static inline unsigned __int128 System_UInt128_LeadingZeroCountu128u128(unsigned __int128 val){ if (val == 0) return 128; return __builtin_clzl(val); }
709749
#endif
710750
static inline uint32_t System_Math_Minu32u32u32(uint32_t lhs, uint32_t rhs)

cilly/src/v2/c_exporter/mod.rs

+27-2
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,9 @@ impl CExporter {
648648
Ok(match root {
649649
CILRoot::StLoc(id, node_idx) => {
650650
let name = local_name(locals, asm, id);
651+
if let CILNode::LocAllocAlgined { tpe, align } = asm[node_idx]{
652+
return Ok(format!("loc_alloc_aligned({name},{tpe},{align},t{hash})",tpe = c_tpe(asm[tpe],asm),hash = encode(asm.alloc_root(root).as_bimap_index().get() as u64)));
653+
}
651654
return Ok(format!("{name} = {node};", node = Self::node_to_string(asm[node_idx].clone(), asm, locals, inputs, sig)?,));
652655
},
653656
CILRoot::StArg(arg, node_idx) =>match inputs[arg as usize].1 {
@@ -940,6 +943,21 @@ impl CExporter {
940943
)?;
941944
}
942945
let blocks = def.blocks(asm).unwrap().to_vec();
946+
// Prepare allocas, if needed.
947+
for root in blocks[0].roots(){
948+
let CILRoot::StLoc(loc,node ) = asm[*root] else{
949+
continue;
950+
};
951+
let CILNode::LocAllocAlgined { tpe, align } = asm[node] else {
952+
continue;
953+
};
954+
writeln!(
955+
method_defs,
956+
"register_alloca_aligned(t{hash}, {tpe},{align});",
957+
hash = encode(root.as_bimap_index().get() as u64),
958+
tpe = c_tpe(asm[tpe], asm),
959+
)?;
960+
}
943961
let mut block_iter = blocks.iter().peekable();
944962
while let Some(block) = block_iter.next() {
945963
writeln!(method_defs, "bb{}:", block.block_id())?;
@@ -1175,7 +1193,7 @@ impl CExporter {
11751193

11761194
let mut cmd = std::process::Command::new(Self::c_compiler());
11771195
if is_main {
1178-
cmd.args(["-D", "MAIN_FILE"]);
1196+
cmd.args(["-DMAIN_FILE"]);
11791197
}
11801198

11811199
cmd.arg("-fPIC");
@@ -1212,11 +1230,18 @@ impl CExporter {
12121230
let stderr = String::from_utf8_lossy(&out.stderr);
12131231
if !*LINKER_RECOVER {
12141232
assert!(
1215-
!(stderr.contains("error:") || stderr.contains("fatal")),
1233+
!(stderr.contains("error:")
1234+
|| stderr.contains("fatal")
1235+
|| stderr.contains("failed")),
12161236
"stdout:{} stderr:{} cmd:{cmd:?}",
12171237
stdout,
12181238
String::from_utf8_lossy(&out.stderr)
12191239
);
1240+
println!(
1241+
"linker success. stdout:{} stderr:{} cmd:{cmd:?}",
1242+
stdout,
1243+
String::from_utf8_lossy(&out.stderr)
1244+
);
12201245
}
12211246

12221247
Ok(())

cilly/src/v2/method.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ impl MethodDef {
392392
}
393393
let mut preamble = vec![];
394394
for (local_id, (_, tpe_idx, align)) in to_map {
395-
if align <= 8 {
395+
if align <= asm.guaranted_align() as u64 {
396396
// Aligement guanrateed by .NET, skip.
397397
continue;
398398
}

src/aggregate.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,9 @@ pub fn handle_aggregate<'tcx>(
251251
(place_get(target_location, ctx)),
252252
)
253253
}
254-
AggregateKind::CoroutineClosure(..) => todo!("Unsuported aggregate kind {aggregate_kind:?}"),
254+
AggregateKind::CoroutineClosure(..) => {
255+
todo!("Unsuported aggregate kind {aggregate_kind:?}")
256+
}
255257
}
256258
}
257259
/// Builds an Algebraic Data Type (struct,enum,union) at location `target_location`, with fields set using ops in `fields`.

src/assembly.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,7 @@ pub fn add_allocation(alloc_id: u64, asm: &mut cilly::v2::Assembly, tcx: TyCtxt<
695695
let byte_hash = calculate_hash(&bytes);
696696
match (align, bytes.len()) {
697697
// Assumes this constant is not a pointer.
698-
(0..=1, 1) | (0..=2, 1..=2) | (0..=4, 1..=4) | (0..=8, 1..=16) => {
698+
(0..=1, len @ 1) | (0..=2, len @ 1..=2) | (0..=4, len @ 1..=4) | (0..=8, len @ 1..=16) if len <= asm.max_static_size()=> {
699699
let alloc_name: IString = if let Some(krate) = krate {
700700
format!(
701701
"s_{}_{}_{}_{thread_local}_{}",
@@ -715,7 +715,10 @@ pub fn add_allocation(alloc_id: u64, asm: &mut cilly::v2::Assembly, tcx: TyCtxt<
715715
.into()
716716
};
717717
let name = asm.alloc_string(alloc_name.clone());
718-
let tpe: Int = Int::from_size_sign(u8::try_from(bytes.len()).unwrap().next_power_of_two(), false);
718+
let tpe: Int = Int::from_size_sign(
719+
u8::try_from(bytes.len()).unwrap().next_power_of_two(),
720+
false,
721+
);
719722
let field_desc = StaticFieldDesc::new(*asm.main_module(), name, cilly::Type::Int(tpe));
720723
// Currently, all static fields are in one module. Consider spliting them up.
721724
let main_module = asm.class_mut(main_module_id);

src/binop/checked/mod.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -506,12 +506,7 @@ pub fn add_unsigned<'tcx>(
506506

507507
result_tuple(
508508
tpe,
509-
super::cmp::lt_unchecked(
510-
ty,
511-
res.clone(),
512-
ops_a.clone(),
513-
ctx,
514-
),
509+
super::cmp::lt_unchecked(ty, res.clone(), ops_a.clone(), ctx),
515510
res,
516511
ctx,
517512
)

src/constant.rs

-1
This file was deleted.

src/lib.rs

-3
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,6 @@ pub mod native_pastrough;
118118
mod codegen_error;
119119
/// Test harnesses.
120120
pub mod compile_test;
121-
/// Code handling loading constant values in CIL.
122-
mod constant;
123-
124121
/// Implementation of compiletime features neccessary for interop.
125122
mod comptime;
126123
/// Signature of a function (inputs)->output

src/utilis/adt.rs

-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use rustc_middle::ty::Ty;
1111

1212
use rustc_codegen_clr_ctx::MethodCompileCtx;
1313

14-
1514
#[derive(Clone, Debug)]
1615
pub(crate) enum FieldOffsetIterator {
1716
Explicit { offsets: Box<[u32]>, index: usize },
@@ -85,7 +84,6 @@ impl FieldOffsetIterator {
8584
}
8685
}
8786
}
88-
8987
}
9088
/// Takes layout of an enum as input, and returns the type of its tag(Void if no tag) and the size of the tag(0 if no tag).
9189
pub fn enum_tag_info(r#enum: Layout<'_>, asm: &mut Assembly) -> (Type, u32) {

0 commit comments

Comments
 (0)