Skip to content

Commit 1263346

Browse files
jacobly0andrewrk
authored andcommitted
use zig-wasm2c for bootstrapping
1 parent a63305b commit 1263346

File tree

8 files changed

+4202
-4581
lines changed

8 files changed

+4202
-4581
lines changed

CMakeLists.txt

+37-14
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@ set(ZIG_STD_DEST "${ZIG_LIB_DIR}/std")
179179
set(ZIG_CONFIG_H_OUT "${CMAKE_BINARY_DIR}/config.h")
180180
set(ZIG_CONFIG_ZIG_OUT "${CMAKE_BINARY_DIR}/config.zig")
181181

182-
set(STAGE1_SOURCES
183-
"${CMAKE_SOURCE_DIR}/stage1/zig1.c"
182+
set(ZIG_WASM2C_SOURCES
183+
"${CMAKE_SOURCE_DIR}/stage1/wasm2c.c"
184184
"${CMAKE_SOURCE_DIR}/stage1/zstd/lib/decompress/huf_decompress.c"
185185
"${CMAKE_SOURCE_DIR}/stage1/zstd/lib/decompress/zstd_ddict.c"
186186
"${CMAKE_SOURCE_DIR}/stage1/zstd/lib/decompress/zstd_decompress.c"
@@ -709,30 +709,53 @@ target_link_libraries(zigcpp LINK_PUBLIC
709709
)
710710

711711
if(MSVC)
712-
set(ZIG1_COMPILE_FLAGS "/std:c99")
713-
set(ZIG2_COMPILE_FLAGS "/std:c99")
712+
set(ZIG_WASM2C_COMPILE_FLAGS "/std:c99 /O2")
713+
set(ZIG1_COMPILE_FLAGS "/std:c99 /Os")
714+
set(ZIG2_COMPILE_FLAGS "/std:c99 /O0")
714715
set(ZIG2_LINK_FLAGS "/STACK:16777216")
715716
else()
717+
set(ZIG_WASM2C_COMPILE_FLAGS "-std=c99 -O2")
716718
set(ZIG1_COMPILE_FLAGS "-std=c99")
717719
set(ZIG2_COMPILE_FLAGS "-std=c99")
718720
set(ZIG2_LINK_FLAGS "-Wl,-z,stack-size=0x10000000")
719721
endif()
720722

721-
add_executable(zig1 ${STAGE1_SOURCES})
722-
set_target_properties(zig1 PROPERTIES COMPILE_FLAGS ${ZIG1_COMPILE_FLAGS})
723+
string(TOLOWER "${CMAKE_HOST_SYSTEM_PROCESSOR}-${CMAKE_HOST_SYSTEM_NAME}" HOST_TARGET_TRIPLE)
724+
set(ZIG1_WASM_SOURCE "${CMAKE_SOURCE_DIR}/stage1/zig1.wasm.zst")
725+
set(ZIG1_C_SOURCE "${CMAKE_BINARY_DIR}/zig1.c")
726+
set(ZIG2_C_SOURCE "${CMAKE_BINARY_DIR}/zig2.c")
727+
set(ZIG_COMPILER_RT_C_SOURCE "${CMAKE_BINARY_DIR}/compiler_rt.c")
728+
729+
add_executable(zig-wasm2c ${ZIG_WASM2C_SOURCES})
730+
set_target_properties(zig-wasm2c PROPERTIES COMPILE_FLAGS ${ZIG_WASM2C_COMPILE_FLAGS})
731+
target_include_directories(zig-wasm2c PUBLIC "${CMAKE_SOURCE_DIR}/stage1/zstd/lib")
732+
target_compile_definitions(zig-wasm2c PRIVATE ZSTD_DISABLE_ASM)
733+
734+
add_custom_command(
735+
OUTPUT "${ZIG1_C_SOURCE}"
736+
COMMAND zig-wasm2c "${ZIG1_WASM_SOURCE}" "${ZIG1_C_SOURCE}"
737+
DEPENDS zig-wasm2c "${ZIG1_WASM_SOURCE}"
738+
COMMENT STATUS "Converting ${ZIG1_WASM_SOURCE} to ${ZIG1_C_SOURCE}"
739+
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
740+
)
741+
742+
add_executable(zig1 ${ZIG1_C_SOURCE} "${CMAKE_SOURCE_DIR}/stage1/wasi.c")
743+
set_target_properties(zig1 PROPERTIES
744+
COMPILE_FLAGS ${ZIG1_COMPILE_FLAGS}
745+
LINK_FLAGS ${ZIG2_LINK_FLAGS})
723746
target_link_libraries(zig1 LINK_PUBLIC m)
724747
target_include_directories(zig1 PUBLIC "${CMAKE_SOURCE_DIR}/stage1/zstd/lib")
725748
target_compile_definitions(zig1 PRIVATE ZSTD_DISABLE_ASM)
726749

727-
set(ZIG2_C_SOURCE "${CMAKE_BINARY_DIR}/zig2.c")
728750
set(ZIG1_WASM_ZST_SOURCE "${CMAKE_SOURCE_DIR}/stage1/zig1.wasm.zst")
729751
set(BUILD_ZIG2_ARGS
730752
"${CMAKE_SOURCE_DIR}/lib"
731-
"${CMAKE_BINARY_DIR}"
732-
zig2
733-
"${ZIG1_WASM_ZST_SOURCE}"
734753
build-exe src/main.zig -ofmt=c -lc
735754
-OReleaseSmall
755+
--name zig2 -femit-bin="${ZIG2_C_SOURCE}"
756+
--pkg-begin build_options "${CMAKE_BINARY_DIR}/config.zig" --pkg-end
757+
-target "${HOST_TARGET_TRIPLE}"
758+
--color on
736759
)
737760

738761
add_custom_command(
@@ -743,14 +766,14 @@ add_custom_command(
743766
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
744767
)
745768

746-
set(ZIG_COMPILER_RT_C_SOURCE "${CMAKE_BINARY_DIR}/compiler_rt.c")
747769
set(BUILD_COMPILER_RT_ARGS
748770
"${CMAKE_SOURCE_DIR}/lib"
749-
"${CMAKE_BINARY_DIR}"
750-
compiler_rt
751-
"${CMAKE_SOURCE_DIR}/stage1/zig1.wasm.zst"
752771
build-obj lib/compiler_rt.zig -ofmt=c
753772
-OReleaseSmall
773+
--name compiler_rt -femit-bin="${ZIG_COMPILER_RT_C_SOURCE}"
774+
--pkg-begin build_options "${CMAKE_BINARY_DIR}/config.zig" --pkg-end
775+
-target "${HOST_TARGET_TRIPLE}"
776+
--color on
754777
)
755778

756779
add_custom_command(

stage1/FuncGen.h

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#ifndef FUNC_GEN_H
2+
#define FUNC_GEN_H
3+
4+
#include "panic.h"
5+
#include "wasm.h"
6+
7+
#include <inttypes.h>
8+
#include <stdbool.h>
9+
#include <stdint.h>
10+
#include <stdio.h>
11+
#include <string.h>
12+
13+
struct Block {
14+
uint32_t type;
15+
uint32_t label;
16+
uint32_t stack_i;
17+
};
18+
19+
struct FuncGen {
20+
int8_t *type;
21+
uint32_t *stack;
22+
struct Block *block;
23+
uint32_t type_i;
24+
uint32_t stack_i;
25+
uint32_t block_i;
26+
uint32_t type_len;
27+
uint32_t stack_len;
28+
uint32_t block_len;
29+
};
30+
31+
static void FuncGen_init(struct FuncGen *self) {
32+
memset(self, 0, sizeof(struct FuncGen));
33+
}
34+
35+
static void FuncGen_reset(struct FuncGen *self) {
36+
self->type_i = 0;
37+
self->stack_i = 0;
38+
self->block_i = 0;
39+
}
40+
41+
static void FuncGen_free(struct FuncGen *self) {
42+
free(self->block);
43+
free(self->stack);
44+
free(self->type);
45+
}
46+
47+
static void FuncGen_outdent(struct FuncGen *self, FILE *out) {
48+
for (uint32_t i = 0; i < self->block_i; i += 1) fputs(" ", out);
49+
}
50+
51+
static void FuncGen_indent(struct FuncGen *self, FILE *out) {
52+
FuncGen_outdent(self, out);
53+
fputs(" ", out);
54+
}
55+
56+
static void FuncGen_cont(struct FuncGen *self, FILE *out) {
57+
FuncGen_indent(self, out);
58+
fputs(" ", out);
59+
}
60+
61+
static uint32_t FuncGen_localAlloc(struct FuncGen *self, int8_t type) {
62+
if (self->type_i == self->type_len) {
63+
self->type_len += 10;
64+
self->type_len *= 2;
65+
self->type = realloc(self->type, sizeof(int8_t) * self->type_len);
66+
if (self->type == NULL) panic("out of memory");
67+
}
68+
uint32_t local_i = self->type_i;
69+
self->type[local_i] = type;
70+
self->type_i += 1;
71+
return local_i;
72+
}
73+
74+
static uint32_t FuncGen_localDeclare(struct FuncGen *self, FILE *out, enum WasmValType val_type) {
75+
uint32_t local_i = FuncGen_localAlloc(self, (int8_t)val_type);
76+
fprintf(out, "%s l%" PRIu32, WasmValType_toC(val_type), local_i);
77+
return local_i;
78+
}
79+
80+
static enum WasmValType FuncGen_localType(const struct FuncGen *self, uint32_t local_idx) {
81+
return self->type[local_idx];
82+
}
83+
84+
static void FuncGen_stackPush(struct FuncGen *self, FILE *out, enum WasmValType val_type) {
85+
if (self->stack_i == self->stack_len) {
86+
self->stack_len += 10;
87+
self->stack_len *= 2;
88+
self->stack = realloc(self->stack, sizeof(uint32_t) * self->stack_len);
89+
if (self->stack == NULL) panic("out of memory");
90+
}
91+
FuncGen_indent(self, out);
92+
fputs("const ", out);
93+
self->stack[self->stack_i] = FuncGen_localDeclare(self, out, val_type);
94+
self->stack_i += 1;
95+
fputs(" = ", out);
96+
}
97+
98+
static uint32_t FuncGen_stackAt(const struct FuncGen *self, uint32_t stack_idx) {
99+
return self->stack[self->stack_i - 1 - stack_idx];
100+
}
101+
102+
static uint32_t FuncGen_stackPop(struct FuncGen *self) {
103+
self->stack_i -= 1;
104+
return self->stack[self->stack_i];
105+
}
106+
107+
static void FuncGen_label(struct FuncGen *self, FILE *out, uint32_t label) {
108+
FuncGen_indent(self, out);
109+
fprintf(out, "goto l%" PRIu32 ";\n", label);
110+
FuncGen_outdent(self, out);
111+
fprintf(out, "l%" PRIu32 ":;\n", label);
112+
}
113+
114+
static void FuncGen_blockBegin(struct FuncGen *self, FILE *out, enum WasmOpcode kind, int64_t type) {
115+
if (self->block_i == self->block_len) {
116+
self->block_len += 10;
117+
self->block_len *= 2;
118+
self->block = realloc(self->block, sizeof(struct Block) * self->block_len);
119+
if (self->block == NULL) panic("out of memory");
120+
}
121+
uint32_t label = FuncGen_localAlloc(self, type < 0 ? ~(int8_t)kind : (int8_t)kind);
122+
FuncGen_indent(self, out);
123+
if (kind == WasmOpcode_if) fprintf(out, "if (l%" PRIu32 ") ", FuncGen_stackPop(self));
124+
fputs("{\n", out);
125+
self->block[self->block_i].type = type < 0 ? ~type : type;
126+
self->block[self->block_i].label = label;
127+
self->block[self->block_i].stack_i = self->stack_i;
128+
self->block_i += 1;
129+
if (kind == WasmOpcode_loop) FuncGen_label(self, out, label);
130+
}
131+
132+
static enum WasmOpcode FuncGen_blockKind(const struct FuncGen *self, uint32_t label_idx) {
133+
int8_t kind = self->type[self->block[self->block_i - 1 - label_idx].label];
134+
return (enum WasmOpcode)(kind < 0 ? ~kind : kind);
135+
}
136+
137+
static int64_t FuncGen_blockType(const struct FuncGen *self, uint32_t label_idx) {
138+
struct Block *block = &self->block[self->block_i - 1 - label_idx];
139+
return self->type[block->label] < 0 ? ~(int64_t)block->type : (int64_t)block->type;
140+
}
141+
142+
static uint32_t FuncGen_blockLabel(const struct FuncGen *self, uint32_t label_idx) {
143+
return self->block[self->block_i - 1 - label_idx].label;
144+
}
145+
146+
static void FuncGen_blockEnd(struct FuncGen *self, FILE *out) {
147+
enum WasmOpcode kind = FuncGen_blockKind(self, 0);
148+
uint32_t label = FuncGen_blockLabel(self, 0);
149+
if (kind != WasmOpcode_loop) FuncGen_label(self, out, label);
150+
self->block_i -= 1;
151+
FuncGen_indent(self, out);
152+
fputs("}\n", out);
153+
if (self->stack_i != self->block[self->block_i].stack_i) {
154+
FuncGen_indent(self, out);
155+
fprintf(out, "// stack mismatch %u != %u\n", self->stack_i, self->block[self->block_i].stack_i);
156+
}
157+
self->stack_i = self->block[self->block_i].stack_i;
158+
}
159+
160+
static bool FuncGen_done(const struct FuncGen *self) {
161+
return self->block_i == 0;
162+
}
163+
164+
#endif /* FUNC_GEN_H */

0 commit comments

Comments
 (0)