From 918c06f81a0ecd6039ac80bc8389dd227ab6d012 Mon Sep 17 00:00:00 2001 From: "Brett R. Toomey" Date: Wed, 5 Sep 2018 20:01:46 +0200 Subject: [PATCH 1/8] First pass on enum checking. Starting codegen --- src/checker.c | 111 +++++++++++++++++++++++++++++++++- src/checker.h | 7 +++ src/llvm.cpp | 52 ++++++++++++++-- src/types.c | 27 ++++++++- src/types.h | 16 +++++ tools/xcconfigs/LLVM.xcconfig | 4 ++ 6 files changed, 209 insertions(+), 8 deletions(-) diff --git a/src/checker.c b/src/checker.c index 3ed8867..3a67b85 100644 --- a/src/checker.c +++ b/src/checker.c @@ -352,6 +352,10 @@ b32 canCoerce(Type *type, Type *target, CheckerContext *ctx) { return type->Width <= target->Width; } + if (type->kind == TypeKind_Enum || IsInteger(target)) { + return canCoerce(type->Enum.backingType, target, ctx); + } + if (IsFloat(type)) { // Coercion between float types requires the target is larger or equal in size. return IsFloat(target) && type->Width <= target->Width; @@ -831,6 +835,85 @@ Type *checkExprTypeVariadic(Expr *expr, CheckerContext *ctx, Package *pkg) { return InvalidType; } +Type *checkExprTypeEnum(Expr *expr, CheckerContext *ctx, Package *pkg) { + ASSERT(expr->kind == ExprKind_TypeEnum); + Expr_TypeEnum enm = expr->TypeEnum; + + Type *backingType = NULL; + if (enm.explicitType) { + Type *type = checkExpr(enm.explicitType, ctx, pkg); + expectType(pkg, type, ctx, enm.explicitType->start); + if (IsInteger(type)) { + backingType = type; + } else { + ReportError( + pkg, TypeMismatchError, enm.explicitType->start, + "Enum backing type must be an integer. Got: %s", + DescribeType(type) + ); + } + } + + b32 firstValue = true; + b32 hasMinMax = false; + u64 maxValue; + + if (backingType) { + // TODO: flags + maxValue = MaxValueForIntOrPointerType(backingType); + hasMinMax = true; + } + + DynamicArray(EnumField) fields = NULL; + ArrayFit(fields, ArrayLen(enm.items)); + + u64 currentValue = 0; + u64 largestValue = 0; + + For(enm.items) { + EnumItem item = enm.items[i]; + + if (item.init) { + CheckerContext itemCtx = {.scope = ctx->scope, .desiredType = backingType}; + Type *type = checkExpr(item.init, &itemCtx, pkg); + + if (!IsConstant(&itemCtx)) { + ReportError( + pkg, TODOError, item.init->start, + "Enum cases must be a constant value"); + continue; + } + + if (backingType && !canCoerce(type, backingType, &itemCtx)) { + ReportError( + pkg, InvalidConversionError, item.init->start, + "Cannot convert %s to type %s", + DescribeExpr(item.init), DescribeType(backingType) + ); + continue; + } + + u64 val = itemCtx.val.u64; + currentValue = val; + largestValue = MAX(largestValue, val); + } + + if (hasMinMax && currentValue > maxValue) { + printf("oops!\n"); + continue; + } + + ArrayPush(fields, (EnumField){.name = item.name, .val = currentValue}); + currentValue++; + } + + backingType = backingType ? backingType : SmallestIntTypeForPositiveValue(largestValue); + Type *type = NewTypeEnum(TypeFlag_None, backingType, fields); + storeInfoBasicExpr(pkg, expr, type, ctx); + ctx->mode = ExprMode_Type; + return type; +} + Type *checkExprTypeFunction(Expr *expr, CheckerContext *ctx, Package *pkg) { ASSERT(expr->kind == ExprKind_TypeFunction); Expr_TypeFunction func = expr->TypeFunction; @@ -1533,6 +1616,25 @@ Type *checkExprSelector(Expr *expr, CheckerContext *ctx, Package *pkg) { break; } + case TypeKind_Enum: { + if (ctx->mode == ExprMode_Type) { + EnumFieldLookupResult result = EnumFieldLookup(base->Enum, expr->Selector.name); + if (!result.field) { + ReportError(pkg, TODOError, expr->Selector.start, "Enum %s has no member named %s", + DescribeType(base), expr->Selector.name); + goto error; + } + + ctx->val.u64 = result.field->val; + SelectorValue val = {.Enum.index = result.index}; + storeInfoSelector(pkg, expr, base, SelectorKind_Enum, val, ctx); + type = base; + ctx->mode = ExprMode_Addressable; + ctx->flags |= CheckerContextFlag_Constant; + break; + } + } + default: { ReportError(pkg, TODOError, expr->start, "%s has no member '%s'", DescribeExpr(expr->Selector.expr), expr->Selector.name); goto error; @@ -1643,6 +1745,9 @@ Type *checkExpr(Expr *expr, CheckerContext *ctx, Package *pkg) { break; case ExprKind_TypeEnum: + type = checkExprTypeEnum(expr, ctx, pkg); + break; + case ExprKind_TypeUnion: case ExprKind_TypePolymorphic: UNIMPLEMENTED(); @@ -1757,8 +1862,12 @@ b32 checkDeclConstant(Decl *declStmt, CheckerContext *ctx, Package *pkg) { break; } - case ExprKind_TypeUnion: case ExprKind_TypeEnum: { + symbol->state = SymbolState_Resolving; + symbol->kind = SymbolKind_Type; + } break; + + case ExprKind_TypeUnion: { UNIMPLEMENTED(); } break; diff --git a/src/checker.h b/src/checker.h index dcf3857..7221424 100644 --- a/src/checker.h +++ b/src/checker.h @@ -58,6 +58,7 @@ struct CheckerInfo_Ident { typedef u8 SelectorKind; #define SelectorKind_None 0x0 #define SelectorKind_Struct 0x1 +#define SelectorKind_Enum 0x2 typedef struct Selector_Struct Selector_Struct; struct Selector_Struct { @@ -65,9 +66,15 @@ struct Selector_Struct { u32 offset; // The member offset in the structure (in bits) }; +typedef struct Selector_Enum Selector_Enum; +struct Selector_Enum { + u32 index; +}; + typedef union SelectorValue SelectorValue; union SelectorValue { Selector_Struct Struct; + Selector_Enum Enum; }; typedef struct CheckerInfo_Selector CheckerInfo_Selector; diff --git a/src/llvm.cpp b/src/llvm.cpp index 82bc828..d941138 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -98,8 +98,8 @@ struct Context { std::vector deferStack; }; -typedef struct BackendStructUserdata BackendStructUserdata; -struct BackendStructUserdata { +typedef struct BackendUserdataAndDebug BackendUserdataAndDebug; +struct BackendUserdataAndDebug { llvm::Type *type; llvm::DIType *debugType; }; @@ -133,6 +133,10 @@ llvm::Type *canonicalize(Context *ctx, Type *type) { } } break; + case TypeKind_Enum: { + return llvm::IntegerType::get(ctx->m->getContext(), type->Width); + }; + case TypeKind_Array: { return llvm::ArrayType::get(canonicalize(ctx, type->Array.elementType), type->Array.length); } break; @@ -156,7 +160,7 @@ llvm::Type *canonicalize(Context *ctx, Type *type) { case TypeKind_Struct: { if (type->Symbol && type->Symbol->backendUserdata) { - return ((BackendStructUserdata *) type->Symbol->backendUserdata)->type; + return ((BackendUserdataAndDebug *) type->Symbol->backendUserdata)->type; } std::vector elements; @@ -225,9 +229,38 @@ llvm::DIType *debugCanonicalize(Context *ctx, Type *type) { return ctx->d.builder->createSubroutineType(pTypes); } + if (type->kind == TypeKind_Enum) { + if (type->Symbol && type->Symbol->backendUserdata) { + return ((BackendUserdataAndDebug *) type->Symbol->backendUserdata)->debugType; + } + + std::vector enumerations; + For(type->Enum.cases) { + EnumField it = type->Enum.cases[i]; + auto enumeration = ctx->d.builder->createEnumerator( + it.name, + it.val + ); + + enumerations.push_back(enumeration); + } + + auto elements = ctx->d.builder->getOrCreateArray(enumerations); + ctx->d.builder->createEnumerationType( + ctx->d.scope, + type->Symbol->name, + ctx->d.file, + 0, + type->Width, + type->Align, + elements, + debugCanonicalize(ctx, type->Enum.backingType) + ); + } + if (type->kind == TypeKind_Struct) { if (type->Symbol && type->Symbol->backendUserdata) { - return ((BackendStructUserdata *) type->Symbol->backendUserdata)->debugType; + return ((BackendUserdataAndDebug *) type->Symbol->backendUserdata)->debugType; } std::vector elementTypes; @@ -932,7 +965,7 @@ llvm::StructType *emitExprTypeStruct(Context *ctx, Expr *expr) { if (type->Symbol) { ty->setName(type->Symbol->name); - BackendStructUserdata *userdata = (BackendStructUserdata *) ArenaAlloc(&ctx->arena, sizeof(BackendStructUserdata)); + BackendUserdataAndDebug *userdata = (BackendUserdataAndDebug *) ArenaAlloc(&ctx->arena, sizeof(BackendUserdataAndDebug)); userdata->type = ty; userdata->debugType = debugType; type->Symbol->backendUserdata = userdata; @@ -986,6 +1019,10 @@ void emitDeclConstant(Context *ctx, Decl *decl) { break; } + case ExprKind_TypeEnum: { + break; + } + default: { llvm::Type *type = canonicalize(ctx, symbol->type); @@ -1557,7 +1594,6 @@ b32 CodegenLLVM(Package *p) { // TODO: Absolute path for dir llvm::DIFile *file = builder->createFile(name, dir); - llvm::DICompileUnit *unit = builder->createCompileUnit( llvm::dwarf::DW_LANG_C, file, @@ -1694,4 +1730,8 @@ void printIR(llvm::Type *value) { value->print(llvm::outs()); } +void printModule(llvm::Module *module) { + module->print(llvm::errs(), nullptr); +} + #pragma clang diagnostic pop diff --git a/src/types.c b/src/types.c index 10363db..91985de 100644 --- a/src/types.c +++ b/src/types.c @@ -114,7 +114,6 @@ b32 TypesIdentical(Type *type, Type *target) { } StructFieldLookupResult StructFieldLookup(Type_Struct type, const char *name) { - u32 index = 0; TypeField *field = NULL; ForEachWithIndex(type.members, i, TypeField *, it) { @@ -128,6 +127,22 @@ StructFieldLookupResult StructFieldLookup(Type_Struct type, const char *name) { return (StructFieldLookupResult){index, field}; } +EnumFieldLookupResult EnumFieldLookup(Type_Enum type, const char *name) { + u32 index = 0; + EnumField *field = NULL; + For(type.cases) { + EnumField *it = &type.cases[i]; + if (it->name == name) { + index = (u32) i; + field = it; + break; + } + } + + return (EnumFieldLookupResult){index, field}; +} + + #if TEST void test_SmallestIntTypeForValue() { INIT_COMPILER(); @@ -239,6 +254,16 @@ Type *NewTypeFunction(TypeFlag flags, DynamicArray(Type *) params, DynamicArray( return type; } +Type *NewTypeEnum(TypeFlag flags, Type *backingType, DynamicArray(EnumField) items) { + Type *type = AllocType(TypeKind_Enum); + type->Width = backingType->Width; + type->Align = backingType->Align; + type->Flags = flags; + type->Enum.cases = items; + type->Enum.backingType = backingType; + return type; +} + Type *NewTypeTuple(TypeFlag flags, DynamicArray(Type *) types) { Type *type = AllocType(TypeKind_Tuple); type->Flags = flags; diff --git a/src/types.h b/src/types.h index 1f90587..7278208 100644 --- a/src/types.h +++ b/src/types.h @@ -105,8 +105,15 @@ struct TypeField { u32 offset; }; +typedef struct EnumField EnumField; +struct EnumField { + const char *name; + u64 val; +}; + struct Type_Struct { TypeFlag Flags; + // TODO: This shouldn't be an indirect type DynamicArray(TypeField *) members; }; @@ -119,6 +126,8 @@ struct Type_Union { struct Type_Enum { TypeFlag Flags; + Type *backingType; + DynamicArray(EnumField) cases; }; struct Type_Tuple { @@ -146,6 +155,7 @@ struct Type { Type_Pointer Pointer; Type_Array Array; Type_Slice Slice; + Type_Enum Enum; Type_Struct Struct; Type_Union Union; Type_Function Function; @@ -159,6 +169,12 @@ struct StructFieldLookupResult { TypeField *field; }; +typedef struct EnumFieldLookupResult EnumFieldLookupResult; +struct EnumFieldLookupResult { + u32 index; + EnumField *field; +}; + #ifdef __cplusplus extern "C" { #endif diff --git a/tools/xcconfigs/LLVM.xcconfig b/tools/xcconfigs/LLVM.xcconfig index e69de29..ffca5e9 100644 --- a/tools/xcconfigs/LLVM.xcconfig +++ b/tools/xcconfigs/LLVM.xcconfig @@ -0,0 +1,4 @@ + +LLVM_CXXFLAGS = -I/usr/local/Cellar/llvm/6.0.0/include -stdlib=libc++ -fPIC -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -std=c++11 -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wcovered-switch-default -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wstring-conversion -DNDEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS + +LLVM_CXXLDFLAGS = -L/usr/local/Cellar/llvm/6.0.0/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVMLTO -lLLVMPasses -lLLVMObjCARCOpts -lLLVMMIRParser -lLLVMSymbolize -lLLVMDebugInfoPDB -lLLVMDebugInfoDWARF -lLLVMCoverage -lLLVMTableGen -lLLVMDlltoolDriver -lLLVMOrcJIT -lLLVMXCoreDisassembler -lLLVMXCoreCodeGen -lLLVMXCoreDesc -lLLVMXCoreInfo -lLLVMXCoreAsmPrinter -lLLVMSystemZDisassembler -lLLVMSystemZCodeGen -lLLVMSystemZAsmParser -lLLVMSystemZDesc -lLLVMSystemZInfo -lLLVMSystemZAsmPrinter -lLLVMSparcDisassembler -lLLVMSparcCodeGen -lLLVMSparcAsmParser -lLLVMSparcDesc -lLLVMSparcInfo -lLLVMSparcAsmPrinter -lLLVMPowerPCDisassembler -lLLVMPowerPCCodeGen -lLLVMPowerPCAsmParser -lLLVMPowerPCDesc -lLLVMPowerPCInfo -lLLVMPowerPCAsmPrinter -lLLVMNVPTXCodeGen -lLLVMNVPTXDesc -lLLVMNVPTXInfo -lLLVMNVPTXAsmPrinter -lLLVMMSP430CodeGen -lLLVMMSP430Desc -lLLVMMSP430Info -lLLVMMSP430AsmPrinter -lLLVMMipsDisassembler -lLLVMMipsCodeGen -lLLVMMipsAsmParser -lLLVMMipsDesc -lLLVMMipsInfo -lLLVMMipsAsmPrinter -lLLVMLanaiDisassembler -lLLVMLanaiCodeGen -lLLVMLanaiAsmParser -lLLVMLanaiDesc -lLLVMLanaiAsmPrinter -lLLVMLanaiInfo -lLLVMHexagonDisassembler -lLLVMHexagonCodeGen -lLLVMHexagonAsmParser -lLLVMHexagonDesc -lLLVMHexagonInfo -lLLVMBPFDisassembler -lLLVMBPFCodeGen -lLLVMBPFAsmParser -lLLVMBPFDesc -lLLVMBPFInfo -lLLVMBPFAsmPrinter -lLLVMARMDisassembler -lLLVMARMCodeGen -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMARMInfo -lLLVMARMAsmPrinter -lLLVMARMUtils -lLLVMAMDGPUDisassembler -lLLVMAMDGPUCodeGen -lLLVMAMDGPUAsmParser -lLLVMAMDGPUDesc -lLLVMAMDGPUInfo -lLLVMAMDGPUAsmPrinter -lLLVMAMDGPUUtils -lLLVMAArch64Disassembler -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser -lLLVMAArch64Desc -lLLVMAArch64Info -lLLVMAArch64AsmPrinter -lLLVMAArch64Utils -lLLVMObjectYAML -lLLVMLibDriver -lLLVMOption -lLLVMWindowsManifest -lLLVMFuzzMutate -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMGlobalISel -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMDebugInfoCodeView -lLLVMDebugInfoMSF -lLLVMX86Desc -lLLVMMCDisassembler -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT -lLLVMLineEditor -lLLVMInterpreter -lLLVMExecutionEngine -lLLVMRuntimeDyld -lLLVMCodeGen -lLLVMTarget -lLLVMCoroutines -lLLVMipo -lLLVMInstrumentation -lLLVMVectorize -lLLVMScalarOpts -lLLVMLinker -lLLVMIRReader -lLLVMAsmParser -lLLVMInstCombine -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData -lLLVMObject -lLLVMMCParser -lLLVMMC -lLLVMBitReader -lLLVMCore -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle -lz -lcurses -lm From e7694b2b6e8fb29dcb42e51000be67241532931a Mon Sep 17 00:00:00 2001 From: "Brett R. Toomey" Date: Thu, 6 Sep 2018 12:03:40 +0200 Subject: [PATCH 2/8] New case for enums --- src/llvm.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/llvm.cpp b/src/llvm.cpp index d941138..f90c6e8 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -913,6 +913,13 @@ llvm::Function *emitExprLitFunction(Context *ctx, Expr *expr, llvm::Function *fn return fn; } +llvm::Value *emitExprTypeEnum(Context *ctx, Expr *expr) { + ASSERT(expr->kind == ExprKind_TypeEnum); + + Type *type = TypeFromCheckerInfo(ctx->checkerInfo[expr->id]); + UNIMPLEMENTED(); +} + llvm::StructType *emitExprTypeStruct(Context *ctx, Expr *expr) { ASSERT(expr->kind == ExprKind_TypeStruct); @@ -1020,6 +1027,7 @@ void emitDeclConstant(Context *ctx, Decl *decl) { } case ExprKind_TypeEnum: { + emitExprTypeEnum(ctx, decl->Constant.values[0]); break; } From 027b74c3f0253691307f8877e635dd43ec110489 Mon Sep 17 00:00:00 2001 From: "Brett R. Toomey" Date: Thu, 6 Sep 2018 21:50:20 +0200 Subject: [PATCH 3/8] Enum codegen working --- src/checker.c | 71 ++++++++++++++--------------- src/checker.h | 2 +- src/llvm.cpp | 121 +++++++++++++++++++++++++++++++++++++------------- 3 files changed, 127 insertions(+), 67 deletions(-) diff --git a/src/checker.c b/src/checker.c index a0459d4..d95c772 100644 --- a/src/checker.c +++ b/src/checker.c @@ -223,12 +223,16 @@ b32 IsFloat(Type *type) { return type->kind == TypeKind_Float; } +b32 isEnum(Type *type) { + return type->kind == TypeKind_Enum; +} + b32 isFunction(Type *type) { return type->kind == TypeKind_Function; } b32 isNumeric(Type *type) { - return IsInteger(type) || IsFloat(type); + return IsInteger(type) || IsFloat(type) || isEnum(type); } b32 isBoolean(Type *type) { @@ -267,10 +271,6 @@ b32 isSlice(Type *type) { return type->kind == TypeKind_Slice; } -b32 isEnum(Type *type) { - return type->kind == TypeKind_Enum; -} - b32 isEnumFlags(Type *type) { return isEnum(type) && (type->Flags & TypeFlag_EnumFlags) != 0; } @@ -366,7 +366,7 @@ b32 canCoerce(Type *type, Type *target, CheckerContext *ctx) { return type->Width <= target->Width; } - if (type->kind == TypeKind_Enum || IsInteger(target)) { + if (isEnum(type) && IsInteger(target)) { return canCoerce(type->Enum.backingType, target, ctx); } @@ -474,6 +474,10 @@ Conversion conversion(Type *type, Type *target) { return result; } + if (type->kind == TypeKind_Enum && IsInteger(target)) { + return ConversionKind_None; + } + if (IsFloat(type) && IsInteger(target)) { result |= ConversionKind_FtoI & ConversionFlag_Float; if (IsSigned(type)) result |= ConversionFlag_Signed; @@ -872,31 +876,28 @@ Type *checkExprTypeEnum(Expr *expr, CheckerContext *ctx, Package *pkg) { ASSERT(expr->kind == ExprKind_TypeEnum); Expr_TypeEnum enm = expr->TypeEnum; + b32 hasMinMax = false; + u64 maxValue; + Type *backingType = NULL; if (enm.explicitType) { Type *type = checkExpr(enm.explicitType, ctx, pkg); - expectType(pkg, type, ctx, enm.explicitType->start); - if (IsInteger(type)) { - backingType = type; - } else { - ReportError( - pkg, TypeMismatchError, enm.explicitType->start, - "Enum backing type must be an integer. Got: %s", - DescribeType(type) - ); + if (ctx->mode == ExprMode_Unresolved) goto unresolved; + + if (ctx->mode != ExprMode_Invalid) { + expectType(pkg, type, ctx, enm.explicitType->start); + if (IsInteger(type)) { + // TODO: flags + maxValue = MaxValueForIntOrPointerType(type); + hasMinMax = true; + backingType = type; + } else { + ReportError(pkg, TypeMismatchError, enm.explicitType->start, + "Enum backing type must be an integer. Got: %s", DescribeType(type)); + } } } - b32 firstValue = true; - b32 hasMinMax = false; - u64 maxValue; - - if (backingType) { - // TODO: flags - maxValue = MaxValueForIntOrPointerType(backingType); - hasMinMax = true; - } - DynamicArray(EnumField) fields = NULL; ArrayFit(fields, ArrayLen(enm.items)); @@ -909,20 +910,15 @@ Type *checkExprTypeEnum(Expr *expr, CheckerContext *ctx, Package *pkg) { if (item.init) { CheckerContext itemCtx = {.scope = ctx->scope, .desiredType = backingType}; Type *type = checkExpr(item.init, &itemCtx, pkg); + if (itemCtx.mode == ExprMode_Unresolved) goto unresolved; // TODO: @Leak this will leak the 'fields' array if (!IsConstant(&itemCtx)) { - ReportError( - pkg, TODOError, item.init->start, + ReportError(pkg, TODOError, item.init->start, "Enum cases must be a constant value"); continue; } - if (backingType && !canCoerce(type, backingType, &itemCtx)) { - ReportError( - pkg, InvalidConversionError, item.init->start, - "Cannot convert %s to type %s", - DescribeExpr(item.init), DescribeType(backingType) - ); + if (backingType && !coerceType(item.init, ctx, &type, backingType, pkg)) { continue; } @@ -932,7 +928,8 @@ Type *checkExprTypeEnum(Expr *expr, CheckerContext *ctx, Package *pkg) { } if (hasMinMax && currentValue > maxValue) { - printf("oops!\n"); + ReportError(pkg, IntOverflowError, item.init->start, + "Enum case is will overflow backing type"); continue; } @@ -945,6 +942,10 @@ Type *checkExprTypeEnum(Expr *expr, CheckerContext *ctx, Package *pkg) { storeInfoBasicExpr(pkg, expr, type, ctx); ctx->mode = ExprMode_Type; return type; + +unresolved: + ctx->mode = ExprMode_Unresolved; + return NULL; } Type *checkExprTypeFunction(Expr *expr, CheckerContext *ctx, Package *pkg) { @@ -1670,7 +1671,7 @@ Type *checkExprSelector(Expr *expr, CheckerContext *ctx, Package *pkg) { } ctx->val.u64 = result.field->val; - SelectorValue val = {.Enum.index = result.index}; + SelectorValue val = {.Enum.value = result.field->val}; storeInfoSelector(pkg, expr, base, SelectorKind_Enum, val, ctx); type = base; ctx->mode = ExprMode_Addressable; diff --git a/src/checker.h b/src/checker.h index f22be25..21332a9 100644 --- a/src/checker.h +++ b/src/checker.h @@ -69,7 +69,7 @@ struct Selector_Struct { typedef struct Selector_Enum Selector_Enum; struct Selector_Enum { - u32 index; + u64 value; }; typedef struct Selector_Import Selector_Import; diff --git a/src/llvm.cpp b/src/llvm.cpp index 5a7834b..6abf079 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -553,6 +553,15 @@ llvm::Value *emitExprSelector(Context *ctx, Expr *expr) { return ctx->b.CreateAlignedLoad(addr, BytesFromBits(info.value.Struct.index)); } + case SelectorKind_Enum: { + llvm::Type *type = canonicalize(ctx, info.type); + if (ctx->returnAddress) { + UNIMPLEMENTED(); + } + + return llvm::ConstantInt::get(type, info.value.Enum.value); + } + case SelectorKind_Import: { Symbol *symbol = info.value.Import.symbol; if (!symbol->backendUserdata) { @@ -1006,11 +1015,61 @@ llvm::Function *emitExprLitFunction(Context *ctx, Expr *expr, llvm::Function *fn return fn; } -llvm::Value *emitExprTypeEnum(Context *ctx, Expr *expr) { +llvm::Type *emitExprTypeEnum(Context *ctx, Expr *expr) { ASSERT(expr->kind == ExprKind_TypeEnum); Type *type = TypeFromCheckerInfo(ctx->checkerInfo[expr->id]); - UNIMPLEMENTED(); + + if (type->Symbol->backendUserdata && !FlagDebug) { + BackendUserdataAndDebug *userdata = (BackendUserdataAndDebug *)type->Symbol->backendUserdata; + return userdata->type; + } + + Type_Enum enm = type->Enum; + + llvm::Type *ty; + if (type->Symbol->backendUserdata) { + ty = ((BackendUserdataAndDebug *)type->Symbol->backendUserdata)->type; + } else { + ty = canonicalize(ctx, enm.backingType); + } + + BackendUserdataAndDebug *userdata; + if (type->Symbol->backendUserdata) { + userdata = (BackendUserdataAndDebug *) type->Symbol->backendUserdata; + ASSERT_MSG(!userdata->debugType, "debugType is only set here, which means this run twice"); + } else { + userdata = (BackendUserdataAndDebug *) ArenaAlloc(&ctx->arena, sizeof(*userdata)); + userdata->type = ty; + type->Symbol->backendUserdata = userdata; + } + + if (FlagDebug) { + llvm::DIType *dbTy = debugCanonicalize(ctx, enm.backingType); + std::vector enumerations; + + For (enm.cases) { + EnumField cse = enm.cases[i]; + llvm::DIEnumerator *e = ctx->d.builder->createEnumerator(cse.name, cse.val); + enumerations.push_back(e); + } + + auto elements = ctx->d.builder->getOrCreateArray(enumerations); + dbTy = ctx->d.builder->createEnumerationType( + ctx->d.scope, + type->Symbol->name, + ctx->d.file, + expr->start.line, + type->Width, + type->Align, + elements, + dbTy + ); + + userdata->debugType = dbTy; + } + + return ty; } llvm::StructType *emitExprTypeStruct(Context *ctx, Expr *expr) { @@ -1032,22 +1091,25 @@ llvm::StructType *emitExprTypeStruct(Context *ctx, Expr *expr) { Type *fieldType = type->Struct.members[index]->type; llvm::Type *ty = canonicalize(ctx, fieldType); - llvm::DIType *dty = debugCanonicalize(ctx, fieldType); + llvm::DIType *dty = NULL; + if (FlagDebug) + dty = debugCanonicalize(ctx, fieldType); + for (size_t j = 0; j < ArrayLen(item.names); j++) { if (FlagDebug) { - llvm::DIDerivedType *member = ctx->d.builder->createMemberType( - ctx->d.scope, - item.names[j], - ctx->d.file, - item.start.line, - fieldType->Width, - fieldType->Align, - type->Struct.members[index]->offset, - llvm::DINode::DIFlags::FlagZero, - dty - ); + llvm::DIDerivedType *member = ctx->d.builder->createMemberType( + ctx->d.scope, + item.names[j], + ctx->d.file, + item.start.line, + fieldType->Width, + fieldType->Align, + type->Struct.members[index]->offset, + llvm::DINode::DIFlags::FlagZero, + dty + ); - debugMembers.push_back(member); + debugMembers.push_back(member); } elementTypes.push_back(ty); @@ -1057,24 +1119,10 @@ llvm::StructType *emitExprTypeStruct(Context *ctx, Expr *expr) { llvm::StructType *ty; if (type->Symbol->backendUserdata) { - ty = (llvm::StructType *) type->Symbol->backendUserdata; + ty = ((BackendStructUserdata *) type->Symbol->backendUserdata)->type; } else { ty = llvm::StructType::create(ctx->m->getContext(), elementTypes); } - llvm::DICompositeType *debugType; - if (FlagDebug) { - debugType = ctx->d.builder->createStructType( - ctx->d.scope, - type->Symbol->name, - ctx->d.file, - type->Symbol->decl->start.line, - type->Width, - type->Align, - llvm::DINode::DIFlags::FlagZero, - NULL, // DerivedFrom - ctx->d.builder->getOrCreateArray(debugMembers) - ); - } if (type->Symbol) { ty->setName(type->Symbol->name); @@ -1084,12 +1132,23 @@ llvm::StructType *emitExprTypeStruct(Context *ctx, Expr *expr) { userdata = (BackendStructUserdata *) type->Symbol->backendUserdata; ASSERT_MSG(!userdata->debugType, "debugType is only set here, which means this run twice"); } else { - userdata = (BackendStructUserdata *) ArenaAlloc(&ctx->arena, sizeof(BackendStructUserdata)); + userdata = (BackendStructUserdata *) ArenaAlloc(&ctx->arena, sizeof(*userdata)); userdata->type = ty; type->Symbol->backendUserdata = userdata; } if (FlagDebug) { + llvm::DICompositeType *debugType = ctx->d.builder->createStructType( + ctx->d.scope, + type->Symbol->name, + ctx->d.file, + type->Symbol->decl->start.line, + type->Width, + type->Align, + llvm::DINode::DIFlags::FlagZero, + NULL, // DerivedFrom + ctx->d.builder->getOrCreateArray(debugMembers) + ); userdata->debugType = debugType; } } From eb12b23b1ab64e730fbea863dc848e3e1ec3d9b4 Mon Sep 17 00:00:00 2001 From: "Brett R. Toomey" Date: Sun, 16 Sep 2018 16:38:43 +0200 Subject: [PATCH 4/8] More updates and bug fixes --- src/checker.c | 20 ++++++++++--------- src/checker.h | 6 ++++-- src/header.c | 37 ++++++++++++++++++++++++++++------ src/llvm.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++-------- src/main.c | 1 - src/types.c | 12 ++++++++++- 6 files changed, 104 insertions(+), 27 deletions(-) diff --git a/src/checker.c b/src/checker.c index d95c772..cbe9209 100644 --- a/src/checker.c +++ b/src/checker.c @@ -232,7 +232,7 @@ b32 isFunction(Type *type) { } b32 isNumeric(Type *type) { - return IsInteger(type) || IsFloat(type) || isEnum(type); + return IsInteger(type) || IsFloat(type); } b32 isBoolean(Type *type) { @@ -474,8 +474,8 @@ Conversion conversion(Type *type, Type *target) { return result; } - if (type->kind == TypeKind_Enum && IsInteger(target)) { - return ConversionKind_None; + if (isEnum(type) && IsInteger(target)) { + return ConversionKind_Enum; } if (IsFloat(type) && IsInteger(target)) { @@ -910,7 +910,7 @@ Type *checkExprTypeEnum(Expr *expr, CheckerContext *ctx, Package *pkg) { if (item.init) { CheckerContext itemCtx = {.scope = ctx->scope, .desiredType = backingType}; Type *type = checkExpr(item.init, &itemCtx, pkg); - if (itemCtx.mode == ExprMode_Unresolved) goto unresolved; // TODO: @Leak this will leak the 'fields' array + if (itemCtx.mode == ExprMode_Unresolved) goto unresolved; if (!IsConstant(&itemCtx)) { ReportError(pkg, TODOError, item.init->start, @@ -929,7 +929,11 @@ Type *checkExprTypeEnum(Expr *expr, CheckerContext *ctx, Package *pkg) { if (hasMinMax && currentValue > maxValue) { ReportError(pkg, IntOverflowError, item.init->start, - "Enum case is will overflow backing type"); + "Value for enum case exceeds the max value for the enum backing type (%s)", + DescribeType(backingType)); + ReportNote(pkg, item.init->start, + "You can force the overflow by explicitly casting the value '%s(%s)", + DescribeType(backingType), DescribeExpr(item.init)); continue; } @@ -944,6 +948,7 @@ Type *checkExprTypeEnum(Expr *expr, CheckerContext *ctx, Package *pkg) { return type; unresolved: + if (fields) ArrayFree(fields); ctx->mode = ExprMode_Unresolved; return NULL; } @@ -2435,7 +2440,7 @@ void checkStmtSwitch(Stmt *stmt, CheckerContext *ctx, Package *pkg) { Type *switchType = BoolType; if (stmt->Switch.match) { switchType = checkExpr(stmt->Switch.match, &switchCtx, pkg); - if (!isNumericOrPointer(switchType) && !isBoolean(switchType)) { + if (!isNumericOrPointer(switchType) && !isBoolean(switchType) && !isEnum(switchType)) { ReportError(pkg, CannotSwitchError, stmt->Switch.match->start, "Cannot switch on value of type %s", DescribeType(switchType)); } @@ -3244,6 +3249,3 @@ info = GetStmtInfo(&pkg, stmt)->Switch #undef pkg #endif - - - diff --git a/src/checker.h b/src/checker.h index 21332a9..8e2a323 100644 --- a/src/checker.h +++ b/src/checker.h @@ -20,7 +20,7 @@ enum Enum_CheckerInfoKind { STATIC_ASSERT(_StmtKind_End <= UINT8_MAX, "enum values overflow storage type"); typedef u8 Conversion; -#define ConversionKind_Mask 0x07 // Lower 3 bits denote the class +#define ConversionKind_Mask 0x0F // Lower 3 bits denote the class #define ConversionKind_None 0 #define ConversionKind_Same 1 #define ConversionKind_FtoI 2 @@ -28,11 +28,13 @@ typedef u8 Conversion; #define ConversionKind_PtoI 4 #define ConversionKind_ItoP 5 #define ConversionKind_Bool 6 -#define ConversionKind_Any 7 +#define ConversionKind_Enum 7 +#define ConversionKind_Any 8 #define ConversionFlag_Extend 0x10 // 0001 #define ConversionFlag_Signed 0x20 // 0010 #define ConversionFlag_Float 0x40 // 0100 (Source type is a Float) +#define ConversionFlag_Enum 0x80 // 1000 typedef struct CheckerInfo_Constant CheckerInfo_Constant; struct CheckerInfo_Constant { diff --git a/src/header.c b/src/header.c index 1a2e574..713613f 100644 --- a/src/header.c +++ b/src/header.c @@ -11,6 +11,9 @@ void cgenType(String *buffer, const char * name, Type *type) { switch (type->kind) { case TypeKind_Int: + if (type->Width == 1) + return cgenType(buffer, name, I8Type); + ArrayPrintf(*buffer, "Kai%s%d", type->Flags & TypeFlag_Signed ? "I" : "U", type->Width); break; @@ -19,10 +22,19 @@ void cgenType(String *buffer, const char * name, Type *type) { break; case TypeKind_Pointer: { - String pointee = NULL; - cgenType(&pointee, NULL, type->Pointer.pointeeType); - ArrayPrintf(*buffer, "%s*", pointee); - ArrayFree(pointee); + if (type == RawptrType) { + ArrayPrintf(*buffer, "KaiRawptr"); + } else { + String pointee = NULL; + cgenType(&pointee, NULL, type->Pointer.pointeeType); + ArrayPrintf(*buffer, "%s*", pointee); + ArrayFree(pointee); + } + } break; + + case TypeKind_Enum: { + cgenType(buffer, name, type->Enum.backingType); + return; } break; case TypeKind_Struct: { @@ -82,6 +94,19 @@ void cgenDecl(HeaderContext *ctx, DynamicArray(Expr_Ident *) names, Type *type, cgenFuncPrototype(&ctx->functions, it->name, type); break; + case TypeKind_Enum: { + For(type->Enum.cases) { + struct EnumField field = type->Enum.cases[i]; + ArrayPrintf( + ctx->primitiveDecls, + "#define %s_%s %lu\n", + type->Symbol->name, + field.name, + field.val + ); + } + } break; + case TypeKind_Struct: { if (type->Symbol->backendUserdata != HEAD_GENERATED) { ArrayPrintf(ctx->primitiveDecls, "typedef "); @@ -96,7 +121,7 @@ void cgenDecl(HeaderContext *ctx, DynamicArray(Expr_Ident *) names, Type *type, cgenType(&ctx->complexDecls, it->name, it->type); ArrayPrintf(ctx->complexDecls, ";\n"); } - ArrayPrintf(ctx->complexDecls, "};\n"); + ArrayPrintf(ctx->complexDecls, "};\n\n"); } break; default: { @@ -126,7 +151,7 @@ void cgenStmt(HeaderContext *ctx, CheckerInfo *info, Stmt *stmt) { } } -const char *headerPreface = "#ifndef KAI_%s_H\n#define KAI_%s_H\n\n#ifndef KAI_TYPES\n#define KAI_TYPES\n#include \n\ntypedef int8_t KaiI8;\ntypedef int16_t KaiI16;\ntypedef int32_t KaiI32;\ntypedef int64_t KaiI64;\n\ntypedef uint8_t KaiU8;\ntypedef uint16_t KaiU16;\ntypedef uint32_t KaiU32;\ntypedef uint64_t KaiU64;\n\ntypedef float KaiF32;\ntypedef double KaiF64;\n#endif\n"; +const char *headerPreface = "#ifndef KAI_%s_H\n#define KAI_%s_H\n\n#ifndef KAI_TYPES\n#define KAI_TYPES\n#include \n\ntypedef int8_t KaiI8;\ntypedef int16_t KaiI16;\ntypedef int32_t KaiI32;\ntypedef int64_t KaiI64;\n\ntypedef uint8_t KaiU8;\ntypedef uint16_t KaiU16;\ntypedef uint32_t KaiU32;\ntypedef uint64_t KaiU64;\n\ntypedef float KaiF32;\ntypedef double KaiF64;\n\ntypedef void * KaiRawptr;\n#endif\n"; void CodegenCHeader(Package *pkg) { char buff[MAX_PATH]; diff --git a/src/llvm.cpp b/src/llvm.cpp index 6abf079..97d813b 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -471,6 +471,13 @@ llvm::Value *emitExprCall(Context *ctx, Expr *expr) { return ctx->b.CreateCall(irFunc, args); } +llvm::Value *emitExprCast(Context *ctx, Expr *expr) { + ASSERT(expr->kind == ExprKind_Cast); + CheckerInfo_BasicExpr info = ctx->checkerInfo[expr->id].BasicExpr; + llvm::Value *value = emitExpr(ctx, expr->Cast.expr); + return ctx->b.CreateBitCast(value, canonicalize(ctx, info.type)); +} + llvm::Value *emitExprLitCompound(Context *ctx, Expr *expr) { ASSERT(expr->kind == ExprKind_LitCompound); CheckerInfo_BasicExpr info = ctx->checkerInfo[expr->id].BasicExpr; @@ -639,6 +646,11 @@ llvm::Value *emitExpr(Context *ctx, Expr *expr, llvm::Type *desiredType) { break; } + case ExprKind_Paren: { + value = emitExpr(ctx, expr->Paren.expr); + break; + } + case ExprKind_LitCompound: { value = emitExprLitCompound(ctx, expr); break; @@ -663,6 +675,10 @@ llvm::Value *emitExpr(Context *ctx, Expr *expr, llvm::Type *desiredType) { case ExprKind_Call: value = emitExprCall(ctx, expr); break; + + case ExprKind_Cast: + value = emitExprCast(ctx, expr); + break; } if (ctx->checkerInfo[expr->id].coerce != ConversionKind_None) { @@ -1755,12 +1771,12 @@ void setupTargetInfo() { static b32 init = false; if (init) return; - // TODO: If no target is specified we can get away with initializing just the native target. - llvm::InitializeAllTargetInfos(); - llvm::InitializeAllTargets(); - llvm::InitializeAllTargetMCs(); - llvm::InitializeAllAsmParsers(); - llvm::InitializeAllAsmPrinters(); + LLVMInitializeX86Target(); + LLVMInitializeX86TargetMC(); + LLVMInitializeX86TargetInfo(); + LLVMInitializeX86AsmParser(); + LLVMInitializeX86AsmPrinter(); + LLVMInitializeX86Disassembler(); init = true; } @@ -1963,8 +1979,31 @@ void printIR(llvm::Type *value) { puts("\n"); } -void printModule(llvm::Module *module) { - module->print(llvm::errs(), nullptr); +// MARK: Hacks for LLVM and libcurses. Sadly, LLVM uses libncurses to try to see +// if the terminal supports color. We're going to stub all of the ncurses functions +// and tell LLVM that color isn't supported +extern "C" { + int setupterm(char *term, int filedes, int *errret) { + return 1; // Tell LLVM that we've failed and it'll disable colors + } + + struct term *set_curterm(struct term *termp) { + ASSERT(false); + return NULL; + } + + int del_curterm(struct term *termp){ + ASSERT(false); + return 1; + } + + int tigetnum(char *capname){ + ASSERT(false); + return 0; + } } + + + #pragma clang diagnostic pop diff --git a/src/main.c b/src/main.c index 7b2f86f..524dc21 100644 --- a/src/main.c +++ b/src/main.c @@ -16,7 +16,6 @@ #define VERSION "0.0.0 (prerelease)" - void outputVersionAndBuildInfo() { printf("%s\n\n", VERSION); diff --git a/src/types.c b/src/types.c index a6f3e6a..24395df 100644 --- a/src/types.c +++ b/src/types.c @@ -417,7 +417,17 @@ const char *DescribeType(Type *type) { return type->Symbol->name; } - return DescribeTypeKind(type->kind); + switch (type->kind) { + case TypeKind_Pointer: { + String desc = NULL; + const char *pointeeType = DescribeType(type->Pointer.pointeeType); + ArrayPrintf(desc, "*%s", pointeeType); + return (char *)desc; + } + + default: + return DescribeTypeKind(type->kind); + } } #if TEST From c684b1e24c289be347bd5354561d75e8bd24bf0d Mon Sep 17 00:00:00 2001 From: "Brett R. Toomey" Date: Sun, 16 Sep 2018 16:42:51 +0200 Subject: [PATCH 5/8] Less deps --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index d93a650..4ccb3c2 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ else endif LLVM_CXXFLAGS = $(shell $(LLVM_CONFIG) --cxxflags) -LLVM_CXXLFLAGS = $(shell $(LLVM_CONFIG) --ldflags --link-static --system-libs --libs) +LLVM_CXXLFLAGS = $(shell $(LLVM_CONFIG) --ldflags --link-static) -lLLVMAsmParser -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMGlobalISel -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMDebugInfoCodeView -lLLVMDebugInfoMSF -lLLVMCodeGen -lLLVMTarget -lLLVMScalarOpts -lLLVMInstCombine -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis -lLLVMProfileData -lLLVMX86Desc -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMMCDisassembler -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMMC -lLLVMX86Utils -lLLVMCore -lLLVMBinaryFormat -lLLVMSupport -lLLVMDemangle -lz -lm LFLAGS = DISABLED_WARNINGS = -Wno-writable-strings -Wno-switch -Wno-c11-extensions -Wno-c99-extensions @@ -53,4 +53,4 @@ install: clean: rm -f $(TARGET) core.o llvm.o $(TEST_TARGET) $(TEST_LOG) $(TEST_MAIN) -.PHONY: all clean debug release tests +.PHONY: all clean debug release tests install From a8298c1e0a36bfd504853a81b0a5ac21d4bd5872 Mon Sep 17 00:00:00 2001 From: "Brett R. Toomey" Date: Sun, 16 Sep 2018 17:50:12 +0200 Subject: [PATCH 6/8] Pass along bool type --- src/llvm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm.cpp b/src/llvm.cpp index 02bbf30..0f72db9 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -1534,7 +1534,7 @@ void emitStmtFor(Context *ctx, Stmt *stmt) { ctx->b.CreateBr(cond); ctx->b.SetInsertPoint(cond); - llvm::Value *condVal = emitExpr(ctx, fore.cond); + llvm::Value *condVal = emitExpr(ctx, fore.cond, canonicalize(ctx, BoolType)); condVal = ctx->b.CreateTruncOrBitCast(condVal, llvm::IntegerType::get(ctx->m->getContext(), 1)); ctx->b.CreateCondBr(condVal, body, post); } else { From 42943bf3491a4f9660a6870db00a93b34fcc7d7a Mon Sep 17 00:00:00 2001 From: "Brett R. Toomey" Date: Sun, 16 Sep 2018 20:58:19 +0200 Subject: [PATCH 7/8] Fixed lookup on declare. Fixed pointer subscript --- src/checker.c | 10 +++++++--- src/checker.h | 1 + src/llvm.cpp | 5 ++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/checker.c b/src/checker.c index 245b2ae..93efd85 100644 --- a/src/checker.c +++ b/src/checker.c @@ -167,7 +167,7 @@ CheckerInfo *CheckerInfoForDecl(Package *pkg, Decl *decl) { } b32 declareSymbol(Package *pkg, Scope *scope, const char *name, Symbol **symbol, Decl *decl) { - Symbol *old = Lookup(scope, name); + Symbol *old = LookupNoRecurse(scope, name); if (old) { ReportError(pkg, RedefinitionError, decl->start, "Duplicate definition of symbol %s", name); ReportNote(pkg, old->decl->start, "Previous definition of %s", name); @@ -664,6 +664,10 @@ Symbol *Lookup(Scope *scope, const char *name) { return NULL; } +Symbol *LookupNoRecurse(Scope *scope, const char *name) { + return MapGet(&scope->members, name); +} + Type *TypeFromCheckerInfo(CheckerInfo info) { switch (info.kind) { case CheckerInfoKind_BasicExpr: @@ -963,7 +967,7 @@ Type *checkExprTypeFunction(Expr *expr, CheckerContext *ctx, Package *pkg) { DynamicArray(Type *) params = NULL; ArrayFit(params, ArrayLen(func.params)); - CheckerContext paramCtx = { pushScope(pkg, ctx->scope) }; + CheckerContext paramCtx = { .scope = pushScope(pkg, ctx->scope) }; For (func.params) { Type *type = checkExpr(func.params[i]->value, ¶mCtx, pkg); if (paramCtx.mode == ExprMode_Invalid) goto error; @@ -1064,7 +1068,7 @@ Type *checkExprLitFunction(Expr *expr, CheckerContext *ctx, Package *pkg) { tuple = NewTypeTuple(TypeFlag_None, resultTypes); } - CheckerContext bodyCtx = { bodyScope, .desiredType = tuple }; + CheckerContext bodyCtx = { .scope = bodyScope, .desiredType = tuple }; ForEach(func.body->stmts, Stmt *) { checkStmt(it, &bodyCtx, pkg); if (bodyCtx.mode == ExprMode_Unresolved) goto unresolved; diff --git a/src/checker.h b/src/checker.h index 8e2a323..0b0c7f1 100644 --- a/src/checker.h +++ b/src/checker.h @@ -161,6 +161,7 @@ struct CheckerInfo { extern "C" { #endif Symbol *Lookup(Scope *scope, const char *name); +Symbol *LookupNoRecurse(Scope *scope, const char *name); Type *TypeFromCheckerInfo(CheckerInfo info); b32 IsInteger(Type *type); b32 IsSigned(Type *type); diff --git a/src/llvm.cpp b/src/llvm.cpp index 0f72db9..68c8d35 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -871,7 +871,10 @@ llvm::Value *emitExprSubscript(Context *ctx, Expr *expr) { } break; case TypeKind_Pointer: { + bool previousReturnAddress = ctx->returnAddress; + ctx->returnAddress = false; aggregate = emitExpr(ctx, expr->Subscript.expr); + ctx->returnAddress = previousReturnAddress; indicies.push_back(index); resultType = TypeFromCheckerInfo(recvInfo)->Pointer.pointeeType; } break; @@ -885,7 +888,7 @@ llvm::Value *emitExprSubscript(Context *ctx, Expr *expr) { if (ctx->returnAddress) { return val; } - + return ctx->b.CreateAlignedLoad(val, BytesFromBits(resultType->Align)); } From 0d0f2d72efeeff2edaa76b90ef6e026d2007b283 Mon Sep 17 00:00:00 2001 From: "Brett R. Toomey" Date: Sun, 16 Sep 2018 21:04:36 +0200 Subject: [PATCH 8/8] Don't return address on subscript index --- src/llvm.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/llvm.cpp b/src/llvm.cpp index 68c8d35..304306c 100644 --- a/src/llvm.cpp +++ b/src/llvm.cpp @@ -836,7 +836,11 @@ llvm::Value *emitExprSubscript(Context *ctx, Expr *expr) { std::vector indicies; + bool prevReturn = ctx->returnAddress; + ctx->returnAddress = false; llvm::Value *index = emitExpr(ctx, expr->Subscript.index); + ctx->returnAddress = prevReturn; + Type *indexType = TypeFromCheckerInfo(indexInfo); // NOTE: LLVM doesn't have unsigned integers and an index in the upper-half