Skip to content

Commit 62d22ae

Browse files
committed
Add MSVC support
1 parent 3c374a2 commit 62d22ae

28 files changed

Lines changed: 855 additions & 194 deletions

include/lauf/config.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ typedef uint64_t lauf_uint;
5252
# define LAUF_NOINLINE [[gnu::noinline]]
5353
# define LAUF_FORCE_INLINE [[gnu::always_inline]] inline
5454
# define LAUF_UNREACHABLE __builtin_unreachable()
55+
#elif defined(_MSC_VER)
56+
# define LAUF_LIKELY(Cond) (Cond)
57+
# define LAUF_UNLIKELY(Cond) (Cond)
58+
# define LAUF_TAIL_CALL
59+
# define LAUF_NOINLINE __declspec(noinline)
60+
# define LAUF_FORCE_INLINE __forceinline
61+
# define LAUF_UNREACHABLE __assume(0)
5562
#endif
5663

5764
//=== configurations ===//
@@ -70,6 +77,12 @@ typedef uint64_t lauf_uint;
7077
_Pragma("GCC diagnostic ignored \"-Wconversion\""); \
7178
__VA_ARGS__; \
7279
_Pragma("GCC diagnostic pop")
80+
#elif defined(_MSC_VER)
81+
# define LAUF_BITFIELD_CONVERSION(...) \
82+
_Pragma("warning(push)"); \
83+
_Pragma("warning(disable : 4267)"); \
84+
__VA_ARGS__; \
85+
_Pragma("warning(pop)")
7386
#else
7487
# define LAUF_BITFIELD_CONVERSION(...) __VA_ARGS__
7588
#endif

include/lauf/runtime/builtin.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ LAUF_HEADER_START
1616
# endif
1717
#elif defined(__GNUC__) || defined(__GNUG__)
1818
# define LAUF_RUNTIME_BUILTIN_IMPL __attribute__((section(".text.lauf_builtin"), aligned(8)))
19+
#elif defined(_MSC_VER)
20+
# define LAUF_RUNTIME_BUILTIN_IMPL __declspec(code_seg(".text.lauf_builtin"))
1921
#else
2022
# define LAUF_RUNTIME_BUILTIN_IMPL
2123
#endif

include/lauf/runtime/memory.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ typedef struct lauf_asm_function lauf_asm_function;
1212
typedef struct lauf_asm_global lauf_asm_global;
1313
typedef struct lauf_asm_layout lauf_asm_layout;
1414
typedef struct lauf_asm_signature lauf_asm_signature;
15+
typedef struct lauf_runtime_address_store lauf_runtime_address_store;
1516
typedef struct lauf_runtime_address lauf_runtime_address;
1617
typedef struct lauf_runtime_fiber lauf_runtime_fiber;
1718
typedef struct lauf_runtime_function_address lauf_runtime_function_address;
@@ -35,7 +36,7 @@ const char* lauf_runtime_get_cstr(lauf_runtime_process* p, lauf_runtime_address
3536

3637
/// Gets the address for a native pointer of the specified allocation.
3738
/// On success, updates `allocation` to the actual address.
38-
bool lauf_runtime_get_address(lauf_runtime_process* p, lauf_runtime_address* allocation,
39+
bool lauf_runtime_get_address(lauf_runtime_process* p, lauf_runtime_address_store* allocation,
3940
const void* ptr);
4041

4142
/// Returns the address of a global variable of the process.
@@ -132,7 +133,8 @@ bool lauf_runtime_unpoison_allocation(lauf_runtime_process* p, lauf_runtime_addr
132133
/// Existing addresses for `a` are only valid if their offset is `< o`; otherwise, they become
133134
/// invalidated. Neither `a` nor `a'` can be freed until the allocation has been merged again.
134135
bool lauf_runtime_split_allocation(lauf_runtime_process* p, lauf_runtime_address addr,
135-
lauf_runtime_address* addr1, lauf_runtime_address* addr2);
136+
lauf_runtime_address_store* addr1,
137+
lauf_runtime_address_store* addr2);
136138

137139
/// Merges an allocation that has been previously split.
138140
///
@@ -162,4 +164,3 @@ bool lauf_runtime_undeclare_weak(lauf_runtime_process* p, lauf_runtime_address a
162164
LAUF_HEADER_END
163165

164166
#endif // LAUF_RUNTIME_MEMORY_H_INCLUDED
165-

include/lauf/runtime/value.h

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,36 @@
88

99
LAUF_HEADER_START
1010

11+
typedef struct lauf_runtime_address_store
12+
{
13+
uint64_t value;
14+
} lauf_runtime_address_store;
15+
1116
typedef struct lauf_runtime_address
1217
{
1318
// Order of the fields chosen carefully:
1419
// acess to allocation is an AND, acess to offset a SHIFT, access to generation SHIFT + AND
1520
// (which is the one only necessary for checks). In addition, treating it as an integer and e.g.
1621
// incrementing it changes allocation first, not offset. That way, bugs are caught earlier.
1722
uint64_t allocation : 30;
18-
uint64_t generation : 2;
19-
uint64_t offset : 32;
23+
uint32_t generation : 2;
24+
uint32_t offset;
2025
} lauf_runtime_address;
2126

2227
static const lauf_runtime_address lauf_runtime_address_null = {0x3FFFFFFF, 0x3, 0xFFFFFFFF};
2328

29+
lauf_runtime_address lauf_runtime_address_from_store(lauf_runtime_address_store addr);
30+
31+
lauf_runtime_address_store lauf_runtime_address_to_store(lauf_runtime_address addr);
32+
33+
void lauf_runtime_address_store_set_allocation(lauf_runtime_address_store* store,
34+
uint32_t allocation);
35+
36+
void lauf_runtime_address_store_set_generation(lauf_runtime_address_store* store,
37+
uint8_t generation);
38+
39+
void lauf_runtime_address_store_set_offset(lauf_runtime_address_store* store, uint32_t offset);
40+
2441
typedef struct lauf_runtime_function_address
2542
{
2643
uint16_t index;
@@ -36,11 +53,10 @@ typedef union lauf_runtime_value
3653
lauf_uint as_uint;
3754
lauf_sint as_sint;
3855
void* as_native_ptr;
39-
lauf_runtime_address as_address;
56+
lauf_runtime_address_store as_address;
4057
lauf_runtime_function_address as_function_address;
4158
} lauf_runtime_value;
4259

4360
LAUF_HEADER_END
4461

4562
#endif // LAUF_RUNTIME_VALUE_H_INCLUDED
46-

src/CMakeLists.txt

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,30 @@ target_include_directories(lauf_core SYSTEM INTERFACE ../include)
3434
target_include_directories(lauf_core PRIVATE ../include .)
3535
target_link_libraries(lauf_core PRIVATE lauf_warnings foonathan::lexy)
3636

37-
if(NOT LAUF_DISPATCH_JUMP_TABLE)
37+
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
38+
if(NOT LAUF_DISPATCH_JUMP_TABLE)
39+
messsage(WARNING "MSVC does not support disabling of jump tables")
40+
endif()
41+
elseif(NOT LAUF_DISPATCH_JUMP_TABLE)
3842
target_compile_definitions(lauf_core PUBLIC LAUF_CONFIG_DISPATCH_JUMP_TABLE=0)
3943
target_compile_options(lauf_core PRIVATE -fno-jump-tables)
4044
endif()
4145
# Since we're using tail calls for dispatching, we don't want to add frame pointers, ever.
4246
# They would record all previously executed instructions in the call stack.
43-
target_compile_options(lauf_core PRIVATE -fomit-frame-pointer)
47+
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
48+
target_compile_options(lauf_core PRIVATE /Oy)
49+
else()
50+
target_compile_options(lauf_core PRIVATE -fomit-frame-pointer)
51+
endif()
4452

4553
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
4654
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
4755
target_compile_definitions(lauf_core PUBLIC LAUF_HAS_TAIL_CALL_ELIMINATION=0)
4856
endif()
57+
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC")
58+
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
59+
target_compile_definitions(lauf_core PUBLIC LAUF_HAS_TAIL_CALL_ELIMINATION=0)
60+
endif()
4961
endif()
5062

5163
target_sources(lauf_core PUBLIC
@@ -107,6 +119,7 @@ target_sources(lauf_core PRIVATE
107119
${src_dir}/runtime/process.cpp
108120
${src_dir}/runtime/stack.hpp
109121
${src_dir}/runtime/stacktrace.cpp
122+
${src_dir}/runtime/value.cpp
110123

111124
${src_dir}/lib/bits.cpp
112125
${src_dir}/lib/debug.cpp

src/lauf/asm/builder.cpp

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,7 @@ void lauf_asm_inst_call(lauf_asm_builder* b, const lauf_asm_function* callee)
739739

740740
LAUF_BUILD_ASSERT(b->cur->vstack.pop(callee->sig.input_count), "missing input values for call");
741741

742-
auto offset = lauf::compress_pointer_offset(b->fn, callee);
742+
auto offset = lauf::new_compress_pointer_offset(b->fn, callee);
743743
b->cur->insts.push_back(*b, LAUF_BUILD_INST_OFFSET(call, offset));
744744

745745
b->cur->vstack.push_output(*b, callee->sig.output_count);
@@ -777,7 +777,7 @@ void lauf_asm_inst_call_indirect(lauf_asm_builder* b, lauf_asm_signature sig)
777777
if (auto callee = get_constant_function(b->mod, *fn_addr, sig))
778778
{
779779
add_pop_top_n(b, 1);
780-
auto offset = lauf::compress_pointer_offset(b->fn, callee);
780+
auto offset = lauf::new_compress_pointer_offset(b->fn, callee);
781781
b->cur->insts.push_back(*b, LAUF_BUILD_INST_OFFSET(call, offset));
782782
}
783783
else
@@ -793,7 +793,7 @@ namespace
793793
{
794794
void add_call_builtin(lauf_asm_builder* b, lauf_runtime_builtin_function callee)
795795
{
796-
auto offset = lauf::compress_pointer_offset(&lauf_runtime_builtin_dispatch, callee.impl);
796+
auto offset = lauf::new_compress_pointer_offset(&lauf_runtime_builtin_dispatch, callee.impl);
797797
if ((callee.flags & LAUF_RUNTIME_BUILTIN_NO_PROCESS) != 0
798798
&& (callee.flags & LAUF_RUNTIME_BUILTIN_NO_PANIC) != 0)
799799
b->cur->insts.push_back(*b, LAUF_BUILD_INST_OFFSET(call_builtin_no_regs, offset));
@@ -1021,10 +1021,12 @@ void lauf_asm_inst_global_addr(lauf_asm_builder* b, const lauf_asm_global* globa
10211021

10221022
b->cur->insts.push_back(*b, LAUF_BUILD_INST_VALUE(global_addr, global->allocation_idx));
10231023
b->cur->vstack.push_constant(*b, [&] {
1024-
lauf_runtime_value result;
1025-
LAUF_BITFIELD_CONVERSION(result.as_address.allocation = global->allocation_idx);
1026-
result.as_address.offset = 0;
1027-
result.as_address.generation = 0; // Always true for globals.
1024+
lauf_runtime_value result;
1025+
lauf_runtime_address addr;
1026+
LAUF_BITFIELD_CONVERSION(addr.allocation = global->allocation_idx);
1027+
addr.offset = 0;
1028+
addr.generation = 0; // Always true for globals.
1029+
result.as_address = lauf_runtime_address_to_store(addr);
10281030
return result;
10291031
}());
10301032
}
@@ -1048,7 +1050,7 @@ void lauf_asm_inst_function_addr(lauf_asm_builder* b, const lauf_asm_function* f
10481050
{
10491051
LAUF_BUILD_CHECK_CUR;
10501052

1051-
auto offset = lauf::compress_pointer_offset(b->fn, function);
1053+
auto offset = lauf::new_compress_pointer_offset(b->fn, function);
10521054
b->cur->insts.push_back(*b, LAUF_BUILD_INST_OFFSET(function_addr, offset));
10531055
b->cur->vstack.push_constant(*b, [&] {
10541056
lauf_runtime_value result;
@@ -1288,7 +1290,7 @@ load_store_constant load_store_constant_folding(lauf_asm_module* mod,
12881290
// TOCTOU is okay, we just can't constant fold because of it.
12891291
auto globals = lauf::get_globals(mod);
12901292

1291-
auto constant_addr = addr.as_constant.as_address;
1293+
auto constant_addr = lauf_runtime_address_from_store(addr.as_constant.as_address);
12921294
if (constant_addr.allocation >= globals.count && constant_addr.generation != 0
12931295
&& constant_addr.offset != 0)
12941296
return load_store_dynamic;
@@ -1330,8 +1332,10 @@ void lauf_asm_inst_load_field(lauf_asm_builder* b, lauf_asm_type type, size_t fi
13301332
else if (constant_folding == load_store_global)
13311333
{
13321334
add_pop_top_n(b, 1);
1333-
b->cur->insts.push_back(*b, LAUF_BUILD_INST_VALUE(load_global_value,
1334-
addr->as_constant.as_address.allocation));
1335+
b->cur->insts.push_back( //
1336+
*b, LAUF_BUILD_INST_VALUE( //
1337+
load_global_value,
1338+
lauf_runtime_address_from_store(addr->as_constant.as_address).allocation));
13351339
b->cur->vstack.push_output(*b, 1);
13361340
}
13371341
else if (type.layout.size == 0 && type.load_fn == nullptr)
@@ -1374,8 +1378,10 @@ void lauf_asm_inst_store_field(lauf_asm_builder* b, lauf_asm_type type, size_t f
13741378
else if (constant_folding == load_store_global)
13751379
{
13761380
add_pop_top_n(b, 1);
1377-
b->cur->insts.push_back(*b, LAUF_BUILD_INST_VALUE(store_global_value,
1378-
addr->as_constant.as_address.allocation));
1381+
b->cur->insts.push_back( //
1382+
*b, LAUF_BUILD_INST_VALUE( //
1383+
store_global_value,
1384+
lauf_runtime_address_from_store(addr->as_constant.as_address).allocation));
13791385
LAUF_BUILD_ASSERT(b->cur->vstack.pop(1), "missing value");
13801386
}
13811387
else if (type.layout.size == 0 && type.store_fn == nullptr)

0 commit comments

Comments
 (0)