Skip to content

Commit 32a1dd6

Browse files
committed
Have a block-based IR for compiling, calculate max stack size
1 parent 5d6c323 commit 32a1dd6

File tree

6 files changed

+592
-321
lines changed

6 files changed

+592
-321
lines changed

bytecode/src/lib.rs

Lines changed: 111 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ pub struct CodeObject<C: Constant = ConstantData> {
113113
pub kwonlyarg_count: usize,
114114
pub source_path: C::Name,
115115
pub first_line_number: usize,
116+
pub max_stacksize: u32,
116117
pub obj_name: C::Name, // Name of the object that created this code object
117118
pub cell2arg: Option<Box<[isize]>>,
118119
pub constants: Box<[C]>,
@@ -246,7 +247,9 @@ pub enum Instruction {
246247
Continue {
247248
target: Label,
248249
},
249-
Break,
250+
Break {
251+
target: Label,
252+
},
250253
Jump {
251254
target: Label,
252255
},
@@ -285,9 +288,7 @@ pub enum Instruction {
285288
YieldValue,
286289
YieldFrom,
287290
SetupAnnotation,
288-
SetupLoop {
289-
end: Label,
290-
},
291+
SetupLoop,
291292

292293
/// Setup a finally handler, which will be called whenever one of this events occurs:
293294
/// - the block is popped
@@ -556,34 +557,6 @@ impl<N: AsRef<str>> fmt::Debug for Arguments<'_, N> {
556557
}
557558

558559
impl<C: Constant> CodeObject<C> {
559-
pub fn new(
560-
flags: CodeFlags,
561-
posonlyarg_count: usize,
562-
arg_count: usize,
563-
kwonlyarg_count: usize,
564-
source_path: C::Name,
565-
first_line_number: usize,
566-
obj_name: C::Name,
567-
) -> Self {
568-
CodeObject {
569-
instructions: Box::new([]),
570-
locations: Box::new([]),
571-
flags,
572-
posonlyarg_count,
573-
arg_count,
574-
kwonlyarg_count,
575-
source_path,
576-
first_line_number,
577-
obj_name,
578-
cell2arg: None,
579-
constants: Box::new([]),
580-
names: Box::new([]),
581-
varnames: Box::new([]),
582-
cellvars: Box::new([]),
583-
freevars: Box::new([]),
584-
}
585-
}
586-
587560
// like inspect.getargs
588561
pub fn arg_names(&self) -> Arguments<C::Name> {
589562
let nargs = self.arg_count;
@@ -696,6 +669,7 @@ impl<C: Constant> CodeObject<C> {
696669
arg_count: self.arg_count,
697670
kwonlyarg_count: self.kwonlyarg_count,
698671
first_line_number: self.first_line_number,
672+
max_stacksize: self.max_stacksize,
699673
cell2arg: self.cell2arg,
700674
}
701675
}
@@ -727,6 +701,7 @@ impl<C: Constant> CodeObject<C> {
727701
arg_count: self.arg_count,
728702
kwonlyarg_count: self.kwonlyarg_count,
729703
first_line_number: self.first_line_number,
704+
max_stacksize: self.max_stacksize,
730705
cell2arg: self.cell2arg.clone(),
731706
}
732707
}
@@ -802,7 +777,7 @@ impl Instruction {
802777
| SetupExcept { handler: l }
803778
| SetupWith { end: l }
804779
| SetupAsyncWith { end: l }
805-
| SetupLoop { end: l }
780+
| Break { target: l }
806781
| Continue { target: l } => Some(l),
807782
_ => None,
808783
}
@@ -822,12 +797,112 @@ impl Instruction {
822797
| SetupExcept { handler: l }
823798
| SetupWith { end: l }
824799
| SetupAsyncWith { end: l }
825-
| SetupLoop { end: l }
800+
| Break { target: l }
826801
| Continue { target: l } => Some(l),
827802
_ => None,
828803
}
829804
}
830805

806+
pub fn unconditional_branch(&self) -> bool {
807+
matches!(self, Jump { .. } | Continue{ .. } | Break { .. } | ReturnValue | Raise { .. })
808+
}
809+
810+
pub fn stack_effect(&self, jump: bool) -> i32 {
811+
match self {
812+
ImportName { .. } | ImportNameless => -1,
813+
ImportStar => -1,
814+
ImportFrom { .. } => 1,
815+
LoadFast(_) | LoadNameAny(_) | LoadGlobal(_) | LoadDeref(_) | LoadClassDeref(_) => 1,
816+
StoreFast(_) | StoreLocal(_) | StoreGlobal(_) | StoreDeref(_) => -1,
817+
DeleteFast(_) | DeleteLocal(_) | DeleteGlobal(_) | DeleteDeref(_) => 0,
818+
LoadClosure(_) => 1,
819+
Subscript => -1,
820+
StoreSubscript => -3,
821+
DeleteSubscript => -2,
822+
LoadAttr { .. } => 0,
823+
StoreAttr { .. } => -2,
824+
DeleteAttr { .. } => -1,
825+
LoadConst { .. } => 1,
826+
UnaryOperation { .. } => 0,
827+
BinaryOperation { .. } | BinaryOperationInplace { .. } | CompareOperation { .. } => -1,
828+
Pop => -1,
829+
Rotate { .. } => 0,
830+
Duplicate => 1,
831+
GetIter => 0,
832+
Continue { .. } => 0,
833+
Break { .. } => 0,
834+
Jump { .. } => 0,
835+
JumpIfTrue { .. } | JumpIfFalse { .. } => -1,
836+
JumpIfTrueOrPop { .. } | JumpIfFalseOrPop { .. } => {
837+
if jump {
838+
0
839+
} else {
840+
-1
841+
}
842+
}
843+
MakeFunction(flags) => {
844+
-2 - flags.contains(MakeFunctionFlags::CLOSURE) as i32
845+
- flags.contains(MakeFunctionFlags::ANNOTATIONS) as i32
846+
- flags.contains(MakeFunctionFlags::KW_ONLY_DEFAULTS) as i32
847+
- flags.contains(MakeFunctionFlags::DEFAULTS) as i32
848+
+ 1
849+
}
850+
CallFunctionPositional { nargs } => -1 - (*nargs as i32) + 1,
851+
CallFunctionKeyword { nargs } => -2 - (*nargs as i32) + 1,
852+
CallFunctionEx { has_kwargs } => -2 - *has_kwargs as i32 + 1,
853+
ForIter { .. } => {
854+
if jump {
855+
-1
856+
} else {
857+
1
858+
}
859+
}
860+
ReturnValue => -1,
861+
YieldValue => 0,
862+
YieldFrom => -1,
863+
SetupAnnotation
864+
| SetupLoop
865+
| SetupFinally { .. }
866+
| EnterFinally
867+
| EndFinally
868+
| SetupExcept { .. } => 0,
869+
SetupWith { .. } => {
870+
if jump {
871+
0
872+
} else {
873+
1
874+
}
875+
}
876+
WithCleanupStart => 0,
877+
WithCleanupFinish => -1,
878+
PopBlock => 0,
879+
Raise { kind } => -(*kind as u8 as i32),
880+
BuildString { size }
881+
| BuildTuple { size, .. }
882+
| BuildList { size, .. }
883+
| BuildSet { size, .. } => -(*size as i32) + 1,
884+
BuildMap { unpack, size, .. } => {
885+
let nargs = if *unpack { *size } else { *size * 2 };
886+
-(nargs as i32) + 1
887+
}
888+
BuildSlice { step } => -2 - (*step as i32) + 1,
889+
ListAppend { .. } | SetAdd { .. } => -1,
890+
MapAdd { .. } | MapAddRev { .. } => -2,
891+
PrintExpr => -1,
892+
LoadBuildClass => 1,
893+
UnpackSequence { size } => -1 + *size as i32,
894+
UnpackEx { before, after } => -1 + *before as i32 + 1 + *after as i32,
895+
FormatValue { .. } => -1,
896+
PopException => 0,
897+
Reverse { .. } => 0,
898+
GetAwaitable => 0,
899+
BeforeAsyncWith => 1,
900+
SetupAsyncWith { .. } => 0,
901+
GetAIter => 0,
902+
GetANext => 1,
903+
}
904+
}
905+
831906
#[allow(clippy::too_many_arguments)]
832907
fn fmt_dis<C: Constant>(
833908
&self,
@@ -922,7 +997,7 @@ impl Instruction {
922997
Duplicate => w!(Duplicate),
923998
GetIter => w!(GetIter),
924999
Continue { target } => w!(Continue, target),
925-
Break => w!(Break),
1000+
Break { target } => w!(Break, target),
9261001
Jump { target } => w!(Jump, target),
9271002
JumpIfTrue { target } => w!(JumpIfTrue, target),
9281003
JumpIfFalse { target } => w!(JumpIfFalse, target),
@@ -937,7 +1012,7 @@ impl Instruction {
9371012
YieldValue => w!(YieldValue),
9381013
YieldFrom => w!(YieldFrom),
9391014
SetupAnnotation => w!(SetupAnnotation),
940-
SetupLoop { end } => w!(SetupLoop, end),
1015+
SetupLoop => w!(SetupLoop),
9411016
SetupExcept { handler } => w!(SetupExcept, handler),
9421017
SetupFinally { handler } => w!(SetupFinally, handler),
9431018
EnterFinally => w!(EnterFinally),

0 commit comments

Comments
 (0)