No flags found
Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.
e.g., #unittest #integration
#production #enterprise
#frontend #backend
873921b
... +15 ...
fe4b650
Use flags to group coverage reports by test type, project and/or folders.
Then setup custom commit statuses and notifications for each flag.
e.g., #unittest #integration
#production #enterprise
#frontend #backend
3140 | 3140 | { |
|
3141 | 3141 | getregs(cdb,retregs); |
|
3142 | 3142 | genregs(cdb,0x19,reg,reg); // SBB reg,reg |
|
3143 | - | if (rex) |
|
3144 | - | code_orrex(cdb.last(), rex); |
|
3143 | + | if (rex || flag & REX_W) |
|
3144 | + | code_orrex(cdb.last(), REX_W); |
|
3145 | 3145 | if (flag) |
|
3146 | 3146 | { } // cdcond() will handle it |
|
3147 | 3147 | else if (jop == JNC) |
1 | 1 | /** |
|
2 | - | * Compiler implementation of the |
|
3 | - | * $(LINK2 http://www.dlang.org, D programming language). |
|
2 | + | * Top level code for the code generator. |
|
4 | 3 | * |
|
5 | 4 | * Copyright: Copyright (C) 1985-1998 by Symantec |
|
6 | 5 | * Copyright (C) 2000-2020 by The D Language Foundation, All Rights Reserved |
|
7 | 6 | * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) |
|
8 | 7 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) |
|
9 | 8 | * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/cgcod.d, backend/cgcod.d) |
|
9 | + | * Documentation: https://dlang.org/phobos/dmd_backend_cgcod.html |
|
10 | 10 | * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/backend/cgcod.d |
|
11 | 11 | */ |
|
12 | 12 |
754 | 754 | bool pushalloc = false; |
|
755 | 755 | tym_t tyf = funcsym_p.ty(); |
|
756 | 756 | tym_t tym = tybasic(tyf); |
|
757 | - | uint farfunc = tyfarfunc(tym); |
|
757 | + | const farfunc = tyfarfunc(tym) != 0; |
|
758 | 758 | ||
759 | 759 | // Special Intel 64 bit ABI prolog setup for variadic functions |
|
760 | 760 | Symbol *sv64 = null; // set to __va_argsave |
1051 | 1051 | } |
|
1052 | 1052 | else if (needframe) // if variables or parameters |
|
1053 | 1053 | { |
|
1054 | - | prolog_frame(cdbx, farfunc, &xlocalsize, &enter, &cfa_offset); |
|
1054 | + | prolog_frame(cdbx, farfunc, xlocalsize, enter, cfa_offset); |
|
1055 | 1055 | hasframe = 1; |
|
1056 | 1056 | } |
|
1057 | 1057 |
1135 | 1135 | } |
|
1136 | 1136 | ||
1137 | 1137 | uint regsaved; |
|
1138 | - | prolog_trace(cdbx, farfunc != 0, ®saved); |
|
1138 | + | prolog_trace(cdbx, farfunc, ®saved); |
|
1139 | 1139 | ||
1140 | 1140 | if (spalign) |
|
1141 | 1141 | cod3_stackadj(cdbx, -spalign); |
7 | 7 | * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) |
|
8 | 8 | * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) |
|
9 | 9 | * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/cod3.d, backend/cod3.d) |
|
10 | + | * Documentation: https://dlang.org/phobos/dmd_backend_cod3.html |
|
10 | 11 | * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/backend/cod3.d |
|
11 | 12 | */ |
|
12 | 13 |
3177 | 3178 | ||
3178 | 3179 | /********************************************** |
|
3179 | 3180 | * Set up frame register. |
|
3180 | - | * Input: |
|
3181 | - | * *xlocalsize amount of local variables |
|
3182 | - | * Output: |
|
3183 | - | * *enter set to true if ENTER instruction can be used, false otherwise |
|
3184 | - | * *xlocalsize amount to be subtracted from stack pointer |
|
3185 | - | * *cfa_offset the frame pointer's offset from the CFA |
|
3181 | + | * Params: |
|
3182 | + | * cdb = write generated code here |
|
3183 | + | * farfunc = true if a far function |
|
3184 | + | * enter = set to true if ENTER instruction can be used, false otherwise |
|
3185 | + | * xlocalsize = amount of local variables, set to amount to be subtracted from stack pointer |
|
3186 | + | * cfa_offset = set to frame pointer's offset from the CFA |
|
3186 | 3187 | * Returns: |
|
3187 | 3188 | * generated code |
|
3188 | 3189 | */ |
|
3189 | - | ||
3190 | - | void prolog_frame(ref CodeBuilder cdb, uint farfunc, uint* xlocalsize, bool* enter, int* cfa_offset) |
|
3190 | + | void prolog_frame(ref CodeBuilder cdb, bool farfunc, ref uint xlocalsize, out bool enter, out int cfa_offset) |
|
3191 | 3191 | { |
|
3192 | 3192 | //printf("prolog_frame\n"); |
|
3193 | - | *cfa_offset = 0; |
|
3193 | + | cfa_offset = 0; |
|
3194 | 3194 | ||
3195 | 3195 | if (0 && config.exe == EX_WIN64) |
|
3196 | 3196 | { |
|
3197 | 3197 | // PUSH RBP |
|
3198 | 3198 | // LEA RBP,0[RSP] |
|
3199 | 3199 | cdb. gen1(0x50 + BP); |
|
3200 | 3200 | cdb.genc1(LEA,(REX_W<<16) | (modregrm(0,4,SP)<<8) | modregrm(2,BP,4),FLconst,0); |
|
3201 | - | *enter = false; |
|
3201 | + | enter = false; |
|
3202 | 3202 | return; |
|
3203 | 3203 | } |
|
3204 | 3204 |
3208 | 3208 | config.exe & (EX_LINUX | EX_LINUX64 | EX_OSX | EX_OSX64 | EX_FREEBSD | EX_FREEBSD64 | EX_DRAGONFLYBSD64 | EX_SOLARIS | EX_SOLARIS64 | EX_WIN64) || |
|
3209 | 3209 | !localsize || |
|
3210 | 3210 | config.flags & CFGstack || |
|
3211 | - | (*xlocalsize >= 0x1000 && config.exe & EX_flat) || |
|
3211 | + | (xlocalsize >= 0x1000 && config.exe & EX_flat) || |
|
3212 | 3212 | localsize >= 0x10000 || |
|
3213 | 3213 | (NTEXCEPTIONS == 2 && |
|
3214 | 3214 | (usednteh & (NTEH_try | NTEH_except | NTEHcpp | EHcleanup | EHtry | NTEHpassthru) && (config.ehmethod == EHmethod.EH_WIN32 && !(funcsym_p.Sfunc.Fflags3 & Feh_none) || config.ehmethod == EHmethod.EH_SEH))) || |
3230 | 3230 | nteh_prolog(cdb); |
|
3231 | 3231 | int sz = nteh_contextsym_size(); |
|
3232 | 3232 | assert(sz != 0); // should be 5*4, not 0 |
|
3233 | - | *xlocalsize -= sz; // sz is already subtracted from ESP |
|
3233 | + | xlocalsize -= sz; // sz is already subtracted from ESP |
|
3234 | 3234 | // by nteh_prolog() |
|
3235 | 3235 | } |
|
3236 | 3236 | } |
3246 | 3246 | * which is why the offset of BP is set to 8 |
|
3247 | 3247 | */ |
|
3248 | 3248 | dwarf_CFA_set_reg_offset(BP, off); // CFA is now 0[EBP] |
|
3249 | - | *cfa_offset = off; // remember the difference between the CFA and the frame pointer |
|
3249 | + | cfa_offset = off; // remember the difference between the CFA and the frame pointer |
|
3250 | 3250 | } |
|
3251 | - | *enter = false; /* do not use ENTER instruction */ |
|
3251 | + | enter = false; /* do not use ENTER instruction */ |
|
3252 | 3252 | } |
|
3253 | 3253 | else |
|
3254 | - | *enter = true; |
|
3254 | + | enter = true; |
|
3255 | 3255 | } |
|
3256 | 3256 | ||
3257 | 3257 | /********************************************** |
3328 | 3328 | { |
|
3329 | 3329 | if (enter) |
|
3330 | 3330 | { // ENTER xlocalsize,0 |
|
3331 | - | cdb.genc(0xC8,0,FLconst,xlocalsize,FLconst,cast(targ_uns) 0); |
|
3331 | + | cdb.genc(ENTER,0,FLconst,xlocalsize,FLconst,cast(targ_uns) 0); |
|
3332 | 3332 | assert(!(config.fulltypes == CVDWARF_C || config.fulltypes == CVDWARF_D)); // didn't emit Dwarf data |
|
3333 | 3333 | } |
|
3334 | 3334 | else if (xlocalsize == REGSIZE && config.flags4 & CFG4optimized) |
4232 | 4232 | else if (config.target_cpu >= TARGET_80286 && |
|
4233 | 4233 | !(config.target_cpu >= TARGET_80386 && config.flags4 & CFG4speed) |
|
4234 | 4234 | ) |
|
4235 | - | cdbx.gen1(0xC9); // LEAVE |
|
4235 | + | cdbx.gen1(LEAVE); // LEAVE |
|
4236 | 4236 | else if (0 && xlocalsize == REGSIZE && Alloca.size == 0 && I32) |
|
4237 | 4237 | { // This doesn't work - I should figure out why |
|
4238 | 4238 | mfuncreg &= ~mask(regx); |
4310 | 4310 | if (cr.Iop == 0x81 && cr.Irm == modregrm(3,0,SP)) // if ADD SP,imm |
|
4311 | 4311 | { |
|
4312 | 4312 | if ( |
|
4313 | - | c.Iop == 0xC9 || // LEAVE |
|
4313 | + | c.Iop == LEAVE || // LEAVE |
|
4314 | 4314 | (c.Iop == 0x8B && c.Irm == modregrm(3,SP,BP)) || // MOV SP,BP |
|
4315 | 4315 | (c.Iop == LEA && c.Irm == modregrm(1,SP,6)) // LEA SP,-imm[BP] |
|
4316 | 4316 | ) |
6822 | 6822 | } |
|
6823 | 6823 | else |
|
6824 | 6824 | { |
|
6825 | - | if (op == 0xC8) |
|
6825 | + | if (op == ENTER) |
|
6826 | 6826 | do16bit(&ggen, cast(FL)c.IFL1,&c.IEV1,0); |
|
6827 | 6827 | } |
|
6828 | 6828 | flags &= CFseg | CFoff | CFselfrel; |
2293 | 2293 | regm_t psw = *pretregs & mPSW; /* save PSW bit */ |
|
2294 | 2294 | const op1 = e1.Eoper; |
|
2295 | 2295 | uint sz1 = tysize(e1.Ety); |
|
2296 | - | uint rex = (I64 && sz1 == 8) ? REX_W : 0; |
|
2297 | - | uint grex = rex << 16; |
|
2298 | 2296 | uint jop = jmpopcode(e1); |
|
2299 | 2297 | ||
2300 | 2298 | uint jop1 = jmpopcode(e21); |
2341 | 2339 | e22.Eoper == OPconst |
|
2342 | 2340 | ) |
|
2343 | 2341 | { |
|
2342 | + | uint sz = tysize(e.Ety); |
|
2343 | + | uint rex = (I64 && sz == 8) ? REX_W : 0; |
|
2344 | + | uint grex = rex << 16; |
|
2345 | + | ||
2344 | 2346 | regm_t retregs; |
|
2345 | 2347 | targ_size_t v1,v2; |
|
2346 | 2348 |
2357 | 2359 | retregs = BYTEREGS; |
|
2358 | 2360 | } |
|
2359 | 2361 | ||
2360 | - | cdcmp_flag = 1; |
|
2362 | + | cdcmp_flag = 1 | rex; |
|
2361 | 2363 | v1 = cast(targ_size_t)e21.EV.Vllong; |
|
2362 | 2364 | v2 = cast(targ_size_t)e22.EV.Vllong; |
|
2363 | 2365 | if (jop == JNC) |
214 | 214 | ||
215 | 215 | __gshared CtfeGlobals ctfeGlobals; |
|
216 | 216 | ||
217 | - | enum CtfeGoal : int |
|
217 | + | enum CTFEGoal : int |
|
218 | 218 | { |
|
219 | - | ctfeNeedRvalue, // Must return an Rvalue (== CTFE value) |
|
220 | - | ctfeNeedLvalue, // Must return an Lvalue (== CTFE reference) |
|
221 | - | ctfeNeedNothing, // The return value is not required |
|
219 | + | RValue, /// Must return an Rvalue (== CTFE value) |
|
220 | + | LValue, /// Must return an Lvalue (== CTFE reference) |
|
221 | + | Nothing, /// The return value is not required |
|
222 | 222 | } |
|
223 | 223 | ||
224 | - | alias ctfeNeedRvalue = CtfeGoal.ctfeNeedRvalue; |
|
225 | - | alias ctfeNeedLvalue = CtfeGoal.ctfeNeedLvalue; |
|
226 | - | alias ctfeNeedNothing = CtfeGoal.ctfeNeedNothing; |
|
227 | - | ||
228 | 224 | //debug = LOG; |
|
229 | 225 | //debug = LOGASSIGN; |
|
230 | 226 | //debug = LOGCOMPILE; |
471 | 467 | return CTFEExp.cantexp; |
|
472 | 468 | } |
|
473 | 469 | // Convert all reference arguments into lvalue references |
|
474 | - | earg = interpretRegion(earg, istate, ctfeNeedLvalue); |
|
470 | + | earg = interpretRegion(earg, istate, CTFEGoal.LValue); |
|
475 | 471 | if (CTFEExp.isCantExp(earg)) |
|
476 | 472 | return earg; |
|
477 | 473 | } |
551 | 547 | VarDeclaration v = (*fd.parameters)[i]; |
|
552 | 548 | debug (LOG) |
|
553 | 549 | { |
|
554 | - | printf("arg[%d] = %s\n", i, earg.toChars()); |
|
550 | + | printf("arg[%zu] = %s\n", i, earg.toChars()); |
|
555 | 551 | } |
|
556 | 552 | ctfeGlobals.stack.push(v); |
|
557 | 553 |
595 | 591 | } |
|
596 | 592 | debug (LOG) |
|
597 | 593 | { |
|
598 | - | printf("interpreted arg[%d] = %s\n", i, earg.toChars()); |
|
594 | + | printf("interpreted arg[%zu] = %s\n", i, earg.toChars()); |
|
599 | 595 | showCtfeExpr(earg); |
|
600 | 596 | } |
|
601 | 597 | debug (LOGASSIGN) |
|
602 | 598 | { |
|
603 | - | printf("interpreted arg[%d] = %s\n", i, earg.toChars()); |
|
599 | + | printf("interpreted arg[%zu] = %s\n", i, earg.toChars()); |
|
604 | 600 | showCtfeExpr(earg); |
|
605 | 601 | } |
|
606 | 602 | } |
715 | 711 | alias visit = Visitor.visit; |
|
716 | 712 | public: |
|
717 | 713 | InterState* istate; |
|
718 | - | CtfeGoal goal; |
|
714 | + | CTFEGoal goal; |
|
719 | 715 | Expression result; |
|
720 | 716 | UnionExp* pue; // storage for `result` |
|
721 | 717 | ||
722 | - | extern (D) this(UnionExp* pue, InterState* istate, CtfeGoal goal) |
|
718 | + | extern (D) this(UnionExp* pue, InterState* istate, CTFEGoal goal) |
|
723 | 719 | { |
|
724 | 720 | this.pue = pue; |
|
725 | 721 | this.istate = istate; |
786 | 782 | if (s.exp && s.exp.hasCode) |
|
787 | 783 | incUsageCtfe(istate, s.loc); |
|
788 | 784 | ||
789 | - | Expression e = interpret(pue, s.exp, istate, ctfeNeedNothing); |
|
785 | + | Expression e = interpret(pue, s.exp, istate, CTFEGoal.Nothing); |
|
790 | 786 | if (exceptionOrCant(e)) |
|
791 | 787 | return; |
|
792 | 788 | } |
1004 | 1000 | */ |
|
1005 | 1001 | if (tf.isref) |
|
1006 | 1002 | { |
|
1007 | - | result = interpret(pue, s.exp, istate, ctfeNeedLvalue); |
|
1003 | + | result = interpret(pue, s.exp, istate, CTFEGoal.LValue); |
|
1008 | 1004 | return; |
|
1009 | 1005 | } |
|
1010 | 1006 | if (tf.next && tf.next.ty == Tdelegate && istate.fd.closureVars.dim > 0) |
1223 | 1219 | UnionExp uei = void; |
|
1224 | 1220 | if (s.increment) |
|
1225 | 1221 | incUsageCtfe(istate, s.increment.loc); |
|
1226 | - | e = interpret(&uei, s.increment, istate, ctfeNeedNothing); |
|
1222 | + | e = interpret(&uei, s.increment, istate, CTFEGoal.Nothing); |
|
1227 | 1223 | if (exceptionOrCant(e)) |
|
1228 | 1224 | return; |
|
1229 | 1225 | } |
1723 | 1719 | { |
|
1724 | 1720 | printf("%s ThisExp::interpret() %s\n", e.loc.toChars(), e.toChars()); |
|
1725 | 1721 | } |
|
1726 | - | if (goal == ctfeNeedLvalue) |
|
1722 | + | if (goal == CTFEGoal.LValue) |
|
1727 | 1723 | { |
|
1728 | 1724 | // We might end up here with istate being zero |
|
1729 | 1725 | // https://issues.dlang.org/show_bug.cgi?id=16382 |
1972 | 1968 | return; |
|
1973 | 1969 | } |
|
1974 | 1970 | } |
|
1975 | - | auto er = interpret(e.e1, istate, ctfeNeedLvalue); |
|
1971 | + | auto er = interpret(e.e1, istate, CTFEGoal.LValue); |
|
1976 | 1972 | if (auto ve = er.isVarExp()) |
|
1977 | 1973 | if (ve.var == istate.fd.vthis) |
|
1978 | 1974 | er = interpret(er, istate); |
2020 | 2016 | } |
|
2021 | 2017 | } |
|
2022 | 2018 | ||
2023 | - | static Expression getVarExp(const ref Loc loc, InterState* istate, Declaration d, CtfeGoal goal) |
|
2019 | + | static Expression getVarExp(const ref Loc loc, InterState* istate, Declaration d, CTFEGoal goal) |
|
2024 | 2020 | { |
|
2025 | 2021 | Expression e = CTFEExp.cantexp; |
|
2026 | 2022 | if (VarDeclaration v = d.isVarDeclaration()) |
2128 | 2124 | errorSupplemental(vie.var.loc, "`%s` was uninitialized and used before set", vie.var.toChars()); |
|
2129 | 2125 | return CTFEExp.cantexp; |
|
2130 | 2126 | } |
|
2131 | - | if (goal != ctfeNeedLvalue && (v.isRef() || v.isOut())) |
|
2127 | + | if (goal != CTFEGoal.LValue && (v.isRef() || v.isOut())) |
|
2132 | 2128 | e = interpret(e, istate, goal); |
|
2133 | 2129 | } |
|
2134 | 2130 | if (!e) |
2163 | 2159 | return; |
|
2164 | 2160 | } |
|
2165 | 2161 | ||
2166 | - | if (goal == ctfeNeedLvalue) |
|
2162 | + | if (goal == CTFEGoal.LValue) |
|
2167 | 2163 | { |
|
2168 | - | VarDeclaration v = e.var.isVarDeclaration(); |
|
2169 | - | if (v && !v.isDataseg() && !v.isCTFE() && !istate) |
|
2170 | - | { |
|
2171 | - | e.error("variable `%s` cannot be read at compile time", v.toChars()); |
|
2172 | - | result = CTFEExp.cantexp; |
|
2173 | - | return; |
|
2174 | - | } |
|
2175 | - | if (v && !hasValue(v)) |
|
2164 | + | if (auto v = e.var.isVarDeclaration()) |
|
2176 | 2165 | { |
|
2177 | - | if (!v.isCTFE() && v.isDataseg()) |
|
2178 | - | e.error("static variable `%s` cannot be read at compile time", v.toChars()); |
|
2179 | - | else // CTFE initiated from inside a function |
|
2166 | + | if (!v.isDataseg() && !v.isCTFE() && !istate) |
|
2167 | + | { |
|
2180 | 2168 | e.error("variable `%s` cannot be read at compile time", v.toChars()); |
|
2181 | - | result = CTFEExp.cantexp; |
|
2182 | - | return; |
|
2183 | - | } |
|
2184 | - | ||
2185 | - | if (v && (v.storage_class & (STC.out_ | STC.ref_)) && hasValue(v)) |
|
2186 | - | { |
|
2187 | - | // Strip off the nest of ref variables |
|
2188 | - | Expression ev = getValue(v); |
|
2189 | - | if (ev.op == TOK.variable || |
|
2190 | - | ev.op == TOK.index || |
|
2191 | - | ev.op == TOK.slice || |
|
2192 | - | ev.op == TOK.dotVariable) |
|
2169 | + | result = CTFEExp.cantexp; |
|
2170 | + | return; |
|
2171 | + | } |
|
2172 | + | if (!hasValue(v)) |
|
2193 | 2173 | { |
|
2194 | - | result = interpret(pue, ev, istate, goal); |
|
2174 | + | if (!v.isCTFE() && v.isDataseg()) |
|
2175 | + | e.error("static variable `%s` cannot be read at compile time", v.toChars()); |
|
2176 | + | else // CTFE initiated from inside a function |
|
2177 | + | e.error("variable `%s` cannot be read at compile time", v.toChars()); |
|
2178 | + | result = CTFEExp.cantexp; |
|
2195 | 2179 | return; |
|
2196 | 2180 | } |
|
2181 | + | ||
2182 | + | if (v.storage_class & (STC.out_ | STC.ref_)) |
|
2183 | + | { |
|
2184 | + | // Strip off the nest of ref variables |
|
2185 | + | Expression ev = getValue(v); |
|
2186 | + | if (ev.op == TOK.variable || |
|
2187 | + | ev.op == TOK.index || |
|
2188 | + | ev.op == TOK.slice || |
|
2189 | + | ev.op == TOK.dotVariable) |
|
2190 | + | { |
|
2191 | + | result = interpret(pue, ev, istate, goal); |
|
2192 | + | return; |
|
2193 | + | } |
|
2194 | + | } |
|
2197 | 2195 | } |
|
2198 | 2196 | result = e; |
|
2199 | 2197 | return; |
2380 | 2378 | { |
|
2381 | 2379 | printf("%s TupleExp::interpret() %s\n", e.loc.toChars(), e.toChars()); |
|
2382 | 2380 | } |
|
2383 | - | if (exceptionOrCant(interpretRegion(e.e0, istate, ctfeNeedNothing))) |
|
2381 | + | if (exceptionOrCant(interpretRegion(e.e0, istate, CTFEGoal.Nothing))) |
|
2384 | 2382 | return; |
|
2385 | 2383 | ||
2386 | 2384 | auto expsx = e.exps; |
2391 | 2389 | return; |
|
2392 | 2390 | ||
2393 | 2391 | // A tuple of assignments can contain void (Bug 5676). |
|
2394 | - | if (goal == ctfeNeedNothing) |
|
2392 | + | if (goal == CTFEGoal.Nothing) |
|
2395 | 2393 | continue; |
|
2396 | 2394 | if (ex.op == TOK.voidExpression) |
|
2397 | 2395 | { |
2732 | 2730 | return; |
|
2733 | 2731 | } |
|
2734 | 2732 | ||
2735 | - | Expression epre = interpret(pue, e.argprefix, istate, ctfeNeedNothing); |
|
2733 | + | Expression epre = interpret(pue, e.argprefix, istate, CTFEGoal.Nothing); |
|
2736 | 2734 | if (exceptionOrCant(epre)) |
|
2737 | 2735 | return; |
|
2738 | 2736 |
3255 | 3253 | { |
|
3256 | 3254 | assert(!fp); |
|
3257 | 3255 | ||
3258 | - | Expression newval = interpretRegion(e.e2, istate, ctfeNeedLvalue); |
|
3256 | + | Expression newval = interpretRegion(e.e2, istate, CTFEGoal.LValue); |
|
3259 | 3257 | if (exceptionOrCant(newval)) |
|
3260 | 3258 | return; |
|
3261 | 3259 |
3264 | 3262 | ||
3265 | 3263 | // Get the value to return. Note that 'newval' is an Lvalue, |
|
3266 | 3264 | // so if we need an Rvalue, we have to interpret again. |
|
3267 | - | if (goal == ctfeNeedRvalue) |
|
3265 | + | if (goal == CTFEGoal.RValue) |
|
3268 | 3266 | result = interpretRegion(newval, istate); |
|
3269 | 3267 | else |
|
3270 | 3268 | result = e1; // VarExp is a CTFE reference |
3399 | 3397 | } |
|
3400 | 3398 | ||
3401 | 3399 | // We must set to aggregate with newaae |
|
3402 | - | e1 = interpretRegion(e1, istate, ctfeNeedLvalue); |
|
3400 | + | e1 = interpretRegion(e1, istate, CTFEGoal.LValue); |
|
3403 | 3401 | if (exceptionOrCant(e1)) |
|
3404 | 3402 | return; |
|
3405 | 3403 | e1 = assignToLvalue(e, e1, newaae); |
3441 | 3439 | else |
|
3442 | 3440 | { |
|
3443 | 3441 | L1: |
|
3444 | - | e1 = interpretRegion(e1, istate, ctfeNeedLvalue); |
|
3442 | + | e1 = interpretRegion(e1, istate, CTFEGoal.LValue); |
|
3445 | 3443 | if (exceptionOrCant(e1)) |
|
3446 | 3444 | return; |
|
3447 | 3445 |
3587 | 3585 | result = CTFEExp.cantexp; |
|
3588 | 3586 | return; |
|
3589 | 3587 | } |
|
3590 | - | e1 = interpretRegion(e1, istate, ctfeNeedLvalue); |
|
3588 | + | e1 = interpretRegion(e1, istate, CTFEGoal.LValue); |
|
3591 | 3589 | if (exceptionOrCant(e1)) |
|
3592 | 3590 | return; |
|
3593 | 3591 |
3614 | 3612 | newval = pue.copy(); |
|
3615 | 3613 | ||
3616 | 3614 | // Determine the return value |
|
3617 | - | if (goal == ctfeNeedLvalue) // https://issues.dlang.org/show_bug.cgi?id=14371 |
|
3615 | + | if (goal == CTFEGoal.LValue) // https://issues.dlang.org/show_bug.cgi?id=14371 |
|
3618 | 3616 | result = e1; |
|
3619 | 3617 | else |
|
3620 | 3618 | { |
3649 | 3647 | return; |
|
3650 | 3648 | if (auto se = e.e1.isSliceExp()) |
|
3651 | 3649 | { |
|
3652 | - | Expression e1x = interpretRegion(se.e1, istate, ctfeNeedLvalue); |
|
3650 | + | Expression e1x = interpretRegion(se.e1, istate, CTFEGoal.LValue); |
|
3653 | 3651 | if (auto dve = e1x.isDotVarExp()) |
|
3654 | 3652 | { |
|
3655 | 3653 | auto ex = dve.e1; |
3872 | 3870 | * |
|
3873 | 3871 | * Returns TOK.cantExpression on failure. If there are no errors, |
|
3874 | 3872 | * it returns aggregate[low..upp], except that as an optimisation, |
|
3875 | - | * if goal == ctfeNeedNothing, it will return NULL |
|
3873 | + | * if goal == CTFEGoal.Nothing, it will return NULL |
|
3876 | 3874 | */ |
|
3877 | 3875 | private Expression interpretAssignToSlice(UnionExp* pue, BinExp e, Expression e1, Expression newval, bool isBlockAssignment) |
|
3878 | 3876 | { |
4042 | 4040 | { |
|
4043 | 4041 | existingSE.setCodeUnit(cast(size_t)(i + firstIndex), value); |
|
4044 | 4042 | } |
|
4045 | - | if (goal == ctfeNeedNothing) |
|
4043 | + | if (goal == CTFEGoal.Nothing) |
|
4046 | 4044 | return null; // avoid creating an unused literal |
|
4047 | 4045 | auto retslice = ctfeEmplaceExp!SliceExp(e.loc, existingSE, |
|
4048 | 4046 | ctfeEmplaceExp!IntegerExp(e.loc, firstIndex, Type.tsize_t), |
4248 | 4246 | if (Expression ex = rb.assignTo(existingAE, cast(size_t)lowerbound, cast(size_t)upperbound)) |
|
4249 | 4247 | return ex; |
|
4250 | 4248 | ||
4251 | - | if (goal == ctfeNeedNothing) |
|
4249 | + | if (goal == CTFEGoal.Nothing) |
|
4252 | 4250 | return null; // avoid creating an unused literal |
|
4253 | 4251 | auto retslice = ctfeEmplaceExp!SliceExp(e.loc, existingAE, |
|
4254 | 4252 | ctfeEmplaceExp!IntegerExp(e.loc, firstIndex, Type.tsize_t), |
4591 | 4589 | } |
|
4592 | 4590 | incUsageCtfe(istate, e.e2.loc); |
|
4593 | 4591 | ||
4594 | - | if (goal != ctfeNeedNothing) |
|
4592 | + | if (goal != CTFEGoal.Nothing) |
|
4595 | 4593 | { |
|
4596 | 4594 | if (e.type.equals(Type.tbool)) |
|
4597 | 4595 | result = IntegerExp.createBool(res); |
4696 | 4694 | ||
4697 | 4695 | // printf("2 ea = %s, %s %s\n", ea.type.toChars(), Token.toChars(ea.op), ea.toChars()); |
|
4698 | 4696 | if (ea.op == TOK.variable || ea.op == TOK.symbolOffset) |
|
4699 | - | result = getVarExp(e.loc, istate, (cast(SymbolExp)ea).var, ctfeNeedRvalue); |
|
4697 | + | result = getVarExp(e.loc, istate, (cast(SymbolExp)ea).var, CTFEGoal.RValue); |
|
4700 | 4698 | else if (auto ae = ea.isAddrExp()) |
|
4701 | 4699 | result = interpretRegion(ae.e1, istate); |
|
4702 | 4700 |
4836 | 4834 | return; |
|
4837 | 4835 | if (!exceptionOrCantInterpret(result)) |
|
4838 | 4836 | { |
|
4839 | - | if (goal != ctfeNeedLvalue) // Peel off CTFE reference if it's unnecessary |
|
4837 | + | if (goal != CTFEGoal.LValue) // Peel off CTFE reference if it's unnecessary |
|
4840 | 4838 | { |
|
4841 | 4839 | if (result == pue.exp()) |
|
4842 | 4840 | result = pue.copy(); |
4910 | 4908 | else |
|
4911 | 4909 | { |
|
4912 | 4910 | UnionExp ue = void; |
|
4913 | - | auto e1 = interpret(&ue, e.e1, istate, ctfeNeedNothing); |
|
4911 | + | auto e1 = interpret(&ue, e.e1, istate, CTFEGoal.Nothing); |
|
4914 | 4912 | if (exceptionOrCant(e1)) |
|
4915 | 4913 | return endTempStackFrame(); |
|
4916 | 4914 | } |
5232 | 5230 | } |
|
5233 | 5231 | if (agg.op == TOK.arrayLiteral || agg.op == TOK.string_) |
|
5234 | 5232 | { |
|
5235 | - | if (goal == ctfeNeedLvalue) |
|
5233 | + | if (goal == CTFEGoal.LValue) |
|
5236 | 5234 | { |
|
5237 | 5235 | // if we need a reference, IndexExp shouldn't be interpreting |
|
5238 | 5236 | // the expression to a value, it should stay as a reference |
5262 | 5260 | return; |
|
5263 | 5261 | if (e1.op == TOK.null_) |
|
5264 | 5262 | { |
|
5265 | - | if (goal == ctfeNeedLvalue && e1.type.ty == Taarray && e.modifiable) |
|
5263 | + | if (goal == CTFEGoal.LValue && e1.type.ty == Taarray && e.modifiable) |
|
5266 | 5264 | { |
|
5267 | 5265 | assert(0); // does not reach here? |
|
5268 | 5266 | } |
5274 | 5272 | if (exceptionOrCant(e2)) |
|
5275 | 5273 | return; |
|
5276 | 5274 | ||
5277 | - | if (goal == ctfeNeedLvalue) |
|
5275 | + | if (goal == CTFEGoal.LValue) |
|
5278 | 5276 | { |
|
5279 | 5277 | // Pointer or reference of a scalar type |
|
5280 | 5278 | if (e1 == e.e1 && e2 == e.e2) |
5308 | 5306 | return; |
|
5309 | 5307 | } |
|
5310 | 5308 | ||
5311 | - | if (goal == ctfeNeedLvalue) |
|
5309 | + | if (goal == CTFEGoal.LValue) |
|
5312 | 5310 | { |
|
5313 | 5311 | Expression e2 = ctfeEmplaceExp!IntegerExp(e.e2.loc, indexToAccess, Type.tsize_t); |
|
5314 | 5312 | emplaceExp!(IndexExp)(pue, e.loc, agg, e2); |
5409 | 5407 | return; |
|
5410 | 5408 | } |
|
5411 | 5409 | ||
5412 | - | CtfeGoal goal1 = ctfeNeedRvalue; |
|
5413 | - | if (goal == ctfeNeedLvalue) |
|
5410 | + | CTFEGoal goal1 = CTFEGoal.RValue; |
|
5411 | + | if (goal == CTFEGoal.LValue) |
|
5414 | 5412 | { |
|
5415 | 5413 | if (e.e1.type.toBasetype().ty == Tsarray) |
|
5416 | 5414 | if (auto ve = e.e1.isVarExp()) |
|
5417 | 5415 | if (auto vd = ve.var.isVarDeclaration()) |
|
5418 | 5416 | if (vd.storage_class & STC.ref_) |
|
5419 | - | goal1 = ctfeNeedLvalue; |
|
5417 | + | goal1 = CTFEGoal.LValue; |
|
5420 | 5418 | } |
|
5421 | 5419 | Expression e1 = interpret(e.e1, istate, goal1); |
|
5422 | 5420 | if (exceptionOrCant(e1)) |
5995 | 5993 | if (soe1.offset == 0 && soe1.var.isVarDeclaration() && isFloatIntPaint(e.type, soe1.var.type)) |
|
5996 | 5994 | { |
|
5997 | 5995 | // *(cast(int*)&v), where v is a float variable |
|
5998 | - | result = paintFloatInt(pue, getVarExp(e.loc, istate, soe1.var, ctfeNeedRvalue), e.type); |
|
5996 | + | result = paintFloatInt(pue, getVarExp(e.loc, istate, soe1.var, CTFEGoal.RValue), e.type); |
|
5999 | 5997 | return; |
|
6000 | 5998 | } |
|
6001 | 5999 |
6176 | 6174 | if ((*se.elements)[i] is null) |
|
6177 | 6175 | (*se.elements)[i] = voidInitLiteral(e.type, v).copy(); |
|
6178 | 6176 | ||
6179 | - | if (goal == ctfeNeedLvalue) |
|
6177 | + | if (goal == CTFEGoal.LValue) |
|
6180 | 6178 | { |
|
6181 | 6179 | // just return the (simplified) dotvar expression as a CTFE reference |
|
6182 | 6180 | if (e.e1 == ex) |
6297 | 6295 | * resulting expression |
|
6298 | 6296 | */ |
|
6299 | 6297 | ||
6300 | - | Expression interpret(UnionExp* pue, Expression e, InterState* istate, CtfeGoal goal = ctfeNeedRvalue) |
|
6298 | + | Expression interpret(UnionExp* pue, Expression e, InterState* istate, CTFEGoal goal = CTFEGoal.RValue) |
|
6301 | 6299 | { |
|
6302 | 6300 | if (!e) |
|
6303 | 6301 | return null; |
|
6304 | 6302 | scope Interpreter v = new Interpreter(pue, istate, goal); |
|
6305 | 6303 | e.accept(v); |
|
6306 | 6304 | Expression ex = v.result; |
|
6307 | - | assert(goal == ctfeNeedNothing || ex !is null); |
|
6305 | + | assert(goal == CTFEGoal.Nothing || ex !is null); |
|
6308 | 6306 | return ex; |
|
6309 | 6307 | } |
|
6310 | 6308 | ||
6311 | 6309 | /// |
|
6312 | - | Expression interpret(Expression e, InterState* istate, CtfeGoal goal = ctfeNeedRvalue) |
|
6310 | + | Expression interpret(Expression e, InterState* istate, CTFEGoal goal = CTFEGoal.RValue) |
|
6313 | 6311 | { |
|
6314 | 6312 | UnionExp ue = void; |
|
6315 | 6313 | auto result = interpret(&ue, e, istate, goal); |
6327 | 6325 | * Returns: |
|
6328 | 6326 | * resulting expression |
|
6329 | 6327 | */ |
|
6330 | - | Expression interpretRegion(Expression e, InterState* istate, CtfeGoal goal = ctfeNeedRvalue) |
|
6328 | + | Expression interpretRegion(Expression e, InterState* istate, CTFEGoal goal = CTFEGoal.RValue) |
|
6331 | 6329 | { |
|
6332 | 6330 | UnionExp ue = void; |
|
6333 | 6331 | auto result = interpret(&ue, e, istate, goal); |
6366 | 6364 | { |
|
6367 | 6365 | if (!s) |
|
6368 | 6366 | return null; |
|
6369 | - | scope Interpreter v = new Interpreter(pue, istate, ctfeNeedNothing); |
|
6367 | + | scope Interpreter v = new Interpreter(pue, istate, CTFEGoal.Nothing); |
|
6370 | 6368 | s.accept(v); |
|
6371 | 6369 | return v.result; |
|
6372 | 6370 | } |
Learn more Showing 5 files with coverage changes found.
src/dmd/backend/gflow.d
src/dmd/backend/cod2.d
src/dmd/backend/cod3.d
src/dmd/dinterpret.d
src/dmd/backend/code_x86.d
Files | Coverage |
---|---|
src/dmd | 77.200% |
Project Totals (203 files) | 77.200% |
fe4b650
b646a5f
f66508a
1da8a5e
2fab3cc
35173d8
016556b
b2f1a37
fa4f32e
ec370e2
18c930d
89fa2d6
187a7fb
54ce9fc
5a6b3ab
ae95799
873921b