From c7c97ad4bb62b83efd6e26cdd4f38ebf164ec40e Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Thu, 8 Feb 2018 14:46:12 -0800 Subject: Basic IR support for `static const` globals (#404) * Basic IR support for `static const` globals Our strategy for lowering global *variables* can fall back to putting their initialization into a function, but that isn't really appropriate for global constants (it also isn't appropriate for arrays, but we'll need to deal with that seaprately). This change adds a distinct case for global constants (rather than treating them as variables), and forces the emission logic to always emit them as a single expression. Doing this makes assumptions about how the IR for these constants gets emitted (and what optimziations might do to it). In order to make things work, I had to switch the handling of initializer-list expressions to not be lowered via temporaries and mutation (since that isn't a good fit for reverting to a single expression). I've added a single test case to ensure that this works in the simplest scenario. My next priority will be to see if this unblocks my work in Falcor. * Fixup: bug fixes --- source/slang/lower-to-ir.cpp | 60 +++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 31 deletions(-) (limited to 'source/slang/lower-to-ir.cpp') diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 5c6f62c38..53cb2e772 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -1295,7 +1295,7 @@ struct ExprLoweringVisitorBase : ExprVisitor { // Allocate a temporary of the given type RefPtr type = lowerSimpleType(context, expr->type); - LoweredValInfo val = createVar(context, type); + List args; UInt argCount = expr->args.Count(); @@ -1305,28 +1305,23 @@ struct ExprLoweringVisitorBase : ExprVisitor { UInt elementCount = (UInt) GetIntVal(arrayType->ArrayLength); auto elementType = lowerType(context, arrayType->baseType); + for (UInt ee = 0; ee < elementCount; ++ee) { - IRValue* indexVal = context->irBuilder->getIntValue( - getIntType(context), - ee); - LoweredValInfo elemVal = subscriptValue( - elementType, - val, - indexVal); - if (ee < argCount) { auto argExpr = expr->args[ee]; LoweredValInfo argVal = lowerRValueExpr(context, argExpr); - - assign(context, elemVal, argVal); + args.Add(getSimpleVal(context, argVal)); } else { SLANG_UNEXPECTED("need to default-initialize array elements"); } } + + return LoweredValInfo::simple( + getBuilder()->emitMakeArray(type, args.Count(), args.Buffer())); } else if (auto vectorType = type->As()) { @@ -1335,7 +1330,6 @@ struct ExprLoweringVisitorBase : ExprVisitor UInt elementCount = (UInt) GetIntVal(vectorType->elementCount); UInt argCounter = 0; - List elements; for (UInt ee = 0; ee < elementCount; ++ee) { UInt argIndex = argCounter++; @@ -1343,8 +1337,7 @@ struct ExprLoweringVisitorBase : ExprVisitor { auto argExpr = expr->args[argIndex]; LoweredValInfo argVal = lowerRValueExpr(context, argExpr); - - elements.Add(getSimpleVal(context, argVal)); + args.Add(getSimpleVal(context, argVal)); } else { @@ -1352,10 +1345,8 @@ struct ExprLoweringVisitorBase : ExprVisitor } } - assign(context, val, LoweredValInfo::simple(getBuilder()->emitConstructorInst( - lowerSimpleType(context, vectorType), - elementCount, - elements.Buffer()))); + return LoweredValInfo::simple( + getBuilder()->emitMakeVector(type, args.Count(), args.Buffer())); } else if (auto declRefType = type->As()) { @@ -1368,26 +1359,21 @@ struct ExprLoweringVisitorBase : ExprVisitor if (ff.getDecl()->HasModifier()) continue; - auto loweredFieldType = lowerType( - context, - GetType(ff)); - LoweredValInfo fieldVal = extractField( - loweredFieldType, - val, - ff); - UInt argIndex = argCounter++; if (argIndex < argCount) { auto argExpr = expr->args[argIndex]; LoweredValInfo argVal = lowerRValueExpr(context, argExpr); - assign(context, fieldVal, argVal); + args.Add(getSimpleVal(context, argVal)); } else { SLANG_UNEXPECTED("need to default-initialize struct fields"); } } + + return LoweredValInfo::simple( + getBuilder()->emitMakeStruct(type, args.Count(), args.Buffer())); } else { @@ -1399,8 +1385,7 @@ struct ExprLoweringVisitorBase : ExprVisitor SLANG_UNEXPECTED("not sure how to initialize this type"); } - - return val; + UNREACHABLE_RETURN(LoweredValInfo()); } LoweredValInfo visitConstantExpr(ConstantExpr* expr) @@ -2997,7 +2982,21 @@ struct DeclLoweringVisitor : DeclVisitor // to a variable over to its type, when it makes sense. auto builder = getBuilder(); - auto irGlobal = builder->createGlobalVar(varType); + + IRGlobalValueWithCode* irGlobal = nullptr; + LoweredValInfo globalVal; + + // a `static const` global is actually a compile-time constant + if (decl->HasModifier() && decl->HasModifier()) + { + irGlobal = builder->createGlobalConstant(varType); + globalVal = LoweredValInfo::simple(irGlobal); + } + else + { + irGlobal = builder->createGlobalVar(varType); + globalVal = LoweredValInfo::ptr(irGlobal); + } irGlobal->mangledName = getMangledName(decl); if (decl) @@ -3007,7 +3006,6 @@ struct DeclLoweringVisitor : DeclVisitor // A global variable's SSA value is a *pointer* to // the underlying storage. - auto globalVal = LoweredValInfo::ptr(irGlobal); context->shared->declValues[ DeclRef(decl, nullptr)] = globalVal; -- cgit v1.2.3