spec: 타깃을 i386 하나로 정하고 far 를 언어에서 뺀다

세그먼트 주소 지정은 x86 리얼모드에만 있는 개념이고, 평평한 주소 공간을 가진
다른 32비트 프로세서에는 대응물이 없다. 영구 제외다.

usize/isize 는 타깃의 포인터 폭이며 특정 비트 수를 약속하지 않는다. 오늘
32비트지만 u32 와 자동 변환되지 않는다. bits16 에서 배울 것은 '32로 정하자'가
아니라 '폭이 언어 의미론으로 새어나가지 않게 하자'이고, 그것이 나중에 다른
폭의 타깃을 여는 유일한 장치다.

타깃이 하나이므로 레이아웃에서 pointer_bits 분기가 전부 사라졌다. 인터럽트
핸들러와 공유 상태는 v0.2 로 내렸다 -- 문법은 아직 파싱되지만 명세의 약속은
아니다.
This commit is contained in:
2026-08-17 05:40:49 +09:00
parent 25d9de65e1
commit 718c323938
7 changed files with 72 additions and 93 deletions
+2 -4
View File
@@ -16,7 +16,7 @@ static char *read_file(const char *name, unsigned long *size)
static void usage(void)
{
puts("usage: fec [--dump-tokens|--dump-ast|--check|--emit-c] file.fe [--target=bits16|bits32] [-o output.c]");
puts("usage: fec [--dump-tokens|--dump-ast|--check] file.fe [--no-checks]");
}
static void dump_tokens(const char *src, unsigned long n, const char *file,
@@ -45,14 +45,12 @@ int main(int argc, char **argv)
FeAst ast;
FeParser p;
FeCheck check;
unsigned pointer_bits=32;
unsigned pointer_bits=FE_PTR_BITS;
if(argc<2){usage();return 2;}
for(i=1;i<argc;i++) {
if(strcmp(argv[i],"--dump-ast")==0) dump=1;
else if(strcmp(argv[i],"--dump-tokens")==0) dump_tok=1;
else if(strcmp(argv[i],"--check")==0) check_only=1;
else if(strncmp(argv[i],"--target=bits16",15)==0) pointer_bits=16;
else if(strncmp(argv[i],"--target=bits32",15)==0) pointer_bits=32;
else if(strcmp(argv[i],"--no-checks")==0) no_checks=1;
else if(strncmp(argv[i],"--target=",9)==0 || strncmp(argv[i],"--model=",8)==0 || strcmp(argv[i],"--strip-error-names")==0) { }
else if(argv[i][0]!='-') file=argv[i];
+1 -1
View File
@@ -11,7 +11,7 @@ static const FeKw keywords[] = {
{"match",FE_TOK_MATCH},{"return",FE_TOK_RETURN},{"break",FE_TOK_BREAK},{"continue",FE_TOK_CONTINUE},
{"defer",FE_TOK_DEFER},{"unsafe",FE_TOK_UNSAFE},{"comptime",FE_TOK_COMPTIME},{"asm",FE_TOK_ASM},
{"try",FE_TOK_TRY},{"catch",FE_TOK_CATCH},{"as",FE_TOK_AS},{"extern",FE_TOK_EXTERN},
{"interrupt",FE_TOK_INTERRUPT},{"interrupt_safe",FE_TOK_INTERRUPT_SAFE},{"far",FE_TOK_FAR},
{"interrupt",FE_TOK_INTERRUPT},{"interrupt_safe",FE_TOK_INTERRUPT_SAFE},
{"true",FE_TOK_TRUE},{"false",FE_TOK_FALSE},{"null",FE_TOK_NULL},{"undefined",FE_TOK_UNDEFINED},
{"shared",FE_TOK_SHARED},{"atomic",FE_TOK_ATOMIC},{"critical",FE_TOK_CRITICAL},
{"self",FE_TOK_SELF},{"Self",FE_TOK_SELFTYPE},{"type",FE_TOK_TYPE},
-3
View File
@@ -43,9 +43,6 @@ static FeNode *type(FeParser *p)
if (is(p,FE_TOK_AND)) {
next(p); n=toknode(p,FE_N_TYPE,t); if(eat(p,FE_TOK_MUT)) n->text=fe_arena_strdup(&p->ast->arena,"&mut",4); n->a=type(p); return n;
}
if (is(p,FE_TOK_FAR)) {
next(p); n=toknode(p,FE_N_TYPE,t); if(is(p,FE_TOK_STAR)||is(p,FE_TOK_XOR)||is(p,FE_TOK_AND)) next(p); n->a=type(p); return n;
}
if (is(p,FE_TOK_LBRACKET)) {
next(p); n=toknode(p,FE_N_TYPE,t);
if(!eat(p,FE_TOK_RBRACKET)) { n->a=expr(p,0); want(p,FE_TOK_RBRACKET,"expected ']' in array type"); }
+19 -21
View File
@@ -441,12 +441,12 @@ static void layout_type(FeTypeCtx *ctx, FeType *t)
if (t->kind == FE_TYPE_ERROR_UNION) {
if (t->error_value && t->error_value->kind != FE_TYPE_VOID) {
layout_type(ctx,t->error_value);
t->align=ctx->pointer_bits==16 ? 1U : fe_type_align(t->error_value);
t->align=fe_type_align(t->error_value);
t->size=round_up(2UL,t->align)+fe_type_size(t->error_value);
t->size=round_up(t->size,t->align);
} else {
t->size=2;
t->align=ctx->pointer_bits==16 ? 1U : 2U;
t->align=2U;
}
t->cycle_state = 2; return;
}
@@ -456,7 +456,7 @@ static void layout_type(FeTypeCtx *ctx, FeType *t)
t->size=fe_type_size(t->elem);
t->align=fe_type_align(t->elem);
} else {
t->align=ctx->pointer_bits==16 ? 1U : fe_type_align(t->elem);
t->align=fe_type_align(t->elem);
t->size=round_up(1UL,t->align)+fe_type_size(t->elem);
t->size=round_up(t->size,t->align);
}
@@ -467,30 +467,29 @@ static void layout_type(FeTypeCtx *ctx, FeType *t)
}
if (t->kind == FE_TYPE_INT) {
t->size = (t->bits + 7U) / 8U;
t->align = ctx->pointer_bits == 16 ? 1U : t->size;
if (t->size > 4UL) t->size = ctx->pointer_bits == 16 ? 2UL : 4UL;
t->align = t->size;
if (t->size > 4UL) t->size = 4UL;
t->cycle_state = 2; return;
}
if (t->kind == FE_TYPE_REF) {
t->size = ctx->pointer_bits == 16 ? 2UL : 4UL;
t->align = ctx->pointer_bits == 16 ? 1U : 4U;
t->size = FE_PTR_SIZE;
t->align = FE_PTR_ALIGN;
t->cycle_state = 2; return;
}
if (t->kind == FE_TYPE_OWNED) {
t->size = t->elem && t->elem->kind==FE_TYPE_SLICE ?
(ctx->pointer_bits == 16 ? 4UL : 8UL) :
(ctx->pointer_bits == 16 ? 2UL : 4UL);
t->align = ctx->pointer_bits == 16 ? 1U : 4U;
2UL * FE_PTR_SIZE : FE_PTR_SIZE;
t->align = FE_PTR_ALIGN;
t->cycle_state = 2; return;
}
if (t->kind == FE_TYPE_SLICE || t->kind == FE_TYPE_STR) {
t->size = ctx->pointer_bits == 16 ? 4UL : 8UL;
t->align = ctx->pointer_bits == 16 ? 1U : 4U;
t->size = 2UL * FE_PTR_SIZE;
t->align = FE_PTR_ALIGN;
t->cycle_state = 2; return;
}
if (t->kind == FE_TYPE_ARRAY) {
layout_type(ctx, t->elem);
t->align = t->packed || ctx->pointer_bits == 16 ? 1U : fe_type_align(t->elem);
t->align = t->packed ? 1U : fe_type_align(t->elem);
t->size = t->length * fe_type_size(t->elem);
t->cycle_state = 2; return;
}
@@ -500,7 +499,7 @@ static void layout_type(FeTypeCtx *ctx, FeType *t)
if (!t->fields[i].type && t->fields[i].ast_node)
t->fields[i].type = fe_type_from_ast(ctx, t->fields[i].ast_node->a);
layout_type(ctx, t->fields[i].type);
align = t->packed || ctx->pointer_bits == 16 ? 1U : fe_type_align(t->fields[i].type);
align = t->packed ? 1U : fe_type_align(t->fields[i].type);
if (align > max_align) max_align = align;
off = round_up(off, align);
t->fields[i].offset = off;
@@ -528,9 +527,9 @@ static void layout_type(FeTypeCtx *ctx, FeType *t)
if (off > max_size) max_size = off;
}
t->bits = t->variant_count > 256U ? 16U : 8U;
off = ctx->pointer_bits == 16 ? t->bits / 8U : round_up(t->bits / 8U, max_align);
t->size = round_up(off + max_size, ctx->pointer_bits == 16 ? 1U : max_align);
t->align = ctx->pointer_bits == 16 ? 1U : max_align;
off = round_up(t->bits / 8U, max_align);
t->size = round_up(off + max_size, max_align);
t->align = max_align;
t->cycle_state = 2;
}
}
@@ -599,8 +598,7 @@ FeType *fe_type_from_ast(FeTypeCtx *ctx, const FeNode *node)
fe_type_from_ast(ctx,node->b));
return fe_type_error_union(ctx,fe_type_from_ast(ctx,node->a));
}
if (node->text && (strcmp(node->text, "*") == 0 ||
strcmp(node->text, "far") == 0))
if (node->text && strcmp(node->text, "*") == 0)
return fe_type_intern(ctx, "<unknown>");
if (node->text && strcmp(node->text, "fn") == 0)
return fe_type_intern(ctx, "<unknown>");
@@ -665,8 +663,8 @@ const char *fe_type_c_name(const FeType *t, unsigned pointer_bits)
return owned_name;
}
if (t->kind != FE_TYPE_INT) return "long";
if (strcmp(t->name, "usize") == 0) return pointer_bits == 16 ? "unsigned short" : "unsigned long";
if (strcmp(t->name, "isize") == 0) return pointer_bits == 16 ? "short" : "long";
if (strcmp(t->name, "usize") == 0) return "unsigned long";
if (strcmp(t->name, "isize") == 0) return "long";
if (strcmp(t->name, "i8") == 0) return "signed char";
if (strcmp(t->name, "u8") == 0) return "unsigned char";
if (strcmp(t->name, "i16") == 0) return "short";
+7
View File
@@ -10,6 +10,13 @@ typedef enum FeTypeKind {
FE_TYPE_REF, FE_TYPE_OWNED, FE_TYPE_UNKNOWN
} FeTypeKind;
/* One target, one pointer width (SPEC 2). usize and isize are that width and
are not promised to be any particular number of bits, which is what keeps a
different width possible later. */
#define FE_PTR_SIZE 4UL
#define FE_PTR_ALIGN 4U
#define FE_PTR_BITS 32U
typedef struct FeFieldType FeFieldType;
/* A type parameter bound to an argument while an instance is checked. */