Skip to content
This repository was archived by the owner on Jun 10, 2024. It is now read-only.

Commit 83c94f0

Browse files
committed
fix: address various abi bugs in codegen
- Ensure ABI is followed for structs too large to be returned in registers (this also required changes in our LLVM) - Clean up a variety of ops in the MLIR lowering, removing some entirely, moving some to the LLVM dialect, converting some ops to intrinsic calls. - Fix the semantics around the is_list intrinsic to capture the difference between any list and nonempty lists. - Lower is_list/is_nonempty_list ops to inlined instructions vs calls to intrinsic functions to allow for better optimization - Flesh out backtrace/symbolication functionality and exception printing - Add implementation of lists:reverse/2 to tiny rt - Add semantic verifier for undefined module-local callees
1 parent 4419621 commit 83c94f0

File tree

40 files changed

+1115
-260
lines changed

40 files changed

+1115
-260
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler/codegen/src/passes/ssa_to_mlir/builder/function.rs

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use liblumen_binary::{Bitstring, Encoding};
22
use liblumen_diagnostics::{SourceSpan, Spanned};
33
use liblumen_llvm::Linkage;
4-
use liblumen_mlir::cir::ICmpPredicate;
5-
use liblumen_mlir::llvm::LinkageAttr;
4+
use liblumen_mlir::llvm::{ICmpPredicate, LinkageAttr};
65
use liblumen_mlir::*;
76
use liblumen_number::Integer;
7+
use liblumen_rt::term::OpaqueTerm;
88
use liblumen_syntax_base::{self as syntax_base, Signature};
99
use liblumen_syntax_ssa::{self as syntax_ssa, ir::instructions::*, DataFlowGraph};
1010
use liblumen_syntax_ssa::{ConstantItem, Immediate, ImmediateTerm};
@@ -226,10 +226,6 @@ impl<'m> ModuleBuilder<'m> {
226226
.get_cir_box_type(builder.get_cir_bigint_type())
227227
.base();
228228
let op = builder.build_constant(loc, ty, builder.get_bigint_attr(i, ty));
229-
// We need a cast to generic integer type because lowering of boxed types
230-
// like bigint is to a pointer type,
231-
//let value = op.get_result(0).base();
232-
//let op = builder.build_cast(loc, value, builder.get_cir_integer_type());
233229
op.get_result(0).base()
234230
}
235231
ConstantItem::Float(f) => {
@@ -570,28 +566,28 @@ impl<'m> ModuleBuilder<'m> {
570566
return Ok(());
571567
}
572568
Opcode::IcmpEq => self
573-
.cir()
569+
.llvm()
574570
.build_icmp(loc, ICmpPredicate::Eq, lhs, rhs)
575571
.base(),
576572
Opcode::IcmpNeq => self
577-
.cir()
573+
.llvm()
578574
.build_icmp(loc, ICmpPredicate::Neq, lhs, rhs)
579575
.base(),
580576
Opcode::IcmpGt => self
581-
.cir()
582-
.build_icmp(loc, ICmpPredicate::Gt, lhs, rhs)
577+
.llvm()
578+
.build_icmp(loc, ICmpPredicate::Ugt, lhs, rhs)
583579
.base(),
584580
Opcode::IcmpGte => self
585-
.cir()
586-
.build_icmp(loc, ICmpPredicate::Gte, lhs, rhs)
581+
.llvm()
582+
.build_icmp(loc, ICmpPredicate::Uge, lhs, rhs)
587583
.base(),
588584
Opcode::IcmpLt => self
589-
.cir()
590-
.build_icmp(loc, ICmpPredicate::Lt, lhs, rhs)
585+
.llvm()
586+
.build_icmp(loc, ICmpPredicate::Ult, lhs, rhs)
591587
.base(),
592588
Opcode::IcmpLte => self
593-
.cir()
594-
.build_icmp(loc, ICmpPredicate::Lte, lhs, rhs)
589+
.llvm()
590+
.build_icmp(loc, ICmpPredicate::Ule, lhs, rhs)
595591
.base(),
596592
Opcode::Eq => {
597593
let callee = self.get_or_declare_builtin("erlang:==/2").unwrap();
@@ -760,27 +756,27 @@ impl<'m> ModuleBuilder<'m> {
760756
}
761757
Opcode::IcmpEq => {
762758
let rhs = self.immediate_to_constant(loc, op.imm);
763-
self.cir().build_icmp(loc, ICmpPredicate::Eq, lhs, rhs).base()
759+
self.llvm().build_icmp(loc, ICmpPredicate::Eq, lhs, rhs).base()
764760
}
765761
Opcode::IcmpNeq => {
766762
let rhs = self.immediate_to_constant(loc, op.imm);
767-
self.cir().build_icmp(loc, ICmpPredicate::Neq, lhs, rhs).base()
763+
self.llvm().build_icmp(loc, ICmpPredicate::Neq, lhs, rhs).base()
768764
}
769765
Opcode::IcmpGt => {
770766
let rhs = self.immediate_to_constant(loc, op.imm);
771-
self.cir().build_icmp(loc, ICmpPredicate::Gt, lhs, rhs).base()
767+
self.llvm().build_icmp(loc, ICmpPredicate::Ugt, lhs, rhs).base()
772768
}
773769
Opcode::IcmpGte => {
774770
let rhs = self.immediate_to_constant(loc, op.imm);
775-
self.cir().build_icmp(loc, ICmpPredicate::Gte, lhs, rhs).base()
771+
self.llvm().build_icmp(loc, ICmpPredicate::Uge, lhs, rhs).base()
776772
}
777773
Opcode::IcmpLt => {
778774
let rhs = self.immediate_to_constant(loc, op.imm);
779-
self.cir().build_icmp(loc, ICmpPredicate::Lt, lhs, rhs).base()
775+
self.llvm().build_icmp(loc, ICmpPredicate::Ult, lhs, rhs).base()
780776
}
781777
Opcode::IcmpLte => {
782778
let rhs = self.immediate_to_constant(loc, op.imm);
783-
self.cir().build_icmp(loc, ICmpPredicate::Lte, lhs, rhs).base()
779+
self.llvm().build_icmp(loc, ICmpPredicate::Ule, lhs, rhs).base()
784780
}
785781
Opcode::Eq => {
786782
let rhs = self.immediate_to_constant(loc, op.imm);
@@ -1162,6 +1158,24 @@ impl<'m> ModuleBuilder<'m> {
11621158
let input = self.values[&op.arg];
11631159
let op = match op.ty {
11641160
CoreType::Term(TermType::List(_)) => builder.build_is_list(loc, input).base(),
1161+
CoreType::Term(TermType::Cons) => builder.build_is_nonempty_list(loc, input).base(),
1162+
CoreType::Term(TermType::Nil) => {
1163+
let raw = builder.build_cast(loc, input, builder.get_i64_type());
1164+
let llvm = builder.llvm();
1165+
let i1 = llvm.get_i64_type();
1166+
let nil = llvm.build_constant(
1167+
loc,
1168+
i1,
1169+
llvm.get_i64_attr(OpaqueTerm::NIL.raw() as i64).base(),
1170+
);
1171+
llvm.build_icmp(
1172+
loc,
1173+
ICmpPredicate::Eq,
1174+
raw.get_result(0).base(),
1175+
nil.get_result(0).base(),
1176+
)
1177+
.base()
1178+
}
11651179
CoreType::Term(TermType::Number) => builder.build_is_number(loc, input).base(),
11661180
CoreType::Term(TermType::Integer) => builder.build_is_integer(loc, input).base(),
11671181
CoreType::Term(TermType::Float) => builder.build_is_float(loc, input).base(),
@@ -1609,6 +1623,7 @@ fn translate_term_ir_type<'a, B: OpBuilder>(
16091623
.get_cir_box_type(builder.get_cir_binary_type())
16101624
.base(),
16111625
TermType::Nil => builder.get_cir_nil_type().base(),
1626+
TermType::Cons => builder.get_cir_box_type(builder.get_cir_cons_type()).base(),
16121627
TermType::List(_) | TermType::MaybeImproperList => {
16131628
builder.get_cir_box_type(builder.get_cir_cons_type()).base()
16141629
}

compiler/codegen/src/passes/ssa_to_mlir/builder/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ impl<'m> ModuleBuilder<'m> {
107107
CirBuilder::new(&self.builder)
108108
}
109109

110+
#[inline]
111+
pub fn llvm(&self) -> LlvmBuilder<'_, OwnedOpBuilder> {
112+
LlvmBuilder::new(&self.builder)
113+
}
114+
110115
pub fn find_function(&self, f: syntax_ssa::FuncRef) -> Signature {
111116
self.module.call_signature(f).clone()
112117
}

compiler/diagnostics/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ impl Reporter {
151151
})
152152
.collect();
153153
self.diagnostic(
154-
Diagnostic::error()
154+
Diagnostic::warning()
155155
.with_message(message)
156156
.with_labels(labels),
157157
);

compiler/macros/src/bif.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,8 @@ fn erlang_type_to_core_type_enum(ident: Ident) -> Expr {
296296
"function" => core_enum_fun_variant(span),
297297
"nil" => core_enum_variant("Nil", span),
298298
"tuple" => core_enum_tuple_variant(None, span),
299-
"list" | "nonempty_list" | "string" | "nonempty_string" | "iovec" => {
300-
core_enum_list_variant(span)
301-
}
299+
"nonempty_list" | "nonempty_string" => core_enum_nonempty_list_variant(span),
300+
"list" | "string" | "iovec" => core_enum_list_variant(span),
302301
"maybe_improper_list"
303302
| "nonempty_improper_list"
304303
| "nonempty_maybe_improper_list"
@@ -406,6 +405,11 @@ fn core_enum_list_variant(span: Span) -> Expr {
406405
parse_quote!(#quoted)
407406
}
408407

408+
fn core_enum_nonempty_list_variant(span: Span) -> Expr {
409+
let quoted = quote_spanned! { span => crate::Type::Term(crate::TermType::Cons) };
410+
parse_quote!(#quoted)
411+
}
412+
409413
fn core_enum_tuple_variant(elements: Option<&[&str]>, span: Span) -> Expr {
410414
let quoted = if elements.is_none() {
411415
quote_spanned! { span =>

compiler/mlir/c_src/include/CIR-c/Dialects.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,6 @@ MLIR_CAPI_EXPORTED MlirOperation mlirCirZExtOp(MlirOpBuilder builder,
172172
MlirLocation location,
173173
MlirValue value, MlirType ty);
174174

175-
MLIR_CAPI_EXPORTED MlirOperation mlirCirICmpOp(MlirOpBuilder builder,
176-
MlirLocation location,
177-
unsigned predicate,
178-
MlirValue lhs, MlirValue rhs);
179-
180175
MLIR_CAPI_EXPORTED MlirOperation mlirCirCastOp(MlirOpBuilder builder,
181176
MlirLocation location,
182177
MlirValue value, MlirType ty);
@@ -222,6 +217,10 @@ MLIR_CAPI_EXPORTED MlirOperation mlirCirIsListOp(MlirOpBuilder builder,
222217
MlirLocation location,
223218
MlirValue value);
224219

220+
MLIR_CAPI_EXPORTED MlirOperation mlirCirIsNonEmptyListOp(MlirOpBuilder builder,
221+
MlirLocation location,
222+
MlirValue value);
223+
225224
MLIR_CAPI_EXPORTED MlirOperation mlirCirIsNumberOp(MlirOpBuilder builder,
226225
MlirLocation location,
227226
MlirValue value);
@@ -457,6 +456,13 @@ MLIR_CAPI_EXPORTED MlirOperation mlirScfExecuteRegionOp(MlirOpBuilder builder,
457456

458457
MLIR_CAPI_EXPORTED bool mlirLLVMFuncOpIsA(MlirOperation op);
459458

459+
MLIR_CAPI_EXPORTED bool mlirLLVMConstantOpIsA(MlirOperation op);
460+
461+
MLIR_CAPI_EXPORTED bool mlirLLVMICmpOpIsA(MlirOperation op);
462+
463+
MLIR_CAPI_EXPORTED MlirAttribute
464+
mlirLLVMICmpPredicateAttrGet(MlirContext ctx, unsigned predicate);
465+
460466
#ifdef __cplusplus
461467
}
462468
#endif

compiler/mlir/c_src/include/CIR/Attributes.td

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -305,18 +305,4 @@ def CIR_FloatAttr : CIR_Attr<"CIRFloat"> {
305305
}];
306306
}
307307

308-
def ICmpPredicateEQ : I64EnumAttrCase<"eq", 0>;
309-
def ICmpPredicateNE : I64EnumAttrCase<"ne", 1>;
310-
def ICmpPredicateLT : I64EnumAttrCase<"lt", 2>;
311-
def ICmpPredicateLE : I64EnumAttrCase<"le", 3>;
312-
def ICmpPredicateGT : I64EnumAttrCase<"gt", 4>;
313-
def ICmpPredicateGE : I64EnumAttrCase<"ge", 5>;
314-
def ICmpPredicate : I64EnumAttr<
315-
"ICmpPredicate",
316-
"integer comparison predicate",
317-
[ICmpPredicateEQ, ICmpPredicateNE, ICmpPredicateLT, ICmpPredicateLE,
318-
ICmpPredicateGT, ICmpPredicateGE]> {
319-
let cppNamespace = "::mlir::cir";
320-
}
321-
322308
#endif

compiler/mlir/c_src/include/CIR/CIR.td

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -450,17 +450,6 @@ def CIR_ZExtOp : CIR_Op<"zext", [NoSideEffect]> {
450450
}];
451451
}
452452

453-
def CIR_ICmpOp : CIR_Op<"icmp", [NoSideEffect, SameTypeOperands]> {
454-
let summary = "Performs a raw integer comparison operation";
455-
456-
let arguments = (ins ICmpPredicate:$predicate, AnyInteger:$lhs, AnyInteger:$rhs);
457-
let results = (outs I1:$result);
458-
459-
let assemblyFormat = [{
460-
$predicate $lhs `,` $rhs `:` type($lhs) attr-dict
461-
}];
462-
}
463-
464453
def CIR_TypeOfOp : CIR_Op<"typeof", [MemoryEffects<[MemRead]>]> {
465454
let summary = "Returns the type information of the given term value";
466455
let description = [{
@@ -491,6 +480,22 @@ def CIR_IsListOp : CIR_Op<"is_list", [MemoryEffects<[MemRead]>]> {
491480
//let hasFolder = 1;
492481
}
493482

483+
def CIR_IsNonEmptyListOp : CIR_Op<"is_nonempty_list", [MemoryEffects<[MemRead]>]> {
484+
let summary = "A type checking predicate for nonempty lists.";
485+
let description = [{
486+
This operation returns true if the given term is a pointer to a cons cell.
487+
}];
488+
489+
let arguments = (ins CIR_AnyTerm:$value);
490+
let results = (outs I1:$result);
491+
492+
let assemblyFormat = [{
493+
$value `:` type($value) attr-dict
494+
}];
495+
496+
//let hasFolder = 1;
497+
}
498+
494499
def CIR_IsNumberOp : CIR_Op<"is_number", [MemoryEffects<[MemRead]>]> {
495500
let summary = "A type checking predicate for numbers.";
496501
let description = [{

compiler/mlir/c_src/lib/CAPI/Ops.cpp

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@
1212
#include "mlir/Dialect/SCF/SCF.h"
1313
#include "mlir/IR/BuiltinOps.h"
1414

15+
#include "llvm/ADT/Optional.h"
16+
1517
using namespace mlir;
1618
using namespace mlir::cir;
1719

20+
using llvm::Optional;
21+
1822
MlirOperation mlirCirIsNullOp(MlirOpBuilder bldr, MlirLocation location,
1923
MlirValue value) {
2024
OpBuilder *builder = unwrap(bldr);
@@ -39,15 +43,6 @@ MlirOperation mlirCirZExtOp(MlirOpBuilder bldr, MlirLocation location,
3943
return wrap(op);
4044
}
4145

42-
MlirOperation mlirCirICmpOp(MlirOpBuilder bldr, MlirLocation location,
43-
unsigned predicate, MlirValue lhs, MlirValue rhs) {
44-
OpBuilder *builder = unwrap(bldr);
45-
auto pred = static_cast<cir::ICmpPredicate>(predicate);
46-
Operation *op = builder->create<cir::ICmpOp>(unwrap(location), pred,
47-
unwrap(lhs), unwrap(rhs));
48-
return wrap(op);
49-
}
50-
5146
MlirOperation mlirCirCastOp(MlirOpBuilder bldr, MlirLocation location,
5247
MlirValue value, MlirType toTy) {
5348
OpBuilder *builder = unwrap(bldr);
@@ -136,6 +131,15 @@ MlirOperation mlirCirIsListOp(MlirOpBuilder bldr, MlirLocation location,
136131
return wrap(op);
137132
}
138133

134+
MlirOperation mlirCirIsNonEmptyListOp(MlirOpBuilder bldr, MlirLocation location,
135+
MlirValue value) {
136+
137+
OpBuilder *builder = unwrap(bldr);
138+
Operation *op =
139+
builder->create<cir::IsNonEmptyListOp>(unwrap(location), unwrap(value));
140+
return wrap(op);
141+
}
142+
139143
MlirOperation mlirCirIsNumberOp(MlirOpBuilder bldr, MlirLocation location,
140144
MlirValue value) {
141145

@@ -669,3 +673,19 @@ MlirOperation mlirScfExecuteRegionOp(MlirOpBuilder bldr, MlirLocation location,
669673
bool mlirLLVMFuncOpIsA(MlirOperation op) {
670674
return isa<LLVM::LLVMFuncOp>(unwrap(op));
671675
}
676+
677+
bool mlirLLVMConstantOpIsA(MlirOperation op) {
678+
return isa<LLVM::ConstantOp>(unwrap(op));
679+
}
680+
681+
bool mlirLLVMICmpOpIsA(MlirOperation op) {
682+
return isa<LLVM::ICmpOp>(unwrap(op));
683+
}
684+
685+
MlirAttribute mlirLLVMICmpPredicateAttrGet(MlirContext ctx,
686+
unsigned predicate) {
687+
Optional<LLVM::ICmpPredicate> pred =
688+
LLVM::symbolizeICmpPredicate((uint64_t)predicate);
689+
Attribute attr = LLVM::ICmpPredicateAttr::get(unwrap(ctx), pred.getValue());
690+
return wrap(attr);
691+
}

0 commit comments

Comments
 (0)