mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
Merge remote-tracking branch 'origin/master' into llvm7
This commit is contained in:
commit
c9474faa4e
@ -199,7 +199,7 @@ else()
|
||||
if(MSVC)
|
||||
set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w")
|
||||
else()
|
||||
set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment -Wno-class-memaccess -Wno-unknown-warning-option")
|
||||
set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment")
|
||||
endif()
|
||||
set_target_properties(embedded_lld_lib PROPERTIES
|
||||
COMPILE_FLAGS ${ZIG_LLD_COMPILE_FLAGS}
|
||||
@ -775,20 +775,25 @@ include_directories(
|
||||
"${CMAKE_SOURCE_DIR}/src"
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /w")
|
||||
elseif(MINGW)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Werror -Wno-error=format= -Wno-error=format -Wno-error=format-extra-args")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror -Wall")
|
||||
# These have to go before the -Wno- flags
|
||||
set(EXE_CFLAGS "-std=c++11")
|
||||
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
if(MSVC)
|
||||
set(EXE_CFLAGS "${EXE_CFLAGS} /w")
|
||||
elseif(MINGW)
|
||||
set(EXE_CFLAGS "${EXE_CFLAGS} -Wall -Werror -Wno-error=format= -Wno-error=format -Wno-error=format-extra-args")
|
||||
else()
|
||||
set(EXE_CFLAGS "${EXE_CFLAGS} -Werror -Wall")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set(EXE_CFLAGS "-std=c++11")
|
||||
set(EXE_CFLAGS "${EXE_CFLAGS}")
|
||||
else()
|
||||
set(EXE_CFLAGS "-std=c++11 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")
|
||||
set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")
|
||||
endif()
|
||||
|
||||
|
||||
set(EXE_LDFLAGS " ")
|
||||
if(MINGW)
|
||||
set(EXE_LDFLAGS "-static -static-libgcc -static-libstdc++")
|
||||
|
||||
@ -1587,7 +1587,7 @@ test "pointer casting" {
|
||||
// operation that Zig cannot protect you against. Use @ptrCast only when other
|
||||
// conversions are not possible.
|
||||
const bytes align(@alignOf(u32)) = []u8{ 0x12, 0x12, 0x12, 0x12 };
|
||||
const u32_ptr = @ptrCast(*const u32, &bytes[0]);
|
||||
const u32_ptr = @ptrCast(*const u32, &bytes);
|
||||
assert(u32_ptr.* == 0x12121212);
|
||||
|
||||
// Even this example is contrived - there are better ways to do the above than
|
||||
|
||||
@ -20,12 +20,12 @@
|
||||
|
||||
struct AstNode;
|
||||
struct ImportTableEntry;
|
||||
struct FnTableEntry;
|
||||
struct ZigFn;
|
||||
struct Scope;
|
||||
struct ScopeBlock;
|
||||
struct ScopeFnDef;
|
||||
struct TypeTableEntry;
|
||||
struct VariableTableEntry;
|
||||
struct ZigType;
|
||||
struct ZigVar;
|
||||
struct ErrorTableEntry;
|
||||
struct BuiltinFnEntry;
|
||||
struct TypeStructField;
|
||||
@ -40,10 +40,17 @@ struct Tld;
|
||||
struct TldExport;
|
||||
struct IrAnalyze;
|
||||
|
||||
enum X64CABIClass {
|
||||
X64CABIClass_Unknown,
|
||||
X64CABIClass_MEMORY,
|
||||
X64CABIClass_INTEGER,
|
||||
X64CABIClass_SSE,
|
||||
};
|
||||
|
||||
struct IrExecutable {
|
||||
ZigList<IrBasicBlock *> basic_block_list;
|
||||
Buf *name;
|
||||
FnTableEntry *name_fn;
|
||||
ZigFn *name_fn;
|
||||
size_t mem_slot_count;
|
||||
size_t next_debug_id;
|
||||
size_t *backward_branch_count;
|
||||
@ -51,7 +58,7 @@ struct IrExecutable {
|
||||
bool invalid;
|
||||
bool is_inline;
|
||||
bool is_generic_instantiation;
|
||||
FnTableEntry *fn_entry;
|
||||
ZigFn *fn_entry;
|
||||
Buf *c_import_buf;
|
||||
AstNode *source_node;
|
||||
IrExecutable *parent_exec;
|
||||
@ -69,7 +76,7 @@ struct IrExecutable {
|
||||
IrBasicBlock *coro_normal_final;
|
||||
IrBasicBlock *coro_suspend_block;
|
||||
IrBasicBlock *coro_final_cleanup_block;
|
||||
VariableTableEntry *coro_allocator_var;
|
||||
ZigVar *coro_allocator_var;
|
||||
};
|
||||
|
||||
enum OutType {
|
||||
@ -191,7 +198,7 @@ struct ConstPtrValue {
|
||||
uint64_t addr;
|
||||
} hard_coded_addr;
|
||||
struct {
|
||||
FnTableEntry *fn_entry;
|
||||
ZigFn *fn_entry;
|
||||
} fn;
|
||||
} data;
|
||||
};
|
||||
@ -202,7 +209,7 @@ struct ConstErrValue {
|
||||
};
|
||||
|
||||
struct ConstBoundFnValue {
|
||||
FnTableEntry *fn;
|
||||
ZigFn *fn;
|
||||
IrInstruction *first_arg;
|
||||
};
|
||||
|
||||
@ -251,7 +258,7 @@ struct ConstGlobalRefs {
|
||||
};
|
||||
|
||||
struct ConstExprValue {
|
||||
TypeTableEntry *type;
|
||||
ZigType *type;
|
||||
ConstValSpecial special;
|
||||
ConstGlobalRefs *global_refs;
|
||||
|
||||
@ -265,7 +272,7 @@ struct ConstExprValue {
|
||||
float128_t x_f128;
|
||||
bool x_bool;
|
||||
ConstBoundFnValue x_bound_fn;
|
||||
TypeTableEntry *x_type;
|
||||
ZigType *x_type;
|
||||
ConstExprValue *x_optional;
|
||||
ConstErrValue x_err_union;
|
||||
ErrorTableEntry *x_err_set;
|
||||
@ -337,7 +344,7 @@ struct Tld {
|
||||
struct TldVar {
|
||||
Tld base;
|
||||
|
||||
VariableTableEntry *var;
|
||||
ZigVar *var;
|
||||
Buf *extern_lib_name;
|
||||
Buf *section_name;
|
||||
};
|
||||
@ -345,7 +352,7 @@ struct TldVar {
|
||||
struct TldFn {
|
||||
Tld base;
|
||||
|
||||
FnTableEntry *fn_entry;
|
||||
ZigFn *fn_entry;
|
||||
Buf *extern_lib_name;
|
||||
};
|
||||
|
||||
@ -353,7 +360,7 @@ struct TldContainer {
|
||||
Tld base;
|
||||
|
||||
ScopeDecls *decls_scope;
|
||||
TypeTableEntry *type_entry;
|
||||
ZigType *type_entry;
|
||||
};
|
||||
|
||||
struct TldCompTime {
|
||||
@ -370,7 +377,7 @@ struct TypeEnumField {
|
||||
struct TypeUnionField {
|
||||
Buf *name;
|
||||
TypeEnumField *enum_field;
|
||||
TypeTableEntry *type_entry;
|
||||
ZigType *type_entry;
|
||||
AstNode *decl_node;
|
||||
uint32_t gen_index;
|
||||
};
|
||||
@ -973,11 +980,11 @@ struct AstNode {
|
||||
// this struct is allocated with allocate_nonzero
|
||||
struct FnTypeParamInfo {
|
||||
bool is_noalias;
|
||||
TypeTableEntry *type;
|
||||
ZigType *type;
|
||||
};
|
||||
|
||||
struct GenericFnTypeId {
|
||||
FnTableEntry *fn_entry;
|
||||
ZigFn *fn_entry;
|
||||
ConstExprValue *params;
|
||||
size_t param_count;
|
||||
};
|
||||
@ -986,14 +993,14 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id);
|
||||
bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b);
|
||||
|
||||
struct FnTypeId {
|
||||
TypeTableEntry *return_type;
|
||||
ZigType *return_type;
|
||||
FnTypeParamInfo *param_info;
|
||||
size_t param_count;
|
||||
size_t next_param_index;
|
||||
bool is_var_args;
|
||||
CallingConvention cc;
|
||||
uint32_t alignment;
|
||||
TypeTableEntry *async_allocator_type;
|
||||
ZigType *async_allocator_type;
|
||||
};
|
||||
|
||||
uint32_t fn_type_id_hash(FnTypeId*);
|
||||
@ -1004,34 +1011,34 @@ enum PtrLen {
|
||||
PtrLenSingle,
|
||||
};
|
||||
|
||||
struct TypeTableEntryPointer {
|
||||
TypeTableEntry *child_type;
|
||||
struct ZigTypePointer {
|
||||
ZigType *child_type;
|
||||
PtrLen ptr_len;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
uint32_t alignment;
|
||||
uint32_t bit_offset;
|
||||
uint32_t unaligned_bit_count;
|
||||
TypeTableEntry *slice_parent;
|
||||
ZigType *slice_parent;
|
||||
};
|
||||
|
||||
struct TypeTableEntryInt {
|
||||
struct ZigTypeInt {
|
||||
uint32_t bit_count;
|
||||
bool is_signed;
|
||||
};
|
||||
|
||||
struct TypeTableEntryFloat {
|
||||
struct ZigTypeFloat {
|
||||
size_t bit_count;
|
||||
};
|
||||
|
||||
struct TypeTableEntryArray {
|
||||
TypeTableEntry *child_type;
|
||||
struct ZigTypeArray {
|
||||
ZigType *child_type;
|
||||
uint64_t len;
|
||||
};
|
||||
|
||||
struct TypeStructField {
|
||||
Buf *name;
|
||||
TypeTableEntry *type_entry;
|
||||
ZigType *type_entry;
|
||||
size_t src_index;
|
||||
size_t gen_index;
|
||||
// offset from the memory at gen_index
|
||||
@ -1040,7 +1047,7 @@ struct TypeStructField {
|
||||
size_t unaligned_bit_count;
|
||||
AstNode *decl_node;
|
||||
};
|
||||
struct TypeTableEntryStruct {
|
||||
struct ZigTypeStruct {
|
||||
AstNode *decl_node;
|
||||
ContainerLayout layout;
|
||||
uint32_t src_field_count;
|
||||
@ -1068,28 +1075,28 @@ struct TypeTableEntryStruct {
|
||||
HashMap<Buf *, TypeStructField *, buf_hash, buf_eql_buf> fields_by_name;
|
||||
};
|
||||
|
||||
struct TypeTableEntryOptional {
|
||||
TypeTableEntry *child_type;
|
||||
struct ZigTypeOptional {
|
||||
ZigType *child_type;
|
||||
};
|
||||
|
||||
struct TypeTableEntryErrorUnion {
|
||||
TypeTableEntry *err_set_type;
|
||||
TypeTableEntry *payload_type;
|
||||
struct ZigTypeErrorUnion {
|
||||
ZigType *err_set_type;
|
||||
ZigType *payload_type;
|
||||
};
|
||||
|
||||
struct TypeTableEntryErrorSet {
|
||||
struct ZigTypeErrorSet {
|
||||
uint32_t err_count;
|
||||
ErrorTableEntry **errors;
|
||||
FnTableEntry *infer_fn;
|
||||
ZigFn *infer_fn;
|
||||
};
|
||||
|
||||
struct TypeTableEntryEnum {
|
||||
struct ZigTypeEnum {
|
||||
AstNode *decl_node;
|
||||
ContainerLayout layout;
|
||||
uint32_t src_field_count;
|
||||
TypeEnumField *fields;
|
||||
bool is_invalid; // true if any fields are invalid
|
||||
TypeTableEntry *tag_int_type;
|
||||
ZigType *tag_int_type;
|
||||
|
||||
ScopeDecls *decls_scope;
|
||||
|
||||
@ -1107,17 +1114,17 @@ struct TypeTableEntryEnum {
|
||||
HashMap<Buf *, TypeEnumField *, buf_hash, buf_eql_buf> fields_by_name;
|
||||
};
|
||||
|
||||
uint32_t type_ptr_hash(const TypeTableEntry *ptr);
|
||||
bool type_ptr_eql(const TypeTableEntry *a, const TypeTableEntry *b);
|
||||
uint32_t type_ptr_hash(const ZigType *ptr);
|
||||
bool type_ptr_eql(const ZigType *a, const ZigType *b);
|
||||
|
||||
struct TypeTableEntryUnion {
|
||||
struct ZigTypeUnion {
|
||||
AstNode *decl_node;
|
||||
ContainerLayout layout;
|
||||
uint32_t src_field_count;
|
||||
uint32_t gen_field_count;
|
||||
TypeUnionField *fields;
|
||||
bool is_invalid; // true if any fields are invalid
|
||||
TypeTableEntry *tag_type; // always an enum or null
|
||||
ZigType *tag_type; // always an enum or null
|
||||
LLVMTypeRef union_type_ref;
|
||||
|
||||
ScopeDecls *decls_scope;
|
||||
@ -1142,7 +1149,7 @@ struct TypeTableEntryUnion {
|
||||
bool have_explicit_tag_type;
|
||||
|
||||
uint32_t union_size_bytes;
|
||||
TypeTableEntry *most_aligned_union_member;
|
||||
ZigType *most_aligned_union_member;
|
||||
|
||||
HashMap<Buf *, TypeUnionField *, buf_hash, buf_eql_buf> fields_by_name;
|
||||
};
|
||||
@ -1151,61 +1158,61 @@ struct FnGenParamInfo {
|
||||
size_t src_index;
|
||||
size_t gen_index;
|
||||
bool is_byval;
|
||||
TypeTableEntry *type;
|
||||
ZigType *type;
|
||||
};
|
||||
|
||||
struct TypeTableEntryFn {
|
||||
struct ZigTypeFn {
|
||||
FnTypeId fn_type_id;
|
||||
bool is_generic;
|
||||
TypeTableEntry *gen_return_type;
|
||||
ZigType *gen_return_type;
|
||||
size_t gen_param_count;
|
||||
FnGenParamInfo *gen_param_info;
|
||||
|
||||
LLVMTypeRef raw_type_ref;
|
||||
|
||||
TypeTableEntry *bound_fn_parent;
|
||||
ZigType *bound_fn_parent;
|
||||
};
|
||||
|
||||
struct TypeTableEntryBoundFn {
|
||||
TypeTableEntry *fn_type;
|
||||
struct ZigTypeBoundFn {
|
||||
ZigType *fn_type;
|
||||
};
|
||||
|
||||
struct TypeTableEntryPromise {
|
||||
struct ZigTypePromise {
|
||||
// null if `promise` instead of `promise->T`
|
||||
TypeTableEntry *result_type;
|
||||
ZigType *result_type;
|
||||
};
|
||||
|
||||
enum TypeTableEntryId {
|
||||
TypeTableEntryIdInvalid,
|
||||
TypeTableEntryIdMetaType,
|
||||
TypeTableEntryIdVoid,
|
||||
TypeTableEntryIdBool,
|
||||
TypeTableEntryIdUnreachable,
|
||||
TypeTableEntryIdInt,
|
||||
TypeTableEntryIdFloat,
|
||||
TypeTableEntryIdPointer,
|
||||
TypeTableEntryIdArray,
|
||||
TypeTableEntryIdStruct,
|
||||
TypeTableEntryIdComptimeFloat,
|
||||
TypeTableEntryIdComptimeInt,
|
||||
TypeTableEntryIdUndefined,
|
||||
TypeTableEntryIdNull,
|
||||
TypeTableEntryIdOptional,
|
||||
TypeTableEntryIdErrorUnion,
|
||||
TypeTableEntryIdErrorSet,
|
||||
TypeTableEntryIdEnum,
|
||||
TypeTableEntryIdUnion,
|
||||
TypeTableEntryIdFn,
|
||||
TypeTableEntryIdNamespace,
|
||||
TypeTableEntryIdBlock,
|
||||
TypeTableEntryIdBoundFn,
|
||||
TypeTableEntryIdArgTuple,
|
||||
TypeTableEntryIdOpaque,
|
||||
TypeTableEntryIdPromise,
|
||||
enum ZigTypeId {
|
||||
ZigTypeIdInvalid,
|
||||
ZigTypeIdMetaType,
|
||||
ZigTypeIdVoid,
|
||||
ZigTypeIdBool,
|
||||
ZigTypeIdUnreachable,
|
||||
ZigTypeIdInt,
|
||||
ZigTypeIdFloat,
|
||||
ZigTypeIdPointer,
|
||||
ZigTypeIdArray,
|
||||
ZigTypeIdStruct,
|
||||
ZigTypeIdComptimeFloat,
|
||||
ZigTypeIdComptimeInt,
|
||||
ZigTypeIdUndefined,
|
||||
ZigTypeIdNull,
|
||||
ZigTypeIdOptional,
|
||||
ZigTypeIdErrorUnion,
|
||||
ZigTypeIdErrorSet,
|
||||
ZigTypeIdEnum,
|
||||
ZigTypeIdUnion,
|
||||
ZigTypeIdFn,
|
||||
ZigTypeIdNamespace,
|
||||
ZigTypeIdBlock,
|
||||
ZigTypeIdBoundFn,
|
||||
ZigTypeIdArgTuple,
|
||||
ZigTypeIdOpaque,
|
||||
ZigTypeIdPromise,
|
||||
};
|
||||
|
||||
struct TypeTableEntry {
|
||||
TypeTableEntryId id;
|
||||
struct ZigType {
|
||||
ZigTypeId id;
|
||||
Buf name;
|
||||
|
||||
LLVMTypeRef type_ref;
|
||||
@ -1216,26 +1223,26 @@ struct TypeTableEntry {
|
||||
bool gen_h_loop_flag;
|
||||
|
||||
union {
|
||||
TypeTableEntryPointer pointer;
|
||||
TypeTableEntryInt integral;
|
||||
TypeTableEntryFloat floating;
|
||||
TypeTableEntryArray array;
|
||||
TypeTableEntryStruct structure;
|
||||
TypeTableEntryOptional maybe;
|
||||
TypeTableEntryErrorUnion error_union;
|
||||
TypeTableEntryErrorSet error_set;
|
||||
TypeTableEntryEnum enumeration;
|
||||
TypeTableEntryUnion unionation;
|
||||
TypeTableEntryFn fn;
|
||||
TypeTableEntryBoundFn bound_fn;
|
||||
TypeTableEntryPromise promise;
|
||||
ZigTypePointer pointer;
|
||||
ZigTypeInt integral;
|
||||
ZigTypeFloat floating;
|
||||
ZigTypeArray array;
|
||||
ZigTypeStruct structure;
|
||||
ZigTypeOptional maybe;
|
||||
ZigTypeErrorUnion error_union;
|
||||
ZigTypeErrorSet error_set;
|
||||
ZigTypeEnum enumeration;
|
||||
ZigTypeUnion unionation;
|
||||
ZigTypeFn fn;
|
||||
ZigTypeBoundFn bound_fn;
|
||||
ZigTypePromise promise;
|
||||
} data;
|
||||
|
||||
// use these fields to make sure we don't duplicate type table entries for the same type
|
||||
TypeTableEntry *pointer_parent[2]; // [0 - mut, 1 - const]
|
||||
TypeTableEntry *optional_parent;
|
||||
TypeTableEntry *promise_parent;
|
||||
TypeTableEntry *promise_frame_parent;
|
||||
ZigType *pointer_parent[2]; // [0 - mut, 1 - const]
|
||||
ZigType *optional_parent;
|
||||
ZigType *promise_parent;
|
||||
ZigType *promise_frame_parent;
|
||||
// If we generate a constant name value for this type, we memoize it here.
|
||||
// The type of this is array
|
||||
ConstExprValue *cached_const_name_val;
|
||||
@ -1282,7 +1289,7 @@ struct FnExport {
|
||||
GlobalLinkageId linkage;
|
||||
};
|
||||
|
||||
struct FnTableEntry {
|
||||
struct ZigFn {
|
||||
LLVMValueRef llvm_value;
|
||||
const char *llvm_name;
|
||||
AstNode *proto_node;
|
||||
@ -1291,11 +1298,11 @@ struct FnTableEntry {
|
||||
Scope *child_scope; // parent is scope for last parameter
|
||||
ScopeBlock *def_scope; // parent is child_scope
|
||||
Buf symbol_name;
|
||||
TypeTableEntry *type_entry; // function type
|
||||
ZigType *type_entry; // function type
|
||||
// in the case of normal functions this is the implicit return type
|
||||
// in the case of async functions this is the implicit return type according to the
|
||||
// zig source code, not according to zig ir
|
||||
TypeTableEntry *src_implicit_return_type;
|
||||
ZigType *src_implicit_return_type;
|
||||
bool is_test;
|
||||
FnInline fn_inline;
|
||||
FnAnalState anal_state;
|
||||
@ -1310,7 +1317,7 @@ struct FnTableEntry {
|
||||
AstNode *fn_static_eval_set_node;
|
||||
|
||||
ZigList<IrInstruction *> alloca_list;
|
||||
ZigList<VariableTableEntry *> variable_list;
|
||||
ZigList<ZigVar *> variable_list;
|
||||
|
||||
Buf *section_name;
|
||||
AstNode *set_alignstack_node;
|
||||
@ -1323,8 +1330,8 @@ struct FnTableEntry {
|
||||
bool calls_or_awaits_errorable_fn;
|
||||
};
|
||||
|
||||
uint32_t fn_table_entry_hash(FnTableEntry*);
|
||||
bool fn_table_entry_eql(FnTableEntry *a, FnTableEntry *b);
|
||||
uint32_t fn_table_entry_hash(ZigFn*);
|
||||
bool fn_table_entry_eql(ZigFn *a, ZigFn *b);
|
||||
|
||||
enum BuiltinFnId {
|
||||
BuiltinFnIdInvalid,
|
||||
@ -1445,11 +1452,11 @@ uint32_t fn_eval_hash(Scope*);
|
||||
bool fn_eval_eql(Scope *a, Scope *b);
|
||||
|
||||
struct TypeId {
|
||||
TypeTableEntryId id;
|
||||
ZigTypeId id;
|
||||
|
||||
union {
|
||||
struct {
|
||||
TypeTableEntry *child_type;
|
||||
ZigType *child_type;
|
||||
PtrLen ptr_len;
|
||||
bool is_const;
|
||||
bool is_volatile;
|
||||
@ -1458,7 +1465,7 @@ struct TypeId {
|
||||
uint32_t unaligned_bit_count;
|
||||
} pointer;
|
||||
struct {
|
||||
TypeTableEntry *child_type;
|
||||
ZigType *child_type;
|
||||
uint64_t size;
|
||||
} array;
|
||||
struct {
|
||||
@ -1466,8 +1473,8 @@ struct TypeId {
|
||||
uint32_t bit_count;
|
||||
} integer;
|
||||
struct {
|
||||
TypeTableEntry *err_set_type;
|
||||
TypeTableEntry *payload_type;
|
||||
ZigType *err_set_type;
|
||||
ZigType *payload_type;
|
||||
} error_union;
|
||||
} data;
|
||||
};
|
||||
@ -1563,17 +1570,17 @@ struct CodeGen {
|
||||
// reminder: hash tables must be initialized before use
|
||||
HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
|
||||
HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
|
||||
HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
|
||||
HashMap<TypeId, TypeTableEntry *, type_id_hash, type_id_eql> type_table;
|
||||
HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
|
||||
HashMap<Buf *, ZigType *, buf_hash, buf_eql_buf> primitive_type_table;
|
||||
HashMap<TypeId, ZigType *, type_id_hash, type_id_eql> type_table;
|
||||
HashMap<FnTypeId *, ZigType *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
|
||||
HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
|
||||
HashMap<GenericFnTypeId *, FnTableEntry *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
|
||||
HashMap<GenericFnTypeId *, ZigFn *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
|
||||
HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
|
||||
HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
|
||||
HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names;
|
||||
HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
|
||||
HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;
|
||||
HashMap<const TypeTableEntry *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
|
||||
HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
|
||||
|
||||
|
||||
ZigList<ImportTableEntry *> import_queue;
|
||||
@ -1586,38 +1593,38 @@ struct CodeGen {
|
||||
uint32_t next_unresolved_index;
|
||||
|
||||
struct {
|
||||
TypeTableEntry *entry_bool;
|
||||
TypeTableEntry *entry_c_int[CIntTypeCount];
|
||||
TypeTableEntry *entry_c_longdouble;
|
||||
TypeTableEntry *entry_c_void;
|
||||
TypeTableEntry *entry_u8;
|
||||
TypeTableEntry *entry_u16;
|
||||
TypeTableEntry *entry_u32;
|
||||
TypeTableEntry *entry_u29;
|
||||
TypeTableEntry *entry_u64;
|
||||
TypeTableEntry *entry_i8;
|
||||
TypeTableEntry *entry_i32;
|
||||
TypeTableEntry *entry_i64;
|
||||
TypeTableEntry *entry_isize;
|
||||
TypeTableEntry *entry_usize;
|
||||
TypeTableEntry *entry_f16;
|
||||
TypeTableEntry *entry_f32;
|
||||
TypeTableEntry *entry_f64;
|
||||
TypeTableEntry *entry_f128;
|
||||
TypeTableEntry *entry_void;
|
||||
TypeTableEntry *entry_unreachable;
|
||||
TypeTableEntry *entry_type;
|
||||
TypeTableEntry *entry_invalid;
|
||||
TypeTableEntry *entry_namespace;
|
||||
TypeTableEntry *entry_block;
|
||||
TypeTableEntry *entry_num_lit_int;
|
||||
TypeTableEntry *entry_num_lit_float;
|
||||
TypeTableEntry *entry_undef;
|
||||
TypeTableEntry *entry_null;
|
||||
TypeTableEntry *entry_var;
|
||||
TypeTableEntry *entry_global_error_set;
|
||||
TypeTableEntry *entry_arg_tuple;
|
||||
TypeTableEntry *entry_promise;
|
||||
ZigType *entry_bool;
|
||||
ZigType *entry_c_int[CIntTypeCount];
|
||||
ZigType *entry_c_longdouble;
|
||||
ZigType *entry_c_void;
|
||||
ZigType *entry_u8;
|
||||
ZigType *entry_u16;
|
||||
ZigType *entry_u32;
|
||||
ZigType *entry_u29;
|
||||
ZigType *entry_u64;
|
||||
ZigType *entry_i8;
|
||||
ZigType *entry_i32;
|
||||
ZigType *entry_i64;
|
||||
ZigType *entry_isize;
|
||||
ZigType *entry_usize;
|
||||
ZigType *entry_f16;
|
||||
ZigType *entry_f32;
|
||||
ZigType *entry_f64;
|
||||
ZigType *entry_f128;
|
||||
ZigType *entry_void;
|
||||
ZigType *entry_unreachable;
|
||||
ZigType *entry_type;
|
||||
ZigType *entry_invalid;
|
||||
ZigType *entry_namespace;
|
||||
ZigType *entry_block;
|
||||
ZigType *entry_num_lit_int;
|
||||
ZigType *entry_num_lit_float;
|
||||
ZigType *entry_undef;
|
||||
ZigType *entry_null;
|
||||
ZigType *entry_var;
|
||||
ZigType *entry_global_error_set;
|
||||
ZigType *entry_arg_tuple;
|
||||
ZigType *entry_promise;
|
||||
} builtin_types;
|
||||
|
||||
EmitFileType emit_file_type;
|
||||
@ -1672,14 +1679,14 @@ struct CodeGen {
|
||||
const char *linker_script;
|
||||
|
||||
// The function definitions this module includes.
|
||||
ZigList<FnTableEntry *> fn_defs;
|
||||
ZigList<ZigFn *> fn_defs;
|
||||
size_t fn_defs_index;
|
||||
ZigList<TldVar *> global_vars;
|
||||
|
||||
OutType out_type;
|
||||
FnTableEntry *cur_fn;
|
||||
FnTableEntry *main_fn;
|
||||
FnTableEntry *panic_fn;
|
||||
ZigFn *cur_fn;
|
||||
ZigFn *main_fn;
|
||||
ZigFn *panic_fn;
|
||||
LLVMValueRef cur_ret_ptr;
|
||||
LLVMValueRef cur_fn_val;
|
||||
LLVMValueRef cur_err_ret_trace_val_arg;
|
||||
@ -1732,12 +1739,12 @@ struct CodeGen {
|
||||
const char **llvm_argv;
|
||||
size_t llvm_argv_len;
|
||||
|
||||
ZigList<FnTableEntry *> test_fns;
|
||||
TypeTableEntry *test_fn_type;
|
||||
ZigList<ZigFn *> test_fns;
|
||||
ZigType *test_fn_type;
|
||||
|
||||
bool each_lib_rpath;
|
||||
|
||||
TypeTableEntry *err_tag_type;
|
||||
ZigType *err_tag_type;
|
||||
ZigList<ZigLLVMDIEnumerator *> err_enumerators;
|
||||
ZigList<ErrorTableEntry *> errors_by_index;
|
||||
bool generate_error_name_table;
|
||||
@ -1761,15 +1768,15 @@ struct CodeGen {
|
||||
|
||||
ZigList<TimeEvent> timing_events;
|
||||
|
||||
Buf *cache_dir;
|
||||
Buf cache_dir;
|
||||
Buf *out_h_path;
|
||||
|
||||
ZigList<FnTableEntry *> inline_fns;
|
||||
ZigList<ZigFn *> inline_fns;
|
||||
ZigList<AstNode *> tld_ref_source_node_stack;
|
||||
|
||||
TypeTableEntry *align_amt_type;
|
||||
TypeTableEntry *stack_trace_type;
|
||||
TypeTableEntry *ptr_to_stack_trace_type;
|
||||
ZigType *align_amt_type;
|
||||
ZigType *stack_trace_type;
|
||||
ZigType *ptr_to_stack_trace_type;
|
||||
|
||||
ZigList<ZigLLVMDIType **> error_di_types;
|
||||
|
||||
@ -1784,7 +1791,7 @@ enum VarLinkage {
|
||||
VarLinkageExternal,
|
||||
};
|
||||
|
||||
struct VariableTableEntry {
|
||||
struct ZigVar {
|
||||
Buf name;
|
||||
ConstExprValue *value;
|
||||
LLVMValueRef value_ref;
|
||||
@ -1809,14 +1816,14 @@ struct VariableTableEntry {
|
||||
// In an inline loop, multiple variables may be created,
|
||||
// In this case, a reference to a variable should follow
|
||||
// this pointer to the redefined variable.
|
||||
VariableTableEntry *next_var;
|
||||
ZigVar *next_var;
|
||||
};
|
||||
|
||||
struct ErrorTableEntry {
|
||||
Buf name;
|
||||
uint32_t value;
|
||||
AstNode *decl_node;
|
||||
TypeTableEntry *set_with_only_this_in_it;
|
||||
ZigType *set_with_only_this_in_it;
|
||||
// If we generate a constant error name value for this error, we memoize it here.
|
||||
// The type of this is array
|
||||
ConstExprValue *cached_error_name_val;
|
||||
@ -1834,6 +1841,7 @@ enum ScopeId {
|
||||
ScopeIdFnDef,
|
||||
ScopeIdCompTime,
|
||||
ScopeIdCoroPrelude,
|
||||
ScopeIdRuntime,
|
||||
};
|
||||
|
||||
struct Scope {
|
||||
@ -1859,7 +1867,7 @@ struct ScopeDecls {
|
||||
AstNode *fast_math_set_node;
|
||||
ImportTableEntry *import;
|
||||
// If this is a scope from a container, this is the type entry, otherwise null
|
||||
TypeTableEntry *container_type;
|
||||
ZigType *container_type;
|
||||
};
|
||||
|
||||
// This scope comes from a block expression in user code.
|
||||
@ -1901,7 +1909,7 @@ struct ScopeVarDecl {
|
||||
Scope base;
|
||||
|
||||
// The variable that creates this scope
|
||||
VariableTableEntry *var;
|
||||
ZigVar *var;
|
||||
};
|
||||
|
||||
// This scope is created for a @cImport
|
||||
@ -1926,6 +1934,15 @@ struct ScopeLoop {
|
||||
ZigList<IrBasicBlock *> *incoming_blocks;
|
||||
};
|
||||
|
||||
// This scope blocks certain things from working such as comptime continue
|
||||
// inside a runtime if expression.
|
||||
// NodeTypeIfBoolExpr, NodeTypeWhileExpr, NodeTypeForExpr
|
||||
struct ScopeRuntime {
|
||||
Scope base;
|
||||
|
||||
IrInstruction *is_comptime;
|
||||
};
|
||||
|
||||
// This scope is created for a suspend block in order to have labeled
|
||||
// suspend for breaking out of a suspend and for detecting if a suspend
|
||||
// block is inside a suspend block.
|
||||
@ -1948,7 +1965,7 @@ struct ScopeCompTime {
|
||||
struct ScopeFnDef {
|
||||
Scope base;
|
||||
|
||||
FnTableEntry *fn_entry;
|
||||
ZigFn *fn_entry;
|
||||
};
|
||||
|
||||
// This scope is created to indicate that the code in the scope
|
||||
@ -2145,6 +2162,7 @@ enum IrInstructionId {
|
||||
IrInstructionIdErrSetCast,
|
||||
IrInstructionIdToBytes,
|
||||
IrInstructionIdFromBytes,
|
||||
IrInstructionIdCheckRuntimeScope,
|
||||
};
|
||||
|
||||
struct IrInstruction {
|
||||
@ -2279,7 +2297,7 @@ struct IrInstructionBinOp {
|
||||
struct IrInstructionDeclVar {
|
||||
IrInstruction base;
|
||||
|
||||
VariableTableEntry *var;
|
||||
ZigVar *var;
|
||||
IrInstruction *var_type;
|
||||
IrInstruction *align_value;
|
||||
IrInstruction *init_value;
|
||||
@ -2336,14 +2354,15 @@ struct IrInstructionElemPtr {
|
||||
struct IrInstructionVarPtr {
|
||||
IrInstruction base;
|
||||
|
||||
VariableTableEntry *var;
|
||||
ZigVar *var;
|
||||
ScopeFnDef *crossed_fndef_scope;
|
||||
};
|
||||
|
||||
struct IrInstructionCall {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *fn_ref;
|
||||
FnTableEntry *fn_entry;
|
||||
ZigFn *fn_entry;
|
||||
size_t arg_count;
|
||||
IrInstruction **args;
|
||||
bool is_comptime;
|
||||
@ -2373,7 +2392,7 @@ struct IrInstructionCast {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *value;
|
||||
TypeTableEntry *dest_type;
|
||||
ZigType *dest_type;
|
||||
CastOp cast_op;
|
||||
LLVMValueRef tmp_ptr;
|
||||
};
|
||||
@ -2410,7 +2429,7 @@ struct IrInstructionStructInitField {
|
||||
struct IrInstructionStructInit {
|
||||
IrInstruction base;
|
||||
|
||||
TypeTableEntry *struct_type;
|
||||
ZigType *struct_type;
|
||||
size_t field_count;
|
||||
IrInstructionStructInitField *fields;
|
||||
LLVMValueRef tmp_ptr;
|
||||
@ -2419,7 +2438,7 @@ struct IrInstructionStructInit {
|
||||
struct IrInstructionUnionInit {
|
||||
IrInstruction base;
|
||||
|
||||
TypeTableEntry *union_type;
|
||||
ZigType *union_type;
|
||||
TypeUnionField *field;
|
||||
IrInstruction *init_value;
|
||||
LLVMValueRef tmp_ptr;
|
||||
@ -2506,7 +2525,7 @@ struct IrInstructionAsm {
|
||||
// Most information on inline assembly comes from the source node.
|
||||
IrInstruction **input_list;
|
||||
IrInstruction **output_types;
|
||||
VariableTableEntry **output_vars;
|
||||
ZigVar **output_vars;
|
||||
size_t return_count;
|
||||
bool has_side_effects;
|
||||
};
|
||||
@ -2648,7 +2667,7 @@ struct IrInstructionCmpxchg {
|
||||
IrInstruction *failure_order_value;
|
||||
|
||||
// if this instruction gets to runtime then we know these values:
|
||||
TypeTableEntry *type;
|
||||
ZigType *type;
|
||||
AtomicOrder success_order;
|
||||
AtomicOrder failure_order;
|
||||
|
||||
@ -2818,7 +2837,7 @@ struct IrInstructionOverflowOp {
|
||||
IrInstruction *op2;
|
||||
IrInstruction *result_ptr;
|
||||
|
||||
TypeTableEntry *result_ptr_type;
|
||||
ZigType *result_ptr_type;
|
||||
};
|
||||
|
||||
struct IrInstructionAlignOf {
|
||||
@ -3234,6 +3253,13 @@ struct IrInstructionSqrt {
|
||||
IrInstruction *op;
|
||||
};
|
||||
|
||||
struct IrInstructionCheckRuntimeScope {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *scope_is_comptime;
|
||||
IrInstruction *is_comptime;
|
||||
};
|
||||
|
||||
static const size_t slice_ptr_index = 0;
|
||||
static const size_t slice_len_index = 1;
|
||||
|
||||
@ -3263,4 +3289,53 @@ enum FloatMode {
|
||||
FloatModeStrict,
|
||||
};
|
||||
|
||||
enum FnWalkId {
|
||||
FnWalkIdAttrs,
|
||||
FnWalkIdCall,
|
||||
FnWalkIdTypes,
|
||||
FnWalkIdVars,
|
||||
FnWalkIdInits,
|
||||
};
|
||||
|
||||
struct FnWalkAttrs {
|
||||
ZigFn *fn;
|
||||
unsigned gen_i;
|
||||
};
|
||||
|
||||
struct FnWalkCall {
|
||||
ZigList<LLVMValueRef> *gen_param_values;
|
||||
IrInstructionCall *inst;
|
||||
bool is_var_args;
|
||||
};
|
||||
|
||||
struct FnWalkTypes {
|
||||
ZigList<ZigLLVMDIType *> *param_di_types;
|
||||
ZigList<LLVMTypeRef> *gen_param_types;
|
||||
};
|
||||
|
||||
struct FnWalkVars {
|
||||
ImportTableEntry *import;
|
||||
LLVMValueRef llvm_fn;
|
||||
ZigFn *fn;
|
||||
ZigVar *var;
|
||||
unsigned gen_i;
|
||||
};
|
||||
|
||||
struct FnWalkInits {
|
||||
LLVMValueRef llvm_fn;
|
||||
ZigFn *fn;
|
||||
unsigned gen_i;
|
||||
};
|
||||
|
||||
struct FnWalk {
|
||||
FnWalkId id;
|
||||
union {
|
||||
FnWalkAttrs attrs;
|
||||
FnWalkCall call;
|
||||
FnWalkTypes types;
|
||||
FnWalkVars vars;
|
||||
FnWalkInits inits;
|
||||
} data;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
2063
src/analyze.cpp
2063
src/analyze.cpp
File diff suppressed because it is too large
Load Diff
200
src/analyze.hpp
200
src/analyze.hpp
@ -14,103 +14,104 @@
|
||||
void semantic_analyze(CodeGen *g);
|
||||
ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
|
||||
ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg);
|
||||
TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
|
||||
TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
|
||||
TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type, bool is_const,
|
||||
ZigType *new_type_table_entry(ZigTypeId id);
|
||||
ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const);
|
||||
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
|
||||
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count);
|
||||
uint64_t type_size(CodeGen *g, TypeTableEntry *type_entry);
|
||||
uint64_t type_size_bits(CodeGen *g, TypeTableEntry *type_entry);
|
||||
TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
|
||||
TypeTableEntry **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
|
||||
TypeTableEntry *get_c_int_type(CodeGen *g, CIntType c_int_type);
|
||||
TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
|
||||
TypeTableEntry *get_optional_type(CodeGen *g, TypeTableEntry *child_type);
|
||||
TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size);
|
||||
TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *ptr_type);
|
||||
TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
|
||||
uint64_t type_size(CodeGen *g, ZigType *type_entry);
|
||||
uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
|
||||
ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
|
||||
ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
|
||||
ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);
|
||||
ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
|
||||
ZigType *get_optional_type(CodeGen *g, ZigType *child_type);
|
||||
ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size);
|
||||
ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);
|
||||
ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
|
||||
AstNode *decl_node, const char *name, ContainerLayout layout);
|
||||
TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
|
||||
TypeTableEntry *get_error_union_type(CodeGen *g, TypeTableEntry *err_set_type, TypeTableEntry *payload_type);
|
||||
TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry);
|
||||
TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name);
|
||||
TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[],
|
||||
TypeTableEntry *field_types[], size_t field_count);
|
||||
TypeTableEntry *get_promise_type(CodeGen *g, TypeTableEntry *result_type);
|
||||
TypeTableEntry *get_promise_frame_type(CodeGen *g, TypeTableEntry *return_type);
|
||||
TypeTableEntry *get_test_fn_type(CodeGen *g);
|
||||
bool handle_is_ptr(TypeTableEntry *type_entry);
|
||||
ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
|
||||
ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type);
|
||||
ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry);
|
||||
ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name);
|
||||
ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[],
|
||||
ZigType *field_types[], size_t field_count);
|
||||
ZigType *get_promise_type(CodeGen *g, ZigType *result_type);
|
||||
ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type);
|
||||
ZigType *get_test_fn_type(CodeGen *g);
|
||||
bool handle_is_ptr(ZigType *type_entry);
|
||||
void find_libc_include_path(CodeGen *g);
|
||||
void find_libc_lib_path(CodeGen *g);
|
||||
|
||||
bool type_has_bits(TypeTableEntry *type_entry);
|
||||
bool type_has_bits(ZigType *type_entry);
|
||||
|
||||
|
||||
ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
|
||||
|
||||
|
||||
VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);
|
||||
ZigVar *find_variable(CodeGen *g, Scope *orig_context, Buf *name, ScopeFnDef **crossed_fndef_scope);
|
||||
Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
|
||||
void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node);
|
||||
bool type_is_codegen_pointer(TypeTableEntry *type);
|
||||
bool type_is_codegen_pointer(ZigType *type);
|
||||
|
||||
TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type);
|
||||
uint32_t get_ptr_align(TypeTableEntry *type);
|
||||
bool get_ptr_const(TypeTableEntry *type);
|
||||
TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry);
|
||||
TypeTableEntry *container_ref_type(TypeTableEntry *type_entry);
|
||||
bool type_is_complete(TypeTableEntry *type_entry);
|
||||
bool type_is_invalid(TypeTableEntry *type_entry);
|
||||
bool type_is_global_error_set(TypeTableEntry *err_set_type);
|
||||
bool type_has_zero_bits_known(TypeTableEntry *type_entry);
|
||||
void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry);
|
||||
ScopeDecls *get_container_scope(TypeTableEntry *type_entry);
|
||||
TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name);
|
||||
TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
|
||||
TypeUnionField *find_union_type_field(TypeTableEntry *type_entry, Buf *name);
|
||||
TypeEnumField *find_enum_field_by_tag(TypeTableEntry *enum_type, const BigInt *tag);
|
||||
TypeUnionField *find_union_field_by_tag(TypeTableEntry *type_entry, const BigInt *tag);
|
||||
ZigType *get_codegen_ptr_type(ZigType *type);
|
||||
uint32_t get_ptr_align(ZigType *type);
|
||||
bool get_ptr_const(ZigType *type);
|
||||
ZigType *validate_var_type(CodeGen *g, AstNode *source_node, ZigType *type_entry);
|
||||
ZigType *container_ref_type(ZigType *type_entry);
|
||||
bool type_is_complete(ZigType *type_entry);
|
||||
bool type_is_invalid(ZigType *type_entry);
|
||||
bool type_is_global_error_set(ZigType *err_set_type);
|
||||
bool type_has_zero_bits_known(ZigType *type_entry);
|
||||
void resolve_container_type(CodeGen *g, ZigType *type_entry);
|
||||
ScopeDecls *get_container_scope(ZigType *type_entry);
|
||||
TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name);
|
||||
TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name);
|
||||
TypeUnionField *find_union_type_field(ZigType *type_entry, Buf *name);
|
||||
TypeEnumField *find_enum_field_by_tag(ZigType *enum_type, const BigInt *tag);
|
||||
TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag);
|
||||
|
||||
bool is_ref(TypeTableEntry *type_entry);
|
||||
bool is_array_ref(TypeTableEntry *type_entry);
|
||||
bool is_container_ref(TypeTableEntry *type_entry);
|
||||
bool is_ref(ZigType *type_entry);
|
||||
bool is_array_ref(ZigType *type_entry);
|
||||
bool is_container_ref(ZigType *type_entry);
|
||||
void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
|
||||
void scan_import(CodeGen *g, ImportTableEntry *import);
|
||||
void preview_use_decl(CodeGen *g, AstNode *node);
|
||||
void resolve_use_decl(CodeGen *g, AstNode *node);
|
||||
FnTableEntry *scope_fn_entry(Scope *scope);
|
||||
ZigFn *scope_fn_entry(Scope *scope);
|
||||
ImportTableEntry *get_scope_import(Scope *scope);
|
||||
void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);
|
||||
VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
|
||||
ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
|
||||
bool is_const, ConstExprValue *init_value, Tld *src_tld);
|
||||
TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
|
||||
FnTableEntry *create_fn(AstNode *proto_node);
|
||||
FnTableEntry *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage);
|
||||
ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
|
||||
ZigFn *create_fn(AstNode *proto_node);
|
||||
ZigFn *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage);
|
||||
void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
|
||||
AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index);
|
||||
FnTableEntry *scope_get_fn_if_root(Scope *scope);
|
||||
bool type_requires_comptime(TypeTableEntry *type_entry);
|
||||
Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, TypeTableEntry *type_entry);
|
||||
Error ATTRIBUTE_MUST_USE type_ensure_zero_bits_known(CodeGen *g, TypeTableEntry *type_entry);
|
||||
void complete_enum(CodeGen *g, TypeTableEntry *enum_type);
|
||||
bool ir_get_var_is_comptime(VariableTableEntry *var);
|
||||
AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index);
|
||||
ZigFn *scope_get_fn_if_root(Scope *scope);
|
||||
bool type_requires_comptime(ZigType *type_entry);
|
||||
Error ATTRIBUTE_MUST_USE ensure_complete_type(CodeGen *g, ZigType *type_entry);
|
||||
Error ATTRIBUTE_MUST_USE type_ensure_zero_bits_known(CodeGen *g, ZigType *type_entry);
|
||||
void complete_enum(CodeGen *g, ZigType *enum_type);
|
||||
bool ir_get_var_is_comptime(ZigVar *var);
|
||||
bool const_values_equal(ConstExprValue *a, ConstExprValue *b);
|
||||
void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max);
|
||||
void eval_min_max_value_int(CodeGen *g, TypeTableEntry *int_type, BigInt *bigint, bool is_max);
|
||||
void eval_min_max_value(CodeGen *g, ZigType *type_entry, ConstExprValue *const_val, bool is_max);
|
||||
void eval_min_max_value_int(CodeGen *g, ZigType *int_type, BigInt *bigint, bool is_max);
|
||||
|
||||
void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val);
|
||||
void analyze_fn_ir(CodeGen *g, FnTableEntry *fn_table_entry, AstNode *return_type_node);
|
||||
void analyze_fn_ir(CodeGen *g, ZigFn *fn_table_entry, AstNode *return_type_node);
|
||||
|
||||
ScopeBlock *create_block_scope(AstNode *node, Scope *parent);
|
||||
ScopeDefer *create_defer_scope(AstNode *node, Scope *parent);
|
||||
ScopeDeferExpr *create_defer_expr_scope(AstNode *node, Scope *parent);
|
||||
Scope *create_var_scope(AstNode *node, Scope *parent, VariableTableEntry *var);
|
||||
Scope *create_var_scope(AstNode *node, Scope *parent, ZigVar *var);
|
||||
ScopeCImport *create_cimport_scope(AstNode *node, Scope *parent);
|
||||
ScopeLoop *create_loop_scope(AstNode *node, Scope *parent);
|
||||
ScopeSuspend *create_suspend_scope(AstNode *node, Scope *parent);
|
||||
ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, FnTableEntry *fn_entry);
|
||||
ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, TypeTableEntry *container_type, ImportTableEntry *import);
|
||||
ScopeFnDef *create_fndef_scope(AstNode *node, Scope *parent, ZigFn *fn_entry);
|
||||
ScopeDecls *create_decls_scope(AstNode *node, Scope *parent, ZigType *container_type, ImportTableEntry *import);
|
||||
Scope *create_comptime_scope(AstNode *node, Scope *parent);
|
||||
Scope *create_coro_prelude_scope(AstNode *node, Scope *parent);
|
||||
Scope *create_runtime_scope(AstNode *node, Scope *parent, IrInstruction *is_comptime);
|
||||
|
||||
void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
|
||||
ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
|
||||
@ -118,39 +119,39 @@ ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
|
||||
void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str);
|
||||
ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str);
|
||||
|
||||
void init_const_bigint(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *bigint);
|
||||
ConstExprValue *create_const_bigint(TypeTableEntry *type, const BigInt *bigint);
|
||||
void init_const_bigint(ConstExprValue *const_val, ZigType *type, const BigInt *bigint);
|
||||
ConstExprValue *create_const_bigint(ZigType *type, const BigInt *bigint);
|
||||
|
||||
void init_const_unsigned_negative(ConstExprValue *const_val, TypeTableEntry *type, uint64_t x, bool negative);
|
||||
ConstExprValue *create_const_unsigned_negative(TypeTableEntry *type, uint64_t x, bool negative);
|
||||
void init_const_unsigned_negative(ConstExprValue *const_val, ZigType *type, uint64_t x, bool negative);
|
||||
ConstExprValue *create_const_unsigned_negative(ZigType *type, uint64_t x, bool negative);
|
||||
|
||||
void init_const_signed(ConstExprValue *const_val, TypeTableEntry *type, int64_t x);
|
||||
ConstExprValue *create_const_signed(TypeTableEntry *type, int64_t x);
|
||||
void init_const_signed(ConstExprValue *const_val, ZigType *type, int64_t x);
|
||||
ConstExprValue *create_const_signed(ZigType *type, int64_t x);
|
||||
|
||||
void init_const_usize(CodeGen *g, ConstExprValue *const_val, uint64_t x);
|
||||
ConstExprValue *create_const_usize(CodeGen *g, uint64_t x);
|
||||
|
||||
void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value);
|
||||
ConstExprValue *create_const_float(TypeTableEntry *type, double value);
|
||||
void init_const_float(ConstExprValue *const_val, ZigType *type, double value);
|
||||
ConstExprValue *create_const_float(ZigType *type, double value);
|
||||
|
||||
void init_const_enum(ConstExprValue *const_val, TypeTableEntry *type, const BigInt *tag);
|
||||
ConstExprValue *create_const_enum(TypeTableEntry *type, const BigInt *tag);
|
||||
void init_const_enum(ConstExprValue *const_val, ZigType *type, const BigInt *tag);
|
||||
ConstExprValue *create_const_enum(ZigType *type, const BigInt *tag);
|
||||
|
||||
void init_const_bool(CodeGen *g, ConstExprValue *const_val, bool value);
|
||||
ConstExprValue *create_const_bool(CodeGen *g, bool value);
|
||||
|
||||
void init_const_type(CodeGen *g, ConstExprValue *const_val, TypeTableEntry *type_value);
|
||||
ConstExprValue *create_const_type(CodeGen *g, TypeTableEntry *type_value);
|
||||
void init_const_type(CodeGen *g, ConstExprValue *const_val, ZigType *type_value);
|
||||
ConstExprValue *create_const_type(CodeGen *g, ZigType *type_value);
|
||||
|
||||
void init_const_runtime(ConstExprValue *const_val, TypeTableEntry *type);
|
||||
ConstExprValue *create_const_runtime(TypeTableEntry *type);
|
||||
void init_const_runtime(ConstExprValue *const_val, ZigType *type);
|
||||
ConstExprValue *create_const_runtime(ZigType *type);
|
||||
|
||||
void init_const_ptr_ref(CodeGen *g, ConstExprValue *const_val, ConstExprValue *pointee_val, bool is_const);
|
||||
ConstExprValue *create_const_ptr_ref(CodeGen *g, ConstExprValue *pointee_val, bool is_const);
|
||||
|
||||
void init_const_ptr_hard_coded_addr(CodeGen *g, ConstExprValue *const_val, TypeTableEntry *pointee_type,
|
||||
void init_const_ptr_hard_coded_addr(CodeGen *g, ConstExprValue *const_val, ZigType *pointee_type,
|
||||
size_t addr, bool is_const);
|
||||
ConstExprValue *create_const_ptr_hard_coded_addr(CodeGen *g, TypeTableEntry *pointee_type,
|
||||
ConstExprValue *create_const_ptr_hard_coded_addr(CodeGen *g, ZigType *pointee_type,
|
||||
size_t addr, bool is_const);
|
||||
|
||||
void init_const_ptr_array(CodeGen *g, ConstExprValue *const_val, ConstExprValue *array_val,
|
||||
@ -169,41 +170,48 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val);
|
||||
|
||||
ConstExprValue *create_const_vals(size_t count);
|
||||
|
||||
TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
|
||||
ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
|
||||
ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value);
|
||||
void expand_undef_array(CodeGen *g, ConstExprValue *const_val);
|
||||
void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value);
|
||||
|
||||
const char *type_id_name(TypeTableEntryId id);
|
||||
TypeTableEntryId type_id_at_index(size_t index);
|
||||
const char *type_id_name(ZigTypeId id);
|
||||
ZigTypeId type_id_at_index(size_t index);
|
||||
size_t type_id_len();
|
||||
size_t type_id_index(TypeTableEntry *entry);
|
||||
TypeTableEntry *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id);
|
||||
Result<bool> type_is_copyable(CodeGen *g, TypeTableEntry *type_entry);
|
||||
size_t type_id_index(ZigType *entry);
|
||||
ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id);
|
||||
Result<bool> type_is_copyable(CodeGen *g, ZigType *type_entry);
|
||||
LinkLib *create_link_lib(Buf *name);
|
||||
bool calling_convention_does_first_arg_return(CallingConvention cc);
|
||||
LinkLib *add_link_lib(CodeGen *codegen, Buf *lib);
|
||||
|
||||
uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry);
|
||||
TypeTableEntry *get_align_amt_type(CodeGen *g);
|
||||
uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry);
|
||||
ZigType *get_align_amt_type(CodeGen *g);
|
||||
PackageTableEntry *new_anonymous_package(void);
|
||||
|
||||
Buf *const_value_to_buffer(ConstExprValue *const_val);
|
||||
void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc);
|
||||
void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc);
|
||||
|
||||
|
||||
ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name);
|
||||
TypeTableEntry *get_ptr_to_stack_trace_type(CodeGen *g);
|
||||
bool resolve_inferred_error_set(CodeGen *g, TypeTableEntry *err_set_type, AstNode *source_node);
|
||||
ZigType *get_ptr_to_stack_trace_type(CodeGen *g);
|
||||
bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node);
|
||||
|
||||
TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry);
|
||||
ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry);
|
||||
|
||||
uint32_t get_coro_frame_align_bytes(CodeGen *g);
|
||||
bool fn_type_can_fail(FnTypeId *fn_type_id);
|
||||
bool type_can_fail(TypeTableEntry *type_entry);
|
||||
bool fn_eval_cacheable(Scope *scope, TypeTableEntry *return_type);
|
||||
AstNode *type_decl_node(TypeTableEntry *type_entry);
|
||||
bool type_can_fail(ZigType *type_entry);
|
||||
bool fn_eval_cacheable(Scope *scope, ZigType *return_type);
|
||||
AstNode *type_decl_node(ZigType *type_entry);
|
||||
|
||||
TypeTableEntry *get_primitive_type(CodeGen *g, Buf *name);
|
||||
ZigType *get_primitive_type(CodeGen *g, Buf *name);
|
||||
|
||||
bool calling_convention_allows_zig_types(CallingConvention cc);
|
||||
const char *calling_convention_name(CallingConvention cc);
|
||||
|
||||
void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
|
||||
X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
|
||||
bool type_is_c_abi_int(CodeGen *g, ZigType *ty);
|
||||
bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
|
||||
|
||||
#endif
|
||||
|
||||
@ -173,4 +173,9 @@ static inline void buf_upcase(Buf *buf) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline Slice<uint8_t> buf_to_slice(Buf *buf) {
|
||||
return Slice<uint8_t>{reinterpret_cast<uint8_t*>(buf_ptr(buf)), buf_len(buf)};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
1507
src/codegen.cpp
1507
src/codegen.cpp
File diff suppressed because it is too large
Load Diff
@ -47,7 +47,7 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script);
|
||||
void codegen_set_test_filter(CodeGen *g, Buf *filter);
|
||||
void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
|
||||
void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
|
||||
void codegen_set_cache_dir(CodeGen *g, Buf *cache_dir);
|
||||
void codegen_set_cache_dir(CodeGen *g, Buf cache_dir);
|
||||
void codegen_set_output_h_path(CodeGen *g, Buf *h_path);
|
||||
void codegen_add_time_event(CodeGen *g, const char *name);
|
||||
void codegen_print_timing_report(CodeGen *g, FILE *f);
|
||||
@ -61,5 +61,4 @@ void codegen_translate_c(CodeGen *g, Buf *path);
|
||||
|
||||
Buf *codegen_generate_builtin_source(CodeGen *g);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
3709
src/ir.cpp
3709
src/ir.cpp
File diff suppressed because it is too large
Load Diff
10
src/ir.hpp
10
src/ir.hpp
@ -11,15 +11,15 @@
|
||||
#include "all_types.hpp"
|
||||
|
||||
bool ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
|
||||
bool ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);
|
||||
bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
|
||||
|
||||
IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
|
||||
TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
|
||||
FnTableEntry *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
|
||||
ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
|
||||
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
|
||||
IrExecutable *parent_exec);
|
||||
|
||||
TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
|
||||
TypeTableEntry *expected_type, AstNode *expected_type_source_node);
|
||||
ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
|
||||
ZigType *expected_type, AstNode *expected_type_source_node);
|
||||
|
||||
bool ir_has_side_effects(IrInstruction *instruction);
|
||||
ConstExprValue *const_ptr_pointee(CodeGen *codegen, ConstExprValue *const_val);
|
||||
|
||||
@ -957,6 +957,14 @@ static void ir_print_enum_to_int(IrPrint *irp, IrInstructionEnumToInt *instructi
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_check_runtime_scope(IrPrint *irp, IrInstructionCheckRuntimeScope *instruction) {
|
||||
fprintf(irp->f, "@checkRuntimeScope(");
|
||||
ir_print_other_instruction(irp, instruction->scope_is_comptime);
|
||||
fprintf(irp->f, ",");
|
||||
ir_print_other_instruction(irp, instruction->is_comptime);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
|
||||
fprintf(irp->f, "inttoerr ");
|
||||
ir_print_other_instruction(irp, instruction->target);
|
||||
@ -1749,6 +1757,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
case IrInstructionIdEnumToInt:
|
||||
ir_print_enum_to_int(irp, (IrInstructionEnumToInt *)instruction);
|
||||
break;
|
||||
case IrInstructionIdCheckRuntimeScope:
|
||||
ir_print_check_runtime_scope(irp, (IrInstructionCheckRuntimeScope *)instruction);
|
||||
break;
|
||||
}
|
||||
fprintf(irp->f, "\n");
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)
|
||||
const char *o_ext = target_o_file_ext(&child_gen->zig_target);
|
||||
Buf *o_out_name = buf_sprintf("%s%s", oname, o_ext);
|
||||
Buf *output_path = buf_alloc();
|
||||
os_path_join(parent_gen->cache_dir, o_out_name, output_path);
|
||||
os_path_join(&parent_gen->cache_dir, o_out_name, output_path);
|
||||
codegen_link(child_gen, buf_ptr(output_path));
|
||||
|
||||
codegen_destroy(child_gen);
|
||||
@ -587,11 +587,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
|
||||
buf_appendf(def_contents, "\n");
|
||||
|
||||
Buf *def_path = buf_alloc();
|
||||
os_path_join(g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
|
||||
os_path_join(&g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
|
||||
os_write_file(def_path, def_contents);
|
||||
|
||||
Buf *generated_lib_path = buf_alloc();
|
||||
os_path_join(g->cache_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
|
||||
os_path_join(&g->cache_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
|
||||
|
||||
gen_lib_args.resize(0);
|
||||
gen_lib_args.append("link");
|
||||
|
||||
26
src/main.cpp
26
src/main.cpp
@ -374,25 +374,26 @@ int main(int argc, char **argv) {
|
||||
CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, zig_lib_dir_buf);
|
||||
codegen_set_out_name(g, buf_create_from_str("build"));
|
||||
|
||||
Buf build_file_abs = BUF_INIT;
|
||||
os_path_resolve(buf_create_from_str("."), buf_create_from_str(build_file), &build_file_abs);
|
||||
Buf *build_file_buf = buf_create_from_str(build_file);
|
||||
Buf build_file_abs = os_path_resolve(&build_file_buf, 1);
|
||||
Buf build_file_basename = BUF_INIT;
|
||||
Buf build_file_dirname = BUF_INIT;
|
||||
os_path_split(&build_file_abs, &build_file_dirname, &build_file_basename);
|
||||
|
||||
Buf *full_cache_dir = buf_alloc();
|
||||
Buf full_cache_dir = BUF_INIT;
|
||||
if (cache_dir == nullptr) {
|
||||
os_path_join(&build_file_dirname, buf_create_from_str(default_zig_cache_name), full_cache_dir);
|
||||
os_path_join(&build_file_dirname, buf_create_from_str(default_zig_cache_name), &full_cache_dir);
|
||||
} else {
|
||||
os_path_resolve(buf_create_from_str("."), buf_create_from_str(cache_dir), full_cache_dir);
|
||||
Buf *cache_dir_buf = buf_create_from_str(cache_dir);
|
||||
full_cache_dir = os_path_resolve(&cache_dir_buf, 1);
|
||||
}
|
||||
|
||||
Buf *path_to_build_exe = buf_alloc();
|
||||
os_path_join(full_cache_dir, buf_create_from_str("build"), path_to_build_exe);
|
||||
os_path_join(&full_cache_dir, buf_create_from_str("build"), path_to_build_exe);
|
||||
codegen_set_cache_dir(g, full_cache_dir);
|
||||
|
||||
args.items[1] = buf_ptr(&build_file_dirname);
|
||||
args.items[2] = buf_ptr(full_cache_dir);
|
||||
args.items[2] = buf_ptr(&full_cache_dir);
|
||||
|
||||
bool build_file_exists;
|
||||
if ((err = os_file_exists(&build_file_abs, &build_file_exists))) {
|
||||
@ -789,7 +790,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf;
|
||||
|
||||
Buf *full_cache_dir = buf_alloc();
|
||||
Buf full_cache_dir = BUF_INIT;
|
||||
Buf *run_exec_path = buf_alloc();
|
||||
if (cmd == CmdRun) {
|
||||
if (buf_out_name == nullptr) {
|
||||
@ -799,13 +800,12 @@ int main(int argc, char **argv) {
|
||||
Buf *global_cache_dir = buf_alloc();
|
||||
os_get_global_cache_directory(global_cache_dir);
|
||||
os_path_join(global_cache_dir, buf_out_name, run_exec_path);
|
||||
os_path_resolve(buf_create_from_str("."), global_cache_dir, full_cache_dir);
|
||||
full_cache_dir = os_path_resolve(&global_cache_dir, 1);
|
||||
|
||||
out_file = buf_ptr(run_exec_path);
|
||||
} else {
|
||||
os_path_resolve(buf_create_from_str("."),
|
||||
buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir),
|
||||
full_cache_dir);
|
||||
Buf *resolve_paths = buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir);
|
||||
full_cache_dir = os_path_resolve(&resolve_paths, 1);
|
||||
}
|
||||
|
||||
Buf *zig_lib_dir_buf = resolve_zig_lib_dir();
|
||||
@ -937,7 +937,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
Buf *test_exe_name = buf_sprintf("test%s", target_exe_file_ext(non_null_target));
|
||||
Buf *test_exe_path = buf_alloc();
|
||||
os_path_join(full_cache_dir, test_exe_name, test_exe_path);
|
||||
os_path_join(&full_cache_dir, test_exe_name, test_exe_path);
|
||||
|
||||
for (size_t i = 0; i < test_exec_args.length; i += 1) {
|
||||
if (test_exec_args.items[i] == nullptr) {
|
||||
|
||||
534
src/os.cpp
534
src/os.cpp
@ -57,6 +57,54 @@ static clock_serv_t cclock;
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
// Ported from std/mem.zig.
|
||||
// Coordinate struct fields with memSplit function
|
||||
struct SplitIterator {
|
||||
size_t index;
|
||||
Slice<uint8_t> buffer;
|
||||
Slice<uint8_t> split_bytes;
|
||||
};
|
||||
|
||||
// Ported from std/mem.zig.
|
||||
static bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte) {
|
||||
for (size_t i = 0; i < self->split_bytes.len; i += 1) {
|
||||
if (byte == self->split_bytes.ptr[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ported from std/mem.zig.
|
||||
static Optional<Slice<uint8_t>> SplitIterator_next(SplitIterator *self) {
|
||||
// move to beginning of token
|
||||
while (self->index < self->buffer.len &&
|
||||
SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
|
||||
{
|
||||
self->index += 1;
|
||||
}
|
||||
size_t start = self->index;
|
||||
if (start == self->buffer.len) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// move to end of token
|
||||
while (self->index < self->buffer.len &&
|
||||
!SplitIterator_isSplitByte(self, self->buffer.ptr[self->index]))
|
||||
{
|
||||
self->index += 1;
|
||||
}
|
||||
size_t end = self->index;
|
||||
|
||||
return Optional<Slice<uint8_t>>::some(self->buffer.slice(start, end));
|
||||
}
|
||||
|
||||
// Ported from std/mem.zig
|
||||
static SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes) {
|
||||
return SplitIterator{0, buffer, split_bytes};
|
||||
}
|
||||
|
||||
|
||||
#if defined(ZIG_OS_POSIX)
|
||||
static void populate_termination(Termination *term, int status) {
|
||||
if (WIFEXITED(status)) {
|
||||
@ -266,15 +314,31 @@ int os_path_real(Buf *rel_path, Buf *out_abs_path) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(ZIG_OS_WINDOWS)
|
||||
// Ported from std/os/path.zig
|
||||
static bool isAbsoluteWindows(Slice<uint8_t> path) {
|
||||
if (path.ptr[0] == '/')
|
||||
return true;
|
||||
|
||||
if (path.ptr[0] == '\\') {
|
||||
return true;
|
||||
}
|
||||
if (path.len < 3) {
|
||||
return false;
|
||||
}
|
||||
if (path.ptr[1] == ':') {
|
||||
if (path.ptr[2] == '/')
|
||||
return true;
|
||||
if (path.ptr[2] == '\\')
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool os_path_is_absolute(Buf *path) {
|
||||
#if defined(ZIG_OS_WINDOWS)
|
||||
if (buf_starts_with_str(path, "/") || buf_starts_with_str(path, "\\"))
|
||||
return true;
|
||||
|
||||
if (buf_len(path) >= 3 && buf_ptr(path)[1] == ':')
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return isAbsoluteWindows(buf_to_slice(path));
|
||||
#elif defined(ZIG_OS_POSIX)
|
||||
return buf_ptr(path)[0] == '/';
|
||||
#else
|
||||
@ -282,14 +346,423 @@ bool os_path_is_absolute(Buf *path) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void os_path_resolve(Buf *ref_path, Buf *target_path, Buf *out_abs_path) {
|
||||
if (os_path_is_absolute(target_path)) {
|
||||
buf_init_from_buf(out_abs_path, target_path);
|
||||
return;
|
||||
#if defined(ZIG_OS_WINDOWS)
|
||||
|
||||
enum WindowsPathKind {
|
||||
WindowsPathKindNone,
|
||||
WindowsPathKindDrive,
|
||||
WindowsPathKindNetworkShare,
|
||||
};
|
||||
|
||||
struct WindowsPath {
|
||||
Slice<uint8_t> disk_designator;
|
||||
WindowsPathKind kind;
|
||||
bool is_abs;
|
||||
};
|
||||
|
||||
|
||||
// Ported from std/os/path.zig
|
||||
static WindowsPath windowsParsePath(Slice<uint8_t> path) {
|
||||
if (path.len >= 2 && path.ptr[1] == ':') {
|
||||
return WindowsPath{
|
||||
path.slice(0, 2),
|
||||
WindowsPathKindDrive,
|
||||
isAbsoluteWindows(path),
|
||||
};
|
||||
}
|
||||
if (path.len >= 1 && (path.ptr[0] == '/' || path.ptr[0] == '\\') &&
|
||||
(path.len == 1 || (path.ptr[1] != '/' && path.ptr[1] != '\\')))
|
||||
{
|
||||
return WindowsPath{
|
||||
path.slice(0, 0),
|
||||
WindowsPathKindNone,
|
||||
true,
|
||||
};
|
||||
}
|
||||
WindowsPath relative_path = {
|
||||
str(""),
|
||||
WindowsPathKindNone,
|
||||
false,
|
||||
};
|
||||
if (path.len < strlen("//a/b")) {
|
||||
return relative_path;
|
||||
}
|
||||
|
||||
os_path_join(ref_path, target_path, out_abs_path);
|
||||
return;
|
||||
{
|
||||
if (memStartsWith(path, str("//"))) {
|
||||
if (path.ptr[2] == '/') {
|
||||
return relative_path;
|
||||
}
|
||||
|
||||
SplitIterator it = memSplit(path, str("/"));
|
||||
{
|
||||
Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
|
||||
if (!opt_component.is_some) return relative_path;
|
||||
}
|
||||
{
|
||||
Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
|
||||
if (!opt_component.is_some) return relative_path;
|
||||
}
|
||||
return WindowsPath{
|
||||
path.slice(0, it.index),
|
||||
WindowsPathKindNetworkShare,
|
||||
isAbsoluteWindows(path),
|
||||
};
|
||||
}
|
||||
}
|
||||
{
|
||||
if (memStartsWith(path, str("\\\\"))) {
|
||||
if (path.ptr[2] == '\\') {
|
||||
return relative_path;
|
||||
}
|
||||
|
||||
SplitIterator it = memSplit(path, str("\\"));
|
||||
{
|
||||
Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
|
||||
if (!opt_component.is_some) return relative_path;
|
||||
}
|
||||
{
|
||||
Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
|
||||
if (!opt_component.is_some) return relative_path;
|
||||
}
|
||||
return WindowsPath{
|
||||
path.slice(0, it.index),
|
||||
WindowsPathKindNetworkShare,
|
||||
isAbsoluteWindows(path),
|
||||
};
|
||||
}
|
||||
}
|
||||
return relative_path;
|
||||
}
|
||||
|
||||
// Ported from std/os/path.zig
|
||||
static uint8_t asciiUpper(uint8_t byte) {
|
||||
if (byte >= 'a' && byte <= 'z') {
|
||||
return 'A' + (byte - 'a');
|
||||
}
|
||||
return byte;
|
||||
}
|
||||
|
||||
// Ported from std/os/path.zig
|
||||
static bool asciiEqlIgnoreCase(Slice<uint8_t> s1, Slice<uint8_t> s2) {
|
||||
if (s1.len != s2.len)
|
||||
return false;
|
||||
for (size_t i = 0; i < s1.len; i += 1) {
|
||||
if (asciiUpper(s1.ptr[i]) != asciiUpper(s2.ptr[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ported from std/os/path.zig
|
||||
static bool compareDiskDesignators(WindowsPathKind kind, Slice<uint8_t> p1, Slice<uint8_t> p2) {
|
||||
switch (kind) {
|
||||
case WindowsPathKindNone:
|
||||
assert(p1.len == 0);
|
||||
assert(p2.len == 0);
|
||||
return true;
|
||||
case WindowsPathKindDrive:
|
||||
return asciiUpper(p1.ptr[0]) == asciiUpper(p2.ptr[0]);
|
||||
case WindowsPathKindNetworkShare:
|
||||
uint8_t sep1 = p1.ptr[0];
|
||||
uint8_t sep2 = p2.ptr[0];
|
||||
|
||||
SplitIterator it1 = memSplit(p1, {&sep1, 1});
|
||||
SplitIterator it2 = memSplit(p2, {&sep2, 1});
|
||||
|
||||
// TODO ASCII is wrong, we actually need full unicode support to compare paths.
|
||||
return asciiEqlIgnoreCase(SplitIterator_next(&it1).value, SplitIterator_next(&it2).value) &&
|
||||
asciiEqlIgnoreCase(SplitIterator_next(&it1).value, SplitIterator_next(&it2).value);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
// Ported from std/os/path.zig
|
||||
static Buf os_path_resolve_windows(Buf **paths_ptr, size_t paths_len) {
|
||||
if (paths_len == 0) {
|
||||
Buf cwd = BUF_INIT;
|
||||
int err;
|
||||
if ((err = os_get_cwd(&cwd))) {
|
||||
zig_panic("get cwd failed");
|
||||
}
|
||||
return cwd;
|
||||
}
|
||||
|
||||
// determine which disk designator we will result with, if any
|
||||
char result_drive_buf[3] = {'_', ':', '\0'}; // 0 needed for strlen later
|
||||
Slice<uint8_t> result_disk_designator = str("");
|
||||
WindowsPathKind have_drive_kind = WindowsPathKindNone;
|
||||
bool have_abs_path = false;
|
||||
size_t first_index = 0;
|
||||
size_t max_size = 0;
|
||||
for (size_t i = 0; i < paths_len; i += 1) {
|
||||
Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
|
||||
WindowsPath parsed = windowsParsePath(p);
|
||||
if (parsed.is_abs) {
|
||||
have_abs_path = true;
|
||||
first_index = i;
|
||||
max_size = result_disk_designator.len;
|
||||
}
|
||||
switch (parsed.kind) {
|
||||
case WindowsPathKindDrive:
|
||||
result_drive_buf[0] = asciiUpper(parsed.disk_designator.ptr[0]);
|
||||
result_disk_designator = str(result_drive_buf);
|
||||
have_drive_kind = WindowsPathKindDrive;
|
||||
break;
|
||||
case WindowsPathKindNetworkShare:
|
||||
result_disk_designator = parsed.disk_designator;
|
||||
have_drive_kind = WindowsPathKindNetworkShare;
|
||||
break;
|
||||
case WindowsPathKindNone:
|
||||
break;
|
||||
}
|
||||
max_size += p.len + 1;
|
||||
}
|
||||
|
||||
// if we will result with a disk designator, loop again to determine
|
||||
// which is the last time the disk designator is absolutely specified, if any
|
||||
// and count up the max bytes for paths related to this disk designator
|
||||
if (have_drive_kind != WindowsPathKindNone) {
|
||||
have_abs_path = false;
|
||||
first_index = 0;
|
||||
max_size = result_disk_designator.len;
|
||||
bool correct_disk_designator = false;
|
||||
|
||||
for (size_t i = 0; i < paths_len; i += 1) {
|
||||
Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
|
||||
WindowsPath parsed = windowsParsePath(p);
|
||||
if (parsed.kind != WindowsPathKindNone) {
|
||||
if (parsed.kind == have_drive_kind) {
|
||||
correct_disk_designator = compareDiskDesignators(have_drive_kind, result_disk_designator, parsed.disk_designator);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!correct_disk_designator) {
|
||||
continue;
|
||||
}
|
||||
if (parsed.is_abs) {
|
||||
first_index = i;
|
||||
max_size = result_disk_designator.len;
|
||||
have_abs_path = true;
|
||||
}
|
||||
max_size += p.len + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate result and fill in the disk designator, calling getCwd if we have to.
|
||||
Slice<uint8_t> result;
|
||||
size_t result_index = 0;
|
||||
|
||||
if (have_abs_path) {
|
||||
switch (have_drive_kind) {
|
||||
case WindowsPathKindDrive: {
|
||||
result = Slice<uint8_t>::alloc(max_size);
|
||||
|
||||
memCopy(result, result_disk_designator);
|
||||
result_index += result_disk_designator.len;
|
||||
break;
|
||||
}
|
||||
case WindowsPathKindNetworkShare: {
|
||||
result = Slice<uint8_t>::alloc(max_size);
|
||||
SplitIterator it = memSplit(buf_to_slice(paths_ptr[first_index]), str("/\\"));
|
||||
Slice<uint8_t> server_name = SplitIterator_next(&it).value;
|
||||
Slice<uint8_t> other_name = SplitIterator_next(&it).value;
|
||||
|
||||
result.ptr[result_index] = '\\';
|
||||
result_index += 1;
|
||||
result.ptr[result_index] = '\\';
|
||||
result_index += 1;
|
||||
memCopy(result.sliceFrom(result_index), server_name);
|
||||
result_index += server_name.len;
|
||||
result.ptr[result_index] = '\\';
|
||||
result_index += 1;
|
||||
memCopy(result.sliceFrom(result_index), other_name);
|
||||
result_index += other_name.len;
|
||||
|
||||
result_disk_designator = result.slice(0, result_index);
|
||||
break;
|
||||
}
|
||||
case WindowsPathKindNone: {
|
||||
Buf cwd = BUF_INIT;
|
||||
int err;
|
||||
if ((err = os_get_cwd(&cwd))) {
|
||||
zig_panic("get cwd failed");
|
||||
}
|
||||
WindowsPath parsed_cwd = windowsParsePath(buf_to_slice(&cwd));
|
||||
result = Slice<uint8_t>::alloc(max_size + parsed_cwd.disk_designator.len + 1);
|
||||
memCopy(result, parsed_cwd.disk_designator);
|
||||
result_index += parsed_cwd.disk_designator.len;
|
||||
result_disk_designator = result.slice(0, parsed_cwd.disk_designator.len);
|
||||
if (parsed_cwd.kind == WindowsPathKindDrive) {
|
||||
result.ptr[0] = asciiUpper(result.ptr[0]);
|
||||
}
|
||||
have_drive_kind = parsed_cwd.kind;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO call get cwd for the result_disk_designator instead of the global one
|
||||
Buf cwd = BUF_INIT;
|
||||
int err;
|
||||
if ((err = os_get_cwd(&cwd))) {
|
||||
zig_panic("get cwd failed");
|
||||
}
|
||||
result = Slice<uint8_t>::alloc(max_size + buf_len(&cwd) + 1);
|
||||
|
||||
memCopy(result, buf_to_slice(&cwd));
|
||||
result_index += buf_len(&cwd);
|
||||
WindowsPath parsed_cwd = windowsParsePath(result.slice(0, result_index));
|
||||
result_disk_designator = parsed_cwd.disk_designator;
|
||||
if (parsed_cwd.kind == WindowsPathKindDrive) {
|
||||
result.ptr[0] = asciiUpper(result.ptr[0]);
|
||||
}
|
||||
have_drive_kind = parsed_cwd.kind;
|
||||
}
|
||||
|
||||
// Now we know the disk designator to use, if any, and what kind it is. And our result
|
||||
// is big enough to append all the paths to.
|
||||
bool correct_disk_designator = true;
|
||||
for (size_t i = 0; i < paths_len; i += 1) {
|
||||
Slice<uint8_t> p = buf_to_slice(paths_ptr[i]);
|
||||
WindowsPath parsed = windowsParsePath(p);
|
||||
|
||||
if (parsed.kind != WindowsPathKindNone) {
|
||||
if (parsed.kind == have_drive_kind) {
|
||||
correct_disk_designator = compareDiskDesignators(have_drive_kind, result_disk_designator, parsed.disk_designator);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!correct_disk_designator) {
|
||||
continue;
|
||||
}
|
||||
SplitIterator it = memSplit(p.sliceFrom(parsed.disk_designator.len), str("/\\"));
|
||||
while (true) {
|
||||
Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
|
||||
if (!opt_component.is_some) break;
|
||||
Slice<uint8_t> component = opt_component.value;
|
||||
if (memEql(component, str("."))) {
|
||||
continue;
|
||||
} else if (memEql(component, str(".."))) {
|
||||
while (true) {
|
||||
if (result_index == 0 || result_index == result_disk_designator.len)
|
||||
break;
|
||||
result_index -= 1;
|
||||
if (result.ptr[result_index] == '\\' || result.ptr[result_index] == '/')
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
result.ptr[result_index] = '\\';
|
||||
result_index += 1;
|
||||
memCopy(result.sliceFrom(result_index), component);
|
||||
result_index += component.len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result_index == result_disk_designator.len) {
|
||||
result.ptr[result_index] = '\\';
|
||||
result_index += 1;
|
||||
}
|
||||
|
||||
Buf return_value = BUF_INIT;
|
||||
buf_init_from_mem(&return_value, (char *)result.ptr, result_index);
|
||||
return return_value;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ZIG_OS_POSIX)
|
||||
// Ported from std/os/path.zig
|
||||
static Buf os_path_resolve_posix(Buf **paths_ptr, size_t paths_len) {
|
||||
if (paths_len == 0) {
|
||||
Buf cwd = BUF_INIT;
|
||||
int err;
|
||||
if ((err = os_get_cwd(&cwd))) {
|
||||
zig_panic("get cwd failed");
|
||||
}
|
||||
return cwd;
|
||||
}
|
||||
|
||||
size_t first_index = 0;
|
||||
bool have_abs = false;
|
||||
size_t max_size = 0;
|
||||
for (size_t i = 0; i < paths_len; i += 1) {
|
||||
Buf *p = paths_ptr[i];
|
||||
if (os_path_is_absolute(p)) {
|
||||
first_index = i;
|
||||
have_abs = true;
|
||||
max_size = 0;
|
||||
}
|
||||
max_size += buf_len(p) + 1;
|
||||
}
|
||||
|
||||
uint8_t *result_ptr;
|
||||
size_t result_len;
|
||||
size_t result_index = 0;
|
||||
|
||||
if (have_abs) {
|
||||
result_len = max_size;
|
||||
result_ptr = allocate_nonzero<uint8_t>(result_len);
|
||||
} else {
|
||||
Buf cwd = BUF_INIT;
|
||||
int err;
|
||||
if ((err = os_get_cwd(&cwd))) {
|
||||
zig_panic("get cwd failed");
|
||||
}
|
||||
result_len = max_size + buf_len(&cwd) + 1;
|
||||
result_ptr = allocate_nonzero<uint8_t>(result_len);
|
||||
memcpy(result_ptr, buf_ptr(&cwd), buf_len(&cwd));
|
||||
result_index += buf_len(&cwd);
|
||||
}
|
||||
|
||||
for (size_t i = first_index; i < paths_len; i += 1) {
|
||||
Buf *p = paths_ptr[i];
|
||||
SplitIterator it = memSplit(buf_to_slice(p), str("/"));
|
||||
while (true) {
|
||||
Optional<Slice<uint8_t>> opt_component = SplitIterator_next(&it);
|
||||
if (!opt_component.is_some) break;
|
||||
Slice<uint8_t> component = opt_component.value;
|
||||
|
||||
if (memEql<uint8_t>(component, str("."))) {
|
||||
continue;
|
||||
} else if (memEql<uint8_t>(component, str(".."))) {
|
||||
while (true) {
|
||||
if (result_index == 0)
|
||||
break;
|
||||
result_index -= 1;
|
||||
if (result_ptr[result_index] == '/')
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
result_ptr[result_index] = '/';
|
||||
result_index += 1;
|
||||
memcpy(result_ptr + result_index, component.ptr, component.len);
|
||||
result_index += component.len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result_index == 0) {
|
||||
result_ptr[0] = '/';
|
||||
result_index += 1;
|
||||
}
|
||||
|
||||
Buf return_value = BUF_INIT;
|
||||
buf_init_from_mem(&return_value, (char *)result_ptr, result_index);
|
||||
return return_value;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Ported from std/os/path.zig
|
||||
Buf os_path_resolve(Buf **paths_ptr, size_t paths_len) {
|
||||
#if defined(ZIG_OS_WINDOWS)
|
||||
return os_path_resolve_windows(paths_ptr, paths_len);
|
||||
#elif defined(ZIG_OS_POSIX)
|
||||
return os_path_resolve_posix(paths_ptr, paths_len);
|
||||
#else
|
||||
#error "missing os_path_resolve implementation"
|
||||
#endif
|
||||
}
|
||||
|
||||
int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) {
|
||||
@ -558,7 +1031,7 @@ int os_exec_process(const char *exe, ZigList<const char *> &args,
|
||||
void os_write_file(Buf *full_path, Buf *contents) {
|
||||
FILE *f = fopen(buf_ptr(full_path), "wb");
|
||||
if (!f) {
|
||||
zig_panic("open failed");
|
||||
zig_panic("os_write_file failed for %s", buf_ptr(full_path));
|
||||
}
|
||||
size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f);
|
||||
if (amt_written != (size_t)buf_len(contents))
|
||||
@ -645,21 +1118,19 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
|
||||
|
||||
int os_get_cwd(Buf *out_cwd) {
|
||||
#if defined(ZIG_OS_WINDOWS)
|
||||
buf_resize(out_cwd, 4096);
|
||||
if (GetCurrentDirectory(buf_len(out_cwd), buf_ptr(out_cwd)) == 0) {
|
||||
char buf[4096];
|
||||
if (GetCurrentDirectory(4096, buf) == 0) {
|
||||
zig_panic("GetCurrentDirectory failed");
|
||||
}
|
||||
buf_init_from_str(out_cwd, buf);
|
||||
return 0;
|
||||
#elif defined(ZIG_OS_POSIX)
|
||||
int err = ERANGE;
|
||||
buf_resize(out_cwd, 512);
|
||||
while (err == ERANGE) {
|
||||
buf_resize(out_cwd, buf_len(out_cwd) * 2);
|
||||
err = getcwd(buf_ptr(out_cwd), buf_len(out_cwd)) ? 0 : errno;
|
||||
char buf[PATH_MAX];
|
||||
char *res = getcwd(buf, PATH_MAX);
|
||||
if (res == nullptr) {
|
||||
zig_panic("unable to get cwd: %s", strerror(errno));
|
||||
}
|
||||
if (err)
|
||||
zig_panic("unable to get cwd: %s", strerror(err));
|
||||
|
||||
buf_init_from_str(out_cwd, res);
|
||||
return 0;
|
||||
#else
|
||||
#error "missing os_get_cwd implementation"
|
||||
@ -898,21 +1369,20 @@ double os_get_time(void) {
|
||||
}
|
||||
|
||||
int os_make_path(Buf *path) {
|
||||
Buf *resolved_path = buf_alloc();
|
||||
os_path_resolve(buf_create_from_str("."), path, resolved_path);
|
||||
Buf resolved_path = os_path_resolve(&path, 1);
|
||||
|
||||
size_t end_index = buf_len(resolved_path);
|
||||
size_t end_index = buf_len(&resolved_path);
|
||||
int err;
|
||||
while (true) {
|
||||
if ((err = os_make_dir(buf_slice(resolved_path, 0, end_index)))) {
|
||||
if ((err = os_make_dir(buf_slice(&resolved_path, 0, end_index)))) {
|
||||
if (err == ErrorPathAlreadyExists) {
|
||||
if (end_index == buf_len(resolved_path))
|
||||
if (end_index == buf_len(&resolved_path))
|
||||
return 0;
|
||||
} else if (err == ErrorFileNotFound) {
|
||||
// march end_index backward until next path component
|
||||
while (true) {
|
||||
end_index -= 1;
|
||||
if (os_is_sep(buf_ptr(resolved_path)[end_index]))
|
||||
if (os_is_sep(buf_ptr(&resolved_path)[end_index]))
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
@ -920,12 +1390,12 @@ int os_make_path(Buf *path) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (end_index == buf_len(resolved_path))
|
||||
if (end_index == buf_len(&resolved_path))
|
||||
return 0;
|
||||
// march end_index forward until next path component
|
||||
while (true) {
|
||||
end_index += 1;
|
||||
if (end_index == buf_len(resolved_path) || os_is_sep(buf_ptr(resolved_path)[end_index]))
|
||||
if (end_index == buf_len(&resolved_path) || os_is_sep(buf_ptr(&resolved_path)[end_index]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
|
||||
void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname);
|
||||
void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path);
|
||||
int os_path_real(Buf *rel_path, Buf *out_abs_path);
|
||||
void os_path_resolve(Buf *ref_path, Buf *target_path, Buf *out_abs_path);
|
||||
Buf os_path_resolve(Buf **paths_ptr, size_t paths_len);
|
||||
bool os_path_is_absolute(Buf *path);
|
||||
|
||||
int os_get_global_cache_directory(Buf *out_tmp_path);
|
||||
|
||||
68
src/util.hpp
68
src/util.hpp
@ -186,4 +186,72 @@ static inline double zig_f16_to_double(float16_t x) {
|
||||
return z;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct Optional {
|
||||
T value;
|
||||
bool is_some;
|
||||
|
||||
static inline Optional<T> some(T x) {
|
||||
return {x, true};
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Slice {
|
||||
T *ptr;
|
||||
size_t len;
|
||||
|
||||
inline Slice<T> slice(size_t start, size_t end) {
|
||||
assert(end <= len);
|
||||
assert(end >= start);
|
||||
return {
|
||||
ptr + start,
|
||||
end - start,
|
||||
};
|
||||
}
|
||||
|
||||
inline Slice<T> sliceFrom(size_t start) {
|
||||
assert(start <= len);
|
||||
return {
|
||||
ptr + start,
|
||||
len - start,
|
||||
};
|
||||
}
|
||||
|
||||
static inline Slice<T> alloc(size_t n) {
|
||||
return {allocate_nonzero<T>(n), n};
|
||||
}
|
||||
};
|
||||
|
||||
static inline Slice<uint8_t> str(const char *literal) {
|
||||
return {(uint8_t*)(literal), strlen(literal)};
|
||||
}
|
||||
|
||||
// Ported from std/mem.zig
|
||||
template<typename T>
|
||||
static inline bool memEql(Slice<T> a, Slice<T> b) {
|
||||
if (a.len != b.len)
|
||||
return false;
|
||||
for (size_t i = 0; i < a.len; i += 1) {
|
||||
if (a.ptr[i] != b.ptr[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ported from std/mem.zig
|
||||
template<typename T>
|
||||
static inline bool memStartsWith(Slice<T> haystack, Slice<T> needle) {
|
||||
if (needle.len > haystack.len)
|
||||
return false;
|
||||
return memEql(haystack.slice(0, needle.len), needle);
|
||||
}
|
||||
|
||||
// Ported from std/mem.zig
|
||||
template<typename T>
|
||||
static inline void memCopy(Slice<T> dest, Slice<T> src) {
|
||||
assert(dest.len >= src.len);
|
||||
memcpy(dest.ptr, src.ptr, src.len * sizeof(T));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -62,6 +62,10 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
|
||||
return self.len;
|
||||
}
|
||||
|
||||
pub fn capacity(self: Self) usize {
|
||||
return self.items.len;
|
||||
}
|
||||
|
||||
/// ArrayList takes ownership of the passed in slice. The slice must have been
|
||||
/// allocated with `allocator`.
|
||||
/// Deinitialize with `deinit` or use `toOwnedSlice`.
|
||||
@ -102,6 +106,11 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
|
||||
new_item_ptr.* = item;
|
||||
}
|
||||
|
||||
pub fn appendAssumeCapacity(self: *Self, item: T) void {
|
||||
const new_item_ptr = self.addOneAssumeCapacity();
|
||||
new_item_ptr.* = item;
|
||||
}
|
||||
|
||||
/// Removes the element at the specified index and returns it.
|
||||
/// The empty slot is filled from the end of the list.
|
||||
pub fn swapRemove(self: *Self, i: usize) T {
|
||||
@ -138,7 +147,7 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
|
||||
}
|
||||
|
||||
pub fn ensureCapacity(self: *Self, new_capacity: usize) !void {
|
||||
var better_capacity = self.items.len;
|
||||
var better_capacity = self.capacity();
|
||||
if (better_capacity >= new_capacity) return;
|
||||
while (true) {
|
||||
better_capacity += better_capacity / 2 + 8;
|
||||
@ -150,8 +159,13 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
|
||||
pub fn addOne(self: *Self) !*T {
|
||||
const new_length = self.len + 1;
|
||||
try self.ensureCapacity(new_length);
|
||||
return self.addOneAssumeCapacity();
|
||||
}
|
||||
|
||||
pub fn addOneAssumeCapacity(self: *Self) *T {
|
||||
assert(self.count() < self.capacity());
|
||||
const result = &self.items[self.len];
|
||||
self.len = new_length;
|
||||
self.len += 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -191,6 +205,17 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
|
||||
};
|
||||
}
|
||||
|
||||
test "std.ArrayList.init" {
|
||||
var bytes: [1024]u8 = undefined;
|
||||
const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
|
||||
|
||||
var list = ArrayList(i32).init(allocator);
|
||||
defer list.deinit();
|
||||
|
||||
assert(list.count() == 0);
|
||||
assert(list.capacity() == 0);
|
||||
}
|
||||
|
||||
test "std.ArrayList.basic" {
|
||||
var bytes: [1024]u8 = undefined;
|
||||
const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
|
||||
|
||||
@ -48,6 +48,12 @@ pub const Builder = struct {
|
||||
cache_root: []const u8,
|
||||
release_mode: ?builtin.Mode,
|
||||
|
||||
pub const CStd = enum {
|
||||
C89,
|
||||
C99,
|
||||
C11,
|
||||
};
|
||||
|
||||
const UserInputOptionsMap = HashMap([]const u8, UserInputOption, mem.hash_slice_u8, mem.eql_slice_u8);
|
||||
const AvailableOptionsMap = HashMap([]const u8, AvailableOption, mem.hash_slice_u8, mem.eql_slice_u8);
|
||||
|
||||
@ -817,6 +823,7 @@ pub const LibExeObjStep = struct {
|
||||
frameworks: BufSet,
|
||||
verbose_link: bool,
|
||||
no_rosegment: bool,
|
||||
c_std: Builder.CStd,
|
||||
|
||||
// zig only stuff
|
||||
root_src: ?[]const u8,
|
||||
@ -918,6 +925,7 @@ pub const LibExeObjStep = struct {
|
||||
.object_src = undefined,
|
||||
.disable_libc = true,
|
||||
.build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable,
|
||||
.c_std = Builder.CStd.C99,
|
||||
};
|
||||
self.computeOutFileNames();
|
||||
return self;
|
||||
@ -952,6 +960,7 @@ pub const LibExeObjStep = struct {
|
||||
.disable_libc = false,
|
||||
.is_zig = false,
|
||||
.linker_script = null,
|
||||
.c_std = Builder.CStd.C99,
|
||||
|
||||
.root_src = undefined,
|
||||
.verbose_link = false,
|
||||
@ -1392,6 +1401,13 @@ pub const LibExeObjStep = struct {
|
||||
|
||||
const is_darwin = self.target.isDarwin();
|
||||
|
||||
const c_std_arg = switch (self.c_std) {
|
||||
Builder.CStd.C89 => "-std=c89",
|
||||
Builder.CStd.C99 => "-std=c99",
|
||||
Builder.CStd.C11 => "-std=c11",
|
||||
};
|
||||
try cc_args.append(c_std_arg);
|
||||
|
||||
switch (self.kind) {
|
||||
Kind.Obj => {
|
||||
cc_args.append("-c") catch unreachable;
|
||||
@ -1678,6 +1694,17 @@ pub const TestStep = struct {
|
||||
self.filter = text;
|
||||
}
|
||||
|
||||
pub fn addObject(self: *TestStep, obj: *LibExeObjStep) void {
|
||||
assert(obj.kind == LibExeObjStep.Kind.Obj);
|
||||
|
||||
self.step.dependOn(&obj.step);
|
||||
|
||||
self.object_files.append(obj.getOutputPath()) catch unreachable;
|
||||
|
||||
// TODO should be some kind of isolated directory that only has this header in it
|
||||
self.include_dirs.append(self.builder.cache_root) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn addObjectFile(self: *TestStep, path: []const u8) void {
|
||||
self.object_files.append(path) catch unreachable;
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ fn printPad(stdout: var, s: []const u8) !void {
|
||||
|
||||
pub fn main() !void {
|
||||
var stdout_file = try std.io.getStdOut();
|
||||
var stdout_out_stream = std.io.FileOutStream.init(&stdout_file);
|
||||
var stdout_out_stream = std.io.FileOutStream.init(stdout_file);
|
||||
const stdout = &stdout_out_stream.stream;
|
||||
|
||||
var buffer: [1024]u8 = undefined;
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
const std = @import("../index.zig");
|
||||
const builtin = @import("builtin");
|
||||
const fmt = std.fmt;
|
||||
|
||||
const Endian = builtin.Endian;
|
||||
const readInt = std.mem.readInt;
|
||||
@ -114,7 +115,7 @@ pub const X25519 = struct {
|
||||
return !zerocmp(u8, out);
|
||||
}
|
||||
|
||||
pub fn createPublicKey(public_key: []const u8, private_key: []const u8) bool {
|
||||
pub fn createPublicKey(public_key: [] u8, private_key: []const u8) bool {
|
||||
var base_point = []u8{9} ++ []u8{0} ** 31;
|
||||
return create(public_key, private_key, base_point);
|
||||
}
|
||||
@ -573,6 +574,16 @@ const Fe = struct {
|
||||
}
|
||||
};
|
||||
|
||||
test "x25519 public key calculation from secret key" {
|
||||
var sk: [32]u8 = undefined;
|
||||
var pk_expected: [32]u8 = undefined;
|
||||
var pk_calculated: [32]u8 = undefined;
|
||||
try fmt.hexToBytes(sk[0..], "8052030376d47112be7f73ed7a019293dd12ad910b654455798b4667d73de166");
|
||||
try fmt.hexToBytes(pk_expected[0..], "f1814f0e8ff1043d8a44d25babff3cedcae6c22c3edaa48f857ae70de2baae50");
|
||||
std.debug.assert(X25519.createPublicKey(pk_calculated[0..], sk));
|
||||
std.debug.assert(std.mem.eql(u8, pk_calculated, pk_expected));
|
||||
}
|
||||
|
||||
test "x25519 rfc7748 vector1" {
|
||||
const secret_key = "\xa5\x46\xe3\x6b\xf0\x52\x7c\x9d\x3b\x16\x15\x4b\x82\x46\x5e\xdd\x62\x14\x4c\x0a\xc1\xfc\x5a\x18\x50\x6a\x22\x44\xba\x44\x9a\xc4";
|
||||
const public_key = "\xe6\xdb\x68\x67\x58\x30\x30\xdb\x35\x94\xc1\xa4\x24\xb1\x5f\x7c\x72\x66\x24\xec\x26\xb3\x35\x3b\x10\xa9\x03\xa6\xd0\xab\x1c\x4c";
|
||||
|
||||
@ -9,12 +9,12 @@ comptime {
|
||||
_ = @import("cases/bitcast.zig");
|
||||
_ = @import("cases/bool.zig");
|
||||
_ = @import("cases/bugs/1111.zig");
|
||||
_ = @import("cases/bugs/1230.zig");
|
||||
_ = @import("cases/bugs/1277.zig");
|
||||
_ = @import("cases/bugs/1421.zig");
|
||||
_ = @import("cases/bugs/394.zig");
|
||||
_ = @import("cases/bugs/655.zig");
|
||||
_ = @import("cases/bugs/656.zig");
|
||||
_ = @import("cases/bugs/726.zig");
|
||||
_ = @import("cases/bugs/828.zig");
|
||||
_ = @import("cases/bugs/920.zig");
|
||||
_ = @import("cases/byval_arg_var.zig");
|
||||
|
||||
@ -28,4 +28,10 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {
|
||||
// TODO figure out how to make this work on darwin - probably libSystem has dlopen/dlsym in it
|
||||
cases.addBuildFile("test/standalone/load_dynamic_library/build.zig");
|
||||
}
|
||||
|
||||
if (!is_windows // TODO support compiling C files on windows with zig build system
|
||||
and builtin.arch == builtin.Arch.x86_64 // TODO add C ABI support for other architectures
|
||||
) {
|
||||
cases.addBuildFile("test/stage1/c_abi/build.zig");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
const S = extern struct {
|
||||
x: i32,
|
||||
};
|
||||
|
||||
extern fn ret_struct() S {
|
||||
return S{ .x = 42 };
|
||||
}
|
||||
|
||||
test "extern return small struct (bug 1230)" {
|
||||
const s = ret_struct();
|
||||
assert(s.x == 42);
|
||||
}
|
||||
16
test/cases/bugs/726.zig
Normal file
16
test/cases/bugs/726.zig
Normal file
@ -0,0 +1,16 @@
|
||||
const assert = @import("std").debug.assert;
|
||||
|
||||
test "@ptrCast from const to nullable" {
|
||||
const c: u8 = 4;
|
||||
var x: ?*const u8 = @ptrCast(?*const u8, &c);
|
||||
assert(x.?.* == 4);
|
||||
}
|
||||
|
||||
test "@ptrCast from var in empty struct to nullable" {
|
||||
const container = struct {
|
||||
var c: u8 = 4;
|
||||
};
|
||||
var x: ?*const u8 = @ptrCast(?*const u8, &container.c);
|
||||
assert(x.?.* == 4);
|
||||
}
|
||||
|
||||
@ -356,6 +356,7 @@ fn testFloatToInts() void {
|
||||
expectFloatToInt(f32, 255.1, u8, 255);
|
||||
expectFloatToInt(f32, 127.2, i8, 127);
|
||||
expectFloatToInt(f32, -128.2, i8, -128);
|
||||
expectFloatToInt(comptime_int, 1234, i16, 1234);
|
||||
}
|
||||
|
||||
fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void {
|
||||
|
||||
@ -674,3 +674,11 @@ test "inline for with same type but different values" {
|
||||
}
|
||||
assert(res == 5);
|
||||
}
|
||||
|
||||
test "refer to the type of a generic function" {
|
||||
const Func = fn (type) void;
|
||||
const f: Func = doNothingWithType;
|
||||
f(i32);
|
||||
}
|
||||
|
||||
fn doNothingWithType(comptime T: type) void {}
|
||||
|
||||
@ -176,3 +176,18 @@ test "pass by non-copying value as method, at comptime" {
|
||||
assert(pt.addPointCoords() == 3);
|
||||
}
|
||||
}
|
||||
|
||||
fn outer(y: u32) fn (u32) u32 {
|
||||
const Y = @typeOf(y);
|
||||
const st = struct {
|
||||
fn get(z: u32) u32 {
|
||||
return z + @sizeOf(Y);
|
||||
}
|
||||
};
|
||||
return st.get;
|
||||
}
|
||||
|
||||
test "return inner function which references comptime variable of outer function" {
|
||||
var func = outer(10);
|
||||
assert(func(3) == 7);
|
||||
}
|
||||
|
||||
@ -311,3 +311,16 @@ fn testTaggedUnionInit(x: var) bool {
|
||||
const y = TaggedUnionWithAVoid{ .A = x };
|
||||
return @TagType(TaggedUnionWithAVoid)(y) == TaggedUnionWithAVoid.A;
|
||||
}
|
||||
|
||||
pub const UnionEnumNoPayloads = union(enum) {
|
||||
A,
|
||||
B,
|
||||
};
|
||||
|
||||
test "tagged union with no payloads" {
|
||||
const a = UnionEnumNoPayloads{ .B = {} };
|
||||
switch (a) {
|
||||
@TagType(UnionEnumNoPayloads).A => @panic("wrong"),
|
||||
@TagType(UnionEnumNoPayloads).B => {},
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,228 @@
|
||||
const tests = @import("tests.zig");
|
||||
|
||||
pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
cases.add(
|
||||
"variable initialization compile error then referenced",
|
||||
\\fn Undeclared() type {
|
||||
\\ return T;
|
||||
\\}
|
||||
\\fn Gen() type {
|
||||
\\ const X = Undeclared();
|
||||
\\ return struct {
|
||||
\\ x: X,
|
||||
\\ };
|
||||
\\}
|
||||
\\export fn entry() void {
|
||||
\\ const S = Gen();
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:12: error: use of undeclared identifier 'T'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"refer to the type of a generic function",
|
||||
\\export fn entry() void {
|
||||
\\ const Func = fn (type) void;
|
||||
\\ const f: Func = undefined;
|
||||
\\ f(i32);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:4:5: error: use of undefined value",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"accessing runtime parameter from outer function",
|
||||
\\fn outer(y: u32) fn (u32) u32 {
|
||||
\\ const st = struct {
|
||||
\\ fn get(z: u32) u32 {
|
||||
\\ return z + y;
|
||||
\\ }
|
||||
\\ };
|
||||
\\ return st.get;
|
||||
\\}
|
||||
\\export fn entry() void {
|
||||
\\ var func = outer(10);
|
||||
\\ var x = func(3);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:4:24: error: 'y' not accessible from inner function",
|
||||
".tmp_source.zig:3:28: note: crossed function definition here",
|
||||
".tmp_source.zig:1:10: note: declared here",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"non int passed to @intToFloat",
|
||||
\\export fn entry() void {
|
||||
\\ const x = @intToFloat(f32, 1.1);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:32: error: expected int type, found 'comptime_float'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"non float passed to @floatToInt",
|
||||
\\export fn entry() void {
|
||||
\\ const x = @floatToInt(i32, i32(54));
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:35: error: expected float type, found 'i32'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"out of range comptime_int passed to @floatToInt",
|
||||
\\export fn entry() void {
|
||||
\\ const x = @floatToInt(i8, 200);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:31: error: integer value 200 cannot be implicitly casted to type 'i8'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"load too many bytes from comptime reinterpreted pointer",
|
||||
\\export fn entry() void {
|
||||
\\ const float: f32 = 5.99999999999994648725e-01;
|
||||
\\ const float_ptr = &float;
|
||||
\\ const int_ptr = @ptrCast(*const i64, float_ptr);
|
||||
\\ const int_val = int_ptr.*;
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:5:28: error: attempt to read 8 bytes from pointer to f32 which is 4 bytes",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"invalid type used in array type",
|
||||
\\const Item = struct {
|
||||
\\ field: SomeNonexistentType,
|
||||
\\};
|
||||
\\var items: [100]Item = undefined;
|
||||
\\export fn entry() void {
|
||||
\\ const a = items[0];
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:12: error: use of undeclared identifier 'SomeNonexistentType'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"@noInlineCall on an inline function",
|
||||
\\inline fn foo() void {}
|
||||
\\
|
||||
\\export fn entry() void {
|
||||
\\ @noInlineCall(foo);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:4:5: error: no-inline call of inline function",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"comptime continue inside runtime switch",
|
||||
\\export fn entry() void {
|
||||
\\ var p: i32 = undefined;
|
||||
\\ comptime var q = true;
|
||||
\\ inline while (q) {
|
||||
\\ switch (p) {
|
||||
\\ 11 => continue,
|
||||
\\ else => {},
|
||||
\\ }
|
||||
\\ q = false;
|
||||
\\ }
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:6:19: error: comptime control flow inside runtime block",
|
||||
".tmp_source.zig:5:9: note: runtime block created here",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"comptime continue inside runtime while error",
|
||||
\\export fn entry() void {
|
||||
\\ var p: error!usize = undefined;
|
||||
\\ comptime var q = true;
|
||||
\\ outer: inline while (q) {
|
||||
\\ while (p) |_| {
|
||||
\\ continue :outer;
|
||||
\\ } else |_| {}
|
||||
\\ q = false;
|
||||
\\ }
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:6:13: error: comptime control flow inside runtime block",
|
||||
".tmp_source.zig:5:9: note: runtime block created here",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"comptime continue inside runtime while optional",
|
||||
\\export fn entry() void {
|
||||
\\ var p: ?usize = undefined;
|
||||
\\ comptime var q = true;
|
||||
\\ outer: inline while (q) {
|
||||
\\ while (p) |_| continue :outer;
|
||||
\\ q = false;
|
||||
\\ }
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:5:23: error: comptime control flow inside runtime block",
|
||||
".tmp_source.zig:5:9: note: runtime block created here",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"comptime continue inside runtime while bool",
|
||||
\\export fn entry() void {
|
||||
\\ var p: usize = undefined;
|
||||
\\ comptime var q = true;
|
||||
\\ outer: inline while (q) {
|
||||
\\ while (p == 11) continue :outer;
|
||||
\\ q = false;
|
||||
\\ }
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:5:25: error: comptime control flow inside runtime block",
|
||||
".tmp_source.zig:5:9: note: runtime block created here",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"comptime continue inside runtime if error",
|
||||
\\export fn entry() void {
|
||||
\\ var p: error!i32 = undefined;
|
||||
\\ comptime var q = true;
|
||||
\\ inline while (q) {
|
||||
\\ if (p) |_| continue else |_| {}
|
||||
\\ q = false;
|
||||
\\ }
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:5:20: error: comptime control flow inside runtime block",
|
||||
".tmp_source.zig:5:9: note: runtime block created here",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"comptime continue inside runtime if optional",
|
||||
\\export fn entry() void {
|
||||
\\ var p: ?i32 = undefined;
|
||||
\\ comptime var q = true;
|
||||
\\ inline while (q) {
|
||||
\\ if (p) |_| continue;
|
||||
\\ q = false;
|
||||
\\ }
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:5:20: error: comptime control flow inside runtime block",
|
||||
".tmp_source.zig:5:9: note: runtime block created here",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"comptime continue inside runtime if bool",
|
||||
\\export fn entry() void {
|
||||
\\ var p: usize = undefined;
|
||||
\\ comptime var q = true;
|
||||
\\ inline while (q) {
|
||||
\\ if (p == 11) continue;
|
||||
\\ q = false;
|
||||
\\ }
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:5:22: error: comptime control flow inside runtime block",
|
||||
".tmp_source.zig:5:9: note: runtime block created here",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"switch with invalid expression parameter",
|
||||
\\export fn entry() void {
|
||||
@ -340,15 +562,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
".tmp_source.zig:2:20: error: return type cannot be opaque",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"non int passed to @intToFloat",
|
||||
\\export fn entry() void {
|
||||
\\ const x = @intToFloat(f32, 1.1);
|
||||
\\}
|
||||
,
|
||||
".tmp_source.zig:2:32: error: expected int type, found 'comptime_float'",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
"use implicit casts to assign null to non-nullable pointer",
|
||||
\\export fn entry() void {
|
||||
|
||||
@ -20,6 +20,9 @@ pub fn addCases(cases: *tests.GenHContext) void {
|
||||
\\ A: i32,
|
||||
\\ B: f32,
|
||||
\\ C: bool,
|
||||
\\ D: u64,
|
||||
\\ E: u64,
|
||||
\\ F: u64,
|
||||
\\};
|
||||
\\export fn entry(foo: Foo) void { }
|
||||
,
|
||||
@ -27,6 +30,9 @@ pub fn addCases(cases: *tests.GenHContext) void {
|
||||
\\ int32_t A;
|
||||
\\ float B;
|
||||
\\ bool C;
|
||||
\\ uint64_t D;
|
||||
\\ uint64_t E;
|
||||
\\ uint64_t F;
|
||||
\\};
|
||||
\\
|
||||
\\TEST_EXPORT void entry(struct Foo foo);
|
||||
@ -34,17 +40,34 @@ pub fn addCases(cases: *tests.GenHContext) void {
|
||||
);
|
||||
|
||||
cases.add("declare union",
|
||||
\\const Big = extern struct {
|
||||
\\ A: u64,
|
||||
\\ B: u64,
|
||||
\\ C: u64,
|
||||
\\ D: u64,
|
||||
\\ E: u64,
|
||||
\\};
|
||||
\\const Foo = extern union {
|
||||
\\ A: i32,
|
||||
\\ B: f32,
|
||||
\\ C: bool,
|
||||
\\ D: Big,
|
||||
\\};
|
||||
\\export fn entry(foo: Foo) void { }
|
||||
\\export fn entry(foo: Foo) void {}
|
||||
,
|
||||
\\struct Big {
|
||||
\\ uint64_t A;
|
||||
\\ uint64_t B;
|
||||
\\ uint64_t C;
|
||||
\\ uint64_t D;
|
||||
\\ uint64_t E;
|
||||
\\};
|
||||
\\
|
||||
\\union Foo {
|
||||
\\ int32_t A;
|
||||
\\ float B;
|
||||
\\ bool C;
|
||||
\\ struct Big D;
|
||||
\\};
|
||||
\\
|
||||
\\TEST_EXPORT void entry(union Foo foo);
|
||||
@ -85,7 +108,6 @@ pub fn addCases(cases: *tests.GenHContext) void {
|
||||
\\export fn a(s: *S) u8 {
|
||||
\\ return s.a;
|
||||
\\}
|
||||
|
||||
,
|
||||
\\struct S;
|
||||
\\TEST_EXPORT uint8_t a(struct S * s);
|
||||
@ -101,7 +123,6 @@ pub fn addCases(cases: *tests.GenHContext) void {
|
||||
\\export fn a(s: *U) u8 {
|
||||
\\ return s.A;
|
||||
\\}
|
||||
|
||||
,
|
||||
\\union U;
|
||||
\\TEST_EXPORT uint8_t a(union U * s);
|
||||
@ -117,7 +138,6 @@ pub fn addCases(cases: *tests.GenHContext) void {
|
||||
\\export fn a(s: *E) u8 {
|
||||
\\ return @enumToInt(s.*);
|
||||
\\}
|
||||
|
||||
,
|
||||
\\enum E;
|
||||
\\TEST_EXPORT uint8_t a(enum E * s);
|
||||
|
||||
18
test/stage1/c_abi/build.zig
Normal file
18
test/stage1/c_abi/build.zig
Normal file
@ -0,0 +1,18 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const rel_opts = b.standardReleaseOptions();
|
||||
|
||||
const c_obj = b.addCObject("cfuncs", "cfuncs.c");
|
||||
c_obj.setBuildMode(rel_opts);
|
||||
c_obj.setNoStdLib(true);
|
||||
|
||||
const main = b.addTest("main.zig");
|
||||
main.setBuildMode(rel_opts);
|
||||
main.addObject(c_obj);
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
test_step.dependOn(&main.step);
|
||||
|
||||
b.default_step.dependOn(test_step);
|
||||
}
|
||||
208
test/stage1/c_abi/cfuncs.c
Normal file
208
test/stage1/c_abi/cfuncs.c
Normal file
@ -0,0 +1,208 @@
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
void zig_panic();
|
||||
|
||||
static void assert_or_panic(bool ok) {
|
||||
if (!ok) {
|
||||
zig_panic();
|
||||
}
|
||||
}
|
||||
|
||||
void zig_u8(uint8_t);
|
||||
void zig_u16(uint16_t);
|
||||
void zig_u32(uint32_t);
|
||||
void zig_u64(uint64_t);
|
||||
void zig_i8(int8_t);
|
||||
void zig_i16(int16_t);
|
||||
void zig_i32(int32_t);
|
||||
void zig_i64(int64_t);
|
||||
|
||||
void zig_f32(float);
|
||||
void zig_f64(double);
|
||||
|
||||
void zig_ptr(void *);
|
||||
|
||||
void zig_bool(bool);
|
||||
|
||||
void zig_array(uint8_t[10]);
|
||||
|
||||
struct BigStruct {
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
uint64_t c;
|
||||
uint64_t d;
|
||||
uint8_t e;
|
||||
};
|
||||
|
||||
void zig_big_struct(struct BigStruct);
|
||||
|
||||
union BigUnion {
|
||||
struct BigStruct a;
|
||||
};
|
||||
|
||||
void zig_big_union(union BigUnion);
|
||||
|
||||
struct SmallStructInts {
|
||||
uint8_t a;
|
||||
uint8_t b;
|
||||
uint8_t c;
|
||||
uint8_t d;
|
||||
};
|
||||
void zig_small_struct_ints(struct SmallStructInts);
|
||||
|
||||
struct SplitStructInts {
|
||||
uint64_t a;
|
||||
uint8_t b;
|
||||
uint32_t c;
|
||||
};
|
||||
void zig_split_struct_ints(struct SplitStructInts);
|
||||
|
||||
struct BigStruct zig_big_struct_both(struct BigStruct);
|
||||
|
||||
void run_c_tests(void) {
|
||||
zig_u8(0xff);
|
||||
zig_u16(0xfffe);
|
||||
zig_u32(0xfffffffd);
|
||||
zig_u64(0xfffffffffffffffc);
|
||||
|
||||
zig_i8(-1);
|
||||
zig_i16(-2);
|
||||
zig_i32(-3);
|
||||
zig_i64(-4);
|
||||
|
||||
zig_f32(12.34f);
|
||||
zig_f64(56.78);
|
||||
|
||||
zig_ptr((void*)0xdeadbeefL);
|
||||
|
||||
zig_bool(true);
|
||||
|
||||
uint8_t array[10] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'};
|
||||
zig_array(array);
|
||||
|
||||
{
|
||||
struct BigStruct s = {1, 2, 3, 4, 5};
|
||||
zig_big_struct(s);
|
||||
}
|
||||
|
||||
{
|
||||
struct SmallStructInts s = {1, 2, 3, 4};
|
||||
zig_small_struct_ints(s);
|
||||
}
|
||||
|
||||
{
|
||||
struct SplitStructInts s = {1234, 100, 1337};
|
||||
zig_split_struct_ints(s);
|
||||
}
|
||||
|
||||
{
|
||||
struct BigStruct s = {30, 31, 32, 33, 34};
|
||||
struct BigStruct res = zig_big_struct_both(s);
|
||||
assert_or_panic(res.a == 20);
|
||||
assert_or_panic(res.b == 21);
|
||||
assert_or_panic(res.c == 22);
|
||||
assert_or_panic(res.d == 23);
|
||||
assert_or_panic(res.e == 24);
|
||||
}
|
||||
}
|
||||
|
||||
void c_u8(uint8_t x) {
|
||||
assert_or_panic(x == 0xff);
|
||||
}
|
||||
|
||||
void c_u16(uint16_t x) {
|
||||
assert_or_panic(x == 0xfffe);
|
||||
}
|
||||
|
||||
void c_u32(uint32_t x) {
|
||||
assert_or_panic(x == 0xfffffffd);
|
||||
}
|
||||
|
||||
void c_u64(uint64_t x) {
|
||||
assert_or_panic(x == 0xfffffffffffffffcULL);
|
||||
}
|
||||
|
||||
void c_i8(int8_t x) {
|
||||
assert_or_panic(x == -1);
|
||||
}
|
||||
|
||||
void c_i16(int16_t x) {
|
||||
assert_or_panic(x == -2);
|
||||
}
|
||||
|
||||
void c_i32(int32_t x) {
|
||||
assert_or_panic(x == -3);
|
||||
}
|
||||
|
||||
void c_i64(int64_t x) {
|
||||
assert_or_panic(x == -4);
|
||||
}
|
||||
|
||||
void c_f32(float x) {
|
||||
assert_or_panic(x == 12.34f);
|
||||
}
|
||||
|
||||
void c_f64(double x) {
|
||||
assert_or_panic(x == 56.78);
|
||||
}
|
||||
|
||||
void c_ptr(void *x) {
|
||||
assert_or_panic(x == (void*)0xdeadbeefL);
|
||||
}
|
||||
|
||||
void c_bool(bool x) {
|
||||
assert_or_panic(x);
|
||||
}
|
||||
|
||||
void c_array(uint8_t x[10]) {
|
||||
assert_or_panic(x[0] == '1');
|
||||
assert_or_panic(x[1] == '2');
|
||||
assert_or_panic(x[2] == '3');
|
||||
assert_or_panic(x[3] == '4');
|
||||
assert_or_panic(x[4] == '5');
|
||||
assert_or_panic(x[5] == '6');
|
||||
assert_or_panic(x[6] == '7');
|
||||
assert_or_panic(x[7] == '8');
|
||||
assert_or_panic(x[8] == '9');
|
||||
assert_or_panic(x[9] == '0');
|
||||
}
|
||||
|
||||
void c_big_struct(struct BigStruct x) {
|
||||
assert_or_panic(x.a == 1);
|
||||
assert_or_panic(x.b == 2);
|
||||
assert_or_panic(x.c == 3);
|
||||
assert_or_panic(x.d == 4);
|
||||
assert_or_panic(x.e == 5);
|
||||
}
|
||||
|
||||
void c_big_union(union BigUnion x) {
|
||||
assert_or_panic(x.a.a == 1);
|
||||
assert_or_panic(x.a.b == 2);
|
||||
assert_or_panic(x.a.c == 3);
|
||||
assert_or_panic(x.a.d == 4);
|
||||
}
|
||||
|
||||
void c_small_struct_ints(struct SmallStructInts x) {
|
||||
assert_or_panic(x.a == 1);
|
||||
assert_or_panic(x.b == 2);
|
||||
assert_or_panic(x.c == 3);
|
||||
assert_or_panic(x.d == 4);
|
||||
}
|
||||
|
||||
void c_split_struct_ints(struct SplitStructInts x) {
|
||||
assert_or_panic(x.a == 1234);
|
||||
assert_or_panic(x.b == 100);
|
||||
assert_or_panic(x.c == 1337);
|
||||
}
|
||||
|
||||
struct BigStruct c_big_struct_both(struct BigStruct x) {
|
||||
assert_or_panic(x.a == 1);
|
||||
assert_or_panic(x.b == 2);
|
||||
assert_or_panic(x.c == 3);
|
||||
assert_or_panic(x.d == 4);
|
||||
assert_or_panic(x.e == 5);
|
||||
struct BigStruct y = {10, 11, 12, 13, 14};
|
||||
return y;
|
||||
}
|
||||
239
test/stage1/c_abi/main.zig
Normal file
239
test/stage1/c_abi/main.zig
Normal file
@ -0,0 +1,239 @@
|
||||
const std = @import("std");
|
||||
const assertOrPanic = std.debug.assertOrPanic;
|
||||
|
||||
extern fn run_c_tests() void;
|
||||
|
||||
export fn zig_panic() noreturn {
|
||||
@panic("zig_panic called from C");
|
||||
}
|
||||
|
||||
test "C importing Zig ABI Tests" {
|
||||
run_c_tests();
|
||||
}
|
||||
|
||||
extern fn c_u8(u8) void;
|
||||
extern fn c_u16(u16) void;
|
||||
extern fn c_u32(u32) void;
|
||||
extern fn c_u64(u64) void;
|
||||
extern fn c_i8(i8) void;
|
||||
extern fn c_i16(i16) void;
|
||||
extern fn c_i32(i32) void;
|
||||
extern fn c_i64(i64) void;
|
||||
|
||||
test "C ABI integers" {
|
||||
c_u8(0xff);
|
||||
c_u16(0xfffe);
|
||||
c_u32(0xfffffffd);
|
||||
c_u64(0xfffffffffffffffc);
|
||||
|
||||
c_i8(-1);
|
||||
c_i16(-2);
|
||||
c_i32(-3);
|
||||
c_i64(-4);
|
||||
}
|
||||
|
||||
export fn zig_u8(x: u8) void {
|
||||
assertOrPanic(x == 0xff);
|
||||
}
|
||||
export fn zig_u16(x: u16) void {
|
||||
assertOrPanic(x == 0xfffe);
|
||||
}
|
||||
export fn zig_u32(x: u32) void {
|
||||
assertOrPanic(x == 0xfffffffd);
|
||||
}
|
||||
export fn zig_u64(x: u64) void {
|
||||
assertOrPanic(x == 0xfffffffffffffffc);
|
||||
}
|
||||
export fn zig_i8(x: i8) void {
|
||||
assertOrPanic(x == -1);
|
||||
}
|
||||
export fn zig_i16(x: i16) void {
|
||||
assertOrPanic(x == -2);
|
||||
}
|
||||
export fn zig_i32(x: i32) void {
|
||||
assertOrPanic(x == -3);
|
||||
}
|
||||
export fn zig_i64(x: i64) void {
|
||||
assertOrPanic(x == -4);
|
||||
}
|
||||
|
||||
extern fn c_f32(f32) void;
|
||||
extern fn c_f64(f64) void;
|
||||
|
||||
test "C ABI floats" {
|
||||
c_f32(12.34);
|
||||
c_f64(56.78);
|
||||
}
|
||||
|
||||
export fn zig_f32(x: f32) void {
|
||||
assertOrPanic(x == 12.34);
|
||||
}
|
||||
export fn zig_f64(x: f64) void {
|
||||
assertOrPanic(x == 56.78);
|
||||
}
|
||||
|
||||
extern fn c_ptr(*c_void) void;
|
||||
|
||||
test "C ABI pointer" {
|
||||
c_ptr(@intToPtr(*c_void, 0xdeadbeef));
|
||||
}
|
||||
|
||||
export fn zig_ptr(x: *c_void) void {
|
||||
assertOrPanic(@ptrToInt(x) == 0xdeadbeef);
|
||||
}
|
||||
|
||||
extern fn c_bool(bool) void;
|
||||
|
||||
test "C ABI bool" {
|
||||
c_bool(true);
|
||||
}
|
||||
|
||||
export fn zig_bool(x: bool) void {
|
||||
assertOrPanic(x);
|
||||
}
|
||||
|
||||
extern fn c_array([10]u8) void;
|
||||
|
||||
test "C ABI array" {
|
||||
var array: [10]u8 = "1234567890";
|
||||
c_array(array);
|
||||
}
|
||||
|
||||
export fn zig_array(x: [10]u8) void {
|
||||
assertOrPanic(std.mem.eql(u8, x, "1234567890"));
|
||||
}
|
||||
|
||||
const BigStruct = extern struct {
|
||||
a: u64,
|
||||
b: u64,
|
||||
c: u64,
|
||||
d: u64,
|
||||
e: u8,
|
||||
};
|
||||
extern fn c_big_struct(BigStruct) void;
|
||||
|
||||
test "C ABI big struct" {
|
||||
var s = BigStruct{
|
||||
.a = 1,
|
||||
.b = 2,
|
||||
.c = 3,
|
||||
.d = 4,
|
||||
.e = 5,
|
||||
};
|
||||
c_big_struct(s);
|
||||
}
|
||||
|
||||
export fn zig_big_struct(x: BigStruct) void {
|
||||
assertOrPanic(x.a == 1);
|
||||
assertOrPanic(x.b == 2);
|
||||
assertOrPanic(x.c == 3);
|
||||
assertOrPanic(x.d == 4);
|
||||
assertOrPanic(x.e == 5);
|
||||
}
|
||||
|
||||
const BigUnion = extern union {
|
||||
a: BigStruct,
|
||||
};
|
||||
extern fn c_big_union(BigUnion) void;
|
||||
|
||||
test "C ABI big union" {
|
||||
var x = BigUnion{
|
||||
.a = BigStruct{
|
||||
.a = 1,
|
||||
.b = 2,
|
||||
.c = 3,
|
||||
.d = 4,
|
||||
.e = 5,
|
||||
},
|
||||
};
|
||||
c_big_union(x);
|
||||
}
|
||||
|
||||
export fn zig_big_union(x: BigUnion) void {
|
||||
assertOrPanic(x.a.a == 1);
|
||||
assertOrPanic(x.a.b == 2);
|
||||
assertOrPanic(x.a.c == 3);
|
||||
assertOrPanic(x.a.d == 4);
|
||||
assertOrPanic(x.a.e == 5);
|
||||
}
|
||||
|
||||
const SmallStructInts = extern struct {
|
||||
a: u8,
|
||||
b: u8,
|
||||
c: u8,
|
||||
d: u8,
|
||||
};
|
||||
extern fn c_small_struct_ints(SmallStructInts) void;
|
||||
|
||||
test "C ABI small struct of ints" {
|
||||
var s = SmallStructInts{
|
||||
.a = 1,
|
||||
.b = 2,
|
||||
.c = 3,
|
||||
.d = 4,
|
||||
};
|
||||
c_small_struct_ints(s);
|
||||
}
|
||||
|
||||
export fn zig_small_struct_ints(x: SmallStructInts) void {
|
||||
assertOrPanic(x.a == 1);
|
||||
assertOrPanic(x.b == 2);
|
||||
assertOrPanic(x.c == 3);
|
||||
assertOrPanic(x.d == 4);
|
||||
}
|
||||
|
||||
const SplitStructInt = extern struct {
|
||||
a: u64,
|
||||
b: u8,
|
||||
c: u32,
|
||||
};
|
||||
extern fn c_split_struct_ints(SplitStructInt) void;
|
||||
|
||||
test "C ABI split struct of ints" {
|
||||
var s = SplitStructInt{
|
||||
.a = 1234,
|
||||
.b = 100,
|
||||
.c = 1337,
|
||||
};
|
||||
c_split_struct_ints(s);
|
||||
}
|
||||
|
||||
export fn zig_split_struct_ints(x: SplitStructInt) void {
|
||||
assertOrPanic(x.a == 1234);
|
||||
assertOrPanic(x.b == 100);
|
||||
assertOrPanic(x.c == 1337);
|
||||
}
|
||||
|
||||
extern fn c_big_struct_both(BigStruct) BigStruct;
|
||||
|
||||
test "C ABI sret and byval together" {
|
||||
var s = BigStruct{
|
||||
.a = 1,
|
||||
.b = 2,
|
||||
.c = 3,
|
||||
.d = 4,
|
||||
.e = 5,
|
||||
};
|
||||
var y = c_big_struct_both(s);
|
||||
assertOrPanic(y.a == 10);
|
||||
assertOrPanic(y.b == 11);
|
||||
assertOrPanic(y.c == 12);
|
||||
assertOrPanic(y.d == 13);
|
||||
assertOrPanic(y.e == 14);
|
||||
}
|
||||
|
||||
export fn zig_big_struct_both(x: BigStruct) BigStruct {
|
||||
assertOrPanic(x.a == 30);
|
||||
assertOrPanic(x.b == 31);
|
||||
assertOrPanic(x.c == 32);
|
||||
assertOrPanic(x.d == 33);
|
||||
assertOrPanic(x.e == 34);
|
||||
var s = BigStruct{
|
||||
.a = 20,
|
||||
.b = 21,
|
||||
.c = 22,
|
||||
.d = 23,
|
||||
.e = 24,
|
||||
};
|
||||
return s;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user